/*
**++
**  MODULE DESCRIPTION:
**
**      This is the heat index module
**
**  AUTHORS:
**
**      Phil Baughn (BASIC version)
**	Rod Falanga (C version)
**
**  CREATION DATE:  18 October 1990
**
**  DESIGN ISSUES:
**
**      A. This module is dominated by a large do loop which repeats while
**	   the User response to requests to do more heat index calculations
**	   in the affirmative.
**	B. Within the do loop, the first thing is to give the system's date
**	   and time and give the module's name.
**	C. The temperature is entered by the User.
**	D. The relative humidity is entered by the User.
**	E. Heat index is then calculated and showed to the User.
**	F. Ask the User if they wish to perform another calculation.
**	G. OUTSIDE OF THE MAIN LOOP: Ask the User if they want an explanation
**	   of the heat index.
**
**  KEYWORDS:
**   
**      heat index
**   
**  MODIFICATION HISTORY:
**
**      {@tbs@}...
**--
*/


/*
**
**  INCLUDE FILES
**
*/

#ifdef VMS
#include stdio
#include math
#else
#include <stdio.h>
#include <math.h>
#endif

/*
**
**  MACRO DEFINITIONS
**
*/

#define DUMMY_LEN	50

static double df;

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This is the main function of the heat index module.
**
**--
*/
#ifdef VMS
void heat_index (void)
#else
void heat_index ()
#endif
{
#ifdef VMS
    extern void position (int, int), 
                print (char *), 
		get_string(char *),
                get_date_time (char *, char *);
#else
    extern void position (), 
                print (), 
		get_string(),
                get_date_time ();
#endif
    char date [DUMMY_LEN], 
         time [DUMMY_LEN], 
#ifdef VMS
         *uppercase (char *), 
#else
         *uppercase (), 
#endif
         again [DUMMY_LEN], 
         temperature_str [DUMMY_LEN*2];
#ifdef VMS
    double get_double (void), 
#else
    double get_double (), 
#endif
	   temperature, 
	   relative_humidity, 
	   apptemp;
#ifdef VMS
    extern double target78 (double, double);
#else
    extern double target78 ();
#endif

    /*	 
    **  This is the beginning of the do loop.
    */	 
    do
    {
        Erase();
	position(2, 27);
	print("HEAT INDEX CALCULATION");
        get_date_time (date, time);
	position(4, 34);
	print(date);
	position(5, 35);
	print(time);

        /*	 
        **  Get the temperature.
        */	 
	position(7, 11);
	print("ENTER THE CURRENT TEMPERATURE IN DEGREES FAHRENHEIT ");
	temperature = get_double();
        /*	 
        **  At this point in the BASIC code, Phil hard coded a variable called
	**  U$ with the value "F".  It appears as though he intended to make
	**  it possible for the User to do things either in Fahrenheit or
	**  in Celcius.  However, at as of version 6.0 of his weather program
	**  that functionality hadn't been incorporated.  Therefore, wherever
	**  any reference to the variable U$ appears, I have chosen to ignore
	**  it and just perform whatever other executable statements should
	**  be performed.
        */	 

        /*	 
        **  Get the relative humidity.
        */	 
	position(8, 11);
	print("ENTER THE RELATIVE HUMIDITY  (`50'= 50% )           ");
	relative_humidity = get_double();

	position(13, 23);
	print("Heat Index Is Also Refered To");
	position(14, 17);
	print("As The Apparent Temperature.  See The H/I");
	position(15, 18);
	print("Explanation & Danger Table For Details.");

        /*	 
        **  Now, go off and determine the heat index.
        */	 
        apptemp = target78 (temperature, relative_humidity);

        /*	 
        **  Now, show the User what the heat index is.
        */	 
	position(19, 19);
        sprintf (temperature_str, "APPARENT TEMPERATURE = %.1f F", apptemp);
	print(temperature_str);

        if (df < 0.)
        {
            position(20, 19);
	    print("SEVERE SULTRINESS...");
        }

        /*	 
        **  Ask the User if they wish to do it again.
        */	 
	position(23, 19);
	print("RUN ANOTHER HEAT INDEX FACTOR (Y/N)");
	get_string(again);
    } while (again[0]=='Y' || again[0]=='y');

    /*	 
    **  This routine actually has something more than a main loop.  It will
    **	ask the User if they want an explanation of everything that they've
    **	learned so far concerning the heat index.
    */	 
    position(24, 16);
    print("View H/I  Explanation & Danger Table? (Y/N)");
    get_string(again);	/* I'll let the variable again do double duty. */

    if (again[0]=='N' || again[0]=='n')
        return;

    /*	 
    **  Give and explanation and return.
    */	 
    Erase();
    print("\n");
    sprintf (temperature_str, "       Your Present Calculated Heat Index Value Is %.1f F.\n", apptemp);
    print(temperature_str);
    print ("  \n");
    print ("       When the  Heat Index reaches 130 degrees or higher, Heat\n");
    print ("       Strokes or  Sunstrokes are  HIGHLY likely with continued\n");
    print ("       exposure!   When the  Heat Index  ranges from 105 to 130\n");
    print ("       degrees,  sunstroke, heat exhaustion and heat cramps are\n");
    print ("       likely with  prolonged exposure and/or physical activity.\n");
    print ("       Heat Index  ranges between 90 and 105 degrees indicate a\n");
    print ("       possibility  of  heat  cramps and  heat  exhaustion with\n");
    print ("       prolonged  exposure and/or physical activity.\n");
    print ("  \n");
    print ("       Program calculations assume an adult, wearing long pants\n");
    print ("       and a  short sleeved shirt,  walking in shade at 3.1 MPH\n");
    print ("       with standard sea level air pressure,  a wind  speed  of\n");
    print ("       5.6 MPH, and a vapor pressure of 1.6kPa.  In effect, the\n");
    print ("       calculations  approximate the temperature  that  current\n");
    print ("       conditions feel like to the average person.\n");
    print ("  \n");
}   /* end of heat_index() */

