Add a new statistics script that creates SVG plots.
This commit is contained in:
parent
1ab746907b
commit
be7dba5b6c
4 changed files with 240 additions and 0 deletions
78
lighttpd/conf.d/mime.conf
Normal file
78
lighttpd/conf.d/mime.conf
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
#######################################################################
|
||||
##
|
||||
## MimeType handling
|
||||
## -------------------
|
||||
##
|
||||
## http://www.lighttpd.net/documentation/configuration.html#mimetypes
|
||||
##
|
||||
## Use the "Content-Type" extended attribute to obtain mime type if
|
||||
## possible
|
||||
##
|
||||
mimetype.use-xattr = "disable"
|
||||
|
||||
##
|
||||
## mimetype mapping
|
||||
##
|
||||
mimetype.assign = (
|
||||
".pdf" => "application/pdf",
|
||||
".sig" => "application/pgp-signature",
|
||||
".spl" => "application/futuresplash",
|
||||
".class" => "application/octet-stream",
|
||||
".ps" => "application/postscript",
|
||||
".torrent" => "application/x-bittorrent",
|
||||
".dvi" => "application/x-dvi",
|
||||
".gz" => "application/x-gzip",
|
||||
".pac" => "application/x-ns-proxy-autoconfig",
|
||||
".swf" => "application/x-shockwave-flash",
|
||||
".tar.gz" => "application/x-tgz",
|
||||
".tgz" => "application/x-tgz",
|
||||
".tar" => "application/x-tar",
|
||||
".zip" => "application/zip",
|
||||
".mp3" => "audio/mpeg",
|
||||
".m3u" => "audio/x-mpegurl",
|
||||
".wma" => "audio/x-ms-wma",
|
||||
".wax" => "audio/x-ms-wax",
|
||||
".ogg" => "application/ogg",
|
||||
".wav" => "audio/x-wav",
|
||||
".gif" => "image/gif",
|
||||
".jpg" => "image/jpeg",
|
||||
".jpeg" => "image/jpeg",
|
||||
".png" => "image/png",
|
||||
".svg" => "image/svg+xml",
|
||||
".xbm" => "image/x-xbitmap",
|
||||
".xpm" => "image/x-xpixmap",
|
||||
".xwd" => "image/x-xwindowdump",
|
||||
".css" => "text/css",
|
||||
".html" => "text/html",
|
||||
".htm" => "text/html",
|
||||
".js" => "text/javascript",
|
||||
".asc" => "text/plain",
|
||||
".c" => "text/plain",
|
||||
".cpp" => "text/plain",
|
||||
".log" => "text/plain",
|
||||
".conf" => "text/plain",
|
||||
".text" => "text/plain",
|
||||
".txt" => "text/plain",
|
||||
".spec" => "text/plain",
|
||||
".dtd" => "text/xml",
|
||||
".xml" => "text/xml",
|
||||
".mpeg" => "video/mpeg",
|
||||
".mpg" => "video/mpeg",
|
||||
".mov" => "video/quicktime",
|
||||
".qt" => "video/quicktime",
|
||||
".avi" => "video/x-msvideo",
|
||||
".asf" => "video/x-ms-asf",
|
||||
".asx" => "video/x-ms-asf",
|
||||
".wmv" => "video/x-ms-wmv",
|
||||
".bz2" => "application/x-bzip",
|
||||
".tbz" => "application/x-bzip-compressed-tar",
|
||||
".tar.bz2" => "application/x-bzip-compressed-tar",
|
||||
".rpm" => "application/x-rpm",
|
||||
# make the default mime type application/octet-stream.
|
||||
"" => "application/octet-stream",
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
#######################################################################
|
||||
|
||||
147
py/stats2.py
Executable file
147
py/stats2.py
Executable file
|
|
@ -0,0 +1,147 @@
|
|||
#!/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:4;
|
||||
stroke-opacity:1;
|
||||
}}
|
||||
rect.bar {{
|
||||
fill:#{0};
|
||||
fill-opacity:1;
|
||||
stroke:#000000;
|
||||
stroke-width:2;
|
||||
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}" 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 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:
|
||||
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
|
||||
|
||||
con = psycopg2.connect("dbname=rlg")
|
||||
cur = con.cursor()
|
||||
|
||||
for game in rlgall.gamelist:
|
||||
xlq = "SELECT count(*) FROM {0} WHERE xl = %s;".format(game.uname)
|
||||
scrq = "SELECT count(*) FROM {0} WHERE score >= %s AND score < %s;".format(game.uname)
|
||||
xls = range(1, 16)
|
||||
scoreblocks = range(10)
|
||||
xlcounts = []
|
||||
scorecounts = []
|
||||
for xl in xls:
|
||||
cur.execute(xlq, [xl])
|
||||
xlcounts.append(cur.fetchone()[0])
|
||||
for sn in scoreblocks:
|
||||
lscore = sn * 1000
|
||||
if sn == 9:
|
||||
hscore = 32000
|
||||
else:
|
||||
hscore = (sn + 1) * 1000
|
||||
cur.execute(scrq, (lscore, hscore))
|
||||
scorecounts.append(cur.fetchone()[0])
|
||||
xlgraph = open("{0}/xl-{1}.svg".format(svgpath, game.uname), "w")
|
||||
scoregraph = open("{0}/score-{1}.svg".format(svgpath, game.uname), "w")
|
||||
xlgraph.write(dochead)
|
||||
scoregraph.write(dochead)
|
||||
xlgraph.write(stylesheet.format("0000ff"))
|
||||
scoregraph.write(stylesheet.format("ffff00"))
|
||||
xlgraph.write(framerect)
|
||||
scoregraph.write(framerect)
|
||||
|
||||
xldivs, xlmax = ylimits(max(xlcounts))
|
||||
scale = 500 / xlmax
|
||||
for xl, count in zip(xls, xlcounts):
|
||||
barx = xl * 50 + 60
|
||||
barh = round(scale * count)
|
||||
bary = 550 - barh
|
||||
xlgraph.write(barstr.format(30, barh, barx, bary))
|
||||
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))
|
||||
|
||||
scoredivs, scoremax = ylimits(max(scorecounts))
|
||||
scale = 500 / scoremax
|
||||
for block, count in zip(scoreblocks, scorecounts):
|
||||
barx = block * 75 + 100
|
||||
barh = round(scale * count)
|
||||
bary = 550 - barh
|
||||
scoregraph.write(barstr.format(75, barh, barx, bary))
|
||||
scoregraph.write(xllabel.format(barx, block * 1000))
|
||||
for yl in range(scoredivs + 1):
|
||||
labeln = int(scoremax * yl / scoredivs)
|
||||
labelh = 550 + 8 - 500 * yl / scoredivs
|
||||
scoregraph.write(ylabel.format(labelh, labeln))
|
||||
|
||||
xlgraph.write(xlabelf.format("Experience level"))
|
||||
xlgraph.write(ylabelf.format("# of games"))
|
||||
scoregraph.write(xlabelf.format("Score"))
|
||||
scoregraph.write(ylabelf.format("# of games"))
|
||||
xlgraph.write(ltitle.format(sitename))
|
||||
xlgraph.write(ctitle.format(game.name))
|
||||
xlgraph.write(rtitle.format(timestr))
|
||||
scoregraph.write(ltitle.format(sitename))
|
||||
scoregraph.write(ctitle.format(game.name))
|
||||
scoregraph.write(rtitle.format(timestr))
|
||||
xlgraph.write('</svg>\n')
|
||||
xlgraph.close()
|
||||
scoregraph.write('</svg>\n')
|
||||
scoregraph.close()
|
||||
|
||||
cur.close()
|
||||
con.close()
|
||||
exit()
|
||||
|
|
@ -14,7 +14,18 @@
|
|||
<li><a href="./high.cgi">High Scores</a></li>
|
||||
<li><a href="./players/">Explorers</a></li>
|
||||
</ul>
|
||||
<h2>Statistics</h2>
|
||||
</div>
|
||||
<div class=graph><img src="./xl-rogue3.svg" alt="Rogue V3 experience"></div>
|
||||
<div class=graph><img src="./xl-rogue4.svg" alt="Rogue V4 experience"></div>
|
||||
<div class=graph><img src="./xl-rogue5.svg" alt="Rogue V5 experience"></div>
|
||||
<div class=graph><img src="./xl-srogue.svg" alt="Super-Rogue experience"></div>
|
||||
<div class=graph><img src="./xl-arogue5.svg" alt="Advanced Rogue 5 experience"></div>
|
||||
<div class=graph><img src="./score-rogue3.svg" alt="Rogue V3 scores"></div>
|
||||
<div class=graph><img src="./score-rogue4.svg" alt="Rogue V4 scores"></div>
|
||||
<div class=graph><img src="./score-rogue5.svg" alt="Rogue V5 scores"></div>
|
||||
<div class=graph><img src="./score-srogue.svg" alt="Super-Rogue scores"></div>
|
||||
<div class=graph><img src="./score-arogue5.svg" alt="Advanced Rogue 5 scores"></div>
|
||||
<div class="foot"><a href="/">rlgallery.org</a> <a href="/recent.cgi">Recent Games</a> <a href="/scoring/high.cgi">High Scores</a></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ div.sentry:nth-child(3n+2) {
|
|||
background-color: #FFE0E0;
|
||||
}
|
||||
|
||||
div.graph {
|
||||
margin: 1em auto;
|
||||
}
|
||||
|
||||
span.shdata {
|
||||
display: table-cell;
|
||||
font-weight: bold;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue