#!/usr/local/bin/perl
#
# Read and process resources file (cpt_tasks.rsc)
# created from processing cpt_tasks.tex


##########################################################
#
# Define parameters 
#
$indir = ".";
$outdir= ".";
$instem= "cpt_tasks";
##########################################################

##########################################################
#
# Open files 
#
open(RSCIN,  "<$indir/$instem.rsc");
open(RSCOUT, ">${outdir}/${instem}.rsc_out");

##########################################################
#
# Read input resources file and write processed output  
#
print RSCOUT<<END;
%
%  This file was created automatically. Do not edit !!
%
END


    
$daysperyear=365;
$nyears = 7;
$first_year = 2001;

$years              = [];
$sub_total_needed   = [];
$grand_total_needed = [];
$sub_total_actual   = [];
$grand_total_actual = [];

for (my $i=0; $i<$nyears; $i++) {
    $years->[$i]              = $first_year + $i; 
    $sub_total_needed->[$i]   = 0.0;
    $grand_total_needed->[$i] = 0.0;
    $sub_total_actual->[$i]   = 0.0;
    $grand_total_actual->[$i] = 0.0;
}



$temp_string = [];

#############################################################################################
#
#  write out column headers
#

     &resources_profile_line ("Deliverable / role",
                              "Start",
	                      "End",
			      $years);
#     print RSCOUT "\\vspace*{-0.1ex}\\\\\n";

#
#   Now parse each line in the resources file, calculate running sums,
#   and write it out again with nice formatting
#

$previous_task = 1;

