config.add_view(player_elo_info_json, route_name="player_elo_info_json", renderer="jsonp")
config.add_route("player_accuracy", "/player/{id:\d+}/accuracy")
- config.add_route("player_accuracy_json", "/player/{id:\d+}/accuracy.json")
+ #config.add_route("player_accuracy_json", "/player/{id:\d+}/accuracy.json")
config.add_view(player_accuracy_json, route_name="player_accuracy", renderer="jsonp")
- config.add_view(player_accuracy_json, route_name="player_accuracy_json", renderer="jsonp")
+ #config.add_view(player_accuracy_json, route_name="player_accuracy_json", renderer="jsonp")
config.add_route("player_index", "/players")
config.add_route("player_index_json", "/players.json")
config.add_view(player_index_json, route_name="player_index_json", renderer="jsonp")
config.add_route("player_damage", "/player/{id:\d+}/damage")
- config.add_view(player_damage_json, route_name="player_damage",
- renderer="json")
+ config.add_view(player_damage_json, route_name="player_damage", renderer="jsonp")
+
+ config.add_route("player_captimes", "/player/{id:\d+}/captimes")
+ config.add_route("player_captimes_json", "/player/{id:\d+}/captimes.json")
+ config.add_view(player_captimes, route_name="player_captimes", renderer="player_captimes.mako")
+ config.add_view(player_captimes_json, route_name="player_captimes_json", renderer="jsonp")
# GAME ROUTES
config.add_route("game_index", "/games")
config.add_view(map_info, route_name="map_info", renderer="map_info.mako")
config.add_view(map_info_json, route_name="map_info_json", renderer="jsonp")
+ config.add_route("map_captimes", "/map/{id:\d+}/captimes")
+ config.add_route("map_captimes_json", "/map/{id:\d+}/captimes.json")
+ config.add_view(map_captimes, route_name="map_captimes", renderer="map_captimes.mako")
+ config.add_view(map_captimes_json, route_name="map_captimes_json", renderer="jsonp")
+
# SEARCH ROUTES
config.add_route("search", "search")
config.add_route("search_json", "search.json")
# we look for players who have activity within the past DELTA hours
DELTA = 6
+VERBOSE = False
+
+INIFILE = None # keep this set to "None"
# classic skin WITHOUT NAME - writes PNGs into "output//###.png"
skin_classic = Skin( "",
# more fancy skin [** WIP **]- writes PNGs into "output/archer/###.png"
skin_archer = Skin( "archer",
- bg = "background_archer-v1",
- overlay = None,
+ #bg = "background_archer-v2_full",
+ bg = "background_archer-v3",
+ overlay = "",
+ nick_maxwidth = 265,
+ gametype_pos = (91,33),
+ nostats_pos = (91,59),
+ elo_pos = (91,47),
+ rank_pos = (91,58),
+ winp_pos = (509,20),
+ wins_pos = (508,35),
+ loss_pos = (508,45),
+ kdr_pos = (392,20),
+ kills_pos = (392,35),
+ deaths_pos = (392,45),
+ ptime_color = (0.05, 0.05, 0.1),
)
# minimal skin - writes PNGs into "output/minimal/###.png"
nick_fontsize = 16,
nick_pos = (36,16),
num_gametypes = 3,
- nick_maxwidth = 300,
+ nick_maxwidth = 280,
gametype_pos = (70,30),
gametype_color = (0.0, 0.0, 0.0),
gametype_text = "%s:",
DELTA = 2**24 # large enough to enforce update, and doesn't result in errors
elif arg == "test":
NUM_PLAYERS = 100
+ elif arg == "verbose":
+ VERBOSE = True
else:
- print """Usage: gen_badges.py [options] [skin list]
+ print """Usage: gen_badges.py [options] <ini-file> [skin list]
Options:
-force Force updating all badges (delta = 2^24)
-test Limit number of players to 100 (for testing)
+ -verbose Show more verbose output
-help Show this help text
+ Ini-File:
+ Name of a Pyramid ini-file to use (e.g. prodution.ini or development.ini).
Skin list:
Space-separated list of skins to use when creating badges.
Available skins: classic, minimal, archer
"""
sys.exit(-1)
else:
- if arg == "classic":
- skins.append(skin_classic)
- elif arg == "minimal":
- skins.append(skin_minimal)
- elif arg == "archer":
- skins.append(skin_archer)
+ if INIFILE == None:
+ INIFILE = arg
+ else:
+ if arg == "classic":
+ skins.append(skin_classic)
+ elif arg == "minimal":
+ skins.append(skin_minimal)
+ elif arg == "archer":
+ skins.append(skin_archer)
if len(skins) == 0:
- skins = [ skin_classic, skin_minimal ]
+ skins = [ skin_classic, skin_minimal, skin_archer ]
+
+if not INIFILE:
+ print "You must provide the name of an ini-file to use! Type 'gen_badges.py -h' for help."
+ sys.exit(-1)
# environment setup
-env = bootstrap('../../../development.ini')
+env = bootstrap(INIFILE)
req = env['request']
req.matchdict = {'id':3}
filter(Player.active_ind == True).\
all()
-playerdata = PlayerData()
+playerdata = PlayerData
if len(players) > 0:
stop = datetime.now()
sstart = datetime.now()
for sk in skins:
- sk.render_image(playerdata, "output/%s/%d.png" % (str(sk), player_id[0]))
+ sk.render_image(playerdata.data, "output/%s/%d.png" % (str(sk), player_id[0]))
sstop = datetime.now()
td = sstop-sstart
render_time += datetime_seconds(td)
+ if VERBOSE == True:
+ print player_id, unicode(playerdata.data['player'].nick)
+
stop = datetime.now()
td = stop-start
total_seconds = datetime_seconds(td)
import sqlalchemy as sa
import sqlalchemy.sql.functions as func
from xonstat.models import *
+from xonstat.views.player import get_games_played, get_overall_stats, get_ranks, get_elos
class PlayerData:
return self.data[key]
return None
+ @classmethod
def get_data(self, player_id):
"""Return player data as dict.
# total games
# wins/losses
# kills/deaths
+
# duel/dm/tdm/ctf elo + rank
+ player = DBSession.query(Player).filter_by(player_id=player_id).\
+ filter(Player.active_ind == True).one()
+ games_played = get_games_played(player_id)
+ overall_stats = get_overall_stats(player_id)
+ ranks = get_ranks(player_id)
+ elos = get_elos(player_id)
- player = DBSession.query(Player).filter(Player.player_id == player_id).one()
-
- games_played = DBSession.query(
- Game.game_type_cd, func.count(), func.sum(PlayerGameStat.alivetime)).\
- filter(Game.game_id == PlayerGameStat.game_id).\
- filter(PlayerGameStat.player_id == player_id).\
- group_by(Game.game_type_cd).\
- order_by(func.count().desc()).\
- all()
-
- total_stats = {}
- total_stats['games'] = 0
- total_stats['games_breakdown'] = {} # this is a dictionary inside a dictionary .. dictception?
- total_stats['games_alivetime'] = {}
- total_stats['gametypes'] = []
- for (game_type_cd, games, alivetime) in games_played:
- total_stats['games'] += games
- total_stats['gametypes'].append(game_type_cd)
- total_stats['games_breakdown'][game_type_cd] = games
- total_stats['games_alivetime'][game_type_cd] = alivetime
-
- (total_stats['kills'], total_stats['deaths'], total_stats['alivetime'],) = DBSession.query(
- func.sum(PlayerGameStat.kills),
- func.sum(PlayerGameStat.deaths),
- func.sum(PlayerGameStat.alivetime)).\
- filter(PlayerGameStat.player_id == player_id).\
- one()
-
- (total_stats['wins'], total_stats['losses']) = DBSession.\
- query("wins", "losses").\
- from_statement(
- "SELECT SUM(win) wins, SUM(loss) losses "
- "FROM (SELECT g.game_id, "
- " CASE "
- " WHEN g.winner = pgs.team THEN 1 "
- " WHEN pgs.rank = 1 THEN 1 "
- " ELSE 0 "
- " END win, "
- " CASE "
- " WHEN g.winner = pgs.team THEN 0 "
- " WHEN pgs.rank = 1 THEN 0 "
- " ELSE 1 "
- " END loss "
- " FROM games g, "
- " player_game_stats pgs "
- " WHERE g.game_id = pgs.game_id "
- " AND pgs.player_id = :player_id) win_loss").\
- params(player_id=player_id).one()
-
- ranks = DBSession.query("game_type_cd", "rank", "max_rank").\
- from_statement(
- "SELECT pr.game_type_cd, pr.rank, overall.max_rank "
- "FROM player_ranks pr, "
- " (SELECT game_type_cd, max(rank) max_rank "
- " FROM player_ranks "
- " GROUP BY game_type_cd) overall "
- "WHERE pr.game_type_cd = overall.game_type_cd "
- " AND player_id = :player_id "
- "ORDER BY rank").\
- params(player_id=player_id).all()
+ games_played_dict = {}
+ for game in games_played:
+ games_played_dict[game.game_type_cd] = game
ranks_dict = {}
- for gtc,rank,max_rank in ranks:
- ranks_dict[gtc] = (rank, max_rank)
-
- elos = DBSession.query(PlayerElo).\
- filter_by(player_id=player_id).\
- order_by(PlayerElo.elo.desc()).\
- all()
+ for gt,rank in ranks.items():
+ ranks_dict[gt] = (rank.rank, rank.max_rank)
elos_dict = {}
- for elo in elos:
+ for gt,elo in elos.items():
if elo.games >= 32:
- elos_dict[elo.game_type_cd] = elo.elo
+ elos_dict[gt] = elo.elo
self.data = {
'player':player,
- 'total_stats':total_stats,
+ 'games_played':games_played_dict,
+ 'overall_stats':overall_stats,
'ranks':ranks_dict,
'elos':elos_dict,
}
+
'width': 560,
'height': 70,
'nick_fontsize': 20,
- 'nick_pos': (56,18),
- 'nick_maxwidth': 280,
+ 'nick_pos': (52,18),
+ 'nick_maxwidth': 270,
'gametype_fontsize':10,
'gametype_pos': (101,33),
'gametype_width': 94,
'ptime_text': "Playing Time: %s",
'ptime_align': 0,
}
-
+
for k,v in params.items():
if self.params.has_key(k):
self.params[k] = v
# setup variables
- player = data.player
- elos = data.elos
- ranks = data.ranks
- #games = data.total_stats['games']
- wins, losses = data.total_stats['wins'], data.total_stats['losses']
- games = wins + losses
- kills, deaths = data.total_stats['kills'], data.total_stats['deaths']
- alivetime = data.total_stats['alivetime']
+ player = data['player']
+ elos = data['elos']
+ ranks = data['ranks']
+ games_played = data['games_played']['overall']
+ overall_stats = data['overall_stats']['overall']
+
+ wins, losses, win_pct = games_played.wins, games_played.losses, games_played.win_pct
+ games = games_played.games
+ kills, deaths, kd_ratio = overall_stats.total_kills, overall_stats.total_deaths, overall_stats.k_d_ratio
+ alivetime = overall_stats.total_playing_time
+
+ # make sorted list of gametypes
+ game_types = []
+ num_games = 0
+ for gt,info in data['games_played'].items():
+ if gt == "overall":
+ continue
+ if info.games > num_games:
+ game_types.insert(0, gt)
+ else:
+ game_types.append(gt)
+
# build image
ctx = C.Context(surf)
self.ctx = ctx
ctx.set_antialias(C.ANTIALIAS_GRAY)
-
+
# draw background
if self.bg == None:
if self.bgcolor != None:
try:
# background texture
bg = C.ImageSurface.create_from_png("img/%s.png" % self.bg)
-
+
# tile image
if bg:
bg_w, bg_h = bg.get_width(), bg.get_height()
## draw player's nickname with fancy colors
-
+
# deocde nick, strip all weird-looking characters
qstr = qfont_decode(player.nick).replace('^^', '^').replace(u'\x00', '')
- chars = []
- for c in qstr:
- # replace weird characters that make problems - TODO
- if ord(c) < 128:
- chars.append(c)
- qstr = ''.join(chars)
+ #chars = []
+ #for c in qstr:
+ # # replace weird characters that make problems - TODO
+ # if ord(c) < 128:
+ # chars.append(c)
+ #qstr = ''.join(chars)
stripped_nick = strip_colors(qstr.replace(' ', '_'))
-
+
# fontsize is reduced if width gets too large
ctx.select_font_face(self.font, C.FONT_SLANT_NORMAL, C.FONT_WEIGHT_NORMAL)
shrinknick = 0
break
# determine width of single whitespace for later use
- xoff, yoff, tw, th = ctx.text_extents("_")[:4]
+ xoff, yoff, tw, th = ctx.text_extents("_ _")[:4]
space_w = tw
+ xoff, yoff, tw, th = ctx.text_extents("__")[:4]
+ space_w -= tw
+
+ # this hilarious code should determine the spacing between characters
+ sep_w = 0.25*space_w
+ if sep_w <= 0:
+ sep_w = 1
# split nick into colored segments
xoffset = 0
txt = parts[1]
del parts[1]
del parts[0]
-
+
if not txt or len(txt) == 0:
# only colorcode and no real text, skip this
continue
-
+
if tag:
if tag.startswith('x'):
r = int(tag[1] * 2, 16) / 255.0
xoff, yoff, tw, th = ctx.text_extents(txt)[:4]
ctx.set_source_rgb(r, g, b)
ctx.move_to(self.nick_pos[0] + xoffset - xoff, self.nick_pos[1])
- ctx.show_text(txt)
+ ctx.show_text(txt.encode("utf-8"))
tw += (len(txt)-len(txt.strip())) * space_w # account for lost whitespaces
- xoffset += tw + 2
+ xoffset += tw + sep_w
## print elos and ranks
-
+
xoffset, yoffset = 0, 0
count = 0
- for gt in data.total_stats['gametypes'][:self.num_gametypes]:
+ for gt in game_types[:self.num_gametypes]:
if not elos.has_key(gt) or not ranks.has_key(gt):
continue
count += 1
-
+
# re-align segments if less than max. gametypes are shown
if count > 0:
if count < self.num_gametypes:
else:
xoffset += 0.5 * diff * self.gametype_width
yoffset += 0.5 * diff * self.gametype_height
-
+
# show a number gametypes the player has participated in
- for gt in data.total_stats['gametypes'][:self.num_gametypes]:
+ for gt in game_types[:self.num_gametypes]:
if not elos.has_key(gt) or not ranks.has_key(gt):
continue
txt = "???"
try:
- ratio = float(wins)/games
- txt = "%.2f%%" % round(ratio * 100, 2)
+ txt = "%.2f%%" % round(win_pct * 100, 2)
except:
- ratio = 0
-
+ win_pct = 0
+
if self.winp_pos:
- if ratio >= 0.5:
- nr = 2*(ratio-0.5)
+ if win_pct >= 0.5:
+ nr = 2*(win_pct-0.5)
r = nr*self.winp_colortop[0] + (1-nr)*self.winp_colormid[0]
g = nr*self.winp_colortop[1] + (1-nr)*self.winp_colormid[1]
b = nr*self.winp_colortop[2] + (1-nr)*self.winp_colormid[2]
else:
- nr = 2*ratio
+ nr = 2*win_pct
r = nr*self.winp_colormid[0] + (1-nr)*self.winp_colorbot[0]
g = nr*self.winp_colormid[1] + (1-nr)*self.winp_colorbot[1]
b = nr*self.winp_colormid[2] + (1-nr)*self.winp_colorbot[2]
txt = self.kdtext_text
self.set_font(self.kdtext_fontsize, self.kdtext_color)
self.show_text(txt, self.kdtext_pos, self.kdtext_align)
-
+
txt = "???"
try:
- ratio = float(kills)/deaths
- txt = "%.3f" % round(ratio, 3)
+ txt = "%.3f" % round(kd_ratio, 3)
except:
- ratio = 0
+ kd_ratio = 0
if self.kdr_pos:
- if ratio >= 1.0:
- nr = ratio-1.0
+ if kd_ratio >= 1.0:
+ nr = kd_ratio-1.0
if nr > 1:
nr = 1
r = nr*self.kdr_colortop[0] + (1-nr)*self.kdr_colormid[0]
g = nr*self.kdr_colortop[1] + (1-nr)*self.kdr_colormid[1]
b = nr*self.kdr_colortop[2] + (1-nr)*self.kdr_colormid[2]
else:
- nr = ratio
+ nr = kd_ratio
r = nr*self.kdr_colormid[0] + (1-nr)*self.kdr_colorbot[0]
g = nr*self.kdr_colormid[1] + (1-nr)*self.kdr_colorbot[1]
b = nr*self.kdr_colormid[2] + (1-nr)*self.kdr_colorbot[2]
--- /dev/null
+<%inherit file="base.mako"/>
+<%namespace name="nav" file="nav.mako" />
+
+<%block name="title">
+Map captimes
+</%block>
+
+
+<div class="row">
+ <div class="span12">
+
+ <h2>${map.name}</h2>
+ <p><a href="${map_url}">Back to map info page</a></p>
+
+ <h3>Fastest flag capture times:</h3>
+
+ <table class="table table-bordered table-condensed">
+ <thead>
+ <tr>
+ <th>Game</th>
+ <th>Captime</th>
+ <th>Nick</th>
+ <th>Server</th>
+ <th>Date</th>
+ </tr>
+ </thead>
+ <tbody>
+ % for ct in captimes:
+ <tr>
+ <td class="tdcenter"><a class="btn btn-primary btn-small" href="${request.route_url('game_info', id=ct.game_id)}" title="View detailed information about this game">view</a></td>
+ <td>${ct.fastest_cap.total_seconds()} seconds</td>
+ <td><span class="nick">${ct.player_nick_html|n}</span></td>
+ <td><a href="${request.route_url('server_info', id=ct.server_id)}" title="Go to the detail page for this server">${ct.server_name}</a></td>
+ <td><span class="abstime" data-epoch="${ct.create_dt_epoch}" title="${ct.create_dt.strftime('%a, %d %b %Y %H:%M:%S UTC')}">${ct.create_dt_fuzzy}</span></td>
+ % endfor
+ </tbody>
+ </table>
+
+ </div>
+</div>
--- /dev/null
+<%inherit file="base.mako"/>
+<%namespace name="nav" file="nav.mako" />
+
+<%block name="title">
+Player captimes
+</%block>
+
+<div class="row">
+ <div class="span12">
+
+ <h2><span class="nick">${player.nick_html_colors()|n}</span></h2>
+ <p><a href="${player_url}">Back to player info page</a></p>
+
+ <h3>Fastest flag capture times:</h3>
+
+ <table class="table table-bordered table-condensed">
+ <thead>
+ <tr>
+ <th>Game</th>
+ <th>Captime</th>
+ ##<th>Nick</th>
+ <th>Map</th>
+ <th>Server</th>
+ <th>Date</th>
+ </tr>
+ </thead>
+ <tbody>
+ % for ct in captimes:
+ <tr>
+ <td class="tdcenter"><a class="btn btn-primary btn-small" href="${request.route_url('game_info', id=ct.game_id)}" title="View detailed information about this game">view</a></td>
+ <td>${ct.fastest_cap.total_seconds()} seconds</td>
+ ##<td><span class="nick">${ct.html_nick|n}</span></td>
+ <td><a href="${request.route_url('map_info', id=ct.map_id)}" title="Go to the detail page for this map">${ct.map_name}</a></td>
+ <td><a href="${request.route_url('server_info', id=ct.server_id)}" title="Go to the detail page for this server">${ct.server_name}</a></td>
+ <td><span class="abstime" data-epoch="${ct.create_dt_epoch}" title="${ct.create_dt.strftime('%a, %d %b %Y %H:%M:%S UTC')}">${ct.create_dt_fuzzy}</span></td>
+ % endfor
+ </tbody>
+ </table>
+
+ </div>
+</div>
from xonstat.views.player import player_game_index_json, player_accuracy_json
from xonstat.views.player import player_damage_json, player_hashkey_info_json
from xonstat.views.player import player_hashkey_info_text, player_elo_info_json
+from xonstat.views.player import player_captimes, player_captimes_json
from xonstat.views.game import game_index, game_info, rank_index
from xonstat.views.game import game_index_json, game_info_json, rank_index_json
from xonstat.views.map import map_info, map_index
from xonstat.views.map import map_info_json, map_index_json
+from xonstat.views.map import map_captimes, map_captimes_json
from xonstat.views.server import server_info, server_game_index, server_index
from xonstat.views.server import server_info_json, server_game_index_json
def map_index_json(request):
"""
- Provides a JSON-serialized list of all the current maps.
+ Provides a JSON-serialized list of all the current maps.
"""
view_data = _map_index_data(request)
def _map_info_data(request):
map_id = request.matchdict['id']
- try:
+ try:
leaderboard_lifetime = int(
request.registry.settings['xonstat.leaderboard_lifetime'])
except:
filter(Game.game_id == PlayerGameStat.game_id).\
filter(Game.map_id == map_id).\
filter(Player.player_id > 2).\
- filter(PlayerGameStat.create_dt >
+ filter(PlayerGameStat.create_dt >
(datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\
order_by(expr.desc(func.sum(PlayerGameStat.score))).\
group_by(Player.nick).\
for (player_id, nick, score) in top_scorers]
# top players by playing time
- top_players = DBSession.query(Player.player_id, Player.nick,
+ top_players = DBSession.query(Player.player_id, Player.nick,
func.sum(PlayerGameStat.alivetime)).\
filter(Player.player_id == PlayerGameStat.player_id).\
filter(Game.game_id == PlayerGameStat.game_id).\
filter(Game.map_id == map_id).\
filter(Player.player_id > 2).\
- filter(PlayerGameStat.create_dt >
+ filter(PlayerGameStat.create_dt >
(datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\
order_by(expr.desc(func.sum(PlayerGameStat.alivetime))).\
group_by(Player.nick).\
for (player_id, nick, score) in top_players]
# top servers using/playing this map
- top_servers = DBSession.query(Server.server_id, Server.name,
+ top_servers = DBSession.query(Server.server_id, Server.name,
func.count(Game.game_id)).\
filter(Game.server_id == Server.server_id).\
filter(Game.map_id == map_id).\
- filter(Game.create_dt >
+ filter(Game.create_dt >
(datetime.utcnow() - timedelta(days=leaderboard_lifetime))).\
order_by(expr.desc(func.count(Game.game_id))).\
group_by(Server.name).\
List the information stored about a given map. JSON.
"""
return [{'status':'not implemented'}]
+
+
+def map_captimes_data(request):
+ map_id = int(request.matchdict['id'])
+
+ MapCaptimes = namedtuple('PlayerCaptimes', ['fastest_cap', 'create_dt', 'create_dt_epoch', 'create_dt_fuzzy',
+ 'player_id', 'player_nick', 'player_nick_stripped', 'player_nick_html',
+ 'game_id', 'server_id', 'server_name'])
+
+ dbquery = DBSession.query('fastest_cap', 'create_dt', 'player_id', 'game_id',
+ 'server_id', 'server_name', 'player_nick').\
+ from_statement(
+ "SELECT ct.fastest_cap, "
+ "ct.create_dt, "
+ "ct.player_id, "
+ "ct.game_id, "
+ "g.server_id, "
+ "s.name server_name, "
+ "pgs.nick player_nick "
+ "FROM player_map_captimes ct, "
+ "games g, "
+ "maps m, "
+ "servers s, "
+ "player_game_stats pgs "
+ "WHERE ct.map_id = :map_id "
+ "AND g.game_id = ct.game_id "
+ "AND g.server_id = s.server_id "
+ "AND m.map_id = ct.map_id "
+ "AND pgs.player_id = ct.player_id "
+ "AND pgs.game_id = ct.game_id "
+ "ORDER BY ct.fastest_cap "
+ ).params(map_id=map_id).all()
+
+ mmap = DBSession.query(Map).filter_by(map_id=map_id).one()
+
+ map_captimes = []
+ for row in dbquery:
+ map_captimes.append(MapCaptimes(
+ fastest_cap=row.fastest_cap,
+ create_dt=row.create_dt,
+ create_dt_epoch=timegm(row.create_dt.timetuple()),
+ create_dt_fuzzy=pretty_date(row.create_dt),
+ player_id=row.player_id,
+ player_nick=row.player_nick,
+ player_nick_stripped=strip_colors(row.player_nick),
+ player_nick_html=html_colors(row.player_nick),
+ game_id=row.game_id,
+ server_id=row.server_id,
+ server_name=row.server_name,
+ ))
+
+ return {
+ 'captimes':map_captimes,
+ 'map_id':map_id,
+ 'map_url':request.route_url('map_info', id=map_id),
+ 'map':mmap,
+ }
+
+def map_captimes(request):
+ return map_captimes_data(request)
+
+def map_captimes_json(request):
+ return map_captimes_data(request)
from sqlalchemy import desc, distinct
from webhelpers.paginate import Page, PageURL
from xonstat.models import *
-from xonstat.util import page_url, to_json, pretty_date, datetime_seconds
+from xonstat.util import page_url, to_json, pretty_date, datetime_seconds, html_colors
from xonstat.views.helpers import RecentGame, recent_games_q
log = logging.getLogger(__name__)
map_id=row.map_id,
times_played=row.times_played,
game_type_cd=row.game_type_cd)
-
+
# if we aren't given a favorite game_type_cd
# then the overall favorite is the one we've
# played the most
The key to the dictionary is the game type code. There is also an
"overall" game_type_cd which is the overall best rank.
- """
+ """
Rank = namedtuple('Rank', ['rank', 'max_rank', 'percentile', 'game_type_cd'])
raw_ranks = DBSession.query("game_type_cd", "rank", "max_rank").\
# Determine the raw accuracy (hit, fired) numbers for $games games
# This is then enumerated to create parameters for a flot graph
- raw_accs = DBSession.query(PlayerWeaponStat.game_id,
+ raw_accs = DBSession.query(PlayerWeaponStat.game_id,
PlayerWeaponStat.hit, PlayerWeaponStat.fired).\
filter(PlayerWeaponStat.player_id == player_id).\
filter(PlayerWeaponStat.weapon_cd == weapon_cd).\
# Determine the damage efficiency (hit, fired) numbers for $games games
# This is then enumerated to create parameters for a flot graph
- raw_dmgs = DBSession.query(PlayerWeaponStat.game_id,
+ raw_dmgs = DBSession.query(PlayerWeaponStat.game_id,
PlayerWeaponStat.actual, PlayerWeaponStat.hit).\
filter(PlayerWeaponStat.player_id == player_id).\
filter(PlayerWeaponStat.weapon_cd == weapon_cd).\
"""
# All player_info fields are converted into JSON-formattable dictionaries
- player_info = player_info_data(request)
+ player_info = player_info_data(request)
player = player_info['player'].to_dict()
games = len(accs)
return {
- 'player_id':player_id,
- 'player_url':request.route_url('player_info', id=player_id),
- 'weapon':weapon_cd,
- 'games':games,
- 'avg':avg,
+ 'player_id':player_id,
+ 'player_url':request.route_url('player_info', id=player_id),
+ 'weapon':weapon_cd,
+ 'games':games,
+ 'avg':avg,
'accs':accs
}
games = len(dmgs)
return {
- 'player_id':player_id,
- 'player_url':request.route_url('player_info', id=player_id),
- 'weapon':weapon_cd,
- 'games':games,
- 'avg':avg,
+ 'player_id':player_id,
+ 'player_url':request.route_url('player_info', id=player_id),
+ 'weapon':weapon_cd,
+ 'games':games,
+ 'avg':avg,
'dmgs':dmgs
}
'version': 1,
'elos': elos,
}]
+
+def player_captimes_data(request):
+ player_id = int(request.matchdict['id'])
+ if player_id <= 2:
+ player_id = -1;
+
+ #player_captimes = DBSession.query(PlayerCaptime).\
+ # filter(PlayerCaptime.player_id==player_id).\
+ # order_by(PlayerCaptime.fastest_cap).\
+ # all()
+
+ PlayerCaptimes = namedtuple('PlayerCaptimes', ['fastest_cap', 'create_dt', 'create_dt_epoch', 'create_dt_fuzzy',
+ 'player_id', 'game_id', 'map_id', 'map_name', 'server_id', 'server_name'])
+
+ dbquery = DBSession.query('fastest_cap', 'create_dt', 'player_id', 'game_id', 'map_id',
+ 'map_name', 'server_id', 'server_name').\
+ from_statement(
+ "SELECT ct.fastest_cap, "
+ "ct.create_dt, "
+ "ct.player_id, "
+ "ct.game_id, "
+ "ct.map_id, "
+ "m.name map_name, "
+ "g.server_id, "
+ "s.name server_name "
+ "FROM player_map_captimes ct, "
+ "games g, "
+ "maps m, "
+ "servers s "
+ "WHERE ct.player_id = :player_id "
+ "AND g.game_id = ct.game_id "
+ "AND g.server_id = s.server_id "
+ "AND m.map_id = ct.map_id "
+ #"ORDER BY ct.fastest_cap "
+ "ORDER BY ct.create_dt desc"
+ ).params(player_id=player_id).all()
+
+ player = DBSession.query(Player).filter_by(player_id=player_id).one()
+
+ player_captimes = []
+ for row in dbquery:
+ player_captimes.append(PlayerCaptimes(
+ fastest_cap=row.fastest_cap,
+ create_dt=row.create_dt,
+ create_dt_epoch=timegm(row.create_dt.timetuple()),
+ create_dt_fuzzy=pretty_date(row.create_dt),
+ player_id=row.player_id,
+ game_id=row.game_id,
+ map_id=row.map_id,
+ map_name=row.map_name,
+ server_id=row.server_id,
+ server_name=row.server_name,
+ ))
+
+ return {
+ 'captimes':player_captimes,
+ 'player_id':player_id,
+ 'player_url':request.route_url('player_info', id=player_id),
+ 'player':player,
+ }
+
+def player_captimes(request):
+ return player_captimes_data(request)
+
+def player_captimes_json(request):
+ return player_captimes_data(request)