Mercurial > hg > rlgallery-misc
view py/stats2.py @ 74:900da50ee11c
Merge lighttpd configuration into one include file.
The lighttpd configuration was previously spread across several files
which were intended to overwrite the defaults. They often became
outdated.
Now all customization is in lighttpd/rlgallery.conf, which should be
included at the end of whatever main lighttpd configuration file is in
use. It should require minimal updates for new lighttpd versions or
distribution changes.
author | John "Elwin" Edwards |
---|---|
date | Wed, 28 Dec 2016 13:12:04 -0500 |
parents | 876786c55450 |
children |
line wrap: on
line source
#!/usr/bin/python3 import psycopg2 import rlgall from datetime import datetime sitename = "rlgallery.org" svgpath = rlgall.webdir timestr = datetime.utcnow().strftime("%Y-%m-%d %H:%M") dochead = """<?xml version="1.0" encoding="UTF-8"?> <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="900" height="600"> """ stylesheet = """<style type="text/css"> rect.frame {{ fill:#ffffff; fill-opacity:1; stroke:#000000; stroke-width:2; stroke-opacity:1; }} rect.bar {{ fill:#{0}; fill-opacity:1; stroke:#000000; stroke-width:2; stroke-opacity:1; }} g.bar3d polygon {{ fill:#{0}; fill-opacity:1; stroke:#000000; stroke-width:1; stroke-opacity:1; }} </style> """ framerect = '<rect width="750" height="500" x="100" y="50" class="frame"/>\n' barstr = '<rect width="{0}" height="{1}" x="{2}" y="{3}" class="bar"/>\n' xllabel = '<text x="{0}" y="570" font-size="15" text-anchor="middle">{1}</text>\n' ylabel = '<text x="90" y="{0:.2f}" font-size="16" text-anchor="end">{1}</text>\n' xlabelf = '<text x="475" y="590" font-size="15" text-anchor="middle">{0}</text>\n' ltitle = '<text x="100" y="35" font-size="16" text-anchor="start">{0}</text>\n' ctitle = '<text x="475" y="34" font-size="18" text-anchor="middle">{0}</text>\n' rtitle = '<text x="850" y="35" font-size="16" text-anchor="end">{0}</text>\n' ylabelf = """<g transform="translate(100, 300)"> <g transform="rotate(-90)"> <text x="0" y="-60" font-size="16" text-anchor="middle">{0}</text> </g> </g> """ def makepolygon(coords): points = [ "{0:.2f},{1:.2f}".format(pt[0], pt[1]) for pt in coords ] pointstr = " ".join(points) return '<polygon points="{}"/>\n'.format(pointstr) def bar3d(x, w, h): ydelta = w / 2 xdelta = ydelta / 3 flowerleft = (x, 550) flowerright = (x + w, 550) fupperleft = (x, 550 - h) fupperright = (x + w, 550 - h) blowerright = (x + w + xdelta, 550 - ydelta) bupperleft = (x + xdelta, 550 - h - ydelta) bupperright = (x + w + xdelta, 550 - h - ydelta) frontface = makepolygon([flowerleft, flowerright, fupperright, fupperleft]) rightface = makepolygon([blowerright, flowerright, fupperright, bupperright]) topface = makepolygon([bupperleft, bupperright, fupperright, fupperleft]) gopen = '<g class="bar3d" clip-path="url(#framer)">\n' gclose = '</g>\n' return gopen + "".join([frontface, rightface, topface]) + gclose class SVGChart(): def __init__(self, filename): self.of = open(filename, "w", encoding="utf-8") self.of.write(dochead) def style(self, barcolor): self.of.write(stylesheet.format(barcolor)) def write(self, obj): self.of.write(obj) def close(self): self.of.write('</svg>\n') self.of.close() def ylimits(x): ll = [2, 3, 4, 5, 6, 8, 10, 15] m = 1 size = 0 while True: for i in ll: if i * m > x * 1.1: size = i lim = i * m break if size: break else: m *= 10 if size in [3, 6]: if lim == 3: divs = 3 else: divs = 6 elif size in [4, 8]: divs = 4 else: if lim == 2: divs = 2 else: divs = 5 return divs, lim def titles(l, c, r): return ltitle.format(l) + ctitle.format(c) + rtitle.format(r) def mkxlgraph(game, xldata): xlgraph = SVGChart("{0}/xl-{1}.svg".format(svgpath, game.uname)) xlgraph.style("0000ff") xlgraph.write(framerect) xlgraph.write('<clipPath id="framer">\n') xlgraph.write(framerect) xlgraph.write('</clipPath>\n') xldivs, xlmax = ylimits(max([ pt[1] for pt in xldata ])) scale = 500 / xlmax for xl, count in xldata: barx = xl * 50 + 60 barh = scale * count bary = 550 - barh if count > 0: xlgraph.write(bar3d(barx, 30, barh)) xlgraph.write(xllabel.format(barx + 15, xl)) for yl in range(xldivs + 1): labeln = int(xlmax * yl / xldivs) labelh = 550 + 8 - 500 * yl / xldivs xlgraph.write(ylabel.format(labelh, labeln)) xlgraph.write(xlabelf.format("Experience level")) xlgraph.write(ylabelf.format("# of games")) xlgraph.write(titles(sitename, game.name, timestr)) xlgraph.close() return def mkscoregraph(game, scoredata): if isinstance(game, rlgall.ARogueGame): scorewidth = 1000 else: scorewidth = 500 scoregraph = SVGChart("{0}/score-{1}.svg".format(svgpath, game.uname)) scoregraph.style("ffff00") scoregraph.write(framerect) scoregraph.write('<clipPath id="framer">\n') scoregraph.write(framerect) scoregraph.write('</clipPath>\n') scoredivs, scoremax = ylimits(max([ pt[1] for pt in scoredata ])) scale = 500 / scoremax for block, count in scoredata: n = block // scorewidth barx = n * 50 + 100 barh = scale * count bary = 550 - barh if count > 0: scoregraph.write(bar3d(barx, 50, barh)) if n % 2 == 0: scoregraph.write(xllabel.format(barx, block)) for yl in range(scoredivs + 1): labeln = int(scoremax * yl / scoredivs) labelh = 550 + 8 - 500 * yl / scoredivs scoregraph.write(ylabel.format(labelh, labeln)) scoregraph.write(xlabelf.format("Score")) scoregraph.write(ylabelf.format("# of games")) scoregraph.write(titles(sitename, game.name, timestr)) scoregraph.close() return def mkdeepgraph(game, deepdata): deepgraph = SVGChart("{0}/deep-{1}.svg".format(svgpath, game.uname)) deepgraph.style("808000") deepgraph.write(framerect) deepgraph.write('<clipPath id="framer">\n') deepgraph.write(framerect) deepgraph.write('</clipPath>\n') deepdivs, deepmax = ylimits(max([ pt[1] for pt in deepdata ])) scale = 500 / deepmax for lev, count in deepdata: barx = lev * 25 + 75 barh = scale * count bary = 550 - barh if count > 0: deepgraph.write(bar3d(barx, 25, barh)) if lev % 3 == 0: deepgraph.write(xllabel.format(barx + 12.5, lev)) for yl in range(deepdivs + 1): labeln = int(deepmax * yl / deepdivs) labelh = 550 + 8 - 500 * yl / deepdivs deepgraph.write(ylabel.format(labelh, labeln)) deepgraph.write(xlabelf.format("Deepest dungeon level")) deepgraph.write(ylabelf.format("# of games")) deepgraph.write(titles(sitename, game.name, timestr)) deepgraph.close() return for game in rlgall.gamelist: xldata = game.getXLCounts(15) deepdata = game.getDepthCounts(30) if isinstance(game, rlgall.ARogueGame): scorewidth = 1000 else: scorewidth = 500 scoredata = game.getScoreCounts(15, scorewidth) mkxlgraph(game, xldata) mkscoregraph(game, scoredata) mkdeepgraph(game, deepdata) exit()