while (<RSCIN>) {
    $line = $_;

    if ( ! ( $line =~ m/^[\s]*\#/ ) ) {        # its not an empty line
        chomp $line;                           # remove end of line
        @token = split (',', $line);           # tokenize assuming comma-separated items
        $ntokens = @token;
	
        print STDOUT "------------------------------------\ni   Token value\n--  -----------\n";
	for (my $i=0; $i<$ntokens; $i++) {
           print STDERR $i."   ".$token[$i]."\n";
        }

	if ( $ntokens < 8 ) {
	    print STDERR "Wrong number of tokens for previous resource =".$ntokens."\n";
	    die "STOP! resource needs fixing in the original source file...\n\n";
        }
	elsif ($ntokens == 0 ) {
            # blank line
        }
	elsif ( $ntokens > 3 ) {
            for (my $i=0; $i<$ntokens; $i++) {
               $token[$i] = &clean_whitespace($token[$i]); 
            }
            my $rsc_deliverable  = $token[0];
            my $rsc_start        = $token[1];
            my $rsc_end          = $token[2];
            my $rsc_type         = $token[3];
            my $rsc_needed       = $token[4];
            my $rsc_actual       = $token[5];
            my $rsc_source       = $token[6];
            my $rsc_description  = $token[7];
	    my ($task, $subtask) = ($rsc_deliverable =~ m/(\d+)/g);  # match any set of digits, then repeat for next set
	    my $float_yr_start   = &date_to_float_years($rsc_start);
            my $float_yr_end     = &date_to_float_years($rsc_end);
            my $float_yr_duration= $float_yr_end - $float_yr_start;
	    my $fte_yrs_needed   = $float_yr_duration * $rsc_needed;
	    my $fte_yrs_actual   = $float_yr_duration * $rsc_actual;
            my ($profile_needed, $profile_actual) =
		&make_profiles ($rsc_start,$rsc_end,$rsc_needed,$rsc_actual);

#
#           If this is a new L2 task, write out sub-total of previous task and then reset sum arrays to zero
#

   	    if ( $task != $previous_task) {
                for (my $i=0; $i<$nyears; $i++) {
                    $temp_string->[$i] = &format_two_values ($sub_total_needed->[$i], $sub_total_actual->[$i]);
                }
   	        my $_string = "Sum, task ".$previous_task."";   
                &resources_profile_line ($_string," "," ",$temp_string);
                print RSCOUT "\\vspace*{-0.1ex}\\\\\n";
                print RSCOUT "\\vspace*{-0.1ex}\\\\\n";
                print RSCOUT "\n";
                print RSCOUT "\\bigbreak\n";
                print RSCOUT "\n";

	        &resources_profile_line ("Deliverable / role",
                                         "Start",
	                                 "End",
			                 $years);
#     print RSCOUT "\\vspace*{-0.1ex}\\\\\n";

                for (my $i=0; $i<$nyears; $i++) {
                    $sub_total_needed->[$i] = 0.0;
                    $sub_total_actual->[$i] = 0.0;
                }
		$previous_task += 1;
	    }

            for (my $i=0; $i<$nyears; $i++) {
		$temp_string->[$i] = &format_two_values ($profile_needed->[$i], $profile_actual->[$i]);
	        $sub_total_needed->[$i]   += $profile_needed->[$i]; 
                $grand_total_needed->[$i] += $profile_needed->[$i]; 
                $sub_total_actual->[$i]   += $profile_actual->[$i]; 
                $grand_total_actual->[$i] += $profile_actual->[$i]; 
            }
#
#           Write out (required and actual) resources for this deliverable
#
	    my $_string = $rsc_deliverable." ".$rsc_description;
            &resources_profile_line ($_string,
                                     $rsc_start,
	                             $rsc_end,
				     $temp_string);
	    
	    }
	else {
            print STDERR "Bad line: $line\n";
        }
    }
}
#
#       Sub-total for the last sub-task
#

        for (my $i=0; $i<$nyears; $i++) {
            $temp_string->[$i] = &format_two_values ($sub_total_needed->[$i], $sub_total_actual->[$i]);
        }
        my $_string = "Sum, task ".$previous_task;   
        &resources_profile_line ($_string," "," ",$temp_string);
        print RSCOUT "\\vspace*{-0.1ex}\\\\\n";
        print RSCOUT "\n";

#
#       Show the grand total
#
        for (my $i=0; $i<$nyears; $i++) {
            $temp_string->[$i] = &format_two_values ($grand_total_needed->[$i], $grand_total_actual->[$i]);
        }
        &resources_profile_line ("CCS TOTAL"," "," ",$temp_string);

close RSCIN;
close RSCOUT;

;




#######################################################################################
#
#   make resource profile 
#

sub make_profiles {

    my ($rsc_start,$rsc_end,$rsc_needed,$rsc_actual) = @_;
    
    my $profile_needed = [];
    my $profile_actual = [];
    my $days_this_year = 0.0;
    
    my ($day_start, $month_start, $year_start) = &split_date($rsc_start);
    my ($day_end,   $month_end,   $year_end)   = &split_date($rsc_end);

#    print STDOUT "nyears = ".$nyears."\n";
    
    for (my $i=0; $i<$nyears; $i++) {

#	print STDOUT "i=".$i."   years(i), start, end ".$years->[$i]." ".$year_start." ".$year_end."\n";
	
        if ($years->[$i] < $year_start | $years->[$i] > $year_end) {        # year is out of range   
	    $days_this_year = 0.0;
	}
	elsif ($years->[$i] == $year_start && $years->[$i] == $year_end) {  # task is contained in 1 year
           $days_this_year = $daysperyear*(&date_to_float_years($rsc_end)-
					   &date_to_float_years($rsc_start));
        }
	elsif ($years->[$i] == $year_start) {                               # starting year (partial year)
           $days_this_year = $daysperyear - &days_since_year_start($rsc_start) + 1; 
        }
	elsif ($years->[$i] == $year_end) {                                 # ending year (partial year)
           $days_this_year = &days_since_year_start($rsc_end);
        }
	else {                                                              # a complete year
	   $days_this_year = $daysperyear;
	}

	$days_this_year = int($days_this_year);
	$pro_rata_factor = $days_this_year / $daysperyear;

	$profile_needed->[$i] = &round($rsc_needed * $pro_rata_factor, 1) ;
        $profile_actual->[$i] = &round($rsc_actual * $pro_rata_factor, 1) ;

#	print STDOUT "rsc_needed, pro_rata_factor, days_this_year = ".
#	             $rsc_needed." , ".$pro_rata_factor." , ".$days_this_year."\n";
#	print STDOUT "i, year, needed, actual = ".
#	              $i."  ".$years->[$i]." ".$profile_needed->[$i]." ".$profile_actual->[$i]."\n\n";	       
    }

    return ($profile_needed, $profile_actual);
    
}


#######################################################################################
#
#   format two numbers ("resources actual" and "resources needed")
#
sub format_two_values {
    my ($first, $second)   = @_;
    my ($_first, $_second) = @_;

    if ($first == 0 && $second == 0) {
       $_first  = " "; # blank for clarity
       $_second = " "; # blank for clarity
    }
    elsif ($first > $second) {
       $_first  = "{\\red\\em{".$first."}}";
       $_second = "{\\red\\em{(".$second.")}}";
    }
    elsif ($first < $second) {
       $_first  = "{\\green\\em{".$first."}}";
       $_second = "{\\green\\em{(".$second.")}}";
    }
    else {
       $_first  = "{\\black{".$first."}}";
       $_second = "{\\black{(".$second.")}}";
    }	
       
    my $_string = "\\makebox[0.041\\textwidth][l]{".$_first."}".
    		  "\\makebox[0.041\\textwidth][l]{".$_second."}";
    return $_string;
    }


#######################################################################################
#
#   format resource profile
#
sub resources_profile_line {
    my ($rsc_deliverable,
        $rsc_start,
	$rsc_end,
	$the_array) =@_;

    my $n = @$the_array;    # number of entries
    
    print RSCOUT "\\framebox[0.22\\textwidth][l]{\\raisebox{-1.2ex}[0.0ex][1.1ex]{\\small{".$rsc_deliverable."}}}%\n".
	         "\\framebox[0.098\\textwidth][l]{\\raisebox{-1.2ex}[0.0ex][1.1ex]{\\small{".$rsc_start."}}}%\n".
	         "\\framebox[0.098\\textwidth][l]{\\raisebox{-1.2ex}[0.0ex][1.1ex]{\\small{".$rsc_end."}}}%\n";

    for (my $i=0; $i<$n; $i++) {
	print RSCOUT "\\framebox[0.09\\textwidth][l]{\\raisebox{-1.2ex}[0.0ex][1.1ex]{\\small{".$the_array->[$i]."}}}%\n";
    }
    print RSCOUT "\\vspace*{-0.3ex}\\newline%\n";
}


########################################################################################
#
#   pretty general functions, string and date manipulations
#

sub round {
    my ($number, $digits) = @_;
    my $rounded_number = int(0.5 + (10.**$digits) * $number) / (10.**$digits);
    return $rounded_number;
}
    
sub clean_whitespace {
    my ($_string) = @_;               # @_ is the (list of) arguments
    chomp $_string;                   # remove end of line, if any 
    $_string =~ s/^\s+//;             # remove any leading whitespace
    $_string =~ s/\s+$//;             # remove any trailing whitespace
    $_string =~ s/\s+/ /g;            # convert intermediate whitespace to single blank
    return $_string;
}

sub upper {
    my ($_string) = @_;               # @_ is the (list of) arguments
    $_string =~ s/[a-z]/uc($1)/ge;    # ~= means "transform..."
    return $_string;
}

sub format_date {
    my ($year, $month, $day) = @_;    # @_ is a list of the arguments
    return "$year/$month/$day";
}
    
sub split_date {
    my $date = shift;
    my ($day, $month, $year) = ($date =~ m/(\d+)/g);  # match any set of digits, then repeat for next set
    return ($day, $month, $year);
}

sub days_since_year_start {
#
#   given full date, find the number of days since Jan 1 
#

    my $_date = shift;
    my @days_per_month= ( 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

    my ($_day, $_month, $_year) = &split_date($_date);

    my $_days_this_year = $_day;
    for (my $i=0; $i<$_month-1; $i++) { 
       $_days_this_year += $days_per_month[$i+1];	
    }

#    print STDOUT "dd, mm, yy = ".$_day." ".$_month." ".$_year."   Days since year start = ".$_days_this_year."\n";
    return ($_days_this_year);
}


sub date_to_float_years {
#
#   convert date (e.g. dd-mm-yyyy or dd/mm/yyyy) to floating point year value  yyyy.xyz)  
#   ignore leap years and so on... 
#

    my $_date = shift;  # input argument

    my $_days_this_year = &days_since_year_start($_date); 
    my ($_day, $_month, $_year) = &split_date($_date);
 
    my $_year_as_float = $_year + $_days_this_year / $daysperyear;

#    print STDOUT "dd, mm, yy = ".$_day." ".$_month." ".$_year."   year as float = ".$_year_as_float."\n";
    
#    $_year_as_float = $_year 
    
    return ($_year_as_float);
}















