using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.IO;
using System.Windows.Forms;
namespace Act2Tcx
{
class Program
{
[STAThread]
static void Main(string[] args)
{
OpenFileDialog openFile = new OpenFileDialog();
openFile.Filter = "GS-Sport ACT File|*.act";
if (openFile.ShowDialog() == DialogResult.OK)
{
Course c = Load(openFile.FileName);
string tcxFile = Path.Combine(
Path.GetDirectoryName(openFile.FileName),
c.Name.Replace(":", "") + ".tcx");
File.WriteAllText(tcxFile, c.ToXml());
MessageBox.Show("Done! - " + tcxFile);
}
}
public static Course Load(string file)
{
DataSet ds = new DataSet();
ds.ReadXml(file);
DataTable trackmaster = ds.Tables["trackmaster"];
DataTable trackPoints = ds.Tables["TrackPoints"];
DataRow row = trackmaster.Rows[0];
DateTime startTime = DateTime.ParseExact(
row["TrackName"].ToString() + " " + row["StartTime"].ToString(),
"yyyy-M-dd HH:mm:ss", null);
Course c = new Course()
{
Name = string.Format("{0:yyyy-MM-dd HH:mm:ss} {1:N0}m", startTime,
decimal.Parse(row["Distence"].ToString()))
};
DateTime currTime = startTime;
foreach (DataRow tp in trackPoints.Rows)
{
c.TrackPoints.Add(new TrackPoint()
{
Time = currTime,
AltitudeMeters = decimal.Parse(tp["Altitude"].ToString()),
HeartRateBpm = decimal.Parse(tp["HeartRate"].ToString()),
LatitudeDegrees = decimal.Parse(tp["Latitude"].ToString()),
LongitudeDegrees = decimal.Parse(tp["Longitude"].ToString())
});
currTime = currTime.AddSeconds(double.Parse(tp["IntervalTime"].ToString()));
}
return c;
}
}
public class Course
{
public string Name;
public List<TrackPoint> TrackPoints = new List<TrackPoint>();
public string ToXml()
{
StringBuilder sb = new StringBuilder();
TrackPoint st = TrackPoints.First(), ed = TrackPoints.Last();
sb.AppendFormat(@"<?xml version=""1.0"" encoding=""UTF-8"" standalone=""no"" ?>
<TrainingCenterDatabase xmlns=""http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xsi:schemaLocation=""http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd"">
<Folders/>
<Courses>
<Course>
<Name>{0}</Name>
<Lap>
<TotalTimeSeconds>{1}</TotalTimeSeconds>
<DistanceMeters>{2}</DistanceMeters>
<BeginPosition>
<LatitudeDegrees>{3}</LatitudeDegrees>
<LongitudeDegrees>{4}</LongitudeDegrees>
</BeginPosition>
<EndPosition>
<LatitudeDegrees>{5}</LatitudeDegrees>
<LongitudeDegrees>{6}</LongitudeDegrees>
</EndPosition>
<AverageHeartRateBpm xsi:type=""HeartRateInBeatsPerMinute_t"">
<Value>{7}</Value>
</AverageHeartRateBpm>
<MaximumHeartRateBpm xsi:type=""HeartRateInBeatsPerMinute_t"">
<Value>{8}</Value>
</MaximumHeartRateBpm>
<Intensity>Active</Intensity>
</Lap>
<Track>
", Name,
(ed.Time - st.Time).TotalSeconds,
0, //DistanceMeters, RunKeeper不需,省略
st.LatitudeDegrees, st.LongitudeDegrees,
ed.LatitudeDegrees, ed.LongitudeDegrees,
0, //AverageHeartRateBpm, RunKeeper不需,省略
TrackPoints.Select(o => o.HeartRateBpm).Max() //MaximumHeartRateBpm
);
foreach (TrackPoint tp in TrackPoints)
sb.AppendLine(tp.ToXml());
sb.AppendLine(@" </Track>
</Course>
</Courses>
</TrainingCenterDatabase>");
return sb.ToString();
}
}
public class TrackPoint
{
public DateTime Time;
public decimal LatitudeDegrees;
public decimal LongitudeDegrees;
public decimal AltitudeMeters;
public decimal DistanceMeters;
public decimal HeartRateBpm;
public string ToXml()
{
return string.Format(@"<Trackpoint>
<Time>{0:yyyy-MM-ddTHH:mm:ssZ}</Time>
<Position>
<LatitudeDegrees>{1}</LatitudeDegrees>
<LongitudeDegrees>{2}</LongitudeDegrees>
</Position>
<AltitudeMeters>{3}</AltitudeMeters>
<DistanceMeters>{4}</DistanceMeters>
<HeartRateBpm xsi:type=""HeartRateInBeatsPerMinute_t"">
<Value>{5}</Value>
</HeartRateBpm>
<SensorState>Absent</SensorState>
</Trackpoint>", Time, LatitudeDegrees, LongitudeDegrees,
AltitudeMeters, DistanceMeters, HeartRateBpm);
}
}
}