#!/bin/sh
# Copyright 1999-2002 Carnegie Mellon University.  
# Portions Copyright 2002 Sun Microsystems, Inc.  
# Portions Copyright 2002 Mitsubishi ElectricResearch Laboratories.
# All Rights Reserved.  Use is subject to license terms.
# 
# See the file "license.terms" for information on usage and
# redistribution of this file, and for a DISCLAIMER OF ALL 
# WARRANTIES.
#
# This script parses the regression log and outputs an HTML summary
#
# usage: makeWebpage < regression.log
#
# Field definitions: 
#   1) "test"
#   2) date
#   3) time
#   4) machine
#   5) System
#   6) testName 
#   7) who 
#   8) status
#   9) audioTime 
#  10) procTime 
#  11) words 
#  12) insertions 
#  13) deletions 
#  14) substitutions 
#  15) sentences 
#  16) correctSentences 
#  17) heapSize 
#  18) loadAverage 
#  19) actualUtterances
#  20) foundUtterances
#  21) gapInsertions
#  22) averageResponseTime
#  23) maxResponseTime
#  24) minResponseTime
#  25) correctOutOfGrammar
#  26) falseOutOfGrammar
#  27) correctInGrammar
#  28) falseInGrammar

gawk '

BEGIN {
    FS = "|"
    F_TEST = 1;
    F_DATE = 2;
    F_TIME = 3;
    F_MACHINE = 4;
    F_SYSTEM = 5;
    F_TEST_NAME = 6;
    F_WHO = 7;
    F_STATUS = 8;
    F_AUDIO_TIME = 9;
    F_PROC_TIME = 10;
    F_WORDS = 11;
    F_INSERTIONS = 12;
    F_DELETIONS = 13;
    F_SUBSTITUTIONS = 14;
    F_SENTENCES = 15;
    F_CORRECT_SENTENCES = 16;
    F_HEAP_SIZE = 17;
    F_LOAD_AVERAGE = 18;
    F_ACTUAL_UTTERANCES = 19;
    F_FOUND_UTTERANCES = 20;
    F_GAP_INSERTIONS = 21;
    F_AVG_RESPONSE_TIME = 22;
    F_MAX_RESPONSE_TIME = 23;
    F_MIN_RESPONSE_TIME = 24;
    F_CORRECT_OOG = 25;
    F_FALSE_OOG = 26;
    F_CORRECT_IG = 27;
    F_FALSE_IG = 28;
    "./getHostname" | getline machine
}

$1 == "environment" && $3 == machine {
    environment = $0;
}

$1 == "build" && $4 == machine {
    buildCount = buildCount + 1;
    buildData[buildCount] = $0;
    testEnv[buildCount] = environment;
}


$1 == "test"  && $4 == machine && $5 == "s4" {
    testCount[$F_TEST_NAME] = testCount[$F_TEST_NAME] + 1;
    testData[$F_TEST_NAME testCount[$F_TEST_NAME]] = $0;
    if (lastTestDate != $F_DATE) {
        lastTestDate = $F_DATE;
	lastTestCount = 0;
    } 
    lastTestData[lastTestCount++] = $F_TEST_NAME "|" testCount[$F_TEST_NAME];
}


$1 == "live_test" && $4 == machine && $5 == "s4" {
    liveTestCount[$F_TEST_NAME] = liveTestCount[$F_TEST_NAME] + 1;
    testData[$F_TEST_NAME liveTestCount[$F_TEST_NAME]] = $0;
    if (lastLiveTestDate != $F_DATE) {
	lastLiveTestDate = $F_DATE;
	lastLiveTestCount = 0;
    }
    lastLiveTestData[lastLiveTestCount++] = $F_TEST_NAME "|" liveTestCount[$F_TEST_NAME];
}


$1 == "rejection_test" && $4 == machine && $5 == "s4" {
    rejectionTestCount[$F_TEST_NAME] = rejectionTestCount[$F_TEST_NAME] + 1;
    testData[$F_TEST_NAME rejectionTestCount[$F_TEST_NAME]] = $0;
    if (lastRejectionTestDate != $F_DATE) {
	lastRejectionTestDate = $F_DATE;
	lastRejectionTestCount = 0;
    }
    lastRejectionTestData[lastRejectionTestCount++] = $F_TEST_NAME "|" rejectionTestCount[$F_TEST_NAME];
}


$1 == "system"  && $2 == machine {
    machineDescription = $0;
}

$1 == "metrics"   {
    metrics = $0;
}

function dateAnchor(date) {
    return "<a href=\"./cgi-bin/whatsNew?"date"\">" date "</a>";
}

