From: Ant Zucaro Date: Fri, 1 Apr 2011 01:48:12 +0000 (-0400) Subject: Import views from old pyramid version of xonstat. Configure a junk view to make sure... X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=e6d0ab1090c603230387deb200631ee18a52b87a;p=xonotic%2Fxonstat.git Import views from old pyramid version of xonstat. Configure a junk view to make sure things work. --- diff --git a/xonstat/__init__.py b/xonstat/__init__.py index 296c0e4..a22c216 100644 --- a/xonstat/__init__.py +++ b/xonstat/__init__.py @@ -1,8 +1,8 @@ +import pyramid_jinja2 import sqlahelper from pyramid.config import Configurator from sqlalchemy import engine_from_config - def main(global_config, **settings): """ This function returns a Pyramid WSGI application. """ @@ -16,8 +16,18 @@ def main(global_config, **settings): from xonstat.models import initialize_sql initialize_sql(engine) + # import the views + # note: have to import here else we'll get` + # "no engine 'default' was configured + from xonstat.views import * + config = Configurator(settings=settings) + + config.add_renderer('.jinja2', pyramid_jinja2.renderer_factory) + config.add_static_view('static', 'xonstat:static') + + config.add_route(name="main_index", pattern="/", view=main_index, renderer='index.jinja2') return config.make_wsgi_app() diff --git a/xonstat/views.py b/xonstat/views.py index 39a187f..117046e 100644 --- a/xonstat/views.py +++ b/xonstat/views.py @@ -1 +1,245 @@ -from xonstat.models import DBSession +import datetime +import re +from pyramid.response import Response +from pyramid.view import view_config + +from xonstat.models import * + +import logging +log = logging.getLogger(__name__) + +########################################################################## +# This is the main index - the entry point to the entire site +########################################################################## +@view_config(renderer='index.jinja2') +def main_index(request): + log.debug("testing logging; entered MainHandler.index()") + return {'project':'xonstat'} + +########################################################################## +# This is the player views area - only views pertaining to Xonotic players +# and their related information goes here +########################################################################## +@view_config(renderer='player_index.mako') +def player_index(request): + players = Session.query(Player) + log.debug("testing logging; entered PlayerHandler.index()") + return {'players':players} + +@view_config(renderer='player_info.mako') +def player_info(request): + player = Session.query(Player).filter_by(player_id=p_player_id) + log.debug("testing logging; entered PlayerHandler.info()") + return {'player':player} + +########################################################################## +# This is the stats views area - only views pertaining to Xonotic +# statistics and its related information goes here +########################################################################## +def get_or_create_server(session=None, name=None): + server = None + try: + # find one by that name, if it exists + server = session.query(Server).filter_by(name=name).one() + log.debug("Found server id {0} with name {1}.".format( + server.server_id, server.name)) + except: + # otherwise create a new one + server = Server(name=name) + session.add(server) + session.flush() + log.debug("Created server id {0} with name {1}".format( + server.server_id, server.name)) + + return server + +def get_or_create_map(session=None, name=None): + gmap = None + try: + # find one by the name, if it exists + gmap = session.query(Map).filter_by(name=name) + log.debug("Found map id {0} with name {1}.".format(gmap.map_id, + gmap.name)) + except: + # otherwise create a new one + gmap = Map(name=name) + session.add(gmap) + session.flush() + log.debug("Created map id {0} with name {1}.".format(gmap.map_id, + gmap.name)) + + return gmap + +def create_game(session=None, start_dt=None, game_type_cd=None, + server_id=None, map_id=None): + game = Game(start_dt=start_dt, game_type_cd=game_type_cd, + server_id=server_id, map_id=map_id) + session.add(game) + session.flush() + log.debug("Created game id {0} on server {1}, map {2} at time \ + {3} and on map {4}".format(game.game_id, + server_id, map_id, start_dt, map_id)) + + return game + +# search for a player and if found, create a new one (w/ hashkey) +def get_or_create_player(session=None, hashkey=None): + # the player object we'll return + player = None + + # if we have a bot + if re.search('^bot#\d+$', hashkey): + player = session.query(Player).filter_by(player_id=1).one() + # if we have an untracked player + elif re.search('^player#\d+$', hashkey): + player = session.query(Player).filter_by(player_id=2).one() + # else it is a tracked player + else: + # see if the player is already in the database + # if not, create one and the hashkey along with it + try: + hashkey = session.query(Hashkey).filter_by( + hashkey=hashkey).one() + player = session.query(Player).filter_by( + player_id=hashkey.player_id).one() + except: + player = Player() + session.add(player) + session.flush() + hashkey = Hashkey(player_id=player.player_id, hashkey=hashkey) + session.add(hashkey) + + return player + +def create_player_game_stat(session=None, player=None, + game=None, player_events=None): + + # in here setup default values (e.g. if game type is CTF then + # set kills=0, score=0, captures=0, pickups=0, fckills=0, etc + pgstat = PlayerGameStat() + + # set player id from player record + pgstat.player_id = player.player_id + + # all games have a score + pgstat.score = 0 + + if game.game_type_cd == 'dm': + pgstat.kills = 0 + pgstat.deaths = 0 + pgstat.suicides = 0 + elif game.game_type_cd == 'ctf': + pgstat.kills = 0 + pgstat.captures = 0 + pgstat.pickups = 0 + pgstat.drops = 0 + pgstat.returns = 0 + pgstat.carrier_frags = 0 + + for (key,value) in player_events.items(): + if key == 'n': pgstat.nick = value + if key == 'total-drops': pgstat.drops = value + if key == 'total-returns': pgstat.returns = value + if key == 'total-fckills': pgstat.carrier_frags = value + if key == 'total-pickups': pgstat.pickups = value + if key == 'total-caps': pgstat.caps = value + if key == 'total-score': pgstat.score = value + if key == 'total-deaths': pgstat.deaths = value + if key == 'total-kills': pgstat.kills = value + if key == 'total-suicides': pgstat.suicides = value + # TODO: alivetime + + # check to see if we had a name, and if + # not use the name from the player id + if pgstat.nick == None: + pgstat.nick = player.nick + + session.add(pgstat) + session.flush() + + return pgstat + +@view_config(renderer='stats_submit.mako') +def stats_submit(request): + session = Session() + + # game meta information + game_meta = {} + player_events = {} + players = [] + + # main loop over each line of the stats body + for line in request.body.split('\n'): + (key, value) = line.strip().split(' ', 1) + + # these are important keys needed to establish + # basic game meta information + if key in 'V' 'T' 'G' 'M' 'S' 'C': + game_meta[key] = value + + # 'P' is a player record. After this key we will get a list + # of events for that player + if key == 'P': + # if we were working on a player record previously, append + # it and work on a new one + if len(player_events) != 0: + players.append(player_events) + player_events = {} + + player_events[key] = value + + # 'e' is an event associated with the current 'P' record + # being processed + if key == 'e': + (subkey, subvalue) = value.split(' ', 1) + player_events[subkey] = subvalue + + # 'n' is a player's name. it is not an event per se, + # but it belongs on the player record + if key == 'n': + player_events[key] = value + + # add the last player we were working on + players.append(player_events) + + # verify required metadata is present + if 'T' not in game_meta or\ + 'G' not in game_meta or\ + 'M' not in game_meta or\ + 'S' not in game_meta: + log.debug("Required game meta fields (T, G, M, or S) missing. "\ + "Can't continue.") + return {'msg':'Error processing the request.'} + + # find or create a record for the server + server = get_or_create_server(session=session, name=game_meta['S']) + + # find or create a record for the map + gmap = get_or_create_map(session=session, name=game_meta['M']) + + # create the game + # FIXME: don't use python now() here, convert from epoch T value + now = datetime.datetime.now() + game = create_game(session=session, start_dt=now, + server_id=server.server_id,\ + game_type_cd=game_meta['G'], map_id=gmap.map_id) + + # find or create a record for each player + # and add stats for each if they were present at the end + # of the game + has_real_players = False + for player_events in players: + if not player_events['P'].startswith('bot'): + has_real_players = True + player = get_or_create_player(session=session, + hashkey=player_events['P']) + if 'joins' in player_events: + pgstat = create_player_game_stat(session=session, + player=player, game=game, player_events=player_events) + + if has_real_players: + session.commit() + return {'msg':'Success! Stats recorded.'} + else: + session.rollback() + return {'msg':'No real players found. Stats ignored.'}