changeset 35:6592cdd1fceb

Add a high score CGI script. /scoring/high.cgi shows a score list, with a configurable length, offset, and game list.
author John "Elwin" Edwards
date Fri, 03 Jan 2014 11:11:07 -0500
parents 86b616d88020
children 09ef92dc4439
files py/rlgall.py web/scoring/high.cgi
diffstat 2 files changed, 124 insertions(+), 79 deletions(-) [+]
line wrap: on
line diff
--- a/py/rlgall.py	Thu Jan 02 13:58:05 2014 -0500
+++ b/py/rlgall.py	Fri Jan 03 11:11:07 2014 -0500
@@ -115,16 +115,14 @@
       clist.append("{0}".format(field))
   of.write(maketablerow(clist, True))
   rnum = 0
-  for i, entry in enumerate(entries):
+  for entry in entries:
     clist = []
     for field in fields:
-      if field == "rank":
-        clist.append(("{0}".format(i + 1), rcell))
-      elif field in entry:
+      if field in entry:
         thing = entry[field]
         if field == "game":
           clist.append((thing.name, cell))
-        elif field == "xl" or field == "score": # Numerics
+        elif field == "xl" or field == "score" or field == "rank": # Numerics
           clist.append((str(thing), rcell))
         elif field == "name":
           clist.append((playerlink(thing), cell))
@@ -260,6 +258,43 @@
     else:
       printTable(newest, self.fields, of)
     return
+  def getHigh(self, n=10, offset=0):
+    "Gets the n highest scores (starting at offset) from the database, \
+     returning a list of dicts."
+    qfields = []
+    for f in self.rankfields:
+      if f == "rank":
+        qfields.append("rank(*) OVER (ORDER BY score DESC)")
+      else:
+        qfields.append(f)
+    qstr = "SELECT " + ", ".join(qfields) + " FROM {0} ".format(self.uname)
+    qvals = []
+    try:
+      n = int(n)
+    except (ValueError, TypeError):
+      return []
+    if n <= 0:
+      return []
+    qstr += " LIMIT %s"
+    qvals.append(n)
+    try:
+      offset = int(offset)
+    except (ValueError, TypeError):
+      return []
+    if offset > 0:
+      qstr += " OFFSET %s"
+      qvals.append(offset)
+    qstr += ";"
+    conn = psycopg2.connect("dbname=rlg")
+    cur = conn.cursor()
+    cur.execute(qstr, qvals)
+    cols = [ col.name for col in cur.description ]
+    data = [ dict(zip(cols, row)) for row in cur.fetchall() ]
+    cur.close()
+    conn.close()
+    for d in data:
+      d["game"] = self
+    return data
 # End Game class definition
 
 class RogueGame(Game):
@@ -311,43 +346,6 @@
     cur.close()
     conn.close()
     return dictlist
-  def getHigh(self, n=10, offset=0):
-    "Gets the n highest scores (starting at offset) from the database, \
-     returning a list of dicts."
-    qstr = "SELECT endt, score, name, xl, fate, startt FROM {0} ORDER BY score DESC ".format(self.uname)
-    qvals = []
-    try:
-      n = int(n)
-    except (ValueError, TypeError):
-      return []
-    if n <= 0:
-      return []
-    qstr += " LIMIT %s"
-    qvals.append(n)
-    try:
-      offset = int(offset)
-    except (ValueError, TypeError):
-      return []
-    if n > 0:
-      qstr += " OFFSET %s"
-      qvals.append(offset)
-    qstr += ";"
-    conn = psycopg2.connect("dbname=rlg")
-    cur = conn.cursor()
-    cur.execute(qstr, qvals)
-    dictlist = []
-    for record in cur:
-      ndict = {"game": self}
-      ndict["endt"] = record[0]
-      ndict["score"] = record[1]
-      ndict["name"] = record[2]
-      ndict["xl"] = record[3]
-      ndict["fate"] = record[4]
-      ndict["startt"] = record[5]
-      dictlist.append(ndict)
-    cur.close()
-    conn.close()
-    return dictlist
   def getPlayer(self, player):
     "Gets all player's games from the database."
     qstr = "SELECT endt, score, name, xl, fate, startt FROM " + self.uname + " WHERE name = %s;"
@@ -406,43 +404,6 @@
   fields = ["name", "score", "class", "xl", "fate", "endt"]
   rankfields = ["rank", "score", "name", "class", "xl", "fate", "endt"]
   pfields = ["score", "class", "xl", "fate", "endt"]
