]> de.git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/views/submission.py
Use a dummy session variable.
[xonotic/xonstat.git] / xonstat / views / submission.py
index 68610cf1ff92806e4ca52cc5b4e077ef6b21ec3a..c248f424017c8b1ca3f9c745d58acb77bf91beed 100644 (file)
@@ -8,6 +8,7 @@ from pyramid.response import Response
 from sqlalchemy import Sequence
 from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
 from xonstat.d0_blind_id import d0_blind_id_verify
+from xonstat.elo import process_elos
 from xonstat.models import *
 from xonstat.util import strip_colors, qfont_decode
 
@@ -100,7 +101,6 @@ def has_minimum_real_players(settings, player_events):
 
     real_players = num_real_players(player_events)
 
-    #TODO: put this into a config setting in the ini file?
     if real_players < minimum_required_players:
         flg_has_min_real_players = False
 
@@ -273,6 +273,9 @@ def create_game(session=None, start_dt=None, game_type_cd=None,
     try:
         session.query(Game).filter(Game.server_id==server_id).\
                 filter(Game.match_id==match_id).one()
+
+        log.debug("Error: game with same server and match_id found! Ignoring.")
+
         # if a game under the same server and match_id found, 
         # this is a duplicate game and can be ignored
         raise pyramid.httpexceptions.HTTPOk('OK')
@@ -375,19 +378,19 @@ def create_player_game_stat(session=None, player=None,
 
     for (key,value) in player_events.items():
         if key == 'n': pgstat.nick = value[:128]
-        if key == 't': pgstat.team = value
-        if key == 'rank': pgstat.rank = value
+        if key == 't': pgstat.team = int(value)
+        if key == 'rank': pgstat.rank = int(value)
         if key == 'alivetime': 
             pgstat.alivetime = datetime.timedelta(seconds=int(round(float(value))))
-        if key == 'scoreboard-drops': pgstat.drops = value
-        if key == 'scoreboard-returns': pgstat.returns = value
-        if key == 'scoreboard-fckills': pgstat.carrier_frags = value
-        if key == 'scoreboard-pickups': pgstat.pickups = value
-        if key == 'scoreboard-caps': pgstat.captures = value
-        if key == 'scoreboard-score': pgstat.score = value
-        if key == 'scoreboard-deaths': pgstat.deaths = value
-        if key == 'scoreboard-kills': pgstat.kills = value
-        if key == 'scoreboard-suicides': pgstat.suicides = value
+        if key == 'scoreboard-drops': pgstat.drops = int(value)
+        if key == 'scoreboard-returns': pgstat.returns = int(value)
+        if key == 'scoreboard-fckills': pgstat.carrier_frags = int(value)
+        if key == 'scoreboard-pickups': pgstat.pickups = int(value)
+        if key == 'scoreboard-caps': pgstat.captures = int(value)
+        if key == 'scoreboard-score': pgstat.score = int(value)
+        if key == 'scoreboard-deaths': pgstat.deaths = int(value)
+        if key == 'scoreboard-kills': pgstat.kills = int(value)
+        if key == 'scoreboard-suicides': pgstat.suicides = int(value)
 
     # check to see if we had a name, and if
     # not use an anonymous handle
@@ -402,7 +405,7 @@ def create_player_game_stat(session=None, player=None,
     # if the player is ranked #1 and it is a team game, set the game's winner
     # to be the team of that player
     # FIXME: this is a hack, should be using the 'W' field (not present)
-    if pgstat.rank == '1' and pgstat.team:
+    if pgstat.rank == 1 and pgstat.team:
         game.winner = pgstat.team
         session.add(game)
 
@@ -412,7 +415,7 @@ def create_player_game_stat(session=None, player=None,
 
 
 def create_player_weapon_stats(session=None, player=None, 
-        game=None, pgstat=None, player_events=None):
+        game=None, pgstat=None, player_events=None, game_meta=None):
     """
     Creates accuracy records for each weapon used by a given player in a
     given game. Parameters:
@@ -423,9 +426,23 @@ def create_player_weapon_stats(session=None, player=None,
     pgstat - Corresponding PlayerGameStat record for these weapon stats
     player_events - dictionary containing the raw weapon values that need to be
         transformed
+    game_meta - dictionary of game metadata (only used for stats version info)
     """
     pwstats = []
 
+    # Version 1 of stats submissions doubled the data sent.
+    # To counteract this we divide the data by 2 only for
+    # POSTs coming from version 1.
+    try:
+        version = int(game_meta['V'])
+        if version == 1:
+            is_doubled = True
+            log.debug('NOTICE: found a version 1 request, halving the weapon stats...')
+        else:
+            is_doubled = False
+    except:
+        is_doubled = False
+
     for (key,value) in player_events.items():
         matched = re.search("acc-(.*?)-cnt-fired", key)
         if matched:
@@ -447,18 +464,28 @@ def create_player_weapon_stats(session=None, player=None,
             if 'acc-' + weapon_cd + '-cnt-fired' in player_events:
                 pwstat.fired = int(round(float(
                         player_events['acc-' + weapon_cd + '-cnt-fired'])))
+                if is_doubled:
+                    pwstat.fired = pwstat.fired/2
             if 'acc-' + weapon_cd + '-fired' in player_events:
                 pwstat.max = int(round(float(
                         player_events['acc-' + weapon_cd + '-fired'])))
+                if is_doubled:
+                    pwstat.max = pwstat.max/2
             if 'acc-' + weapon_cd + '-cnt-hit' in player_events:
                 pwstat.hit = int(round(float(
                         player_events['acc-' + weapon_cd + '-cnt-hit'])))
+                if is_doubled:
+                    pwstat.hit = pwstat.hit/2
             if 'acc-' + weapon_cd + '-hit' in player_events:
                 pwstat.actual = int(round(float(
                         player_events['acc-' + weapon_cd + '-hit'])))
+                if is_doubled:
+                    pwstat.actual = pwstat.actual/2
             if 'acc-' + weapon_cd + '-frags' in player_events:
                 pwstat.frags = int(round(float(
                         player_events['acc-' + weapon_cd + '-frags'])))
+                if is_doubled:
+                    pwstat.frags = pwstat.frags/2
 
             session.add(pwstat)
             pwstats.append(pwstat)
@@ -516,7 +543,7 @@ def parse_body(request):
 
 
 def create_player_stats(session=None, player=None, game=None, 
-        player_events=None):
+        player_events=None, game_meta=None):
     """
     Creates player game and weapon stats according to what type of player
     """
@@ -527,7 +554,7 @@ def create_player_stats(session=None, player=None, game=None,
     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)
+            player_events=player_events, game_meta=game_meta)
 
 
 def stats_submit(request):
@@ -535,7 +562,8 @@ def stats_submit(request):
     Entry handler for POST stats submissions.
     """
     try:
-        session = DBSession()
+        # placeholder for the actual session
+        session = None
 
         log.debug("\n----- BEGIN REQUEST BODY -----\n" + request.body +
                 "----- END REQUEST BODY -----\n\n")
@@ -545,7 +573,7 @@ def stats_submit(request):
             log.debug("ERROR: Unverified request")
             raise pyramid.httpexceptions.HTTPUnauthorized("Unverified request")
 
-        (game_meta, players) = parse_body(request)  
+        (game_meta, players) = parse_body(request)
 
         if not has_required_metadata(game_meta):
             log.debug("ERROR: Required game meta missing")
@@ -575,6 +603,12 @@ def stats_submit(request):
         except:
             revision = "unknown"
 
+        #----------------------------------------------------------------------
+        # This ends the "precondition" section of sanity checks. All
+        # functions not requiring a database connection go ABOVE HERE.
+        #----------------------------------------------------------------------
+        session = DBSession()
+
         server = get_or_create_server(session=session, hashkey=idfp, 
                 name=game_meta['S'], revision=revision,
                 ip_addr=get_remote_addr(request))
@@ -605,11 +639,11 @@ def stats_submit(request):
                     hashkey=player_events['P'], nick=nick)
                 log.debug('Creating stats for %s' % player_events['P'])
                 create_player_stats(session=session, player=player, game=game, 
-                        player_events=player_events)
+                        player_events=player_events, game_meta=game_meta)
 
         # update elos
         try:
-            game.process_elos(session)
+            process_elos(game, session)
         except Exception as e:
             log.debug('Error (non-fatal): elo processing failed.')
 
@@ -617,5 +651,6 @@ def stats_submit(request):
         log.debug('Success! Stats recorded.')
         return Response('200 OK')
     except Exception as e:
-        session.rollback()
+        if session:
+            session.rollback()
         return e