return server
-def get_or_create_map(session=None, name=None):
+def get_or_create_map(session, name):
"""
Find a map by name or create one if not found. Parameters:
session - SQLAlchemy database session factory
name - map name of the map to be found or created
"""
- try:
- # find one by the name, if it exists
- gmap = session.query(Map).filter_by(name=name).one()
- log.debug("Found map id {0}: {1}".format(gmap.map_id,
- gmap.name))
- except NoResultFound, e:
+ maps = session.query(Map).filter_by(name=name).order_by(Map.map_id).all()
+
+ if maps is None or len(maps) == 0:
gmap = Map(name=name)
session.add(gmap)
session.flush()
- log.debug("Created map id {0}: {1}".format(gmap.map_id,
- gmap.name))
- except MultipleResultsFound, e:
- # multiple found, so use the first one but warn
- log.debug(e)
- gmaps = session.query(Map).filter_by(name=name).order_by(
- Map.map_id).all()
- gmap = gmaps[0]
- log.debug("Found map id {0}: {1} but found \
- multiple".format(gmap.map_id, gmap.name))
+ log.debug("Created map id {}: {}".format(gmap.map_id, gmap.name))
+ elif len(maps) == 1:
+ gmap = maps[0]
+ log.debug("Found map id {}: {}".format(gmap.map_id, gmap.name))
+ else:
+ gmap = maps[0]
+ map_id_list = ", ".join(["{}".format(m.map_id) for m in maps])
+ log.warn("Multiple maps found for {} ({})! Using the first one.".format(name, map_id_list))
return gmap
-def create_game(session, start_dt, game_type_cd, server_id, map_id,
- match_id, duration, mod, winner=None):
+def create_game(session, game_type_cd, server_id, map_id, match_id, start_dt, duration, mod,
+ winner=None):
"""
Creates a game. Parameters:
session - SQLAlchemy database session factory
- start_dt - when the game started (datetime object)
game_type_cd - the game type of the game being played
+ mod - mods in use during the game
server_id - server identifier of the server hosting the game
map_id - map on which the game was played
- winner - the team id of the team that won
+ match_id - a unique match ID given by the server
+ start_dt - when the game started (datetime object)
duration - how long the game lasted
- mod - mods in use during the game
+ winner - the team id of the team that won
"""
seq = Sequence('games_game_id_seq')
game_id = session.execute(seq)
- game = Game(game_id=game_id, start_dt=start_dt, game_type_cd=game_type_cd,
- server_id=server_id, map_id=map_id, winner=winner)
+ game = Game(game_id=game_id, start_dt=start_dt, game_type_cd=game_type_cd, server_id=server_id,
+ map_id=map_id, winner=winner)
game.match_id = match_id
game.mod = mod[:64]
# resolved.
game.create_dt = start_dt
- try:
- game.duration = datetime.timedelta(seconds=int(round(float(duration))))
- except:
- pass
+ game.duration = duration
try:
- session.query(Game).filter(Game.server_id==server_id).\
- filter(Game.match_id==match_id).one()
+ 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')
- except NoResultFound, e:
+ # if a game under the same server_id and match_id exists, this is a duplicate
+ msg = "Duplicate game (pre-existing match_id)"
+ log.debug(msg)
+ raise pyramid.httpexceptions.HTTPOk(body=msg, content_type="text/plain")
+
+ except NoResultFound:
# 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))
+ log.debug("Created game id {} on server {}, map {} at {}"
+ .format(game.game_id, server_id, map_id, start_dt))
return game
return pgstat
-def create_game_stat(session, game_meta, game, server, gmap, player, events):
+def create_game_stat(session, game, gmap, player, events):
"""Game stats handler for all game types"""
game_type_cd = game.game_type_cd
return teamstat
-def create_weapon_stats(session, game_meta, game, player, pgstat, events):
+def create_weapon_stats(session, version, game, player, pgstat, events):
"""Weapon stats handler for all game types"""
pwstats = []
# 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...')
"----- END REQUEST BODY -----\n\n")
(idfp, status) = verify_request(request)
- (game_meta, raw_players, raw_teams) = parse_stats_submission(request.body)
- revision = game_meta.get('R', 'unknown')
- duration = game_meta.get('D', None)
+ submission = Submission(request.body, request.headers)
- # only players present at the end of the match are eligible for stats
- raw_players = filter(played_in_game, raw_players)
-
- do_precondition_checks(request, game_meta, raw_players)
-
- # the "duel" gametype is fake
- if len(raw_players) == 2 \
- and num_real_players(raw_players) == 2 \
- and game_meta['G'] == 'dm':
- game_meta['G'] = 'duel'
+ do_precondition_checks(request.registry.settings, submission)
#----------------------------------------------------------------------
# Actual setup (inserts/updates) below here
#----------------------------------------------------------------------
session = DBSession()
- game_type_cd = game_meta['G']
-
# All game types create Game, Server, Map, and Player records
# the same way.
server = get_or_create_server(
- session = session,
- hashkey = idfp,
- name = game_meta['S'],
- revision = revision,
- ip_addr = get_remote_addr(request),
- port = game_meta.get('U', None),
- impure_cvars = game_meta.get('C', 0))
-
- gmap = get_or_create_map(
- session = session,
- name = game_meta['M'])
+ session=session,
+ hashkey=idfp,
+ name=submission.server_name,
+ revision=submission.revision,
+ ip_addr=get_remote_addr(request),
+ port=submission.port_number,
+ impure_cvars=submission.impure_cvar_changes
+ )
+
+ gmap = get_or_create_map(session, submission.map_name)
game = create_game(
- session = session,
- start_dt = datetime.datetime.utcnow(),
- server_id = server.server_id,
- game_type_cd = game_type_cd,
- map_id = gmap.map_id,
- match_id = game_meta['I'],
- duration = duration,
- mod = game_meta.get('O', None))
+ session=session,
+ game_type_cd=submission.game_type_cd,
+ mod=submission.mod,
+ server_id=server.server_id,
+ map_id=gmap.map_id,
+ match_id=submission.match_id,
+ start_dt=datetime.datetime.utcnow(),
+ duration=submission.duration
+ )
# keep track of the players we've seen
player_ids = []
pgstats = []
hashkeys = {}
- for events in raw_players:
- player = get_or_create_player(
- session = session,
- hashkey = events['P'],
- nick = events.get('n', None))
-
- pgstat = create_game_stat(session, game_meta, game, server,
- gmap, player, events)
+ for events in submission.humans + submission.bots:
+ player = get_or_create_player(session, events['P'], events.get('n', None))
+ pgstat = create_game_stat(session, game, gmap, player, events)
pgstats.append(pgstat)
if player.player_id > 1:
- anticheats = create_anticheats(session, pgstat, game, player, events)
+ create_anticheats(session, pgstat, game, player, events)
if player.player_id > 2:
player_ids.append(player.player_id)
hashkeys[player.player_id] = events['P']
- if should_do_weapon_stats(game_type_cd) and player.player_id > 1:
- pwstats = create_weapon_stats(session, game_meta, game, player,
- pgstat, events)
+ if should_do_weapon_stats(submission.game_type_cd) and player.player_id > 1:
+ create_weapon_stats(session, submission.version, game, player, pgstat, events)
# store them on games for easy access
game.players = player_ids
- for events in raw_teams:
- try:
- teamstat = create_team_stat(session, game, events)
- except Exception as e:
- raise e
+ for events in submission.teams:
+ create_team_stat(session, game, events)
- if server.elo_ind and gametype_elo_eligible(game_type_cd):
+ if server.elo_ind and gametype_elo_eligible(submission.game_type_cd):
ep = EloProcessor(session, game, pgstats)
ep.save(session)
log.debug('Success! Stats recorded.')
# ranks are fetched after we've done the "real" processing
- ranks = get_ranks(session, player_ids, game_type_cd)
+ ranks = get_ranks(session, player_ids, submission.game_type_cd)
# plain text response
request.response.content_type = 'text/plain'
return {
- "now" : calendar.timegm(datetime.datetime.utcnow().timetuple()),
- "server" : server,
- "game" : game,
- "gmap" : gmap,
- "player_ids" : player_ids,
- "hashkeys" : hashkeys,
- "elos" : ep.wip,
- "ranks" : ranks,
+ "now": calendar.timegm(datetime.datetime.utcnow().timetuple()),
+ "server": server,
+ "game": game,
+ "gmap": gmap,
+ "player_ids": player_ids,
+ "hashkeys": hashkeys,
+ "elos": ep.wip,
+ "ranks": ranks,
}
except Exception as e: