2 from collections import namedtuple
3 from datetime import datetime, timedelta
5 import sqlalchemy.sql.expression as expr
6 import sqlalchemy.sql.functions as func
7 from pyramid import httpexceptions
8 from webhelpers.paginate import Page
9 from xonstat.models import DBSession, Server, Map, Game, PlayerGameStat, Player, PlayerCaptime
10 from xonstat.models.map import MapCapTime
11 from xonstat.util import page_url, html_colors
12 from xonstat.views.helpers import RecentGame, recent_games_q
14 log = logging.getLogger(__name__)
16 def _map_index_data(request):
17 if request.params.has_key('page'):
18 current_page = request.params['page']
23 map_q = DBSession.query(Map).\
24 order_by(Map.map_id.desc())
26 maps = Page(map_q, current_page, items_per_page=25, url=page_url)
28 except Exception as e:
31 return {'maps':maps, }
34 def map_index(request):
36 Provides a list of all the current maps.
38 return _map_index_data(request)
41 def map_index_json(request):
43 Provides a JSON-serialized list of all the current maps.
45 view_data = _map_index_data(request)
47 maps = [m.to_dict() for m in view_data['maps']]
52 def _map_info_data(request):
53 map_id = int(request.matchdict['id'])
56 leaderboard_lifetime = int(
57 request.registry.settings['xonstat.leaderboard_lifetime'])
59 leaderboard_lifetime = 30
61 leaderboard_count = 10
62 recent_games_count = 20
65 Captime = namedtuple('Captime', ['player_id', 'nick_html_colors',
66 'fastest_cap', 'game_id'])
69 gmap = DBSession.query(Map).filter_by(map_id=map_id).one()
71 # recent games played in descending order
72 rgs = recent_games_q(map_id=map_id).limit(recent_games_count).all()
73 recent_games = [RecentGame(row) for row in rgs]
75 # top players by score
76 top_scorers = DBSession.query(Player.player_id, Player.nick,
77 func.sum(PlayerGameStat.score)).\
78 filter(Player.player_id == PlayerGameStat.player_id).\
79 filter(Game.game_id == PlayerGameStat.game_id).\
80 filter(Game.map_id == map_id).\
81 filter(Player.player_id > 2).\
82 filter(PlayerGameStat.create_dt >
83 (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\
84 order_by(expr.desc(func.sum(PlayerGameStat.score))).\
85 group_by(Player.nick).\
86 group_by(Player.player_id).all()[0:leaderboard_count]
88 top_scorers = [(player_id, html_colors(nick), score) \
89 for (player_id, nick, score) in top_scorers]
91 # top players by playing time
92 top_players = DBSession.query(Player.player_id, Player.nick,
93 func.sum(PlayerGameStat.alivetime)).\
94 filter(Player.player_id == PlayerGameStat.player_id).\
95 filter(Game.game_id == PlayerGameStat.game_id).\
96 filter(Game.map_id == map_id).\
97 filter(Player.player_id > 2).\
98 filter(PlayerGameStat.create_dt >
99 (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\
100 order_by(expr.desc(func.sum(PlayerGameStat.alivetime))).\
101 group_by(Player.nick).\
102 group_by(Player.player_id).all()[0:leaderboard_count]
104 top_players = [(player_id, html_colors(nick), score) \
105 for (player_id, nick, score) in top_players]
107 # top servers using/playing this map
108 top_servers = DBSession.query(Server.server_id, Server.name,
109 func.count(Game.game_id)).\
110 filter(Game.server_id == Server.server_id).\
111 filter(Game.map_id == map_id).\
112 filter(Game.create_dt >
113 (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\
114 order_by(expr.desc(func.count(Game.game_id))).\
115 group_by(Server.name).\
116 group_by(Server.server_id).all()[0:leaderboard_count]
118 # TODO make this a configuration parameter to be set in the settings
120 captimes_raw = DBSession.query(Player.player_id, Player.nick,
121 PlayerCaptime.fastest_cap, PlayerCaptime.game_id).\
122 filter(PlayerCaptime.map_id == map_id).\
123 filter(Player.player_id == PlayerCaptime.player_id).\
124 order_by(PlayerCaptime.fastest_cap).\
128 captimes = [Captime(c.player_id, html_colors(c.nick),
129 c.fastest_cap, c.game_id) for c in captimes_raw]
131 except Exception as e:
134 'recent_games':recent_games,
135 'top_scorers':top_scorers,
136 'top_players':top_players,
137 'top_servers':top_servers,
142 def map_info(request):
144 List the information stored about a given map.
146 mapinfo_data = _map_info_data(request)
148 # FIXME: code clone, should get these from _map_info_data
149 leaderboard_count = 10
150 recent_games_count = 20
152 for i in range(leaderboard_count-len(mapinfo_data['top_scorers'])):
153 mapinfo_data['top_scorers'].append(('-', '-', '-'))
155 for i in range(leaderboard_count-len(mapinfo_data['top_players'])):
156 mapinfo_data['top_players'].append(('-', '-', '-'))
158 for i in range(leaderboard_count-len(mapinfo_data['top_servers'])):
159 mapinfo_data['top_servers'].append(('-', '-', '-'))
164 def map_info_json(request):
166 List the information stored about a given map. JSON.
168 return [{'status':'not implemented'}]
171 def map_captimes_data(request):
172 map_id = int(request.matchdict['id'])
174 current_page = request.params.get('page', 1)
177 mmap = DBSession.query(Map).filter_by(map_id=map_id).one()
179 mct_q = DBSession.query(PlayerCaptime.fastest_cap, PlayerCaptime.create_dt,
180 PlayerCaptime.player_id, PlayerCaptime.game_id,
181 Game.server_id, Server.name.label('server_name'),
182 PlayerGameStat.nick.label('player_nick')).\
183 filter(PlayerCaptime.map_id==map_id).\
184 filter(PlayerCaptime.game_id==Game.game_id).\
185 filter(PlayerCaptime.map_id==Map.map_id).\
186 filter(Game.server_id==Server.server_id).\
187 filter(PlayerCaptime.player_id==PlayerGameStat.player_id).\
188 filter(PlayerCaptime.game_id==PlayerGameStat.game_id).\
189 order_by(expr.asc(PlayerCaptime.fastest_cap))
191 except Exception as e:
192 raise httpexceptions.HTTPNotFound
194 map_captimes = Page(mct_q, current_page, items_per_page=20, url=page_url)
196 map_captimes.items = [MapCapTime(row) for row in map_captimes.items]
201 'captimes':map_captimes,
204 def map_captimes(request):
205 return map_captimes_data(request)
207 def map_captimes_json(request):
208 current_page = request.params.get('page', 1)
209 data = map_captimes_data(request)
212 "map": data["map"].to_dict(),
213 "captimes": [e.to_dict() for e in data["captimes"].items],
214 "page": current_page,