/// <summary> /// Caculate basic stats for each sprocket. This mostly allows to know the times during which we used a given gear /// </summary> /// <param name="activity"></param> /// <param name="sprocketTrack"></param> /// <returns>Returns an IList<SprocketComboInfo> of the sprocket combo info</returns> public static IList <SprocketComboInfo> Calculate(IActivity activity, ITimeDataSeries <SprocketCombo> sprocketTrack) { List <SprocketCombo> sprockets = GetSprocketCombos(activity); List <SprocketComboInfo> result = new List <SprocketComboInfo>(sprockets.Count + 1); SprocketCombo lastItemSprocket = null; DateTime sectionStartTime = sprocketTrack.StartTime; // Create the results for each zone foreach (SprocketCombo combo in sprockets) { result.Add(new SprocketComboInfo(combo)); } // Go through and find the corresponding sprocket combo for each point foreach (ITimeValueEntry <SprocketCombo> item in sprocketTrack) { // We found a change in gear, add section to times if (lastItemSprocket != item.Value) { DateTime currentItemTime = sprocketTrack.EntryDateTime(item); // First item, ignore it if (lastItemSprocket != null) { int index = sprockets.IndexOf(lastItemSprocket); result[index].Times.Add(new ValueRange <DateTime>(sectionStartTime, currentItemTime)); } sectionStartTime = currentItemTime; lastItemSprocket = item.Value; } } // Add last section if (lastItemSprocket != null && sprocketTrack.Count > 0) { int index = sprockets.IndexOf(lastItemSprocket); DateTime endTime = sprocketTrack.EntryDateTime(sprocketTrack[sprocketTrack.Count - 1]); result[index].Times.Add(new ValueRange <DateTime>(sectionStartTime, endTime)); // There is also a "totals" when Calculate is used in ST, add it although it's a bit useless for now SprocketComboInfo totals = new SprocketComboInfo(null); totals.Times.Add(new ValueRange <DateTime>(sprocketTrack.StartTime, endTime)); result.Add(totals); } return(result); }
//ST interpolate is not handling subseconds, interpolate better if possible internal static T getValFromDateTimeIndex <T>(ITimeDataSeries <T> track, DateTime time, int i) { T dist; if (i < 0 || i >= track.Count || track.Count <= 1) { //index out of bound //Note that the distance track may not start at result StartTime, then this will report result at 0 sec Debug.Assert(true, "index out of bounds"); i = Math.Max(i, 0); i = Math.Min(i, track.Count - 1); dist = track[i].Value; } else if (time == track.EntryDateTime(track[i])) { //Exact time, no interpolation dist = track[i].Value; } else { if (i == 0) { i = 1; } float elapsed = (float)((time - track.StartTime).TotalSeconds); float f = (elapsed - track[i - 1].ElapsedSeconds) / (float)(track[i].ElapsedSeconds - track[i - 1].ElapsedSeconds); dist = track[i - 1].Value; //assignment for compiler if (dist is float) { float v0 = (float)(object)(track[i - 1].Value); float v1 = (float)(object)(track[i].Value); dist = (T)(object)(v0 + (v1 - v0) * f); } else if (dist is IGPSPoint) { IGPSPoint v0 = (IGPSPoint)(object)(track[i - 1].Value); IGPSPoint v1 = (IGPSPoint)(object)(track[i].Value); float lat = (v0.LatitudeDegrees + (v1.LatitudeDegrees - v0.LatitudeDegrees) * f); float lon = (v0.LongitudeDegrees + (v1.LongitudeDegrees - v0.LongitudeDegrees) * f); float ele = (v0.ElevationMeters + (v1.ElevationMeters - v0.ElevationMeters) * f); dist = (T)(object)(new GPSPoint(lat, lon, ele)); } else { //Added to satisfy compiler - not possible to configure Debug.Assert(true, "Unexpected ITimeDataSeries"); dist = default(T); } } return(dist); }
/// <summary> /// Create gear guess selection chart based on gear ratios /// </summary> /// <param name="input">Pre-calculated raw data to estimate from. This should already be smoothed or filtered if desired.</param> /// <returns>Gear guess NumericTimeDataSeries</returns> public static NumericTimeDataSeries GuessGears(INumericTimeDataSeries input, List <SprocketCombo> sprockets) { ITimeDataSeries <SprocketCombo> guessSprockets = GuessSprockets(input, sprockets); NumericTimeDataSeries guessSeries = new NumericTimeDataSeries(); DateTime lastTime = input.StartTime; // Iterate through entire data series, recreating the result foreach (ITimeValueEntry <SprocketCombo> item in guessSprockets) { float ratio = 0; if (item.Value != null) { ratio = item.Value.GearRatio; } guessSeries.Add(guessSprockets.EntryDateTime(item), ratio); } return(guessSeries); }