#####
# updates the data array with info for the given test
#
function updateData(testName, testCount) {
    split(testData[testName testCount], data);
}

####
# returns the word error rate for the given test
#
function getWER(testName, testCount, _errors, _words) {
    updateData(testName, testCount);
    _errors = data[F_INSERTIONS] + data[F_DELETIONS] + data[F_SUBSTITUTIONS];
    _words = data[F_WORDS];

    if (_words == "" || _words == 0) {
        return "N/A";
    } else {
	return _errors / _words * 100;
    }
}

####
# returns the rejection accuracy for the given test
#
function getRejectionAccuracy(testName, testCount) {
    updateData(testName, testCount);
    ra = (data[F_CORRECT_OOG] + data[F_CORRECT_IG]);
    if (ra == "" || ra == 0) {
	return "N/A";
    } else {    
	return (ra * 100 / data[F_SENTENCES]);
    }
}

####
# gets the speed for the given test
#
function getSpeed(testName, testCount, _audioTime, _procTime) {
    updateData(testName, testCount);
    _audioTime = data[F_AUDIO_TIME];
    _procTime = data[F_PROC_TIME];

    if (_audioTime == "" || _procTime == "" || _audioTime == 0 || _procTime == 0) {
        return "N/A";
    } else {
	return _procTime / _audioTime;
    }
}

####
# gets the average heap size
#
function getHeap(testName, testCount) {
    updateData(testName, testCount);

# print "Data " testData[testName testCount]

    if (data[F_HEAP_SIZE] == "") {
        return "N/A";
    } else {
	return data[F_HEAP_SIZE];
    }
}

## Finds the last reported WER

function getLastGoodWER(testName, count, wer) {
    do {
      wer = getWER(testName, count);
      count--;
    } while (count > 0 && wer == "N/A");
    return wer;
}

function getLastGoodRejectionAccuracy(testName, count, ra) {
    do {
	ra = getRejectionAccuracy(testName, count);
	count--;
    } while (count > 0 && ra == "N/A");
    return ra;
}

####
# returns the accuracy status for the given test
#
function getAccuracyStatus(testName, count) {
  thisWER = getWER(testName, count);
  prevWER = getLastGoodWER(testName, count - 1);
  return getLessIsBetterMetricStatus(thisWER, prevWER);
}

####
# returns the rejection accuracy status for the given test
#
function getRejectionAccuracyStatus(testName, count) {
    thisRA = getRejectionAccuracy(testName, count);
    prevRA = getLastGoodRejectionAccuracy(testName, count-1);
    return getMoreIsBetterMetricStatus(thisRA, prevRA);
}


## Finds the last reported speed

function getLastGoodSpeed(testName, count,  speed) {
    # print "in last good speed";
    do {
      speed = getSpeed(testName, count);
      count--;
     #  print "    Lgs ", speed, testName, count, "\n";
    } while (count > 0 && speed == "N/A");
    # printf("out last good speed %d [%s]\n", count, speed);
    return speed;
}

####
# returns the speed status for the given test
#
function getSpeedStatus(testName, count, _slowThreshold, _fastThreshold) {
  thisSpeed = getSpeed(testName, count);
  prevSpeed = getLastGoodSpeed(testName, count - 1);
  return getLessIsBetterThresholdMetricStatus(thisSpeed, prevSpeed, 0.1);
}

####
# returns the heap average for the given test
#
function getHeapStatus(testName, count, _minThreshold, _maxThreshold) {
  thisHeap = getHeap(testName, count);
  prevHeap = getHeap(testName, count - 1);
  return getLessIsBetterThresholdMetricStatus(thisHeap, prevHeap, 0.1);
}

####
# return the status of the test
#
function getRunStatus(testName, count) {
    updateData(testName, count);
    status = data[F_STATUS];

    if (status == "OK") {
      return "<td>" status "</td>";
    } else {
      return "<td bgcolor=#ffcccc>" status "</td>";
    }
}


####
# return the status of gap insertion rate
#
function getGapInsertionRateStatus(testName, testCount) {
    thisGapRate = getGapInsertionRate(testName, testCount);
    prevGapRate = getGapInsertionRate(testName, testCount - 1);
    return getLessIsBetterMetricStatus(thisGapRate, prevGapRate);
}

function getGapInsertionRate(testName, testCount) {
    gapInsertion = "N/A";
    updateData(testName, testCount);
    gapInsertion = data[F_GAP_INSERTIONS];
    totalWords = data[F_WORDS];
    if (gapInsertion == "") {
	gapInsertion = "N/A";
    } else if (totalWords > 0) {
	gapInsertion = (gapInsertion / totalWords) * 100;
    }
    return gapInsertion;
}


