11 #include "ziggurat.hpp"
15 #define MAX_PLAYERS 16
17 float match_stddev = 70.0f;
23 struct highest_ranking {
25 bool operator() (const player &a, const player &b) const {
26 if (a.points != b.points) {
27 return a.points > b.points;
29 return a.margin > b.margin;
36 return rand() * (1.0f / RAND_MAX);
39 // FIXME: replace rejection method with a better method! this one can only ever go to [-5z, +5z]
41 float draw_gaussian(float stddev)
44 float z = draw_unit() * 10.0f - 5.0f;
45 float y = draw_unit();
52 float draw_gaussian(float mu, float stddev)
54 static bool inited = false;
55 static long unsigned seed = time(NULL);
57 static float fn[128], wn[128];
59 r4_nor_setup(kn, fn, wn);
63 return r4_nor(&seed, kn, fn, wn) * stddev + mu;
67 int main(int argc, char **argv)
69 int trials = atoi(argv[1]);
71 if (scanf("%f", &match_stddev) != 1) {
72 fprintf(stderr, "Could't read match stddev\n");
77 if (scanf("%d", &num_players) != 1) {
78 fprintf(stderr, "Could't read number of players\n");
82 if (num_players > MAX_PLAYERS) {
83 fprintf(stderr, "Max %d players supported\n", MAX_PLAYERS);
87 vector<string> players;
88 map<string, int> player_map;
89 float ratings[MAX_PLAYERS];
90 float ratings_stddev[MAX_PLAYERS];
91 bool has_scores[MAX_PLAYERS][MAX_PLAYERS];
92 for (int pl1 = 0; pl1 < num_players; ++pl1) {
93 for (int pl2 = 0; pl2 < num_players; ++pl2) {
94 has_scores[pl1][pl2] = false;
98 int scores[MAX_PLAYERS][MAX_PLAYERS];
99 for (int i = 0; i < num_players; ++i) {
101 float rating, rating_stddev;
102 int ret = scanf("%s %f %f", buf, &rating, &rating_stddev);
104 fprintf(stderr, "Couldn't read player %d\n", i);
111 rating_stddev = 0.0f;
114 players.push_back(buf);
117 ratings_stddev[i] = rating_stddev;
121 char pl1[256], pl2[256];
124 if (scanf("%s %s %d %d", pl1, pl2, &score1, &score2) != 4) {
128 if (player_map.count(pl1) == 0) {
129 fprintf(stderr, "Unknown player '%s'\n", pl1);
132 if (player_map.count(pl2) == 0) {
133 fprintf(stderr, "Unknown player '%s'\n", pl2);
137 scores[player_map[pl1]][player_map[pl2]] = score1;
138 scores[player_map[pl2]][player_map[pl1]] = score2;
139 has_scores[player_map[pl1]][player_map[pl2]] = true;
140 has_scores[player_map[pl2]][player_map[pl1]] = true;
143 int placements[MAX_PLAYERS][MAX_PLAYERS];
144 for (int i = 0; i < num_players; ++i) {
145 for (int j = 0; j < num_players; ++j) {
146 placements[i][j] = 0;
150 for (int i = 0; i < trials; ++i) {
151 // draw true strength for all players
152 float drawn_ratings[MAX_PLAYERS];
153 for (int p = 0; p < num_players; ++p) {
154 drawn_ratings[p] = draw_gaussian(ratings[p], ratings_stddev[p]);
157 // draw the missing matches
158 for (int pl1 = 0; pl1 < num_players; ++pl1) {
159 for (int pl2 = pl1 + 1; pl2 < num_players; ++pl2) {
160 if (has_scores[pl1][pl2]) {
164 float mu = drawn_ratings[pl1] - drawn_ratings[pl2];
166 int score = lrintf(draw_gaussian(mu, match_stddev));
167 scores[pl1][pl2] = score;
168 scores[pl2][pl1] = -score;
172 // sum up the points and margin for each player
173 player stats[MAX_PLAYERS];
174 for (int pl1 = 0; pl1 < num_players; ++pl1) {
175 stats[pl1].player_index = pl1;
176 stats[pl1].points = 0;
177 stats[pl1].margin = 0;
178 for (int pl2 = 0; pl2 < num_players; ++pl2) {
182 stats[pl1].margin += scores[pl1][pl2];
183 stats[pl1].margin -= scores[pl2][pl1];
184 if (scores[pl1][pl2] > scores[pl2][pl1]) {
185 stats[pl1].points += 2;
186 } else if (scores[pl1][pl2] == scores[pl2][pl1]) {
192 // order by points and then margin
193 sort(stats, stats + num_players, highest_ranking());
194 for (int j = 0; j < num_players; ++j) {
195 ++placements[stats[j].player_index][j];
199 for (int i = 0; i < num_players; ++i) {
200 printf("%-15s", players[i].c_str());
201 for (int j = 0; j < num_players; ++j) {
202 printf(" %5d", placements[i][j]);