Пример #1
0
        private static Record GetDistancePaceRecord(IActivity activity, RecordCategory category)
        {
            float fastestSpeed = 0;
            float currentSpeed;
            float currentDistance = 0;

            if (activity.GPSRoute != null && activity.GPSRoute.TotalElapsedSeconds > 0 && ActivityInfoCache.Instance.GetInfo(activity).DistanceMetersMoving >= category.Meters)
            {
                int           recordStart = 0, recordEnd = 0, startIndex, endIndex = 0;
                List <double> p2pDistance = new List <double>();

                // Go through each starting point
                for (startIndex = 0; startIndex < activity.GPSRoute.Count; startIndex++)
                {
                    // Find end GPS point that's the proper distance away
                    while (currentDistance <= category.Meters)
                    {
                        endIndex += 1;

                        // Typical return point.  End has exceeded route.  Construct and return record for this activity/category.
                        if (endIndex >= activity.GPSRoute.Count)
                        {
                            // Construct record GPS route
                            GPSRoute recordGPS = new GPSRoute();
                            NumericTimeDataSeries recordHRTrack = new NumericTimeDataSeries();
                            NumericTimeDataSeries pwrTrack      = new NumericTimeDataSeries();
                            NumericTimeDataSeries elevTrack     = new NumericTimeDataSeries();
                            NumericTimeDataSeries cadTrack      = new NumericTimeDataSeries();
                            DistanceDataTrack     distTrack     = new DistanceDataTrack();

                            for (int i = recordStart; i <= recordEnd; i++)
                            {
                                // Record information/statistics
                                DateTime time = activity.GPSRoute.EntryDateTime(activity.GPSRoute[i]);

                                recordGPS.Add(time, activity.GPSRoute[i].Value);
                                if (activity.HeartRatePerMinuteTrack != null &&
                                    activity.HeartRatePerMinuteTrack.StartTime <= time &&
                                    activity.HeartRatePerMinuteTrack.StartTime.AddSeconds(activity.HeartRatePerMinuteTrack.TotalElapsedSeconds) >= time)
                                {
                                    recordHRTrack.Add(time, activity.HeartRatePerMinuteTrack.GetInterpolatedValue(time).Value);
                                }

                                if (activity.PowerWattsTrack != null &&
                                    activity.PowerWattsTrack.StartTime <= time &&
                                    activity.PowerWattsTrack.StartTime.AddSeconds(activity.PowerWattsTrack.TotalElapsedSeconds) >= time)
                                {
                                    pwrTrack.Add(time, activity.PowerWattsTrack.GetInterpolatedValue(time).Value);
                                }

                                if (activity.CadencePerMinuteTrack != null &&
                                    activity.CadencePerMinuteTrack.StartTime <= time &&
                                    activity.CadencePerMinuteTrack.StartTime.AddSeconds(activity.CadencePerMinuteTrack.TotalElapsedSeconds) >= time)
                                {
                                    cadTrack.Add(time, activity.CadencePerMinuteTrack.GetInterpolatedValue(time).Value);
                                }

                                if (activity.DistanceMetersTrack != null &&
                                    activity.DistanceMetersTrack.StartTime <= time &&
                                    activity.DistanceMetersTrack.StartTime.AddSeconds(activity.DistanceMetersTrack.TotalElapsedSeconds) >= time)
                                {
                                    distTrack.Add(time, activity.DistanceMetersTrack.GetInterpolatedValue(time).Value);
                                }

                                if (activity.ElevationMetersTrack != null &&
                                    activity.ElevationMetersTrack.StartTime <= time &&
                                    activity.ElevationMetersTrack.StartTime.AddSeconds(activity.ElevationMetersTrack.TotalElapsedSeconds) >= time)
                                {
                                    elevTrack.Add(time, activity.ElevationMetersTrack.GetInterpolatedValue(time).Value);
                                }
                            }

                            // Return record
                            Record record = new Record(activity, category, recordGPS, recordHRTrack, pwrTrack, cadTrack, distTrack, elevTrack);
                            return(record);
                        }
                        else
                        {
                            // Add to end of route until category distance is found
                            currentDistance += activity.GPSRoute[endIndex].Value.DistanceMetersToPoint(activity.GPSRoute[endIndex - 1].Value);
                        }
                    }

                    // In meters / second
                    currentSpeed = currentDistance / (activity.GPSRoute[endIndex].ElapsedSeconds - activity.GPSRoute[startIndex].ElapsedSeconds);

                    // Store fastest info (in meters / second)
                    if (fastestSpeed < currentSpeed)
                    {
                        fastestSpeed = currentSpeed;
                        recordStart  = startIndex;
                        recordEnd    = endIndex;
                    }

                    // Remove first point from routeDistance, and go to next starting point.
                    currentDistance -= activity.GPSRoute[startIndex].Value.DistanceMetersToPoint(activity.GPSRoute[startIndex + 1].Value);
                }
            }

            // Activity does not contain GPS data or not long enough
            return(null);
        }
