home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / games / volume2 / dating / date.v2.p < prev    next >
Text File  |  1987-10-26  |  15KB  |  758 lines

  1. program date(input, output, Questions, database, bbase);
  2.  
  3. (*
  4.              Date-A-Base version 2.0
  5.                 by
  6.                       Thomas M. Johnson
  7.  
  8.                    john1233@csd4.milw.wisc.edu
  9.                  or
  10.                          tommyj@lakesys
  11.  
  12.     file used:
  13.        .date/Questions - holds the questionaire
  14.        .date/database  - all the people registered with the Date-A-Base
  15.              and their information
  16.        .date/bbase     - data used by the brouse command.
  17.  
  18.     version 2.0 must have getw.h in the same directory. This routine
  19.       allows Pascal to access the C getlogin() function.
  20.  
  21.  
  22. (c) 1987 Thomas M. Johnson *)
  23.  
  24.  
  25.  
  26.  
  27. const
  28.     NUMOFQUESTIONS = 49;
  29.     STRINGLENGTH = 20;
  30.     ONE = 1;
  31.     LOW = 'a';
  32.  
  33. type
  34.     string = packed array [ONE..STRINGLENGTH] of char;
  35.     answerarray = packed array [ONE..NUMOFQUESTIONS] of char;
  36.     userp = ^ usertype;
  37.     usertype = 
  38.     record 
  39.         login: string;
  40.         sex: char;
  41.         timeson: integer;
  42.         answers: answerarray;
  43.         laston: integer;
  44.         next: userp
  45.     end;
  46.  
  47. var
  48.     Questions: text;
  49.     database: file of usertype;
  50.     head: userp;
  51.     static: usertype;
  52.     bbase: text;
  53.     continue: boolean;
  54.  
  55. #include "getw.h"
  56.  
  57.     function cstrings(var string1: answerarray; string2: answerarray): real;
  58.  
  59.     (* The function cstrings takes 2 strings and compares them.
  60.        cstrings then returns the percent identical the strings are.
  61.        The strings are compared letter for letter and must be in the
  62.        same place in the string.                               *)
  63.  
  64.  
  65.     var
  66.     counter: integer;
  67.     percent: integer;
  68.  
  69.     begin
  70.     percent := 0;
  71.  
  72.     for counter := ONE to NUMOFQUESTIONS do 
  73.         if string1[counter] = string2[counter] then 
  74.         percent := percent + 1;
  75.     cstrings := percent / NUMOFQUESTIONS * 100
  76.     end; { cstrings }
  77.  
  78.     function yesNo: boolean;
  79.  
  80.     const
  81.     yes = 'y';
  82.     no = 'n';
  83.  
  84.     var
  85.     ch: char;
  86.  
  87.     begin
  88.     repeat
  89.         write(output, ' (y/n) ');
  90.         readln(input, ch)
  91.     until (ch = yes) or (ch = no);
  92.     yesNo := ch = yes
  93.     end; { yesNo }
  94.  
  95.  
  96.  
  97.  
  98.     function getanswer(ubound: char): char;
  99.  
  100.     (* The function getanswer reads in a character and checks to see
  101.        if it is in the range of lobound to ubound. If it isn't, then the
  102.        user is reprompted.                                          *)
  103.  
  104.  
  105.     var
  106.     tempchar: char;
  107.     charindex: char;
  108.  
  109.     begin
  110.     repeat
  111.         writeln(output);
  112.  
  113.         for charindex := LOW to ubound do 
  114.         write(output, charindex);
  115.  
  116.         writeln(output);
  117.         write(output, 'Your choice: ');
  118.         readln(input, tempchar)
  119.     until (tempchar >= LOW) and (tempchar <= ubound);
  120.  
  121.     writeln(output);
  122.     getanswer := tempchar
  123.     end; { getanswer }
  124.  
  125.     procedure clearstring(var tempstring: string);
  126.  
  127.     const
  128.  
  129.     blank = ' ';
  130.     var
  131.     i: integer;
  132.  
  133.     begin
  134.     for i := ONE to STRINGLENGTH do 
  135.         tempstring[i] := blank
  136.     end; { clearstring }
  137.  
  138.  
  139.  
  140.     procedure readstring(var tempstring: string);
  141.  
  142.     (* read a string from standard input. the string must have
  143.        a length of 2 or greater or it is invalid.   *)
  144.  
  145.  
  146.     const
  147.     init = 0;
  148.     inc = 1;
  149.  
  150.     var
  151.     ch: char;
  152.     length: integer;
  153.  
  154.     begin
  155.     repeat
  156.         clearstring(tempstring);
  157.         length := init;
  158.         while not eoln(input) do begin
  159.         read(input, ch);
  160.         length := length + inc;
  161.         tempstring[length] := ch
  162.         end;
  163.         readln(input)
  164.     until length > 1
  165.  
  166.     end; { readstring }
  167.  
  168.     procedure readint(var sum: integer);
  169.  
  170.     (* read in a string from standard input and convert to an
  171.        integer.     *)
  172.  
  173.  
  174.     const
  175.     init = 0;
  176.     inc = 1;
  177.     base = 10;
  178.     intlow = '0';
  179.     inthigh = '9';
  180.  
  181.     var
  182.     i: integer;
  183.     done: boolean;
  184.     hold: string;
  185.  
  186.     begin
  187.     i := inc;
  188.     done := false;
  189.     sum := init;
  190.     readstring(hold);
  191.     while (i <= STRINGLENGTH) and not done do 
  192.         if (hold[i] < intlow) or (hold[i] > inthigh) then 
  193.         done := true
  194.         else begin
  195.         sum := sum * base + (ord(hold[i]) - ord(intlow));
  196.         if sum > maxint then 
  197.             done := true
  198.         else 
  199.             i := i + inc
  200.         end
  201.     end; { readint }
  202.  
  203.  
  204.  
  205.     procedure printques(var quests: answerarray);
  206.  
  207.     (* prints the questions from the file Questions.
  208.        the question file is set up like:
  209.     
  210.        The question
  211.        the answers
  212.                .
  213.                .
  214.                .
  215.                .
  216.        ^G (up limit)
  217.     
  218.        then ^G is just a marker to signify where the answers end.
  219.        low limit is usually and 'a'
  220.        up limit the the last answer
  221.     
  222.        *)
  223.  
  224.     var
  225.     ch: char;
  226.     uplimit: char;
  227.     chset: set of char;
  228.     i: integer;
  229.  
  230.     begin
  231.     reset(Questions,'.date/Questions');
  232.     i := 1;
  233.     chset := ['A'..'Z', 'a'..'z', '0'..'9', '?', '.', ' ', '-', '/'];
  234.     ch := ' ';
  235.     while not eof(Questions) do begin
  236.         while not eoln(Questions) do begin
  237.         read(Questions, ch);
  238.         if ch in chset then 
  239.             write(output, ch)
  240.         else begin
  241.             readln(Questions, uplimit);
  242.             quests[i] := getanswer(uplimit);
  243.             i := i + 1
  244.         end
  245.         end;
  246.         readln(Questions);
  247.         writeln(output)
  248.     end
  249.     end; { printques }
  250.  
  251.  
  252.     function test(string1: string; string2: string): boolean;
  253.  
  254.     (* I was having a lot of trouble converting the Search function from
  255.        version 1 to this version because the strings were coming out
  256.        of the getw.h external procedure 1 character longer than all the
  257.        other strings. So the comparison was always false. This function
  258.        takes the place of that comparison.
  259.        *)
  260.  
  261.     var
  262.     same: boolean;
  263.     i: integer;
  264.     chset: set of char;
  265.  
  266.  
  267.     begin
  268.     i := ONE;
  269.     same := true;
  270.     chset := ['a'..'z', 'A'..'Z', '0'..'9'];
  271.  
  272.     while (string1[i] in chset) and (string2[i] in chset) and same do begin
  273.         same := string1[i] = string2[i];
  274.         i := i + ONE
  275.     end;
  276.  
  277.     test := same;
  278.     if string1[i + ONE] <> string2[i + ONE] then 
  279.         test := false
  280.     end; { test }
  281.  
  282.  
  283.  
  284.  
  285.     function Search(lookfor: string; var hisrec: usertype): boolean;
  286.  
  287.     (* scan the linked list to find a match between the string lookfor 
  288.        and the .login field. If there is a match, a true is returned with
  289.        the record of that person. Otherwise a false is returned *)
  290.  
  291.  
  292.     var
  293.     found: boolean;
  294.     temptr: userp;
  295.  
  296.     begin
  297.     found := false;
  298.     temptr := head;
  299.  
  300.     while (temptr <> nil) and not found do 
  301.         if test(temptr^.login, lookfor) then begin
  302.         hisrec := temptr^;
  303.         found := true
  304.         end else 
  305.         temptr := temptr^.next;
  306.  
  307.     Search := found
  308.     end; { Search }
  309.  
  310.  
  311.     procedure newUser;
  312.  
  313.     (* if the person in not in the linked list, add him *)
  314.  
  315.  
  316.     const
  317.     male = 'm';
  318.     female = 'f';
  319.     inc = 1;
  320.  
  321.     var
  322.     ch: char;
  323.     node: userp;
  324.  
  325.  
  326.  
  327.     begin
  328.     writeln(output, 'To use the Date-A-Base you will have to answer a');
  329.     writeln(output, 'personal questionaire. Your answers to all the');
  330.     writeln(output, 'questions will be available for anyone registered');
  331.     writeln(output, 'in the Date-A-Base to look at.');
  332.     writeln(output);
  333.     writeln(output, 'Do you want to continue? ');
  334.     continue := yesNo;
  335.  
  336.     if continue then begin
  337.         repeat
  338.         writeln(output);
  339.         writeln(output, 'What sex are you? m or f');
  340.         readln(input, ch)
  341.         until (ch = male) or (ch = female);
  342.         static.sex := ch;
  343.         with static do begin
  344.         timeson := inc;
  345.         laston := wallclock
  346.         end;
  347.         printques(static.answers);
  348.         writeln(output);
  349.         new(node);
  350.         node^ := static;
  351.         node^.next := head;
  352.         head := node
  353.     end
  354.     end; { newUser }
  355.  
  356.  
  357.  
  358.  
  359.     procedure oldUser;
  360.  
  361.     (* the person is already registered. Just get his data. *)
  362.  
  363.  
  364.     const
  365.  
  366.  
  367.     inc = 1;
  368.     var
  369.     temptr: userp;
  370.     found: boolean;
  371.  
  372.  
  373.     begin
  374.     writeln(output);
  375.     with static do begin
  376.         timeson := timeson + inc;
  377.         laston := wallclock
  378.     end;
  379.     temptr := head;
  380.     found := false;
  381.     while (temptr <> nil) and not found do 
  382.         if temptr^.login = static.login then begin
  383.         static.next := temptr^.next;
  384.         temptr^ := static;
  385.         found := true
  386.         end else 
  387.         temptr := temptr^.next
  388.  
  389.     end; { oldUser }
  390.  
  391.     procedure initialize;
  392.  
  393.     (* This procedure reads in the current file with all registered
  394.        users into a linked list. *)
  395.  
  396.  
  397.     const
  398.  
  399.     copymax = 15;
  400.     var
  401.     node: userp;
  402.     name: string;
  403.     i: integer;
  404.  
  405.     begin
  406.     head := nil;
  407.     reset(database,'.date/database');
  408.     while not eof(database) do begin
  409.         new(node);
  410.         read(database, node^);
  411.         node^.next := head;
  412.         head := node
  413.     end;
  414.     writeln(output);
  415.     writeln(output);
  416.     writeln(output, '               The');
  417.     writeln(output, '           Date-A-Base');
  418.     writeln(output);
  419.     writeln(output);
  420.     writeln(output, '  The computerized dating service.');
  421.     writeln(output);
  422.     writeln(output);
  423.     writeln(output);
  424.     continue := true;
  425.     clearstring(name);
  426.     getwh(name);
  427.     for i := ONE to copymax do 
  428.         static.login[i] := name[i];
  429.     if not Search(name, static) then 
  430.         newUser
  431.     else 
  432.         oldUser
  433.  
  434.  
  435.     end; { initialize }
  436.  
  437.     procedure savedata;
  438.  
  439.     (* save the linked list in the file database *)
  440.  
  441.  
  442.     var
  443.     pointer: userp;
  444.  
  445.  
  446.     begin
  447.     rewrite(database,'.date/database');
  448.     pointer := head;
  449.     if pointer <> nil then 
  450.         while pointer^.next <> nil do begin
  451.         write(database, pointer^);
  452.         pointer := pointer^.next
  453.         end;
  454.     write(database, pointer^)
  455.  
  456.     end; { savedata }
  457.  
  458.     procedure answer;
  459.  
  460.     (* answer the questionaire again *)
  461.  
  462.  
  463.     var
  464.     check: boolean;
  465.     temptr: userp;
  466.     found: boolean;
  467.  
  468.     begin
  469.     writeln(output);
  470.     writeln(output, 'Are you sure you want to answer all the');
  471.     writeln(output, 'questions again?');
  472.     check := yesNo;
  473.     if check then 
  474.         printques(static.answers);
  475.     temptr := head;
  476.     found := false;
  477.     while (temptr <> nil) and not found do 
  478.         if temptr^.login = static.login then begin
  479.         static.next := temptr^.next;
  480.         temptr^ := static;
  481.         found := true
  482.         end else 
  483.         temptr := temptr^.next
  484.  
  485.     end; { answer }
  486.  
  487.     procedure brouse;
  488.  
  489.     (* give a quick scan of someone else's questionaire. the data for
  490.        the brouse is in bbase. Data looks like:
  491.     
  492.               the topic
  493.               the maximum answer
  494.               answer
  495.                 .
  496.                 .
  497.                 .
  498.     
  499.                 *)
  500.  
  501.  
  502.     const
  503.     low = 'a';
  504.     clicks = 86400;                    (* number of seconds in a day *)
  505.     field = 3;
  506.     zero = 0;
  507.     marker = 15;
  508.  
  509.     var
  510.     who: string;
  511.     index: char;
  512.     ch: char;
  513.     max: char;
  514.     i: integer;
  515.     j: integer;
  516.     time: integer;
  517.     rec: usertype;
  518.  
  519.     begin
  520.     writeln(output, 'Whose questionare do you want to brouse?');
  521.     write(output, '? ');
  522.     readstring(who);
  523.  
  524.  
  525.  
  526.     if Search(who, rec) then begin
  527.  
  528.         i := ONE;
  529.         j := ONE;
  530.         reset(bbase,'.date/bbase');
  531.         writeln(output);
  532.         write(output, 'Name: ');
  533.         writeln(output, rec.login);
  534.         write(output, 'Used the Date-A-Base ');
  535.         write(output, rec.timeson: field);
  536.         if rec.timeson = ONE then 
  537.         writeln(output, ' time. ')
  538.         else 
  539.         writeln(output, ' times. ');
  540.  
  541.         write(output, 'Last used the Date-A-Base: ');
  542.         time := wallclock - rec.laston;
  543.         time := time div clicks;
  544.         if time = zero then 
  545.         writeln(output, 'today.');
  546.         if time = ONE then 
  547.         writeln(output, 'yesterday.');
  548.         if time > ONE then begin
  549.         write(output, time: field);
  550.         writeln(output, ' days ago.')
  551.         end;
  552.  
  553.         writeln(output);
  554.         while not eof(bbase) do begin
  555.         while not eoln(bbase) do begin
  556.             read(bbase, ch);
  557.             write(output, ch)
  558.         end;
  559.         readln(bbase);
  560.         readln(bbase, max);
  561.         for index := low to max do begin
  562.             if index = rec.answers[i] then begin
  563.             while not eoln(bbase) do begin
  564.                 read(bbase, ch);
  565.                 write(output, ch)
  566.             end;
  567.             writeln(output);
  568.             readln(bbase)
  569.             end else 
  570.             readln(bbase)
  571.         end;
  572.         if j = marker then begin
  573.             repeat
  574.             writeln(output);
  575.             writeln(output, 'Continue? ')
  576.             until yesNo;
  577.             j := zero;
  578.             writeln(output)
  579.         end;
  580.         j := j + ONE;
  581.         i := i + ONE
  582.         end                    (* while not eof *)
  583.     end else 
  584.         writeln(output, 'Sorry that person is not registered!');
  585.  
  586.     repeat
  587.         writeln(output);
  588.         writeln(output, 'Return to the menu? ')
  589.     until yesNo
  590.     end; { brouse }
  591.  
  592.     procedure delete;
  593.  
  594.     (* delete a person from the linked list *)
  595.  
  596.     var
  597.     found: boolean;
  598.     pointer: userp;
  599.  
  600.     begin
  601.     found := false;
  602.     writeln(output, 'Are you sure you want to delete yourself?');
  603.     if yesNo then begin
  604.         pointer := head;
  605.         if pointer^.login = static.login then begin
  606.         head := pointer^.next;
  607.         dispose(pointer)
  608.         end else 
  609.         while not found do 
  610.             while pointer^.next <> nil do 
  611.             if pointer^.next^.login = static.login then begin
  612.                 pointer^.next := pointer^.next^.next;
  613.                 dispose(pointer^.next);
  614.                 found := true
  615.             end else 
  616.                 pointer := pointer^.next
  617.     end
  618.     end; { delete }
  619.  
  620.  
  621.  
  622.  
  623.  
  624.     procedure match;
  625.  
  626.     (* find a match between 2 people. scans the whole linked list
  627.        and reports all matches greater than the amount entered. *)
  628.  
  629.  
  630.     const
  631.     loginfield = 47;
  632.     perfield = 5;
  633.     dplaces = 0;
  634.     namefield = 33;
  635.     low = 9;
  636.     high = 100;
  637.  
  638.  
  639.     var
  640.     pointer: userp;
  641.     percent: integer;
  642.     per: real;
  643.     found: boolean;
  644.  
  645.  
  646.     begin
  647.     pointer := head;
  648.     writeln(output);
  649.     writeln(output, 'What is the lowest percent match that');
  650.     writeln(output, 'you want to see? ');
  651.     repeat
  652.         write(output, ' (10 - 99) ');
  653.  
  654.         readint(percent)
  655.     until (percent > low) and (percent < high);
  656.  
  657.  
  658.     writeln(output);
  659.     write(output, '%': perfield);
  660.     writeln(output, 'name': namefield);
  661.     writeln(output, '----------------------------------------------------');
  662.  
  663.     found := false;
  664.     if pointer <> nil then 
  665.         while pointer <> nil do begin
  666.         per := cstrings(static.answers, pointer^.answers);
  667.         if (per >= percent) and (static.sex <> pointer^.sex) then begin
  668.             found := true;
  669.             writeln(output);
  670.             write(output, per: perfield: dplaces);
  671.             write(output, '%');
  672.             writeln(output, pointer^.login: loginfield)
  673.         end;
  674.         pointer := pointer^.next
  675.         end;
  676.     if not found then begin
  677.         writeln(output);
  678.         writeln(output, 'Sorry, no matches found today. Try again later.')
  679.     end;
  680.     repeat
  681.         writeln(output);
  682.         writeln(output);
  683.         writeln(output, 'Are you ready to continue?')
  684.     until yesNo
  685.  
  686.     end; { match }
  687.  
  688.     procedure bye;
  689.  
  690.     begin
  691.     writeln(output);
  692.     writeln(output, 'Thank you for using the Date-A-Base');
  693.     writeln(output, 'Hope to hear from you again soon.');
  694.     writeln(output);
  695.     writeln(output);
  696.     writeln(output);
  697.     writeln(output);
  698.     writeln(output);
  699.     writeln(output,'(c) 1987 Thomas M. Johnson');
  700.     writeln(output)
  701.     end; { bye }
  702.  
  703.  
  704.     procedure menu;
  705.  
  706.     (* The procedure menu is the programs main menu. It prints the
  707.        commands and executes the proper subroutine based on the users
  708.        choice.                                                  *)
  709.  
  710.  
  711.     const
  712.  
  713.     lastchoice = 'e';
  714.     var
  715.     choice: char;
  716.  
  717.     begin
  718.     repeat
  719.         writeln(output);
  720.         writeln(output);
  721.         writeln(output, '                           Menu');
  722.         writeln(output, '                           ----');
  723.         writeln(output);
  724.         writeln(output, '                 [a]                  answer questionare');
  725.         writeln(output, '                 [b]                  brouse questionare');
  726.         writeln(output, '                 [c]                  make a match');
  727.         writeln(output, '                 [d]                  delete your questionare');
  728.         writeln(output);
  729.         writeln(output, '                 [e]                  quit');
  730.  
  731.         choice := getanswer(lastchoice);
  732.  
  733.         case choice of
  734.         'a':
  735.             answer;
  736.         'b':
  737.             brouse;
  738.         'c':
  739.             match;
  740.         'd':
  741.             delete;
  742.         'e':
  743.             writeln(output)
  744.         end
  745.     until choice = lastchoice
  746.  
  747.     end; { menu }
  748.  
  749. begin
  750.     initialize;
  751.     if continue then begin
  752.     menu;
  753.     savedata
  754.     end;
  755.     bye
  756. end. { date }
  757.  
  758.