
	/*
	** This program parses an EMA response CSV file
	** and a results-spans.txt file from PhoneView.
	** It correlates them to create two types of output:
	**
	** per day:
	** (1) EMA (qty of EMAs, from 0 to N)
	** (2) wrist motion active (%time moving)
	** (3) wrist at rest (%time on but not moving)
	** (4) lapse meals reported in EMA (from 0 to N)
	** (5) planned meals reported in EMA (from 0 to N)
	** (6) both (meal was both lapse and planned) in EMA (from 0 to N)
	** (7) wrist meals detected (from 0 to N)
	**
	** per meal:
	** (1) start time
	** (2) end time (for EMA meals this is unknown so +1 min from start)
	** (3) meal type (wrist, planned, lapse, both)
	** (4) bites
	** (5) duration (min)
	** (6) eating rate (sec per bite)
	**
	** Fields (7+) are only applicable to EMA meals; for wrist the
	** output is x.
	**
	** (7) EMA time delta (time since last EMA response)
	**     time between when EMA response occurred and when meal
	**     happened (printing in hours, storing in sec)
	** (8) match time delta (nearest EMA-to-wrist difference)
	**     (printing in hours, storing in program in sec)
	** (9) #wrist detections in prior DELTA_W hours
	** (10) #wrist detections in subsequent DELTA_W hours
	** (11) #planned in prior DELTA_W hours
	** (12) #planned in subsequent DELTA_W hours
	** (13) #lapse in prior DELTA_W hours
	** (14) #lapse in subsequent DELTA_W hours
	** (15) #both in prior DELTA_W hours
	** (16) #both in subsequent DELTA_W hours
	**
	** will possibly add other fields here later
	**
	** The date range to be processed is the union of all dates
	** covered in both the EMA and PhoneView files.
	**
	** See ema-to-events.c for more details on how EMA data is
	** converted into meal-level data.
	**
	** Wrist motion data is filename, start, end, class,
	** where class {0,1,2,3}={eating,other,rest,walking}.
	*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define	DEBUG		0
#define	MAX_EMA		1000
#define	MAX_MEALS	10000
#define	MAX_SPANS	20000
#define	MAX_CALENDAR	365	/* units are days */
#define	DELTA_W		7200	/* units are seconds */
#define	SEPARATOR	','

#define	SWAP_INT(x,y)	{ swap_int=x; x=y; y=swap_int; }
#define	SWAP_DOUBLE(x,y) { swap_double=x; x=y; y=swap_double; }
#define	SWAP_STR(x,y)	{strcpy(swap_str,x); strcpy(x,y); strcpy(y,swap_str);}

	/* conversion functions unix-to-timestamp (below) */
void DateFromTimestamp();
int TimeStamp(unsigned char, unsigned char, unsigned char,
		unsigned char, unsigned char, unsigned char);


int main(int argc, char *argv[])

