import datetime\r
import logging\r
+import os\r
import pyramid.httpexceptions\r
import re\r
import time\r
\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
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
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
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
\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
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
# 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
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
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
\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
return Response('200 OK')\r
except Exception as e:\r
session.rollback()\r
- raise e\r
+ return e\r