PROGRAM GuestList(Input,Output,FileName,FileName);
{Written by Jason J Schwarz in Turbo Pascal v6.0.
Purpose : this program is a database program to keep track
           of people coming to a party.  It keeps track
           of their name, company, answer to attendance, and
           the names of two friends.}
USES CRT;
CONST
     NoPeople = 100;
     NameLngth = 30;
     Categories = 8;
TYPE
    Str = ARRAY [1..NameLngth] OF CHAR;
    PeopleArray = ARRAY [1..NoPeople,1..Categories] OF Str;
VAR
   FileName : TEXT;
   PeopleData : PeopleArray;
   UserInput : CHAR;

PROCEDURE Clear(VAR TempData : Str);
VAR
   Count : INTEGER;
BEGIN
         FOR Count:=1 TO NameLngth DO BEGIN
              TempData[Count]:=CHR(0);
         END;{Count}
END;{Clear}

PROCEDURE ClearArray;
VAR
   People : INTEGER;
   Category : INTEGER;
   TempData : Str;
BEGIN
     Clear(TempData);
     FOR People:=1 TO NoPeople DO BEGIN
         FOR Category:=1 TO Categories DO BEGIN
             PeopleData[People,Category]:=TempData;
         END;{Category}
     END;{People}
END;{ClearArray}

PROCEDURE FieldReset(VAR PersonNumb, Field, Count : INTEGER;
                     VAR TempData : Str);
BEGIN
     PersonNumb:=PersonNumb+1;
     Field:=1;
     Clear(TempData);
     Count:=0;
END;{FieldReset}

PROCEDURE DataReset(VAR Data : CHAR;
                    VAR Field, Count, PersonNumb : INTEGER;
                    VAR TempData : Str);
BEGIN
     IF PersonNumb>NoPeople THEN BEGIN
        WRITELN(Output,'Too many entries in data file!');
     END ELSE BEGIN{PersonNumb>NoPeople}
         PeopleData[PersonNumb,Field]:=TempData;
         Clear(TempData);
         Data:=CHR(0);
         Field:=Field+1;
         PeopleData[PersonNumb,Field]:=TempData;
         Count:=-1;
     END;{PersonNumb<=NoPeople}
END;{DataReset}

PROCEDURE Save;
VAR
   PersonNumb : INTEGER;
   Field : INTEGER;
   TempData : Str;
BEGIN
     REWRITE(FileName);
     Clear(TempData);
     FOR PersonNumb:=1 TO NoPeople DO BEGIN
       IF PeopleData[PersonNumb,1]<>TempData THEN BEGIN
         FOR Field:=1 TO Categories DO BEGIN
           WRITE(FileName,PeopleData[PersonNumb,Field],' ');
         END;{Field}
         WRITELN(FileName);
       END{PeopleData<>TempData}
     END;{PersonNumb}
     CLOSE(FileName);
     HALT(0);
END;{Save}

PROCEDURE ShowPerson(VAR Count : INTEGER);
BEGIN
               WRITELN(Output,'Last name: ',PeopleData[Count,1]);
               WRITELN(Output,'First name: ',PeopleData[Count,2]);
               WRITELN(Output,'Corporation: ',PeopleData[Count,4]);
               WRITELN(Output,'Response: ',PeopleData[Count,3]);
END;{ShowPerson}

PROCEDURE FindPer(VAR LName, FName : Str);
VAR
   Count : INTEGER;
BEGIN
     CLRSCR;
     REPEAT
          WRITELN(Output,'What is the first name?');
          READLN(Input,FName);
     UNTIL FName[1]<>CHR(32);
     REPEAT
           WRITELN(Output,'What is the last name?');
           READLN(Input,LName);
     UNTIL LName[1]<>CHR(32);
     FOR COUNT:=1 TO NameLngth DO BEGIN
         LName[Count]:=UPCASE(LName[Count]);
         IF LName[Count]=CHR(32) THEN LName[Count]:=CHR(0);
         FName[Count]:=UPCASE(FName[Count]);
         IF FName[Count]=CHR(32) THEN FName[Count]:=CHR(0);
     END;{Count}
END;{FindPer}

