#!/usr/bin/perl -w use strict; use warnings; use Date::Manip; use Math::Round; my $datetime; # Stores date and time pulled from log my $entry; # Stores the log entry for processing my $action; # Stores the action for processing (this will be the key to the # hash). my $time; # the $datetime converted to UNIX timestamp my %begin; # Data structure for storing the beginning of a time frame my %end; # Data structure for storing the end of a time frame my %ind; # Data structure for storing individual timecards my %misc; # Data structure for storing miscellaneous (<0.25hrs) timecards my ($bc,$ec); # variables for determining if we have a complete set. while(<>) { if(/^\s*$/) { # If current line is an empty string, skip to next line next; } chomp; ($datetime,$entry) = split /:\s{1,2}/; #print STDERR "$datetime: $entry\n"; $time = UnixDate($datetime, "%s"); #print STDERR "$time: $entry\n"; if($entry =~ /^Begin/) { #print STDERR "DEBUG: Writing an BEGIN action\n"; #print STDERR "$time: "; $action = $entry; $action =~ s/^Begin\s+(.+)\s*/$1/; $action =~ s/\s+$//; # trim off any whitespace at the end #print STDERR "$action\n"; push(@{$begin{$action}},$time); } if($entry =~ /^End/) { #print STDERR "DEBUG: Writing an END action\n"; #print STDERR "$time: "; $action = $entry; $action =~ s/^End\s+(.+)\s*/$1/; $action =~ s/\s+$//; # trim off any whitespace at the end #print STDERR "$action\n"; push(@{$end{$action}},$time); } } # We're here, begin processing my $act; my $gtot = 0; foreach $act (sort keys %begin) { # For every activity we started. # error checking $bc = 0; $ec = 0; $bc = @{$begin{$act}}; # or die "Activity \"$act\" is incomplete. Missing Begin.\n"; #print STDERR "$act\n"; $ec = @{$end{$act}}; # or die "Activity \"$act\" is incomplete. Missing End.\n"; #print STDERR "DEBUG: \"$act\" bc=$bc,ec=$ec\n"; if(($bc - $ec) > 1) { # haven't logged more than one closing time # print STDERR "Activity \"$act\" is incomplete. Missing multiple Ends.\n"; exit 2; } elsif($bc > $ec) { # should be exactly one greater # print STDERR "Activity \"$act\" is incomplete. Missing one End. Removing last from array.\n"; pop(@{$begin{$act}}); # GRATUITOUS USE OF GOTO HERE! goto THERE; # END GRATUITOUS USE OF GOTO HERE! } elsif($ec > $bc) { # have missed a begin time # print STDERR "Activity \"$act\" is incomplete. Missing Begin.\n"; exit 1; } else { THERE: my $sum = 0; # DOIT while(@{$begin{$act}} && @{$end{$act}}) { my $beg = shift @{$begin{$act}}; my $en = shift @{$end{$act}}; $sum += $en - $beg; } #printf ("\"$act\": %10ds %3.2fhr\n", $sum, ($sum / 3600 >= 0.25)?nearest(0.25, $sum / 3600):$sum / 3600); #printf ("\"$act\":\t\t%10ds\t%3.2fhrs\n", $sum, $sum / 3600); # If sum is greater than fifteen minutes, put it individual list # otherwise, put it in # 2014-10-02: Remove miscellaneous, since we will no longer be reporting in # fifteen minute increments #$sum > 900?$ind{$act}=$sum:$misc{$act}=$sum; $ind{$act}=$sum; $gtot += $sum; } } #my $spr; my $sec; my $hrs; my $min; my $fhrs; my $ctot = 0; my $utot = 0; # DEBUGGING #foreach $act (sort keys %ind) { # print STDERR "Activity: " . $act . " "; # print STDERR "$ind{$act}s " . $ind{$act}/3600 . "hrs "; # print STDERR $ind{$act}%3600/60 . "min\n"; #} format STDOUT = @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> $act, $sec, $hrs, $min, $fhrs . foreach $act (sort keys %ind) { #$spr = sprintf("%3.2fhrs",nearest(0.25, $ind{$act}/3600)); $min = sprintf("%dmin",nearest(1, $ind{$act}%3600/60)); $hrs = sprintf("%dhrs",$ind{$act}/3600); $fhrs = sprintf("%.2fhrs",$ind{$act}/3600); $sec = "$ind{$act}s"; write; if($act =~ /^\d{8}/) { #print STDERR "Got a case\n"; $ctot += $ind{$act}; } else { #print STDERR "Got a non-case\n"; $utot += $ind{$act}; } # } elsif($changed == 0) { # print "\n"; # printf ("Case total: %10ds, %3.2fhrs, %3.2fhrs (rounded)\n", $ctot, $ctot / 3600, nearest(0.25, $ctot / 3600)); # print "\n"; # $changed = 1; #} # else { # $min = sprintf("%dmin",nearest(1, $ind{$act}%3600/60)); # $hrs = sprintf("%dhrs",$ind{$act}/3600); # $fhrs = sprintf("%.2fhrs",$ind{$act}/3600); # $sec = "$ind{$act}s"; # write; # $utot += $ind{$act}; # } } print "\n"; printf ("Case total: %10ds, %3.2fhrs, %3.2fhrs (rounded)\n", $ctot, $ctot / 3600, nearest(0.25, $ctot / 3600)); print "\n"; print "\n"; printf ("Unnumbered total: %10ds, %3.2fhrs, %3.2fhrs (rounded)\n", $utot, $utot / 3600, nearest(0.25, $utot / 3600)); print "\n"; # REMOVED 2014-10-02 #$tot = 0; #foreach $act (sort keys %misc) { # $spr = sprintf("%3.2fhrs", $misc{$act}/3600); # $sec = "$misc{$act}s"; # write; # $tot += $misc{$act}; #} #print "\n"; #printf ("Miscellaneous total: %10ds, %3.2fhrs, %3.2fhrs (rounded)\n", $tot,$tot / 3600, nearest(0.25, $tot / 3600)); #print "\n"; $gtot = $ctot + $utot; print "\n"; printf "Grand Total: %10ds, %.02fhrs\n", $gtot, $gtot / 3600; #my §ion_post { # #};