From d963a5d96352ece425d76233351d3f9c879dbf30 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Mon, 19 Mar 2012 02:52:47 +0100 Subject: [PATCH] Take standard deviation of estimated mu into account when doing MC simulation. --- mcwordfeud.cpp | 19 ++++++++++++++----- www/index.pl | 20 ++++++++++---------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/mcwordfeud.cpp b/mcwordfeud.cpp index 2bd4a52..b48936d 100644 --- a/mcwordfeud.cpp +++ b/mcwordfeud.cpp @@ -14,7 +14,7 @@ using namespace std; #define MAX_PLAYERS 16 -float match_stddev = 70.0f; +float match_variance = 70.0f * 70.0f; struct player { int player_index; @@ -67,12 +67,15 @@ float draw_gaussian(float mu, float stddev) int main(int argc, char **argv) { int trials = atoi(argv[1]); + float match_stddev; if (scanf("%f", &match_stddev) != 1) { fprintf(stderr, "Could't read match stddev\n"); exit(1); } + match_variance = match_stddev * match_stddev; + int num_players; if (scanf("%d", &num_players) != 1) { fprintf(stderr, "Could't read number of players\n"); @@ -87,6 +90,7 @@ int main(int argc, char **argv) vector players; map player_map; float ratings[MAX_PLAYERS]; + float ratings_variance[MAX_PLAYERS]; bool has_scores[MAX_PLAYERS][MAX_PLAYERS]; for (int pl1 = 0; pl1 < num_players; ++pl1) { for (int pl2 = 0; pl2 < num_players; ++pl2) { @@ -97,19 +101,23 @@ int main(int argc, char **argv) int scores[MAX_PLAYERS][MAX_PLAYERS]; for (int i = 0; i < num_players; ++i) { char buf[256]; - float rating; - int ret = scanf("%s %f", buf, &rating); + float rating, rating_stddev; + int ret = scanf("%s %f %f", buf, &rating, &rating_stddev); if (ret < 1) { fprintf(stderr, "Couldn't read player %d\n", i); exit(1); } - if (ret != 2) { + if (ret < 2) { rating = 1500.0f; } + if (ret < 3) { + rating_stddev = 0.0f; + } players.push_back(buf); player_map[buf] = i; ratings[i] = rating; + ratings_variance[i] = rating_stddev * rating_stddev; } for ( ;; ) { @@ -151,8 +159,9 @@ int main(int argc, char **argv) } float mu = ratings[pl1] - ratings[pl2]; + float stddev = sqrt(match_variance + ratings_variance[pl1] + ratings_variance[pl2]); - int score = lrintf(draw_gaussian(mu, match_stddev)); + int score = lrintf(draw_gaussian(mu, stddev)); scores[pl1][pl2] = score; scores[pl2][pl1] = -score; } diff --git a/www/index.pl b/www/index.pl index 604edc2..d1943ae 100755 --- a/www/index.pl +++ b/www/index.pl @@ -25,6 +25,7 @@ binmode STDOUT, ':utf8'; my %players = (); my %ratings = (); +my %ratings_stddev = (); my @matches = (); my %parms = (); my $match_stddev; @@ -39,7 +40,7 @@ sub color { } sub make_table { - my ($lowest_division, $used_ratings) = @_; + my ($lowest_division, $used_ratings, $used_ratings_stddev) = @_; print <<"EOF"; @@ -58,11 +59,9 @@ EOF printf MCCALC "%d\n", scalar keys %players; for my $id (keys %players) { - if (exists($used_ratings->{$id}) && defined($used_ratings->{$id})) { - printf MCCALC "%s %f\n", $id, $used_ratings->{$id}; - } else { - printf MCCALC "%s %f\n", $id, 1500.0; - } + my $rating = $used_ratings->{$id} // 1500.0; + my $rating_stddev = $used_ratings_stddev->{$id} // $parms{-3}; + printf MCCALC "%s %f %f\n", $id, $rating, $rating_stddev; } for my $match (@matches) { @@ -80,7 +79,7 @@ EOF chomp; my @x = split /\s+/; my $id = $x[0]; - my $player = sprintf "%s (%.0f)", $players{$id}, $ratings{$id}; + my $player = sprintf "%s (%.0f ± %.0f)", $players{$id}, ($ratings{$id} // 1500.0), ($ratings_stddev{$id} // $parms{-3}); $prob{$player} = [ @x[1..$#x] ]; } close MCCALC; @@ -230,13 +229,14 @@ print <<"EOF"; EOF # Get players and ratings -$q = $dbh->prepare('SELECT fotballdeltagere.id,fotballdeltagere.navn,rating FROM fotballdeltagere JOIN fotballserier ON fotballdeltagere.serie=fotballserier.nr LEFT JOIN ratings ON fotballdeltagere.id=ratings.id WHERE sesong=? AND divisjon=? AND avdeling=?'); +$q = $dbh->prepare('SELECT fotballdeltagere.id,fotballdeltagere.navn,rating,rating_stddev FROM fotballdeltagere JOIN fotballserier ON fotballdeltagere.serie=fotballserier.nr LEFT JOIN ratings ON fotballdeltagere.id=ratings.id WHERE sesong=? AND divisjon=? AND avdeling=?'); $q->execute($season, $division, $subdivision); while (my $ref = $q->fetchrow_hashref) { my $id = $ref->{'id'}; $players{$id} = sanitize(Encode::decode_utf8($ref->{'navn'})); $ratings{$id} = $ref->{'rating'}; + $ratings_stddev{$id} = $ref->{'rating_stddev'}; } $q->finish; @@ -259,14 +259,14 @@ while (my $ref = $q->fetchrow_hashref) { $q->finish; my $lowest_division = ($division == $max_division); -make_table($lowest_division, {}); +make_table($lowest_division, {}, {}); print <<"EOF";

Under er en variant som tar relativ spillestyrke med i beregningen; se ratingsiden.

EOF -make_table($lowest_division, \%ratings); +make_table($lowest_division, \%ratings, \%ratings_stddev); print << "EOF"; -- 2.39.2