From 5284447498a001bb4a3f4d6f2503399514824a00 Mon Sep 17 00:00:00 2001 From: Damien Date: Thu, 1 Jan 2015 11:27:59 +0100 Subject: [PATCH] FitRideFile: Add new FIT fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Especially for Vectors new metrics - Left and Righ Platform Center Offset - eg: -8mm and -11mm - Left and Right Top dead Center - eg: 10° and 11° - Left and Right Bottom dead Center - eg: 203° and 210° - Left and Right Peak Power Phase Start - eg: 83° and 76° - Left and Right Peak Power Phase End - eg: 115° and 125° --- qwt/src/qwt_plot_item.cpp | 3 +- src/AllPlot.cpp | 560 ++++++++++++++++++++++++++++++++++ src/AllPlot.h | 28 ++ src/AllPlotWindow.cpp | 116 ++++++- src/AllPlotWindow.h | 12 + src/Bin2RideFile.cpp | 5 +- src/BinRideFile.cpp | 2 +- src/ComparePane.cpp | 5 +- src/Computrainer3dpFile.cpp | 8 +- src/CriticalPowerWindow.cpp | 5 +- src/CsvRideFile.cpp | 11 + src/FitRideFile.cpp | 242 ++++++++++++--- src/FitlogParser.cpp | 6 +- src/FitlogRideFile.cpp | 6 +- src/FixGaps.cpp | 24 ++ src/GcRideFile.cpp | 2 +- src/GpxParser.cpp | 7 +- src/IntervalNavigator.cpp | 4 +- src/IntervalSummaryWindow.cpp | 18 +- src/JsonRideFile.l | 10 + src/JsonRideFile.y | 26 ++ src/ManualRideFile.cpp | 6 +- src/PolarRideFile.cpp | 2 +- src/PwxRideFile.cpp | 6 +- src/QuarqParser.cpp | 5 +- src/RawRideFile.cpp | 10 +- src/RideEditor.cpp | 22 +- src/RideFile.cpp | 208 ++++++++++++- src/RideFile.h | 45 ++- src/RideFileTableModel.cpp | 32 ++ src/RideSummaryWindow.cpp | 4 +- src/SlfParser.cpp | 2 +- src/SplitActivityWizard.cpp | 4 +- src/SrdRideFile.cpp | 2 +- src/SrmRideFile.cpp | 1 + src/SyncRideFile.cpp | 1 + src/TacxCafRideFile.cpp | 5 +- src/TcxParser.cpp | 6 +- src/TxtRideFile.cpp | 4 +- src/WkoRideFile.cpp | 1 + 40 files changed, 1375 insertions(+), 91 deletions(-) diff --git a/qwt/src/qwt_plot_item.cpp b/qwt/src/qwt_plot_item.cpp index d6265d614..a41e118f9 100644 --- a/qwt/src/qwt_plot_item.cpp +++ b/qwt/src/qwt_plot_item.cpp @@ -423,7 +423,8 @@ void QwtPlotItem::hide() \param on Show if true, otherwise hide \sa isVisible(), show(), hide() */ -void QwtPlotItem::setVisible( bool on ) +void QwtPlotItem:: +setVisible( bool on ) { if ( on != d_data->isVisible ) { diff --git a/src/AllPlot.cpp b/src/AllPlot.cpp index 87530a1f8..22f69e88c 100644 --- a/src/AllPlot.cpp +++ b/src/AllPlot.cpp @@ -422,6 +422,26 @@ AllPlotObject::AllPlotObject(AllPlot *plot) : plot(plot) rpsCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); rpsCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 3)); + lpcoCurve = new QwtPlotCurve(tr("Left Pedal Center Offset")); + lpcoCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + lpcoCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 3)); + + rpcoCurve = new QwtPlotCurve(tr("Right Pedal Center Offset")); + rpcoCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + rpcoCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 3)); + + ldcCurve = new QwtPlotIntervalCurve(tr("Left Pedal Power Phase")); + ldcCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 3)); + + rdcCurve = new QwtPlotIntervalCurve(tr("Right Pedal Power Phase")); + rdcCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 3)); + + lpppCurve = new QwtPlotIntervalCurve(tr("Left Peak Pedal Power Phase")); + lpppCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 3)); + + rpppCurve = new QwtPlotIntervalCurve(tr("Right Peak Pedal Power Phase")); + rpppCurve->setYAxis(QwtAxisId(QwtAxis::yLeft, 3)); + wCurve = new QwtPlotCurve(tr("W' Balance (kJ)")); wCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); wCurve->setYAxis(QwtAxisId(QwtAxis::yRight, 2)); @@ -462,6 +482,7 @@ AllPlotObject::setColor(QColor color) << wattsDCurve << cadDCurve << nmDCurve << hrDCurve << apCurve << cadCurve << tempCurve << hrCurve << torqueCurve << balanceLCurve << balanceRCurve << lteCurve << rteCurve << lpsCurve << rpsCurve + << lpcoCurve << rpcoCurve << altCurve << slopeCurve << altSlopeCurve << rvCurve << rcadCurve << rgctCurve << gearCurve << smo2Curve << thbCurve << o2hbCurve << hhbCurve; @@ -488,6 +509,14 @@ AllPlotObject::setColor(QColor color) // has to be different... windCurve->setPen(pen); if (antialias)windCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + ldcCurve->setPen(pen); + if (antialias)ldcCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + rdcCurve->setPen(pen); + if (antialias)rdcCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + lpppCurve->setPen(pen); + if (antialias)lpppCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + rpppCurve->setPen(pen); + if (antialias)rpppCurve->setRenderHint(QwtPlotItem::RenderAntialiased); // and alt needs a feint brush altCurve->setBrush(QBrush(altCurve->pen().color().lighter(150))); @@ -533,6 +562,12 @@ AllPlotObject::~AllPlotObject() rteCurve->detach(); delete rteCurve; lpsCurve->detach(); delete lpsCurve; rpsCurve->detach(); delete rpsCurve; + lpcoCurve->detach(); delete lpcoCurve; + rpcoCurve->detach(); delete rpcoCurve; + ldcCurve->detach(); delete ldcCurve; + rdcCurve->detach(); delete rdcCurve; + lpppCurve->detach(); delete lpppCurve; + rpppCurve->detach(); delete rpppCurve; } void @@ -575,6 +610,12 @@ AllPlotObject::setVisible(bool show) rteCurve->detach(); lpsCurve->detach(); rpsCurve->detach(); + lpcoCurve->detach(); + rpcoCurve->detach(); + ldcCurve->detach(); + rdcCurve->detach(); + lpppCurve->detach(); + rpppCurve->detach(); balanceLCurve->detach(); balanceRCurve->detach(); intervalHighlighterCurve->detach(); @@ -626,6 +667,12 @@ AllPlotObject::setVisible(bool show) rteCurve->attach(plot); lpsCurve->attach(plot); rpsCurve->attach(plot); + lpcoCurve->attach(plot); + rpcoCurve->attach(plot); + ldcCurve->attach(plot); + rdcCurve->attach(plot); + lpppCurve->attach(plot); + rpppCurve->attach(plot); balanceLCurve->attach(plot); balanceRCurve->attach(plot); @@ -684,6 +731,18 @@ AllPlotObject::hideUnwanted() lpsCurve->detach(); rpsCurve->detach(); } + if (!plot->showPCO) { + lpcoCurve->detach(); + rpcoCurve->detach(); + } + if (!plot->showDC) { + ldcCurve->detach(); + rdcCurve->detach(); + } + if (!plot->showPPP) { + lpppCurve->detach(); + rpppCurve->detach(); + } if (!plot->showBalance) { balanceLCurve->detach(); balanceRCurve->detach(); @@ -860,6 +919,12 @@ AllPlot::configChanged(qint32) standard->rteCurve->setRenderHint(QwtPlotItem::RenderAntialiased); standard->lpsCurve->setRenderHint(QwtPlotItem::RenderAntialiased); standard->rpsCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->lpcoCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->rpcoCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->ldcCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->rdcCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->lpppCurve->setRenderHint(QwtPlotItem::RenderAntialiased); + standard->rpppCurve->setRenderHint(QwtPlotItem::RenderAntialiased); standard->balanceLCurve->setRenderHint(QwtPlotItem::RenderAntialiased); standard->balanceRCurve->setRenderHint(QwtPlotItem::RenderAntialiased); standard->intervalHighlighterCurve->setRenderHint(QwtPlotItem::RenderAntialiased); @@ -976,6 +1041,24 @@ AllPlot::configChanged(qint32) QPen rpsPen = QPen(GColor(CRPS)); rpsPen.setWidth(width); standard->rpsCurve->setPen(rpsPen); + QPen lpcoPen = QPen(GColor(CLPS)); + lpcoPen.setWidth(width); + standard->lpcoCurve->setPen(lpcoPen); + QPen rpcoPen = QPen(GColor(CRPS)); + rpcoPen.setWidth(width); + standard->rpcoCurve->setPen(rpcoPen); + QPen ldcPen = QPen(GColor(CLPS)); + ldcPen.setWidth(width); + standard->ldcCurve->setPen(ldcPen); + QPen rdcPen = QPen(GColor(CRPS)); + rdcPen.setWidth(width); + standard->rdcCurve->setPen(rdcPen); + QPen lpppPen = QPen(GColor(CLPS)); + lpppPen.setWidth(width); + standard->lpppCurve->setPen(lpppPen); + QPen rpppPen = QPen(GColor(CRPS)); + rpppPen.setWidth(width); + standard->rpppCurve->setPen(rpppPen); QPen wPen = QPen(GColor(CWBAL)); wPen.setWidth(width); // don't thicken standard->wCurve->setPen(wPen); @@ -1118,6 +1201,30 @@ AllPlot::configChanged(qint32) p.setAlpha(64); standard->rpsCurve->setBrush(QBrush(p)); + p = standard->lpcoCurve->pen().color(); + p.setAlpha(64); + standard->lpcoCurve->setBrush(QBrush(p)); + + p = standard->rpcoCurve->pen().color(); + p.setAlpha(64); + standard->rpcoCurve->setBrush(QBrush(p)); + + p = standard->ldcCurve->pen().color(); + p.setAlpha(64); + standard->ldcCurve->setBrush(QBrush(p)); + + p = standard->rdcCurve->pen().color(); + p.setAlpha(64); + standard->rdcCurve->setBrush(QBrush(p)); + + p = standard->lpppCurve->pen().color(); + p.setAlpha(64); + standard->lpppCurve->setBrush(QBrush(p)); + + p = standard->rpppCurve->pen().color(); + p.setAlpha(64); + standard->rpppCurve->setBrush(QBrush(p)); + p = standard->slopeCurve->pen().color(); p.setAlpha(64); standard->slopeCurve->setBrush(QBrush(p)); @@ -1163,6 +1270,12 @@ AllPlot::configChanged(qint32) standard->rteCurve->setBrush(Qt::NoBrush); standard->lpsCurve->setBrush(Qt::NoBrush); standard->rpsCurve->setBrush(Qt::NoBrush); + standard->lpcoCurve->setBrush(Qt::NoBrush); + standard->rpcoCurve->setBrush(Qt::NoBrush); + standard->ldcCurve->setBrush(Qt::NoBrush); + standard->rdcCurve->setBrush(Qt::NoBrush); + standard->lpppCurve->setBrush(Qt::NoBrush); + standard->rpppCurve->setBrush(Qt::NoBrush); standard->slopeCurve->setBrush(Qt::NoBrush); //standard->altSlopeCurve->setBrush((Qt::NoBrush)); //standard->balanceLCurve->setBrush(Qt::NoBrush); @@ -1335,16 +1448,19 @@ struct DataPoint { double time, hr, watts, atiss, antiss, np, rv, rcad, rgct, smo2, thb, o2hb, hhb, ap, xp, speed, cad, alt, temp, wind, torque, lrbalance, lte, rte, lps, rps, + lpco, rpco, ltdc, rtdc, lbdc, rbdc, ltppp, rtppp, lbppp, rbppp, kphd, wattsd, cadd, nmd, hrd, slope; DataPoint(double t, double h, double w, double at, double an, double n, double rv, double rcad, double rgct, double smo2, double thb, double o2hb, double hhb, double l, double x, double s, double c, double a, double te, double wi, double tq, double lrb, double lte, double rte, double lps, double rps, + double lpco, double rpco, double ltdc, double rtdc, double lbdc, double rbdc, double ltppp, double rtppp, double lbppp, double rbppp, double kphd, double wattsd, double cadd, double nmd, double hrd, double sl) : time(t), hr(h), watts(w), atiss(at), antiss(an), np(n), rv(rv), rcad(rcad), rgct(rgct), smo2(smo2), thb(thb), o2hb(o2hb), hhb(hhb), ap(l), xp(x), speed(s), cad(c), alt(a), temp(te), wind(wi), torque(tq), lrbalance(lrb), lte(lte), rte(rte), lps(lps), rps(rps), + lpco(lpco), rpco(rpco), ltdc(ltdc), rtdc(rtdc), lbdc(lbdc), rbdc(rbdc), ltppp(ltppp), rtppp(rtppp), lbppp(lbppp), rbppp(rbppp), kphd(kphd), wattsd(wattsd), cadd(cadd), nmd(nmd), hrd(hrd), slope(sl) {} }; @@ -1501,6 +1617,12 @@ AllPlot::recalc(AllPlotObject *objects) if (!objects->rteArray.empty()) objects->rteCurve->setSamples(data, data); if (!objects->lpsArray.empty()) objects->lpsCurve->setSamples(data, data); if (!objects->rpsArray.empty()) objects->rpsCurve->setSamples(data, data); + if (!objects->lpcoArray.empty()) objects->lpcoCurve->setSamples(data, data); + if (!objects->rpcoArray.empty()) objects->rpcoCurve->setSamples(data, data); + if (!objects->ltdcArray.empty()) objects->ldcCurve->setSamples(new QwtIntervalSeriesData(intData)); + if (!objects->rtdcArray.empty()) objects->rdcCurve->setSamples(new QwtIntervalSeriesData(intData));; + if (!objects->ltpppArray.empty()) objects->lpppCurve->setSamples(new QwtIntervalSeriesData(intData)); + if (!objects->rtpppArray.empty()) objects->rpppCurve->setSamples(new QwtIntervalSeriesData(intData)); return; } @@ -1546,6 +1668,17 @@ AllPlot::recalc(AllPlotObject *objects) double totalRTE = 0.0; double totalLPS = 0.0; double totalRPS = 0.0; + double totalLPCO = 0.0; + double totalRPCO = 0.0; + double totalLTDC = 0.0; + double totalRTDC = 0.0; + double totalLBDC = 0.0; + double totalRBDC = 0.0; + double totalLTPPP = 0.0; + double totalRTPPP = 0.0; + double totalLBPPP = 0.0; + double totalRBPPP = 0.0; + QList list; @@ -1585,6 +1718,13 @@ AllPlot::recalc(AllPlotObject *objects) objects->smoothRTE.resize(rideTimeSecs + 1); objects->smoothLPS.resize(rideTimeSecs + 1); objects->smoothRPS.resize(rideTimeSecs + 1); + objects->smoothLPCO.resize(rideTimeSecs + 1); + objects->smoothRPCO.resize(rideTimeSecs + 1); + objects->smoothLDC.resize(rideTimeSecs + 1); + objects->smoothRDC.resize(rideTimeSecs + 1); + objects->smoothLPPP.resize(rideTimeSecs + 1); + objects->smoothRPPP.resize(rideTimeSecs + 1); + // do the smoothing by calculating the average of the "applysmooth" values left // of the current data point - for points in time smaller than "applysmooth" // only the available datapoints left are used to build the average @@ -1617,6 +1757,16 @@ AllPlot::recalc(AllPlotObject *objects) (!objects->rteArray.empty() ? objects->rteArray[i] : 0), (!objects->lpsArray.empty() ? objects->lpsArray[i] : 0), (!objects->rpsArray.empty() ? objects->rpsArray[i] : 0), + (!objects->lpcoArray.empty() ? objects->lpcoArray[i] : 0), + (!objects->rpcoArray.empty() ? objects->rpcoArray[i] : 0), + (!objects->ltdcArray.empty() ? objects->ltdcArray[i] : 0), + (!objects->rtdcArray.empty() ? objects->rtdcArray[i] : 0), + (!objects->lbdcArray.empty() ? objects->lbdcArray[i] : 0), + (!objects->rbdcArray.empty() ? objects->rbdcArray[i] : 0), + (!objects->ltpppArray.empty() ? objects->ltpppArray[i] : 0), + (!objects->rtpppArray.empty() ? objects->rtpppArray[i] : 0), + (!objects->lbpppArray.empty() ? objects->lbpppArray[i] : 0), + (!objects->rbpppArray.empty() ? objects->rbpppArray[i] : 0), (!objects->accelArray.empty() ? objects->accelArray[i] : 0), (!objects->wattsDArray.empty() ? objects->wattsDArray[i] : 0), (!objects->cadDArray.empty() ? objects->cadDArray[i] : 0), @@ -1683,6 +1833,26 @@ AllPlot::recalc(AllPlotObject *objects) totalLPS += (objects->lpsArray[i]>0?objects->lpsArray[i]:0); if (!objects->rpsArray.empty()) totalRPS += (objects->rpsArray[i]>0?objects->rpsArray[i]:0); + if (!objects->lpcoArray.empty()) + totalLPCO += objects->lpcoArray[i]; + if (!objects->rpcoArray.empty()) + totalRPCO += objects->rpcoArray[i]; + if (!objects->ltdcArray.empty()) + totalLTDC += (objects->ltdcArray[i]>0?objects->ltdcArray[i]:0); + if (!objects->rtdcArray.empty()) + totalRTDC += (objects->rtdcArray[i]>0?objects->rtdcArray[i]:0); + if (!objects->lbdcArray.empty()) + totalLBDC += (objects->lbdcArray[i]>0?objects->lbdcArray[i]:0); + if (!objects->rbdcArray.empty()) + totalRBDC += (objects->rbdcArray[i]>0?objects->rbdcArray[i]:0); + if (!objects->ltpppArray.empty()) + totalLTPPP += (objects->ltpppArray[i]>0?objects->ltpppArray[i]:0); + if (!objects->rtpppArray.empty()) + totalRTPPP += (objects->rtpppArray[i]>0?objects->rtpppArray[i]:0); + if (!objects->lbpppArray.empty()) + totalLBPPP += (objects->lbpppArray[i]>0?objects->lbpppArray[i]:0); + if (!objects->rbpppArray.empty()) + totalRBPPP += (objects->rbpppArray[i]>0?objects->rbpppArray[i]:0); totalDist = objects->distanceArray[i]; list.append(dp); @@ -1720,6 +1890,16 @@ AllPlot::recalc(AllPlotObject *objects) totalRTE -= dp.rte; totalLPS -= dp.lps; totalRPS -= dp.rps; + totalLPCO -= dp.lpco; + totalRPCO -= dp.rpco; + totalLTDC -= dp.ltdc; + totalRTDC -= dp.rtdc; + totalLBDC -= dp.lbdc; + totalRBDC -= dp.rbdc; + totalLTPPP -= dp.ltppp; + totalRTPPP -= dp.rtppp; + totalLBPPP -= dp.lbppp; + totalRBPPP -= dp.rbppp; totalBalance -= (dp.lrbalance>0?dp.lrbalance:50); list.removeFirst(); } @@ -1757,6 +1937,12 @@ AllPlot::recalc(AllPlotObject *objects) objects->smoothRTE[secs] = 0.0; objects->smoothLPS[secs] = 0.0; objects->smoothRPS[secs] = 0.0; + objects->smoothLPCO[secs] = 0.0; + objects->smoothRPCO[secs] = 0.0; + objects->smoothLDC[secs] = QwtIntervalSample(); + objects->smoothRDC[secs] = QwtIntervalSample(); + objects->smoothLPPP[secs] = QwtIntervalSample(); + objects->smoothRPPP[secs] = QwtIntervalSample(); objects->smoothBalanceL[secs] = 50; objects->smoothBalanceR[secs] = 50; } @@ -1807,6 +1993,12 @@ AllPlot::recalc(AllPlotObject *objects) objects->smoothRTE[secs] = totalRTE / list.size(); objects->smoothLPS[secs] = totalLPS / list.size(); objects->smoothRPS[secs] = totalRPS / list.size(); + objects->smoothLPCO[secs] = totalLPCO / list.size(); + objects->smoothRPCO[secs] = totalRPCO / list.size(); + objects->smoothLDC[secs] = QwtIntervalSample( bydist ? totalDist : secs / 60.0, QwtInterval(totalLTDC / list.size(), totalLBDC / list.size() ) ); + objects->smoothRDC[secs] = QwtIntervalSample( bydist ? totalDist : secs / 60.0, QwtInterval(totalRTDC / list.size(), totalRBDC / list.size() ) ); + objects->smoothLPPP[secs] = QwtIntervalSample( bydist ? totalDist : secs / 60.0, QwtInterval(totalLTPPP / list.size(), totalLBPPP / list.size() ) ); + objects->smoothRPPP[secs] = QwtIntervalSample( bydist ? totalDist : secs / 60.0, QwtInterval(totalRTPPP / list.size(), totalRBPPP / list.size() ) ); } objects->smoothDistance[secs] = totalDist; objects->smoothTime[secs] = secs / 60.0; @@ -1856,6 +2048,12 @@ AllPlot::recalc(AllPlotObject *objects) objects->smoothRTE.resize(0); objects->smoothLPS.resize(0); objects->smoothRPS.resize(0); + objects->smoothLPCO.resize(0); + objects->smoothRPCO.resize(0); + objects->smoothLDC.resize(0); + objects->smoothRDC.resize(0); + objects->smoothLPPP.resize(0); + objects->smoothRPPP.resize(0); objects->smoothBalanceL.resize(0); objects->smoothBalanceR.resize(0); @@ -1908,6 +2106,13 @@ AllPlot::recalc(AllPlotObject *objects) objects->smoothRTE.append(dp->rte); objects->smoothLPS.append(dp->lps); objects->smoothRPS.append(dp->rps); + objects->smoothLPCO.append(dp->lpco); + objects->smoothRPCO.append(dp->rpco); + objects->smoothLDC.append(QwtIntervalSample( bydist ? objects->smoothDistance.last() : objects->smoothTime.last(), QwtInterval(dp->ltdc , dp->rbdc ) )); + objects->smoothRDC.append(QwtIntervalSample( bydist ? objects->smoothDistance.last() : objects->smoothTime.last(), QwtInterval(dp->rtdc , dp->rbdc ) )); + objects->smoothLPPP.append(QwtIntervalSample( bydist ? objects->smoothDistance.last() : objects->smoothTime.last(), QwtInterval(dp->ltppp , dp->lbppp ) )); + objects->smoothRPPP.append(QwtIntervalSample( bydist ? objects->smoothDistance.last() : objects->smoothTime.last(), QwtInterval(dp->rtppp , dp->rbppp ) )); + double head = dp->headwind * (context->athlete->useMetricUnits ? 1.0f : MILES_PER_KM); double speed = dp->kph * (context->athlete->useMetricUnits ? 1.0f : MILES_PER_KM); @@ -2056,6 +2261,23 @@ AllPlot::recalc(AllPlotObject *objects) if (!objects->rpsArray.empty()) objects->rpsCurve->setSamples(xaxis.data() + startingIndex, objects->smoothRPS.data() + startingIndex, totalPoints); + if (!objects->lpcoArray.empty()) objects->lpcoCurve->setSamples(xaxis.data() + startingIndex, + objects->smoothLPCO.data() + startingIndex, totalPoints); + if (!objects->rpcoArray.empty()) objects->rpcoCurve->setSamples(xaxis.data() + startingIndex, + objects->smoothRPCO.data() + startingIndex, totalPoints); + if (!objects->ltdcArray.empty()) { + objects->ldcCurve->setSamples(new QwtIntervalSeriesData(objects->smoothLDC)); + } + if (!objects->rtdcArray.empty()) { + objects->rdcCurve->setSamples(new QwtIntervalSeriesData(objects->smoothRDC)); + } + if (!objects->ltpppArray.empty()) { + objects->lpppCurve->setSamples(new QwtIntervalSeriesData(objects->smoothLPPP)); + } + if (!objects->rtpppArray.empty()) { + objects->rpppCurve->setSamples(new QwtIntervalSeriesData(objects->smoothRPPP)); + } + setAltSlopePlotStyle(objects->altSlopeCurve); setYMax(); @@ -2623,6 +2845,12 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) double *smoothRTE = &plot->standard->smoothRTE[startidx]; double *smoothLPS = &plot->standard->smoothLPS[startidx]; double *smoothRPS = &plot->standard->smoothRPS[startidx]; + double *smoothLPCO = &plot->standard->smoothLPCO[startidx]; + double *smoothRPCO = &plot->standard->smoothRPCO[startidx]; + QwtIntervalSample *smoothLDC = &plot->standard->smoothLDC[startidx]; + QwtIntervalSample *smoothRDC = &plot->standard->smoothRDC[startidx]; + QwtIntervalSample *smoothLPPP = &plot->standard->smoothLPPP[startidx]; + QwtIntervalSample *smoothRPPP = &plot->standard->smoothRPPP[startidx]; // deltas double *smoothAC = &plot->standard->smoothAccel[startidx]; @@ -2715,6 +2943,12 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) standard->rpsCurve->detach(); standard->balanceLCurve->detach(); standard->balanceRCurve->detach(); + standard->lpcoCurve->detach(); + standard->rpcoCurve->detach(); + standard->ldcCurve->detach(); + standard->rdcCurve->detach(); + standard->lpppCurve->detach(); + standard->rpppCurve->detach(); standard->wattsCurve->setVisible(rideItem->ride()->areDataPresent()->watts && showPowerState < 2); standard->atissCurve->setVisible(rideItem->ride()->areDataPresent()->watts && showATISS); @@ -2752,6 +2986,12 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) standard->rpsCurve->setVisible(rideItem->ride()->areDataPresent()->rps && showPS); standard->balanceLCurve->setVisible(rideItem->ride()->areDataPresent()->lrbalance && showBalance); standard->balanceRCurve->setVisible(rideItem->ride()->areDataPresent()->lrbalance && showBalance); + standard->lpcoCurve->setVisible(rideItem->ride()->areDataPresent()->lpco && showPCO); + standard->rpcoCurve->setVisible(rideItem->ride()->areDataPresent()->rpco && showPCO); + standard->ldcCurve->setVisible(rideItem->ride()->areDataPresent()->ltdc && showDC); + standard->rdcCurve->setVisible(rideItem->ride()->areDataPresent()->rtdc && showDC); + standard->lpppCurve->setVisible(rideItem->ride()->areDataPresent()->ltppp && showPPP); + standard->rpppCurve->setVisible(rideItem->ride()->areDataPresent()->rtppp && showPPP); if (showW) { standard->wCurve->setSamples(bydist ? plot->standard->wprimeDist.data() : plot->standard->wprimeTime.data(), @@ -2798,6 +3038,21 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) standard->rteCurve->setSamples(xaxis, smoothRTE, points); standard->lpsCurve->setSamples(xaxis, smoothLPS, points); standard->rpsCurve->setSamples(xaxis, smoothRPS, points); + standard->lpcoCurve->setSamples(xaxis, smoothLPCO, points); + standard->rpcoCurve->setSamples(xaxis, smoothRPCO, points); + + QVector tmpLDC(points); + memcpy(tmpLDC.data(), smoothLDC, (points) * sizeof(QwtIntervalSample)); + standard->ldcCurve->setSamples(new QwtIntervalSeriesData(tmpLDC)); + QVector tmpRDC(points); + memcpy(tmpRDC.data(), smoothRDC, (points) * sizeof(QwtIntervalSample)); + standard->rdcCurve->setSamples(new QwtIntervalSeriesData(tmpRDC)); + QVector tmpLPPP(points); + memcpy(tmpLPPP.data(), smoothLPPP, (points) * sizeof(QwtIntervalSample)); + standard->lpppCurve->setSamples(new QwtIntervalSeriesData(tmpLPPP)); + QVector tmpRPPP(points); + memcpy(tmpRPPP.data(), smoothRPPP, (points) * sizeof(QwtIntervalSample)); + standard->rpppCurve->setSamples(new QwtIntervalSeriesData(tmpRPPP)); /*QVector _time(stopidx-startidx); qMemCopy( _time.data(), xaxis, (stopidx-startidx) * sizeof( double ) ); @@ -2842,6 +3097,8 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) setSymbol(standard->rteCurve, points); setSymbol(standard->lpsCurve, points); setSymbol(standard->rpsCurve, points); + setSymbol(standard->lpcoCurve, points); + setSymbol(standard->rpcoCurve, points); setAltSlopePlotStyle(standard->altSlopeCurve); setYMax(); @@ -2948,6 +3205,18 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx) standard->lpsCurve->attach(this); standard->rpsCurve->attach(this); } + if (!plot->standard->smoothLPCO.empty()) { + standard->lpcoCurve->attach(this); + standard->rpcoCurve->attach(this); + } + if (!plot->standard->smoothLDC.empty()) { + standard->ldcCurve->attach(this); + standard->rdcCurve->attach(this); + } + if (!plot->standard->smoothLPPP.empty()) { + standard->lpppCurve->attach(this); + standard->rpppCurve->attach(this); + } refreshReferenceLines(); refreshIntervalMarkers(); @@ -3016,6 +3285,12 @@ AllPlot::setDataFromPlot(AllPlot *plot) standard->rteCurve->detach(); standard->lpsCurve->detach(); standard->rpsCurve->detach(); + standard->lpcoCurve->detach(); + standard->rpcoCurve->detach(); + standard->ldcCurve->detach(); + standard->rdcCurve->detach(); + standard->lpppCurve->detach(); + standard->rpppCurve->detach(); standard->wCurve->setVisible(false); standard->mCurve->setVisible(false); @@ -3053,6 +3328,12 @@ AllPlot::setDataFromPlot(AllPlot *plot) standard->rteCurve->setVisible(false); standard->lpsCurve->setVisible(false); standard->rpsCurve->setVisible(false); + standard->lpcoCurve->setVisible(false); + standard->rpcoCurve->setVisible(false); + standard->ldcCurve->setVisible(false); + standard->rdcCurve->setVisible(false); + standard->lpppCurve->setVisible(false); + standard->rpppCurve->setVisible(false); QwtPlotCurve *ourCurve = NULL, *thereCurve = NULL; QwtPlotCurve *ourCurve2 = NULL, *thereCurve2 = NULL; @@ -3323,6 +3604,49 @@ AllPlot::setDataFromPlot(AllPlot *plot) } break; + case RideFile::lpco: + case RideFile::rpco: + { + ourCurve = standard->lpcoCurve; + ourCurve2 = standard->rpcoCurve; + thereCurve = referencePlot->standard->lpcoCurve; + thereCurve2 = referencePlot->standard->rpcoCurve; + title = tr("Left/Right Pedal Center Offset"); + } + break; + + case RideFile::ltdc: + { + ourICurve = standard->ldcCurve; + thereICurve = referencePlot->standard->ldcCurve; + title = tr("Left Power Phase"); + } + break; + + case RideFile::rtdc: + { + ourICurve = standard->rdcCurve; + thereICurve = referencePlot->standard->rdcCurve; + title = tr("Right Power Phase"); + } + break; + + case RideFile::ltppp: + { + ourICurve = standard->lpppCurve; + thereICurve = referencePlot->standard->lpppCurve; + title = tr("Left Peak Power Phase"); + } + break; + + case RideFile::rtppp: + { + ourICurve = standard->rpppCurve; + thereICurve = referencePlot->standard->rpppCurve; + title = tr("Right Peak Power Phase"); + } + break; + case RideFile::lrbalance: { ourCurve = standard->balanceLCurve; @@ -3568,6 +3892,12 @@ AllPlot::setDataFromPlots(QList plots) standard->rteCurve->detach(); standard->lpsCurve->detach(); standard->rpsCurve->detach(); + standard->lpcoCurve->detach(); + standard->rpcoCurve->detach(); + standard->ldcCurve->detach(); + standard->rdcCurve->detach(); + standard->lpppCurve->detach(); + standard->rpppCurve->detach(); standard->wCurve->setVisible(false); standard->mCurve->setVisible(false); @@ -3605,6 +3935,12 @@ AllPlot::setDataFromPlots(QList plots) standard->rteCurve->setVisible(false); standard->lpsCurve->setVisible(false); standard->rpsCurve->setVisible(false); + standard->lpcoCurve->setVisible(false); + standard->rpcoCurve->setVisible(false); + standard->ldcCurve->setVisible(false); + standard->rdcCurve->setVisible(false); + standard->lpppCurve->setVisible(false); + standard->rpppCurve->setVisible(false); // clear previous curves foreach(QwtPlotCurve *prior, compares) { @@ -3933,6 +4269,55 @@ AllPlot::setDataFromPlots(QList plots) } break; + case RideFile::rpco: + case RideFile::lpco: + { + ourCurve = new QwtPlotCurve(tr("Left Pedal Center Offset")); + ourCurve->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve = referencePlot->standard->lpcoCurve; + ourCurve2 = new QwtPlotCurve(tr("Right Pedal Center Offset")); + ourCurve2->setPaintAttribute(QwtPlotCurve::FilterPoints, true); + thereCurve2 = referencePlot->standard->rpcoCurve; + title = tr("Left/Right Pedal Center Offset"); + } + break; + + case RideFile::ltdc: + case RideFile::lbdc: + { + ourICurve = new QwtPlotIntervalCurve(tr("Left Power Phase")); + thereICurve = referencePlot->standard->ldcCurve; + title = tr("Left Power Phase"); + } + break; + + case RideFile::rtdc: + case RideFile::rbdc: + { + ourICurve = new QwtPlotIntervalCurve(tr("Right Power Phase")); + thereICurve = referencePlot->standard->rdcCurve; + title = tr("Right Power Phase"); + } + break; + + case RideFile::ltppp: + case RideFile::lbppp: + { + ourICurve = new QwtPlotIntervalCurve(tr("Left Peak Power Phase")); + thereICurve = referencePlot->standard->lpppCurve; + title = tr("Left Peak Power Phase"); + } + break; + + case RideFile::rtppp: + case RideFile::rbppp: + { + ourICurve = new QwtPlotIntervalCurve(tr("Right Peak Power Phase")); + thereICurve = referencePlot->standard->rpppCurve; + title = tr("Right Peak Power Phase"); + } + break; + case RideFile::lrbalance: { ourCurve = new QwtPlotCurve(tr("Left Balance")); @@ -4453,6 +4838,39 @@ AllPlot::setDataFromObject(AllPlotObject *object, AllPlot *reference) standard->rpsCurve->setVisible(true); } + if (!object->lpcoArray.empty()) { + standard->lpcoCurve->setSamples(xaxis.data(), object->smoothLPCO.data(), totalPoints); + standard->rpcoCurve->setSamples(xaxis.data(), object->smoothRPCO.data(), totalPoints); + standard->lpcoCurve->attach(this); + standard->lpcoCurve->setVisible(true); + standard->rpcoCurve->attach(this); + standard->rpcoCurve->setVisible(true); + } + + if (!object->ltdcArray.empty()) { + standard->ldcCurve->setSamples(new QwtIntervalSeriesData(object->smoothLDC)); + standard->ldcCurve->attach(this); + standard->ldcCurve->setVisible(true); + } + + if (!object->rtdcArray.empty()) { + standard->rdcCurve->setSamples(new QwtIntervalSeriesData(object->smoothRDC)); + standard->rdcCurve->attach(this); + standard->rdcCurve->setVisible(true); + } + + if (!object->ltpppArray.empty()) { + standard->lpppCurve->setSamples(new QwtIntervalSeriesData(object->smoothLPPP)); + standard->lpppCurve->attach(this); + standard->lpppCurve->setVisible(true); + } + + if (!object->rtpppArray.empty()) { + standard->rpppCurve->setSamples(new QwtIntervalSeriesData(object->smoothRPPP)); + standard->rpppCurve->attach(this); + standard->rpppCurve->setVisible(true); + } + // to the max / min standard->grid->detach(); @@ -4493,6 +4911,12 @@ AllPlot::setDataFromObject(AllPlotObject *object, AllPlot *reference) standard->rteCurve->setVisible(referencePlot->showTE); standard->lpsCurve->setVisible(referencePlot->showPS); standard->rpsCurve->setVisible(referencePlot->showPS); + standard->lpcoCurve->setVisible(referencePlot->showPCO); + standard->rpcoCurve->setVisible(referencePlot->showPCO); + standard->ldcCurve->setVisible(referencePlot->showDC); + standard->rdcCurve->setVisible(referencePlot->showDC); + standard->lpppCurve->setVisible(referencePlot->showPPP); + standard->rpppCurve->setVisible(referencePlot->showPPP); // set xaxis -- but not min/max as we get called during smoothing // and massively quicker to reuse data and replot @@ -4586,6 +5010,16 @@ AllPlot::setDataFromRideFile(RideFile *ride, AllPlotObject *here) here->rteArray.resize(dataPresent->rte ? npoints : 0); here->lpsArray.resize(dataPresent->lps ? npoints : 0); here->rpsArray.resize(dataPresent->rps ? npoints : 0); + here->lpcoArray.resize(dataPresent->lpco ? npoints : 0); + here->rpcoArray.resize(dataPresent->rpco ? npoints : 0); + here->ltdcArray.resize(dataPresent->ltdc ? npoints : 0); + here->rtdcArray.resize(dataPresent->rtdc ? npoints : 0); + here->lbdcArray.resize(dataPresent->lbdc ? npoints : 0); + here->rbdcArray.resize(dataPresent->rbdc ? npoints : 0); + here->ltpppArray.resize(dataPresent->ltppp ? npoints : 0); + here->rtpppArray.resize(dataPresent->rtppp ? npoints : 0); + here->lbpppArray.resize(dataPresent->lbppp ? npoints : 0); + here->rbpppArray.resize(dataPresent->rbppp ? npoints : 0); here->timeArray.resize(npoints); here->distanceArray.resize(npoints); @@ -4626,6 +5060,12 @@ AllPlot::setDataFromRideFile(RideFile *ride, AllPlotObject *here) here->rteCurve->detach(); here->lpsCurve->detach(); here->rpsCurve->detach(); + here->lpcoCurve->detach(); + here->rpcoCurve->detach(); + here->ldcCurve->detach(); + here->rdcCurve->detach(); + here->lpppCurve->detach(); + here->rpppCurve->detach(); if (!here->altArray.empty()) { here->altCurve->attach(this); @@ -4676,6 +5116,18 @@ AllPlot::setDataFromRideFile(RideFile *ride, AllPlotObject *here) here->balanceLCurve->attach(this); here->balanceRCurve->attach(this); } + if (!here->lpcoArray.empty()) { + here->lpcoCurve->attach(this); + here->rpcoCurve->attach(this); + } + if (!here->ltdcArray.empty()) { + here->ldcCurve->attach(this); + here->rdcCurve->attach(this); + } + if (!here->ltpppArray.empty()) { + here->lpppCurve->attach(this); + here->rpppCurve->attach(this); + } here->wCurve->setVisible(dataPresent->watts && showW); here->mCurve->setVisible(dataPresent->watts && showW); @@ -4708,6 +5160,12 @@ AllPlot::setDataFromRideFile(RideFile *ride, AllPlotObject *here) here->rpsCurve->setVisible(dataPresent->rps && showPS); here->balanceLCurve->setVisible(dataPresent->lrbalance && showBalance); here->balanceRCurve->setVisible(dataPresent->lrbalance && showBalance); + here->lpcoCurve->setVisible(dataPresent->lpco && showPCO); + here->rpcoCurve->setVisible(dataPresent->rpco && showPCO); + here->ldcCurve->setVisible(dataPresent->ltdc && showDC); + here->rdcCurve->setVisible(dataPresent->rtdc && showDC); + here->lpppCurve->setVisible(dataPresent->ltppp && showPPP); + here->rpppCurve->setVisible(dataPresent->rtppp && showPPP); // deltas here->accelCurve->setVisible(dataPresent->kph && showAccel); @@ -4787,6 +5245,16 @@ AllPlot::setDataFromRideFile(RideFile *ride, AllPlotObject *here) if (!here->rteArray.empty()) here->rteArray[arrayLength] = point->rte; if (!here->lpsArray.empty()) here->lpsArray[arrayLength] = point->lps; if (!here->rpsArray.empty()) here->rpsArray[arrayLength] = point->rps; + if (!here->lpcoArray.empty()) here->lpcoArray[arrayLength] = point->lpco; + if (!here->rpcoArray.empty()) here->rpcoArray[arrayLength] = point->rpco; + if (!here->ltdcArray.empty()) here->ltdcArray[arrayLength] = point->ltdc; + if (!here->rtdcArray.empty()) here->rtdcArray[arrayLength] = point->rtdc; + if (!here->lbdcArray.empty()) here->lbdcArray[arrayLength] = point->lbdc; + if (!here->rbdcArray.empty()) here->rbdcArray[arrayLength] = point->rbdc; + if (!here->ltpppArray.empty()) here->ltpppArray[arrayLength] = point->ltppp; + if (!here->rtpppArray.empty()) here->rtpppArray[arrayLength] = point->rtppp; + if (!here->lbpppArray.empty()) here->lbpppArray[arrayLength] = point->lbppp; + if (!here->rbpppArray.empty()) here->rbpppArray[arrayLength] = point->rbppp; here->distanceArray[arrayLength] = max(0, (context->athlete->useMetricUnits @@ -4841,6 +5309,12 @@ AllPlot::setDataFromRideFile(RideFile *ride, AllPlotObject *here) here->rpsCurve->detach(); here->balanceLCurve->detach(); here->balanceRCurve->detach(); + here->lpcoCurve->detach(); + here->rpcoCurve->detach(); + here->ldcCurve->detach(); + here->rdcCurve->detach(); + here->lpppCurve->detach(); + here->rpppCurve->detach(); foreach(QwtPlotMarker *mrk, here->d_mrk) delete mrk; @@ -4914,6 +5388,9 @@ AllPlot::setShow(RideFile::SeriesType type, bool state) setShowBalance(false); setShowTE(false); setShowPS(false); + setShowPCO(false); + setShowDC(false); + setShowPPP(false); break; case RideFile::secs: @@ -4992,6 +5469,22 @@ AllPlot::setShow(RideFile::SeriesType type, bool state) case RideFile::rps: setShowPS(state); break; + case RideFile::lpco: + case RideFile::rpco: + setShowPCO(state); + break; + case RideFile::ltdc: + case RideFile::rtdc: + case RideFile::lbdc: + case RideFile::rbdc: + setShowDC(state); + break; + case RideFile::ltppp: + case RideFile::rtppp: + case RideFile::lbppp: + case RideFile::rbppp: + setShowPPP(state); + break; case RideFile::interval: break; case RideFile::vam: @@ -5471,6 +5964,48 @@ AllPlot::setShowPS(bool show) replot(); } +void +AllPlot::setShowDC(bool show) +{ + showDC = show; + standard->ldcCurve->setVisible(show); + standard->rdcCurve->setVisible(show); + setYMax(); + + // remember the curves and colors + isolation = false; + curveColors->saveState(); + replot(); +} + +void +AllPlot::setShowPPP(bool show) +{ + showPPP = show; + standard->lpppCurve->setVisible(show); + standard->rpppCurve->setVisible(show); + setYMax(); + + // remember the curves and colors + isolation = false; + curveColors->saveState(); + replot(); +} + +void +AllPlot::setShowPCO(bool show) +{ + showPCO = show; + standard->lpcoCurve->setVisible(show); + standard->rpcoCurve->setVisible(show); + setYMax(); + + // remember the curves and colors + isolation = false; + curveColors->saveState(); + replot(); +} + void AllPlot::setShowGrid(bool show) { @@ -5590,6 +6125,25 @@ AllPlot::setPaintBrush(int state) p = standard->rpsCurve->pen().color(); p.setAlpha(64); standard->rpsCurve->setBrush(QBrush(p)); + p = standard->lpcoCurve->pen().color(); + p.setAlpha(64); + standard->lpcoCurve->setBrush(QBrush(p)); + p = standard->rpcoCurve->pen().color(); + p.setAlpha(64); + standard->rpcoCurve->setBrush(QBrush(p)); + p = standard->ldcCurve->pen().color(); + p.setAlpha(64); + standard->ldcCurve->setBrush(QBrush(p)); + p = standard->rdcCurve->pen().color(); + p.setAlpha(64); + standard->rdcCurve->setBrush(QBrush(p)); + p = standard->lpppCurve->pen().color(); + p.setAlpha(64); + standard->lpppCurve->setBrush(QBrush(p)); + + p = standard->rpppCurve->pen().color(); + p.setAlpha(64); + standard->rpppCurve->setBrush(QBrush(p)); p = standard->slopeCurve->pen().color(); p.setAlpha(64); @@ -5636,6 +6190,12 @@ AllPlot::setPaintBrush(int state) standard->rteCurve->setBrush(Qt::NoBrush); standard->lpsCurve->setBrush(Qt::NoBrush); standard->rpsCurve->setBrush(Qt::NoBrush); + standard->lpcoCurve->setBrush(Qt::NoBrush); + standard->rpcoCurve->setBrush(Qt::NoBrush); + standard->ldcCurve->setBrush(Qt::NoBrush); + standard->rdcCurve->setBrush(Qt::NoBrush); + standard->lpppCurve->setBrush(Qt::NoBrush); + standard->rpppCurve->setBrush(Qt::NoBrush); standard->slopeCurve->setBrush(Qt::NoBrush); //standard->altSlopeCurve->setBrush(Qt::NoBrush); //standard->balanceLCurve->setBrush(Qt::NoBrush); diff --git a/src/AllPlot.h b/src/AllPlot.h index d730e830d..e8171092f 100644 --- a/src/AllPlot.h +++ b/src/AllPlot.h @@ -371,6 +371,12 @@ class AllPlotObject : public QObject QwtPlotCurve *rteCurve; QwtPlotCurve *lpsCurve; QwtPlotCurve *rpsCurve; + QwtPlotCurve *lpcoCurve; + QwtPlotCurve *rpcoCurve; + QwtPlotIntervalCurve *ldcCurve; + QwtPlotIntervalCurve *rdcCurve; + QwtPlotIntervalCurve *lpppCurve; + QwtPlotIntervalCurve *rpppCurve; // source data QVector match; @@ -415,6 +421,16 @@ class AllPlotObject : public QObject QVector rteArray; QVector lpsArray; QVector rpsArray; + QVector lpcoArray; + QVector rpcoArray; + QVector ltdcArray; + QVector rtdcArray; + QVector lbdcArray; + QVector rbdcArray; + QVector ltpppArray; + QVector rtpppArray; + QVector lbpppArray; + QVector rbpppArray; // smoothed data QVector smoothWatts; @@ -452,6 +468,12 @@ class AllPlotObject : public QObject QVector smoothRTE; QVector smoothLPS; QVector smoothRPS; + QVector smoothLPCO; + QVector smoothRPCO; + QVector smoothLDC; + QVector smoothRDC; + QVector smoothLPPP; + QVector smoothRPPP; QVector smoothRelSpeed; // highlighting intervals @@ -554,6 +576,9 @@ class AllPlot : public QwtPlot void setShowBalance(bool show); void setShowTE(bool show); void setShowPS(bool show); + void setShowPCO(bool show); + void setShowDC(bool show); + void setShowPPP(bool show); void setShowGrid(bool show); void setPaintBrush(int state); void setShadeZones(bool x) { shade_zones=x; } @@ -606,6 +631,9 @@ class AllPlot : public QwtPlot bool showBalance; bool showTE; bool showPS; + bool showPCO; + bool showDC; + bool showPPP; bool showRV; bool showRGCT; bool showRCad; diff --git a/src/AllPlotWindow.cpp b/src/AllPlotWindow.cpp index 7af04d8fd..e6747e9b4 100644 --- a/src/AllPlotWindow.cpp +++ b/src/AllPlotWindow.cpp @@ -226,6 +226,18 @@ AllPlotWindow::AllPlotWindow(Context *context) : showPS->setCheckState(Qt::Unchecked); seriesRight->addRow(new QLabel(""), showPS); + showPCO = new QCheckBox(tr("Pedal Center Offset"), this); + showPCO->setCheckState(Qt::Unchecked); + seriesRight->addRow(new QLabel(""), showPCO); + + showDC = new QCheckBox(tr("Power Phase (Death Center)"), this); + showDC->setCheckState(Qt::Unchecked); + seriesRight->addRow(new QLabel(""), showDC); + + showPPP = new QCheckBox(tr("Peak Power Phase"), this); + showPPP->setCheckState(Qt::Unchecked); + seriesRight->addRow(new QLabel(""), showPPP); + // running ! seriesRight->addRow(new QLabel(""), new QLabel("")); @@ -687,6 +699,10 @@ AllPlotWindow::AllPlotWindow(Context *context) : connect(showBalance, SIGNAL(stateChanged(int)), this, SLOT(setShowBalance(int))); connect(showPS, SIGNAL(stateChanged(int)), this, SLOT(setShowPS(int))); connect(showTE, SIGNAL(stateChanged(int)), this, SLOT(setShowTE(int))); + connect(showPCO, SIGNAL(stateChanged(int)), this, SLOT(setShowPCO(int))); + connect(showDC, SIGNAL(stateChanged(int)), this, SLOT(setShowDC(int))); + connect(showPPP, SIGNAL(stateChanged(int)), this, SLOT(setShowPPP(int))); + connect(showGrid, SIGNAL(stateChanged(int)), this, SLOT(setShowGrid(int))); connect(showFull, SIGNAL(stateChanged(int)), this, SLOT(setShowFull(int))); connect(showInterval, SIGNAL(stateChanged(int)), this, SLOT(setShowInterval(int))); @@ -1050,6 +1066,27 @@ AllPlotWindow::compareChanged() if (showW->isChecked()) { s.one = RideFile::wprime; s.two = RideFile::none; wanted << s;}; if (showBalance->isChecked()) { s.one = RideFile::lrbalance; s.two = RideFile::none; wanted << s;}; + /* + if (showTE->isChecked()) { + s.one = RideFile::lte; s.two = RideFile::none; wanted << s; + s.one = RideFile::rte; s.two = RideFile::none; wanted << s; + } + if (showPS->isChecked()) { + s.one = RideFile::lps; s.two = RideFile::none; wanted << s; + s.one = RideFile::rps; s.two = RideFile::none; wanted << s; + } + if (showPCO->isChecked()) { + s.one = RideFile::lpco; s.two = RideFile::rpco; wanted << s; + } + if (showDC->isChecked()) { + s.one = RideFile::ltdc; s.two = RideFile::lbdc; wanted << s; + s.one = RideFile::rtdc; s.two = RideFile::rbdc; wanted << s; + } + if (showPPP->isChecked()) { + s.one = RideFile::ltppp; s.two = RideFile::lbppp; wanted << s; + s.one = RideFile::rtppp; s.two = RideFile::rbppp; wanted << s; + }*/ + // create blank and add to gui QPalette palette; palette.setBrush(QPalette::Background, Qt::NoBrush); @@ -2757,6 +2794,69 @@ AllPlotWindow::setShowTE(int value) } +void +AllPlotWindow::setShowPCO(int value) +{ + showPCO->setChecked(value); + + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + + bool checked = ( ( value == Qt::Checked ) && showPCO->isEnabled()) ? true : false; + + allPlot->setShowPCO(checked); + foreach (AllPlot *plot, allPlots) + plot->setShowPCO(checked); + // and the series stacks too + forceSetupSeriesStackPlots(); // scope changed so force redraw + +} + +void +AllPlotWindow::setShowDC(int value) +{ + showDC->setChecked(value); + + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + + bool checked = ( ( value == Qt::Checked ) && showDC->isEnabled()) ? true : false; + + allPlot->setShowDC(checked); + foreach (AllPlot *plot, allPlots) + plot->setShowDC(checked); + // and the series stacks too + forceSetupSeriesStackPlots(); // scope changed so force redraw + +} + +void +AllPlotWindow::setShowPPP(int value) +{ + showPPP->setChecked(value); + + // compare mode selfcontained update + if (isCompare()) { + compareChanged(); + return; + } + + bool checked = ( ( value == Qt::Checked ) && showPPP->isEnabled()) ? true : false; + + allPlot->setShowPPP(checked); + foreach (AllPlot *plot, allPlots) + plot->setShowPPP(checked); + // and the series stacks too + forceSetupSeriesStackPlots(); // scope changed so force redraw + +} + void AllPlotWindow::setShowHelp(int value) { @@ -3151,7 +3251,8 @@ AllPlotWindow::setupSeriesStackPlots() if (showtHb->isChecked() && rideItem->ride()->areDataPresent()->thb) { s.one = RideFile::thb; s.two = RideFile::none; serieslist << s; } if (showO2Hb->isChecked() && rideItem->ride()->areDataPresent()->o2hb) { s.one = RideFile::o2hb; s.two = RideFile::none; serieslist << s; } if (showHHb->isChecked() && rideItem->ride()->areDataPresent()->hhb) { s.one = RideFile::hhb; s.two = RideFile::none; serieslist << s; } - if (showSpeed->isChecked() && rideItem->ride()->areDataPresent()->kph) { s.one = RideFile::kph; s.two = RideFile::none; serieslist << s; } + if (showWind->isChecked() && rideItem->ride()->areDataPresent()->headwind) addHeadwind=true; //serieslist << RideFile::headwind; + if (showSpeed->isChecked() && rideItem->ride()->areDataPresent()->kph) {s.one = RideFile::kph; s.two = (addHeadwind ? RideFile::headwind : RideFile::none); serieslist << s; } if (showAccel->isChecked() && rideItem->ride()->areDataPresent()->kph) { s.one = RideFile::kphd; s.two = RideFile::none; serieslist << s; } if (showCad->isChecked() && rideItem->ride()->areDataPresent()->cad) { s.one = RideFile::cad; s.two = RideFile::none; serieslist << s; } if (showCadD->isChecked() && rideItem->ride()->areDataPresent()->cad) { s.one = RideFile::cadd; s.two = RideFile::none; serieslist << s; } @@ -3160,8 +3261,7 @@ AllPlotWindow::setupSeriesStackPlots() if (showAlt->isChecked() && rideItem->ride()->areDataPresent()->alt) { s.one = RideFile::alt; s.two = RideFile::none; serieslist << s; } if (showAltSlope->currentIndex() > 0 && rideItem->ride()->areDataPresent()->alt) { s.one = RideFile::alt; s.two = RideFile::slope; serieslist << s; } if (showSlope->isChecked() && rideItem->ride()->areDataPresent()->slope) { s.one = RideFile::slope; s.two = RideFile::none; serieslist << s; } - if (showTemp->isChecked() && rideItem->ride()->areDataPresent()->temp) { s.one = RideFile::temp; s.two = RideFile::none; serieslist << s; } - if (showWind->isChecked() && rideItem->ride()->areDataPresent()->headwind) addHeadwind=true; //serieslist << RideFile::headwind; + if (showTemp->isChecked() && rideItem->ride()->areDataPresent()->temp) { s.one = RideFile::temp; s.two = RideFile::none; serieslist << s; } if (showNP->isChecked() && rideItem->ride()->areDataPresent()->watts) { s.one = RideFile::NP; s.two = RideFile::none; serieslist << s; } if (showRV->isChecked() && rideItem->ride()->areDataPresent()->rvert) { s.one = RideFile::rvert; s.two = RideFile::none; serieslist << s; } if (showRCad->isChecked() && rideItem->ride()->areDataPresent()->rcad) { s.one = RideFile::rcad; s.two = RideFile::none; serieslist << s; } @@ -3177,12 +3277,17 @@ AllPlotWindow::setupSeriesStackPlots() s.one = RideFile::rte; s.two = RideFile::none; serieslist << s; } if (showPS->isChecked() && rideItem->ride()->areDataPresent()->lps) { s.one = RideFile::lps; s.two = RideFile::none; serieslist << s; s.one = RideFile::rps; s.two = RideFile::none; serieslist << s; } + if (showPCO->isChecked() && rideItem->ride()->areDataPresent()->lpco) { s.one = RideFile::lpco; s.two = RideFile::rpco; serieslist << s;} + if (showDC->isChecked() && rideItem->ride()->areDataPresent()->ltdc) { s.one = RideFile::ltdc; s.two = RideFile::lbdc; serieslist << s; + s.one = RideFile::rtdc; s.two = RideFile::rbdc; serieslist << s; } + if (showPPP->isChecked() && rideItem->ride()->areDataPresent()->ltppp) { s.one = RideFile::ltppp; s.two = RideFile::lbppp; serieslist << s; + s.one = RideFile::rtppp; s.two = RideFile::rbppp; serieslist << s; } bool first = true; foreach(SeriesWanted x, serieslist) { // create that plot - AllPlot *_allPlot = new AllPlot(this, this, context, x.one, (addHeadwind && x.one == RideFile::kph ? RideFile::headwind : x.two), first); + AllPlot *_allPlot = new AllPlot(this, this, context, x.one, x.two, first); _allPlot->setAutoFillBackground(false); _allPlot->setPalette(palette); _allPlot->setPaintBrush(paintBrush->checkState()); @@ -3377,6 +3482,9 @@ AllPlotWindow::setupStackPlots() _allPlot->setShowAP((showAP->isEnabled()) ? ( showAP->checkState() == Qt::Checked ) : false ); _allPlot->setShowTE((showTE->isEnabled()) ? ( showTE->checkState() == Qt::Checked ) : false ); _allPlot->setShowPS((showPS->isEnabled()) ? ( showPS->checkState() == Qt::Checked ) : false ); + _allPlot->setShowPCO((showPCO->isEnabled()) ? ( showPCO->checkState() == Qt::Checked ) : false ); + _allPlot->setShowDC((showDC->isEnabled()) ? ( showDC->checkState() == Qt::Checked ) : false ); + _allPlot->setShowPPP((showPPP->isEnabled()) ? ( showPPP->checkState() == Qt::Checked ) : false ); _allPlot->replot(); } diff --git a/src/AllPlotWindow.h b/src/AllPlotWindow.h index 73a18ac59..d9c648efc 100644 --- a/src/AllPlotWindow.h +++ b/src/AllPlotWindow.h @@ -83,6 +83,9 @@ class AllPlotWindow : public GcChartWindow Q_PROPERTY(int showBalance READ isShowBalance WRITE setShowBalance USER true) Q_PROPERTY(int showTE READ isShowTE WRITE setShowTE USER true) Q_PROPERTY(int showPS READ isShowPS WRITE setShowPS USER true) + Q_PROPERTY(int showPCO READ isShowPCO WRITE setShowPCO USER true) + Q_PROPERTY(int showDC READ isShowDC WRITE setShowDC USER true) + Q_PROPERTY(int showPPP READ isShowPPP WRITE setShowPPP USER true) Q_PROPERTY(int showTemp READ isShowTemp WRITE setShowTemp USER true) Q_PROPERTY(int showW READ isShowW WRITE setShowW USER true) @@ -141,6 +144,9 @@ class AllPlotWindow : public GcChartWindow int isShowHrD() const { return showHrD->checkState(); } int isShowTE() const { return showTE->checkState(); } int isShowPS() const { return showPS->checkState(); } + int isShowPCO() const { return showPCO->checkState(); } + int isShowDC() const { return showDC->checkState(); } + int isShowPPP() const { return showPPP->checkState(); } int isShowBalance() const { return showBalance->checkState(); } int isShowTemp() const { return showTemp->checkState(); } int isShowW() const { return showW->checkState(); } @@ -196,6 +202,9 @@ class AllPlotWindow : public GcChartWindow void setShowBalance(int state); void setShowPS(int state); void setShowTE(int state); + void setShowPCO(int state); + void setShowDC(int state); + void setShowPPP(int state); void setShowRV(int state); void setShowRCad(int state); void setShowRGCT(int state); @@ -313,6 +322,9 @@ class AllPlotWindow : public GcChartWindow QCheckBox *showBalance; QCheckBox *showTE; QCheckBox *showPS; + QCheckBox *showPCO; + QCheckBox *showDC; + QCheckBox *showPPP; QCheckBox *showW; QCheckBox *showRV; QCheckBox *showRGCT; diff --git a/src/Bin2RideFile.cpp b/src/Bin2RideFile.cpp index b74349fbe..3db751565 100644 --- a/src/Bin2RideFile.cpp +++ b/src/Bin2RideFile.cpp @@ -90,7 +90,8 @@ struct Bin2FileReaderState if (count) *count += 1; - res += c; + if (c != 0) + res += c; } return res; } @@ -243,7 +244,7 @@ struct Bin2FileReaderState lng = lng/10000000.0; // 0.0 values at end are for garmin vector torque efficiency/pedal smoothness which are not available - rideFile->appendPoint(*secs, cad, hr, km, kph, nm, watts, alt, lng, lat, 0.0, 0, temp, lrbal, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); + rideFile->appendPoint(*secs, cad, hr, km, kph, nm, watts, alt, lng, lat, 0.0, 0, temp, lrbal, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); (*secs)++; } diff --git a/src/BinRideFile.cpp b/src/BinRideFile.cpp index 7a414797a..420aac83c 100644 --- a/src/BinRideFile.cpp +++ b/src/BinRideFile.cpp @@ -488,7 +488,7 @@ struct BinFileReaderState int lat = 0; // the 0.0 values are L and R torque efficiency and pedal smoothness which are not available in this format - rideFile->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, lng, lat, headwind, grade, temperature, lrbalance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); + rideFile->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, lng, lat, headwind, grade, temperature, lrbalance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); } void decodeSparseData(const BinDefinition &def, const std::vector values) { diff --git a/src/ComparePane.cpp b/src/ComparePane.cpp index 10c21d5eb..0a7a6817b 100644 --- a/src/ComparePane.cpp +++ b/src/ComparePane.cpp @@ -717,7 +717,10 @@ ComparePane::dropEvent(QDropEvent *event) add.data->appendPoint(p->secs - offset, p->cad, p->hr, p->km - offsetKM, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, p->headwind, - p->slope, p->temp, p->lrbalance, p->lte, p->rte, p->lps, p->rps, p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, 0); + p->slope, p->temp, + p->lrbalance, p->lte, p->rte, p->lps, p->rps, + p->lpco, p->rpco, p->ltdc, p->rtdc, p->lbdc, p->rbdc, p->ltppp, p->rtppp, p->lbppp, p->rbppp, + p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, 0); // get derived data calculated RideFilePoint *l = add.data->dataPoints().last(); diff --git a/src/Computrainer3dpFile.cpp b/src/Computrainer3dpFile.cpp index befa116a8..6f12e53b9 100644 --- a/src/Computrainer3dpFile.cpp +++ b/src/Computrainer3dpFile.cpp @@ -239,7 +239,10 @@ RideFile *Computrainer3dpFileReader::openRideFile(QFile & file, (double) hr, km, speed, 0.0, watts, altitude, 0, 0, 0.0, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, // pedal torque eff / pedal smoothness - 0.0, 0.0, + 0.0, 0.0, // pedal platform offset + 0.0, 0.0, 0.0, 0.0, //pedal top and bottom death center + 0.0, 0.0, 0.0, 0.0, //pedal peak power phase + 0.0, 0.0, // smO2 / thb 0.0, 0.0, 0.0, // running dynamics 0); } @@ -294,6 +297,9 @@ RideFile *Computrainer3dpFileReader::openRideFile(QFile & file, RideFile::NoTemp, // temp 0.0, 0.0, 0.0, 0.0, 0.0, // pedal torque effectiveness / pedal smoothness + 0.0, 0.0, // pedal platform offset + 0.0, 0.0, 0.0, 0.0, //pedal top and bottom death center + 0.0, 0.0, 0.0, 0.0, //pedal peak power phase 0.0, 0.0, // smO2 / tHb 0.0, 0.0, 0.0, // running dynamics 0); diff --git a/src/CriticalPowerWindow.cpp b/src/CriticalPowerWindow.cpp index 03a263791..2108e91e7 100644 --- a/src/CriticalPowerWindow.cpp +++ b/src/CriticalPowerWindow.cpp @@ -1012,7 +1012,10 @@ CriticalPowerWindow::showIntervalCurve(IntervalItem *current, int index) if ((p->secs+f.recIntSecs()) >= current->start && p->secs <= (current->stop+f.recIntSecs())) { f.appendPoint(p->secs, p->cad, p->hr, p->km, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, p->headwind, - p->slope, p->temp, p->lrbalance, p->lte, p->rte, p->lps, p->rps, p->smo2, p->thb, + p->slope, p->temp, p->lrbalance, + p->lte, p->rte, p->lps, p->rps, + p->lpco, p->rpco, p->ltdc, p->rtdc, p->lbdc, p->rbdc, p->ltppp, p->rtppp, p->lbppp, p->rbppp, + p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, 0); } } diff --git a/src/CsvRideFile.cpp b/src/CsvRideFile.cpp index bfdce5fd9..c4cfcfc92 100644 --- a/src/CsvRideFile.cpp +++ b/src/CsvRideFile.cpp @@ -647,6 +647,8 @@ RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors, QListappendPoint(seconds, cad, hr, km, kph, nm, watts, alt, lon, lat, 0.0, 0.0, temp, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); else if (csvType == moxy) { @@ -656,11 +658,17 @@ RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors, QListappendPoint((minutes * 60.0)+1, cad, hr, km, // dupe it so we have 1s recording easier to merge kph, nm, watts, alt, lon, lat, headwind, slope, temp, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, smo2, thb, 0.0, 0.0, 0.0, interval); } else { @@ -668,6 +676,9 @@ RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors, QList #include +#define FIT_DEBUG false // debug traces + #define RECORD_TYPE 20 static int fitFileReaderRegistered = @@ -55,7 +57,18 @@ struct FitDefinition { // introduced into the file format typedef qint64 fit_value_t; #define NA_VALUE std::numeric_limits::max() +typedef std::string fit_string_value; +enum fitValueType { SingleValue, DoubleValue, StringValue }; +typedef enum fitValueType FitValueType; + +struct FitValue +{ + FitValueType type; + fit_value_t v; + fit_value_t v2; + fit_string_value s; +}; struct FitFileReaderState { @@ -93,6 +106,22 @@ struct FitFileReaderState (*count) += size; } + fit_string_value read_text(int len, int *count = NULL) + { + char c; + fit_string_value res = ""; + for (int i = 0; i < len; ++i) { + if (file.read(&c, 1) != 1) + throw TruncatedRead(); + if (count) + *count += 1; + + if (c != 0) + res += c; + } + return res; + } + fit_value_t read_int8(int *count = NULL) { qint8 i; if (file.read(reinterpret_cast( &i), 1) != 1) @@ -207,11 +236,11 @@ struct FitFileReaderState return i == 0x00000000 ? NA_VALUE : i; } - void decodeFileId(const FitDefinition &def, int, const std::vector values) { + void decodeFileId(const FitDefinition &def, int, const std::vector values) { int i = 0; int manu = -1, prod = -1; foreach(const FitField &field, def.fields) { - fit_value_t value = values[i++]; + fit_value_t value = values[i++].v; if( value == NA_VALUE ) continue; @@ -255,38 +284,42 @@ struct FitFileReaderState rideFile->setFileFormat("FIT (*.fit)"); } - void decodeSession(const FitDefinition &def, int, const std::vector values) { + void decodeSession(const FitDefinition &def, int, const std::vector values) { int i = 0; foreach(const FitField &field, def.fields) { - fit_value_t value = values[i++]; + fit_value_t value = values[i++].v; if( value == NA_VALUE ) continue; - //printf("decodeSession field %d: %d bytes, num %d, type %d\n", i, field.size, field.num, field.type ); + if (FIT_DEBUG) { + printf("decodeSession field %d: %d bytes, num %d, type %d\n", i, field.size, field.num, field.type ); + } } } - void decodeDeviceInfo(const FitDefinition &def, int, const std::vector values) { + void decodeDeviceInfo(const FitDefinition &def, int, const std::vector values) { int i = 0; foreach(const FitField &field, def.fields) { - fit_value_t value = values[i++]; + fit_value_t value = values[i++].v; if( value == NA_VALUE ) continue; - //printf("decodeDeviceInfo field %d: %d bytes, num %d, type %d\n", i, field.size, field.num, field.type ); + if (FIT_DEBUG) { + printf("decodeDeviceInfo field %d: %d bytes, num %d, type %d\n", i, field.size, field.num, field.type ); + } } } - void decodeEvent(const FitDefinition &def, int, const std::vector values) { + void decodeEvent(const FitDefinition &def, int, const std::vector values) { int time = -1; int event = -1; int event_type = -1; qint16 data16 = -1; int i = 0; foreach(const FitField &field, def.fields) { - fit_value_t value = values[i++]; + fit_value_t value = values[i++].v; if( value == NA_VALUE ) continue; @@ -344,12 +377,15 @@ struct FitFileReaderState break; } } - // printf("event type %d\n", event_type); + + if (FIT_DEBUG) { + printf("event type %d\n", event_type); + } last_event = event; last_event_type = event_type; } - void decodeLap(const FitDefinition &def, int time_offset, const std::vector values) { + void decodeLap(const FitDefinition &def, int time_offset, const std::vector values) { time_t time = 0; if (time_offset > 0) time = last_time + time_offset; @@ -359,7 +395,7 @@ struct FitFileReaderState time_t this_start_time = 0; ++interval; foreach(const FitField &field, def.fields) { - fit_value_t value = values[i++]; + fit_value_t value = values[i++].v; if( value == NA_VALUE ) continue; @@ -384,13 +420,25 @@ struct FitFileReaderState rideFile->addInterval(this_start_time - start_time, time - start_time, QString(QObject::tr("Lap %1")).arg(interval)); } - void decodeRecord(const FitDefinition &def, int time_offset, const std::vector values) { + void decodeRecord(const FitDefinition &def, int time_offset, const std::vector values) { time_t time = 0; if (time_offset > 0) time = last_time + time_offset; double alt = 0, cad = 0, km = 0, hr = 0, lat = 0, lng = 0, badgps = 0, lrbalance = 0; double kph = 0, temperature = RideFile::NoTemp, watts = 0, slope = 0; double leftTorqueEff = 0, rightTorqueEff = 0, leftPedalSmooth = 0, rightPedalSmooth = 0; + + double leftPedalCenterOffset = 0; + double rightPedalCenterOffset = 0; + double leftTopDeathCenter = 0; + double rightTopDeathCenter = 0; + double leftBottomDeathCenter = 0; + double rightBottomDeathCenter = 0; + double leftTopPeakPowerPhase = 0; + double rightTopPeakPowerPhase = 0; + double leftBottomPeakPowerPhase = 0; + double rightBottomPeakPowerPhase = 0; + double rvert = 0, rcad = 0, rcontact = 0; double smO2 = 0, tHb = 0; bool run=false; @@ -398,7 +446,8 @@ struct FitFileReaderState fit_value_t lati = NA_VALUE, lngi = NA_VALUE; int i = 0; foreach(const FitField &field, def.fields) { - fit_value_t value = values[i++]; + fit_value_t value = values[i].v; + fit_value_t value2 = values[i++].v2; if( value == NA_VALUE ) continue; @@ -463,7 +512,8 @@ struct FitFileReaderState rvert = value / 100.0f; break; - case 40: // IS RUNNING ACTIVITY? + case 40: // ACTIVITY_TYPE + // TODO We should know/test value for run run = true; break; @@ -473,33 +523,55 @@ struct FitFileReaderState case 43: // LEFT_TORQUE_EFFECTIVENESS leftTorqueEff = value / 2.0; - //qDebug() << "LEFT_TORQUE_EFFECTIVENESS" << leftTorqueEff; break; case 44: // RIGHT_TORQUE_EFFECTIVENESS rightTorqueEff = value / 2.0; - //qDebug() << "RIGHT_TORQUE_EFFECTIVENESS" << rightTorqueEff; break; case 45: // LEFT_PEDAL_SMOOTHNESS leftPedalSmooth = value / 2.0; - //qDebug() << "LEFT_PEDAL_SMOOTHNESS" << leftPedalSmooth; break; case 46: // RIGHT_PEDAL_SMOOTHNESS rightPedalSmooth = value / 2.0; - //qDebug() << "RIGHT_PEDAL_SMOOTHNESS" << rightPedalSmooth; break; case 47: // COMBINED_PEDAL_SMOOTHNES //qDebug() << "COMBINED_PEDAL_SMOOTHNES" << value; break; - case 53: // RUNNING CADENCE FRACTIONAL VALUE break; - case 54: // tHb tHb= value/100.0f; break; case 57: // SMO2 smO2= value/10.0f; break; + case 61: // ? GPS Altitude ? + break; + case 66: // ?? + break; + case 67: // ? Left Platform Center Offset ? + leftPedalCenterOffset = value; + break; + case 68: // ? Right Platform Center Offset ? + rightPedalCenterOffset = value; + break; + case 69: // ? Left Power Phase (Top and Bottom Dead Center) ? + leftTopDeathCenter = value; + leftBottomDeathCenter = value2; + break; + case 70: // ? Left Peak Phase ? + leftTopPeakPowerPhase = value; + leftBottomPeakPowerPhase = value2; + break; + case 71: // ? Right Power Phase (Top and Bottom Dead Center) ? + rightTopDeathCenter = value; + rightBottomDeathCenter = value2; + break; + case 72: // ? Right Peak Phase ? + rightTopPeakPowerPhase = value; + rightBottomPeakPowerPhase = value2; + break; + + default: unknown_record_fields.insert(field.num); } @@ -572,6 +644,16 @@ struct FitFileReaderState double deltaRightTE = rightTorqueEff - prevPoint->rte; double deltaLeftPS = leftPedalSmooth - prevPoint->lps; double deltaRightPS = rightPedalSmooth - prevPoint->rps; + double deltaLeftPedalCenterOffset = leftPedalCenterOffset - prevPoint->lpco; + double deltaRightPedalCenterOffset = rightPedalCenterOffset - prevPoint->rpco; + double deltaLeftTopDeathCenter = leftTopDeathCenter - prevPoint->ltdc; + double deltaRightTopDeathCenter = rightTopDeathCenter - prevPoint->rtdc; + double deltaLeftBottomDeathCenter = leftBottomDeathCenter - prevPoint->lbdc; + double deltaRightBottomDeathCenter = rightBottomDeathCenter - prevPoint->rbdc; + double deltaLeftTopPeakPowerPhase = leftTopPeakPowerPhase - prevPoint->ltppp; + double deltaRightTopPeakPowerPhase = rightTopPeakPowerPhase - prevPoint->rtppp; + double deltaLeftBottomPeakPowerPhase = leftBottomPeakPowerPhase - prevPoint->lbppp; + double deltaRightBottomPeakPowerPhase = rightBottomPeakPowerPhase - prevPoint->rbppp; double deltaSmO2 = smO2 - prevPoint->smo2; double deltaTHb = tHb - prevPoint->thb; double deltarvert = rvert - prevPoint->rvert; @@ -604,6 +686,16 @@ struct FitFileReaderState prevPoint->rte + (deltaRightTE * weight), prevPoint->lps + (deltaLeftPS * weight), prevPoint->rps + (deltaRightPS * weight), + prevPoint->lpco + (deltaLeftPedalCenterOffset * weight), + prevPoint->rpco + (deltaRightPedalCenterOffset * weight), + prevPoint->ltdc + (deltaLeftTopDeathCenter * weight), + prevPoint->rtdc + (deltaRightTopDeathCenter * weight), + prevPoint->lbdc + (deltaLeftBottomDeathCenter * weight), + prevPoint->rbdc + (deltaRightBottomDeathCenter * weight), + prevPoint->ltppp + (deltaLeftTopPeakPowerPhase * weight), + prevPoint->rtppp + (deltaRightTopPeakPowerPhase * weight), + prevPoint->lbppp + (deltaLeftBottomPeakPowerPhase * weight), + prevPoint->rbppp + (deltaRightBottomPeakPowerPhase * weight), prevPoint->smo2 + (deltaSmO2 * weight), prevPoint->thb + (deltaTHb * weight), prevPoint->rvert + (deltarvert * weight), @@ -618,6 +710,9 @@ struct FitFileReaderState if (km < 0.00001f) km = last_distance; rideFile->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, lng, lat, headwind, slope, temperature, lrbalance, leftTorqueEff, rightTorqueEff, leftPedalSmooth, rightPedalSmooth, + leftPedalCenterOffset, rightPedalCenterOffset, + leftTopDeathCenter, rightTopDeathCenter, leftBottomDeathCenter, rightBottomDeathCenter, + leftTopPeakPowerPhase, rightTopPeakPowerPhase, leftBottomPeakPowerPhase, rightBottomPeakPowerPhase, smO2, tHb, rvert, rcad, rcontact, interval); last_time = time; last_distance = km; @@ -638,9 +733,12 @@ struct FitFileReaderState def.is_big_endian = read_uint8(&count); def.global_msg_num = read_uint16(def.is_big_endian, &count); int num_fields = read_uint8(&count); - //printf("definition: local type=%d global=%d arch=%d fields=%d\n", - // local_msg_type, def.global_msg_num, def.is_big_endian, - // num_fields ); + + if (FIT_DEBUG) { + printf("definition: local type=%d global=%d arch=%d fields=%d\n", + local_msg_type, def.global_msg_num, def.is_big_endian, + num_fields ); + } for (int i = 0; i < num_fields; ++i) { def.fields.push_back(FitField()); @@ -650,8 +748,11 @@ struct FitFileReaderState field.size = read_uint8(&count); int base_type = read_uint8(&count); field.type = base_type & 0x1f; - //printf(" field %d: %d bytes, num %d, type %d\n", - // i, field.size, field.num, field.type ); + + if (FIT_DEBUG) { + printf(" field %d: %d bytes, num %d, type %d, size %d\n", + i, field.size, field.num, field.type, field.size ); + } } } else { @@ -673,43 +774,78 @@ struct FitFileReaderState return count; } const FitDefinition &def = local_msg_types[local_msg_type]; - //printf( "message local=%d global=%d\n", local_msg_type, - // def.global_msg_num ); - std::vector values; + if (FIT_DEBUG) { + printf( "read_record message local=%d global=%d\n", local_msg_type, + def.global_msg_num ); + } + + std::vector values; foreach(const FitField &field, def.fields) { - fit_value_t v; + FitValue value; int size; + switch (field.type) { - case 0: v = read_uint8(&count); size = 1; break; - case 1: v = read_int8(&count); size = 1; break; - case 2: v = read_uint8(&count); size = 1; break; - case 3: v = read_int16(def.is_big_endian, &count); size = 2; break; - case 4: v = read_uint16(def.is_big_endian, &count); size = 2; break; - case 5: v = read_int32(def.is_big_endian, &count); size = 4; break; - case 6: v = read_uint32(def.is_big_endian, &count); size = 4; break; - //case 7: // String + case 0: value.type = SingleValue; value.v = read_uint8(&count); size = 1; break; + case 1: value.type = SingleValue; value.v = read_int8(&count); size = 1; break; + case 2: value.type = SingleValue; value.v = read_uint8(&count); size = 1; + // Multi-values ? + if (field.size>size) { + value.type = DoubleValue; + value.v2 = read_uint8(&count); + size = 2; + } + break; + case 3: value.type = SingleValue; value.v = read_int16(def.is_big_endian, &count); size = 2; break; + case 4: value.type = SingleValue; value.v = read_uint16(def.is_big_endian, &count); size = 2; + // Multi-values ? + if (field.size>size) { + value.type = DoubleValue; + value.v2 = read_uint16(def.is_big_endian, &count); + size = 4; + } + break; + case 5: value.type = SingleValue; value.v = read_int32(def.is_big_endian, &count); size = 4; break; + case 6: value.type = SingleValue; value.v = read_uint32(def.is_big_endian, &count); size = 4; break; + case 7: value.type = StringValue; value.s = read_text(field.size, &count); size = field.size; break; + + //case 8: // FLOAT32 //case 9: // FLOAT64 - case 10: v = read_uint8z(&count); size = 1; break; - case 11: v = read_uint16z(def.is_big_endian, &count); size = 2; break; - case 12: v = read_uint32z(def.is_big_endian, &count); size = 4; break; + case 10: value.type = SingleValue; value.v = read_uint8z(&count); size = 1; break; + case 11: value.type = SingleValue; value.v = read_uint16z(def.is_big_endian, &count); size = 2; break; + case 12: value.type = SingleValue; value.v = read_uint32z(def.is_big_endian, &count); size = 4; break; //case 13: // BYTE // we may need to add support for float, string + byte base types here default: read_unknown( field.size, &count ); - v = NA_VALUE; + value.type = SingleValue; + value.v = NA_VALUE; unknown_base_type.insert(field.num); size = field.size; } // Quick fix : we need to support multivalues - if (size < field.size) + if (size < field.size) { + if (FIT_DEBUG) { + printf( " warning : size=%d for size=%d (num=%d)\n", + field.size, field.type, field.num); + } read_unknown( field.size-size, &count ); + } - values.push_back(v); - //printf( " field: type=%d num=%d value=%lld\n", - // field.type, field.num, v ); + values.push_back(value); + + if (FIT_DEBUG) { + printf( " field: type=%d num=%d ", + field.type, field.num); + if (value.type == SingleValue) + printf( "value=%lld\n", value.v ); + else if (value.type == DoubleValue) + printf( "value=%lld value2=%lld\n", value.v, value.v2 ); + else if (value.type == StringValue) + printf( "salue=%s\n",value.s.c_str() ); + } } // Most of the record types in the FIT format aren't actually all // that useful. FileId, Lap, and Record clearly are. The one @@ -721,15 +857,27 @@ struct FitFileReaderState case 19: decodeLap(def, time_offset, values); break; case RECORD_TYPE: decodeRecord(def, time_offset, values); break; case 21: decodeEvent(def, time_offset, values); break; + case 23: //decodeDeviceInfo(def, time_offset, values); break; /* device info */ case 18: //decodeSession(def, time_offset, values); break; /* session */ + + case 2: /* DEVICE_SETTINGS */ + case 3: /* USER_PROFILE */ + case 7: /* ZONES_TARGET12 */ + case 13: /* unknown */ case 22: /* undocumented */ case 72: /* undocumented - new for garmin 800*/ case 34: /* activity */ case 49: /* file creator */ case 79: /* unknown */ case 104: /* battery */ + case 113: /* unknown */ + case 125: /* unknown */ + case 128: /* unknown */ + case 147: /* unknown */ + break; + default: unknown_global_msg_nums.insert(def.global_msg_num); } diff --git a/src/FitlogParser.cpp b/src/FitlogParser.cpp index aa7a753ea..7ab98ac6a 100644 --- a/src/FitlogParser.cpp +++ b/src/FitlogParser.cpp @@ -100,7 +100,11 @@ FitlogParser::startElement( const QString&, const QString&, // now add rideFile->appendPoint(point.secs,point.cad,point.hr,point.km,point.kph,point.nm, point.watts,point.alt,point.lon,point.lat, point.headwind, - 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0,// running dynamics point.interval); } diff --git a/src/FitlogRideFile.cpp b/src/FitlogRideFile.cpp index bfbcf6505..440f56b55 100644 --- a/src/FitlogRideFile.cpp +++ b/src/FitlogRideFile.cpp @@ -150,7 +150,11 @@ FitlogFileReader::writeRideFile(Context *context, const RideFile *ride, QFile &f break; f.appendPoint(p->secs, p->cad, p->hr, p->km, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, p->headwind, - 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, // running dynamics 0); } diff --git a/src/FixGaps.cpp b/src/FixGaps.cpp index 24e6c1427..b3cf408d6 100644 --- a/src/FixGaps.cpp +++ b/src/FixGaps.cpp @@ -198,12 +198,23 @@ FixGaps::postProcess(RideFile *ride, DataProcessorConfig *config=0) double rtedelta = (point->rte - last->rte) / (double) count; double lpsdelta = (point->lps - last->lps) / (double) count; double rpsdelta = (point->rps - last->rps) / (double) count; + double lpcodelta = (point->lpco - last->lpco) / (double) count; + double rpcodelta = (point->rpco - last->rpco) / (double) count; + double ltdcdelta = (point->ltdc - last->ltdc) / (double) count; + double rtdcdelta = (point->rtdc - last->rtdc) / (double) count; + double lbdcdelta = (point->lbdc - last->lbdc) / (double) count; + double rbdcdelta = (point->rbdc - last->rbdc) / (double) count; + double ltpppdelta = (point->ltppp - last->ltppp) / (double) count; + double rtpppdelta = (point->rtppp - last->rtppp) / (double) count; + double lbpppdelta = (point->lbppp - last->lbppp) / (double) count; + double rbpppdelta = (point->rbppp - last->rbppp) / (double) count; double smo2delta = (point->smo2 - last->smo2) / (double) count; double thbdelta = (point->thb - last->thb) / (double) count; double rcontactdelta = (point->rcontact - last->rcontact) / (double) count; double rcaddelta = (point->rcad - last->rcad) / (double) count; double rvertdelta = (point->rvert - last->rvert) / (double) count; + // add the points for(int i=0; isecs+((i+1)*ride->recIntSecs()), @@ -224,6 +235,16 @@ FixGaps::postProcess(RideFile *ride, DataProcessorConfig *config=0) last->rte + ((i+1)*rtedelta), last->lps + ((i+1)*lpsdelta), last->rps + ((i+1)*rpsdelta), + last->lpco + ((i+1)*lpcodelta), + last->rpco + ((i+1)*rpcodelta), + last->ltdc + ((i+1)*ltdcdelta), + last->rtdc + ((i+1)*rtdcdelta), + last->lbdc + ((i+1)*lbdcdelta), + last->rbdc + ((i+1)*rbdcdelta), + last->ltppp + ((i+1)*ltpppdelta), + last->rtppp + ((i+1)*rtpppdelta), + last->lbppp + ((i+1)*lbpppdelta), + last->rbppp + ((i+1)*rbpppdelta), last->smo2 + ((i+1)*smo2delta), last->thb + ((i+1)*thbdelta), last->rvert + ((i+1)*rvertdelta), @@ -260,6 +281,9 @@ FixGaps::postProcess(RideFile *ride, DataProcessorConfig *config=0) 0, 0, 0.0, 0.0, 0.0, 0.0, //pedal torque / smoothness + 0.0, 0.0, // pedal platform offset + 0.0, 0.0, 0.0, 0.0, //pedal top and bottom death center + 0.0, 0.0, 0.0, 0.0, //pedal peak power phase 0.0, 0.0, // smO2 / thb 0.0, 0.0, 0.0, // running dynamics last->interval); diff --git a/src/GcRideFile.cpp b/src/GcRideFile.cpp index 42fd0b01b..600edd6f7 100644 --- a/src/GcRideFile.cpp +++ b/src/GcRideFile.cpp @@ -147,7 +147,7 @@ GcFileReader::openRideFile(QFile &file, QStringList &errors, QList*) 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, headwind, 0.0, RideFile::NoTemp, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); + rideFile->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, 0.0, RideFile::NoTemp, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); if (!recIntSet) { rideFile->setRecIntSecs(sample.attribute("len").toDouble()); recIntSet = true; diff --git a/src/GpxParser.cpp b/src/GpxParser.cpp index f006ef6d2..cecd02ac9 100644 --- a/src/GpxParser.cpp +++ b/src/GpxParser.cpp @@ -199,7 +199,8 @@ bool if(rideFile->dataPoints().empty()) { // first point rideFile->appendPoint(secs, cad, hr, distance, speed, 0, watts, alt, lon, lat, 0, 0.0, temp, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); } else { // assumption that the change in ride is linear... :) @@ -219,6 +220,7 @@ bool // no smart recording, or delta exceeds HW treshold, or no time elements; just insert the data rideFile->appendPoint(secs, cad, hr, distance, speed, 0,watts, alt, lon, lat, 0, 0.0, temp, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); } else { @@ -247,6 +249,9 @@ bool temp, 0, 0.0, 0.0, 0.0, 0.0, // pedal torque/smoothness + 0.0, 0.0, // pedal platform offset + 0.0, 0.0, 0.0, 0.0, //pedal top and bottom death center + 0.0, 0.0, 0.0, 0.0, //pedal peak power phase 0.0, 0.0, // SmO2 / tHb 0.0, 0.0, 0.0, // running dynamics 0); diff --git a/src/IntervalNavigator.cpp b/src/IntervalNavigator.cpp index c7cac32c4..c3e2574fb 100644 --- a/src/IntervalNavigator.cpp +++ b/src/IntervalNavigator.cpp @@ -884,7 +884,9 @@ IntervalNavigator::selectRide(const QModelIndex &index) const RideFilePoint *p = ride->dataPoints()[i]; f->appendPoint(p->secs, p->cad, p->hr, p->km, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, p->headwind, p->slope, p->temp, p->lrbalance, - p->lte, p->rte, p->lps, p->rps, p->smo2, p->thb, + p->lte, p->rte, p->lps, p->rps, + p->lpco, p->rpco, p->ltdc, p->rtdc, p->lbdc, p->rbdc, p->ltppp, p->rtppp, p->lbppp, p->rbppp, + p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, 0); // derived data diff --git a/src/IntervalSummaryWindow.cpp b/src/IntervalSummaryWindow.cpp index bd678e102..dd90fde8f 100644 --- a/src/IntervalSummaryWindow.cpp +++ b/src/IntervalSummaryWindow.cpp @@ -149,7 +149,11 @@ void IntervalSummaryWindow::calcInterval(QList intervals, QString f.appendPoint(p->secs-timeOff, p->cad, p->hr, p->km-distOff, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, p->headwind, p->slope, p->temp, p->lrbalance, - p->lte, p->rte, p->lps, p->rps, p->smo2, p->thb, + p->lte, p->rte, p->lps, p->rps, + p->lpco, p->rpco, + p->ltdc, p->rtdc, p->lbdc, p->rbdc, + p->ltppp, p->rtppp, p->lbppp, p->rbppp, + p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, 0); // derived data @@ -184,7 +188,11 @@ void IntervalSummaryWindow::calcInterval(IntervalItem* interval, QString& html) const RideFilePoint *p = ride->dataPoints()[i]; f.appendPoint(p->secs, p->cad, p->hr, p->km, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, p->headwind, p->slope, p->temp, p->lrbalance, - p->lte, p->rte, p->lps, p->rps, p->smo2, p->thb, + p->lte, p->rte, p->lps, p->rps, + p->lpco, p->rpco, + p->ltdc, p->rtdc, p->lbdc, p->rbdc, + p->ltppp, p->rtppp, p->lbppp, p->rbppp, + p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, 0); // derived data @@ -266,7 +274,11 @@ void IntervalSummaryWindow::calcInterval(RideFileInterval interval, QString& htm const RideFilePoint *p = ride->dataPoints()[i]; f.appendPoint(p->secs, p->cad, p->hr, p->km, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, p->headwind, p->slope, p->temp, p->lrbalance, - p->lte, p->rte, p->lps, p->rps, p->smo2, p->thb, + p->lte, p->rte, p->lps, p->rps, + p->lpco, p->rpco, + p->ltdc, p->rtdc, p->lbdc, p->rbdc, + p->ltppp, p->rtppp, p->lbppp, p->rbppp, + p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, 0); // derived data diff --git a/src/JsonRideFile.l b/src/JsonRideFile.l index 0de3caaaa..7a10cbc4f 100644 --- a/src/JsonRideFile.l +++ b/src/JsonRideFile.l @@ -135,6 +135,16 @@ void JsonRideFilefree (void * ptr , yyscan_t /*scanner*/) \"RTE\" return RTE; \"LPS\" return LPS; \"RPS\" return RPS; +\"LPCO\" return LPCO; +\"RPCO\" return RPCO; +\"LTDC\" return LTDC; +\"RTDC\" return RTDC; +\"LBDC\" return LBDC; +\"RBDC\" return RBDC; +\"LTPPP\" return LTPPP; +\"RTPPP\" return RTPPP; +\"LBPPP\" return LBPPP; +\"RBPPP\" return RBPPP; \"SMO2\" return SMO2; \"THB\" return THB; \"RCON\" return RCON; diff --git a/src/JsonRideFile.y b/src/JsonRideFile.y index 068166257..ee26467a2 100644 --- a/src/JsonRideFile.y +++ b/src/JsonRideFile.y @@ -113,6 +113,7 @@ static QString protect(const QString string) %token REFERENCES %token SAMPLES SECS KM WATTS NM CAD KPH HR ALTITUDE LAT LON HEADWIND SLOPE TEMP %token LRBALANCE LTE RTE LPS RPS THB SMO2 RVERT RCAD RCON +%token LPCO RPCO LTDC RTDC LBDC RBDC LTPPP RTPPP LBPPP RBPPP %start document %% @@ -239,6 +240,11 @@ sample: '{' series_list '}' { jc->JsonRide->appendPoint(jc->JsonPoin jc->JsonPoint.slope, jc->JsonPoint.temp, jc->JsonPoint.lrbalance, jc->JsonPoint.lte, jc->JsonPoint.rte, jc->JsonPoint.lps, jc->JsonPoint.rps, + jc->JsonPoint.lpco, jc->JsonPoint.rpco, + jc->JsonPoint.ltdc, jc->JsonPoint.rtdc, + jc->JsonPoint.lbdc, jc->JsonPoint.rbdc, + jc->JsonPoint.ltppp, jc->JsonPoint.rtppp, + jc->JsonPoint.lbppp, jc->JsonPoint.rbppp, jc->JsonPoint.smo2, jc->JsonPoint.thb, jc->JsonPoint.rvert, jc->JsonPoint.rcad, jc->JsonPoint.rcontact, jc->JsonPoint.interval); @@ -264,6 +270,16 @@ series: SECS ':' number { jc->JsonPoint.secs = jc->JsonNumber; } | RTE ':' number { jc->JsonPoint.rte = jc->JsonNumber; } | LPS ':' number { jc->JsonPoint.lps = jc->JsonNumber; } | RPS ':' number { jc->JsonPoint.rps = jc->JsonNumber; } + | LPCO ':' number { jc->JsonPoint.lpco = jc->JsonNumber; } + | RPCO ':' number { jc->JsonPoint.rpco = jc->JsonNumber; } + | LTDC ':' number { jc->JsonPoint.ltdc = jc->JsonNumber; } + | RTDC ':' number { jc->JsonPoint.rtdc = jc->JsonNumber; } + | LBDC ':' number { jc->JsonPoint.lbdc = jc->JsonNumber; } + | RBDC ':' number { jc->JsonPoint.rbdc = jc->JsonNumber; } + | LTPPP ':' number { jc->JsonPoint.ltppp = jc->JsonNumber; } + | RTPPP ':' number { jc->JsonPoint.rtppp = jc->JsonNumber; } + | LBPPP ':' number { jc->JsonPoint.lbppp = jc->JsonNumber; } + | RBPPP ':' number { jc->JsonPoint.rbppp = jc->JsonNumber; } | SMO2 ':' number { jc->JsonPoint.smo2 = jc->JsonNumber; } | THB ':' number { jc->JsonPoint.thb = jc->JsonNumber; } | RVERT ':' number { jc->JsonPoint.rvert = jc->JsonNumber; } @@ -546,6 +562,16 @@ JsonFileReader::writeRideFile(Context *, const RideFile *ride, QFile &file) cons if (ride->areDataPresent()->rte) out << ", \"RTE\":" << QString("%1").arg(p->rte); if (ride->areDataPresent()->lps) out << ", \"LPS\":" << QString("%1").arg(p->lps); if (ride->areDataPresent()->rps) out << ", \"RPS\":" << QString("%1").arg(p->rps); + if (ride->areDataPresent()->lpco) out << ", \"LPCO\":" << QString("%1").arg(p->lpco); + if (ride->areDataPresent()->rpco) out << ", \"RPCO\":" << QString("%1").arg(p->rpco); + if (ride->areDataPresent()->ltdc) out << ", \"LTDC\":" << QString("%1").arg(p->ltdc); + if (ride->areDataPresent()->rtdc) out << ", \"RTDC\":" << QString("%1").arg(p->rtdc); + if (ride->areDataPresent()->lbdc) out << ", \"LBDC\":" << QString("%1").arg(p->lbdc); + if (ride->areDataPresent()->rbdc) out << ", \"RBDC\":" << QString("%1").arg(p->rbdc); + if (ride->areDataPresent()->ltppp) out << ", \"LTPPP\":" << QString("%1").arg(p->ltppp); + if (ride->areDataPresent()->rtppp) out << ", \"RTPPP\":" << QString("%1").arg(p->rtppp); + if (ride->areDataPresent()->lbppp) out << ", \"LBPPP\":" << QString("%1").arg(p->lbppp); + if (ride->areDataPresent()->rbppp) out << ", \"RBPPP\":" << QString("%1").arg(p->rbppp); if (ride->areDataPresent()->smo2) out << ", \"SMO2\":" << QString("%1").arg(p->smo2); if (ride->areDataPresent()->thb) out << ", \"THB\":" << QString("%1").arg(p->thb); if (ride->areDataPresent()->rcad) out << ", \"RCAD\":" << QString("%1").arg(p->rcad); diff --git a/src/ManualRideFile.cpp b/src/ManualRideFile.cpp index 0b2430d7a..161abe1be 100644 --- a/src/ManualRideFile.cpp +++ b/src/ManualRideFile.cpp @@ -126,7 +126,11 @@ RideFile *ManualFileReader::openRideFile(QFile &file, QStringList &errors, QList kph, nm, watts, alt, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, 0.0, - 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, // pedal platform offset + 0.0, 0.0, 0.0, 0.0, //pedal top and bottom death center + 0.0, 0.0, 0.0, 0.0, //pedal peak power phase + 0.0, 0.0, 0.0, 0.0, 0.0, // running dynamics interval); QMap bsm; diff --git a/src/PolarRideFile.cpp b/src/PolarRideFile.cpp index 90976cc42..d8129c689 100644 --- a/src/PolarRideFile.cpp +++ b/src/PolarRideFile.cpp @@ -262,7 +262,7 @@ this differently alt *= METERS_PER_FOOT; } - rideFile->appendPoint(seconds, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, lrbalance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); + rideFile->appendPoint(seconds, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, lrbalance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 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/PwxRideFile.cpp b/src/PwxRideFile.cpp index 0d8e911e0..c1aed3ac3 100644 --- a/src/PwxRideFile.cpp +++ b/src/PwxRideFile.cpp @@ -247,7 +247,11 @@ PwxFileReader::PwxFromDomDoc(QDomDocument doc, QStringList &errors) const // add the data point rideFile->appendPoint(add.secs, add.cad, add.hr, add.km, add.kph, add.nm, add.watts, add.alt, add.lon, add.lat, add.headwind, - add.slope, add.temp, add.lrbalance, add.lte, add.rte, add.lps, add.rps, + add.slope, add.temp, add.lrbalance, + add.lte, add.rte, add.lps, add.rps, + add.lpco, add.rpco, + add.ltdc, add.rtdc, add.lbdc, add.rbdc, + add.ltppp, add.rtppp, add.lbppp, add.rbppp, add.smo2, add.thb, add.rvert, add.rcad, add.rcontact, add.interval); diff --git a/src/QuarqParser.cpp b/src/QuarqParser.cpp index 379368148..8808e1a2d 100644 --- a/src/QuarqParser.cpp +++ b/src/QuarqParser.cpp @@ -51,7 +51,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.0, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); + kph, nm, watts, 0, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); seconds_from_start += SAMPLE_INTERVAL; } @@ -114,6 +114,9 @@ QuarqParser::endElement( const QString&, const QString&, const QString& qName) if (qName == "Qollector") { rideFile->appendPoint(seconds_from_start, cad, hr, km, kph, nm, watts, 0, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, + 0.0,0.0,0.0,0.0, + 0.0,0.0, + 0.0,0.0,0.0,0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0); } diff --git a/src/RawRideFile.cpp b/src/RawRideFile.cpp index d89282c01..f1b2b0e1f 100644 --- a/src/RawRideFile.cpp +++ b/src/RawRideFile.cpp @@ -71,7 +71,12 @@ time_cb(struct tm *, time_t since_epoch, void *context) 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, 0.0, 0.0, - RideFile::NoTemp, 0.0, 0.0,0.0,0.0,0.0,0.0,0.0, + RideFile::NoTemp, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0,0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, + 0.0,0.0, 0.0,0.0,0.0, // running dynamic state->last_interval); state->last_secs = secs; @@ -90,6 +95,9 @@ data_cb(double secs, double nm, double mph, double watts, double miles, double a mph * KM_PER_MILE, nm, watts, alt, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, 0.0, 0.0,0.0,0.0,0.0, // pedal smooth/te 0.0,0.0, + 0.0,0.0,0.0,0.0, + 0.0,0.0,0.0,0.0, + 0.0,0.0, 0.0,0.0,0.0, interval); state->last_secs = secs; diff --git a/src/RideEditor.cpp b/src/RideEditor.cpp index 8dfece0e0..80dce256c 100644 --- a/src/RideEditor.cpp +++ b/src/RideEditor.cpp @@ -231,6 +231,16 @@ RideEditor::whatColumns() << tr("Right TE") << tr("Left PS") << tr("Right PS") + << tr("Left Platform Center Offset") + << tr("Right Platform Center Offset") + << tr("Left Top Dead Center") + << tr("Right Top Dead Center") + << tr("Left Bottom Dead Center") + << tr("Right Bottom Dead Center") + << tr("Left Peak Power Phase Start") + << tr("Right Peak Power Phase Start") + << tr("Left Peak Power Phase End") + << tr("Right Peak Power Phase End") << tr("SmO2") << tr("tHb") << tr("Vertical Oscillation") @@ -826,7 +836,17 @@ RideEditor::insColumn(QString name) if (name == tr("Left TE")) series = RideFile::lte; if (name == tr("Right TE")) series = RideFile::rte; if (name == tr("Left PS")) series = RideFile::lps; - if (name == tr("Right PS")) series = RideFile::rps; + if (name == tr("Right PS")) series = RideFile::rps; + if (name == tr("Left Platform Center Offset")) series = RideFile::lpco; + if (name == tr("Right Platform Center Offset")) series = RideFile::rpco; + if (name == tr("Left Top Dead Center")) series = RideFile::ltdc; + if (name == tr("Right Top Dead Center")) series = RideFile::rtdc; + if (name == tr("Left Bottom Dead Center")) series = RideFile::lbdc; + if (name == tr("Right Bottom Dead Center")) series = RideFile::rbdc; + if (name == tr("Left Peak Power Phase Start")) series = RideFile::ltppp; + if (name == tr("Right Peak Power Phase Start")) series = RideFile::rtppp; + if (name == tr("Left Peak Power Phase End")) series = RideFile::lbppp; + if (name == tr("Right Peak Power Phase End")) series = RideFile::rbppp; if (name == tr("SmO2")) series = RideFile::smo2; if (name == tr("tHb")) series = RideFile::thb; if (name == tr("Vertical Oscillation")) series = RideFile::rvert; diff --git a/src/RideFile.cpp b/src/RideFile.cpp index f1cba98a7..f3d42ce1b 100644 --- a/src/RideFile.cpp +++ b/src/RideFile.cpp @@ -175,6 +175,16 @@ RideFile::seriesName(SeriesType series) case RideFile::rte: return QString(tr("Right Torque Efficiency")); case RideFile::lps: return QString(tr("Left Pedal Smoothness")); case RideFile::rps: return QString(tr("Righ Pedal Smoothness")); + case RideFile::lpco: return QString(tr("Left Platform Center Offset")); + case RideFile::rpco: return QString(tr("Right Platform Center Offset")); + case RideFile::ltdc: return QString(tr("Left Top Dead Center")); + case RideFile::rtdc: return QString(tr("Right Top Dead Center")); + case RideFile::lbdc: return QString(tr("Left Bottom Dead Center")); + case RideFile::rbdc: return QString(tr("Right Bottom Dead Center")); + case RideFile::ltppp: return QString(tr("Left Peak Power Phase Start")); + case RideFile::rtppp: return QString(tr("Right Peak Power Phase Start")); + case RideFile::lbppp: return QString(tr("Left Peak Power Phase End")); + case RideFile::rbppp: return QString(tr("Right Peak Power Phase End")); case RideFile::interval: return QString(tr("Interval")); case RideFile::vam: return QString(tr("VAM")); case RideFile::wattsKg: return QString(tr("Watts per Kilogram")); @@ -218,6 +228,16 @@ RideFile::colorFor(SeriesType series) case RideFile::rte: return GColor(CRTE); case RideFile::lps: return GColor(CLPS); case RideFile::rps: return GColor(CRPS); + case RideFile::lpco: return GColor(CLPS); + case RideFile::rpco: return GColor(CRPS); + case RideFile::ltdc: return GColor(CLPS); + case RideFile::rtdc: return GColor(CRPS); + case RideFile::lbdc: return GColor(CLPS); + case RideFile::rbdc: return GColor(CRPS); + case RideFile::ltppp: return GColor(CLPS); + case RideFile::rtppp: return GColor(CRPS); + case RideFile::lbppp: return GColor(CLPS); + case RideFile::rbppp: return GColor(CRPS); case RideFile::interval: return QColor(Qt::white); case RideFile::wattsKg: return GColor(CPOWER); case RideFile::wprime: return GColor(CWBAL); @@ -272,7 +292,17 @@ RideFile::unitName(SeriesType series, Context *context) case RideFile::lte: return QString(tr("%")); case RideFile::rte: return QString(tr("%")); case RideFile::lps: return QString(tr("%")); - case RideFile::rps: return QString(tr("%")); + case RideFile::rps: return QString(tr("%")); + case RideFile::lpco: return QString(tr("mm")); + case RideFile::rpco: return QString(tr("mm")); + case RideFile::ltdc: return QString(tr("°")); + case RideFile::rtdc: return QString(tr("°")); + case RideFile::lbdc: return QString(tr("°")); + case RideFile::rbdc: return QString(tr("°")); + case RideFile::ltppp: return QString(tr("°")); + case RideFile::rtppp: return QString(tr("°")); + case RideFile::lbppp: return QString(tr("°")); + case RideFile::rbppp: return QString(tr("°")); case RideFile::interval: return QString(tr("Interval")); case RideFile::vam: return QString(tr("meters per hour")); case RideFile::wattsKg: return QString(useMetricUnits ? tr("watts/kg") : tr("watts/kg")); // always kg ! @@ -637,6 +667,26 @@ void RideFile::updateMin(RideFilePoint* point) minPoint->rps = point->rps; if (minPoint->lrbalance == 0 || point->lrbalancelrbalance) minPoint->lrbalance = point->lrbalance; + if (point->lpcolpco) + minPoint->lpco = point->lpco; + if (point->rpcorpco) + minPoint->rpco = point->rpco; + if (minPoint->ltdc == 0 || point->ltdcltdc) + minPoint->ltdc = point->ltdc; + if (minPoint->rtdc == 0 || point->rtdcrtdc) + minPoint->rtdc = point->rtdc; + if (minPoint->lbdc == 0 || point->lbdclbdc) + minPoint->lbdc = point->ltdc; + if (minPoint->rbdc == 0 || point->rbdcrbdc) + minPoint->rbdc = point->rbdc; + if (minPoint->ltppp == 0 || point->ltpppltppp) + minPoint->ltppp = point->ltppp; + if (minPoint->rtppp == 0 || point->rtppprtppp) + minPoint->rtppp = point->rtppp; + if (minPoint->lbppp == 0 || point->lbppplbppp) + minPoint->lbppp = point->ltppp; + if (minPoint->rbppp == 0 || point->rbppprbppp) + minPoint->rbppp = point->rbppp; if (minPoint->smo2 == 0 || point->smo2smo2) minPoint->smo2 = point->smo2; if (minPoint->o2hb == 0 || point->o2hbo2hb) @@ -694,6 +744,26 @@ void RideFile::updateMax(RideFilePoint* point) maxPoint->rps = point->rps; if (point->lrbalance>maxPoint->lrbalance) maxPoint->lrbalance = point->lrbalance; + if (point->lpco>maxPoint->lpco) + maxPoint->lpco = point->lpco; + if (point->rpco>maxPoint->rpco) + maxPoint->rpco = point->rpco; + if (point->ltdc>maxPoint->ltdc) + maxPoint->ltdc = point->ltdc; + if (point->rtdc>maxPoint->rtdc) + maxPoint->rtdc = point->rtdc; + if (point->lbdc>maxPoint->lbdc) + maxPoint->lbdc = point->ltdc; + if (point->rbdc>maxPoint->rbdc) + maxPoint->rbdc = point->rbdc; + if (point->ltppp>maxPoint->ltppp) + maxPoint->ltppp = point->ltppp; + if (point->rtppp>maxPoint->rtppp) + maxPoint->rtppp = point->rtppp; + if (point->lbppp>maxPoint->lbppp) + maxPoint->lbppp = point->ltppp; + if (point->rbppp>maxPoint->rbppp) + maxPoint->rbppp = point->rbppp; if (point->smo2>maxPoint->smo2) maxPoint->smo2 = point->smo2; if (point->thb>maxPoint->thb) @@ -733,6 +803,15 @@ void RideFile::updateAvg(RideFilePoint* point) totalPoint->lps += point->lps; totalPoint->rps += point->rps; totalPoint->lrbalance += point->lrbalance; + totalPoint->lpco += point->lpco; + totalPoint->rpco += point->rpco; + totalPoint->ltdc += point->ltdc; + totalPoint->rtdc += point->rtdc; + totalPoint->rbdc += point->rbdc; + totalPoint->ltppp += point->ltppp; + totalPoint->rtppp += point->rtppp; + totalPoint->lbppp += point->lbppp; + totalPoint->rbppp += point->rbppp; totalPoint->smo2 += point->smo2; totalPoint->thb += point->thb; totalPoint->o2hb += point->o2hb; @@ -764,6 +843,16 @@ void RideFile::updateAvg(RideFilePoint* point) avgPoint->rte = totalPoint->rte/totalCount; avgPoint->lps = totalPoint->lps/totalCount; avgPoint->rps = totalPoint->rps/totalCount; + avgPoint->lpco = totalPoint->lpco/totalCount; + avgPoint->rpco = totalPoint->rpco/totalCount; + avgPoint->ltdc = totalPoint->ltdc/totalCount; + avgPoint->rtdc = totalPoint->rtdc/totalCount; + avgPoint->lbdc = totalPoint->lbdc/totalCount; + avgPoint->rbdc = totalPoint->rbdc/totalCount; + avgPoint->ltppp = totalPoint->ltppp/totalCount; + avgPoint->rtppp = totalPoint->rtppp/totalCount; + avgPoint->lbppp = totalPoint->lbppp/totalCount; + avgPoint->rbppp = totalPoint->rbppp/totalCount; avgPoint->smo2 = totalPoint->smo2/totalCount; avgPoint->thb = totalPoint->thb/totalCount; avgPoint->o2hb = totalPoint->o2hb/totalCount; @@ -779,6 +868,9 @@ void RideFile::appendPoint(double secs, double cad, double hr, double km, double lon, double lat, double headwind, double slope, double temp, double lrbalance, double lte, double rte, double lps, double rps, + double lpco, double rpco, + double ltdc, double rtdc, double lbdc, double rbdc, + double ltppp, double rtppp, double lbppp, double rbppp, double smo2, double thb, double rvert, double rcad, double rcontact, int interval) @@ -797,6 +889,14 @@ void RideFile::appendPoint(double secs, double cad, double hr, double km, if (!std::isfinite(rps) || rps<0) rps=0; if (!std::isfinite(lte) || lte<0) lte=0; if (!std::isfinite(rte) || rte<0) rte=0; + if (!std::isfinite(ltdc) || ltdc<0) ltdc=0; + if (!std::isfinite(rtdc) || rtdc<0) rtdc=0; + if (!std::isfinite(lbdc) || lbdc<0) lbdc=0; + if (!std::isfinite(rbdc) || rbdc<0) rbdc=0; + if (!std::isfinite(ltppp) || ltppp<0) ltppp=0; + if (!std::isfinite(rtppp) || rtppp<0) rtppp=0; + if (!std::isfinite(lbppp) || lbppp<0) lbppp=0; + if (!std::isfinite(rbppp) || rbppp<0) rbppp=0; if (!std::isfinite(smo2) || smo2<0) smo2=0; if (!std::isfinite(thb) || thb<0) thb=0; if (!std::isfinite(rvert) || rvert<0) rvert=0; @@ -809,7 +909,12 @@ void RideFile::appendPoint(double secs, double cad, double hr, double km, if (alt > RideFile::maximumFor(RideFile::alt)) alt = RideFile::maximumFor(RideFile::alt); RideFilePoint* point = new RideFilePoint(secs, cad, hr, km, kph, nm, watts, alt, lon, lat, - headwind, slope, temp, lrbalance, lte, rte, lps, rps, + headwind, slope, temp, + lrbalance, + lte, rte, lps, rps, + lpco, rpco, + ltdc, rtdc, lbdc, rbdc, + ltppp, rtppp, lbppp, rbppp, smo2, thb, rvert, rcad, rcontact, interval); @@ -833,6 +938,16 @@ void RideFile::appendPoint(double secs, double cad, double hr, double km, dataPresent.rte |= (rte != 0); dataPresent.lps |= (lps != 0); dataPresent.rps |= (rps != 0); + dataPresent.lpco |= (lpco != 0); + dataPresent.rpco |= (rpco != 0); + dataPresent.ltdc |= (ltdc != 0); + dataPresent.rtdc |= (rtdc != 0); + dataPresent.lbdc |= (lbdc != 0); + dataPresent.rbdc |= (rbdc != 0); + dataPresent.ltppp |= (ltppp != 0); + dataPresent.rtppp |= (rtppp != 0); + dataPresent.lbppp |= (lbppp != 0); + dataPresent.rbppp |= (rbppp != 0); dataPresent.smo2 |= (smo2 != 0); dataPresent.thb |= (thb != 0); dataPresent.rvert |= (rvert != 0); @@ -851,6 +966,9 @@ void RideFile::appendPoint(const RideFilePoint &point) point.nm,point.watts,point.alt,point.lon,point.lat, point.headwind, point.slope, point.temp, point.lrbalance, point.lte, point.rte, point.lps, point.rps, + point.lpco, point.rpco, + point.ltdc, point.rtdc, point.lbdc, point.rbdc, + point.ltppp, point.rtppp, point.lbppp, point.rbppp, point.smo2, point.thb, point.rvert, point.rcad, point.rcontact, point.interval); @@ -878,6 +996,16 @@ RideFile::setDataPresent(SeriesType series, bool value) case rte : dataPresent.rte = value; break; case lps : dataPresent.lps = value; break; case rps : dataPresent.rps = value; break; + case lpco : dataPresent.lpco = value; break; + case rpco : dataPresent.rpco = value; break; + case ltdc : dataPresent.ltdc = value; break; + case rtdc : dataPresent.rtdc = value; break; + case lbdc : dataPresent.lbdc = value; break; + case rbdc : dataPresent.rbdc = value; break; + case ltppp : dataPresent.ltppp = value; break; + case rtppp : dataPresent.rtppp = value; break; + case lbppp : dataPresent.lbppp = value; break; + case rbppp : dataPresent.rbppp = value; break; case smo2 : dataPresent.smo2 = value; break; case thb : dataPresent.thb = value; break; case o2hb : dataPresent.o2hb = value; break; @@ -918,6 +1046,16 @@ RideFile::isDataPresent(SeriesType series) case rps : return dataPresent.rps; break; case lte : return dataPresent.lte; break; case rte : return dataPresent.rte; break; + case lpco : return dataPresent.lpco; break; + case rpco : return dataPresent.rpco; break; + case ltdc : return dataPresent.ltdc; break; + case rtdc : return dataPresent.rtdc; break; + case lbdc : return dataPresent.lbdc; break; + case rbdc : return dataPresent.rbdc; break; + case ltppp : return dataPresent.ltppp; break; + case rtppp : return dataPresent.rtppp; break; + case lbppp : return dataPresent.lbppp; break; + case rbppp : return dataPresent.rbppp; break; case smo2 : return dataPresent.smo2; break; case thb : return dataPresent.thb; break; case o2hb : return dataPresent.o2hb; break; @@ -954,6 +1092,16 @@ RideFile::setPointValue(int index, SeriesType series, double value) case rte : dataPoints_[index]->rte = value; break; case lps : dataPoints_[index]->lps = value; break; case rps : dataPoints_[index]->rps = value; break; + case lpco : dataPoints_[index]->lpco = value; break; + case rpco : dataPoints_[index]->rpco = value; break; + case ltdc : dataPoints_[index]->ltdc = value; break; + case rtdc : dataPoints_[index]->rtdc = value; break; + case lbdc : dataPoints_[index]->lbdc = value; break; + case rbdc : dataPoints_[index]->rbdc = value; break; + case ltppp : dataPoints_[index]->ltppp = value; break; + case rtppp : dataPoints_[index]->rtppp = value; break; + case lbppp : dataPoints_[index]->lbppp = value; break; + case rbppp : dataPoints_[index]->rbppp = value; break; case smo2 : dataPoints_[index]->smo2 = value; break; case thb : dataPoints_[index]->thb = value; break; case o2hb : dataPoints_[index]->o2hb = value; break; @@ -995,6 +1143,16 @@ RideFilePoint::value(RideFile::SeriesType series) const case RideFile::lps : return lps; break; case RideFile::rps : return rps; break; case RideFile::thb : return thb; break; + case RideFile::lpco : return lpco; break; + case RideFile::rpco : return rpco; break; + case RideFile::ltdc : return ltdc; break; + case RideFile::rtdc : return rtdc; break; + case RideFile::lbdc : return lbdc; break; + case RideFile::rbdc : return rbdc; break; + case RideFile::ltppp : return ltppp; break; + case RideFile::rtppp : return rtppp; break; + case RideFile::lbppp : return lbppp; break; + case RideFile::rbppp : return rbppp; break; case RideFile::smo2 : return smo2; break; case RideFile::o2hb : return o2hb; break; case RideFile::hhb : return hhb; break; @@ -1043,6 +1201,16 @@ RideFilePoint::setValue(RideFile::SeriesType series, double value) case RideFile::lps : lps = value; break; case RideFile::rps : rps = value; break; case RideFile::thb : thb = value; break; + case RideFile::lpco : lpco = value; break; + case RideFile::rpco : rpco = value; break; + case RideFile::ltdc : ltdc = value; break; + case RideFile::rtdc : rtdc = value; break; + case RideFile::lbdc : lbdc = value; break; + case RideFile::rbdc : rbdc = value; break; + case RideFile::ltppp : ltppp = value; break; + case RideFile::rtppp : rtppp = value; break; + case RideFile::lbppp : lbppp = value; break; + case RideFile::rbppp : rbppp = value; break; case RideFile::smo2 : smo2 = value; break; case RideFile::o2hb : o2hb = value; break; case RideFile::hhb : hhb = value; break; @@ -1132,6 +1300,16 @@ RideFile::decimalsFor(SeriesType series) case rps : case lte : case rte : return 0; break; + case lpco : + case rpco : + case ltdc : + case rtdc : + case lbdc : + case rbdc : + case ltppp : + case rtppp : + case lbppp : + case rbppp : return 0; break; case smo2 : return 0; break; case thb : return 2; break; case o2hb : return 2; break; @@ -1177,6 +1355,16 @@ RideFile::maximumFor(SeriesType series) case lte : case rte : case lrbalance : return 100; break; + case lpco : + case rpco : return 100; break; + case ltdc : + case rtdc : + case lbdc : + case rbdc : + case ltppp : + case rtppp : + case lbppp : + case rbppp : return 360; break; case smo2 : return 100; break; case thb : return 20; break; case o2hb : return 20; break; @@ -1222,6 +1410,16 @@ RideFile::minimumFor(SeriesType series) case lps : case rps : case lrbalance : return 0; break; + case lpco : + case rpco : return -100; break; + case ltdc : + case rtdc : + case lbdc : + case rbdc : + case ltppp : + case rtppp : + case lbppp : + case rbppp : return 0; break; case smo2 : return 0; break; case thb : return 0; break; case o2hb : return 0; break; @@ -1292,7 +1490,11 @@ void RideFile::appendReference(const RideFilePoint &point) referencePoints_.append(new RideFilePoint(point.secs,point.cad,point.hr,point.km,point.kph,point.nm, point.watts,point.alt,point.lon,point.lat, point.headwind, point.slope, point.temp, point.lrbalance, - point.lte, point.rte, point.lps, point.rps, point.smo2, point.thb, + point.lte, point.rte, point.lps, point.rps, + point.lpco, point.rpco, + point.ltdc, point.rtdc, point.lbdc, point.rbdc, + point.ltppp, point.rtppp, point.lbppp, point.rbppp, + point.smo2, point.thb, point.rvert, point.rcad, point.rcontact, point.interval)); } diff --git a/src/RideFile.h b/src/RideFile.h index 5ebbeeb37..ef1535b45 100644 --- a/src/RideFile.h +++ b/src/RideFile.h @@ -60,7 +60,8 @@ struct RideFileDataPresent { // basic (te = torqueeffectiveness, ps = pedal smoothness) bool secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, slope, temp; - bool lrbalance, lte, rte, lps, rps, smo2, thb, interval; + bool lrbalance, lte, rte, lps, rps, lpco, rpco, ltdc, rtdc, lbdc, rbdc, ltppp, rtppp, lbppp, rbppp; + bool smo2, thb, interval; // derived bool np,xp,apower,wprime,atiss,antiss,gear,hhb,o2hb; @@ -73,7 +74,9 @@ struct RideFileDataPresent secs(false), cad(false), hr(false), km(false), kph(false), nm(false), watts(false), alt(false), lon(false), lat(false), headwind(false), slope(false), temp(false), - lrbalance(false), lte(false), rte(false), lps(false), rps(false), smo2(false), thb(false), interval(false), + lrbalance(false), lte(false), rte(false), lps(false), rps(false), + lpco(false), rpco(false), ltdc(false), rtdc(false), lbdc(false), rbdc(false), ltppp(false), rtppp(false), lbppp(false), rbppp(false), + smo2(false), thb(false), interval(false), np(false), xp(false), apower(false), wprime(false), atiss(false), antiss(false),gear(false),hhb(false),o2hb(false), rvert(false), rcad(false), rcontact(false) {} @@ -144,7 +147,9 @@ class RideFile : public QObject // QObject to emit signals alt, lon, lat, headwind, slope, temp, interval, NP, xPower, vam, wattsKg, lrbalance, lte, rte, lps, rps, aPower, wprime, aTISS, anTISS, smo2, thb, - rvert, rcad, rcontact, gear, o2hb, hhb, none }; + rvert, rcad, rcontact, gear, o2hb, hhb, + lpco, rpco, ltdc, rtdc, lbdc, rbdc, ltppp, rtppp, lbppp, rbppp, + none }; enum specialValues { NoTemp = -255 }; typedef enum seriestype SeriesType; @@ -173,6 +178,9 @@ class RideFile : public QObject // QObject to emit signals double lon, double lat, double headwind, double slope, double temperature, double lrbalance, double lte, double rte, double lps, double rps, + double lpco, double rpco, + double ltdc, double rtdc, double lbdc, double rbdc, + double ltppp, double rtppp, double lbppp, double rbppp, double smo2, double thb, double rvert, double rcad, double rcontact, int interval); @@ -315,9 +323,18 @@ struct RideFilePoint { // recorded data double secs, cad, hr, km, kph, nm, watts, alt, lon, lat, headwind, slope, temp; + + // pedals double lrbalance, lte, rte, lps, rps; + double lpco, rpco; // left and right platform center offset + double ltdc, rtdc, lbdc, rbdc; // left and right top and bottom death center + double ltppp, rtppp, lbppp, rbppp; // left and right top (start) and bottom (stop) peak power phase + + // oxy double smo2, thb; - double hrd, cadd, kphd, nmd, wattsd; // acceleration in watts/s km/s + + // acceleration in watts/s km/s + double hrd, cadd, kphd, nmd, wattsd; // running data double rvert, rcad, rcontact; @@ -331,8 +348,12 @@ struct RideFilePoint // create blank point 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), headwind(0.0), - slope(0.0), temp(-255.0), lrbalance(0), lte(0.0), rte(0.0), - lps(0.0), rps(0.0), + slope(0.0), temp(-255.0), + lrbalance(0), + lte(0.0), rte(0.0), lps(0.0), rps(0.0), + lpco(0.0), rpco(0.0), + ltdc(0.0), rtdc(0.0), lbdc(0.0), rbdc(0.0), + ltppp(0.0), rtppp(0.0), lbppp(0.0), rbppp(0.0), smo2(0.0), thb(0.0), hrd(0.0), cadd(0.0), kphd(0.0), nmd(0.0), wattsd(0.0), rvert(0.0), rcad(0.0), rcontact(0.0), @@ -342,15 +363,23 @@ struct RideFilePoint // create point supplying all values RideFilePoint(double secs, double cad, double hr, double km, double kph, double nm, double watts, double alt, double lon, double lat, - double headwind, double slope, double temp, double lrbalance, + double headwind, double slope, double temp, + double lrbalance, double lte, double rte, double lps, double rps, + double lpco, double rpco, + double ltdc, double rtdc, double lbdc, double rbdc, + double ltppp, double rtppp, double lbppp, double rbppp, double smo2, double thb, double rvert, double rcad, double rcontact, int interval) : secs(secs), cad(cad), hr(hr), km(km), kph(kph), nm(nm), watts(watts), alt(alt), lon(lon), lat(lat), headwind(headwind), slope(slope), temp(temp), - lrbalance(lrbalance), lte(lte), rte(rte), lps(lps), rps(rps), + lrbalance(lrbalance), + lte(lte), rte(rte), lps(lps), rps(rps), + lpco(lpco), rpco(rpco), + ltdc(ltdc), rtdc(rtdc), lbdc(lbdc), rbdc(rbdc), + ltppp(ltppp), rtppp(rtppp), lbppp(lbppp), rbppp(rbppp), smo2(smo2), thb(thb), hrd(0.0), cadd(0.0), kphd(0.0), nmd(0.0), wattsd(0.0), rvert(rvert), rcad(rcad), rcontact(rcontact), interval(interval), diff --git a/src/RideFileTableModel.cpp b/src/RideFileTableModel.cpp index 641ac1023..3b2aea92e 100644 --- a/src/RideFileTableModel.cpp +++ b/src/RideFileTableModel.cpp @@ -141,6 +141,38 @@ RideFileTableModel::setHeadings(RideFile::SeriesType series) headings_ << tr("Right PS"); headingsType << RideFile::rps; } + if (series == RideFile::lpco || ride->areDataPresent()->lpco) { + headings_ << tr("Left Platform Center Offset"); + headingsType << RideFile::lpco; + } + if (series == RideFile::rpco || ride->areDataPresent()->rpco) { + headings_ << tr("Right Platform Center Offset"); + headingsType << RideFile::rpco; + } + if (series == RideFile::ltdc || ride->areDataPresent()->ltdc) { + headings_ << tr("Left Top Dead Center"); + headingsType << RideFile::ltdc; + } + if (series == RideFile::rtdc || ride->areDataPresent()->rtdc) { + headings_ << tr("Right Top Dead Center"); + headingsType << RideFile::rtdc; + } + if (series == RideFile::lbdc || ride->areDataPresent()->lbdc) { + headings_ << tr("Left Bottom Dead Center"); + headingsType << RideFile::lbdc; + } + if (series == RideFile::rbdc || ride->areDataPresent()->rbdc) { + headings_ << tr("Right Bottom Dead Center"); + headingsType << RideFile::rbdc; + } + if (series == RideFile::ltppp || ride->areDataPresent()->ltppp) { + headings_ << tr("Left Peak Power Phase Start"); + headingsType << RideFile::ltppp; + } + if (series == RideFile::rtppp || ride->areDataPresent()->rtppp) { + headings_ << tr("Right Peak Power Phase Start"); + headingsType << RideFile::rtppp; + } if (series == RideFile::smo2 || ride->areDataPresent()->smo2) { headings_ << tr("SmO2"); headingsType << RideFile::smo2; diff --git a/src/RideSummaryWindow.cpp b/src/RideSummaryWindow.cpp index 908cad89b..32060cd5d 100644 --- a/src/RideSummaryWindow.cpp +++ b/src/RideSummaryWindow.cpp @@ -946,7 +946,9 @@ RideSummaryWindow::htmlSummary() break; f.appendPoint(p->secs, p->cad, p->hr, p->km, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, p->headwind, - p->slope, p->temp, p->lrbalance, p->lte, p->rte, p->lps, p->rps, + p->slope, p->temp, p->lrbalance, + p->lte, p->rte, p->lps, p->rps, + p->lpco, p->rpco, p->ltdc, p->rtdc, p->lbdc, p->rbdc, p->ltppp, p->rtppp, p->lbppp, p->rbppp, p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, 0); // derived data diff --git a/src/SlfParser.cpp b/src/SlfParser.cpp index 96e83a4af..5b2649246 100644 --- a/src/SlfParser.cpp +++ b/src/SlfParser.cpp @@ -149,7 +149,7 @@ SlfParser::endElement( const QString&, const QString&, const QString& qName) distance *= KM_PER_MILE; alt *= FEET_PER_METER; } - rideFile->appendPoint(secs, cadence, hr, distance, speed, torque, power, alt, lon, lat, headwind, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, lap); + rideFile->appendPoint(secs, cadence, hr, distance, speed, torque, power, alt, lon, lat, headwind, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, lap); secs += samplingRate; } } diff --git a/src/SplitActivityWizard.cpp b/src/SplitActivityWizard.cpp index 97367a349..a8670005e 100644 --- a/src/SplitActivityWizard.cpp +++ b/src/SplitActivityWizard.cpp @@ -781,7 +781,9 @@ SplitConfirm::createRideFile(long start, long stop) returning->appendPoint(p->secs - offset, // start from zero! p->cad, p->hr, p->km - distanceoffset, p->kph, p->nm, p->watts, p->alt, p->lon, p->lat, - p->headwind, p->slope, p->temp, p->lrbalance, p->lte, p->rte, p->lps, p->rps, + p->headwind, p->slope, p->temp, + p->lrbalance, p->lte, p->rte, p->lps, p->rps, + p->lpco, p->rpco, p->ltdc, p->rtdc, p->lbdc, p->rbdc, p->ltppp, p->rtppp, p->lbppp, p->rbppp, p->smo2, p->thb, p->rvert, p->rcad, p->rcontact, p->interval); diff --git a/src/SrdRideFile.cpp b/src/SrdRideFile.cpp index 23bf83b22..0f9237ea5 100644 --- a/src/SrdRideFile.cpp +++ b/src/SrdRideFile.cpp @@ -92,7 +92,7 @@ RideFile *SrdFileReader::openRideFile(QFile &file, QStringList &errorStrings, QL km = w->dist_data[i]; // add to ride - result->appendPoint(time, cad, hr, km, kph, nm, watts, alt, lon, lat, wind, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); + result->appendPoint(time, cad, hr, km, kph, nm, watts, alt, lon, lat, wind, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); // keep a track of time time += w->recording_interval; diff --git a/src/SrmRideFile.cpp b/src/SrmRideFile.cpp index e563e0e84..597d713f7 100644 --- a/src/SrmRideFile.cpp +++ b/src/SrmRideFile.cpp @@ -315,6 +315,7 @@ RideFile *SrmFileReader::openRideFile(QFile &file, QStringList &errorStrings, QL double nm = watts / 2.0 / PI / cad * 60.0; result->appendPoint(secs, cad, hr, km, kph, nm, watts, alt, 0.0, 0.0, 0.0, 0.0, temp, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); ++blkidx; diff --git a/src/SyncRideFile.cpp b/src/SyncRideFile.cpp index 3a2ea9748..4e33cf92d 100644 --- a/src/SyncRideFile.cpp +++ b/src/SyncRideFile.cpp @@ -132,6 +132,7 @@ struct SyncFileReaderState km += intSecs * kph / 3600.0; rideFile->setRecIntSecs(intSecs); rideFile->appendPoint(*secs, cad, hr, km, kph, nm, watts, alt, lng, lat, headwind, grade, temp, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, interval); *secs = *secs + intSecs; diff --git a/src/TacxCafRideFile.cpp b/src/TacxCafRideFile.cpp index b3d41f7d1..88535f739 100644 --- a/src/TacxCafRideFile.cpp +++ b/src/TacxCafRideFile.cpp @@ -185,7 +185,9 @@ struct RideFilePoint readSinglePoint(const QByteArray& record, const double& tim double speed = (relativeDistance - lastDistance) / recordingIntervalInSeconds; - struct RideFilePoint point(timeInSeconds, cadence, heartRate, relativeDistance / 1000.0, speed * 3.6, 0.0, power, 0.0, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); + struct RideFilePoint point(timeInSeconds, cadence, heartRate, relativeDistance / 1000.0, speed * 3.6, 0.0, power, 0.0, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0); return point; } @@ -209,6 +211,7 @@ bool readRideData(RideFile *rideFile, const QByteArray& block, const int nrOfRec nextDataPoint.watts, nextDataPoint.alt, nextDataPoint.lon, nextDataPoint.lat, nextDataPoint.headwind, 0.0, RideFile::NoTemp, 0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,nextDataPoint.interval); } return true; diff --git a/src/TcxParser.cpp b/src/TcxParser.cpp index 62d5192cc..5b8c11f92 100644 --- a/src/TcxParser.cpp +++ b/src/TcxParser.cpp @@ -169,6 +169,7 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName) rideFile->appendPoint(secs, cadence, hr, distance, speed, torque, power, alt, lon, lat, headwind, 0.0, RideFile::NoTemp, 0.0, 0.0,0.0,0.0,0.0,0.0,0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,rcad,0.0, // no running dynamics in the schema ? lap); @@ -195,7 +196,9 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName) // no smart recording, or delta exceeds HW treshold, just insert the data rideFile->appendPoint(secs, cadence, hr, distance, speed, torque, power, alt, lon, lat, headwind, 0.0, RideFile::NoTemp, 0.0, - 0.0,0.0,0.0,0.0,0.0,0.0, + 0.0,0.0,0.0,0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, + 0.0,0.0, 0.0, // vertical oscillation rcad, // run cadence 0.0, // gct @@ -229,6 +232,7 @@ TcxParser::endElement( const QString&, const QString&, const QString& qName) RideFile::NoTemp, 0.0, 0.0,0.0,0.0,0.0, + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,0.0, 0.0, // vertical oscillation prevPoint->rcad + (deltarcad * weight),// run cadence diff --git a/src/TxtRideFile.cpp b/src/TxtRideFile.cpp index 55ef1bfc9..cbcb119c6 100644 --- a/src/TxtRideFile.cpp +++ b/src/TxtRideFile.cpp @@ -204,7 +204,7 @@ RideFile *TxtFileReader::openRideFile(QFile &file, QStringList &errors, QListappendPoint(secs, cad, hr, km, kph, 0.0, watts, 0.0, 0.0, 0.0, headwind, 0.0, RideFile::NoTemp, 0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0); + rideFile->appendPoint(secs, cad, hr, km, kph, 0.0, watts, 0.0, 0.0, 0.0, headwind, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0); } } @@ -386,7 +386,7 @@ RideFile *TxtFileReader::openRideFile(QFile &file, QStringList &errors, QList= 0) torq = tokens.at(torqIndex).toDouble(); if (wattsIndex >= 0) watts = tokens.at(wattsIndex).toDouble(); - rideFile->appendPoint(secs, rpm, bpm, km, kph, torq, watts, 0.0, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, 0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0); + rideFile->appendPoint(secs, rpm, bpm, km, kph, torq, watts, 0.0, 0.0, 0.0, 0.0, 0.0, RideFile::NoTemp, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0, 0); } } diff --git a/src/WkoRideFile.cpp b/src/WkoRideFile.cpp index 4bd9d4f73..e8e04faa2 100644 --- a/src/WkoRideFile.cpp +++ b/src/WkoRideFile.cpp @@ -489,6 +489,7 @@ WkoParser::parseRawData(WKO_UCHAR *fb) results->appendPoint((double)rtime/1000, cad, hr, km, kph, nm, watts, alt, lon, lat, wind, slope, temp, 0.0, 0.0,0.0,0.0,0.0, // vector pedal torque eff and smoothness not supported in WKO (?) + 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,0.0, 0.0,0.0,0.0, // running dynamics 0);