X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonstat.git;a=blobdiff_plain;f=xonstat%2Fviews%2Fmap.py;h=f1daf4aabe7f57c385ce1a0a1511fa9fe8e22773;hp=fff321f9e3af10b6c25210822b58fa03e505ed40;hb=2d53f7f9232b23ada761231482262392cf72192c;hpb=ed2724e703b7b440bb87558df38043b1f6f9fe7e diff --git a/xonstat/views/map.py b/xonstat/views/map.py old mode 100755 new mode 100644 index fff321f..f1daf4a --- a/xonstat/views/map.py +++ b/xonstat/views/map.py @@ -1,125 +1,219 @@ -import logging -import sqlalchemy.sql.functions as func -import sqlalchemy.sql.expression as expr -from datetime import datetime, timedelta -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 map_index(request): - """ - Provides a list of all the current maps. - """ - if 'page' in request.matchdict: - current_page = request.matchdict['page'] - else: - current_page = 1 - - try: - map_q = DBSession.query(Map).\ - order_by(Map.map_id.desc()) - - maps = Page(map_q, current_page, url=page_url) - - - except Exception as e: - maps = None - - return {'maps':maps, } - - -def map_info(request): - """ - List the information stored about a given map. - """ - map_id = request.matchdict['id'] - - try: - leaderboard_lifetime = int( - request.registry.settings['xonstat.leaderboard_lifetime']) - except: - leaderboard_lifetime = 30 - - leaderboard_count = 10 - recent_games_count = 20 - - try: - gmap = DBSession.query(Map).filter_by(map_id=map_id).one() - - # recent games on this map - recent_games = DBSession.query(Game, Server, Map, PlayerGameStat).\ - filter(Game.server_id==Server.server_id).\ - filter(Game.map_id==Map.map_id).\ - filter(Game.map_id==map_id).\ - filter(PlayerGameStat.game_id==Game.game_id).\ - filter(PlayerGameStat.rank==1).\ - order_by(expr.desc(Game.start_dt)).all()[0:recent_games_count] - - for i in range(recent_games_count-len(recent_games)): - recent_games.append(('-', '-', '-', '-')) - - - # top players by score - top_scorers = DBSession.query(Player.player_id, Player.nick, - func.sum(PlayerGameStat.score)).\ - filter(Player.player_id == PlayerGameStat.player_id).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.map_id == map_id).\ - filter(Player.player_id > 2).\ - filter(PlayerGameStat.create_dt > - (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\ - order_by(expr.desc(func.sum(PlayerGameStat.score))).\ - group_by(Player.nick).\ - group_by(Player.player_id).all()[0:10] - - top_scorers = [(player_id, html_colors(nick), score) \ - for (player_id, nick, score) in top_scorers] - - for i in range(leaderboard_count-len(top_scorers)): - top_scorers.append(('-', '-', '-')) - - # top players by playing time - top_players = DBSession.query(Player.player_id, Player.nick, - func.sum(PlayerGameStat.alivetime)).\ - filter(Player.player_id == PlayerGameStat.player_id).\ - filter(Game.game_id == PlayerGameStat.game_id).\ - filter(Game.map_id == map_id).\ - filter(Player.player_id > 2).\ - filter(PlayerGameStat.create_dt > - (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\ - order_by(expr.desc(func.sum(PlayerGameStat.alivetime))).\ - group_by(Player.nick).\ - group_by(Player.player_id).all()[0:10] - - top_players = [(player_id, html_colors(nick), score) \ - for (player_id, nick, score) in top_players] - - for i in range(leaderboard_count-len(top_players)): - top_players.append(('-', '-', '-')) - - # top servers using/playing this map - top_servers = DBSession.query(Server.server_id, Server.name, - func.count(Game.game_id)).\ - filter(Game.server_id == Server.server_id).\ - filter(Game.map_id == map_id).\ - filter(Game.create_dt > - (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\ - order_by(expr.desc(func.count(Game.game_id))).\ - group_by(Server.name).\ - group_by(Server.server_id).all()[0:10] - - for i in range(leaderboard_count-len(top_servers)): - top_servers.append(('-', '-', '-')) - - except Exception as e: - gmap = None - return {'gmap':gmap, - 'recent_games':recent_games, - 'top_scorers':top_scorers, - 'top_players':top_players, - 'top_servers':top_servers, - } +import logging +from collections import namedtuple +from datetime import datetime, timedelta + +import sqlalchemy.sql.expression as expr +import sqlalchemy.sql.functions as func +from pyramid.httpexceptions import HTTPNotFound +from webhelpers.paginate import Page +from xonstat.models import DBSession, Server, Map, Game, PlayerGameStat, Player, PlayerCaptime +from xonstat.models.map import MapCapTime +from xonstat.util import page_url, html_colors +from xonstat.views.helpers import RecentGame, recent_games_q + +log = logging.getLogger(__name__) + +# Defaults +INDEX_COUNT = 20 + + +class MapIndex(object): + """Returns a list of maps.""" + + def __init__(self, request): + """Common parameter parsing.""" + self.request = request + self.page = request.params.get("page", 1) + + # all views share this data, so we'll precalculate + self.maps = self.map_index() + + def map_index(self): + """Returns the raw data shared by all renderers.""" + try: + map_q = DBSession.query(Map).order_by(Map.map_id.desc()) + maps = Page(map_q, self.page, items_per_page=INDEX_COUNT, url=page_url) + + except Exception as e: + log.debug(e) + raise HTTPNotFound + + return maps + + def html(self): + """For rendering this data using something HTML-based.""" + return { + 'maps': self.maps, + } + + def json(self): + """For rendering this data using JSON.""" + return { + 'maps': [m.to_dict() for m in self.maps], + } + + +def _map_info_data(request): + map_id = int(request.matchdict['id']) + + try: + leaderboard_lifetime = int( + request.registry.settings['xonstat.leaderboard_lifetime']) + except: + leaderboard_lifetime = 30 + + leaderboard_count = 10 + recent_games_count = 20 + + # captime tuples + Captime = namedtuple('Captime', ['player_id', 'nick_html_colors', + 'fastest_cap', 'game_id']) + + try: + gmap = DBSession.query(Map).filter_by(map_id=map_id).one() + + # recent games played in descending order + rgs = recent_games_q(map_id=map_id).limit(recent_games_count).all() + recent_games = [RecentGame(row) for row in rgs] + + # top players by score + top_scorers = DBSession.query(Player.player_id, Player.nick, + func.sum(PlayerGameStat.score)).\ + filter(Player.player_id == PlayerGameStat.player_id).\ + filter(Game.game_id == PlayerGameStat.game_id).\ + filter(Game.map_id == map_id).\ + filter(Player.player_id > 2).\ + filter(PlayerGameStat.create_dt > + (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\ + order_by(expr.desc(func.sum(PlayerGameStat.score))).\ + group_by(Player.nick).\ + group_by(Player.player_id).all()[0:leaderboard_count] + + top_scorers = [(player_id, html_colors(nick), score) \ + for (player_id, nick, score) in top_scorers] + + # top players by playing time + top_players = DBSession.query(Player.player_id, Player.nick, + func.sum(PlayerGameStat.alivetime)).\ + filter(Player.player_id == PlayerGameStat.player_id).\ + filter(Game.game_id == PlayerGameStat.game_id).\ + filter(Game.map_id == map_id).\ + filter(Player.player_id > 2).\ + filter(PlayerGameStat.create_dt > + (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\ + order_by(expr.desc(func.sum(PlayerGameStat.alivetime))).\ + group_by(Player.nick).\ + group_by(Player.player_id).all()[0:leaderboard_count] + + top_players = [(player_id, html_colors(nick), score) \ + for (player_id, nick, score) in top_players] + + # top servers using/playing this map + top_servers = DBSession.query(Server.server_id, Server.name, + func.count(Game.game_id)).\ + filter(Game.server_id == Server.server_id).\ + filter(Game.map_id == map_id).\ + filter(Game.create_dt > + (datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\ + order_by(expr.desc(func.count(Game.game_id))).\ + group_by(Server.name).\ + group_by(Server.server_id).all()[0:leaderboard_count] + + # TODO make this a configuration parameter to be set in the settings + # top captimes + captimes_raw = DBSession.query(Player.player_id, Player.nick, + PlayerCaptime.fastest_cap, PlayerCaptime.game_id).\ + filter(PlayerCaptime.map_id == map_id).\ + filter(Player.player_id == PlayerCaptime.player_id).\ + order_by(PlayerCaptime.fastest_cap).\ + limit(10).\ + all() + + captimes = [Captime(c.player_id, html_colors(c.nick), + c.fastest_cap, c.game_id) for c in captimes_raw] + + except Exception as e: + gmap = None + return {'gmap':gmap, + 'recent_games':recent_games, + 'top_scorers':top_scorers, + 'top_players':top_players, + 'top_servers':top_servers, + 'captimes':captimes, + } + + +def map_info(request): + """ + List the information stored about a given map. + """ + mapinfo_data = _map_info_data(request) + + # FIXME: code clone, should get these from _map_info_data + leaderboard_count = 10 + recent_games_count = 20 + + for i in range(leaderboard_count-len(mapinfo_data['top_scorers'])): + mapinfo_data['top_scorers'].append(('-', '-', '-')) + + for i in range(leaderboard_count-len(mapinfo_data['top_players'])): + mapinfo_data['top_players'].append(('-', '-', '-')) + + for i in range(leaderboard_count-len(mapinfo_data['top_servers'])): + mapinfo_data['top_servers'].append(('-', '-', '-')) + + return mapinfo_data + + +def map_info_json(request): + """ + List the information stored about a given map. JSON. + """ + return [{'status':'not implemented'}] + + +def map_captimes_data(request): + map_id = int(request.matchdict['id']) + + current_page = request.params.get('page', 1) + + try: + mmap = DBSession.query(Map).filter_by(map_id=map_id).one() + + mct_q = DBSession.query(PlayerCaptime.fastest_cap, PlayerCaptime.create_dt, + PlayerCaptime.player_id, PlayerCaptime.game_id, + Game.server_id, Server.name.label('server_name'), + PlayerGameStat.nick.label('player_nick')).\ + filter(PlayerCaptime.map_id==map_id).\ + filter(PlayerCaptime.game_id==Game.game_id).\ + filter(PlayerCaptime.map_id==Map.map_id).\ + filter(Game.server_id==Server.server_id).\ + filter(PlayerCaptime.player_id==PlayerGameStat.player_id).\ + filter(PlayerCaptime.game_id==PlayerGameStat.game_id).\ + order_by(expr.asc(PlayerCaptime.fastest_cap)) + + except Exception as e: + raise httpexceptions.HTTPNotFound + + map_captimes = Page(mct_q, current_page, items_per_page=20, url=page_url) + + map_captimes.items = [MapCapTime(row) for row in map_captimes.items] + + return { + 'map_id':map_id, + 'map':mmap, + 'captimes':map_captimes, + } + +def map_captimes(request): + return map_captimes_data(request) + +def map_captimes_json(request): + current_page = request.params.get('page', 1) + data = map_captimes_data(request) + + return { + "map": data["map"].to_dict(), + "captimes": [e.to_dict() for e in data["captimes"].items], + "page": current_page, + }