<commit_before>﻿using System;
using System.Collections.Generic;

namespace PlayerRank.Scoring
{
    public class EloScoringStrategy : IScoringStrategy
    {
        private const double k = 32;

        public void NewPlayer(Player player)
        {
            player.Score = 1400;
        }

        public void UpdateScores(League league, Game game)
        {
            var results = game.GetResults();
            var previousScores = new Dictionary<string, double>();

            foreach (var playerName in results.Keys)
            {
                previousScores.Add(playerName, league.GetPlayer(playerName).Score);
            }

            foreach (var playerAName in results.Keys)
            {
                foreach (var playerBName in results.Keys)
                {
                    if (playerAName == playerBName) continue;

                    var playerAResult = results[playerAName];
                    var playerBResult = results[playerBName];

                    var playerA = league.GetPlayer(playerAName);

                    var propabilityOfWinning = ExpectedValue(previousScores[playerAName], previousScores[playerBName]);
                    var ratingChange = RatingChange(propabilityOfWinning, (playerAResult > playerBResult));
                    var ratingChangeAsReal = Math.Round(2*ratingChange/results.Count, MidpointRounding.AwayFromZero);

                    playerA.AddScore(ratingChangeAsReal);
                }
            }
        }

        private double RatingChange(double expectedValue, bool win)
        {
            var w = (win) ? 1 : 0;
            return k*(w - expectedValue);
        }

        private double ExpectedValue(double ratingA, double ratingB)
        {
            return 1/(1 + Math.Pow(10.0, (ratingB - ratingA)/400));
        }
    }
}<commit_msg>figuring out how this works<commit_after>﻿using System;
using System.Collections.Generic;

namespace PlayerRank.Scoring
{
    public class EloScoringStrategy : IScoringStrategy
    {
        /// <summary> also known as K in the ELO formula </summary>
        private const double ratingChangeBaseMultiplier = 32;

        /// <summary> the difference in rating where one person is almost certain to win </summary>
        private const double maximumSkillGap = 400;

        public void NewPlayer(Player player)
        {
            player.Score = 1400;
        }

        public void UpdateScores(League league, Game game)
        {
            var results = game.GetResults();
            var previousScores = new Dictionary<string, double>();

            foreach (var playerName in results.Keys)
            {
                previousScores.Add(playerName, league.GetPlayer(playerName).Score);
            }

            foreach (var playerAName in results.Keys)
            {
                foreach (var playerBName in results.Keys)
                {
                    if (playerAName == playerBName) continue;

                    var playerAResult = results[playerAName];
                    var playerBResult = results[playerBName];

                    var playerA = league.GetPlayer(playerAName);

                    var chanceOfPlayerAWinning = ChanceOfWinning(previousScores[playerAName], previousScores[playerBName]);
                    var didPlayerAWin = (playerAResult > playerBResult);
                    var ratingChange = RatingChange(chanceOfPlayerAWinning, didPlayerAWin);
                    // adjust for the fact that we're playing against multiple people
                    var adjustedRatingChange = 2 * ratingChange / results.Count;
                    var integerRatingChange = Math.Round(adjustedRatingChange, MidpointRounding.AwayFromZero);

                    playerA.AddScore(integerRatingChange);
                }
            }
        }

        private double RatingChange(double expectedToWin, bool actuallyWon)
        {
            var w = (actuallyWon) ? 1 : 0;
            return ratingChangeBaseMultiplier*(w - expectedToWin);
        }

        /// <summary>
        /// the chance of a player with rating <param name="ratingA"/> beating a player with rating <param name="ratingB"/>
        /// </summary>
        /// <remarks>
        /// See https://www.wolframalpha.com/input/?i=plot+1%2F%281+%2B+Pow%2810%2C+%28y+-+x%29%2F400%29%29%3B 
        /// for a graph of this function.
        private double ChanceOfWinning(double ratingA, double ratingB)
        {
            return 1/(1 + Math.Pow(10.0, (ratingB - ratingA)/maximumSkillGap));
        }
    }
}
{'fraction_non_alphanumeric': 0.08498458828709819, 'fraction_numerical': 0.012769704975781594, 'mean_word_length': 1.8716814159292035, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 16, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3092339', 'n_tokens_mistral': 1241, 'n_tokens_neox': 1133, 'n_words': 286}