home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
simtel
/
sigm
/
vols000
/
vol024
/
recipe.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1984-04-29
|
20KB
|
793 lines
{++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
** PROGRAM TITLE THE RECIPE SYSTEM
**
** Translated by: Raymond E. Penley from the BASIC
** version into Pascal.
**
** DATE WRITTEN: 23 FEB 1980
**
** WRITTEN FOR: Computer hobbyists
**
** PROGRAM SUMMARY:
**
** The recipe system stores recipes and retrives recipies
** by means of a numeric key that represents the foods
** used in the meal. Foods are divided into four
** categories according to their nutritional value.
** For more comments see the original program.
**
** INPUT AND OUTPUT FILES:
** RCPDAT.XXX and RCPDAT.YYY
** - the DATA and the backup files
** RCPDAT.MST - the statistics file
**
** MODIFICATION RECORD:
** 28 Feb 80 -
** 2 Jun 80 -Rewritten for Pascal/Z v 3.0
** 8 Jun 80 -Rewrote SCAN
**
** ORIGINAL PROGRAM:
** T.G.LEWIS, 'THE MIND APPLIANCE'
** HAYDEN BOOK COMPANY
**
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
PROGRAM RECIPE;
CONST
default = 80; (* Default length for strings *)
str_len = 73; (* Length of a recipe line plus one char *)
StrMax = 255; (* Max Length of strings allowed *)
EOS = '|'; (* End of String marker *)
Master = 'RCPDAT.MST';
Tab20 = 20 ;
Tab15 = 15 ;
INPUT = 0; (***** PASCAL/Z ver 3.n *****)
TYPE
ALFA = STRING 10 ;
BYTE = 0..255;
LINE = string default;
Mstring = string 255 ;
DataType = record
MR, (* MaxRecords *)
CR : integer; (* Curr_Rcds *)
F1, (* current_ID *)
F2, (* backup_ID *)
date : string 14 (* last_update *)
end;
S$0 = STRING 0 ; { zero length string }
S$255 = STRING 255 ; { max string length }
VAR
adding_recipies, (* adding recipies state flag *)
comanding, (* Command mode flag *)
done (* Program execution flag *)
: boolean;
bell, (* ASCII bell char *)
ch,
command : char;
data : datatype;
End_of_File, (* End of File flag *)
End_of_Text (* End of Text flag *)
: boolean;
error_flag : BYTE;
CRT_width, (* Width of video display *)
Curr_Rcds, (* No. of current active records *)
Hash, (* Computed Index value of Recipe *)
ix, (* global indexer *)
Last, (* length of last line read *)
MaxRecords, (* Maximum records allowed *)
TTY_width (* Width of teletype device *)
: integer;
Last_update : string 14; (* date of last file update *)
matrix : packed array[1..5] of LINE;
(* File Identifiers <FID> *)
current_ID, (* Current file ID *)
backup_ID :string 14; (* Back up file ID *)
(* File descriptor <FCB> *)
stats :FILE of datatype;
{$C- [ctrl-c checking OFF]}
{$F- [floating point error checking OFF]}
{$M- [integer mult & divd checking OFF]}
(*---Required for Pascal/Z supplied string functions---*)
FUNCTION LENGTH(X: S$255): INTEGER; EXTERNAL;
PROCEDURE SETLENGTH(VAR X :S$0; Y :INTEGER); EXTERNAL;
(*----------------------------------------------*)
(* DISK I/O *)
(*----------------------------------------------*)
Procedure OPEN_MASTER;
begin
(* OPEN file RECIPE.MST for READ assign stats *)
RESET(master, stats);
READ(stats, data );
with data do begin
MaxRecords := MR;
Curr_Rcds := CR;
current_ID := F1;
backup_ID := F2;
last_update := date
end(* with *)
end;
Procedure UPDATE_MASTER;
begin
(* OPEN file RECIPE.MST for WRITE assign stats *)
REWRITE(master, stats);
with data do begin
MR := MaxRecords;
CR := Curr_Rcds;
F1 := current_ID ;
F2 := backup_ID ;
date := last_update
end(* with *);
WRITE(stats, data )
end;
Procedure GETLINE(VAR fx : TEXT;
VAR INBUFF : LINE );
{ This Procedure gets a line of text from a disk file.
Returns:
End_of_Text = true if the input buffer length
exceeded.
End_of_File = true if EOF
INBUFF = input buffer }
VAR CH : CHAR;
ix, length : integer;
begin
length := 0;
End_of_Text := FALSE;
SETLENGTH(INBUFF,0);
WHILE NOT EOF(fx) AND (CH <> EOS) DO
begin
If length < str_len then
begin(* valid *)
READ(fx, CH );
length := SUCC(length);
APPEND(INBUFF,CH)
end(* If *)
ELSE
End_of_Text := TRUE;
end(* WHILE *);
If length >= last then
last:=length
Else
REPEAT
APPEND(INBUFF,EOS);
last := PRED(last)
UNTIL last=length;
End_of_File := EOF(fx)
end(*---of GetLine---*);
Procedure PUTLINE( VAR fx : TEXT;
VAR this : LINE );
{ This Procedure puts a line of text to a disk file }
VAR CH : char;
pos : integer;
begin
pos := 0;
REPEAT
pos := SUCC(pos);
CH := this[ pos ];
If CH <> EOS then Write(fx, CH)
UNTIL (CH = EOS) OR (pos = str_len);
Write(fx, EOS) (* Mark the End of String *)
end(*---of PUTLINE---*);
Procedure PUT_RECORD( VAR fx : TEXT;
VAR Index : integer );
VAR jx : integer;
begin
Writeln(fx, Index:5);
For jx:=1 to 5 do
PUTLINE(fx,matrix[jx] );
end(*---of PUT_RECORD---*);
Procedure GET_RECORD(VAR fx : TEXT;
VAR Index : integer );
VAR JJ : integer;
begin
READLN (fx, Index);
FOR JJ := 1 to 5 DO
GETLINE(fx,matrix[JJ]);
end(*---of GET_RECORD---*);
(*----------------------------------------------*)
(* CONSOLE I/O *)
(*----------------------------------------------*)
Procedure KEYIN(VAR CIX : char); EXTERNAL;
(*---Single char input directly from keyboard---*)
Procedure PRINT(this : Mstring);
(* Print the string 'this' until EOS *)
VAR
CH : CHAR;
pos : integer;
begin
pos := 0;
REPEAT
pos := SUCC(pos);
CH := this[ pos ];
If CH <> EOS then Write(CH)
UNTIL (CH = EOS) OR (pos = str_len);
Writeln
end(*---of PRINT---*);
Procedure SCAN( VAR Arg_string : LINE ;
count : integer ;
VAR status : BYTE );
(*----------------------------------------------*)
(* version: 3.1 /8 JUN 80/ by R.E.Penley *)
(*----------------------------------------------*
** Scan will scan your input line and return:
STATUS:
0 -OK, valid inputs
1 -an attempt was made to exceed "count"
characters - so I truncated the string at
count chars for you.
2 -an invalid character was detected.
You figure out what to do with it!
LENGTH(arg string) = 0 means a null string input.
**
Valid Alphanumeric chars are the ASCII char set
starting at the space [ CHR(32) ] and
ending at the tilde [ CHR(126) ].
*----------------------------------------------*
GLOBAL StrMax = 255;
BYTE = 0..255;
LINE = STRING Default;
*----------------------------------------------*)
VAR loop : (scanning, found, notfound);
ix : 1..StrMax;
begin
{ return status = 0 if no errors detected. }
status := 0;
{ return status = 1 if requested length is exceeded }
If LENGTH(arg_string) > count then
begin
status := 1;
SETLENGTH(arg_string,count)
end;
loop := scanning;
ix := 1;
While (loop=scanning) do
{ return status = 2 if any invalid chars found }
begin
If ix > LENGTH(arg_string) then
loop := notfound{excellent - no invalid chars}
Else
If arg_string[ix] IN [' '..'~'] then{good show - keep going}
ix := SUCC(ix)
Else
begin
loop := found{invalid char};
status := 2
end
end{while}
End(*---of SCAN 3.1---*);
(*----------------------------------------------*)
(* UTILITY ROUTINES *)
(*----------------------------------------------*)
Function YORN : boolean ;
{
YES/NO INPUT MODULE
Returns:
TRUE FOR 'Y' or 'y' INPUT
FALSE FOR 'N' or 'n' INPUT
}
VAR
ans : ALFA;
valid : boolean;
begin
REPEAT
valid := true;
READ(ans);
CASE ans[1] of
'Y','y': YORN := true;
'N','n': YORN := false;
Else: begin
valid := false;
Writeln(BELL, 'Please answer ''Y'' or ''N'' ')
end
end{case}
Until valid{response}
End(*---of YORN---*);
Procedure CLEAR;
(* Device dependent procedure *)
begin
Write( CHR(26) )
end;
Procedure SKIP(L1 : integer);
VAR ix : integer;
begin
FOR ix:=1 to L1 do Writeln
end;
Procedure PAUSE;
CONST sign = 'Type return to continue:';
VAR dummy : char;
begin
SKIP(4);
Write(sign);
Readln(dummy)
end;
Procedure BREAK;
begin
CLEAR;
SKIP(5)
end;
Procedure DRAW(picture : Mstring; count : integer );
{ Draw a picture count times }
VAR ix : integer;
begin
FOR ix:=1 to count DO Write( picture );
Writeln
end(*---of DRAW---*);
Procedure ShowRecipe;
VAR JJ : integer;
begin
FOR JJ := 1 to 5 DO
PRINT(matrix[JJ]) ;
Writeln
end(*--of ShowRecipe--*);
Procedure Display_One(VAR Index : integer);
begin
Writeln;
Writeln( 'Recipe #', Index:5 );
Writeln;
DRAW( '- ', 20);
Writeln;
ShowRecipe;
skip(4)
end(*---of Display_One---*);
(*----------------------------------------------*
* ADD MODULE *
*----------------------------------------------*)
{$C+ [ctrl-c checking ON]}
Procedure InputFeatures(VAR I : integer);
(******************************************
* Input Features of Recipe *
******************************************)
(*
RETURNS:
Hash value computed for various choices
**)
CONST Msg1 = 'None of these' ;
VAR F, D, V, P :integer;
Function QUIRY(X2 : integer) : integer;
VAR ix : integer;
cix : char;
begin
REPEAT
Writeln;
Write('Enter Choice (1 to', X2:2, ') ');
KEYIN(cix);write(cix);
ix := (ORD(cix) - ORD('0'))
UNTIL (ix>=1) AND (ix<=X2) ;
QUIRY := ix
end;
begin
Writeln;
Writeln( ' Enter number of choice :');
Writeln;
Writeln( ' ':Tab15, 'Fibre Foods' );
Writeln;
Writeln( ' ':Tab15, '1. Bread (flour)');
Writeln( ' ':Tab15, '2. Oats' );
Writeln( ' ':Tab15, '3. Rice');
Writeln( ' ':Tab15, '4. Corn' );
Writeln( ' ':Tab15, '5. Macaroni');
Writeln( ' ':Tab15, '6. Noodles' );
Writeln( ' ':Tab15, '7. Spaghetti');
Writeln( ' ':Tab15, '8. ', Msg1 );
F := QUIRY(8);
BREAK;
Writeln;
Writeln( ' ':Tab15, 'Protein' );
Writeln;
Writeln( ' ':Tab15, '1. Beef');
Writeln( ' ':Tab15, '2. Poultry' );
Writeln( ' ':Tab15, '3. Fish');
Writeln( ' ':Tab15, '4. Eggs' );
Writeln( ' ':Tab15, '5. Beans');
Writeln( ' ':Tab15, '6. Nuts' );
Writeln( ' ':Tab15, '7. ', Msg1 );
P := QUIRY(7);
BREAK;
Writeln;
Writeln( ' ':Tab15, 'Dairy' );
Writeln;
Writeln( ' ':Tab15, '1. Milk');
Writeln( ' ':Tab15, '2. Cheese' );
Writeln( ' ':Tab15, '3. Cottage Cheese');
Writeln( ' ':Tab15, '4. Cream' );
Writeln( ' ':Tab15, '5. Sour Cream');
Writeln( ' ':Tab15, '6. ', Msg1 );
D := QUIRY(6);
BREAK;
Writeln;
Writeln( ' ':Tab15, 'Fruits and Vegetables' );
Writeln;
Writeln( ' ':Tab15, '1. Citrus');
Writeln( ' ':Tab15, '2. Melon' );
Writeln( ' ':Tab15, '3. Juices');
Writeln( ' ':Tab15, '4. Greens' );
Writeln( ' ':Tab15, '5. Yellows & Reds' );
Writeln( ' ':Tab15, '6. ', Msg1 );
V := QUIRY(6);
CLEAR;
{*****************************************}
{ Compute the index value by assigning }
{ a weight to each digit in the set. }
{*****************************************}
I := 252*F + 36*P + 6*D + V - 295
{******************************************}
end{of InputFeatures};
Procedure InputRecipe;
(*---------------------------------------*
* Input individual recipies *
*---------------------------------------*)
LABEL
99; (*---EXIT---*)
CONST
prompt = '>';
VAR
state : (absent, done, adding) ;
ix, jx : integer;
temp : STRING 14;
One_Line : LINE;
YES : boolean;
(* File descriptors <FCB> *)
current,
backup : TEXT;
PROCEDURE CORRECT;
CONST question = 'Are there any corrections to be made';
msg1 = 'Enter <cr> return if correct or Reenter the line';
begin
REPEAT
BREAK;
Writeln(bell,' ':(TTY_width DIV 2) -10, 'HERE IS YOUR RECIPE');
Writeln;
ShowRecipe;
Writeln;
Writeln(question);
YES := YORN;
If YES then
begin
BREAK;
Writeln(msg1);
Writeln;
For ix:=1 to 5 do
begin
REPEAT
PRINT(matrix[ix]);
SETLENGTH(one_line,0);
READLN(one_Line);
SCAN(one_Line, str_len - 1, error_flag);
If (LENGTH(one_Line) > 0) AND (error_flag=0) then
begin
APPEND(one_Line,EOS);
matrix[ix] := one_Line
end;
If error_flag IN [1,2] then
CASE error_flag of
1: writeln('Invalid length, please reinput');
2: writeln('Alpha numerics only, please reinput')
End{case}
Until error_flag=0;
end{for}
end(* If *)
Until not YES
end(*---of Correct---*);
Function adding_desired : boolean ;
CONST addquest = 'Do you want to ADD recipies? ';
begin
PAUSE;
BREAK;
Write(addquest);
adding_desired := YORN;
CLEAR
end;
begin(*---InputRecipe---*)
If not adding_desired then{EXIT}goto 99;
adding_recipies := true ;
state := adding ;
(* OPEN file backup_ID for WRITE assign backup *)
REWRITE(backup_ID, backup);
(* OPEN file current_ID for READ assign current *)
RESET(current_ID, current);
{$C- [ctrl-c checking OFF]}
If NOT EOF(current) then
begin(* COPY current to back_up *)
ix := 0 ;
While ix < Curr_Rcds do
begin
ix := SUCC(ix);
GET_RECORD(current,hash);
PUT_RECORD(backup,hash)
end(* while *)
end(* COPY current to back_up *);
{$C+ [ctrl-c checking ON]}
(*---Input/Enter additional recipies until done---*)
(*---or curr_records > Max_Records allowed ---*)
REPEAT
If Curr_Rcds > MaxRecords then
state := done
Else
begin(*---add more recipies---*)
Writeln('Identify Recipe with features. First ');
InputFeatures(HASH);
BREAK;
Writeln('Now Enter 5 lines of the recipe');
Writeln;
For jx := 1 to 5 DO
begin
REPEAT
write(prompt);
SETLENGTH(one_line,0);
READLN(one_line);
SCAN(one_Line, str_len - 1, error_flag);
If error_flag IN [1,2] then
CASE error_flag of
1: writeln('Invalid length, please reinput');
2: writeln('Alpha numerics only, please reinput')
End{case}
Until error_flag=0;
APPEND(one_Line,EOS);
matrix[jx] := one_Line
end{For};
Correct(* if required *);
Curr_Rcds := SUCC(Curr_Rcds);
PUT_RECORD(backup,hash);
If not adding_desired then state := done;
end(*---add more recipies---*)
UNTIL state<>adding;
(*--------------------------------------------*)
(* SWAP file ID`s *)
(* Back Up file is now the Current file *)
(*--------------------------------------------*)
temp := backup_ID;
backup_ID := current_ID;
current_ID := temp;
UPDATE_MASTER;(*--status file--*)
99:(* Come here if do not desire to add *)
End{*--of InputRecipe--*};
(*--------------------------------------*)
(* DUMP/FIND MODULE *)
(*--------------------------------------*)
PROCEDURE FILE_SCAN ;
(*
GLOBAL
MaxRecords = maximum allowed records
Curr_Rcds = # of recipes in file
*)
VAR
state : (absent, found, searching) ;
Rcds,
index : integer;
fa : TEXT; (* FCB. File descriptor *)
Procedure DUMP;
(**********************************)
(* OUTPUT all Recipes from file *)
(**********************************)
begin
REPEAT
If Rcds > Curr_Rcds then
state := absent
Else
begin
Rcds := SUCC(Rcds);
GET_RECORD(fa,hash);
Display_One(hash);
PAUSE
end(* else *)
UNTIL state<>searching
end(*--of DUMP--*);
Procedure FIND;
(************************************)
(* Lookup recipes from file *)
(************************************)
begin {$C- [ctrl-c checking OFF]}
InputFeatures(Index);
REPEAT
If Rcds > Curr_Rcds then
state := absent
Else
begin
Rcds := SUCC(Rcds);
GET_RECORD(fa,hash);
If HASH=Index then
begin
CLEAR;
Display_One(hash);
PAUSE
end
end(* else *)
Until state<>searching
end(*--of Lookup--*); {$C+ [ctrl-c checking ON]}
begin(*---File_Scan---*)
CLEAR;
state := absent;
If adding_recipies then{read in new stats}
OPEN_MASTER;
(* OPEN file current_ID for READ assign fa *)
RESET(current_ID, fa);
If NOT EOF(fa) then
If Curr_rcds=0 then
state := absent
Else
begin
state := searching ;
Rcds := 1 ;
CASE command of
'O', 'o': DUMP;
'F', 'f': FIND
End{case commmand of}
end(* else *);
If state=absent then
begin
BREAK;
Writeln('That''s all the Recipes on File')
end;
PAUSE
end(*---of File_Scan---*);
(*--------------------------------------*)
(* INITIALIZATION *)
(*--------------------------------------*)
Procedure INIT1;
begin
bell := CHR(7) ;
CRT_width := 80 ;
TTY_width := 72 ;
last := str_len ;
MaxRecords := 75 ;
(* maximum number of records =
# BYTES per Record times # of records
# BYTES per record =
# chars per line + overhead per line times
# of lines. ***)
Curr_Rcds := 0 ;
Last_Update := 'YY/MM/DD ';
current_ID := 'RCPDAT.XXX ';
backup_ID := 'RCPDAT.YYY ';
adding_recipies := false;
end;
Procedure INIT2;
begin
(* OPEN file `RECIPE.MST` for READ assign stats *)
RESET(master, stats);
If EOF(stats) then(* not found *)
(* OPEN file `RECIPE.MST` for WRITE assign stats *)
UPDATE_MASTER
Else
begin(* READ in data record *)
READ(stats, data );
with data do begin
MaxRecords := MR;
Curr_Rcds := CR;
current_ID := F1;
backup_ID := F2;
last_update := date
end(* with *)
end(* READ in data record *);
SKIP(5);
Writeln('Last update of Recipe data file was ', last_update);
Writeln('File currently consists of ', Curr_Rcds:4, ' Recipies');
Writeln;
Write('Please enter todays date <YY/MM/DD> ');
last_update := ' ';{<<<=== 14 spaces required ===}
For ix:=1 to 8 do
begin
if (ix=3) or (ix=6) then
ch := '/'
else
KEYIN(ch);
write(ch);
last_update[ix] := ch
end{for};
writeln
end(*--of INIT2---*);
(*----------------------------------------------*
* MAIN PROGRAM *
*----------------------------------------------*)
BEGIN
INIT1; (* start the initialization process here *)
CLEAR;
DRAW('************',TTY_width DIV 12);
Writeln;
Writeln( ' ':22, 'The Recipe System');
Writeln;
DRAW('************',TTY_width DIV 12);
INIT2; (* finish init now *)
{ Now execute the program until done }
done := false;
While not done do
begin
CLEAR;
DRAW('************',TTY_width DIV 12);
SKIP(3);
Writeln( ' ':Tab15, 'Select One of the following:');
Writeln;
Writeln( ' ':Tab20, 'I(nput Recipes');
Writeln( ' ':Tab20, 'O(utput all Recipes');
Writeln( ' ':Tab20, 'F(ind a Recipe');
Writeln( ' ':Tab20, 'S(top');
comanding := true;
WHILE comanding do
begin
comanding := false;
Writeln;
Write(' ':(Tab15), 'Enter choice ' );
KEYIN(command);write(command);
CASE command of
'I', 'i': InputRecipe;
'O', 'o',
'F', 'f': File_Scan;
'S', 's': done := true;
Else: begin
Write(BELL);
comanding := true
end
End{ case }
end{while comanding}
end{ while not done }
End{---of Program Recipe---}.