Пример #2
0
        /// <summary>
        /// Used to generate the record properties of the supplied activity
        /// </summary>
        /// <param name="activity">The full activity for the record</param>
        /// <param name="category">The Record Category for this record</param>
        /// <param name="gpsTrack">The GPS route of the actual record</param>
        /// <param name="hrTrack">The HR track of the actual record</param>
        /// <param name="pwrTrack">The power track of the actual record</param>
        /// <param name="cadTrack">The cadence track of the actual record</param>
        public Record(IActivity activity, RecordCategory category, IGPSRoute gpsTrack, INumericTimeDataSeries hrTrack, INumericTimeDataSeries pwrTrack, INumericTimeDataSeries cadTrack, IDistanceDataTrack distTrack, INumericTimeDataSeries elevTrack, DateTime activityStartTime)
        {
            // Create new activity from template
            IActivity recActivity = (IActivity)Activator.CreateInstance(activity.GetType());

            // HACK: Manually Clone 'activity' until a better way is found
            recActivity.Category                = activity.Category;
            recActivity.DistanceMetersTrack     = distTrack;
            recActivity.ElevationMetersTrack    = elevTrack;
            recActivity.GPSRoute                = gpsTrack;
            recActivity.HasStartTime            = activity.HasStartTime;
            recActivity.HeartRatePerMinuteTrack = hrTrack;
            recActivity.Intensity               = activity.Intensity;
            recActivity.Location                = activity.Location;
            recActivity.Name                                 = activity.Name;
            recActivity.PowerWattsTrack                      = pwrTrack;
            recActivity.CadencePerMinuteTrack                = cadTrack;
            recActivity.Weather.Conditions                   = activity.Weather.Conditions;
            recActivity.Weather.CurentDirectionDegrees       = activity.Weather.CurentDirectionDegrees;
            recActivity.Weather.CurentSpeedKilometersPerHour = activity.Weather.CurentSpeedKilometersPerHour;
            recActivity.Weather.HumidityPercent              = activity.Weather.HumidityPercent;
            recActivity.Weather.TemperatureCelsius           = activity.Weather.TemperatureCelsius;
            recActivity.Weather.WindDirectionDegrees         = activity.Weather.WindDirectionDegrees;
            recActivity.Weather.WindSpeedKilometersPerHour   = activity.Weather.WindSpeedKilometersPerHour;

            // Set the start time for the record activity
            recActivity.StartTime = activityStartTime;

            // Set up the activity info for pulling summary data
            ActivityInfo info = ActivityInfoCache.Instance.GetInfo(recActivity);

            // Set the record category
            this.category = category;

            // Max and Min elevation seen over the route
            float maxE = float.NegativeInfinity;
            float minE = float.PositiveInfinity;

            if (activity.GPSRoute != null && activity.GPSRoute.Count > 0)
            {
                GPSRoute startRoute = new GPSRoute();
                for (int i = 0; i < activity.GPSRoute.Count; i++)
                {
                    GPSPoint p = (GPSPoint)activity.GPSRoute[i].Value;
                    if (p.ElevationMeters > maxE)
                    {
                        maxE = p.ElevationMeters;
                    }

                    if (p.ElevationMeters < minE)
                    {
                        minE = p.ElevationMeters;
                    }

                    if (gpsTrack.Count == 0)
                    {
                        break;
                    }

                    if (p.Equals((GPSPoint)gpsTrack[0].Value))
                    {
                        break;
                    }
                    else
                    {
                        startRoute.Add(activity.GPSRoute.EntryDateTime(activity.GPSRoute[i]), p);
                    }
                }
                startDistance = startRoute.TotalDistanceMeters;
            }
            else if (activity.ElevationMetersTrack != null)
            {
                for (int i = 0; i < activity.ElevationMetersTrack.Count; i++)
                {
                    if (activity.ElevationMetersTrack[i].Value > maxE)
                    {
                        maxE = activity.ElevationMetersTrack[i].Value;
                    }

                    if (activity.ElevationMetersTrack[i].Value < maxE)
                    {
                        minE = activity.ElevationMetersTrack[i].Value;
                    }
                }
                startDistance = 0;
            }

            this.maxElevation  = maxE;
            this.minElevation  = minE;
            this.trueStartDate = activity.StartTime;
            this.activity      = recActivity;
        }
