/*
 * RASP89 - Rocket Altitude Simulation Program Engine Database Listing
 * Based on the simple BASIC program written by
 * Harry Stine in 1979, modified and converted
 * into C by Mark A. Storin, Sept/Oct 1989.
 * Rev 2 by Kent Hoult, June 1990.
 *
 * 02/18/94  Added MAC support
 *           Revised output format to remove tabs and allow longer data fields
 *           Added input prompts, alternate outputs, error checking and input defaults 
 *           Rev 3.3 - Warren Massey (massey@travis.llnl.gov)
 */

/* #define MSDOS  1 */
/* #define UNIX   1 */
/* #define VMS    1 */
#define MAC    1 

#include <stdio.h>
#include <ctype.h>

#define VERSION   "3.3" 
#define MAXENG    1
#define TRUE      1
#define FALSE     0
#define TTYmax    20          /* Max length of an input string from stdin */
#define MCmax     12          /* Max length of engine designation string, e.g. G80 */
#define MAXT      64          /* Max array size used to hold time/thrust 
                                 datapairs read from RASP.ENG file. A datapoint
                                 consists of time & thrust datums so this array
                                 can hold MAXT/2 datapoints. */

FILE *stream,  *efile, *fopen();

#ifdef MAC
#include <console.h>
#include <fonts.h>
FILE *fopenc();
int MsgSent = FALSE;
#endif

/*
 * Global Variables
 */
int Error     = FALSE;
int destnum   = 1;      /* index into array of devices for output - dest */

char fname[64];      /* output file name for simulation */
char tty_input[TTYmax];
char Bell = '\7';
char prefix_char = ' ';
char efile_name[] = {"rasp.eng"}; /* name of engine database file */

struct engine {
    double t2;           /* thrust duration    (seconds)                 */
    double m2;           /* propellant wt.     (kilograms)               */
    double wt;           /* initial engine wt. (kilograms)               */
    double thrust[MAXT]; /* thrust curve     (Time-sec,Thrust-Newtons)   */
    double navg;         /* average thrust     (newtons)                 */
    double ntot;         /* total impulse      (newton-seconds)          */
    double npeak;        /* peak thrust        (newtons)                 */
    int    dia;          /* engine diameter    (millimeters)             */
    int    len;          /* engine length      (millimeters)             */
    int    delay[8];     /* ejection delays available (sec)              */
    char   mfg[32];      /* manufacturer info                            */
    char   Mcode[MCmax]; /* engine name                                  */
   };

struct engine e_info[MAXENG];


int *get_input( input, input_max )
    int input_max;
    char *input;
{
    int i, c;
    c = getc( stdin );
    if( (c != '\n') && (c != EOF) ) {
        ungetc( c, stdin );
        fgets( input, input_max, stdin );
        sscanf( input, "%s%*c", input );
    }
    else {
        strcpy( input, "") ;
    }
}        


/*   "dump_buffer()" must be called after every "scanf()" to avoid screwing up
 *   "get_input()"
 */   
int dump_buffer() {
  for (;;)
     switch( getchar() ) {
     case EOF: return EOF;
     case '\n': return 0;
     default: ;
  }
}

load_engine(e) int e; {
  int k, dia, len, more, x;
  char s[256], *c, sdelay[32];
  double sum,peak, t1, t2, f1, f2;
  double *p;

  for(more = TRUE; more;) {
    if((c = fgets(s, 256, efile)) != NULL) {
      if(*c != ';') {
        x = sscanf(s, "%s %d %d %s %lf %lf %s", e_info[e].Mcode, &e_info[e].dia,
                   &e_info[e].len, sdelay, &e_info[e].m2, &e_info[e].wt,
                   e_info[e].mfg);
        if( x == EOF) 
        {
          return(-1);
        }
        else if( x != 7) {
          printf("\n*** Error - Bad line in rasp.eng\n%c", Bell);
          Error = TRUE;
          return(-1);
        }
        more = FALSE;
      }
    }
    else
      return(-1);
  }
  k = 0;
  for(more = TRUE; more;) {
    if((c = fgets(s, 256, efile)) != NULL) {
      if(*c != ';') {
        if(k >= MAXT) {
          printf("\n*** Error - Thrust table overflow in rasp.eng\n%c", Bell);
          Error = TRUE;
          return(-1);
        }

        x = sscanf(s, "%lf %lf", &e_info[e].thrust[k], &e_info[e].thrust[k+1]);
        if( x != 2 ) {
          printf("\n*** Error - Bad thrust table line in rasp.eng\n%c", Bell);
          Error = TRUE;
          return(-1);
        }
        if(e_info[e].thrust[k+1] == 0) {
          e_info[e].t2 = e_info[e].thrust[k];
          more = FALSE;
        }
        else
          k += 2;
      }
    }
    else {
      printf("\n*** Error - unexpected EOF while loading thrust curve.\n%c", Bell);
      Error = TRUE;
      return(-1);
    }
  }
  t1 = f1 = sum = peak = 0.0;
  p = &e_info[e].thrust[0];
  do {
    t2 = *p++;
    f2 = *p++;
    if(f2 > peak) peak = f2;
    sum += (t2 - t1) * (f1 + f2) * 0.5;
    t1 = t2;
    f1 = f2;
  } while (f1 != 0.0);
  e_info[e].ntot = sum;
  e_info[e].npeak = peak;
  if( t1 > 0.0 )
     e_info[e].navg = sum / t1;
  else
     e_info[e].navg = 0.0;
  c = sdelay;
  for(k = 0; k < 7; k++) {
    e_info[e].delay[k] = (int) strtol(c, &c, 10);
    if(*c != '-') {
      e_info[e].delay[k+1] = -1;
      break;
    }
    else
      c++;

  }
  return(e);
}

