]> de.git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/views/submission.py
Add a JSON Elo view to support autobalance.
[xonotic/xonstat.git] / xonstat / views / submission.py
index 95c83738df4384b438dbbca87532aec5a922d7d0..364babb67ff3419fcb34f704f78a1fc8687a5142 100644 (file)
@@ -31,7 +31,7 @@ def is_blank_game(players):
     for events in players:
         if is_real_player(events):
             for (key,value) in events.items():
-                if key == 'scoreboard-score' and value != '0':
+                if key == 'scoreboard-score' and value != 0:
                     flg_nonzero_score = True
                 if r.search(key):
                     flg_acc_events = True
@@ -107,6 +107,22 @@ def has_minimum_real_players(settings, player_events):
     return flg_has_min_real_players
 
 
+def verify_requests(settings):
+    """
+    Determines whether or not to verify requests using the blind_id algorithm
+    """
+    try:
+        val_verify_requests = settings['xonstat.verify_requests']
+        if val_verify_requests == "true":
+            flg_verify_requests = True
+        else:
+            flg_verify_requests = False
+    except:
+        flg_verify_requests = True
+
+    return flg_verify_requests
+
+
 def has_required_metadata(metadata):
     """
     Determines if a give set of metadata has enough data to create a game,
@@ -165,7 +181,7 @@ def register_new_nick(session, player, new_nick):
         if not re.search('^Anonymous Player #\d+$', player.nick):
             player_nick = PlayerNick()
             player_nick.player_id = player.player_id
-            player_nick.stripped_nick = player.stripped_nick
+            player_nick.stripped_nick = stripped_nick
             player_nick.nick = player.nick
             session.add(player_nick)
 
@@ -175,6 +191,36 @@ def register_new_nick(session, player, new_nick):
     session.add(player)
 
 
+def update_fastest_cap(session, player_id, game_id,  map_id, captime):
+    """
+    Check the fastest cap time for the player and map. If there isn't
+    one, insert one. If there is, check if the passed time is faster.
+    If so, update!
+    """
+    # we don't record fastest cap times for bots or anonymous players
+    if player_id <= 2:
+        return
+
+    # see if a cap entry exists already
+    # then check to see if the new captime is faster
+    try:
+        cur_fastest_cap = session.query(PlayerCaptime).filter_by(
+            player_id=player_id, map_id=map_id).one()
+
+        # current captime is faster, so update
+        if captime < cur_fastest_cap.fastest_cap:
+            cur_fastest_cap.fastest_cap = captime
+            cur_fastest_cap.game_id = game_id
+            cur_fastest_cap.create_dt = datetime.datetime.utcnow()
+            session.add(cur_fastest_cap)
+
+    except NoResultFound, e:
+        # none exists, so insert
+        cur_fastest_cap = PlayerCaptime(player_id, game_id, map_id, captime)
+        session.add(cur_fastest_cap)
+        session.flush()
+
+
 def get_or_create_server(session=None, name=None, hashkey=None, ip_addr=None,
         revision=None):
     """
@@ -253,7 +299,8 @@ def get_or_create_map(session=None, name=None):
 
 
 def create_game(session=None, start_dt=None, game_type_cd=None, 
-        server_id=None, map_id=None, winner=None, match_id=None):
+        server_id=None, map_id=None, winner=None, match_id=None,
+        duration=None):
     """
     Creates a game. Parameters:
 
@@ -270,6 +317,11 @@ def create_game(session=None, start_dt=None, game_type_cd=None,
                 server_id=server_id, map_id=map_id, winner=winner)
     game.match_id = match_id
 
+    try:
+        game.duration = datetime.timedelta(seconds=int(round(float(duration))))
+    except:
+        pass
+
     try:
         session.query(Game).filter(Game.server_id==server_id).\
                 filter(Game.match_id==match_id).one()
@@ -282,6 +334,7 @@ def create_game(session=None, start_dt=None, game_type_cd=None,
     except NoResultFound, e:
         # server_id/match_id combination not found. game is ok to insert
         session.add(game)
+        session.flush()
         log.debug("Created game id {0} on server {1}, map {2} at \
                 {3}".format(game.game_id, 
                     server_id, map_id, start_dt))
@@ -394,6 +447,9 @@ def create_player_game_stat(session=None, player=None,
         if key == 'scoreboard-deaths': pgstat.deaths = int(value)
         if key == 'scoreboard-kills': pgstat.kills = int(value)
         if key == 'scoreboard-suicides': pgstat.suicides = int(value)
+        if key == 'scoreboard-captime':
+            pgstat.fastest_cap = datetime.timedelta(seconds=float(value)/100)
+        if key == 'avglatency': pgstat.avg_latency = float(value)
 
     # check to see if we had a name, and if
     # not use an anonymous handle
@@ -512,7 +568,7 @@ def parse_body(request):
             if key in 'S' 'n':
                 value = unicode(value, 'utf-8')
 
-            if key in 'V' 'T' 'G' 'M' 'S' 'C' 'R' 'W' 'I':
+            if key in 'V' 'T' 'G' 'M' 'S' 'C' 'R' 'W' 'I' 'D':
                 game_meta[key] = value
 
             if key == 'P':
@@ -550,7 +606,12 @@ def create_player_stats(session=None, player=None, game=None,
     pgstat = create_player_game_stat(session=session, 
         player=player, game=game, player_events=player_events)
 
-    #TODO: put this into a config setting in the ini file?
+    # fastest cap "upsert"
+    if game.game_type_cd == 'ctf' and pgstat.fastest_cap is not None:
+        update_fastest_cap(session, pgstat.player_id, game.game_id, 
+                game.map_id, pgstat.fastest_cap)
+
+    # bots don't get weapon stats. sorry, bots!
     if not re.search('^bot#\d+$', player_events['P']):
         create_player_weapon_stats(session=session, 
             player=player, game=game, pgstat=pgstat,
@@ -569,9 +630,10 @@ def stats_submit(request):
                 "----- END REQUEST BODY -----\n\n")
 
         (idfp, status) = verify_request(request)
-        if not idfp:
-            log.debug("ERROR: Unverified request")
-            raise pyramid.httpexceptions.HTTPUnauthorized("Unverified request")
+        if verify_requests(request.registry.settings):
+            if not idfp:
+                log.debug("ERROR: Unverified request")
+                raise pyramid.httpexceptions.HTTPUnauthorized("Unverified request")
 
         (game_meta, players) = parse_body(request)
 
@@ -615,14 +677,19 @@ def stats_submit(request):
 
         gmap = get_or_create_map(session=session, name=game_meta['M'])
 
-        # FIXME: use the gmtime instead of utcnow() when the timezone bug is
-        # fixed
+        # duration is optional
+        if 'D' in game_meta:
+            duration = game_meta['D']
+        else:
+            duration = None
+
         game = create_game(session=session, 
                 start_dt=datetime.datetime.utcnow(),
                 #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, match_id=game_meta['I'])
+                   map_id=gmap.map_id, match_id=game_meta['I'],
+                   duration=duration)
 
         # find or create a record for each player
         # and add stats for each if they were present at the end