diff --git a/src/Aerolab.cpp b/src/Aerolab.cpp index 3c4bd99ea..84c31cf06 100644 --- a/src/Aerolab.cpp +++ b/src/Aerolab.cpp @@ -158,6 +158,10 @@ Aerolab::setData(RideItem *_rideItem, bool new_zoom) { // Unpack: double power = max(0, p1->watts); double v = p1->kph/vfactor; + double headwind = v; + if( dataPresent->headwind ) { + headwind = p1->headwind/vfactor; + } double f = 0.0; double a = 0.0; d += v * dt; @@ -172,7 +176,7 @@ Aerolab::setData(RideItem *_rideItem, bool new_zoom) { } f *= eta; // adjust for drivetrain efficiency if using a crank-based meter - double s = slope( f, a, m, crr, cda, rho, v ); + double s = slope( f, a, m, crr, cda, rho, headwind ); double de = s * v * dt; e += de; diff --git a/src/Computrainer3dpFile.cpp b/src/Computrainer3dpFile.cpp index 3b0ad9bae..77855f266 100644 --- a/src/Computrainer3dpFile.cpp +++ b/src/Computrainer3dpFile.cpp @@ -237,7 +237,7 @@ RideFile *Computrainer3dpFileReader::openRideFile(QFile & file, // special case first data point rideFile->appendPoint((double) ms/1000, (double) cad, (double) hr, km, speed, 0.0, watts, - altitude, 0, 0, 0); + altitude, 0, 0, 0.0, 0); } // while loop since an interval in the .3dp file might // span more than one CT_EMIT_MS interval @@ -285,6 +285,7 @@ RideFile *Computrainer3dpFileReader::openRideFile(QFile & file, interpol_alt, 0, // lon 0, // lat + 0.0, // headwind 0); // reset averaging sums diff --git a/src/CsvRideFile.cpp b/src/CsvRideFile.cpp index 26922176c..03c12c80e 100644 --- a/src/CsvRideFile.cpp +++ b/src/CsvRideFile.cpp @@ -142,6 +142,7 @@ RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors) const else if (lineno > unitsHeader) { double minutes,nm,kph,watts,km,cad,alt,hr,dfpm; double lat = 0.0, lon = 0.0; + double headwind = 0.0; int interval; int pause; if (!ergomo && !iBike) { @@ -175,6 +176,7 @@ RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors) const if( iBikeVersion >= 11 && ( dfpm > 0.0 || dfpmExists ) ) { dfpmExists = true; watts = dfpm; + headwind = line.section(',', 1, 1).toDouble(); } else { watts = line.section(',', 2, 2).toDouble(); @@ -195,6 +197,7 @@ RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors) const km *= KM_PER_MILE; kph *= KM_PER_MILE; alt *= METERS_PER_FOOT; + headwind *= KM_PER_MILE; } } else { @@ -234,7 +237,7 @@ RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors) const watts = 0; rideFile->appendPoint(minutes * 60.0, cad, hr, km, - kph, nm, watts, alt, lat, lon, interval); + kph, nm, watts, alt, lat, lon, headwind, interval); } ++lineno; } diff --git a/src/GcRideFile.cpp b/src/GcRideFile.cpp index cfe8ed3a2..ef5326148 100644 --- a/src/GcRideFile.cpp +++ b/src/GcRideFile.cpp @@ -89,6 +89,7 @@ GcFileReader::openRideFile(QFile &file, QStringList &errors) const for (QDomElement sample = samples.firstChildElement("sample"); !sample.isNull(); sample = sample.nextSiblingElement("sample")) { double secs, cad, hr, km, kph, nm, watts, alt, lon, lat; + double headwind = 0.0; secs = sample.attribute("secs", "0.0").toDouble(); cad = sample.attribute("cad", "0.0").toDouble(); hr = sample.attribute("hr", "0.0").toDouble(); @@ -101,7 +102,7 @@ GcFileReader::openRideFile(QFile &file, QStringList &errors) const lat = sample.attribute("lat", "0.0").toDouble(); while ((interval < intervalStops.size()) && (secs >= intervalStops[interval])) ++interval; - rideFile->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, lon, lat, interval); + rideFile->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, interval); if (!recIntSet) { rideFile->setRecIntSecs(sample.attribute("len").toDouble()); recIntSet = true; diff --git a/src/ManualRideFile.cpp b/src/ManualRideFile.cpp index adbca7100..690870801 100644 --- a/src/ManualRideFile.cpp +++ b/src/ManualRideFile.cpp @@ -125,7 +125,7 @@ RideFile *ManualFileReader::openRideFile(QFile &file, QStringList &errors) const interval = 0; rideFile->appendPoint(minutes * 60.0, cad, hr, km, - kph, nm, watts, alt, 0.0, 0.0, interval); + kph, nm, watts, alt, 0.0, 0.0, 0.0, interval); QMap bsm; bsm.insert("value", QString("%1").arg(bs)); rideFile->metricOverrides.insert("skiba_bike_score", bsm); diff --git a/src/PolarRideFile.cpp b/src/PolarRideFile.cpp index c4fce8298..1bf4a35aa 100644 --- a/src/PolarRideFile.cpp +++ b/src/PolarRideFile.cpp @@ -200,7 +200,7 @@ this differently next_interval = intervals.at(interval); } } - rideFile->appendPoint(seconds, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, interval); + rideFile->appendPoint(seconds, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, 0.0, interval); //fprintf(stderr, " %f, %f, %f, %f, %f, %f, %f, %d\n", seconds, cad, hr, km, kph, nm, watts, alt, interval); } diff --git a/src/QuarqParser.cpp b/src/QuarqParser.cpp index 1a99c526b..c7ecd6608 100644 --- a/src/QuarqParser.cpp +++ b/src/QuarqParser.cpp @@ -52,7 +52,7 @@ QuarqParser::incrementTime( const double new_time ) while (time_diff > seconds_from_start) { rideFile->appendPoint(seconds_from_start, cad, hr, km, - kph, nm, watts, 0, 0.0, 0.0, 0); + kph, nm, watts, 0, 0.0, 0.0, 0.0, 0); seconds_from_start += SAMPLE_INTERVAL; } @@ -114,7 +114,7 @@ QuarqParser::endElement( const QString&, const QString&, const QString& qName) // flush one last data point if (qName == "Qollector") { rideFile->appendPoint(seconds_from_start, cad, hr, km, - kph, nm, watts, 0, 0.0, 0.0, 0); + kph, nm, watts, 0, 0.0, 0.0, 0.0, 0); } return TRUE; diff --git a/src/RawRideFile.cpp b/src/RawRideFile.cpp index 922092c48..a9378a7ec 100644 --- a/src/RawRideFile.cpp +++ b/src/RawRideFile.cpp @@ -70,7 +70,7 @@ time_cb(struct tm *, time_t since_epoch, void *context) double secs = since_epoch - state->start_since_epoch; state->rideFile->appendPoint(secs, 0.0, 0.0, state->last_miles * KM_PER_MILE, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, state->last_interval); + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, state->last_interval); state->last_secs = secs; } @@ -84,7 +84,7 @@ data_cb(double secs, double nm, double mph, double watts, double miles, double a ReadState *state = (ReadState*) context; state->rideFile->appendPoint(secs, cad, hr, miles * KM_PER_MILE, - mph * KM_PER_MILE, nm, watts, alt, 0.0, 0.0, interval); + mph * KM_PER_MILE, nm, watts, alt, 0.0, 0.0, 0.0, interval); state->last_secs = secs; state->last_miles = miles; state->last_interval = interval; diff --git a/src/RideFile.cpp b/src/RideFile.cpp index e65a51d95..d8ad45409 100644 --- a/src/RideFile.cpp +++ b/src/RideFile.cpp @@ -231,10 +231,10 @@ QStringList RideFileFactory::listRideFiles(const QDir &dir) const void RideFile::appendPoint(double secs, double cad, double hr, double km, double kph, double nm, double watts, double alt, - double lon, double lat, int interval) + double lon, double lat, double headwind, int interval) { dataPoints_.append(new RideFilePoint(secs, cad, hr, km, kph, - nm, watts, alt, lon, lat, interval)); + nm, watts, alt, lon, lat, headwind, interval)); dataPresent.secs |= (secs != 0); dataPresent.cad |= (cad != 0); dataPresent.hr |= (hr != 0); @@ -245,5 +245,6 @@ void RideFile::appendPoint(double secs, double cad, double hr, double km, dataPresent.alt |= (alt != 0); dataPresent.lon |= (lon != 0); dataPresent.lat |= (lat != 0); + dataPresent.headwind |= (headwind != 0); dataPresent.interval |= (interval != 0); } diff --git a/src/RideFile.h b/src/RideFile.h index f2365f32e..b35afcc1b 100644 --- a/src/RideFile.h +++ b/src/RideFile.h @@ -43,23 +43,23 @@ struct RideFilePoint { - double secs, cad, hr, km, kph, nm, watts, alt, lon, lat;; + double secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind;; int interval; RideFilePoint() : secs(0.0), cad(0.0), hr(0.0), km(0.0), kph(0.0), - nm(0.0), watts(0.0), alt(0.0), lon(0.0), lat(0.0), interval(0) {} + nm(0.0), watts(0.0), alt(0.0), lon(0.0), lat(0.0), headwind(0.0), interval(0) {} RideFilePoint(double secs, double cad, double hr, double km, double kph, - double nm, double watts, double alt, double lon, double lat, int interval) : + double nm, double watts, double alt, double lon, double lat, double headwind, int interval) : secs(secs), cad(cad), hr(hr), km(km), kph(kph), nm(nm), - watts(watts), alt(alt), lon(lon), lat(lat), interval(interval) {} + watts(watts), alt(alt), lon(lon), lat(lat), headwind(headwind), interval(interval) {} }; struct RideFileDataPresent { - bool secs, cad, hr, km, kph, nm, watts, alt, lon, lat, interval; + bool secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, interval; // whether non-zero data of each field is present RideFileDataPresent(): secs(false), cad(false), hr(false), km(false), - kph(false), nm(false), watts(false), alt(false), lon(false), lat(false), interval(false) {} + kph(false), nm(false), watts(false), alt(false), lon(false), lat(false), headwind(false), interval(false) {} }; struct RideFileInterval @@ -106,7 +106,7 @@ class RideFile void appendPoint(double secs, double cad, double hr, double km, double kph, double nm, double watts, double alt, - double lon, double lat, int interval); + double lon, double lat, double headwind, int interval); const QList &intervals() const { return intervals_; } void addInterval(double start, double stop, const QString &name) { diff --git a/src/RideSummaryWindow.cpp b/src/RideSummaryWindow.cpp index 1f1c559f7..3b4e063be 100644 --- a/src/RideSummaryWindow.cpp +++ b/src/RideSummaryWindow.cpp @@ -184,7 +184,7 @@ RideSummaryWindow::htmlSummary() const if (p->secs >= interval.stop) break; f.appendPoint(p->secs, p->cad, p->hr, p->km, p->kph, p->nm, - p->watts, p->alt, p->lon, p->lat, 0); + p->watts, p->alt, p->lon, p->lat, p->headwind, 0); } if (f.dataPoints().size() == 0) { // Interval empty, do not compute any metrics diff --git a/src/SplitRideDialog.cpp b/src/SplitRideDialog.cpp index b93e67e69..e92e7dbc7 100644 --- a/src/SplitRideDialog.cpp +++ b/src/SplitRideDialog.cpp @@ -140,7 +140,7 @@ SplitRideDialog::CreateNewRideFile(const RideFile *ride, int nRecStart, int nRec { RideFilePoint *pPoint = ride->dataPoints().at(nItem); newRideFile->appendPoint(pPoint->secs-pointStart->secs, pPoint->cad, pPoint->hr, pPoint->km - pointStart->km, - pPoint->kph, pPoint->nm, pPoint->watts, pPoint->alt, pPoint->lon, pPoint->lat, pPoint->interval-pointStart->interval); + pPoint->kph, pPoint->nm, pPoint->watts, pPoint->alt, pPoint->lon, pPoint->lat, pPoint->headwind, pPoint->interval-pointStart->interval); } newRideFile->setDeviceType(ride->deviceType()); diff --git a/src/SrmRideFile.cpp b/src/SrmRideFile.cpp index be07f7ad8..09ec22cc3 100644 --- a/src/SrmRideFile.cpp +++ b/src/SrmRideFile.cpp @@ -202,7 +202,7 @@ RideFile *SrmFileReader::openRideFile(QFile &file, QStringList &errorStrings) co km += result->recIntSecs() * kph / 3600.0; double nm = watts / 2.0 / PI / cad * 60.0; - result->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, interval); + result->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, 0.0, interval); ++blkidx; if ((blkidx == blockhdrs[blknum].chunkcnt) && (blknum + 1 < blockcnt)) { diff --git a/src/TcxParser.cpp b/src/TcxParser.cpp index f2e9f0173..cfaaadbd1 100644 --- a/src/TcxParser.cpp +++ b/src/TcxParser.cpp @@ -132,10 +132,11 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName) // for smart recording, the delta_t will not be constant // average all the calculations based on the previous // point. + headwind = 0.0; if(rideFile->dataPoints().empty()) { // first point rideFile->appendPoint(secs, cadence, hr, distance, - speed, torque, power, alt, lon, lat, lap); + speed, torque, power, alt, lon, lat, headwind, lap); } else { // assumption that the change in ride is linear... :) @@ -153,7 +154,7 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName) if(deltaSecs == 1) { // no smart recording, just insert the data rideFile->appendPoint(secs, cadence, hr, distance, - speed, torque, power, alt, lon, lat, lap); + speed, torque, power, alt, lon, lat, headwind, lap); } else { for(int i = 1; i <= deltaSecs; i++) { @@ -176,6 +177,7 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName) prevPoint->alt + (deltaAlt * weight), lon, // lon lat, // lat + headwind, // headwind lap); } prevPoint = rideFile->dataPoints().back(); diff --git a/src/TcxParser.h b/src/TcxParser.h index 7c15b291b..d970f7ce6 100644 --- a/src/TcxParser.h +++ b/src/TcxParser.h @@ -56,6 +56,7 @@ private: double alt; double lat; double lon; + double headwind; }; #endif // _TcxParser_h diff --git a/src/WkoRideFile.cpp b/src/WkoRideFile.cpp index b53ac07da..93a0e665f 100644 --- a/src/WkoRideFile.cpp +++ b/src/WkoRideFile.cpp @@ -414,7 +414,7 @@ WKO_UCHAR *WkoParseRawData(WKO_UCHAR *fb, RideFile *rideFile, QStringList &error // !! needs to be modified to support the new alt patch rideFile->appendPoint((double)rtime/1000, cad, hr, km, - kph, nm, watts, alt, lon, lat, 0); + kph, nm, watts, alt, lon, lat, 0.0, 0); } // increment time - even for null records (perhaps especially for null