####
# return the status of utterance ratio
#
function getUtteranceRatioStatus(testName, testCount) {
    thisRatio = getUtteranceRatio(testName, testCount);
    prevRatio = getUtteranceRatio(testName, testCount - 1);

    if (thisRatio == "N/A") {
	return "<td bgcolor=#ffcccc>" thisRatio "</td>";
    }
    if (prevRatio == "N/A") {
	return "<td>" thisRatio "</td>";
    }
    
    thisDistFromOne = distFromOne(thisRatio);
    prevDistFromOne = distFromOne(prevRatio);

    if (thisDistFromOne > prevDistFromOne) {
	return "<td bgcolor=#ffcccc>" thisRatio "</td>";
    }
    if (thisDistFromOne < prevDistFromOne) {
	return "<td bgcolor=#99ff99>" thisRatio "</td>";
    }
    return "<td>" thisRatio "</td>";
}

function getUtteranceRatio(testName, testCount) {
    ratio = "N/A";
    updateData(testName, testCount);
    actualUtterances = data[F_ACTUAL_UTTERANCES];
    foundUtterances = data[F_FOUND_UTTERANCES];
    if (actualUtterances > 0) {
        ratio = foundUtterances / actualUtterances;
    }
    return ratio;
}

function distFromOne(x) {
    dist = x - 1.0;
    if (dist >= 0) {
	return dist;
    } else if (dist < 0) {
	return -dist;
    }
}
	

####
# return the status of average response time
#
function getAvgResponseTimeStatus(testName, testCount) {
    thisAvgTime = getResponseTime(testName, testCount, F_AVG_RESPONSE_TIME);
    prevAvgTime = getResponseTime(testName, testCount-1, F_AVG_RESPONSE_TIME);
    return getLessIsBetterThresholdMetricStatus(thisAvgTime, prevAvgTime, 0.1);
}


function getMaxResponseTimeStatus(testName, testCount) {
    thisMaxTime = getResponseTime(testName, testCount, F_MAX_RESPONSE_TIME);
    prevMaxTime = getResponseTime(testName, testCount-1, F_MAX_RESPONSE_TIME);
    return getLessIsBetterThresholdMetricStatus(thisMaxTime, prevMaxTime, 0.1);
}


function getMinResponseTimeStatus(testName, testCount) {
    thisMinTime = getResponseTime(testName, testCount, F_MIN_RESPONSE_TIME);
    prevMinTime = getResponseTime(testName, testCount-1, F_MIN_RESPONSE_TIME);
    return getLessIsBetterThresholdMetricStatus(thisMinTime, prevMinTime, 0.1);
}

function getResponseTime(testName, testCount, INDEX) {
    responseTime = "N/A";
    updateData(testName, testCount);
    responseTime = data[INDEX];
    if (responseTime == "") {
	responseTime = "N/A";
    }
    return responseTime;
}

function getMoreIsBetterMetricStatus(thisMetric, prevMetric) {
    if (thisMetric == "N/A") {
	return "<td bgcolor=#ffcccc>" "N/A" "</td>";
    }
    if (prevMetric == "N/A") {
	return "<td>" thisMetric"</td>";
    }
    if (thisMetric < prevMetric) {
	return "<td bgcolor=#ffcccc>" thisMetric "</td>";
    }
    if (thisMetric > prevMetric) {
	return "<td bgcolor=#99ff99>" thisMetric "</td>";
    }
    return "<td>" thisMetric "</td>";
}

function getLessIsBetterMetricStatus(thisMetric, prevMetric) {
    if (thisMetric == "N/A") {
	return "<td bgcolor=#ffcccc>" "N/A" "</td>";
    }
    if (prevMetric == "N/A") {
	return "<td>" thisMetric"</td>";
    }
    if (thisMetric > prevMetric) {
	return "<td bgcolor=#ffcccc>" thisMetric "</td>";
    }
    if (thisMetric < prevMetric) {
	return "<td bgcolor=#99ff99>" thisMetric "</td>";
    }
    return "<td>" thisMetric "</td>";
}

function getLessIsBetterThresholdMetricStatus(thisMetric, prevMetric, threshold) {
    if (thisMetric == "N/A") {
	return "<td bgcolor=#ffcccc>" "N/A" "</td>";
    }
    if (prevMetric == "N/A") {
	return "<td>" thisMetric"</td>";
    }
    prevMetricPlusTenPercent = prevMetric * (1.0 + threshold);
    prevMetricMinusTenPercent = prevMetric * (1.0 - threshold);

    if (thisMetric > prevMetricPlusTenPercent) {
	return "<td bgcolor=#ffcccc>" thisMetric "</td>";
    }
    if (thisMetric < prevMetricMinusTenPercent) {
	return "<td bgcolor=#99ff99>" thisMetric "</td>";
    }
    return "<td>" thisMetric "</td>";
}


