From a934534f0688d01fff6ae0009907c4240c9fef48 Mon Sep 17 00:00:00 2001 From: Ant Zucaro Date: Sun, 16 Sep 2012 12:51:25 -0400 Subject: [PATCH] Undo the addition of zykure's games breakdown stuff. While the changes are appreciated, they introduce WAY too many database queries and LOC. They will be rewritten using a more efficient query structure before inclusion. Also I'd prefer to use tabs instead of pills, with the tabs being on the left or right, not along the top/bottom. --- xonstat/templates/player_info.mako | 253 ++++-------------------- xonstat/views/player.py | 298 +++-------------------------- 2 files changed, 57 insertions(+), 494 deletions(-) diff --git a/xonstat/templates/player_info.mako b/xonstat/templates/player_info.mako index c88c96c..3149228 100644 --- a/xonstat/templates/player_info.mako +++ b/xonstat/templates/player_info.mako @@ -8,14 +8,11 @@ ${nav.nav('players')} <%block name="js"> % if player is not None: + - - % endif @@ -193,55 +184,33 @@ Player Information Last Seen: ${recent_games[0][1].fuzzy_date()}
- Playing Time: ${total_stats['alivetime']} - % if total_stats['alivetime_month'] and total_stats['alivetime'] > total_stats['alivetime_month']: - % if total_stats['alivetime_week'] and total_stats['alivetime_month'] > total_stats['alivetime_week']: -
(${total_stats['alivetime_month']} this month; ${total_stats['alivetime_week']} this week) - % else: -
(${total_stats['alivetime_month']} this month) - % endif - % endif -

+ Playing Time: ${total_stats['alivetime']}
- <% games_breakdown_str = ', '.join(["{0} {1}".format(ng, gt) for (gt, ng) in total_stats['games_breakdown'].items()]) %> - Games Played: ${total_stats['games']}
(${games_breakdown_str})

-

- -
-

- % if fav_server is not None: - Favorite Server: ${fav_server[0]['name']}
- % endif + <% games_breakdown_str = ', '.join(["{0} {1}".format(ng, gt) for (gt, ng) in games_breakdown]) %> + Games Played: ${total_games} (${games_breakdown_str})
% if fav_map is not None: - Favorite Map: ${fav_map[0]['name']}
- % endif - - % if fav_weapon is not None: - Favorite Weapon: ${fav_weapon[0]['name']}
- % endif - - % if total_stats['games'] > 0 and total_stats['wins'] is not None: - Win Percentage: ${round(float(total_stats['wins'])/total_stats['games'] * 100, 2)}% (${total_stats['wins']} wins, ${total_stats['games'] - total_stats['wins']} losses)
- % endif - - % if total_stats['kills'] > 0 and total_stats['deaths'] > 0: - Kill Ratio: ${round(float(total_stats['kills'])/total_stats['deaths'], 3)} (${total_stats['kills']} kills, ${total_stats['deaths']} deaths, ${total_stats['suicides']} suicides)
+ Favorite Map: ${fav_map['name']}
% endif

- - -
-
+

+ % if total_games > 0 and total_stats['wins'] is not None: + Win Percentage: ${round(float(total_stats['wins'])/total_games * 100, 2)}% (${total_stats['wins']} wins, ${total_games - total_stats['wins']} losses)
+ % endif + + % if total_stats['kills'] > 0 and total_stats['deaths'] > 0: + Kill Ratio: ${round(float(total_stats['kills'])/total_stats['deaths'], 3)} (${total_stats['kills']} kills, ${total_stats['deaths']} deaths)
+ % endif + % if elos_display is not None and len(elos_display) > 0: Elo: - ${elos_display} - %if '*' in elos_display: - *preliminary Elo - %endif + ${', '.join(elos_display)}
+ %if '*' in ', '.join(elos_display): + *preliminary Elo
+ %endif % endif % if ranks_display != '': @@ -251,6 +220,7 @@ Player Information

+ % if 'nex' in recent_weapons or 'rifle' in recent_weapons or 'minstanex' in recent_weapons or 'uzi' in recent_weapons or 'shotgun' in recent_weapons:
@@ -265,7 +235,7 @@ Player Information

Nex

- +
% endif @@ -275,7 +245,7 @@ Player Information

Rifle

- +
% endif @@ -285,7 +255,7 @@ Player Information

Minstanex

- +
% endif @@ -295,7 +265,7 @@ Player Information

Uzi

- +
% endif @@ -305,7 +275,7 @@ Player Information

