/// <summary> /// Get list of fixtures when the precedent round is a group round and no random drawing is performed /// TODO: Currently only work when there is two qualified teams by group /// </summary> /// <param name="round">The round to draw</param> /// <param name="previousRound">The previous round</param> /// <returns></returns> public static List <Match> DrawNoRandomDrawing(KnockoutRound round, GroupsRound previousRound) { //We assume teams are added in round in the order of ranking and group List <Match> res = new List <Match>(); RoundProgrammation programmation = round.programmation; for (int i = 0; i < round.clubs.Count / 2; i++) { Club home = i < round.clubs.Count / 4 ? round.clubs[i * 4] : round.clubs[((i - (round.clubs.Count / 4)) * 4) + 2]; Club away = i < round.clubs.Count / 4 ? round.clubs[(i * 4) + 3] : round.clubs[((i - (round.clubs.Count / 4)) * 4) + 1]; DateTime day = GetRoundProgrammationDate(round, programmation); if (round.rules.Contains(Rule.AtHomeIfTwoLevelDifference)) { Club[] switchedTeams = SwitchTeams(home, away); home = switchedTeams[0]; away = switchedTeams[1]; } res.Add(new Match(home, away, day, !round.twoLegs)); } TVSchedule(res, round.programmation.tvScheduling, 0); if (round.twoLegs) { CreateSecondLegKnockOutRound(res, round, programmation); } return(res); }
private static DateTime GetRoundProgrammationDate(Round round, RoundProgrammation programmation) { DateTime day = programmation.gamesDays[0].ConvertToDateTime(Session.Instance.Game.date.Year); if (Utils.IsBeforeWithoutYear(day, round.DateInitialisationRound())) { day = programmation.gamesDays[0].ConvertToDateTime(Session.Instance.Game.date.Year + 1); } day.AddHours(programmation.defaultHour.Hours); day.AddMinutes(programmation.defaultHour.Minutes); return(day); }
/// <summary> /// Get list of fixtures when the precedent round is a knockout round and no random drawing is performed /// </summary> /// <param name="round">The round to draw</param> /// <param name="previousRound">The previous round</param> /// <returns></returns> public static List <Match> DrawNoRandomDrawing(KnockoutRound round, KnockoutRound previousRound) { //We assume teams are added in round in the order of the games List <Match> res = new List <Match>(); List <Club> clubsList = new List <Club>(); for (int i = previousRound.matches.Count - round.clubs.Count; i < previousRound.matches.Count; i++) { clubsList.Add(previousRound.matches[i].Winner); } RoundProgrammation programmation = round.programmation; for (int i = 0; i < clubsList.Count / 2; i++) { Club home = clubsList[i * 2]; Club away = clubsList[(i * 2) + 1]; DateTime day = GetRoundProgrammationDate(round, programmation); if (round.rules.Contains(Rule.AtHomeIfTwoLevelDifference)) { Club[] switchedTeams = SwitchTeams(home, away); home = switchedTeams[0]; away = switchedTeams[1]; } res.Add(new Match(home, away, day, !round.twoLegs)); } TVSchedule(res, round.programmation.tvScheduling, 0); if (round.twoLegs) { CreateSecondLegKnockOutRound(res, round, programmation); } return(res); }
/// <summary> /// The drawing for direct-elimination round /// </summary> /// <param name="round">The round to draw</param> /// <returns>The list of games of this round</returns> public static List <Match> Draw(KnockoutRound round) { List <Match> res = new List <Match>(); List <Club>[] hats = new List <Club>[] { new List <Club>(), new List <Club>() }; if (round.randomDrawingMethod == RandomDrawingMethod.Ranking) { GroupsRound previousRound = round.Tournament.rounds[round.Tournament.rounds.IndexOf(round) - 1] as GroupsRound; List <Club>[] clubsByRankPosition = new List <Club> [previousRound.maxClubsInGroup]; List <Club> allClubs = new List <Club>(); for (int i = 0; i < clubsByRankPosition.Length; i++) { clubsByRankPosition[i] = new List <Club>(); } for (int i = 0; i < previousRound.groupsCount; i++) { List <Club> ranking = previousRound.Ranking(i); for (int j = 0; j < ranking.Count; j++) { clubsByRankPosition[j].Add(ranking[j]); } } for (int i = 0; i < clubsByRankPosition.Length; i++) { clubsByRankPosition[i].Sort(new ClubRankingComparator(previousRound.matches)); allClubs.AddRange(clubsByRankPosition[i]); } allClubs = new List <Club>(allClubs.GetRange(0, round.clubs.Count)); hats[0].AddRange(allClubs.GetRange(0, round.clubs.Count / 2)); hats[1].AddRange(allClubs.GetRange(round.clubs.Count / 2, round.clubs.Count / 2)); } else if (round.randomDrawingMethod == RandomDrawingMethod.Coefficient) { List <Club> allClubs = new List <Club>(round.clubs); allClubs.Sort(new ClubComparator(ClubAttribute.CONTINENTAL_COEFFICIENT)); hats[0].AddRange(allClubs.GetRange(0, round.clubs.Count / 2)); hats[1].AddRange(allClubs.GetRange(round.clubs.Count / 2, round.clubs.Count / 2)); } else if (round.randomDrawingMethod == RandomDrawingMethod.Geographic) { List <Club> allClubs = new List <Club>(round.clubs); int currentClubsByGroups = allClubs.Count; int groupsNumber = 1; while ((currentClubsByGroups / 2) % 2 == 0 && (allClubs.Count / groupsNumber) > 20) { currentClubsByGroups /= 2; groupsNumber *= 2; } KMeansClustering kmeans = new KMeansClustering(allClubs, groupsNumber); hats = kmeans.CreateClusters(); } //Random else { List <Club> allClubs = new List <Club>(round.clubs); allClubs.Shuffle(); for (int i = 0; i < allClubs.Count; i++) { hats[i < allClubs.Count / 2 ? 0 : 1].Add(allClubs[i]); } } RoundProgrammation programmation = round.programmation; int currentGeographicHat = 0; for (int i = 0; i < round.clubs.Count / 2; i++) { Club home; Club away; if (round.randomDrawingMethod != RandomDrawingMethod.Geographic) { int hat = Session.Instance.Random(0, 2); home = DrawClub(hats[hat]); away = DrawClub(hats[hat == 1 ? 0 : 1]); } else { if (hats[currentGeographicHat].Count < 2) { currentGeographicHat++; } home = DrawClub(hats[currentGeographicHat]); away = DrawClub(hats[currentGeographicHat]); } DateTime day = GetRoundProgrammationDate(round, programmation); if (round.rules.Contains(Rule.AtHomeIfTwoLevelDifference)) { Club[] switchedTeams = SwitchTeams(home, away); home = switchedTeams[0]; away = switchedTeams[1]; } res.Add(new Match(home, away, day, !round.twoLegs)); } TVSchedule(res, round.programmation.tvScheduling, 0); if (round.twoLegs) { CreateSecondLegKnockOutRound(res, round, programmation); } return(res); }
private static void CreateSecondLegKnockOutRound(List <Match> gamesList, Round round, RoundProgrammation programmation) { List <Match> games = new List <Match>(); List <Match> firstRound = new List <Match>(gamesList); foreach (Match m in firstRound) { DateTime day = programmation.gamesDays[1].ConvertToDateTime(Session.Instance.Game.date.Year); if (Utils.IsBeforeWithoutYear(day, round.DateInitialisationRound())) { day = programmation.gamesDays[1].ConvertToDateTime(Session.Instance.Game.date.Year + 1); } day.AddHours(programmation.defaultHour.Hours); day.AddMinutes(programmation.defaultHour.Minutes); Match secondRound = new Match(m.away, m.home, day, !round.twoLegs, m); games.Add(secondRound); gamesList.Add(secondRound); } TVSchedule(games, round.programmation.tvScheduling, 0); }
/// <summary> /// Round robin algorithm to generate games /// </summary> /// <param name="clubs">List of clubs</param> /// <param name="programmation">TV / Federation schedule for games</param> /// <param name="twoLegged">One or two games</param> /// <returns></returns> public static List <Match> GenerateCalendar(List <Club> clubs, Round tournamentRound, bool twoLegged) { RoundProgrammation programmation = tournamentRound.programmation; List <Match> res = new List <Match>(); bool ghost = false; int teams = clubs.Count; if (teams % 2 == 1) { ghost = true; teams++; } int totalRound = teams - 1; int gamesPerRound = teams / 2; string[,] rounds = new string[totalRound, gamesPerRound]; for (int round = 0; round < totalRound; round++) { for (int match = 0; match < gamesPerRound; match++) { int home = (round + match) % (teams - 1); int away = (teams - 1 - match + round) % (teams - 1); if (match == 0) { away = teams - 1; } rounds[round, match] = (home + 1) + " v " + (away + 1); } } string[,] interleaved = new string[totalRound, gamesPerRound]; int evn = 0; int odd = (teams / 2); for (int i = 0; i < totalRound; i++) { if (i % 2 == 0) { for (int j = 0; j < gamesPerRound; j++) { interleaved[i, j] = rounds[evn, j]; } evn++; } else { for (int j = 0; j < gamesPerRound; j++) { interleaved[i, j] = rounds[odd, j]; } odd++; } } rounds = interleaved; for (int round = 0; round < totalRound; round++) { if (round % 2 == 1) { rounds[round, 0] = flip(rounds[round, 0]); } } for (int i = 0; i < totalRound; i++) { List <Match> matchs = new List <Match>(); for (int j = 0; j < gamesPerRound; j++) { string[] compenents = rounds[i, j].Split(new string[] { " v " }, StringSplitOptions.None); int a = int.Parse(compenents[0]); int b = int.Parse(compenents[1]); if (!ghost || (a != teams && b != teams)) { //-1 car index dans liste de 0 à n-1, et des clubs de 1 à n Club e1 = clubs[a - 1]; Club e2 = clubs[b - 1]; //Game day DateTime jour = programmation.gamesDays[i].ConvertToDateTime(Session.Instance.Game.date.Year); if (Utils.IsBeforeWithoutYear(jour, tournamentRound.DateInitialisationRound())) { jour = programmation.gamesDays[i].ConvertToDateTime(Session.Instance.Game.date.Year + 1); } jour = jour.AddHours(programmation.defaultHour.Hours); jour = jour.AddMinutes(programmation.defaultHour.Minutes); Match m = new Match(e1, e2, jour, false); res.Add(m); matchs.Add(m); } } TVSchedule(matchs, programmation.tvScheduling, i + 1); } if (twoLegged) { if (ghost) { gamesPerRound--; } //Part 1 : manager Journey [2-end] int nbGamesFirstRound = res.Count / gamesPerRound; List <Match> games; for (int i = 1; i < nbGamesFirstRound; i++) { games = new List <Match>(); for (int j = 0; j < gamesPerRound; j++) { Match mbase = res[gamesPerRound * i + j]; DateTime jour = programmation.gamesDays[nbGamesFirstRound + i - 1].ConvertToDateTime(Session.Instance.Game.date.Year); if (Utils.IsBeforeWithoutYear(jour, tournamentRound.DateInitialisationRound())) { jour = programmation.gamesDays[nbGamesFirstRound + i - 1].ConvertToDateTime(Session.Instance.Game.date.Year + 1); } jour = jour.AddHours(programmation.defaultHour.Hours); jour = jour.AddMinutes(programmation.defaultHour.Minutes); Match retour = new Match(mbase.away, mbase.home, jour, false); games.Add(retour); res.Add(retour); } if (nbGamesFirstRound - i >= programmation.lastMatchDaysSameDayNumber) { TVSchedule(games, programmation.tvScheduling, nbGamesFirstRound + i); } } //Last journey : first journey inverted games = new List <Match>(); for (int i = 0; i < gamesPerRound; i++) { Match mbase = res[i]; DateTime jour = programmation.gamesDays[programmation.gamesDays.Count - 1].ConvertToDateTime(Session.Instance.Game.date.Year); if (Utils.IsBeforeWithoutYear(jour, tournamentRound.DateInitialisationRound())) { jour = programmation.gamesDays[programmation.gamesDays.Count - 1].ConvertToDateTime(Session.Instance.Game.date.Year + 1); } jour = jour.AddHours(programmation.defaultHour.Hours); jour = jour.AddMinutes(programmation.defaultHour.Minutes); Match retour = new Match(mbase.away, mbase.home, jour, false); games.Add(retour); res.Add(retour); } if (programmation.lastMatchDaysSameDayNumber < 1) { TVSchedule(games, programmation.tvScheduling, nbGamesFirstRound * 2); } } return(res); }