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