enabled UTF-8 encoded playernicks for testing (FIXME: it is known that some nicks cause problems with cairo currently)
# we look for players who have activity within the past DELTA hours
DELTA = 6
+VERBOSE = False
+
# classic skin WITHOUT NAME - writes PNGs into "output//###.png"
skin_classic = Skin( "",
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]
Options:
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,
}
+
"""Render an image for the given player id."""
# 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
# 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
# this hilarious code should determine the spacing between characters
sep_w = 0.25*space_w
if sep_w <= 0:
- sep_w = 1
+ sep_w = 1
# split nick into colored segments
xoffset = 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 + sep_w
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
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 = "???"
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]