#!/usr/bin/perl -w
# (C) Jochen Puchalla 2005-2010

$steigdist=200; # minimum distance for climbing percentage calculation
# $deltat=20; # seconds between points
$g=9.81; # gravitation
$cw=0.4; # air resistance
$rho=1.2; # air density
$roll=0.003; # roll resistance
$minspeed=1.4; # ignore lower speeds than 1.4 m/s (5 km/h)
$mindeltah=1.5; # ignore height noise

use GD::Simple;

foreach $file (@ARGV)
{
	if (! open(INPUT,"<$file") )
	{
		print STDERR "Can't open input file $file\n";
		next;
	}

	$filecore=$file;
	$filecore =~ s/.tour$//g;

	if ($file eq $filecore)
	{
		print STDERR "$file is not a tour file\n";
		$bad++;
		next;
	}

	# open output file:
	if (! open(OUTPUT,">$filecore.png") ) { print STDERR "Can't open output file $filecore.png\n"; $bad++; next; }
	print "Generating $filecore.png\n";

	# open gnuplot data file:
	if (! open(GOUTPUT,">gnuplot.dat") ) { print STDERR "Can't open output file gnuplot.dat\n"; $bad++; next; }
	printf GOUTPUT ("#Dist Alt Speed Power Rollpower Climbpower Accelpower Airpower\n");
	print "Generating $filecore-data.png\n";

	$distdiff=2000; # resolution for numbered length scale

	# set values to 0 for every new file:
	$sums=0;
	$sumt=0;
	$sumh=0;
	$work=0;
	$count=0;
	$maxcount=0;
	$h_max=10;
	$s_max=0;
	$shift=0;
	$minus=-1;

	# initialize some values:
	$v[1]=0;
	$power[1]=0;
	$rollp[1]=0;
	$airp[1]=0;
	$climbp[1]=0;
	$accelp[1]=0;
	$seconds[0]=0;
	$maxspeed=50; # km/h to display

	while ($line=<INPUT>)
	{
		if ($line =~ /^Date=/)
		{
			@temp = split(/=/, $line);
			$date=$temp[1];
			chop $date;
			if ($date =~ /^$/) {$date="unknown date";}
		}
		if ($line =~ /^Title=/)
		{
			@temp = split(/=/, $line);
			$title=$temp[1];
			chop $title;
			if ($title =~ /^$/) {$title="untitled";}
		}
		if ($line =~ /^Start=/)
		{
			@temp = split(/=/, $line);
			$start=$temp[1];
			chop $start;
			if ($start =~ /^$/) {$start="untitled";}
		}
		if ($line =~ /^Finish=/)
		{
			@temp = split(/=/, $line);
			$finish=$temp[1];
			chop $finish;
			if ($finish =~ /^$/) {$finish="untitled";}
		}
		if ($line =~ /^Weight=/)
		{
			@temp = split(/=/, $line);
			$W=$temp[1];
			chop $W;
		}
		if ($line =~ /^Speed=/)
		{
			@temp = split(/=/, $line);
			@temp2 = split(/;/, $temp[1]);
			$topspeed=$temp2[0];
			if ($topspeed > $maxspeed) {$maxspeed = sprintf ("%.0f", $topspeed/10)*11;}
# 			print "$maxspeed";
		}
		if ($line =~ /^Temperature=/)
		{
			@temp = split(/=/, $line);
			@temp = split(/;/, $temp[1]);
			$celsius=$temp[1]; # take medium value
		}
		if ($line =~ /#Pulse/) # data starts
		{
			while ($line=<INPUT>) # read all data into buffer
			{
#				if ($line =~ /\d/) {printf("%s hallo\n",$line);last;}
				@value = split(/\t/, $line); #split at tabs
				if ($line =~ /^$/) {last;}
				$count++;
				$h[$count]=$value[3]; # Höhe
				$s[$count]=$value[7]; # Strecke
				$time[$count]=$value[12]; # Zeitinfo
				@part = split(/\:/, $time[$count]); #split at :
				$seconds[$count]=$part[0]*3600+$part[1]*60+$part[2]; # Sekunden
# 				print $seconds[$count]." ";
				$deltat=$seconds[$count]-$seconds[$count-1];
				$s_max=$s[$count]; # total distance
				if($h[$count]>$h_max){$h_max=$h[$count];} # maximum height
				if($h[$count]<$minus*$shift) {$shift=$minus*$h[$count];} # negative heights?

				if ($count>1) # ab 2. Datenpunkt
				{
					$v[$count]=($s[$count]-$s[$count-1])/$deltat;          # speed
					if ($v[$count]>$minspeed){$sums=$sums+($s[$count]-$s[$count-1]);$sumt=$sumt+$deltat;} # if v > minimum speed sum up distance
					if ($h[$count]-$h[$count-1]>$mindeltah){$sumh=$sumh+($h[$count]-$h[$count-1]);} # if delta h > x m count height
					$climbp[$count]=($h[$count]-$h[$count-1])*$g*$W/$deltat;         # climb
					$accelp[$count]=$W/2*($v[$count]**2-$v[$count-1]**2)/$deltat;         # accel
					$airp[$count]=$cw/2*$rho*$v[$count]**3;       # air
					$rollp[$count]=$roll*$W*$g*$v[$count];         # roll
					$power[$count]=$climbp[$count]+$accelp[$count]+$airp[$count]+$rollp[$count]; # total power
					if ($power[$count]<0){$power[$count]=0;} # negative power means braking!
					if ($v[$count]>$minspeed){$work=$work+$power[$count]*20;} # if v > minimum speed sum up work
				}
				printf GOUTPUT ("%.2f  $h[$count]  %.2f  $power[$count]  $rollp[$count]  $climbp[$count]  $accelp[$count]  $airp[$count] \n",$s[$count]/1000,$v[$count]*3.6);
			}
		}
	}

	if($sumt<600){unlink("$filecore.png"); printf STDOUT "Too little data to plot\n"; next;} # too little data to plot!

	# Durchschnittsgeschw.:
	$geschw=int($sums/$sumt*360)/100;

	# Durchschnittsleistung:
	$leistung=int($work/$sumt);

	# NO NEGATIVE HEIGHTS!
	$i=0;
	while ($i < $count) { $i++; $h[$i]=$h[$i]+$shift; }
	$h_max=$h_max+$shift;

########################### print with libgd here:

	# Picture Sizes:
	$xoff=20;	# left offset
	$legend=110;	# key width
	$xres=$s_max/50+$xoff+$legend;  # picture width
	if ($xres<$xoff+$legend+360){$xres=$xoff+$legend+360;} 	# minimum picture width
	$xpart=$xres-$xoff-$legend; 	# drawing width
	$ypart=sqrt($h_max)*20;		# drawing height
	$yres=$ypart+80;	# picture height
	if ($yres<260){$yres=260;} 	# minimum picture height
	$yoff=$yres-40;		# bottom offset

	# create a new image
	$img = GD::Simple->new($xres,$yres);
	$img->bgcolor('white');
	$img->fgcolor('blue');

	# allocate some colors
	$col1= $img->colorAllocate(0,16,48); #<-11
	$col2= $img->colorAllocate(0,8,128); #-10
	$col3= $img->colorAllocate(0,0,255); #-8
	$col4= $img->colorAllocate(0,128,255); #-6
	$col5= $img->colorAllocate(0,192,224); #-4
	$col6= $img->colorAllocate(48,224,224); #-2

	$col7= $img->colorAllocate(224,224,224); #0

	$col8= $img->colorAllocate(224,224,48); #+2 gelb
	$col9= $img->colorAllocate(224,192,0); #+4 orange
	$col10= $img->colorAllocate(255,128,0); #+6
	$col11= $img->colorAllocate(255,0,0); #+8 rot
	$col12= $img->colorAllocate(128,8,0); #+10
	$col13= $img->colorAllocate(48,16,0); #>+11

	#START NAME AND HEIGHT:
    $img->angle(-90);
	$img->fgcolor('black');$img->bgcolor('black');
	$img->moveTo($xoff-1,$yoff+22);
	$img->string('- ' . $start . " - " . $h[1] . "m");
    $img->angle(0);

	#TITLE AND HM:
	$img->fgcolor('black');$img->bgcolor('black');
	$img->moveTo($xres*0.5-210,15);
	$img->string($date . " - " . $title . " - " . $sumh . " Hm" . "  " . $geschw . " km/h" . "  " . $leistung . " W" . "  " . $celsius . " C");

	$h_finish=$h[$count];
	$maxcount=$count;
	$count=0;
	$minsteig=0;
	$maxsteig=0;
	$h[0]=$h[1];
	$s[0]=$s[1];
	$olds=$s[1];
	$oldh=$h[1];

	#PRINT PROFILE:
	while ($count < $maxcount)
	{
		$count++;

		if($s[$count]-$olds < $steigdist){next;} # Teilstrecke lang genug f�r Plot?
		$steig[$count] = ($h[$count]-$oldh) / ($s[$count]-$olds) *100 ; # Steigung
		if($steig[$count] < $minsteig){$minsteig=$steig[$count]} # maximales Gef�lle
		if($steig[$count] > $maxsteig){$maxsteig=$steig[$count]} # maximale Steigung
		$img->fgcolor($col1);$img->bgcolor($col1);
		if ($steig[$count]>-11){$img->fgcolor($col2);$img->bgcolor($col2);}
		if ($steig[$count]>-9){$img->fgcolor($col3);$img->bgcolor($col3);}
		if ($steig[$count]>-7){$img->fgcolor($col4);$img->bgcolor($col4);}
		if ($steig[$count]>-5){$img->fgcolor($col5);$img->bgcolor($col5);}
		if ($steig[$count]>-3){$img->fgcolor($col6);$img->bgcolor($col6);}
		if ($steig[$count]>-1){$img->fgcolor($col7);$img->bgcolor($col7);}
		if ($steig[$count]>1){$img->fgcolor($col8);$img->bgcolor($col8);}
		if ($steig[$count]>3){$img->fgcolor($col9);$img->bgcolor($col9);}
		if ($steig[$count]>5){$img->fgcolor($col10);$img->bgcolor($col10);}
		if ($steig[$count]>7){$img->fgcolor($col11);$img->bgcolor($col11);}
		if ($steig[$count]>9){$img->fgcolor($col12);$img->bgcolor($col12);}
		if ($steig[$count]>11){$img->fgcolor($col13);$img->bgcolor($col13);}
		my $poly = new GD::Polygon;
#		print "s_max=$s_max xpart=$xpart h_max=$h_max ypart=$ypart s(count)=$s[$count]\n";		# debug
		$poly->addPt($xoff+($s[$count]/$s_max*$xpart),$yoff-($h[$count]/$h_max*$ypart)); #ro
		$poly->addPt($xoff+($olds/$s_max*$xpart),$yoff-($oldh/$h_max*$ypart)); #lo
		$poly->addPt($xoff+($olds/$s_max*$xpart),$yoff); #lu
		$poly->addPt($xoff+($s[$count]/$s_max*$xpart),$yoff); #ru
		$img->penSize(1,1);
		$img->polygon($poly);

		$olds=$s[$count]; $oldh=$h[$count];
	}

	#PRINT SPEED 0-$maxspeed km/h:
	$img->fgcolor($col12);
	$count=1;
	$olds=$s[1];
	$oldv=$v[1];
	while ($count < $maxcount)
	{
		$count++;

		$img->moveTo($xoff+($olds/$s_max*$xpart),$yoff-($oldv/$maxspeed*3.6*$ypart));
		$img->lineTo($xoff+($s[$count]/$s_max*$xpart),$yoff-($v[$count]/$maxspeed*3.6*$ypart)); # speed
#		print "s_max=$s_max xpart=$xpart h_max=$h_max ypart=$ypart s(count)=$s[$count]\n";		# debug

		$olds=$s[$count]; $oldv=$v[$count];
	}

	#HIGHT LINES AND SPEED:
	$img->fgcolor('black');
	$height=0;
	$hdiff=20;	# Linienabstand Höhenmeter
	if($h_max>200){$hdiff=int($h_max/100)*10;}
	if($h_max>1000){$hdiff=int($h_max/1000)*100;}
	while ($height < $h_max-$hdiff/2)
	{
		$img->moveTo($xoff+0,$yoff-($height/$h_max*$ypart));
		$img->string($height . 'm' . ' ' . int($height/$h_max*$maxspeed) . 'km/h');
		$img->lineTo($xres-$legend,$yoff-($height/$h_max*$ypart));
		$height=$height+$hdiff;
	}

	#PRINT HIGHEST AND LOWEST SLOPES
	$count=0;
	$alt=1;
	$h[0]=$h[1];
	$s[0]=$s[1];
	$olds=$s[1];
	$oldh=$h[1];
    $img->angle(-90);
	while ($count < $maxcount)
	{
		$count++;
		if($s[$count]-$olds < $steigdist){next;}
		$steig[$count] = ($h[$count]-$oldh) / ($s[$count]-$olds) *100 ; #Steigung
		if($steig[$count]>$maxsteig*0.9 || $steig[$count]<$minsteig*0.9 || abs($steig[$count])>9.9999)
		{
			$steig=abs(int($steig[$count]*10)/10);
#			if($steig<2){break;}
			$img->fgcolor('white');
			$img->moveTo($xoff+9+($olds/$s_max*$xpart),$yoff-1);
			$img->string($steig . '%');
			$img->moveTo($xoff+7+($olds/$s_max*$xpart),$yoff-1);
			$img->string($steig . '%');
			$img->moveTo($xoff+9+($olds/$s_max*$xpart),$yoff+1);
			$img->string($steig . '%');
			$img->moveTo($xoff+7+($olds/$s_max*$xpart),$yoff+1);
			$img->string($steig . '%');
			$img->fgcolor('black');
			$img->moveTo($xoff+8+($olds/$s_max*$xpart),$yoff);
			$img->string($steig . '%');
			$alt=$alt*(-1);
		}
		$olds=$s[$count]; $oldh=$h[$count];
	}
    $img->angle(0);

	#H_MAX:
	$img->moveTo($xoff+0,$yoff-($ypart));
	$img->string($h_max . 'm' . ' ' . $maxspeed . 'km/h');
	$img->lineTo($xres-$legend,$yoff-($ypart));

	#KM:
	$img->fgcolor('black');
    $img->angle(-90);
	$dist=0;
	$bw=1;
	while ($dist < $s_max-$distdiff)
	{
		#LINIE UND ZAHL:
		$img->fgcolor('black');$img->bgcolor('black');
		$img->moveTo($xoff+$dist/$s_max*$xpart,$yoff+32);
		$img->string($dist/1000);
		$img->moveTo($xoff+$dist/$s_max*$xpart,$yoff+28); #unten
		$img->lineTo($xoff+$dist/$s_max*$xpart,$yoff); #oben
		#EISENBAHNFELD:
		my $poly = new GD::Polygon;
		if($bw<0){$img->bgcolor('white');}
		$poly->addPt($xoff+$dist/$s_max*$xpart,$yoff); #lo
		$poly->addPt($xoff+($dist+$distdiff)/$s_max*$xpart,$yoff); #ro
		$poly->addPt($xoff+($dist+$distdiff)/$s_max*$xpart,$yoff+5); #ru
		$poly->addPt($xoff+$dist/$s_max*$xpart,$yoff+5); #lu
		$img->penSize(1,1);
		$img->polygon($poly);
		$bw=$bw*(-1); #B/W-Flag
		#WEITERGEHEN:
		$dist=$dist+$distdiff;
	}

	#LETZTE LINIE UND ZAHL:
	$img->fgcolor('black');$img->bgcolor('black');
	$img->moveTo($xoff+$dist/$s_max*$xpart,$yoff+32);
	$img->string($dist/1000);
	$img->moveTo($xoff+$dist/$s_max*$xpart,$yoff+28); #unten
	$img->lineTo($xoff+$dist/$s_max*$xpart,$yoff); #oben

	#LETZTES EISENBAHNFELD:
	my $poly = new GD::Polygon;
	if($bw<0){$img->bgcolor('white');}
	$poly->addPt($xoff+$dist/$s_max*$xpart,$yoff); #lo
	$poly->addPt($xoff+$s_max/$s_max*$xpart,$yoff); #ro
	$poly->addPt($xoff+$s_max/$s_max*$xpart,$yoff+5); #ru
	$poly->addPt($xoff+$dist/$s_max*$xpart,$yoff+5); #lu
	$img->penSize(1,1);
	$img->polygon($poly);

	#S_MAX UND FINISH NAME AND HEIGHT:
	$img->fgcolor('black');$img->bgcolor('black');
	$img->moveTo($xoff+14+$xpart,$yoff+32);
	$img->string($s_max/1000 . 'km - ' . $finish . " - " . $h_finish . "m");
	$img->moveTo($xoff+$s_max/$s_max*$xpart,$yoff+28);
	$img->lineTo($xoff+$s_max/$s_max*$xpart,$yoff);

	#LEGENDE:
    $img->angle(0);
	my $poly2 = new GD::Polygon;
	$img->fgcolor($col1);$img->bgcolor($col1);
	$poly2->addPt($xres-20,0);
	$poly2->addPt($xres,0);
	$poly2->addPt($xres,20);
	$poly2->addPt($xres-20,20);
	$img->polygon($poly2);
	$img->fgcolor('black');
	$img->moveTo( $xres-60,17 );
	$img->string('< -11%');

	my $poly3 = new GD::Polygon;
	$img->fgcolor($col2);$img->bgcolor($col2);
	$poly3->addPt($xres-20,20);
	$poly3->addPt($xres,20);
	$poly3->addPt($xres,40);
	$poly3->addPt($xres-20,40);
	$img->polygon($poly3);
	$img->fgcolor('black');
	$img->moveTo( $xres-90,37 );
	$img->string('-11% - -9%');

	my $poly4 = new GD::Polygon;
	$img->fgcolor($col3);$img->bgcolor($col3);
	$poly4->addPt($xres-20,40);
	$poly4->addPt($xres,40);
	$poly4->addPt($xres,60);
	$poly4->addPt($xres-20,60);
	$img->polygon($poly4);
	$img->fgcolor('black');
	$img->moveTo( $xres-90,57 );
	$img->string('-9% - -7%');

	my $poly5 = new GD::Polygon;
	$img->fgcolor($col4);$img->bgcolor($col4);
	$poly5->addPt($xres-20,60);
	$poly5->addPt($xres,60);
	$poly5->addPt($xres,80);
	$poly5->addPt($xres-20,80);
	$img->polygon($poly5);
	$img->fgcolor('black');
	$img->moveTo( $xres-84,77 );
	$img->string('-7% - -5%');

	my $poly6 = new GD::Polygon;
	$img->fgcolor($col5);$img->bgcolor($col5);
	$poly6->addPt($xres-20,80);
	$poly6->addPt($xres,80);
	$poly6->addPt($xres,100);
	$poly6->addPt($xres-20,100);
	$img->polygon($poly6);
	$img->fgcolor('black');
	$img->moveTo( $xres-84,97 );
	$img->string('-5% - -3%');

	my $poly7 = new GD::Polygon;
	$img->fgcolor($col6);$img->bgcolor($col6);
	$poly7->addPt($xres-20,100);
	$poly7->addPt($xres,100);
	$poly7->addPt($xres,120);
	$poly7->addPt($xres-20,120);
	$img->polygon($poly7);
	$img->fgcolor('black');
	$img->moveTo( $xres-84,117 );
	$img->string('-3% - -1%');

	my $poly8 = new GD::Polygon;
	$img->fgcolor($col7);$img->bgcolor($col7);
	$poly8->addPt($xres-20,120);
	$poly8->addPt($xres,120);
	$poly8->addPt($xres,140);
	$poly8->addPt($xres-20,140);
	$img->polygon($poly8);
	$img->fgcolor('black');
	$img->moveTo( $xres-84,137 );
	$img->string('-1% - +1%');

	my $poly9 = new GD::Polygon;
	$img->fgcolor($col8);$img->bgcolor($col8);
	$poly9->addPt($xres-20,140);
	$poly9->addPt($xres,140);
	$poly9->addPt($xres,160);
	$poly9->addPt($xres-20,160);
	$img->polygon($poly9);
	$img->fgcolor('black');
	$img->moveTo( $xres-84,157 );
	$img->string('+1% - +3%');

	my $poly10 = new GD::Polygon;
	$img->fgcolor($col9);$img->bgcolor($col9);
	$poly10->addPt($xres-20,160);
	$poly10->addPt($xres,160);
	$poly10->addPt($xres,180);
	$poly10->addPt($xres-20,180);
	$img->polygon($poly10);
	$img->fgcolor('black');
	$img->moveTo( $xres-84,177 );
	$img->string('+3% - +5%');

	my $poly11 = new GD::Polygon;
	$img->fgcolor($col10);$img->bgcolor($col10);
	$poly11->addPt($xres-20,180);
	$poly11->addPt($xres,180);
	$poly11->addPt($xres,200);
	$poly11->addPt($xres-20,200);
	$img->polygon($poly11);
	$img->fgcolor('black');
	$img->moveTo( $xres-84,197 );
	$img->string('+5% - +7%');

	my $poly12 = new GD::Polygon;
	$img->fgcolor($col11);$img->bgcolor($col11);
	$poly12->addPt($xres-20,200);
	$poly12->addPt($xres,200);
	$poly12->addPt($xres,220);
	$poly12->addPt($xres-20,220);
	$img->polygon($poly12);
	$img->fgcolor('black');
	$img->moveTo( $xres-84,217 );
	$img->string('+7% - +9%');

	my $poly13 = new GD::Polygon;
	$img->fgcolor($col12);$img->bgcolor($col12);
	$poly13->addPt($xres-20,220);
	$poly13->addPt($xres,220);
	$poly13->addPt($xres,240);
	$poly13->addPt($xres-20,240);
	$img->polygon($poly13);
	$img->fgcolor('black');
	$img->moveTo( $xres-90,237 );
	$img->string('+9% - +11%');

	my $poly14 = new GD::Polygon;
	$img->fgcolor($col13);$img->bgcolor($col13);
	$poly14->addPt($xres-20,240);
	$poly14->addPt($xres,240);
	$poly14->addPt($xres,260);
	$poly14->addPt($xres-20,260);
	$img->polygon($poly14);
	$img->fgcolor('black');
	$img->moveTo( $xres-60,257 );
	$img->string('> +11%');

	print OUTPUT $img->png;
	close OUTPUT;
	close GOUTPUT;
	close INPUT;

	if (-z "$filecore.png"){remove("$filecore.png")};

########################### print with gnuplot here:

open(GNUPLOT,"|gnuplot ") || die("can't call gnuplot \n");
GNUPLOT->autoflush(1);
print GNUPLOT <<"--END--";
set term png enhanced large size 1280,800
set out "gnuplot.png"
set grid
set mxtics 5
set lmargin 5
set rmargin 4
set tmargin 0
set bmargin 2
set style data lines
set multiplot
set size 1,0.32
set origin 0,0
plot "gnuplot.dat" using 1:4 title "Leistung [W]" linewidth 3 lt 2
replot "gnuplot.dat" using 1:4 smooth bezier title "ca. Leistung [W]" linewidth 3 lt 1
#unset xtics
set origin 0,0.32
plot "gnuplot.dat" using 1:3 title "Geschw. [km/h]" linewidth 3 lt 3
set origin 0,0.64
set title "$date $title (von $start nach $finish)  $sumh Hm  $geschw km/h  $leistung W  $celsius C" 0,-1
plot "gnuplot.dat" using 1:2 title 'Hoehe [m]' linewidth 3 lt -1
#replot "gnuplot.dat" using 1:5 title "Rollwiderstand [W]" linewidth 3
#replot "gnuplot.dat" using 1:6 title "Steigleistung [W]" linewidth 3
#replot "gnuplot.dat" using 1:7 title "Beschl.leistung [W]" linewidth 3
#replot "gnuplot.dat" using 1:8 title "Luftwiderstand [W]" linewidth 3
--END--
close(GNUPLOT);
rename "gnuplot.png","$filecore-data.png";
unlink("gnuplot.dat");
}

exit(0);
