]> git.sesse.net Git - wloh/blob - www/rating.pl
Make the pages validate as XHTML 1.1.
[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
15 my $dbh = DBI->connect($config::local_connstr, $config::local_username, $config::local_password)
16         or die "connect: " . $DBI::errstr;
17 $dbh->{AutoCommit} = 0;
18 $dbh->{RaiseError} = 1;
19
20 binmode STDOUT, ':utf8';
21
22 # Find auxillary parameters.
23 my %params = ();
24 my $q = $dbh->prepare('SELECT * FROM ratings WHERE id < 0');
25 $q->execute;
26 while (my $ref = $q->fetchrow_hashref) {
27         $params{$ref->{'id'}} = $ref->{'rating'};
28 }
29 my $match_stddev = $params{-2} * sqrt(2.0);
30
31 print CGI->header(-type=>'text/html; charset=utf-8', -expires=>'+5m');
32 POSIX::setlocale(&POSIX::LC_ALL, 'nb_NO.UTF-8');
33
34 printf <<"EOF", $params{-3}, $match_stddev;
35 <?xml version="1.0" encoding="UTF-8" ?>
36 <!DOCTYPE
37   html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
38   "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
39 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="no">
40   <head>
41     <title>WLoH-rating</title>
42     <link rel="stylesheet" href="/style" type="text/css" />
43   </head>
44   <body>
45     <h1>WLoH-rating</h1>
46
47     <p><em>Dette er et hobbyprosjekt fra tredjepart, og ikke en offisiell del av
48       <a href="http://wordfeud.aasmul.net/">Wordfeud Leage of Honour</a>.</em></p>
49
50     <p>Ratingen er dog basert på spilledata fra WLoH (takk til Lobotommy
51       for tilgang!), og oppdateres
52       hver hele time. Den er fullstendig uoffisiell, og har ingen innflytelse
53       på WLoH, men brukes for å estimere vinnersannsynligheter i
54       <a href="/">sannsynlighetsberegningen</a>.</p>
55
56     <p>Modellen kan endre seg når som helst når jeg føler for det :-)
57       Ikke ta ratingen alt for alvorlig, selv om den er basert på
58       relativt fornuftige matematiske modeller. Husk at all statistikk
59       sier mer om fortiden enn om framtiden.</p>
60
61     <h2>Modellparametre</h2>
62
63     <p>For de som vet litt om slikt. Det finnes også en lengre, mer detaljert
64       <a href="/ratings-explained">forklaring</a> beregnet på ikke-matematikere.</p>
65
66     <ul>
67       <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: $params{-1}.</li>
68       <li>Rimelighetfunksjon, prior: Normalfordeling med µ=1500, &sigma;=%.1f (est.)</li>
69       <li>Rimelighetfunksjon, per kamp: Normalfordeling med µ=(score1 - score2), &sigma;=%.1f (est.)</li>
70       <li>Vekting: Inneværende sesong samt de tre siste vektes fullt ut
71         (likt med prior). Deretter eksponentielt synkende vekting, med
72         halveringstid på tre sesonger. Spill som er registrert med
73         150-0, 0-150 eller 150-150 ignoreres.</li>
74     </ul>
75
76     <h2>Divisjonsoversikt</h2>
77
78     <table>
79       <tr>
80         <th>Div.</th>
81         <th>Snitt</th>
82         <th>Std.avvik</th>
83       </tr>
84 EOF
85
86 $q = $dbh->prepare('SELECT divisjon,AVG(rating) AS avg_rating,STDDEV(rating) AS stddev_rating FROM ratings NATURAL JOIN siste_divisjon GROUP BY divisjon ORDER BY divisjon');
87 $q->execute;
88
89 my $i = 0;
90 while (my $ref = $q->fetchrow_hashref) {
91         if (++$i % 2 == 0) {
92                 print "      <tr class=\"odd\">\n";
93         } else {
94                 print "      <tr class=\"even\">\n";
95         }
96         printf "        <th>%d.</th>\n", $ref->{'divisjon'};
97         printf "        <td class=\"num\">%.1f</td>\n", $ref->{'avg_rating'};
98         printf "        <td class=\"num\">%.1f</td>\n", $ref->{'stddev_rating'};
99         print "      </tr>\n";
100 }
101
102 print <<"EOF";
103     </table>
104
105   <h2>Rankingliste</h2>
106
107   <table>
108     <tr>
109       <th></th>
110       <th>Nick</th>
111       <th>Rating</th>
112       <th>Std.avvik</th>
113       <th>Sist sett</th>
114     </tr>
115 EOF
116
117 $q = $dbh->prepare('
118 SELECT *
119 FROM ratings
120   NATURAL JOIN kanonisk_navn
121   NATURAL JOIN siste_divisjon
122 ORDER BY rating DESC');
123 $q->execute;
124
125 $i = 0;
126 while (my $ref = $q->fetchrow_hashref) {
127         if (++$i % 2 == 0) {
128                 print "    <tr class=\"odd\">\n";
129         } else {
130                 print "    <tr class=\"even\">\n";
131         }
132         printf "      <th>%d.</th>\n", $i;
133         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'}));
134         printf "      <td class=\"num\">%.1f</td>\n", $ref->{'rating'};
135         printf "      <td class=\"num\">%.1f</td>\n", $ref->{'rating_stddev'};
136         printf "      <td><a href=\"http://wordfeud.aasmul.net/serie-%d\">%s</a></td>\n", $ref->{'serie_id'}, $ref->{'serie_navn'};
137         print "    </tr>\n";
138 }
139
140 print <<"EOF";
141     </table>
142   </body>
143 </html>
144 EOF
145
146 $match_stddev = $params{-2} * sqrt(2.0);
147
148 $dbh->rollback;