use strict;
use Data::Dumper;
use List::Util qw(sum);

my $dir = $ARGV[0];#資料夾路徑
my $times = $ARGV[1];#模擬次數
my @method = split //,$ARGV[2];#使用行車方法
my $trip;#trip檔名
my %duration;#移動時間
my %routeLength;#路徑總長度
my %waitSteps;#等待總時間
my %timeLoss;#低速時間
my $highList;#CI上限List
my $lowList;#CI下限List
my %Reduration;#重新計算後的移動時間
my %RerouteLength;#重新計算後的路徑總長度
my %RewaitSteps;#重新計算後的等待總時間
my %RetimeLoss;#重新計算後的低速時間
my $msg;#輸出訊息
my @title = qw(None RG RG+PC RG+TLP ALL PC TLP PC+TLP);#輸出內容method title

#初始化hash array
foreach my $key (@method){
	(@{$duration{$key}}, @{$routeLength{$key}}, @{$waitSteps{$key}}, @{$timeLoss{$key}}) = ();
}

#於所有Trip檔中抓出EV的特定欄位，並且加入List
for my $num (0..$times-1){
	foreach my $var (@method){
		#設定檔名
		$trip = "$dir/trip_$var\_$num.txt";
		#print $trip."\n";
		
		#載入trip
		#open FILE, $trip or die "open file $trip error!";
		open FILE, $trip or next;
		while (<FILE>){
			#找出EV的log並且抓取需要的欄位
			if($_ =~ /id="A_0"[\w\W]+duration="([0-9\.]+)"[\w\W]+routeLength="([0-9\.]+)"[\w\W]+waitSteps="([0-9\.]+)"[\w\W]+timeLoss="([0-9\.]+)"/){
				push @{$duration{$var}}, $1;
				push @{$routeLength{$var}}, $2;
				push @{$waitSteps{$var}}, $3;
				push @{$timeLoss{$var}}, $4;
				last;
			}
		}
		close FILE;
	}
	
	#Check同次模擬採用的所有方法都有完成模擬，否則移除不採計
	for (my $var = 1; $var < @method; $var++) {
		if (@{$duration{$method[0]}} > @{$duration{$method[$var]}}) {
			my $index = @{$duration{$method[0]}}-1; 
			foreach my $key (@method){
				splice @{$duration{$key}},$index,1;
				splice @{$routeLength{$key}},$index,1;
				splice @{$waitSteps{$key}},$index,1;
				splice @{$timeLoss{$key}},$index,1;
			}
			last;
		}elsif(@{$duration{$method[0]}} < @{$duration{$method[$var]}}) {
			my $index = @{$duration{$method[$var]}}-1;
			foreach my $key (@method){
				splice @{$duration{$key}},$index,1;
				splice @{$routeLength{$key}},$index,1;
				splice @{$waitSteps{$key}},$index,1;
				splice @{$timeLoss{$key}},$index,1;
			}
			last;
		}
	}
}
#print Dumper(\%duration);

#當數值超過3筆才進行CI計算
if (@{$duration{$method[0]}} > 3) {
	#取得CI區間值
	($highList, $lowList) = &CI(%duration);

	#移除CI區間之外的數值
	foreach my $key (keys %duration){
		for(my $var = @{$duration{$key}}-1; $var >= 0; $var--){
			#移除上界
			if ($duration{$key}[$var]>$$highList{$key}[0]) {
				splice @{$duration{$key}},$var,1;
				splice @{$routeLength{$key}},$var,1;
				splice @{$waitSteps{$key}},$var,1;
				splice @{$timeLoss{$key}},$var,1;
			}
=head
			#移除下界
			elsif ($duration{$key}[$var]<$$lowList{$key}[0]) {
				splice @{$duration{$key}},$var,1;
				splice @{$routeLength{$key}},$var,1;
				splice @{$waitSteps{$key}},$var,1;
				splice @{$timeLoss{$key}},$var,1;
			}
=cut
		}
	}
}

#當沒有可用資料時直接補0
if (@{$duration{$method[0]}} == 0) {
	foreach my $key (@method){
		$duration{$key}[0] = 0;
		$routeLength{$key}[0] = 0;
		$waitSteps{$key}[0] = 0;
		$timeLoss{$key}[0] = 0;
	}
}

#重新取得平均值
%Reduration = &AVG(%duration);
%RerouteLength = &AVG(%routeLength);
%RewaitSteps = &AVG(%waitSteps);
%RetimeLoss = &AVG(%timeLoss);

#輸出結果
$msg = "Trip";
foreach my $i (@title){
	$msg .= "\t$i";
}
$msg .="\nduration";
foreach my $i (@method){
	$msg .= "\t" . $Reduration{$i}[0];
}
$msg .="\nrouteLength";
foreach my $i (@method){
	$msg .= "\t" . $RerouteLength{$i}[0];
}
$msg .="\nwaitSteps";
foreach my $i (@method){
	$msg .= "\t" . $RewaitSteps{$i}[0];
}
$msg .="\ntimeLoss";
foreach my $i (@method){
	$msg .= "\t" . $RetimeLoss{$i}[0];
}
#print $msg . "\n";

#輸出檔案
open OUTFILE, ">$dir/trip.txt";
print OUTFILE $msg;
close OUTFILE;

#接收hash of arry並且計算平均值
sub AVG{
	my %list = @_;
	my %result;
	
	for my $key (keys %list){
		$result{$key}[0] = sum(@{$list{$key}})/@{$list{$key}};
	}
	return %result;
}

#Standard Deviation
sub STD{
	my %list = @_;
	my %average = &AVG(%list);
	my %sqtotal;
	my %result;
	
	foreach my $key (keys %list){
		for my $i (0..@{$list{$key}}-1){
			$sqtotal{$key}[0] += ($average{$key}[0]-$list{$key}[$i]) ** 2;
		}
	}

	foreach my $key (keys %list){
		$result{$key}[0] = ($sqtotal{$key}[0]/(@{$list{$key}})) ** 0.5;
	}
	return %result;
}

#Confidence interval
sub CI{
	my %list = @_;
	my %average = &AVG(%list);
	my %std = &STD(%list);
	my %high;
	my %low;

	foreach my $key (keys %list){
		push @{$high{$key}}, ($average{$key}[0]+1.96*($std{$key}[0]/(@{$list{$key}} ** 0.5)));
		push @{$low{$key}}, ($average{$key}[0]-1.96*($std{$key}[0]/(@{$list{$key}} ** 0.5)));
	}
	return (\%high, \%low);
}