{
FILE		*fpt;
int		i,j,k,e,field,length;
int		TotalEMA,ValidEMA;
char		text[320],byte;
int		ema_year[MAX_EMA],ema_month[MAX_EMA],ema_day[MAX_EMA];
int		ema_hour,ema_minute,ema_second;
int		ema_timestamp[MAX_EMA];
char		ema_lapse[MAX_EMA][80];
char		ema_lapse_type[MAX_EMA][80];
char		ema_meal[MAX_EMA][4][80];
int		year,month,day;
unsigned char	cyear,cmonth,cday,chour,cminute,csecond;
int		eyear,emonth,eday,ehour,eminute,esecond;
int		iyear,imonth,iday,ihour,iminute,isecond;
int		smallest;
char		swap_str[320];
int		swap_int;
double		swap_double;
char		header[3200];
char		s_filename[320],s_start[32],s_end[32];
int		TotalSpans;
int		*span_class;
int		*span_start_ts;
int		*span_end_ts;
int		*span_bites;	   /* only applic if class = 0 */
double		*span_duration;  /* only applic if class = 0 */
double		*span_spb;	   /* only applic if class = 0 */
int		EMA_in_span,EMA_lapse_in_span;
int		TotalCalendarDays,calendar_start,calendar_end;
int		calendar_timestamp[MAX_CALENDAR];
int		calendar_ema[MAX_CALENDAR];
int		calendar_wrist_active[MAX_CALENDAR];
int		calendar_wrist_rest[MAX_CALENDAR];
int		calendar_meal_ema_lapse[MAX_CALENDAR];
int		calendar_meal_ema_planned[MAX_CALENDAR];
int		calendar_meal_ema_both[MAX_CALENDAR];
int		calendar_meal_wrist[MAX_CALENDAR];
char		meal_name[MAX_MEALS][80];
int		meal_unixtime[MAX_MEALS];	/* units are sec */
int		meal_year[MAX_MEALS],meal_month[MAX_MEALS],meal_day[MAX_MEALS];
int		meal_ema_type[MAX_MEALS];
int		meal_hour_start[MAX_MEALS],meal_min_start[MAX_MEALS];
int		meal_hour_end[MAX_MEALS],meal_min_end[MAX_MEALS];
int		meal_delta_ema[MAX_MEALS];	/* units are sec */
int		meal_delta_match[MAX_MEALS];	/* units are sec */
int		meal_bites[MAX_MEALS];	   /* only applic for wrist meals */
double		meal_duration[MAX_MEALS];  /* only applic for wrist meals */
double		meal_spb[MAX_MEALS];       /* only applic for wrist meals */
int		TotalMeals;
int		closest_index,closest_delta,delta;
int		*meals_nearby[4][2];
int		meal_has_been_matched[MAX_MEALS]; /* index of match */


if (argc != 3)
  {
  printf("Usage:  parse-ema [ema.csv] [wrist.txt]\n");
  exit(0);
  }

	/* allocate memory for spans */
span_class=(int *)calloc(MAX_SPANS,sizeof(int));
span_start_ts=(int *)calloc(MAX_SPANS,sizeof(int));
span_end_ts=(int *)calloc(MAX_SPANS,sizeof(int));
span_bites=(int *)calloc(MAX_SPANS,sizeof(int));
span_duration=(double *)calloc(MAX_SPANS,sizeof(double));
span_spb=(double *)calloc(MAX_SPANS,sizeof(double));


	/* allocate memory for counters for nearby meals */
for (j=0; j<4; j++)
  {
  meals_nearby[j][0]=calloc(MAX_MEALS,sizeof(int));
  meals_nearby[j][1]=calloc(MAX_MEALS,sizeof(int));
  }

	/* read the EMA file */
if ((fpt=fopen(argv[1],"r")) == NULL)
  {
  printf("Unable to open %s for reading\n",argv[1]);
  exit(0);
  }
TotalMeals=0;
TotalEMA=0;
field=0;
length=0;
while (1)
  {
  i=fread(&byte,1,1,fpt);
  if (i == 1  &&  byte == '\r')
    continue;
  if (i == 0  ||  byte == ','  ||  byte == '\n')
    {
    text[length]=0;
    if (DEBUG)
      printf("%d => %s\n",field,text);
    if (field == 0)
      {
      if (strcmp(text,"Compliance") == 0  ||  strlen(text) == 0
		||  strcmp(text,"who") == 0)
        ValidEMA=0;	/* last 2 lines of file or first line of file */
      else
        ValidEMA=1;
      ema_year[TotalEMA]=ema_month[TotalEMA]=ema_day[TotalEMA]=0;
      }
    if (field == 11)	/* EMA response day/time */
      {
      if (strlen(text) > 1)
        {
        text[4]=text[7]=text[10]=0;
        ema_year[TotalEMA]=atoi(&(text[1]));  /* clip the millenium */
        ema_month[TotalEMA]=atoi(&(text[5]));
        ema_day[TotalEMA]=atoi(&(text[8]));
        text[13]=text[16]=text[19]=0;
        ema_hour=atoi(&(text[11]));
        ema_minute=atoi(&(text[14]));
        ema_second=atoi(&(text[17]));
		/* convert date to unix-timestamps */
        ema_timestamp[TotalEMA]=TimeStamp((unsigned char)(ema_year[TotalEMA]),
		(unsigned char)(ema_month[TotalEMA]),
		(unsigned char)(ema_day[TotalEMA]),
		ema_hour,ema_minute,ema_second);
        }
      }
    if (field == 12)	/* EMA request day/time - use if no field 11 */
      {
      if (strlen(text) > 1  &&  ema_year[TotalEMA] == 0)
        {
        text[4]=text[7]=text[10]=0;
        ema_year[TotalEMA]=atoi(&(text[1]));	/* clip millenium */
        ema_month[TotalEMA]=atoi(&(text[5]));
        ema_day[TotalEMA]=atoi(&(text[8]));
        text[13]=text[16]=text[19]=0;
        ema_hour=atoi(&(text[11]));
        ema_minute=atoi(&(text[14]));
        ema_second=atoi(&(text[17]));
        ema_timestamp[TotalEMA]=TimeStamp((unsigned char)(ema_year[TotalEMA]),
		(unsigned char)(ema_month[TotalEMA]),
		(unsigned char)(ema_day[TotalEMA]),
		ema_hour,ema_minute,ema_second);
        }
      }
    if (field == 20)
      strcpy(ema_lapse[TotalEMA],text);
    if (field == 21)
      strcpy(ema_lapse_type[TotalEMA],text);
    if (field == 23)
      strcpy(ema_meal[TotalEMA][0],text);
    if (field == 24)
      strcpy(ema_meal[TotalEMA][1],text);
    if (field == 25)
      strcpy(ema_meal[TotalEMA][2],text);
    if (field == 26)
      strcpy(ema_meal[TotalEMA][3],text);
    field++;
    length=0;
    if (i == 0)
      break;
    if (byte == '\n')
      {
      if (ValidEMA)
        {
        TotalEMA++;
        if (TotalEMA >= MAX_EMA)
	  {
	  printf("MAX_EMA (%d) exceeded\n",MAX_EMA);
	  exit(0);
	  }
        }
      field=0;
      }
    continue;
    }
  text[length]=byte;
  length++;
  }
fclose(fpt);



        /* sort EMA timestamps */
for (i=0; i<TotalEMA; i++)
  {
  smallest=i;
  for (j=i+1; j<TotalEMA; j++)
    if (ema_timestamp[j] < ema_timestamp[smallest])
      smallest=j;
  if (smallest != i)
    {
    SWAP_INT(ema_day[i],ema_day[smallest]);
    SWAP_INT(ema_month[i],ema_month[smallest]);
    SWAP_INT(ema_year[i],ema_year[smallest]);
    SWAP_INT(ema_timestamp[i],ema_timestamp[smallest]);
    SWAP_STR(ema_lapse[i],ema_lapse[smallest]);
    SWAP_STR(ema_lapse_type[i],ema_lapse_type[smallest]);
    for (j=0; j<4; j++)
      SWAP_STR(ema_meal[i][j],ema_meal[smallest][j]);
    }
  }


if (0)	/* print out all EMAs */
for (i=0; i<TotalEMA; i++)
  {
  printf("%d-%d-%d\t%d\t%s\t%s\t%s\t%s\t%s\t%s\n",
	ema_year[i],ema_month[i],ema_day[i],
	ema_timestamp[i],
	ema_lapse[i],ema_lapse_type[i],
	ema_meal[i][0],ema_meal[i][1],ema_meal[i][2],ema_meal[i][3]);
  }


	/* read the results-spans text file */
if ((fpt=fopen(argv[2],"r")) == NULL)
  {
  printf("Unable to open %s for reading\n",argv[2]);
  exit(0);
  }
TotalSpans=0;
field=0;
length=0;
while (1)
  {
  i=fread(&byte,1,1,fpt);
  if (i == 1  &&  byte == '\r')
    continue;
  if (i == 0  ||  byte == ','  ||  byte == '\n')
    {
    text[length]=0;
    if (field == 0)
      strcpy(s_filename,text);
    if (field == 1)
      strcpy(s_start,text);
    if (field == 2)
      strcpy(s_end,text);
    if (field == 3)
      span_class[TotalSpans]=atoi(text);
    if (field == 4)
      span_bites[TotalSpans]=atoi(text);
    if (field == 5)
      span_duration[TotalSpans]=atof(text);
    if (field == 6)
      span_spb[TotalSpans]=atof(text);
    field++;
    length=0;
    if (i == 0)
      break;
    if (byte == '\n')
      {
	/* EOL -- convet text strings to timestamps */

	/* convert date/time to unix-timestamps */
      strcpy(text,s_filename);
      e=strlen(text);
      text[e-4]=text[e-7]=text[e-10]=text[e-15]=0;
      cyear=(unsigned char)atoi(&(text[e-13]));	/* clip the millenium */
      cyear=cyear+1;	/* Brown IRB wanted year obfuscated (-1) */
      cmonth=(unsigned char)atoi(&(text[e-9]));
      cday=(unsigned char)atoi(&(text[e-6]));
      strcpy(text,s_start);
      text[2]=0;
      chour=(unsigned char)atoi(&(text[0]));
      cminute=(unsigned char)atoi(&(text[3]));
      csecond=0;
      span_start_ts[TotalSpans]=TimeStamp(cyear,cmonth,cday,
		chour,cminute,csecond);
      strcpy(text,s_end);
      text[2]=0;
      chour=(unsigned char)atoi(&(text[0]));
      cminute=(unsigned char)atoi(&(text[3]));
      csecond=0;
      span_end_ts[TotalSpans]=TimeStamp(cyear,cmonth,cday,
		chour,cminute,csecond);
      if (0)
        printf("%d => %s %s %d %d %d\n",TotalSpans,s_start,s_end,
		span_class[TotalSpans],
		span_start_ts[TotalSpans],span_end_ts[TotalSpans]);

	/* reset counters for next line */
      field=0;
      TotalSpans++;
      if (TotalSpans >= MAX_SPANS)
	{
	printf("MAX_SPANS (%d) exceeded\n",MAX_SPANS);
	exit(0);
	}
      }
    continue;
    }
  text[length]=byte;
  length++;
  }
fclose(fpt);



TotalMeals=0;
	/* parse meals from wrist motion data */
for (i=0; i<TotalSpans; i++)
  {
  if (span_class[i] == 0)	/* eating class is 0 */
    {
    strcpy(meal_name[TotalMeals],"wrist");
    meal_unixtime[TotalMeals]=span_start_ts[i];
    DateFromTimestamp(span_start_ts[i],
	&iyear,&imonth,&iday,&ihour,&iminute,&isecond);
    meal_hour_start[TotalMeals]=ihour;
    meal_min_start[TotalMeals]=iminute;
    meal_year[TotalMeals]=iyear;
    meal_month[TotalMeals]=imonth+1;
    meal_day[TotalMeals]=iday+1;
    DateFromTimestamp(span_end_ts[i],
	&iyear,&imonth,&iday,&ihour,&iminute,&isecond);
    meal_hour_end[TotalMeals]=ihour;
    meal_min_end[TotalMeals]=iminute;
    meal_delta_ema[TotalMeals]=0;
    meal_delta_match[TotalMeals]=0;
    meal_bites[TotalMeals]=span_bites[i];
    meal_duration[TotalMeals]=span_duration[i];
    meal_spb[TotalMeals]=span_spb[i];
    TotalMeals++;
    if (TotalMeals >= MAX_MEALS)
      {
      printf("MAX_MEALS (%d) exceeded\n",MAX_MEALS);
      exit(0);
      }
    }
  }



	/* convert EMA to meals and add to list */
for (i=0; i<TotalEMA; i++)
  {
  if (strlen(ema_lapse[i]) > 0)
    {
    strcpy(meal_name[TotalMeals],"lapse");
    strcpy(text,ema_lapse[i]);
    text[strlen(text)-3]=0;
    csecond=(unsigned char)atoi(&(text[strlen(text)+1]));
    text[strlen(text)-3]=0;
    cminute=(unsigned char)atoi(&(text[strlen(text)+1]));
    chour=(unsigned char)atoi(&(text[0]));
    meal_year[TotalMeals]=ema_year[i];
    cyear=(unsigned char)(ema_year[i]);
    meal_month[TotalMeals]=ema_month[i];
    cmonth=(unsigned char)(ema_month[i]);
    meal_day[TotalMeals]=ema_day[i];
    cday=(unsigned char)(ema_day[i]);
    meal_hour_start[TotalMeals]=(int)chour;
    meal_min_start[TotalMeals]=(int)cminute;
    meal_unixtime[TotalMeals]=TimeStamp(cyear,cmonth,cday,
				chour,cminute,csecond);
    meal_hour_end[TotalMeals]=meal_hour_start[TotalMeals];
    meal_min_end[TotalMeals]=meal_min_start[TotalMeals]+1;
    meal_delta_ema[TotalMeals]=ema_timestamp[i]-meal_unixtime[TotalMeals];
    meal_delta_match[TotalMeals]=0;
    meal_bites[TotalMeals]=0;	/* not applic */
    meal_duration[TotalMeals]=meal_spb[TotalMeals]=0.0;	/* not applic */
    TotalMeals++;
    if (TotalMeals >= MAX_MEALS)
      {
      printf("MAX_MEALS (%d) exceeded\n",MAX_MEALS);
      exit(0);
      }
    }
  for (j=0; j<4; j++)
    {
    if (strlen(ema_meal[i][j]) > 0)
      {
      strcpy(meal_name[TotalMeals],"planned");
      strcpy(text,ema_meal[i][j]);
      text[strlen(text)-3]=0;
      csecond=(unsigned char)atoi(&(text[strlen(text)+1]));
      text[strlen(text)-3]=0;
      cminute=(unsigned char)atoi(&(text[strlen(text)+1]));
      chour=(unsigned char)atoi(&(text[0]));
      meal_year[TotalMeals]=ema_year[i];
      cyear=(unsigned char)(ema_year[i]);
      meal_month[TotalMeals]=ema_month[i];
      cmonth=(unsigned char)(ema_month[i]);
      meal_day[TotalMeals]=ema_day[i];
      cday=(unsigned char)(ema_day[i]);
      meal_hour_start[TotalMeals]=(int)chour;
      meal_min_start[TotalMeals]=(int)cminute;
      meal_unixtime[TotalMeals]=TimeStamp(cyear,cmonth,cday,
				chour,cminute,csecond);
      meal_hour_end[TotalMeals]=meal_hour_start[TotalMeals];
      meal_min_end[TotalMeals]=meal_min_start[TotalMeals]+1;
      meal_delta_ema[TotalMeals]=ema_timestamp[i]-meal_unixtime[TotalMeals];
      meal_delta_match[TotalMeals]=0;
      meal_bites[TotalMeals]=0;	/* not applic */
      meal_duration[TotalMeals]=meal_spb[TotalMeals]=0.0; /* not applic */
      TotalMeals++;
      if (TotalMeals >= MAX_MEALS)
        {
        printf("MAX_MEALS (%d) exceeded\n",MAX_MEALS);
        exit(0);
        }
      }
    }
  }


	/* sort meals by unix timestamps */
for (i=0; i<TotalMeals; i++)
  {
  smallest=i;
  for (j=i+1; j<TotalMeals; j++)
    if (meal_unixtime[j] < meal_unixtime[smallest])
      smallest=j;
  if (smallest != i)
    {
    SWAP_STR(meal_name[i],meal_name[smallest]);
    SWAP_INT(meal_unixtime[i],meal_unixtime[smallest]);
    SWAP_INT(meal_year[i],meal_year[smallest]);
    SWAP_INT(meal_month[i],meal_month[smallest]);
    SWAP_INT(meal_day[i],meal_day[smallest]);
    SWAP_INT(meal_hour_start[i],meal_hour_start[smallest]);
    SWAP_INT(meal_min_start[i],meal_min_start[smallest]);
    SWAP_INT(meal_hour_end[i],meal_hour_end[smallest]);
    SWAP_INT(meal_min_end[i],meal_min_end[smallest]);
    SWAP_INT(meal_delta_ema[i],meal_delta_ema[smallest]);
    SWAP_INT(meal_delta_match[i],meal_delta_match[smallest]);
    SWAP_INT(meal_bites[i],meal_bites[smallest]);
    SWAP_DOUBLE(meal_duration[i],meal_duration[smallest]);
    SWAP_DOUBLE(meal_spb[i],meal_spb[smallest]);
    }
  }

	/* eliminate duplicates */
for (i=0; i<TotalMeals-1; i++)
  {
  if (meal_month[i] == meal_month[i+1]  &&
	meal_day[i] == meal_day[i+1]  &&
	meal_hour_start[i] == meal_hour_start[i+1]  &&
	meal_min_start[i] == meal_min_start[i+1]  &&
	!(strcmp(meal_name[i],"wrist") == 0  ||
	strcmp(meal_name[i+1],"wrist") == 0))
    {
    strcpy(meal_name[i],"both");
    for (j=i+1; j<TotalMeals-1; j++)
      {
      strcpy(meal_name[j],meal_name[j+1]);
      meal_unixtime[j]=meal_unixtime[j+1];
      meal_year[j]=meal_year[j+1];
      meal_month[j]=meal_month[j+1];
      meal_day[j]=meal_day[j+1];
      meal_hour_start[j]=meal_hour_start[j+1];
      meal_min_start[j]=meal_min_start[j+1];
      meal_hour_end[j]=meal_hour_end[j+1];
      meal_min_end[j]=meal_min_end[j+1];
      meal_delta_ema[j]=meal_delta_ema[j+1];
      meal_delta_match[j]=meal_delta_match[j+1];
      meal_bites[j]=meal_bites[j+1];
      meal_duration[j]=meal_duration[j+1];
      meal_spb[j]=meal_spb[j+1];
      }
    TotalMeals--;
    i--;
    }
  }



	/* calcualte time-delta for each EMA meal to closest wrist meal */
for (i=0; i<TotalMeals; i++)
  meal_has_been_matched[i]=-1;	/* not matched */
	/* two passes -- lapses (or both) first, as they are most important */
for (i=0; i<TotalMeals; i++)
  {
  if (!(strcmp(meal_name[i],"lapse") == 0  ||
	strcmp(meal_name[i],"both") == 0))
    continue;
  closest_delta=9999999;
  closest_index=-1;
  for (j=0; j<TotalMeals; j++)
    {
    if (i == j)
      continue;
    if (strcmp(meal_name[j],"wrist") != 0)
      continue;
    if (meal_has_been_matched[j] != -1)
      continue;
    delta=meal_unixtime[j]-meal_unixtime[i];
    if (abs(delta) < abs(closest_delta))
      {
      closest_delta=delta;
      closest_index=j;
      }
    }
  if (closest_index != -1)
    {
    meal_delta_match[i]=closest_delta;
    meal_has_been_matched[closest_index]=i;	/* wrist pointing to EMA */
    meal_has_been_matched[i]=closest_index;	/* EMA pointing to wrist */
    }
  }
	/* second pass -- match other EMAs (planned) */
for (i=0; i<TotalMeals; i++)
  {
  if (strcmp(meal_name[i],"planned") != 0)
    continue;
  closest_delta=9999999;
  closest_index=-1;
  for (j=0; j<TotalMeals; j++)
    {
    if (i == j)
      continue;
    if (strcmp(meal_name[j],"wrist") != 0)
      continue;
    if (meal_has_been_matched[j] != -1)
      continue;
    delta=meal_unixtime[j]-meal_unixtime[i];
    if (abs(delta) < abs(closest_delta))
      {
      closest_delta=delta;
      closest_index=j;
      }
    }
  if (closest_index != -1)
    {
    meal_delta_match[i]=closest_delta;
    meal_has_been_matched[closest_index]=i;	/* wrist pointing to EMA */
    meal_has_been_matched[i]=closest_index;	/* EMA pointing to wrist */
    }
  }



	/* count number of meals within +- DELTA_W of each EMA meal */
for (i=0; i<TotalMeals; i++)
  {
  for (j=0; j<4; j++)	/* 0...4 => wrist, lapse, planned, both */
    meals_nearby[j][0][i]=meals_nearby[j][1][i]=0; /* 0...1 => prior, after */
  if (strcmp(meal_name[i],"wrist") == 0)
    continue;		/* N/A for wrist meals */
  for (j=0; j<TotalMeals; j++)
    {
    if (i == j)
      continue;	/* do not count same meal */
	/* determine which type of meal; k indicates counter index */
    if (strcmp(meal_name[j],"wrist") == 0)
      k=0;
    else if (strcmp(meal_name[j],"lapse") == 0)
      k=1;
    else if (strcmp(meal_name[j],"planned") == 0)
      k=2;
    else if (strcmp(meal_name[j],"both") == 0)
      k=3;
    else
      {
      printf("Bug?  Unknown type of meal %d => %s\n",j,meal_name[j]);
      exit(0);
      }
	/* determine if delta falls within search window (before or after) */
    delta=meal_unixtime[j]-meal_unixtime[i];
    if (delta < 0  &&  delta >= 0-DELTA_W)
      meals_nearby[k][0][i]++;	/* meal is before */
    if (delta >= 0  &&  delta <= 0+DELTA_W)
      meals_nearby[k][1][i]++;	/* meal is after */
    }
  }



	/* calculate union of date range for EMA and wrist data */
if (span_start_ts[0] < ema_timestamp[0])
  calendar_start=span_start_ts[0];
else
  calendar_start=ema_timestamp[0];
if (span_start_ts[TotalSpans-1] > ema_timestamp[TotalEMA-1])
  calendar_end=span_start_ts[TotalSpans-1];
else
  calendar_end=ema_timestamp[TotalEMA-1];
	/* increment through entire calendar range to calculate daily stats */
TotalCalendarDays=0;
calendar_timestamp[0]=calendar_start;
while (calendar_timestamp[TotalCalendarDays] < calendar_end)
  {
  calendar_ema[TotalCalendarDays]=0;
  DateFromTimestamp(calendar_timestamp[TotalCalendarDays],
	&iyear,&imonth,&iday,&ihour,&iminute,&isecond);
  for (i=0; i<TotalEMA; i++)
    {
    DateFromTimestamp(ema_timestamp[i],
	&eyear,&emonth,&eday,&ehour,&eminute,&esecond);
    if (eyear == iyear  &&  emonth == imonth  &&  eday == iday)
      calendar_ema[TotalCalendarDays]++;
    }
	/* calculate #seconds of day that device was active/rest */
  calendar_wrist_active[TotalCalendarDays]=0;
  calendar_wrist_rest[TotalCalendarDays]=0;
  for (i=0; i<TotalSpans; i++)
    {
    DateFromTimestamp(span_start_ts[i],
	&eyear,&emonth,&eday,&ehour,&eminute,&esecond);
    if (eyear == iyear  &&  emonth == imonth  &&  eday == iday)
      {
      if (span_class[i] == 2)	/* rest class is 2 */
        calendar_wrist_rest[TotalCalendarDays]+=
		(span_end_ts[i]-span_start_ts[i]);
      else
        calendar_wrist_active[TotalCalendarDays]+=
		(span_end_ts[i]-span_start_ts[i]);
      }
    }
	/* calculate #meals (both EMA and wrist) for the day */
  calendar_meal_ema_lapse[TotalCalendarDays]=0;
  calendar_meal_ema_planned[TotalCalendarDays]=0;
  calendar_meal_ema_both[TotalCalendarDays]=0;
  calendar_meal_wrist[TotalCalendarDays]=0;
  for (i=0; i<TotalMeals; i++)
    {
if (0)
printf("looking for %d-%d-%d testing %d-%d-%d\n",iyear,imonth,iday,
	meal_year[i],meal_month[i],meal_day[i]);
	/* must increment imonth and iday by 1 because they range 0...N-1 */
    if (meal_year[i] == iyear  &&  meal_month[i] == imonth+1  &&
	meal_day[i] == iday+1)
      {
      if (strcmp(meal_name[i],"wrist") == 0)
        calendar_meal_wrist[TotalCalendarDays]++;
      else if (strcmp(meal_name[i],"lapse") == 0)
        calendar_meal_ema_lapse[TotalCalendarDays]++;
      else if (strcmp(meal_name[i],"planned") == 0)
        calendar_meal_ema_planned[TotalCalendarDays]++;
      else if (strcmp(meal_name[i],"both") == 0)
        calendar_meal_ema_both[TotalCalendarDays]++;
      }
    }
  TotalCalendarDays++;
  calendar_timestamp[TotalCalendarDays]=
		calendar_timestamp[TotalCalendarDays-1]+86400;
  }


if (1)	/* print out calendar */
  {
  printf("date%cEMA%cw_actv%cw_rest%cl_meal%cp_meal%cb_meal%cw_meal\n",
	SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR);
  for (i=0; i<TotalCalendarDays; i++)
    {
    DateFromTimestamp(calendar_timestamp[i],
	&iyear,&imonth,&iday,&ihour,&iminute,&isecond);
    printf("%d-%d-%d%c%d%c%.2lf%c%.2lf%c%d%c%d%c%d%c%d\n",
	iyear+2000,imonth+1,iday+1,SEPARATOR,
	calendar_ema[i],SEPARATOR,
	(double)(calendar_wrist_active[i])/86400.0,SEPARATOR,
	(double)(calendar_wrist_rest[i])/86400.0,SEPARATOR,
	calendar_meal_ema_lapse[i],SEPARATOR,
	calendar_meal_ema_planned[i],SEPARATOR,
	calendar_meal_ema_both[i],SEPARATOR,
	calendar_meal_wrist[i]);
    }
  }
  


if (1)	/* print out all meals */
  {
  printf("date%cstart%cend%ctype%cd_ema%cd_match%cw_prior%cw_after%cl_prior%cl_after%cp_prior%cp_after%cb_prior%cb_after%cbites%cdur%cspb\n",
	SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR,
	SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR,
	SEPARATOR,SEPARATOR,SEPARATOR,
	SEPARATOR,SEPARATOR,SEPARATOR);
  for (i=0; i<TotalMeals; i++)
    {
    printf("%d-%d-%d%c%02d:%02d%c%02d:%02d%c%s",
	meal_year[i],meal_month[i],meal_day[i],SEPARATOR,
	meal_hour_start[i],meal_min_start[i],SEPARATOR,
	meal_hour_end[i],meal_min_end[i],SEPARATOR,
	meal_name[i]);
    if (strcmp(meal_name[i],"wrist") != 0)
      printf("%c%.1lf%c%.1lf",
	SEPARATOR,(double)(meal_delta_ema[i])/3600.0,
	SEPARATOR,(double)(meal_delta_match[i])/3600.0);
    else
      printf("%cNA%cNA",SEPARATOR,SEPARATOR);
    if (strcmp(meal_name[i],"wrist") != 0)
      printf("%c%d%c%d%c%d%c%d%c%d%c%d%c%d%c%d",
	SEPARATOR,meals_nearby[0][0][i],SEPARATOR,meals_nearby[0][1][i],
	SEPARATOR,meals_nearby[1][0][i],SEPARATOR,meals_nearby[1][1][i],
	SEPARATOR,meals_nearby[2][0][i],SEPARATOR,meals_nearby[2][1][i],
	SEPARATOR,meals_nearby[3][0][i],SEPARATOR,meals_nearby[3][1][i]);
    else
      printf("%cNA%cNA%cNA%cNA%cNA%cNA%cNA%cNA",
	SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR,
	SEPARATOR,SEPARATOR,SEPARATOR,SEPARATOR);
    if (strcmp(meal_name[i],"wrist") == 0)
      printf("%c%d%c%.1lf%c%.1lf\n",
	SEPARATOR,meal_bites[i],
	SEPARATOR,meal_duration[i],
	SEPARATOR,meal_spb[i]);
    else
      printf("%c%d%c%.1lf%c%.1lf\n",
	SEPARATOR,meal_bites[meal_has_been_matched[i]],
	SEPARATOR,meal_duration[meal_has_been_matched[i]],
	SEPARATOR,meal_spb[meal_has_been_matched[i]]);
    }

  }


}
	






	/* convert a seconds-since-Jan1,2000 timestamp into date components */