Пример #3
0
        //public IDistanceDataTrack GetSmoothedDistanceTrack(int seconds, out float min, out float max)
        //{
        //    IDistanceDataTrack distanceTrack;
        //    if (record.Activity.DistanceMetersTrack != null)
        //    {
        //        // #1 Use Distance track from activity
        //        distanceTrack = record.Activity.DistanceMetersTrack;
        //    }
        //    else
        //    {
        //        if (record.Activity.GPSRoute != null)
        //        {
        //            // #2 Otherwise create a distance track from GPS
        //            distanceTrack = Utilities.CreateDistanceDataTrack(record.Activity);
        //            return Utilities.STSmooth(distanceTrack, seconds, min, max);
        //        }
        //        else
        //        {
        //            // Else, no distance track, and cannot create one.
        //            distanceTrack = new DistanceDataTrack();
        //        }
        //    }
        //}

        //public INumericTimeDataSeries GetSmoothedGradeTrack(int seconds, out float min, out float max)
        //{
        //    NumericTimeDataSeries gradeTrack = new NumericTimeDataSeries();
        //    for (int i = 0; i < record.Activity.ElevationMetersTrack.Count; i++)
        //    {
        //        if (i == 0)
        //        {
        //            gradeTrack.Add(record.Activity.ElevationMetersTrack[i].ElapsedSeconds, 0);
        //        }
        //    }
        //}

        #region Constructors

        public Feature(IActivity activity, feature_type type, DateTime inStartTime, DateTime inEndTime)
        {
            startTime        = inStartTime;
            endTime          = inEndTime;
            added            = false;
            hillNumber       = 0;
            _feature_type    = type;
            masterActivityID = activity.ReferenceId;

            // Default fill and line color
            fillColor     = Color.FromArgb(125, 146, 94, 9);
            lineColor     = Color.FromArgb(255, 146, 94, 9);
            lineWidth     = 1;
            selectedColor = Color.Empty;
            routeWidth    = PluginMain.GetApplication().SystemPreferences.RouteSettings.RouteWidth;

            IGPSRoute recordGPS = new GPSRoute();
            INumericTimeDataSeries recordHRTrack = new NumericTimeDataSeries();
            INumericTimeDataSeries pwrTrack      = new NumericTimeDataSeries();
            INumericTimeDataSeries elevTrack     = new NumericTimeDataSeries();
            INumericTimeDataSeries cadTrack      = new NumericTimeDataSeries();
            IDistanceDataTrack     distTrack     = new DistanceDataTrack();
            RecordCategory         category      = new RecordCategory();

            ActivityInfo ai    = ActivityInfoCache.Instance.GetInfo(activity);
            DateTime     start = activity.StartTime;

            if (activity.GPSRoute != null)
            {
                // Check and make sure the route has points
                if (activity.GPSRoute.Count > 0)
                {
                    // If the time passed in is before the start of the gps track, get the first value
                    if (activity.GPSRoute.StartTime > inStartTime)
                    {
                        startPoint = activity.GPSRoute[0].Value;
                    }
                    else
                    {
                        // Set the start point
                        ITimeValueEntry <IGPSPoint> sPoint = activity.GPSRoute.GetInterpolatedValue(inStartTime);
                        if (sPoint != null)
                        {
                            startPoint = sPoint.Value;
                        }
                    }

                    // If the time passed in is after the end of the gps track, get the last value
                    if (activity.GPSRoute.StartTime.AddSeconds(activity.GPSRoute[activity.GPSRoute.Count - 1].ElapsedSeconds) < inEndTime)
                    {
                        endPoint = activity.GPSRoute[activity.GPSRoute.Count - 1].Value;
                    }
                    else
                    {
                        // Set the end point
                        ITimeValueEntry <IGPSPoint> ePoint = activity.GPSRoute.GetInterpolatedValue(inEndTime);
                        if (ePoint != null)
                        {
                            endPoint = ePoint.Value;
                        }
                    }
                }


                // Create the GPSRoute
                for (int i = 0; i < activity.GPSRoute.Count; i++)
                {
                    if (activity.GPSRoute.StartTime.AddSeconds(activity.GPSRoute[i].ElapsedSeconds) >= inStartTime &&
                        activity.GPSRoute.StartTime.AddSeconds(activity.GPSRoute[i].ElapsedSeconds) <= inEndTime)
                    {
                        recordGPS.Add(activity.GPSRoute.StartTime.AddSeconds(activity.GPSRoute[i].ElapsedSeconds), activity.GPSRoute[i].Value);
                    }
                }
            }

            // Create the Distance Track
            INumericTimeDataSeries allDistanceTrack  = ai.MovingDistanceMetersTrack; // Utilities.GetDistanceTrack(activity);
            INumericTimeDataSeries allElevationTrack = ai.SmoothedElevationTrack;    // Utilities.GetElevationTrack(activity);

            // Work your way through the moving meters track to create all others
            if (allDistanceTrack != null)
            {
                for (int i = 0; i < allDistanceTrack.Count; i++)
                {
                    DateTime time = allDistanceTrack.StartTime.AddSeconds(allDistanceTrack[i].ElapsedSeconds);
                    if (time >= inStartTime &&
                        time <= inEndTime)
                    {
                        // Add the distance point
                        distTrack.Add(time, allDistanceTrack[i].Value);
                        ITimeValueEntry <float> point = null;

                        // Find the elevation point at this time and add it
                        if (allElevationTrack != null && allElevationTrack.Count > 0)
                        {
                            point = allElevationTrack.GetInterpolatedValue(time);
                            if (point != null)
                            {
                                elevTrack.Add(time, point.Value);
                            }
                        }

                        // Find the HR point at this time and add it
                        if (activity.HeartRatePerMinuteTrack != null && activity.HeartRatePerMinuteTrack.Count > 0)
                        {
                            point = activity.HeartRatePerMinuteTrack.GetInterpolatedValue(time);
                            if (point != null)
                            {
                                recordHRTrack.Add(time, point.Value);
                            }
                        }

                        // Find the power point at this time and add it
                        if (activity.PowerWattsTrack != null && activity.PowerWattsTrack.Count > 0)
                        {
                            point = activity.PowerWattsTrack.GetInterpolatedValue(time);
                            if (point != null)
                            {
                                pwrTrack.Add(time, point.Value);
                            }
                        }

                        // Find the cadence point at this time and add it
                        if (activity.CadencePerMinuteTrack != null && activity.CadencePerMinuteTrack.Count > 0)
                        {
                            point = activity.CadencePerMinuteTrack.GetInterpolatedValue(time);
                            if (point != null)
                            {
                                cadTrack.Add(time, point.Value);
                            }
                        }
                    }
                    else if (allDistanceTrack.StartTime.AddSeconds(allDistanceTrack[i].ElapsedSeconds) > inEndTime)
                    {
                        break;
                    }
                }
            }

            // Get the start/end distance
            if (distTrack != null && distTrack.Count > 0)
            {
                startDistance = distTrack[0].Value;
                endDistance   = distTrack[distTrack.Count - 1].Value;
            }
            else
            {
                startDistance = 0;
                endDistance   = 0;
            }

            // Get the start/end elevation
            if (elevTrack != null && elevTrack.Count > 0)
            {
                startElevation = elevTrack[0].Value;
                endElevation   = elevTrack[elevTrack.Count - 1].Value;
            }
            else
            {
                startElevation = 0;
                endElevation   = 0;
            }

            // Build the record
            record = new Record(activity, category, recordGPS, recordHRTrack, pwrTrack, cadTrack, distTrack, elevTrack, inStartTime);

            // Create a reference id for this hill
            refId = Guid.NewGuid().ToString("D");

            double distanceX = endDistance - startDistance;

            distance = distanceX;

            double elev = endElevation - startElevation;

            elevGain = elev;

            // Find the start percents from the distance track
            if (allDistanceTrack != null && allDistanceTrack.Count > 0)
            {
                startPercentDistance = startDistance / allDistanceTrack[allDistanceTrack.Count - 1].Value;
                endPercentDistance   = endDistance / allDistanceTrack[allDistanceTrack.Count - 1].Value;

                startPercentTime = ((inStartTime - allDistanceTrack.StartTime).TotalSeconds / allDistanceTrack[allDistanceTrack.Count - 1].ElapsedSeconds);
                endPercentTime   = ((inEndTime - allDistanceTrack.StartTime).TotalSeconds / allDistanceTrack[allDistanceTrack.Count - 1].ElapsedSeconds);
            }

            // Calculate the VAM (Velocity Ascended, Meters per hour)
            // Calculate the W/kg (Relative power)
            vam = 0;
            wKg = 0;
            if (elevGain > 0)
            {
                vam = (elevGain * 60f * 60f) / record.TotalTime.TotalSeconds;
                wKg = vam / ((2 + (avgGrade * 10f)) * 100f);
            }

            ActivityInfo aiRec = ActivityInfoCache.Instance.GetInfo(record.Activity);

            stoppedTime = aiRec.TimeNotMoving;
        }
