0aa3f6014f28ced6956835d349b909925e9e77e6
[xonotic/xonstat.git] / xonstat / batch / badges / gen_badges.py
1 #-*- coding: utf-8 -*-
2
3 import sys
4 from datetime import datetime
5 import sqlalchemy as sa
6 import sqlalchemy.sql.functions as func
7 from sqlalchemy import distinct
8 from pyramid.paster import bootstrap
9 from xonstat.models import *
10
11 from skin import Skin
12 from playerdata import PlayerData
13
14
15 # maximal number of query results (for testing, set to None to get all)
16 NUM_PLAYERS = None
17
18 # we look for players who have activity within the past DELTA hours
19 DELTA = 6
20
21
22 # classic skin WITHOUT NAME - writes PNGs into "output//###.png"
23 skin_classic = Skin( "",
24         bg              = "broken_noise",
25         overlay         = "overlay_classic",
26     )
27
28 # more fancy skin [** WIP **]- writes PNGs into "output/archer/###.png"
29 skin_archer = Skin( "archer",
30         bg              = "background_archer-v1",
31         overlay         = None,
32     )
33
34 # minimal skin - writes PNGs into "output/minimal/###.png"
35 skin_minimal = Skin( "minimal",
36         bg              = None,
37         bgcolor         = (0.04, 0.04, 0.04, 1.0),
38         overlay         = "overlay_minimal",
39         width           = 560,
40         height          = 40,
41         nick_fontsize   = 16,
42         nick_pos        = (36,16),
43         num_gametypes   = 3,
44         nick_maxwidth   = 300,
45         gametype_pos    = (70,30),
46         gametype_color  = (0.0, 0.0, 0.0),
47         gametype_text   = "%s:",
48         gametype_width  = 100,
49         gametype_fontsize = 10,
50         gametype_align  = -1,
51         gametype_upper  = False,
52         elo_pos         = (75,30),
53         elo_text        = "Elo %.0f",
54         elo_color       = (0.7, 0.7, 0.7),
55         elo_align       = 1,
56         rank_pos        = None,
57         nostats_pos     = None,
58         #nostats_pos     = (75,30),
59         #nostats_fontsize = 10,
60         #nostats_angle   = 0,
61         #nostats_text    = "no stats yet!",
62         #nostats_color   = (0.7, 0.4, 0.4),
63         kdr_pos         = (392,15),
64         kdr_fontsize    = 10,
65         kdr_colortop    = (0.6, 0.8, 0.6),
66         kdr_colormid    = (0.6, 0.6, 0.6),
67         kdr_colorbot    = (0.8, 0.6, 0.6),
68         kills_pos       = None,
69         deaths_pos      = None,
70         winp_pos        = (508,15),
71         winp_fontsize   = 10,
72         winp_colortop   = (0.6, 0.8, 0.8),
73         winp_colormid   = (0.6, 0.6, 0.6),
74         winp_colorbot   = (0.8, 0.8, 0.6),
75         wins_pos        = None,
76         loss_pos        = None,
77         ptime_pos       = (451,30),
78         ptime_color     = (0.7, 0.7, 0.7),
79     )
80
81
82 # parse cmdline parameters (for testing)
83
84 skins = []
85 for arg in sys.argv[1:]:
86     if arg.startswith("-"):
87         arg = arg[1:]
88         if arg == "force":
89             DELTA = 2**24   # large enough to enforce update, and doesn't result in errors
90         elif arg == "test":
91             NUM_PLAYERS = 100
92         else:
93             print """Usage:  gen_badges.py [options] [skin list]
94     Options:
95         -force      Force updating all badges (delta = 2^24)
96         -test       Limit number of players to 100 (for testing)
97         -help       Show this help text
98     Skin list:
99         Space-separated list of skins to use when creating badges.
100         Available skins:  classic, minimal, archer
101         If no skins are given, classic and minmal will be used by default.
102         NOTE: Output directories must exists before running the program!
103 """
104             sys.exit(-1)
105     else:
106         if arg == "classic":
107             skins.append(skin_classic)
108         elif arg == "minimal":
109             skins.append(skin_minimal)
110         elif arg == "archer":
111             skins.append(skin_archer)
112
113 if len(skins) == 0:
114     skins = [ skin_classic, skin_minimal ]
115
116 # environment setup
117 env = bootstrap('../../../development.ini')
118 req = env['request']
119 req.matchdict = {'id':3}
120
121 print "Requesting player data from db ..."
122 cutoff_dt = datetime.utcnow() - timedelta(hours=DELTA)
123 start = datetime.now()
124 players = []
125 if NUM_PLAYERS:
126     players = DBSession.query(distinct(Player.player_id)).\
127             filter(Player.player_id == PlayerElo.player_id).\
128             filter(Player.player_id == PlayerGameStat.player_id).\
129             filter(PlayerGameStat.create_dt > cutoff_dt).\
130             filter(Player.nick != None).\
131             filter(Player.player_id > 2).\
132             filter(Player.active_ind == True).\
133             limit(NUM_PLAYERS).all()
134 else:
135     players = DBSession.query(distinct(Player.player_id)).\
136             filter(Player.player_id == PlayerElo.player_id).\
137             filter(Player.player_id == PlayerGameStat.player_id).\
138             filter(PlayerGameStat.create_dt > cutoff_dt).\
139             filter(Player.nick != None).\
140             filter(Player.player_id > 2).\
141             filter(Player.active_ind == True).\
142             all()
143
144 playerdata = PlayerData()
145
146 if len(players) > 0:
147     stop = datetime.now()
148     td = stop-start
149     total_seconds = (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
150     print "Query took %.2f seconds" % (total_seconds)
151
152     print "Creating badges for %d players ..." % len(players)
153     start = datetime.now()
154     data_time, render_time = 0,0
155     for player_id in players:
156         req.matchdict['id'] = player_id
157
158         sstart = datetime.now()
159         playerdata.get_data(player_id)
160         sstop = datetime.now()
161         td = sstop-sstart
162         total_seconds = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
163         data_time += total_seconds
164
165         sstart = datetime.now()
166         for sk in skins:
167             sk.render_image(playerdata, "output/%s/%d.png" % (str(sk), player_id[0]))
168         sstop = datetime.now()
169         td = sstop-sstart
170         total_seconds = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
171         render_time += total_seconds
172
173     stop = datetime.now()
174     td = stop-start
175     total_seconds = float(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6
176     print "Creating the badges took %.1f seconds (%.3f s per player)" % (total_seconds, total_seconds/float(len(players)))
177     print "Total time for rendering images: %.3f s" % render_time
178     print "Total time for getting data: %.3f s" % data_time
179
180 else:
181     print "No active players found!"
182