print_engine_info(e)
     int e;
{
  int d;
  fprintf(stream,"%c %-8s  %-9s  %8.2lf   %8.2lf  %8.2lf  %6.2lf  ", prefix_char,
         e_info[e].Mcode, e_info[e].mfg, e_info[e].navg, e_info[e].ntot,
         e_info[e].npeak, e_info[e].t2);
  for(d = 0; e_info[e].delay[d] >= 0; d++)
    fprintf(stream,"%d ", e_info[e].delay[d]);
  fprintf(stream,"\n");
}

print_engine_header() {
  fprintf(stream,"%c\n", prefix_char);
  fprintf(stream,"%c                       Average    Total      Peak      Burn\n",prefix_char);
  fprintf(stream,"%c                       Thrust    Impulse    Thrust     Time    Delays\n",prefix_char);
  fprintf(stream,"%c   Type     Mfg/Opt     (Nt)     (Nt-Sec)    (Nt)     (Sec)    (Sec)\n",prefix_char);
  fprintf(stream,"%c --------  ---------  --------   --------  --------  ------  ----------\n",prefix_char);

}

worker() {
	int minval, maxval, ianswer;	
  
      do {

      minval = 1;
      maxval = 3;
      for(;;)
      {
        printf("\nSend data to:\n\t(1) Screen\n\t(2) Printer\n\t");
        printf("(3) Disk file\n\nChoice?[%d] ", destnum);
        get_input( tty_input, TTYmax );
        if( sscanf(tty_input, "%d", &ianswer) != EOF )
           destnum = ianswer;
        if( destnum < minval )
        { 
           printf("\n*** Error - \"%d\" is too small! Minimum allowed is \"%d\" ***\n%c",
                  destnum, minval, Bell );
           destnum = minval;
        }
        else if( destnum > maxval )
        { 
           printf("\n*** Error - \"%d\" is too large! Maximum allowed is \"%d\" ***\n%c",
                  destnum, maxval, Bell );
           destnum = maxval;
        }
        else break;
      }


#ifdef MSDOS
        if (destnum == 1)
            strcpy(fname, "CON");
        else if (destnum == 2)
            strcpy(fname, "PRN");
#endif
#ifdef UNIX
        if (destnum == 1)
            strcpy(fname, "/dev/tty");
        else if (destnum == 2)
            strcpy(fname, "/dev/lp");
#endif
#ifdef VMS
        if (destnum == 1)
            strcpy(fname, "TT:");
        else if (destnum == 2)
            strcpy(fname, "LP:");
#endif
#ifdef MAC
        if (destnum == 1){
            console_options.title  = "\pRASP Output";
            console_options.txFont = monaco;
            console_options.txSize = 9;   /* Font size in points */
            console_options.ncols  = 80;
            console_options.nrows  = 25;
            console_options.top    =100;
            console_options.left   = 30;
            if( !MsgSent ) {
               MsgSent = TRUE;
               printf("\n\nScrolling of the display may be throttled with the mouse button.\n");
               sleep(1);
            }
         }
        else if (destnum == 2){
            console_options.title  = "\pRASP Print Window";
            console_options.txFont = courier;
            console_options.txSize = 12;   /* Font size in points */
            console_options.nrows  = 25;
            console_options.ncols  = 80;
            console_options.top    = 50;
            console_options.left   = 10;
        }
#endif
        else if (destnum == 3){
            printf("Enter file name: ");
            scanf("%s", fname);
            dump_buffer();
        }
        else{
           continue;
        }


#ifdef MAC
        if( destnum == 3 ){
           if ((stream = fopen(fname,"w")) == NULL)
                printf("%s cannot be opened.\n",fname);
         }
        else{
           if ((stream = fopenc()) == NULL)
                printf("CONSOLE cannot be opened.\n");
           else 
                if (destnum == 2) cecho2printer( stream );
        }
#else
        if ((stream = fopen(fname,"w")) == NULL)
             printf("%s cannot be opened.\n",fname);
#endif


    } while (stream == NULL);

   if((efile = fopen(efile_name,"r")) == NULL) {
      printf("\n*** Error - unable to open engine database %s ***\n%c",
             efile_name, Bell);
      Error = TRUE;
      return(-1);
   }

   print_engine_header();
   while(load_engine(0) != -1)
      print_engine_info(0);
    
   fclose( efile );
}


main(argc, argv)
int argc;
char*argv[];
{
    char ans[3] = "N", canswer[3];
    int i;
    
#ifdef MAC
    console_options.txFont = monaco;
    console_options.txSize = 9;   /* font size in points */
    console_options.procID = 8;
    console_options.nrows  = 25;
    console_options.ncols  = 80;
    console_options.top    = 50;
    console_options.left   = 10;
    console_options.title  = "\pRASP Input";
    console_options.pause_atexit = 0;
    argc = ccommand(&argv);
#endif   

   printf("\nRASP - Rocket Altitude Simulation Program Engine Database V%s\n\n", VERSION);

    for (;;)
    {
        Error = FALSE;
        worker();
        if( Error ) exit(0);

        printf("\nDo again(Y/N)? [ %s ]:  ", ans);
        get_input( tty_input, TTYmax );
        if( sscanf(tty_input, "%s", canswer) != EOF )
           strcpy( ans, canswer );
        if ((strncmp(ans,"y",1) == 0) || (strncmp(ans,"Y",1) == 0)) 
        {
#ifdef MAC
           if( destnum == 1 ) fclose(stream);
#endif            
           continue;
         }
         else exit(0);
     }
}
