Mercurial > hg > rlgallery-misc
comparison py/stats2.py @ 45:0f4163dbbafc
SVG charts: separate database-querying and chart-printing code.
Create Game methods in rlgall.py to get histogram data for score, xl,
maxdepth. In stats2.py, make the chart-printing functions use this
data and avoid running hard-coded queries.
author | John "Elwin" Edwards |
---|---|
date | Thu, 16 Jan 2014 16:25:09 -0800 |
parents | 3ecbd4fa2a08 |
children | 5cf88bd4e556 |
comparison
equal
deleted
inserted
replaced
44:7c789e87ee5d | 45:0f4163dbbafc |
---|---|
41 <text x="0" y="-60" font-size="16" text-anchor="middle">{0}</text> | 41 <text x="0" y="-60" font-size="16" text-anchor="middle">{0}</text> |
42 </g> | 42 </g> |
43 </g> | 43 </g> |
44 """ | 44 """ |
45 | 45 |
46 class SVGChart(): | |
47 def __init__(self, filename): | |
48 self.of = open(filename, "w", encoding="utf-8") | |
49 self.of.write(dochead) | |
50 def style(self, barcolor): | |
51 self.of.write(stylesheet.format(barcolor)) | |
52 def write(self, obj): | |
53 self.of.write(obj) | |
54 def close(self): | |
55 self.of.write('</svg>\n') | |
56 self.of.close() | |
57 | |
46 def ylimits(x): | 58 def ylimits(x): |
47 ll = [2, 3, 4, 5, 6, 8, 10, 15] | 59 ll = [2, 3, 4, 5, 6, 8, 10, 15] |
48 m = 1 | 60 m = 1 |
49 size = 0 | 61 size = 0 |
50 while True: | 62 while True: |
69 divs = 2 | 81 divs = 2 |
70 else: | 82 else: |
71 divs = 5 | 83 divs = 5 |
72 return divs, lim | 84 return divs, lim |
73 | 85 |
74 def mkxlgraph(game, xls, xlcounts): | 86 def titles(l, c, r): |
75 xlgraph = open("{0}/xl-{1}.svg".format(svgpath, game.uname), "w") | 87 return ltitle.format(l) + ctitle.format(c) + rtitle.format(r) |
76 xlgraph.write(dochead) | 88 |
77 xlgraph.write(stylesheet.format("0000ff")) | 89 def mkxlgraph(game, xldata): |
90 xlgraph = SVGChart("{0}/xl-{1}.svg".format(svgpath, game.uname)) | |
91 xlgraph.style("0000ff") | |
78 xlgraph.write(framerect) | 92 xlgraph.write(framerect) |
79 xldivs, xlmax = ylimits(max(xlcounts)) | 93 xldivs, xlmax = ylimits(max([ pt[1] for pt in xldata ])) |
80 scale = 500 / xlmax | 94 scale = 500 / xlmax |
81 for xl, count in zip(xls, xlcounts): | 95 for xl, count in xldata: |
82 barx = xl * 50 + 60 | 96 barx = xl * 50 + 60 |
83 barh = round(scale * count) | 97 barh = round(scale * count) |
84 bary = 550 - barh | 98 bary = 550 - barh |
85 xlgraph.write(barstr.format(30, barh, barx, bary)) | 99 xlgraph.write(barstr.format(30, barh, barx, bary)) |
86 xlgraph.write(xllabel.format(barx + 15, xl)) | 100 xlgraph.write(xllabel.format(barx + 15, xl)) |
88 labeln = int(xlmax * yl / xldivs) | 102 labeln = int(xlmax * yl / xldivs) |
89 labelh = 550 + 8 - 500 * yl / xldivs | 103 labelh = 550 + 8 - 500 * yl / xldivs |
90 xlgraph.write(ylabel.format(labelh, labeln)) | 104 xlgraph.write(ylabel.format(labelh, labeln)) |
91 xlgraph.write(xlabelf.format("Experience level")) | 105 xlgraph.write(xlabelf.format("Experience level")) |
92 xlgraph.write(ylabelf.format("# of games")) | 106 xlgraph.write(ylabelf.format("# of games")) |
93 xlgraph.write(ltitle.format(sitename)) | 107 xlgraph.write(titles(sitename, game.name, timestr)) |
94 xlgraph.write(ctitle.format(game.name)) | |
95 xlgraph.write(rtitle.format(timestr)) | |
96 xlgraph.write('</svg>\n') | |
97 xlgraph.close() | 108 xlgraph.close() |
98 return | 109 return |
99 | 110 |
100 def mkscoregraph(game, scoreblocks, scorecounts): | 111 def mkscoregraph(game, scoredata): |
101 if isinstance(game, rlgall.ARogueGame): | 112 if isinstance(game, rlgall.ARogueGame): |
102 scorewidth = 1500 | 113 scorewidth = 1500 |
103 else: | 114 else: |
104 scorewidth = 1000 | 115 scorewidth = 1000 |
105 scoregraph = open("{0}/score-{1}.svg".format(svgpath, game.uname), "w") | 116 scoregraph = SVGChart("{0}/score-{1}.svg".format(svgpath, game.uname)) |
106 scoregraph.write(dochead) | 117 scoregraph.style("ffff00") |
107 scoregraph.write(stylesheet.format("ffff00")) | |
108 scoregraph.write(framerect) | 118 scoregraph.write(framerect) |
109 scoredivs, scoremax = ylimits(max(scorecounts)) | 119 scoredivs, scoremax = ylimits(max([ pt[1] for pt in scoredata ])) |
110 scale = 500 / scoremax | 120 scale = 500 / scoremax |
111 for block, count in zip(scoreblocks, scorecounts): | 121 for block, count in scoredata: |
112 barx = block * 75 + 100 | 122 n = block // scorewidth |
123 barx = n * 75 + 100 | |
113 barh = round(scale * count) | 124 barh = round(scale * count) |
114 bary = 550 - barh | 125 bary = 550 - barh |
115 scoregraph.write(barstr.format(75, barh, barx, bary)) | 126 scoregraph.write(barstr.format(75, barh, barx, bary)) |
116 scoregraph.write(xllabel.format(barx, block * scorewidth)) | 127 scoregraph.write(xllabel.format(barx, block)) |
117 for yl in range(scoredivs + 1): | 128 for yl in range(scoredivs + 1): |
118 labeln = int(scoremax * yl / scoredivs) | 129 labeln = int(scoremax * yl / scoredivs) |
119 labelh = 550 + 8 - 500 * yl / scoredivs | 130 labelh = 550 + 8 - 500 * yl / scoredivs |
120 scoregraph.write(ylabel.format(labelh, labeln)) | 131 scoregraph.write(ylabel.format(labelh, labeln)) |
121 scoregraph.write(xlabelf.format("Score")) | 132 scoregraph.write(xlabelf.format("Score")) |
122 scoregraph.write(ylabelf.format("# of games")) | 133 scoregraph.write(ylabelf.format("# of games")) |
123 scoregraph.write(ltitle.format(sitename)) | 134 scoregraph.write(titles(sitename, game.name, timestr)) |
124 scoregraph.write(ctitle.format(game.name)) | |
125 scoregraph.write(rtitle.format(timestr)) | |
126 scoregraph.write('</svg>\n') | |
127 scoregraph.close() | 135 scoregraph.close() |
128 return | 136 return |
129 | 137 |
130 def mkdeepgraph(game, deeps, deepcounts): | 138 def mkdeepgraph(game, deepdata): |
131 deepgraph = open("{0}/deep-{1}.svg".format(svgpath, game.uname), "w") | 139 deepgraph = SVGChart("{0}/deep-{1}.svg".format(svgpath, game.uname)) |
132 deepgraph.write(dochead) | 140 deepgraph.style("808000") |
133 deepgraph.write(stylesheet.format("808000")) | |
134 deepgraph.write(framerect) | 141 deepgraph.write(framerect) |
135 deepdivs, deepmax = ylimits(max(deepcounts)) | 142 deepdivs, deepmax = ylimits(max([ pt[1] for pt in deepdata ])) |
136 scale = 500 / deepmax | 143 scale = 500 / deepmax |
137 for lev, count in zip(deeps, deepcounts): | 144 for lev, count in deepdata: |
138 barx = lev * 25 + 75 | 145 barx = lev * 25 + 75 |
139 barh = round(scale * count) | 146 barh = round(scale * count) |
140 bary = 550 - barh | 147 bary = 550 - barh |
141 deepgraph.write(barstr.format(25, barh, barx, bary)) | 148 deepgraph.write(barstr.format(25, barh, barx, bary)) |
142 if lev % 3 == 0: | 149 if lev % 3 == 0: |
145 labeln = int(deepmax * yl / deepdivs) | 152 labeln = int(deepmax * yl / deepdivs) |
146 labelh = 550 + 8 - 500 * yl / deepdivs | 153 labelh = 550 + 8 - 500 * yl / deepdivs |
147 deepgraph.write(ylabel.format(labelh, labeln)) | 154 deepgraph.write(ylabel.format(labelh, labeln)) |
148 deepgraph.write(xlabelf.format("Deepest dungeon level")) | 155 deepgraph.write(xlabelf.format("Deepest dungeon level")) |
149 deepgraph.write(ylabelf.format("# of games")) | 156 deepgraph.write(ylabelf.format("# of games")) |
150 deepgraph.write(ltitle.format(sitename)) | 157 deepgraph.write(titles(sitename, game.name, timestr)) |
151 deepgraph.write(ctitle.format(game.name)) | |
152 deepgraph.write(rtitle.format(timestr)) | |
153 deepgraph.write('</svg>\n') | |
154 deepgraph.close() | 158 deepgraph.close() |
155 return | 159 return |
156 | 160 |
157 con = psycopg2.connect("dbname=rlg") | |
158 cur = con.cursor() | |
159 | |
160 for game in rlgall.gamelist: | 161 for game in rlgall.gamelist: |
161 xlq = "SELECT count(*) FROM {0} WHERE xl = %s;".format(game.uname) | 162 xldata = game.getXLCounts(15) |
162 scrq = "SELECT count(*) FROM {0} WHERE score >= %s AND score < %s;".format(game.uname) | 163 deepdata = game.getDepthCounts(30) |
163 deepq = "SELECT count(*) FROM {0} WHERE maxdepth = %s;".format(game.uname) | |
164 xls = range(1, 16) | |
165 scoreblocks = range(10) | |
166 deeps = range(1, 31) | |
167 xlcounts = [] | |
168 scorecounts = [] | |
169 deepcounts = [] | |
170 if isinstance(game, rlgall.ARogueGame): | 164 if isinstance(game, rlgall.ARogueGame): |
171 scorewidth = 1500 | 165 scorewidth = 1500 |
172 else: | 166 else: |
173 scorewidth = 1000 | 167 scorewidth = 1000 |
174 for xl in xls: | 168 scoredata = game.getScoreCounts(10, scorewidth) |
175 cur.execute(xlq, [xl]) | 169 mkxlgraph(game, xldata) |
176 xlcounts.append(cur.fetchone()[0]) | 170 mkscoregraph(game, scoredata) |
177 for sn in scoreblocks: | 171 mkdeepgraph(game, deepdata) |
178 lscore = sn * scorewidth | |
179 if sn == 9: | |
180 hscore = scorewidth * 32 | |
181 else: | |
182 hscore = (sn + 1) * scorewidth | |
183 cur.execute(scrq, (lscore, hscore)) | |
184 scorecounts.append(cur.fetchone()[0]) | |
185 for lev in deeps: | |
186 cur.execute(deepq, [lev]) | |
187 deepcounts.append(cur.fetchone()[0]) | |
188 mkxlgraph(game, xls, xlcounts) | |
189 mkscoregraph(game, scoreblocks, scorecounts) | |
190 mkdeepgraph(game, deeps, deepcounts) | |
191 | 172 |
192 cur.close() | |
193 con.close() | |
194 exit() | 173 exit() |