#! /usr/bin/gawk -f
# Last edited on 2013-11-30 05:00:33 by stolfilocal

BEGIN { 
  # Reads the hand-entered blink location file, performs consistency checks, 
  # outputs cleaned up file.
  
  # Input file has one line per run, with fields 
  #   
  #   {SUBJID} {RUNID} {FLAG}  {TINI[0]} {TFIN[0]}  {TINI[1]} {TFIN[1]} ... {TINI[nb-1]} {TFIN[nb-1]} 
  #
  # where {FLAG} is "-" (normal run) or "*" (weird run), {TINI[k]} and
  # {TFIN[k]} are starting and ending times of blink number {k} in the run
  # (in seconds, relative to the start of the run). 
  
  # Output has one line per blink in the format
  #   
  #   {SUBJID} {RUNID} {NFLAG} {K} {TINI[K]} {TFIN[K]}
  #   
  # where {NFLAG} is 0 if {FLAG} is "-", 1 if the {FLAG} is "*"
  
  # Argument {trun} is the total run length in seconds:
  if (trun == "") { arg_error(("must define {trun}")); }
  
  abort = -1;
  
  nruns = 0;   # Number of runs processed.
  nblinks = 0; # Total number of blinks.

  nruns_ok = 0;   # Number of unflagged runs.
  blinks_ok = 0;  # Total number of blinks in unflagged runs.
}

(abort >= 0) { exit(abort); }

# Remove comments: 
// {
  gsub(/[ ]*[#].*$/, "", $0);
}

# Skip blank lines:
/^[ ]*$/ { 
  next;
}

# process data lines:
/^[ ]*[0-9]+[ ]+[0-9]+[ ]+[-*]([ ]+|$)/ {
  if (NF < 3) { data_error(("wrong number of fields")); }
  subjid = $1;
  runid = $2;
  flag = $3;
  nb = int((NF-3)/2); # Number of blinks in run.
  if (NF != 2*nb + 3) { data_error(("invalid number of fields")); }
  tini_min = -0.4;  # Min time of next blink.
  tini_max = trun - 0.1;  # Max time to start a blink.
  for (k = 0; k < nb; k++) 
    { tini = process_time($(2*k+4), ("tini[" k "]"), tini_min, tini_max);
      tfin_min = tini + 0.1;  # Min time of end of blink.
      tfin_max = tini + 0.8;  # Max time of next blink.
      if (tfin_max > trun + 0.4) { tfin_max = trun + 0.4; }
      tfin = process_time($(2*k+5), ("tfin[" k "]"), tfin_min, tfin_max);
      process_blink(subjid,runid,flag,k,tini,tfin);
      tini_min = tfin + 0.09;
      nblinks++;
      if (flag == "-") { nblinks_ok++; }
    }
  nruns++;
  if (flag == "-") { nruns_ok++; }
  next;
}

# Anything else:
// { 
  data_error(("invalid line format"));
}

END {
  if (abort >= 0) { exit(abort); }
  printf "%d blinks in %d runs (%.2f blinks/run)\n", nblinks, nruns, nblinks/nruns > "/dev/stderr";
  printf "%d blinks in %d unflagged runs (%.2f blinks/run)\n", nblinks_ok, nruns_ok, nblinks_ok/nruns_ok > "/dev/stderr";
}

function process_time(t, name, tmin, tmax) { 
  if (t !~ /^[-+]?[0-9]+([.][0-9]+|)$/) { data_error(("invalid field " name " = \"" t "\"")); }
  t = t + 0.0;
  if ((t < tmin) || (t > tmax)) { data_error(("field " name " = " t " out of range [" tmin " _ " tmax "]")); }
  return t;
}

function process_blink(subjid,runid,flag,k,tini,tfin) {
  printf "%s %s %s %2d", subjid, runid, (flag == "-" ? 0 : 1), k;
  printf " %7.2f %7.2f\n", tini-0.04, tfin+0.04;
}

function arg_error(msg) {
  printf "** %s\n", msg > "/dev/stderr";
  abort = 1;
  exit(1);
}

function data_error(msg) {
  printf "  «%s»\n", $0 > "/dev/stderr";
  printf "%s:%d: ** %s\n", FILENAME, FNR, msg > "/dev/stderr";
  abort = 1;
  exit(1);
}