Today we start from the code we developed for Monday's class. Here's the template.py file: import cgi #-------------------(this is template.py)-------------- class Engine(object): def __init__(self): # print "New engine created." self.input = cgi.FieldStorage() def execute(self): s = self.retrieveState() if s.isEmpty() or self.reset(): self.initializeState(s) else: self.updateState(s) self.saveState(s) self.reportState(s) self.getReadyforMoreInput() def retrieveState(self): return State() def initializeState(self, s): pass def saveState(self, s): pass def reportState(self, s): pass def getReadyforMoreInput(self): pass def reset(self): return False class State(object): def isEmpty(self): return True #------------------------------(end of template.py)---------------- Here's the actual driver for the engine, file is called one: #!/usr/bin/python import template, random class One(template.Engine): def __init__(self): template.Engine.__init__(self) def retrieveState(self): # print "I am retrieving state..." (message, n1, n2, m1, m2) = ("", "", "", "", "") if self.input.has_key("message"): message = self.input["message"].value if self.input.has_key("n1"): n1 = self.input["n1"].value if self.input.has_key("n2"): n2 = self.input["n2"].value if self.input.has_key("m1"): m1 = self.input["m1"].value if self.input.has_key("m2"): m2 = self.input["m2"].value return MyState(message, n1, n2, m1, m2) def reset(self): reset = "" if self.input.has_key("reset"): reset = self.input["reset"].value return reset def initializeState(self, s): # print "I am being asked to initialize the state..." s.message = "Welcome" s.n1 = str(random.randrange(-50, 50)) s.n2 = str(random.randrange(-50, 50)) s.m1 = "0" s.m2 = "0" def updateState(self, s): # print "I am being asked to update the state based on input..." answer = "" if self.input.has_key("answer"): answer = self.input["answer"].value if answer and int(answer) == int(s.n1) + int(s.n2): s.message = "Very good." s.m1 = str(int(s.m1) + 1) else: s.message = "No, no, no." s.m2 = str(int(s.m2) + 1) s.message += "Score now: " + s.m1 + " out of " + s.m2 s.n1 = str(random.randrange(-50, 50)) s.n2 = str(random.randrange(-50, 50)) def saveState(self, s): print "
" print "" print "" print "" print "" print "" def reportState(self, s): print s.message + "

" print "What is " + s.n1 + " + " + s.n2 + "?" def getReadyforMoreInput(self): print "Answer:

" print "" print "" print "

" class MyState(template.State): def __init__(self, message, n1, n2, m1, m2): self.message = message self.n1 = n1 self.n2 = n2 self.m1 = m1 self.m2 = m2 def isEmpty(self): # print "I am being asked if I am empty..." return not self.message print "Content-type: text/html\n\n" # [1] one = One() # [2] one.execute() # [3] #------------------------(end of client side state driver)-------------- We are going to develop this into a server-side state program, as follows: a) replace the lines [1], [2], [3] above with: class Two(One): pass print "Content-type: text/html\n\n" driver = Two() driver.execute() b) now when you call the driver (one) it's an instance of type Two that's driving c) we will replace some of the methods in One (overriding them): -- retrieveState -- saveState d) we will also add a few methods in support of these ones. The most notable need is that of having session IDs. Session IDs will need to be kept somewhere. We create a table in database homeworkThree (or any other you want). My table is called hwFour. Call yours whatever you want but keep track of that and adjust the instructions accordingly. This is the basic SQL with which I created my table: mysql> create table hwFour ( -> session_id char(8) primary key, -> message varchar(240), -> n1 int, -> n2 int, -> m1 int, -> m2 int, -> modified timestamp -> ); Here's how I did it: -bash-3.2$ cd /nobackup/ -bash-3.2$ cd dgerman/ -bash-3.2$ cd mysql-5.0.22 -bash-3.2$ pwd /nobackup/dgerman/mysql-5.0.22 That is, I first moved into the right folder, then issued the right command: -bash-3.2$ ./connect_aslbird Enter password: Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 17 Server version: 5.0.22-log Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | homeworkThree | | test | +--------------------+ 3 rows in set (0.18 sec) mysql> use homeworkThree; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> create table hwFour ( -> session_id char(8) primary key, -> message varchar(240), -> n1 int, -> n2 int, -> m1 int, -> m2 int, -> modified timestamp -> ); Query OK, 0 rows affected (0.01 sec) mysql> show tables; +-------------------------+ | Tables_in_homeworkThree | +-------------------------+ | enrollment | | hwFour | +-------------------------+ 2 rows in set (0.00 sec) mysql> describe hwFour; +------------+--------------+------+-----+-------------------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+-------------------+-------+ | session_id | char(8) | NO | PRI | | | | message | varchar(240) | YES | | NULL | | | n1 | int(11) | YES | | NULL | | | n2 | int(11) | YES | | NULL | | | m1 | int(11) | YES | | NULL | | | m2 | int(11) | YES | | NULL | | | modified | timestamp | YES | | CURRENT_TIMESTAMP | | +------------+--------------+------+-----+-------------------+-------+ 7 rows in set (0.04 sec) mysql> select * from hwFour; Empty set (0.00 sec) mysql> Here's how we could insert a new session ID (if we had one) in this table: mysql> insert into hwFour (session_id) values ("1234abcd"); Query OK, 1 row affected (0.01 sec) mysql> select * from hwFour; +------------+---------+------+------+------+------+---------------------+ | session_id | message | n1 | n2 | m1 | m2 | modified | +------------+---------+------+------+------+------+---------------------+ | 1234abcd | NULL | NULL | NULL | NULL | NULL | 2009-07-06 13:24:01 | +------------+---------+------+------+------+------+---------------------+ 1 row in set (0.00 sec) mysql> Now let's start working on our new program. I present only the relevant new material. Here's the program looking for a session ID, generating one if necessary, initializing state and saving it: import MySQLdb, sys class Two(One): def retrieveState(self): if self.input.has_key("session_ID"): id = self.input["session_ID"].value print "Content-type: text/html\n\n" print "Your id is:", id, "

