#!/usr/bin/perl

##  Author:		John Freund  jpf11@cornell.edu
##  Script Name:	rccsv2gems.pl
##  Function:		Takes Race Capture Pro (v1.13) csv logs and converts them to a
##			GEMS Data Analysis compatible format
##  Notes:		Thanks to neoraptor on the autosportlabs.org forums for
##			providing the format!
##  Issues:		neoraptor has mentioned that sometimes the logs can have
##			non-numerical data that is erroneous but can cause GEMS DA to
##			reject the import.  This script could be modified to catch
##			those erroenous values and remove them from the output but 
##			that is for a future revision.
##  Version:		1.1
##
##  Changes:		1.1 - Added code to zero_start_time function that handles time
##				rollover at midnight.  Not a complete catch as to make
##				things simpler I assume the log will end before 10am 
##				the next day.  Also fixes time conversion issues for
##				times earlier than 10am as the values did not have
##				leading zeroes (i.e. 00 or 01-09 for hour) by and thus
##				the function I was using for time conversion to epoch
##				time was failing.  I just pad some zeroes in front 
##				right before the conversion, and then I add 86400 secs
##				if we're rolled past midnight.
##				Also got rid of the fill_in_the_blanks function by 
##				rolling it into the zero_start_time function.
##			1.0	initial release
##
##  Usage:		rccsv2gems.pl INPUTFILENAME OUTPUTFILENAME

use strict;
use Text::CSV;
use Scalar::Util 'looks_like_number';
use Time::Piece;

my $script_name="rccsv2gems.pl";
my $version="1.0";

my $file = shift(@ARGV); #takes parameter of RaceCapture Pro csv log to modify for GEMS
my $output = shift(@ARGV);

if (!defined $file) {
	die "Error - No input file specified.\n";
}

if (!defined $output) {
	die "Error - No output file specified,\n";
}


sub modify_headers {
	my @array=@_;
	for(my $i = 0; $i <= $#{$array[0]} ; $i++){
		my @element = split (/\|/, $array[0][$i]);
		$array[0][$i]=$element[0];	
	}
}

sub move_time_to_first_column {
	my @array=@_;
	my $timecolumn="null";
	for(my $i = 0; $i <= $#{$array[0]} ; $i++){
		if ( $array[0][$i] =~ /"Time"/ ) {
			$timecolumn = $i;
		}
	}
	if ($timecolumn == "null"){
		die "Time column is not present in input csv!\n";
	}
	for(my $i = 0; $i <= $#array; $i++){
		my $swap = $array[$i][0];
		$array[$i][0] = $array[$i][$timecolumn];
		$array[$i][$timecolumn] = $swap;
	}
}

sub convert_time {
	my $time=$_[0];
	(my $HHMMSS, my $ms) = split(/\./,$time);
	my $date = Time::Piece->strptime($HHMMSS, "%H%M%S");
	my $epoch_time = $date->epoch;
	my $newtime = "$epoch_time.$ms";
	return $newtime;
}

sub zero_start_time {  #resets the time columns value to start at 0 by subtracting first value, also covers for going over midnight somewhat
	my @array=@_;
	my $base_time="null";
	my $pastmidnight="0";
	my $last_time="0";
	for(my $i = 1; $i <= $#array ; $i++){
		if (( looks_like_number($array[$i][0]) != 0 ) && ( $last_time > 230000 ) && ( $array[$i][0] < 100000 )){
			$pastmidnight="1";
		}
		if (( looks_like_number($array[$i][0]) != 0 ) && ($base_time == "null" )) {
			$last_time=$array[$i][0];
			$base_time=convert_time($array[$i][0]);
			$array[$i][0]="0.000";
			
		}
		else {
			if ( looks_like_number($array[$i][0]) != 0 ) {
				if ( $array[$i][0] < 100000) {
					if ( $array[$i][0] < 10 ) {
							$array[$i][0]="00000$array[$i][0]";
					} elsif ( $array[$i][0] < 100 ) {
                                                        $array[$i][0]="0000$array[$i][0]";
					} elsif ( $array[$i][0] < 1000 ) {
                                                        $array[$i][0]="000$array[$i][0]";
                                        } elsif ( $array[$i][0] < 10000 ) {
                                                        $array[$i][0]="00$array[$i][0]";
                                        } else { $array[$i][0] = "0$array[$i][0]";
					}
					
				}
				my $converted_time = convert_time($array[$i][0]);
				if ( $pastmidnight == "1" ) {
					$converted_time+=86400;
				}	
				my $diff=($converted_time - $base_time);
				$array[$i][0]=sprintf"%.3f",$diff;
			}
		}
	}
	if ($base_time == "null"){
		die "No time values were present!\n";
	}
}

sub strip_ctrlm {
	my @array=@_;
	for(my $i = 0; $i <= $#array ; $i++){
		$array[$i][0] =~ s/\r//g;	
	}
}


sub fill_in_the_blanks {
	my @array = @_;
	my @line = @{ $array[1] };
	for(my $i = 1; $i <= $#array ; $i++){
		for(my $j = 0; $j <= $#{$array[0]} ; $j++){
			if ( looks_like_number($array[$i][$j]) == "0" ) {
				if ( looks_like_number($line[$j]) == "0" ) {
					$line[$j]="0.000";
				}	
				$array[$i][$j]="$line[$j]";
			}
			else {
				$line[$j]=$array[$i][$j];
			}
		}
	}

}


sub main{
	my @data;
	my $csv = Text::CSV->new;
	my $input="$file";
	my $output="$output";
#	my $trash="trashfile";

	print "$script_name - Race Capture Pro CSV to GEMS DA conversion utility v$version\n\n";
	print "Initiating conversion...\n";

	open(INFILE,$input) || die "Can't open file $input";
	open(OUTFILE,">$output") || die "Can't open file $output";
#	open(TRASH,">$trash") || die "Can't open file $trash";

	my $i=0;
	while (<INFILE>) {
		chomp;
		if ($i == 0) {
			push @data, [split /,/];
		}
#		else {
#			if (/"X"/) {   
#			  print TRASH "$_\n";
#			}
#		}
		else {  #Now to deal with the data I want to keep
			if($csv->parse($_)) {       #checks to see if data exists in $_ and parses it if it does
				$i++;
				my @fields=$csv->fields;  # puts the values from each field in an array
				push @data, [ @fields ];
				my $elements=@fields;     #gets the number of elements in the array
			}
		}
	}

        modify_headers(@data);
        move_time_to_first_column(@data);
        zero_start_time(@data);
	strip_ctrlm(@data);
	fill_in_the_blanks(@data);

        for(my $i = 0; $i <= $#data; $i++){
                for(my $j = 0; $j <= $#{$data[0]} ; $j++){
                        if ($#{$data[0]} == $j){
                                print OUTFILE "$data[$i][$j]";
                        }
                        else {
                                print OUTFILE "$data[$i][$j],";
                        }
                }
                print OUTFILE "\r\n";
        }

	close INFILE;
	close OUTFILE;
#	close TRASH;

	print "Success!  Input file $file has been converted to $output.\n"; 
}

main;