Shotgun

- +
% endif @@ -331,7 +301,7 @@ Player Information

Rocket

- +
% endif @@ -341,7 +311,7 @@ Player Information

Mortar

- +
% endif @@ -351,7 +321,7 @@ Player Information

Electro

- +
% endif @@ -361,7 +331,7 @@ Player Information

Crylink

- +
% endif @@ -371,7 +341,7 @@ Player Information

Hagar

- +
% endif @@ -381,7 +351,7 @@ Player Information

Laser

- +
% endif @@ -393,166 +363,9 @@ Player Information
% endif -
-
-

Game Breakdown

- -
- % for gtc in gametypes: - <% gtc_key = gtc.lower() %> - % if gtc_key == "overall": - <% total = total_stats['games'] %> - <% alivetime = total_stats['alivetime'] %> - <% wins = total_stats['wins'] %> - <% losses = total - wins %> - <% kills = total_stats['kills'] %> - <% deaths = total_stats['deaths'] %> - <% suicides = total_stats['suicides'] %> - % elif total_stats['games_breakdown'].has_key(gtc_key): - <% total = total_stats['games_breakdown'][gtc_key] %> - <% alivetime = total_stats['games_alivetime'][gtc_key] %> - <% wins = total_stats[gtc_key+'_wins'] %> - <% losses = total - wins %> - % if gtc_key == "ctf": - <% caps = total_stats[gtc_key+'_caps'] %> - <% pickups = total_stats[gtc_key+'_pickups'] %> - <% returns = total_stats[gtc_key+'_returns'] %> - <% drops = total_stats[gtc_key+'_drops'] %> - <% fckills = total_stats[gtc_key+'_fckills'] %> - % else: - <% kills = total_stats[gtc_key+'_kills'] %> - <% deaths = total_stats[gtc_key+'_deaths'] %> - <% suicides = total_stats[gtc_key+'_suicides'] %> - % endif - % endif - % if gtc_key == 'overall' or total_stats['games_breakdown'].has_key(gtc_key): - % if gtc_key == 'overall': -
- % else: -
- % endif -
${gtc}
- - - - - - - - % if gtc_key == 'overall': - - % else: - - % endif - - - - - % if gtc_key == 'overall': - - % else: - - % endif - - - - - - - % if gtc_key == 'ctf': - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - % else: - - - - - - - - - - - - - - - - - - - - - - - - - - % endif - -
Games Played:${total}${round(float(total)/total_stats['games'] * 100, 2)}% of all games
Playing Time:${alivetime} hours${round(float(alivetime.total_seconds())/total_stats['alivetime'].total_seconds() * 100, 2)}% of total playing time
Win Percentage:${round(float(wins)/total * 100, 2)}%${wins} wins, ${losses} losses
Caps:${round(float(caps)/total, 2)} per game${caps} total
Pickups:${round(float(pickups)/total, 2)} per game${pickups} total
Drops:${round(float(drops)/total, 2)} per game${drops} total
Returns:${round(float(returns)/total, 2)} per game${returns} total
FC Kills:${round(float(fckills)/total, 2)} per game${fckills} total
Cap Ratio:${round(float(caps)/pickups, 3)}
Drop Ratio:${round(float(drops)/pickups, 3)}
Return Ratio:${round(float(returns)/fckills, 3)}
Kills:${round(float(kills)/total, 2)} per game${kills} total
Deaths:${round(float(deaths)/total, 2)} per game${deaths} total
Suicides:${round(float(suicides)/total, 2)} per game${suicides} total
Kill Ratio:${round(float(kills)/deaths, 3)}
Suicide Ratio:${round(float(suicides)/deaths, 3)}
-
- % endif - % endfor -
-
-
- ##### RECENT GAMES (v2) #### % if recent_games: -

Recent Games