" self.id = id Con = MySQLdb.Connect(host="silo.cs.indiana.edu", port=44089, user="lbird", passwd="sp00n", db="homeworkThree") Cursor = Con.cursor() sql = "SELECT message, n1, n2, m1, m2 FROM hwFour WHERE session_id = '%s'" % id Cursor.execute(sql) Results = Cursor.fetchall() (message, n1, n2, m1, m2) = Results[0] Con.close() return MyState(message, n1, n2, m1, m2) else: print "Location: http://silo.cs.indiana.edu:44063/cgi-bin/0708/one?session_ID=%s\n\n" % self.generate_ID() sys.exit() def generate_ID(self): id = "" for i in range(8): id += str(random.randrange(10)) Con = MySQLdb.Connect(host="silo.cs.indiana.edu", port=44089, user="lbird", passwd="sp00n", db="homeworkThree") Cursor = Con.cursor() sql = "insert into hwFour (session_id) values ('" + id + "')" for i in range(10): if Cursor.execute(sql): Con.close() return id print "Content-type: text/html\n\nError. Please reload." Con.close() def saveState(self, s): sql = "update hwFour set message = '%s', n1 = '%s', n2 = '%s', m1 = '%s', m2 = '%s' where session_id = '%s'" % (s.message, s.n1, s.n2, s.m1, s.m2, self.id) # print "


%s
" % sql Con = MySQLdb.Connect(host="silo.cs.indiana.edu", port=44089, user="lbird", passwd="sp00n", db="homeworkThree") Cursor = Con.cursor() Cursor.execute(sql) Con.close() print "
" print "" % self.id driver = Two() driver.execute() Example: a) Calling this program with: http://silo.cs.indiana.edu:44063/cgi-bin/0708/one b) Immediately turns the url into: http://silo.cs.indiana.edu:44063/cgi-bin/0708/one?session_ID=56785825 c) The screen looks like this: +----------------------------------------+ | Your id is: 56785825 | | | | Welcome | | | | What is -5 + -6? Answer: [_______] | | | | (Proceed) (Reset) | +----------------------------------------+ d) The database looks like this: mysql> select * from hwFour; +------------+---------+------+------+------+------+---------------------+ | session_id | message | n1 | n2 | m1 | m2 | modified | +------------+---------+------+------+------+------+---------------------+ | 56785825 | Welcome | -5 | -6 | 0 | 0 | 2009-07-08 09:47:18 | +------------+---------+------+------+------+------+---------------------+ 1 row in set (0.00 sec) mysql> So we're almost there. The final programs are listed here: http://www.cs.indiana.edu/classes/a202-dger/sum2009/0707/template.txt http://www.cs.indiana.edu/classes/a202-dger/sum2009/0707/one.txt