]> de.git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/views.py
Add basic display of player weapon stats.
[xonotic/xonstat.git] / xonstat / views.py
index 532f2e6e57a1604719e4ad95c62f9bc771a38433..b78d97c41f9b5e424c02a1544e7a999cf0b8f14d 100755 (executable)
@@ -1,10 +1,14 @@
 import datetime
+import time
 import re
 from pyramid.response import Response
 from pyramid.view import view_config
+from webhelpers.paginate import Page, PageURL
 
 from xonstat.models import *
+from xonstat.util import page_url
 from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
+from sqlalchemy import desc
 
 
 import logging
@@ -25,6 +29,7 @@ def main_index(request):
 @view_config(renderer='player_index.mako')
 def player_index(request):
     players = DBSession.query(Player)
+
     log.debug("testing logging; entered PlayerHandler.index()")
     return {'players':players}
 
@@ -33,35 +38,121 @@ def player_info(request):
     player_id = request.matchdict['id']
     try:
         player = DBSession.query(Player).filter_by(player_id=player_id).one()
-        recent_games = DBSession.query("game_id", "server_name", "map_name").\
-                from_statement("select g.game_id, s.name as server_name, m.name as map_name "
-                        "from player_game_stats gs, games g, servers s, maps m "
-                        "where gs.player_id=:player_id "
-                        "and gs.game_id = g.game_id "
-                        "and g.server_id = s.server_id "
-                        "and g.map_id = m.map_id "
-                        "order by g.start_dt desc "
-                        "limit 10 offset 1").\
-                        params(player_id=player_id).all()
+        recent_games = DBSession.query(PlayerGameStat, Game, Server, Map).\
+                filter(PlayerGameStat.player_id == player_id).\
+                filter(PlayerGameStat.game_id == Game.game_id).\
+                filter(Game.server_id == Server.server_id).\
+                filter(Game.map_id == Map.map_id).\
+                order_by(Game.game_id.desc())[0:10]
 
-        log.debug(recent_games)
     except Exception as e:
-        raise e
         player = None
-    return {'player':player, 'recent_games':recent_games}
+        recent_games = None
+    return {'player':player, 
+            'recent_games':recent_games}
+
+
+def player_game_index(request):
+    player_id = request.matchdict['player_id']
+    current_page = request.matchdict['page']
+
+    try:
+        player = DBSession.query(Player).filter_by(player_id=player_id).one()
+
+        games_q = DBSession.query(PlayerGameStat, Game, Server, Map).\
+                filter(PlayerGameStat.player_id == player_id).\
+                filter(PlayerGameStat.game_id == Game.game_id).\
+                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)
+
+        
+    except Exception as e:
+        player = None
+        games = None
+        raise e
+
+    return {'player':player,
+            'games':games}
+
+
+def player_weapon_stats(request):
+    game_id = request.matchdict['game_id']
+    pgstat_id = request.matchdict['pgstat_id']
+    try:
+        pwstats = DBSession.query(PlayerWeaponStat).\
+                filter_by(game_id=game_id).\
+                filter_by(player_game_stat_id=pgstat_id).\
+                order_by(PlayerWeaponStat.weapon_cd).\
+                all()
+
+    except Exception as e:
+        pwstats = None
+    return {'pwstats':pwstats}
 
 
 ##########################################################################
 # This is the game views area - only views pertaining to Xonotic
 # games and their related information goes here
 ##########################################################################
+def game_index(request):
+    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)
+
+    return {'games':games}
+
+
 def game_info(request):
     game_id = request.matchdict['id']
     try:
