PROGRAM Minimuf_CalculateTheMuf;
{
This program calculates and displays on the screen MUF information, hour-
by-hour (GMT), for one path.  A graph is drawn.  After displaying the MUF
information on the screen, a hard copy can be printed.

The program is set to print MUF values from a QTH in Dallas, Texas.
The program can be customized to any QTH and the 15 pre-programmed path
choices can be modified by changing the setup file MUFSETUP.DAT.

This program is based on a BASIC program originally published in QEX of
November, 1983.  The QEX program was an adaptation to the IBM PC BASIC
by John E. Anderson WD4MUO of a BASIC program published in QST of
December, 1982.

This program was adapted to TurboPascal by Keith Seabourn, 5N6SKD from
these BASIC programs found in QEX and QST.  The adaptation to Pascal is
not a particularly good example of Pascal coding technique.  The procedure
MinimufCalcLoop was taken directly from BASIC to Pascal and includes the
limitations of BASIC, including brief variable names and GOTO statements.

Source:  QEX November, 1983 and QST December 1982, page 38.
Source of Polynomial flux to sunspot number conversion:  Gilder, James H.;
  Basic Computer Programs in Science and Engineering; Hayden 1980.
}

CONST
   Mstr : array[1..12] of string[3] = ('JAN','FEB','MAR','APR','MAY',
            'JUN','JUL','AUG','SEP','OCT','NOV','DEC');
   M : array[1..12] of integer = (31,29,31,30,31,30,31,31,30,31,30,31);
   PI = 3.141593;
   Xstr = '===============================================================================';
   Spaces = '                                                                                ;';
   Yes : set of char = ['Y','y'];
   No : set of char = ['N','n'];
   MinMuf : integer = 7;
   MaxMuf : integer = 28;
   MaxPathLength = 24;

TYPE
  FileNameType = string[14];
  Long_String = string[255];

VAR
   L1, L2, W1, W2, R0, R1, P0, P1, SF, S9, Tam, J9 : REAL;
   TLat, TLon, RLat, RLon : REAL;
   Ch, M0, D6, LP, TA, I, T5 : INTEGER;
   Title, Line : STRING [80];
   Tstr, Rstr : STRING [32];
   T1, T2, X : INTEGER;
   ANstr, AN1str, TAstr, Dstr : CHAR;
   Plot : ARRAY [0..23, 7..28] of CHAR;
   Muf : ARRAY [0..23] of REAL;
   XPos, YPos : BYTE;
   Path : array [1..15] of string[24];
   Lat,
   Lon : array [1..15] of real;
   StationCall : string [11];
   StationLat,
   StationLon : real;
   SetupFile : Text;
   MaxChoices : byte;
   SetupFileError : boolean;
   Cntr : integer;
   CSstr : string[11];

{$U+}


FUNCTION Fnacs (X : REAL) : REAL;
   BEGIN
      Fnacs := -ARCTAN (X / SQRT(-X * X + 1)) + 1.5708
   END;


{*****************************************************************************}
{This function checks for the existence of a file of the name passed to it
by attempting to reset the file with I/O error checking switched off, and
then looking at IOResult, the built-in variable that holds I/O error
messages.  This function will NOT check for files in any but the current
directory--use the "Find_First" function in GETFILE.LIB for those.

function EXISTS: boolean;
  input : a filename of a TYPE declared in user program (BEFORE including this
              file!)
  output: true if exists else false.}


