5 from collections import OrderedDict
6 from pyramid.response import Response
7 from sqlalchemy import desc, func, over
8 from collections import namedtuple
9 from webhelpers.paginate import Page, PageURL
10 from xonstat.models import *
11 from xonstat.util import page_url
12 from xonstat.views.helpers import RecentGame, recent_games_q
16 log = logging.getLogger(__name__)
20 def _game_index_data(request):
22 game_type_descr = None
24 if request.params.has_key('game_type_cd'):
25 game_type_cd = request.params['game_type_cd']
27 game_type_descr = DBSession.query(GameType.descr).\
28 filter(GameType.game_type_cd == game_type_cd).\
30 except Exception as e:
33 if request.params.has_key('page'):
34 current_page = request.params['page']
39 rgs_q = recent_games_q(game_type_cd=game_type_cd)
41 games = Page(rgs_q, current_page, items_per_page=10, url=page_url)
43 # replace the items in the canned pagination class with more rich ones
44 games.items = [RecentGame(row) for row in games.items]
47 for game in games.items:
48 pgstats[game.game_id] = DBSession.query(PlayerGameStat).\
49 filter(PlayerGameStat.game_id == game.game_id).\
50 order_by(PlayerGameStat.scoreboardpos).\
51 order_by(PlayerGameStat.score).all()
53 except Exception as e:
57 game_type_descr = None
59 return {'games':games,
61 'game_type_cd':game_type_cd,
62 'game_type_descr':game_type_descr,
66 def game_index(request):
68 Provides a list of current games, with the associated game stats.
69 These games are ordered by game_id, with the most current ones first.
72 return _game_index_data(request)
75 def game_index_json(request):
77 Provides a list of current games, with the associated game stats.
78 These games are ordered by game_id, with the most current ones first.
81 return [{'status':'not implemented'}]
84 def _game_info_data(request):
85 game_id = request.matchdict['id']
87 if request.params.has_key('show_elo'):
97 (game, server, map, gametype) = DBSession.query(Game, Server, Map, GameType).\
98 filter(Game.game_id == game_id).\
99 filter(Game.server_id == Server.server_id).\
100 filter(Game.map_id == Map.map_id).\
101 filter(Game.game_type_cd == GameType.game_type_cd).one()
103 pgstats = DBSession.query(PlayerGameStat).\
104 filter(PlayerGameStat.game_id == game_id).\
105 order_by(PlayerGameStat.scoreboardpos).\
106 order_by(PlayerGameStat.score).\
109 # if at least one player has a valid latency, we'll show the column
110 for pgstat in pgstats:
111 if pgstat.avg_latency is not None:
114 q = DBSession.query(TeamGameStat).\
115 filter(TeamGameStat.game_id == game_id)
116 if game.game_type_cd == 'ctf':
117 q = q.order_by(TeamGameStat.caps.desc())
118 elif game.game_type_cd == 'ca':
119 q = q.order_by(TeamGameStat.rounds.desc())
120 # dom -> ticks, rc -> laps, nb -> goals, as -> objectives
122 q = q.order_by(TeamGameStat.score.desc())
126 stats_by_team = OrderedDict()
127 for pgstat in pgstats:
128 if pgstat.team not in stats_by_team.keys():
129 stats_by_team[pgstat.team] = []
130 stats_by_team[pgstat.team].append(pgstat)
133 if game.game_type_cd == 'ctf':
134 for pgstat in pgstats:
135 if pgstat.fastest is not None:
136 captimes.append(pgstat)
137 captimes = sorted(captimes, key=lambda x:x.fastest)
140 for pgstat in pgstats:
141 if pgstat.team in [5,14,13,10]:
142 team = pgstat.team_html_color()
143 if pgstat.teamscore is not None:
144 if not teamscores.has_key(team):
145 teamscores[team] = pgstat.teamscore
147 if teamscores[team] != pgstat.teamscore: # this should not happen!
148 teamscores[team] = None
149 if len(teamscores) == 0:
152 ### RANDOM SCORES FOR TESTING
153 teams = ["red","blue","yellow","pink"]
154 random.shuffle(teams)
156 for k in range(random.randint(2,4)):
158 teamscores[team] = random.randint(-5,150)
161 #TeamInfo = namedtuple('TeamInfo', ['team','scoreboardpos','playercount','teamscore'])
164 #last_pgs = pgstats[0]
165 #for pgstat in pgstats:
166 # if pgstat.team != last_pgs.team:
167 # teams[last_pgs.scoreboardpos] = TeamInfo(
168 # team=last_pgs.team,
169 # scoreboardpos=last_pgs.scoreboardpos,
170 # playercount=pgstat.scoreboardpos-last_pgs.scoreboardpos,
171 # teamscore=last_pgs.teamscore)
173 #teams[last_pgs.scoreboardpos] = TeamInfo(
174 # team=last_pgs.team,
175 # scoreboardpos=last_pgs.scoreboardpos,
176 # playercount=pgstat.scoreboardpos-last_pgs.scoreboardpos,
177 # teamscore=last_pgs.teamscore)
181 for (pwstat, pgstat, weapon) in DBSession.query(PlayerWeaponStat, PlayerGameStat, Weapon).\
182 filter(PlayerWeaponStat.game_id == game_id).\
183 filter(PlayerWeaponStat.weapon_cd == Weapon.weapon_cd).\
184 filter(PlayerWeaponStat.player_game_stat_id == \
185 PlayerGameStat.player_game_stat_id).\
186 order_by(PlayerGameStat.scoreboardpos).\
187 order_by(PlayerGameStat.score).\
188 order_by(Weapon.descr).\
190 if pgstat.player_game_stat_id not in pwstats:
191 pwstats[pgstat.player_game_stat_id] = []
193 # NOTE adding pgstat to position 6 in order to display nick.
194 # You have to use a slice [0:5] to pass to the accuracy
196 pwstats[pgstat.player_game_stat_id].append((weapon.descr,
197 weapon.weapon_cd, pwstat.actual, pwstat.max,
198 pwstat.hit, pwstat.fired, pgstat))
200 except Exception as inst:
224 'teamscores':teamscores,
226 'show_latency':show_latency,
227 'stats_by_team':stats_by_team,
231 def game_info(request):
233 List the game stats (scoreboard) for a particular game. Paginated.
235 return _game_info_data(request)
238 def game_info_json(request):
240 List the game stats (scoreboard) for a particular game. Paginated. JSON.
242 return [{'status':'not implemented'}]
245 def _rank_index_data(request):
246 if request.params.has_key('page'):
247 current_page = request.params['page']
251 game_type_cd = request.matchdict['game_type_cd']
253 ranks_q = DBSession.query(PlayerRank).\
254 filter(PlayerRank.game_type_cd==game_type_cd).\
255 order_by(PlayerRank.rank)
257 ranks = Page(ranks_q, current_page, url=page_url)
264 'game_type_cd':game_type_cd,
268 def rank_index(request):
270 Provide a list of gametype ranks, paginated.
272 return _rank_index_data(request)
275 def rank_index_json(request):
277 Provide a list of gametype ranks, paginated. JSON.
279 return [{'status':'not implemented'}]
282 def game_finder_data(request):
283 if request.params.has_key('page'):
284 current_page = request.params['page']
290 server_id, map_id, player_id = None, None, None
291 range_start, range_end, game_type_cd = None, None, None
292 game_type_descr = None
294 # these become WHERE clauses when present
295 if request.params.has_key('server_id'):
296 server_id = request.params['server_id']
297 query['server_id'] = server_id
299 if request.params.has_key('map_id'):
300 map_id = request.params['map_id']
301 query['map_id'] = map_id
303 if request.params.has_key('player_id'):
304 player_id = request.params['player_id']
305 query['player_id'] = player_id
307 if request.params.has_key('range_start'):
308 range_start = request.params['range_start']
309 query['range_start'] = range_start
311 if request.params.has_key('range_end'):
312 range_end = request.params['range_end']
313 query['range_end'] = range_end
315 if request.params.has_key('type'):
316 game_type_cd = request.params['type']
317 query['type'] = game_type_cd
319 game_type_descr = DBSession.query(GameType.descr).\
320 filter(GameType.game_type_cd == game_type_cd).\
322 except Exception as e:
325 rgs_q = recent_games_q(server_id=server_id, map_id=map_id,
326 player_id=player_id, game_type_cd=game_type_cd)
328 recent_games = Page(rgs_q, current_page, url=page_url)
330 recent_games.items = [RecentGame(row) for row in recent_games.items]
333 'recent_games':recent_games,
335 'game_type_cd':game_type_cd,
338 def game_finder(request):
340 Provide a list of recent games with an advanced filter.
342 return game_finder_data(request)