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:
114 print("in the player_id block")
116 print("forced player")
117 recent_games_q = recent_games_q.\
118 filter(PlayerGameStat.player_id==player_id).\
119 filter(Game.players.contains([player_id]))
121 print("in the alias block")
122 recent_games_q = recent_games_q.\
123 filter(PlayerGameStat.scoreboardpos==1).\
124 filter(Game.game_id==pgstat_alias.game_id).\
125 filter(Game.players.contains([player_id])).\
126 filter(pgstat_alias.player_id==player_id)
128 # supports versus queries
129 if player_id_2 is not None:
130 recent_games_q = recent_games_q.\
131 filter(Game.players.contains([player_id, player_id_2]))
134 recent_games_q = recent_games_q.\
135 filter(PlayerGameStat.scoreboardpos==1)
137 if game_type_cd is not None:
138 recent_games_q = recent_games_q.\
139 filter(Game.game_type_cd==game_type_cd.lower())
141 if cutoff is not None:
142 right_now = datetime.utcnow()
143 recent_games_q = recent_games_q.\
144 filter(expr.between(Game.create_dt, cutoff, right_now))
146 if start_game_id is not None:
147 recent_games_q = recent_games_q.filter(Game.game_id <= start_game_id)
149 if end_game_id is not None:
150 recent_games_q = recent_games_q.filter(Game.game_id >= end_game_id)
152 return recent_games_q