# # MathPoc : Proof of concept of a simple math problem, bringing it to the browser # # Alex Boschmans # # Version 0.2, February 2011 # # 0.2 Added some error checks and expanded math to not just adding but also # subtraction and multiplication and divisions. Extensively commented code. header = """ MATH Proof of Concept """ footer = "" indexhtml = """

Math Proof of Concept

Please answer the following question

How much is %d %s %d ?

Answer:
""" def generatequestion(): # This generates the question that we will pose using the random function # Generate a random question using 2 random numbers between 1 and 10 number1 = random.randint(1,10) number2 = random.randint(1,10) # Now we choose an operatioin ops = ["+", "-", "x", "/"] operation = random.choice(ops) # Let's check the division if operation == "/": # Prevent divisions with remainders using the modulo operator # Using module on the two numbers evaluates to 0 when no remainder is present # While the modulo remainder is not equal to 0, generate two new numbers while number1 % number2 <> 0: number1 = random.randint(1,10) number2 = random.randint(1,10) # Assemble the html, inputting the numbers in the foreseen places in the html # In a more extensive project, you would keep this html in a template file and # call it with a dictionary of items that need to be filled in the template question = indexhtml % (number1, operation, number2, number1, number2, operation) # Add common html like header and footer - these are defined just once and reused # for each page html = header + question + footer # Return the completed html to the calling function (in this case index) return html # This is the class that the cherrypy server uses and where you create the views that the # webuser sees. After each definition there is a .exposed=True that indicates if the # webuser can see this page or not. class MathPoc: def index(self): # This is the main index page that is shown to the user when he first visits the site. # We create the page by calling the function generatequestion (which is outside the class # MathPoc but accessible and we show it to the user by 'return'ing the page page = generatequestion() return page # The webuser will now see the page and will have a chance to enter an answer. # In the html form I've specified that the submitted result will go to the url "response" # I've added all the values I want to receive either as hidden values (eg the # original numbers, the operation) or as part of the form (eg the answer) index.exposed = True def response(self, answer, number1, number2, operation): # First check if we received an answer or if the user submitted without an answer if answer: # Calculate our own answer ourselves and generate a response to the user # We receive strings, so convert them to integers using int() number1 = int(number1) number2 = int(number2) answer = int(answer) # Answer is dependent on operation if operation == "+": solution = number1 + number2 elif operation == "-": solution = number1 - number2 elif operation == "x": solution = number1 * number2 else: solution = number1 / number2 # See if the answer is correct and display according the result # Using templates, you could put all this in one template and # call the template with options so it knows what to show if solution <> answer: html = """

Sorry.

The question was : %s %s %s = ?

Your answer %s is wrong. The correct answer is %d.

Try Again.

""" % (number1, operation, number2, answer, solution) else: html = """

Correct !

The question was : %s %s %s = %s

Your answer is correct !

Try Again.

""" % (number1, operation, number2, answer) else: # We did not receive an answer html = """

Sorry ?

You need to fill in an answer !

Try Again.

""" # Return the page to the user, adding the common html return header + html + footer response.exposed = True if __name__ == '__main__': import random import cherrypy import os, sys # Set the current directory - this is probably not needed for this example, cruft. try: current_dir = os.path.dirname(os.path.abspath(__file__)) except: # probably running inside py2exe which doesn't set __file__ current_dir = os.path.dirname(unicode(sys.executable, sys.getfilesystemencoding( ))) # Set up site-wide config first so we get a log if errors occur. # Adding the setting 'environment': 'production' to the below turns off auto-reload. # Otherwise CherryPy monitors the code and any change to code reloads the server - handy for development ! cherrypy.config.update({'server.socket_port':8888, 'server.socket_host':'127.0.0.1', 'log.error_file': 'site.log', 'log.screen': True}) # CherryPy will complain of an empty config but will continue conf = {} cherrypy.tree.mount(MathPoc()) #cherrypy.config.update({'server.socket_port':8888}) cherrypy.quickstart(MathPoc(),'/', config=conf)