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
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
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')
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
# 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)
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:
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:
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)
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
"""
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):
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")
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")
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))
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.')
log.debug('Success! Stats recorded.')
return Response('200 OK')
except Exception as e:
- session.rollback()
+ if session:
+ session.rollback()
return e