rendered paste bodyimport 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)