function printSingleTest(testName, testCount) {
    updateData(testName, testCount);
    date = data[F_DATE];
    runTime = data[F_PROC_TIME];
    status = getRunStatus(testName, testCount);
    accuracy = getAccuracyStatus(testName, testCount);
    speed = getSpeedStatus(testName, testCount);
    heap = getHeapStatus(testName, testCount);
    print "<tr>"
    print "<td>" dateAnchor(date)  "</td>"
    print status;
    print accuracy;
    print speed;
    print heap;
    print "<td>" fmtTime(runTime)"</td>";
    print "</tr>"
}


function printSingleLiveTest(testName, testCount) {
    updateData(testName, testCount);
    date = data[F_DATE];
    runTime = data[F_PROC_TIME];
    status = getRunStatus(testName, testCount);
    accuracy = getAccuracyStatus(testName, testCount);
    speed = getSpeedStatus(testName, testCount);
    heap = getHeapStatus(testName, testCount);
    gapInsertion = getGapInsertionRateStatus(testName, testCount);
    utteranceRatio = getUtteranceRatioStatus(testName, testCount);
    avgResponseTime = getAvgResponseTimeStatus(testName, testCount);
    maxResponseTime = getMaxResponseTimeStatus(testName, testCount);
    minResponseTime = getMinResponseTimeStatus(testName, testCount);

    print "<tr>"
    print "<td>" dateAnchor(date)  "</td>"
    print status;
    print accuracy;
    print speed;
    print heap;
    print "<td>" fmtTime(runTime)"</td>";
    print gapInsertion;
    print utteranceRatio;
    print avgResponseTime;
    print minResponseTime;
    print maxResponseTime;
    print "</tr>"
}


function printSingleRejectionTest(testName, testCount) {
    updateData(testName, testCount);
    date = data[F_DATE];
    runTime = data[F_PROC_TIME];
    status = getRunStatus(testName, testCount);
    rejection = getRejectionAccuracyStatus(testName, testCount);
    speed = getSpeedStatus(testName, testCount);
    heap = getHeapStatus(testName, testCount);
    print "<tr>"
    print "<td>" dateAnchor(date)  "</td>"
    print status;
    print rejection;
    print speed;
    print heap;
    print "<td>" fmtTime(runTime)"</td>";
    print "</tr>"
}


function printLongSingleTest(testName, testCount) {
    updateData(testName, testCount);
    date = data[F_DATE];
    status = getRunStatus(testName, testCount);
    accuracy = getAccuracyStatus(testName, testCount);
    speed = getSpeedStatus(testName, testCount);
    heap = getHeapStatus(testName, testCount);
    print "<tr>";
    print "<td>" dateAnchor(date)  "</td>";
    print "<td><a href=#" testName ">" testName  "</a></td>";
    print status;
    print accuracy;
    print speed;
    print heap;
    print "</tr>";
}


function printLongSingleLiveTest(testName, testCount) {

    updateData(testName, testCount);
    date = data[F_DATE];
    status = getRunStatus(testName, testCount);
    accuracy = getAccuracyStatus(testName, testCount);
    speed = getSpeedStatus(testName, testCount);
    heap = getHeapStatus(testName, testCount);
    gapInsertion = getGapInsertionRateStatus(testName, testCount);
    utteranceRatio = getUtteranceRatioStatus(testName, testCount);
    avgResponseTime = getAvgResponseTimeStatus(testName, testCount);

    print "<tr>";
    print "<td>" dateAnchor(date)  "</td>";
    print "<td><a href=#" testName ">" testName  "</a></td>";
    print status;
    print accuracy;
    print speed;
    print heap;
    print gapInsertion;
    print utteranceRatio;
    print avgResponseTime;
    print "</tr>";
}


function printLongSingleRejectionTest(testName, testCount) {
    updateData(testName, testCount);
    date = data[F_DATE];
    status = getRunStatus(testName, testCount);
    rejectionAccuracy = getRejectionAccuracyStatus(testName, testCount);
    speed = getSpeedStatus(testName, testCount);
    heap = getHeapStatus(testName, testCount);
    print "<tr>";
    print "<td>" dateAnchor(date)  "</td>";
    print "<td><a href=#" testName ">" testName  "</a></td>";
    print status;
    print rejectionAccuracy;
    print speed;
    print heap;
    print "</tr>";
}


