#!/usr/bin/perl -W

# clodi5t-to-hmaser.pl < /data/clodi5t/20040429.log > /data/hmaser5t/20040429.log

# Lue clodin mittausdataa ja
#  a) vähennä näytteiden määrää keskiarvoistamalla
#  b) vaihda kanavien numeroiden tilalle  nimet

use strict;

use Time::Local;

# Muunna aikamerkkijono sekunneiksi. Jos merkkijonon lopussa on
# ylimääräisiä merkkejä (esimerkiksi sadasosasekunteja) jätetään ne
# huomiotta.
# @param str yyyymmddHHMMSS-muodossa oleva aikamerkkijono
# @return aika sekunteina keskiyöstä 1.1.1970
die "strtimegm broken"
    unless strtimegm("2004062306473600") == 1087973256;
sub strtimegm {
    my ($sec, $min, $hour, $mday, $mon, $year);
    my ($str, $time);

    $str = shift;
    $year = substr($str, 0, 4);
    $mon = substr($str, 4, 2);
    $mday = substr($str, 6, 2);
    $hour = substr($str, 8, 2);
    $min = substr($str, 10, 2);
    $sec = substr($str, 12, 2);
    die "unable to parse date \"$str\""
	unless (defined($year) && defined($mon) && defined($mday)
	&& defined($hour) && defined($min) && defined($sec));
    $year -= 1900;
    $mon -= 1;
    $time = timegm($sec,$min,$hour,$mday,$mon,$year);
    die "weird time"
	unless ($time > 100);
    return $time;
}
# Muunna sekunnit aikamerkkijonoksi.
# @param seconds aika sekunteina keskiyöstä 1.1.1970
# @return yyyymmddHHMMSS-muodossa oleva aikamerkkijono
die "timegmstr broken"
    unless timegmstr(1087973256) eq "2004062306473600";
sub timegmstr {
    my ($sec, $min, $hour, $mday, $mon, $year) = gmtime(shift);
    $year += 1900;
    $mon += 1;
    return sprintf("%04d%02d%02d%02d%02d%02d00", $year, $mon,
		   $mday, $hour, $min, $sec);
}


# FIXME: rethink syntax
# FIXME: rethink variable names

my $line = 0;
my %bindings = ( "&bind" => "&bind",
		 "&set_average_period" => "&set_average_period",
		 "&comment" => "&comment" );

my %average;
my %average_n;
my %average_time;
my $second_len;

my %average_period;

while(<>) {
# FIXME: rething variable names and structure
    my ($rawtime, $rawchannel, $rawsample, $column4, $column5);
    my ($time, $channel, $sample);
    my $timediff;

    $line++;
    chomp;
    ($rawtime, $rawchannel, $rawsample, $column4, $column5) = split;
    die "Parse error on line $line"
	unless defined($rawtime) && defined($rawchannel) && defined($rawsample);
    $channel = $bindings{$rawchannel};
    die "Unknown channel \"$rawchannel\", adjust binding rules"
	unless defined($channel);
    if ($channel eq "&bind") {
	die "bind: Parse error on line $line"
	    unless defined($rawsample) && defined($column4);
	$bindings{$rawsample} = $column4;
	next;
    }
    if ($channel eq "&comment") {
    }
    if ($channel eq "&set_average_period") {
	die "set_average_period: Parse error on line $line"
	    unless defined($rawsample) && defined($column4);
	$average_period{$rawsample} = $column4;
    }
    if ($channel eq "&set_second_len") {
	if ($rawsample == "+0.01") {
	    next;
	}
	$second_len = $rawsample / 1000000;
	next;
    }
#   FIXME
#    die "Length of second unknown on line $line"
#	unless defined($second_len);
    if (!defined($second_len)) {
	next;
    }

    $sample = $rawsample * $second_len;
    die "average period for channel $channel unknown on line $line"
	unless defined($average_period{$channel});
    if ($average_period{$channel}) {
	$time = strtimegm($rawtime);
	if (!defined($average_n{$channel})) {
	    $average{$channel} = 0; # never used, this will be multiplied by zero later
	    $average_n{$channel} = 0;
	    $average_time{$channel} = $time;
#	$average_time{$channel} = $rawtime;
#	print "$rawchannel averaging starts $rawtime\n";
	}
	
#    avg = (avg * n + k) / (n + 1)
	$average{$channel} = ($average{$channel} * $average_n{$channel} + $sample) / ($average_n{$channel} + 1);
	$average_n{$channel}++;
	
#    my $timediff = $time - strtimegm($average_time{$channel});
	$timediff = $time - $average_time{$channel};
#    print "$rawtime $rawchannel $rawsample, $timediff s\n";
	
#    if ($time >= (strtimegm($average_time{$channel}) + $average_period)) {
	if ($timediff >= $average_period{$channel}) {
	    my $middle = timegmstr($average_time{$channel} + $average_period{$channel}/2);
	    print "$middle\t$channel\t$average{$channel}\n";
	    $average_n{$channel} = 0;
	    $average_time{$channel} = $time;
	}
    } else {
	print "$rawtime\t$channel\t$sample\n";
    }
}

    
    
	
    
