void compute(RideItem *item, Specification spec, const QHash<QString,RideMetric*> &) { // no ride or no samples if (spec.isEmpty(item->ride())) { setValue(RideFile::NIL); setCount(0); return; } total = count = 0; RideFileIterator it(item->ride(), spec); while (it.hasNext()) { struct RideFilePoint *point = it.next(); if (point->cad > 0) { total += point->cad; ++count; } else if (point->rcad > 0) { total += point->rcad; ++count; } } setValue(count > 0 ? total / count : count); setCount(count); }
void compute(RideItem *item, Specification spec, const QHash<QString,RideMetric*> &) { // no ride or no samples if (spec.isEmpty(item->ride()) && // pace only makes sense for running or swimming !item->isRun && !item->isSwim) { setValue(RideFile::NIL); setCount(0); return; } seconds = 0; const PaceZones *zone = item->context->athlete->paceZones(item->isSwim); int zoneRange = item->paceZoneRange; // get zone ranges if (zone && zoneRange >= 0) { // iterate and compute RideFileIterator it(item->ride(), spec); while (it.hasNext()) { struct RideFilePoint *point = it.next(); if (zone->whichZone(zoneRange, point->kph) == level) seconds += item->ride()->recIntSecs(); } } setValue(seconds); }
void compute(RideItem *item, Specification spec, const QHash<QString,RideMetric*> &) { // no ride or no samples if (spec.isEmpty(item->ride()) || item->ride()->recIntSecs() == 0) { setValue(RideFile::NIL); setCount(0); return; } int rollingwindowsize = 30 / item->ride()->recIntSecs(); double total = 0; int count = 0; // no point doing a rolling average if the // sample rate is greater than the rolling average // window!! if (rollingwindowsize > 1) { QVector<double> rolling(rollingwindowsize); int index = 0; double sum = 0; // loop over the data and convert to a rolling // average for the given windowsize RideFileIterator it(item->ride(), spec); while (it.hasNext()) { struct RideFilePoint *point = it.next(); sum += point->watts; sum -= rolling[index]; rolling[index] = point->watts; total += pow(sum/rollingwindowsize,4); // raise rolling average to 4th power count ++; // move index on/round index = (index >= rollingwindowsize-1) ? 0 : index+1; } } if (count) { np = pow(total / (count), 0.25); secs = count * item->ride()->recIntSecs(); } else { np = secs = 0; } setValue(np); setCount(secs); }
void compute(RideItem *item, Specification spec, const QHash<QString,RideMetric*> &) { // no ride or no samples if (spec.isEmpty(item->ride()) || // xPowerSwim only makes sense for running and it needs recIntSecs > 0 !item->isSwim || item->ride()->recIntSecs() == 0) { setValue(RideFile::NIL); setCount(0); return; } double weight = item->getWeight(); static const double EPSILON = 0.1; static const double NEGLIGIBLE = 0.1; double secsDelta = item->ride()->recIntSecs(); double sampsPerWindow = 25.0 / secsDelta; double attenuation = sampsPerWindow / (sampsPerWindow + secsDelta); double sampleWeight = secsDelta / (sampsPerWindow + secsDelta); double lastSecs = 0.0; double weighted = 0.0; double total = 0.0; int count = 0; RideFileIterator it(item->ride(), spec); while (it.hasNext()) { struct RideFilePoint *point = it.next(); while ((weighted > NEGLIGIBLE) && (point->secs > lastSecs + secsDelta + EPSILON)) { weighted *= attenuation; lastSecs += secsDelta; total += pow(weighted, 3.0); count++; } weighted *= attenuation; weighted += sampleWeight * swimming_power(weight, point->kph/3.6); lastSecs = point->secs; total += pow(weighted, 3.0); count++; } xpower = count ? pow(total / count, 1/3.0) : 0.0; secs = count * secsDelta; setValue(xpower); setCount(secs); }
void compute(RideItem *item, Specification spec, const QHash<QString,RideMetric*> &) { // no ride or no samples if (spec.isEmpty(item->ride()) || !item->isRun) { setValue(RideFile::NIL); setCount(0); return; } QList<BestIntervalDialog::BestInterval> results; BestIntervalDialog::findBestsKPH(item->ride(), spec, secs, 1, results); if (results.count() > 0 && results.first().avg > 0 && results.first().avg < 36) pace = 60.0 / results.first().avg; else pace = 0.0; setValue(pace); }
void compute(RideItem *item, Specification spec, const QHash<QString,RideMetric*> &) { // no ride or no samples if (spec.isEmpty(item->ride()) || !item->isRun) { setValue(RideFile::NIL); setCount(0); return; } QList<AddIntervalDialog::AddedInterval> results; AddIntervalDialog::findPeaks(item->context, true, item->ride(), spec, RideFile::kph, RideFile::original, secs, 1, results, "", ""); if (results.count() > 0 && results.first().avg > 0 && results.first().avg < 36) pace = 60.0 / results.first().avg; else pace = 0.0; setValue(pace); }
void compute(RideItem *item, Specification spec, const QHash<QString,RideMetric*> &) { // no ride or no samples if (spec.isEmpty(item->ride()) || item->context->athlete->zones(item->isRun) == NULL || item->zoneRange < 0 || !item->ride()->areDataPresent()->watts) { setValue(RideFile::NIL); setCount(0); return; } seconds = 0; // iterate and compute RideFileIterator it(item->ride(), spec); while (it.hasNext()) { struct RideFilePoint *point = it.next(); if (item->context->athlete->zones(item->isRun)->whichZone(item->zoneRange, point->watts) == level) seconds += item->ride()->recIntSecs(); } setValue(seconds); }
void compute(RideItem *item, Specification spec, const QHash<QString,RideMetric*> &) { // no ride or no samples if (spec.isEmpty(item->ride()) || !item->isRun || item->ride()->recIntSecs() == 0) { setValue(RideFile::NIL); setCount(0); return; } double weight = item->ride()->getWeight(); double height = item->ride()->getHeight(); int rollingwindowsize120 = 120 / item->ride()->recIntSecs(); int rollingwindowsize30 = 30 / item->ride()->recIntSecs(); double total = 0.0; int count = 0; // no point doing a rolling average if the // sample rate is greater than the rolling average // window!! if (rollingwindowsize30 > 1) { QVector<double> rollingSpeed(rollingwindowsize120); QVector<double> rollingSlope(rollingwindowsize120); QVector<double> rollingPower(rollingwindowsize30); int index120 = 0; int index30 = 0; double sumSpeed = 0.0; double sumSlope = 0.0; double sumPower = 0.0; double initial_speed = 0.0; // loop over the data and convert to a rolling // average for the given windowsize RideFileIterator it(item->ride(), spec); while (it.hasNext()) { struct RideFilePoint *point = it.next(); double speed = point->kph/3.6; sumSpeed += speed; sumSpeed -= rollingSpeed[index120]; rollingSpeed[index120] = speed; double speed120 = sumSpeed/std::min(count+1, rollingwindowsize120); // speed rolling average double slope = point->slope/100.0; sumSlope += slope; sumSlope -= rollingSlope[index120]; rollingSlope[index120] = slope; double slope120 = sumSlope/std::min(count+1, rollingwindowsize120); // slope rolling average // running power based on 120sec averages double watts = running_power(weight, height, speed120, slope120, speed120*item->ride()->recIntSecs(), initial_speed); initial_speed = speed120; sumPower += watts; sumPower -= rollingPower[index30]; rollingPower[index30] = watts; total += pow(sumPower/std::min(count+1, rollingwindowsize30), 4); // raise rolling average to 4th power count ++; // move index on/round index120 = (index120 >= rollingwindowsize120-1) ? 0 : index120+1; index30 = (index30 >= rollingwindowsize30-1) ? 0 : index30+1; } } if (count) { lnp = pow(total/count, 0.25); secs = count * item->ride()->recIntSecs(); } else { lnp = secs = 0; } setValue(lnp); setCount(secs); }