PageRenderTime 43ms CodeModel.GetById 32ms app.highlight 9ms RepoModel.GetById 0ms app.codeStats 1ms

/website/game_list.php

https://github.com/spacebat/aichallenge
PHP | 332 lines | 274 code | 25 blank | 33 comment | 66 complexity | 3b0b7d646d42a2fb242f08bc8c5e22f5 MD5 | raw file
  1<?php
  2
  3require_once('mysql_login.php');
  4require_once('memcache.php');
  5require_once('pagination.php');
  6require_once('nice.php');
  7
  8//require_once('api_functions.php');
  9
 10//require_once('session.php');
 11// session is needed to highlight the current user
 12// but is not included here so that json requests go faster
 13// you must include it in your php if you wish to render html tables
 14
 15// used for looking at latest results only with view more link
 16//  should be smaller than page size
 17$top_results_size = 10;
 18// used for looking at pages with pagination links
 19$page_size = 50;
 20
 21// this function doesn't really belong here, but I can't think of a good place
 22// it works like filter_input with an optional filter and default value
 23function get_type_or_else($key, $type=NULL, $default=NULL) {
 24    if (isset($_GET[$key])) {
 25        $value = $_GET[$key];
 26        if ($type == NULL) {
 27            return $value;
 28        } else {
 29            $filter_value = filter_var($value, $type, FILTER_NULL_ON_FAILURE);
 30            if ($filter_value !== NULL) {
 31                return $filter_value;
 32            }
 33        }
 34    }
 35    return $default;
 36}
 37
 38function cache_key($page=0, $user_id=NULL, $submission_id=NULL, $map_id=NULL, $format='json') {
 39    if ($page == -1) {
 40        $page = "page_count";
 41    }
 42    if ($user_id !== NULL) {
 43        $key = "game_list:user:" . strval($user_id);
 44    } elseif ($submission_id !== NULL) {
 45        $key = "game_list:submission:" . strval($submission_id);
 46    } elseif ($map_id !== NULL) {
 47        $key = "game_list:map:" . strval($map_id);
 48    } else {
 49        $key = "game_list:all::";
 50    }
 51    return $key. ":" . strval($page) . ":" . $format;
 52}
 53
 54// page 0 is all results, page 1 is the top N results
 55function produce_cache_results($page=0, $user_id=NULL, $submission_id=NULL, $map_id=NULL) {
 56    global $memcache;
 57    global $page_size;
 58
 59    $page_count_query = "select_game_list_page_count";
 60    $list_query = "select_game_list";
 61    if ($user_id !== NULL) {
 62        $list_select_field = "user_id";
 63        $list_id = $user_id;
 64        $list_type = "user";
 65        $list_id_field = "username";
 66    } elseif ($submission_id !== NULL) {
 67        $list_select_field = "submission_id";
 68        $list_id = $submission_id;
 69        $list_type = "submission";
 70        $list_id_field = "submission_id";
 71    } elseif ($map_id !== NULL) {
 72        $page_count_query = "select_map_game_list_page_count";
 73        $list_query = "select_map_game_list";
 74        $list_select_field = "map_id";
 75        $list_id = $map_id;
 76        $list_type = "map";
 77        $list_id_field = "map_id";
 78    } else {
 79        // make the where clause always return true
 80        $page_count_query = "select_map_game_list_page_count";
 81        $list_query = "select_map_game_list";
 82        $list_select_field = "1";
 83        $list_id = 1;
 84        $list_type = NULL;
 85    }
 86    $list_results = contest_query($page_count_query, $list_select_field, $list_id);
 87    if ($list_results) {
 88        while ($list_row = mysql_fetch_array($list_results, MYSQL_NUM)) {
 89            $row_count = $list_row[0];
 90            $page_count = ceil($row_count / $page_size);
 91        }
 92    }
 93    $memcache->set(cache_key(-1, $user_id, $submission_id, $map_id), $page_count);
 94    if ($page == 0) {
 95        $offset = 0;
 96        $limit = $row_count;
 97    } else {
 98        $offset = ($page - 1) * $page_size;
 99        $limit = $page_size;
100    }
101    $json = array("fields" => array(),
102                  "values" => array());
103    if ($page > 0) {
104        $json["page"] = $page;
105        $json["page_count"] = $page_count;
106    }
107    $list_results = contest_query($list_query, $list_select_field, $list_id, $limit, $offset);
108    $list_id_name = NULL;
109    if ($list_results) {
110        $field_count = mysql_num_fields($list_results);
111        $row_count = mysql_num_rows($list_results);
112        $field_names = array();
113        for ($i = 0; $i < $field_count; $i++) {
114            $field_names[] = mysql_field_name($list_results, $i);
115        }
116        $json["fields"] = $field_names;
117        // this list and offset should match the results of the sql queries
118        //    select_game_list
119        $user_fields = array("user_id", "submission_id", "username", "version", "player_id", "game_rank", "status", "skill", "mu", "sigma", "skill_change", "mu_change", "sigma_change");
120        $user_fields_offset = 9;
121        /*
122        if ($user_id !== NULL or $submission_id !== NULL) {
123            foreach ($user_fields as $user_field) {
124                $json["fields"][] = $user_field;
125            }
126        }
127        */
128        $row_num = 0;
129        $game_row_num = 0;
130        $page_num = 0;
131        $last_game_id = -1;
132        $cur_row = NULL;
133        while ($list_row = mysql_fetch_array($list_results, MYSQL_NUM)) {
134            // get list name, run once
135            if ($list_type and !$list_id_name) {
136                $list_row_by_name = array_combine($field_names, $list_row);
137                $list_id_name = $list_row_by_name[$list_id_field];
138            }
139            // get additional opponent info
140            if ($list_row[0] == $last_game_id) {
141                for ($i = 0; $i < count($user_fields); $i++) {
142                    $cur_row[$i + $user_fields_offset][] = $list_row[$i + $user_fields_offset];
143                }
144            } else {
145            // get new game info
146                // dump results of row
147                if ($cur_row !== NULL) {
148                    $json["values"][] = $cur_row;
149                    $game_row_num++;
150                }
151                // setup new row
152                $row_num++;
153                $cur_row = $list_row;
154                for ($i = 0; $i < count($user_fields); $i++) {
155                    $cur_row[$i + $user_fields_offset] = array($cur_row[$i + $user_fields_offset]);
156                }
157            }
158            $last_game_id = $list_row[0];
159        }
160        // dump last row
161        if ($cur_row !== NULL) {
162            $json["values"][] = $cur_row;
163        }
164        // dump results
165        if ($list_type) {
166            $json["type"] = $list_type;
167            $json["type_id"] = $list_id;
168            $json["type_name"] = $list_id_name;
169        } else {
170            $json["type"] = "all";
171        }
172        $json_result = json_encode($json);
173        $memcache->set(cache_key($page, $user_id, $submission_id, $map_id),
174                       $json_result);
175        return $json_result;
176    }
177    return NULL;
178}
179
180function create_game_list_table($json, $top=FALSE, $targetpage=NULL) {
181    global $top_results_size;
182
183    if ($targetpage === NULL) {
184	$targetpage = $_SERVER['PHP_SELF'];
185    }
186    if ($json == NULL) {
187        return '<h4>There are no games at this time.  Please check back later.</h4>';
188    }
189    if ($json['type'] == 'user') {
190        $user_id = $json['type_id'];
191    } else {
192        $user_id = NULL;
193    }
194    $table = '<table class="games">';
195    if (array_key_exists('type', $json) && strcmp($json['type'], "all") != 0) {
196        // language by name, others by id
197        if ($json['type'] == 'language') {
198            $page_string = '?'.$json['type'].'='.$json['type_name'].'&page=';
199        } else {
200            $page_string = '?'.$json['type'].'='.$json['type_id'].'&page=';
201        }
202    } else {
203        $page_string = '?page=';
204    }
205    if (!$top) {
206        $table .= '<caption>'.getPaginationString($json['page'], $json['page_count'], 10, $page_string)."</caption>";
207    }
208    // produce header
209    $table .= '<thead><tr><th>Time</th>';
210    if ($user_id) {
211        $table .= '<th>Version</th><th>Skill</th>';
212    }
213    $table .= '<th>Opponents</th>';
214    if ($user_id) {
215        $table .= '<th>Outcome</th>';
216        $table .= '<th>Status</th>';
217    }
218    $table .= '<th>Map</th><th>Viewer</th></tr></thead>';
219    if (count($json["values"]) > 0) {
220        $table .= '<tbody>';
221        $oddity = 'even';
222        $fields = $json["fields"];
223        $row_num = 0;
224        foreach ($json["values"] as $values) {
225            $row_num++;
226            $row = array_combine($fields, $values);
227            
228            // find current user info
229            if ($user_id) {
230                for ($i = 0; $i < $row['players']; $i++) {
231                    if ($row["user_id"][$i] == $user_id) {
232                        $user_version = $row["version"][$i];
233                        $user_submission_id = $row["submission_id"][$i];
234                        $user_skill = $row["skill"][$i];
235                        $user_mu = $row["mu"][$i];
236                        $user_sigma = $row["sigma"][$i];
237                        $user_skill_change = $row["skill_change"][$i];
238                        $user_mu_change = $row["mu_change"][$i];
239                        $user_sigma_change = $row["sigma_change"][$i];
240                        $user_rank = $row["game_rank"][$i];
241                        $user_status = $row["status"][$i];
242                        break;
243                    }
244                }                
245            }
246
247            $oddity = $oddity == 'odd' ? 'even' : 'odd';  // quite odd?
248            $user_class = current_username() == $row["username"] ? ' user' : '';
249            $table .= "<tr class=\"$oddity$user_class\">";
250
251            $time = new DateTime($row["timestamp"]);
252            // $time = "<span title=\"".no_wrap(nice_interval($now->diff($time))." ago")."\">".no_wrap($time->format('j M G:i'))."</span>";
253            $time = nice_datetime_span($time);
254            $table .= "<td>$time</td>";
255
256            if ($user_id) {
257                $table .= "<td class=\"number\">".nice_version($user_version, NULL, $user_submission_id)."</td>";
258                $table .= "<td class=\"number\">".nice_skill($user_skill, $user_mu, $user_sigma, $user_skill_change, $user_mu_change, $user_sigma_change)."</td>";
259            }
260
261            // TODO: consider linking the submission id instead
262            $opponents = "";
263            for ($i = 0; $i < $row['players']; $i++) {
264                $opponents .= nice_opponent($row["user_id"][$i], $row["username"][$i], $row["game_rank"][$i] + 1, $row["user_id"][$i] == $user_id);
265            }
266            $table .= "<td class=\"list\">$opponents</td>";
267
268            if ($user_id) {
269                $outcome = nice_outcome($user_rank+1, $row['players']);
270                $table .= "<td>$outcome</td>";
271
272                $table .= "<td>$user_status</td>";
273            }
274
275            $map = nice_map($row['map_name']);
276            $table .= "<td>$map</td>";
277
278            $game = nice_game($row['game_id'], $row['game_length'], $row['winning_turn'], $row['ranking_turn'], $row['cutoff'], $user_id);
279            $table .= "<td>$game</td>";
280
281            $table .= "</tr>";
282            if ($top and $row_num == $top_results_size) {
283                break;
284            }
285        }
286        $table .= '</tbody>';
287    }
288    if ($top) {
289        $table .= '<caption align="bottom"><a href="'.$targetpage.$page_string.'1">View More &raquo;</a></caption>';
290    }
291    $table .= '</table>';
292    if (!$top) {
293        $table .= '<div style="text-align:center">'.getPaginationString($json['page'], $json['page_count'], 10, $page_string)."</div>";
294    }
295
296    return $table;
297}
298
299function get_game_list_json($page=0, $user_id=NULL, $submission_id=NULL, $map_id=NULL) {
300    global $memcache;
301
302    $cache_key = cache_key($page, $user_id, $submission_id, $map_id);
303    if ($memcache) {
304        $results = $memcache->get($cache_key);
305    }
306    $results = NULL; // use to force data refresh when debugging
307    if (!$results) {
308        $results = produce_cache_results($page, $user_id, $submission_id, $map_id);
309    }
310    return $results;
311}
312
313function get_game_list_table($page=0, $user_id=NULL, $submission_id=NULL, $map_id=NULL, $top=FALSE, $targetpage=NULL) {
314    global $memcache;
315    $format = $top ? 'top' : 'table';
316    $page = $top ? 1 : $page;
317    $cache_key = cache_key($page, $user_id, $submission_id, $map_id, $format);
318    if ($memcache) {
319        $results = $memcache->get($cache_key);
320    }
321    $results = NULL; // use to force data refresh when debugging
322    if (!$results) {
323        $json = get_game_list_json($page, $user_id, $submission_id, $map_id);
324        $results = create_game_list_table(json_decode($json, true), $top, $targetpage);
325        if ($memcache) {
326            $memcache->set($cache_key, $results);
327        }
328    }
329    return $results;
330}
331
332?>