#!/bin/sh

# Shell script to convert a SCC logbook to html-format.
# Copyright (C) 2001-2004 Open Challenge B.V.
# Copyright (C) 2004-2005 OpenEyeT Professional Services.
# Copyright (C) 2005-2009 QNH.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING.
# If not, write to the Free Software Foundation,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Contact information: http://scc.qnh-infrastructure.nl/index.html 

# SCC-release:	1.9.28
# file-version:	$Revision: 1.98 $


set -u

ProgName=${0##*/};			export ProgName

if [ $# -ne 1 ]
then
	echo "Syntax error, use ${ProgName} <name>" >&2
	exit 1
fi

SCC_BIN=/opt/scc/bin
SCC_TOP=/var/opt/scc
export SCC_BIN SCC_TOP

# Perform the security settings before calling any program.
PATH=/sbin:/usr/sbin:/usr/bin:/bin;	export PATH

# Add the directories containing collections of symlinks to programs on Syllable:
for dir in /boot/system/bin /usr/indexes/bin /usr/indexes/sbin /system/indexes/bin /system/indexes/sbin
do
	if [ -d "${dir}" ]
	then
		PATH="${PATH}:${dir}"
	fi
done

export SCC_DATA=${SCC_TOP}/data
export SCC_TMP=${SCC_TOP}/tmp
export SCC_CONF=/etc/opt/scc/conf

export TMPDIR=${SCC_TMP}
export TMP=${SCC_TMP}

export SHELL=/bin/sh
export LANG=C

cd ${SCC_TMP}

umask 077

. ${SCC_BIN}/scc_modules/scc_utils

busybox_check sort
if [ $? -eq 1 ]
then
	exit 0		# We require the full sort.
fi

export TMP_FILE=${SCC_TMP}/scc_log_html_$$

trap "rm -f ${TMP_FILE}" 0
trap "exit 2" 1 2 3 15

# Replace special HTML-characters in input.
sed	-e 's/&/\&amp;/g'	\
	-e 's/</\&lt;/g'	\
	-e 's/>/\&gt;/g'	\
	-e "s/'/\&#39;/g"	\
	-e 's/"/\&quot;/g' >${TMP_FILE}

if [ ! -s ${TMP_FILE} ]
then
	exit 0
fi

TABLE_TAG="<TABLE CLASS=SCC SUMMARY=\"Summary of scc-runs\" BORDER CELLSPACING=1 CELLPADDING=4>"
TOP_NAME="<A NAME=cfg_top></A>"
TOP_URL="<A HREF=\"#cfg_top\">Top</A>&nbsp;&nbsp;&nbsp;&nbsp;"

echo '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'
echo "<HTML>"

echo "<HEAD>"
echo '<LINK HREF="style.css" REL="stylesheet" TYPE="text/css">'
echo "<TITLE>Logbook: $1</TITLE>"
echo "</HEAD>"

echo "<BODY>"
echo "<DIV class=SCC_LOG>";
echo "${TOP_NAME}"

echo "<H1>Logbook: ${1}</H1>"

echo "<DIV class=SCC_LOG_NAV>";

# DO NOT CHANGE THE FOLLOWING HTML-CODE WITHOUT CONSULTING scc.cgi IN scc-srv
echo "<H4>"
echo "	<A HREF=index.html>Home</A>&nbsp;&nbsp;&nbsp;&nbsp;"
echo "	<A HREF=scc.${1}.html>Configuration</A>&nbsp;&nbsp;&nbsp;&nbsp;"
echo '	<A HREF="#cfg_statistics">Statistics</A>'
echo "</H4>"
echo "</DIV><!-- class=SCC_LOG_NAV -->";
echo "<H4>Summary of runs of SCC</H4>"

# Build a table with URL's to reported differences in the logbook.
# Use the date/time of the run as the ID for HREF and NAME.
# Sort the data reverse to show the most recent change at the top of the table.
# Check the code in scc-log for the specific layout of the logbook.
grep -e ":result::" -e ":remark::" -e ":runtime::" -e ":count::" ${TMP_FILE}	|
awk -F: '/:result::/	{
				stat_cnt_runs++;
				if ( length( prev_res ) )
				{
					# restart or identical, no number of differences.
					print prev_res ":" ":" prev_runtime ":" prev_remark;
					prev_remark="";
					prev_runtime="";
				}
				prev_res=$0;
			}
	/:remark::/	{
				# A remark can contain ":", syntax of a line is: <date>:<time>:remark::<remark>
				prev_remark = $5;
				for ( i = 6; i <= NF; i++ )
				{
					prev_remark = sprintf( "%s: %s", prev_remark, $i );
				}
			}
	/:runtime::/	{
				# Use a separate counter as older versions of SCC did not record the runtime.
				stat_runtime_cnt++;
				stat_runtime_total+=$NF;
				if ( $NF > stat_runtime_max )
				{
					stat_runtime_max=$NF;
				}
				if ( $NF < stat_runtime_min || stat_runtime_min == 0 )
				{
					stat_runtime_min=$NF;
				}
				prev_runtime=$NF;
			}
	/:count::/	{
				stat_change_cnt++;
				stat_change_total+=$NF;
				if ( $NF > stat_change_max )
				{
					stat_change_max=$NF;
				}
				if ( $NF < stat_change_min || stat_change_min == 0 )
				{
					stat_change_min=$NF;
				}
				# changes detected, report
				print prev_res ":" $NF ":" prev_runtime ":" prev_remark;
				prev_res=""
				prev_remark=""
			}
END			{
				# unreported results?
				if ( length( prev_res ) )
				{
					print prev_res ":" ":" prev_runtime ":" prev_remark;
				}
				if ( stat_cnt_runs == 0 )
				{
					stat_cnt_runs=1;
					stat_runtime_cnt=1;
				}
				printf( "0:9:runs total          : %d\n", stat_cnt_runs );
				printf( "0:8:runs with changes   : %d\n", stat_change_cnt );
				printf( "0:7:runs perc. changes  : %d\n", ( 100 * stat_change_cnt ) / stat_cnt_runs );
				printf( "0:6:change count min.   : %d\n", stat_change_min );
				printf( "0:5:change count max.   : %d\n", stat_change_max );
				if ( stat_change_cnt == 0 )
				{
					stat_change_cnt = 1;
				}
				printf( "0:4:change count average: %d\n", stat_change_total / stat_change_cnt );
				printf( "0:3:runtime min.        : %d\n", stat_runtime_min );
				printf( "0:2:runtime max.        : %d\n", stat_runtime_max );
				printf( "0:1:runtime average     : %d\n", stat_runtime_total / stat_runtime_cnt );
			}'			|
sort -r						|
awk -F":" '{
		# The variable u is not initialized in a BEGIN-clause.
		# Therefore we check for the first record.
		if ( NR == 1 )
		{
			print "<DIV class=SCC_LOG_SUMMARY>";
			print u;
			print "<THEAD>";
			print "	<TR class=Odd>";
			print "		<TH>Date</TH>";
			print "		<TH>Time</TH>";
			print "		<TH>Runtime</TH>";
			print "		<TH>Result</TH>";
			print "		<TH>Count</TH>";
			print "		<TH>Remark</TH>";
			print "	</TR>";
			print "</THEAD>";

			print "<TBODY>";
			tr_c = "Even";
		}
	}
