private static Result calculateActivityZoneGoal(IActivity activity, IntervalsGoal goal, ActInfo act, double[] domain, IList<double[]> image) { bool foundAny = false; int back = 0, front = 0; int bestBack = 0, bestFront = 0; double best; if (goal.UpperBound) best = double.MinValue; else best = double.MaxValue; int length = act.Length; while (front < length) { bool inWindow = true; for (int i = 0; i < image.Count; i++) { if (image[i][back] < goal.Intervals[i][0] || image[i][front] > goal.Intervals[i][1]) { inWindow = false; break; } } if (inWindow) { double domainDiff = domain[front] - domain[back]; int upperBound = goal.UpperBound ? 1 : -1; if (upperBound*best < upperBound*domainDiff && (goal.Domain == GoalParameter.Elevation || act.validElevation && (act.aElevation[front] - act.aElevation[back]) / (act.aDistance[front] - act.aDistance[back]) >= Settings.MinGrade)) { foundAny = true; best = domainDiff; bestBack = back; bestFront = front; } if (back == front || (front < length - 1 && isInZone(image, goal, front + 1))) front++; else back++; } else { if (back == front) { if (front < length - 1 && !isInZone(image, goal, front + 1)) back++; front++; } else back++; } } if (foundAny) { return new Result(goal, activity, act.Pauses, domain[bestBack], domain[bestFront], act.aTime[bestBack], act.aTime[bestFront], act.aDistance[bestBack], act.aDistance[bestFront], act.aElevation[bestBack], act.aElevation[bestFront], act.aDateTime[bestBack], act.aDateTime[bestFront]); } return null; }
private static Result calculateActivityPointGoal(IActivity activity, PointGoal goal, ActInfo act, double[] domain, double[] image) { bool foundAny = false; int back = 0, front = 0; int bestBack = 0, bestFront = 0; double best; if (goal.UpperBound) best = double.MinValue; else best = double.MaxValue; while (front < act.Length && back < act.Length) { if (image[front] - image[back] >= goal.Value) { double domainDiff = domain[front] - domain[back]; int upperBound = goal.UpperBound ? 1 : -1; if (upperBound*best < upperBound*domainDiff && (!act.validElevation || act.validElevation && (act.aElevation[front] - act.aElevation[back]) / (act.aDistance[front] - act.aDistance[back]) >= Settings.MinGrade)) { foundAny = true; best = domainDiff; bestBack = back; bestFront = front; } back++; } else { front++; } } if (foundAny) { return new Result(goal, activity, act.Pauses, domain[bestBack], domain[bestFront], act.aTime[bestBack], act.aTime[bestFront], act.aDistance[bestBack], act.aDistance[bestFront], act.aElevation[bestBack], act.aElevation[bestFront], act.aDateTime[bestBack], act.aDateTime[bestFront]); } return null; }
private static void calculateActivity(IActivity activity, IValueRangeSeries<DateTime> pause, IList<Goal> goals, SortedList<Result, Result>[] results) { ActInfo act = new ActInfo(activity, pause, goals); foreach (Goal goal in goals) { Result result = null; if (Goal.IsZoneGoal(goal.Image)) { if (act.ZoneOk(goal)) { result = calculateActivityZoneGoal(activity, (IntervalsGoal)goal, act, act.getGoalTrack(goal.Domain), act.getGoalZoneTrack(goal.Image)); } } else { result = calculateActivityPointGoal(activity, (PointGoal)goal, act, act.getGoalTrack(goal.Domain), act.getGoalTrack(goal.Image)); } if (result != null) { //results array are referenced by goal index. (Could be dictionary) int resultIndex = goals.IndexOf(goal); if (results[resultIndex] == null) { results[resultIndex] = new SortedList<Result, Result>(); } if (results[resultIndex].Count > 0 && results[resultIndex].Count >= goal.Order) { Result last = Result.LastResult(results[resultIndex]); if (result.BetterResult(last)) { results[resultIndex].Remove(last); } } if (results[resultIndex].Count < goal.Order) { results[resultIndex].Add(result, result); } } } }