PROCEDURE CheckRes(VAR Respond : Str;
                   VAR Count : INTEGER;
                   VAR NewResp : CHAR);
BEGIN
IF Respond[1]<>NewResp THEN BEGIN
   Respond[1]:=NewResp;
   PeopleData[Count,3]:=Respond;
END ELSE BEGIN{Change}
         WRITELN(Output,'Same response as before!');
         READLN(Input);
    END;{No Change}
END;{CheckRes}

PROCEDURE Response;
VAR
   LName : Str;
   FName : Str;
   Count : INTEGER;
   Counter : INTEGER;
   Respond : Str;
   NewResp : CHAR;
BEGIN
     FindPer(LName,FName);
     FOR Count:=1 TO NoPeople DO BEGIN
         IF LName=PeopleData[Count,1] THEN BEGIN
            IF FName=PeopleData[Count,2] THEN BEGIN
               Respond:=PeopleData[Count,3];
               FOR Counter:=2 TO NameLngth DO BEGIN
                   Respond[Counter]:=CHR(0);
               END;{Counter}
               Writeln(Output,'Is that person coming to the party?');
               Readln(Input,NewResp);
               NewResp:=UPCASE(NewResp);
               CheckRes(Respond,Count,NewResp);
            END;{FName}
         END;{LName}
     END;{Count}
     WRITELN(Output,'NO MORE ENTRIES ON THIS NAME');
     READLN(Input);
END;{Response}

PROCEDURE Show;
VAR
   LName : Str;
   FName : Str;
   Count : INTEGER;
BEGIN
     FindPer(LName, FName);
     FOR Count:=1 TO NoPeople DO BEGIN
         IF LName=PeopleData[Count,1] THEN BEGIN
            IF FName=PeopleData[Count,2] THEN BEGIN
                ShowPerson(Count);
            END;{ShowPerson}
         END;{LName}
     END;{Count}
     WRITELN(Output,'NO MORE ENTRIES ON THIS NAME');
     READLN(Input);
END; {Show}

PROCEDURE DisplayFrnd(VAR Count : INTEGER);
VAR
   Counter : INTEGER;
   Company : Str;
BEGIN
     WRITELN(Output,'This person knows the following people:');
     For Counter:=1 TO NoPeople DO BEGIN
         If PeopleData[Count,4]=PeopleData[Counter,4] THEN
            WRITELN(Output,PeopleData[Counter,1],PeopleData[Counter,2]);
     END;{Counter}
     WRITELN(Output,PeopleData[Count,5],PeopleData[Count,6]);
     WRITELN(Output,PeopleData[Count,7],PeopleData[Count,8]);
END;{DisplayFrnd}

PROCEDURE Knows;
VAR
   LName : Str;
   FName : Str;
   Count : INTEGER;
BEGIN
     FindPer (LName, FName);
     FOR Count:=1 TO NoPeople DO BEGIN
         IF LName=PeopleData[Count,1] THEN BEGIN
            IF FName=PeopleData[Count,2] THEN BEGIN
               DisplayFrnd(Count);
            END;{FName}
         END;{LName}
    END;{Count}
    WRITELN(Output,'NO MORE ENTRIES ON THIS NAME');
    READLN(Input);
END;{Knows}

PROCEDURE KnownName (VAR Count, Person : INTEGER;
                     VAR LName, FName  : Str);
VAR
   Count2 : INTEGER;
   TempData : Str;
BEGIN
     Person:=5+Person;
     Clear(TempData);
     FOR Count2:=1 to NoPeople DO BEGIN
         IF PeopleData[Count2,1]=LName THEN BEGIN
            IF PeopleData[Count2,2]=FName THEN BEGIN
               IF PeopleData[Count,4]<>PeopleData[Count2,4] THEN BEGIN
                  PeopleData[Count,Person]:=PeopleData[Count2,1];
                  PeopleData[Count,Person+1]:=PeopleData[Count2,2];
                  WRITELN(Output,'Person Recorded...');
               END ELSE BEGIN{Different Companies}
                   WRITELN(Output,'You already know that person!');
                   PeopleData[Count,Person]:=TempData;
                   PeopleData[Count,Person+1]:=TempData;
                   READLN(Input);
               END;{Same Companies}
            END{FName}
         END{LName}
     END;{Count2}
     WRITELN(Output,'NO MORE ENTRIES FOUND ON THIS NAME');
     READLN(Input);
