#!/bin/bash

###
### IDMEASUREMENTS - Calculate timing measurements and graphs for documents not shepherded by ADs
###
### Version 1.0.0
###
### Written in 2008 by Jari Arkko
### Donated to the public domain.
###
### Changelog:
###
### 1.0.0   Initial version from admeasurements
###
### Usage:
###
###   admeasurements [ --doc pattern ] [ --copy ] [ --quiet ] [ --timestamp ]
###

###
### Process arguments
###

THISPROG=$0
DEBUG=0
DOC=all
COPY=0
QUIET=0
RERUN=0
TIMESTAMP=0
PREFFAMILY=IPv6

while [ $# -gt 0 ]
do
  case $1 in
    --doc)       shift;
                 DOC="$1";
                 shift;;
    --timestamp) shift;
                 TIMESTAMP=1;;
    --copy)      shift;
                 COPY=1;;
    --rerun)     shift;
                 RERUN=1;;
    --quiet)     shift;
                 QUIET=1;;
    --debug)     shift;
                 DEBUG=1;;
    --prefer-family=IPv4)
                 shift;
                 PREFFAMILY=IPv4;;
    --prefer-family=IPv6)
                 shift;
                 PREFFAMILY=IPv6;;
    *)           echo 'idmeasurements: Unrecognized argument ('$1') -- exit';
                 exit 1;;
  esac
done

###
### FUNCTION: Common AWK functions
###

COMMONFUNCS='

function draftnameisofficial(d) {
  return(d ~ /^draft-ietf-/ ||
         d ~ /^draft-iab-/ ||
         d ~ /^draft-iesg-/ ||
         d ~ /^draft-irtf-/);
}

function stringtonumericdate(date) {
  split(date,datea,"-");
  year = datea[1] + 0;
  month = datea[2] + 0;
  day = datea[3] + 0;
  return(year + ((month-1+(day-1)/30) / 12.0));
}

function numericdatetostring(num) {
  year = sprintf("%d",num);
  num -= year;
  num *= 12;
  month = sprintf("%d",1 + num);
  num -= (month - 1);
  num *= 30;
  day = sprintf("%d",num);
  return(year "-" month "-" day);
}

function dateminus(d1,days) {
  x = stringtonumericdate(d1);
  #printf("to numeric = %f\n", x);
  x -= days / (12*30);
  #printf("with substraction = %f\n", x);
  return(numericdatetostring(x));
}

function dateyear(d) {
  split(d,d1a,"-");
  return(d1a[1]);
}

function datemonth(d) {
  split(d,d1a,"-");
  return(d1a[2]);
}

function dateyearmonth(d) {
  return(dateyear(d) "-" datemonth(d));
}

function addmonth(d) {
  y = dateyear(d);
  m = datemonth(d);
  if (m == 12) return(sprintf("%04d-%02d",y+1,1));
  else return(sprintf("%04d-%02d",y,m+1));
}

function datelt(d1,d2) {
  split(d1,d1a,"-");
  split(d2,d2a,"-");
  y1 = d1a[1] + 0;
  m1 = d1a[2] + 0;
  d1 = d1a[3] + 0;
  y2 = d2a[1] + 0;
  m2 = d2a[2] + 0;
  d2 = d2a[3] + 0;
  if (y1 < y2) return(1);
  if (y1 > y2) return(0);
  if (m1 < m2) return(1);
  if (m1 > m2) return(0);
  if (d1 < d2) return(1);
  if (d1 > d2) return(0);
  return(0);
}

function datele(d1,d2) {
  split(d1,d1a,"-");
  split(d2,d2a,"-");
  y1 = d1a[1] + 0;
  m1 = d1a[2] + 0;
  d1 = d1a[3] + 0;
  y2 = d2a[1] + 0;
  m2 = d2a[2] + 0;
  d2 = d2a[3] + 0;
  if (y1 < y2) return(1);
  if (y1 > y2) return(0);
  if (m1 < m2) return(1);
  if (m1 > m2) return(0);
  if (d1 < d2) return(1);
  if (d1 > d2) return(0);
  return(1);
}

