This is the third installment of this type of notes. Two down (4, 6), two more to go (5, 7).
I hope you're going through these notes in the order I wrote them: 4, 6, now 2, then 5 and 7.
This problem asks that we solve the Flag Quiz using CGI and either Perl or Python.
I suggest we use Python with hidden fields (Homework Two) and Perl for Homework Five.
As you recall, Homework Five is a variant of Homework Two where state is kept server-side (instead of client-side).
As far as the problem per se, we all know it: it's described in the text on page 32.
The text is the .pdf we have been using since the beginning of the semester:
The state needs to be kept client-side for this homework assignment.http://www.cs.indiana.edu/~dgerman/eowp06.pdf
Images are located in the same place:
Every time we work out a problem like this we can apply our template.http://silo.cs.indiana.edu:11350/images/
First step is to determine what our state is made of.
The following are immediate candidates (as we already know):
The inputs also need to be discussed:
So I guess we have what we need to get started.
Let's do this in Python, and trying to match our Homework Four (PHP) development.
<? ?> <form> </form> | #!/usr/bin/python
print "Content-type: text/html\n\n"
print """
<form>
</form>
""" |
Basically this includes a code portion, along with a "get ready for more input" portion.
So we see more needs to be done in Python to get the same thing(s) done.
As a matter of fact the following also need to be added:
a) load the module that implements the common gateway interface:
b) create an object that contains the incoming data, parsed:import cgi
c) initialize the five state variables and one input variable:q = cgi.FieldStorage()
d) read their values (retrieve state, read input):(message, questions, key, correct, total, answer) = ("", "", "", "", "", "")
We sketch more of the basic layout:if q.has_key("message") : message = q["message"].value if q.has_key("questions"): questions = q["questions"].value if q.has_key("key") : key = q["key"].value if q.has_key("correct") : correct = q["correct"].value if q.has_key("total") : total = q["total"].value if q.has_key("answer") : answer = q["answer"].value
if ($message) {
} else {
$message = "Welcome to the game, are you ready?";
}
| if message: pass else: message = "Welcome to the game, are you ready?" |
We also enhance the content of the form as well (as expected the code on the right is partial):
<?=$message?> <p> Press <input type="submit" value="Proceed"> to move on. <input type="hidden" name="message" value="<?=$message?>"> | %s <p>
Press <input type="submit" value="Proceed"> to move on.
<input type="hidden" name="message" value="%s">
</form>
""" % (message, message) |
Obviously, we are just acknowledging the initialization of $message.
Perhaps this would be a good time to approach state initialization in general:
$correct = 0;
$total = 0;
$questions = "Italy," .
"Australia," .
"United States," .
"South Africa," .
"Spain,China," .
"Russia," .
"Brazil";
$key = ""; // there is no key in the beginning |
correct = 0
total = 0
questions = "Italy," + \
"Australia," + \
"United States," + \
"South Africa," + \
"Spain," + \
"China," + \
"Russia," + \
"Brazil"
key = "" # there is no key in the beginning
|
Let's decide to save the state on the client side:
<input type="hidden" name="correct" value="<?=$correct?>"> <input type="hidden" name="total" value="<?=$total?>"> <input type="hidden" name="questions" value="<?=$questions?>"> <input type="hidden" name="key" value="<?=$key?>"> | <input type="hidden" name="questions" value="%s">
<input type="hidden" name="key" value="%s">
<input type="hidden" name="correct" value="%s">
<input type="hidden" name="total" value="%s"> |
In Python this is a two-step process, the second part of which includes:
""" % (message, message, questions, key, correct, total) |
Now let's make some changes. Add (at the top of the code part) these definitions:
This was in PHP, in Python that becomes:$url = "http://www.cs.indiana.edu/classes/a202-dger/fall2005/notes/flagquiz/images"; $names = array ("Australia", "United States", "Russia", "Spain", "Italy", "South Africa", "Brazil", "China");
We really need the square brackets here, the round ones won't do, you will see why.url = "http://www.cs.indiana.edu/classes/a202-dger/fall2005/notes/flagquiz/images" names = ["Australia", "United States", "Russia", "Spain", "Italy", "South Africa", "Brazil", "China"]
Also modify the line that initializes $questions too:
That was in PHP, in Python it becomes:$questions = join(",", $names);
This way we leave ourselves open to the idea of shuffling, initially.questions = ",".join(names)
We should now take care of the user submissions coming after the initial screen.
In Python that becomes:if ($key) { if ($answer == $key) { $correct += 1; } else { } $total += 1; } else { }
Next we need to grab the answer key that follows from the remaining questions:if key: if answer == key: correct = str(int(correct) + 1) else: pass total = str(int(total) + 1) else: pass
In Python that becomes:list($key, $questions) = split(",", $questions, 2);
At the same time we need to update the message, and be ready to ask questions. So we have:names = questions.split(",") (key, questions) = (names[0], ",".join(names[1:]))
Update the message if the answer is correct:
In Python that becomes:$message = "Very good.";
Update the message if the answer is incorrect:message = "Very good."
In Python that becomes:$message = "No, that was not it.";
Update the message with the new values of the score:message = "No, that was not it"
In Python that becomes:$message .= " Score currently: $correct out of $total.";
Prepare the question you want to ask:message += " Score currently: " + correct + " out of " + total + "."
In Python that becomes:$question = "Whose country is this flag: <img src='$url/$key.png'> <input type=text name='answer'> <p>";
Show the question and get ready for (more) user input:question = "Whose country is this flag: <img src='%s/%s.png'> <input type=text name='answer'> <p>" % (url, key)
In Python that becomes:<?=$question?>
... followed (in the right place) by something like this:%s
Also, don't forget to initialize question so you can show it on the first screen:""" % (message, question, ...
Now the program works almost as intended, except at the end of the quiz.... answer, question) = ("", "", "", "", "", "", "")
So we need to not ask a new question if we are not able to:
In Python that becomes:if ($questions) { // ... } else { $question = "The game has ended, new game starting, are you ready? <p>"; $correct = 0; $total = 0; $questions = join(",", $names); $key = ""; // there is no key in the beginning }
Furthermore we need to tie seamlessly into the next game.if questions: # ... else: question = "The game has ended, new game starting, are you ready? <p>"; correct = 0; total = 0; questions = ",".join(names) key = ""; # there is no key in the beginning
In Python that becomes:$message = "Welcome to a new game, score currently: $correct out of $total.";
That goes into a previously empty branch of the program.message = "Welcome to a new game, score currently: " + correct + " out of " + total + "."
This is what we have obtained:
What remains to be done:http://silo.cs.indiana.edu:11350/cgi-bin/1118/one
These are very simple things.
A. To shuffle the array you need to invoke the following with each initialization:
You can check withshuffle($names);
php.net on the use of shuffle. You need to shuffle the array each time you initialize or re-initialize the code.
In Python that becomes:
Of course, you also need this:random.shuffle(names)
B. To add a reset button you do two things:import random
B.1) Add the button to the form:
In Python that is entirely identical.Press <input type="submit" name="reset" value="Reset"> to reset the game.
B.2) Change the condition in the outer if to:
In Python that becomes:if ($message && ! $reset) {
Also, this, again:if message and not reset:
And:... answer, question, reset) = ("", "", "", "", "", "", "", "")
C. Finally, to switch from client-side state to server-side state: becomes Homework Five (soon to come).if q.has_key("reset") : reset = q["reset"].value