private static void SpreadPairs(IDictionary <int, List <Race> > pairs, DistanceDrawSpreading spreading) { if (pairs.Count == 0) { return; } Func <Race, Race, bool> equal; switch (spreading) { case DistanceDrawSpreading.None: return; case DistanceDrawSpreading.Clubs: equal = (x, y) => x.Competitor.ClubCode == y.Competitor.ClubCode; break; case DistanceDrawSpreading.Nationalities: equal = (x, y) => x.Competitor.NationalityCode == y.Competitor.NationalityCode; break; default: throw new ArgumentOutOfRangeException(nameof(spreading), spreading, null); } var lowPair = pairs.Keys.Min(); var highPair = pairs.Keys.Max(); foreach (var pair in pairs) { if (pair.Value.Count < 2 || !equal(pair.Value[0], pair.Value[1])) { continue; } for (var i = -1; pair.Key + i >= lowPair && pair.Key + i <= highPair; i = i * -1 - Math.Max(0, Math.Sign(i))) { var otherPair = pairs[pair.Key + i]; if (otherPair.Count > 0 && TrySwap(pair.Value, otherPair, equal)) { break; } } } }
private static IReadOnlyDictionary <int, IReadOnlyCollection <Race> > FillHeatsByCompetitorsOrder(int firstPair, int pairCount, bool hasFillPair, IReadOnlyCollection <CompetitorBase> competitors, bool reverse = false, DistanceDrawSpreading spreading = DistanceDrawSpreading.None) { var pairs = new Dictionary <int, List <Race> >(); var count = 0; for (var pair = 1; pair <= pairCount; pair++) { IEnumerable <CompetitorBase> heatCompetitors; if (!reverse && pair == 1 && (competitors.Count % 2) == 1) { heatCompetitors = competitors.Take(1); } else if (hasFillPair && (!reverse && pair == 2 || reverse && pair == pairCount - 1)) { heatCompetitors = Enumerable.Empty <CompetitorBase>(); } else { heatCompetitors = competitors.Skip(count).Take(2); } var races = new List <Race>(); var lane = 0; foreach (var competitor in heatCompetitors) { races.Add(new Race { Lane = lane, Competitor = competitor }); lane++; } pairs.Add(firstPair + pair - 1, races); count += races.Count; } SpreadPairs(pairs, spreading); return(new ReadOnlyDictionary <int, IReadOnlyCollection <Race> >(pairs.ToDictionary(p => p.Key, p => (IReadOnlyCollection <Race>)p.Value.AsReadOnly()))); }