4c4800de990386f995187820be5142e0999adb21
[xonotic/xonstat.git] / xonstat / views / game.py
1 import datetime
2 import logging
3 import re
4 import time
5 from pyramid.response import Response
6 from sqlalchemy import desc, func, over
7 from webhelpers.paginate import Page, PageURL
8 from xonstat.models import *
9 from xonstat.util import page_url
10 from xonstat.views.helpers import RecentGame, recent_games_q
11
12 log = logging.getLogger(__name__)
13
14
15 def _game_index_data(request):
16     if request.params.has_key('page'):
17         current_page = request.params['page']
18     else:
19         current_page = 1
20
21     games_q = DBSession.query(Game, Server, Map).\
22             filter(Game.server_id == Server.server_id).\
23             filter(Game.map_id == Map.map_id).\
24             order_by(Game.game_id.desc())
25
26     games = Page(games_q, current_page, items_per_page=10, url=page_url)
27
28     pgstats = {}
29     for (game, server, map) in games:
30         pgstats[game.game_id] = DBSession.query(PlayerGameStat).\
31                 filter(PlayerGameStat.game_id == game.game_id).\
32                 order_by(PlayerGameStat.scoreboardpos).\
33                 order_by(PlayerGameStat.score).all()
34
35     return {'games':games,
36             'pgstats':pgstats}
37
38
39 def game_index(request):
40     """
41     Provides a list of current games, with the associated game stats.
42     These games are ordered by game_id, with the most current ones first.
43     Paginated.
44     """
45     return _game_index_data(request)
46
47
48 def game_index_json(request):
49     """
50     Provides a list of current games, with the associated game stats.
51     These games are ordered by game_id, with the most current ones first.
52     Paginated. JSON.
53     """
54     return [{'status':'not implemented'}]
55
56
57 def _game_info_data(request):
58     game_id = request.matchdict['id']
59
60     if request.params.has_key('show_elo'):
61         show_elo = True
62     else:
63         show_elo = False
64
65     if request.params.has_key('show_latency'):
66         show_latency = True
67     else:
68         show_latency = False
69
70     try:
71         notfound = False
72
73         (game, server, map) = DBSession.query(Game, Server, Map).\
74                 filter(Game.game_id == game_id).\
75                 filter(Game.server_id == Server.server_id).\
76                 filter(Game.map_id == Map.map_id).one()
77
78         pgstats = DBSession.query(PlayerGameStat).\
79                 filter(PlayerGameStat.game_id == game_id).\
80                 order_by(PlayerGameStat.scoreboardpos).\
81                 order_by(PlayerGameStat.score).\
82                 all()
83
84         captimes = []
85         if game.game_type_cd == 'ctf':
86             for pgstat in pgstats:
87                 if pgstat.fastest is not None:
88                     captimes.append(pgstat)
89
90             captimes = sorted(captimes, key=lambda x:x.fastest)
91
92         pwstats = {}
93         for (pwstat, pgstat, weapon) in DBSession.query(PlayerWeaponStat, PlayerGameStat, Weapon).\
94                 filter(PlayerWeaponStat.game_id == game_id).\
95                 filter(PlayerWeaponStat.weapon_cd == Weapon.weapon_cd).\
96                 filter(PlayerWeaponStat.player_game_stat_id == \
97                     PlayerGameStat.player_game_stat_id).\
98                 order_by(PlayerGameStat.scoreboardpos).\
99                 order_by(PlayerGameStat.score).\
100                 order_by(Weapon.descr).\
101                 all():
102                     if pgstat.player_game_stat_id not in pwstats:
103                         pwstats[pgstat.player_game_stat_id] = []
104
105                     # NOTE adding pgstat to position 6 in order to display nick.
106                     # You have to use a slice [0:5] to pass to the accuracy 
107                     # template
108                     pwstats[pgstat.player_game_stat_id].append((weapon.descr, 
109                         weapon.weapon_cd, pwstat.actual, pwstat.max, 
110                         pwstat.hit, pwstat.fired, pgstat))
111
112     except Exception as inst:
113         game = None
114         server = None
115         map = None
116         pgstats = None
117         pwstats = None
118         captimes = None
119         show_elo = False
120         show_latency = False
121         raise inst
122
123     return {'game':game,
124             'server':server,
125             'map':map,
126             'pgstats':pgstats,
127             'pwstats':pwstats,
128             'captimes':captimes,
129             'show_elo':show_elo,
130             'show_latency':show_latency,
131             }
132
133
134 def game_info(request):
135     """
136     List the game stats (scoreboard) for a particular game. Paginated.
137     """
138     return _game_info_data(request)
139
140
141 def game_info_json(request):
142     """
143     List the game stats (scoreboard) for a particular game. Paginated. JSON.
144     """
145     return [{'status':'not implemented'}]
146
147
148 def _rank_index_data(request):
149     if request.params.has_key('page'):
150         current_page = request.params['page']
151     else:
152         current_page = 1
153
154     game_type_cd = request.matchdict['game_type_cd']
155
156     ranks_q = DBSession.query(PlayerRank).\
157             filter(PlayerRank.game_type_cd==game_type_cd).\
158             order_by(PlayerRank.rank)
159
160     ranks = Page(ranks_q, current_page, url=page_url)
161
162     if len(ranks) == 0:
163         ranks = None
164
165     return {
166             'ranks':ranks,
167             'game_type_cd':game_type_cd,
168            }
169
170
171 def rank_index(request):
172     """
173     Provide a list of gametype ranks, paginated.
174     """
175     return _rank_index_data(request)
176
177
178 def rank_index_json(request):
179     """
180     Provide a list of gametype ranks, paginated. JSON.
181     """
182     return [{'status':'not implemented'}]
183
184
185 def game_finder_data(request):
186     if request.params.has_key('page'):
187         current_page = request.params['page']
188     else:
189         current_page = 1
190
191     query = {}
192
193     server_id, map_id, player_id = None, None, None
194     range_start, range_end = None, None
195     # these become WHERE clauses when present
196     if request.params.has_key('server_id'):
197         server_id = request.params['server_id']
198         query['server_id'] = server_id
199
200     if request.params.has_key('map_id'):
201         map_id = request.params['map_id']
202         query['map_id'] = map_id
203
204     if request.params.has_key('player_id'):
205         player_id = request.params['player_id']
206         query['player_id'] = player_id
207
208     if request.params.has_key('range_start'):
209         range_start = request.params['range_start']
210         query['range_start'] = range_start
211
212     if request.params.has_key('range_end'):
213         range_end = request.params['range_end']
214         query['range_end'] = range_end
215
216     rgs_q = recent_games_q(server_id=server_id, map_id=map_id,
217             player_id=player_id)
218
219     recent_games = Page(rgs_q, current_page, url=page_url)
220
221     recent_games.items = [RecentGame(row) for row in recent_games.items]
222
223     return {
224             'recent_games':recent_games,
225             'query':query,
226            }
227
228 def game_finder(request):
229     """
230     Provide a list of recent games with an advanced filter.
231     """
232     return game_finder_data(request)