All pastes #2002403 Raw Edit

Maths Problem Generator

public python v1 · immutable
#2002403 ·published 2010-11-25 23:08 UTC
rendered paste body
import BaseHTTPServerimport pickleimport randomimport mathimport copyimport cgiimport timeimport reimport threadingimport urlparseimport sysimport decimalHOST_NAME = 'localhost'PORT_NUMBER = 4079formula_templates = [  {"name":"--TEMPLATE--", "disabled":True, "generateInputs":"return {'x':int(math.floor(random.random()*1000)), 'y':int(math.floor(random.random()*1000))}", "formula":"z=x+y", "problem":"What is z?", "resultTemplate":"%z%", "checkResult":"return (int(z) == int(x)+int(y))"},]formulae = []def nl2br(s):  return s.replace("\n", "<br>")def tabifyCode(code):  return "".join(["\t"+line+"\n" for line in code.split("\n")])def generateFormula(formula_template=None):  if formula_template == None:    formula_templates_inuse = [i for i,v in enumerate(formula_templates) if not v["disabled"]]    i = random.choice(formula_templates_inuse)    formula_template = formula_templates[i]  formula = {"template":copy.copy(formula_template), "solved":False}    exec("def generateInputs():\n"+tabifyCode(formula_template["generateInputs"]))  formula["inputs"] = generateInputs()    formulae.append(formula)  saveFormulae()  return len(formulae)-1def _checkResult(code, args):  exec("def checkResult("+", ".join(args.keys())+"):\n"+tabifyCode(code))  return checkResult(**args)def checkResult(id, formula, params):  values = {}  for k,v in params.iteritems():    if k == "template_id":      continue    k,i = k.rsplit("_", 1)    v = v[0]    if k in values:      if v != values[k]:        return False    else:      values[k] = v    #TODO: Check we have all the values we need and no more    formula["solved"] = _checkResult(formula["template"]["checkResult"], values)  if formula["solved"]:    def getValue(o):      return values[o.group(1)]    formula["solution"] = re.sub(r'%([a-zA-Z]+)%', getValue, formula["template"]["resultTemplate"])    saveFormulae()    return True  return Falsedef editTemplate(id, formula_template, params):  try:    name = params["name"][0]    disabled = params.has_key("disabled") and True or False    generateInputs = params["generateInputs"][0]    formula = params["formula"][0]    problem = params["problem"][0]    resultTemplate = params["resultTemplate"][0]    checkResult = params["checkResult"][0]        exec("def _generateInputs():\n"+tabifyCode(generateInputs))    exec("def _checkResult():\n"+tabifyCode(checkResult))        if params.has_key("test"):      formula_template = {}    formula_template["name"] = name    formula_template["disabled"] = bool(disabled)    formula_template["generateInputs"] = generateInputs    formula_template["formula"] = formula    formula_template["problem"] = problem    formula_template["resultTemplate"] = resultTemplate    formula_template["checkResult"] = checkResult    if params.has_key("test"):      return generateFormula(formula_template)        saveFormulaTemplates()    return True  except:    return Falsedef saveFormulae():  try:    f = file("formulae.pickle", "w")    pickle.dump(formulae, f)    f.close()  except:    print sys.exc_info()[0]def saveFormulaTemplates():  try:    f = file("templates.pickle", "w")    pickle.dump(formula_templates, f)    f.close()  except:    print sys.exc_info()[0]class MathHelperRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):  def do_GET(self):    if self.path == "/":      formula_templates_inuse = (i for i,v in enumerate(formula_templates) if not v["disabled"])      for i in formula_templates_inuse:        break      else:        self.send_response(302)        self.send_header("Location", "/templates")        self.send_header("Content-type", "text/html")        self.end_headers()        self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/templates\">Redirect</a></body></html>")      id = generateFormula()      self.send_response(302)      self.send_header("Location", "/formulae/%i" % id)      self.send_header("Content-type", "text/html")      self.end_headers()      self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/formulae/%i\">Redirect</a></body></html>" % id)        elif self.path.startswith("/formulae/"):      try:        id = None        incorrect = False        template_id = None        if self.path.endswith("/incorrect"):          incorrect = True        if (len(self.path.split("/")) == 5 or (incorrect and len(self.path.split("/")) == 6)) and self.path.split("/")[3] == "test":          path = self.path.split("/")          template_id = int(path[4])          id = int(path[2])        elif incorrect:          id = int(self.path[10:-10])        else:          id = int(self.path[10:])        formula = formulae[id]      except (ValueError, IndexError):        self.send_error(404)        return      self.writeFormula(id, formula, incorrect, template_id)        elif self.path == "/formulae":      self.writeFormulaList()        elif self.path == "/templates":      self.writeTemplateList()        elif self.path.startswith("/templates/") and self.path.endswith("/test"):      try:        id = int(self.path[11:-5])        formula_template = formula_templates[id]      except (ValueError, IndexError):        self.send_error(404)        return            formula_id = generateFormula(formula_template)      self.send_response(302)      self.send_header("Location", "/formulae/%i" % formula_id)      self.send_header("Content-type", "text/html")      self.end_headers()      self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/formulae/%i\">Redirect</a></body></html>" % formula_id)        elif self.path.startswith("/templates/"):      try:        edited = False        new = False        invalid = False        if self.path.endswith("/edited"):          id = int(self.path[11:-7])          edited = True        elif self.path.endswith("/new"):          id = int(self.path[11:-4])          new = True        elif self.path.endswith("/invalid"):          id = int(self.path[11:-8])          invalid = True        else:          id = int(self.path[11:])        formula_template = formula_templates[id]      except (ValueError, IndexError):        self.send_error(404)        return      self.writeTemplateEditPage(id, formula_template, new, edited)        elif self.path == "/style.css":      self.writeCSS()        elif self.path == "/quit":      threading.Thread(target=self.server.shutdown).start()      self.send_response(200)      self.send_header("Content-type", "text/plain")      self.end_headers()      self.wfile.write("Server shutting down.")        else:      self.send_error(404)    def do_POST(self):    clen = -1    try:      clen = int(self.headers["Content-length"])    except (ValueError, ValueError):      pass    params = urlparse.parse_qs(self.rfile.read(clen), True)        if self.path.startswith("/formulae/") and self.path.endswith("/check-result"):      try:        id = int(self.path[10:-13])        formula = formulae[id]      except (ValueError, IndexError):        self.send_error(404)        return            try:        if params.has_key("template_id"):          template_id = int(params["template_id"][0])        else:          template_id = None      except (IndexError):        self.send_error(404)        return            if checkResult(id, formula, params):        if template_id != None:          self.send_response(302)          self.send_header("Location", "/templates/%i" % template_id)          self.send_header("Content-type", "text/html")          self.end_headers()          self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/templates/%i\">Redirect</a></body></html>" % template_id)        else:          self.writeCorrectResult()      else:        self.send_response(302)        self.send_header("Location", "/formulae/%i/%sincorrect" % (id, template_id != None and ("test/%i/" % template_id) or ""))        self.send_header("Content-type", "text/html")        self.end_headers()        self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/formulae/%i/%sincorrect\">Redirect</a></body></html>" % (id, template_id != None and ("test/%i/" % template_id) or ""))        elif self.path == "/templates/new":      formula_templates.append(copy.copy(formula_templates[0]))      id = len(formula_templates)-1      formula_template = formula_templates[id]      formula_template["disabled"] = True      saveFormulaTemplates()      self.send_response(302)      self.send_header("Location", "/templates/%i/new" % id)      self.send_header("Content-type", "text/html")      self.end_headers()      self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/templates/%i/new\">Redirect</a></body></html>" % id)        elif self.path.startswith("/templates/") and self.path.endswith("/edit"):      try:        id = int(self.path[11:-5])        formula_template = formula_templates[id]      except (ValueError, IndexError):        self.send_error(404)        return            r = editTemplate(id, formula_template, params)      if params.has_key("test") and r is not False:        self.send_response(302)        self.send_header("Location", "/formulae/%i/test/%s" % (r, id))        self.send_header("Content-type", "text/html")        self.end_headers()        self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/formulae/%i/test/%s\">Redirect</a></body></html>" % (r, id))      elif r:        self.send_response(302)        self.send_header("Location", "/templates/%i/edited" % id)        self.send_header("Content-type", "text/html")        self.end_headers()        self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/templates/%i/edited\">Redirect</a></body></html>" % id)      else:        self.send_response(302)        self.send_header("Location", "/templates/%i/invalid" % id)        self.send_header("Content-type", "text/html")        self.end_headers()        self.wfile.write("<html><head><title>Redirect</title></head><body><a href=\"/templates/%i/invalid\">Redirect</a></body></html>" % id)        else:      self.send_error(404)    def writeFormula(self, id, formula, incorrect, template_id):    self.send_response(200)    self.send_header("Content-type", "text/html")    self.end_headers()        self.wfile.write("<html><head><title>Formula #%i</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" /></head>" % id)    self.wfile.write("<body><div id=\"wrapper\"><h1>Formula #%i</h1><form action=\"/formulae/%i/check-result\" method=\"POST\">" % (id, id))    if incorrect:      self.wfile.write("<p style=\"color:red;font-weight:bold;\" onclick=\"this.style.display='none'\">Incorrect solution.</p>")    self.wfile.write("<p><label>Formula:</label> %s</p>" % nl2br(cgi.escape(formula["template"]["formula"])))    self.wfile.write("<p><label>Inputs:</label> %s</p>" % "<br>".join(tuple("<strong>%s =</strong> %s" % (cgi.escape(k), cgi.escape(str(v))) for k,v in formula["inputs"].items())))    self.wfile.write("<p><label>Problem:</label> %s</p>" % nl2br(cgi.escape(formula["template"]["problem"])))        def sanitize(o):      return cgi.escape(o.group(0))    def _inc():      i = 0      while True:        yield i        i += 1    inc = _inc()    def makeInput(o):      i = inc.next()      return "<input type=\"text\" name=\"%s_%i\" style=\"width:4em\">" % (o.group(1), inc.next())    answerform = formula["template"]["resultTemplate"]    answerform = re.sub(r'(.*?)(?:%[a-zA-Z]%|$)', sanitize, formula["template"]["resultTemplate"])    answerform = re.sub(r'%([a-zA-Z]+)%', makeInput, answerform)        self.wfile.write("<p><label>Solution:</label> %s</p>" % nl2br(answerform))    for k,v in formula["inputs"].iteritems():      self.wfile.write("<input type=\"hidden\" name=\"%s_%i\" value=\"%s\">" % (k, inc.next(), str(v)))    if template_id != None:      self.wfile.write("<input type=\"hidden\" name=\"template_id\" value=\"%i\">" % template_id)    self.wfile.write("<p><input type=\"submit\" value=\"Check\"> - <a href=\"/\">Skip</a></p>")    self.wfile.write("</form><span style=\"float:right\"><a href=\"/templates\">View Templates</a> - <a href=\"/formulae\">View Previous Problems</a></span></body></html>")    def writeFormulaList(self):    self.send_response(200)    self.send_header("Content-type", "text/html")    self.end_headers()        self.wfile.write("<html><head><title>Previous Problems</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" /></head>")    self.wfile.write("<body><div id=\"wrapper\"><h1>Previous Problems</h1><table><thead><tr><th>ID</th><th>Formula</th><th>Inputs</th><th>Problem</th><th>Solution</th></tr></thead><tbody>")    for i,formula in enumerate(formulae):      self.wfile.write("<tr><td><a href=\"/formulae/%i\">%i</a></td><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>" % (i, i, nl2br(cgi.escape(formula["template"]["formula"])), "<br>".join(tuple("<strong>%s =</strong> %s" % (cgi.escape(k), cgi.escape(str(v))) for k,v in formula["inputs"].items())), nl2br(cgi.escape(formula["template"]["problem"])), formula["solved"] and nl2br(cgi.escape(formula["solution"])) or "<a href=\"/formulae/%i\" style=\"color:red\">Not solved</a>" % i))    self.wfile.write("</tbody></table><a href=\"/\" style=\"float:right\">Back</a></div></body></html>")    def writeTemplateList(self):    self.send_response(200)    self.send_header("Content-type", "text/html")    self.end_headers()        self.wfile.write("<html><head><title>Formula Templates</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" /></head>")    self.wfile.write("<body><h1>Formula Templates</h1><table><thead><tr><th>ID</th><th>Name</th><th>Input Generation Function</th><th>Formula</th><th>Problem</th><th>Solution Template</th><th>Solution Checking Function</th><th>Disabled?</th><th>Test</th></tr></thead><tbody>")    for i,formula_template in enumerate(formula_templates):      self.wfile.write("<tr><td><a href=\"/templates/%i\">%i</a></td><td><a href=\"/templates/%i\">%s</a></td><td><code>%s</code></td><td>%s</td><td>%s</td><td>%s</td><td><code>%s</code></td><td>%s</td><td><a href=\"/templates/%i/test\">Go</a></td></tr>" % (i, i, i, cgi.escape(formula_template["name"]), nl2br(cgi.escape(formula_template["generateInputs"])), nl2br(cgi.escape(formula_template["formula"])), nl2br(cgi.escape(formula_template["problem"])), nl2br(cgi.escape(formula_template["resultTemplate"])), nl2br(cgi.escape(formula_template["checkResult"])), formula_template["disabled"] and "<span style=\"color:red\">Yes</a>" or "<span style=\"color:green\">No</a>", i))    self.wfile.write("</tbody></table>")    self.wfile.write("<form action=\"/templates/new\" method=\"POST\"><input type=\"submit\" value=\"New Template\"></form>")    self.wfile.write("<a href=\"/\" style=\"float:right\">Back</a></body></html>")    def writeTemplateEditPage(self, id, formula_template, new=False, edited=True):    self.wfile.write("<html><head><title>Template #%i - %s</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" /></head>" % (id, formula_template["name"]))    self.wfile.write("<body><div id=\"wrapper\"><h1>Template #%i - %s</h1><form action=\"/templates/%i/edit\" method=\"POST\">" % (id, formula_template["name"], id))    if new:      self.wfile.write("<p style=\"color:green;font-weight:bold;\" onclick=\"this.style.display='none'\">New template.</p>")    if edited:      self.wfile.write("<p style=\"color:green;font-weight:bold;\" onclick=\"this.style.display='none'\">Successfully edited.</p>")    self.wfile.write("<p><label>Name:</label> <input type=\"text\" name=\"name\" value=\"%s\"></p>" % cgi.escape(formula_template["name"]))    self.wfile.write("<p><label>Input Generation Function:</label> <textarea name=\"generateInputs\">%s</textarea></p>" % cgi.escape(formula_template["generateInputs"]))    self.wfile.write("<p><label>Formula:</label> <textarea name=\"formula\">%s</textarea></p>" % cgi.escape(formula_template["formula"]))    self.wfile.write("<p><label>Problem:</label> <textarea name=\"problem\">%s</textarea></p>" % cgi.escape(formula_template["problem"]))    self.wfile.write("<p><label>Solution Template:</label> <textarea name=\"resultTemplate\">%s</textarea></p>" % cgi.escape(formula_template["resultTemplate"]))    self.wfile.write("<p><label>Solution Checking Function:</label> <textarea name=\"checkResult\">%s</textarea></p>" % cgi.escape(formula_template["checkResult"]))    self.wfile.write("<p><label>Disabled:</label> <input type=\"checkbox\" name=\"disabled\" %s value=\"yes\"></p>" % (formula_template["disabled"] and "checked" or ""))    self.wfile.write("<p><input type=\"submit\" value=\"%s\"> <input type=\"submit\" name=\"test\" value=\"Test\"></p>" % (new and "Create" or "Edit"))    self.wfile.write("</form><a href=\"/templates\" style=\"float:right\">Back</a></div></body></html>")    def writeCorrectResult(self):    self.send_response(200)    self.send_header("Content-type", "text/html")    self.send_header("Refresh", "5;url=/")    self.end_headers()        self.wfile.write("<html><head><title>Correct Solution!</title><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" /></head>")    self.wfile.write("<body><div id=\"wrapper\"><h1>Correct Solution!</h1><p><a href=\"/\">Click here</a> to go on to the next question.</p></div></body></html>")    def writeCSS(self):    self.send_response(200)    self.send_header("Content-type", "text/css")    self.end_headers()    self.wfile.write("body{text-align:center;min-width:40%;} #wrapper{text-align:left;width:40%;margin-left:auto;margin-right:auto;} form p{width:40%;clear:left;margin:0;padding:5px 0 8px 0;padding-left:155px;border-top:1px dashed gray;min-height:2em;} form label{font-weight:bold;float:left;margin-left:-155px;width:150px;} form input[type=\"text\"]{width:180px;} form textarea{width:250px;height:150px;white-space:nowrap;overflow:auto;}")try:  f = file("templates.pickle", "r")  formula_templates = pickle.load(f)  f.close()except:  saveFormulaTemplates()try:  f = file("formulae.pickle", "r")  formulae = pickle.load(f)  f.close()except:  saveFormulae()if __name__ == '__main__':  server_class = BaseHTTPServer.HTTPServer  httpd = server_class((HOST_NAME, PORT_NUMBER), MathHelperRequestHandler)  print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER)  httpd.serve_forever()  httpd.server_close()  print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER)