home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Overload
/
ShartewareOverload.cdr
/
busi
/
sched25.zip
/
SCHED.PAS
< prev
Wrap
Pascal/Delphi Source File
|
1989-04-25
|
25KB
|
716 lines
{****************************************************************************}
{* *}
{* Class Scheduling Program *}
{* ======================== *}
{* *}
{* From a list of classes and sections, this program will generate all *}
{* possible options *}
{* *}
{* *}
{* *}
{****************************************************************************}
PROGRAM Schedule (INPUT, OUTPUT);
CONST
HOURS = 0;
MINUTES = 1;
{ the gaps must be at least that large to be usefull }
MinFree = 120; { 2 hours (in minutes) }
{ when the sum of the gaps reach that value the schedule is 'bad' }
MaxGap = 240; { 4 hours (in minutes) }
FF = 12; { form feed character }
Stars = { used for the printout procedure }
'**********************************************************************';
TYPE
String4 = STRING[4];
String6 = STRING[6];
String7 = STRING[7];
String8 = STRING[8];
String11 = STRING[11];
String12 = STRING[12];
String40 = STRING[40];
String80 = STRING[80];
String255= STRING[255];
TimeList = ^TimeRec;
TimeRec = RECORD
Day : INTEGER;
T1 : INTEGER;
T2 : INTEGER;
Next: TimeList;
END;
DataList = ^DataRec;
DataRec = RECORD
Name : String8;
Section : String4;
Extra : String80;
InSched : BOOLEAN;
Times : TimeList;
Next : DataList
END;
ClasList = ^ClasRec;
ClasRec = RECORD
Info : DataList;
Used : BOOLEAN;
T1 : INTEGER;
T2 : INTEGER;
Prev : ClasList;
Next : ClasList
END;
ClasArr = ARRAY[0..4] OF ClasList;
DataArr = ARRAY[0..19] OF DataList;
VAR
Last_line: String255;
Earliest, Latest : String255;
First, Last, I, SchedNum, OptNum, Max, Code : INTEGER;
NoOutput, Normal, Ok : BOOLEAN;
Sched : ClasArr;
Data : DataArr;
Ptr : DataList;
Time : TimeList;
Ch : CHAR;
MaxStr, EarlyDef, LateDef : String6;
FileIn, FileOut : String12;
InFile, OutFile : TEXT;
titles : boolean;
{ -------------------------------------------------------- }
function upcasestring(S : String255) : String255;
var
i, len : INTEGER;
BEGIN
i := 1;
len := LENGTH(S);
WHILE (i <= len) DO BEGIN
S[i] := upcase(S[i]);
i := i + 1;
END;
upcasestring := S;
end;
PROCEDURE Error(S : String255; Msg : String255);
VAR
x, i : INTEGER;
BEGIN
i := LENGTH(S) - 2;
WRITELN('Error on line:');
WRITELN(Last_line);
WRITE('at: ');
FOR x := 4 TO (LENGTH(Last_line) - i) DO
WRITE(' ');
WRITELN(Copy(S, 1, i));
WRITELN('Error type: ', Msg);
HALT;
END;
{ get rid of tabs }
FUNCTION FIX_TABS(S : String255) : String255;
VAR
i, len : INTEGER;
BEGIN
i := 1;
len := LENGTH(S);
WHILE (i <= len) DO BEGIN
IF S[i] = ^I THEN
S[i] := ' ';
i := i + 1;
END;
FIX_TABS := S;
END;
{ -------------------------------------------------------- }
FUNCTION Ltrim(S : String255) : String255;
VAR
I : INTEGER;
BEGIN { Ltrim }
I := 1;
WHILE S[I] = ' ' DO I := I + 1;
Ltrim := Copy (S, I, 255)
END; { Ltrim }
{============================================================================}
{= This procedure converts the head of the string S into a the a number =}
{= The head of the string must have the format: =}
{= HH:MMxx for example 9:30am or 12:00pm =}
{= The integer value returned is the time in minutes. =}
{============================================================================}
PROCEDURE ConvertTime(S : String255; VAR T : INTEGER);
VAR
Hours, Minutes, i : INTEGER;
AmPm, Dummy : CHAR;
{ ---------------------------------------------------}
PROCEDURE Check_Time(S : STring255; Kind : INTEGER);
VAR
i, error_code : INTEGER;
BEGIN
IF Kind = HOURS THEN BEGIN
Val(Copy(S, 1, Pos(':', S) - 1), i, error_code);
IF error_code <> 0 THEN
Error(S, 'not a number');
IF i IN [1..12] THEN
EXIT;
Error(S, 'Hours must be 1 to 12.');
END
ELSE BEGIN
{ check if second digit is a number. users can type
1:0, and it will be ok. }
Val(Copy(S, 2, 2), i, error_code);
IF error_code = 0 THEN
Val(Copy(S, 1, 2), i, error_code)
ELSE
Val(Copy(S, 1, 1), i, error_code);
IF error_code <> 0 THEN
Error(S, 'not a number');
IF i IN [0..59] THEN
EXIT;
Error(S, 'Minutes must be 0 to 59.');
END;
END;
{ ---------------------------------------------------}
BEGIN { ConvertTime }
Check_Time(S, HOURS);
Val(Copy(S, 1, Pos(':', S) - 1), Hours, I);
S := Copy(S, Pos(':', S) + 1, 255);
Check_Time(S, MINUTES);
{ check for ambiguous input }
Val(Copy(S, 1, 2), Minutes, I);
IF I = 0 THEN BEGIN { both character are digits }
Val(Copy(S, 1, 2), Minutes, I);
S := Copy(S, 3, 255);
END
ELSE BEGIN { only the first is. }
Val(Copy(S, 1, 1), Minutes, I);
S := Copy(S, 2, 255);
END;
AmPm := S[1];
{ check what this really was... }
IF NOT (AmPm IN ['a', 'A', 'p', 'P', ' ', '-']) THEN
Error(S, 'You need an `am'' or a `pm'', or space ` '' or dash `-''.');
IF (AmPm IN ['p','P']) AND (Hours <> 12) THEN Hours := Hours + 12;
T := Hours * 60 + Minutes;
END; { ConvertTime }
{============================================================================}
{= This procedure reads all the days and times of a section and stores the =}
{= information in a TimeList. =}
{============================================================================}
PROCEDURE GetHours(S : String255; DataPtr : DataList);
VAR
Day, T1, T2, Count : INTEGER;
Time,Ptr,Ptr1: TimeList;
Day_error : BOOLEAN;
BEGIN { GetHours }
Time := NIL;
S := LTRIM(S);
Day_error := TRUE;
WHILE S[1] IN ['M','T','W','F'] DO BEGIN { Loop as long it is a day code }
Day_error := FALSE;
Ptr1 := Time;
{ Start by getting all the days of a section with the same hours }
{ and store the day code into the list. }
WHILE S[1] IN ['M','T','W','F'] DO BEGIN
NEW(Ptr); { make a new entry for that day }
Ptr^.Next := Time;
Count := 1; { dirty trick that tells me if the day is 1 or 2 char long }
{ Convert the day into an integer code stored in the list }
CASE S[1] OF
'M' : Ptr^.Day := 0;
'W' : Ptr^.Day := 2;
'F' : Ptr^.Day := 4;
'T' : BEGIN
Count := 2; { Here we are, those are 2 character long days }
IF S[2] IN ['u','U'] THEN Ptr^.Day := 1
ELSE IF S[2] IN ['h','H'] THEN Ptr^.Day := 3
ELSE
ERROR(S, 'The day isn''t Tu or Th');
END
END;
Time := Ptr; { add the new entry to the list }
{ scan the rest of the string }
S := LTRIM(COPY(S, Count + 1, 255));
END;
{ Now, we read all the days for a given time. We have to read the times }
ConvertTime(S,T1);
{ skip up to next time info }
S := LTRIM(COPY(S, POS('-', S) + 1, 255));
ConvertTime(S, T2);
{ skip up to field deliminator }
S := LTRIM(COPY(S, POS(' ', S), 255));
{ determine the extreme values for all the data }
IF T1 < First THEN First := T1;
IF T2 > Last THEN Last := T2;
{ traverse the whole list to store the time }
{!!! this information is disgustingly redundant !!!}
Ptr := Time;
WHILE Ptr <> Ptr1 DO BEGIN
Ptr^.T1 := T1;
Ptr^.T2 := T2;
Ptr := Ptr^.Next
END;
END;
IF Day_error THEN
Error(S, 'Did not find any days of the week.');
DataPtr^.Extra := COPY(S, 1, LENGTH(S)-1);
DataPtr^.Times := Time
END; { GetHours }
{=========================================================================}
{=========================================================================}
PROCEDURE ReadData;
label
bottom;
VAR
I : INTEGER;
S : String255;
Ptr, Ptr2 : DataList;
BEGIN { ReadData }
FOR I := 0 TO 19 DO Data[I] := NIL;
First := 1440;
Last := 0;
I := 0;
WHILE NOT EOF(InFile) DO BEGIN
NEW(Ptr);
READLN(InFile, S);
S := FIX_TABS(S); { get rid of tabs }
S := upcasestring(S);
S := LTRIM(S);
if S[1] = ';' then goto bottom;
if length(S) = 0 then goto bottom;
Last_line := Copy(S, 1, 255); { error msg line }
S := S + ' X';
Ptr^.Name := COPY(S, 1, POS(' ', S));
S := LTRIM(COPY(S, POS(' ', S), 255));
Ptr^.Section := COPY(S, 1, POS(' ', S));
S := LTRIM(COPY(S, POS(' ', S), 255));
GetHours(S, Ptr);
Ptr^.Next := NIL;
IF Data[I] = NIL THEN
Data[I] := Ptr
ELSE IF Data[I]^.Name <> Ptr^.Name THEN BEGIN
I := I + 1;
Data[I] := Ptr
END
ELSE BEGIN
Ptr2 := Data[I];
WHILE Ptr2^.Next <> NIL DO Ptr2 := Ptr2^.Next;
Ptr2^.Next := Ptr
END;
bottom:;
END;
CLOSE(InFile)
END; { ReadData }
{============================================================================}
{= When processing is finished with one person, this procedure erases =}
{= all the data structures used to keep information. =}
{============================================================================}
PROCEDURE EraseInfo;
VAR
I : INTEGER;
Ptr1, Temp1 : DataList;
Ptr2, Temp2 : TimeList;
BEGIN { EraseInfo }
I := 0;
WHILE Data[I] <> NIL DO BEGIN
Ptr1 := Data[I];
WHILE Ptr1 <> NIL DO BEGIN
Ptr2 := Ptr1^.Times;
WHILE Ptr2 <> NIL DO BEGIN
Temp2 := Ptr2;
Ptr2 := Ptr2^.Next;
DISPOSE(Temp2)
END;
Temp1 := Ptr1;
Ptr1 := Ptr1^.Next;
DISPOSE(Temp1)
END;
I := I + 1
END;
FOR I := 0 TO 4 DO DISPOSE(Sched[I])
END; { EraseInfo }
{***********************************************************************}
{* *}
{* Results printing *}
{* *}
{***********************************************************************}
{============================================================================}
{= This function determines how 'good' a schedule is. =}
{= The way this is done is by summing up all the inter-class gaps that are =}
{= shorter than the constant MinFree. Then, if that sum is larger or =}
{= equal to the constant MaxGap, the schedule is 'bad'. =}
{============================================================================}
FUNCTION Optimized : BOOLEAN;
VAR
Gap, I : INTEGER;
Ptr : ClasList;
BEGIN { Optimized }
Gap := 0;
FOR I := 0 TO 4 DO BEGIN
Ptr := Sched[I];
Ptr := Ptr^.Next;
IF Ptr <> NIL THEN
WHILE Ptr^.Next <> NIL DO BEGIN
IF NOT Ptr^.Used THEN
IF(Ptr^.T2-Ptr^.T1) < MinFree THEN Gap := Gap + Ptr^.T2-Ptr^.T1;
Ptr := Ptr^.Next
END
END;
IF Gap < MaxGap THEN OptNum := OptNum + 1;
Optimized := (Gap < MaxGap) OR Normal
END; { Optimized }
{============================================================================}
{= Converts an integer representing a time in minutes into a string =}
{============================================================================}
FUNCTION TimeStr(T : INTEGER): String7;
VAR
S : String7;
S1 : String7;
AmPm : CHAR;
BEGIN { TimeStr }
IF (T DIV 60) >= 12 THEN BEGIN
IF (T DIV 60) <> 12 THEN T := T - 60 * 12;
AmPm := 'p'
END ELSE AmPm := 'a';
Str(T DIV 60:2,S);
Str(T MOD 60:2,S1);
S := S + ':' + S1 + AmPm + 'm';
IF (T MOD 60) = 0 THEN S[4] := '0';
TimeStr := S
END; { TimeStr }
{============================================================================}
{= Counts the number of schedules and prints them out if NoOutput is false =}
{= Will print out only optimized schedules if Normal is false =}
{= NoOutput and Normal are global boolean variables =}
{============================================================================}
PROCEDURE PrintOut(VAR OutFile : TEXT);
VAR
Ch : CHAR;
Ptr1: DataList;
Ptr : ClasList;
DatOut : ARRAY[0..4,0..95] OF String11;
Time, T, I, J : INTEGER;
BEGIN { PrintOut }
IF Optimized THEN BEGIN
SchedNum := SchedNum + 1;
IF NOT NoOutput THEN BEGIN
FOR I := 0 TO 4 DO
FOR J := 0 TO (Last-First) DIV 15 DO
DatOut[I,J] := ' ';
FOR I := 0 TO 4 DO BEGIN
Ptr := Sched[I];
WHILE Ptr <> NIL DO BEGIN
IF Ptr^.Used THEN BEGIN
DatOut[I,(Ptr^.T1-First) DIV 15] := '───────────';
DatOut[I,(Ptr^.T1-First) DIV 15+1] :=
Ptr^.Info^.Name + ' ';
DatOut[I,(Ptr^.T1-First) DIV 15+2] :=
Ptr^.Info^.Section + ' ';
DatOut[I,(Ptr^.T2-First) DIV 15] := '───────────';
END;
Ptr := Ptr^.Next
END
END;
IF FileOut = '' THEN Clrscr
ELSE
if not titles then WRITELN(OutFile, CHR(FF));
if not titles then begin
WRITELN(OutFile);
WRITELN(OutFile, 'Attempt schedule ', SchedNum : 2);
WRITELN(OutFile, '═══════════════════');
WRITELN(OutFile);
WRITELN(OutFile);
WRITELN(OutFile, ' ╔':9,
'═══════════╤═══════════╤═══════════╤═══════════╤═══════════╗');
WRITELN(OutFile, ' ║':9, '│':12, '│':12, '│':12, '│':12, '║':12);
WRITELN(OutFile, ' ║' : 9, ' MONDAY │ TUESDAY │ WEDNESDAY ',
'│ THURSDAY │ FRIDAY ║');
WRITELN(OutFile, ' ║':9, '│':12, '│':12, '│':12, '│':12, '║':12);
WRITELN(OutFile, ' ╠':9,
'═══════════╪═══════════╪═══════════╪═══════════╪═══════════╣');
FOR J := 0 TO (Last-First) DIV 15 DO BEGIN
IF (J MOD 2) = 0 THEN
WRITE(OutFile, TimeStr((J + First DIV 15 ) * 15), ' ║')
ELSE WRITE(OutFile, '║' : 9);
FOR I:= 0 TO 4 DO BEGIN
WRITE(OutFile, DatOut[I, J] : 11);
IF I = 4 THEN WRITELN(OutFile, '║')
ELSE WRITE(OutFile, '│')
END
END;
WRITELN(OutFile, ' ╚':9,
'═══════════╧═══════════╧═══════════╧═══════════╧═══════════╝');
end;
WRITELN(OutFile);
WRITELN(OutFile, 'Classes selected :');
WRITELN(OutFile, '==================');
I := 0;
WHILE Data[I] <> NIL DO BEGIN
Ptr1 := Data[I];
WHILE Ptr1 <> NIL DO BEGIN
IF Ptr1^.InSched THEN
WRITELN(OutFile, Ptr1^.Name, ' ', Ptr1^.Section, ' ', Ptr1^.Extra);
Ptr1 := Ptr1^.Next
END;
I := I + 1
END;
IF FileOut = '' THEN BEGIN
REPEAT UNTIL KeyPressed;
READ(Ch)
END
END
END
END; { PrintOut }
{***********************************************************************}
{* *}
{* Data manipulation *}
{* *}
{***********************************************************************}
{============================================================================}
{= Main procedure that will find every possible and imaginable schedule =}
{= formed from an original list of classes and sections. =}
{============================================================================}
PROCEDURE MakeSched(Index,Cnt : INTEGER);
VAR
Ptr : DataList;
I : INTEGER;
{============================================================================}
{= Returns the value true if the section times pointed to by Ptr can fit =}
{= in our current schedule. =}
{============================================================================}
FUNCTION Fit(Ptr : TimeList) : BOOLEAN;
VAR
Ptr2 : ClasList;
Ok : BOOLEAN;
BEGIN { Fit }
Ok := TRUE;
WHILE (Ptr <> NIL) AND Ok DO BEGIN
Ptr2 := Sched[Ptr^.Day];
Ok := FALSE;
WHILE (Ptr2 <> NIL) AND NOT Ok DO BEGIN
Ok := Ptr2^.T2 >= Ptr^.T2;
IF NOT Ok THEN Ptr2 := Ptr2^.Next
END;
IF Ok THEN Ok := (Ptr2^.T1 <= Ptr^.T1) AND NOT Ptr2^.Used;
Ptr := Ptr^.Next
END;
Fit := Ok
END; { Fit }
{============================================================================}
{=
{============================================================================}
PROCEDURE Coalesce;
VAR
Temp,Ptr : ClasList;
I : INTEGER;
BEGIN { Coalesce }
FOR I := 0 TO 4 DO BEGIN
Ptr := Sched[I];
WHILE Ptr^.Next <> NIL DO BEGIN
Temp := Ptr^.Next;
IF (NOT Ptr^.Used) AND (NOT Temp^.Used) THEN BEGIN
Ptr^.T2 := Temp^.T2;
Ptr^.Next := Temp^.Next;
IF Temp^.Next <> NIL THEN
Temp^.Next^.Prev := Ptr;
END ELSE Ptr := Ptr^.Next
END
END
END; { Coalesce }
{============================================================================}
{============================================================================}
PROCEDURE Insert(Ptr : DataList);
VAR
Temp,Ptr2 : ClasList;
Ptr1 : TimeList;
BEGIN { Insert }
Ptr1 := Ptr^.Times;
WHILE Ptr1<> NIL DO BEGIN
Ptr2 := Sched[Ptr1^.Day];
WHILE Ptr2^.T2 < Ptr1^.T2 DO Ptr2 := Ptr2^.Next;
{ split current free block }
IF Ptr2^.T1 < Ptr1^.T1 THEN BEGIN
NEW(Temp);
Temp^.T1 := Ptr2^.T1;
Temp^.T2 := Ptr1^.T1 - 1;
IF Ptr2^.Prev <> NIL THEN Ptr2^.Prev^.Next := Temp
ELSE Sched[Ptr1^.Day] := Temp;
Temp^.Prev := Ptr2^.Prev;
Temp^.Next := Ptr2;
Ptr2^.Prev := Temp;
Temp^.Used := FALSE
END;
IF Ptr2^.T2 > Ptr1^.T2 THEN BEGIN
NEW(Temp);
Temp^.T1 := Ptr1^.T2+1;
Temp^.T2 := Ptr2^.T2;
IF Ptr2^.Next <> NIL THEN
Ptr2^.Next^.Prev := Temp;
Temp^.Prev := Ptr2;
Temp^.Next := Ptr2^.Next;
Ptr2^.Next := Temp;
Temp^.Used := FALSE
END;
Ptr2^.T1 := Ptr1^.T1;
Ptr2^.T2 := Ptr1^.T2;
Ptr2^.Info := Ptr;
Ptr2^.Used := TRUE;
Ptr1 := Ptr1^.Next;
END;
Coalesce;
END; { Insert }
{============================================================================}
{============================================================================}
PROCEDURE Remove(Ptr : TimeList);
VAR
Temp,Ptr2 : ClasList;
BEGIN { Remove }
WHILE Ptr <> NIL DO BEGIN
Ptr2 := Sched[Ptr^.Day];
WHILE Ptr2^.T1 <> Ptr^.T1 DO Ptr2 := Ptr2^.Next;
Ptr2^.Used := FALSE;
Ptr := Ptr^.Next
END;
Coalesce;
END; { Remove }
BEGIN { MakeSched }
IF (Data[Index] <> NIL) AND (Cnt < Max) THEN BEGIN
Ptr := Data[Index];
WHILE Ptr <> NIL DO BEGIN
IF Fit(Ptr^.Times) THEN BEGIN
Ptr^.InSched := TRUE;
Insert(Ptr);
MakeSched(Index + 1, Cnt + 1);
Ptr^.InSched := FALSE;
Remove(Ptr^.Times)
END;
Ptr := Ptr^.Next
END;
MakeSched(Index + 1,Cnt)
END ELSE
IF Cnt = Max THEN IF FileOut = '' THEN PrintOut(OUTPUT)
ELSE PrintOut(OutFile)
END; { MakeSched }
{============================================================================}
{============================================================================}
FUNCTION Yes(X, Y : INTEGER; Default : CHAR) : BOOLEAN;
VAR
Ch : CHAR;
BEGIN { Yes }
REPEAT
GOTOXY(X,Y); WRITE(Default);
GOTOXY(X,Y); READ(KBD,Ch);
GOTOXY(X,Y); WRITE(Ch)
UNTIL Ch IN ['y','Y','n','N',CHR(13)];
IF Ch = CHR(13) THEN Ch := Default;
Yes := (Ch = 'Y') OR (Ch = 'y')
END; { Yes }
BEGIN { Schedule }
ClrScr;
GOTOXY(0,0);
WRITELN(Stars);
WRITELN('*','Schedule Maker 2.5 - by Mallku Caballero':55,'*':14);
WRITELN(Stars);
GOTOXY(5,6); WRITE('Enter schedule file : ');
REPEAT
GOTOXY(27,6);
READLN(FileIn);
ASSIGN(InFile, FileIn);
{$I-} RESET(Infile) {$I+};
Ok := IOResult = 0;
IF NOT Ok THEN BEGIN
GOTOXY(45, 6); WRITE('Can not find file -- hit any key',CHR(7));
READ(KBD, Ch);
GOTOXY(27, 6); WRITE(' ')
END
UNTIL Ok;
ASSIGN(InFile,FileIn);
RESET(Infile);
ReadData;
GOTOXY(5,7); WRITE('How many classes ?');
Max := 0;
REPEAT
GOTOXY(27,7);
READLN(MaxStr);
VAL(MaxStr,Max,Code);
UNTIL (Code = 0) AND (Max > 0);
EarlyDef := LTRIM(TimeStr(First));
LateDef := LTRIM(TimeStr(Last));
GOTOXY(5,8); WRITE('Earliest time : ',EarlyDef);
GOTOXY(27,8); READLN(Earliest);
Earliest := Copy(Earliest + Copy(EarlyDef,LENGTH(Earliest)+1,7),1,8);
GOTOXY(5,9); WRITE('Latest time : ',LateDef);
GOTOXY(27,9); READLN(Latest);
Latest := COPY(Latest + COPY(LateDef,LENGTH(Latest)+1,7),1,8);
ConvertTime(Earliest,First);
ConvertTime(Latest,Last);
FOR I := 0 TO 4 DO BEGIN
NEW(Sched[I]);
Sched[I]^.Used := FALSE;
Sched[I]^.T1 := First;
Sched[I]^.T2 := Last;
Sched[I]^.Prev := NIL;
Sched[I]^.Next := NIL
END;
SchedNum := 0;
OptNum := 0;
NoOutput := TRUE;
Normal := TRUE;
MakeSched(0,0);
GOTOXY(5,13);
IF SchedNum > 0 THEN BEGIN
WRITE(SchedNum:3,' schedules have been generated.');
GOTOXY(5,14); WRITE(OptNum:3,' optimized schedules generated.');
GOTOXY(5,16); WRITE('Display (Y/N) ? ');
IF Yes(36,16,'Y') THEN BEGIN
GOTOXY(5,17); WRITE('Optimized (Y/N) ?');
IF optNum > 0 THEN
Normal := NOT Yes(36,17,'Y')
else
Normal := NOT Yes(36,17,'N');
GOTOXY(5,18); WRITE('Output file (CR for display) : ');
READLN(FileOut);
IF FileOut <> '' THEN BEGIN
ASSIGN(OutFile, FileOut);
REWRITE(OutFile)
END;
GOTOXY(5,19); WRITE('Output ouly course titles (Y/N) : ');
titles := YES(37, 19, 'Y');
NoOutput := FALSE;
SchedNum := 0;
MakeSched(0,0);
IF FileOut <> '' THEN CLOSE(OutFile)
END
END
ELSE WRITE('Unable to generate any schedules.');
EraseInfo;
END. { Schedule }