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