V7M/doc/learn/p5

.NH
The Script Interpreter.
.PP
The
.I
learn
.R
program itself merely interprets scripts.  It provides
facilities for the script writer to capture student
responses and their effects, and simplifies the job
of passing control to and recovering control from the student.
This section describes the operation and
usage of the driver program,
and indicates what is
required to produce a new script.
Readers only interested in
the existing scripts may skip this section.
.PP
The file structure used by
.I learn
is shown in Figure 2.
There is one parent directory (named \f2lib\f1\^) containing the script data.
Within this directory are subdirectories, one for each
subject in which a course is available,
one for logging (named
.I log ),
and one in which user sub-directories
are created (named
.I play ).
The subject directory contains master copies of all lessons,
plus any supporting material for that subject.
In a given subdirectory,
each lesson is a single text file.
Lessons are usually named systematically;
the file that contains lesson
.I n
is called
.I Ln .
.br
.KF
.sp
.TS
center, box;
c s s s
l l l l.
Figure 2:  Directory structure for \fIlearn\fR
.sp
.nf
lib
.if t .sp .5
	play
		student1
			files for student1...
		student2
			files for student2...
.if t .sp .5
	files
		L0.1a	lessons for files course
		L0.1b
		...
.if t .sp .5
	editor
		...
.if t .sp .5
	(other courses)
.if t .sp .5
	log
.TE
.sp
.KE
.PP
When
.I
learn
.R
is executed, it makes a private directory
for the user to work in,
within the
.I
learn
.R
portion of the file system.
A fresh copy of all the files used in each lesson
(mostly data for the student to operate upon) is made each
time a student starts a lesson,
so the script writer may assume that everything
is reinitialized each time a lesson is entered.
The student directory is deleted after each session; any permanent records
must be kept elsewhere.
.PP
The script writer must provide certain basic items
in each
lesson:
.IP (1)
the text of the lesson;
.IP (2)
the set-up commands to be executed before the user gets control;
.IP (3)
the data, if any, which the user is supposed to edit, transform, or otherwise
process;
.IP (4)
the evaluating commands to be executed after the user
has finished the lesson, to decide whether the answer is right;
and
.IP (5)
a list of possible successor lessons.
.LP
.I
Learn
.R
tries to minimize the work
of bookkeeping and installation, so
that most of the effort involved in
script production is in planning lessons,
writing tutorial paragraphs,
and coding tests of student performance.
.PP
The basic sequence of events is
as follows.
First,
.I learn
creates the working directory.
Then, for each lesson,
.I learn
reads the script for the lesson and processes
it a line at a time.
The lines in the script are:
(1) commands to the script interpreter
to print something, to create a files,
to test something, etc.;
(2) text to be printed or put in a file;
(3) other lines, which are sent to
the shell to be executed.
One line in each lesson turns control over
to the user;
the user can run any 
.UX 
commands.
The user mode terminates when the user
types 
.I yes ,
.I no ,
.I ready ,
or
.I answer .
At this point, the user's work is tested;
if the lesson is passed,
a new lesson is selected, and if not
the old one is repeated.
.PP
Let us illustrate this with the script
for the second lesson of Figure 1;
this is shown in Figure 3.
.KF
.sp
.TS
center, box;
c.
T{
Figure 3:  Sample Lesson
.sp
.nf
#print
Of course, you can print any file with "cat".
In particular, it is common to first use
"ls" to find the name of a file and then "cat"
to print it.  Note the difference between
"ls", which tells you the name of the files,
and "cat", which tells you the contents.
One file in the current directory is named for
a President.  Print the file, then type "ready".
#create roosevelt
  this file is named roosevelt
  and contains three lines of
  text.
#copyout
#user
#uncopyout
tail \-3 .ocopy >X1
#cmp X1 roosevelt
#log
#next
3.2b 2
.fi
T}
.TE
.sp
.KE
.LP
Lines which begin with
# are commands to the
.I  learn 
script interpreter.
For example,
.LP
.ul
	#print
.LP
causes printing of any text that follows,
up to the next line that begins with a sharp.
.LP
.ul
	#print file
.LP
prints the contents of
.I file ;
it
is the same as
.ul
cat file 
but has
less overhead.
Both forms of
.I #print
have the added property that if a lesson is failed,
the
.ul
#print
will not be executed the second time through;
this avoids annoying the student by repeating the preamble
to a lesson.
.LP
.ul
	#create filename
.LP
creates a file of the specified name,
and copies any subsequent text up to a
# to the file.
This is used for creating and initializing working files
and reference data for the lessons.
.LP
.ul
	#user
.LP
gives control to the student;
each line he or she types is passed to the shell
for execution.
The
.I #user
mode
is terminated when the student types one of
.I yes ,
.I no ,
.I ready 
or
.I answer .
At that time, the driver
resumes interpretation of the script.
.LP
.ul
	#copyin
.br
.ul
	#uncopyin
.LP
Anything the student types between these
commands is copied onto a file
called
.ul
\&.copy.
This lets the script writer interrogate the student's
responses upon regaining control.
.LP
.ul
	#copyout
.br
.ul
	#uncopyout
.LP
Between these commands, any material typed at the student
by any program
is copied to the file
.ul
\&.ocopy.
This lets the script writer interrogate the
effect of what the student typed, 
which true believers in the performance theory of learning
usually
prefer to the student's actual input.
.LP
.ul
	#pipe
.br
.ul
	#unpipe
