]> git.xonotic.org Git - xonotic/xonstat.git/blob - xonstat/views/player.py
Remove extraneous print in player_info JSON view.
[xonotic/xonstat.git] / xonstat / views / player.py
1 import datetime
2 import json
3 import logging
4 import re
5 import sqlalchemy as sa
6 import sqlalchemy.sql.functions as func
7 import time
8 from pyramid.response import Response
9 from pyramid.url import current_route_url
10 from sqlalchemy import desc, distinct
11 from webhelpers.paginate import Page, PageURL
12 from xonstat.models import *
13 from xonstat.util import page_url, datetime_seconds
14
15 log = logging.getLogger(__name__)
16
17
18 def player_index_data(request):
19     if request.params.has_key('page'):
20         current_page = request.params['page']
21     else:
22         current_page = 1
23
24     try:
25         player_q = DBSession.query(Player).\
26                 filter(Player.player_id > 2).\
27                 filter(Player.active_ind == True).\
28                 filter(sa.not_(Player.nick.like('Anonymous Player%'))).\
29                 order_by(Player.player_id.desc())
30
31         players = Page(player_q, current_page, items_per_page=10, url=page_url)
32
33     except Exception as e:
34         players = None
35         raise e
36
37     return {'players':players
38            }
39
40
41 def player_index(request):
42     """
43     Provides a list of all the current players.
44     """
45     return player_index_data(request)
46
47
48 def player_index_json(request):
49     """
50     Provides a list of all the current players. JSON.
51     """
52     return [{'status':'not implemented'}]
53
54
55 def _get_games_played(player_id):
56     """
57     DEPRECATED: Now included in _get_total_stats()
58     
59     Provides a breakdown by gametype of the games played by player_id.
60
61     Returns a tuple containing (total_games, games_breakdown), where
62     total_games is the absolute number of games played by player_id
63     and games_breakdown is an array containing (game_type_cd, # games)
64     """
65     games_played = DBSession.query(Game.game_type_cd, func.count()).\
66             filter(Game.game_id == PlayerGameStat.game_id).\
67             filter(PlayerGameStat.player_id == player_id).\
68             group_by(Game.game_type_cd).\
69             order_by(func.count().desc()).all()
70
71     total = 0
72     for (game_type_cd, games) in games_played:
73         total += games
74
75     return (total, games_played)
76
77
78 def _get_total_stats(player_id):
79     """
80     Provides aggregated stats by player_id.
81
82     Returns a dict with the keys 'kills', 'deaths', 'alivetime'.
83
84     games = how many games a player has played
85     games_breakdown = how many games of given type a player has played (dictionary)
86     games_alivetime = how many time a player has spent in a give game type (dictionary)
87     kills = how many kills a player has over all games
88     deaths = how many deaths a player has over all games
89     suicides = how many suicides a player has over all games
90     alivetime = how long a player has played over all games
91     alivetime_week = how long a player has played over all games in the last week
92     alivetime_month = how long a player has played over all games in the last month
93     wins = how many games a player has won
94
95     If any of the above are None, they are set to 0.
96     """
97     # 7 and 30 day windows
98     one_week_ago  = datetime.datetime.utcnow() - datetime.timedelta(days=7)
99     one_month_ago = datetime.datetime.utcnow() - datetime.timedelta(days=30)
100
101     total_stats = {}
102
103     games_played = DBSession.query(
104             Game.game_type_cd, func.count(), func.sum(PlayerGameStat.alivetime)).\
105             filter(Game.game_id == PlayerGameStat.game_id).\
106             filter(PlayerGameStat.player_id == player_id).\
107             group_by(Game.game_type_cd).\
108             order_by(func.count().desc()).\
109             all()
110
111     total_stats['games'] = 0
112     total_stats['games_breakdown'] = {}  # this is a dictionary inside a dictionary .. dictception?
113     total_stats['games_alivetime'] = {}
114     for (game_type_cd, games, alivetime) in games_played:
115         total_stats['games'] += games
116         total_stats['games_breakdown'][game_type_cd] = games
117         total_stats['games_alivetime'][game_type_cd] = alivetime
118
119      # more fields can be added here, e.g. 'collects' for kh games
120     (total_stats['kills'], total_stats['deaths'], total_stats['suicides'],
121      total_stats['alivetime'],) = DBSession.query(
122             func.sum(PlayerGameStat.kills),
123             func.sum(PlayerGameStat.deaths),
124             func.sum(PlayerGameStat.suicides),
125             func.sum(PlayerGameStat.alivetime)).\
126             filter(PlayerGameStat.player_id == player_id).\
127             one()
128
129     (total_stats['alivetime_week'],) = DBSession.query(
130             func.sum(PlayerGameStat.alivetime)).\
131             filter(PlayerGameStat.player_id == player_id).\
132             filter(PlayerGameStat.create_dt > one_week_ago).\
133             one()
134
135     (total_stats['alivetime_month'],) = DBSession.query(
136             func.sum(PlayerGameStat.alivetime)).\
137             filter(PlayerGameStat.player_id == player_id).\
138             filter(PlayerGameStat.create_dt > one_month_ago).\
139             one()
140
141     (total_stats['wins'],) = DBSession.\
142             query("total_wins").\
143             from_statement(
144                 "select count(*) total_wins "
145                 "from games g, player_game_stats pgs "
146                 "where g.game_id = pgs.game_id "
147                 "and player_id=:player_id "
148                 "and (g.winner = pgs.team or pgs.rank = 1)"
149             ).params(player_id=player_id).one()
150
151 #    (total_stats['wins'],) = DBSession.query(
152 #            func.count("*")).\
153 #            filter(Game.game_id == PlayerGameStat.game_id).\
154 #            filter(PlayerGameStat.player_id == player_id).\
155 #            filter(Game.winner == PlayerGameStat.team or PlayerGameStat.rank == 1).\
156 #            one()
157
158     (total_stats['duel_wins'],) = DBSession.query(
159             func.count("*")).\
160             filter(Game.game_id == PlayerGameStat.game_id).\
161             filter(Game.game_type_cd == "duel").\
162             filter(PlayerGameStat.player_id == player_id).\
163             filter(PlayerGameStat.rank == 1).\
164             one()
165
166     (total_stats['duel_kills'], total_stats['duel_deaths'], total_stats['duel_suicides'],) = DBSession.query(
167             func.sum(PlayerGameStat.kills),
168             func.sum(PlayerGameStat.deaths),
169             func.sum(PlayerGameStat.suicides)).\
170             filter(Game.game_id == PlayerGameStat.game_id).\
171             filter(Game.game_type_cd == "duel").\
172             filter(PlayerGameStat.player_id == player_id).\
173             one()
174
175     (total_stats['dm_wins'],) = DBSession.query(
176             func.count("*")).\
177             filter(Game.game_id == PlayerGameStat.game_id).\
178             filter(Game.game_type_cd == "dm").\
179             filter(PlayerGameStat.player_id == player_id).\
180             filter(PlayerGameStat.rank == 1).\
181             one()
182
183     (total_stats['dm_kills'], total_stats['dm_deaths'], total_stats['dm_suicides'],) = DBSession.query(
184             func.sum(PlayerGameStat.kills),
185             func.sum(PlayerGameStat.deaths),
186             func.sum(PlayerGameStat.suicides)).\
187             filter(Game.game_id == PlayerGameStat.game_id).\
188             filter(Game.game_type_cd == "dm").\
189             filter(PlayerGameStat.player_id == player_id).\
190             one()
191
192     (total_stats['tdm_kills'], total_stats['tdm_deaths'], total_stats['tdm_suicides'],) = DBSession.query(
193             func.sum(PlayerGameStat.kills),
194             func.sum(PlayerGameStat.deaths),
195             func.sum(PlayerGameStat.suicides)).\
196             filter(Game.game_id == PlayerGameStat.game_id).\
197             filter(Game.game_type_cd == "tdm").\
198             filter(PlayerGameStat.player_id == player_id).\
199             one()
200
201     (total_stats['tdm_wins'],) = DBSession.query(
202             func.count("*")).\
203             filter(Game.game_id == PlayerGameStat.game_id).\
204             filter(Game.game_type_cd == "tdm").\
205             filter(PlayerGameStat.player_id == player_id).\
206             filter(PlayerGameStat.rank == 1).\
207             one()
208
209     (total_stats['ctf_wins'],) = DBSession.query(
210             func.count("*")).\
211             filter(Game.game_id == PlayerGameStat.game_id).\
212             filter(Game.game_type_cd == "ctf").\
213             filter(PlayerGameStat.player_id == player_id).\
214             filter(PlayerGameStat.rank == 1).\
215             one()
216
217     (total_stats['ctf_caps'], total_stats['ctf_pickups'], total_stats['ctf_drops'],
218      total_stats['ctf_returns'], total_stats['ctf_fckills'],) = DBSession.query(
219             func.sum(PlayerGameStat.captures),
220             func.sum(PlayerGameStat.pickups),
221             func.sum(PlayerGameStat.drops),
222             func.sum(PlayerGameStat.returns),
223             func.sum(PlayerGameStat.carrier_frags)).\
224             filter(Game.game_id == PlayerGameStat.game_id).\
225             filter(Game.game_type_cd == "ctf").\
226             filter(PlayerGameStat.player_id == player_id).\
227             one()
228
229     for (key,value) in total_stats.items():
230         if value == None:
231             total_stats[key] = 0
232
233     return total_stats
234
235
236 def _get_fav_map(player_id):
237     """
238     Get the player's favorite map. The favorite map is defined
239     as the map that he or she has played the most in the past 
240     90 days.
241
242     Returns a dictionary with keys for the map's name and id.
243     """
244     # 90 day window
245     back_then = datetime.datetime.utcnow() - datetime.timedelta(days=90)
246
247     raw_fav_map = DBSession.query(Map.name, Map.map_id).\
248             filter(Game.game_id == PlayerGameStat.game_id).\
249             filter(Game.map_id == Map.map_id).\
250             filter(PlayerGameStat.player_id == player_id).\
251             filter(PlayerGameStat.create_dt > back_then).\
252             group_by(Map.name, Map.map_id).\
253             order_by(func.count().desc()).\
254             limit(5).all()
255
256     fav_map = []
257     for map_e in raw_fav_map:
258         entry = {}
259         entry['name'] = map_e[0]
260         entry['id']   = map_e[1]
261         fav_map.append(entry)
262
263     return fav_map
264
265
266 def _get_fav_weapon(player_id):
267     """
268     Get the player's favorite weapon. The favorite weapon is defined
269     as the weapon that he or she has employed the most in the past 
270     90 days.
271
272     Returns a sequence of dictionaries with keys for the weapon's name and id.
273     The sequence holds the most-used weapons in decreasing order.
274     """
275     # 90 day window
276     back_then = datetime.datetime.utcnow() - datetime.timedelta(days=90)
277
278     raw_fav_weapon = DBSession.query(Weapon.descr, Weapon.weapon_cd).\
279             filter(Game.game_id == PlayerWeaponStat.game_id).\
280             filter(PlayerWeaponStat.player_id == player_id).\
281             filter(PlayerWeaponStat.weapon_cd == Weapon.weapon_cd).\
282             filter(PlayerWeaponStat.create_dt > back_then).\
283             group_by(Weapon.descr, Weapon.weapon_cd).\
284             order_by(func.count().desc()).\
285             limit(5).all()
286
287     fav_weapon = []
288     for wpn_e in raw_fav_weapon:
289         entry = {}
290         entry['name'] = wpn_e[0]
291         entry['id']   = wpn_e[1]
292         fav_weapon.append(entry)
293
294     return fav_weapon
295
296
297 def _get_fav_server(player_id):
298     """
299     Get the player's favorite server. The favorite server is defined
300     as the server that he or she has played on the most in the past 
301     90 days.
302
303     Returns a sequence of dictionaries with keys for the server's name and id.
304     The sequence holds the most-used servers in decreasing order.
305     """
306     # 90 day window
307     back_then = datetime.datetime.utcnow() - datetime.timedelta(days=90)
308
309     raw_fav_server = DBSession.query(Server.name, Server.server_id).\
310             filter(Game.game_id == PlayerGameStat.game_id).\
311             filter(Game.server_id == Server.server_id).\
312             filter(PlayerGameStat.player_id == player_id).\
313             filter(PlayerGameStat.create_dt > back_then).\
314             group_by(Server.name, Server.server_id).\
315             order_by(func.count().desc()).\
316             limit(5).all()
317
318     fav_server = []
319     for srv_e in raw_fav_server:
320         entry = {}
321         entry['name'] = srv_e[0]
322         entry['id']   = srv_e[1]
323         fav_server.append(entry)
324
325     return fav_server
326
327
328 def _get_rank(player_id):
329     """
330     Get the player's rank as well as the total number of ranks.
331     """
332     rank = DBSession.query("game_type_cd", "rank", "max_rank").\
333             from_statement(
334                 "select pr.game_type_cd, pr.rank, overall.max_rank "
335                 "from player_ranks pr,  "
336                    "(select game_type_cd, max(rank) max_rank "
337                     "from player_ranks  "
338                     "group by game_type_cd) overall "
339                 "where pr.game_type_cd = overall.game_type_cd  "
340                 "and player_id = :player_id "
341                 "order by rank").\
342             params(player_id=player_id).all()
343
344     return rank;
345
346
347 def get_accuracy_stats(player_id, weapon_cd, games):
348     """
349     Provides accuracy for weapon_cd by player_id for the past N games.
350     """
351     # Reaching back 90 days should give us an accurate enough average
352     # We then multiply this out for the number of data points (games) to
353     # create parameters for a flot graph
354     try:
355         raw_avg = DBSession.query(func.sum(PlayerWeaponStat.hit),
356                 func.sum(PlayerWeaponStat.fired)).\
357                 filter(PlayerWeaponStat.player_id == player_id).\
358                 filter(PlayerWeaponStat.weapon_cd == weapon_cd).\
359                 one()
360
361         avg = round(float(raw_avg[0])/raw_avg[1]*100, 2)
362
363         # Determine the raw accuracy (hit, fired) numbers for $games games
364         # This is then enumerated to create parameters for a flot graph
365         raw_accs = DBSession.query(PlayerWeaponStat.game_id, 
366             PlayerWeaponStat.hit, PlayerWeaponStat.fired).\
367                 filter(PlayerWeaponStat.player_id == player_id).\
368                 filter(PlayerWeaponStat.weapon_cd == weapon_cd).\
369                 order_by(PlayerWeaponStat.game_id.desc()).\
370                 limit(games).\
371                 all()
372
373         # they come out in opposite order, so flip them in the right direction
374         raw_accs.reverse()
375
376         accs = []
377         for i in range(len(raw_accs)):
378             accs.append((raw_accs[i][0], round(float(raw_accs[i][1])/raw_accs[i][2]*100, 2)))
379     except:
380         accs = []
381         avg = 0.0
382
383     return (avg, accs)
384
385
386 def get_damage_stats(player_id, weapon_cd, games):
387     """
388     Provides damage info for weapon_cd by player_id for the past N games.
389     """
390     try:
391         raw_avg = DBSession.query(func.sum(PlayerWeaponStat.actual),
392                 func.sum(PlayerWeaponStat.hit)).\
393                 filter(PlayerWeaponStat.player_id == player_id).\
394                 filter(PlayerWeaponStat.weapon_cd == weapon_cd).\
395                 one()
396
397         avg = round(float(raw_avg[0])/raw_avg[1], 2)
398
399         # Determine the damage efficiency (hit, fired) numbers for $games games
400         # This is then enumerated to create parameters for a flot graph
401         raw_dmgs = DBSession.query(PlayerWeaponStat.game_id, 
402             PlayerWeaponStat.actual, PlayerWeaponStat.hit).\
403                 filter(PlayerWeaponStat.player_id == player_id).\
404                 filter(PlayerWeaponStat.weapon_cd == weapon_cd).\
405                 order_by(PlayerWeaponStat.game_id.desc()).\
406                 limit(games).\
407                 all()
408
409         # they come out in opposite order, so flip them in the right direction
410         raw_dmgs.reverse()
411
412         dmgs = []
413         for i in range(len(raw_dmgs)):
414             # try to derive, unless we've hit nothing then set to 0!
415             try:
416                 dmg = round(float(raw_dmgs[i][1])/raw_dmgs[i][2], 2)
417             except:
418                 dmg = 0.0
419
420             dmgs.append((raw_dmgs[i][0], dmg))
421     except Exception as e:
422         dmgs = []
423         avg = 0.0
424
425     return (avg, dmgs)
426
427
428 def player_info_data(request):
429     player_id = int(request.matchdict['id'])
430     if player_id <= 2:
431         player_id = -1;
432
433     try:
434         player = DBSession.query(Player).filter_by(player_id=player_id).\
435                 filter(Player.active_ind == True).one()
436
437         # games played, alivetime, wins, kills, deaths
438         total_stats = _get_total_stats(player.player_id)
439
440         # games breakdown - N games played (X ctf, Y dm) etc
441         # DEPRECATED: included in total_stats, see above
442         # (total_games, games_breakdown) = _get_games_played(player.player_id)
443
444         # favorite map from the past 90 days
445         try:
446             fav_map = _get_fav_map(player.player_id)
447         except:
448             fav_map = None
449
450         # favorite weapon from the past 90 days
451         try:
452             fav_weapon = _get_fav_weapon(player.player_id)
453         except:
454             fav_weapon = None
455
456         # favorite server from the past 90 days
457         try:
458             fav_server = _get_fav_server(player.player_id)
459         except:
460             fav_server = None
461
462         # friendly display of elo information and preliminary status
463         elos = DBSession.query(PlayerElo).filter_by(player_id=player_id).\
464                 filter(PlayerElo.game_type_cd.in_(['ctf','duel','dm'])).\
465                 order_by(PlayerElo.elo.desc()).all()
466
467         elos_display = []
468         elos_dict    = {}
469         for elo in elos:
470             if elo.games > 32:
471                 str = "{0} ({1})"
472             else:
473                 str = "{0}* ({1})"
474
475             elos_display.append(str.format(round(elo.elo, 3),
476                 elo.game_type_cd))
477             elos_dict[elo.game_type_cd] = round(elo.elo, 3)
478         elos_display = ', '.join(elos_display)
479
480         # get current rank information
481         ranks = _get_rank(player_id)
482         
483         ranks_display = []
484         ranks_dict    = {}
485         for gtc,rank,max_rank in ranks:
486             ranks_display.append("{1} of {2} ({0})".format(gtc, rank, max_rank))
487             ranks_dict[gtc] = (rank, max_rank)
488         ranks_display = ', '.join(ranks_display)
489
490
491         # which weapons have been used in the past 90 days
492         # and also, used in 5 games or more?
493         back_then = datetime.datetime.utcnow() - datetime.timedelta(days=90)
494         recent_weapons = []
495         for weapon in DBSession.query(PlayerWeaponStat.weapon_cd, func.count()).\
496                 filter(PlayerWeaponStat.player_id == player_id).\
497                 filter(PlayerWeaponStat.create_dt > back_then).\
498                 group_by(PlayerWeaponStat.weapon_cd).\
499                 having(func.count() > 4).\
500                 all():
501                     recent_weapons.append(weapon[0])
502
503         # recent games table, all data
504         recent_games = DBSession.query(PlayerGameStat, Game, Server, Map).\
505                 filter(PlayerGameStat.player_id == player_id).\
506                 filter(PlayerGameStat.game_id == Game.game_id).\
507                 filter(Game.server_id == Server.server_id).\
508                 filter(Game.map_id == Map.map_id).\
509                 order_by(Game.game_id.desc())[0:10]
510
511     except Exception as e:
512         player = None
513         elos = None
514         elos_display = None
515         total_stats = None
516         recent_games = None
517         # DEPRECATED: included in total_stats, see above
518         #total_games = None
519         #games_breakdown = None
520         recent_weapons = []
521         fav_map = None
522         fav_weapon = None
523         fav_server = None
524         ranks = None
525         ranks_display = None;
526
527     return {'player':player,
528             'elos':elos_dict,
529             'elos_display':elos_display,
530             'recent_games':recent_games,
531             'total_stats':total_stats,
532             # DEPRECATED: included in total_stats, see above
533             #'total_games':total_games,
534             #'games_breakdown':games_breakdown,
535             'recent_weapons':recent_weapons,
536             'fav_map':fav_map,
537             'fav_weapon':fav_weapon,
538             'fav_server':fav_server,
539             'ranks':ranks_dict,
540             'ranks_display':ranks_display,
541             }
542
543
544 def player_info(request):
545     """
546     Provides detailed information on a specific player
547     """
548     return player_info_data(request)
549
550
551 def player_info_json(request):
552     """
553     Provides detailed information on a specific player. JSON.
554     """
555     player_info = player_info_data(request)
556     json_result = {
557         'player': {
558             'id':               player_info['player'].player_id,
559             'nick':             player_info['player'].nick.encode('utf-8'),
560             'stripped_nick':    player_info['player'].nick_strip_colors(),
561             'joined':           player_info['player'].create_dt.isoformat(),
562             },
563         'elos':         player_info['elos'],
564         'ranks':        player_info['ranks'],
565         'total_stats':  {
566                 'games':            player_info['total_stats']['games'],
567                 'games_breakdown':  player_info['total_stats']['games_breakdown'],
568                 'alivetime':        datetime_seconds(player_info['total_stats']['alivetime']),
569                 'kills':            player_info['total_stats']['kills'],
570                 'deaths':           player_info['total_stats']['deaths'],
571                 'suicides':         player_info['total_stats']['suicides'],
572                 'wins':             player_info['total_stats']['wins'],
573                 # FIXME - current "wins" query is flawed!
574                 #'losses':           player_info['total_stats']['loses'],
575             },
576         'recent_games': [
577                 {
578                     'game_id':      game.game_id,
579                     'game_type':    game.game_type_cd,
580                     'server':       server.name,
581                     'map':          map.name,
582                     'team':         gamestat.team,
583                     'rank':         gamestat.rank,
584                     'win':          ((gamestat.team != None and gamestat.team == game.winner)
585                                         or (gamestat.team == None and gamestat.rank == 1)),
586                     'time':         game.create_dt.isoformat(),
587                 }
588                 for (gamestat, game, server, map) in player_info['recent_games'][:5]
589             ],
590         }
591     return json_result
592
593
594 def player_game_index_data(request):
595     player_id = request.matchdict['player_id']
596
597     if request.params.has_key('page'):
598         current_page = request.params['page']
599     else:
600         current_page = 1
601
602     try:
603         games_q = DBSession.query(Game, Server, Map).\
604             filter(PlayerGameStat.game_id == Game.game_id).\
605             filter(PlayerGameStat.player_id == player_id).\
606             filter(Game.server_id == Server.server_id).\
607             filter(Game.map_id == Map.map_id).\
608             order_by(Game.game_id.desc())
609
610         games = Page(games_q, current_page, items_per_page=10, url=page_url)
611
612         pgstats = {}
613         for (game, server, map) in games:
614             pgstats[game.game_id] = DBSession.query(PlayerGameStat).\
615                     filter(PlayerGameStat.game_id == game.game_id).\
616                     order_by(PlayerGameStat.rank).\
617                     order_by(PlayerGameStat.score).all()
618
619     except Exception as e:
620         player = None
621         games = None
622
623     return {'player_id':player_id,
624             'games':games,
625             'pgstats':pgstats}
626
627
628 def player_game_index(request):
629     """
630     Provides an index of the games in which a particular
631     player was involved. This is ordered by game_id, with
632     the most recent game_ids first. Paginated.
633     """
634     return player_game_index_data(request)
635
636
637 def player_game_index_json(request):
638     """
639     Provides an index of the games in which a particular
640     player was involved. This is ordered by game_id, with
641     the most recent game_ids first. Paginated. JSON.
642     """
643     return [{'status':'not implemented'}]
644
645
646 def player_accuracy_data(request):
647     player_id = request.matchdict['id']
648     allowed_weapons = ['nex', 'rifle', 'shotgun', 'uzi', 'minstanex']
649     weapon_cd = 'nex'
650     games = 20
651
652     if request.params.has_key('weapon'):
653         if request.params['weapon'] in allowed_weapons:
654             weapon_cd = request.params['weapon']
655
656     if request.params.has_key('games'):
657         try:
658             games = request.params['games']
659
660             if games < 0:
661                 games = 20
662             if games > 50:
663                 games = 50
664         except:
665             games = 20
666
667     (avg, accs) = get_accuracy_stats(player_id, weapon_cd, games)
668
669     # if we don't have enough data for the given weapon
670     if len(accs) < games:
671         games = len(accs)
672
673     return {
674             'player_id':player_id, 
675             'player_url':request.route_url('player_info', id=player_id), 
676             'weapon':weapon_cd, 
677             'games':games, 
678             'avg':avg, 
679             'accs':accs
680             }
681
682
683 def player_accuracy(request):
684     """
685     Provides the accuracy for the given weapon. (JSON only)
686     """
687     return player_accuracy_data(request)
688
689
690 def player_accuracy_json(request):
691     """
692     Provides a JSON response representing the accuracy for the given weapon.
693
694     Parameters:
695        weapon = which weapon to display accuracy for. Valid values are 'nex',
696                 'shotgun', 'uzi', and 'minstanex'.
697        games = over how many games to display accuracy. Can be up to 50.
698     """
699     return player_accuracy_data(request)
700
701
702 def player_damage_data(request):
703     player_id = request.matchdict['id']
704     allowed_weapons = ['grenadelauncher', 'electro', 'crylink', 'hagar',
705             'rocketlauncher', 'laser']
706     weapon_cd = 'rocketlauncher'
707     games = 20
708
709     if request.params.has_key('weapon'):
710         if request.params['weapon'] in allowed_weapons:
711             weapon_cd = request.params['weapon']
712
713     if request.params.has_key('games'):
714         try:
715             games = request.params['games']
716
717             if games < 0:
718                 games = 20
719             if games > 50:
720                 games = 50
721         except:
722             games = 20
723
724     (avg, dmgs) = get_damage_stats(player_id, weapon_cd, games)
725
726     # if we don't have enough data for the given weapon
727     if len(dmgs) < games:
728         games = len(dmgs)
729
730     return {
731             'player_id':player_id, 
732             'player_url':request.route_url('player_info', id=player_id), 
733             'weapon':weapon_cd, 
734             'games':games, 
735             'avg':avg, 
736             'dmgs':dmgs
737             }
738
739
740 def player_damage_json(request):
741     """
742     Provides a JSON response representing the damage for the given weapon.
743
744     Parameters:
745        weapon = which weapon to display damage for. Valid values are
746          'grenadelauncher', 'electro', 'crylink', 'hagar', 'rocketlauncher',
747          'laser'.
748        games = over how many games to display damage. Can be up to 50.
749     """
750     return player_damage_data(request)