2 from calendar import timegm
3 from datetime import datetime
5 import sqlalchemy.sql.expression as expr
6 from sqlalchemy.orm import aliased
7 from xonstat.models import DBSession, Server, Map, Game, PlayerGameStat, GameType
8 from xonstat.util import pretty_date, html_colors
10 log = logging.getLogger(__name__)
12 class RecentGame(object):
14 This is a helper class to facilitate showing recent games
15 data within mako. The idea is to take the results of a query
16 and transform it into class members easily accessible later.
17 It is like a namedtuple but a little easier to form.
19 The constructor takes a query row that has been fetched, and
20 it requires the following columns to be present in the row:
22 game_id, game_type_cd, game_type_descr, winner, start_dt,
23 server_id, server_name, map_id, map_name, player_id, nick,
26 The following columns are optional:
30 This class is meant to be used in conjunction with recent_games_q,
31 which will return rows matching this specification.
33 def __init__(self, row):
34 self.game_id = row.game_id
35 self.game_type_cd = row.game_type_cd
36 self.game_type_descr = row.game_type_descr
37 self.winner = row.winner
38 self.start_dt = row.start_dt
39 self.fuzzy_date = pretty_date(row.start_dt)
40 self.epoch = timegm(row.start_dt.timetuple())
41 self.server_id = row.server_id
42 self.server_name = row.server_name
43 self.map_id = row.map_id
44 self.map_name = row.map_name
45 self.player_id = row.player_id
47 self.nick_html_colors = html_colors(row.nick)
52 self.elo_delta = row.elo_delta
58 "game_id" : self.game_id,
59 "game_type_cd" : self.game_type_cd,
60 "winning_team" : self.winner,
61 "fuzzy_dt" : self.fuzzy_date,
63 "server_id" : self.server_id,
64 "server_name" : self.server_name,
65 "map_id" : self.map_id,
66 "map_name" : self.map_name,
67 "player_id" : self.player_id,
72 return "<RecentGame(id=%s, gametype=%s, server=%s, map=%s)>" % (self.game_id, self.game_type_cd, self.server_name, self.map_name)
75 def recent_games_q(server_id=None, map_id=None, player_id=None,
76 game_type_cd=None, cutoff=None, force_player_id=False,
77 start_game_id=None, end_game_id=None, player_id_2=None):
79 Returns a SQLA query of recent game data. Parameters filter
80 the results returned if they are provided. If not, it is
81 assumed that results from all servers and maps is desired.
83 The cutoff parameter provides a way to limit how far back to
84 look when querying. Only games that happened on or after the
85 cutoff (which is a datetime object) will be returned.
87 pgstat_alias = aliased(PlayerGameStat, name='pgstat_alias')
89 recent_games_q = DBSession.query(Game.game_id, GameType.game_type_cd,
90 Game.winner, Game.start_dt, GameType.descr.label('game_type_descr'),
91 Server.server_id, Server.name.label('server_name'), Map.map_id,
92 Map.name.label('map_name'), PlayerGameStat.player_id,
93 PlayerGameStat.nick, PlayerGameStat.rank, PlayerGameStat.team,
94 PlayerGameStat.elo_delta).\
95 filter(Game.server_id==Server.server_id).\
96 filter(Game.map_id==Map.map_id).\
97 filter(Game.game_id==PlayerGameStat.game_id).\
98 filter(Game.game_type_cd==GameType.game_type_cd).\
99 order_by(expr.desc(Game.create_dt))
101 # the various filters provided get tacked on to the query
102 if server_id is not None:
103 recent_games_q = recent_games_q.\
104 filter(Server.server_id==server_id)
106 if map_id is not None:
107 recent_games_q = recent_games_q.\
108 filter(Map.map_id==map_id)
110 # Note: force_player_id makes the pgstat row returned be from the
111 # specified player_id. Otherwise it will just look for a game
112 # *having* that player_id, but returning the #1 player's pgstat row
113 if player_id is not None:
115 recent_games_q = recent_games_q.\
116 filter(PlayerGameStat.player_id==player_id).\
117 filter(Game.players.contains([player_id]))
119 recent_games_q = recent_games_q.\
120 filter(PlayerGameStat.scoreboardpos==1).\
121 filter(Game.game_id==pgstat_alias.game_id).\
122 filter(Game.players.contains([player_id])).\
123 filter(pgstat_alias.player_id==player_id)
125 # supports versus queries
126 if player_id_2 is not None:
127 recent_games_q = recent_games_q.\
128 filter(Game.players.contains([player_id, player_id_2]))
131 recent_games_q = recent_games_q.\
132 filter(PlayerGameStat.scoreboardpos==1)
134 if game_type_cd is not None:
135 recent_games_q = recent_games_q.\
136 filter(Game.game_type_cd==game_type_cd.lower())
138 if cutoff is not None:
139 right_now = datetime.utcnow()
140 recent_games_q = recent_games_q.\
141 filter(expr.between(Game.create_dt, cutoff, right_now))
143 if start_game_id is not None:
144 recent_games_q = recent_games_q.filter(Game.game_id <= start_game_id)
146 if end_game_id is not None:
147 recent_games_q = recent_games_q.filter(Game.game_id >= end_game_id)
149 return recent_games_q