home *** CD-ROM | disk | FTP | other *** search
/ Sunny 1,000 Collection / SUNNY1000.iso / Files / Dos / Sport / GOLF43.ZIP / GOLF.PAS < prev    next >
Pascal/Delphi Source File  |  1994-08-23  |  64KB  |  1,849 lines

  1. { Golf43 ... rebuilt}
  2. {$M $4000,0,0} {No Heap needed...no "dynamic" variables}
  3. {With $N, uses 80x87 chip with if available, else uses simulation of it}
  4. {Shorter & faster with $N+,$E- ,but then 80x87 is required}
  5. {Works OK without either!...i.e. no IEEE math...shortest.}
  6. Program Golf;
  7. {This is a program to calculate the golf handicap of any number of
  8.  individuals who may have played on any number of courses.  It provides
  9.  and a file of courses, plus an individual game file for each golfer.
  10.  It shows the last max_diffs scores , or all scores, whichever is less (used in
  11.  actual handicap calculations) with the ones used (Best 10 or best half)
  12.  highlighted.  A separate highlight shows the midpoint scores which are
  13.  the ones that are most likely to be replaced by a new score.  The Hcp
  14.  is 96% of the average of the best (lowest) differences between adjusted
  15.  gross score and course rated par.  The adjusted gross score is the score
  16.  resulting from reducing the score for any given hole in which a net
  17.  score of more than a bogie was recorded (1973 rules). The 1993 rules
  18.  changed this to a maximum of double bogie plus hcp/10.  The change is
  19.  incorporated for scores after 1992.}
  20.  
  21.  
  22. uses Dos,Crt,Printer;
  23. {$I golfspec}
  24.  
  25.   procedure Surname(instring: string; var outstring: string);
  26.   {Called by Gindex}
  27.   var
  28.     i,j        : byte;
  29.     tail       : string;
  30.  
  31.   begin
  32.     j := 0;
  33.     outstring := '';
  34.     tail := '';
  35.  
  36.     for i := 1 to Length(instring) do
  37.     if instring[i] = ' '
  38.       then
  39.         begin
  40.           j := 0;
  41.           tail := outstring;
  42.         end
  43.       else
  44.         begin
  45.           if j = 0 then
  46.             outstring := '';
  47.           outstring := outstring + instring[i];
  48.           j := succ(j);
  49.         end;
  50.     outstring := outstring + tail;
  51.   end; {Surname}
  52.  
  53.   procedure Test(var x:array255; var iname:string;
  54.                      jname:string; i,j:integer);
  55.   {Called by Cindex and Gindex}
  56.   var
  57.     k : integer;
  58.   begin
  59.     if jname > iname then
  60.       begin
  61.         k := x[i];
  62.         x[i] := x[j];
  63.         x[j] := k;
  64.         iname := jname;
  65.       end {if statement}
  66.   end;      {of test procedure}
  67.  
  68.   procedure Align(fsize,msize: integer; var line_no,over_top: byte);
  69.     begin
  70.       line_no := line_no + over_top;
  71.       if line_no > msize then
  72.         if line_no < (fsize - msize)
  73.          then
  74.           begin
  75.             over_top := line_no - (msize div 2) - 1;
  76.             line_no  := line_no - over_top;
  77.           end
  78.          else
  79.           begin
  80.             over_top := fsize - msize;
  81.             line_no  := line_no - over_top;
  82.           end
  83.         else
  84.          over_top := 0;
  85.     end;
  86.  
  87.   procedure Cindex(ctype : byte);
  88.     var
  89.       i,j,k,n,xi : integer;
  90.       iname,jname,name
  91.                  : string;
  92.  
  93.     begin
  94.       reset(courses);
  95.       n := filesize(courses);
  96.       if club.id <> 0 then course_id := club.id;     {Not "Nowhere"}
  97.         case ctype of
  98.       1: for i := 0 to n
  99.            do cx[i] := i;
  100.       2: for i := n-1 downto 1 do
  101.            begin
  102.              Seek(courses,cx[i]);
  103.              Read(courses,club);
  104.              iname := club.name;
  105.              for j := i-1 downto 1 do
  106.                begin
  107.                  Seek(courses,cx[j]);
  108.                  Read(courses,club);
  109.                  jname := club.name;
  110.                  Test(cx,iname,jname,i,j);
  111.                end    {j loop}
  112.            end;       {i loop}
  113.       end;    {case statement}
  114.       for i := 0 to FileSize(courses) do
  115.           if cx[i] = course_id then
  116.              course_hiline := i + 1;
  117.           course_over_top := 0;
  118.       Align(FileSize(courses),max_course_box,course_hiline,course_over_top);
  119.     end;     {Cindex procedure}
  120.  
  121.   procedure Gindex(gtype : byte);
  122.     var
  123.       i,j,k,n,xi : integer;
  124.       iname,jname,name
  125.                  : string;
  126.  
  127.     begin
  128.       reset(golfers);
  129.       n := filesize(golfers);
  130.       if golfer.id <> 0 then golfer_id := golfer.id;  {Not "Nobody"}
  131.         case gtype of
  132.       1: for i := 0 to n do
  133.              gx[i] := i;
  134.       2..4: for i := n-1 downto 1 do
  135.             begin
  136.              Seek(golfers,gx[i]);
  137.              Read(golfers,golfer);
  138.              case gtype of
  139.                2: iname := golfer.name;
  140.                3: Surname(golfer.name,iname);
  141.                4: Str(golfer.hcp:5:2,iname);
  142.              end;  {inner case 1 statement}
  143.              for j := i-1 downto 1 do
  144.                begin
  145.                  Seek(golfers,gx[j]);
  146.                  Read(golfers,golfer);
  147.                  case gtype of
  148.                    2: jname := golfer.name;
  149.                    3: Surname(golfer.name,jname);
  150.                    4: Str(golfer.hcp:5:2,jname);
  151.                  end;  {inner case 2 statement}
  152.                  Test(gx,iname,jname,i,j);
  153.                end     {j loop}
  154.             end;       {i loop}
  155.       end;    {outer case statement}
  156.       for i := 0 to FileSize(golfers) do
  157.           if gx[i] = golfer_id then
  158.              golfer_hiline := i + 1;
  159.           golfer_over_top := 0;
  160.       Align(FileSize(golfers),max_golfer_box,golfer_hiline,golfer_over_top);
  161.     end;     {Gindex procedure}
  162.  
  163.   Procedure Select (var ch: char; var hiline,over_top: byte;
  164.                         file_size: integer; height: byte);
  165.     begin
  166.        ch := ReadKey;
  167.        if ch = #0
  168.        then
  169.        begin
  170.          ch := ReadKey;
  171.          case ch of
  172.            'H':   {Up-arrow}
  173.             if hiline > 1
  174.               then hiline := Pred(hiline)
  175.               else if (hiline = 1) and (over_top > 0)
  176.                       then over_top := Pred(over_top);
  177.            'P':   {Down-arrow}
  178.             if hiline < height
  179.               then hiline :=Succ(hiline)
  180.               else if (hiline = height) and (file_size > (over_top + height))
  181.                       then over_top := Succ(over_top);
  182.             '-':  {Alt-x}
  183.             begin
  184.               option := ProgramExit;
  185.               exit;
  186.             end;
  187.          end; {case}
  188.          case ch of
  189.            'H','P' : ch := #0;
  190.          end;  {set for repeat of arrows (Non-zero if not arrows)}
  191.        end {if then block}
  192.     end;     {Select}
  193.  
  194.  
  195.   Procedure GetName(var name:string; len : byte);
  196.     var
  197.       x,y,counter : byte;
  198.       ch : char;
  199.     begin
  200.       x := WhereX;
  201.       y := WhereY;
  202.       name := '';
  203.       counter := 0;
  204.       repeat
  205.         ch := ReadKey;
  206.         case ch of
  207.         #0:
  208.           begin
  209.           ch := ReadKey;
  210.           case ch of
  211.           '-':   {Alt-x}
  212.              begin
  213.                option := ProgramExit;
  214.                exit;
  215.              end;
  216.           'K':   {Back-arrow}
  217.             if counter > 0 then
  218.              begin
  219.               counter := pred(counter);
  220.               name := Copy(name,1,counter);
  221.              end; {if counter}
  222.           end; {inner case}
  223.           end; {#0 response}
  224.  
  225.         #8 : if counter > 0 then
  226.              begin
  227.               counter := pred(counter);
  228.               name := Copy(name,1,counter);
  229.              end; {if counter}
  230.         #13: len := counter;
  231.         #27: Exit;
  232.         ' '..'~': begin
  233.                     name := name + ch;
  234.                     counter := succ(counter);
  235.                   end;
  236.         end; {outer case}
  237.       GotoXY(x,y);
  238.       ClrEol;
  239.       Write(name);
  240.       until counter = len;
  241.     end; {GetName}
  242.  
  243.  
  244.  
  245.   Procedure ScoreCard;
  246.     var
  247.       hole,t1,t2,t3: byte;
  248.     begin
  249.       Window(1,15,80,25);   {score screen}
  250.       ClrScr;
  251.       GotoXY(1,1);
  252.       Writeln ('Golfer: ',golfer.name,'      HCP = ',golfer.hcp:4:1
  253.       ,'     Anti_Hcp = ',AntiHcp:4:1);
  254.       Write ('Course: ',club.name);
  255.       Write ('       Rated par = ',club.rated_par:5:1);
  256.       xloc := WhereX;
  257.       yloc := WhereY;
  258.       Writeln;
  259.       if color then TextColor(yellow);
  260.       Write('Hole ');
  261.       for hole := 1 to max_holes do Write(hole:3);
  262.       Writeln;
  263.       Write('Par  ');
  264.       card_par := 0;
  265.       for hole := 1 to max_holes do
  266.         begin
  267.           T2 := club.card_par[hole];
  268.           Write(T2:3);
  269.           card_par := card_par + T2;
  270.         end;
  271.       Writeln(' = ',card_par:3);
  272.       if color then Textcolor(yellow);
  273.       option := CourseAnalysis;
  274.     end;      {ScoreCard}
  275.  
  276.   Procedure Course_Box( xloc, yloc: byte;
  277.                              width, height: byte;
  278.                              name: string;
  279.                              file_size:integer;
  280.                              var over_top,hiline:byte); forward;
  281.  
  282.     Procedure Add_Course(var ch : char; var club : course_type);
  283.        var sum : byte;
  284.            x,y    : integer;
  285.            name   : string;
  286.  
  287.        begin
  288.              begin
  289.                Window(1,15,80,25);
  290.                ClrScr;
  291.                GotoXY(1,11);
  292.                Write('Escape to abort, digits for score,');
  293.                Write(' Backspace to correct, other for next score');
  294.                GotoXY(1,1);
  295.                club.name := '                                 ';
  296.                Write ('Name of new course is: ');
  297.  
  298.                GetName(name,32);
  299.                if option = ProgramExit then exit;
  300.                club.name := name;
  301.                Writeln;
  302.  
  303.                Write('  Rated par,(space), slope for ',club.name,' = ');
  304.                y := WhereY;
  305.                x := WhereX;
  306.                Readln(club.rated_par,ch,club.slope);
  307.                GotoXY(x,y);
  308.                ClrEol;
  309.                Writeln(club.rated_par:4:1,'/',club.slope);
  310.                Writeln('Enter pars from card (',max_holes,' holes)');
  311.                sum := 0;
  312.                Window(1,18,80,20);
  313.               for hole := 1 to max_holes do
  314.                  begin
  315.                    club.card_par[hole] := 4;  {Could be set in golfspec}
  316.                    sum := sum + club.card_par[hole];
  317.                    Write(club.card_par[hole]:3);
  318.                  end;
  319.                Writeln(' = ',sum:3);
  320.                hole := 1;
  321.                repeat {until not back-arrow}
  322.                  repeat  {until hole > max_holes}
  323.                    Window (3 * hole -2,18,3 * hole,20);
  324.                    TextBackground(white);
  325.                    Write(club.card_par[hole]:2,' ');
  326.                    GotoXY(1,1);
  327.                    club.card_par[hole] := Getnum(ch,club.card_par[hole],99);
  328.                    TextBackground(green);
  329.                    if option = ProgramExit then exit;
  330.                    if ch = #27 then exit;
  331.                    GotoXY(1,1);
  332.                    Writeln(club.card_par[hole]:3);
  333.                    case ch of
  334.                      #203 : if hole > 1 then hole := pred(hole);
  335.                      else
  336.                        hole := succ(hole);
  337.                      end;
  338.                  until hole > max_holes;
  339.                  begin
  340.                    Window(3*max_holes +1,18,80,25);
  341.                    sum := 0;
  342.                    for hole := 1 to max_holes do
  343.                      sum := sum + club.card_par[hole];
  344.                    TextBackground(white);
  345.                    Writeln(' = ',sum:3);
  346.                    TextBackground(green);
  347.                    ch := ReadKey;
  348.                    case ch of
  349.                     #0 : begin
  350.                            ch := Readkey;
  351.                            case ch of
  352.                              'K' : begin      {Back-Arrow}
  353.                                      GotoXY(1,1);
  354.                                      Writeln(' = ',sum:3);
  355.                                      hole := max_holes;
  356.                                      ch := #8;
  357.                                    end;
  358.                            end;
  359.                          end;
  360.                     #8 : begin  {Backspace}
  361.                            GotoXY(1,1);
  362.                            Writeln(' = ',sum:3);
  363.                            hole := max_holes;
  364.                          end;
  365.                    end;
  366.                  end;
  367.                until ch <> #8;
  368.                club.id := FileSize(courses);
  369.                Window(1,15,80,25);
  370.                ClrScr;
  371.                GotoXY(1,2);
  372.                if club.rated_par <= 0 then club.rated_par := sum;
  373.                Writeln('Club id ',club.id,': Clubname: "',club.name,
  374.                '", rated par = ', club.rated_par:4:1);
  375.                Write(' Pars = ');
  376.                for hole := 1 to max_holes do
  377.                    Write(club.card_par[hole]:3);
  378.                Writeln(' = ',sum:3);
  379.                Writeln('Is this OK to save?  Y/N');
  380.                ch := ReadKey;
  381.                if ch = #27 then exit;
  382.                if (ch = 'Y') or (ch = 'y') then
  383.                 begin
  384.                   Seek(courses,club.id);
  385.                   Write(courses,club);
  386.                   course_id := club.id;
  387.                   Cindex(course_view);
  388.                   Course_Box (80,1, SizeOf(club.name) + 2, max_course_box,
  389.                    'Courses',FileSize(courses),course_over_top,course_hiline);
  390.                 end;
  391.              end;
  392.  
  393.        end;    {Add_Course}
  394.  
  395.   Procedure Course_Box;
  396.     var
  397.       lineno        : byte;
  398.       CurrCourse    : course_type;
  399.       ch            : char;
  400.       course_height : byte;
  401.       print         : boolean;
  402.     begin
  403.       If file_size > max_course_box then course_height := max_course_box
  404.         else course_height := file_size;
  405.       If hiline > course_height then over_top := hiline - course_height;
  406.       Repeat
  407.         Box (xloc,yloc,width,course_height,name);
  408.         if color then TextBackground(green);
  409.         if color then TextColor(yellow);
  410.         repeat
  411.            ClrScr;
  412.            Seek (courses,over_top);
  413.            for lineno :=  1 to course_height do
  414.            begin
  415.              GotoXY(1,lineno);
  416.              Seek (courses,cx[over_top + lineno - 1]);
  417.              Read(courses,CurrCourse);
  418.              if lineno = hiline then
  419.                begin
  420.                  if color then TextBackground(red)
  421.                           else HighVideo ;
  422.                  club := CurrCourse;  {'club' is the selected course}
  423.                end;
  424.              ClrEol;      {in case there is some garbage on the line}
  425.                           {Paints correct Background color}
  426.              Write(CurrCourse.name);     {On assured clear background}
  427.              GotoXY(width - 2,lineno);   {Prepare to write club.id}
  428.              Write(CurrCourse.id:3);
  429.              if color then TextBackground(green)
  430.                       else LowVideo;
  431.              GotoXY (1,hiline);
  432.            end; {for loop}
  433.            Select(ch,hiline,over_top,file_size,course_height);
  434.            if ch = #27 then exit;
  435.         until ch <> #0; { "Enter" key}
  436.         If club.id = 0 then
  437.           Add_Course(ch,club);
  438.         course_id := club.id;
  439.         if option = ProgramExit then exit;
  440.         if ch = #27 then exit;
  441.        Until club.id <> 0;
  442.       option := SelectGolfer;
  443.     end;   {Course_Box}
  444.  
  445.   Procedure Golfer_Box( xloc, yloc: byte;
  446.                            width, height: byte;
  447.                            name: string;
  448.                            file_size:integer;
  449.                            var over_top,hiline:byte);forward;
  450.  
  451.     Procedure Add_Golfer(var ch : char; var golfer : golfer_type);
  452.  
  453.     var
  454.       i   : byte;
  455.       status : char;
  456.       name   : string;
  457.  
  458.     begin
  459.       Window(1,15,80,25);
  460.       ClrScr;
  461.       golfer := nobody;
  462.       Write(golfer.name,': ');
  463.       golfer.name := space20;   {Clear the background}
  464.  
  465.       GetName(name,20);
  466.       if option = ProgramExit then exit;
  467.       golfer.name := name;
  468.  
  469.       Writeln;
  470.       Writeln('Declared handicap : ');
  471.       Readln(golfer.hcp);
  472.       if option = ProgramExit then exit;
  473.       if status = #27 then exit;
  474.       golfer.id := FileSize(golfers);
  475.       ClrScr;
  476.       Writeln('New golfer #',golfer.id,' is ',golfer.name);
  477.       Writeln('Declared Handicap is ',golfer.hcp:3:1);
  478.       Writeln('Is this OK? Y/N');
  479.       ch := Readkey;
  480.       if ch = #27 then exit;
  481.       if (ch = 'Y') or (ch = 'y') then
  482.         begin
  483.           Seek(golfers,golfer.id);
  484.           Write(golfers,golfer);
  485.           golfer_id := golfer.id;
  486.           Gindex(golfer_view);
  487.           Str(golfer.id,s);
  488.           Assign (game_file,'golfr' + s);
  489.           Rewrite (game_file);
  490.           Close(game_file);
  491.           golfer.id := FileSize(golfers);
  492.           if golfer.id > max_golfer_box then
  493.           begin
  494.             golfer_hiline := max_golfer_box;
  495.             golfer_over_top := golfer.id - max_golfer_box;
  496.           end
  497.           else
  498.           begin
  499.             golfer_hiline := golfer.id;
  500.             golfer_over_top := 0;
  501.           end;
  502.           Golfer_Box (1,1,SizeOf(golfer.name) + 6,max_golfer_box,'Golfers',
  503.           FileSize(golfers),golfer_over_top,golfer_hiline);
  504.         end
  505.         else
  506.           golfer.id := 0;
  507.     end;  {Add_Golfer}
  508.  
  509.     Procedure Handicap_Box(xloc,yloc,width,height: byte);
  510.     begin
  511.       if width < 15 then width := 15;
  512.       Box(xloc,yloc,width,height,'Handicap Box');
  513.     end; {Handicap_Box}
  514.  
  515.     Function Handicap(var last20 : real20;last : word) : real;
  516.        var
  517.          BestLast : real20;
  518.          front,back,last_game,middle : word;
  519.          temp,temp2,realtemp : real;
  520.          i,j  : word;
  521.          x_pos,y_pos  : shortint;
  522.        begin
  523.          if last = 0 then
  524.          begin
  525.            handicap := 0;
  526.            AntiHcp  := 0;
  527.            exit;
  528.          end;
  529.          BestLast := last20;
  530.          if last < max_diffs then last_game := last
  531.                       else last_game:= max_diffs;
  532.          middle := (last_game + 1) div 2;
  533.          for front := 1 to last_game do    {Sort}
  534.          begin
  535.            for back := front to last_game do
  536.            begin
  537.               if BestLast[front] > BestLast[back] then
  538.               begin
  539.                 temp := BestLast[front];
  540.                 BestLast[front] := BestLast[back];
  541.                 BestLast[back] := temp;
  542.               end
  543.            end
  544.          end;
  545.          temp := 0;
  546.          temp2 := 0;
  547.  
  548.            for front := 1 to middle do
  549.              temp := temp + BestLast[front] * 2;
  550.            for front := middle + 1 to last_game do
  551.              temp2 := temp2 + BestLast[front] * 2;
  552.  
  553.          if ((middle * 2) <> last_game) then
  554.          begin
  555.            temp := temp - BestLast[middle];
  556.            temp2 := temp2 + BestLast[middle];
  557.          end;
  558.          Realtemp := (temp / last_game) * percent/100;
  559.          handicap := realtemp;
  560.          AntiHcp  := (temp2 / last_game) * percent/100;
  561.          x_pos := WhereX;
  562.          y_pos := WhereY;
  563.          Handicap_Box(1,11,((last_game + 1) div 2)* 5,2);
  564.          GotoXY(1,1);
  565.          if (last_game div 2) * 2 = last_game
  566.           then temp := (BestLast[middle] + BestLast[middle + 1]) / 2
  567.           else temp := BestLast[middle];
  568.          for i := 1 to last_game do
  569.            begin
  570.              if color then TextColor(black);
  571.              if last20[i] = temp then
  572.                if color then TextColor(blue);
  573.              if last20[i] < temp then
  574.                if color then TextColor(red);
  575.            Write(last20[i]:5:1);
  576.            if i = last_game - (last_game div 2) then Writeln;
  577.            end;
  578.          if color then TextColor(yellow);
  579.          Window(1,15,80,25);
  580.          GotoXY(x_pos,y_pos);
  581.        end;  {Handicap}
  582.  
  583.     Procedure Get_Score (var status: char; var curr_game: game_type);forward;
  584.     Procedure Post;forward;
  585.  
  586.   Procedure Golfer_Box;
  587.     var
  588.       lineno         : byte;
  589.       CurrGolfer     : golfer_type;
  590.       ch             : char;
  591.       hcp            : real;
  592.       golfer_height  : byte;
  593.       status         : char;
  594.  
  595.     begin
  596.       if file_size > max_golfer_box then golfer_height := max_golfer_box
  597.         else golfer_height := file_size;
  598.       if hiline > golfer_height then over_top := hiline - golfer_height;
  599.       repeat
  600.         Box (xloc,yloc,width,golfer_height,name);
  601.         if color then TextBackground(green);
  602.         if color then TextColor(yellow);
  603.         repeat
  604.           ClrScr;
  605.           Seek (golfers,over_top);
  606.           for lineno := 1 to  golfer_height do
  607.           begin
  608.             GotoXY(1,lineno);
  609.             Seek(golfers,gx[over_top + lineno -1]);
  610.             Read(golfers,CurrGolfer);
  611.             if lineno = hiline then
  612.               begin
  613.                 if color then TextBackground(red)
  614.                          else HighVideo;
  615.                 golfer := CurrGolfer;  {'golfer' is selected golfer}
  616.               end;
  617.             ClrEol;      {in case there is some garbage on the line}
  618.                          {Paints correct Background color}
  619.              Write(CurrGolfer.name);
  620.             GotoXY(width - 4,lineno);
  621.             Write(CurrGolfer.hcp:4:2);
  622.             if color then TextBackground(green)
  623.                      else LowVideo;
  624.             GotoXY (1,hiline);
  625.           end;
  626.           Select (ch,hiline,over_top,file_size,golfer_height);
  627.           if ch = #27 then exit
  628.         until  ch <> #0;  {"Almost any" key}
  629.         if golfer.id <> 0
  630.           then
  631.             begin
  632.               Str(Golfer.id,s);
  633.               Assign (game_file,'golfr' + s);
  634. {$I-}
  635.               Reset(game_file);
  636. {$I+}
  637.               if ioresult <> 0 then
  638.                 begin
  639.                   Rewrite(game_file);
  640.                   Reset(game_file);
  641.                 end     {if ioresult}
  642.             end    {if golfer.id then}
  643.           else  {golfer.id = 0}
  644.             Add_golfer(status,golfer);
  645.         golfer_id := golfer.id;
  646.         if option = ProgramExit then exit;
  647.         if status = #27 then exit;
  648.       until golfer.id <> 0;
  649.       Seek(golfers,golfer.id);
  650.       Read(golfers,golfer);
  651.       hcp := Handicap(golfer.last_20,golfer.no_of_games);
  652.       option := PostScore;
  653.     end;    {Golfer_Box}
  654.  
  655.  
  656.   Procedure Equitable_Stroke_Control
  657.         (var esc_score : scores;actual,par : scores;hcp : real);
  658.  
  659.     var
  660.        hole,normal_over,extra,hole_max : shortint;
  661.  
  662.     Procedure ESC1973;
  663.       begin
  664.        if actual[hole] <= (par[hole] + normal_over)
  665.           then esc_score[hole] := actual[hole]
  666.           else
  667.            begin
  668.              esc_score[hole] := par[hole] + normal_over;
  669.              if extra > 0 then
  670.                 begin
  671.                    extra := extra - 1;
  672.                    esc_score[hole] := esc_score[hole] + 1;
  673.                 end
  674.            end
  675.        end;
  676.  
  677.     Procedure ESC1993;
  678.       begin
  679.         if actual[hole] > hole_max then esc_score[hole] := hole_max
  680.                                    else esc_score[hole] := actual[hole];
  681.       end;
  682.  
  683.     begin  {Equitable_Stroke_Control}
  684.  
  685.        {Values needed for 1973 Equitable Stroke Control rules}
  686.        normal_over := (System.Round(hcp) div max_holes) + 1;
  687.        extra := System.Round(hcp) mod max_holes;
  688.  
  689.        {Value needed for 1993 Equitable Stroke Control rules}
  690.        hole_max := (System.Round(hcp) div 10) + 6;
  691.  
  692.        Window(1,20,80,21);
  693.        Write('EqStr');
  694.        Eq_sum := 0;
  695.        for hole := 1 to max_holes do
  696.           begin
  697.             case adj_score_rule of
  698.               0: esc_score[hole] := actual[hole];
  699.               1: if actual[hole] > 2 * par[hole]  {double par rule}
  700.                    then esc_score[hole] := 2 * par[hole]
  701.                    else esc_score[hole] := actual[hole];
  702.               2: ESC1973;
  703.               3: ESC1993;
  704.               4: if year < 1973
  705.                   then esc_score[hole] := actual[hole]
  706.                   else if year < 1993
  707.                           then ESC1973
  708.                           else ESC1993;
  709.             end; {case}
  710.             if color then
  711.               begin
  712.                 if esc_score[hole] < par[hole] then TextColor(red);
  713.                 if esc_score[hole] > par[hole] then TextColor(black);
  714.                 if esc_score[hole] = par[hole] then TextColor(blue);
  715.               end;
  716.             if esc_score[hole] = actual[hole]
  717.               then Write('  .')
  718.               else Write(esc_score[hole]:3);
  719.             eq_sum := eq_sum + esc_score[hole];
  720.             if color then TextColor(yellow);
  721.           end; {for holes}
  722.             Write(' =',eq_sum:5:1);
  723.             Write('- ',club.rated_par:4:1,' =');
  724.             eq_sum := eq_sum - club.rated_par;
  725.             Writeln (eq_sum:5:1);
  726.     end;     {Equitable_Stroke_Control}
  727.  
  728.   Procedure Get_Score;
  729.     var
  730.       hole,t1,t2,t3: integer;
  731.     begin
  732.       GetDate(year,month,day,dayofweek);
  733.       Window(1,15,80,25);   {score screen}
  734.       GotoXY(1,11);
  735.       Write('press <enter> when date is OK.');
  736.       GotoXY(xloc +3 ,2);
  737.       Write('Date  ',month:2,'/',day:2,'/',year);
  738.       GotoXY(xloc +8,2);
  739.       Get_Date(status,month,day,year);
  740.       if option = ProgramExit then exit;
  741.       if status = #27 then
  742.         begin
  743.           option := PostScore;
  744.           Window(1,20,80,21);
  745.           exit;
  746.         end;
  747.       GotoXY(1,11);
  748.       Write('Escape to abort, digits for score,');
  749.       Write(' Backspace to correct, other for next score');
  750.       GotoXY(1,5);
  751.       Write('Score');
  752.       T1 := 0;
  753.       for hole := 1 to max_holes do
  754.         curr_game.score[hole] := club.card_par[hole];
  755.       hole := 1;
  756.       repeat {until not <- }
  757.         repeat {until hole > max_holes}
  758.           T2 := curr_game.score[hole];
  759.           Window(3+hole*3,19,5+hole*3,20);
  760.           if color then TextBackground(white);
  761.           Write(T2:3);
  762.           GotoXY(2,1);
  763.           T2 := GetNum(status,T2,99);
  764.           if option = ProgramExit then exit;
  765.           case status of
  766.             #27 :
  767.               begin
  768.                 option := SelectGolfer;
  769.                 Window(1,20,80,21);
  770.                 exit;
  771.               end;
  772.             #203 :
  773.              if hole > 1 then
  774.                          begin
  775.                            curr_game.score[hole] := T2;
  776.                            hole := hole - 2;
  777.                          end;
  778.             else  {case}
  779.               begin
  780.                 if color then
  781.                   begin
  782.                     if T2 < club.card_par[hole] then TextColor(Lightred);
  783.                     if T2 > club.card_par[hole] then TextColor(Darkgray);
  784.                     if T2 = club.card_par[hole] then  TextColor(LightBlue);
  785.                   end;
  786.                 GotoXY (1,1);
  787.                 if color then TextBackground(green);
  788.                 Write(T2:3);
  789.                 if color then TextColor(yellow);
  790.                 curr_game.score[hole] := T2;
  791.               end; {else case}
  792.             end; {case}
  793.           hole := succ(hole);
  794.         until hole > max_holes;
  795.         for hole := 1 to max_holes do T1 := T1 + curr_game.score[hole];
  796.         Window(6+max_holes*3,19,80,20);
  797.         TextBackground(white);
  798.         Write(' =',T1:4);
  799.         ch := Readkey;
  800.         if ch = #0 then ch := Readkey;
  801.         if ch = 'K' then
  802.           begin
  803.             hole := max_holes;
  804.             GotoXY(1,1);
  805.             TextBackground(green);
  806.             ClrEol;
  807.             T1 := 0;
  808.           end; {of reset for a back-arrow}
  809.       until ch <> 'K';  {Until not a back-arrow}
  810.       Window(6 + max_holes*3,19,80,20);
  811.       TextBackground(green);
  812.       Write(' =',T1:4,' -',card_par:3,' =');
  813.       T1 := T1 - card_par;
  814.       Writeln(T1:3);
  815.       Equitable_Stroke_Control( esc_score,
  816.                                 curr_game.score,
  817.                                 club.card_par,
  818.                                 golfer.hcp);
  819.       if color then TextBackground(green);
  820.     end;     {Get_Score}
  821.  
  822.   Procedure Post;
  823.     var
  824.       s : integer;
  825.       i : shortint;
  826.       ans,ch : char;
  827.       temp : real;
  828.       status : char;
  829.  
  830.     begin
  831.       scorecard;
  832.       Get_Score(status,curr_game);
  833.       if option = ProgramExit then exit;
  834.       repeat
  835.         GotoXY(1,7);
  836.         ClrEol;
  837.         if status = #27 then ans := status
  838.           else
  839.             begin
  840.               Write('OK for posting? Y/N ');
  841.               ans := ReadKey;
  842.               if ans = #0 then
  843.                 begin
  844.                   ans := Readkey;
  845.                   if ans = '-' then
  846.                     begin
  847.                       option := ProgramExit;
  848.                       exit;
  849.                     end
  850.                 end
  851.             end;
  852.       until ans in ['Y','y','N','n',#27];
  853.       case ans of
  854.         'Y','y':
  855.           begin
  856. {$I-}
  857.             s := FileSize(game_file);
  858.             if IOResult <> 0 then exit;
  859. {$I+}
  860.             if s < max_diffs
  861.               then s := s + 1
  862.               else
  863.                 begin
  864.                   s := max_diffs;
  865.                   for i := 1 to s-1 do
  866.                     golfer.last_20[i] := golfer.last_20[i+1];
  867.                 end; {if FileSize}
  868.             if IOResult <> 0 then exit;
  869.             golfer.last_20[s] := eq_sum; {New game always at end}
  870.             curr_game.game_no := FileSize(game_file) + 1;
  871.             golfer.no_of_games := curr_game.game_no;
  872.             golfer.hcp := Handicap(golfer.last_20,golfer.no_of_games);
  873.             curr_game.hcp := round(golfer.hcp);
  874.             curr_game.course_id := club.id;
  875.             curr_game.year := year - 1900;
  876.             curr_game.month := month;
  877.             curr_game.day   := day;
  878.             GotoXY(1,WhereY + 5);
  879.             Writeln('Posted..New Hcp is: ',golfer.hcp:5:2,' (',
  880.                      round(golfer.hcp):2,'), Game no ',curr_game.game_no:4);
  881.             i := WhereY;
  882.             Seek (game_file,FileSize(game_file));
  883.             Write(game_file,curr_game);
  884.             Seek(golfers,golfer.id);
  885.             Write(golfers,golfer);
  886.           end; {Yes case}
  887.         'N','n',#27: Write('--not posted');
  888.       end; {case}
  889.       option := CourseAnalysis;
  890.     end;     {Post}
  891.  
  892.   Procedure Analysis(var gamefile: game_file_type;
  893.                          club : course_type );
  894.     type
  895.       score_range = -3..10;
  896.       over_by_hole_type = array[score_range,holes] of integer;
  897.       difficulty_type = record
  898.                           order  : shortint;
  899.                           rank   : shortint;
  900.                           overage: real;
  901.                         end;
  902.       ranking_type = array[holes] of difficulty_type;
  903.     const
  904.       over_par:array [score_range] of string[15] =
  905.       ('Double Eagle...','Eagles.........','Birdies........'
  906.       ,'Pars...........','Bogies.........','Double_bogies..'
  907.       ,'Triple_bogies..','Quad_bogies....','Five_overs.....'
  908.       ,'Six_overs......','Seven_overs....','Eight_overs....'
  909.       ,'Nine_overs.....','Over Nine over!');
  910.     var
  911.       over_by_hole   : over_by_hole_type;
  912.       average        : array [holes] of real;
  913.       front9,back9   : real;
  914.       totals         : real;
  915.       hole           : shortint;
  916.       sums           : array [holes] of integer;
  917.       current_game   : game_type;
  918.       this_course,
  919.       this_game_file : shortint;
  920.       score_count    : integer;
  921.       sum_scores     : array [score_range] of integer;
  922.       sum_card_pars  : integer;
  923.       overage        : score_range;
  924.       hole_rank      : ranking_type;
  925.       key            : shortint;
  926.       start_date,end_date,
  927.       curr_date      : longint;
  928.       month,day,year,dayofweek : word;
  929.       total          : integer;
  930.       status         : char;
  931.       BestSum,  WorstSum,  LastSum : byte;
  932.       BestDate, WorstDate, LastDate: longint;
  933.       Hcp            : real;
  934.     procedure Sort (var row : ranking_type; key:shortint; length : shortint);
  935.  
  936.     {row is an array of elements to be sorted, while length is the number of
  937.     elements in the array.  row[i] serves as both element and sort key.
  938.     Necessary to write a new procedure for each element type and sort key!?
  939.     The elements here MUST be in an array (not a file) }
  940.  
  941.       var
  942.         jump, m, n : shortint;    {These are used as indices into array}
  943.         temp       : difficulty_type;  {This too must be same type as element}
  944.         alldone    : boolean;
  945.  
  946.       procedure Interchange;
  947.         begin   {interchange elements ... within Sort}
  948.           temp   := row[m];   {Here row[i] is used as element}
  949.           row[m] := row[n];
  950.           row[n] := temp;
  951.           alldone:= false;
  952.         end;    {Interchange}
  953.  
  954.       begin   {Sort ... within Analysis}
  955.         jump := length;
  956.         while jump > 1 do
  957.          begin
  958.            jump := jump div 2;
  959.            repeat
  960.              alldone := true;
  961.              for m := 1 to length - jump do
  962.                begin
  963.                  n := m + jump;
  964.                  {Test sort keys for desired order}
  965.                  case key of
  966.                    1: {Here row[i] is used as sort key}
  967.                      if row[m].overage < row[n].overage then Interchange;
  968.                    2:
  969.                      if row[m].order > row[n].order then Interchange;
  970.                  end; {case}
  971.                end {for}
  972.            until alldone
  973.         end {while}
  974.       end; {Sort}
  975.  
  976.     begin   {Analysis}
  977.       Window(1,10,80,25);
  978.       ClrScr;
  979. {$I-}
  980.       Reset (game_file);
  981. {$I-}
  982.       if ioresult <> 0 then
  983.         begin
  984.           Window(1,1,80,25);
  985.           GotoXY(25,15);
  986.           Writeln('No game file for this golfer!');
  987.           option := PostScore;
  988.           exit;
  989.         end;
  990.       GetDate(year,month,day,dayofweek);
  991.       month := 1;
  992.       day   := 1;
  993.       Window(1,11,80,25);
  994.       Writeln('Starting date for analysis');
  995.       Window(1,12,80,25);
  996.       Get_Date(status,month,day,year);
  997.       Window(1,13,80,25);
  998.       start_date := 10000*(Year - 1990) + month*100 + day;
  999.       Window(1,14,80,25);
  1000.       Writeln('Ending date');
  1001.       Window(1,15,80,25);
  1002.       GetDate(year,month,day,dayofweek);
  1003.       Get_Date(status,month,day,year);
  1004.       end_date := 10000*(year - 1990)+month*100+day;
  1005.       Window(1,17,80,25);
  1006.       Writeln('Printing? Y/N ');
  1007.       ch := ReadKey;
  1008.       printing := ch in ['y','Y'];
  1009.       if ch = #0 then ch := ReadKey;
  1010.       Window(1,1,80,25);
  1011.       ClrScr;
  1012.       for hole := 1 to max_holes do
  1013.         begin
  1014.           for overage := -3 to 10 do
  1015.               over_by_hole[overage,hole] := 0;
  1016.           sums[hole] := 0;
  1017.           average[hole] := 0;
  1018.         end;
  1019.       for overage := -3 to 10 do
  1020.           sum_scores [overage] := 0;
  1021.       sum_card_pars := 0;
  1022.       total := 0;
  1023.       score_count := 0;
  1024.       While FilePos(game_file) < FileSize(game_file) do
  1025.         begin
  1026. {$I-}
  1027.           Read(game_file,current_game);
  1028.           if ioresult <> 0 then
  1029.             begin
  1030.               GotoXY(10,10);
  1031.               Write('No Game file for this golfer!');
  1032.               option := ProgramExit;
  1033.               exit;
  1034.             end;
  1035. {$I+}
  1036.           with club do
  1037.             begin;
  1038.               with current_game do
  1039.                 begin;
  1040.                   curr_date := 10000*(year - 90)+month*100+day;
  1041.                   if (curr_date >= start_date) and
  1042.                   (curr_date <= end_date) then
  1043.                     begin
  1044.                       total := total + 1;
  1045.                       last_game_no := current_game.game_no;
  1046.                       if first_game_no = 0 then
  1047.                         first_game_no := last_game_no;
  1048.                       if club.id = current_game.course_id then
  1049.                         begin
  1050.                           score_count := Succ(score_count);
  1051.                           LastSum  := 0;
  1052.                           LastDate := curr_date;
  1053.                       for hole := 1 to max_holes do
  1054.                         begin
  1055.                           lastsum := lastsum + score[hole];
  1056.                           for overage := -3 to 10 do
  1057.                             if score[hole] = (card_par[hole] + overage ) then
  1058.                               over_by_hole[overage,hole] :=
  1059.                                 Succ(over_by_hole[overage,hole]);
  1060.                           if score[hole] > (card_par[hole] + 10) then
  1061.                             over_by_hole[10,hole] :=
  1062.                               Succ(over_by_hole[10,hole]);
  1063.                           sums[hole] := sums[hole] + score[hole];
  1064.                         end; {hole 1 to max_holes}
  1065.                         if score_count = 1
  1066.                          then
  1067.                            begin
  1068.                              Worstsum := lastsum;
  1069.                              Bestsum := lastsum;
  1070.                              bestdate := curr_date;
  1071.                              worstdate := curr_date;
  1072.                            end
  1073.                          else
  1074.                            begin
  1075.                              if lastsum > worstsum then
  1076.                                begin
  1077.                                  worstsum := lastsum;
  1078.                                  worstdate := curr_date;
  1079.                                end;
  1080.                              if bestsum > lastsum then
  1081.                                begin
  1082.                                  bestsum  := lastsum;
  1083.                                  bestdate := curr_date;
  1084.                                end;
  1085.                            end; {Best,worst,last}
  1086.                       end; {club.id = curr_game.course_id}
  1087.                   end; {current_date in bounds}
  1088.               end; {inner with (current_game)}
  1089.           end; {outer with (club)}
  1090.         end;  {while}
  1091.       Window(1,1,80,25);
  1092.       if score_count = 0 then
  1093.         begin
  1094.           GotoXY(5,12);
  1095.           Writeln(golfer.name,' has not played at ',club.name,'!');
  1096.           option := ProgramExit;
  1097.           exit;
  1098.         end;
  1099.       if printing then
  1100. {$I-}
  1101.         repeat
  1102.           Writeln(lst,'Analysis ',score_count,' scores at ',club.name,
  1103.            ' (',total,' in all) For ',golfer.name );
  1104.            errcode := IOResult;
  1105.            if errcode <> 0 then Writeln('Turn on Printer');
  1106.         until errcode = 0;
  1107. {$I+}
  1108.       ClrScr;
  1109.       Writeln('Analysis of ',score_count,' scores at ',club.name,
  1110.       ' (',total,' in all) For ',golfer.name );
  1111.       if color then
  1112.         TextColor(yellow);
  1113.       Write('For Hole number');
  1114.       for hole := 1 to max_holes do
  1115.         Write(hole:3);
  1116.       Writeln(' Total');
  1117.       Write(' Card par      ');
  1118.       for hole := 1 to max_holes do
  1119.         begin
  1120.           Write(club.card_par[hole]:3);
  1121.           sum_card_pars := sum_card_pars + club.card_par[hole];
  1122.         end;
  1123.       Write(' =',sum_card_pars:4);
  1124.       Writeln;
  1125.       for overage := -3 to 10 do
  1126.         begin
  1127.           case overage of
  1128.             -1,-2,-3: if color then TextColor(red);
  1129.              0   : if color then TextColor(blue);
  1130.           else
  1131.             if color then TextColor(black);
  1132.           end; {case}
  1133.           for hole := 1 to max_holes do
  1134.               sum_scores[overage] := sum_scores[overage]
  1135.               + over_by_hole[overage,hole];
  1136.           if sum_scores[overage] <> 0 then
  1137.             begin
  1138.               Write(over_par[overage]);
  1139.               for hole := 1 to max_holes do
  1140.                 if over_by_hole[overage,hole] = 0 then Write('  .')
  1141.                 else Write(over_by_hole[overage,hole]:3);
  1142.               Writeln(' =',sum_scores[overage]:4);
  1143.             end;
  1144.         end; {for overage loop}
  1145.       if color then
  1146.         TextColor(yellow);
  1147.       Writeln('  Hole number (Personal difficulty rank) and ''over_par average''');
  1148.       front9 := 0;
  1149.       back9  := 0;
  1150.       for hole := 1 to front do
  1151.         begin
  1152.           average[hole] := sums[hole] / score_count;
  1153.           front9 := front9 + average[hole];
  1154.         end;
  1155.       for hole := front + 1 to max_holes do
  1156.         begin
  1157.            average[hole] := sums[hole] / score_count;
  1158.            back9 := back9 + average[hole];
  1159.         end;
  1160.       totals := front9 + back9;
  1161.       for hole := 1 to max_holes do
  1162.         begin
  1163.           hole_rank[hole].order := hole;
  1164.           hole_rank[hole].overage := average[hole] - club.card_par[hole];
  1165.         end;
  1166.       Sort(hole_rank,1,max_holes);
  1167.       for hole := 1 to max_holes do
  1168.         hole_rank[hole].rank := hole;
  1169.       Sort(hole_rank,2,max_holes);
  1170.       for hole := 1 to front do
  1171.         begin
  1172.           Write(' hole ',hole:2,' (',hole_rank[hole].rank:2,') : ',
  1173.             average[hole]:6:3);
  1174.           Write(' -',club.card_par[hole]:2,' = ');
  1175.           Write(average[hole] - club.card_par[hole]:6:3);
  1176.           If hole + front <= max_holes then
  1177.             begin
  1178.               Write('   hole ',hole + front:2,' (',
  1179.                     hole_rank[hole + front].rank:2,
  1180.                     ') : ',average[hole + front]:6:3);
  1181.               Write(' -',club.card_par[hole + front]:2,' = ');
  1182.               Write(average[hole + front] - club.card_par[hole + front]:6:3);
  1183.             end;
  1184.           Writeln;
  1185.         end;
  1186.       Write(' Front       :',front9:7:3);Write('                ');
  1187.       Writeln('Back        :',back9:7:3);
  1188.       GetDate(year,month,day,dayofweek);
  1189.       Writeln(' Grand average =',totals:7:3,' , current (',
  1190.       month,'/',day,'/',year,') hcp =',
  1191.       golfer.hcp:5:1,'  Anti-hcp =', AntiHcp:5:1);
  1192.       Write(' Best: ',BestSum,' on ',(BestDate mod 10000) div 100,'/',
  1193.                                     (BestDate mod 100),'/',
  1194.                                     (BestDate div 10000) + 1990,';  ');
  1195.       Write('Worst: ',WorstSum,' on ',(WorstDate mod 10000) div 100,'/',
  1196.                                     (WorstDate mod 100),'/',
  1197.                                     (WorstDate div 10000) + 1990,';  ');
  1198.       Write('Last: ',LastSum,' on ',(LastDate mod 10000) div 100,'/',
  1199.                                     (LastDate mod 100),'/',
  1200.                                     (LastDate div 10000) + 1990);
  1201.       if printing then
  1202.         begin
  1203.           Write(lst,' from ', (start_Date mod 10000) div 100,'/',
  1204.                        (start_Date mod 100),'/',
  1205.                        (start_Date div 10000) + 1990,';  ');
  1206.           Writeln(lst,' to ', (end_Date mod 10000) div 100,'/',
  1207.                        (end_Date mod 100),'/',
  1208.                        (end_Date div 10000) + 1990,';  ');
  1209.           Writeln(lst);
  1210.           Write(lst,'For Hole number');
  1211.           for hole := 1 to max_holes do
  1212.             Write(lst,hole:3);
  1213.           Writeln(lst,' Total');
  1214.           Write(lst,' Card par      ');
  1215.           for hole := 1 to max_holes do
  1216.             Write(lst,club.card_par[hole]:3);
  1217.           Write(lst,' =',sum_card_pars:4);
  1218.           Writeln(lst);
  1219.           for overage := -3 to 10 do
  1220.             begin
  1221.               if sum_scores[overage] <> 0 then
  1222.                 begin
  1223.                   Write(lst,over_par[overage]);
  1224.                   for hole := 1 to max_holes do
  1225.                     if over_by_hole[overage,hole] = 0 then Write(lst,'  .')
  1226.                     else Write(lst,over_by_hole[overage,hole]:3);
  1227.                   Writeln(lst,' =',sum_scores[overage]:4);
  1228.                 end;
  1229.             end;
  1230.           for hole := 1 to 3 do
  1231.             Writeln(lst);
  1232.           Writeln(lst,'  Hole number (Personal difficulty rank) and ''over_par average''');
  1233.           Writeln(lst);
  1234.           for hole := 1 to front do
  1235.             begin
  1236.               Write(lst,' hole ',hole:2,' (',hole_rank[hole].rank:2,') : ',
  1237.                 average[hole]:6:3);
  1238.               Write(lst,' -',club.card_par[hole]:2,' = ');
  1239.               Write(lst,average[hole] - club.card_par[hole]:6:3);
  1240.               If hole + front <= max_holes then
  1241.                 begin
  1242.                   Write(lst,'   hole ',hole + front:2,' (',hole_rank[hole + front].rank:2,
  1243.                   ') : ',average[hole + front]:6:3);
  1244.                   Write(lst,' -',club.card_par[hole + front]:2,' = ');
  1245.                   Write(lst,average[hole + front] - club.card_par[hole + front]:6:3);
  1246.                 end;
  1247.               Writeln(lst);
  1248.           end;
  1249.           Write(lst,' Front       :',front9:7:3);Write(lst,'                ');
  1250.           Writeln(lst,'Back        :',back9:7:3);
  1251.           GetDate(year,month,day,dayofweek);
  1252.           Writeln(lst,' Grand average =',totals:7:3,' , current (',
  1253.           month,'/',day,'/',year,') hcp =',
  1254.           golfer.hcp:5:1,'  Anti-hcp =', AntiHcp:5:1);
  1255.           Writeln(lst);
  1256.           Writeln(lst,' Best:  ',BestSum,' on ',
  1257.                (BestDate mod 10000) div 100,'/',
  1258.                (BestDate mod 100),'/',
  1259.                (BestDate div 10000) + 1990,';  ');
  1260.           Writeln(lst,' Worst: ',WorstSum,' on ',
  1261.                (WorstDate mod 10000) div 100,'/',
  1262.                (WorstDate mod 100),'/',
  1263.                (WorstDate div 10000) + 1990,';  ');
  1264.           Writeln(lst,' Last:  ',LastSum,' on ',
  1265.                (LastDate mod 10000) div 100,'/',
  1266.                (LastDate mod 100),'/',
  1267.                (LastDate div 10000) + 1990);
  1268.           Writeln(lst,#12);
  1269.           Write(lst,golfer.name,'''s Game list from ',
  1270.                (start_date mod 10000) div 100,'/',
  1271.                (start_date mod 100),'/',
  1272.                (start_date div 10000) + 1990);
  1273.           Writeln(lst,' to ',
  1274.                (end_date mod 10000) div 100,'/',
  1275.                (end_date mod 100),'/',
  1276.                (end_date div 10000) + 1990);
  1277.           prev_game.course_id := 0;
  1278.           for score_count := first_game_no to last_game_no do
  1279.             begin
  1280.               Seek(game_file,score_count - 1);
  1281.               Read(game_file,current_game);
  1282.               if current_game.course_id <> prev_game.course_id then
  1283.                 begin
  1284.                   prev_game.course_id := current_game.course_id;
  1285.                   Seek(courses,current_game.course_id);
  1286.                   Read(courses,club);
  1287.                   Writeln(lst,'      ',club.name);
  1288.                   total := 0;
  1289.                   Write(lst,'   Par =  ');
  1290.                   for hole := 1 to max_holes do
  1291.                     begin
  1292.                       Write(lst,club.card_par[hole]:3);
  1293.                       total := total + club.card_par[hole];
  1294.                     end;
  1295.                   Writeln(lst,' =',total:4);
  1296.                 end;
  1297.                 total := 0;
  1298.                 with current_game do
  1299.                 begin
  1300.                   Write(lst,month:2,'/',day:2,'/19',year:2);
  1301.                   for hole := 1 to max_holes do
  1302.                    begin
  1303.                      write(lst,score[hole]:3);
  1304.                                total := total + score[hole];
  1305.                    end;
  1306.                   Writeln(lst,' =',total:4);
  1307.                 end;
  1308.             end;
  1309.           Writeln(lst,#12);
  1310.         end;
  1311.       Readln;
  1312.       if color then TextBackground(black);
  1313.       ClrScr;
  1314.       option := ProgramExit;
  1315.     end;   {Analysis}
  1316.  
  1317.   Procedure Edit(var hiline: byte);
  1318.     var
  1319.       oldfile  : string[12];
  1320.       saveid   : byte;
  1321.       i        : integer;
  1322.       t1,t2    : integer;
  1323.       t3,t4    : integer;
  1324.       chr      : char;
  1325.       newfile  : string[12];
  1326.       copycom  : string;
  1327.       ch       : string[1];
  1328.       hcp      : real;
  1329.     const
  1330.       savename : string[20] = '                    ';
  1331.       quit     : byte = 4;
  1332.  
  1333.     begin
  1334.       Str(golfer.id,s);
  1335.       copycom := '/c copy golfr' + s + ' golfr' + s + '.bak >temp ';
  1336.       SwapVectors;
  1337.       exec('c:\command.com',copycom);
  1338.       SwapVectors;
  1339.       if DosError <> 0 then Writeln('DosError = ',DosError);
  1340.       newfile := savename;
  1341.       if color then TextColor(black);
  1342.       if color then TextBackground(green);
  1343.       Seek(golfers,golfer_id);
  1344.       Read(golfers,golfer);
  1345.       hcp := Handicap(golfer.last_20,golfer.no_of_games);
  1346.       savename := golfer.name;
  1347.       saveid := golfer.id;
  1348.       golfer := nobody;
  1349.       golfer.name := savename;
  1350.       golfer.id := saveid;
  1351.       Str(saveid,ch);
  1352.       newfile := 'golfr' + ch;
  1353.       Window (40,11,80,16);
  1354.       ClrScr;
  1355.       Writeln('Name of gamefile: ');
  1356.       Read(oldfile);
  1357.       t1 := WhereX;
  1358.       if oldfile = '' then oldfile := newfile + '.bak';
  1359.       Assign (old,oldfile);
  1360. {$I-}
  1361.       Reset (old);
  1362. {$I+}
  1363.       if ioresult <> 0 then
  1364.         begin
  1365.           Writeln('File error');
  1366.           option := ProgramExit;
  1367.           exit;
  1368.         end;
  1369.       GotoXY(t1,2);
  1370.       Writeln(oldfile ,'  --> ', newfile);
  1371.       Assign (game_file, newfile);Rewrite (game_file);
  1372.       Writeln('Press <delete> to skip game');
  1373.       Writeln('Press <insert> to add game, ');
  1374.       Write('<esc> to abort,');
  1375.       Writeln(' other to include ');
  1376.       repeat
  1377.         Read(old,curr_game);
  1378.         Seek(courses,curr_game.course_id);
  1379.         year := curr_game.year + 1900;
  1380.         month := curr_game.month;
  1381.         day := curr_game.day;
  1382.         if color then TextColor(black);
  1383.         if color then TextBackground(green);
  1384. {$I-}
  1385.         Read(courses,club);
  1386.         if ioresult <> 0 then
  1387.           begin
  1388.             Write('Error in ''''courses'''' file');
  1389.             option := ProgramExit;
  1390.             exit;
  1391.           end;
  1392. {$I+}
  1393.         Scorecard;
  1394.         if color then TextColor(black);
  1395.         if color then TextBackground(green);
  1396.         GotoXY(xloc + 2,2);
  1397.         Writeln ('Date ', month:2,'/',day:2,'/',year);
  1398.         GotoXY(1,5);
  1399.         Write('Score');
  1400.         t2 := 0;
  1401.         t4 := 0;
  1402.         for hole := 1 to max_holes do
  1403.           begin
  1404.             t1 := curr_game.score[hole];
  1405.             t3 := club.card_par[hole];
  1406.             if t3 = t1 then if color then TextColor(blue);
  1407.             if t3 > t1 then if color then TextColor(red);
  1408.             Write(t1:3);
  1409.             t2 := t2 + t1;
  1410.             t4 := t4 + t3;
  1411.             if color then TextColor(black);
  1412.           end;
  1413.         Writeln(' = ', t2:4,' - ',t4,' = ',t4 - t3);
  1414.         Equitable_Stroke_Control(esc_score,curr_game.score,
  1415.                               club.card_par,golfer.hcp);
  1416.         chr := ReadKey;
  1417.         if chr = #0 then chr := ReadKey;
  1418.         case chr of
  1419.          'R':  {Insert key}
  1420.            begin
  1421.              Course_Box (80,1, SizeOf(club.name) + 2, max_course_box,
  1422.              'Courses', FileSize(courses), course_over_top, course_hiline);
  1423.              Post;
  1424.              Seek(old,FilePos(old) - 1);
  1425.            end;
  1426.          'S',#27: {Nothing}
  1427.         else
  1428.           begin {compound statement}
  1429.             Seek (game_file,FileSize(game_file));
  1430.             curr_game.game_no := FilePos(game_file) + 1;
  1431.             if golfer.no_of_games > max_diffs - 1
  1432.               then
  1433.                 begin
  1434.                   for i := 1 to max_diffs - 1 do
  1435.                     golfer.last_20[i] := golfer.last_20[i+1];
  1436.                   golfer.last_20[max_diffs] := eq_sum;
  1437.                 end
  1438.               else
  1439.                 golfer.last_20[golfer.no_of_games+1] := eq_sum;
  1440.             golfer.no_of_games := curr_game.game_no;
  1441.             golfer.hcp := Handicap(golfer.last_20,golfer.no_of_games);
  1442.             curr_game.hcp := round(golfer.hcp);
  1443.             curr_game.course_id := club.id;
  1444.             Write(game_file,curr_game);
  1445.             Seek(golfers,golfer.id);
  1446.             Write(golfers,golfer);
  1447.           end {compound statement}
  1448.         end; {case}
  1449.      until eof(old) or (chr = #27);
  1450.      Window(42,8,80,12);
  1451.      GotoXY(1,2);
  1452.      hiline := quit;
  1453.      Close(old);
  1454.      Close(game_file);
  1455.      option := ProgramExit;
  1456.     end;  {Edit}
  1457.  
  1458.   Procedure View_Golfer_Box(xloc,yloc: byte);
  1459.  
  1460.     var
  1461.       ch : char;
  1462.       x,view,over_top,hiline,counter : byte;
  1463.     const
  1464.       NumberOfViews : byte = 5;
  1465.       ViewWidth     : byte = 14;
  1466.             {array[1..NumberOfViews] won't compile}
  1467.             {Nor will string[ViewWidth]....neither are REALLY constants!}
  1468.       views : array[1..5] of string[34] =
  1469.                   (' Original Entry Order',
  1470.                    ' Alphabetic Order',
  1471.                    ' last name',
  1472.                    ' handicap',
  1473.                    '  ------Print-----');
  1474.  
  1475.     Procedure PrintGolfers;
  1476.       var i,j : integer;
  1477.       begin
  1478. {$I-}
  1479.         repeat
  1480.           Writeln(lst,'  Roster sorted by ',views[golfer_view]);
  1481.           errcode := IOResult;
  1482.           if errcode <> 0 then writeln('Turn on Printer');
  1483.         until errcode = 0;
  1484. {$I+}
  1485.         Writeln(lst);
  1486.         Write(lst,' Name                    ');
  1487.         Writeln(lst,'Hcp');
  1488.         for i := 1 to FileSize(golfers) - 1 do
  1489.           begin
  1490.             Seek(golfers,gx[i]);
  1491.             Read(golfers,golfer);
  1492.             Write(lst,golfer.name);
  1493.             for j := 1 to 25 - Length(golfer.name) do Write(lst,' ');
  1494.             Writeln(lst,golfer.hcp:5:2);
  1495.           end;
  1496.         Writeln(lst,#12);
  1497.       end;
  1498.  
  1499.     begin  {View_Golfer_Vox}
  1500.       over_top := 0;
  1501.       hiline   := golfer_view;
  1502.       Box (xloc, yloc, ViewWidth + 6, NumberOfViews, 'View golfer in');
  1503.       if color then TextColor(yellow);
  1504.       repeat
  1505.         for counter := 1 to NumberOfViews do
  1506.         begin
  1507.           if counter = hiline
  1508.            then
  1509.               begin
  1510.                 if color then TextBackground(red)
  1511.                          else HighVideo;
  1512.                 view := counter;
  1513.               end
  1514.            else
  1515.               begin
  1516.                 if color then TextBackground(green)
  1517.                          else LowVideo;
  1518.               end;
  1519.           GotoXY(1,counter);
  1520.           Write(views[counter]);
  1521.           GotoXY(1,view);
  1522.         end; {for loop}
  1523.         Select(ch,hiline,over_top,NumberOfViews,NumberOfViews);
  1524.         if option = ProgramExit then exit;
  1525.         if ch = #13
  1526.            then
  1527.            case hiline of
  1528.              1..4 :
  1529.                begin
  1530.                 Gindex(hiline);
  1531.                 golfer_view := view;
  1532.                end;
  1533.              5: PrintGolfers;
  1534.            end;
  1535.         TextBackground(green);
  1536.       until ch = #13;
  1537.       Golfer_Box (1,1, SizeOf(golfer.name) + 5, max_golfer_box,
  1538.         'Golfer name───────-Hcp', FileSize(golfers), golfer_over_top,
  1539.          golfer_hiline);
  1540.       option := SelectGolfer;
  1541.     end;    {View_Golfer_Box}
  1542.  
  1543.   Procedure View_Course_Box(xloc,yloc: byte);
  1544.  
  1545.     var
  1546.       ch : char;
  1547.       view,over_top,hiline,counter : byte;
  1548.  
  1549.     const
  1550.        NumberOfViews : byte = 3;
  1551.        ViewWidth     : byte = 14;
  1552.             {array[1..NumberOfViews] won't compile}
  1553.             {Nor will string[ViewWidth]....neither are REALLY constants!}
  1554.        views : array[1..3] of string[22] =
  1555.                   (' Entry Order     ',
  1556.                    ' Alphabetic Order',
  1557.                    ' ----Print---    ');
  1558.  
  1559.     Procedure PrintCourses;
  1560.       var i,j,counter : integer;
  1561.       begin
  1562. {$I-}
  1563.         repeat
  1564.           Writeln(lst,'   Courses in',views[course_view],
  1565.                       '     Par   Rated/Slope');
  1566.           errcode := IOResult;
  1567.           if errcode <> 0 then Writeln('Turn on Printer');
  1568.         until errcode = 0;
  1569. {$I+}
  1570.         Writeln(lst);
  1571.         for counter := 1 to FileSize(courses) - 1 do
  1572.           begin
  1573.             Seek(courses,cx[counter]);
  1574.             Read(courses,club);
  1575.             Write(lst,club.name);
  1576.             for j := 1 to 32 - Length(club.name) do Write(lst,' ');
  1577.             j := 0;
  1578.             for i := 1 to max_holes do j := j + club.card_par[i];
  1579.             Write(lst,j:5);
  1580.             Writeln(lst,club.rated_par:9:1,'/',club.slope:4);
  1581.           end;
  1582.             Writeln(lst,#12);
  1583.       end; {PrintCourses}
  1584.  
  1585.     begin  {View_Course_Box}
  1586.       over_top := 0;
  1587.       hiline   := course_view;
  1588.       Box (xloc, yloc, ViewWidth + 6, NumberOfViews, 'View Course in');
  1589.       if color then TextColor(yellow);
  1590.       repeat
  1591.         for counter := 1 to NumberOfViews do
  1592.           begin
  1593.             if counter = hiline
  1594.               then
  1595.                 begin
  1596.                   if color then TextBackground(red)
  1597.                            else HighVideo;
  1598.                   view := counter;
  1599.                 end
  1600.               else
  1601.                 begin
  1602.                   if color then TextBackground(green)
  1603.                            else LowVideo;
  1604.                 end;
  1605.             GotoXY(1,counter);
  1606.             Write(views[counter]);
  1607.             GotoXY(1,view);
  1608.           end; {for loop}
  1609.         Select(ch,hiline,over_top,NumberOfViews,NumberOfViews);
  1610.         if option = ProgramExit then exit;
  1611.         if ch = #13
  1612.           then
  1613.             case hiline of
  1614.               1..2 :
  1615.                 begin
  1616.                   Cindex(view);
  1617.                   course_view := view;
  1618.                 end;
  1619.               3: PrintCourses;
  1620.             end;
  1621.         TextBackground(green);
  1622.       until ch = #13;
  1623.       Course_Box (80,1, SizeOf(club.name) + 2, max_course_box,
  1624.       'Courses', FileSize(courses), course_over_top, course_hiline);
  1625.       option := SelectGolfer;
  1626.     end;    {ViewCourseBox}
  1627.  
  1628.   Procedure Option_Box(xloc,yloc: byte);
  1629.     var
  1630.       ch : char;
  1631.       over_top,hiline,counter : byte;
  1632.     const
  1633.       NumberOfOptions : byte = 8;
  1634.       OptionWidth     : byte = 14;
  1635.             {array[1..NumberOfOptions] won't compile}
  1636.             {Nor will string[OptionWidth]....neither are REALLY constants!}
  1637.       options : array[1..8] of string[14] =
  1638.                   (' View - Course',
  1639.                    ' Course  (->)',
  1640.                    ' View - Golfer',
  1641.                    ' Golfer  (<-)',
  1642.                    ' Post a score',
  1643.                    ' Analysis',
  1644.                    ' Quit  (Alt-x)',
  1645.                    ' Edit gamefile');
  1646.     begin
  1647.       over_top := 0;
  1648.       option := SelectCourse;
  1649.       repeat {until exit}
  1650.         hiline := ord(option) + 1;
  1651.           repeat {till C/R, left or right arrow}
  1652.             Box (xloc, yloc, OptionWidth + 4, NumberOfOptions, 'Options');
  1653.             if color then
  1654.               begin
  1655.                 TextColor(yellow);
  1656.                 TextBackground(green);
  1657.               end;
  1658.             Clrscr;
  1659.             for counter := 1 to NumberOfOptions do
  1660.               begin
  1661.                 if counter = hiline
  1662.                   then
  1663.                     begin
  1664.                     if color then TextBackground(red)
  1665.                              else HighVideo
  1666.                     end
  1667.                   else
  1668.                     begin
  1669.                       if color then TextBackground(green)
  1670.                                else LowVideo
  1671.                     end;
  1672.                 GotoXY(1,counter);
  1673.                 Write(options[counter]);
  1674.                 GotoXY(1,counter + 1);
  1675.               end;  {counter loop}
  1676.             GotoXY(1,hiline);
  1677.             Select(ch,hiline,over_top,NumberOfOptions,NumberOfOptions);
  1678.             GotoXY(1,hiline);
  1679.             case ch of
  1680.               '-': hiline := ord(succ(option_type(ProgramExit)));
  1681.               'K':  {Left-arrow}
  1682.                    hiline := ord(succ(option_type(SelectGolfer)));
  1683.               'M':  {Right-arrow}
  1684.                    hiline := ord(succ(option_type(SelectCourse)));
  1685.             end;   {ch case }
  1686.             option := option_type(pred(hiline));
  1687.             GotoXY(1,hiline);
  1688.           until ch in [#13,'K','M'];
  1689.           case option of
  1690.             ViewCourses:
  1691.               View_Course_Box(50,2);
  1692.             SelectCourse:
  1693.               Course_Box(80,1,SizeOf(club.name) + 2,max_course_box,
  1694.               'Courses', FileSize(courses), course_over_top, course_hiline);
  1695.             ViewGolfer:
  1696.               View_Golfer_box(2,2);
  1697.             SelectGolfer:
  1698.               Golfer_Box (1,1,SizeOf(golfer.name) + 5,max_golfer_box,
  1699.               'Golfer name───────-Hcp', FileSize(golfers), golfer_over_top,
  1700.                golfer_hiline);
  1701.             PostScore: Post;
  1702.             CourseAnalysis: Analysis(game_file, club);
  1703.             ProgramExit: Exit;
  1704.             EditGames: Edit(hiline);
  1705.           end; {case option}
  1706.           TextBackground(green);
  1707.       until false; {actually, till an exit is taken above}
  1708.     end;
  1709. {--------------------------------------------------------}
  1710. {  Start of Main Program  }
  1711.   var
  1712.     hcp : real;
  1713.   begin
  1714.     Window(1,1,80,25);
  1715.     for id := 1 to ParamCount do
  1716.       begin
  1717.         pstring := ParamStr(id);
  1718.         case pstring[1] of
  1719.           'h' : val(Copy(pstring,2,Length(pstring)),max_holes,code);
  1720.           '%' : val(Copy(pstring,2,Length(pstring)),percent,code);
  1721.           'g' : val(Copy(pstring,2,Length(pstring)),max_diffs,code);
  1722.           'a' : val(Copy(pstring,2,Length(pstring)),adj_score_rule,code);
  1723.           's' : begin
  1724.                   ch := char(pstring[2]);
  1725.                   case ch of
  1726.                     '+' : use_slope := true;
  1727.                     '-' : use_slope := false;
  1728.                   end; {case of slope + or -}
  1729.                 end;  { of slope}
  1730.         end; { of case pstring}
  1731.       end;  { of Params}
  1732.   {See if mono or color}
  1733.     intr($11,regs);
  1734.     mono := (regs.ax and $30) = $30;
  1735.     color := not mono;
  1736.     ClrScr;
  1737.     writeln(' Color = ',color);
  1738.     writeln(' Nmbr of holes = ',max_holes:2);
  1739.     writeln(' Adj. Score rule #',adj_score_rule:1);
  1740.     GotoXY(55,1);
  1741.     writeln('Max diffs in Hcp = ',max_diffs:2);
  1742.     GotoXY(55,2);
  1743.     writeln('Percent is ',percent:3,'%');
  1744.     GotoXY(55,3);
  1745.     writeln('Slope = ',use_slope);
  1746.     Back := max_holes div 2;
  1747.     Front := max_holes - Back;
  1748.    {Get status from last execution}
  1749.     Assign(default,'golf.ini');
  1750. {$I-}
  1751.     Reset(default);
  1752.     Readln(default, golfer_view  , course_view,
  1753.                     golfer_id    , course_id);
  1754. {$I+}
  1755.     if ioresult <> 0 then
  1756.       begin
  1757.         Rewrite(default);
  1758.         Writeln(default,1,' ',1,' ',0,' ',0);
  1759.         Close(default);
  1760.         Reset(default);
  1761.         Readln(default, golfer_view  , course_view,
  1762.                         golfer_id    , course_id);
  1763.       end;
  1764.  {Prepare Golfers and Courses files}
  1765.     Assign (golfers,'Golfers');
  1766. {$I-}
  1767.     Reset(golfers);
  1768.     Seek(golfers,golfer_id);
  1769.     Read(golfers,golfer);
  1770. {$I+}
  1771.     if IOResult <> 0
  1772.       then
  1773.         begin
  1774.           Rewrite(golfers);
  1775.           Write(golfers,nobody);
  1776.           Close(golfers);
  1777.           Reset(golfers);
  1778.           Read(golfers,golfer);
  1779.         end
  1780.       else
  1781.         begin
  1782.           Str(golfer_id,s);
  1783.           Assign(game_file,'golfr' + s);
  1784.           if golfer_id <> 0 then
  1785.             Reset(game_file);
  1786.         end;
  1787.     Assign(courses,'courses');
  1788. {$I-}
  1789.     Reset(courses);
  1790.     Seek(courses,course_id);
  1791.     Read(courses,club);
  1792. {$I+}
  1793.     if IOResult <> 0 then
  1794.       begin
  1795.         Rewrite(courses);
  1796.         Write(courses,nowhere);
  1797.         Close (courses);
  1798.         Reset(courses);
  1799.         Read(courses,club);
  1800.       end;
  1801.    {Initialize cx and gx background}
  1802.     for id := 0 to 255 do
  1803.       begin
  1804.         cx[id] := 0;
  1805.         gx[id] := 0;
  1806.       end;
  1807.    {Equivalent to Cindex(1) and Gindex(1) without Align}
  1808.     for id := 0 to FileSize(courses) do  cx[id] := id;
  1809.     for id := 0 to FileSize(golfers) do  gx[id] := id;
  1810.     Course_hiline := course_id;
  1811.     Course_over_top := 0;
  1812.     Cindex(course_view);
  1813.     Seek(courses,course_id);
  1814.     Read(courses,club);
  1815.  
  1816.     golfer_hiline := golfer_id;
  1817.     golfer_over_top := 0;
  1818.     Gindex(golfer_view);
  1819.     GotoXY(32,16);
  1820.     Writeln(version);
  1821.     GotoXY(24,17);
  1822.     Writeln(copyrite);
  1823.     GotoXY(19,18);
  1824.     Writeln('See Golf.txt to see how and why to register');
  1825.     GotoXY(12,20);
  1826.     Writeln('Use up/down arrows to select, Enter to activate selection');
  1827.     Seek(golfers,golfer_id);
  1828.     Read(golfers,golfer);
  1829.     hcp := Handicap(golfer.last_20,golfer.no_of_games);
  1830.  
  1831.     Option_Box(28,1);
  1832.  
  1833.     Close(Golfers);
  1834.     Close(courses);
  1835. {$I-}
  1836.      Close(game_file);
  1837.      if IOResult <> 0 then;  {No Operation?}
  1838. {$I+}
  1839.      Close (default); Assign(default,'golf.ini'); Rewrite(default);
  1840.      Writeln(default, golfer_view:4   ,course_view:4,
  1841.                       golfer_id:4     ,course_id:4);
  1842.      Close(default);
  1843.      Window(1,1,80,25);
  1844.      if color then TextColor(lightgray);
  1845.      if color then TextBackground(black)
  1846.               else LowVideo;
  1847.      ClrScr;
  1848.   end.
  1849.