/** * Calculate strides array * @return array */ public function calculate() { if (!$this->Trackdata->has(Trackdata\Object::TIME) || !$this->Trackdata->has(Trackdata\Object::DISTANCE) || !$this->Trackdata->has(Trackdata\Object::CADENCE)) { return; } $Time = $this->Trackdata->time(); $Distance = $this->Trackdata->distance(); $Cadence = $this->Trackdata->cadence(); $Size = $this->Trackdata->num(); $this->Strides[] = $Cadence[0] > 0 && $Time[0] > 0 ? round($Distance[0] * 1000 * 100 / ($Cadence[0] * 2 / 60 * $Time[0])) : 0; for ($i = 1; $i < $Size; ++$i) { $this->Strides[] = $Cadence[$i] > 0 && $Time[$i] - $Time[$i - 1] > 0 ? round(($Distance[$i] - $Distance[$i - 1]) * 1000 * 100 / ($Cadence[$i] * 2 / 60 * ($Time[$i] - $Time[$i - 1]))) : 0; } return $this->Strides; }
/** * Run fast smoothing for step size * * Although this does not look nice and is not the cleanest code, * direct access to the arrays is approx. 5-times faster. * (0.02s vs 0.11s for an array of 10.000 elements) */ protected function runFastSmoothingForSteps() { $distance = $this->Trackdata->distance(); $time = $this->Trackdata->time(); $lastDist = 0; $lastTime = 0; foreach ($distance as $i => $dist) { if ($i != 0 && $i % $this->StepSize == 0) { $pace = $dist - $lastDist > 0 ? round(($time[$i] - $lastTime) / ($dist - $lastDist)) : 0; if ($this->KeepArraySize) { for ($j = 0; $j < $this->StepSize; ++$j) { $this->Smoothed[] = $pace; } } else { $this->Smoothed[] = $pace; } $lastDist = $dist; $lastTime = $time[$i]; } } if ($this->KeepArraySize && isset($i)) { $pace = $dist - $lastDist > 0 ? round(($time[$i] - $lastTime) / ($dist - $lastDist)) : 0; for ($j = count($this->Smoothed), $num = $this->Trackdata->num(); $j < $num; ++$j) { $this->Smoothed[] = $pace; } } }
public function testSimpleInsert() { $T = new Object(array(Object::ACTIVITYID => 1, Object::TIME => array(20, 40, 60), Object::DISTANCE => array(0.1, 0.2, 0.3), Object::HEARTRATE => array(100, 120, 130))); $T->pauses()->add(new Pause(40, 10)); $I = new Inserter($this->PDO, $T); $I->setAccountID(1); $I->insert(); $data = $this->PDO->query('SELECT * FROM `' . PREFIX . 'trackdata` WHERE `accountid`=1')->fetch(PDO::FETCH_ASSOC); $N = new Object($data); $this->assertEquals(1, $N->activityID()); $this->assertEquals(array(20, 40, 60), $N->time()); $this->assertEquals(array(0.1, 0.2, 0.3), $N->distance()); $this->assertEquals(array(100, 120, 130), $N->heartRate()); $this->assertFalse($N->pauses()->isEmpty()); }
public function testSimpleUpdate() { $Inserter = new Inserter($this->PDO, new Object(array(Object::ACTIVITYID => 1, Object::TIME => array(20, 40, 60), Object::DISTANCE => array(0.1, 0.2, 0.3), Object::HEARTRATE => array(100, 120, 130)))); $Inserter->setAccountID(1); $Inserter->insert(); $Track = new Object($this->PDO->query('SELECT * FROM `' . PREFIX . 'trackdata` WHERE `activityid`=1')->fetch(PDO::FETCH_ASSOC)); $Track->set(Object::HEARTRATE, array(120, 140, 150)); $Changed = clone $Track; $Changed->set(Object::DISTANCE, array(0.15, 0.3, 0.45)); $Updater = new Updater($this->PDO, $Changed, $Track); $Updater->setAccountID(1); $Updater->update(); $Result = new Object($this->PDO->query('SELECT * FROM `' . PREFIX . 'trackdata` WHERE `activityid`=1')->fetch(PDO::FETCH_ASSOC)); $this->assertEquals(1, $Result->activityID()); $this->assertEquals(array(20, 40, 60), $Result->time()); $this->assertEquals(array(0.15, 0.3, 0.45), $Result->distance()); $this->assertEquals(array(100, 120, 130), $Result->heartRate()); }
/** * 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\Object::TIME) || !$this->Trackdata->has(Trackdata\Object::DISTANCE)) { return; } $everyNthPoint = ceil($this->Size / 1000); //self::$everyNthElevationPoint * ceil($this->Size/1000); $n = $everyNthPoint; $distance = 0; $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; }