/***************************************************************

   FILE:  EDFIX.C
   USAGE: EDFIX CONTROL_FILE_NAME

                     Eric Firing
                     Fri  03-31-1989

   08/22/90 Willa Zhu --
          The variable hdop in struct GPS_LINE_TYPE is
          replaced by pdop (in a floating format) whenever
          WECOMA gps fix file is used.  Therefore, the type
          of hdop and hdop_max has been changed from int to
          double in order to read both hdop (integer) and pdop
          (float).

          The program also updated to comment out the duplicated
          fix records.

91/10/15 JR - changed pc_fix_dt in TRANSIT_LINE_TYPE from int to
          long int so as to accommodate larger values on the PC
          (otherwise, this can cause discrepancies between the
          edfix result and the input Transit summary file entry).

1999/09/15 PJ
          The summary from ubprint does not always output dopN, dopE and
          dopV. Consequently, if these are not present, no fix will be
          considered good by edfix. Therefore, reading in function
          get_gps_line() should take care of this.

2000/11/24 PJ 
           Files should be closed iff they have been opened.


----------------------------------------------------------------

control file structure:

     output: (file name)
     transit_file:
         min_elevation=
         max_elevation=
         max_iterations=
         max_dr=
         time_since_gps=
     gps_file:
         max_hdop=
         time_since_3=

****************************************************************/
#include "common.h"
#include "dbhost.h"    /* PROTOTYPE_ALLOWED */
#include "dbext.h"     /* FILE_NAME_TYPE */
#include "ioserv.h"    /* check_error(), check_fopen(), get_parameters(),
                          print_parameters(), PARAMETER_ENTRY_LIST_TYPE */

#define VBUFSIZE 8192

typedef struct
{
   int      el_min,
            el_max,
            it_max,
            dop_min;
   double   dr_max,
            time_since_gps;
} TRANSIT_CRITERION_TYPE;

typedef struct
{
   double   hdop_max;
   double   time_since_3;
} GPS_CRITERION_TYPE;

typedef struct
{
   double   time,
            lon,
            lat;
   int      elevation,
            iterations;
   double   dr_dist;
   int      used;
   long     pc_fix_dt;
   int      good;
} TRANSIT_LINE_TYPE;

typedef struct
{
   double   time,
            lon,
            lat;
   int      nsat,
            quality;
   double   hdop;
   int      dopN,
            dopE,
            dopV,
            altitude,
            good;
} GPS_LINE_TYPE;

#if PROTOTYPE_ALLOWED
void edit_transit(TRANSIT_LINE_TYPE *fix, TRANSIT_CRITERION_TYPE *accept,
   double last_gps_time);
void edit_gps(GPS_LINE_TYPE *fix, GPS_CRITERION_TYPE *accept,
   double last_3gps_time);
void write_transit_line(FILE *fp_out, TRANSIT_LINE_TYPE *fix);
int get_transit_line(FILE *fp_in, TRANSIT_LINE_TYPE *fix);
void write_gps_line(FILE *fp_out, GPS_LINE_TYPE *fix);
int get_gps_line(FILE *fp_in, GPS_LINE_TYPE *fix);
#else
void edit_transit();
void edit_gps();
void write_transit_line();
int get_transit_line();
void write_gps_line();
int get_gps_line();
#endif

double last_time = -1;

#if PROTOTYPE_ALLOWED
void edit_transit(TRANSIT_LINE_TYPE *fix, TRANSIT_CRITERION_TYPE *accept, double last_gps_time)
#else
void edit_transit(fix, accept, last_gps_time)
TRANSIT_LINE_TYPE *fix;
TRANSIT_CRITERION_TYPE *accept;
double last_gps_time;
#endif
{
   if (fix->elevation  >= accept->el_min      &&
       fix->elevation  <= accept->el_max      &&
       fix->iterations <= accept->it_max      &&
       fix->dr_dist    <= accept->dr_max      &&
       fix->time-last_gps_time >= accept->time_since_gps)
      fix->good = 1;
    else
      fix->good = 0;
}

#if PROTOTYPE_ALLOWED
void edit_gps(GPS_LINE_TYPE *fix, GPS_CRITERION_TYPE *accept, double last_3gps_time)
#else
void edit_gps(fix, accept, last_3gps_time)
GPS_LINE_TYPE *fix;
GPS_CRITERION_TYPE *accept;
double last_3gps_time;
#endif
{
   if (fix->hdop                <= accept->hdop_max    &&
       fix->time-last_3gps_time <= accept->time_since_3)
      fix->good = 1;
    else
      fix->good = 0;
}

