Mercurial > hg > rlgallery-misc
comparison py/stats2.py @ 38:d2c3c29ca4f9
Add a new statistics script that creates SVG plots.
author | John "Elwin" Edwards |
---|---|
date | Fri, 10 Jan 2014 07:15:39 -0500 |
parents | |
children | a97a20571526 |
comparison
equal
deleted
inserted
replaced
37:c045d4dcf88a | 38:d2c3c29ca4f9 |
---|---|
1 #!/usr/bin/python3 | |
2 | |
3 import psycopg2 | |
4 import rlgall | |
5 from datetime import datetime | |
6 | |
7 sitename = "rlgallery.org" | |
8 svgpath = rlgall.webdir | |
9 timestr = datetime.utcnow().strftime("%Y-%m-%d %H:%M") | |
10 | |
11 dochead = """<?xml version="1.0" encoding="UTF-8"?> | |
12 <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="900" height="600"> | |
13 """ | |
14 stylesheet = """<style type="text/css"> | |
15 rect.frame {{ | |
16 fill:#ffffff; | |
17 fill-opacity:1; | |
18 stroke:#000000; | |
19 stroke-width:4; | |
20 stroke-opacity:1; | |
21 }} | |
22 rect.bar {{ | |
23 fill:#{0}; | |
24 fill-opacity:1; | |
25 stroke:#000000; | |
26 stroke-width:2; | |
27 stroke-opacity:1; | |
28 }} | |
29 </style> | |
30 """ | |
31 framerect = '<rect width="750" height="500" x="100" y="50" class="frame"/>\n' | |
32 barstr = '<rect width="{0}" height="{1}" x="{2}" y="{3}" class="bar"/>\n' | |
33 xllabel = '<text x="{0}" y="570" font-size="15" text-anchor="middle">{1}</text>\n' | |
34 ylabel = '<text x="90" y="{0}" font-size="16" text-anchor="end">{1}</text>\n' | |
35 xlabelf = '<text x="475" y="590" font-size="15" text-anchor="middle">{0}</text>\n' | |
36 ltitle = '<text x="100" y="35" font-size="16" text-anchor="start">{0}</text>\n' | |
37 ctitle = '<text x="475" y="34" font-size="18" text-anchor="middle">{0}</text>\n' | |
38 rtitle = '<text x="850" y="35" font-size="16" text-anchor="end">{0}</text>\n' | |
39 ylabelf = """<g transform="translate(100, 300)"> | |
40 <g transform="rotate(-90)"> | |
41 <text x="0" y="-60" font-size="16" text-anchor="middle">{0}</text> | |
42 </g> | |
43 </g> | |
44 """ | |
45 | |
46 def ylimits(x): | |
47 ll = [2, 3, 4, 5, 6, 8, 10, 15] | |
48 m = 1 | |
49 size = 0 | |
50 while True: | |
51 for i in ll: | |
52 if i * m > x: | |
53 size = i | |
54 lim = i * m | |
55 break | |
56 if size: | |
57 break | |
58 else: | |
59 m *= 10 | |
60 if size in [3, 6]: | |
61 if lim == 3: | |
62 divs = 3 | |
63 else: | |
64 divs = 6 | |
65 elif size in [4, 8]: | |
66 divs = 4 | |
67 else: | |
68 if lim == 2: | |
69 divs = 2 | |
70 else: | |
71 divs = 5 | |
72 return divs, lim | |
73 | |
74 con = psycopg2.connect("dbname=rlg") | |
75 cur = con.cursor() | |
76 | |
77 for game in rlgall.gamelist: | |
78 xlq = "SELECT count(*) FROM {0} WHERE xl = %s;".format(game.uname) | |
79 scrq = "SELECT count(*) FROM {0} WHERE score >= %s AND score < %s;".format(game.uname) | |
80 xls = range(1, 16) | |
81 scoreblocks = range(10) | |
82 xlcounts = [] | |
83 scorecounts = [] | |
84 for xl in xls: | |
85 cur.execute(xlq, [xl]) | |
86 xlcounts.append(cur.fetchone()[0]) | |
87 for sn in scoreblocks: | |
88 lscore = sn * 1000 | |
89 if sn == 9: | |
90 hscore = 32000 | |
91 else: | |
92 hscore = (sn + 1) * 1000 | |
93 cur.execute(scrq, (lscore, hscore)) | |
94 scorecounts.append(cur.fetchone()[0]) | |
95 xlgraph = open("{0}/xl-{1}.svg".format(svgpath, game.uname), "w") | |
96 scoregraph = open("{0}/score-{1}.svg".format(svgpath, game.uname), "w") | |
97 xlgraph.write(dochead) | |
98 scoregraph.write(dochead) | |
99 xlgraph.write(stylesheet.format("0000ff")) | |
100 scoregraph.write(stylesheet.format("ffff00")) | |
101 xlgraph.write(framerect) | |
102 scoregraph.write(framerect) | |
103 | |
104 xldivs, xlmax = ylimits(max(xlcounts)) | |
105 scale = 500 / xlmax | |
106 for xl, count in zip(xls, xlcounts): | |
107 barx = xl * 50 + 60 | |
108 barh = round(scale * count) | |
109 bary = 550 - barh | |
110 xlgraph.write(barstr.format(30, barh, barx, bary)) | |
111 xlgraph.write(xllabel.format(barx + 15, xl)) | |
112 for yl in range(xldivs + 1): | |
113 labeln = int(xlmax * yl / xldivs) | |
114 labelh = 550 + 8 - 500 * yl / xldivs | |
115 xlgraph.write(ylabel.format(labelh, labeln)) | |
116 | |
117 scoredivs, scoremax = ylimits(max(scorecounts)) | |
118 scale = 500 / scoremax | |
119 for block, count in zip(scoreblocks, scorecounts): | |
120 barx = block * 75 + 100 | |
121 barh = round(scale * count) | |
122 bary = 550 - barh | |
123 scoregraph.write(barstr.format(75, barh, barx, bary)) | |
124 scoregraph.write(xllabel.format(barx, block * 1000)) | |
125 for yl in range(scoredivs + 1): | |
126 labeln = int(scoremax * yl / scoredivs) | |
127 labelh = 550 + 8 - 500 * yl / scoredivs | |
128 scoregraph.write(ylabel.format(labelh, labeln)) | |
129 | |
130 xlgraph.write(xlabelf.format("Experience level")) | |
131 xlgraph.write(ylabelf.format("# of games")) | |
132 scoregraph.write(xlabelf.format("Score")) | |
133 scoregraph.write(ylabelf.format("# of games")) | |
134 xlgraph.write(ltitle.format(sitename)) | |
135 xlgraph.write(ctitle.format(game.name)) | |
136 xlgraph.write(rtitle.format(timestr)) | |
137 scoregraph.write(ltitle.format(sitename)) | |
138 scoregraph.write(ctitle.format(game.name)) | |
139 scoregraph.write(rtitle.format(timestr)) | |
140 xlgraph.write('</svg>\n') | |
141 xlgraph.close() | |
142 scoregraph.write('</svg>\n') | |
143 scoregraph.close() | |
144 | |
145 cur.close() | |
146 con.close() | |
147 exit() |