/^0:/	{
		# We print the statistics as pre-formatted text.
		# Last part of the data. The END-statement takes care of the </PRE>.
		# Format of the data is:
		#0:<order>:<label>:<value>
		if ( statistics == 0 )		# No heading yet?
		{
			print "</TBODY>";
			print "</TABLE>";
			print "</DIV><!-- class=SCC_LOG_SUMMARY -->";
			print "<HR>";
			print "<DIV class=SCC_LOG_STATS>";
			print "<A NAME=cfg_statistics></A>"
			printf( "<H4>%sStatistics</H4>\n", t );
			statistics=1;		# Heading done!

			print u;
			print "<THEAD>";
			print "	<TR class=Odd>";
			print "		<TH>Category</TH>";
			print "		<TH>Value</TH>";
			print "	</TR>";
			print "</THEAD>";

			print "<TBODY>";
			s_tr="Even";
		}
		print "<TR class=" s_tr ">";
		if ( s_tr != "Even" )
		{
			s_tr = "Even";
		}
		else
		{
			s_tr = "Odd";
		}
		print "	<TD class=Even>" $3 "</TD>";		# Category
		print "	<TD class=Odd align=right>" $4 "</TD>";	# Value
		print "</TR>";
		next;
	}
{
	# Show data of a run.
	# Format of the input is:
	#<date>:<time>:result::different:<count>:<runtime>:<remark>
	if ( $5 == "different" )
	{
		print "<TR class=" tr_c "_Emp>";
	}
	else
	{
		print "<TR class=" tr_c ">";
	}

	if ( tr_c != "Even" )
	{
		tr_c = "Even";
	}
	else
	{
		tr_c = "Odd";
	}

	if ( $5 == "different" )
	{
		# When there are differences, we want to go back to this point in the table
		printf( "<TD class=Even><A NAME=\"back_%s_%s\"></A>%s</TD>\n", $1, $2, $1 );	# Date
	}
	else
	{
		print "	<TD class=Even>" $1 "</TD>";	# Date
	}
	print "	<TD class=Odd>" $2 "</TD>";	# Time
	if ( length( $7 ) > 0 )			# Runtime available?
	{
		printf( "	<TD class=Even align=right>%s</TD>\n", $7 );
	}
	else
	{
		print "	<TD class=Even>&nbsp;</TD>";
	}
	if ( $5 == "different" )		# Result
	{
		printf( "	<TD class=Odd_Emp><A HREF=\"#log_%s_%s\">%s</A></TD>\n", $1, $2, $5 );
	}
	else
	{
		printf( "	<TD class=Odd>%s</TD>\n", $5 );
	}
	if ( length( $6 ) > 0 )			# Count available?
	{
		printf( "	<TD class=Even align=right>%s</TD>\n", $6 );
	}
	else
	{
		print "	<TD class=Even>&nbsp;</TD>";
	}
	remark = $8;				# Possibly contains ":"
	for ( i = 9; i <= NF; i++ )
	{
		remark = sprintf( "%s: %s", remark, $i );
	}
	if ( length( remark ) > 0 )
	{
		printf( "	<TD class=Odd_Emp align=left>%s</TD>\n", remark );
	}
	else
	{
		print "	<TD class=Odd>&nbsp;</TD>";
	}
	print "</TR>";
}
END	{
	print "</TBODY>";
	print "</TABLE>";
	print "</DIV><!-- class=SCC_LOG_STATS -->";
}' t="${TOP_URL}" u="${TABLE_TAG}"

# Now the table is present, we show the data.
# Use the date/time of the run as the ID for HREF and NAME.
awk -F: '{
	# Sort the log file, most recent run first, 
	# within the run keep the data in the order of the log file.
	log_date=$1;
	log_time=$2;
	gsub( "-", "", log_date );
	gsub( /\./, "", log_time );
	printf( "%s:%06d:%s:%s\n", log_date, log_time, NR, $0 );
}' ${TMP_FILE}				|
sort -t: -k 1,1nr -k 2,2nr -k 3,3n	|
sed -e 's/^[0-9]*:[0-9]*:[0-9]*://'	|
awk -F":"	'BEGIN	{ first_log_entry = 1; }
	/:result::different$/	{
			if ( show_data )
			{
				print "</PRE>";		# end of previously showed data
			}
			show_data=1;			# indicate that we are going to show differences
			prev_class="";			# reset class-identifier for this run
			print "<HR>";
			if ( first_log_entry )
			{
				print "<DIV class=SCC_LOG_ENTRY>";
				first_log_entry=0;
			}
			printf( "<H4>%s<A HREF=\"#back_%s_%s\">Back</A>&nbsp;&nbsp;&nbsp;&nbsp;", u, $1, $2 );
			printf( "<A NAME=\"log_%s_%s\">Differences at: %s %s</A></H4>\n", $1, $2, $1, $2 );
			print "<PRE>";
			next;
		}
	/:result::identical$|:result::.re.start$/	{
			if ( show_data )
			{
				print "</PRE>";		# end of previously showed data
			}
			show_data=0;			# the are no differences: do not show data
			next;
		}
	/:data::/	{
			if ( show_data )
			{
				# Do not show the classification on each line, only once in bold format.
				change=$5;		# old/new
				# $6 is empty to separate changed data from the classification
				class=$7;
				for ( i = 8; length( $i ) > 0; i++ )
				{
					class=sprintf( "%s - %s", class, $i );
				}
				if ( class != prev_class )
				{
					print "<BR>";
					print "<B>" class "</B>";
					prev_class=class;
				}
				printf( "%s:	", change );
				for ( i++; i < NF; i++ )
				{
					printf( "%s:", $i );
				}
				print $i;
			}
			next;
		}
		{
			# No data, classifications:
			# possible classifications are: count, remark, previous date and time
			if ( show_data )
			{
				printf( "%-30.30s: %s\n", $3, $5 );
			}
			next;
		}
END	{
		if ( show_data )
		{
			print "</PRE>";		# end of previously showed data
		}
		print "<HR>";
		if ( first_log_entry == 0 )	# Have any log-entries been printed?
		{
			print "</DIV><!-- class=SCC_LOG_ENTRY -->";	# Mark the end of all log-entries.
		}
	}' u="${TOP_URL}"

rm -f ${TMP_FILE}

echo "<P>Generated by SCC (&copy; <A HREF=\"http://scc.qnh-infrastructure.nl\">QNH</A>) on $(date)</P>"

echo "</DIV><!-- class=SCC_LOG -->";
echo "</BODY>"
echo "</HTML>"

exit 0
