]> git.sesse.net Git - wloh/commitdiff
Take standard deviation of estimated mu into account when doing MC simulation.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 19 Mar 2012 01:52:47 +0000 (02:52 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 19 Mar 2012 01:52:47 +0000 (02:52 +0100)
mcwordfeud.cpp
www/index.pl

index 2bd4a5243cc1847b8251b5d4ed1ed48787dd2531..b48936d4a36c43a606fe57a95061a6e486bd9f89 100644 (file)
@@ -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<string> players;
        map<string, int> 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;
                        }
index 604edc263dd4aa184ccab9d9decf387967948562..d1943ae08b51af076fbff942e9ca48642bbf8090 100755 (executable)
@@ -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 &pm; %.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";
     <p>Under er en variant som tar relativ spillestyrke med i beregningen;
       se <a href="/rating">ratingsiden</a>.</p>
 EOF
 
-make_table($lowest_division, \%ratings);
+make_table($lowest_division, \%ratings, \%ratings_stddev);
 
 print << "EOF";
     </table>