]> de.git.xonotic.org Git - xonotic/xonstat.git/blobdiff - xonstat/views/submission.py
Do not use x-server-ip.
[xonotic/xonstat.git] / xonstat / views / submission.py
index e0048d6d2d23cde93bfb42d261f926a999577499..66dcd1107dc8ca57a30d683ea7eaa616680f85aa 100755 (executable)
@@ -1,5 +1,6 @@
 import datetime\r
 import logging\r
+import os\r
 import pyramid.httpexceptions\r
 import re\r
 import time\r
@@ -14,8 +15,8 @@ log = logging.getLogger(__name__)
 \r
 def get_remote_addr(request):\r
     """Get the Xonotic server's IP address"""\r
-    if 'X-Server-IP' in request.headers:\r
-        return request.headers['X-Server-IP']\r
+    if 'X-Forwarded-For' in request.headers:\r
+        return request.headers['X-Forwarded-For']\r
     else:\r
         return request.remote_addr\r
 \r
@@ -45,6 +46,20 @@ def verify_request(request):
     return (idfp, status)\r
 \r
 \r
+def num_real_players(player_events):\r
+    """\r
+    Returns the number of real players (those who played \r
+    and are on the scoreboard).\r
+    """\r
+    real_players = 0\r
+\r
+    for events in player_events:\r
+        if is_real_player(events):\r
+            real_players += 1\r
+\r
+    return real_players\r
+\r
+\r
 def has_minimum_real_players(settings, player_events):\r
     """\r
     Determines if the collection of player events has enough "real" players\r
@@ -59,10 +74,7 @@ def has_minimum_real_players(settings, player_events):
     except:\r
         minimum_required_players = 2\r
 \r
-    real_players = 0\r
-    for events in player_events:\r
-        if is_real_player(events):\r
-            real_players += 1\r
+    real_players = num_real_players(player_events)\r
 \r
     #TODO: put this into a config setting in the ini file?\r
     if real_players < minimum_required_players:\r
@@ -81,6 +93,7 @@ def has_required_metadata(metadata):
     if 'T' not in metadata or\\r
         'G' not in metadata or\\r
         'M' not in metadata or\\r
+        'I' not in metadata or\\r
         'S' not in metadata:\r
             flg_has_req_metadata = False\r
 \r
@@ -215,7 +228,7 @@ def get_or_create_map(session=None, name=None):
 \r
 \r
 def create_game(session=None, start_dt=None, game_type_cd=None, \r
-        server_id=None, map_id=None, winner=None):\r
+        server_id=None, map_id=None, winner=None, match_id=None):\r
     """\r
     Creates a game. Parameters:\r
 \r
@@ -230,10 +243,20 @@ def create_game(session=None, start_dt=None, game_type_cd=None,
     game_id = session.execute(seq)\r
     game = Game(game_id=game_id, start_dt=start_dt, game_type_cd=game_type_cd,\r
                 server_id=server_id, map_id=map_id, winner=winner)\r
-    session.add(game)\r
-    log.debug("Created game id {0} on server {1}, map {2} at \\r
-            {3}".format(game.game_id, \r
-                server_id, map_id, start_dt))\r
+    game.match_id = match_id\r
+\r
+    try:\r
+        session.query(Game).filter(Game.server_id==server_id).\\r
+                filter(Game.match_id==match_id).one()\r
+        # if a game under the same server and match_id found, \r
+        # this is a duplicate game and can be ignored\r
+        raise pyramid.httpexceptions.HTTPOk\r
+    except NoResultFound, e:\r
+        # server_id/match_id combination not found. game is ok to insert\r
+        session.add(game)\r
+        log.debug("Created game id {0} on server {1}, map {2} at \\r
+                {3}".format(game.game_id, \r
+                    server_id, map_id, start_dt))\r
 \r
     return game\r
 \r
