+
+
+def player_hashkey_info_data(request):
+ # hashkey = request.matchdict['hashkey']
+
+ # the incoming hashkey is double quoted, and WSGI unquotes once...
+ # hashkey = unquote(hashkey)
+
+ # if using request verification to obtain the hashkey
+ (idfp, status) = verify_request(request)
+ log.debug("d0_blind_id verification: idfp={0} status={1}\n".format(idfp, status))
+
+ log.debug("\n----- BEGIN REQUEST BODY -----\n" + request.body +
+ "----- END REQUEST BODY -----\n\n")
+
+ # if config is to *not* verify requests and we get nothing back, this
+ # query will return nothing and we'll 404.
+ try:
+ player = DBSession.query(Player).\
+ filter(Player.player_id == Hashkey.player_id).\
+ filter(Player.active_ind == True).\
+ filter(Hashkey.hashkey == idfp).one()
+
+ games_played = get_games_played(player.player_id)
+ overall_stats = get_overall_stats(player.player_id)
+ fav_maps = get_fav_maps(player.player_id)
+ elos = get_elos(player.player_id)
+ ranks = get_ranks(player.player_id)
+ most_recent_game = get_recent_games(player.player_id, 1)[0]
+
+ except Exception as e:
+ raise pyramid.httpexceptions.HTTPNotFound
+
+ return {'player':player,
+ 'hashkey':idfp,
+ 'games_played':games_played,
+ 'overall_stats':overall_stats,
+ 'fav_maps':fav_maps,
+ 'elos':elos,
+ 'ranks':ranks,
+ 'most_recent_game':most_recent_game,
+ }
+
+
+def player_hashkey_info_json(request):
+ """
+ Provides detailed information on a specific player. JSON.
+ """
+
+ # All player_info fields are converted into JSON-formattable dictionaries
+ player_info = player_hashkey_info_data(request)
+
+ player = player_info['player'].to_dict()
+
+ games_played = {}
+ for game in player_info['games_played']:
+ games_played[game.game_type_cd] = to_json(game)
+
+ overall_stats = {}
+ for gt,stats in player_info['overall_stats'].items():
+ overall_stats[gt] = to_json(stats)
+
+ elos = {}
+ for gt,elo in player_info['elos'].items():
+ elos[gt] = to_json(elo.to_dict())
+
+ ranks = {}
+ for gt,rank in player_info['ranks'].items():
+ ranks[gt] = to_json(rank)
+
+ fav_maps = {}
+ for gt,mapinfo in player_info['fav_maps'].items():
+ fav_maps[gt] = to_json(mapinfo)
+
+ most_recent_game = to_json(player_info['most_recent_game'])
+
+ return [{
+ 'version': 1,
+ 'player': player,
+ 'games_played': games_played,
+ 'overall_stats': overall_stats,
+ 'fav_maps': fav_maps,
+ 'elos': elos,
+ 'ranks': ranks,
+ 'most_recent_game': most_recent_game,
+ }]
+
+
+def player_hashkey_info_text(request):
+ """
+ Provides detailed information on a specific player. Plain text.
+ """
+ # UTC epoch
+ now = timegm(datetime.datetime.utcnow().timetuple())
+
+ # All player_info fields are converted into JSON-formattable dictionaries
+ player_info = player_hashkey_info_data(request)
+
+ # gather all of the data up into aggregate structures
+ player = player_info['player']
+ games_played = player_info['games_played']
+ overall_stats = player_info['overall_stats']
+ elos = player_info['elos']
+ ranks = player_info['ranks']
+ fav_maps = player_info['fav_maps']
+ most_recent_game = player_info['most_recent_game']
+
+ # one-offs for things needing conversion for text/plain
+ player_joined = timegm(player.create_dt.timetuple())
+ player_joined_dt = player.create_dt
+ alivetime = int(datetime_seconds(overall_stats['overall'].total_playing_time))
+
+ # this is a plain text response, if we don't do this here then
+ # Pyramid will assume html
+ request.response.content_type = 'text/plain'
+
+ return {
+ 'version': 1,
+ 'now': now,
+ 'player': player,
+ 'hashkey': player_info['hashkey'],
+ 'player_joined': player_joined,
+ 'player_joined_dt': player_joined_dt,
+ 'games_played': games_played,
+ 'overall_stats': overall_stats,
+ 'alivetime': alivetime,
+ 'fav_maps': fav_maps,
+ 'elos': elos,
+ 'ranks': ranks,
+ 'most_recent_game': most_recent_game,
+ }
+
+
+def player_elo_info_data(request):
+ """
+ Provides elo information on a specific player. Raw data is returned.
+ """
+ (idfp, status) = verify_request(request)
+ log.debug("d0_blind_id verification: idfp={0} status={1}\n".format(idfp, status))
+
+ log.debug("\n----- BEGIN REQUEST BODY -----\n" + request.body +
+ "----- END REQUEST BODY -----\n\n")
+
+ hashkey = request.matchdict['hashkey']
+
+ # the incoming hashkey is double quoted, and WSGI unquotes once...
+ hashkey = unquote(hashkey)
+
+ try:
+ player = DBSession.query(Player).\
+ filter(Player.player_id == Hashkey.player_id).\
+ filter(Player.active_ind == True).\
+ filter(Hashkey.hashkey == hashkey).one()
+
+ elos = get_elos(player.player_id)
+
+ except Exception as e:
+ log.debug(e)
+ raise pyramid.httpexceptions.HTTPNotFound
+
+ return {
+ 'hashkey':hashkey,
+ 'player':player,
+ 'elos':elos,
+ }
+
+
+def player_elo_info_json(request):
+ """
+ Provides elo information on a specific player. JSON.
+ """
+ elo_info = player_elo_info_data(request)
+
+ player = player_info['player'].to_dict()
+
+ elos = {}
+ for gt, elo in elo_info['elos'].items():
+ elos[gt] = to_json(elo.to_dict())
+
+ return [{
+ 'version': 1,
+ 'player': player,
+ 'elos': elos,
+ }]
+
+
+def player_elo_info_text(request):
+ """
+ Provides elo information on a specific player. Plain text.
+ """
+ # UTC epoch
+ now = timegm(datetime.datetime.utcnow().timetuple())
+
+ # All player_info fields are converted into JSON-formattable dictionaries
+ elo_info = player_elo_info_data(request)
+
+ # this is a plain text response, if we don't do this here then
+ # Pyramid will assume html
+ request.response.content_type = 'text/plain'
+
+ return {
+ 'version': 1,
+ 'now': now,
+ 'hashkey': elo_info['hashkey'],
+ 'player': elo_info['player'],
+ 'elos': elo_info['elos'],
+ }
+
+
+def player_captimes_data(request):
+ player_id = int(request.matchdict['player_id'])
+ if player_id <= 2:
+ player_id = -1;
+
+ if request.params.has_key('page'):
+ current_page = request.params['page']
+ else:
+ current_page = 1
+
+ PlayerCaptimes = namedtuple('PlayerCaptimes', ['fastest_cap',
+ 'create_dt', 'create_dt_epoch', 'create_dt_fuzzy',
+ 'player_id', 'game_id', 'map_id', 'map_name', 'server_id', 'server_name'])
+
+ player = DBSession.query(Player).filter_by(player_id=player_id).one()
+
+ #pct_q = DBSession.query('fastest_cap', 'create_dt', 'player_id', 'game_id', 'map_id',
+ # 'map_name', 'server_id', 'server_name').\
+ # from_statement(
+ # "SELECT ct.fastest_cap, "
+ # "ct.create_dt, "
+ # "ct.player_id, "
+ # "ct.game_id, "
+ # "ct.map_id, "
+ # "m.name map_name, "
+ # "g.server_id, "
+ # "s.name server_name "
+ # "FROM player_map_captimes ct, "
+ # "games g, "
+ # "maps m, "
+ # "servers s "
+ # "WHERE ct.player_id = :player_id "
+ # "AND g.game_id = ct.game_id "
+ # "AND g.server_id = s.server_id "
+ # "AND m.map_id = ct.map_id "
+ # #"ORDER BY ct.fastest_cap "
+ # "ORDER BY ct.create_dt desc"
+ # ).params(player_id=player_id)
+
+ try:
+ pct_q = DBSession.query(PlayerCaptime.fastest_cap, PlayerCaptime.create_dt,
+ PlayerCaptime.player_id, PlayerCaptime.game_id, PlayerCaptime.map_id,
+ Map.name.label('map_name'), Game.server_id, Server.name.label('server_name')).\
+ filter(PlayerCaptime.player_id==player_id).\
+ filter(PlayerCaptime.game_id==Game.game_id).\
+ filter(PlayerCaptime.map_id==Map.map_id).\
+ filter(Game.server_id==Server.server_id).\
+ order_by(expr.desc(PlayerCaptime.create_dt))
+
+ player_captimes = Page(pct_q, current_page, items_per_page=20, url=page_url)
+
+ # replace the items in the canned pagination class with more rich ones
+ player_captimes.items = [PlayerCaptimes(
+ fastest_cap=row.fastest_cap,
+ create_dt=row.create_dt,
+ create_dt_epoch=timegm(row.create_dt.timetuple()),
+ create_dt_fuzzy=pretty_date(row.create_dt),
+ player_id=row.player_id,
+ game_id=row.game_id,
+ map_id=row.map_id,
+ map_name=row.map_name,
+ server_id=row.server_id,
+ server_name=row.server_name
+ ) for row in player_captimes.items]
+
+ except Exception as e:
+ player = None
+ player_captimes = None
+
+ return {
+ 'player_id':player_id,
+ 'player':player,
+ 'captimes':player_captimes,
+ #'player_url':request.route_url('player_info', id=player_id),
+ }
+
+
+def player_captimes(request):
+ return player_captimes_data(request)
+
+
+def player_captimes_json(request):
+ return player_captimes_data(request)
+
+
+def player_weaponstats_data_json(request):
+ player_id = int(request.matchdict["id"])
+ if player_id <= 2:
+ player_id = -1;
+
+ game_type_cd = request.params.get("game_type", None)
+ if game_type_cd == "overall":
+ game_type_cd = None
+
+ limit = 20
+ if request.params.has_key("limit"):
+ limit = int(request.params["limit"])
+
+ if limit < 0:
+ limit = 20
+ if limit > 50:
+ limit = 50
+
+
+ # the game_ids of the most recently played ones
+ # of the given game type is used for a subquery
+ games_list = DBSession.query(Game.game_id).\
+ filter(Game.players.contains([player_id]))
+
+ if game_type_cd is not None:
+ games_list = games_list.filter(Game.game_type_cd == game_type_cd)
+
+ games_list = games_list.order_by(Game.game_id.desc()).limit(limit)
+
+ weapon_stats_raw = DBSession.query(PlayerWeaponStat).\
+ filter(PlayerWeaponStat.player_id == player_id).\
+ filter(PlayerWeaponStat.game_id.in_(games_list)).\
+ all()
+
+ games_to_weapons = {}
+ weapons_used = {}
+ sum_avgs = {}
+ for ws in weapon_stats_raw:
+ if ws.game_id not in games_to_weapons:
+ games_to_weapons[ws.game_id] = [ws.weapon_cd]
+ else:
+ games_to_weapons[ws.game_id].append(ws.weapon_cd)
+
+ weapons_used[ws.weapon_cd] = weapons_used.get(ws.weapon_cd, 0) + 1
+ sum_avgs[ws.weapon_cd] = sum_avgs.get(ws.weapon_cd, 0) + float(ws.hit)/float(ws.fired)
+
+ # Creating zero-valued weapon stat entries for games where a weapon was not
+ # used in that game, but was used in another game for the set. This makes
+ # the charts look smoother
+ for game_id in games_to_weapons.keys():
+ for weapon_cd in set(weapons_used.keys()) - set(games_to_weapons[game_id]):
+ weapon_stats_raw.append(PlayerWeaponStat(player_id=player_id,
+ game_id=game_id, weapon_cd=weapon_cd))
+
+ # averages for the weapons used in the range
+ avgs = {}
+ for w in weapons_used.keys():
+ avgs[w] = round(sum_avgs[w]/float(weapons_used[w])*100, 2)
+
+ weapon_stats_raw = sorted(weapon_stats_raw, key = lambda x: x.game_id)
+ games = sorted(games_to_weapons.keys())
+ weapon_stats = [ws.to_dict() for ws in weapon_stats_raw]
+
+ return {
+ "weapon_stats": weapon_stats,
+ "weapons_used": weapons_used.keys(),
+ "games": games,
+ "averages": avgs,
+ }
+