Пример #4
0
        // Use the GPS track as a base when creating the TrackPoints.
        // Use heartbeat data if available
        private TrackPoint[] GetTrackPointsFromGPSTrack(IActivity activity)
        {
            if (activity.GPSRoute == null)
                return null;
            List<TrackPoint> tps = new List<TrackPoint>();
            double accDistance = 0;
            ITimeValueEntry<IGPSPoint> prevPoint = null;

            // Removing GPS points at identical time is a workaround for the funbeat server not being able to handle them
            // Ought to be fixed on the server side
            IGPSRoute ActGPSRoute = new GPSRoute(activity.GPSRoute);
            ActGPSRoute.AllowMultipleAtSameTime = false;

            foreach (ITimeValueEntry<IGPSPoint> p in ActGPSRoute)
            {

                TrackPoint tp = new TrackPoint();
                if (p == ActGPSRoute[0])
                    tp.isStartPoint = true;
                tp.TimeStamp = ConvertToLocalTime(ActGPSRoute.StartTime.AddSeconds(p.ElapsedSeconds));

                DateTime actualTime = ActGPSRoute.StartTime.AddSeconds(p.ElapsedSeconds);

                // Get heartrate track
                if (activity.HeartRatePerMinuteTrack != null)
                {
                    if (actualTime < activity.HeartRatePerMinuteTrack.StartTime)
                        actualTime = activity.HeartRatePerMinuteTrack.StartTime;

                    ITimeValueEntry<float> interpolatedHR = activity.HeartRatePerMinuteTrack.GetInterpolatedValue(actualTime);
                    if (interpolatedHR != null)
                    {
                        float heartRate = interpolatedHR.Value;
                        tp.HR = Convert.ToInt32(heartRate);
                    }
                    else
                    {
                        tp.HR = null;
                    }
                }
                else
                {
                    tp.HR = null;
                }

                // Get cadence track
                if (activity.CadencePerMinuteTrack != null)
                {
                    if (actualTime < activity.CadencePerMinuteTrack.StartTime)
                        actualTime = activity.CadencePerMinuteTrack.StartTime;

                    ITimeValueEntry<float> interpolatedCadence = activity.CadencePerMinuteTrack.GetInterpolatedValue(actualTime);
                    if (interpolatedCadence != null)
                    {
                        float cadence = interpolatedCadence.Value;
                        tp.Cad = Convert.ToInt32(cadence);
                        if (double.IsNaN((double)tp.Cad))
                        {
                            tp.Cad = null;
                        }
                    }
                    else
                    {
                        tp.Cad = null;
                    }
                }
                else
                {
                    tp.Cad = null;
                }

                tp.Latitude = Convert.ToDouble(p.Value.LatitudeDegrees);
                tp.Longitude = Convert.ToDouble(p.Value.LongitudeDegrees);
                tp.Altitude = Convert.ToDouble(p.Value.ElevationMeters);
                if (double.IsNaN((double)tp.Altitude))
                {
                    tp.Altitude = null;
                }

                if (prevPoint != null)
                    accDistance += p.Value.DistanceMetersToPoint(prevPoint.Value);
                tp.Distance = accDistance / 1000;

                tps.Add(tp);
                prevPoint = p;
            }
            return tps.ToArray();
        }