-        game = DBSession.query(Game).filter_by(game_id=game_id).one()
-    except:
-        game = None
-    return {'game':game}
+        notfound = False
+
+        (start_dt, game_type_cd, server_id, server_name, map_id, map_name) = \
+        DBSession.query("start_dt", "game_type_cd", "server_id", 
+                "server_name", "map_id", "map_name").\
+                from_statement("select g.start_dt, g.game_type_cd, "
+                        "g.server_id, s.name as server_name, g.map_id, "
+                        "m.name as map_name "
+                        "from games g, servers s, maps m "
+                        "where g.game_id = :game_id "
+                        "and g.server_id = s.server_id "
+                        "and g.map_id = m.map_id").\
+                        params(game_id=game_id).one()
+
+        player_game_stats = DBSession.query(PlayerGameStat).\
+                from_statement("select * from player_game_stats "
+                        "where game_id = :game_id "
+                        "order by score desc").\
+                            params(game_id=game_id).all()
+    except Exception as inst:
+        notfound = True
+        start_dt = None
+        game_type_cd = None
+        server_id = None
+        server_name = None
+        map_id = None
+        map_name = None
+        player_game_stats = None
+
+    return {'notfound':notfound,
+            'start_dt':start_dt,
+            'game_type_cd':game_type_cd,
+            'server_id':server_id,
+            'server_name':server_name,
+            'map_id':map_id,
+            'map_name':map_name,
+            'player_game_stats':player_game_stats}
 
 
 ##########################################################################
@@ -72,9 +163,40 @@ def server_info(request):
     server_id = request.matchdict['id']
     try:
         server = DBSession.query(Server).filter_by(server_id=server_id).one()
-    except:
+        recent_games = DBSession.query(Game, Server, Map).\
+                filter(Game.server_id == server_id).\
+                filter(Game.server_id == Server.server_id).\
+                filter(Game.map_id == Map.map_id).\
+                order_by(Game.game_id.desc())[0:10]
+
+    except Exception as e:
         server = None
-    return {'server':server}
+        recent_games = None
+    return {'server':server,
+            'recent_games':recent_games}
+
+
+def server_game_index(request):
+    server_id = request.matchdict['server_id']
+    current_page = request.matchdict['page']
+
+    try:
+        server = DBSession.query(Server).filter_by(server_id=server_id).one()
+
+        games_q = DBSession.query(Game, Server, Map).\
+                filter(Game.server_id == server_id).\
+                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)
+    except Exception as e:
+        server = None
+        games = None
+        raise e
+
+    return {'games':games,
+            'server':server}
 
 
 ##########################################################################
@@ -240,38 +362,39 @@ def create_player_game_stat(session=None, player=None,
 
 
 def create_player_weapon_stats(session=None, player=None, 
-        game=None, player_events=None):
+        game=None, pgstat=None, player_events=None):
     pwstats = []
 
     for (key,value) in player_events.items():
         matched = re.search("acc-(.*?)-cnt-fired", key)
         if matched:
-            log.debug("Matched key: {0}".format(key))
             weapon_cd = matched.group(1)
             pwstat = PlayerWeaponStat()
             pwstat.player_id = player.player_id
             pwstat.game_id = game.game_id
+            pwstat.player_game_stat_id = pgstat.player_game_stat_id
             pwstat.weapon_cd = weapon_cd
-            try:
-                pwstat.max = int(player_events['acc-' + weapon_cd + '-fired'])
-            except:
-                pwstat.max = 0
-            try:
-                pwstat.actual = int(player_events['acc-' + weapon_cd + '-hit'])
-            except:
-                pwstat.actual = 0
-            try:
-                pwstat.fired = int(player_events['acc-' + weapon_cd + '-cnt-fired'])
-            except:
-                pwstat.fired = 0
-            try:
-                pwstat.hit = int(player_events['acc-' + weapon_cd + '-cnt-hit'])
-            except:
-                pwstat.hit = 0
-            try:
-                pwstat.frags = int(player_events['acc-' + weapon_cd + '-frags'])
-            except:
-                pwstat.frags = 0
+
+            if 'n' in player_events:
+                pwstat.nick = player_events['n']
+            else:
+                pwstat.nick = player_events['P']
+
+            if 'acc-' + weapon_cd + '-cnt-fired' in player_events:
+                pwstat.fired = int(round(float(
+                        player_events['acc-' + weapon_cd + '-cnt-fired'])))
+            if 'acc-' + weapon_cd + '-fired' in player_events:
+                pwstat.max = int(round(float(
+                        player_events['acc-' + weapon_cd + '-fired'])))
+            if 'acc-' + weapon_cd + '-cnt-hit' in player_events:
+                pwstat.hit = int(round(float(
+                        player_events['acc-' + weapon_cd + '-cnt-hit'])))
+            if 'acc-' + weapon_cd + '-hit' in player_events:
+                pwstat.actual = int(round(float(
+                        player_events['acc-' + weapon_cd + '-hit'])))
+            if 'acc-' + weapon_cd + '-frags' in player_events:
+                pwstat.frags = int(round(float(
+                        player_events['acc-' + weapon_cd + '-frags'])))
 
             session.add(pwstat)
             pwstats.append(pwstat)
