/// <summary> /// Pour une année donnée, calcule les points à la semaine du classement ATP. /// </summary> /// <remarks>Un recalcul doit être fait si le barème change dans la table SQL "points".</remarks> /// <param name="year">L'année à traiter.</param> public void ComputeAtpRankingForYear(int year) { int weeksCount = Tools.YearIs53Week(year) ? 53 : 52; bool previousYearIs53 = Tools.YearIs53Week(year - 1); string query = "delete from atp_ranking where year = @year"; SqlTools.ExecuteNonQuery(query, new SqlParam("@year", DbType.UInt32, year)); List <Edition> editionsOfTheYear = Edition.GetByPeriod(new DateTime(year, 1, 1), new DateTime(year, 12, 31), null, null, false); foreach (Edition edition in editionsOfTheYear.Where(_ => !_.StatisticsAreCompute)) { LoadEditionsStatistics(edition); } List <Player> potentialPlayersOfTheYear = Player.GetList.Where(_ => _.ID != Player.UNKNOWN_PLAYER_ID && _.DateBegin.HasValue && _.DateBegin.Value.Year <= year && _.DateEnd.HasValue && _.DateEnd.Value.Year + 1 >= year).ToList(); for (uint week = 1; week <= weeksCount; week++) { List <Edition> editionsOfTheWeek = editionsOfTheYear.Where(_ => Tools.GetWeekNoFromDate(_.DateEnd) == week).ToList(); foreach (Player player in potentialPlayersOfTheYear) { uint pointsOfTheWeek = 0; uint pointsOfCalendarYear = 0; uint pointsOfRollingYear = 0; List <ulong> tournamentsIdSingle = new List <ulong>(); List <ulong> tournamentsIdCalendar = new List <ulong>(); List <ulong> tournamentsIdRolling = new List <ulong>(); // Récupère les points de la semaine en cours bool?multipleEditionsInAWeek = null; foreach (Edition edition in editionsOfTheWeek) { List <Edition.Stats> stats = edition.Statistics.Where(_ => _.Player.ID == player.ID).ToList(); if (stats.Any(_ => _.StatType == StatType.points)) { pointsOfTheWeek += stats.First(_ => _.StatType == StatType.points).Value; tournamentsIdSingle.Add(edition.Tournament.ID); multipleEditionsInAWeek = multipleEditionsInAWeek.HasValue ? true : false; } } // Pour info if (multipleEditionsInAWeek.HasValue && multipleEditionsInAWeek.Value) { Tools.WriteLog(string.Format("Mutiple tournois joués par le joueur {0}/{1} dans la semaine {2} de l'année {3} ({4}).", player.ID, player.Name, week, year, string.Join(",", tournamentsIdSingle))); } pointsOfCalendarYear += pointsOfTheWeek; tournamentsIdCalendar.AddRange(tournamentsIdSingle); // Charge les points de l'année en cours pour la semaine antérieure à celle courante query = "select * from atp_ranking where year = @year and week_no = @week and player_ID = @player"; using (DataTableReader reader = SqlTools.ExecuteReader(query, new SqlParam("@year", DbType.UInt32, year), new SqlParam("@week", DbType.UInt32, week - 1), new SqlParam("@player", DbType.UInt64, player.ID))) { if (reader.Read()) { pointsOfCalendarYear += reader.GetUint32("year_calendar_points"); tournamentsIdCalendar.AddRange(reader.ToIdList("tournaments_calendar_concat")); } } pointsOfRollingYear += pointsOfCalendarYear; tournamentsIdRolling.AddRange(tournamentsIdCalendar); // Charge les points de l'année dernière postérieure à la semaine courante query = "select * from atp_ranking where year = @year and week_no > @week and player_ID = @player and tournaments_concat <> ''"; using (DataTableReader reader = SqlTools.ExecuteReader(query, new SqlParam("@year", DbType.UInt32, year - 1), new SqlParam("@week", DbType.UInt32, previousYearIs53 ? (week + 1) : week), new SqlParam("@player", DbType.UInt64, player.ID))) { while (reader.Read()) { List <ulong> tournamentsFromlastyear = reader.ToIdList("tournaments_concat").ToList(); uint pointsFromLastyear = reader.GetUint32("week_points"); if (tournamentsFromlastyear.Any(_ => tournamentsIdSingle.Contains(_))) { tournamentsFromlastyear.RemoveAll(_ => tournamentsIdSingle.Contains(_)); pointsFromLastyear = 0; foreach (ulong tournamentIdLastYear in tournamentsFromlastyear) { Edition lastYearEdition = Edition.GetByYearAndTournament(tournamentIdLastYear, (uint)(year - 1)); if (lastYearEdition != null) { if (!lastYearEdition.StatisticsAreCompute) { LoadEditionsStatistics(lastYearEdition); } IEnumerable <Edition.Stats> lastyearEditionPointsStats = lastYearEdition.Statistics.Where(_ => _.Player == player && _.StatType == StatType.points); pointsFromLastyear += lastyearEditionPointsStats.FirstOrDefault().Value; } } } pointsOfRollingYear += pointsFromLastyear; tournamentsIdRolling.AddRange(tournamentsFromlastyear); } } // si le joueur n'a joué aucun tournoi sur les 12 derniers mois, il n'est pas classé if (tournamentsIdRolling.Count == 0) { continue; } query = SqlTools.BuildInsertQuery("atp_ranking", new Dictionary <string, string> { { "player_ID", "@player" }, { "year", "@year" }, { "week_no", "@week" }, { "week_points", "@points" }, { "year_calendar_points", "@calendar" }, { "year_rolling_points", "@rolling" }, { "tournaments_concat", "@t_single" }, { "tournaments_calendar_concat", "@t_calendar" }, { "tournaments_rolling_concat", "@t_rolling" } }); SqlTools.ExecuteNonQuery(query, new SqlParam("@player", DbType.UInt64, player.ID), new SqlParam("@year", DbType.UInt32, year), new SqlParam("@week", DbType.UInt32, week), new SqlParam("@points", DbType.UInt32, pointsOfTheWeek), new SqlParam("@calendar", DbType.UInt32, pointsOfCalendarYear), new SqlParam("@rolling", DbType.UInt32, pointsOfRollingYear), new SqlParam("@t_single", DbType.String, string.Join(";", tournamentsIdSingle)), new SqlParam("@t_calendar", DbType.String, string.Join(";", tournamentsIdCalendar)), new SqlParam("@t_rolling", DbType.String, string.Join(";", tournamentsIdRolling))); ComputeEloAtDate(player, editionsOfTheWeek, year, week); } // calcule les classements (civil et glissant) // TODO : mieux à faire pour la rêgle en cas d'égalité string[] types = new[] { "calendar", "rolling" }; foreach (string t in types) { query = "select player_ID from atp_ranking where week_no = @week and year = @year order by year_" + t + "_points desc, length(tournaments_" + t + "_concat) - length(replace(tournaments_" + t + "_concat, ';', '')) desc"; using (DataTableReader reader = SqlTools.ExecuteReader(query, new SqlParam("@year", DbType.UInt32, year), new SqlParam("@week", DbType.UInt32, week))) { int rank = 0; while (reader.Read()) { ++rank; SqlTools.ExecuteNonQuery("update atp_ranking set year_" + t + "_ranking = @rank where player_ID = @player and week_no = @week and year = @year", new SqlParam("@year", DbType.UInt32, year), new SqlParam("@week", DbType.UInt32, week), new SqlParam("@player", DbType.UInt64, reader["player_ID"]), new SqlParam("@rank", DbType.UInt16, rank)); } } } } }