示例#1
0
        public void TestLoadAthlete()
        {
            //setup mock persistence
            var trackBuilder        = new TrackEntity.Builder();
            var trackSegmentBuilder = new TrackSegmentEntity.Builder();

            trackSegmentBuilder.TrackPoints.Add(new TrackPointVO.Builder {
                Time = DateTimeOffset.Now, Cadence = 92, HeartRate = 140, Latitude = 40, Longitude = 8
            });
            trackSegmentBuilder.TrackPoints.Add(new TrackPointVO.Builder {
                Time = DateTimeOffset.Now.AddSeconds(3), Cadence = 92, HeartRate = 140, Latitude = 40, Longitude = 8
            });
            trackSegmentBuilder.TrackPoints.Add(new TrackPointVO.Builder {
                Time = DateTimeOffset.Now.AddSeconds(5), Cadence = 95, HeartRate = 140, Latitude = 40, Longitude = 8
            });

            trackBuilder.TrackSegments.Add(trackSegmentBuilder.Build());

            var activities     = new List <ActivityEntity>();
            var activityEntity = new ActivityEntity.Builder
            {
                Name  = "A bike training",
                Sport = Model.ACTIVITY_SPORT.BIKING
            };

            activityEntity.Tracks.Add(trackBuilder.Build());

            var persistence = A.Fake <IPersistence>();

            A.CallTo(() => persistence.GetAthlete("Test")).Returns(new AthleteEntity(new List <ActivityEntity>()
            {
                activityEntity
            }, "Test", 1));

            //test
            var athlete = persistence.GetAthlete("Test");

            athlete.Name.Should().Be("Test");
            athlete.Activities.Should().HaveCount(1);
            athlete.Activities[0].Tracks[0].TrackSegments[0].TrackPoints.Should().HaveCount(3);
            athlete.Activities[0].Tracks[0].TrackSegments[0].TrackPoints[2].Cadence.Should().Be(95);
        }