@@ -313,7 +336,7 @@ def create_player_game_stat(session=None, player=None,
     # all games have a score\r
     pgstat.score = 0\r
 \r
-    if game.game_type_cd == 'dm':\r
+    if game.game_type_cd == 'dm' or game.game_type_cd == 'tdm' or game.game_type_cd == 'duel':\r
         pgstat.kills = 0\r
         pgstat.deaths = 0\r
         pgstat.suicides = 0\r
@@ -346,6 +369,9 @@ def create_player_game_stat(session=None, player=None,
     if pgstat.nick == None:\r
         pgstat.nick = player.nick\r
 \r
+    # whichever nick we ended up with, strip it and store as the stripped_nick\r
+    pgstat.stripped_nick = qfont_decode(strip_colors(pgstat.nick))\r
+\r
     # if the nick we end up with is different from the one in the\r
     # player record, change the nick to reflect the new value\r
     if pgstat.nick != player.nick and player.player_id > 2:\r
@@ -437,7 +463,7 @@ def parse_body(request):
             if key in 'S' 'n':\r
                 value = unicode(value, 'utf-8')\r
 \r
-            if key in 'V' 'T' 'G' 'M' 'S' 'C' 'R' 'W':\r
+            if key in 'V' 'T' 'G' 'M' 'S' 'C' 'R' 'W' 'I':\r
                 game_meta[key] = value\r
 \r
             if key == 'P':\r
@@ -494,39 +520,43 @@ def stats_submit(request):
 \r
         (idfp, status) = verify_request(request)\r
         if not idfp:\r
-            raise pyramid.httpexceptions.HTTPUnauthorized\r
-\r
-        log.debug('Remote address:')\r
-        log.debug(get_remote_addr(request))\r
+            log.debug("ERROR: Unverified request")\r
+            raise pyramid.httpexceptions.HTTPUnauthorized("Unverified request")\r
 \r
         (game_meta, players) = parse_body(request)  \r
 \r
         if not has_required_metadata(game_meta):\r
-            log.debug("Required game meta fields missing. "\\r
-                    "Can't continue.")\r
-            raise pyramid.exceptions.HTTPUnprocessableEntity\r
+            log.debug("ERROR: Required game meta missing")\r
+            raise pyramid.exceptions.HTTPUnprocessableEntity("Missing game meta")\r
 \r
         if not is_supported_gametype(game_meta['G']):\r
-            raise pyramid.httpexceptions.HTTPOk\r
+            log.debug("ERROR: Unsupported gametype")\r
+            raise pyramid.httpexceptions.HTTPOk("OK")\r
 \r
         if not has_minimum_real_players(request.registry.settings, players):\r
-            log.debug("The number of real players is below the minimum. " + \r
-                "Stats will be ignored.")\r
-            raise pyramid.httpexceptions.HTTPOk\r
+            log.debug("ERROR: Not enough real players")\r
+            raise pyramid.httpexceptions.HTTPOk("OK")\r
+\r
+        # FIXME: if we have two players and game type is 'dm',\r
+        # change this into a 'duel' gametype. This should be\r
+        # removed when the stats actually send 'duel' instead of 'dm'\r
+        if num_real_players(players) == 2 and game_meta['G'] == 'dm':\r
+            game_meta['G'] = 'duel'\r
 \r
         server = get_or_create_server(session=session, hashkey=idfp, \r
                 name=game_meta['S'], revision=game_meta['R'],\r
                 ip_addr=get_remote_addr(request))\r
 \r
         gmap = get_or_create_map(session=session, name=game_meta['M'])\r
-        log.debug(gmap)\r
 \r
+        # FIXME: use the gmtime instead of utcnow() when the timezone bug is\r
+        # fixed\r
         game = create_game(session=session, \r
-                start_dt=datetime.datetime(\r
-                    *time.gmtime(float(game_meta['T']))[:6]), \r
+                start_dt=datetime.datetime.utcnow(),\r
+                #start_dt=datetime.datetime(\r
+                    #*time.gmtime(float(game_meta['T']))[:6]), \r
                 server_id=server.server_id, game_type_cd=game_meta['G'], \r
-                   map_id=gmap.map_id)\r
-        log.debug(gmap)\r
+                   map_id=gmap.map_id, match_id=game_meta['I'])\r
 \r
         # find or create a record for each player\r
         # and add stats for each if they were present at the end\r
@@ -550,4 +580,4 @@ def stats_submit(request):
         return Response('200 OK')\r
     except Exception as e:\r
         session.rollback()\r
-        raise e\r
+        return e\r