/** * Get a workout from a string. * * @param string $string The data. * @return \SportTrackerConnector\Workout\Workout */ public function fromString($string) { $simpleXML = new SimpleXMLElement($string); $workout = new Workout(); if (isset($simpleXML->metadata->author->name)) { $workout->setAuthor(new Author($simpleXML->metadata->author->name)); } foreach ($simpleXML->trk as $simpleXMLTrack) { $track = new Track(); // Sport. if (isset($simpleXMLTrack->type)) { $track->setSport(SportGuesser::getSportFromCode($simpleXMLTrack->type)); } // Track points. foreach ($simpleXMLTrack->trkseg->trkpt as $point) { $attributes = $point->attributes(); $dateTime = new DateTime($point->time); $trackPoint = new TrackPoint((string) $attributes['lat'], (string) $attributes['lon'], $dateTime); $trackPoint->setElevation((int) $point->ele); if (isset($point->extensions)) { $trackPoint->setExtensions($this->parseExtensions($point->extensions)); } $track->addTrackPoint($trackPoint); } $workout->addTrack($track); } return $workout; }
/** * Get a workout from a string. * * @param string $string The data. * @return \SportTrackerConnector\Workout\Workout */ public function fromString($string) { $simpleXML = new SimpleXMLElement($string); $workout = new Workout(); foreach ($simpleXML->Activities[0] as $simpleXMLActivity) { $workoutTrack = new Track(); // Sport. $attributes = $simpleXMLActivity->attributes(); if (isset($attributes['Sport'])) { $workoutTrack->setSport(SportGuesser::getSportFromCode((string) $attributes['Sport'])); } // Track points. foreach ($simpleXMLActivity->Lap as $lap) { foreach ($lap->Track as $track) { foreach ($track->Trackpoint as $trackPoint) { $dateTime = new DateTime($trackPoint->Time); $latitude = (string) $trackPoint->Position->LatitudeDegrees; $longitude = (string) $trackPoint->Position->LongitudeDegrees; $workoutTrackPoint = new TrackPoint($latitude, $longitude, $dateTime); $workoutTrackPoint->setElevation(round((double) $trackPoint->AltitudeMeters, 2)); if ($trackPoint->DistanceMeters) { $workoutTrackPoint->setDistance($trackPoint->DistanceMeters); } $extensions = $this->parseExtensions($trackPoint); $workoutTrackPoint->setExtensions($extensions); $workoutTrack->addTrackPoint($workoutTrackPoint); } } } $workout->addTrack($workoutTrack); } return $workout; }
/** * Test setting/getting the author. */ public function testSetGetAuthor() { $workout = new Workout(); $this->assertNull($workout->getAuthor()); $author = new Author(); $workout->setAuthor($author); $this->assertSame($author, $workout->getAuthor()); }
/** * Test dumping a workout to a TCX string. */ public function testDumpToStringMultiActivity() { $workout = new Workout(); $workout->addTrack(new Track(array($this->getTrackPoint('53.551075', '9.993672', '2014-05-30T17:12:58+00:00', 11, null, 78), $this->getTrackPoint('53.550085', '9.992682', '2014-05-30T17:12:59+00:00', 10, 128, 88)), SportMapperInterface::RUNNING)); $workout->addTrack(new Track(array($this->getTrackPoint('53.549075', '9.991672', '2014-05-30T17:13:00+00:00', 9, 258, 98), $this->getTrackPoint('53.548085', '9.990682', '2014-05-30T17:13:01+00:00', 8, 456, 108)), SportMapperInterface::SWIMMING)); $tcx = new TCX(); $actual = $tcx->dumpToString($workout); $this->assertXmlStringEqualsXmlFile(__DIR__ . '/Expected/testDumpToStringMultiActivity.tcx', $actual); }
/** * Test loading a workout from a string with multiple activities. */ public function testFromStringMultiActivity() { $expected = new Workout(); $expected->addTrack(new Track(array($this->getTrackPoint('53.551075', '9.993672', '2014-05-30T17:12:58+00:00', 11, 0, 78), $this->getTrackPoint('53.550085', '9.992682', '2014-05-30T17:12:59+00:00', 10, 128, 88)), SportMapperInterface::RUNNING)); $expected->addTrack(new Track(array($this->getTrackPoint('53.549075', '9.991672', '2014-05-30T17:13:00+00:00', 9, null, 98), $this->getTrackPoint('53.548085', '9.990682', '2014-05-30T17:13:01+00:00', 8, 258, 108)), SportMapperInterface::SWIMMING)); $tcx = new TCX(); $actual = $tcx->fromString(file_get_contents(__DIR__ . '/Fixtures/testFromStringMultiActivity.tcx')); $this->assertEquals($expected, $actual); }
/** * Dump a workout to string. * * @param Workout $workout The workout to dump. * @return string */ public function dumpToString(Workout $workout) { $data = array(); $tracks = $workout->getTracks(); foreach ($tracks as $track) { $data[] = array('workout' => array('points' => $this->writeTrackPoints($track->getTrackpoints()))); } return json_encode($data, JSON_PRETTY_PRINT); }
/** * Test loading a workout from a GPX string with multiple tracks. */ public function testFromStringMultiTrack() { $expected = new Workout(); $expected->addTrack(new Track(array($this->getTrackPoint('53.551075', '9.993672', '2014-05-30T17:12:58+00:00', 11, 78), $this->getTrackPoint('53.550085', '9.992682', '2014-05-30T17:12:59+00:00', 10, 88)), SportMapperInterface::RUNNING)); $expected->addTrack(new Track(array($this->getTrackPoint('53.549075', '9.991672', '2014-05-30T17:13:00+00:00', 9, 98), $this->getTrackPoint('53.548085', '9.990682', '2014-05-30T17:13:01+00:00', 8, 108)), SportMapperInterface::SWIMMING)); $expected->setAuthor(new Author('John Doe')); $gpx = new GPX(); $actual = $gpx->fromString(file_get_contents(__DIR__ . '/Fixtures/testFromStringMultiTrack.gpx')); $this->assertEquals($expected, $actual); }
/** * Test dumping a workout to a GPX string. */ public function testDumpToStringMultiTrack() { $workout = new Workout(); $workout->addTrack(new Track(array($this->getTrackPoint('53.551075', '9.993672', '2014-05-30T17:12:58+00:00', 11, 0, 78), $this->getTrackPoint('53.550085', '9.992682', '2014-05-30T17:12:59+00:00', 10, 10, 88)), SportMapperInterface::RUNNING)); $workout->addTrack(new Track(array($this->getTrackPoint('53.549075', '9.991672', '2014-05-30T17:13:00+00:00', 9, null, 98), $this->getTrackPoint('53.548085', '9.990682', '2014-05-30T17:13:01+00:00', 8, null, 108)), SportMapperInterface::SWIMMING)); $workout->setAuthor(new Author('John Doe')); $gpx = new JSON(); $actual = $gpx->dumpToString($workout); $this->assertJsonStringEqualsJsonFile(__DIR__ . '/Expected/testDumpToStringMultiTrack.json', $actual); }
/** * Test dump unknown extensions throws no error. */ public function testDumpUnknownExtensionsThrowsNoError() { $workout = new Workout(); $trackPoint = $this->getTrackPoint('53.551075', '9.993672', '2014-05-30T17:12:58+00:00', 11, 78); $genericExtensions = $this->getMockForAbstractClass('SportTrackerConnector\\Workout\\Workout\\Extension\\AbstractExtension'); $trackPoint->addExtension($genericExtensions); $workout->addTrack(new Track(array($trackPoint), SportMapperInterface::RUNNING)); $gpx = new GPX(); $actual = $gpx->dumpToString($workout); $this->assertXmlStringEqualsXmlFile(__DIR__ . '/Expected/testDumpUnknownExtensionsThrowsNoError.gpx', $actual); }
/** * Test fetching a workout with multiple sports from an HTML page. */ public function testFetchWorkoutFromHTMLWithMultiSport() { $idWorkout = 1; $loggerMock = $this->getMock('Psr\\Log\\LoggerInterface'); $workoutTCX = file_get_contents(__DIR__ . '/Fixtures/workout-multi.tcx'); $polarAPIMock = $this->getPolarAPIMock(array('fetchWorkoutTCX')); $polarAPIMock->expects($this->once())->method('fetchWorkoutTCX')->with($idWorkout)->willReturn($workoutTCX); $polarMock = $this->getMock('SportTrackerConnector\\Tracker\\Polar\\Tracker', array('getPolarAPI'), array($loggerMock)); $polarMock->expects($this->once())->method('getPolarAPI')->willReturn($polarAPIMock); $expected = new Workout(); $expected->addTrack(new Track(array($this->getTrackPoint('53.551075', '9.993672', '2014-05-30T17:12:58+00:00', '-4.11', 78), $this->getTrackPoint('53.550085', '9.992682', '2014-05-30T17:12:59+00:00', '-4.11', 88)), SportMapperInterface::CYCLING_SPORT)); $expected->addTrack(new Track(array($this->getTrackPoint('53.551074', '9.993671', '2014-05-30T17:12:58+00:00', '6.10', 78), $this->getTrackPoint('53.550084', '9.992681', '2014-05-30T17:12:59+00:00', '6.10', 88)), SportMapperInterface::RUNNING)); $actual = $polarMock->downloadWorkout($idWorkout); $this->assertEquals($expected, $actual); }
/** * Download a workout. * * @param integer $idWorkout The ID of the workout to download. * @return Workout */ public function downloadWorkout($idWorkout) { $this->logger->debug('Downloading JSON for workout "' . $idWorkout . '"'); $json = $this->getEndomondoAPI()->getWorkout($idWorkout); $workout = new Workout(); $track = new Track(); $track->setSport($this->getSportMapper()->getSportFromCode($json['sport'])); if (isset($json['points'])) { $this->logger->debug('Writing track points.'); foreach ($json['points'] as $point) { $trackPoint = new TrackPoint($point['lat'], $point['lng'], new DateTime($point['time'], $this->getTimeZone())); if (isset($point['alt'])) { $trackPoint->setElevation($point['alt']); } if (isset($point['hr'])) { $trackPoint->addExtension(new HR($point['hr'])); } $track->addTrackPoint($trackPoint); } } else { $this->logger->warning('No track points found for workout "' . $idWorkout . '".'); } $workout->addTrack($track); return $workout; }
/** * Write the tracks to the TCX. * * @param XMLWriter $xmlWriter The XML writer. * @param Workout $workout The workout. */ protected function writeTracks(XMLWriter $xmlWriter, Workout $workout) { $xmlWriter->startElement('Activities'); foreach ($workout->getTracks() as $track) { $xmlWriter->startElement('Activity'); $xmlWriter->writeAttribute('Sport', ucfirst($track->getSport())); // Use the start date time as the ID. This could be anything. $xmlWriter->writeElement('Id', $this->formatDateTime($track->getStartDateTime())); $xmlWriter->startElement('Lap'); $xmlWriter->writeAttribute('StartTime', $this->formatDateTime($track->getStartDateTime())); $xmlWriter->writeElement('TotalTimeSeconds', $track->getDuration()->getTotalSeconds()); $xmlWriter->writeElement('DistanceMeters', $track->getLength()); $this->writeLapHeartRateDate($xmlWriter, $track); $xmlWriter->startElement('Track'); $this->writeTrackPoints($xmlWriter, $track->getTrackpoints()); $xmlWriter->endElement(); $xmlWriter->endElement(); $xmlWriter->endElement(); } $xmlWriter->endElement(); }
/** * Test downloading a workout with points. */ public function testDownloadWorkoutWithPoints() { $idWorkout = 1; $stravaAPI = $this->getStravaAPIMock(array('getWorkout')); $stravaAPI->expects($this->once())->method('getWorkout')->with($idWorkout)->willReturn(array('latlng' => array(array('10.0', '53.0'), array('10.1', '53.1'), array('10.2', '53.2')), 'time' => array(new \DateTime('2014-07-27 20:33:15', new \DateTimeZone('UTC')), new \DateTime('2014-07-27 20:33:16', new \DateTimeZone('UTC')), new \DateTime('2014-07-27 20:33:17', new \DateTimeZone('UTC'))), 'altitude' => array(0, 10, -2), 'heartrate' => array(130, 140, 150))); $logger = $this->getMockForAbstractClass('Psr\\Log\\LoggerInterface'); $accessToken = '1234567890abc'; $strava = $this->getMock('SportTrackerConnector\\Tracker\\Strava\\Tracker', array('getStravaAPI'), array($logger, $accessToken)); $strava->expects($this->once())->method('getStravaAPI')->willReturn($stravaAPI); $actual = $strava->downloadWorkout($idWorkout); $expected = new Workout(); $track = new Track(); $track->addTrackPoint($this->getTrackPoint(10, 53, '2014-07-27 20:33:15', 0, 130)); $track->addTrackPoint($this->getTrackPoint(10.1, 53.1, '2014-07-27 20:33:16', 10, 140)); $track->addTrackPoint($this->getTrackPoint(10.2, 53.2, '2014-07-27 20:33:17', -2, 150)); $expected->addTrack($track); $this->assertEquals($expected, $actual); }
/** * Download a workout. * * @param integer $idWorkout The ID of the workout to download. * @return Workout */ public function downloadWorkout($idWorkout) { $this->logger->debug('Downloading JSON summary for workout "' . $idWorkout . '"'); $workout = new Workout(); $track = new Track(); try { $workoutDetails = $this->getStravaAPI()->getWorkout($idWorkout); $this->logger->debug('Writing track points.'); $pointsSize = count(reset($workoutDetails)); for ($i = 0; $i < $pointsSize; $i++) { $latitude = $workoutDetails['latlng'][$i][0]; $longitude = $workoutDetails['latlng'][$i][1]; $dateTime = $workoutDetails['time'][$i]; $dateTime->setTimezone($this->getTimeZone()); $trackPoint = new TrackPoint($latitude, $longitude, $dateTime); if (isset($workoutDetails['altitude'])) { $trackPoint->setElevation($workoutDetails['altitude'][$i]); } if (isset($workoutDetails['heartrate'])) { $trackPoint->addExtension(new HR($workoutDetails['heartrate'][$i])); } $track->addTrackPoint($trackPoint); } } catch (NoTrackPointsFoundException $e) { $this->logger->warning('No track points found for workout "' . $idWorkout . '".'); } $workout->addTrack($track); return $workout; }
/** * Test downloading a workout with points. */ public function testDownloadWorkoutWithPoints() { $idWorkout = 1; $endomondoAPI = $this->getEndomondoAPIMock(array('getWorkout')); $endomondoAPI->expects($this->once())->method('getWorkout')->with($idWorkout)->willReturn(array('sport' => 15, 'points' => array(array('lat' => '10.0', 'lng' => '53.0', 'time' => '2014-07-27 20:33:15'), array('lat' => '10.1', 'lng' => '53.1', 'time' => '2014-07-27 20:33:16', 'alt' => 10, 'hr' => 140), array('lat' => '10.2', 'lng' => '53.2', 'time' => '2014-07-27 20:33:17', 'alt' => -2, 'hr' => 150)))); $logger = $this->getMockForAbstractClass('Psr\\Log\\LoggerInterface'); $endomondo = $this->getMock('SportTrackerConnector\\Tracker\\Endomondo\\Tracker', array('getEndomondoAPI'), array($logger)); $endomondo->expects($this->once())->method('getEndomondoAPI')->willReturn($endomondoAPI); $actual = $endomondo->downloadWorkout($idWorkout); $expected = new Workout(); $track = new Track(); $track->setSport(SportMapperInterface::GOLF); $track->addTrackPoint($this->getTrackPoint(10, 53, '2014-07-27 20:33:15')); $track->addTrackPoint($this->getTrackPoint(10.1, 53.1, '2014-07-27 20:33:16', 10, 140)); $track->addTrackPoint($this->getTrackPoint(10.2, 53.2, '2014-07-27 20:33:17', -2, 150)); $expected->addTrack($track); $this->assertEquals($expected, $actual); }
/** * Post a workout to endomondo. * * Each track of a workout is uploaded individually. * * @param Workout $workout * @return array IDs of the workouts posted on endomondo. */ public function postWorkout(Workout $workout) { $workoutIds = array(); foreach ($workout->getTracks() as $track) { $workoutIds[] = $this->postTrack($track); } return $workoutIds; }
/** * Write the metadata in the GPX. * * @param XMLWriter $xmlWriter The XML writer. * @param Workout $workout The workout. */ protected function writeMetaData(XMLWriter $xmlWriter, Workout $workout) { $xmlWriter->startElement('metadata'); if ($workout->getAuthor() !== null) { $xmlWriter->startElement('author'); $xmlWriter->writeElement('name', $workout->getAuthor()->getName()); $xmlWriter->endElement(); } $xmlWriter->endElement(); }