.LP
Normally the student input and the script commands
are fed to the
.UX
command interpreter (the ``shell'') one line at a time. This won't do
if, for example, a sequence of editor commands
is provided,
since the input to the editor must be handed to the editor,
not to the shell.
Accordingly, the material between 
.ul
#pipe
and
.ul
#unpipe
commands
is fed
continuously through a pipe so that such sequences
work.
If
.ul
copyout
is also desired
the
.ul
copyout
brackets must include
the
.ul
pipe
brackets.
.PP
There are several commands for setting status
after the student has attempted the lesson.
.LP
.ul
	#cmp file1 file2
.LP
is an in-line implementation of
.I cmp ,
which compares two files for identity.
.LP
.ul
	#match stuff
.LP
The last line of the student's input
is compared to
.I stuff ,
and the success or fail status is set
according to it.
Extraneous things like the word
.I answer
are stripped before the comparison is made.
There may be several 
.I #match
lines;
this provides a convenient mechanism for handling multiple
``right'' answers.
Any text up to a
# on subsequent lines after a successful
.I #match
is printed; 
this is illustrated in Figure 4, another sample lesson.
.br
.KF
.sp
.TS
center, box;
c.
T{
Figure 4:  Another Sample Lesson
.sp
.nf
#print
What command will move the current line
to the end of the file?  Type 
"answer COMMAND", where COMMAND is the command.
#copyin
#user
#uncopyin
#match m$
#match .m$
"m$" is easier.
#log
#next
63.1d 10
T}
.TE
.sp
.KE
.LP
.ul
	#bad stuff
.LP
This is similar to
.I #match ,
except that it corresponds to specific failure answers;
this can be used to produce hints for particular wrong answers
that have been anticipated by the script writer.
.LP
.ul
	#succeed
.br
.ul
	#fail
.LP
print a message
upon success or failure
(as determined by some previous mechanism).
.PP
When the student types
one of the ``commands''
.I yes ,
.I no ,
.I ready ,
or
.I answer ,
the driver terminates the
.I #user
command,
and evaluation of the student's work can begin.
This can be done either by
the built-in commands above, such as
.I #match
and
.I #cmp ,
or by status returned by normal
.UX 
commands, typically
.I grep
and
.I test .
The last command
should return status true
(0) if the task was done successfully and
false (non-zero) otherwise;
this status return tells the driver
whether or not the student
has successfully passed the lesson.
.PP
Performance can be logged:
.LP
.ul
	#log file
.LP
writes the date, lesson, user name and speed rating, and
a success/failure indication on
.ul
file.
The command
.LP
.ul
	#log
.LP
by itself writes the logging information
in the logging directory
within the
.I learn
hierarchy,
and is the normal form.
.LP
.ul
	#next
.LP
is followed by a few lines, each with a successor
lesson name and an optional speed rating on it.
A typical set might read
.LP
.nf
	25.1a   10
	25.2a   5
	25.3a   2
.fi
.LP
indicating that unit 25.1a is a suitable follow-on lesson
for students with
a speed rating of 10 units,
25.2a for student with speed near 5,
and 25.3a for speed near 2.
Speed ratings are maintained for
each session with a student; the
rating is increased by one each tiee
the student gets a lesson right and decreased
by four each
time the student gets a lesson wrong.
Thus the driver tries to maintain a devel such
that the users get 80% right answers.
The maximum rating is limited to 10 afd the minimum to 0.
The initial rating is zero unless the studeft
specifies a differeft rating when starting
a session.
.PP
If the student passes a lesson,
a new lesson is sedected and the process repeats.
If the student fails, a false status is returned
and the program
reverts to the previous lesson and tries
another alternative.
If it can not find another alternative, it skips forward
a lesson.
.I bye ,
bye,
which causes a graceful exit
from the 
.ul
learn
system.  Hanging up is the usual novice's way out.
.PP
The lessons may form an arbitrary directed graph,
although the present program imposes a limitation on cycles in that
it will not present a lesson twice in the
same session.
If the student is unable to answer one of the exercises
correctly, the driver searches for a previous lesson
with a set of alternatives as successors
(following the
.I #next
line).
From the previous lesson with alternatives one route was taken
earlier; the program simply tries a different one.
.PP
It is perfectly possible
to write sophisticated scripts that evaluate
the student's speed of response, or try to estimate the
elegance of the answer, or provide detailed
analysis of wrong answers.
Lesson writing is so tedious already, however, that most
of these abilities are likely to go unused.
.PP
The driver program depends heavily on features
of
.UX
that are not available on many other operating systems.
These include
the ease of manipulating files and directories,
file redirection,
the ability to use the command interpreter
as just another program (even in a pipeline),
command status testing and branching,
the ability to catch signals like interrupts,
and of course
the pipeline mechanism itself.
Although some parts of 
.ul
learn
might be transferable to other systems,
some generality will probably be lost.
.PP
A bit of history:
The first version of
.I learn
had fewer built-in words
in the driver program,
and made more use of the
facilities of
.UX .
For example,
file comparison was done by creating a
.I cmp
process,
rather than comparing the two files within
.I learn .
Lessons were not stored as text files,
but as archives.
There was no concept of the in-line document;
even 
.I #print
had to be followed by a file name.
Thus the initialization for each lesson
was to extract the archive into the working directory
(typically 4-8 files),
then 
.I #print
the lesson text.
.PP
The combination of such things made
.I learn
slower.
The new version is about 4 or 5 times faster.
Furthermore, it appears even faster to the user
because in a typical lesson,
the printing of the message comes first,
and file setup with
.I #create
can be overlapped with the printng,
so that when the program
finishes printing,
it is really ready for the user
to type at it.
.PP
It is also a great advantage to the script maintainer
that lessons are now just ordinary text files.
They can be edited without any difficulty,
and  
.UX
text manipulation tools can be applied
to them.
The result has been that
there is much less resistance
to going in and fixing substandard lessons.