/** * @param \Runalyze\View\Dataset\Table $Table */ protected function displayTrainingRows(\Runalyze\View\Dataset\Table $Table) { $Context = new \Runalyze\Dataset\Context(new Runalyze\Model\Activity\Entity(), $this->AccountID); foreach ($this->Trainings as $training) { $date = date("d.m.Y", $training['time']); $link = Ajax::trainingLink($training['id'], $date, true); $Context->setActivityData($training); echo '<tr class="r">'; echo '<td class="l"><small>' . $link . '</small></td>'; echo $Table->codeForColumns($Context); echo '</tr>'; } }
/** * Display extreme trainings */ private function displayExtremeTrainings() { $hot = DB::getInstance()->query('SELECT `temperature`, `id`, `time` FROM `' . PREFIX . 'training` WHERE `temperature` IS NOT NULL ' . $this->getYearDependenceForQuery() . ' AND accountid = ' . SessionAccountHandler::getId() . ' ORDER BY `temperature` DESC LIMIT 5')->fetchAll(); $cold = DB::getInstance()->query('SELECT `temperature`, `id`, `time` FROM `' . PREFIX . 'training` WHERE `temperature` IS NOT NULL ' . $this->getYearDependenceForQuery() . ' AND accountid = ' . SessionAccountHandler::getId() . ' ORDER BY `temperature` ASC LIMIT 5')->fetchAll(); foreach ($hot as $i => $h) { $hot[$i] = $h['temperature'] . ' °C ' . __('on') . ' ' . Ajax::trainingLink($h['id'], date('d.m.Y', $h['time'])); } foreach ($cold as $i => $c) { $cold[$i] = $c['temperature'] . ' °C ' . __('on') . ' ' . Ajax::trainingLink($c['id'], date('d.m.Y', $c['time'])); } echo '<p>'; echo '<strong>' . __('Hottest activities') . ':</strong> '; echo implode(', ', $hot) . '<br>'; echo '<strong>' . __('Coldest activities') . ':</strong> '; echo implode(', ', $cold) . '<br>'; echo '</p>'; }
/** * Init calculations */ protected function runCalculations() { foreach ($this->Distances as $km) { $Prognosis = $this->PrognosisObject->inSeconds($km); $PB = new PersonalBest($km, DB::getInstance(), false); $PB->lookupWithDetails(); $VDOTprognosis = new VDOT(); $VDOTprognosis->fromPace($km, $Prognosis); $VDOTpb = new VDOT(); $VDOTpb->fromPace($km, $PB->seconds()); $PacePrognosis = new Pace($Prognosis, $km, Pace::MIN_PER_KM); $PacePB = new Pace($PB->seconds(), $km, Pace::MIN_PER_KM); $DateWithLink = Ajax::trainingLink($PB->activityId(), date('d.m.Y', $PB->timestamp()), true); $this->Prognoses[] = array('distance' => Distance::format($km, $km <= 3), 'prognosis' => Duration::format($Prognosis), 'prognosis-pace' => $PacePrognosis->valueWithAppendix(), 'prognosis-vdot' => $VDOTprognosis->uncorrectedValue(), 'diff' => !$PB->exists() ? '-' : ($PB->seconds() > $Prognosis ? '+ ' : '- ') . Duration::format(abs(round($PB->seconds() - $Prognosis))), 'diff-class' => $PB->seconds() > $Prognosis ? 'plus' : 'minus', 'pb' => $PB->seconds() > 0 ? Duration::format($PB->seconds()) : '-', 'pb-pace' => $PB->seconds() > 0 ? $PacePB->valueWithAppendix() : '-', 'pb-vdot' => $PB->seconds() > 0 ? $VDOTpb->uncorrectedValue() : '-', 'pb-date' => $PB->seconds() > 0 ? $DateWithLink : '-'); } }
/** * Display the table with general records */ private function displayRekorde() { foreach ($this->rekorde as $rekord) { echo '<table class="fullwidth zebra-style">'; echo '<thead><tr><th colspan="11" class="l">' . $rekord['name'] . '</th></tr></thead>'; echo '<tbody>'; $output = false; $sports = DB::getInstance()->query($rekord['sportquery'])->fetchAll(); $Request = DB::getInstance()->prepare($rekord['datquery']); foreach ($sports as $sport) { $Request->bindValue('sportid', $sport['id']); $Request->execute(); $data = $Request->fetchAll(); if (!empty($data)) { $output = true; echo '<tr class="r">'; echo '<td class="b l">' . Icon::getSportIconForGif($sport['img'], $sport['name']) . ' ' . $sport['name'] . '</td>'; $j = 0; foreach ($data as $j => $dat) { if ($rekord['speed']) { $Pace = new Pace($dat['s'], $dat['distance'], SportFactory::getSpeedUnitFor($sport['id'])); $code = $Pace->valueWithAppendix(); } else { $code = $dat['distance'] != 0 ? Distance::format($dat['distance']) : Duration::format($dat['s']); } echo '<td class="small"><span title="' . date("d.m.Y", $dat['time']) . '"> ' . Ajax::trainingLink($dat['id'], $code) . ' </span></td>'; } for (; $j < 9; $j++) { echo HTML::emptyTD(); } echo '</tr>'; } } if (!$output) { echo '<tr><td colspan="11"><em>' . __('No data available') . '</em></td></tr>'; } echo '</tbody>'; echo '</table>'; } }
/** * Get fieldset for basic endurance * @return \FormularFieldset */ public function getFieldsetBasicEndurance() { $BasicEndurance = new BasicEndurance(); $BasicEndurance->readSettingsFromConfiguration(); $BEresults = $BasicEndurance->asArray(); $Strategy = new Prognosis\Daniels(); $Strategy->setupFromDatabase(); $Strategy->adjustVDOT(false); $Prognosis = new Prognosis\Prognosis(); $Prognosis->setStrategy($Strategy); $GeneralTable = ' <table class="fullwidth zebra-style"> <tbody class="top-and-bottom-border"> <tr> <td>' . __('<strong>Current VDOT</strong> <small>(based on heart rate)</small>') . '</td> <td class="r">' . round(Configuration::Data()->vdot(), 2) . '</td> <td> </td> <td>' . sprintf(__('<strong>Target kilometer per week</strong> <small>(%s weeks)</small>'), round($BasicEndurance->getDaysForWeekKm() / 7)) . '</td> <td class="r">' . Distance::format($BasicEndurance->getTargetWeekKm(), false, 0) . '</td> <td class="small">' . sprintf(__('done by %s%'), round(100 * $BEresults['weekkm-percentage'])) . '</td> <td class="small">(ø ' . Distance::format($BEresults['weekkm-result'] / $BasicEndurance->getDaysForWeekKm() * 7, false, 0) . ')</td> <td class="small">x' . $BasicEndurance->getPercentageForWeekKilometer() . '</td> <td rowspan="2" class="bottom-spacer b" style="vertical-align:middle;">= ' . round($BEresults['percentage']) . '%</td> </tr> <tr> <td>' . __('<strong>Marathon time</strong> <small>(optimal)</small>') . '</td> <td class="r">' . Duration::format($Prognosis->inSeconds(42.195)) . '</td> <td> </td> <td>' . sprintf(__('<strong>Target long run</strong> <small>(%s weeks)</small>'), round($BasicEndurance->getDaysToRecognizeForLongjogs() / 7)) . '</td> <td class="r">' . Distance::format($BasicEndurance->getRealTargetLongjogKmPerWeek(), false, 0) . '</td> <td class="small">' . sprintf(__('done by %s%'), round(100 * $BEresults['longjog-percentage'])) . '</td> <td class="small">(' . round($BEresults['longjog-result'], 1) . ' points)</td> <td class="small">x' . $BasicEndurance->getPercentageForLongjogs() . '</td> </tr> </tbody> </table>'; $LongjogTable = '<table class="fullwidth zebra-style c"> <thead> <tr> <th>' . __('Date') . '*</th> <th>' . __('Distance') . '</th> <th>' . __('Points') . '</th> </tr> </thead> <tbody>'; $IgnoredLongjogs = 0; $Longjogs = DB::getInstance()->query($BasicEndurance->getQuery(0, true))->fetchAll(); foreach ($Longjogs as $Longjog) { if ($Longjog['points'] >= 0.2) { $LongjogTable .= '<tr> <td>' . Ajax::trainingLink($Longjog['id'], date('d.m.Y', $Longjog['time'])) . '</td> <td>' . Distance::format($Longjog['distance']) . '</td> <td>' . round($Longjog['points'], 1) . ' points</td> </tr>'; } else { $IgnoredLongjogs++; } } $LongjogTable .= '<tr class="top-spacer no-zebra"> <td></td> <td></td> <td class="b">= ' . round($BEresults['longjog-result'], 1) . ' points</td> </tr> </tbody> </table>'; $LongjogTable .= '<p class="small">' . sprintf(__('* %s "long" jogs do not show up, ' . 'because they have less than 0.2 points.'), $IgnoredLongjogs) . '</p>'; $LongjogTable .= '<p class="small">' . sprintf(__('* In general, all runs with more than %s are being considered.'), Distance::format($BasicEndurance->getMinimalDistanceForLongjogs())) . '</p>'; $Fieldset = new FormularFieldset(__('Basic endurance')); $Fieldset->addBlock(__('Your basic endurance is based on your weekly kilometers and your long jogs.<br>' . 'The target is derived from the possible marathon time based on your current shape.') . '<br> '); $Fieldset->addBlock($GeneralTable); $Fieldset->addBlock(__('The points for your long runs are weighted by time and quadratic in distance. ' . 'That means, a long jog yesterday gives more points than a long jog two weeks ago ' . 'and a 30k-jog gives more points than two 20k-jogs.') . '<br> '); $Fieldset->addBlock($LongjogTable); $Fieldset->addBlock(__('The basic endurance is <strong>not</strong> from Jack Daniels.<br>' . 'It\'s our own attempt to adjust the prognosis for long distances based on your current endurance.')); return $Fieldset; }
/** * Display all training rows */ private function displayTrainingRows() { foreach ($this->Trainings as $training) { $date = date("d.m.Y", $training['time']); $link = Ajax::trainingLink($training['id'], $date, true); echo '<tr class="r">'; echo '<td class="l"><small>' . $link . '</small></td>'; $this->Dataset->setActivityData($training); $this->Dataset->displayTableColumns(); echo '</tr>'; } }
/** * Init calculations */ protected function runCalculations() { if (!$this->PrognosisObject->isValid()) { return; } foreach ($this->Distances as $km) { $Prognosis = $this->PrognosisObject->inSeconds($km); $PB = new PersonalBest($km, DB::getInstance(), false); $PB->lookupWithDetails(); $VDOTprognosis = new VDOT(); $VDOTprognosis->fromPace($km, $Prognosis); $VDOTpb = new VDOT(); $VDOTpb->fromPace($km, $PB->seconds()); $PacePrognosis = new Pace($Prognosis, $km, SportFactory::getSpeedUnitFor(Configuration::General()->runningSport())); $PacePB = new Pace($PB->seconds(), $km, SportFactory::getSpeedUnitFor(Configuration::General()->runningSport())); $DateWithLink = Ajax::trainingLink($PB->activityId(), date('d.m.Y', $PB->timestamp()), true); $this->Prognoses[] = array('distance' => (new Distance($km))->stringAuto(), 'prognosis' => Duration::format($Prognosis), 'prognosis-pace' => $PacePrognosis->valueWithAppendix(), 'prognosis-vdot' => $VDOTprognosis->uncorrectedValue(), 'diff' => !$PB->exists() ? '-' : ($PB->seconds() > $Prognosis ? '+ ' : '- ') . Duration::format(abs(round($PB->seconds() - $Prognosis))), 'diff-class' => $PB->seconds() > $Prognosis ? 'plus' : 'minus', 'pb' => $PB->seconds() > 0 ? Duration::format($PB->seconds()) : '-', 'pb-pace' => $PB->seconds() > 0 ? $PacePB->valueWithAppendix() : '-', 'pb-vdot' => $PB->seconds() > 0 ? $VDOTpb->uncorrectedValue() : '-', 'pb-date' => $PB->seconds() > 0 ? $DateWithLink : '-'); } }
/** * Show prognosis for a given distance * @param double $distance */ protected function showPrognosis($distance) { $PB = new PersonalBest($distance); $PB->lookupWithDetails(); $PBTime = $PB->exists() ? Duration::format($PB->seconds()) : '-'; $PBString = $PB->exists() ? Ajax::trainingLink($PB->activityId(), $PBTime, true) : $PBTime; $Prognosis = new Duration($this->Prognosis->inSeconds($distance)); $Distance = new Distance($distance); $Pace = new Pace($Prognosis->seconds(), $distance, SportFactory::getSpeedUnitFor(Configuration::General()->runningSport())); echo '<p> <span class="right"> ' . sprintf(__('<small>from</small> %s <small>to</small> <strong>%s</strong>'), $PBString, $Prognosis->string(Duration::FORMAT_AUTO, 0)) . ' <small>(' . $Pace->valueWithAppendix() . ')</small> </span> <strong>' . $Distance->stringAuto(true, 1) . '</strong> </p>'; }
/** * Display prev/next navigation */ protected function displayNavigation() { $prevId = Linker::prevId($this->Context->activity()->id(), $this->Context->activity()->timestamp()); $nextId = Linker::nextId($this->Context->activity()->id(), $this->Context->activity()->timestamp()); if ($prevId !== false) { echo Ajax::trainingLink($prevId, '<i class="fa fa-fw fa-chevron-left"></i>'); } else { echo '<i class="transparent-70 fa-grey fa fa-fw fa-chevron-left"></i>'; } if ($nextId !== false) { echo Ajax::trainingLink($nextId, '<i class="fa fa-fw fa-chevron-right"></i>'); } else { echo '<i class="transparent-70 fa-grey fa fa-fw fa-chevron-right"></i>'; } }
/** * Display extreme trainings */ protected function displayExtremeTrainings() { $hot = DB::getInstance()->query('SELECT `temperature`, `id`, `time` FROM `' . PREFIX . 'training` WHERE `temperature` IS NOT NULL ' . $this->getSportAndYearDependenceForQuery() . ' AND accountid = ' . SessionAccountHandler::getId() . ' ORDER BY `temperature` DESC LIMIT 5')->fetchAll(); $cold = DB::getInstance()->query('SELECT `temperature`, `id`, `time` FROM `' . PREFIX . 'training` WHERE `temperature` IS NOT NULL ' . $this->getSportAndYearDependenceForQuery() . ' AND accountid = ' . SessionAccountHandler::getId() . ' ORDER BY `temperature` ASC LIMIT 5')->fetchAll(); $windiest = DB::getInstance()->query('SELECT `wind_speed`, `id`, `time` FROM `' . PREFIX . 'training` WHERE `wind_speed` IS NOT NULL ' . $this->getSportAndYearDependenceForQuery() . ' AND accountid = ' . SessionAccountHandler::getId() . ' ORDER BY `wind_speed` DESC LIMIT 5')->fetchAll(); $maxhumidity = DB::getInstance()->query('SELECT `humidity`, `id`, `time` FROM `' . PREFIX . 'training` WHERE `humidity` IS NOT NULL ' . $this->getSportAndYearDependenceForQuery() . ' AND accountid = ' . SessionAccountHandler::getId() . ' ORDER BY `humidity` DESC LIMIT 5')->fetchAll(); foreach ($hot as $i => $h) { $hot[$i] = Temperature::format($h['temperature'], true) . ' ' . __('on') . ' ' . Ajax::trainingLink($h['id'], date('d.m.Y', $h['time'])); } foreach ($cold as $i => $c) { $cold[$i] = Temperature::format($c['temperature'], true) . ' ' . __('on') . ' ' . Ajax::trainingLink($c['id'], date('d.m.Y', $c['time'])); } foreach ($windiest as $i => $w) { $windiest[$i] = (new WindSpeed($w['wind_speed']))->string() . ' ' . __('on') . ' ' . Ajax::trainingLink($w['id'], date('d.m.Y', $w['time'])); } foreach ($maxhumidity as $i => $h) { $maxhumidity[$i] = (new Humidity($h['humidity']))->string() . ' ' . __('on') . ' ' . Ajax::trainingLink($w['id'], date('d.m.Y', $h['time'])); } echo '<p>'; echo '<strong>' . __('Hottest activities') . ':</strong> '; echo (empty($hot) ? __('none') : implode(', ', $hot)) . '<br>'; echo (empty($hot) ? __('none') : '<strong>' . __('Coldest activities')) . ':</strong> '; echo implode(', ', $cold) . '<br>'; echo '<strong>' . __('Most windy activities') . ':</strong> '; echo (empty($windiest) ? __('none') : implode(', ', $windiest)) . '<br>'; echo '<strong>' . __('Highest humidity activities') . ':</strong> '; echo (empty($maxhumidity) ? __('none') : implode(', ', $maxhumidity)) . '<br>'; echo '</p>'; }