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