X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonstat.git;a=blobdiff_plain;f=xonstat%2Fviews%2Fgame.py;h=58d48f89d4a356dafdc853a390373dc0d13a5286;hp=05ff27760a3cce895aec106f341266d4c5cd8fb9;hb=51c42763989fcd89c3d213b897773005ce02c7b7;hpb=37332daf95dd5972f7535a780303285b6ceea7fc diff --git a/xonstat/views/game.py b/xonstat/views/game.py old mode 100755 new mode 100644 index 05ff277..58d48f8 --- a/xonstat/views/game.py +++ b/xonstat/views/game.py @@ -1,94 +1,342 @@ -import datetime -import logging -import re -import time -from pyramid.response import Response -from sqlalchemy import desc -from webhelpers.paginate import Page, PageURL -from xonstat.models import * -from xonstat.util import page_url - -log = logging.getLogger(__name__) - - -def game_index(request): - """ - Provides a list of current games, with the associated game stats. - These games are ordered by game_id, with the most current ones first. - Paginated. - """ - if 'page' in request.matchdict: - current_page = request.matchdict['page'] - else: - current_page = 1 - - games_q = DBSession.query(Game, Server, Map).\ - filter(Game.server_id == Server.server_id).\ - filter(Game.map_id == Map.map_id).\ - order_by(Game.game_id.desc()) - - games = Page(games_q, current_page, url=page_url) - - pgstats = {} - for (game, server, map) in games: - pgstats[game.game_id] = DBSession.query(PlayerGameStat).\ - filter(PlayerGameStat.game_id == game.game_id).\ - order_by(PlayerGameStat.rank).\ - order_by(PlayerGameStat.score).all() - - return {'games':games, - 'pgstats':pgstats} - - -def game_info(request): - """ - List the game stats (scoreboard) for a particular game. Paginated. - """ - game_id = request.matchdict['id'] - try: - notfound = False - - (game, server, map) = DBSession.query(Game, Server, Map).\ - filter(Game.game_id == game_id).\ - filter(Game.server_id == Server.server_id).\ - filter(Game.map_id == Map.map_id).one() - - pgstats = DBSession.query(PlayerGameStat).\ - filter(PlayerGameStat.game_id == game_id).\ - order_by(PlayerGameStat.rank).\ - order_by(PlayerGameStat.score).\ - all() - - pwstats = {} - for (pwstat, pgstat, weapon) in DBSession.query(PlayerWeaponStat, PlayerGameStat, Weapon).\ - filter(PlayerWeaponStat.game_id == game_id).\ - filter(PlayerWeaponStat.weapon_cd == Weapon.weapon_cd).\ - filter(PlayerWeaponStat.player_game_stat_id == \ - PlayerGameStat.player_game_stat_id).\ - order_by(PlayerGameStat.rank).\ - order_by(PlayerGameStat.score).\ - all(): - if pgstat.player_game_stat_id not in pwstats: - pwstats[pgstat.player_game_stat_id] = [] - - # NOTE adding pgstat to position 6 in order to display nick. - # You have to use a slice [0:5] to pass to the accuracy - # template - pwstats[pgstat.player_game_stat_id].append((weapon.descr, - weapon.weapon_cd, pwstat.actual, pwstat.max, - pwstat.hit, pwstat.fired, pgstat)) - - except Exception as inst: - game = None - server = None - map = None - pgstats = None - pwstats = None - raise inst - - return {'game':game, - 'server':server, - 'map':map, - 'pgstats':pgstats, - 'pwstats':pwstats, - } +import datetime +import logging +import re +import time +from collections import OrderedDict +from pyramid.response import Response +from sqlalchemy import desc, func, over +from collections import namedtuple +from webhelpers.paginate import Page, PageURL +from xonstat.models import * +from xonstat.util import page_url +from xonstat.views.helpers import RecentGame, recent_games_q + +import random + +log = logging.getLogger(__name__) + + +# DEPRECATED +def _game_index_data(request): + game_type_cd = None + game_type_descr = None + + if request.params.has_key('game_type_cd'): + game_type_cd = request.params['game_type_cd'] + try: + game_type_descr = DBSession.query(GameType.descr).\ + filter(GameType.game_type_cd == game_type_cd).\ + one()[0] + except Exception as e: + game_type_cd = None + + if request.params.has_key('page'): + current_page = request.params['page'] + else: + current_page = 1 + + try: + rgs_q = recent_games_q(game_type_cd=game_type_cd) + + games = Page(rgs_q, current_page, items_per_page=10, url=page_url) + + # replace the items in the canned pagination class with more rich ones + games.items = [RecentGame(row) for row in games.items] + + pgstats = {} + for game in games.items: + pgstats[game.game_id] = DBSession.query(PlayerGameStat).\ + filter(PlayerGameStat.game_id == game.game_id).\ + order_by(PlayerGameStat.scoreboardpos).\ + order_by(PlayerGameStat.score).all() + + except Exception as e: + games = None + pgstats = None + game_type_cd = None + game_type_descr = None + + return {'games':games, + 'pgstats':pgstats, + 'game_type_cd':game_type_cd, + 'game_type_descr':game_type_descr, + } + + +def game_index(request): + """ + Provides a list of current games, with the associated game stats. + These games are ordered by game_id, with the most current ones first. + Paginated. + """ + return _game_index_data(request) + + +def game_index_json(request): + """ + Provides a list of current games, with the associated game stats. + These games are ordered by game_id, with the most current ones first. + Paginated. JSON. + """ + return [{'status':'not implemented'}] + + +def _game_info_data(request): + game_id = request.matchdict['id'] + + if request.params.has_key('show_elo'): + show_elo = True + else: + show_elo = False + + show_latency = False + + try: + notfound = False + + (game, server, map, gametype) = DBSession.query(Game, Server, Map, GameType).\ + filter(Game.game_id == game_id).\ + filter(Game.server_id == Server.server_id).\ + filter(Game.map_id == Map.map_id).\ + filter(Game.game_type_cd == GameType.game_type_cd).one() + + pgstats = DBSession.query(PlayerGameStat).\ + filter(PlayerGameStat.game_id == game_id).\ + order_by(PlayerGameStat.scoreboardpos).\ + order_by(PlayerGameStat.score).\ + all() + + # if at least one player has a valid latency, we'll show the column + for pgstat in pgstats: + if pgstat.avg_latency is not None: + show_latency = True + + q = DBSession.query(TeamGameStat).\ + filter(TeamGameStat.game_id == game_id) + if game.game_type_cd == 'ctf': + q = q.order_by(TeamGameStat.caps.desc()) + elif game.game_type_cd == 'ca': + q = q.order_by(TeamGameStat.rounds.desc()) + # dom -> ticks, rc -> laps, nb -> goals, as -> objectives + + q = q.order_by(TeamGameStat.score.desc()) + + tgstats = q.all() + + stats_by_team = OrderedDict() + for pgstat in pgstats: + if pgstat.team not in stats_by_team.keys(): + stats_by_team[pgstat.team] = [] + stats_by_team[pgstat.team].append(pgstat) + + captimes = [] + if game.game_type_cd == 'ctf': + for pgstat in pgstats: + if pgstat.fastest is not None: + captimes.append(pgstat) + captimes = sorted(captimes, key=lambda x:x.fastest) + + teamscores = {} + for pgstat in pgstats: + if pgstat.team in [5,14,13,10]: + team = pgstat.team_html_color() + if pgstat.teamscore is not None: + if not teamscores.has_key(team): + teamscores[team] = pgstat.teamscore + else: + if teamscores[team] != pgstat.teamscore: # this should not happen! + teamscores[team] = None + if len(teamscores) == 0: + teamscores = None + + ### RANDOM SCORES FOR TESTING + teams = ["red","blue","yellow","pink"] + random.shuffle(teams) + teamscores = {} + for k in range(random.randint(2,4)): + team = teams[k-1] + teamscores[team] = random.randint(-5,150) + ### END + + #TeamInfo = namedtuple('TeamInfo', ['team','scoreboardpos','playercount','teamscore']) + # + #teams = {} + #last_pgs = pgstats[0] + #for pgstat in pgstats: + # if pgstat.team != last_pgs.team: + # teams[last_pgs.scoreboardpos] = TeamInfo( + # team=last_pgs.team, + # scoreboardpos=last_pgs.scoreboardpos, + # playercount=pgstat.scoreboardpos-last_pgs.scoreboardpos, + # teamscore=last_pgs.teamscore) + # last_pgs = pgstat + #teams[last_pgs.scoreboardpos] = TeamInfo( + # team=last_pgs.team, + # scoreboardpos=last_pgs.scoreboardpos, + # playercount=pgstat.scoreboardpos-last_pgs.scoreboardpos, + # teamscore=last_pgs.teamscore) + #print teams + + pwstats = {} + for (pwstat, pgstat, weapon) in DBSession.query(PlayerWeaponStat, PlayerGameStat, Weapon).\ + filter(PlayerWeaponStat.game_id == game_id).\ + filter(PlayerWeaponStat.weapon_cd == Weapon.weapon_cd).\ + filter(PlayerWeaponStat.player_game_stat_id == \ + PlayerGameStat.player_game_stat_id).\ + order_by(PlayerGameStat.scoreboardpos).\ + order_by(PlayerGameStat.score).\ + order_by(Weapon.descr).\ + all(): + if pgstat.player_game_stat_id not in pwstats: + pwstats[pgstat.player_game_stat_id] = [] + + # NOTE adding pgstat to position 6 in order to display nick. + # You have to use a slice [0:5] to pass to the accuracy + # template + pwstats[pgstat.player_game_stat_id].append((weapon.descr, + weapon.weapon_cd, pwstat.actual, pwstat.max, + pwstat.hit, pwstat.fired, pgstat)) + + except Exception as inst: + game = None + server = None + map = None + gametype = None + pgstats = None + tgstats = None + pwstats = None + captimes = None + teams = None + show_elo = False + show_latency = False + stats_by_team = None + raise inst + + return {'game':game, + 'server':server, + 'map':map, + 'gametype':gametype, + 'pgstats':pgstats, + 'tgstats':tgstats, + 'pwstats':pwstats, + 'captimes':captimes, + 'teams':teams, + 'teamscores':teamscores, + 'show_elo':show_elo, + 'show_latency':show_latency, + 'stats_by_team':stats_by_team, + } + + +def game_info(request): + """ + List the game stats (scoreboard) for a particular game. Paginated. + """ + return _game_info_data(request) + + +def game_info_json(request): + """ + List the game stats (scoreboard) for a particular game. Paginated. JSON. + """ + return [{'status':'not implemented'}] + + +def _rank_index_data(request): + if request.params.has_key('page'): + current_page = request.params['page'] + else: + current_page = 1 + + game_type_cd = request.matchdict['game_type_cd'] + + ranks_q = DBSession.query(PlayerRank).\ + filter(PlayerRank.game_type_cd==game_type_cd).\ + order_by(PlayerRank.rank) + + ranks = Page(ranks_q, current_page, url=page_url) + + if len(ranks) == 0: + ranks = None + + return { + 'ranks':ranks, + 'game_type_cd':game_type_cd, + } + + +def rank_index(request): + """ + Provide a list of gametype ranks, paginated. + """ + return _rank_index_data(request) + + +def rank_index_json(request): + """ + Provide a list of gametype ranks, paginated. JSON. + """ + return [{'status':'not implemented'}] + + +def game_finder_data(request): + if request.params.has_key('page'): + current_page = request.params['page'] + else: + current_page = 1 + + query = {} + + server_id, map_id, player_id = None, None, None + range_start, range_end, game_type_cd = None, None, None + game_type_descr = None + + # these become WHERE clauses when present + if request.params.has_key('server_id'): + server_id = request.params['server_id'] + query['server_id'] = server_id + + if request.params.has_key('map_id'): + map_id = request.params['map_id'] + query['map_id'] = map_id + + if request.params.has_key('player_id'): + player_id = request.params['player_id'] + query['player_id'] = player_id + + if request.params.has_key('range_start'): + range_start = request.params['range_start'] + query['range_start'] = range_start + + if request.params.has_key('range_end'): + range_end = request.params['range_end'] + query['range_end'] = range_end + + if request.params.has_key('type'): + game_type_cd = request.params['type'] + query['type'] = game_type_cd + try: + game_type_descr = DBSession.query(GameType.descr).\ + filter(GameType.game_type_cd == game_type_cd).\ + one()[0] + except Exception as e: + game_type_cd = None + + rgs_q = recent_games_q(server_id=server_id, map_id=map_id, + player_id=player_id, game_type_cd=game_type_cd) + + recent_games = Page(rgs_q, current_page, url=page_url) + + recent_games.items = [RecentGame(row) for row in recent_games.items] + + return { + 'recent_games':recent_games, + 'query':query, + 'game_type_cd':game_type_cd, + } + +def game_finder(request): + """ + Provide a list of recent games with an advanced filter. + """ + return game_finder_data(request)