void DateFromTimestamp(unsigned int timestamp,
                        int     *Year,		  /* 0...256 (can be added to 2000 to get 4-digit year) */
                        int     *Month,		  /* 0...11 */
                        int     *Day,		  /* 0...30 */
                        int     *Hour,		  /* 0...23 */
                        int     *Min,		  /* 0...59 */
                        int     *Sec)		  /* 0...59 */

{
unsigned int    total_seconds;
unsigned int    days_in_month[12]={31,28,31,30,31,30,31,31,30,31,30,31};

total_seconds=timestamp;
*Year=0;
while (total_seconds >= 31536000)
  {
  if ((*Year)%4 == 0)
    {
    if (total_seconds < 31536000+86400)
      break;
    total_seconds-=(31536000+86400);
    }
  else
    total_seconds-=(31536000);
  (*Year)++;
  }
if ((*Year)%4 == 0)
  days_in_month[1]=29;	/* leap year */
*Month=0;
while (total_seconds >= days_in_month[*Month]*86400)
  {
  total_seconds-=(days_in_month[*Month]*86400);
  (*Month)++;
  }
*Day=0;
while (total_seconds >= 86400)
  {
  total_seconds-=(86400);
  (*Day)++;
  }
*Hour=(total_seconds/3600);
total_seconds-=((*Hour)*3600);
*Min=(total_seconds/60);
*Sec=(total_seconds%60);
}



	/* compute the time in seconds, since Jan 1 2000 12:00am */
	/* the month and day are 1-indexed */
int TimeStamp(unsigned char RTCYEARL,		/* 0...256 */
			  unsigned char	RTCMON,			/* 1...12 */
			  unsigned char	RTCDAY,			/* 1...31 */
			  unsigned char	RTCHOUR,		/* 0...23 */
			  unsigned char	RTCMIN,			/* 0...59 */
			  unsigned char	RTCSEC)			/* 0...59 */
{
const int   days[12]={31,28,31,30,31,30,31,31,30,31,30,31};
int         j;
int			elapsed;

elapsed=0;
for (j=0; j<RTCYEARL; j++)
  elapsed+=31536000;
j=(RTCYEARL+3)/4;
elapsed+=(j*86400);
for (j=1; j<RTCMON; j++)
  elapsed+=(days[j-1]*86400);
if (RTCYEARL%4 == 0  &&  RTCMON > 2)
  elapsed+=86400;
elapsed+=((RTCDAY-1)*86400);
elapsed+=(RTCHOUR*3600);
elapsed+=(RTCMIN*60);
elapsed+=RTCSEC;
return(elapsed);
}
