diff --git a/xonstat/views/player.py b/xonstat/views/player.py index c590422..b1fbd5d 100644 --- a/xonstat/views/player.py +++ b/xonstat/views/player.py @@ -10,7 +10,7 @@ from pyramid.url import current_route_url from sqlalchemy import desc, distinct from webhelpers.paginate import Page, PageURL from xonstat.models import * -from xonstat.util import page_url, datetime_seconds +from xonstat.util import page_url log = logging.getLogger(__name__) @@ -54,8 +54,6 @@ def player_index_json(request): def _get_games_played(player_id): """ - DEPRECATED: Now included in _get_total_stats() - Provides a breakdown by gametype of the games played by player_id. Returns a tuple containing (total_games, games_breakdown), where @@ -75,68 +73,30 @@ def _get_games_played(player_id): return (total, games_played) +# TODO: should probably factor the above function into this one such that +# total_stats['ctf_games'] is the count of CTF games and so on... def _get_total_stats(player_id): """ Provides aggregated stats by player_id. Returns a dict with the keys 'kills', 'deaths', 'alivetime'. - games = how many games a player has played - games_breakdown = how many games of given type a player has played (dictionary) - games_alivetime = how many time a player has spent in a give game type (dictionary) kills = how many kills a player has over all games deaths = how many deaths a player has over all games - suicides = how many suicides a player has over all games alivetime = how long a player has played over all games - alivetime_week = how long a player has played over all games in the last week - alivetime_month = how long a player has played over all games in the last month - wins = how many games a player has won If any of the above are None, they are set to 0. """ - # 7 and 30 day windows - one_week_ago = datetime.datetime.utcnow() - datetime.timedelta(days=7) - one_month_ago = datetime.datetime.utcnow() - datetime.timedelta(days=30) - total_stats = {} - - games_played = DBSession.query( - Game.game_type_cd, func.count(), func.sum(PlayerGameStat.alivetime)).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(PlayerGameStat.player_id == player_id).\ - group_by(Game.game_type_cd).\ - order_by(func.count().desc()).\ - all() - - total_stats['games'] = 0 - total_stats['games_breakdown'] = {} # this is a dictionary inside a dictionary .. dictception? - total_stats['games_alivetime'] = {} - for (game_type_cd, games, alivetime) in games_played: - total_stats['games'] += games - total_stats['games_breakdown'][game_type_cd] = games - total_stats['games_alivetime'][game_type_cd] = alivetime - - # more fields can be added here, e.g. 'collects' for kh games - (total_stats['kills'], total_stats['deaths'], total_stats['suicides'], - total_stats['alivetime'],) = DBSession.query( - func.sum(PlayerGameStat.kills), - func.sum(PlayerGameStat.deaths), - func.sum(PlayerGameStat.suicides), - func.sum(PlayerGameStat.alivetime)).\ - filter(PlayerGameStat.player_id == player_id).\ - one() - - (total_stats['alivetime_week'],) = DBSession.query( - func.sum(PlayerGameStat.alivetime)).\ - filter(PlayerGameStat.player_id == player_id).\ - filter(PlayerGameStat.create_dt > one_week_ago).\ - one() - - (total_stats['alivetime_month'],) = DBSession.query( - func.sum(PlayerGameStat.alivetime)).\ - filter(PlayerGameStat.player_id == player_id).\ - filter(PlayerGameStat.create_dt > one_month_ago).\ - one() + (total_stats['kills'], total_stats['deaths'], total_stats['alivetime']) = DBSession.\ + query("total_kills", "total_deaths", "total_alivetime").\ + from_statement( + "select sum(kills) total_kills, " + "sum(deaths) total_deaths, " + "sum(alivetime) total_alivetime " + "from player_game_stats " + "where player_id=:player_id" + ).params(player_id=player_id).one() (total_stats['wins'],) = DBSession.\ query("total_wins").\ @@ -148,84 +108,6 @@ def _get_total_stats(player_id): "and (g.winner = pgs.team or pgs.rank = 1)" ).params(player_id=player_id).one() -# (total_stats['wins'],) = DBSession.query( -# func.count("*")).\ -# filter(Game.game_id == PlayerGameStat.game_id).\ -# filter(PlayerGameStat.player_id == player_id).\ -# filter(Game.winner == PlayerGameStat.team or PlayerGameStat.rank == 1).\ -# one() - - (total_stats['duel_wins'],) = DBSession.query( - func.count("*")).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.game_type_cd == "duel").\ - filter(PlayerGameStat.player_id == player_id).\ - filter(PlayerGameStat.rank == 1).\ - one() - - (total_stats['duel_kills'], total_stats['duel_deaths'], total_stats['duel_suicides'],) = DBSession.query( - func.sum(PlayerGameStat.kills), - func.sum(PlayerGameStat.deaths), - func.sum(PlayerGameStat.suicides)).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.game_type_cd == "duel").\ - filter(PlayerGameStat.player_id == player_id).\ - one() - - (total_stats['dm_wins'],) = DBSession.query( - func.count("*")).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.game_type_cd == "dm").\ - filter(PlayerGameStat.player_id == player_id).\ - filter(PlayerGameStat.rank == 1).\ - one() - - (total_stats['dm_kills'], total_stats['dm_deaths'], total_stats['dm_suicides'],) = DBSession.query( - func.sum(PlayerGameStat.kills), - func.sum(PlayerGameStat.deaths), - func.sum(PlayerGameStat.suicides)).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.game_type_cd == "dm").\ - filter(PlayerGameStat.player_id == player_id).\ - one() - - (total_stats['tdm_kills'], total_stats['tdm_deaths'], total_stats['tdm_suicides'],) = DBSession.query( - func.sum(PlayerGameStat.kills), - func.sum(PlayerGameStat.deaths), - func.sum(PlayerGameStat.suicides)).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.game_type_cd == "tdm").\ - filter(PlayerGameStat.player_id == player_id).\ - one() - - (total_stats['tdm_wins'],) = DBSession.query( - func.count("*")).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.game_type_cd == "tdm").\ - filter(PlayerGameStat.player_id == player_id).\ - filter(PlayerGameStat.rank == 1).\ - one() - - (total_stats['ctf_wins'],) = DBSession.query( - func.count("*")).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.game_type_cd == "ctf").\ - filter(PlayerGameStat.player_id == player_id).\ - filter(PlayerGameStat.rank == 1).\ - one() - - (total_stats['ctf_caps'], total_stats['ctf_pickups'], total_stats['ctf_drops'], - total_stats['ctf_returns'], total_stats['ctf_fckills'],) = DBSession.query( - func.sum(PlayerGameStat.captures), - func.sum(PlayerGameStat.pickups), - func.sum(PlayerGameStat.drops), - func.sum(PlayerGameStat.returns), - func.sum(PlayerGameStat.carrier_frags)).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.game_type_cd == "ctf").\ - filter(PlayerGameStat.player_id == player_id).\ - one() - for (key,value) in total_stats.items(): if value == None: total_stats[key] = 0 @@ -251,80 +133,15 @@ def _get_fav_map(player_id): filter(PlayerGameStat.create_dt > back_then).\ group_by(Map.name, Map.map_id).\ order_by(func.count().desc()).\ - limit(5).all() + limit(1).one() - fav_map = [] - for map_e in raw_fav_map: - entry = {} - entry['name'] = map_e[0] - entry['id'] = map_e[1] - fav_map.append(entry) + fav_map = {} + fav_map['name'] = raw_fav_map[0] + fav_map['id'] = raw_fav_map[1] return fav_map -def _get_fav_weapon(player_id): - """ - Get the player's favorite weapon. The favorite weapon is defined - as the weapon that he or she has employed the most in the past - 90 days. - - Returns a sequence of dictionaries with keys for the weapon's name and id. - The sequence holds the most-used weapons in decreasing order. - """ - # 90 day window - back_then = datetime.datetime.utcnow() - datetime.timedelta(days=90) - - raw_fav_weapon = DBSession.query(Weapon.descr, Weapon.weapon_cd).\ - filter(Game.game_id == PlayerWeaponStat.game_id).\ - filter(PlayerWeaponStat.player_id == player_id).\ - filter(PlayerWeaponStat.weapon_cd == Weapon.weapon_cd).\ - filter(PlayerWeaponStat.create_dt > back_then).\ - group_by(Weapon.descr, Weapon.weapon_cd).\ - order_by(func.count().desc()).\ - limit(5).all() - - fav_weapon = [] - for wpn_e in raw_fav_weapon: - entry = {} - entry['name'] = wpn_e[0] - entry['id'] = wpn_e[1] - fav_weapon.append(entry) - - return fav_weapon - - -def _get_fav_server(player_id): - """ - Get the player's favorite server. The favorite server is defined - as the server that he or she has played on the most in the past - 90 days. - - Returns a sequence of dictionaries with keys for the server's name and id. - The sequence holds the most-used servers in decreasing order. - """ - # 90 day window - back_then = datetime.datetime.utcnow() - datetime.timedelta(days=90) - - raw_fav_server = DBSession.query(Server.name, Server.server_id).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.server_id == Server.server_id).\ - filter(PlayerGameStat.player_id == player_id).\ - filter(PlayerGameStat.create_dt > back_then).\ - group_by(Server.name, Server.server_id).\ - order_by(func.count().desc()).\ - limit(5).all() - - fav_server = [] - for srv_e in raw_fav_server: - entry = {} - entry['name'] = srv_e[0] - entry['id'] = srv_e[1] - fav_server.append(entry) - - return fav_server - - def _get_rank(player_id): """ Get the player's rank as well as the total number of ranks. @@ -438,8 +255,7 @@ def player_info_data(request): total_stats = _get_total_stats(player.player_id) # games breakdown - N games played (X ctf, Y dm) etc - # DEPRECATED: included in total_stats, see above - # (total_games, games_breakdown) = _get_games_played(player.player_id) + (total_games, games_breakdown) = _get_games_played(player.player_id) # favorite map from the past 90 days try: @@ -447,25 +263,12 @@ def player_info_data(request): except: fav_map = None - # favorite weapon from the past 90 days - try: - fav_weapon = _get_fav_weapon(player.player_id) - except: - fav_weapon = None - - # favorite server from the past 90 days - try: - fav_server = _get_fav_server(player.player_id) - except: - fav_server = None - # friendly display of elo information and preliminary status elos = DBSession.query(PlayerElo).filter_by(player_id=player_id).\ filter(PlayerElo.game_type_cd.in_(['ctf','duel','dm'])).\ order_by(PlayerElo.elo.desc()).all() elos_display = [] - elos_dict = {} for elo in elos: if elo.games > 32: str = "{0} ({1})" @@ -474,18 +277,11 @@ def player_info_data(request): elos_display.append(str.format(round(elo.elo, 3), elo.game_type_cd)) - elos_dict[elo.game_type_cd] = round(elo.elo, 3) - elos_display = ', '.join(elos_display) # get current rank information ranks = _get_rank(player_id) - - ranks_display = [] - ranks_dict = {} - for gtc,rank,max_rank in ranks: - ranks_display.append("{1} of {2} ({0})".format(gtc, rank, max_rank)) - ranks_dict[gtc] = (rank, max_rank) - ranks_display = ', '.join(ranks_display) + ranks_display = ', '.join(["{1} of {2} ({0})".format(gtc, rank, + max_rank) for gtc, rank, max_rank in ranks]) # which weapons have been used in the past 90 days @@ -510,33 +306,23 @@ def player_info_data(request): except Exception as e: player = None - elos = None elos_display = None total_stats = None recent_games = None - # DEPRECATED: included in total_stats, see above - #total_games = None - #games_breakdown = None + total_games = None + games_breakdown = None recent_weapons = [] fav_map = None - fav_weapon = None - fav_server = None - ranks = None ranks_display = None; return {'player':player, - 'elos':elos_dict, 'elos_display':elos_display, 'recent_games':recent_games, 'total_stats':total_stats, - # DEPRECATED: included in total_stats, see above - #'total_games':total_games, - #'games_breakdown':games_breakdown, + 'total_games':total_games, + 'games_breakdown':games_breakdown, 'recent_weapons':recent_weapons, 'fav_map':fav_map, - 'fav_weapon':fav_weapon, - 'fav_server':fav_server, - 'ranks':ranks_dict, 'ranks_display':ranks_display, } @@ -552,43 +338,7 @@ def player_info_json(request): """ Provides detailed information on a specific player. JSON. """ - player_info = player_info_data(request) - json_result = { - 'player': { - 'id': player_info['player'].player_id, - 'nick': player_info['player'].nick.encode('utf-8'), - 'stripped_nick': player_info['player'].nick_strip_colors(), - 'joined': player_info['player'].create_dt.isoformat(), - }, - 'elos': player_info['elos'], - 'ranks': player_info['ranks'], - 'total_stats': { - 'games': player_info['total_stats']['games'], - 'games_breakdown': player_info['total_stats']['games_breakdown'], - 'alivetime': datetime_seconds(player_info['total_stats']['alivetime']), - 'kills': player_info['total_stats']['kills'], - 'deaths': player_info['total_stats']['deaths'], - 'suicides': player_info['total_stats']['suicides'], - 'wins': player_info['total_stats']['wins'], - # FIXME - current "wins" query is flawed! - #'losses': player_info['total_stats']['loses'], - }, - 'recent_games': [ - { - 'game_id': game.game_id, - 'game_type': game.game_type_cd, - 'server': server.name, - 'map': map.name, - 'team': gamestat.team, - 'rank': gamestat.rank, - 'win': ((gamestat.team != None and gamestat.team == game.winner) - or (gamestat.team == None and gamestat.rank == 1)), - 'time': game.create_dt.isoformat(), - } - for (gamestat, game, server, map) in player_info['recent_games'][:5] - ], - } - return json_result + return [{'status':'not implemented'}] def player_game_index_data(request): -- 2.39.2