public static Dictionary <int, TrackSectorViewModel> ToTrackSectors(this IList <LapDataPointViewModel> lapDataPoints)
        {
            if (lapDataPoints.Count() < 3)
            {
                return(new Dictionary <int, TrackSectorViewModel>());
            }
            int lastDataPointInFirstSectorIndex               = (lapDataPoints.Count() / 3) - 1;
            int lastDataPointInSecondSectorIndex              = lastDataPointInFirstSectorIndex * 2;
            LapDataPointViewModel lastDataPointInFirstSector  = null;
            LapDataPointViewModel lastDataPointInSecondSector = null;
            LapDataPointViewModel lastDataPointInFinalSector  = null;

            for (int i = 0 + 1; i < lapDataPoints.Count(); i++)
            {
                var dataPoint = lapDataPoints[i];
                if (i <= lastDataPointInFirstSectorIndex)
                {
                    if (dataPoint.Latitude.HasValue && dataPoint.Longitude.HasValue && dataPoint.Heading.HasValue)
                    {
                        lastDataPointInFirstSector = dataPoint;
                    }
                }
                else if (i <= lastDataPointInSecondSectorIndex)
                {
                    if (dataPoint.Latitude.HasValue && dataPoint.Longitude.HasValue && dataPoint.Heading.HasValue)
                    {
                        lastDataPointInSecondSector = dataPoint;
                    }
                    dataPoint.SectorNumber = 2;
                }
                else
                {
                    if (dataPoint.Latitude.HasValue && dataPoint.Longitude.HasValue && dataPoint.Heading.HasValue)
                    {
                        lastDataPointInFinalSector = dataPoint;
                    }
                    dataPoint.SectorNumber = 3;
                }
            }

            if (lastDataPointInFirstSector == null || lastDataPointInSecondSector == null || lastDataPointInFinalSector == null)
            {
                return(new Dictionary <int, TrackSectorViewModel>());
            }

            var firstSector  = lastDataPointInFirstSector.ToTrackSector(1);
            var secondSector = lastDataPointInSecondSector.ToTrackSector(2);
            var finalSector  = lastDataPointInFinalSector.ToTrackSector(3, true);

            return(new Dictionary <int, TrackSectorViewModel> {
                { 1, firstSector }, { 2, secondSector }, { 3, finalSector }
            });
        }
Beispiel #2
0
        private void geolocator_PositionChanged(IGeolocator sender, PositionChangedEventArgs args)
        {
            if (!isTiming && isFirstReading)
            {
                // Speed threshold for starting timing - 4m/s
#if DEBUG
                if (!args.Position.Speed.HasValue || double.IsNaN(args.Position.Speed.Value) || args.Position.Speed.Value < 0.5d)
                {
                    return;
                }
#else
                if (!args.Position.Speed.HasValue || double.IsNaN(args.Position.Speed.Value) || args.Position.Speed.Value < 4d)
                {
                    return;
                }
#endif
                isFirstReading = false;
                stopwatch.Start();
                isTiming = true;
                if (TimingStarted != null)
                {
                    TimingStarted(this, null);
                }
            }

            var    elapsedTime      = stopwatch.Elapsed;
            double?speedInUserUnits = args.Position.Speed.HasValue && !double.IsNaN(args.Position.Speed.Value)
                                        ? isMetricUnits
                                            ? args.Position.Speed * Constants.KMH_TO_METRES_PER_SECOND
                                            : args.Position.Speed * Constants.KMH_TO_METRES_PER_SECOND / Constants.MILES_TO_KILOMETRES
                                        : null;

            var newGeographicLapDataPoint = new LapDataPointViewModel
            {
                ElapsedTime  = elapsedTime,
                Altitude     = args.Position.Altitude.HasValue && !double.IsNaN(args.Position.Altitude.Value) ?  args.Position.Altitude : null,
                Heading      = args.Position.Heading.HasValue && !double.IsNaN(args.Position.Heading.Value) ?  args.Position.Heading : null,
                Latitude     = args.Position.Latitude,
                Longitude    = args.Position.Longitude,
                Speed        = speedInUserUnits,
                SectorNumber = currentSector != null ? currentSector.SectorNumber : 1,
                Timestamp    = args.Position.Timestamp.ToLocalTime()
            };
            lapCoordinates.Add(newGeographicLapDataPoint);
            // Assuming this adding to the end of the list for performance
            int possibleLapEndGeographicLapDataPointIndex = lastGeographicLapDataPointIndex;
            lastGeographicLapDataPointIndex = lapCoordinates.Count - 1;

            bool skipCurrentCoordinate = false;
            if (generateSectors && currentSector == null)
            {
                skipCurrentCoordinate = true;
                if (newGeographicLapDataPoint.Heading.HasValue)
                {
                    double?lastHeading = headingNormalisation.Any() ? headingNormalisation.Last() : (double?)null;
                    headingNormalisation.Add(newGeographicLapDataPoint.Heading.Value);
                    if (lastHeading.HasValue && HeadingIsWithinRange(lastHeading.Value, newGeographicLapDataPoint.Heading.Value, 30d))
                    {
                        currentSector = newGeographicLapDataPoint.ToTrackSector(1, true);
                    }
                }
            }

            if (skipCurrentCoordinate)
            {
                return;
            }

            int  currentSectorNumber         = currentSector.SectorNumber;
            bool sectorCompleted             = PositionCompletesSector(newGeographicLapDataPoint, lastGeographicLapDataPoint, currentSector);
            var  possibleSectorEndCoordinate = lastGeographicLapDataPoint;
            lastGeographicLapDataPoint = newGeographicLapDataPoint;
            bool lapComplete = false;
            if (sectorCompleted)
            {
                lapComplete = currentSector.IsFinishLine;
                int nextSectorNumber = currentSectorNumber + 1;
                if (nextSectorNumber > lastSectorNumber)
                {
                    nextSectorNumber = firstSectorNumber;
                }

                // Fix the sector number for the current point, i.e. Move it over into the next sector and possibleSectorEndCoordinate is the end of the last sector
                newGeographicLapDataPoint.SectorNumber = nextSectorNumber;

                if (sectorCoordinates.Any())
                {
                    currentSector = sectorCoordinates.Single(s => s.SectorNumber == nextSectorNumber);
                }
                else
                {
                    lapComplete = true;
                }

                if (!lapComplete)
                {
                    EndSector(possibleSectorEndCoordinate, currentSectorNumber);
                }
            }
            if (lapComplete)
            {
                EndLap(possibleSectorEndCoordinate, possibleLapEndGeographicLapDataPointIndex, currentSectorNumber);
            }
        }