]> git.sesse.net Git - wloh/blob - www/rating.pl
f69b19ac2307a3f9392dadc625f14bfe7b190537
[wloh] / www / rating.pl
1 #! /usr/bin/perl
2 use strict;
3 use warnings;
4 no warnings qw(once);
5 use CGI;
6 use CGI::Carp qw( fatalsToBrowser );
7 use DBI;
8 use Encode;
9 use POSIX;
10 use HTML::Entities;
11 use utf8;
12 use locale;
13 require '../config.pm';
14 require '../common.pm';
15
16 my $dbh = DBI->connect($config::local_connstr, $config::local_username, $config::local_password)
17         or die "connect: " . $DBI::errstr;
18 $dbh->{AutoCommit} = 0;
19 $dbh->{RaiseError} = 1;
20
21 binmode STDOUT, ':utf8';
22
23 my $aux_parms = wloh_common::get_auxillary_parameters($dbh);
24 my $match_stddev = $aux_parms->{'score_stddev'} * sqrt(2.0);
25
26 print CGI->header(-type=>'text/html; charset=utf-8', -expires=>'+5m');
27 POSIX::setlocale(&POSIX::LC_ALL, 'nb_NO.UTF-8');
28
29 printf <<"EOF", $aux_parms->{'rating_prior_stddev'}, $match_stddev;
30 <?xml version="1.0" encoding="UTF-8" ?>
31 <!DOCTYPE
32   html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
33   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
34 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="no">
35   <head>
36     <title>WLoH-rating</title>
37     <link rel="stylesheet" href="style" type="text/css" />
38   </head>
39   <body>
40     <h1>WLoH-rating</h1>
41
42     <p><em>Dette er et hobbyprosjekt fra tredjepart, og ikke en offisiell del av
43       <a href="http://wordfeud.aasmul.net/">Wordfeud Leage of Honour</a>.</em></p>
44
45     <p>Ratingen er dog basert på spilledata fra WLoH (takk til Lobotommy
46       for tilgang!), og oppdateres
47       hver hele time. Den er fullstendig uoffisiell, og har ingen innflytelse
48       på WLoH, men brukes for å estimere vinnersannsynligheter i
49       <a href="index">sannsynlighetsberegningen</a>.</p>
50
51     <p>Modellen kan endre seg når som helst når jeg føler for det :-)
52       Ikke ta ratingen alt for alvorlig, selv om den er basert på
53       relativt fornuftige matematiske modeller. Husk at all statistikk
54       sier mer om fortiden enn om framtiden.</p>
55
56     <h2>Modellparametre</h2>
57
58     <p>For de som vet litt om slikt. Det finnes også en lengre, mer detaljert
59       <a href="ratings-explained">forklaring</a> beregnet på ikke-matematikere.</p>
60
61     <ul>
62       <li>MLE-basert modell med én skalar (styrke) per spiller og to globale skalarer (begge standardavvik, se under), løst med syklisk MM (minorization-maximization). Antall iterasjoner før konvergens: $aux_parms->{num_iterations}.</li>
63       <li>Rimelighetfunksjon, prior: Normalfordeling med µ=500, &sigma;=%.1f (est.)</li>
64       <li>Rimelighetfunksjon, per kamp: Normalfordeling med µ=(score1 - score2), &sigma;=%.1f (est.)</li>
65       <li>Vekting: Inneværende sesong samt de tre siste vektes fullt ut
66         (likt med prior). Deretter eksponentielt synkende vekting, med
67         halveringstid på tre sesonger. Spill som er registrert med
68         0-0, 150-0, 0-150 eller 150-150 ignoreres.</li>
69     </ul>
70
71     <h2>Divisjonsoversikt</h2>
72
73     <table>
74       <tr>
75         <th>Div.</th>
76         <th>Snitt</th>
77         <th>Std.avvik</th>
78       </tr>
79 EOF
80
81 my $cgi = CGI->new;
82 my $locale = wloh_common::get_locale($cgi);
83 my $season = wloh_common::get_max_season($dbh, $locale);
84
85 # Pick up all the subdivisions' ratings.
86 my %subdivision_ratings = ();
87 my $q = $dbh->prepare('SELECT divisjon, avdeling, serie_id, AVG(rating) AS avg_rating FROM ratings NATURAL JOIN siste_divisjon WHERE sesong=? GROUP BY divisjon, avdeling, serie_id ORDER BY divisjon, avdeling');
88 $q->execute($season);
89
90 while (my $ref = $q->fetchrow_hashref) {
91         my $division = $ref->{'divisjon'};
92         my $rating = $ref->{'avg_rating'};
93         my $id = $ref->{'serie_id'};
94
95         push @{$subdivision_ratings{$division}}, [ $id, $rating ];
96 }
97
98 $q = $dbh->prepare('SELECT divisjon,AVG(rating) AS avg_rating,STDDEV(rating) AS stddev_rating FROM ratings NATURAL JOIN siste_divisjon WHERE sesong=? GROUP BY divisjon ORDER BY divisjon');
99 $q->execute($season);
100
101 my $i = 0;
102 while (my $ref = $q->fetchrow_hashref) {
103         if (++$i % 2 == 0) {
104                 print "      <tr class=\"odd\">\n";
105         } else {
106                 print "      <tr class=\"even\">\n";
107         }
108         printf "        <th>%d.</th>\n", $ref->{'divisjon'};
109         printf "        <td class=\"num\">%.1f</td>\n", $ref->{'avg_rating'};
110         printf "        <td class=\"num\">%.1f</td>\n", $ref->{'stddev_rating'};
111
112         for my $arr (@{$subdivision_ratings{$ref->{'divisjon'}}}) {
113                 my ($id, $rating) = @$arr;
114                 printf "        <td class=\"num\"><a href=\"http://wordfeud.aasmul.net/serie-%d\">%.1f</a></td>\n", $id, $rating;
115         }
116         print "      </tr>\n";
117 }
118
119 print <<"EOF";
120     </table>
121
122   <h2>Rankingliste</h2>
123
124   <table>
125     <tr>
126       <th></th>
127       <th>Nick</th>
128       <th>Rating</th>
129       <th>Std.avvik</th>
130       <th>Sist sett</th>
131     </tr>
132 EOF
133
134 $q = $dbh->prepare('
135 SELECT *
136 FROM ratings
137   NATURAL JOIN kanonisk_navn
138   NATURAL JOIN siste_divisjon
139   NATURAL JOIN spiller_kultur
140 WHERE kultur=?
141 ORDER BY rating DESC');
142 $q->execute($locale);
143
144 $i = 0;
145 while (my $ref = $q->fetchrow_hashref) {
146         if (++$i % 2 == 0) {
147                 print "    <tr class=\"odd\">\n";
148         } else {
149                 print "    <tr class=\"even\">\n";
150         }
151         printf "      <th>%d.</th>\n", $i;
152         printf "      <td><a href=\"http://wordfeud.aasmul.net/bruker-%d\">%s</a></td>\n", $ref->{'id'}, HTML::Entities::encode_entities(Encode::decode_utf8($ref->{'navn'}));
153         printf "      <td class=\"num\">%.1f</td>\n", $ref->{'rating'};
154         printf "      <td class=\"num\">%.1f</td>\n", $ref->{'rating_stddev'};
155         printf "      <td><a href=\"http://wordfeud.aasmul.net/serie-%d\">%s</a></td>\n", $ref->{'serie_id'}, $ref->{'serie_navn'};
156         print "    </tr>\n";
157 }
158 print "    </table>\n";
159
160 wloh_common::output_last_sync($dbh);
161
162 print <<"EOF";
163   </body>
164 </html>
165 EOF
166
167 $dbh->rollback;