return ($newr1, $newrd1);
}
+sub calc_rating_double {
+ my ($rating1, $rd1, $rating2, $rd2, $rating3, $rd3, $rating4, $rd4, $score1, $score2) = @_;
+ my $result = `/srv/foosball.sesse.net/foosrank $rating1 $rd1 $rating2 $rd2 $rating3 $rd3 $rating4 $rd4 $score1 $score2`;
+ chomp $result;
+ my ($newr1, $newrd1) = split / /, $result;
+
+ $newrd1 = 30.0 if ($newrd1 < 30.0);
+
+ return ($newr1, $newrd1);
+}
+
+
1;
#include <algorithm>
// step sizes
-static const double int_step_size = 50.0;
-static const double pdf_step_size = 10.0;
+static const double int_step_size = 75.0;
+static const double pdf_step_size = 15.0;
// rating constant (see below)
static const double rating_constant = 455.0;
double binomial_precompute = prodai(k, a) / fac(k-1);
winfac /= rating_constant;
- return simpson_integrate(ProbScoreEvaluator(k, a, binomial_precompute, r1, mu2, sigma2, winfac), 0.0, 3000.0, int_step_size);
+ return simpson_integrate(ProbScoreEvaluator(k, a, binomial_precompute, r1, mu2, sigma2, winfac), 0.0, 6000.0, int_step_size);
}
// normalize the curve so we know that A ~= 1
least_squares(curve, mu_est, sigma_est, mu, sigma);
}
+// int(normpdf[mu2, sigma2](t2) * ..., t2=0..3000);
+class OuterIntegralEvaluator {
+private:
+ double theta1, mu2, sigma2, mu_t, sigma_t;
+ int score1, score2;
+ double winfac;
+
+public:
+ OuterIntegralEvaluator(double theta1, double mu2, double sigma2, double mu3, double sigma3, double mu4, double sigma4, int score1, int score2, double winfac)
+ : theta1(theta1), mu2(mu2), sigma2(sigma2), mu_t(mu3 + mu4), sigma_t(sqrt(sigma3*sigma3 + sigma4*sigma4)), score1(score1), score2(score2), winfac(winfac) {}
+
+ double operator() (double theta2) const
+ {
+ double z = (theta2 - mu2) / sigma2;
+ double gaussian = exp(-(z*z/2.0));
+ double r1 = theta1 + theta2;
+ return gaussian * opponent_rating_pdf(score1, score2, r1, mu_t, sigma_t, winfac);
+ }
+};
+
+void compute_new_double_rating(double mu1, double sigma1, double mu2, double sigma2, double mu3, double sigma3, double mu4, double sigma4, int score1, int score2, double &mu, double &sigma)
+{
+ vector<pair<double, double> > curve;
+
+ if (score1 > score2) {
+ for (double r1 = 0.0; r1 < 3000.0; r1 += pdf_step_size) {
+ double z = (r1 - mu1) / sigma1;
+ double gaussian = exp(-(z*z/2.0));
+ curve.push_back(make_pair(r1, gaussian * simpson_integrate(OuterIntegralEvaluator(r1,mu2,sigma2,mu3,sigma3,mu4,sigma4,score1,score2,0.5), 0.0, 3000.0, int_step_size)));
+ }
+ } else {
+ for (double r1 = 0.0; r1 < 3000.0; r1 += pdf_step_size) {
+ double z = (r1 - mu1) / sigma1;
+ double gaussian = exp(-(z*z/2.0));
+ curve.push_back(make_pair(r1, gaussian * simpson_integrate(OuterIntegralEvaluator(r1,mu2,sigma2,mu3,sigma3,mu4,sigma4,score2,score1,-0.5), 0.0, 3000.0, int_step_size)));
+ }
+ }
+
+ double mu_est, sigma_est;
+ normalize(curve);
+ estimate_musigma(curve, mu_est, sigma_est);
+ least_squares(curve, mu_est, sigma_est, mu, sigma);
+}
+
int main(int argc, char **argv)
{
double mu1 = atof(argv[1]);
double mu2 = atof(argv[3]);
double sigma2 = atof(argv[4]);
- if (argc > 6) {
+ if (argc > 8) {
+ double mu3 = atof(argv[5]);
+ double sigma3 = atof(argv[6]);
+ double mu4 = atof(argv[7]);
+ double sigma4 = atof(argv[8]);
+ int score1 = atoi(argv[9]);
+ int score2 = atoi(argv[10]);
+ double mu, sigma;
+ compute_new_double_rating(mu1, sigma1, mu2, sigma2, mu3, sigma3, mu4, sigma4, score1, score2, mu, sigma);
+ printf("%f %f\n", mu, sigma);
+ } else if (argc > 6) {
int score1 = atoi(argv[5]);
int score2 = atoi(argv[6]);
double mu, sigma;
my $score1 = $ref->{'score1'};
my $score2 = $ref->{'score2'};
- # make virtual "team players"
- my ($rating_team1, $rd_team1) = foosball::combine_ratings($rating1_1, $rd1_1, $rating1_2, $rd1_2);
- my ($rating_team2, $rd_team2) = foosball::combine_ratings($rating2_1, $rd2_1, $rating2_2, $rd2_2);
-
- my ($new_t1r, undef) = foosball::calc_rating($rating_team1, $rd_team1, $rating_team2, $rd_team2, $score1, $score2);
- my ($new_t2r, undef) = foosball::calc_rating($rating_team2, $rd_team2, $rating_team1, $rd_team1, $score2, $score1);
- my $newr1_1 = $rating1_1 + ($new_t1r - $rating_team1);
- my $newr1_2 = $rating1_2 + ($new_t1r - $rating_team1);
- my $newr2_1 = $rating2_1 + ($new_t2r - $rating_team2);
- my $newr2_2 = $rating2_2 + ($new_t2r - $rating_team2);
-
- my (undef, $newrd1_1) = foosball::calc_rating($rating1_1, $rd1_1, $rating_team2, $rd_team2, $score1, $score2);
- my (undef, $newrd1_2) = foosball::calc_rating($rating1_2, $rd1_2, $rating_team2, $rd_team2, $score1, $score2);
- my (undef, $newrd2_1) = foosball::calc_rating($rating2_1, $rd2_1, $rating_team1, $rd_team1, $score2, $score1);
- my (undef, $newrd2_2) = foosball::calc_rating($rating2_2, $rd2_2, $rating_team1, $rd_team1, $score2, $score1);
+ my ($newr1_1, $newrd1_1) = foosball::calc_rating_double($rating1_1, $rd1_1, $rating1_2, $rd1_2, $rating2_1, $rd2_1, $rating2_2, $rd2_2, $score1, $score2);
+ my ($newr1_2, $newrd1_2) = foosball::calc_rating_double($rating1_2, $rd1_2, $rating1_1, $rd1_1, $rating2_1, $rd2_1, $rating2_2, $rd2_2, $score1, $score2);
+ my ($newr2_1, $newrd2_1) = foosball::calc_rating_double($rating2_1, $rd2_1, $rating2_2, $rd2_2, $rating1_1, $rd1_1, $rating1_2, $rd1_2, $score2, $score1);
+ my ($newr2_2, $newrd2_2) = foosball::calc_rating_double($rating2_2, $rd2_2, $rating2_1, $rd2_1, $rating1_1, $rd1_1, $rating1_2, $rd1_2, $score2, $score1);
printf("%-10s/%-10s - %-10s/%-10s: %u - %u, new ratings %u/%u %u/%u %u/%u %u/%u\n",
$ref->{'team1_username1'}, $ref->{'team1_username2'},
my ($rating2_1, $rd2_1) = foosball::find_double_rating($dbh, $team2_username1);
my ($rating2_2, $rd2_2) = foosball::find_double_rating($dbh, $team2_username2);
+my ($newr1_1, $newrd1_1) = foosball::calc_rating_double($rating1_1, $rd1_1, $rating1_2, $rd1_2, $rating2_1, $rd2_1, $rating2_2, $rd2_2, $score1, $score2);
+my ($newr1_2, $newrd1_2) = foosball::calc_rating_double($rating1_2, $rd1_2, $rating1_1, $rd1_1, $rating2_1, $rd2_1, $rating2_2, $rd2_2, $score1, $score2);
+my ($newr2_1, $newrd2_1) = foosball::calc_rating_double($rating2_1, $rd2_1, $rating2_2, $rd2_2, $rating1_1, $rd1_1, $rating1_2, $rd1_2, $score2, $score1);
+my ($newr2_2, $newrd2_2) = foosball::calc_rating_double($rating2_2, $rd2_2, $rating2_1, $rd2_1, $rating1_1, $rd1_1, $rating1_2, $rd1_2, $score2, $score1);
# make virtual "team players"
-my ($rating_team1, $rd_team1) = foosball::combine_ratings($rating1_1, $rd1_1, $rating1_2, $rd1_2);
-my ($rating_team2, $rd_team2) = foosball::combine_ratings($rating2_1, $rd2_1, $rating2_2, $rd2_2);
-
-my $q = $foosball::q;
-
-my ($new_t1r, undef) = foosball::calc_rating($rating_team1, $rd_team1, $rating_team2, $rd_team2, $score1, $score2);
-my ($new_t2r, undef) = foosball::calc_rating($rating_team2, $rd_team2, $rating_team1, $rd_team1, $score2, $score1);
-my $newr1_1 = $rating1_1 + ($new_t1r - $rating_team1);
-my $newr1_2 = $rating1_2 + ($new_t1r - $rating_team1);
-my $newr2_1 = $rating2_1 + ($new_t2r - $rating_team2);
-my $newr2_2 = $rating2_2 + ($new_t2r - $rating_team2);
-
-my (undef, $newrd1_1) = foosball::calc_rating($rating1_1, $rd1_1, $rating_team2, $rd_team2, $score1, $score2);
-my (undef, $newrd1_2) = foosball::calc_rating($rating1_2, $rd1_2, $rating_team2, $rd_team2, $score1, $score2);
-my (undef, $newrd2_1) = foosball::calc_rating($rating2_1, $rd2_1, $rating_team1, $rd_team1, $score2, $score1);
-my (undef, $newrd2_2) = foosball::calc_rating($rating2_2, $rd2_2, $rating_team1, $rd_team1, $score2, $score1);
$dbh->do('INSERT INTO double_results (gametime,team1_username1,team1_username2,team2_username1,team2_username2,score1,score2) VALUES (CURRENT_TIMESTAMP,?,?,?,?,?,?)',
undef, $team1_username1, $team1_username2, $team2_username1, $team2_username2, $score1, $score2);
score1,
score2,
ra1.rating_diff as diff1,
- ra2.rating_diff as diff2
+ ra2.rating_diff as diff2,
+ ra3.rating_diff as diff3,
+ ra4.rating_diff as diff4
from
double_results re
join double_rating ra1
and re.team1_username1=ra1.username
join double_rating ra2
on re.gametime=ra2.ratetime
- and re.team2_username1=ra2.username
+ and re.team1_username2=ra2.username
+ join double_rating ra3
+ on re.gametime=ra3.ratetime
+ and re.team2_username1=ra3.username
+ join double_rating ra4
+ on re.gametime=ra4.ratetime
+ and re.team2_username2=ra4.username
union all
select
to_char(gametime, \'IYYY-MM-DD HH24:MI\') as gametime,
score1,
score2,
ra1.rating_diff as diff1,
- ra2.rating_diff as diff2
+ null as diff2,
+ ra2.rating_diff as diff3,
+ null as diff4
from
single_results re
join single_rating ra1
order by gametime desc limit 10');
$q->execute();
while (my $ref = $q->fetchrow_hashref) {
- $ref->{'diff1'} = sprintf "%+d", int($ref->{'diff1'} + 0.5);
- $ref->{'diff2'} = sprintf "%+d", int($ref->{'diff2'} + 0.5);
+ if (defined($ref->{'diff2'})) {
+ $ref->{'diff1'} = sprintf "%+d / %+d",
+ int($ref->{'diff1'} + 0.5),
+ int($ref->{'diff2'} + 0.5);
+ $ref->{'diff2'} = sprintf "%+d / %+d",
+ int($ref->{'diff3'} + 0.5),
+ int($ref->{'diff4'} + 0.5);
+ } else {
+ $ref->{'diff1'} = sprintf "%+d", int($ref->{'diff1'} + 0.5);
+ $ref->{'diff2'} = sprintf "%+d", int($ref->{'diff3'} + 0.5);
+ }
push @last_games, $ref;
}