#if PROTOTYPE_ALLOWED
void write_transit_line(FILE *fp_out, TRANSIT_LINE_TYPE *fix)
#else
void write_transit_line(fp_out, fix)
FILE *fp_out;
TRANSIT_LINE_TYPE *fix;
#endif
{
   if (!fix->good || (last_time == fix->time))
      fprintf(fp_out, "%%");
   fprintf(fp_out, "%13.7f  %13.7f %13.7f  %3d %2d %5.2f %2d  %ld\n",
                    fix->time,
                    fix->lon,
                    fix->lat,
                    fix->elevation,
                    fix->iterations,
                    fix->dr_dist,
                    fix->used,
                    fix->pc_fix_dt);
   last_time = fix->time;
}

#if PROTOTYPE_ALLOWED
int get_transit_line(FILE *fp_in, TRANSIT_LINE_TYPE *fix)
#else
int get_transit_line(fp_in, fix)
FILE *fp_in;
TRANSIT_LINE_TYPE *fix;
#endif
{
   int n = 0;
   char line_buffer[120];
   char *start;

   while (fgets(line_buffer, 120, fp_in) != NULL && n!= 8)
   {
      start = strchr(line_buffer, '%');
      if (start == NULL)             /* no % found */
      {
         start = line_buffer;
         fix->good = 1;
      }
      else
      {
         start++;
         fix->good = 0;
      }

      n = sscanf(start, " %lf %lf %lf %d %d %lf %d %ld\n",
                    &fix->time,
                    &fix->lon,
                    &fix->lat,
                    &fix->elevation,
                    &fix->iterations,
                    &fix->dr_dist,
                    &fix->used,
                    &fix->pc_fix_dt);
      if (n == 8)
         return(1);      /* a transit fix was found */
   }
   return(-1);        /* EOF */
}


#if PROTOTYPE_ALLOWED
void write_gps_line(FILE *fp_out, GPS_LINE_TYPE *fix)
#else
void write_gps_line(fp_out, fix)
FILE *fp_out;
GPS_LINE_TYPE *fix;
#endif
{
   if ((!fix->good) || (last_time == fix->time))
      fprintf(fp_out, "%%");
   fprintf(fp_out, "%13.7f %13.7f %13.7f",
                             fix->time,
                             fix->lon,
                             fix->lat);
   fprintf(fp_out, "  %1d %1d %4.1f %3d %3d %3d  %3d\n",
                             fix->nsat,
                             fix->quality,
                             fix->hdop,
                             fix->dopN,
                             fix->dopE,
                             fix->dopV,
                             fix->altitude);
   last_time = fix->time;
}

#if PROTOTYPE_ALLOWED
int get_gps_line(FILE *fp_in, GPS_LINE_TYPE *fix)
#else
int get_gps_line(fp_in, fix)
FILE *fp_in;
GPS_LINE_TYPE *fix;
#endif
{
   int n = 0;
   char line_buffer[120];
   char *start;

   while (fgets(line_buffer, 120, fp_in) != NULL && n != 10)
   {
      start = strchr(line_buffer, '%');
      if (start == NULL)             /* no % found */
      {
         start = line_buffer;
         fix->good = 1;
      }
      else
      {
         start++;
         fix->good = 0;
      }

      n = sscanf(start, " %lf %lf %lf %d %d %lf %d %d %d %d",
                                &fix->time,
                                &fix->lon,
                                &fix->lat,
                                &fix->nsat,
                                &fix->quality,
                                &fix->hdop,
                                &fix->dopN,
                                &fix->dopE,
                                &fix->dopV,
                                &fix->altitude);
      if (n == 10)
         return(1);
      
      /* 1999/09/15 PJ */
      n = sscanf(start, " %lf %lf %lf %d %d %lf %d",
                 &fix->time,
                 &fix->lon,
                 &fix->lat,
                 &fix->nsat,
                 &fix->quality,
                 &fix->hdop,
                 &fix->altitude);
      if(n==7){
        fix->dopN = fix->dopE = fix->dopV = -1;
        return(1);
      }
   }
   return(EOF);
}

