]> de.git.xonotic.org Git - xonotic/xonstat.git/blob - xonstat/views/player.py
Reduce the operations in hex_repl for a small performance boost.
[xonotic/xonstat.git] / xonstat / views / player.py
1 import datetime\r
2 import logging\r
3 import re\r
4 import sqlalchemy as sa\r
5 import sqlalchemy.sql.functions as func\r
6 import time\r
7 from pyramid.response import Response\r
8 from pyramid.url import current_route_url\r
9 from sqlalchemy import desc\r
10 from webhelpers.paginate import Page, PageURL\r
11 from xonstat.models import *\r
12 from xonstat.util import page_url\r
13 \r
14 log = logging.getLogger(__name__)\r
15 \r
16 \r
17 def player_index(request):\r
18     """\r
19     Provides a list of all the current players. \r
20     """\r
21     if 'page' in request.matchdict:\r
22         current_page = int(request.matchdict['page'])\r
23     else:\r
24         current_page = 1\r
25 \r
26     try:\r
27         player_q = DBSession.query(Player).\\r
28                 filter(Player.player_id > 2).\\r
29                 filter(Player.active_ind == True).\\r
30                 filter(sa.not_(Player.nick.like('Anonymous Player%'))).\\r
31                 order_by(Player.player_id.desc())\r
32 \r
33         players = Page(player_q, current_page, items_per_page=10, url=page_url)\r
34 \r
35         last_linked_page = current_page + 4\r
36         if last_linked_page > players.last_page:\r
37             last_linked_page = players.last_page\r
38 \r
39         pages_to_link = range(current_page+1, last_linked_page+1)\r
40 \r
41     except Exception as e:\r
42         players = None\r
43         raise e\r
44 \r
45     return {'players':players,\r
46             'pages_to_link':pages_to_link,\r
47             }\r
48 \r
49 \r
50 def games_played(player_id):\r
51     """\r
52     Provides a breakdown by gametype of the games played by player_id.\r
53 \r
54     Returns a tuple containing (total_games, games_breakdown), where\r
55     total_games is the absolute number of games played by player_id\r
56     and games_breakdown is an array containing (game_type_cd, # games)\r
57     """\r
58     games_played = DBSession.query(Game.game_type_cd, func.count()).\\r
59             filter(Game.game_id == PlayerGameStat.game_id).\\r
60             filter(PlayerGameStat.player_id == player_id).\\r
61             group_by(Game.game_type_cd).\\r
62             order_by(func.count().desc()).all()\r
63 \r
64     total = 0\r
65     for (game_type_cd, games) in games_played:\r
66         total += games\r
67 \r
68     return (total, games_played)\r
69 \r
70 \r
71 def player_info(request):\r
72     """\r
73     Provides detailed information on a specific player\r
74     """\r
75     player_id = int(request.matchdict['id'])\r
76     if player_id <= 2:\r
77         player_id = -1;\r
78 \r
79     try:\r
80         player = DBSession.query(Player).filter_by(player_id=player_id).\\r
81                 filter(Player.active_ind == True).one()\r
82 \r
83         (total_games, games_breakdown) = games_played(player.player_id)\r
84 \r
85         elos = DBSession.query(PlayerElo).filter_by(player_id=player_id).\\r
86                 filter(PlayerElo.game_type_cd.in_(['ctf','duel','dm'])).\\r
87                 order_by(PlayerElo.elo.desc()).all()\r
88 \r
89         elos_display = []\r
90         for elo in elos:\r
91             if elo.games > 32:\r
92                 str = "{0} ({1})"\r
93             else:\r
94                 str = "{0}* ({1})"\r
95 \r
96             elos_display.append(str.format(round(elo.elo, 3),\r
97                 elo.game_type_cd))\r
98 \r
99         weapon_stats = DBSession.query("descr", "weapon_cd", "actual_total", \r
100                 "max_total", "hit_total", "fired_total", "frags_total").\\r
101                 from_statement(\r
102                     "select cw.descr, cw.weapon_cd, sum(actual) actual_total, "\r
103                     "sum(max) max_total, sum(hit) hit_total, "\r
104                     "sum(fired) fired_total, sum(frags) frags_total "\r
105                     "from player_weapon_stats ws, cd_weapon cw "\r
106                     "where ws.weapon_cd = cw.weapon_cd "\r
107                     "and player_id = :player_id "\r
108                     "group by descr, cw.weapon_cd "\r
109                     "order by descr"\r
110                 ).params(player_id=player_id).all()\r
111 \r
112         recent_games = DBSession.query(PlayerGameStat, Game, Server, Map).\\r
113                 filter(PlayerGameStat.player_id == player_id).\\r
114                 filter(PlayerGameStat.game_id == Game.game_id).\\r
115                 filter(Game.server_id == Server.server_id).\\r
116                 filter(Game.map_id == Map.map_id).\\r
117                 order_by(Game.game_id.desc())[0:10]\r
118 \r
119         game_stats = {}\r
120         (game_stats['avg_rank'], game_stats['total_kills'], \r
121                 game_stats['total_deaths'], game_stats['total_suicides'], \r
122                 game_stats['total_score'], game_stats['total_time'], \r
123                 game_stats['total_held'], game_stats['total_captures'], \r
124                 game_stats['total_pickups'],game_stats['total_drops'], \r
125                 game_stats['total_returns'], game_stats['total_collects'], \r
126                 game_stats['total_destroys'], game_stats['total_dhk'], \r
127                 game_stats['total_pushes'], game_stats['total_pushed'], \r
128                 game_stats['total_carrier_frags'], \r
129                 game_stats['total_alivetime'],\r
130                 game_stats['total_games_played']) = DBSession.\\r
131                         query("avg_rank", "total_kills", "total_deaths", \r
132                 "total_suicides", "total_score", "total_time", "total_held",\r
133                 "total_captures", "total_pickups", "total_drops", \r
134                 "total_returns", "total_collects", "total_destroys", \r
135                 "total_dhk", "total_pushes", "total_pushed", \r
136                 "total_carrier_frags", "total_alivetime", \r
137                 "total_games_played").\\r
138                 from_statement(\r
139                     "select round(avg(rank)) avg_rank, sum(kills) total_kills, "\r
140                     "sum(deaths) total_deaths, sum(suicides) total_suicides, "\r
141                     "sum(score) total_score, sum(time) total_time, "\r
142                     "sum(held) total_held, sum(captures) total_captures, "\r
143                     "sum(pickups) total_pickups, sum(drops) total_drops, "\r
144                     "sum(returns) total_returns, sum(collects) total_collects, "\r
145                     "sum(destroys) total_destroys, sum(destroys_holding_key) total_dhk, "\r
146                     "sum(pushes) total_pushes, sum(pushed) total_pushed, "\r
147                     "sum(carrier_frags) total_carrier_frags, "\r
148                     "sum(alivetime) total_alivetime, count(*) total_games_played "\r
149                     "from player_game_stats "\r
150                     "where player_id=:player_id"\r
151                 ).params(player_id=player_id).one()\r
152 \r
153         for (key,value) in game_stats.items():\r
154             if value == None:\r
155                 game_stats[key] = '-'\r
156 \r
157     except Exception as e:\r
158         player = None\r
159         elos_display = None\r
160         weapon_stats = None\r
161         game_stats = None\r
162         recent_games = None\r
163         total_games = None\r
164         games_breakdown = None\r
165 \r
166     return {'player':player, \r
167             'elos_display':elos_display,\r
168             'recent_games':recent_games,\r
169             'weapon_stats':weapon_stats,\r
170             'game_stats':game_stats, \r
171             'total_games':total_games,\r
172             'games_breakdown':games_breakdown}\r
173 \r
174 \r
175 def player_game_index(request):\r
176     """\r
177     Provides an index of the games in which a particular\r
178     player was involved. This is ordered by game_id, with\r
179     the most recent game_ids first. Paginated.\r
180     """\r
181     player_id = request.matchdict['player_id']\r
182 \r
183     if 'page' in request.matchdict:\r
184         current_page = request.matchdict['page']\r
185     else:\r
186         current_page = 1\r
187 \r
188     try:\r
189         games_q = DBSession.query(Game, Server, Map).\\r
190             filter(PlayerGameStat.game_id == Game.game_id).\\r
191             filter(PlayerGameStat.player_id == player_id).\\r
192             filter(Game.server_id == Server.server_id).\\r
193             filter(Game.map_id == Map.map_id).\\r
194             order_by(Game.game_id.desc())\r
195 \r
196         games = Page(games_q, current_page, url=page_url)\r
197 \r
198         pgstats = {}\r
199         for (game, server, map) in games:\r
200             pgstats[game.game_id] = DBSession.query(PlayerGameStat).\\r
201                     filter(PlayerGameStat.game_id == game.game_id).\\r
202                     order_by(PlayerGameStat.rank).\\r
203                     order_by(PlayerGameStat.score).all()\r
204 \r
205     except Exception as e:\r
206         player = None\r
207         games = None\r
208 \r
209     return {'player_id':player_id,\r
210             'games':games,\r
211             'pgstats':pgstats}\r