Example #1
0
 /**
  * Database key
  * @return string
  */
 public function column()
 {
     if (\Runalyze\Configuration::Vdot()->useElevationCorrection()) {
         return 'vdot_with_elevation';
     }
     return 'vdot';
 }
 /**
  * Get VDOT with elevation
  * @return double vdot with elevation influence
  */
 public function getCurrentlyUsedVdot()
 {
     return Configuration::Vdot()->useElevationCorrection() && $this->getVdotWithElevation() > 0 ? $this->getVdotWithElevationCorrected() : $this->getVdotCorrected();
 }
Example #3
0
 /**
  * Recalculate VDOT shape
  * @return float new shape
  */
 public function recalculateVDOTshape()
 {
     $Shape = new JD\Shape(DB::getInstance(), SessionAccountHandler::getId(), Configuration::General()->runningSport(), Configuration::Vdot());
     $Shape->setCorrector(new JD\VDOTCorrector($this->vdotFactor()));
     $Shape->calculate();
     $this->updateVdotShape($Shape->value());
     return $Shape->value();
 }
Example #4
0
			GROUP BY `index`')->fetchAll();
    //	Cache::set('calculationsPlotData'.$Year.$All.$lastHalf.$lastYear, $Data, '300');
    //}
    foreach ($Data as $dat) {
        $index = $dat['index'] + $AddDays;
        $Trimps_raw[$index] = 1 * $dat['trimp'];
        if ($dat['vdot'] != 0) {
            $VDOTs_raw[$index] = $dat['vdot'];
            // Remember: These values are already multiplied with `s`
            $Durations_raw[$index] = (double) $dat['s'];
        }
    }
    $StartDayInYear = $All || $lastHalf || $lastYear ? Time::diffInDays($StartTime, mktime(0, 0, 0, 1, 1, $StartYear)) + 1 : 0;
    $LowestIndex = $AddDays + 1;
    $HighestIndex = $AddDays + 1 + $NumberOfDays;
    $VDOTdays = Configuration::Vdot()->days();
    $ATLdays = Configuration::Trimp()->daysForATL();
    $CTLdays = Configuration::Trimp()->daysForCTL();
    $TSBModel = new Runalyze\Calculation\Performance\TSB($Trimps_raw, $CTLdays, $ATLdays);
    $TSBModel->calculate();
    if ($All) {
        $maxATL = $TSBModel->maxFatigue();
        $maxCTL = $TSBModel->maxFitness();
        if ($maxATL != Configuration::Data()->maxATL()) {
            Configuration::Data()->updateMaxATL($maxATL);
        }
        if ($maxCTL != Configuration::Data()->maxCTL()) {
            Configuration::Data()->updateMaxCTL($maxCTL);
        }
    } else {
        $maxATL = Configuration::Data()->maxATL();
 /**
  * All categories
  * @return ConfigurationCategory[]
  */
 private function allCategories()
 {
     return array(Configuration::General(), Configuration::Privacy(), Configuration::ActivityView(), Configuration::ActivityForm(), Configuration::Design(), Configuration::DataBrowser(), Configuration::Vdot(), Configuration::Trimp(), Configuration::BasicEndurance(), Configuration::Misc());
 }
Example #6
0
 /**
  * Update vdot shape and corrector
  */
 protected function updateVDOTshapeAndCorrector()
 {
     $timestampLimit = time() - Configuration::Vdot()->days() * DAY_IN_S;
     if ($this->Object->usesVDOT() && $this->Object->vdotByHeartRate() > 0 && $this->Object->timestamp() > $timestampLimit) {
         Configuration::Data()->recalculateVDOTshape();
         if ($this->Object->typeid() == Configuration::General()->competitionType()) {
             Configuration::Data()->recalculateVDOTcorrector();
         }
     }
 }
Example #7
0
        $Data = DB::getInstance()->query('
			SELECT
				YEAR(FROM_UNIXTIME(`time`)) as `y`,
				MONTH(FROM_UNIXTIME(`time`)) as `m`,
				DAY(FROM_UNIXTIME(`time`)) as `d`,
				SUM(' . JD\Shape::mysqlVDOTsum($withElevation) . ')/SUM(' . JD\Shape::mysqlVDOTsumTime($withElevation) . ') as `vdot`
			FROM `' . PREFIX . 'training`
			WHERE
				`vdot`>0 AND use_vdot<>0
			GROUP BY `y`, `m`, `d`
			ORDER BY `y` ASC, `m` ASC, `d` ASC')->fetchAll();
        Cache::set('prognosePlotData', $Data, '300');
    }
    if (!empty($Data)) {
        $StartTime = mktime(12, 0, 0, $Data[0]['m'], $Data[0]['d'], $Data[0]['y']);
        $windowWidth = Configuration::Vdot()->days();
        $VDOTs = [$Data[0]['vdot']];
        $Indices = [0];
        // A 'prefix' of 15 days is needed to use uniform kernel only as 'rear mirror'
        foreach ($Data as $dat) {
            $VDOTs[] = $dat['vdot'];
            $Indices[] = 15 + Time::diffInDays($StartTime, mktime(12, 0, 0, $dat['m'], $dat['d'], $dat['y']));
        }
        $MovingAverage = new WithKernel($VDOTs, $Indices);
        $MovingAverage->setKernel(new Kernel\Uniform($windowWidth));
        $MovingAverage->calculate();
        foreach ($MovingAverage->movingAverage() as $i => $value) {
            if ($i > 0) {
                // TODO: use correct GA
                $Strategy->setVDOT(Configuration::Data()->vdotFactor() * $value);
                $index = $StartTime + DAY_IN_S * ($Indices[$i] - 15);
Example #8
0
 /**
  * @param string $key
  * @return string
  */
 private static function queryForVdot($key)
 {
     $Sum = \Runalyze\Configuration::Vdot()->useElevationCorrection() ? 'IF(`vdot_with_elevation`>0,`vdot_with_elevation`,`vdot`)*`s`' : '`vdot`*`s`';
     return 'SUM(IF(`use_vdot`=1 AND `vdot`>0,' . $Sum . ',0))/SUM(IF(`use_vdot`=1 AND `vdot`>0,`s`,0)) as `' . $key . '`';
 }
Example #9
0
    /**
     * Display with corrector
     */
    protected function displayWithElevation()
    {
        if ($this->Context->hasRoute() && ($this->Context->route()->elevationUp() > 0 || $this->Context->route()->elevationDown())) {
            $up = $this->Context->route()->elevationUp();
            $down = $this->Context->route()->elevationDown();
        } else {
            $up = $this->Context->activity()->elevation();
            $down = $up;
        }
        $Modifier = new Elevation\DistanceModifier($this->Context->activity()->distance(), $up, $down, Configuration::Vdot());
        $VDOT = new JD\VDOT(0, new JD\VDOTCorrector(Configuration::Data()->vdotFactor()));
        $VDOT->fromPaceAndHR($Modifier->correctedDistance(), $this->Context->activity()->duration(), $this->Context->activity()->hrAvg() / Configuration::Data()->HRmax());
        $Fieldset = new FormularFieldset(__('Correction: considering elevation'));
        $Fieldset->setHtmlCode('
			<p class="warning small ' . (Configuration::Vdot()->useElevationCorrection() ? 'hide' : '') . '">
				' . __('This correction method is currently unused.') . '
			</p>

			<div class="w50">
				<label>' . __('Up/Down') . '</label>
				<span class="as-input">+' . $up . '/-' . $down . '&nbsp;m</span>
			</div>
			<div class="w50 double-height-right">
				<label>&rArr; ' . __('VDOT') . '</label>
				<span class="as-input ' . (!Configuration::Vdot()->useElevationCorrection() ? '' : 'highlight') . '">' . $VDOT->value() . '</span>
			</div>
			<div class="w50">
				<label>' . __('Influence') . '</label>
				<span class="as-input">' . sprintf("%+d", 1000 * $Modifier->additionalDistance()) . 'm = ' . Distance::format($Modifier->correctedDistance(), false, 3) . '</span>
			</div>
		');
        $Fieldset->display();
    }
    /**
     * Init complete data
     */
    private function initCompleteData()
    {
        $withElevation = Configuration::Vdot()->useElevationCorrection();
        $Query = '
			SELECT
				SUM(`s`) as `s`,
				SUM(IF(`distance`>0,`s`,0)) as `s_sum_with_distance`,
				SUM(`distance`) as `distance`,
				SUM(' . JD\Shape::mysqlVDOTsum($withElevation) . ')/SUM(' . JD\Shape::mysqlVDOTsumTime($withElevation) . ') as `vdot`,
				SUM(`trimp`) as `trimp`,
				SUM(`jd_intensity`) as `jd_intensity`,
				' . $this->getTimerIndexForQuery() . ' as `i`
			FROM
				`' . PREFIX . 'training`
			WHERE
				`accountid`=:sessid ' . $this->getSportAndYearDependenceForQuery();
        $Query .= ' GROUP BY ' . $this->getTimerForOrderingInQuery() . ' ASC';
        $Request = DB::getInstance()->prepare($Query);
        $Request->bindValue('sessid', SessionAccountHandler::getId(), PDO::PARAM_INT);
        $Request->execute();
        $this->CompleteData = $Request->fetchAll();
    }
Example #11
0
 /**
  * Get string for selecting dataset in query
  * @return string
  */
 public function getQuerySelectForSet()
 {
     $String = '';
     $Sum = Configuration::Vdot()->useElevationCorrection() ? 'IF(`vdot_with_elevation`>0,`vdot_with_elevation`,`vdot`)*`s`' : '`vdot`*`s`';
     $showVdot = 0;
     foreach ($this->data as $set) {
         if ($set['summary'] == 1) {
             if ($set['name'] == 'vdot' || $set['name'] == 'vdoticon') {
                 $showVdot = 1;
             } elseif ($set['name'] == 'temperature') {
                 $String .= ', ' . $set['summary_mode'] . '(NULLIF(`' . $set['name'] . '`,0)) as `' . $set['name'] . '`';
             } elseif ($set['name'] != 'pace') {
                 if ($set['summary_mode'] != 'AVG') {
                     $String .= ', ' . $set['summary_mode'] . '(`' . $set['name'] . '`) as `' . $set['name'] . '`';
                 } else {
                     $String .= ', SUM(`s`*`' . $set['name'] . '`*(`' . $set['name'] . '` > 0))' . '/SUM(`s`*(`' . $set['name'] . '` > 0)) as `' . $set['name'] . '`';
                 }
             }
         }
     }
     if ($showVdot) {
         $String .= ', SUM(IF(`use_vdot`=1 AND `vdot`>0,' . $Sum . ',0))/SUM(IF(`use_vdot`=1 AND `vdot`>0,`s`,0)) as `vdot`';
     }
     return $String;
 }
Example #12
0
    $WKplugin = $Factory->newInstance('RunalyzePluginStat_Wettkampf');
}
if (!isset($distance)) {
    $distance = 10;
}
$DataFailed = false;
$Prognosis = array();
$Results = array();
$Strategy = new Prognosis\Daniels();
$Strategy->adjustVDOT(false);
$PrognosisObj = new Prognosis\Prognosis();
$PrognosisObj->setStrategy($Strategy);
if (START_TIME != time()) {
    $Data = Cache::get('prognosePlotData');
    if (is_null($Data)) {
        $withElevation = Configuration::Vdot()->useElevationCorrection();
        $Data = DB::getInstance()->query('
			SELECT
				YEAR(FROM_UNIXTIME(`time`)) as `y`,
				MONTH(FROM_UNIXTIME(`time`)) as `m`,
				SUM(' . JD\Shape::mysqlVDOTsum($withElevation) . ')/SUM(' . JD\Shape::mysqlVDOTsumTime($withElevation) . ') as `vdot`
			FROM `' . PREFIX . 'training`
			WHERE
				`vdot`>0 AND use_vdot<>0
			GROUP BY `y`, `m`
			ORDER BY `y` ASC, `m` ASC')->fetchAll();
        Cache::set('prognosePlotData', $Data, '300');
    }
    foreach ($Data as $dat) {
        // TODO: use correct GA
        $Strategy->setVDOT(Configuration::Data()->vdotFactor() * $dat['vdot']);
Example #13
0
 /**
  * Prognosis time by heart rate after correction
  * @return string
  */
 public function prognosisByHRafterCorrection()
 {
     if (Configuration::Vdot()->useCorrectionFactor()) {
         $Prognosis = new Daniels();
         $Prognosis->adjustVDOT(false);
         $Prognosis->setVDOT(Configuration::Data()->vdotFactor() * $this->Activity->vdotByHeartRate());
         return $this->formatTime($Prognosis->inSeconds($this->Activity->distance()));
     }
     return '-';
 }
 /**
  * Init conditions fieldset
  */
 protected function initConditions()
 {
     $this->addConditionFieldWithChosen('typeid', 'type', 'name', __('Type'), __('Choose activity type(s)'));
     $this->addConditionFieldWithChosen('weatherid', 'weather', 'name', __('Weather'), __('Choose weather conditions'));
     $this->addConditionFieldWithChosen('equipmentid', 'equipment', 'name', __('Equipment'), __('Choose equipment'));
     $this->addConditionFieldWithChosen('tagid', 'tag', 'tag', __('Tag'), __('Choose tag'));
     $this->addFieldNotes();
     $this->addNumericConditionField('distance', __('Distance'), FormularInput::$SIZE_SMALL, Configuration::General()->distanceUnitSystem()->distanceUnit());
     $this->addNumericConditionField('elevation', __('Elevation'), FormularInput::$SIZE_SMALL, Configuration::General()->distanceUnitSystem()->elevationUnit());
     $this->addStringConditionField('route', __('Route'), FormularInput::$SIZE_MIDDLE);
     $this->addDurationField('s', __('Duration'));
     $this->addNumericConditionField('temperature', __('Temperature'), FormularInput::$SIZE_SMALL, Configuration::General()->temperatureUnit()->unit());
     $this->addNumericConditionField('humidity', __('Humidity'), FormularInput::$SIZE_SMALL, (new Humidity())->unit());
     $this->addNumericConditionField('pressure', __('Pressure'), FormularInput::$SIZE_SMALL, (new Pressure())->unit());
     $this->addNumericConditionField('wind_speed', __('Wind Speed'), FormularInput::$SIZE_SMALL, (new WindSpeed())->unit());
     $this->addStringConditionField('comment', __('Title'), FormularInput::$SIZE_MIDDLE);
     $this->addNumericConditionField('pulse_avg', __('avg. HR'), FormularInput::$SIZE_SMALL, FormularUnit::$BPM);
     $this->addNumericConditionField('kcal', __('Calories'), FormularInput::$SIZE_SMALL, FormularUnit::$KCAL);
     $this->addStringConditionField('partner', __('Partner'), FormularInput::$SIZE_MIDDLE);
     $this->addNumericConditionField('pulse_max', __('max. HR'), FormularInput::$SIZE_SMALL, FormularUnit::$BPM);
     $this->addNumericConditionField('cadence', __('Cadence'), FormularInput::$SIZE_SMALL, FormularUnit::$SPM);
     $this->addBooleanField('is_public', __('Is public'));
     $this->addNumericConditionField('jd_intensity', __('JD points'), FormularInput::$SIZE_SMALL);
     $this->addNumericConditionField('groundcontact', __('Ground contact'), FormularInput::$SIZE_SMALL, FormularUnit::$MS);
     $this->addNumericConditionField('groundcontact_balance', __('Ground Contact Balance'), FormularInput::$SIZE_SMALL, 'L' . FormularUnit::$PERCENT);
     $this->addNumericConditionField('vertical_oscillation', __('Vertical oscillation'), FormularInput::$SIZE_SMALL, FormularUnit::$CM);
     $this->addNumericConditionField('vertical_ratio', __('Vertical ratio'), FormularInput::$SIZE_SMALL, FormularUnit::$PERCENT);
     $this->addNumericConditionField('stride_length', __('Stride length'), FormularInput::$SIZE_SMALL, Configuration::General()->distanceUnitSystem()->strideLengthUnit());
     if (Configuration::Vdot()->useElevationCorrection()) {
         $this->addNumericConditionField('vdot_with_elevation', __('VDOT'), FormularInput::$SIZE_SMALL);
     } else {
         $this->addNumericConditionField('vdot', __('VDOT'), FormularInput::$SIZE_SMALL);
     }
     $this->addBooleanField('use_vdot', __('Uses VDOT'));
     $this->addNumericConditionField('trimp', __('TRIMP'), FormularInput::$SIZE_SMALL);
 }
 /**
  * Get order
  * @return string
  */
 protected function getOrder()
 {
     $sort = !isset($_POST['search-sort-by']) || array_key_exists($_POST['search-sort-by'], $this->AllowedKeys) ? '`time`' : $this->DB->escape($_POST['search-sort-by'], false);
     $order = !isset($_POST['search-sort-order']) ? 'DESC' : $this->DB->escape($_POST['search-sort-order'], false);
     if ($sort == 'vdot' && Configuration::Vdot()->useElevationCorrection()) {
         return ' ORDER BY IF(`t`.`vdot_with_elevation`>0, `t`.`vdot_with_elevation`, `t`.`vdot`) ' . $order;
     }
     if ($sort == 'pace') {
         return ' ORDER BY IF(`t`.`distance`>0, `t`.`s`/`t`.`distance`, 0) ' . $order;
     }
     return ' ORDER BY `t`.' . $sort . ' ' . $order;
 }
Example #16
0
 /**
  * Value of used VDOT (uncorrected)
  * @return float
  */
 public function usedVdot()
 {
     if (Configuration::Vdot()->useElevationCorrection()) {
         if ($this->Activity->vdotWithElevation() > 0) {
             return $this->Activity->vdotWithElevation();
         }
     }
     return $this->Activity->vdotByHeartRate();
 }
Example #17
0
 /**
  * Calculate VDOT by heart rate with elevation influence
  * @param int $up
  * @param int $down
  * @return float
  */
 public function calculateVDOTbyHeartRateWithElevationFor($up, $down)
 {
     $Modifier = new Elevation\DistanceModifier($this->Activity->distance(), $up, $down, Configuration::Vdot());
     return $this->calculateVDOTbyHeartRate($Modifier->correctedDistance());
 }
    /**
     * Get fieldset for VDOT
     * @return \FormularFieldset
     */
    public function getFieldsetVDOT()
    {
        $Table = '<table class="fullwidth zebra-style">
				<thead>
					<tr>
						<th colspan="10">' . sprintf(__('VDOT values of the last %s days'), Configuration::Vdot()->days()) . '</th>
					</tr>
				</thead>
				<tbody class="top-and-bottom-border">';
        $Tooltip = new Tooltip('');
        $VDOT = new VDOT(0, new VDOTCorrector(Configuration::Data()->vdotFactor()));
        $VDOTs = DB::getInstance()->query('SELECT `id`,`time`,`distance`,IF(`vdot_with_elevation`>0,`vdot_with_elevation`,`vdot`) as `vdot` FROM `' . PREFIX . 'training` WHERE time>=' . (time() - Configuration::Vdot()->days() * DAY_IN_S) . ' AND vdot>0 AND use_vdot=1 AND accountid = ' . SessionAccountHandler::getId() . ' ORDER BY time ASC')->fetchAll();
        foreach ($VDOTs as $i => $Data) {
            if ($i % 10 == 0) {
                $Table .= '<tr>';
            }
            $Tooltip->setText(date('d.m.Y', $Data['time']) . ': ' . Distance::format($Data['distance']));
            $VDOT->setValue($Data['vdot']);
            $Table .= '<td ' . $Tooltip->attributes() . '>' . Ajax::trainingLink($Data['id'], $VDOT->value()) . '</td>';
            if ($i % 10 == 9) {
                $Table .= '</tr>';
            }
        }
        if (count($VDOTs) % 10 != 0) {
            $Table .= HTML::emptyTD(10 - count($VDOTs) % 10);
        }
        $Table .= '</tbody></table>';
        $Fieldset = new FormularFieldset(__('VDOT'));
        $Fieldset->addBlock(sprintf(__('The VDOT value is the average, weighted by the time, of the VDOT of your activities in the last %s days.'), Configuration::Vdot()->days()));
        $Fieldset->addBlock(sprintf(__('Your current VDOT shape: <strong>%s</strong><br>&nbsp;'), Configuration::Data()->vdot()));
        $Fieldset->addBlock($Table);
        $Fieldset->addInfo(__('Jack Daniels uses VDOT as a fixed value and not based on the training progress.<br>' . 'We do instead predict the VDOT from all activities based on the heart rate. ' . 'These formulas are derived from Jack Daniels\' tables as well.'));
        return $Fieldset;
    }
Example #19
0
 /**
  * Update vdot shape and corrector
  */
 protected function updateVDOTshapeAndCorrector()
 {
     $timestampLimit = time() - Configuration::Vdot()->days() * DAY_IN_S;
     if ($this->hasChanged(Entity::USE_VDOT) && ($this->NewObject->timestamp() >= $timestampLimit || $this->knowsOldObject() && $this->OldObject->timestamp() > $timestampLimit) || $this->NewObject->usesVDOT() && ($this->hasChanged(Entity::VDOT) || $this->hasChanged(Entity::VDOT_WITH_ELEVATION) || $this->hasChanged(Entity::TIMESTAMP) && $this->knowsOldObject() && ($this->NewObject->timestamp() >= $timestampLimit && $this->OldObject->timestamp() < $timestampLimit || $this->NewObject->timestamp() < $timestampLimit && $this->OldObject->timestamp() >= $timestampLimit))) {
         Configuration::Data()->recalculateVDOTshape();
     }
     if (($this->NewObject->usesVDOT() || $this->hasChanged(Entity::USE_VDOT)) && ($this->NewObject->typeid() == Configuration::General()->competitionType() || $this->knowsOldObject() && $this->OldObject->typeid() == Configuration::General()->competitionType())) {
         Configuration::Data()->recalculateVDOTcorrector();
     }
 }
Example #20
0
?>

<p class="info">
	<?php 
_e('<strong>VDOT/Time (Shape):</strong> by your shape at that time<br>');
?>
	<?php 
_e('The time is the prognosis by Runalyze.');
?>
</p>

<p class="info">
	<?php 
_e('<strong>Corrector:</strong> Ratio between VDOT and VDOT (by HR)');
?>
</p>

<?php 
if (Configuration::Vdot()->useElevationCorrection()) {
    ?>
<p class="warning">
	<?php 
    _e('The distance correction for elevation is not used in this table.');
    ?>
</p>
<?php 
}
?>

<?php 
echo Ajax::wrapJSforDocumentReady('$("#ajax").addClass("big-window");');