Skip to content

Instantly share code, notes, and snippets.

@LastDragon-ru
Created December 26, 2019 19:16
Show Gist options
  • Save LastDragon-ru/577a94d086fb786735c389271133015b to your computer and use it in GitHub Desktop.
Save LastDragon-ru/577a94d086fb786735c389271133015b to your computer and use it in GitHub Desktop.
Add distance to indoor txc
<?php
namespace App\Console\Commands;
use Carbon\Carbon;
use Illuminate\Console\Command;
use SimpleXMLElement;
class TcxFixCommand extends Command {
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'tcx:fix
{--d|distance= : total distance in meters}
{path : path to tcx file}';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Add distance into indoor tcx.';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct() {
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle() {
// Settings
$path = $this->argument('path');
$distance = (float) $this->option('distance');
// Load
$tcx = simplexml_load_file($path);
foreach ($tcx->Activities as $activities) {
foreach ($activities->Activity as $activity) {
foreach ($activity->Lap as $lap) {
// Add global distance
$this->fixDistance($lap, $distance);
// Process tracks
foreach ($lap->Track as $track) {
$start = Carbon::parse($track->Trackpoint[0]->Time);
$end = Carbon::parse($track->Trackpoint[count($track->Trackpoint) - 1]->Time);
$speed = $distance / ($end->timestamp - $start->timestamp);
foreach ($track->Trackpoint as $point) {
$t = Carbon::parse($point->Time);
$d = $speed * ($t->timestamp - $start->timestamp);
$this->fixDistance($point, $d);
}
}
}
}
}
// Save
$ext = pathinfo($path, PATHINFO_EXTENSION);
$dir = pathinfo($path, PATHINFO_DIRNAME);
$name = pathinfo($path, PATHINFO_FILENAME);
$file = "{$dir}/{$name}.fixed.{$ext}";
$tcx->saveXML($file);
$this->line($file);
return 0;
}
protected function fixDistance(SimpleXMLElement $node, float $distance) {
if (isset($node->DistanceMeters)) {
$node->DistanceMeters = $distance;
} else {
$this->insertAfter($node->TotalTimeSeconds ?: $node->Time, "<DistanceMeters>{$this->distance($distance)}</DistanceMeters>");
}
}
protected function distance(float $distance): string {
return sprintf("%1.1f", $distance);
}
protected function insertAfter(SimpleXMLElement $target, string $insert) {
$target = dom_import_simplexml($target);
$insert = $target->ownerDocument->importNode(dom_import_simplexml(new SimpleXMLElement($insert)), true);
$target->nextSibling
? $target->parentNode->insertBefore($insert, $target->nextSibling)
: $target->parentNode->appendChild($insert);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment