Mercurial > hg > rlgallery-misc
comparison py/stats2.py @ 56:5cf88bd4e556
stats2.py: add some 3D perspective to the graphs.
| author | John "Elwin" Edwards |
|---|---|
| date | Mon, 26 May 2014 19:50:02 -0700 |
| parents | 0f4163dbbafc |
| children | 876786c55450 |
comparison
equal
deleted
inserted
replaced
| 55:e421ea2519ec | 56:5cf88bd4e556 |
|---|---|
| 24 fill-opacity:1; | 24 fill-opacity:1; |
| 25 stroke:#000000; | 25 stroke:#000000; |
| 26 stroke-width:2; | 26 stroke-width:2; |
| 27 stroke-opacity:1; | 27 stroke-opacity:1; |
| 28 }} | 28 }} |
| 29 g.bar3d polygon {{ | |
| 30 fill:#{0}; | |
| 31 fill-opacity:1; | |
| 32 stroke:#000000; | |
| 33 stroke-width:1; | |
| 34 stroke-opacity:1; | |
| 35 }} | |
| 29 </style> | 36 </style> |
| 30 """ | 37 """ |
| 31 framerect = '<rect width="750" height="500" x="100" y="50" class="frame"/>\n' | 38 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' | 39 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' | 40 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' | 41 ylabel = '<text x="90" y="{0:.2f}" 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' | 42 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' | 43 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' | 44 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' | 45 rtitle = '<text x="850" y="35" font-size="16" text-anchor="end">{0}</text>\n' |
| 39 ylabelf = """<g transform="translate(100, 300)"> | 46 ylabelf = """<g transform="translate(100, 300)"> |
| 40 <g transform="rotate(-90)"> | 47 <g transform="rotate(-90)"> |
| 41 <text x="0" y="-60" font-size="16" text-anchor="middle">{0}</text> | 48 <text x="0" y="-60" font-size="16" text-anchor="middle">{0}</text> |
| 42 </g> | 49 </g> |
| 43 </g> | 50 </g> |
| 44 """ | 51 """ |
| 52 | |
| 53 def makepolygon(coords): | |
| 54 points = [ "{0:.2f},{1:.2f}".format(pt[0], pt[1]) for pt in coords ] | |
| 55 pointstr = " ".join(points) | |
| 56 return '<polygon points="{}"/>\n'.format(pointstr) | |
| 57 | |
| 58 def bar3d(x, w, h): | |
| 59 ydelta = w / 2 | |
| 60 xdelta = ydelta / 3 | |
| 61 flowerleft = (x, 550) | |
| 62 flowerright = (x + w, 550) | |
| 63 fupperleft = (x, 550 - h) | |
| 64 fupperright = (x + w, 550 - h) | |
| 65 blowerright = (x + w + xdelta, 550 - ydelta) | |
| 66 bupperleft = (x + xdelta, 550 - h - ydelta) | |
| 67 bupperright = (x + w + xdelta, 550 - h - ydelta) | |
| 68 frontface = makepolygon([flowerleft, flowerright, fupperright, fupperleft]) | |
| 69 rightface = makepolygon([blowerright, flowerright, fupperright, bupperright]) | |
| 70 topface = makepolygon([bupperleft, bupperright, fupperright, fupperleft]) | |
| 71 gopen = '<g class="bar3d" clip-path="url(#framer)">\n' | |
| 72 gclose = '</g>\n' | |
| 73 return gopen + "".join([frontface, rightface, topface]) + gclose | |
| 45 | 74 |
| 46 class SVGChart(): | 75 class SVGChart(): |
| 47 def __init__(self, filename): | 76 def __init__(self, filename): |
| 48 self.of = open(filename, "w", encoding="utf-8") | 77 self.of = open(filename, "w", encoding="utf-8") |
| 49 self.of.write(dochead) | 78 self.of.write(dochead) |
| 59 ll = [2, 3, 4, 5, 6, 8, 10, 15] | 88 ll = [2, 3, 4, 5, 6, 8, 10, 15] |
| 60 m = 1 | 89 m = 1 |
| 61 size = 0 | 90 size = 0 |
| 62 while True: | 91 while True: |
| 63 for i in ll: | 92 for i in ll: |
| 64 if i * m > x: | 93 if i * m > x * 1.1: |
| 65 size = i | 94 size = i |
| 66 lim = i * m | 95 lim = i * m |
| 67 break | 96 break |
| 68 if size: | 97 if size: |
| 69 break | 98 break |
| 88 | 117 |
| 89 def mkxlgraph(game, xldata): | 118 def mkxlgraph(game, xldata): |
| 90 xlgraph = SVGChart("{0}/xl-{1}.svg".format(svgpath, game.uname)) | 119 xlgraph = SVGChart("{0}/xl-{1}.svg".format(svgpath, game.uname)) |
| 91 xlgraph.style("0000ff") | 120 xlgraph.style("0000ff") |
| 92 xlgraph.write(framerect) | 121 xlgraph.write(framerect) |
| 122 xlgraph.write('<clipPath id="framer">\n') | |
| 123 xlgraph.write(framerect) | |
| 124 xlgraph.write('</clipPath>\n') | |
| 93 xldivs, xlmax = ylimits(max([ pt[1] for pt in xldata ])) | 125 xldivs, xlmax = ylimits(max([ pt[1] for pt in xldata ])) |
| 94 scale = 500 / xlmax | 126 scale = 500 / xlmax |
| 95 for xl, count in xldata: | 127 for xl, count in xldata: |
| 96 barx = xl * 50 + 60 | 128 barx = xl * 50 + 60 |
| 97 barh = round(scale * count) | 129 barh = scale * count |
| 98 bary = 550 - barh | 130 bary = 550 - barh |
| 99 xlgraph.write(barstr.format(30, barh, barx, bary)) | 131 if count > 0: |
| 132 xlgraph.write(bar3d(barx, 30, barh)) | |
| 100 xlgraph.write(xllabel.format(barx + 15, xl)) | 133 xlgraph.write(xllabel.format(barx + 15, xl)) |
| 101 for yl in range(xldivs + 1): | 134 for yl in range(xldivs + 1): |
| 102 labeln = int(xlmax * yl / xldivs) | 135 labeln = int(xlmax * yl / xldivs) |
| 103 labelh = 550 + 8 - 500 * yl / xldivs | 136 labelh = 550 + 8 - 500 * yl / xldivs |
| 104 xlgraph.write(ylabel.format(labelh, labeln)) | 137 xlgraph.write(ylabel.format(labelh, labeln)) |
| 114 else: | 147 else: |
| 115 scorewidth = 1000 | 148 scorewidth = 1000 |
| 116 scoregraph = SVGChart("{0}/score-{1}.svg".format(svgpath, game.uname)) | 149 scoregraph = SVGChart("{0}/score-{1}.svg".format(svgpath, game.uname)) |
| 117 scoregraph.style("ffff00") | 150 scoregraph.style("ffff00") |
| 118 scoregraph.write(framerect) | 151 scoregraph.write(framerect) |
| 152 scoregraph.write('<clipPath id="framer">\n') | |
| 153 scoregraph.write(framerect) | |
| 154 scoregraph.write('</clipPath>\n') | |
| 119 scoredivs, scoremax = ylimits(max([ pt[1] for pt in scoredata ])) | 155 scoredivs, scoremax = ylimits(max([ pt[1] for pt in scoredata ])) |
| 120 scale = 500 / scoremax | 156 scale = 500 / scoremax |
| 121 for block, count in scoredata: | 157 for block, count in scoredata: |
| 122 n = block // scorewidth | 158 n = block // scorewidth |
| 123 barx = n * 75 + 100 | 159 barx = n * 75 + 100 |
| 124 barh = round(scale * count) | 160 barh = scale * count |
| 125 bary = 550 - barh | 161 bary = 550 - barh |
| 126 scoregraph.write(barstr.format(75, barh, barx, bary)) | 162 if count > 0: |
| 163 scoregraph.write(bar3d(barx, 75, barh)) | |
| 127 scoregraph.write(xllabel.format(barx, block)) | 164 scoregraph.write(xllabel.format(barx, block)) |
| 128 for yl in range(scoredivs + 1): | 165 for yl in range(scoredivs + 1): |
| 129 labeln = int(scoremax * yl / scoredivs) | 166 labeln = int(scoremax * yl / scoredivs) |
| 130 labelh = 550 + 8 - 500 * yl / scoredivs | 167 labelh = 550 + 8 - 500 * yl / scoredivs |
| 131 scoregraph.write(ylabel.format(labelh, labeln)) | 168 scoregraph.write(ylabel.format(labelh, labeln)) |
| 137 | 174 |
| 138 def mkdeepgraph(game, deepdata): | 175 def mkdeepgraph(game, deepdata): |
| 139 deepgraph = SVGChart("{0}/deep-{1}.svg".format(svgpath, game.uname)) | 176 deepgraph = SVGChart("{0}/deep-{1}.svg".format(svgpath, game.uname)) |
| 140 deepgraph.style("808000") | 177 deepgraph.style("808000") |
| 141 deepgraph.write(framerect) | 178 deepgraph.write(framerect) |
| 179 deepgraph.write('<clipPath id="framer">\n') | |
| 180 deepgraph.write(framerect) | |
| 181 deepgraph.write('</clipPath>\n') | |
| 142 deepdivs, deepmax = ylimits(max([ pt[1] for pt in deepdata ])) | 182 deepdivs, deepmax = ylimits(max([ pt[1] for pt in deepdata ])) |
| 143 scale = 500 / deepmax | 183 scale = 500 / deepmax |
| 144 for lev, count in deepdata: | 184 for lev, count in deepdata: |
| 145 barx = lev * 25 + 75 | 185 barx = lev * 25 + 75 |
| 146 barh = round(scale * count) | 186 barh = scale * count |
| 147 bary = 550 - barh | 187 bary = 550 - barh |
| 148 deepgraph.write(barstr.format(25, barh, barx, bary)) | 188 if count > 0: |
| 189 deepgraph.write(bar3d(barx, 25, barh)) | |
| 149 if lev % 3 == 0: | 190 if lev % 3 == 0: |
| 150 deepgraph.write(xllabel.format(barx + 12.5, lev)) | 191 deepgraph.write(xllabel.format(barx + 12.5, lev)) |
| 151 for yl in range(deepdivs + 1): | 192 for yl in range(deepdivs + 1): |
| 152 labeln = int(deepmax * yl / deepdivs) | 193 labeln = int(deepmax * yl / deepdivs) |
| 153 labelh = 550 + 8 - 500 * yl / deepdivs | 194 labelh = 550 + 8 - 500 * yl / deepdivs |