END;{KnownName}

PROCEDURE AddKnown;
VAR
   LName : Str;
   FName : Str;
   Count : INTEGER;
   Person : INTEGER;
BEGIN
     FindPer(LName,FName);
     FOR Count:=1 to NoPeople DO BEGIN
         IF PeopleData[Count,1]=LName THEN BEGIN
            IF PeopleData[Count,2]=FName THEN BEGIN
               CLRSCR;
               WRITELN(Output,'Please enter the names of two people');
               WRITELN(Output,'this person knows.  Press <RETURN> to');
               WRITELN(Output,'begin');
               READLN(Input);
               Person:=0;
               FindPer(LName,FName);
               KnownName(Count,Person,LName,FName);
               Person:=2;
               FindPer(LName,FName);
               KnownName(Count,Person,LName,FName);
               Exit;
            END;{FName}
         END;{LName}
     END;{Count}
     WRITELN(Output,'THAT PERSON IS NOT REGISTERED');
     READLN(Input);
END;{AddKnown}

PROCEDURE Swap (VAR Count : INTEGER);
VAR
   TempData : Str;
   Move : Str;
   Counter : INTEGER;
BEGIN
     Clear(TempData);
     FOR Counter:=1 TO CATEGORIES DO BEGIN
         Move:=TempData;
         Move:=PeopleData[Count,Counter];
         IF PeopleData[Count+1,Counter]<>TempData THEN BEGIN
            PeopleData[Count,Counter]:=PeopleData[Count+1,Counter];
         END ELSE BEGIN{Null Comparison}
             PeopleData[Count,Counter]:=TempData;
         END;{Set to Null}
         IF Move<>TempData THEN BEGIN
            PeopleData[Count+1,Counter]:=Move;
         END ELSE BEGIN{Null Comparison}
            PeopleData[Count+1,Counter]:=TempData;
         END;{Set to Null}
    END;{Counter}
END;{Swap}

PROCEDURE Sort;
VAR
   Count2 : INTEGER;
   Count : INTEGER;
   Counter : INTEGER;
BEGIN
     FOR Count2:=1 TO NoPeople DO BEGIN
         FOR Count:=1 TO NoPeople-1 DO BEGIN
             IF PeopleData[Count,1]>PeopleData[Count+1,1] THEN Swap(Count);
                IF PeopleData[Count,1]=PeopleData[Count+1,1] THEN BEGIN
                   IF PeopleData[Count,2]>PeopleData[Count+1,2] THEN Swap(Count);
                END;{Identical}
         END;{Count}
     END;{Count2}
END;{Sort}

PROCEDURE GetData(VAR LName, FName, Company, Respond : Str);
VAR
   Count : INTEGER;
BEGIN
     CLRSCR;
     WRITELN(Output,'What is the new person''s first name?');
     READLN(Input,FName);
     WRITELN(Output,'What is the new person''s last name?');
     READLN(Input,LName);
     WRITELN(Output,'Will that person come to the party?');
     READLN(Input,Respond);
     WRITELN(Output,'What company does that person work for?');
     READLN(Input,Company);
     FOR COUNT:=1 TO NameLngth DO BEGIN
         LName[Count]:=UPCASE(LName[Count]);
         FName[Count]:=UPCASE(FName[Count]);
         Company[Count]:=UPCASE(Company[Count]);
         Respond[Count]:=UPCASE(Respond[Count]);
         IF LName[Count]=CHR(32) THEN LName[Count]:=CHR(0);
         IF FName[Count]=CHR(32) THEN FName[Count]:=CHR(0);
         IF Company[Count]=CHR(32) THEN Company[Count]:=CHR(0);
         IF Respond[Count]=CHR(32) THEN Respond[Count]:=CHR(0);
     END;{Count}
     FOR Count:=2 TO NameLngth DO Respond[Count]:=CHR(0);
END;{GetData}

PROCEDURE Insert (VAR LName, FName, Respond, Company : Str);
VAR
   Count : INTEGER;
   TempData : Str;
   Inserted : Boolean;