#if PROTOTYPE_ALLOWED
void do_it(FILE *fp_cnt)
#else
void do_it(fp_cnt)
FILE *fp_cnt;
#endif
{
   FILE *fp_out, *fp_gps, *fp_transit;
   TRANSIT_LINE_TYPE transit_fix;
   GPS_LINE_TYPE gps_fix;
   double   last_gps_time = -9999.9,
            last_3gps_time= -9999.9;
   int transit_finished = 1;
   int gps_finished = 1;
   int transit_needed = 1;
   int gps_needed = 1;

   static   FILE_NAME_TYPE out_filename, gps_filename, transit_filename;
   static   GPS_CRITERION_TYPE gps_crit;
   static   TRANSIT_CRITERION_TYPE transit_crit;

   static   PARAMETER_LIST_ENTRY_TYPE parameters[] =
      {
         { " output:",        " %79s", out_filename,           TYPE_STRING },
         { " transit_file:",  " %79s", transit_filename,       TYPE_STRING },
         { " min_elevation=", " %d",   &transit_crit.el_min,   TYPE_INT    },
         { " max_elevation=", " %d",   &transit_crit.el_max,   TYPE_INT    },
         { " max_iterations="," %d",   &transit_crit.it_max,   TYPE_INT    },
         { " max_dr=",        " %lf",  &transit_crit.dr_max,   TYPE_DOUBLE },
         { " time_since_gps="," %lf",  &transit_crit.time_since_gps,
                                                               TYPE_DOUBLE },
         { " gps_file:",      " %79s", gps_filename,           TYPE_STRING },
         { " max_hdop=",      " %lf",  &gps_crit.hdop_max,     TYPE_DOUBLE },
         { " time_since_3=",  " %lf",  &gps_crit.time_since_3, TYPE_DOUBLE },
         { NULL,              NULL,    NULL,                   0           }
      };                   /* parameters[] */

   /* dummy to force linkage of floating point routines in Turbo C 2.0 */
   sin(0.0);

   if(get_parameters(fp_cnt, parameters, NULL))  exit(-1);

   fp_out = check_fopen(out_filename,"w");
#ifdef VBUF
    check_error(setvbuf(fp_out,  NULL, _IOFBF, VBUFSIZE),
                 "Error in setvbuf for fp_out in do_it.");
#endif
   if (strcmp(transit_filename, "none") != 0)
   {
      fp_transit = check_fopen(transit_filename,"r");
#ifdef VBUF
      check_error(setvbuf(fp_transit,  NULL, _IOFBF, VBUFSIZE),
                 "Error in setvbuf for fp_transit in do_it.");
#endif
      transit_finished = 0;
   }
   if (strcmp(gps_filename, "none") != 0)
   {
      fp_gps = check_fopen(gps_filename,"r");
#ifdef VBUF
      check_error(setvbuf(fp_gps,  NULL, _IOFBF, VBUFSIZE),
                 "Error in setvbuf for fp_gps in do_it.");
#endif
      gps_finished = 0;
   }

   fprintf(fp_out, "%%  Edited and combined fix files:\n%%");
   print_parameters(fp_out, parameters, NULL, "\n%%");
   fprintf(fp_out, "\n");

   do
   {
      if (!transit_finished && transit_needed &&
          get_transit_line(fp_transit, &transit_fix) == EOF)
      {
         transit_finished = 1;
      }
      else
      {
         transit_needed = 0;
      }
      if (!gps_finished && gps_needed  &&
          get_gps_line(fp_gps, &gps_fix) == EOF)
      {
         gps_finished = 1;
      }
      else
      {
         gps_needed = 0;
      }
      if (!gps_finished && !transit_finished)
      {
         if (gps_fix.time < transit_fix.time)
         {
            if (gps_fix.nsat >= 3)           /* this stmt & next one swapped */
               last_3gps_time = gps_fix.time;   /* 01/25/91 */
            if (gps_fix.good)
               edit_gps(&gps_fix, &gps_crit, last_3gps_time);
            if (gps_fix.good)
               last_gps_time = gps_fix.time;
            write_gps_line(fp_out, &gps_fix);
            gps_needed = 1;
         }
         else
         {
            if (transit_fix.good)
               edit_transit(&transit_fix, &transit_crit, last_gps_time);
            write_transit_line(fp_out, &transit_fix);
            transit_needed = 1;
         }
      }
      else if (!gps_finished)      /* but transit is finished */
      {
         if (gps_fix.nsat >= 3)           /* this stmt & next one swapped */
            last_3gps_time = gps_fix.time;   /* 02/27/91 */
         if (gps_fix.good)
            edit_gps(&gps_fix, &gps_crit, last_3gps_time);
         write_gps_line(fp_out, &gps_fix);
         gps_needed = 1;
      }
      else if (!transit_finished)    /* but gps is finished */
      {
         if (transit_fix.good)
            edit_transit(&transit_fix, &transit_crit, last_gps_time);
         write_transit_line(fp_out, &transit_fix);
         transit_needed = 1;
      }
   } while (!gps_finished || !transit_finished);

   fclose(fp_out);
   /* 2000/11/24 PJ */
   if (strcmp(transit_filename, "none") != 0)
     fclose(fp_transit);
   if (strcmp(gps_filename, "none") != 0)
     fclose(fp_gps);
   printf("\nEDFIX completed.\n");
   return;
}


