ハートレートゾーンごとの割合を計算する

 ZwiftでZ2ライドをした時にほんまにZ2でいけたかを計算するために、各ハートレートゾーンごとの割合を出すphpスクリプトを作ってみた。.tcx、.fit、.gpxに対応。バイナリファイルである.fitと、子要素とか使いにくい.gpxはgpsbabelで.tcxに変換。gpsbabelの出力ファイルを-にしたら標準出力に表示してくれた。

#!/usr/bin/php
<?php
error_reporting(E_ERROR);
$margins=array(60,75,85,95);
$zones=array(0,0,0,0,0);
$maxhr = 191;
$duration = 3600;	#unit:second
$file = $argv[1];
$ext = strstr($file,'.');

switch($ext){
	case ".gpx":
		$xml = simplexml_load_string(`gpsbabel -t -i gpx -f $file -o gtrnctr,course=0 -F -`);
		break;
	case ".fit":
		$xml = simplexml_load_string(`gpsbabel -t -i garmin_fit,allpoints=1 -f $file -o gtrnctr,course=0 -F -`);
		break;
	case ".tcx":
		$xml = simplexml_load_file($file);
		break;
	default;
		die("$ext is not supported.");
}
	$elements = $xml->Activities->Activity->Lap->Track->Trackpoint;
	$endtime = strtotime($elements[0]->Time) + $duration ;
	foreach($elements as $element){
		$data[] = array(
			'time' => strtotime($element->Time),
			'hr_ratio' => $element->HeartRateBpm->Value / $maxhr *100
		) ;
	}

foreach($data as $i => $datum){
	if($datum[$i] > $endtime){ break;}
	foreach($margins as $i => $margin){
		if( $datum['hr_ratio'] <= $margin ){
			$zones[$i]++;
			break;
		}
	}
}

foreach($zones as $n => $zone){
	$zones_ratio[$n] = round( ($zone / array_sum($zones)) * 1000) /10;
}
$output = implode("\t",$zones_ratio);

if(getenv('TERM')){
	echo "$output\n";
}else{
	exec("echo $output|zenity --text-info --height=100");
}

?>

 時間を区切っているのはクールダウン部分を除外するため。
 Z2は何%までかについては70%と75%の両方の説があるけど、Zwiftアプリが採用しているらしき75%を採用。

 実行例。