private void CalculateSeriesDependentScores( SeriesResults resultsWorkInProgress, SeriesCompetitorResults compResults) { // first pass to make sure series based DNC's are filled in. foreach (var race in resultsWorkInProgress.SailedRaces) { var score = compResults.CalculatedScores[race]; var scoreCode = GetScoreCode(score.RawScore); if (IsSeriesBasedScore(scoreCode) && !IsAverage(score.RawScore.Code)) { score.ScoreValue = CalculateSeriesBasedValue( resultsWorkInProgress, compResults, race); } } // second pass to get averages. foreach (var race in resultsWorkInProgress.SailedRaces) { var score = compResults.CalculatedScores[race]; var scoreCode = GetScoreCode(score.RawScore); if (IsSeriesBasedScore(scoreCode) && IsAverage(score.RawScore.Code)) { score.ScoreValue = CalculateSeriesBasedValue( resultsWorkInProgress, compResults, race); } } }
public SeriesResults CalculateResults(Series series) { SeriesResults returnResults = GetResults(series); AddCodesUsed(returnResults); AddTrend(returnResults, series); return(returnResults); }
protected override void CalculateOverrides(SeriesResults resultsWorkInProgress, SeriesCompetitorResults compResults) { foreach (var race in resultsWorkInProgress.SailedRaces) { var score = compResults.CalculatedScores[race]; var defaultScore = GetDefaultScore(race, resultsWorkInProgress); if (score?.ScoreValue != null && score.ScoreValue < defaultScore) { score.ScoreValue = defaultScore; } } }
private SeriesResults GetResults(Series series) { SeriesResults returnResults = BuildResults(series); SetScores(returnResults, series .Races .SelectMany( r => r .Scores)); return(returnResults); }
private void AddTrend(SeriesResults results, Series series) { if ((series.TrendOption ?? TrendOption.None) == TrendOption.None) { return; } var newSeries = series.ShallowCopy(); switch (series.TrendOption) { case TrendOption.PreviousDay: newSeries.Races = RemoveLastDaysRaces(series.Races); break; case TrendOption.PreviousRace: newSeries.Races = RemoveLastRace(series.Races); break; case TrendOption.PreviousWeek: newSeries.Races = RemoveLastWeeksRaces(series.Races); break; } if (!newSeries.Races.Where(r => (r.State == RaceState.Raced || r.State == null)).Any()) { return; } var oldResults = GetResults(newSeries); int maxOldRank = oldResults.Results.Values.Max(v => v.Rank) ?? 0; foreach (var comp in results.Competitors) { int oldRank; if (oldResults.Results.ContainsKey(comp) && oldResults.Results[comp]?.Rank != null) { oldRank = oldResults.Results[comp].Rank.Value; } else { oldRank = maxOldRank + 1; } if (results.Results[comp]?.Rank != null) { results.Results[comp].Trend = 0 - (results.Results[comp].Rank - oldRank); } } }
private Decimal?CalculateSeriesBasedValue( SeriesResults resultsWorkInProgress, SeriesCompetitorResults compResults, Race race) { var score = compResults.CalculatedScores[race]; var scoreCode = GetScoreCode(score.RawScore); return((scoreCode.Formula.ToUpperInvariant()) switch { AVERAGE_FORMULANAME => CalculateAverage(compResults), AVE_AFTER_DISCARDS_FORMULANAME => CalculateAverageNoDiscards(compResults), AVE_PRIOR_RACES_FORMULANAME => CalculateAverageOfPrior(compResults, race), SERIESCOMPETITORS_FORMULANAME => GetNumberOfCompetitors(resultsWorkInProgress) + (scoreCode.FormulaValue ?? 0), _ => null, });
protected override void DiscardScores( SeriesResults resultsWorkInProgress, SeriesCompetitorResults compResults) { int numOfDiscards = GetNumberOfDiscards(resultsWorkInProgress); var compResultsOrdered = compResults.CalculatedScores.Values.OrderBy(s => s.ScoreValue) .ThenBy(s => s.RawScore.Race.Date) .ThenBy(s => s.RawScore.Race.Order) .Where(s => GetScoreCode(s.RawScore)?.Discardable ?? true); foreach (var score in compResultsOrdered.Take(numOfDiscards)) { score.Discard = true; } }
protected void SetScores(SeriesResults resultsWorkInProgress, IEnumerable <Score> scores) { ValidateSeries(resultsWorkInProgress, scores); ClearRawScores(scores); foreach (var comp in resultsWorkInProgress.Competitors) { SeriesCompetitorResults compResults = CalculateSimpleScores(comp, scores); AddDefaultScores(resultsWorkInProgress, compResults); CalculateRaceDependentScores(resultsWorkInProgress, compResults); CalculateSeriesDependentScores(resultsWorkInProgress, compResults); CalculateOverrides(resultsWorkInProgress, compResults); DiscardScores(resultsWorkInProgress, compResults); resultsWorkInProgress.Results[comp] = compResults; } CalculateTotals(resultsWorkInProgress, scores); CalculateRanks(resultsWorkInProgress); resultsWorkInProgress.Competitors = ReorderCompetitors(resultsWorkInProgress); }
private void AddCodesUsed(SeriesResults results) { var scoreCodes = new Dictionary <string, ScoreCodeSummary>(); foreach (var comp in results.Competitors) { foreach (var race in results.SailedRaces) { var curScore = results.Results[comp].CalculatedScores[race]; if (!String.IsNullOrWhiteSpace(curScore.RawScore.Code) && !scoreCodes.ContainsKey(curScore.RawScore.Code)) { scoreCodes.Add(curScore.RawScore.Code, GetScoreCodeSummary(curScore.RawScore.Code)); } } } results.ScoreCodesUsed = scoreCodes; }
private void CalculateRaceDependentScores(SeriesResults resultsWorkInProgress, SeriesCompetitorResults compResults) { //calculate non-average codes first foreach (var race in resultsWorkInProgress.SailedRaces) { var score = compResults.CalculatedScores[race]; var scoreCode = GetScoreCode(score.RawScore); if (scoreCode != null) { if (IsTrivialCalculation(scoreCode)) { score.ScoreValue = GetTrivialScoreValue(score); } else if (IsRaceBasedValue(scoreCode)) { score.ScoreValue = CalculateRaceBasedValue(score, race); } } } }
private SeriesResults BuildResults(Series series) { var returnResults = new SeriesResults { Races = series.Races .OrderBy(r => r.Date) .ThenBy(r => r.Order).ToList(), Competitors = series .Races .SelectMany( r => r .Scores .Select(s => s.Competitor)) .Distinct() .ToList(), Results = new Dictionary <Competitor, SeriesCompetitorResults>() }; returnResults.NumberOfDiscards = GetNumberOfDiscards(returnResults); return(returnResults); }
private void AddDefaultScores( SeriesResults resultsWorkInProgress, SeriesCompetitorResults compResults) { //Fill in DNCs foreach (var race in resultsWorkInProgress.SailedRaces) { if (!compResults.CalculatedScores.ContainsKey(race)) { compResults.CalculatedScores.Add(race, new CalculatedScore { RawScore = new Score { Code = DEFAULT_CODE, Competitor = compResults.Competitor, Race = race } }); } } }
/// The series score for each boat will be a percentage calculated as /// follows: divide the sum of her race scores by the sum of the points /// she would have scored if she had placed first in every race in /// which she competed; multiply the result by 100.2 The qualified boat /// with the highest series score is the winner, and others are ranked /// accordingly. protected override void CalculateTotals( SeriesResults results, IEnumerable <Score> scores) { results.IsPercentSystem = true; results.PercentRequired = ScoringSystem.ParticipationPercent; var raceCount = results.Races.Where(r => (r.State ?? RaceState.Raced) == RaceState.Raced || r.State == RaceState.Preliminary).Count(); var requiredRaces = raceCount * ((ScoringSystem.ParticipationPercent ?? 0) / 100m); foreach (var comp in results.Competitors) { var currentCompResults = results.Results[comp]; if (currentCompResults.CalculatedScores.Where(s => s.Value.RawScore.Code != DEFAULT_CODE).Count() < requiredRaces) { currentCompResults.TotalScore = null; } else { var racesToExclude = currentCompResults .CalculatedScores .Where(s => s.Value.Discard) .Select(s => s.Key.Id); var perfectScore = scores.Where(s => !racesToExclude.Contains(s.RaceId)) .Count(s => CameToStart(s)); var compTotal = currentCompResults .CalculatedScores.Values .Sum(s => !s.Discard ? (s.ScoreValue ?? 0.0m) : 0.0m); currentCompResults.PointsEarned = compTotal; currentCompResults.PointsPossible = perfectScore; currentCompResults.TotalScore = compTotal * 100 / perfectScore; } } }