-  def getHigh(self, n=10, offset=0):
-    "Gets the n highest scores (starting at offset) from the database, \
-     returning a list of dicts."
-    qstr = "SELECT endt, score, name, xl, class, fate FROM {0} ORDER BY score DESC ".format(self.uname)
-    qvals = []
-    try:
-      n = int(n)
-    except (ValueError, TypeError):
-      return []
-    if n <= 0:
-      return []
-    qstr += " LIMIT %s"
-    qvals.append(n)
-    try:
-      offset = int(offset)
-    except (ValueError, TypeError):
-      return []
-    if n > 0:
-      qstr += " OFFSET %s"
-      qvals.append(offset)
-    qstr += ";"
-    conn = psycopg2.connect("dbname=rlg")
-    cur = conn.cursor()
-    cur.execute(qstr, qvals)
-    dictlist = []
-    for record in cur:
-      ndict = {"game": self}
-      ndict["endt"] = record[0]
-      ndict["score"] = record[1]
-      ndict["name"] = record[2]
-      ndict["xl"] = record[3]
-      ndict["class"] = record[4]
-      ndict["fate"] = record[5]
-      dictlist.append(ndict)
-    cur.close()
-    conn.close()
-    return dictlist
   def getRecent(self, n=20):
     return []
   def getPlayer(self, player):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/scoring/high.cgi	Fri Jan 03 11:11:07 2014 -0500
@@ -0,0 +1,84 @@
+#!/usr/bin/python3
+
+import sys
+import cgi
+import rlgall
+
+checkstr = '{0}:<input type="checkbox" name="g" value="{1}" checked="checked"> '
+uncheckstr = '{0}:<input type="checkbox" name="g" value="{1}"> '
+
+cgidata = cgi.FieldStorage()
+
+formgames = cgidata.getlist("g")
+if "all" in formgames:
+  games = rlgall.gamelist
+else:
+  games = []
+  for g in rlgall.gamelist:
+    if g.uname in formgames:
+      games.append(g)
+  if not games:
+    games = rlgall.gamelist
+
+formstart = cgidata.getfirst("s")
+if not formstart:
+  start = 0
+else:
+  try:
+    start = int(formstart)
+  except ValueError:
+    start = 0
+if start < 0:
+  start = 0
+
+deflimit = (12 // len(games)) * 5
+formlimit = cgidata.getfirst("l")
+if not formlimit:
+  limit = deflimit
+else:
+  try:
+    limit = int(formlimit)
+  except ValueError:
+    limit = deflimit
+if limit <= 0:
+  limit = deflimit
+
+
+sys.stdout.write("Content-Type: text/html; charset=utf-8\r\n\r\n")
+sys.stdout.write(rlgall.phead.format("High Scores"))
+sys.stdout.write(rlgall.ptop)
+sys.stdout.write(rlgall.navscore.format("High Scores"))
+if len(games) == 1:
+  if start == 0:
+    intitle = "Top {0} scores for {1}".format(limit, games[0].name)
+  else:
+    intitle = "Scores {0} - {1} for {2}".format(start + 1, start + limit, 
+                games[0].name)
+  sys.stdout.write(rlgall.pti.format(intitle))
+  highlist = games[0].getHigh(limit, start)
+  rlgall.printTable(highlist, games[0].rankfields, sys.stdout)
+else:
+  if start == 0:
+    intitle = "Top {0} scores".format(limit)
+  else:
+    intitle = "Scores {0} - {1}".format(start + 1, start + limit)
+  sys.stdout.write(rlgall.pti.format(intitle))
+  for g in games:
+    sys.stdout.write(rlgall.secthead.format(g.name))
+    highlist = g.getHigh(limit, start)
+    rlgall.printTable(highlist, g.rankfields, sys.stdout)
+sys.stdout.write('<form action="/scoring/high.cgi" method="get">\n')
+sys.stdout.write('<div>Number of scores: ')
+sys.stdout.write('<input type="text" name="l" value="{0}">'.format(limit))
+sys.stdout.write(' Skip the first: ')
+sys.stdout.write('<input type="text" name="s" value="{0}">'.format(start))
+sys.stdout.write('</div><div>')
+for game in rlgall.gamelist:
+  if game in games:
+    sys.stdout.write(checkstr.format(game.name, game.uname))
+  else:
+    sys.stdout.write(uncheckstr.format(game.name, game.uname))
+sys.stdout.write('</div><div><input type="submit" value="Get Scores">')
+sys.stdout.write('</div></form>')
+sys.stdout.write(rlgall.pend)
+exit()