BEGIN
     Clear(TempData);
     Inserted:=False;
     FOR Count:=1 TO NoPeople DO BEGIN
       IF Inserted=False THEN BEGIN
         IF PeopleData[Count,1]=TempData THEN BEGIN
            IF PeopleData[Count,2]=TempData THEN BEGIN
               Inserted:=True;
               PeopleData[Count,1]:=LName;
               PeopleData[Count,2]:=FName;
               PeopleData[Count,3]:=Respond;
               PeopleData[Count,4]:=Company;
            END;{PeopleData[Count,1]}
         END;{PeopleData[Count,2]}
       END;{Inserted}
     END;{Count}
     IF Inserted=False THEN WRITELN(Output,'Data file full!');
END;{Insert}

PROCEDURE AddPerson;
VAR
   LName : Str;
   FName : Str;
   Company : Str;
   Respond : Str;
   Count : INTEGER;
BEGIN
     GetData(LName,FName,Company,Respond);
     FOR Count:=1 TO NoPeople DO BEGIN
         IF LName=PeopleData[Count,1] THEN BEGIN
            IF FName=PeopleData[Count,2] THEN BEGIN
            WRITELN(Output,'Duplicate Name!');
            READLN(Input);
            EXIT;
            END;{FName}
         END;{LName}
     END;{Count}
     Insert(LName,FName,Respond,Company);
     WRITELN(Output,'Sorting...');
     Sort;
END;{AddPerson}

PROCEDURE LoadError;
BEGIN
     CLOSE(FileName);
     REWRITE(FileName);
     CLOSE(FileName);
END;{LoadError}

PROCEDURE Load;
VAR
   Count : INTEGER;
   Data : CHAR;
   TempData : Str;
   PersonNumb : INTEGER;
   Field : INTEGER;
BEGIN
     {$I-}
     RESET(FileName);
     {$I+}
     IF IOResult <> 0 THEN LoadError
     ELSE BEGIN {IOResult Check}
         PersonNumb:=1;
         Field:=1;
         Clear(Tempdata);
         Count:=0;
         WHILE NOT EOF(FileName) DO BEGIN
                 WHILE NOT EOLN(FileName) DO BEGIN
                   IF Field > Categories THEN FieldReset(PersonNumb, Field, Count, TempData);
                   READ(FileName,Data);
                   IF Data = CHR(32) THEN DataReset(Data,Field,Count,PersonNumb,TempData);
                   Count:=Count+1;
                   TempData[Count]:=UPCASE(Data);
                 END;{EOLN}
                     DataReset(Data,Field,Count,PersonNumb,TempData);
                     FOR Count:=Field to Categories DO BEGIN
                         DataReset(Data,Field,Count,PersonNumb,TempData);
                     END;{Count}
                     READLN(FileName);
                     FieldReset(PersonNumb,Field,Count,TempData);
        END;{EOF}
     END;{Read}
END;{Load}

PROCEDURE WriteMenu;
BEGIN
     CLRSCR;
     WRITELN(Output,'Party Attendance Menu');
     WRITELN(Output,'E to quit without saving.');
     WRITELN(Output,'Q to save file and quit program.');
     WRITELN(Output,'S to show information on person.');
     WRITELN(Output,'R to change response.');
     WRITELN(Output,'W to list people known.');
     WRITELN(Output,'I to add more people known.');
     WRITELN(Output,'A to add person to party list.');
END;

PROCEDURE React (VAR UserInput : CHAR);
BEGIN
     READLN(Input,UserInput);
     UserInput:=UPCASE(UserInput);
     CASE UserInput of
         'Q' : Save;
         'S' : Show;
         'R' : Response;
         'W' : Knows;
         'I' : Addknown;
         'A' : AddPerson;
     END;{CASE}
END;{React}

BEGIN
ClearArray;
ASSIGN(FileName,'Guests');
WRITELN(Output,'Loading...');
Load;
CLOSE(FileName);
WRITELN(Output,'Sorting...');
Sort;
REPEAT
     WriteMenu;
     React(UserInput);
UNTIL UserInput='E';
END.
