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() |
