Abstract. This is a demo CGI program written in Scheme, and using the LAML libraries
for CGI programming and the LAML HTML mirror for Scheme. The game is operational, and it can be played from here if you are connected to the Internet. |
the-game-sect 1 The Game We first describe the game. |
1.1 The Game |
the-game 1.1 The Game |
design-sect 2 The overall design Although this program is simple and small we have used a structure which, in some respects at least, can be used for larger and more realistic CGI programs. |
2.1 The overall design |
design 2.1 The overall design |
#!/bin/sh string=? ; exec /pack/mzscheme/bin/mzscheme -r $0 "$@" ;; This program implements a number guessing game, ;; which is commonly used to illustrate simple WWW ;; server programming. (load "/user/normark/scheme/tools/number-guess/number-guess.scm")The name of the file must be number-guess.cgi, and it should be file protected to be executable (typically with chmod 755).
This starts MzScheme via a shell script, and the load line is executed. It would be perfectly possible to place the entire Scheme program here, but we prefer in general to organize our software in a directory outside the .public_html catalogue. Therefore I load the number guessing program from the tools/number-guess directory in my LAML development directory, which happens to be /normark/scheme.
As another important point, we decide to organize the number guessing
system as a single program, which in the page-write
part branches between a game init part () and a game
playing part (). We could as well have written two separate CGI programs,
which probably would have been preferable in case the 'System' is larger.
(This would typically call for common definitions organized in a shared scheme
number guessing libary file).
the-program-sect 3 The Program In this section we describe the number guessing program details. |
3.1 The preamble part 3.2 The init game part 3.3 The game part |
preamble-part 3.1 The preamble part |
We first see kn-laml-dir, which is a variable that points at my laml directory, in which this software resides. In reality it is not used, but in general it isuseful to have variable that points to the source file directory, here source-directory (defined via kn-laml-dir).
laml-dir is important, because it's value points at the root of the LAML system, which is used. Using the program at cs.auc.dk it is natural to use the shared LAML system in /pack/laml/. Alternatively, normark's /user/normark/scheme can be used (which is the LAML development system).
The variable number-guess-url-prefix and not least the derived function number-guess-url are used to address the number guessing program from a browser. The function returns an URL with actual URL parameters - following the question mark. The function make-url-parameters is from the cgi LAML library, and it makes a list of actual URL parameters. We will meet the function number-guess-url later on.
Next comes the loading part of the program. Here laml.scm is loaded from the designated
laml-dir, and a number of other libraries are loaded. In this context, the most important are the cgi.scm
libraray () and the encode-decode.scm library (), which is used by cgi.scm.
In other-settings we set the variable cgi-testing to #f and we register the current
time in cur-time. The time is not used in this program, but it general this number is useful for
a variety of purposes (such as making file names 'unique').
In the section url-parameters we extract the URL parameters passed to the program.
The variable language-preference controls whether danish or english is used in the game, with english as the default.
The function text-choice uses the variable language-preference.
The variable mode is important because it controls the part of the program to be started; Possible values are
the symbols init or play, with init as the default. The function defaulted-get is a function from the LAML general library.
The CGI library function extract-url-parameters
decodes the URL parameters.
The variable url-pars is an association list (a list of cons pairs), such as
((language . "english") (mode . "init"))
This ends the game preamble part.
init-game 3.2 The init game part |
Also notice the form element, generated by form-1 at (). This
determines the program which will receive form input when
submitted. Thus, when we submit a new guess this detail determines the
receiving CGI program. Here, we reuse the same program for this
purpose (possible due the outer branching discussed above), but notice
that we switch to play mode. We pass the language-preference on as the
language parameter.
After a welcome text we call guess-part (), which renders the form used for the user's guess.
Let us now look at guess-part, which returns part of the body. The function text-line renders
an input field, in which the guess can be entered (). The secret number is passed on using
a hidden field (). In a better version of the program we should protect this field from being
read directly in the document source. The submit button is also made in this function ().
game-part 3.3 The game part |
We first have to extract the submitted form input. This is done by extract-form-input
from the CGI library (), which returns an association list such as
((secret-number . "42") (players-guess . "22"))
We prepare a body with a new form element (as above) (). The conditional ()
compares the secret number with the players guess, and an appropriate hint is presented.
Notice how guess-part is activated if no exact hit is found ( ). In the
lucky case where the player guesses the number an URL is given to restart the game ().