コード例 #1
0
        public ScorePlayer Calculate(ScorePlayer player, IEnumerable <Tuple <ScorePlayer, double> > opponents, double factor = 1.0)
        {
            // Step 3
            double v = 0.0;

            foreach (var opponent in opponents)
            {
                var e = this.E(player.RatingScaled, opponent.Item1.RatingScaled, opponent.Item1.RdScaled);
                v += Math.Pow(this.G(opponent.Item1.RdScaled), 2) * e * (1 - e);
            }

            v = Math.Pow(v, -1.0);

            // Step 4
            double delta = 0.0;

            foreach (var opponent in opponents)
            {
                delta += this.G(opponent.Item1.RdScaled) * (opponent.Item2 - this.E(player.RatingScaled, opponent.Item1.RatingScaled, opponent.Item1.RdScaled));
            }

            delta *= v;

            // Step 5
            const double epsilon = 0.000001;

            double A, a, B;

            A = a = Math.Log(Math.Pow(player.Vol, 2));

            var delta2 = delta * delta;
            var rd2    = player.RdScaled * player.RdScaled;

            if (delta2 > rd2 + v)
            {
                B = Math.Log(delta2 - rd2 - v);
            }
            else
            {
                int k = 0;
                while (this.F(delta, a, player.RdScaled, v, a - k * Config.Tau) < 0)
                {
                    ++k;
                }

                B = a - k * Config.Tau;
            }

            // Step 5.3
            double fa = this.F(delta, a, player.RdScaled, v, A);
            double fb = this.F(delta, a, player.RdScaled, v, B);

            // Step 5.4
            while (Math.Abs(B - A) > epsilon)
            {
                double C  = A + (A - B) * fa / (fb - fa);
                double fc = this.F(delta, a, player.RdScaled, v, C);

                if (fc * fb < 0)
                {
                    A  = B;
                    fa = fb;
                }
                else
                {
                    fa = fa / 2.0;
                }

                B  = C;
                fb = fc;
            }

            // Step 5.5
            double vol1 = Math.Pow(Math.E, A / 2.0);

            // Step 6
            double rdstar = Math.Sqrt(rd2 + vol1 * vol1);

            // Step 7
            double rdnew     = 1.0 / Math.Sqrt(1 / (rdstar * rdstar) + 1 / v);
            double ratingnew = 0.0;

            foreach (var opponent in opponents)
            {
                ratingnew += (rdnew * rdnew) * this.G(opponent.Item1.RatingScaled) * (opponent.Item2 - this.E(player.RatingScaled, opponent.Item1.RatingScaled, opponent.Item1.RdScaled));
            }

            // Step 8
            var result = new ScorePlayer(player.Id);

            result.RatingScaled = player.RatingScaled + ratingnew * factor;
            result.RdScaled     = (rdnew - player.RdScaled) * factor + player.RdScaled;

            return(result);
        }
コード例 #2
0
        public ScorePlayer Calculate(ScorePlayer player, IEnumerable<Tuple<ScorePlayer, double>> opponents, double factor = 1.0)
        {
            // Step 3
            double v = 0.0;
            foreach(var opponent in opponents)
            {
                var e = this.E(player.RatingScaled, opponent.Item1.RatingScaled, opponent.Item1.RdScaled);
                v += Math.Pow(this.G(opponent.Item1.RdScaled), 2) * e * (1 - e);
            }

            v = Math.Pow(v, -1.0);

            // Step 4
            double delta = 0.0;
            foreach(var opponent in opponents)
            {
                delta += this.G(opponent.Item1.RdScaled) * (opponent.Item2 - this.E(player.RatingScaled, opponent.Item1.RatingScaled, opponent.Item1.RdScaled));
            }

            delta *= v;

            // Step 5
            const double epsilon = 0.000001;

            double A, a, B;
            A = a = Math.Log(Math.Pow(player.Vol, 2));

            var delta2 = delta *  delta;
            var rd2 = player.RdScaled * player.RdScaled;
            if (delta2 > rd2 + v)
            {
                B = Math.Log(delta2 - rd2 - v);
            }
            else
            {
                int k = 0;
                while (this.F(delta, a, player.RdScaled, v, a - k * Config.Tau) < 0)
                {
                    ++k;
                }

                B = a - k * Config.Tau;
            }

            // Step 5.3
            double fa = this.F(delta, a, player.RdScaled, v, A);
            double fb = this.F(delta, a, player.RdScaled, v, B);

            // Step 5.4
            while (Math.Abs(B - A) > epsilon)
            {
                double C = A + (A - B) * fa / (fb - fa);
                double fc = this.F(delta, a, player.RdScaled, v, C);

                if (fc * fb < 0)
                {
                    A = B;
                    fa = fb;
                }
                else
                {
                    fa = fa / 2.0;
                }

                B = C;
                fb = fc;
            }

            // Step 5.5
            double vol1 = Math.Pow(Math.E, A / 2.0);

            // Step 6
            double rdstar = Math.Sqrt(rd2 + vol1 * vol1);

            // Step 7
            double rdnew = 1.0 / Math.Sqrt(1 / (rdstar * rdstar) + 1 / v);
            double ratingnew = 0.0;
            foreach(var opponent in opponents)
            {
                ratingnew += (rdnew * rdnew) * this.G(opponent.Item1.RatingScaled) * (opponent.Item2 - this.E(player.RatingScaled, opponent.Item1.RatingScaled, opponent.Item1.RdScaled));
            }

            // Step 8
            var result = new ScorePlayer(player.Id);

            result.RatingScaled = player.RatingScaled + ratingnew * factor;
            result.RdScaled = (rdnew - player.RdScaled) * factor + player.RdScaled;

            return result;
        }