Exemple #1
0
        public async Task <IActionResult> Run(int iterations, string type)
        {
            var running = await _jobService.AlgorithmIsRunning();

            if (running)
            {
                return(StatusCode(409, "Algorithm is already running"));
            }
            var ratingJob = new RatingJob
            {
                JobId     = 0,
                StartTime = DateTime.Now,
            };
            int jobId;

            switch (type)
            {
            case "singles":
                ratingJob.Type = "Algorithm.Singles";
                await _ratingJobRepository.Insert(ratingJob);

                var singlesInstance = (Algorithm)_serviceProvider.GetService(typeof(Algorithm));
                jobId = int.Parse(BackgroundJob.Enqueue(() => singlesInstance.UpdateRating(iterations, false, ratingJob.Id)));
                break;

            case "doubles":
                ratingJob.Type = "Algorithm.Doubles";
                await _ratingJobRepository.Insert(ratingJob);

                var doublesInstance = (AlgorithmDoubles)_serviceProvider.GetService(typeof(AlgorithmDoubles));
                jobId = int.Parse(BackgroundJob.Enqueue(() => doublesInstance.UpdateRating(iterations, null, ratingJob.Id)));
                break;

            default:
                return(StatusCode(400, "Type must be singles or doubles"));
            }
            ratingJob.JobId = jobId;
            await _ratingJobRepository.Update(ratingJob);

            return(StatusCode(200, "Algorithm started"));
        }
        public async Task UpdateRating(int count, bool asAlternate, int jobId)
        {
            // resolve any events
            await _playerService.ResolvePlayerEvents();

            // await _resultService.ResolveResultEvents();

            _ratingJobId = jobId;
            var            conn        = new SqlConnection(_config.ConnectionStrings.DefaultConnection);
            SqlTransaction transaction = null;
            RatingRule     rule        = RatingRule.GetDefault("singles", _config.ConnectionStrings.DefaultConnection);

            try
            {
                _logger.LogInformation("Started Singles Algorithm - {0} iterations", count);

                var resultThreshold = DateTime.UtcNow.AddMonths(-1 * int.Parse(_config.OldestResultInMonths));
                _logger.LogInformation("Retrieving Players...");
                await LogStatus("Loading players...");

                var players =
                    (await _playerService.GetPlayersWithResults("singles", resultThreshold)).ToDictionary(item => item.Id);

                _logger.LogInformation("Retrieving Results...");
                await LogStatus("Loading results...");

                var playerResults = await _resultService.GetPlayerResultsFromYear("singles", resultThreshold);

                _logger.LogInformation("Running calculations...");
                await DoCalculation(count, players, rule, playerResults);

                _logger.LogInformation("Calculating Competitiveness...");
                await LogStatus("Calculating competitiveness...");

                foreach (var row in players.Values)
                {
                    if (playerResults == null || playerResults.Count <= 0)
                    {
                        continue;
                    }
                    var player  = row;
                    var results = GetRatingResults(player, players, playerResults[player.Id], rule);
                    var comp    = CalculateCompetitiveness(results);
                    row.Stats.CompetitiveMatchPct = comp.Item1;
                    row.Stats.RoutineMatchPct     = comp.Item2;
                    row.Stats.DecisiveMatchPct    = comp.Item3;
                }

                _logger.LogInformation("Correcting players...");
                await LogStatus("Correcting players...");

                DoPostProcessing(playerResults, players.Values.ToList(), rule);

                _logger.LogInformation("Saving Sub Ratings");
                await LogStatus("Saving Sub Ratings...");

                foreach (var player in players.Values)
                {
                    // update sub rating
                    if (player.Stats.SubRating != null)
                    {
                        await _subRatingRepository.AddOrUpdateSubRating(player.Stats.SubRating);
                    }
                }

                _logger.LogInformation("Saving Ratings");
                await LogStatus("Saving Ratings...");

                conn.Open();
                transaction = conn.BeginTransaction();

                foreach (var player in players.Values)
                {
                    conn.Execute(@"update playerrating set finalrating = @FinalRating, actualrating = @ActualRating, ratingreliability = @RatingReliability, " +
                                 "competitiveMatchPct = @CompetitiveMatchPct, routineMatchPct = @RoutineMatchPct, decisiveMatchPct = @DecisiveMatchPct, " +
                                 "inactiveRating = NULL, activeSinglesResults = @ActiveSinglesResults, playergender = @Gender where playerId = @Id",
                                 new {
                        Id = player.Id,
                        CompetitiveMatchPct = player.Stats.CompetitiveMatchPct,
                        RoutineMatchPct     = player.Stats.RoutineMatchPct,
                        DecisiveMatchPct    = player.Stats.DecisiveMatchPct,
                        RatingReliability   = player.Stats.RatingReliability,
                        ActualRating        = player.Stats.ActualRating,
                        FinalRating         = player.Stats.FinalRating,
                        Gender = player.Gender,
                        ActiveSinglesResults = player.Stats.ActiveSinglesResults
                    }, transaction: transaction);
                }

                transaction.Commit();

                // clean up the players
                players = null;
                GC.Collect();

                UpdateDisconnectedPools(rule, playerResults);

                await LogStatus("Completed");

                _logger.LogInformation("Algorithm Completed Successfully");
            }
            catch (Exception e)
            {
                try
                {
                    transaction?.Rollback();
                }
                catch (Exception e2)
                {
                    LogException(e2);
                }
                LogException(e);
                _logger.LogError("Algorithm Failed");
                await LogStatus("Failed");
            }
            finally
            {
                transaction?.Dispose();
                conn.Close();
                // close the job
                var job = await _ratingJobRepository.GetById(_ratingJobId);

                job.EndTime = DateTime.Now;
                await _ratingJobRepository.Update(job);
            }
        }
        public async Task UpdateRating(int count, RatingRule rule, int jobId)
        {
            // resolve any events
            await _playerService.ResolvePlayerEvents();

            // await _resultService.ResolveResultEvents();

            _ratingJobId = jobId;

            try
            {
                // always update the rule
                _ratingRule = rule ?? RatingRule.GetDefault("doubles", _config.ConnectionStrings.DefaultConnection);

                await LogStatus("Loading Players...");

                _logger.LogInformation("Retrieving Players...");
                await LogStatus("Loading players...");

                var resultThreshold = DateTime.UtcNow.AddMonths(-1 * int.Parse(_config.OldestResultInMonths));
                var players         = (await _playerService.GetPlayersWithResults("doubles", resultThreshold)).ToDictionary(item => item.Id);
                // all doubles results in the last year
                _logger.LogInformation("Retrieving Results...");
                await LogStatus("Loading results...");

                var results = await _resultService.GetPlayerResultsFromYear("doubles", resultThreshold);

                _logger.LogInformation("Running calculations...");
                for (var i = 0; i < count; i++)
                {
                    await LogStatus($"Running calculations - Iteration {i + 1}");

                    DoCalc(players, i + 1, results);
                }

                _logger.LogInformation("Calculating Competitiveness...");
                await LogStatus("Calculating competitiveness...");

                foreach (var player in players)
                {
                    var ratingResults = LoadRatingResults(results[player.Value.Id]);
                    player.Value.Stats.CompetitiveMatchPctDoubles = CalculateCompetitiveness(ratingResults);
                }

                _logger.LogInformation("Correcting players...");
                await LogStatus("Correcting players...");

                NormalizeRatingsII(players.Values.ToList(), results);

                _logger.LogInformation("Saving Ratings");
                await LogStatus("Saving Ratings...");

                using (var connection = new SqlConnection(_config.ConnectionStrings.DefaultConnection))
                {
                    connection.Open();
                    using (var transaction = connection.BeginTransaction())
                    {
                        const string updateQuery = "Update PlayerRating Set FinalDoublesRating = @FinalDoublesRating, DoublesRating = @DoublesRating, DoublesReliability = @DoublesReliability," +
                                                   " CompetitiveMatchPctDoubles = @CompetitiveMatchPctDoubles, ActiveDoublesResults = @ActiveDoublesResults, DoublesBenchmarkRating = @DoublesBenchmarkRating" +
                                                   " PlayerGender = @Gender Where playerid = @Id";
                        foreach (var player in players)
                        {
                            connection.Execute(updateQuery, new
                            {
                                DoublesRating              = player.Value.Stats.DoublesRating,
                                DoublesReliability         = player.Value.Stats.DoublesReliability,
                                FinalDoublesRating         = player.Value.Stats.FinalDoublesRating,
                                CompetitiveMatchPctDoubles = player.Value.Stats.CompetitiveMatchPctDoubles,
                                DoublesBenchmarkRating     = player.Value.Stats.DoublesBenchmarkRating,
                                Id     = player.Value.Id,
                                Gender = player.Value.Gender,
                                ActiveDoublesResults = player.Value.Stats.ActiveDoublesResults
                            }, transaction: transaction);
                        }
                        transaction.Commit();
                    }
                }

                // clean up players
                players = null;
                GC.Collect();

                await LogStatus("Checking for disconnected pools...");

                UpdateDisconnectedPools(results);

                await LogStatus("Completed");

                _logger.LogInformation("Algorithm Completed Successfully");
            }
            catch (Exception e)
            {
                LogException(e);
                _logger.LogInformation("Algorithm Failed");
                await LogStatus("Failed");
            }
            finally
            {
                // close the job
                var job = await _ratingJobRepository.GetById(_ratingJobId);

                job.EndTime = DateTime.Now;
                await _ratingJobRepository.Update(job);
            }
        }