function daydifference(d1,d2) {
  split(d1,d1a,"-");
  split(d2,d2a,"-");
  y1 = d1a[1] + 0;
  m1 = d1a[2] + 0;
  d1 = d1a[3] + 0;
  u1 = (y1 - 1970) * 365 + m1 * 30 + d1;
  y2 = d2a[1] + 0;
  m2 = d2a[2] + 0;
  d2 = d2a[3] + 0;
  u2 = (y2 - 1970) * 365 + m2 * 30 + d2;
  return(u1 - u2);
}

function html_file_css_head(title,csshtmlfile,slogan) {
  csshtmlfileseensection[csshtmlfile] = 0;
  if (substr(csshtmlfile,1,5) != "/dev/") close(csshtmlfile);
  printf("<!DOCTYPE html PUBLIC %c-//W3C//DTD XHTML 1.0 Transitional//EN%c %chttp://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd%c>\n", 34, 34, 34, 34) > csshtmlfile;
  printf("<html xmlns=%chttp://www.w3.org/1999/xhtml%c xml:lang=%cen%c lang=%cen%c>\n",
         34, 34, 34, 34, 34, 34) >> csshtmlfile;
  printf("<head>\n") >> csshtmlfile;
  printf("<meta http-equiv=%cContent-Type%c content=%ctext/html;charset=utf-8%c />\n",
         34, 34, 34, 34) >> csshtmlfile;
  printf("<link href=%c../admeasurements/admeasurements.css%c rel=%cstylesheet%c type=%ctext/css%c />\n",
         34, 34, 34, 34, 34, 34) >> csshtmlfile;
  printf("<title>%s</title>\n", title) >> csshtmlfile;
  printf("</head>\n") >> csshtmlfile;
  printf("<body>\n") >> csshtmlfile;
  printf("<div class=%cpage%c>\n", 34, 34) >> csshtmlfile;
  printf("<table border=%c0%c width=%c100%%%c>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("<tbody>\n") >> csshtmlfile;
  printf("<tr><td class=%cwglist%c>\n", 34, 34) >> csshtmlfile;
  printf("   <a href=%chttp://tools.ietf.org%c><img class=%clogo%c alt=%cIETF%c src=%chttp://tools.ietf.org/images/ietflogo3h.png%c/></a><br/><br/>\n", 34, 34, 34, 34, 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c><a href=%chttp://www.ietf.org/%c>IETF Home</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c><a href=%chttp://tools.ietf.org/about%c>About Tools</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c><a href=%chttp://tools.ietf.org/dailydose%c>News</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c><a href=%chttp://tools.ietf.org/html/%c>Documents</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <br/>\n") >> csshtmlfile;
  printf("   <div class=%ctopitem%c><a href=%chttp://www.arkko.com/tools/stats.html%c>Statistics</a>:</div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c>&nbsp; &nbsp; <a href=%chttp://www.arkko.com/tools/docstats.html%c>Docs</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c>&nbsp; &nbsp; <a href=%chttp://www.iana.org/about/performance/%c>IANA</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c>&nbsp; &nbsp; <a href=%chttp://www.arkko.com/tools/admeasurements/%c>IESG</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c>&nbsp; &nbsp; <a href=%chttp://www.arkko.com/tools/lifecyclestats.html%c>Lifecycle</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c>&nbsp; &nbsp; <a href=%chttp://www.arkko.com/tools/rfceditorstats.html%c>RFC Ed</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("   <div class=%cmenuitem%c>&nbsp; &nbsp; <a href=%chttp://rtg.ietf.org/~fenner/iesg/%c>Misc</a></div>\n", 34, 34, 34, 34) >> csshtmlfile;
  printf("</td>\n") >> csshtmlfile;
  printf("\n") >> csshtmlfile;
  printf("<td>\n") >> csshtmlfile;
  printf("\n") >> csshtmlfile;
  printf("<div class=%cadmeasurements%c>\n", 34, 34) >> csshtmlfile;
  printf("<div class=%cadmeasurements_banner%c>\n", 34, 34) >> csshtmlfile;
  printf("<h1>%s</h1>\n", title) >> csshtmlfile;
  printf("\n") >> csshtmlfile;
  printf("<div class=%cadmeasurements_slogan%c>\n", 34, 34) >> csshtmlfile;
  printf("&#8220;%s&#8221;\n", slogan) >> csshtmlfile;
  printf("</div><!-- admeasurements_slogan -->\n") >> csshtmlfile;
  printf("\n") >> csshtmlfile;
  printf("</div><!-- admeasurements_banner -->\n") >> csshtmlfile;
  printf("</div><!-- admeasurements -->\n") >> csshtmlfile;
  printf("\n") >> csshtmlfile;
  printf("<div class=%cadmeasurements%c>\n", 34, 34) >> csshtmlfile;
  printf("\n") >> csshtmlfile;
  printf("<table class=%cadmeasurements_columns%c>\n", 34, 34) >> csshtmlfile;
  printf("<tbody>\n") >> csshtmlfile;
  printf("<tr>\n") >> csshtmlfile;
  printf("<td class=%cadmeasurements_topic%c>\n", 34, 34) >> csshtmlfile;
}

function html_file_css_section(title,csshtmlfile) {
  if (csshtmlfileseensection[csshtmlfile] != 0) {
    printf("\n<div style=%cclear:both;padding:1px;%c></div>\n", 34, 34) >> csshtmlfile;
  }

  csshtmlfileseensection[csshtmlfile] = 1;

  printf("\n<h2>%s</h2>\n\n", title) >> csshtmlfile;
}

function html_file_css_section_nextcol(title,csshtmlfile) {
  csshtmlfileseensection[csshtmlfile] = 1;
  printf("\n</td>\n\n<td class=%cadmeasurements_topic%c>\n", 34, 34) >> csshtmlfile;
  printf("\n<h2>%s</h2>\n\n", title) >> csshtmlfile;
}

function html_file_css_end(htmlfile) {
  printf("</td>\n") >> htmlfile;
  printf("</tr>\n") >> htmlfile;
  printf("</tbody>\n") >> htmlfile;
  printf("</table><!-- admeasurements_columns -->\n") >> htmlfile;
  printf("</div><!-- admeasurements -->\n") >> htmlfile;
  printf("</td>\n") >> htmlfile;
  printf("</tr>\n") >> htmlfile;
  printf("</tbody>\n") >> htmlfile;
  printf("</table><!-- page -->\n") >> htmlfile;
  printf("</div><!-- page -->\n") >> htmlfile;
  printf("</body>\n") >> htmlfile;
  printf("</html>\n") >> htmlfile;
  close(htmlfile);
}

function plottojpg(file,epsfile,jpgfile) {
  system("gnuplot < " file);
  cmd = "convert " epsfile " " jpgfile;
  system(cmd);
}
'

###
### URLs
###

ADDRAFTDATABASEURL=http://arkko.com/tools/admeasurements/adwork.txt
ALLIDURL=http://www.ietf.org/internet-drafts/all_id.txt

###
### Initialize
###

CURYEAR=`date +%Y`
CURMON=`date +%m`
CURDAY=`date +%d`
tmpdir=/tmp/idm_tmp
if [ $RERUN = 0 ]
then
  rm -rf $tmpdir
  mkdir $tmpdir
fi
cd $tmpdir
WGETOPTS="--prefer-family="$PREFFAMILY" -q"
export WGETOPTS

if [ $TIMESTAMP = 1 ]
then
  echo 'Running idmeasurements on '`date`'...'
fi

###
### Fetch database
###

if [ $RERUN = 0 ]
then

if wget $WGETOPTS -O adwork.txt $ADDRAFTDATABASEURL
then
  nop=nop
else
  echo 'idmeasurements: cannot access '$ADDRAFTDATABASEURL' - exit'
  exit 1
fi

fi

###
### Find out the timing of drafts not yet in AD processing
###

if [ $RERUN = 0 ]
then

if [ $QUIET = 0 ]
then
  echo Finding out drafts not handled by ADs...
fi

if wget $WGETOPTS -O all_id.txt $ALLIDURL
then
  nop=nop
else
  echo 'admeasurements: Cannot retrieve all_id.txt -- continuing...'
  touch all_id.txt
fi
grep '^draft-[0-9a-zA-Z]' all_id.txt |
egrep '(Expired)|(Active)' |
cut -f1 -d'	' |
cut -f1 -d' ' |
sed 's/-[0-9][0-9]$//' |
(if [ $DOC = all ]
 then
   cat
 else
   grep "$DOC"
fi) |
sort -u > all_id_list.txt
cut -f6 -d: adwork.txt | sort -u > ad_id_list.txt
join -v 1 all_id_list.txt ad_id_list.txt > nonad_id_list.txt

if [ $QUIET = 0 ]
then
  echo Calculating timing for drafts not handled by ADs...
fi

awk -v now=`date +%Y-%m-%d` \
    -v curyear=$CURYEAR -v curmonth=$CURMON -v curday=$CURDAY \
    -v debug=$DEBUG \
    -v preffamily=$PREFFAMILY \
'
'"$COMMONFUNCS"'

function startdoctable(name,htmlf) {
  printf("<!DOCTYPE HTML PUBLIC %c-//W3C//DTD HTML 4.01 Transitional//EN%c>\n", 34, 34) >> htmlf;
  printf("<html><head>\n") >> htmlf;
  html_file_css_head("Document Processing Time Details for " name,htmlf, "End-to-End Delay from draft-smith to an RFC");
  html_file_css_section("Document Timeline",htmlf);
  printf("<img src=%c%s-timeline.jpg%c style=%cborder:0%c alt=%ctimeline%c>\n",
         34, name, 34, 34, 34, 34, 34) >> htmlf;
}

function addarg(c,a) {
  return(sprintf("%s %c%s%c",c,34,a,34));
}

function generate_timeline(draftname,jpgfile,
                           initialindividualsubmission,diff1,indname,
                           initialsubmission,diff2,
                           firstiesgstate,totaldays,
                           firstapprov,diff3,
                           firstpub) {
  cmd = "drafttimeline";
  cmd = addarg(cmd,"--versions");
  cmd = addarg(cmd,"--prefer-family=" preffamily);
  cmd = addarg(cmd,draftname);
  cmd = addarg(cmd,jpgfile);
  cmd = addarg(cmd,initialindividualsubmission);
  cmd = addarg(cmd,diff1);
  cmd = addarg(cmd,indname);
  cmd = addarg(cmd,initialsubmission);
  cmd = addarg(cmd,diff2);
  cmd = addarg(cmd,firstiesgstate);
  cmd = addarg(cmd,totaldays);
  cmd = addarg(cmd,firstapprov);
  cmd = addarg(cmd,diff3);
  cmd = addarg(cmd,firstpub);
  system(cmd);
}

BEGIN {
  if (debug) printf("idmeasurements: debug: begin\n") >> "/dev/stderr";
  disclaimer = "<p>";
  disclaimer = disclaimer sprintf("Statistics run taken %d.%d.%d by the ", curday, curmonth, curyear);
  disclaimer = disclaimer sprintf("<a href=%chttp://www.arkko.com/tools/idmeasurements.html%c>idmeasurements</a>.", 34, 34);
  disclaimer = disclaimer "</p>\n";
}

/^draft/ {

  name = $1;

  #
  # Create html file
  #

  htmlfile = name "-timing.html";
  if (debug) printf("idmeasurements: debug: processing %s to %s\n", name, htmlfile) >> "/dev/stderr";
  startdoctable(name,htmlfile);
  
  #
  # Figure out when the initial submissions etc were
  #

  agefile = name ".age";
  system("docage --expires --prefer-family=" preffamily " " name " > " agefile);
  agereplacesfile = name ".replaces-age";
  system("docage --replaces --prefer-family=" preffamily " " name " > " agereplacesfile);
  initialsubmission = "";
  getline initialsubmission < agefile;
  getline expiration < agefile;
  if (debug) printf("idmeasurements: age entry %s: %s, %s\n", name, initialsubmission, expiration) >> "/dev/stderr";
  close(agefile);
  if (initialsubmission == "") {
    printf("# docage problem with %s -- skipping\n", name);
    next;
  } else {
    initialindividualsubmission = "";
    initialindividualsubmissionline = "";
    getline initialindividualsubmissionline < agereplacesfile;
    close(agereplacesfile);
    split(initialindividualsubmissionline,comps,":");
    initialindividualsubmission = comps[1];
    indname = comps[2];
    if (expiration == "none") {
      lastdayforthisdraft = now;
    } else {
      lastdayforthisdraft = expiration;
    }
    if (initialsubmission != "none") {
      diff2 = daydifference(lastdayforthisdraft,initialsubmission)
    } else {
      diff2 = 0;
    }
    if (initialindividualsubmission != "" && initialsubmission != "none") {
      diff1 = daydifference(initialsubmission,initialindividualsubmission);
      if (diff1 < 0) {
        printf("warning:submission earlier than individual document submission in %s\n", name);
        diff1 = 30;
        initialindividualsubmission = dateminus(initialsubmission,30);
      }
    } else if (initialindividualsubmission != "none") {
      diff1 = daydifference(lastdayforthisdraft,initialindividualsubmission)
    } else {
      diff1 = 0;
    }
  
    #
    # Print draft-timing-nonad.txt entry
    #
  
    if (debug) printf("idmeasurements: debug: timing entry\n") >> "/dev/stderr";
    printf("timing:%s:%s:%s:%d:%d:%d:%d:%d:%d:%s:%d:%s:%s:%d:%s:%d\n",
           name, "none", "none",
           0, 0, 0, 0,
           0, 0, initialindividualsubmission, diff1, indname, initialsubmission, diff2, "none", 0);
    
    #
    # Generate timeline graph
    #
  
    if (debug) printf("idmeasurements: debug: timeline\n") >> "/dev/stderr";
    generate_timeline(name,name "-timeline.jpg",
                      initialindividualsubmission,diff1,indname,
                      initialsubmission,diff2,
                      "none",0,
                      "none",0,
                      expiration == "none" ? "none" : "(expired)");
  
    #
    # Print rest of the html
    #
  
    if (debug) printf("idmeasurements: debug: html %s\n", htmlfile) >> "/dev/stderr";
    html_file_css_section("IESG Processing Time Statistics",htmlfile);
    printf("<p>The document has not been received by the AD/IESG yet, no timing calculated.\n") >> htmlfile;
    html_file_css_section("Overall Processing Time Statistics",htmlfile);
    printf("<p>Document was in individual and WG process for %d days, ",
           diff1 + diff2) >> htmlfile;
    printf("and in IESG/RFC Editor process for %d days, %d days in total. ",
           0, 0) >> htmlfile;
    torfc = diff1 + diff2;
    printf("This is %d years and %d months.</p>\n",
           torfc / 365, (torfc % 365) / 30) >> htmlfile;
    if (expiration != "none") {
      printf("<p>Draft expired on %s.</p>\n", expiration) >> htmlfile;
    }
    html_file_css_section("Data Source and Freshness",htmlfile);
    printf("<p>%s</p>\n", disclaimer) >> htmlfile;
  
    #
    # Done! Finish the html file
    #
  
    if (debug) printf("idmeasurements: debug: end of html %s\n", htmlfile) >> "/dev/stderr";
    html_file_css_end(htmlfile);
    if (debug) printf("idmeasurements: debug: done with %s\n", htmlfile) >> "/dev/stderr";
    next;
  }
}

END {
  if (debug) printf("idmeasurements: debug: end\n") >> "/dev/stderr";
}
' < nonad_id_list.txt > draft-timing-nonad.txt

fi

###
### Copy
###

if [ $COPY = 1 ]
then

  if [ $QUIET = 0 ]
  then
    echo 'Copying...'
  fi

  SCPOPTS=-q

  scp $SCPOPTS \
      /home/jar/LME/IETF/Tools/idmeasurements.html \
      $THISPROG \
      jarkko@users.piuha.net:public_html/tools/
  scp $SCPOPTS \
      draft-timing-nonad.txt \
      jarkko@users.piuha.net:public_html/tools/admeasurements
  for alpha in a b c d e f g h i j k l m o p q r s t u v w x y z
  do
    scp $SCPOPTS \
        draft-${alpha}*.jpg \
        jarkko@users.piuha.net:public_html/tools/lifecycle
    scp $SCPOPTS \
        draft-${alpha}*.html \
        jarkko@users.piuha.net:public_html/tools/lifecycle
  done
fi

###
### Cleanup
###

exit 0