示例#2
0
        public IEnumerable <ActivityEntity> ImportActivitiesStream(Stream stream, IDictionary <string, ACTIVITY_SPORT> categoryMapping)
        {
            _Logger.Info("Importing data stream");
            _CurrentContext = PARSE_CONTEXT.ROOT;
            XmlReaderSettings settings = new XmlReaderSettings
            {
                Async = false
            };

            using (XmlReader reader = XmlReader.Create(stream, settings))
            {
                // SAX parsing for performance
                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.Element:
                        switch (reader.Name)
                        {
                        case "gpx":
                            _CurrentContext         = PARSE_CONTEXT.GPX;
                            _CurrentCreator         = reader.GetAttribute("creator");
                            _CurrentActivityBuilder = new ActivityEntity.Builder
                            {
                                OriginSystem = _CurrentCreator
                            };
                            while (reader.MoveToNextAttribute())
                            {
                                if (reader.Name.StartsWith("xmlns:") && reader.Value.ToLower() == "http://www.garmin.com/xmlschemas/trackpointextension/v1")
                                {
                                    _XmlNamespaces["gpxtpx"] = reader.Name.Replace("xmlns:", "") + ":";
                                }
                            }
                            break;

                        case "metadata":
                            _CurrentContext = PARSE_CONTEXT.METADATA;
                            break;

                        case "time":
                            if (_CurrentContext == PARSE_CONTEXT.METADATA)
                            {
                                _CurrentContext = PARSE_CONTEXT.ACTIVITY_TIME;
                            }
                            else if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_POINT_TIME;
                            }
                            break;

                        case "trk":
                            _CurrentContext      = PARSE_CONTEXT.TRACK;
                            _CurrentTrackBuilder = new TrackEntity.Builder();
                            break;

                        case "name":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_NAME;
                            }
                            break;

                        case "trkseg":
                            _CurrentContext             = PARSE_CONTEXT.TRACK_SEGMENT;
                            _CurrentTrackSegmentBuilder = new TrackSegmentEntity.Builder();
                            break;

                        case "trkpt":
                            _CurrentContext = PARSE_CONTEXT.TRACK_POINT;
                            float latitude;
                            var   style   = System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign;
                            var   culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
                            if (!float.TryParse(reader.GetAttribute("lat"), style, culture, out latitude))
                            {
                                break;
                            }
                            float longitude;
                            if (!float.TryParse(reader.GetAttribute("lon"), style, culture, out longitude))
                            {
                                break;
                            }
                            _CurrentTrackPointBuilder = new TrackPointVO.Builder()
                            {
                                Latitude  = latitude,
                                Longitude = longitude
                            };
                            break;

                        case "type":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_TYPE;
                            }
                            break;

                        case "ele":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_POINT_ELEVATION;
                            }
                            break;

                        case "extensions":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_POINT_EXTENSIONS;
                            }
                            break;

                        case "power":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_EXTENSIONS)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_POINT_POWER;
                            }
                            break;

                        default:
                            if (reader.Name == _XmlNamespaces["gpxtpx"] + "TrackPointExtension")
                            {
                                if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_EXTENSIONS)
                                {
                                    _CurrentContext = PARSE_CONTEXT.TRACK_POINT_GPXTPX_EXTENSION;
                                }
                            }
                            else if (reader.Name == _XmlNamespaces["gpxtpx"] + "atemp")
                            {
                                if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_GPXTPX_EXTENSION)
                                {
                                    _CurrentContext = PARSE_CONTEXT.TRACK_POINT_TEMPERATURE;
                                }
                            }
                            else if (reader.Name == _XmlNamespaces["gpxtpx"] + "hr")
                            {
                                if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_GPXTPX_EXTENSION)
                                {
                                    _CurrentContext = PARSE_CONTEXT.TRACK_POINT_HR;
                                }
                            }
                            else if (reader.Name == _XmlNamespaces["gpxtpx"] + "cad")
                            {
                                if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_GPXTPX_EXTENSION)
                                {
                                    _CurrentContext = PARSE_CONTEXT.TRACK_POINT_CADENCE;
                                }
                            }
                            break;
                        }
                        break;

                    case XmlNodeType.Text:
                        switch (_CurrentContext)
                        {
                        case PARSE_CONTEXT.ACTIVITY_TIME:
                            DateTimeOffset activityStartTime;
                            string         activityStartTimeAsString = reader.Value;
                            if (DateTimeOffset.TryParse(activityStartTimeAsString, out activityStartTime))
                            {
                                _Logger.Debug(string.Format("Activity start time {0}", activityStartTime));
                            }
                            else
                            {
                                _Logger.Error(string.Format("Error parsing date {0}", activityStartTimeAsString));
                            }
                            if (_CurrentActivityBuilder != null)
                            {
                                _CurrentActivityBuilder.Time = activityStartTime;
                                if (!string.IsNullOrEmpty(activityStartTimeAsString))
                                {
                                    _CurrentActivityBuilder.OriginId = $"{_CurrentCreator ?? ""}{activityStartTimeAsString}";
                                }
                            }
                            break;

                        case PARSE_CONTEXT.TRACK_POINT_TIME:
                            DateTimeOffset segmentTime;
                            string         segmentTimeAsString = reader.Value;
                            if (DateTimeOffset.TryParse(segmentTimeAsString, out segmentTime))
                            {
                                _Logger.Debug(string.Format("Segment start time {0}", segmentTime));
                            }
                            else
                            {
                                _Logger.Error(string.Format("Error parsing date {0}", segmentTimeAsString));
                            }
                            if (_CurrentTrackPointBuilder != null)
                            {
                                _CurrentTrackPointBuilder.Time = segmentTime;
                            }
                            break;

                        case PARSE_CONTEXT.TRACK_NAME:
                            if (_CurrentActivityBuilder != null)
                            {
                                _CurrentActivityBuilder.Name = reader.Value;
                            }
                            if (_CurrentTrackBuilder != null)
                            {
                                _CurrentTrackBuilder.Name = reader.Value;
                            }
                            break;

                        case PARSE_CONTEXT.TRACK_TYPE:
                            if (_CurrentActivityBuilder != null)
                            {
                                ACTIVITY_SPORT sport;
                                if (!categoryMapping.TryGetValue(reader.Value, out sport))
                                {
                                    sport = ACTIVITY_SPORT.OTHER;
                                }
                                if (_CurrentActivityBuilder != null)
                                {
                                    _CurrentActivityBuilder.Sport = sport;
                                }
                                _Logger.Debug(string.Format("Activity sport {0}", sport));
                            }
                            break;

                        case PARSE_CONTEXT.TRACK_POINT_ELEVATION:
                            if (_CurrentTrackPointBuilder != null)
                            {
                                float elevation;
                                var   style   = System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign;
                                var   culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
                                if (!float.TryParse(reader.Value, style, culture, out elevation))
                                {
                                    var countPoints = _CurrentTrackSegmentBuilder.TrackPoints.Count;
                                    elevation = countPoints > 0 ? _CurrentTrackSegmentBuilder.TrackPoints[countPoints - 1].Elevation : 0;
                                }
                                _CurrentTrackPointBuilder.Elevation = elevation;
                            }
                            break;

                        case PARSE_CONTEXT.TRACK_POINT_POWER:
                            if (_CurrentTrackPointBuilder != null)
                            {
                                int power;
                                if (!int.TryParse(reader.Value, out power))
                                {
                                    var countPoints = _CurrentTrackSegmentBuilder.TrackPoints.Count;
                                    power = countPoints > 0 ? _CurrentTrackSegmentBuilder.TrackPoints[countPoints - 1].Power : 0;
                                }
                                _CurrentTrackPointBuilder.Power = power;
                            }
                            break;

                        case PARSE_CONTEXT.TRACK_POINT_TEMPERATURE:
                            if (_CurrentTrackPointBuilder != null)
                            {
                                float temperature;
                                var   style   = System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign;
                                var   culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
                                if (!float.TryParse(reader.Value, style, culture, out temperature))
                                {
                                    var countPoints = _CurrentTrackSegmentBuilder.TrackPoints.Count;
                                    temperature = countPoints > 0 ? _CurrentTrackSegmentBuilder.TrackPoints[countPoints - 1].Temperature : 0;
                                }
                                _CurrentTrackPointBuilder.Temperature = temperature;
                            }
                            break;

                        case PARSE_CONTEXT.TRACK_POINT_HR:
                            if (_CurrentTrackPointBuilder != null)
                            {
                                int hr;
                                if (!int.TryParse(reader.Value, out hr))
                                {
                                    var countPoints = _CurrentTrackSegmentBuilder.TrackPoints.Count;
                                    hr = countPoints > 0 ? _CurrentTrackSegmentBuilder.TrackPoints[countPoints - 1].HeartRate : 0;
                                }
                                _CurrentTrackPointBuilder.HeartRate = hr;
                            }
                            break;

                        case PARSE_CONTEXT.TRACK_POINT_CADENCE:
                            if (_CurrentTrackPointBuilder != null)
                            {
                                int cadence;
                                if (!int.TryParse(reader.Value, out cadence))
                                {
                                    var countPoints = _CurrentTrackSegmentBuilder.TrackPoints.Count;
                                    cadence = countPoints > 0 ? _CurrentTrackSegmentBuilder.TrackPoints[countPoints - 1].Cadence : 0;
                                }
                                _CurrentTrackPointBuilder.Cadence = cadence;
                            }
                            break;
                        }
                        break;

                    case XmlNodeType.EndElement:
                        switch (reader.Name)
                        {
                        case "gpx":
                            var allPoints = _CurrentActivityBuilder.Tracks.SelectMany(track => track.TrackSegments.SelectMany(segment => segment.TrackPoints));
                            _CurrentActivityBuilder.HeartRate         = (int)Math.Round(allPoints.Where(point => point.HeartRate > 0).DefaultIfEmpty().Average(point => point?.HeartRate) ?? 0);
                            _CurrentActivityBuilder.Cadence           = (int)Math.Round(allPoints.Where(point => point.Cadence > 0).DefaultIfEmpty().Average(point => point?.Cadence) ?? 0);
                            _CurrentActivityBuilder.Power             = (int)Math.Round(allPoints.Where(point => point.Power > 0).DefaultIfEmpty().Average(point => point?.Power) ?? 0);
                            _CurrentActivityBuilder.Temperature       = (int)Math.Round(allPoints.Where(point => point.Temperature > 0).DefaultIfEmpty().Average(point => point?.Temperature) ?? 0);
                            _CurrentActivityBuilder.TracksPointsCount = allPoints.Count();
                            var activity = _CurrentActivityBuilder.Build();
                            _CurrentActivityBuilder = null;
                            _CurrentContext         = PARSE_CONTEXT.ROOT;
                            yield return(activity);

                            break;

                        case "time":
                            if (_CurrentContext == PARSE_CONTEXT.ACTIVITY_TIME)
                            {
                                _CurrentContext = PARSE_CONTEXT.METADATA;
                            }
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_TIME)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_POINT;
                            }
                            break;

                        case "metadata":
                            if (_CurrentContext == PARSE_CONTEXT.METADATA)
                            {
                                _CurrentContext = PARSE_CONTEXT.GPX;
                            }
                            break;

                        case "trk":
                            _CurrentContext = PARSE_CONTEXT.GPX;
                            if (_CurrentActivityBuilder != null && _CurrentTrackBuilder != null)
                            {
                                _CurrentActivityBuilder.Tracks.Add(_CurrentTrackBuilder.Build());
                            }
                            _CurrentTrackBuilder = null;
                            break;

                        case "name":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_NAME)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK;
                            }
                            break;

                        case "trkseg":
                            _CurrentContext = PARSE_CONTEXT.TRACK;
                            if (_CurrentTrackBuilder != null && _CurrentTrackSegmentBuilder != null)
                            {
                                _CurrentTrackBuilder.TrackSegments.Add(_CurrentTrackSegmentBuilder.Build());
                            }
                            _CurrentTrackSegmentBuilder = null;
                            break;

                        case "trkpt":
                            _CurrentContext = PARSE_CONTEXT.TRACK_SEGMENT;
                            if (_CurrentTrackSegmentBuilder != null && _CurrentTrackPointBuilder != null)
                            {
                                _CurrentTrackSegmentBuilder.TrackPoints.Add(_CurrentTrackPointBuilder.Build());
                            }
                            _CurrentTrackPointBuilder = null;
                            break;

                        case "type":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_TYPE)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK;
                            }
                            break;

                        case "ele":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_ELEVATION)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_POINT;
                            }
                            break;

                        case "extensions":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_EXTENSIONS)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_POINT;
                            }
                            break;

                        case "power":
                            if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_POWER)
                            {
                                _CurrentContext = PARSE_CONTEXT.TRACK_POINT_EXTENSIONS;
                            }
                            break;

                        default:
                            if (reader.Name == _XmlNamespaces["gpxtpx"] + "TrackPointExtension")
                            {
                                if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_GPXTPX_EXTENSION)
                                {
                                    _CurrentContext = PARSE_CONTEXT.TRACK_POINT_EXTENSIONS;
                                }
                            }
                            else if (reader.Name == _XmlNamespaces["gpxtpx"] + "atemp")
                            {
                                if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_TEMPERATURE)
                                {
                                    _CurrentContext = PARSE_CONTEXT.TRACK_POINT_GPXTPX_EXTENSION;
                                }
                            }
                            else if (reader.Name == _XmlNamespaces["gpxtpx"] + "hr")
                            {
                                if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_HR)
                                {
                                    _CurrentContext = PARSE_CONTEXT.TRACK_POINT_GPXTPX_EXTENSION;
                                }
                            }
                            else if (reader.Name == _XmlNamespaces["gpxtpx"] + "cad")
                            {
                                if (_CurrentContext == PARSE_CONTEXT.TRACK_POINT_CADENCE)
                                {
                                    _CurrentContext = PARSE_CONTEXT.TRACK_POINT_GPXTPX_EXTENSION;
                                }
                            }
                            break;
                        }
                        break;
                    }
                }
            }
        }