function exists(ThisFile : FileNameType):boolean;
var
  tempFile : text;  {We can get away with assigning a text file to ANY
                     filename because we aren't going to do any input/output}
begin
  assign(tempFile,ThisFile);
  {$I-}
  reset(tempFile);
  {$I+}
  if IOResult = 0 then exists := true
    else exists := false;
  close(tempFile);
end;


{****************************************************************************}
Procedure Alert(Message : Long_String);{* This routine prints MESSAGE to the*}
                                       {* screen and makes an obnoxious     *}
Var                                    {* noise for about 1 second          *}
  I : Integer;                         {*************************************}
  i1,i2,i3,i4 : integer;


begin
  write(Message);
  for i4 := 10 downto 1 do
    begin
    i2 := 250 + i4 * 25;
    for i3 := 2 downto 1 do
      begin
      for i1 := 1 to 30 - i3 * 2 do
        begin
        sound(i1 + i2 + i3 * 2);
        delay(2);
        end;
      delay(5);
      i2 := i2 + 30;
      end;
    nosound;
    end;
end;


PROCEDURE Initialize;
   BEGIN
      R0 := PI / 180.0;
      P1 := 2.0 * PI;
      R1 := 180.0 / PI;
      P0 := PI / 2.0;
      TITLE := COPY(Spaces,1,36) + 'MINIMUF' + COPY(Spaces,1,36);
      AN1str := '*';
   END;



PROCEDURE ReadSetupFileData;
{Reads the file MUFSETUP.DAT on the default drive.  Returns
  StationCall : string[11] : callsign of station
  StationLat,
  StationLon  : real : latitude, longitude for station
  Path : array [1..15] of string[24] : path options
  Lat  : array [1..15] of real : latitude for each path option
  Lon  : array [1..15] of real : longitude for each path option
  SetupFileError : boolean : TRUE if an error is found in the file
                             FALSE if data is good
}

var
  OneChar : char;
  LatStr,
  LonStr : string[7];
  ConvError : integer;
  I, J : integer;

begin
  SetupFileError := False;
  assign(SetupFile,'MUFSETUP.DAT');
  if exists('MUFSETUP.DAT') then
    begin
      reset(SetupFile);
      {Get station call, station latitude, station longitude}
      StationCall := '';
      I := 1;
      repeat
        read(SetupFile,OneChar);
        if OneChar<>';' then StationCall := StationCall + OneChar;
        I := I + 1;
      until ((OneChar=';') or (I>(SizeOf(StationCall)-1)) or (OneChar=^M));
      if ((OneChar <> ';') or (I>(SizeOf(StationCall)-1)) or (OneChar=^M)) then
        begin
          SetupFileError := True;
          writeln('An error occurred while reading setup file.');
          writeln('The Station Call "',StationCall,'" is more than ',
              (SizeOf(StationCall)-1):2,' characters');
          writeln('or latitude or longitude data is missing.');
          writeln;
        end;

      {Parse for Latitude}
      if not SetupFileError then
        begin
          I := 1;
          LatStr := '';
          repeat
            read(SetupFile,OneChar);
            if OneChar<>';' then LatStr := LatStr + OneChar;
            I := I + 1;
          until ((OneChar=';') or (I>(SizeOf(LatStr)-1)) or (OneChar=^M));
          val(LatStr,StationLat,ConvError);
          if (Length(LatStr)=0) or (OneChar<>';') or (I>(SizeOf(LatStr)-1))
                  or (ConvError<>0) then
            begin
              SetupFileError := True;
              writeln('An error occurred while reading setup file.');
              writeln('The latitude "',LatStr,'" is not in the correct ',
                  'format or has too many digits.');
              writeln;
            end;
        end;

      {Parse for Longitude}
      if not SetupFileError then
        begin
          I := 1;
          LonStr := '';
          repeat
            read(SetupFile,OneChar);
            if (OneChar<>';') and (OneChar<>^M) then LonStr := LonStr + OneChar;
            I := I + 1;
          until (OneChar=^M) or (I>(SizeOf(LonStr)-1));
          val(LonStr,StationLon,ConvError);
          if ((Length(LonStr)=0) or (I>(SizeOf(LonStr)-1)) or (ConvError<>0)) then
            begin
              SetupFileError := True;
              writeln('An error occurred while reading setup file.');
              writeln('The longitude "',LonStr,'" is not in the correct ',
                  'format or has too many digits.');
              writeln;
           end;
        end;
      read(SetupFile,OneChar); {skip the Line Feed}

      {Read remainder of SetupFile and parse for path options}
      I := 1;
      while not (SetupFileError or EOF(SetupFile)) do
        begin
          Path[I] := '';
          Lat[I] := 0.0;
          Lon[I] := 0.0;
          LatStr := '';
          LonStr := '';
          J := 0;

          repeat
            J := J + 1;
            read(SetupFile,OneChar);
            if OneChar<>';' then Path[I] := Path[I] + OneChar;
          until (OneChar=';') or (J>MaxPathLength+1) or (OneChar = ^M);
          if (OneChar <> ';') or (J>MaxPathLength+1) then
            begin
              SetupFileError := True;
              if (J > MaxPathLength) or (OneChar = ^M) then
                begin
                  writeln('An error occurred while reading setup file.');
                  writeln('The path "',Path[I],'" is more than ',
                      MaxPathLength:2,' characters');
                  writeln('or latitude or longitude data is missing.');
                  writeln;
                end;
            end;

          if not SetupFileError then
            begin
              J := 1;
              repeat
                read(SetupFile,OneChar);
                if (OneChar<>';') and (OneChar<>^M) then LatStr := LatStr + OneChar;
                J := J + 1;
              until (OneChar=';') or (J>(SizeOf(LatStr)-1)) or (OneChar=^M);
              val(LatStr,Lat[I],ConvError);

              if (Length(LatStr)<=0) or (OneChar<>';') or (J>(SizeOf(LatStr)-1))
                    or (ConvError<>0) then
                begin
                  SetupFileError := True;
                  writeln('An error occurred while reading setup file.');
                  writeln('The latitude "',LatStr,'" in the path "',Path[I],'"');
                  writeln('is not in the correct format or has too many digits.');
                  writeln;
                end;
            end;

          if not SetupFileError then
            begin
              J := 1;
              repeat
                read(SetupFile,OneChar);
                if (OneChar<>';') and (OneChar<>^M) then LonStr := LonStr + OneChar;
                J := J + 1;
              until (OneChar=^M) or (J>(SizeOf(LonStr))) or (EOF(SetupFile));
              val(LonStr,Lon[I],ConvError);
              if (Length(LonStr) <=0) or (J > (SizeOf(LonStr)))
                      or (ConvError <> 0) then
                begin
                  SetupFileError := True;
                  writeln('An error occurred while reading setup file.');
                  writeln('The longitude "',LonStr,'" in the path "',Path[I],'"');
                  writeln('is not in the correct format or has too many digits.');
                  writeln;
                end;
            end;

          I := I + 1;
          read(SetupFile,OneChar);  {skip LineFeed}
        end;  {while not(SetupFileError or EOF(SetupFile)}

      if SetupFileError then
        begin
          gotoxy(1,WhereY+1);
          alert('An error occurred while reading setup file.');
          writeln;
          writeln('Use an ASCII word processor to carefully check the file');
          writeln('MUFSETUP.DAT then try again.');
          write('Press any key to continue...');
          repeat until keypressed;

          MaxChoices := 0;
        end
      else
        MaxChoices := I - 1;
    end  {if SetupFile exists}
  else    {if SetupFile does not exist}
    begin
      alert('MUFSETUP.DAT cannot be found. Program aborting.');
    end;
end;  {procedure ReadSetupFileData}


PROCEDURE PrintScreenHeader;
   BEGIN
      CLRSCR;
      TEXTCOLOR(Black);
      TEXTBACKGROUND(LightGray);
      WRITELN (Xstr);
      WRITELN (TITLE);
      WRITELN (Xstr);
      TEXTCOLOR(LightGray);
      TEXTBACKGROUND(Black);
   END;



PROCEDURE DisplayOptionMenu;
   BEGIN
      WRITELN;
      WRITELN ('Path Options');
      WRITELN;
      FOR I := 1 TO MaxChoices do
         WRITELN(I:3,' ',CSstr,' ',Path[I]);
      WRITELN (' 16 ', CSstr, ' TO A SPECIFIED POINT');
      WRITELN (' 17 ','BETWEEN SPECIFIED POINTS');
   END;


PROCEDURE GetTransmitterLatLon;
   BEGIN
      REPEAT
         WRITELN;
         WRITE ('TRANSMITTER LATITUDE ("-" for East)?');
         READLN (L1);
         IF (L1 < -90.0) OR (L1 > 90.0) THEN
               WRITELN ('INVALID LATITUDE.  MUST BE IN RANGE (-90 TO +90).');
      UNTIL (L1 >= -90.0) AND (L1 <= 90.0);

      REPEAT
         WRITE ('TRANSMITTER LONGITUDE ("-" for South)?');
         READLN (W1);
         IF (W1 < -360.0) OR (W1 > 360.0) THEN
               WRITELN ('INVALID LONGITUDE.  MUST BE IN RANGE (-360 TO +360).');
      UNTIL (W1 >= -360.0) AND (W1 <= 360.0);
   END;   {Procedure GetTransmitterLatLon}



PROCEDURE GetReceiverLatLon;
   BEGIN
      REPEAT
         WRITELN;
         WRITE ('RECEIVER LATITUDE ("-" for East)?');
         READLN (L2);
         IF (L2 < -90.0) OR (L2 > 90.0) THEN
               WRITELN ('INVALID LATITUDE.  MUST BE IN RANGE (-90 TO +90).');
      UNTIL (L2 >= -90.0) AND (L2 <= 90.0);

      REPEAT
         WRITE ('RECEIVER LONGITUDE ("-" for South)?');
         READLN (W2);
         IF (W2 < -360.0) OR (W2 > 360.0) THEN
               WRITELN ('INVALID LONGITUDE.  MUST BE IN RANGE (-360 TO +360).');
      UNTIL (W2 >= -360.0) AND (W2 <= 360.0);
   END;   {Procedure GetReceiverLatLon}



PROCEDURE GetLatitudeLongitude;
   BEGIN
      Tstr := CSstr;

      CASE Ch OF
         1..15 : BEGIN
                    L1 := StationLat;
                    W1 := StationLon;
                    L2 := Lat[Ch];
                    W2 := Lon[Ch];
                    Rstr := Path[Ch];
                 END;

             16: BEGIN
                    L1 := StationLat;
                    W1 := StationLon;
                    Rstr := 'RECEIVER';
                    GetReceiverLatLon;
                 END;

             17: BEGIN
                    Tstr := 'TRANSMITTER';
                    Rstr := 'RECEIVER';
                    GetTransmitterLatLon;
                    GetReceiverLatLon;
                 END;
      END;  {Case}
   TLat := L1;
   TLon := W1;
   RLat := L2;
   RLon := W2;
END;   {Procedure GetLatitudeLongitude}


PROCEDURE GetDayMonth;
BEGIN
   REPEAT
      WRITELN;
      WRITELN ('Input day and month as (day month)? ');
      READLN (D6,M0);
      IF (M0<1) OR (M0>12) THEN WRITELN ('Invalid Month.  Must be in range (1 to 12)');
      IF (D6<1) OR (D6>M[M0]) THEN WRITELN ('Invalid Day.  Must be in range (1 to ', M[M0], ')');
   UNTIL (M0>=1) AND (M0<=12) AND (D6>=1) AND (D6<=M[M0]);
END;


PROCEDURE SolarFluxToSunSpot;
BEGIN
   S9 := -103.7767 + 1.797429 * SF - (3.384356E-03)*SF*SF + (4.525515E-06)*SF*SF*SF;
   S9 := INT (100 * S9 +0.5)/100;
END;


PROCEDURE SunSpotData;
BEGIN
   WRITELN;
   WRITE ('STATE SOURCE OF SOLAR ACTIVITY - S=sunspot no.  F=solar flux ? ');
   READLN (AN1str);
   IF (AN1str='S') OR (AN1str='s') THEN
   BEGIN
      REPEAT
         WRITELN;
         WRITE ('INPUT SMOOTHED INTERNATIONAL SUNSPOT NUMBER= ? ');
         READLN (S9);
         IF S9<0 THEN WRITELN ('INVALID SUNSPOT NUMBER.  MUST BE NON-NEGATIVE.');
      UNTIL (S9 >= 0.0);
      END

   ELSE
   BEGIN
      REPEAT
         WRITE ('INPUT SMOOTHED MEAN 10.7cm SOLAR FLUX ? ');
         READLN (SF);
         IF (SF<65) THEN WRITELN ('INVALID FLUX NUMBER, MUST BE GREATER THAN 65.');
         IF (SF>245) THEN WRITELN ('RESULTS MAY BE INACCURATE FOR FLUX GREATER THAN 245.');
      UNTIL SF>=65;
      SolarFluxToSunSpot;
      WRITELN ('A FLUX OF ', SF:5:1, ' EQUATES TO A SUNSPOT NUMBER OF ', S9:3:0);
      END;
END;   {Procedure SunSpotData}


PROCEDURE HardCopyFlag;
BEGIN
TEXTBACKGROUND(LightGray);
TEXTCOLOR(Black);
   REPEAT
      WRITE ('Want Printout(Y/N)?',^G,^G,^G);
      TEXTBACKGROUND(Black);
      TEXTCOLOR(LightGray);
      WRITE (' ');
      READ (ANstr);
      IF (ANstr IN Yes) THEN LP := 1;
      IF (ANstr IN No)  THEN LP := 0;
   UNTIL (ANstr IN Yes) OR (ANstr IN No);
END;   {Procedure HardCopyFlag}


PROCEDURE ThresholdFlag;
BEGIN
   REPEAT
      WRITELN;
      WRITELN;
      WRITE ('WANT FLAG ON MUF ABOVE GIVEN FREQ (Y or N)? ');
      READLN (TAstr);
      IF (TAstr IN Yes) THEN
      BEGIN
         TA:=1;
         WRITE ('SPECIFY FREQ IN MHZ.? ');
         READLN (Tam);
         END;
      IF (TAstr IN No) THEN TA:=0;
   UNTIL (TAstr IN Yes) OR (TAstr IN No);
END;


PROCEDURE HardCopyHeader;
BEGIN
   WRITELN(LST,'      1   3   5   7   9  11  13  15  17  19  21  23');
END;


PROCEDURE HardCopyFooter;
BEGIN
   WRITELN(LST,'      1   3   5   7   9  11  13  15  17  19  21  23   ');
END;


PROCEDURE HardCopyDataPrint;
   BEGIN

   T5 := MaxMuf;
   WRITE(LST,T5:2, '|');
   FOR I:=0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST,'   Date: ', D6:2, ' ', Mstr[M0]);

   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST);

   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST,'Sunspot Number = ', S9:3:0);

   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST);

   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST,'From: ', COPY(Tstr, 1, 22));

   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST,'      Lat: ', TLat:3:0, ' Lon: ',TLon:4:0);


   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST,'To: ', COPY(Rstr, 1, 24));

   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST,'      Lat: ', RLat:3:0, ' Lon: ', RLon:4:0);

   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST);

   T5 := T5 - 1;
   WRITE(LST,T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(LST,' ', Plot[I,T5]);
   WRITELN(LST,'   UTC    MUF   UTC    MUF');

   FOR T5 := MaxMuf-10 DOWNTO MinMuf DO
      BEGIN
      T1 := (MaxMuf-10) - T5;
      T2 := T1 + 12;
      WRITE(LST,T5:2,'|');
      FOR I := 0 TO 23 DO WRITE(LST,' ',Plot[I,T5]);
      WRITELN(LST,'    ',T1:2,'   ',Muf[T1]:4:1,'    ',T2:2,'   ',Muf[T2]:4:1);
      END;  {T5 := MaxMuf-10 DOWNTO MinMuf-12}

   END;


FUNCTION SGN(X : REAL) :REAL;
   {Simulates BASIC function SGN}
   BEGIN
   IF X < 0.0 THEN SGN := -1.0;
   IF X = 0.0 THEN SGN := 0.0;
   IF X > 0.0 THEN SGN := 1.0;
   END;


FUNCTION POWER(X, Y : REAL) :REAL;
   {Raises X to the Yth power}
   {Simulates BASIC X^Y or FORTRAN X**Y}
   BEGIN
   POWER := EXP(Y * LN(X));
   END;


PROCEDURE MinimufCalcLoop;
LABEL
   Label198, Label214, Label215, Label223, Label228, Label234;

CONST
   MIN_EXP = -88.02969;

VAR
   K7, G1, K6, K5, P, Q, A, B, C, D, W0, L0 : REAL;
   T6, Y1, Y2, K1, K8, K9, G0, M9, T, T4, C0, T9 : REAL;
   G9, G8, U, G7, G2, U1, EXP_U, EXP_U1, EXP_K9A, EXP_K9B : REAL;

BEGIN
   K7 := SIN(L1) * SIN(L2) + COS(L1) * COS(L2) * COS(W2-W1);
   IF K7 < -1.0 THEN K7 := -1.0;
   IF K7 > 1.0 THEN K7 := 1.0;
   G1 := Fnacs(K7);
   K6 := 1.59 * G1;
   IF K6 < 1.0 THEN K6 := 1.0;
   K5 := 1.0/K6;
   J9 := 100.0;
   K1 := 1.0/(2.0*K6);
   WHILE (SGN(0.9999-1.0/K6)*K1) <= (SGN(0.9999-1.0/K6)*(1.0 - 1.0/(2.0*K6))) DO
      BEGIN
      IF K5 <> 1.0 THEN K5 := 0.5;
      P := SIN(L2);
      Q := COS(L2);
      A := (SIN(L1) - P*COS(G1)) / (Q * SIN(G1));
      B := G1 * K1;
      C := P * COS(B) + Q * SIN(B) * A;
      D := (COS(B) - C * P) / (Q * SQRT(1 - C*C));
      IF D < -1.0 THEN D := -1.0;
      IF D > 1.0 THEN D := 1.0;
      D := Fnacs(D);
      W0 := W2 + SGN(SIN(W1-W2))*D;
      IF W0 < 0.0 THEN W0 := W0+P1;
      IF W0 >= P1 THEN W0 := W0-P1;
      IF C < -1.0 THEN C := -1.0;
      IF C > 1.0 THEN C := 1.0;
      L0 := P0 - Fnacs(C);
      Y1 := 0.0172 * (10 + (M0-1)*30.4 + D6);
      Y2 := 0.409 * COS(Y1);
      K8 := 3.82*W0 + 12.0 + 0.13*(SIN(Y1) + 1.2*SIN(2*Y1));
      K8 := K8 - 12*(1 + SGN(K8-24.0))*SGN(ABS(K8-24.0));
      IF COS(L0+Y2) > -0.26 THEN GOTO Label198;
      K9 := 0.0;
      G0 := 0.0;
      M9 := 2.5 * G1 * K5;
      IF M9 > P0 THEN M9 := P0;
      M9 := SIN(M9);
      M9 := 1.0 + 2.5 * M9 * SQRT(M9);
      GOTO Label223;

      Label198:
      K9 := (-0.26 + SIN(Y2)*SIN(L0)) / (COS(Y2)*COS(L0) + 9.999999E-04);
      K9 := 12.0 - ARCTAN(K9/SQRT(ABS(1.0 - K9*K9))) * 7.639437;
      T := K8 - K9/2.0 + 12.0*(1-SGN(K8-K9/2))*SGN(ABS(K8-K9/2));
      T4 := K8 + K9/2 - 12.0*(1+SGN(K8+K9/2-24.0))*SGN(ABS(K8+K9/2-24.0));
      C0 := ABS(COS(L0+Y2));
      T9 := 9.7 * POWER(C0,9.600001);
      IF T9 < 0.1 THEN T9 := 0.1;
      M9 := 2.5 * G1 * K5;
      IF M9 > P0 THEN M9 := P0;
      M9 := SIN(M9);
      M9 := 1.0 + 2.5 * M9 * SQRT(M9);
      IF T4 < T THEN GOTO Label214;
      IF ((T5-T) * (T4-T5)) > 0.0 THEN GOTO Label215;
      GOTO Label228;

      Label214:
      IF ((T5-T4) * (T-T5)) > 0.0 THEN GOTO Label228;

      Label215:
      T6 := T5 + 12.0*(1.0+SGN(T-T5))*SGN(ABS(T-T5));
      G9 := PI*(T6-T)/K9;
      G8 := PI*T9/K9;
      U := (T-T6)/T9;
      IF U >= MIN_EXP THEN EXP_U := EXP(U) ELSE EXP_U := 0.0;
      IF (-K9/T9) >= MIN_EXP THEN EXP_K9A := EXP(-K9/T9) ELSE EXP_K9A := 0.0;
      IF ((K9-24.0)/2.0) >= MIN_EXP THEN EXP_K9B := EXP((K9-24.0)/2.0) ELSE EXP_K9B := 0.0;
      G0 := C0*(SIN(G9) + G8*(EXP_U-COS(G9)))/(1.0 + G8*G8);
      G7 := C0 * (G8*(EXP_K9A+1.0)) * EXP_K9B / (1.0 + G8*G8);
      IF G0 < G7 THEN G0 := G7;

      Label223:
      G2 := (1.0+S9/250.0) * M9 * SQRT(6.0+58.0*SQRT(G0));
      IF ((K9-24.0)/3.0) >= MIN_EXP THEN EXP_K9B := EXP((K9-24.0)/3.0) ELSE EXP_K9B := 0.0;
      G2 := G2*(1.0-0.1*EXP_K9B);
      G2 := G2*(1.0+(1.0-SGN(L1)*SGN(L2))*0.1);
      G2 := G2*(1.0-0.1*(1.0+SGN(ABS(SIN(L0))-COS(L0))));
      GOTO Label234;

      Label228:
      T6 := T5 + 12.0*(1.0+SGN(T4-T5))*SGN(ABS(T4-T5));
      G8 := PI*T9/K9;
      U := (T4-T6)/2.0;
      U1 := -K9/T9;
      IF U >= MIN_EXP THEN EXP_U := EXP(U) ELSE EXP_U := 0.0;
      IF U1 >= MIN_EXP THEN EXP_U1 := EXP(U1) ELSE EXP_U1 := 0.0;
      G0 := C0*(G8*(EXP_U1+1.0))*EXP_U/(1.0 + G8*G8);
      GOTO Label223;

      Label234:
      IF G2 < J9 THEN J9 := G2;

      K1 := K1 + 0.9999-1.0/K6;
      END;   {While}
   END;  {Procedure}


PROCEDURE DataPrint;
   BEGIN

   T5 := MaxMuf;
   WRITE(T5:2, '|');
   FOR I:=0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN('   Date: ', D6:2, ' ', Mstr[M0]);

   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN;

   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN('Sunspot Number = ', S9:3:0);

   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN;

   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN('From: ', COPY(Tstr, 1, 22));

   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN('      Lat: ', TLat:3:0, ' Lon: ',TLon:4:0);


   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN('To: ', COPY(Rstr, 1, 24));

   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN('      Lat: ', RLat:3:0, ' Lon: ', RLon:4:0);

   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN;

   T5 := T5 - 1;
   WRITE(T5:2, '|');
   FOR I := 0 TO 23 DO WRITE(' ', Plot[I,T5]);
   WRITELN('   UTC    MUF   UTC    MUF');

   FOR T5 := MaxMuf-10 DOWNTO MinMuf DO
      BEGIN
      T1 := (MaxMuf-10) - T5;
      T2 := T1 + 12;
      WRITE(T5:2,'|');
      FOR I := 0 TO 23 DO WRITE(' ',Plot[I,T5]);
      WRITELN('    ',T1:2,'   ',Muf[T1]:4:1,'    ',T2:2,'   ',Muf[T2]:4:1);
      END;  {T5 := MaxMuf-10 DOWNTO MinMuf-12}

   END;


PROCEDURE PrintGraphHeader;
   BEGIN
   WRITELN('      1   3   5   7   9  11  13  15  17  19  21  23');
   END;

PROCEDURE PrintGraphFooter;
   BEGIN
   WRITE  ('      1   3   5   7   9  11  13  15  17  19  21  23   ');
   END;


PROCEDURE ClearPlotArray;
   BEGIN
   {Initialize plotting array to blanks}
   FOR I := 0 TO 23 DO
      BEGIN
      FOR T5 := (MinMuf+1) TO (MaxMuf-1) DO Plot[I,T5] := ' ';
      END;
   FOR I := 0 TO 23 DO
      BEGIN
      Plot[I,MinMuf] := '=';
      Plot[I,MaxMuf] := '=';
      Plot[I,14] := '-';
      Plot[I,21] := '-';
      END;

   END;




{MAIN PROGRAM}
BEGIN
Initialize;
ReadSetupFileData;
IF not SetupFileError then
   BEGIN
      CSstr := StationCall;
      REPEAT
      BEGIN
         REPEAT
            PrintScreenHeader;
            DisplayOptionMenu;
            ClearPlotArray;
            WRITE ('CHOICE? ');
            READLN (Ch);
            IF (Ch<1) OR (Ch>17) THEN
            BEGIN
               CLRSCR;
               GOTOXY(30,12);
               WRITELN ('BAD CHOICE NUMBER',^G);
               DELAY (500);
               END;
         UNTIL (Ch>=1) AND (Ch<=17);

         {If this is the first time through, then get date and sunspot info}
         {If this is the first time, AN1str='*' from Initialize}
         {If we have been through before, AN1str = S,s,F,f from SunSpotData}
         IF AN1str='*' THEN
            BEGIN
            CLRSCR;
            PrintScreenHeader;
            GetDayMonth;
            SunSpotData;
            ThresholdFlag;
            END;

         GetLatitudeLongitude;

         CLRSCR;
         PrintScreenHeader;
         GOTOXY(25,12);
         WRITE('Calculating the MUF for **00z');

         L1 := L1 * R0;
         W1 := W1 * R0;
         L2 := L2 * R0;
         W2 := W2 * R0;
         FOR T5 := 0 TO 23 DO
            BEGIN
            GOTOXY(49,12);
            WRITE(T5:2);
            MinimufCalcLoop;
            IF TA = 0 THEN Dstr := '*';
            IF TA = 1 THEN
               BEGIN
               IF J9 >= Tam THEN Dstr := '*'
               ELSE Dstr := '.'
               END;
            I := ROUND(J9);

            {Set a  floor of <MinMuf>MHz and a ceiling of <MaxMuf>MHz for the plot}
            IF I < MinMuf THEN
               BEGIN
               I := MinMuf;
               Dstr := '@';
               END;
            IF I > MaxMuf THEN
               BEGIN
               I := MaxMuf;
               Dstr := '@';
               END;

            Muf[T5] := J9;
            Plot[T5,I] := Dstr;
            END;  {T5 := 0 TO 23}

         CLRSCR;
         PrintGraphHeader;
         DataPrint;
         PrintGraphFooter;
         XPos := WhereX;
         YPos := WhereY;
         HardCopyFlag;
         IF LP = 1 THEN
            BEGIN
            HardCopyHeader;
            HardCopyDataPrint;
            HardCopyFooter;
            END;

         GOTOXY(XPos,YPos);
         CLREOL;
         TEXTBACKGROUND(LightGray);
         TEXTCOLOR(Black);
         WRITE ('Plot another (Y/N)?', ^G, ^G, ^G);
         TEXTBACKGROUND(Black);
         TEXTCOLOR(LightGray);
         WRITE (' ');
         READLN (ANstr);
         END;   {Repeat Main Loop}
      UNTIL (ANstr IN No);
   END;  {If there is no SetupFileError}
END.