function fmtTime(seconds) {
    if (seconds == "N/A") {
	return seconds;
    }
    hours = int(seconds / 3600);
    seconds -= hours * 3600;

    mins = int(seconds / 60);
    seconds -= mins * 60;

    return sprintf("%02.2d:%02.2d:%02.2d", hours, mins, seconds);
}

function printTestResults(testName) {
    print("<br><br>");
    print("<a name=" testName "></a>");
    print "<table align=center cellpadding=2 cellspacing=2 border=1 width=60%>";
    print "<tbody>";
    print "<tr align=center>";
    print "<td valign=top rowspan=1 colspan=6 bgcolor=#ccccff>";
    print "<big><b>" testName "</b></big>";
    print "<br>"
    print "</td>";
    print "</tr>";
    print "<tr>";
    print "<td valign=top bgcolor=#ccffff><b>Date<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Run Status<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Word Error Rate<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Time (X Realtime)<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Avg Heap (MB)<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Test Time<br> </b></td>";
    
    for (i = 1; i <= testCount[testName]; i++) {
	printSingleTest(testName, i);
    }
    print "</tr>";
    print "<tbody>";
    print "</table>";
    print "<br>";
}


function printLiveTestResults(testName) {
    print("<br><br>");
    print("<a name=" testName "></a>");
    print "<table align=center cellpadding=2 cellspacing=2 border=1 width=60%>";
    print "<tbody>";
    print "<tr align=center>";
    print "<td valign=top rowspan=1 colspan=11 bgcolor=#ccccff>";
    print "<big><b>" testName "</b></big>";
    print "<br>"
    print "</td>";
    print "</tr>";
    print "<tr>";
    print "<td valign=top rowspan=2 bgcolor=#ccffff><b>Date<br> </b></td>";
    print "<td valign=top rowspan=2 bgcolor=#ccffff><b>Run Status<br> </b></td>";
    print "<td valign=top rowspan=2 bgcolor=#ccffff><b>Word Error Rate<br> </b></td>";
    print "<td valign=top rowspan=2 bgcolor=#ccffff><b>Time (X Realtime)<br> </b></td>";
    print "<td valign=top rowspan=2 bgcolor=#ccffff><b>Avg Heap (MB)<br> </b></td>";
    print "<td valign=top rowspan=2 bgcolor=#ccffff><b>Test Time<br> </b></td>";
    print "<td valign=top rowspan=2 bgcolor=#ccffff><a href=#glossary><b>Gap Insertion Rate (%)<br></b></a></td>";
    print "<td valign=top rowspan=2 bgcolor=#ccffff><a href=#glossary><b>Utterance Ratio<br> </b></a></td>";
    print "<td valign=top rowspan=1 colspan=3 bgcolor=#ccffff><a href=#glossary><b>Response Time (s)<br></b></a></td>";
    print "</tr>";
    print "<tr>";
    print "<td valign=top bgcolor=#ccffff><b>Avg<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Min<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Max<br> </b></td>";
    print "</tr>";
    
    for (i = 1; i <= liveTestCount[testName]; i++) {
	printSingleLiveTest(testName, i);
    }
    print "</tr>";
    print "<tbody>";
    print "</table>";
    print "<br>";
}


function printRejectionTestResults(testName) {
    print("<br><br>");
    print("<a name=" testName "></a>");
    print "<table align=center cellpadding=2 cellspacing=2 border=1 width=60%>";
    print "<tbody>";
    print "<tr align=center>";
    print "<td valign=top rowspan=1 colspan=6 bgcolor=#ccccff>";
    print "<big><b>" testName "</b></big>";
    print "<br>"
    print "</td>";
    print "</tr>";
    print "<tr>";
    print "<td valign=top bgcolor=#ccffff><b>Date<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Run Status<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><a href=#glossary><b>Rejection Accuracy</b></a></td>";
    print "<td valign=top bgcolor=#ccffff><b>Time (X Realtime)<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Avg Heap (MB)<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Test Time<br> </b></td>";
    
    for (i = 1; i <= rejectionTestCount[testName]; i++) {
	printSingleRejectionTest(testName, i);
    }
    print "</tr>";
    print "<tbody>";
    print "</table>";
    print "<br>";
}


####
# Prints summary info
#
function printSummaryInfo() {
    split(finalBuildRecord, data);
    print "Host:             " data[4]
    print "Date:             " data[2]
    print "Build Status:     " data[7]
    print "Build Time:       " data[8] " Secs"
    print "Run Time:         " data[9] " Secs"
    print ""
    print ""
}

