Ejemplo n.º 1
0
        /// <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));
                        }
                    }
                }
            }
        }