@@ -295,24 +418,22 @@ def parse_body(request):
             if key in 'V' 'T' 'G' 'M' 'S' 'C' 'R' 'W':
                 game_meta[key] = value
 
-            if key == 't':
-                current_team = value
-    
             if key == 'P':
                 # if we were working on a player record already, append
                 # it and work on a new one (only set team info)
                 if len(player_events) != 0:
                     players.append(player_events)
-                    player_events = {'t':current_team}
+                    player_events = {}
     
                 player_events[key] = value
-    
+
             if key == 'e':
                 (subkey, subvalue) = value.split(' ', 1)
                 player_events[subkey] = subvalue
-
             if key == 'n':
                 player_events[key] = value
+            if key == 't':
+                player_events[key] = value
         except:
             # no key/value pair - move on to the next line
             pass
@@ -324,6 +445,18 @@ def parse_body(request):
     return (game_meta, players)
 
 
+def create_player_stats(session=None, player=None, game=None, 
+        player_events=None):
+    if 'joins' in player_events and 'matches' in player_events\
+            and 'scoreboardvalid' in player_events:
+                pgstat = create_player_game_stat(session=session, 
+                        player=player, game=game, player_events=player_events)
+                if not re.search('^bot#\d+$', player_events['P']):
+                        create_player_weapon_stats(session=session, 
+                            player=player, game=game, pgstat=pgstat,
+                            player_events=player_events)
+    
+
 @view_config(renderer='stats_submit.mako')
 def stats_submit(request):
     try:
@@ -338,8 +471,18 @@ def stats_submit(request):
             'S' not in game_meta:
             log.debug("Required game meta fields (T, G, M, or S) missing. "\
                     "Can't continue.")
-            raise Exception
+            raise Exception("Required game meta fields (T, G, M, or S) missing.")
     
+        has_real_players = False
+        for player_events in players:
+            if not player_events['P'].startswith('bot'):
+                if 'joins' in player_events and 'matches' in player_events\
+                    and 'scoreboardvalid' in player_events:
+                    has_real_players = True
+
+        if not has_real_players:
+            raise Exception("No real players found. Stats ignored.")
+
         server = get_or_create_server(session=session, name=game_meta['S'])
         gmap = get_or_create_map(session=session, name=game_meta['M'])
 
@@ -348,35 +491,25 @@ def stats_submit(request):
         else:
             winner = None
 
-        # FIXME: don't use python now() here, convert from epoch T value
-        game = create_game(session=session, start_dt=datetime.datetime.now(), 
+        game = create_game(session=session, 
+                start_dt=datetime.datetime(
+                    *time.gmtime(float(game_meta['T']))[:6]), 
                 server_id=server.server_id, game_type_cd=game_meta['G'], 
                 map_id=gmap.map_id, winner=winner)
     
         # 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 and 'matches' in player_events\
-                    and 'scoreboardvalid' in player_events:
-                pgstat = create_player_game_stat(session=session, 
-                        player=player, game=game, player_events=player_events)
-                #pwstats = create_player_weapon_stats(session=session, 
-                        #player=player, game=game, player_events=player_events)
+            log.debug('Creating stats for %s' % player_events['P'])
+            create_player_stats(session=session, player=player, game=game, 
+                    player_events=player_events)
     
-        if has_real_players:
-            session.commit()
-            log.debug('Success! Stats recorded.')
-            return Response('200 OK')
-        else:
-            session.rollback()
-            log.debug('No real players found. Stats ignored.')
-            return {'msg':'No real players found. Stats ignored.'}
+        session.commit()
+        log.debug('Success! Stats recorded.')
+        return Response('200 OK')
     except Exception as e:
         session.rollback()
         raise e