示例#3
0
        public IEnumerable <ActivityEntity> ImportActivitiesStream(Stream stream, IDictionary <string, ACTIVITY_SPORT> categoryMapping)
        {
            _Logger.Info("Importing data stream");
            XmlReaderSettings settings = new XmlReaderSettings
            {
                Async = false
            };

            using (XmlReader reader = XmlReader.Create(stream, settings))
            {
                // SAX parsing for performance
                while (reader.Read())
                {
                    switch (reader.NodeType)
                    {
                    case XmlNodeType.Element:
                        switch (reader.Name)
                        {
                        case "FitnessWorkbook":
                            _CurrentContext = PARSE_CONTEXT.FITNESS_WORKBOOK;
                            break;

                        case "AthleteLog":
                            _CurrentContext = PARSE_CONTEXT.ATHLETE_LOG;
                            break;

                        case "Athlete":
                            _CurrentContext = PARSE_CONTEXT.ATHLETE;
                            //_CurrentAthlete = new AthleteEntity(new List<ActivityVO>(), reader.GetAttribute("Name"), reader.GetAttribute("Id"));
                            break;

                        case "Activity":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY;
                            DateTimeOffset activityStartTime;
                            string         activityStartTimeAsString = reader.GetAttribute("StartTime");
                            if (DateTimeOffset.TryParse(activityStartTimeAsString, out activityStartTime))
                            {
                                _Logger.Debug(string.Format("Activity start time {0}", activityStartTime));
                            }
                            else
                            {
                                _Logger.Error(string.Format("Error parsing date {0}", activityStartTimeAsString));
                            }
                            _CurrentActivityBuilder = new ActivityEntity.Builder
                            {
                                OriginId     = reader.GetAttribute("Id"),
                                OriginSystem = "FITLOG",
                                Time         = activityStartTime
                            };
                            break;

                        case "Metadata":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_METADATA;
                            break;

                        case "Calories":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_CALORIES;
                            int calories;
                            if (int.TryParse(reader.GetAttribute("TotalCal"), out calories))
                            {
                                if (_CurrentActivityBuilder != null)
                                {
                                    _CurrentActivityBuilder.Calories = calories;
                                }
                                _Logger.Debug(string.Format("Activity calories {0}", calories));
                            }
                            break;

                        case "Name":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_NAME;
                            break;

                        case "Category":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_CATEGORY;
                            string         category = reader.GetAttribute("Id");
                            ACTIVITY_SPORT sport;
                            if (!categoryMapping.TryGetValue(category, out sport))
                            {
                                sport = ACTIVITY_SPORT.OTHER;
                            }
                            if (_CurrentActivityBuilder != null)
                            {
                                _CurrentActivityBuilder.Sport = sport;
                            }
                            _Logger.Debug(string.Format("Activity sport {0}", sport));
                            break;

                        case "Location":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_LOCATION;
                            string location = reader.GetAttribute("Name");
                            if (_CurrentActivityBuilder != null)
                            {
                                _CurrentActivityBuilder.Location = location;
                            }
                            _Logger.Debug(string.Format("Activity location {0}", location));
                            break;

                        case "EquipmentUsed":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_EQUIPMENT_USED;
                            break;

                        case "EquipmentItem":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_EQUIPMENT_ITEM;
                            break;

                        case "Track":
                            _CurrentContext             = PARSE_CONTEXT.ACTIVITY_TRACK;
                            _CurrentTrackSegmentBuilder = new TrackSegmentEntity.Builder();
                            string         startTimeAsString = reader.GetAttribute("StartTime");
                            DateTimeOffset startTime;
                            if (DateTimeOffset.TryParse(startTimeAsString, out startTime))
                            {
                                _CurrentTrackStartTime = startTime;
                                _Logger.Debug(string.Format("Track start time {0}", startTime));
                            }
                            else
                            {
                                _Logger.Error(string.Format("Track parsing date {0}", startTimeAsString));
                            }
                            break;

                        case "pt":
                            if (_CurrentTrackSegmentBuilder == null)
                            {
                                break;
                            }
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_TRACK_PT;
                            int tm;
                            var tmAsString = reader.GetAttribute("tm");
                            if (int.TryParse(tmAsString, out tm))
                            {
                                _LastTrackTime = _CurrentTrackStartTime.AddSeconds(tm);
                            }
                            else
                            {
                                _Logger.Error(string.Format("Error parsing tm (number of seconds since start {0}", tmAsString));
                                break;
                            }
                            float latitude;
                            var   style   = System.Globalization.NumberStyles.AllowDecimalPoint | System.Globalization.NumberStyles.AllowLeadingSign;
                            var   culture = System.Globalization.CultureInfo.CreateSpecificCulture("en-US");
                            if (!float.TryParse(reader.GetAttribute("lat"), style, culture, out latitude))
                            {
                                break;
                            }
                            float longitude;
                            if (!float.TryParse(reader.GetAttribute("lon"), style, culture, out longitude))
                            {
                                break;
                            }
                            float elevation;
                            if (!float.TryParse(reader.GetAttribute("ele"), style, culture, out elevation))
                            {
                                var countPoints = _CurrentTrackSegmentBuilder.TrackPoints.Count;
                                elevation = countPoints > 0 ? _CurrentTrackSegmentBuilder.TrackPoints[countPoints - 1].Elevation : 0;
                            }
                            int hr;
                            if (!int.TryParse(reader.GetAttribute("hr"), out hr))
                            {
                                var countPoints = _CurrentTrackSegmentBuilder.TrackPoints.Count;
                                hr = countPoints > 0 ? _CurrentTrackSegmentBuilder.TrackPoints[countPoints - 1].HeartRate : 0;
                            }
                            int cadence;
                            if (!int.TryParse(reader.GetAttribute("cadence"), out cadence))
                            {
                                var countPoints = _CurrentTrackSegmentBuilder.TrackPoints.Count;
                                cadence = countPoints > 0 ? _CurrentTrackSegmentBuilder.TrackPoints[countPoints - 1].Cadence : 0;
                            }
                            TrackPointVO trackPoint = new TrackPointVO.Builder
                            {
                                Time      = _LastTrackTime,
                                Latitude  = latitude,
                                Longitude = longitude,
                                Elevation = elevation,
                                HeartRate = hr,
                                Cadence   = cadence
                            };
                            _CurrentTrackSegmentBuilder.TrackPoints.Add(trackPoint);
                            _Logger.Trace(string.Format("Trackpoint time {0}, latitude {1}, longitude {2}, elevation {3}, heart-rate {4}, cadence {5}",
                                                        _LastTrackTime, latitude, longitude, elevation, hr, cadence));
                            break;
                        }
                        break;

                    case XmlNodeType.Text:
                        switch (_CurrentContext)
                        {
                        case PARSE_CONTEXT.ACTIVITY_NAME:
                            var name = reader.Value;
                            if (_CurrentActivityBuilder != null)
                            {
                                _CurrentActivityBuilder.Name = name;
                            }
                            _Logger.Debug(string.Format("Activity name {0}", name));
                            break;
                        }
                        break;

                    case XmlNodeType.EndElement:
                        switch (reader.Name)
                        {
                        case "FitnessWorkbook":
                            _CurrentContext = PARSE_CONTEXT.ROOT;
                            break;

                        case "AthleteLog":
                            _CurrentContext = PARSE_CONTEXT.FITNESS_WORKBOOK;
                            break;

                        case "Athlete":
                            _CurrentContext = PARSE_CONTEXT.FITNESS_WORKBOOK;
                            break;

                        case "Activity":
                            _CurrentContext = PARSE_CONTEXT.FITNESS_WORKBOOK;
                            if (_LastTrackTime != DateTimeOffset.MinValue && _CurrentActivityBuilder.Time != null)
                            {
                                _CurrentActivityBuilder.TimeSpan = _LastTrackTime - _CurrentActivityBuilder.Time;
                            }
                            var allPoints = _CurrentActivityBuilder.Tracks.SelectMany(track => track.TrackSegments.SelectMany(s => s.TrackPoints));
                            _CurrentActivityBuilder.HeartRate         = (int)Math.Round(allPoints.Where(point => point.HeartRate > 0).DefaultIfEmpty().Average(point => point?.HeartRate) ?? 0);
                            _CurrentActivityBuilder.Cadence           = (int)Math.Round(allPoints.Where(point => point.Cadence > 0).DefaultIfEmpty().Average(point => point?.Cadence) ?? 0);
                            _CurrentActivityBuilder.Power             = (int)Math.Round(allPoints.Where(point => point.Power > 0).DefaultIfEmpty().Average(point => point?.Power) ?? 0);
                            _CurrentActivityBuilder.Temperature       = (int)Math.Round(allPoints.Where(point => point.Temperature > 0).DefaultIfEmpty().Average(point => point?.Temperature) ?? 0);
                            _CurrentActivityBuilder.TracksPointsCount = allPoints.Count();
                            var activity = _CurrentActivityBuilder.Build();
                            _CurrentActivityBuilder = null;
                            _LastTrackTime          = DateTimeOffset.MinValue;
                            yield return(activity);

                            break;

                        case "Metadata":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY;
                            break;

                        case "Calories":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY;
                            break;

                        case "Name":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY;
                            break;

                        case "Category":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY;
                            break;

                        case "Location":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY;
                            break;

                        case "EquipmentUsed":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY;
                            break;

                        case "EquipmentItem":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_EQUIPMENT_USED;
                            break;

                        case "Track":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY;
                            var segment      = _CurrentTrackSegmentBuilder.Build();
                            var trackBuilder = new TrackEntity.Builder();
                            trackBuilder.TrackSegments.Add(segment);
                            if (_CurrentActivityBuilder != null)
                            {
                                _CurrentActivityBuilder.Tracks.Add(trackBuilder.Build());
                            }
                            _CurrentTrackSegmentBuilder = null;
                            break;

                        case "pt":
                            _CurrentContext = PARSE_CONTEXT.ACTIVITY_TRACK;
                            break;
                        }
                        //_LoggerService.Debug(string.Format("End Element {0}", reader.Name));
                        break;

                    default:
                        //_LoggerService.Debug(string.Format("Other node {0} with value {1}",
                        //    reader.NodeType, reader.Value));
                        break;
                    }
                }
            }
            _Logger.Info("Imported data stream");
        }