/*
**++
**  FUNCTIONAL DESCRIPTION:
**
**      This function determines the heat index and returns that heat index
**  to the calling routine.
**
**	After staring at the BASIC code for TARGET78 and it's dependent
**  label routines, I have simply given up on trying to make it structured.
**  It is simply too convoluted for me to unravel.
**
**  FORMAL PARAMETERS:
**
**      ta:
**          a double, which is the temperature that the User entered
**       
**      rh:
**          a double, which is the relative humidity that the User entered
**
**  RETURN VALUE:
**
**      a double, which is the heat index
**
**--
*/
#ifdef VMS
static double target78 (double ta, double rh)
#else
static double target78 (ta, rh)
double ta, rh;
#endif
{
    double tc,
	   es, 
	   e, 
	   tb, hc, ra, za, qu, r3, c, n1, n2, n3, n4, n5,
	   pb, 
	   q, 
	   rs, 
	   zs, 
	   ehc, 
	   phi2, 
	   r, 
	   chc, 
	   pinf, 
	   her, 
	   era, 
	   hr, 
	   ara, 
	   aza, 
	   q2u, 
	   qj, 
	   k, 
	   l, 
	   f, 
	   rf, 
	   qv,
	   eza,
	   w1, w2, w3, w4, w5, w6, w7,
	   apptemp;
    int it;

    apptemp = 0.;

    /*	 
    **  Change the temperature to celcius.
    */	 
    tc = (ta - 32.) * 5. / 9.;

    /*	 
    **  I have absolutely no idea what any of these variables and equations
    **	mean.
    */	 
    es = 6.11 * pow(10.0, ((7.567 * tc) / (239.7 + tc)));
    e = .01 * rh * es;
    tb = 37;
    pb = 5.65;
    q = 180;
    rs = .0387;
    zs = .0521;
    ehc = 17.4;
    phi2 = .84;
    r = .124;
    chc = 11.6;
    pinf = .1 * e;
    her = 4.18 + .036 * tc;
    era = 1 / (ehc + her);
    qv = q * (.143 - .00112 * tc - .0168 * pinf);
    eza = .060606 / ehc;
    hr = 3.35 + .049 * tc;
    ara = 1 / (chc + hr);
    aza = .060606 / chc;
    q2u = ((tb - tc) + (pb - pinf) * era / (zs + eza)) / (rs + era);
    qj = (q - qv - (1 - phi2) * q2u) / phi2;
    k = (rs + ara) + (zs + aza) / r - ((tb - tc) + (pb - pinf) / r) / qj;
    l = (rs + ara) * (zs + aza);
    l = (l - ((tb - tc) * (zs + aza) + (pb - pinf) * ara) / qj) / r;
    f = k * k - 4 * l;

    if (f < 0.)
    {
        df = -1.;
        goto target84;;
    }
    rf = .5 * (-k + sqrt(f));
    df = 60 * rf;
    if (df < 0.)
        goto target84;
    w1 = .2016;
    w2 = (1 - phi2) / (rs + era);
    w3 = phi2 / (rs + rf + ara);
    w4 = 159.0984;
    w5 = 37.;
    w6 = 4.05 * era / (zs + eza);
    w7 = 4.05 * (rf + ara) / (zs + r * rf + aza);
    apptemp = (-w4 + w2 * (w5 + w6) + w3 * (w5 + w7)) / (w1 + w2 + w3);
    goto target84;
target84:
    if (df < 0.)
        goto target83;
target86:
    apptemp = 32 + 1.8 * apptemp;
    return apptemp;
target83:
    hc = 12.3;
    hr = 4.1 + .028 * tc;
    ra = 1 / (hc + hr);
    za = .060606 / hc;
    qu = q - qv;
    for (it = 1;  it <= 10;  it++)
    {
	zs = ((pb - pinf) * ra) / (qu * (rs + ra) - (tb - tc)) - za;
	if (zs < 0.)
	    zs = 0.;
        r3 = pow (zs / 600000., 0.2);
	c = abs(rs - r3);
	if (c <= .0001)
	    goto target85;
	rs = .5 * (rs + r3);
    }
target85:
    n1 = 159.0984;
    n2 = 37.;
    n3 = 4.05 * ra / (zs + za);
    n4 = (rs + ra);
    n5 = .2016;
    apptemp = (-n1 + (n2 + n3) / n4) / (n5 + 1 / n4);
    goto target86;
}   /* end of target78() */