# Field definitions: 
#   1) "build"
#   2) date
#   3) time
#   4) machine
#   5) who 
#   6) 'make' 
#   7) status
#   8) buildTime 
#   9) testTime 
#

function printBuildHistory() {
   print "<hr><br>"
   print("<a name=build_history></a>");
   print "<table cellpadding=2 cellspacing=2 border=1 width=80% align=center>";
   print "<tbody>";
   print "<tr align=center>";
   print "<td valign=top rowspan=1 colspan=7";
   print "    bgcolor=#ccccff><big><b>Test History<br>";
   print "</b></big></td> </tr>";
   print "<tr>";
   print "<td valign=top bgcolor=#99ffff align=center><b>Date<br>";
   print "</b></td>";

   print "<td valign=top bgcolor=#99ffff align=center><b>Test Name<br>";
   print "</b></td>";

   print "<td valign=top bgcolor=#99ffff align=center><b>Java Version<br>";
   print "</b></td>";
   print "<td valign=top bgcolor=#99ffff align=center><b>Uptime<br>";
   print "</b></td>";

   print "<td valign=top bgcolor=#99ffff align=center><b>Build Time<br>";
   print "</b></td>";
   print "<td valign=top bgcolor=#99ffff align=center><b>Test";
   print "Time</b><br>";
   print "</td>";
   print "<td valign=top bgcolor=#99ffff align=center><b>Status<br>";
   print "</b></td>";
   print "</tr>";

   for (i = 1; i <= buildCount; i++) {
        split(buildData[i], data);
        split(testEnv[i], envData);

        print("<tr>");
        print "<td>" dateAnchor(data[2]) "</td>";
        print "<td>" data[10] "</td>";
        print "<td>" envData[5] "</td>";
        print "<td>" envData[6] "</td>";
	print "<td>" fmtTime(data[8]) "</td>";
	print "<td>" fmtTime(data[9]) "</td>";

	status = data[7];

	if (status == "OK") {
	    print "<td>" "OK" "</td>";
	} else {
            print "<td bgcolor=#ffcccc>" status "</td>";
	}
       print("</tr>");
   }
   print "</tbody>";
   print "</table>";
}


function printMachineDescription() {
    split(machineDescription, data);
    split(environment, envData);
    javaHome = envData[4];
    javaVersion = envData[5];
    uptime = envData[6];
    "date" | getline theDate;

    print("<br><br>");
    print("<table cellpadding=2 cellspacing=2 border=0 width=90%");
    print("align=center>");
    print("<tbody>");
    print("<tr align=center>");
    print("<td rowspan=1 colspan=2 bgcolor=#ccccff><big><b>Tests");
    print("   run on " machine "<br>");
    print("</b></big></td>");
    print(" </tr>");
    print(" <tr>");
    print(" <td ><b>Test Date </b></td> <td> " theDate " </td></tr>");
    print(" <tr><td ><b>Test Details </b></td> <td> " )
    print("<a href=http://www.speech.cs.cmu.edu/cgi-bin/cmusphinx/twiki/view/Sphinx4/?topic=TaskStatus> Sphinx 4 Twiki</a></td>");
    print(" </tr>");

    print(" <td ><b>CPUs </b></td> <td> " data[3] " </td>");
    print(" </tr>");
    print(" <tr>");
      print(" <td ><b>Architecture </b></td> <td >" data[7] " </td>");
    print(" </tr>");
    print(" <tr>");
      print(" <td ><b>Clock Speed </b></td> <td >" data[5] "MHz</td>");
    print(" </tr>");
    print(" <tr>");
      print(" <td ><b>Memory </b></td> <td >" data[6] "MB</td>");
    print(" </tr>");
    print(" <tr>");
      print(" <td ><b>Cache </b></td> <td >" data[4] "MB</td>");
    print(" </tr>");
    print(" <tr>");
      print(" <td ><b>OS </b></td> <td >" data[8] "</td>");
    print(" </tr>");
    print(" <tr>");
      print(" <td ><b>JAVA_HOME </b></td> <td >" javaHome "</td>");
    print(" </tr>");

    print(" <tr>");
      print(" <td ><b>Java Version </b></td> <td >" javaVersion "</td>");
    print(" </tr>");

    print(" <tr>");
      print(" <td ><b>Uptime</b></td> <td >" uptime "</td>");
    print(" </tr>");
        
    print("</tbody>");
    print("</table>");
}


