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