/** * @return array */ public function sliceElevation() { if ($this->Object->hasCorrectedElevations()) { return $this->slice(Entity::ELEVATIONS_CORRECTED); } elseif ($this->Object->hasOriginalElevations()) { return $this->slice(Entity::ELEVATIONS_ORIGINAL); } return array(); }
/** * Tasks before insertion */ protected function before() { parent::before(); $Calculator = new Calculator($this->Object); if (Configuration::ActivityForm()->correctElevation() && !$this->Object->hasCorrectedElevations()) { $Calculator->tryToCorrectElevation(); } $Calculator->calculateElevation(); }
/** * @param \Runalyze\Model\Activity\Entity $activity * @param \Runalyze\Model\Route\Entity $route * @param int $offset * @return \Runalyze\Calculation\NightDetector $this-reference */ public function setFromEntities(Activity\Entity $activity, Route\Entity $route, $offset = 0) { if ($route->hasGeohashes() && $route->get(Route\Entity::STARTPOINT) != '') { $timestamp = $activity->timestamp() + 0.5 * $activity->duration(); $coordinate = (new Geohash())->decode($route->get(Route\Entity::STARTPOINT))->getCoordinate(); $this->setFrom($timestamp, $coordinate, $offset); } else { $this->Value = null; } return $this; }
/** * Construct collector * @param \Runalyze\Model\Trackdata\Entity $trackdata * @param int $key * @param \Runalyze\Model\Route\Entity $route * @throws \InvalidArgumentException */ public function __construct(Trackdata $trackdata, $key, Route $route) { if (!$route->has($key)) { throw new \InvalidArgumentException('Route has no data for "' . $key . '".'); } $this->Key = $key; $this->Precision = Configuration::ActivityView()->plotPrecision(); $this->KnowsDistance = $trackdata->has(Trackdata::DISTANCE); $this->init($trackdata); $this->LoopRoute = new Loop($route); $this->collect(); }
/** * Tasks before insertion */ protected function before() { parent::before(); $Calculator = new Calculator($this->Object); if (Configuration::ActivityForm()->correctElevation() && !$this->Object->hasCorrectedElevations()) { try { $Calculator->tryToCorrectElevation(); } catch (NoValidStrategyException $e) { // Well, obviously that did not work. Probably all API limits have been reached. } } $Calculator->calculateElevation(); }
/** * Calculate VDOT by heart rate with elevation influence * @return float */ public function calculateVDOTbyHeartRateWithElevation() { if ($this->knowsRoute()) { if ($this->Route->elevationUp() > 0 || $this->Route->elevationDown() > 0) { return $this->calculateVDOTbyHeartRateWithElevationFor($this->Route->elevationUp(), $this->Route->elevationDown()); } return $this->calculateVDOTbyHeartRateWithElevationFor($this->Route->elevation(), $this->Route->elevation()); } return $this->calculateVDOTbyHeartRateWithElevationFor($this->Activity->elevation(), $this->Activity->elevation()); }
/** * Add icon for current pause */ protected function addCurrentPauseIcon() { $Pause = $this->Trackdata->pauses()->at($this->PauseIndex); $Index = $this->RouteLoop->index(); $Tooltip = sprintf(__('<strong>Pause</strong> of %s'), Duration::format($Pause->duration())); $Tooltip .= '<br>' . sprintf(__('<strong>Distance:</strong> %s'), Distance::format($this->Trackdata->at($Index, Trackdata\Entity::DISTANCE))); $Tooltip .= '<br>' . sprintf(__('<strong>Time:</strong> %s'), Duration::format($this->Trackdata->at($Index, Trackdata\Entity::TIME))); if ($Pause->hasHeartRateInfo()) { $Tooltip .= '<br>' . sprintf(__('<strong>Heart rate:</strong>') . ' ' . __('%s to %s'), $Pause->hrStart(), $Pause->hrEnd() . ' bpm'); } $this->addMarkerGeohash($this->Route->at($Index, Route\Entity::GEOHASHES), $this->pauseIcon(), $Tooltip); }
/** * Save changes for route */ protected function saveChangesForRoute() { if (null === $this->Route || $this->OldRoute->isEmpty()) { return; } $this->Route->synchronize(); if ($this->Route->isEmpty()) { $Deleter = new Model\Route\Deleter($this->PDO, $this->Route); $Deleter->setAccountID($this->AccountID); $Deleter->delete(); $this->Route = null; $this->Activity->set(Entity::ROUTEID, 0); $this->Activity->set(Entity::ELEVATION, 0); } else { $Updater = new Model\Route\Updater($this->PDO, $this->Route, $this->OldRoute); $Updater->setAccountID($this->AccountID); $Updater->update(); } }
/** * Calculate power array * * A constant factor of 1.5 was used in previous versions - and I don't know why. * Without this factor results equal standard tools. * * @author Nils Frohberg * @author Hannes Christiansen * @see http://www.blog.ultracycle.net/2010/05/cycling-power-calculations * @param int $weight [kg] Weight of rider and bike * @param float $powerFactor constant factor * @return array */ public function calculate($weight = 75, $powerFactor = 1.0) { if (!$this->Trackdata->has(Trackdata\Entity::TIME) || !$this->Trackdata->has(Trackdata\Entity::DISTANCE)) { return []; } $everyNthPoint = ceil($this->Size / 1000); $n = $everyNthPoint; $grade = 0; $calcGrade = $this->knowsRoute() && $this->Route->hasElevations(); $ArrayTime = $this->Trackdata->time(); $ArrayDist = $this->Trackdata->distance(); $ArrayElev = $this->knowsRoute() ? $this->Route->elevations() : array(); $Frl = $weight * self::GRAVITY * self::CRR; $Fwpr = 0.5 * self::AREA * self::CW * $this->rho(); $Fslp = $weight * self::GRAVITY; for ($i = 0; $i < $this->Size - 1; $i++) { if ($i % $everyNthPoint == 0) { if ($i + $n > $this->Size - 1) { $n = $this->Size - $i - 1; } $distance = ($ArrayDist[$i + $n] - $ArrayDist[$i]) * 1000; $grade = $distance == 0 || !$calcGrade ? 0 : ($ArrayElev[$i + $n] - $ArrayElev[$i]) / $distance; } $distance = $ArrayDist[$i + 1] - $ArrayDist[$i]; $time = $ArrayTime[$i + 1] - $ArrayTime[$i]; if ($time > 0) { $Vmps = $distance * 1000 / $time; $Fw = $Fwpr * $Vmps * $Vmps; $Fsl = $Fslp * $grade; $this->Power[] = round(max($powerFactor * ($Frl + $Fw + $Fsl) * $Vmps, 0)); } else { $this->Power[] = 0; } } $this->Power[] = $this->Power[$this->Size - 2]; /* XXX */ return $this->Power; }
/** * Update if activity was at night */ protected function updateIfActivityWasAtNight() { if (null !== $this->Route && $this->Route->hasGeohashes() && $this->hasChanged(Entity::TIMESTAMP)) { $this->NewObject->set(Entity::IS_NIGHT, (new NightDetector())->setFromEntities($this->NewObject, $this->Route)->value()); } }
/** * Keys to insert * @return array */ protected function keys() { return array_merge(array(self::ACCOUNTID), Entity::allDatabaseProperties()); }
/** * Remove elevation correction */ public function removeElevationCorrection() { $this->Route->set(Route\Entity::ELEVATIONS_CORRECTED, array()); $this->Route->set(Route\Entity::ELEVATIONS_SOURCE, ''); }
/** * Calculate if activity was at night */ protected function calculateIfActivityWasAtNight() { if (null !== $this->Route && $this->Route->hasGeohashes()) { $this->Object->set(Entity::IS_NIGHT, (new NightDetector())->setFromEntities($this->Object, $this->Route)->value()); } }
/** * Calculate distance of current step from latitude/longitude * @return double */ public function calculatedStepDistance() { $LastGeohash = (new Geohash())->decode($this->Object->at($this->LastIndex, Entity::GEOHASHES))->getCoordinate(); $IndexGeohash = (new Geohash())->decode($this->Object->at($this->Index, Entity::GEOHASHES))->getCoordinate(); return Entity::gpsDistance($LastGeohash->getLatitude(), $LastGeohash->getLongitude(), $IndexGeohash->getLatitude(), $IndexGeohash->getLongitude()); }