# "metrics|$date|$fileCount|$javaFileCount|$classCount|$lineCount|$packageCount|"
function printMetrics() {
   print("<a name=metrics></a>");
    split(metrics, data);

    print("<br><br>");
    print("<table cellpadding=2 cellspacing=2 border=0 width=90%");
    print("align=center>");
    print("<tbody>");
    print("<tr align=center>");
    print("<td rowspan=1 colspan=2 bgcolor=#ccccff><big><b>");
    print(" Sphinx 4 Metrics  <br>");
    print("</b></big></td>");
    print(" </tr>");
    print(" <tr>");
    print(" <td ><b>Number of files </b></td> <td> " data[3] " </td>");
    print(" </tr>");
    print(" <tr>");
    print(" <td ><b>Number of source files </b></td> <td >" data[4] " </td>");
    print(" </tr>");
    print(" <tr>");
    print(" <td ><b>Number of classes</b></td> <td >" data[5] "</td>");
    print(" </tr>");
    print(" <tr>");
    print(" <td ><b>Source lines of code</b></td> <td >" data[6] "</td>");
    print(" </tr>");
    print(" <tr>");
    print(" <td ><b>Packages </b></td> <td >" data[7] "</td>");
    print(" </tr>");
    print("</tbody>");
    print("</table>");
    print "<br>";

}

function printHeader() {
    print "<html>";
    print "<head>";
    print "   <title>S4 Regression Test Results</title>";
    print "   <meta http-equiv=content-type ";
    print "       content=text/html;charset=ISO-8859-1>";
    print "</head>";
    print "<body>";
}

function printFooter() {
    print "</body>";
    print "</html>";
}


function printKey() {
    print "<br>";
    print("<table cellpadding=2 cellspacing=2 border=0 ");
    print("align=center>");
    print("<tr align=center>");
    print("<td rowspan=1 colspan=2 bgcolor=#ccccff><big><b>");
    print(" Color Key <br>"); print("</b></big></td>");
    print("<tbody>");
    print  "<tr><td bgcolor=#99ff99> Improved result </td>";
    print "<td bgcolor=#ffcccc> Degraded result </td> </tr>";
    print("</tbody>");
    print("</table>");
    print "<br>";
}

function printTitle() {
    print "<table cellpadding=0 cellspacing=0 border=0 width=100%";
    print "    align=center bgcolor=#ccccff>";
    print "<tbody>";
    print "<tr>";
    print "<td valign=top align=center><br>";
    print "<big><big><b>Sphinx 4 Regression Test";
    print "Summary</b></big></big><br>";
    print "<br>";
    print "</td>";
    print "</tr>";
    print "</tbody>";
    print "</table>";
    print "<br>";
}

function printDetailedTestTitle() {
   print "<hr><br>"
    print "<table cellpadding=0 cellspacing=0 border=0 width=100%";
    print "    align=center bgcolor=#ccccff>";
    print "<tbody>";
    print "<tr>";
    print "<td valign=top align=center>";
    print "<big><b>Detailed Test Results"
    print "</b></big>";
    print "</td>";
    print "</tr>";
    print "</tbody>";
    print "</table>";
    print "<br>";
}

# prints the latest tests

function printLatestTestResults(  _testName, _testCount) {
    print("<br><br>");
    print("<a name=latest_results></a>");
    print "<table align=center cellpadding=2 cellspacing=2 border=1 width=80%>";
    print "<tbody>";
    print "<tr align=center>";
    print "<td valign=top rowspan=1 colspan=6 bgcolor=#ccccff>";
    print "<big><b>" "Latest Test Results" "</b></big>";
    print "<br>"
    print "</td>";
    print "</tr>";
    print "<tr>";
    print "<td valign=top bgcolor=#ccffff><b>Date<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Test Name<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Run Status<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Word Error Rate<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Time (X Realtime)<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Avg Heap (MB)<br> </b></td>";

    for (i = 0; i < lastTestCount; i++) {
        split(lastTestData[i], thisData);
	_testName = thisData[1];
	_testCount = thisData[2];
	printLongSingleTest(_testName, _testCount);
    }
    print "</tr>";
    print "<tbody>";
    print "</table>";
    print "<br>";
}


# prints the latest live tests

function printLatestLiveTestResults(  _testName, _testCount) {
    print("<br><br>");
    print("<a name=latest_live_results></a>");
    print "<table align=center cellpadding=2 cellspacing=2 border=1 width=80%>";
    print "<tbody>";
    print "<tr align=center>";
    print "<td valign=top rowspan=1 colspan=9 bgcolor=#ccccff>";
    print "<big><b>" "Latest Live Test Results" "</b></big>";
    print "<br>"
    print "</td>";
    print "</tr>";
    print "<tr>";
    print "<td valign=top bgcolor=#ccffff><b>Date<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Test Name<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Run Status<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Word Error Rate<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Time (X Realtime)<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Avg Heap (MB)<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><a href=#glossary><b>Gap Insertion Rate (%)<br> </b></a></td>";
    print "<td valign=top bgcolor=#ccffff><a href=#glossary><b>Utterance Ratio<br> </b></a></td>";
    print "<td valign=top bgcolor=#ccffff><a href=#glossary><b>Avg Response Time (s)<br> </b></a></td>";

    for (i = 0; i < lastLiveTestCount; i++) {
        split(lastLiveTestData[i], thisData);
	_testName = thisData[1];
	_testCount = thisData[2];
	printLongSingleLiveTest(_testName, _testCount);
    }
    print "</tr>";
    print "<tbody>";
    print "</table>";
    print "<br>";
}


# prints the latest live tests

function printLatestRejectionTestResults(  _testName, _testCount) {
    print("<br><br>");
    print("<a name=latest_rejection_results></a>");
    print "<table align=center cellpadding=2 cellspacing=2 border=1 width=80%>";
    print "<tbody>";
    print "<tr align=center>";
    print "<td valign=top rowspan=1 colspan=9 bgcolor=#ccccff>";
    print "<big><b>" "Latest Rejection Test Results" "</b></big>";
    print "<br>"
    print "</td>";
    print "</tr>";
    print "<tr>";
    print "<td valign=top bgcolor=#ccffff><b>Date<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Test Name<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Run Status<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><a href=#glossary><b>Rejection Accuracy<br> </b></a></td>";
    print "<td valign=top bgcolor=#ccffff><b>Time (X Realtime)<br> </b></td>";
    print "<td valign=top bgcolor=#ccffff><b>Avg Heap (MB)<br> </b></td>";

    for (i = 0; i < lastRejectionTestCount; i++) {
        split(lastRejectionTestData[i], thisData);
	_testName = thisData[1];
	_testCount = thisData[2];
	printLongSingleRejectionTest(_testName, _testCount);
    }
    print "</tr>";
    print "<tbody>";
    print "</table>";
    print "<br>";
}


# prints the table of contents

function printTOC() {
    print("<h2> Table of Contents</h2>");
    # print("<small>");
    print("<ul>");
    print("<li><a href=#latest_results> Latest Results </a></li>");
    print("<li><a href=#build_history> Build History </a></li>");
    print("<li>Detailed Test Results</li>");
    print("<ul>");
    for (i in testCount) {
	print("<li><a href=#" i ">"  i "</a></li>") | "sort";
    }
    for (i in liveTestCount) {
	print("<li><a href=#" i ">"  i "</a></li>") | "sort";
    }
    for (i in rejectionTestCount) {
	print("<li><a href=#" i ">"  i "</a></li>") | "sort";
    }
    close("sort");
    print("</ul>");
    print("</ul>");
    # print("</small>");
}

function printHeaderTable() {
    print "<table align=center cellpadding=2 cellspacing=2 border=0 width=100%>";
    print("<tr>");
    print("<td valign=top bgcolor=#ddddff>\n");
    printTOC();
    print("</td>\n");
    
    print("<td valign=top>\n");
    printMachineDescription();
    printMetrics();
    printKey();
    print("</td>\n");
    
    print("</tr>");
    print("</table>")
}

function printGlossary() {
    print "<a name=glossary><h2>Glossary</h2></a><p>\n"
    print "<b>Gap Insertion Rate</b> - Gap insertions are words inserted in the non-speech regions of audio. The gap insertion rate is defined the percentage of recognized words that are gap insertions:<br>gap insertion rate = number of gap insertions / total number of words recognized<p>\n";
    print "<b>Response Time</b> - This is defined the time between audio entering the front end, to the decoder obtaining the first feature with an UTTERANCE_START signal.<p>\n";
    print "<b>Utterance Ratio</b> - This is defined as the number of utterances detected (by the endpointer) divided by the actual number of utterances.<p>\n";
    print "<b>Rejection Accuracy</b> - This is defined as the percentage of utterances that are correctly classified as in-grammar or out-of-grammar.<p>\n"
}


END {
    print("<html>");
    printHeader();
    printTitle();
    printHeaderTable()
    printLatestTestResults();
    printLatestLiveTestResults();
    printLatestRejectionTestResults();
    printDetailedTestTitle();
    for (i in testCount) {
        printTestResults(i);
    }
    for (i in liveTestCount) {
	printLiveTestResults(i);
    }
    for (i in rejectionTestCount) {
	printRejectionTestResults(i);
    }
    printBuildHistory();
    printGlossary();
    printFooter();
}

'  $*

