diff --git a/src/DialWindow.cpp b/src/DialWindow.cpp index 0ad8a314d..e738e8ede 100644 --- a/src/DialWindow.cpp +++ b/src/DialWindow.cpp @@ -24,7 +24,6 @@ DialWindow::DialWindow(MainWindow *mainWindow) : { setContentsMargins(0,0,0,0); setInstanceName("Dial"); - resetValues(); QWidget *c = new QWidget; QVBoxLayout *cl = new QVBoxLayout(c); @@ -55,6 +54,8 @@ DialWindow::DialWindow(MainWindow *mainWindow) : connect(mainWindow, SIGNAL(telemetryUpdate(RealtimeData)), this, SLOT(telemetryUpdate(RealtimeData))); connect(seriesSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(seriesChanged())); connect(mainWindow, SIGNAL(configChanged()), this, SLOT(seriesChanged())); + connect(mainWindow, SIGNAL(stop()), this, SLOT(stop())); + connect(mainWindow, SIGNAL(start()), this, SLOT(start())); // setup colors seriesChanged(); @@ -63,7 +64,7 @@ DialWindow::DialWindow(MainWindow *mainWindow) : resizeEvent(NULL); // set to zero - telemetryUpdate(RealtimeData()); + resetValues(); } void @@ -147,11 +148,14 @@ void DialWindow::seriesChanged() case RealtimeData::LapTime: case RealtimeData::Distance: case RealtimeData::Lap: - case RealtimeData::Load: case RealtimeData::None: foreground = GColor(CPLOTMARKER); break; + case RealtimeData::Load: + foreground = Qt::blue; + break; + case RealtimeData::XPower: case RealtimeData::Joules: case RealtimeData::BikeScore: diff --git a/src/DialWindow.h b/src/DialWindow.h index 615a15f32..546bbf6b9 100644 --- a/src/DialWindow.h +++ b/src/DialWindow.h @@ -99,7 +99,7 @@ class DialWindow : public GcWindow double avg30, avgLap, avgTotal; double lapNumber; int count; - void resetValues() { instantValue = avg30 = avgLap = avgTotal = lapNumber = 0; } + void resetValues() { instantValue = avg30 = avgLap = avgTotal = lapNumber = 0; telemetryUpdate(RealtimeData()); } // controls QComboBox *seriesSelector; diff --git a/src/ErgFile.cpp b/src/ErgFile.cpp index 2a849f91a..e7a7999f6 100644 --- a/src/ErgFile.cpp +++ b/src/ErgFile.cpp @@ -26,7 +26,7 @@ ErgFile::ErgFile(QString filename, int &mode, double Cp) leftPoint=rightPoint=0; MaxWatts = Ftp = 0; int lapcounter = 0; - int format = ERG; // either ERG or MRC + format = ERG; // either ERG or MRC // running totals for CRS file format long rdist = 0; // running total for distance @@ -269,7 +269,7 @@ ErgFile::wattsAt(long x, int &lapnum) } lapnum = lap; - } + } else lapnum = 0; // find right section of the file while (x < Points.at(leftPoint).x || x > Points.at(rightPoint).x) { diff --git a/src/ErgFile.h b/src/ErgFile.h index 9338963fc..de7a314cf 100644 --- a/src/ErgFile.h +++ b/src/ErgFile.h @@ -65,6 +65,7 @@ class ErgFile ~ErgFile(); // delete the contents bool isValid(); // is the file valid or not? + int format; // ERG, CRS or MRC currently supported int wattsAt(long, int&); // return the watts value for the passed msec double gradientAt(long, int&); // return the gradient value for the passed meter int nextLap(long); // return the msecs value for the next Lap marker @@ -72,8 +73,8 @@ class ErgFile QString Version, // version number / identifer Units, // units used Filename, // filename from inside file - Name, // workout name - Format; // only ever seen MINUTES WATTS + Name; // workout name + long Duration; // Duration of this workout in msecs int Ftp; // FTP this file was targetted at int MaxWatts; // maxWatts in this ergfile (scaling) diff --git a/src/ErgFilePlot.cpp b/src/ErgFilePlot.cpp index 9852b4bac..06d2704a5 100644 --- a/src/ErgFilePlot.cpp +++ b/src/ErgFilePlot.cpp @@ -23,7 +23,7 @@ static ErgFile *ergFile; static QList *courseData; static long Now; -static int MaxWatts; +static double MaxWatts; // Load history double ErgFileData::x(size_t i) const { return courseData ? courseData->at(i).x : 0; } @@ -34,7 +34,7 @@ QwtData *ErgFileData::copy() const { return new ErgFileData(); } // Now bar double NowData::x(size_t) const { return Now; } -double NowData::y(size_t i) const { return (i ? MaxWatts : 0); } +double NowData::y(size_t i) const { return (i ? (MaxWatts ? MaxWatts : 500) : 0); } size_t NowData::size() const { return 2; } QwtData *NowData::copy() const { return new NowData(); } @@ -48,24 +48,105 @@ ErgFilePlot::ErgFilePlot(QList *data) courseData = data; // what we plot Now = 0; // where we are - // Setup the axis (of evil :-) + // Setup the left axis (Power) setAxisTitle(yLeft, "Watts"); - //setAxisScale(yLeft, 0, 500); // watts -- Autoscale please! - enableAxis(yLeft, false); - enableAxis(xBottom, false); // very little value and some cpu overhead + enableAxis(yLeft, true); + QwtScaleDraw *sd = new QwtScaleDraw; + sd->setTickLength(QwtScaleDiv::MajorTick, 3); + setAxisMaxMinor(yLeft, 0); + setAxisScaleDraw(QwtPlot::yLeft, sd); + + QPalette pal; + pal.setColor(QPalette::WindowText, GColor(CPOWER)); + pal.setColor(QPalette::Text, GColor(CPOWER)); + axisWidget(QwtPlot::yLeft)->setPalette(pal); + + QFont stGiles; + stGiles.fromString(appsettings->value(this, GC_FONT_CHARTLABELS, QFont().toString()).toString()); + stGiles.setPointSize(appsettings->value(NULL, GC_FONT_CHARTLABELS_SIZE, 8).toInt()); + QwtText title("Watts"); + title.setFont(stGiles); + QwtPlot::setAxisFont(yLeft, stGiles); + QwtPlot::setAxisTitle(yLeft, title); + + + //setAxisScale(yLeft, 0, 1000); // we autoscale, since peaks are so much higher than troughs + enableAxis(xBottom, true); + distdraw = new DistScaleDraw; + distdraw->setTickLength(QwtScaleDiv::MajorTick, 3); + timedraw = new TimeScaleDraw; + timedraw->setTickLength(QwtScaleDiv::MajorTick, 3); + setAxisMaxMinor(xBottom, 0); + setAxisScaleDraw(QwtPlot::xBottom, timedraw); + + // set the axis so we default to an hour workout + setAxisScale(xBottom, (double)0, 1000 * 60 * 60 , 15 * 60 * 1000); + + title.setFont(stGiles); + title.setText("Time (mins)"); + QwtPlot::setAxisFont(xBottom, stGiles); + QwtPlot::setAxisTitle(xBottom, title); + + pal.setColor(QPalette::WindowText, Qt::blue); + pal.setColor(QPalette::Text, Qt::blue); + axisWidget(QwtPlot::xBottom)->setPalette(pal); + + + // set all the orher axes off but scaled + setAxisScale(yRight, 0, 250); // max cadence and hr enableAxis(yRight, false); + setAxisScale(yRight2, 0, 60); // max speed of 60mph/60kmh seems ok to me! + enableAxis(yRight2, false); // Load Curve LodCurve = new QwtPlotCurve("Course Load"); - QPen Lodpen = QPen(Qt::blue, 1.0); - LodCurve->setPen(Lodpen); - LodCurve->setData(lodData); LodCurve->attach(this); LodCurve->setYAxis(QwtPlot::yLeft); + + // load curve is blue for time and grey for gradient QColor brush_color = QColor(Qt::blue); brush_color.setAlpha(64); LodCurve->setBrush(brush_color); // fill below the line + QPen Lodpen = QPen(Qt::blue, 1.0); + LodCurve->setPen(Lodpen); + + // telemetry history + wattsCurve = new QwtPlotCurve("Power"); + QPen wattspen = QPen(GColor(CPOWER)); + wattsCurve->setPen(wattspen); + wattsCurve->attach(this); + wattsCurve->setYAxis(QwtPlot::yLeft); + wattsCurve->setPaintAttribute(QwtPlotCurve::PaintFiltered); + wattsData = new CurveData; + wattsCurve->setRawData(wattsData->x(), wattsData->y(), wattsData->count()); + + // telemetry history + hrCurve = new QwtPlotCurve("Heartrate"); + QPen hrpen = QPen(GColor(CHEARTRATE)); + hrCurve->setPen(hrpen); + hrCurve->attach(this); + hrCurve->setYAxis(QwtPlot::yRight); + hrData = new CurveData; + hrCurve->setRawData(hrData->x(), hrData->y(), hrData->count()); + + // telemetry history + cadCurve = new QwtPlotCurve("Cadence"); + QPen cadpen = QPen(GColor(CCADENCE)); + cadCurve->setPen(cadpen); + cadCurve->attach(this); + cadCurve->setYAxis(QwtPlot::yRight); + cadData = new CurveData; + cadCurve->setRawData(cadData->x(), cadData->y(), cadData->count()); + + // telemetry history + speedCurve = new QwtPlotCurve("Speed"); + QPen speedpen = QPen(GColor(CSPEED)); + speedCurve->setPen(speedpen); + speedCurve->attach(this); + speedCurve->setYAxis(QwtPlot::yRight2); + speedData = new CurveData; + speedCurve->setRawData(speedData->x(), speedData->y(), speedData->count()); // Now pointer NowCurve = new QwtPlotCurve("Now"); @@ -75,11 +156,16 @@ ErgFilePlot::ErgFilePlot(QList *data) NowCurve->attach(this); NowCurve->setYAxis(QwtPlot::yLeft); + bydist = false; + + setAutoReplot(false); } void ErgFilePlot::setData(ErgFile *ergfile) { + reset(); + ergFile = ergfile; // clear the previous marks (if any) for(int i=0; ivalue(this, GC_FONT_CHARTLABELS, QFont().toString()).toString()); + stGiles.setPointSize(appsettings->value(NULL, GC_FONT_CHARTLABELS_SIZE, 8).toInt()); + QPalette pal; + if (ergfile) { + // is this by distance or time? + bydist = (ergfile->format == CRS) ? true : false; + + if (bydist == true) { + + QColor brush_color = QColor(Qt::gray); + brush_color.setAlpha(64); + LodCurve->setBrush(brush_color); // fill below the line + QPen Lodpen = QPen(Qt::gray, 1.0); + LodCurve->setPen(Lodpen); + + } else { + + QColor brush_color = QColor(Qt::blue); + brush_color.setAlpha(64); + LodCurve->setBrush(brush_color); // fill below the line + QPen Lodpen = QPen(Qt::blue, 1.0); + LodCurve->setPen(Lodpen); + + } + // set up again //setTitle(ergFile->Name); courseData = &ergfile->Points; - MaxWatts = ergfile->MaxWatts; + MaxWatts = LodCurve->maxYValue(); for(int i=0; i < ergFile->Laps.count(); i++) { // Show Lap Number QwtText text(QString::number(ergFile->Laps.at(i).LapNum)); text.setFont(QFont("Helvetica", 10, QFont::Bold)); - text.setColor(Qt::black); + text.setColor(GColor(CPLOTMARKER)); // vertical line QwtPlotMarker *add = new QwtPlotMarker(); add->setLineStyle(QwtPlotMarker::VLine); + add->setLinePen(QPen(GColor(CPLOTMARKER), 0, Qt::DashDotLine)); add->setLabelAlignment(Qt::AlignRight | Qt::AlignTop); - add->setLinePen(QPen(Qt::black, 0, Qt::DashDotLine)); add->setValue(ergFile->Laps.at(i).x, 0.0); add->setLabel(text); add->attach(this); @@ -115,13 +228,75 @@ ErgFilePlot::setData(ErgFile *ergfile) } // set the axis so we use all the screen estate - if ((*courseData).count()) setAxisScale(xBottom, (double)0, (double)(*courseData).last().x); + if ((*courseData).count()) { + double maxX = (double)(*courseData).last().x; + + if (bydist) { + + // tics every 5 kilometer, if workout shorter tics every 1000m + double step = 5000; + if (maxX <= 1000) step = 100; + else if (maxX < 5000) step = 1000; + + // axis setup for distance + setAxisScale(xBottom, (double)0, maxX, step); + + QwtText title; + title.setFont(stGiles); + title.setText("Distance (km)"); + QwtPlot::setAxisFont(xBottom, stGiles); + QwtPlot::setAxisTitle(xBottom, title); + + pal.setColor(QPalette::WindowText, Qt::gray); + pal.setColor(QPalette::Text, Qt::gray); + axisWidget(QwtPlot::xBottom)->setPalette(pal); + + // only allocate a new one if its not the current (they get freed by Qwt) + if (axisScaleDraw(xBottom) != distdraw) + setAxisScaleDraw(QwtPlot::xBottom, (distdraw=new DistScaleDraw())); + + } else { + + // tics every 15 minutes, if workout shorter tics every minute + setAxisScale(xBottom, (double)0, maxX, maxX > (15*60*1000) ? 15*60*1000 : 60*1000); + + QwtText title; + title.setFont(stGiles); + title.setText("Time (mins)"); + QwtPlot::setAxisFont(xBottom, stGiles); + QwtPlot::setAxisTitle(xBottom, title); + + pal.setColor(QPalette::WindowText, Qt::blue); + pal.setColor(QPalette::Text, Qt::blue); + axisWidget(QwtPlot::xBottom)->setPalette(pal); + + // only allocate a new one if its not the current (they get freed by Qwt) + if (axisScaleDraw(xBottom) != timedraw) + setAxisScaleDraw(QwtPlot::xBottom, (timedraw=new TimeScaleDraw())); + } + } } else { // clear the plot we have nothing selected + bydist = false; // do by time when no workout selected MaxWatts = 0; courseData = NULL; + + QwtText title; + title.setFont(stGiles); + title.setText("Time (mins)"); + QwtPlot::setAxisFont(xBottom, stGiles); + QwtPlot::setAxisTitle(xBottom, title); + + pal.setColor(QPalette::WindowText, Qt::blue); + pal.setColor(QPalette::Text, Qt::blue); + axisWidget(QwtPlot::xBottom)->setPalette(pal); + + // set the axis so we default to an hour workout + if (axisScaleDraw(xBottom) != timedraw) + setAxisScaleDraw(QwtPlot::xBottom, (timedraw=new TimeScaleDraw())); + setAxisScale(xBottom, (double)0, 1000 * 60 * 60, 15*60*1000); } } @@ -132,3 +307,154 @@ ErgFilePlot::setNow(long msecs) replot(); // and update } +void +ErgFilePlot::performancePlot(RealtimeData rtdata) +{ + // we got some data + // x is plotted in meters or micro-seconds + double x = bydist ? (rtdata.getDistance() * 1000) : rtdata.getMsecs(); + + // when not using a workout we need to extend the axis when we + // go out of bounds -- we do not use autoscale for x, because we + // want to control stepping and tick marking add another 30 mins + if (!ergFile && axisScaleDiv(xBottom)->upperBound() <= x) { + double maxX = x + ( 30 * 60 * 1000); + setAxisScale(xBottom, (double)0, maxX, maxX > (15*60*1000) ? 15*60*1000 : 60*1000); + } + + double watts = rtdata.getWatts(); + double speed = rtdata.getSpeed(); + double cad = rtdata.getCadence(); + double hr = rtdata.getHr(); + + wattssum += watts; + hrsum += hr; + cadsum += cad; + speedsum += speed; + + if (counter < 25) { + counter++; + return; + } else { + watts = wattssum / 26; + hr = hrsum / 26; + cad = cadsum / 26; + speed = speedsum / 26; + counter=0; + wattssum = hrsum = cadsum = speedsum = 0; + } + + double zero = 0; + + if (!wattsData->count()) wattsData->append(&zero, &watts, 1); + wattsData->append(&x, &watts, 1); + wattsCurve->setRawData(wattsData->x(), wattsData->y(), wattsData->count()); + + if (!hrData->count()) hrData->append(&zero, &hr, 1); + hrData->append(&x, &hr, 1); + hrCurve->setRawData(hrData->x(), hrData->y(), hrData->count()); + + if (!speedData->count()) speedData->append(&zero, &speed, 1); + speedData->append(&x, &speed, 1); + speedCurve->setRawData(speedData->x(), speedData->y(), speedData->count()); + + if (!cadData->count()) cadData->append(&zero, &cad, 1); + cadData->append(&x, &cad, 1); + cadCurve->setRawData(cadData->x(), cadData->y(), cadData->count()); + + const bool cacheMode = canvas()->testPaintAttribute(QwtPlotCanvas::PaintCached); + +#if 0 +#if QT_VERSION >= 0x040000 && defined(Q_WS_X11) + // Even if not recommended by TrollTech, Qt::WA_PaintOutsidePaintEvent + // works on X11. This has an tremendous effect on the performance.. + + canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, true); +#endif + + canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, false); + wattsCurve->draw(0, wattsCurve->dataSize() - 1); + hrCurve->draw(0, hrCurve->dataSize() - 1); + cadCurve->draw(0, cadCurve->dataSize() - 1); + speedCurve->draw(0, speedCurve->dataSize() - 1); + canvas()->setPaintAttribute(QwtPlotCanvas::PaintCached, cacheMode); + +#if QT_VERSION >= 0x040000 && defined(Q_WS_X11) + canvas()->setAttribute(Qt::WA_PaintOutsidePaintEvent, false); +#endif +#endif + +} + +void +ErgFilePlot::start() +{ + reset(); +} + +void +ErgFilePlot::reset() +{ + // reset data + counter = hrsum = wattssum = speedsum = cadsum = 0; + + // note the origin of the data is not a point 0, but the first + // average over 5 seconds. this leads to a small gap on the left + // which is better than the traces all starting from 0,0 which whilst + // is factually correct, does not tell us anything useful and look horrid. + // instead when we place the first points on the plots we add them twice + // once for time/distance of 0 and once for the current point in time + wattsData->clear(); + wattsCurve->setRawData(wattsData->x(), wattsData->y(), wattsData->count()); + cadData->clear(); + cadCurve->setRawData(cadData->x(), cadData->y(), cadData->count()); + hrData->clear(); + hrCurve->setRawData(hrData->x(), hrData->y(), hrData->count()); + speedData->clear(); + speedCurve->setRawData(speedData->x(), speedData->y(), speedData->count()); +} + +// curve data.. code snaffled in from the Qwt example (realtime_plot) +CurveData::CurveData(): d_count(0) { } + +void CurveData::append(double *x, double *y, int count) +{ + int newSize = ((d_count + count) / 1000 + 1 ) * 1000; + if (newSize > size()) { + d_x.resize(newSize); + d_y.resize(newSize); + } + + for (register int i = 0; i < count; i++) { + d_x[d_count + i] = x[i]; + d_y[d_count + i] = y[i]; + } + d_count += count; +} + +int CurveData::count() const +{ + return d_count; +} + +int CurveData::size() const +{ + return d_x.size(); +} + +const double *CurveData::x() const +{ + return d_x.data(); +} + +const double *CurveData::y() const +{ + return d_y.data(); +} + +void CurveData::clear() +{ + d_count = 0; + d_x.clear(); + d_y.clear(); +} diff --git a/src/ErgFilePlot.h b/src/ErgFilePlot.h index 423641ebc..6e89c6dd7 100644 --- a/src/ErgFilePlot.h +++ b/src/ErgFilePlot.h @@ -30,11 +30,16 @@ #include #include #include +#include +#include +#include #include "ErgFile.h" #include "Settings.h" #include "Colors.h" +#include "RealtimeData.h" + class ErgFileData : public QwtData { @@ -56,6 +61,45 @@ class NowData : public QwtData void init() ; }; +// incremental data, for each curve +class CurveData +{ + // A container class for growing data +public: + + CurveData(); + + void append(double *x, double *y, int count); + void clear(); + + int count() const; + int size() const; + const double *x() const; + const double *y() const; + +private: + int d_count; + QwtArray d_x; + QwtArray d_y; +}; + +class DistScaleDraw: public QwtScaleDraw +{ +public: + DistScaleDraw() { } + + // we do 100m for <= a kilo + virtual QwtText label(double v) const { if (v<1000) return QString("%1").arg(v/1000, 0, 'g', 1); + else return QString("%1").arg(round(v/1000)); } +}; +class TimeScaleDraw: public QwtScaleDraw +{ +public: + TimeScaleDraw() { } + + virtual QwtText label(double v) const { return QString("%1").arg(round(v/60000)); } +}; + class ErgFilePlot : public QwtPlot { Q_OBJECT @@ -68,18 +112,43 @@ class ErgFilePlot : public QwtPlot QList Marks; void setData(ErgFile *); // set the course + void reset(); // reset counters etc when plot changes void setNow(long); // set point we're add for progress pointer - //void plot(); + + public slots: + + void performancePlot(RealtimeData); + void start(); private: + bool bydist; + QwtPlotGrid *grid; QwtPlotCurve *LodCurve; + QwtPlotCurve *wattsCurve; + QwtPlotCurve *hrCurve; + QwtPlotCurve *cadCurve; + QwtPlotCurve *speedCurve; QwtPlotCurve *NowCurve; + CurveData *wattsData, + *hrData, + *cadData, + *speedData; + + double counter; + double wattssum, + hrsum, + cadsum, + speedsum; + ErgFileData lodData; NowData nowData; + DistScaleDraw *distdraw; + TimeScaleDraw *timedraw; + ErgFilePlot(); }; diff --git a/src/MainWindow.h b/src/MainWindow.h index 79b00ee14..6ee77742c 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -145,6 +145,11 @@ class MainWindow : public QMainWindow void notifyTelemetryUpdate(const RealtimeData &rtData) { telemetryUpdate(rtData); } void notifyErgFileSelected(ErgFile *x) { ergFileSelected(x); } void notifySetNow(long now) { setNow(now); } + void notifyNewLap() { emit newLap(); } + void notifyStart() { emit start(); } + void notifyUnPause() { emit unpause(); } + void notifyPause() { emit pause(); } + void notifyStop() { emit stop(); } @@ -171,9 +176,16 @@ class MainWindow : public QMainWindow void rideDeleted(RideItem *); void rideDirty(); void rideClean(); + + // realtime void telemetryUpdate(RealtimeData rtData); void ergFileSelected(ErgFile *); void setNow(long); + void newLap(); + void start(); + void unpause(); + void pause(); + void stop(); public slots: void showTreeContextMenuPopup(const QPoint &); diff --git a/src/NullController.cpp b/src/NullController.cpp index 410144a05..ff3d59f8e 100644 --- a/src/NullController.cpp +++ b/src/NullController.cpp @@ -23,6 +23,8 @@ #include "RaceDispatcher.h" #include "RealtimeData.h" +#include + NullController::NullController(TrainTool *parent, DeviceConfiguration *) : RealtimeController(parent), parent(parent), load(100) @@ -47,11 +49,11 @@ int NullController::restart() { void NullController::getRealtimeData(RealtimeData &rtData) { rtData.setName((char *)"Null"); - rtData.setWatts(load); + rtData.setWatts(load + ((rand()%25)-15)); rtData.setLoad(load); - rtData.setSpeed(20); - rtData.setCadence(90); - rtData.setHr(145); + rtData.setSpeed(45 + ((rand()%5)-2)); + rtData.setCadence(85 + ((rand()%10)-5)); + rtData.setHr(145 + ((rand()%3)-2)); } void NullController::pushRealtimeData(RealtimeData &) { diff --git a/src/RealtimeData.cpp b/src/RealtimeData.cpp index d8428bdb3..297f78fc2 100644 --- a/src/RealtimeData.cpp +++ b/src/RealtimeData.cpp @@ -24,7 +24,7 @@ RealtimeData::RealtimeData() { name[0] = '\0'; - watts = hr = speed = wheelRpm = cadence = load = 0; + lap = watts = hr = speed = wheelRpm = cadence = load = 0; msecs = lapMsecs = bikeScore = joules = 0; } @@ -142,6 +142,9 @@ double RealtimeData::value(DataSeries series) const case Time: return msecs; break; + case Lap: return lap; + break; + case LapTime: return lapMsecs; break; @@ -190,6 +193,7 @@ const QList &RealtimeData::listDataSeries() // better populate it first! seriesList << None; seriesList << Time; + seriesList << Lap; seriesList << LapTime; seriesList << Distance; seriesList << Watts; @@ -215,6 +219,9 @@ QString RealtimeData::seriesName(DataSeries series) case Time: return tr("Time"); break; + case Lap: return tr("Lap"); + break; + case LapTime: return tr("Lap Time"); break; @@ -246,3 +253,13 @@ QString RealtimeData::seriesName(DataSeries series) break; } } + +void RealtimeData::setLap(long lap) +{ + this->lap = lap; +} + +long RealtimeData::getLap() const +{ + return lap; +} diff --git a/src/RealtimeData.h b/src/RealtimeData.h index c58a1fd51..1cea34f47 100644 --- a/src/RealtimeData.h +++ b/src/RealtimeData.h @@ -56,6 +56,7 @@ public: void setBikeScore(long); void setJoules(long); void setXPower(long); + void setLap(long); const char *getName() const; double getWatts() const; @@ -71,6 +72,7 @@ public: long getBikeScore() const; long getJoules() const; long getXPower() const; + long getLap() const; private: @@ -82,7 +84,7 @@ private: // derived data double distance; - int lap; + long lap; long msecs; long lapMsecs; long bikeScore, joules, xPower; diff --git a/src/RealtimePlot.cpp b/src/RealtimePlot.cpp index 5b6550157..2ff680331 100644 --- a/src/RealtimePlot.cpp +++ b/src/RealtimePlot.cpp @@ -30,16 +30,16 @@ // Power history double RealtimePwrData::x(size_t i) const { return (double)50-i; } -double RealtimePwrData::y(size_t i) const { return pwrData[(pwrCur+100+i) <150 ? (pwrCur+100+i) : (pwrCur+100+i-150)]; } +double RealtimePwrData::y(size_t i) const { return pwrData[(pwrCur+i) < 50 ? (pwrCur+i) : (pwrCur+i-50)]; } size_t RealtimePwrData::size() const { return 50; } QwtData *RealtimePwrData::copy() const { return new RealtimePwrData(const_cast(this)); } -void RealtimePwrData::init() { pwrCur=0; for (int i=0; i<150; i++) pwrData[i]=0; } -void RealtimePwrData::addData(double v) { pwrData[pwrCur++] = v; if (pwrCur==150) pwrCur=0; } +void RealtimePwrData::init() { pwrCur=0; for (int i=0; i<50; i++) pwrData[i]=0; } +void RealtimePwrData::addData(double v) { pwrData[pwrCur++] = v; if (pwrCur==50) pwrCur=0; } // 30 second Power rolling avg -double Realtime30PwrData::x(size_t i) const { return (double)50-i; } +double Realtime30PwrData::x(size_t i) const { return i ? 0 : 50; } -double Realtime30PwrData::y(size_t i) const { int pwr30=0; if (i==1) { for (int x=0; x<150; x++) { pwr30+=pwrData[x]; } pwr30 /= 150; } return pwr30; } +double Realtime30PwrData::y(size_t i) const { double pwr30=0; for (int x=0; x<150; x++) { pwr30+=pwrData[x]; } pwr30 /= 150; return pwr30; } size_t Realtime30PwrData::size() const { return 50; } QwtData *Realtime30PwrData::copy() const { return new Realtime30PwrData(const_cast(this)); } void Realtime30PwrData::init() { pwrCur=0; for (int i=0; i<150; i++) pwrData[i]=0; } @@ -93,6 +93,11 @@ RealtimePlot::RealtimePlot() : pwrCurve(NULL) setAxisTitle(yRight, "Cadence / HR"); setAxisTitle(yRight2, "Speed"); setAxisTitle(xBottom, "Seconds Ago"); + setAxisMaxMinor(xBottom, 0); + setAxisMaxMinor(yLeft, 0); + setAxisMaxMinor(yLeft2, 0); + setAxisMaxMinor(yRight, 0); + setAxisMaxMinor(yRight2, 0); QPalette pal; setAxisScale(yLeft, 0, 500); // watts diff --git a/src/RealtimePlot.h b/src/RealtimePlot.h index cc4e986be..372c22d91 100644 --- a/src/RealtimePlot.h +++ b/src/RealtimePlot.h @@ -35,12 +35,13 @@ class Realtime30PwrData : public QwtData { int pwrCur_; int &pwrCur; + double pwr30; double pwrData_[150]; double (&pwrData)[150]; public: - Realtime30PwrData() : pwrCur(pwrCur_), pwrData(pwrData_) {} - Realtime30PwrData(Realtime30PwrData *other) : pwrCur(other->pwrCur_), pwrData(other->pwrData_) {} + Realtime30PwrData() : pwrCur(pwrCur_), pwrData(pwrData_) { init(); } + Realtime30PwrData(Realtime30PwrData *other) : pwrCur(other->pwrCur_), pwrData(other->pwrData_) { init(); } double x(size_t i) const ; double y(size_t i) const ; diff --git a/src/RealtimePlotWindow.cpp b/src/RealtimePlotWindow.cpp index 0576b50aa..642286a63 100644 --- a/src/RealtimePlotWindow.cpp +++ b/src/RealtimePlotWindow.cpp @@ -59,6 +59,7 @@ void RealtimePlotWindow::telemetryUpdate(RealtimeData rtData) { rtPlot->pwrData.addData(rtData.value(RealtimeData::Watts)); + rtPlot->pwr30Data.addData(rtData.value(RealtimeData::Watts)); rtPlot->cadData.addData(rtData.value(RealtimeData::Cadence)); rtPlot->spdData.addData(rtData.value(RealtimeData::Speed)); rtPlot->hrData.addData(rtData.value(RealtimeData::HeartRate)); diff --git a/src/TrainTool.cpp b/src/TrainTool.cpp index b6bbacfe8..e93754016 100644 --- a/src/TrainTool.cpp +++ b/src/TrainTool.cpp @@ -57,7 +57,7 @@ TrainTool::TrainTool(MainWindow *parent, const QDir &home) : GcWindow(parent), h mainLayout->setSpacing(0); setContentsMargins(0,0,0,0); - +#if 0 // not in this release .. or for a while TBH serverTree = new QTreeWidget; serverTree->setFrameStyle(QFrame::NoFrame); serverTree->setColumnCount(1); @@ -68,6 +68,7 @@ TrainTool::TrainTool(MainWindow *parent, const QDir &home) : GcWindow(parent), h allServers = new QTreeWidgetItem(serverTree, HEAD_TYPE); allServers->setText(0, tr("Race Servers")); serverTree->expandItem(allServers); +#endif deviceTree = new QTreeWidget; deviceTree->setFrameStyle(QFrame::NoFrame); @@ -98,24 +99,23 @@ TrainTool::TrainTool(MainWindow *parent, const QDir &home) : GcWindow(parent), h buttonPanel->setContentsMargins(0,0,0,0); QVBoxLayout *panel = new QVBoxLayout; panel->setSpacing(0); + panel->setContentsMargins(0,0,0,0); QHBoxLayout *buttons = new QHBoxLayout; buttons->setSpacing(0); + buttons->setContentsMargins(0,0,0,0); startButton = new QPushButton(tr("Start"), this); - startButton->setMaximumHeight(100); pauseButton = new QPushButton(tr("Pause"), this); - pauseButton->setMaximumHeight(100); stopButton = new QPushButton(tr("Stop"), this); - stopButton->setMaximumHeight(100); recordSelector = new QCheckBox(this); recordSelector->setText(tr("Save workout data")); recordSelector->setChecked(Qt::Checked); + recordSelector->hide(); // we don't let users change this for now buttons->addWidget(startButton); buttons->addWidget(pauseButton); buttons->addWidget(stopButton); panel->addLayout(buttons); - panel->addWidget(recordSelector); + //panel->addWidget(recordSelector); buttonPanel->setLayout(panel); - buttonPanel->setFixedHeight(90); mainLayout->addWidget(buttonPanel); trainSplitter = new QSplitter; @@ -128,11 +128,11 @@ TrainTool::TrainTool(MainWindow *parent, const QDir &home) : GcWindow(parent), h cl->addWidget(trainSplitter); trainSplitter->addWidget(deviceTree); - trainSplitter->addWidget(serverTree); + //trainSplitter->addWidget(serverTree); trainSplitter->addWidget(workoutTree); // handle config changes - connect(serverTree,SIGNAL(itemSelectionChanged()), this, SLOT(serverTreeWidgetSelectionChanged())); + //connect(serverTree,SIGNAL(itemSelectionChanged()), this, SLOT(serverTreeWidgetSelectionChanged())); connect(deviceTree,SIGNAL(itemSelectionChanged()), this, SLOT(deviceTreeWidgetSelectionChanged())); connect(workoutTree,SIGNAL(itemSelectionChanged()), this, SLOT(workoutTreeWidgetSelectionChanged())); connect(main, SIGNAL(configChanged()), this, SLOT(configChanged())); @@ -470,6 +470,10 @@ void TrainTool::Start() // when start button is pressed { if (status&RT_RUNNING) { newLap(); + + // tell the world + main->notifyNewLap(); + } else { // open the controller if it is selected @@ -477,6 +481,9 @@ void TrainTool::Start() // when start button is pressed if (deviceController == NULL) return; else deviceController->start(); // start device + // tell the world + main->notifyStart(); + // we're away! status |=RT_RUNNING; @@ -484,7 +491,7 @@ void TrainTool::Start() // when start button is pressed setStreamController(); if (streamController != NULL) status |= RT_STREAMING; - setStartText(tr("Lap/Interval")); + setStartText(tr("Lap")); load_period.restart(); session_time.start(); @@ -544,6 +551,7 @@ void TrainTool::Pause() // pause capture to recalibrate if ((status&RT_RUNNING) == 0) return; if (status&RT_PAUSED) { + session_time.start(); lap_time.start(); status &=~RT_PAUSED; @@ -555,7 +563,12 @@ void TrainTool::Pause() // pause capture to recalibrate if (status & RT_RECORDING) disk_timer->start(SAMPLERATE); load_period.restart(); if (status & RT_WORKOUT) load_timer->start(LOADRATE); + + // tell the world + main->notifyUnPause(); + } else { + session_elapsed_msec += session_time.elapsed(); lap_elapsed_msec += lap_time.elapsed(); deviceController->pause(); @@ -567,6 +580,9 @@ void TrainTool::Pause() // pause capture to recalibrate if (status & RT_RECORDING) disk_timer->stop(); if (status & RT_WORKOUT) load_timer->stop(); load_msecs += load_period.restart(); + + // tell the world + main->notifyPause(); } } @@ -617,9 +633,14 @@ void TrainTool::Stop(int deviceStatus) // when stop button is pressed if (status & RT_WORKOUT) { load_timer->stop(); load_msecs = 0; - main->notifySetNow(load_msecs); } + main->notifySetNow(load_msecs); + + + // tell the world + main->notifyStop(); + // Re-enable gui elements //recordSelector->setEnabled(true); @@ -661,6 +682,7 @@ void TrainTool::updateData(RealtimeData &rtData) void TrainTool::guiUpdate() // refreshes the telemetry { RealtimeData rtData; + rtData.setLap(displayLap + displayWorkoutLap); // user laps + predefined workout lap if (deviceController == NULL) return; @@ -694,6 +716,13 @@ void TrainTool::guiUpdate() // refreshes the telemetry // go update the displays... main->notifyTelemetryUpdate(rtData); // signal everyone to update telemetry + + // set now to current time when not using a workout + // but limit to almost every second (account for + // slight timing errors of 100ms or so) + if (!(status&RT_WORKOUT) && rtData.getMsecs()%1000 < 100) { + main->notifySetNow(rtData.getMsecs()); + } } } diff --git a/src/WorkoutPlotWindow.cpp b/src/WorkoutPlotWindow.cpp index 72dbdd5dd..9fb66ab01 100644 --- a/src/WorkoutPlotWindow.cpp +++ b/src/WorkoutPlotWindow.cpp @@ -25,6 +25,7 @@ WorkoutPlotWindow::WorkoutPlotWindow(MainWindow *mainWindow) : setContentsMargins(0,0,0,0); setInstanceName("RT Plot"); setControls(NULL); + setProperty("color", GColor(CRIDEPLOTBACKGROUND)); QVBoxLayout *layout = new QVBoxLayout(this); layout->setSpacing(0); @@ -34,12 +35,17 @@ WorkoutPlotWindow::WorkoutPlotWindow(MainWindow *mainWindow) : connect(mainWindow, SIGNAL(setNow(long)), this, SLOT(setNow(long))); connect(mainWindow, SIGNAL(ergFileSelected(ErgFile*)), this, SLOT(ergFileSelected(ErgFile*))); - + connect(mainWindow, SIGNAL(telemetryUpdate(RealtimeData)), ergPlot, SLOT(performancePlot(RealtimeData))); + connect(mainWindow, SIGNAL(start()), ergPlot, SLOT(start())); } void WorkoutPlotWindow::ergFileSelected(ErgFile *f) { + // rename window to workout name + if (f && f->Name != "") setProperty("subtitle", f->Name); + else setProperty("subtitle", ""); + ergPlot->setData(f); ergPlot->replot(); } diff --git a/src/WorkoutPlotWindow.h b/src/WorkoutPlotWindow.h index 9a7d9c5cc..9afa5ec86 100644 --- a/src/WorkoutPlotWindow.h +++ b/src/WorkoutPlotWindow.h @@ -30,6 +30,9 @@ #include "ErgFilePlot.h" #include "RealtimeData.h" // for realtimedata structure +#include "Settings.h" +#include "Colors.h" + class WorkoutPlotWindow : public GcWindow { Q_OBJECT diff --git a/src/test/workouts/15x30s@128%FTP.erg b/src/test/workouts/15x30s@128%FTP.erg new file mode 100644 index 000000000..2484c79af --- /dev/null +++ b/src/test/workouts/15x30s@128%FTP.erg @@ -0,0 +1,87 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 1x5x30s+1x10x30 second efforts at 128% of FTP. +FILE NAME = 260WFTPRider_15x30s@128%FTP.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 78 +1.0 78 +1.0 104 +2.0 104 +2.0 143 +10.0 143 +10.0 169 +40.5 169 +40.5 260 +42.5 260 +42.5 169 +44.5 169 +44.5 333 +45.0 333 +45.0 143 +45.5 143 +45.5 333 +46.0 333 +46.0 143 +46.5 143 +46.5 333 +47.0 333 +47.0 143 +47.5 143 +47.5 333 +48.0 333 +48.0 143 +48.5 143 +48.5 333 +49.0 333 +49.0 143 +54.0 143 +54.0 333 +54.5 333 +54.5 143 +55.0 143 +55.0 333 +55.5 333 +55.5 143 +56.0 143 +56.0 333 +56.5 333 +56.5 143 +57.0 143 +57.0 333 +57.5 333 +57.5 143 +58.0 143 +58.0 333 +58.5 333 +58.5 143 +59.0 143 +59.0 333 +59.5 333 +59.5 143 +60.0 143 +60.0 333 +60.5 333 +60.5 143 +61.0 143 +61.0 333 +61.5 333 +61.5 143 +62.0 143 +62.0 333 +62.5 333 +62.5 143 +63.0 143 +63.0 333 +63.5 333 +63.5 143 +64.0 143 +64.0 104 +65.0 104 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/1x10x30s@128%.erg b/src/test/workouts/1x10x30s@128%.erg new file mode 100644 index 000000000..1c6882f36 --- /dev/null +++ b/src/test/workouts/1x10x30s@128%.erg @@ -0,0 +1,67 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 1x10x30 second efforts at 128% of FTP. +FILE NAME = 260WFTPRider_1x10x30s@128%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 78 +1.0 78 +1.0 104 +2.0 104 +2.0 143 +10.0 143 +10.0 169 +50.0 169 +50.0 260 +52.0 260 +52.0 169 +54.0 169 +54.0 333 +54.5 333 +54.5 143 +55.0 143 +55.0 333 +55.5 333 +55.5 143 +56.0 143 +56.0 333 +56.5 333 +56.5 143 +57.0 143 +57.0 333 +57.5 333 +57.5 143 +58.0 143 +58.0 333 +58.5 333 +58.5 143 +59.0 143 +59.0 333 +59.5 333 +59.5 143 +60.0 143 +60.0 333 +60.5 333 +60.5 143 +61.0 143 +61.0 333 +61.5 333 +61.5 143 +62.0 143 +62.0 333 +62.5 333 +62.5 143 +63.0 143 +63.0 333 +63.5 333 +63.5 143 +64.0 143 +64.0 104 +65.0 104 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/1x50m@50-55%.erg b/src/test/workouts/1x50m@50-55%.erg new file mode 100644 index 000000000..2a9d9f74f --- /dev/null +++ b/src/test/workouts/1x50m@50-55%.erg @@ -0,0 +1,85 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 1x50 Minute effort at 50-55% of FTP - Variable Load +FILE NAME = 260WFTPRider_1x50m@50-55%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.55 131 +6.12 140 +6.68 138 +7.28 141 +7.81 133 +8.46 131 +8.99 136 +9.72 139 +10.49 138 +11.47 130 +12.07 140 +12.95 137 +13.91 140 +14.54 136 +15.16 130 +15.75 141 +16.65 134 +17.56 133 +18.23 133 +18.95 142 +19.75 136 +20.28 134 +21.15 133 +21.84 139 +22.8 142 +23.75 140 +24.31 135 +25.06 133 +25.66 142 +26.18 140 +26.81 130 +27.51 132 +28.08 141 +28.9 136 +29.59 139 +30.29 131 +30.87 141 +31.73 133 +32.61 134 +33.55 134 +34.55 135 +35.4 133 +35.99 142 +36.94 132 +37.5 135 +38.44 132 +39.17 138 +40.0 137 +40.63 133 +41.13 134 +42.06 130 +43.06 137 +44.03 141 +44.85 136 +45.74 138 +46.67 138 +47.64 136 +48.51 132 +49.02 134 +49.97 137 +50.87 141 +51.48 134 +52.22 131 +53.14 136 +53.8 131 +54.47 137 +55.0 133 +57.0 104 +57.0 104 +60.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/1x50m@55-60%.erg b/src/test/workouts/1x50m@55-60%.erg new file mode 100644 index 000000000..c8fd3ddcc --- /dev/null +++ b/src/test/workouts/1x50m@55-60%.erg @@ -0,0 +1,85 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 1x50 Minute effort at 55-60% - Variable Load +FILE NAME = 260WFTPRider_1x50m@55-60%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.55 144 +6.12 153 +6.68 151 +7.28 154 +7.81 146 +8.46 144 +8.99 149 +9.72 152 +10.49 151 +11.47 143 +12.07 153 +12.95 150 +13.91 153 +14.54 149 +15.16 143 +15.75 154 +16.65 147 +17.56 146 +18.23 146 +18.95 155 +19.75 149 +20.28 147 +21.15 146 +21.84 152 +22.8 155 +23.75 153 +24.31 148 +25.06 146 +25.66 155 +26.18 153 +26.81 143 +27.51 145 +28.08 154 +28.9 149 +29.59 152 +30.29 144 +30.87 154 +31.73 146 +32.61 147 +33.55 147 +34.55 148 +35.4 146 +35.99 155 +36.94 145 +37.5 148 +38.44 145 +39.17 151 +40.0 150 +40.63 146 +41.13 147 +42.06 143 +43.06 150 +44.03 154 +44.85 149 +45.74 151 +46.67 151 +47.64 149 +48.51 145 +49.02 147 +49.97 150 +50.87 154 +51.48 147 +52.22 144 +53.14 149 +53.8 144 +54.47 150 +55.0 146 +57.0 104 +57.0 104 +60.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/1x60m@56-75%.erg b/src/test/workouts/1x60m@56-75%.erg new file mode 100644 index 000000000..bf6cb40e6 --- /dev/null +++ b/src/test/workouts/1x60m@56-75%.erg @@ -0,0 +1,99 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 1x60 Minute effort at 56-75% of FTP - Variable Load +FILE NAME = 260WFTPRider_1x60m@56-75%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.55 153 +6.12 185 +6.68 178 +7.28 190 +7.81 159 +8.46 152 +8.99 169 +9.72 180 +10.49 179 +11.47 149 +12.07 184 +12.95 175 +13.91 186 +14.54 170 +15.16 149 +15.75 190 +16.65 161 +17.56 158 +18.23 160 +18.95 193 +19.75 171 +20.28 164 +21.15 160 +21.84 183 +22.8 193 +23.75 186 +24.31 167 +25.06 160 +25.66 191 +26.18 186 +26.81 146 +27.51 154 +28.08 187 +28.9 170 +29.59 182 +30.29 151 +30.87 189 +31.73 157 +32.61 162 +33.55 162 +34.55 164 +35.4 159 +35.99 192 +36.94 155 +37.5 167 +38.44 155 +39.17 179 +40.0 175 +40.63 159 +41.13 163 +42.06 149 +43.06 174 +44.03 190 +44.85 171 +45.74 177 +46.67 179 +47.64 169 +48.51 157 +49.02 163 +49.97 174 +50.87 188 +51.48 163 +52.22 151 +53.14 169 +53.8 153 +54.47 175 +55.21 160 +55.77 180 +56.3 151 +56.92 146 +57.65 157 +58.27 152 +59.22 182 +59.95 167 +60.6 179 +61.3 182 +62.0 182 +62.73 150 +63.71 163 +64.65 149 +65.0 193 +67.0 104 +67.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/1x60m@76-90%.erg b/src/test/workouts/1x60m@76-90%.erg new file mode 100644 index 000000000..e4626048f --- /dev/null +++ b/src/test/workouts/1x60m@76-90%.erg @@ -0,0 +1,105 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 1x60 Minute effort at 76-90% of FTP. +FILE NAME = 260WFTPRider_1x60m@76-90%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.0 156 +10.0 156 +10.0 208 +12.5 208 +12.5 143 +15.0 143 +15.69 219 +16.68 228 +17.39 216 +18.04 220 +18.94 212 +19.49 206 +20.09 227 +20.62 231 +21.49 211 +22.0 211 +22.86 199 +23.67 198 +24.49 233 +25.43 204 +26.25 221 +26.81 202 +27.33 229 +27.96 213 +28.55 218 +29.16 222 +29.85 211 +30.67 206 +31.43 223 +32.32 219 +32.98 199 +33.9 217 +34.6 212 +35.25 230 +35.87 202 +36.69 217 +37.47 230 +38.16 206 +39.08 199 +39.68 210 +40.29 233 +40.97 207 +41.75 198 +42.5 212 +43.34 209 +44.13 207 +44.69 210 +45.69 230 +46.55 201 +47.12 217 +48.11 202 +49.1 213 +49.67 211 +50.27 199 +51.22 219 +51.81 211 +52.43 224 +53.24 224 +53.95 226 +54.53 214 +55.21 223 +55.89 205 +56.52 226 +57.47 207 +58.14 204 +58.67 203 +59.67 217 +60.32 220 +60.85 203 +61.57 224 +62.28 201 +63.09 207 +64.03 231 +64.99 209 +65.55 206 +66.05 206 +66.64 228 +67.16 225 +68.12 232 +69.11 211 +70.06 223 +71.05 199 +71.76 231 +72.28 230 +73.25 205 +73.77 222 +74.53 200 +75.0 227 +75.0 104 +80.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/1x60m@88-94%.erg b/src/test/workouts/1x60m@88-94%.erg new file mode 100644 index 000000000..cdde5c598 --- /dev/null +++ b/src/test/workouts/1x60m@88-94%.erg @@ -0,0 +1,105 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 1x60 Minute effort at 88-94% of FTP. +FILE NAME = 260WFTPRider_1x60m@88-94%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.0 156 +10.0 156 +10.0 208 +12.5 208 +12.5 143 +15.0 143 +15.69 237 +16.68 241 +17.39 236 +18.04 238 +18.94 234 +19.49 232 +20.09 241 +20.62 243 +21.49 234 +22.0 234 +22.86 229 +23.67 229 +24.49 243 +25.43 231 +26.25 238 +26.81 230 +27.33 242 +27.96 235 +28.55 237 +29.16 239 +29.85 234 +30.67 232 +31.43 239 +32.32 237 +32.98 229 +33.9 236 +34.6 234 +35.25 242 +35.87 230 +36.69 237 +37.47 242 +38.16 232 +39.08 229 +39.68 234 +40.29 243 +40.97 233 +41.75 229 +42.5 235 +43.34 233 +44.13 232 +44.69 234 +45.69 242 +46.55 230 +47.12 237 +48.11 230 +49.1 235 +49.67 234 +50.27 229 +51.22 238 +51.81 234 +52.43 240 +53.24 239 +53.95 240 +54.53 236 +55.21 239 +55.89 232 +56.52 240 +57.47 232 +58.14 231 +58.67 231 +59.67 237 +60.32 238 +60.85 231 +61.57 240 +62.28 230 +63.09 233 +64.03 242 +64.99 233 +65.55 232 +66.05 232 +66.64 241 +67.16 240 +68.12 243 +69.11 234 +70.06 239 +71.05 229 +71.76 242 +72.28 242 +73.25 232 +73.77 239 +74.53 229 +75.0 241 +75.0 104 +80.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/1x60m@91-105%.erg b/src/test/workouts/1x60m@91-105%.erg new file mode 100644 index 000000000..e6992be54 --- /dev/null +++ b/src/test/workouts/1x60m@91-105%.erg @@ -0,0 +1,105 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 1x60 Minute effort at 91-105% of FTP. +FILE NAME = 260WFTPRider_1x60m@91-105%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.0 156 +10.0 156 +10.0 234 +12.5 234 +12.5 143 +15.0 143 +15.69 258 +16.68 267 +17.39 255 +18.04 259 +18.94 251 +19.49 245 +20.09 266 +20.62 270 +21.49 250 +22.0 250 +22.86 238 +23.67 237 +24.49 272 +25.43 243 +26.25 260 +26.81 241 +27.33 268 +27.96 252 +28.55 257 +29.16 261 +29.85 250 +30.67 245 +31.43 262 +32.32 258 +32.98 238 +33.9 256 +34.6 251 +35.25 269 +35.87 241 +36.69 256 +37.47 269 +38.16 245 +39.08 238 +39.68 249 +40.29 272 +40.97 246 +41.75 237 +42.5 251 +43.34 248 +44.13 246 +44.69 249 +45.69 269 +46.55 240 +47.12 256 +48.11 241 +49.1 252 +49.67 250 +50.27 238 +51.22 258 +51.81 250 +52.43 263 +53.24 263 +53.95 265 +54.53 253 +55.21 262 +55.89 244 +56.52 265 +57.47 246 +58.14 243 +58.67 242 +59.67 256 +60.32 259 +60.85 242 +61.57 263 +62.28 240 +63.09 246 +64.03 270 +64.99 248 +65.55 245 +66.05 245 +66.64 267 +67.16 264 +68.12 271 +69.11 250 +70.06 262 +71.05 238 +71.76 270 +72.28 269 +73.25 244 +73.77 261 +74.53 239 +75.0 266 +75.0 104 +80.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/20x15s@150%.erg b/src/test/workouts/20x15s@150%.erg new file mode 100644 index 000000000..25bdece8a --- /dev/null +++ b/src/test/workouts/20x15s@150%.erg @@ -0,0 +1,107 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = MicroIntervals 1x20x15 second efforts at 150% of FTP. +FILE NAME = 260WFTPRider_20x15s@150%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 78 +1.0 78 +1.0 104 +2.0 104 +2.0 143 +10.0 143 +10.0 169 +47.0 169 +47.0 260 +49.0 260 +49.0 169 +54.0 169 +54.0 390 +54.25 390 +54.25 143 +54.5 143 +54.5 390 +54.75 390 +54.75 143 +55.0 143 +55.0 390 +55.25 390 +55.25 143 +55.5 143 +55.5 390 +55.75 390 +55.75 143 +56.0 143 +56.0 390 +56.25 390 +56.25 143 +56.5 143 +56.5 390 +56.75 390 +56.75 143 +57.0 143 +57.0 390 +57.25 390 +57.25 143 +57.5 143 +57.5 390 +57.75 390 +57.75 143 +58.0 143 +58.0 390 +58.25 390 +58.25 143 +58.5 143 +58.5 390 +58.75 390 +58.75 143 +59.0 143 +59.0 390 +59.25 390 +59.25 143 +59.5 143 +59.5 390 +59.75 390 +59.75 143 +60.0 143 +60.0 390 +60.25 390 +60.25 143 +60.5 143 +60.5 390 +60.75 390 +60.75 143 +61.0 143 +61.0 390 +61.25 390 +61.25 143 +61.5 143 +61.5 390 +61.75 390 +61.75 143 +62.0 143 +62.0 390 +62.25 390 +62.25 143 +62.5 143 +62.5 390 +62.75 390 +62.75 143 +63.0 143 +63.0 390 +63.25 390 +63.25 143 +63.5 143 +63.5 390 +63.75 390 +63.75 143 +64.0 143 +64.0 104 +65.0 104 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/20x30s@128%FTP.erg b/src/test/workouts/20x30s@128%FTP.erg new file mode 100644 index 000000000..efd44739d --- /dev/null +++ b/src/test/workouts/20x30s@128%FTP.erg @@ -0,0 +1,107 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x10x30 second efforts at 128% of FTP. +FILE NAME = 260WFTPRider_20x30s@128%FTP.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 78 +1.0 78 +1.0 104 +2.0 104 +2.0 143 +10.0 143 +10.0 169 +35.5 169 +35.5 260 +37.5 260 +37.5 169 +39.5 169 +39.5 333 +40.0 333 +40.0 143 +40.5 143 +40.5 333 +41.0 333 +41.0 143 +41.5 143 +41.5 333 +42.0 333 +42.0 143 +42.5 143 +42.5 333 +43.0 333 +43.0 143 +43.5 143 +43.5 333 +44.0 333 +44.0 143 +44.5 143 +44.5 333 +45.0 333 +45.0 143 +45.5 143 +45.5 333 +46.0 333 +46.0 143 +46.5 143 +46.5 333 +47.0 333 +47.0 143 +47.5 143 +47.5 333 +48.0 333 +48.0 143 +48.5 143 +48.5 333 +49.0 333 +49.0 143 +54.0 143 +54.0 333 +54.5 333 +54.5 143 +55.0 143 +55.0 333 +55.5 333 +55.5 143 +56.0 143 +56.0 333 +56.5 333 +56.5 143 +57.0 143 +57.0 333 +57.5 333 +57.5 143 +58.0 143 +58.0 333 +58.5 333 +58.5 143 +59.0 143 +59.0 333 +59.5 333 +59.5 143 +60.0 143 +60.0 333 +60.5 333 +60.5 143 +61.0 143 +61.0 333 +61.5 333 +61.5 143 +62.0 143 +62.0 333 +62.5 333 +62.5 143 +63.0 143 +63.0 333 +63.5 333 +63.5 143 +64.0 143 +64.0 104 +65.0 104 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/2x20m@76-90%.erg b/src/test/workouts/2x20m@76-90%.erg new file mode 100644 index 000000000..62a0b42e2 --- /dev/null +++ b/src/test/workouts/2x20m@76-90%.erg @@ -0,0 +1,81 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x20 Minute intervals at 76-90% of FTP L3 +FILE NAME = 260WFTPRider_2x20m@76-90%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.8 203 +21.61 228 +22.36 198 +23.18 202 +24.16 201 +24.81 220 +25.35 230 +26.17 220 +26.84 228 +27.82 216 +28.5 226 +29.11 223 +29.66 227 +30.56 212 +31.08 204 +31.78 223 +32.72 220 +33.4 201 +34.04 232 +35.01 233 +35.53 221 +36.1 222 +36.76 199 +37.58 215 +38.21 213 +39.2 200 +40.0 225 +40.0 143 +42.5 143 +42.5 143 +45.0 143 +45.56 214 +46.11 203 +46.8 233 +47.76 224 +48.58 212 +49.23 229 +50.07 205 +50.8 204 +51.63 222 +52.56 219 +53.53 223 +54.35 230 +54.89 206 +55.6 225 +56.25 216 +56.79 223 +57.77 204 +58.32 220 +59.06 198 +60.03 213 +60.66 212 +61.57 227 +62.15 219 +62.96 218 +63.49 230 +64.48 225 +65.0 203 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/2x20m@80%Iso.erg b/src/test/workouts/2x20m@80%Iso.erg new file mode 100644 index 000000000..bc6dcfbb2 --- /dev/null +++ b/src/test/workouts/2x20m@80%Iso.erg @@ -0,0 +1,31 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x20 Minute isopower intervals at 80% of FTP. +FILE NAME = 260WFTPRider_2x20m@80%Iso.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.0 208 +40.0 208 +40.0 156 +45.0 156 +45.0 208 +65.0 208 +65.0 156 +65.0 156 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/2x20m@85%Iso.erg b/src/test/workouts/2x20m@85%Iso.erg new file mode 100644 index 000000000..5bdf9c43a --- /dev/null +++ b/src/test/workouts/2x20m@85%Iso.erg @@ -0,0 +1,31 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x20 Minute isopower intervals at 85% of FTP. +FILE NAME = 260WFTPRider_2x20m@85%Iso.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.0 221 +40.0 221 +40.0 156 +45.0 156 +45.0 221 +65.0 221 +65.0 156 +65.0 156 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/2x20m@88-94%.erg b/src/test/workouts/2x20m@88-94%.erg new file mode 100644 index 000000000..2985e8e2b --- /dev/null +++ b/src/test/workouts/2x20m@88-94%.erg @@ -0,0 +1,81 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x20 Minute intervals at 88-94% of FTP. +FILE NAME = 260WFTPRider_2x20m@88-94%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.8 231 +21.61 241 +22.36 229 +23.18 230 +24.16 230 +24.81 238 +25.35 242 +26.17 238 +26.84 241 +27.82 236 +28.5 240 +29.11 239 +29.66 241 +30.56 235 +31.08 231 +31.78 239 +32.72 238 +33.4 230 +34.04 243 +35.01 243 +35.53 238 +36.1 239 +36.76 229 +37.58 236 +38.21 235 +39.2 230 +40.0 240 +40.0 143 +42.5 143 +42.5 143 +45.0 143 +45.56 236 +46.11 231 +46.8 243 +47.76 239 +48.58 235 +49.23 241 +50.07 231 +50.8 231 +51.63 239 +52.56 237 +53.53 239 +54.35 242 +54.89 232 +55.6 240 +56.25 236 +56.79 239 +57.77 231 +58.32 238 +59.06 229 +60.03 235 +60.66 235 +61.57 241 +62.15 238 +62.96 237 +63.49 242 +64.48 240 +65.0 231 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/2x20m@90%Iso.erg b/src/test/workouts/2x20m@90%Iso.erg new file mode 100644 index 000000000..ef1dae8ec --- /dev/null +++ b/src/test/workouts/2x20m@90%Iso.erg @@ -0,0 +1,31 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x20 Minute isopower intervals at 90% of FTP. +FILE NAME = 260WFTPRider_2x20m@90%Iso.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.0 234 +40.0 234 +40.0 156 +45.0 156 +45.0 234 +65.0 234 +65.0 156 +65.0 156 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/2x20m@91-105%.erg b/src/test/workouts/2x20m@91-105%.erg new file mode 100644 index 000000000..2c6da7435 --- /dev/null +++ b/src/test/workouts/2x20m@91-105%.erg @@ -0,0 +1,81 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x20 Minute intervals at 91-105% of FTP. +FILE NAME = 260WFTPRider_2x20m@91-105%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.8 242 +21.61 267 +22.36 237 +23.18 241 +24.16 240 +24.81 259 +25.35 269 +26.17 259 +26.84 267 +27.82 255 +28.5 265 +29.11 262 +29.66 266 +30.56 251 +31.08 243 +31.78 262 +32.72 259 +33.4 240 +34.04 271 +35.01 272 +35.53 260 +36.1 261 +36.76 238 +37.58 254 +38.21 252 +39.2 239 +40.0 264 +40.0 143 +42.5 143 +42.5 143 +45.0 143 +45.56 253 +46.11 242 +46.8 272 +47.76 263 +48.58 251 +49.23 268 +50.07 244 +50.8 243 +51.63 261 +52.56 258 +53.53 262 +54.35 269 +54.89 245 +55.6 264 +56.25 255 +56.79 262 +57.77 243 +58.32 259 +59.06 237 +60.03 252 +60.66 251 +61.57 266 +62.15 258 +62.96 257 +63.49 269 +64.48 264 +65.0 242 +65.0 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/2x25m@76-90%.erg b/src/test/workouts/2x25m@76-90%.erg new file mode 100644 index 000000000..8023cb364 --- /dev/null +++ b/src/test/workouts/2x25m@76-90%.erg @@ -0,0 +1,96 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x25 Minute intervals at 76-90% of FTP L3 +FILE NAME = 260WFTPRider_2x25m@76-90%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +6.5 130 +6.5 156 +11.0 156 +11.0 208 +13.0 208 +13.0 143 +15.0 143 +15.69 219 +16.68 228 +17.39 216 +18.04 220 +18.94 212 +19.49 206 +20.09 227 +20.62 231 +21.49 211 +22.0 211 +22.86 199 +23.67 198 +24.49 233 +25.43 204 +26.25 221 +26.81 202 +27.33 229 +27.96 213 +28.55 218 +29.16 222 +29.85 211 +30.67 206 +31.43 223 +32.32 219 +32.98 199 +33.9 217 +34.6 212 +35.25 230 +35.87 202 +36.69 217 +37.47 230 +38.16 206 +39.08 199 +39.68 210 +40.0 233 +40.0 143 +42.5 143 +42.5 143 +45.0 143 +45.56 214 +46.11 203 +46.8 233 +47.76 224 +48.58 212 +49.23 229 +50.07 205 +50.8 204 +51.63 222 +52.56 219 +53.53 223 +54.35 230 +54.89 206 +55.6 225 +56.25 216 +56.79 223 +57.77 204 +58.32 220 +59.06 198 +60.03 213 +60.66 212 +61.57 227 +62.15 219 +62.96 218 +63.49 230 +64.48 225 +65.28 203 +65.81 219 +66.46 215 +67.38 204 +68.38 212 +69.08 222 +69.68 199 +70.0 222 +70.0 104 +75.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/30MinsOfPowerV1.erg b/src/test/workouts/30MinsOfPowerV1.erg new file mode 100644 index 000000000..10858f812 --- /dev/null +++ b/src/test/workouts/30MinsOfPowerV1.erg @@ -0,0 +1,220 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 30 Mins of Power V1 +FILE NAME = 260WFTPRider_30MinsOfPowerV1.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +6.0 130 +6.0 156 +10.0 156 +10.0 208 +12.5 208 +12.5 143 +15.0 143 +15.25 228 +15.5 231 +15.75 227 +16.0 229 +16.25 226 +16.5 223 +16.75 231 +17.0 233 +17.25 225 +17.5 225 +17.75 221 +18.0 221 +18.06 260 +18.12 280 +18.18 289 +18.24 294 +18.3 296 +18.36 297 +18.42 299 +18.42 221 +18.42 221 +18.67 226 +18.92 224 +19.17 223 +19.42 226 +19.67 225 +19.92 232 +20.17 233 +20.42 221 +20.67 224 +20.92 228 +21.17 230 +21.42 222 +21.48 261 +21.54 280 +21.6 290 +21.65 294 +21.71 296 +21.77 297 +21.83 299 +21.83 221 +21.83 221 +22.08 226 +22.33 229 +22.58 226 +22.83 224 +23.08 226 +23.33 233 +23.58 227 +23.83 227 +24.08 230 +24.33 221 +24.58 229 +24.83 229 +24.89 264 +24.95 282 +25.01 290 +25.07 294 +25.13 297 +25.19 298 +25.25 299 +25.25 221 +25.25 221 +25.5 233 +25.75 228 +26.0 223 +26.25 229 +26.5 221 +26.75 228 +27.0 228 +27.25 227 +27.5 230 +27.75 221 +28.0 221 +28.25 229 +28.31 264 +28.37 282 +28.43 290 +28.49 294 +28.55 297 +28.61 298 +28.67 299 +28.67 221 +28.67 221 +28.92 227 +29.17 227 +29.42 233 +29.67 221 +29.92 229 +30.17 222 +30.42 229 +30.67 227 +30.92 230 +31.17 233 +31.42 226 +31.67 229 +31.73 264 +31.79 282 +31.85 290 +31.9 294 +31.96 297 +32.02 298 +32.08 299 +32.08 221 +32.08 221 +32.33 227 +32.58 229 +32.83 227 +33.08 222 +33.33 224 +33.58 231 +33.83 221 +34.08 227 +34.33 233 +34.58 229 +34.83 230 +35.08 223 +35.14 262 +35.2 280 +35.26 290 +35.32 294 +35.38 296 +35.44 297 +35.5 299 +35.5 221 +35.5 221 +35.75 225 +36.0 232 +36.25 221 +36.5 223 +36.75 223 +37.0 226 +37.25 230 +37.5 224 +37.75 227 +38.0 227 +38.25 229 +38.5 233 +38.56 266 +38.62 283 +38.68 291 +38.74 295 +38.8 297 +38.86 298 +38.92 299 +38.92 221 +38.92 221 +39.17 228 +39.42 223 +39.67 221 +39.92 226 +40.17 230 +40.42 227 +40.67 223 +40.92 228 +41.17 232 +41.42 222 +41.67 228 +41.92 227 +41.98 264 +42.04 281 +42.1 290 +42.15 294 +42.21 296 +42.27 298 +42.33 299 +42.33 221 +42.33 221 +42.58 232 +42.83 230 +43.08 231 +43.33 227 +43.58 231 +43.83 221 +44.08 231 +44.33 224 +44.58 227 +44.83 227 +45.08 222 +45.33 233 +45.39 266 +45.45 283 +45.51 291 +45.57 295 +45.63 297 +45.69 298 +45.75 299 +45.75 221 +45.75 221 +46.0 222 +46.25 222 +46.5 231 +46.75 231 +47.0 225 +47.25 222 +47.5 224 +47.75 227 +49.67 104 +52.67 104 +[END COURSE DATA] diff --git a/src/test/workouts/3x20m@76-90%.erg b/src/test/workouts/3x20m@76-90%.erg new file mode 100644 index 000000000..217e52b6f --- /dev/null +++ b/src/test/workouts/3x20m@76-90%.erg @@ -0,0 +1,108 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 2x20 Minute intervals at 76-90% of FTP L3 +FILE NAME = 260WFTPRider_3x20m@76-90%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.8 203 +21.61 228 +22.36 198 +23.18 202 +24.16 201 +24.81 220 +25.35 230 +26.17 220 +26.84 228 +27.82 216 +28.5 226 +29.11 223 +29.66 227 +30.56 212 +31.08 204 +31.78 223 +32.72 220 +33.4 201 +34.04 232 +35.01 233 +35.53 221 +36.1 222 +36.76 199 +37.58 215 +38.21 213 +39.2 200 +40.0 225 +40.0 143 +42.5 143 +42.5 143 +42.5 143 +43.3 219 +44.25 201 +45.0 224 +45.71 201 +46.69 198 +47.57 228 +48.42 206 +48.93 209 +49.78 205 +50.55 227 +51.15 199 +51.84 217 +52.66 202 +53.65 214 +54.21 200 +54.75 217 +55.71 231 +56.25 199 +56.87 226 +57.53 205 +58.24 214 +59.16 202 +59.76 218 +60.47 232 +61.13 225 +61.94 205 +62.5 207 +62.5 143 +65.0 143 +65.94 198 +66.45 228 +67.41 213 +68.09 202 +68.75 222 +69.52 203 +70.49 198 +71.13 229 +72.12 218 +72.97 215 +73.9 198 +74.63 203 +75.24 203 +76.1 226 +76.77 232 +77.75 207 +78.57 198 +79.17 227 +79.96 225 +80.69 219 +81.52 216 +82.29 221 +83.19 208 +84.1 200 +85.0 205 +85.0 104 +90.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/3x20m@80%Iso.erg b/src/test/workouts/3x20m@80%Iso.erg new file mode 100644 index 000000000..3550a8160 --- /dev/null +++ b/src/test/workouts/3x20m@80%Iso.erg @@ -0,0 +1,35 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 3x20 Minute isopower intervals at 80% of FTP. +FILE NAME = 260WFTPRider_3x20m@80%Iso.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.0 208 +40.0 208 +40.0 156 +42.5 156 +42.5 208 +62.5 208 +62.5 156 +65.0 156 +65.0 208 +85.0 208 +85.0 156 +85.0 156 +85.0 104 +90.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/45MinsOfPowerV1.erg b/src/test/workouts/45MinsOfPowerV1.erg new file mode 100644 index 000000000..5e3fca94c --- /dev/null +++ b/src/test/workouts/45MinsOfPowerV1.erg @@ -0,0 +1,304 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 45 Mins of Power V1 +FILE NAME = 260WFTPRider_45MinsOfPowerV1.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +6.0 130 +6.0 156 +10.0 156 +10.0 208 +12.5 208 +12.5 143 +15.0 143 +15.25 228 +15.5 231 +15.75 227 +16.0 229 +16.25 226 +16.5 223 +16.75 231 +17.0 233 +17.25 225 +17.5 225 +17.75 221 +18.0 221 +18.06 260 +18.12 280 +18.18 289 +18.24 294 +18.3 296 +18.36 297 +18.42 299 +18.42 221 +18.42 221 +18.67 226 +18.92 224 +19.17 223 +19.42 226 +19.67 225 +19.92 232 +20.17 233 +20.42 221 +20.67 224 +20.92 228 +21.17 230 +21.42 222 +21.48 261 +21.54 280 +21.6 290 +21.65 294 +21.71 296 +21.77 297 +21.83 299 +21.83 221 +21.83 221 +22.08 226 +22.33 229 +22.58 226 +22.83 224 +23.08 226 +23.33 233 +23.58 227 +23.83 227 +24.08 230 +24.33 221 +24.58 229 +24.83 229 +24.89 264 +24.95 282 +25.01 290 +25.07 294 +25.13 297 +25.19 298 +25.25 299 +25.25 221 +25.25 221 +25.5 233 +25.75 228 +26.0 223 +26.25 229 +26.5 221 +26.75 228 +27.0 228 +27.25 227 +27.5 230 +27.75 221 +28.0 221 +28.25 229 +28.31 264 +28.37 282 +28.43 290 +28.49 294 +28.55 297 +28.61 298 +28.67 299 +28.67 221 +28.67 221 +28.92 227 +29.17 227 +29.42 233 +29.67 221 +29.92 229 +30.17 222 +30.42 229 +30.67 227 +30.92 230 +31.17 233 +31.42 226 +31.67 229 +31.73 264 +31.79 282 +31.85 290 +31.9 294 +31.96 297 +32.02 298 +32.08 299 +32.08 221 +32.08 221 +32.33 227 +32.58 229 +32.83 227 +33.08 222 +33.33 224 +33.58 231 +33.83 221 +34.08 227 +34.33 233 +34.58 229 +34.83 230 +35.08 223 +35.14 262 +35.2 280 +35.26 290 +35.32 294 +35.38 296 +35.44 297 +35.5 299 +35.5 221 +35.5 221 +35.75 225 +36.0 232 +36.25 221 +36.5 223 +36.75 223 +37.0 226 +37.25 230 +37.5 224 +37.75 227 +38.0 227 +38.25 229 +38.5 233 +38.56 266 +38.62 283 +38.68 291 +38.74 295 +38.8 297 +38.86 298 +38.92 299 +38.92 221 +38.92 221 +39.17 228 +39.42 223 +39.67 221 +39.92 226 +40.17 230 +40.42 227 +40.67 223 +40.92 228 +41.17 232 +41.42 222 +41.67 228 +41.92 227 +41.98 264 +42.04 281 +42.1 290 +42.15 294 +42.21 296 +42.27 298 +42.33 299 +42.33 221 +42.33 221 +42.58 232 +42.83 230 +43.08 231 +43.33 227 +43.58 231 +43.83 221 +44.08 231 +44.33 224 +44.58 227 +44.83 227 +45.08 222 +45.33 233 +45.39 266 +45.45 283 +45.51 291 +45.57 295 +45.63 297 +45.69 298 +45.75 299 +45.75 221 +45.75 221 +46.0 222 +46.25 222 +46.5 231 +46.75 231 +47.0 225 +47.25 222 +47.5 224 +47.75 227 +48.0 232 +48.25 221 +48.5 233 +48.75 227 +48.81 264 +48.87 281 +48.93 290 +48.99 294 +49.05 296 +49.11 298 +49.17 299 +49.17 221 +49.17 221 +49.42 232 +49.67 233 +49.92 224 +50.17 229 +50.42 225 +50.67 229 +50.92 223 +51.17 225 +51.42 230 +51.67 222 +51.92 226 +52.17 228 +52.23 264 +52.29 282 +52.35 290 +52.4 294 +52.46 297 +52.52 298 +52.58 299 +52.58 221 +52.58 221 +52.83 229 +53.08 221 +53.33 228 +53.58 223 +53.83 233 +54.08 229 +54.33 224 +54.58 227 +54.83 232 +55.08 221 +55.33 226 +55.58 227 +55.64 264 +55.7 281 +55.76 290 +55.82 294 +55.88 296 +55.94 298 +56.0 299 +56.0 221 +56.0 221 +56.25 226 +56.5 232 +56.75 221 +57.0 221 +57.25 233 +57.5 224 +57.75 224 +58.0 224 +58.25 230 +58.5 222 +58.75 231 +59.0 228 +59.06 264 +59.12 282 +59.18 290 +59.24 294 +59.3 297 +59.36 298 +59.42 299 +59.42 221 +59.42 221 +59.67 223 +59.92 232 +60.17 225 +60.42 228 +60.67 228 +60.92 224 +61.17 225 +61.42 227 +63.33 104 +66.33 104 +[END COURSE DATA] diff --git a/src/test/workouts/4x5m@106-120%.erg b/src/test/workouts/4x5m@106-120%.erg new file mode 100644 index 000000000..50667b647 --- /dev/null +++ b/src/test/workouts/4x5m@106-120%.erg @@ -0,0 +1,84 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 4x5 Minute intervals at 106-120% of FTP with variable load. +FILE NAME = 260WFTPRider_4x5m@106-120%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.4 281 +20.81 306 +21.18 276 +21.59 280 +22.08 279 +22.4 298 +22.67 308 +23.09 298 +23.42 306 +23.91 294 +24.25 304 +24.56 301 +24.83 305 +25.0 290 +25.0 156 +30.0 156 +30.41 279 +30.84 306 +31.24 283 +31.62 284 +31.93 287 +32.33 311 +32.63 277 +33.05 290 +33.46 310 +33.84 279 +34.29 277 +34.75 296 +35.0 293 +35.0 156 +40.0 156 +40.46 299 +40.81 306 +41.23 301 +41.69 301 +42.04 276 +42.49 289 +42.76 280 +43.07 278 +43.38 291 +43.75 284 +44.11 304 +44.47 285 +44.89 286 +45.0 288 +45.0 156 +50.0 156 +50.28 307 +50.7 280 +51.07 295 +51.46 276 +51.78 307 +52.21 286 +52.56 309 +52.93 283 +53.21 302 +53.59 285 +54.07 300 +54.32 309 +54.69 290 +55.0 292 +55.0 104 +60.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/4x5m@110%Iso.erg b/src/test/workouts/4x5m@110%Iso.erg new file mode 100644 index 000000000..14bf5b279 --- /dev/null +++ b/src/test/workouts/4x5m@110%Iso.erg @@ -0,0 +1,39 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 4x5 Minute intervals at 110% of FTP with isopower load. +FILE NAME = 260WFTPRider_4x5m@110%Iso.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.0 286 +25.0 286 +25.0 156 +30.0 156 +30.0 286 +35.0 286 +35.0 156 +40.0 156 +40.0 286 +45.0 286 +45.0 156 +50.0 156 +50.0 286 +55.0 286 +55.0 156 +60.0 156 +60.0 104 +65.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/6x3m@106-120%.erg b/src/test/workouts/6x3m@106-120%.erg new file mode 100644 index 000000000..4711d6d14 --- /dev/null +++ b/src/test/workouts/6x3m@106-120%.erg @@ -0,0 +1,125 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 6x3 Minute intervals at 106-120% of FTP with variable load. +FILE NAME = 260WFTPRider_6x3m@106-120%.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.22 281 +20.44 306 +20.64 276 +20.86 280 +21.11 279 +21.3 298 +21.47 308 +21.7 298 +21.89 306 +22.14 294 +22.33 304 +22.52 301 +22.69 305 +22.93 290 +23.0 282 +23.0 156 +26.0 156 +26.19 283 +26.43 288 +26.6 277 +26.8 279 +27.02 287 +27.27 295 +27.47 293 +27.7 304 +27.91 305 +28.11 281 +28.32 277 +28.51 309 +28.68 280 +28.86 281 +29.0 282 +29.0 156 +32.0 156 +32.21 304 +32.41 288 +32.59 295 +32.83 296 +33.06 277 +33.24 310 +33.43 296 +33.63 292 +33.88 286 +34.08 286 +34.26 304 +34.5 298 +34.71 309 +34.89 289 +35.0 301 +35.0 156 +38.0 156 +38.2 305 +38.41 297 +38.65 295 +38.88 277 +39.1 299 +39.27 290 +39.43 288 +39.63 277 +39.8 303 +39.98 298 +40.21 291 +40.45 302 +40.66 279 +40.85 302 +41.0 301 +41.0 156 +44.0 156 +44.19 306 +44.4 307 +44.63 295 +44.85 295 +45.05 285 +45.29 306 +45.52 281 +45.72 298 +45.9 285 +46.13 310 +46.32 277 +46.57 306 +46.78 284 +46.99 279 +47.0 301 +47.0 156 +50.0 156 +50.18 307 +50.4 280 +50.61 295 +50.82 276 +51.01 307 +51.24 286 +51.44 309 +51.64 283 +51.82 302 +52.03 285 +52.27 300 +52.44 309 +52.65 290 +52.88 292 +53.0 302 +53.0 156 +55.0 156 +55.0 104 +60.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/6x3m@110%Iso.erg b/src/test/workouts/6x3m@110%Iso.erg new file mode 100644 index 000000000..4b115b74e --- /dev/null +++ b/src/test/workouts/6x3m@110%Iso.erg @@ -0,0 +1,47 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 6x3 Minute intervals at 110% of FTP - Isopower +FILE NAME = 260WFTPRider_6x3m@110%Iso.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +7.0 130 +7.0 156 +15.0 156 +15.0 208 +17.5 208 +17.5 143 +20.0 143 +20.0 286 +23.0 286 +23.0 156 +26.0 156 +26.0 286 +29.0 286 +29.0 156 +32.0 156 +32.0 286 +35.0 286 +35.0 156 +38.0 156 +38.0 286 +41.0 286 +41.0 156 +44.0 156 +44.0 286 +47.0 286 +47.0 156 +50.0 156 +50.0 286 +53.0 286 +53.0 156 +55.0 156 +55.0 104 +60.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/Christmas.crs b/src/test/workouts/Christmas.crs new file mode 100644 index 000000000..c420eed5d --- /dev/null +++ b/src/test/workouts/Christmas.crs @@ -0,0 +1,88 @@ +[COURSE HEADER] +VERSION = 2 +UNITS = METRIC +DESCRIPTION = golden cheetah +FILE NAME = /home/markl/.goldencheetah/Mark Liversedge/Christmas.crs +DISTANCE GRADE WIND +[END COURSE HEADER] +[COURSE DATA] +0.506991 -0.0351091 0 +0.501159 -0.303896 0 +0.50019 -0.426038 0 +0.50492 2.00329 0 +0.50542 -1.44454 0 +0.50238 -0.481707 0 +0.50707 -0.122468 0 +0.50711 0.732977 0 +0.50477 0.912693 0 +0.50086 0.520305 0 +0.50503 1.47694 0 +0.50236 2.10009 0 +0.50719 -0.614957 0 +0.50177 -4.60988 0 +0.50636 -1.39071 0 +0.50224 -1.8983 0 +0.50772 -1.40589 0 +0.50655 -0.747606 0 +0.50267 0.969025 0 +0.50154 0.420505 0 +0.5062 1.98143 0 +0.5058 -1.30645 0 +0.502 -0.908367 0 +0.503 -1.17217 0 +0.5053 2.05601 0 +0.5013 -1.38859 0 +0.5003 2.74795 0 +0.5016 0.327552 0 +0.5036 -1.59075 0 +0.5017 0.455451 0 +0.5056 -0.587816 0 +0.5036 -0.281771 0 +0.5062 -0.0596602 0 +0.5026 -0.472344 0 +0.5099 -0.347715 0 +0.5055 2.1909 0 +0.5003 -2.03978 0 +0.5073 -0.839543 0 +0.505 -0.574653 0 +0.5029 1.91569 0 +0.5111 -1.63608 0 +0.5021 2.93766 0 +0.5087 -3.88028 0 +0.5032 0.689189 0 +0.5034 0.00735002 0 +0.508 -0.540748 0 +0.5048 0.481577 0 +0.5016 2.17484 0 +0.5025 0.509254 0 +0.508 -0.58189 0 +0.5015 -2.01595 0 +0.5057 2.04588 0 +0.5069 1.75222 0 +0.504 0.954563 0 +0.5035 1.0143 0 +0.5054 -0.510091 0 +0.5033 -0.591099 0 +0.5058 0.123567 0 +0.5046 -2.32878 0 +0.5078 -1.16916 0 +0.505 1.59327 0 +0.5017 2.70062 0 +0.5077 1.69096 0 +0.5003 1.39117 0 +0.5006 1.03276 0 +0.5076 3.64106 0 +0.5017 -1.19693 0 +0.5022 -2.1814 0 +0.5029 -0.705906 0 +0.5025 -0.238209 0 +0.5069 0.112843 0 +0.5032 -0.0874404 0 +0.5056 0.0549842 0 +0.505 0.13802 0 +0.5005 0.154446 0 +0.5045 -0.971853 0 +0.5051 1.28925 0 +0.5072 -0.449132 0 +0.5027 -1.11279 0 +[END COURSE DATA] diff --git a/src/test/workouts/ERG_03_75%.mrc b/src/test/workouts/ERG_03_75%.mrc new file mode 100644 index 000000000..9e26f7234 --- /dev/null +++ b/src/test/workouts/ERG_03_75%.mrc @@ -0,0 +1,74 @@ +[COURSE HEADER] +FTP = 240 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = Rob Campbell's File +FILE NAME = 250Watts_150W2_1_03_ERG3_xErg.mrc +MINUTES PERCENT +[END COURSE HEADER] + +[COURSE DATA] +0.0 0 +0.0 47 +10.0 47 +10.0 150 +13.0 93 +13.0 47 +16.0 107 +16.0 200 +16.5 140 +16.5 50 +19.0 60 +19.0 200 +19.5 175 +19.5 52 +22.0 53 +22.0 200 +22.5 175 +22.5 47 +25.0 78 +25.0 200 +25.5 175 +25.5 57 +28.0 57 +28.0 200 +28.5 175 +28.5 59 +31.0 58 +31.0 200 +31.5 175 +31.5 52 +34.0 56 +34.0 200 +34.5 176 +34.5 47 +37.0 72 +37.0 200 +37.5 175 +37.5 38 +40.0 55 +40.0 200 +40.5 175 +40.5 35 +43.0 64 +43.0 200 +43.5 172 +43.5 35 +46.0 47 +46.0 200 +46.5 175 +46.5 43 +49.0 53 +49.0 200 +49.5 175 +49.5 34 +52.0 65 +52.0 200 +52.5 173 +52.5 33 +55.0 48 +55.0 200 +55.5 159 +55.5 47 +60.5 33 +[END COURSE DATA] diff --git a/src/test/workouts/FTPCheckup.erg b/src/test/workouts/FTPCheckup.erg new file mode 100644 index 000000000..06882e024 --- /dev/null +++ b/src/test/workouts/FTPCheckup.erg @@ -0,0 +1,42 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = FTP Checkup +FILE NAME = 260WFTPRider_FTPCheckup.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 130 +2.0 130 +2.0 143 +4.5 143 +4.5 156 +7.0 156 +7.0 143 +7.0 143 +7.0 130 +8.0 130 +8.0 182 +9.0 182 +9.0 130 +10.0 130 +10.0 182 +11.0 182 +11.0 130 +12.0 130 +12.0 182 +13.0 182 +15.0 299 +15.0 299 +20.0 299 +20.0 156 +30.0 156 +35.0 276 +35.0 276 +55.0 276 +55.0 130 +55.0 130 +60.0 130 +[END COURSE DATA] diff --git a/src/test/workouts/HourofPowerV1.erg b/src/test/workouts/HourofPowerV1.erg index 3580913c6..86fea130f 100644 --- a/src/test/workouts/HourofPowerV1.erg +++ b/src/test/workouts/HourofPowerV1.erg @@ -1,388 +1,388 @@ -[COURSE HEADER] -VERSION = 2 -UNITS = ENGLISH -DESCRIPTION = Bill Black's Hour of Power -FILE NAME = HourofPowerV1.erg -FTP = 275 -MINUTES WATTS -[END COURSE HEADER] - -[COURSE DATA] -0.0 124 -2.0 124 -2.0 155 -6.0 155 -6.0 186 -10.0 186 -10.0 248 -12.5 248 -12.5 170 -15.0 170 -15.25 272 -15.5 276 -15.75 271 -16.0 273 -16.25 269 -16.5 267 -16.75 276 -17.0 278 -17.25 269 -17.5 269 -17.75 264 -18.0 264 -18.06 311 -18.12 333 -18.18 345 -18.24 350 -18.3 353 -18.36 354 -18.42 356 -18.42 264 -18.42 264 -18.67 269 -18.92 268 -19.17 266 -19.42 270 -19.67 268 -19.92 276 -20.17 278 -20.42 264 -20.67 267 -20.92 273 -21.17 275 -21.42 266 -21.48 311 -21.54 334 -21.6 345 -21.65 350 -21.71 353 -21.77 354 -21.83 356 -21.83 264 -21.83 264 -22.08 270 -22.33 274 -22.58 270 -22.83 268 -23.08 270 -23.33 278 -23.58 271 -23.83 271 -24.08 275 -24.33 265 -24.58 273 -24.83 273 -24.89 315 -24.95 336 -25.01 346 -25.07 351 -25.13 353 -25.19 354 -25.25 356 -25.25 264 -25.25 264 -25.5 278 -25.75 272 -26.0 267 -26.25 273 -26.5 265 -26.75 272 -27.0 272 -27.25 271 -27.5 275 -27.75 264 -28.0 264 -28.25 273 -28.31 315 -28.37 336 -28.43 346 -28.49 351 -28.55 353 -28.61 354 -28.67 356 -28.67 264 -28.67 264 -28.92 271 -29.17 271 -29.42 278 -29.67 264 -29.92 274 -30.17 266 -30.42 273 -30.67 270 -30.92 275 -31.17 278 -31.42 270 -31.67 273 -31.73 315 -31.79 336 -31.85 346 -31.9 351 -31.96 353 -32.02 354 -32.08 356 -32.08 264 -32.08 264 -32.33 271 -32.58 274 -32.83 271 -33.08 266 -33.33 267 -33.58 275 -33.83 264 -34.08 271 -34.33 278 -34.58 273 -34.83 275 -35.08 267 -35.14 312 -35.2 334 -35.26 345 -35.32 350 -35.38 353 -35.44 354 -35.5 356 -35.5 264 -35.5 264 -35.75 269 -36.0 277 -36.25 264 -36.5 266 -36.75 266 -37.0 270 -37.25 275 -37.5 268 -37.75 271 -38.0 272 -38.25 274 -38.5 278 -38.56 318 -38.62 337 -38.68 346 -38.74 351 -38.8 353 -38.86 354 -38.92 356 -38.92 264 -38.92 264 -39.17 272 -39.42 267 -39.67 264 -39.92 270 -40.17 274 -40.42 271 -40.67 266 -40.92 272 -41.17 276 -41.42 265 -41.67 273 -41.92 271 -41.98 314 -42.04 335 -42.1 346 -42.15 351 -42.21 353 -42.27 354 -42.33 356 -42.33 264 -42.33 264 -42.58 277 -42.83 275 -43.08 275 -43.33 271 -43.58 276 -43.83 264 -44.08 275 -44.33 267 -44.58 271 -44.83 271 -45.08 265 -45.33 278 -45.39 318 -45.45 337 -45.51 346 -45.57 351 -45.63 353 -45.69 354 -45.75 356 -45.75 264 -45.75 264 -46.0 265 -46.25 265 -46.5 275 -46.75 276 -47.0 268 -47.25 265 -47.5 267 -47.75 271 -48.0 276 -48.25 264 -48.5 278 -48.75 271 -48.81 314 -48.87 335 -48.93 346 -48.99 351 -49.05 353 -49.11 354 -49.17 356 -49.17 264 -49.17 264 -49.42 276 -49.67 278 -49.92 268 -50.17 273 -50.42 269 -50.67 273 -50.92 266 -51.17 268 -51.42 274 -51.67 265 -51.92 270 -52.17 272 -52.23 315 -52.29 335 -52.35 346 -52.4 351 -52.46 353 -52.52 354 -52.58 356 -52.58 264 -52.58 264 -52.83 274 -53.08 264 -53.33 272 -53.58 267 -53.83 278 -54.08 274 -54.33 268 -54.58 271 -54.83 276 -55.08 264 -55.33 269 -55.58 271 -55.64 314 -55.7 335 -55.76 346 -55.82 351 -55.88 353 -55.94 354 -56.0 356 -56.0 264 -56.0 264 -56.25 270 -56.5 277 -56.75 264 -57.0 264 -57.25 278 -57.5 267 -57.75 267 -58.0 268 -58.25 274 -58.5 265 -58.75 276 -59.0 272 -59.06 314 -59.12 335 -59.18 346 -59.24 351 -59.3 353 -59.36 354 -59.42 356 -59.42 264 -59.42 264 -59.67 267 -59.92 277 -60.17 268 -60.42 272 -60.67 272 -60.92 268 -61.17 269 -61.42 271 -61.67 276 -61.92 278 -62.17 275 -62.42 271 -62.48 314 -62.54 335 -62.6 346 -62.65 351 -62.71 353 -62.77 354 -62.83 356 -62.83 264 -62.83 264 -63.08 270 -63.33 267 -63.58 268 -63.83 277 -64.08 265 -64.33 269 -64.58 275 -64.83 275 -65.08 267 -65.33 272 -65.58 274 -65.83 264 -65.89 311 -65.95 334 -66.01 345 -66.07 350 -66.13 353 -66.19 354 -66.25 356 -66.25 264 -66.25 264 -66.5 266 -66.75 265 -67.0 276 -67.25 274 -67.5 266 -67.75 277 -68.0 274 -68.25 272 -68.5 265 -68.75 273 -69.0 265 -69.25 265 -69.31 311 -69.37 334 -69.43 345 -69.49 350 -69.55 353 -69.61 354 -69.67 356 -69.67 264 -69.67 264 -69.92 272 -70.17 265 -70.42 269 -70.67 278 -70.92 275 -71.17 269 -71.42 273 -71.67 277 -71.92 275 -72.17 270 -72.42 269 -72.67 274 -72.73 316 -72.79 336 -72.85 346 -72.9 351 -72.96 353 -73.02 354 -73.08 356 -73.08 264 -73.08 264 -73.33 273 -73.58 275 -73.83 269 -74.08 265 -74.33 272 -74.58 277 -74.83 269 -75.08 272 -77.0 124 -80.0 124 -[END COURSE DATA] +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = Hour of Power V1 +FILE NAME = 260WFTPRider_HourofPowerV1.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +6.0 130 +6.0 156 +10.0 156 +10.0 208 +12.5 208 +12.5 143 +15.0 143 +15.25 228 +15.5 231 +15.75 227 +16.0 229 +16.25 226 +16.5 223 +16.75 231 +17.0 233 +17.25 225 +17.5 225 +17.75 221 +18.0 221 +18.06 260 +18.12 280 +18.18 289 +18.24 294 +18.3 296 +18.36 297 +18.42 299 +18.42 221 +18.42 221 +18.67 226 +18.92 224 +19.17 223 +19.42 226 +19.67 225 +19.92 232 +20.17 233 +20.42 221 +20.67 224 +20.92 228 +21.17 230 +21.42 222 +21.48 261 +21.54 280 +21.6 290 +21.65 294 +21.71 296 +21.77 297 +21.83 299 +21.83 221 +21.83 221 +22.08 226 +22.33 229 +22.58 226 +22.83 224 +23.08 226 +23.33 233 +23.58 227 +23.83 227 +24.08 230 +24.33 221 +24.58 229 +24.83 229 +24.89 264 +24.95 282 +25.01 290 +25.07 294 +25.13 297 +25.19 298 +25.25 299 +25.25 221 +25.25 221 +25.5 233 +25.75 228 +26.0 223 +26.25 229 +26.5 221 +26.75 228 +27.0 228 +27.25 227 +27.5 230 +27.75 221 +28.0 221 +28.25 229 +28.31 264 +28.37 282 +28.43 290 +28.49 294 +28.55 297 +28.61 298 +28.67 299 +28.67 221 +28.67 221 +28.92 227 +29.17 227 +29.42 233 +29.67 221 +29.92 229 +30.17 222 +30.42 229 +30.67 227 +30.92 230 +31.17 233 +31.42 226 +31.67 229 +31.73 264 +31.79 282 +31.85 290 +31.9 294 +31.96 297 +32.02 298 +32.08 299 +32.08 221 +32.08 221 +32.33 227 +32.58 229 +32.83 227 +33.08 222 +33.33 224 +33.58 231 +33.83 221 +34.08 227 +34.33 233 +34.58 229 +34.83 230 +35.08 223 +35.14 262 +35.2 280 +35.26 290 +35.32 294 +35.38 296 +35.44 297 +35.5 299 +35.5 221 +35.5 221 +35.75 225 +36.0 232 +36.25 221 +36.5 223 +36.75 223 +37.0 226 +37.25 230 +37.5 224 +37.75 227 +38.0 227 +38.25 229 +38.5 233 +38.56 266 +38.62 283 +38.68 291 +38.74 295 +38.8 297 +38.86 298 +38.92 299 +38.92 221 +38.92 221 +39.17 228 +39.42 223 +39.67 221 +39.92 226 +40.17 230 +40.42 227 +40.67 223 +40.92 228 +41.17 232 +41.42 222 +41.67 228 +41.92 227 +41.98 264 +42.04 281 +42.1 290 +42.15 294 +42.21 296 +42.27 298 +42.33 299 +42.33 221 +42.33 221 +42.58 232 +42.83 230 +43.08 231 +43.33 227 +43.58 231 +43.83 221 +44.08 231 +44.33 224 +44.58 227 +44.83 227 +45.08 222 +45.33 233 +45.39 266 +45.45 283 +45.51 291 +45.57 295 +45.63 297 +45.69 298 +45.75 299 +45.75 221 +45.75 221 +46.0 222 +46.25 222 +46.5 231 +46.75 231 +47.0 225 +47.25 222 +47.5 224 +47.75 227 +48.0 232 +48.25 221 +48.5 233 +48.75 227 +48.81 264 +48.87 281 +48.93 290 +48.99 294 +49.05 296 +49.11 298 +49.17 299 +49.17 221 +49.17 221 +49.42 232 +49.67 233 +49.92 224 +50.17 229 +50.42 225 +50.67 229 +50.92 223 +51.17 225 +51.42 230 +51.67 222 +51.92 226 +52.17 228 +52.23 264 +52.29 282 +52.35 290 +52.4 294 +52.46 297 +52.52 298 +52.58 299 +52.58 221 +52.58 221 +52.83 229 +53.08 221 +53.33 228 +53.58 223 +53.83 233 +54.08 229 +54.33 224 +54.58 227 +54.83 232 +55.08 221 +55.33 226 +55.58 227 +55.64 264 +55.7 281 +55.76 290 +55.82 294 +55.88 296 +55.94 298 +56.0 299 +56.0 221 +56.0 221 +56.25 226 +56.5 232 +56.75 221 +57.0 221 +57.25 233 +57.5 224 +57.75 224 +58.0 224 +58.25 230 +58.5 222 +58.75 231 +59.0 228 +59.06 264 +59.12 282 +59.18 290 +59.24 294 +59.3 297 +59.36 298 +59.42 299 +59.42 221 +59.42 221 +59.67 223 +59.92 232 +60.17 225 +60.42 228 +60.67 228 +60.92 224 +61.17 225 +61.42 227 +61.67 232 +61.92 233 +62.17 231 +62.42 227 +62.48 263 +62.54 281 +62.6 290 +62.65 294 +62.71 296 +62.77 298 +62.83 299 +62.83 221 +62.83 221 +63.08 226 +63.33 224 +63.58 225 +63.83 232 +64.08 222 +64.33 225 +64.58 231 +64.83 230 +65.08 223 +65.33 228 +65.58 230 +65.83 221 +65.89 261 +65.95 280 +66.01 289 +66.07 294 +66.13 296 +66.19 297 +66.25 299 +66.25 221 +66.25 221 +66.5 223 +66.75 222 +67.0 231 +67.25 230 +67.5 222 +67.75 232 +68.0 230 +68.25 228 +68.5 222 +68.75 229 +69.0 222 +69.25 222 +69.31 261 +69.37 280 +69.43 289 +69.49 294 +69.55 296 +69.61 297 +69.67 299 +69.67 221 +69.67 221 +69.92 228 +70.17 222 +70.42 225 +70.67 233 +70.92 231 +71.17 225 +71.42 229 +71.67 232 +71.92 230 +72.17 226 +72.42 225 +72.67 230 +72.73 265 +72.79 282 +72.85 290 +72.9 295 +72.96 297 +73.02 298 +73.08 299 +73.08 221 +73.08 221 +73.33 229 +73.58 230 +73.83 225 +74.08 222 +74.33 228 +74.58 232 +74.83 225 +75.08 228 +77.0 104 +80.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/HourofPowerV2.erg b/src/test/workouts/HourofPowerV2.erg new file mode 100644 index 000000000..d1b3c6e83 --- /dev/null +++ b/src/test/workouts/HourofPowerV2.erg @@ -0,0 +1,388 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = Hour of Power V2 +FILE NAME = 260WFTPRider_HourofPowerV2.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +6.0 130 +6.0 156 +10.0 156 +10.0 208 +12.5 208 +12.5 143 +15.0 143 +15.25 228 +15.5 231 +15.75 227 +16.0 229 +16.25 226 +16.5 223 +16.75 231 +17.0 233 +17.25 225 +17.5 225 +17.75 221 +18.0 221 +18.06 260 +18.12 280 +18.18 289 +18.24 294 +18.3 296 +18.36 297 +18.42 299 +18.42 221 +18.42 221 +18.67 226 +18.92 224 +19.17 223 +19.42 226 +19.67 225 +19.92 232 +20.17 233 +20.42 221 +20.67 224 +20.92 228 +21.17 230 +21.42 222 +21.48 261 +21.54 280 +21.6 290 +21.65 294 +21.71 296 +21.77 297 +21.83 299 +21.83 221 +21.83 221 +22.08 226 +22.33 229 +22.58 226 +22.83 224 +23.08 226 +23.33 233 +23.58 227 +23.83 227 +24.08 230 +24.33 221 +24.58 229 +24.83 229 +24.89 264 +24.95 282 +25.01 290 +25.07 294 +25.13 297 +25.19 298 +25.25 299 +25.25 221 +25.25 221 +25.5 233 +25.75 228 +26.0 223 +26.25 229 +26.5 221 +26.75 228 +27.0 228 +27.25 227 +27.5 230 +27.75 221 +28.0 221 +28.25 229 +28.31 264 +28.37 282 +28.43 290 +28.49 294 +28.55 297 +28.61 298 +28.67 299 +28.67 221 +28.67 221 +28.92 227 +29.17 227 +29.42 233 +29.67 221 +29.92 229 +30.17 222 +30.42 229 +30.67 227 +30.92 230 +31.17 233 +31.42 226 +31.67 229 +31.73 264 +31.79 282 +31.85 290 +31.9 294 +31.96 297 +32.02 298 +32.08 299 +32.08 221 +32.08 221 +32.33 227 +32.58 229 +32.83 227 +33.08 222 +33.33 224 +33.58 231 +33.83 221 +34.08 227 +34.33 233 +34.58 229 +34.83 230 +35.08 223 +35.14 262 +35.2 280 +35.26 290 +35.32 294 +35.38 296 +35.44 297 +35.5 299 +35.5 221 +35.5 221 +35.75 225 +36.0 232 +36.25 221 +36.5 223 +36.75 223 +37.0 226 +37.25 230 +37.5 224 +37.75 227 +38.0 227 +38.25 229 +38.5 233 +38.56 266 +38.62 283 +38.68 291 +38.74 295 +38.8 297 +38.86 298 +38.92 299 +38.92 221 +38.92 221 +39.17 231 +39.42 226 +39.67 224 +39.92 229 +40.17 233 +40.42 230 +40.67 226 +40.92 231 +41.17 235 +41.42 225 +41.67 231 +41.92 230 +41.98 265 +42.04 282 +42.1 290 +42.15 295 +42.21 297 +42.27 298 +42.33 299 +42.33 221 +42.33 221 +42.58 237 +42.83 235 +43.08 236 +43.33 232 +43.58 236 +43.83 226 +44.08 236 +44.33 229 +44.58 232 +44.83 232 +45.08 227 +45.33 238 +45.39 269 +45.45 284 +45.51 291 +45.57 295 +45.63 297 +45.69 298 +45.75 299 +45.75 221 +45.75 221 +46.0 230 +46.25 230 +46.5 239 +46.75 239 +47.0 233 +47.25 230 +47.5 232 +47.75 235 +48.0 240 +48.25 229 +48.5 241 +48.75 235 +48.81 267 +48.87 283 +48.93 291 +48.99 295 +49.05 297 +49.11 298 +49.17 299 +49.17 221 +49.17 221 +49.42 242 +49.67 243 +49.92 234 +50.17 239 +50.42 235 +50.67 239 +50.92 233 +51.17 235 +51.42 240 +51.67 232 +51.92 236 +52.17 238 +52.23 269 +52.29 284 +52.35 291 +52.4 295 +52.46 297 +52.52 298 +52.58 299 +52.58 221 +52.58 221 +52.83 242 +53.08 234 +53.33 241 +53.58 236 +53.83 246 +54.08 242 +54.33 237 +54.58 240 +54.83 245 +55.08 234 +55.33 239 +55.58 240 +55.64 270 +55.7 284 +55.76 292 +55.82 295 +55.88 297 +55.94 298 +56.0 299 +56.0 221 +56.0 221 +56.25 242 +56.5 248 +56.75 237 +57.0 237 +57.25 249 +57.5 240 +57.75 240 +58.0 240 +58.25 246 +58.5 238 +58.75 247 +59.0 244 +59.06 272 +59.12 285 +59.18 292 +59.24 295 +59.3 297 +59.36 298 +59.42 299 +59.42 221 +59.42 221 +59.67 241 +59.92 250 +60.17 243 +60.42 246 +60.67 246 +60.92 242 +61.17 243 +61.42 245 +61.67 250 +61.92 251 +62.17 249 +62.42 245 +62.48 272 +62.54 286 +62.6 292 +62.65 295 +62.71 297 +62.77 298 +62.83 299 +62.83 221 +62.83 221 +63.08 247 +63.33 245 +63.58 246 +63.83 253 +64.08 243 +64.33 246 +64.58 252 +64.83 251 +65.08 244 +65.33 249 +65.58 251 +65.83 242 +65.89 271 +65.95 285 +66.01 292 +66.07 295 +66.13 297 +66.19 298 +66.25 299 +66.25 221 +66.25 221 +66.5 246 +66.75 245 +67.0 254 +67.25 253 +67.5 245 +67.75 255 +68.0 253 +68.25 251 +68.5 245 +68.75 252 +69.0 245 +69.25 245 +69.31 272 +69.37 286 +69.43 292 +69.49 295 +69.55 297 +69.61 298 +69.67 299 +69.67 221 +69.67 221 +69.92 254 +70.17 248 +70.42 251 +70.67 259 +70.92 257 +71.17 251 +71.42 255 +71.67 258 +71.92 256 +72.17 252 +72.42 251 +72.67 256 +72.73 278 +72.79 288 +72.85 293 +72.9 296 +72.96 297 +73.02 298 +73.08 299 +73.08 221 +73.08 221 +73.33 229 +73.58 230 +73.83 225 +74.08 222 +74.33 228 +74.58 232 +74.83 225 +75.08 228 +77.0 104 +80.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/Road110MinsTempoHilly.erg b/src/test/workouts/Road110MinsTempoHilly.erg new file mode 100644 index 000000000..fe2d8dc68 --- /dev/null +++ b/src/test/workouts/Road110MinsTempoHilly.erg @@ -0,0 +1,310 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = Brisk 110 minute hilly road ride. TSS 121. +FILE NAME = 260WFTPRider_Road110MinsTempoHilly.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.0 156 +7.5 156 +7.5 156 +10.0 156 +10.33 153 +10.67 177 +11.0 416 +11.33 281 +11.67 62 +12.0 125 +12.33 161 +12.67 104 +13.0 133 +13.33 169 +13.67 278 +14.0 265 +14.33 185 +14.67 237 +15.0 239 +15.33 208 +15.67 68 +16.0 114 +16.33 151 +16.67 299 +17.0 187 +17.33 296 +17.67 104 +18.0 195 +18.33 221 +18.67 338 +19.0 138 +19.33 239 +19.67 216 +20.0 161 +20.33 283 +20.67 182 +21.0 268 +21.33 104 +21.67 190 +22.0 151 +22.33 91 +22.67 133 +23.0 94 +23.33 130 +23.67 104 +24.0 190 +24.33 159 +24.67 200 +25.0 174 +25.33 190 +25.67 179 +26.0 179 +26.33 177 +26.67 169 +27.0 164 +27.33 130 +27.67 112 +28.0 177 +28.33 234 +28.67 185 +29.0 190 +29.33 164 +29.67 172 +30.0 169 +30.33 174 +30.67 166 +31.0 182 +31.33 182 +31.67 203 +32.0 234 +32.33 203 +32.67 203 +33.0 159 +33.33 96 +33.67 226 +34.0 221 +34.33 273 +34.67 304 +35.0 250 +35.33 99 +35.67 239 +36.0 190 +36.33 203 +36.67 177 +37.0 151 +37.33 99 +37.67 226 +38.0 151 +38.33 65 +38.67 172 +39.0 130 +39.33 205 +39.67 192 +40.0 224 +40.33 224 +40.67 218 +41.0 276 +41.33 195 +41.67 224 +42.0 221 +42.33 190 +42.67 226 +43.0 218 +43.33 213 +43.67 299 +44.0 250 +44.33 268 +44.67 278 +45.0 268 +45.33 294 +45.67 211 +46.0 177 +46.33 172 +46.67 242 +47.0 273 +47.33 169 +47.67 107 +48.0 65 +48.33 250 +48.67 34 +49.0 101 +49.33 161 +49.67 229 +50.0 304 +50.33 216 +50.67 159 +51.0 304 +51.33 159 +51.67 291 +52.0 185 +52.33 101 +52.67 104 +53.0 94 +53.33 109 +53.67 234 +54.0 237 +54.33 151 +54.67 138 +55.0 437 +55.33 135 +55.67 216 +56.0 179 +56.33 96 +56.67 148 +57.0 130 +57.33 364 +57.67 159 +58.0 96 +58.33 437 +58.67 68 +59.0 151 +59.33 39 +59.67 81 +60.0 133 +60.33 187 +60.67 122 +61.0 179 +61.33 330 +61.67 244 +62.0 255 +62.33 208 +62.67 250 +63.0 247 +63.33 125 +63.67 109 +64.0 68 +64.33 341 +64.67 211 +65.0 317 +65.33 133 +65.67 148 +66.0 224 +66.33 437 +66.67 130 +67.0 268 +67.33 283 +67.67 289 +68.0 302 +68.33 382 +68.67 52 +69.0 185 +69.33 140 +69.67 70 +70.0 276 +70.33 120 +70.67 169 +71.0 120 +71.33 146 +71.67 198 +72.0 203 +72.33 161 +72.67 130 +73.0 218 +73.33 164 +73.67 205 +74.0 203 +74.33 190 +74.67 151 +75.0 159 +75.33 187 +75.67 213 +76.0 226 +76.33 213 +76.67 164 +77.0 169 +77.33 208 +77.67 234 +78.0 229 +78.33 221 +78.67 190 +79.0 208 +79.33 221 +79.67 229 +80.0 198 +80.33 133 +80.67 218 +81.0 242 +81.33 361 +81.67 205 +82.0 221 +82.33 237 +82.67 218 +83.0 224 +83.33 229 +83.67 179 +84.0 109 +84.33 224 +84.67 205 +85.0 70 +85.33 146 +85.67 195 +86.0 177 +86.33 112 +86.67 226 +87.0 231 +87.33 226 +87.67 278 +88.0 224 +88.33 257 +88.67 221 +89.0 231 +89.33 247 +89.67 257 +90.0 244 +90.33 270 +90.67 320 +91.0 322 +91.33 281 +91.67 330 +92.0 237 +92.33 237 +92.67 237 +93.0 351 +93.33 247 +93.67 55 +94.0 174 +94.33 143 +94.67 130 +95.0 114 +95.33 114 +95.67 437 +96.0 226 +96.33 169 +96.67 328 +97.0 192 +97.33 296 +97.67 159 +98.0 122 +98.33 96 +98.67 75 +99.0 135 +99.33 159 +99.67 179 +100.0 203 +100.33 140 +100.67 419 +101.0 112 +101.33 195 +101.67 169 +102.0 62 +102.33 182 +102.67 117 +103.0 356 +103.33 109 +103.67 101 +104.0 398 +104.33 78 +104.67 159 +105.0 86 +105.33 49 +105.67 374 +106.0 213 +106.32 104 +106.32 104 +110.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/Road130MinsTempoHilly.erg b/src/test/workouts/Road130MinsTempoHilly.erg new file mode 100644 index 000000000..129794cfc --- /dev/null +++ b/src/test/workouts/Road130MinsTempoHilly.erg @@ -0,0 +1,363 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 130 Minute Road Ride. Hilly start and end, Middle TT section. +FILE NAME = 260WFTPRider_Road130MinsTempoHilly.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.0 156 +7.5 156 +7.5 156 +10.0 156 +10.33 138 +10.67 114 +11.0 309 +11.33 333 +11.67 182 +12.0 161 +12.33 179 +12.67 289 +13.0 143 +13.33 156 +13.67 135 +14.0 229 +14.33 104 +14.67 127 +15.0 138 +15.33 239 +15.67 234 +16.0 31 +16.33 99 +16.67 192 +17.0 320 +17.33 335 +17.67 190 +18.0 81 +18.33 224 +18.67 104 +19.0 289 +19.33 164 +19.67 140 +20.0 177 +20.33 81 +20.67 130 +21.0 260 +21.33 226 +21.67 216 +22.0 135 +22.33 255 +22.67 182 +23.0 198 +23.33 60 +23.67 192 +24.0 216 +24.33 255 +24.67 250 +25.0 166 +25.33 60 +25.67 216 +26.0 195 +26.33 218 +26.67 127 +27.0 229 +27.33 213 +27.67 146 +28.0 156 +28.33 177 +28.67 203 +29.0 130 +29.33 179 +29.67 182 +30.0 148 +30.33 125 +30.67 125 +31.0 122 +31.33 91 +31.67 229 +32.0 377 +32.33 52 +32.67 213 +33.0 94 +33.33 164 +33.67 224 +34.0 169 +34.33 198 +34.67 221 +35.0 187 +35.33 146 +35.67 166 +36.0 312 +36.33 161 +36.67 185 +37.0 114 +37.33 135 +37.67 218 +38.0 203 +38.33 159 +38.67 179 +39.0 169 +39.33 177 +39.67 195 +40.0 216 +40.33 169 +40.67 174 +41.0 257 +41.33 174 +41.67 117 +42.0 169 +42.33 229 +42.67 237 +43.0 216 +43.33 260 +43.67 226 +44.0 172 +44.33 133 +44.67 169 +45.0 211 +45.33 185 +45.67 205 +46.0 182 +46.33 213 +46.67 200 +47.0 190 +47.33 195 +47.67 166 +48.0 70 +48.33 187 +48.67 187 +49.0 169 +49.33 169 +49.67 179 +50.0 182 +50.33 185 +50.67 190 +51.0 169 +51.33 120 +51.67 127 +52.0 127 +52.33 112 +52.67 138 +53.0 120 +53.33 127 +53.67 177 +54.0 164 +54.33 151 +54.67 146 +55.0 213 +55.33 255 +55.67 151 +56.0 99 +56.33 130 +56.67 166 +57.0 224 +57.33 34 +57.67 23 +58.0 312 +58.33 216 +58.67 250 +59.0 234 +59.33 172 +59.67 278 +60.0 268 +60.33 224 +60.67 208 +61.0 211 +61.33 234 +61.67 218 +62.0 211 +62.33 229 +62.67 218 +63.0 221 +63.33 237 +63.67 205 +64.0 221 +64.33 250 +64.67 192 +65.0 198 +65.33 221 +65.67 216 +66.0 237 +66.33 260 +66.67 255 +67.0 268 +67.33 200 +67.67 169 +68.0 213 +68.33 226 +68.67 257 +69.0 205 +69.33 195 +69.67 260 +70.0 205 +70.33 229 +70.67 255 +71.0 221 +71.33 99 +71.67 286 +72.0 218 +72.33 237 +72.67 247 +73.0 224 +73.33 182 +73.67 250 +74.0 231 +74.33 211 +74.67 203 +75.0 239 +75.33 244 +75.67 283 +76.0 260 +76.33 205 +76.67 190 +77.0 221 +77.33 216 +77.67 221 +78.0 244 +78.33 263 +78.67 211 +79.0 229 +79.33 231 +79.67 195 +80.0 208 +80.33 268 +80.67 239 +81.0 205 +81.33 216 +81.67 237 +82.0 252 +82.33 224 +82.67 263 +83.0 252 +83.33 252 +83.67 143 +84.0 112 +84.33 91 +84.67 117 +85.0 148 +85.33 125 +85.67 133 +86.0 130 +86.33 130 +86.67 130 +87.0 140 +87.33 135 +87.67 140 +88.0 169 +88.33 164 +88.67 127 +89.0 140 +89.33 117 +89.67 127 +90.0 156 +90.33 190 +90.67 156 +91.0 182 +91.33 221 +91.67 127 +92.0 99 +92.33 125 +92.67 151 +93.0 192 +93.33 195 +93.67 120 +94.0 177 +94.33 179 +94.67 146 +95.0 143 +95.33 190 +95.67 161 +96.0 211 +96.33 138 +96.67 192 +97.0 161 +97.33 200 +97.67 135 +98.0 143 +98.33 159 +98.67 174 +99.0 174 +99.33 179 +99.67 166 +100.0 190 +100.33 130 +100.67 151 +101.0 224 +101.33 385 +101.67 75 +102.0 78 +102.33 244 +102.67 224 +103.0 143 +103.33 172 +103.67 156 +104.0 216 +104.33 182 +104.67 96 +105.0 135 +105.33 200 +105.67 187 +106.0 169 +106.33 179 +106.67 174 +107.0 177 +107.33 164 +107.67 140 +108.0 135 +108.33 164 +108.67 114 +109.0 208 +109.33 218 +109.67 216 +110.0 91 +110.33 101 +110.67 166 +111.0 172 +111.33 125 +111.67 109 +112.0 174 +112.33 330 +112.67 60 +113.0 117 +113.33 338 +113.67 221 +114.0 182 +114.33 302 +114.67 208 +115.0 130 +115.33 257 +115.67 250 +116.0 385 +116.33 44 +116.67 322 +117.0 192 +117.33 390 +117.67 268 +118.0 255 +118.33 127 +118.67 304 +119.0 159 +119.33 107 +119.67 185 +120.0 174 +120.33 166 +120.67 252 +121.0 161 +121.33 291 +121.67 94 +122.0 107 +122.33 302 +122.67 86 +123.0 164 +123.33 107 +123.67 166 +124.0 411 +124.33 104 +130.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/Road57MinsTempoSurges.erg b/src/test/workouts/Road57MinsTempoSurges.erg new file mode 100644 index 000000000..84df9145c --- /dev/null +++ b/src/test/workouts/Road57MinsTempoSurges.erg @@ -0,0 +1,192 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = 20 mile road ride, surge every 2 mins, 60-100% FTP +FILE NAME = 260WFTPRider_Road57MinsTempoSurges.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.0 156 +7.5 156 +7.5 156 +10.0 156 +10.33 172 +10.67 159 +11.0 70 +11.33 255 +11.67 187 +12.0 125 +12.33 122 +12.67 205 +13.0 164 +13.33 174 +13.67 177 +14.0 177 +14.33 218 +14.67 224 +15.0 213 +15.33 252 +15.67 221 +16.0 211 +16.33 182 +16.67 195 +17.0 211 +17.33 187 +17.67 195 +18.0 179 +18.33 255 +18.67 247 +19.0 263 +19.33 239 +19.67 276 +20.0 250 +20.33 185 +20.67 140 +21.0 182 +21.33 203 +21.67 205 +22.0 203 +22.33 224 +22.67 224 +23.0 263 +23.33 218 +23.67 242 +24.0 229 +24.33 179 +24.67 78 +25.0 234 +25.33 211 +25.67 190 +26.0 195 +26.33 270 +26.67 247 +27.0 229 +27.33 252 +27.67 221 +28.0 211 +28.33 185 +28.67 195 +29.0 200 +29.33 195 +29.67 213 +30.0 185 +30.33 216 +30.67 237 +31.0 263 +31.33 237 +31.67 252 +32.0 237 +32.33 198 +32.67 185 +33.0 195 +33.33 192 +33.67 166 +34.0 182 +34.33 239 +34.67 257 +35.0 252 +35.33 231 +35.67 257 +36.0 224 +36.33 200 +36.67 169 +37.0 192 +37.33 203 +37.67 177 +38.0 195 +38.33 224 +38.67 255 +39.0 239 +39.33 242 +39.67 247 +40.0 156 +40.33 190 +40.67 203 +41.0 187 +41.33 169 +41.67 190 +42.0 203 +42.33 250 +42.67 255 +43.0 244 +43.33 239 +43.67 250 +44.0 247 +44.33 161 +44.67 179 +45.0 195 +45.33 166 +45.67 177 +46.0 182 +46.33 270 +46.67 247 +47.0 252 +47.33 255 +47.67 250 +48.0 226 +48.33 166 +48.67 174 +49.0 161 +49.33 205 +49.67 179 +50.0 172 +50.33 250 +50.67 281 +51.0 226 +51.33 255 +51.67 247 +52.0 221 +52.33 151 +52.67 205 +53.0 195 +53.33 185 +53.67 192 +54.0 216 +54.33 255 +54.67 195 +55.0 247 +55.33 255 +55.67 213 +56.0 242 +56.33 169 +56.67 185 +57.0 200 +57.33 213 +57.67 192 +58.0 179 +58.33 226 +58.67 250 +59.0 250 +59.33 247 +59.67 252 +60.0 247 +60.33 190 +60.67 200 +61.0 198 +61.33 192 +61.67 187 +62.0 172 +62.33 281 +62.67 231 +63.0 247 +63.33 260 +63.67 263 +64.0 257 +64.33 153 +64.67 205 +65.0 195 +65.33 187 +65.67 190 +66.0 200 +66.33 283 +66.67 257 +66.95 164 +66.95 104 +70.0 104 +[END COURSE DATA] diff --git a/src/test/workouts/WarmUp.erg b/src/test/workouts/WarmUp.erg new file mode 100644 index 000000000..bee3fd3f8 --- /dev/null +++ b/src/test/workouts/WarmUp.erg @@ -0,0 +1,19 @@ +[COURSE HEADER] +FTP = 260 +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = +FILE NAME = 260WFTPRider_WarmUp.erg +MINUTES WATTS +[END COURSE HEADER] + +[COURSE DATA] +0.0 104 +2.0 104 +2.0 130 +5.0 130 +5.0 156 +7.5 156 +7.5 156 +10.0 156 +[END COURSE DATA] diff --git a/src/test/workouts/angels.erg b/src/test/workouts/angels.erg new file mode 100644 index 000000000..9dbf0a598 --- /dev/null +++ b/src/test/workouts/angels.erg @@ -0,0 +1,125 @@ +[COURSE HEADER] +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = The Sufferfest - ANGELS +FILE NAME = ANGELS.ERG +FTP = 300 +MINUTES WATTS +[END COURSE HEADER] +[COURSE DATA] + +0.00 244 +2.08 244 +2.08 244 +5.82 244 +5.82 463 +6.27 463 +6.27 244 +6.83 244 +6.83 354 +7.78 354 +7.78 681 +8.25 681 +8.25 354 +9.13 354 +9.13 627 +10.17 627 +10.17 518 +11.08 518 +11.08 627 +12.05 627 +12.05 518 +13.02 518 +13.02 627 +14.02 627 +14.02 518 +15.13 518 +15.13 627 +16.12 627 +16.12 518 +17.55 518 +17.55 627 +18.55 627 +18.55 518 +19.63 518 +19.63 244 +23.92 244 +23.92 572 +24.48 572 +24.48 681 +25.17 681 +25.17 572 +25.60 572 +25.60 681 +25.78 681 +25.78 791 +26.47 791 +26.47 572 +28.22 572 +28.22 681 +29.10 681 +29.10 572 +30.82 572 +30.82 681 +31.80 681 +31.80 244 +36.53 244 +36.53 463 +38.62 463 +38.62 572 +40.70 572 +40.70 681 +42.53 681 +42.53 736 +44.48 736 +44.48 244 +49.38 244 +49.38 681 +49.75 681 +49.75 791 +49.95 791 +49.95 681 +50.32 681 +50.32 791 +50.65 791 +50.65 681 +51.58 681 +51.58 791 +52.17 791 +52.17 681 +52.48 681 +52.48 736 +52.58 736 +52.58 791 +52.93 791 +52.93 681 +53.50 681 +53.50 791 +53.70 791 +53.70 681 +54.07 681 +54.07 791 +54.25 791 +54.25 681 +54.72 681 +54.72 736 +54.93 736 +54.93 791 +55.20 791 +55.20 681 +55.37 681 +55.37 791 +55.62 791 +55.62 681 +55.88 681 +55.88 736 +56.03 736 +56.03 681 +57.10 681 +57.10 900 +57.45 900 +57.45 135 +63.47 135 + +[END COURSE DATA] + diff --git a/src/test/workouts/averydarkplace.erg b/src/test/workouts/averydarkplace.erg new file mode 100644 index 000000000..a76380b9a --- /dev/null +++ b/src/test/workouts/averydarkplace.erg @@ -0,0 +1,101 @@ +[COURSE HEADER] +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = The Sufferfest - A VERY DARK PLACE +FILE NAME = A_VERY_DARK_PLACE.ERG +FTP = 300 +MINUTES WATTS +[END COURSE HEADER] +[COURSE DATA] + +0.00 135 +2.50 135 +2.50 354 +4.65 354 +4.65 408 +5.62 408 +5.62 463 +6.63 463 +6.63 518 +8.25 518 +8.25 900 +8.77 900 +8.77 463 +10.50 463 +10.50 900 +11.03 900 +11.03 463 +12.65 463 +12.65 681 +16.65 681 +16.65 135 +20.47 135 +20.47 681 +21.10 681 +21.10 709 +22.72 709 +22.72 736 +23.02 736 +23.02 763 +23.78 763 +23.78 791 +24.45 791 +24.45 135 +28.15 135 +28.15 791 +28.48 791 +28.48 709 +30.23 709 +30.23 791 +30.53 791 +30.53 736 +31.23 736 +31.23 763 +31.95 763 +31.95 900 +32.20 900 +32.20 135 +35.78 135 +35.78 681 +36.17 681 +36.17 791 +36.48 791 +36.48 681 +36.73 681 +36.73 736 +37.05 736 +37.05 681 +37.25 681 +37.25 791 +37.62 791 +37.62 681 +37.82 681 +37.82 791 +38.27 791 +38.27 681 +38.48 681 +38.48 791 +38.73 791 +38.73 572 +38.98 572 +38.98 791 +39.87 791 +39.87 135 +43.53 135 +43.53 681 +43.83 681 +43.83 736 +45.73 736 +45.73 763 +46.32 763 +46.32 791 +46.65 791 +46.65 763 +47.23 763 +47.23 900 +47.57 900 +47.57 135 +52.15 135 + +[END COURSE DATA] + diff --git a/src/test/workouts/downwardspiral.erg b/src/test/workouts/downwardspiral.erg new file mode 100644 index 000000000..ee9e1ada6 --- /dev/null +++ b/src/test/workouts/downwardspiral.erg @@ -0,0 +1,103 @@ +[COURSE HEADER] +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = The Sufferfest - DOWNWARD SPIRAL +FILE NAME = DOWNWARD_SPIRAL.ERG +FTP = 300 +MINUTES WATTS +[END COURSE HEADER] +[COURSE DATA] + +0.00 135 +1.10 135 +1.10 135 +4.23 135 +4.23 354 +6.78 354 +6.78 681 +7.28 681 +7.28 354 +8.43 354 +8.43 681 +8.95 681 +8.95 354 +9.80 354 +9.80 845 +12.00 845 +12.00 135 +14.15 135 +14.15 845 +15.90 845 +15.90 135 +17.88 135 +17.88 845 +19.47 845 +19.47 135 +21.13 135 +21.13 845 +22.43 845 +22.43 135 +23.80 135 +23.80 845 +24.92 845 +24.92 135 +26.05 135 +26.05 900 +26.83 900 +26.83 135 +27.72 135 +27.72 900 +28.28 900 +28.28 135 +28.90 135 +28.90 900 +29.20 900 +29.20 135 +34.50 135 +34.50 845 +36.58 845 +36.58 135 +38.78 135 +38.78 845 +40.60 845 +40.60 135 +42.62 135 +42.62 845 +44.17 845 +44.17 135 +45.85 135 +45.85 845 +47.12 845 +47.12 135 +48.50 135 +48.50 845 +49.52 845 +49.52 135 +50.67 135 +50.67 900 +51.43 900 +51.43 135 +52.27 135 +52.27 900 +52.77 900 +52.77 135 +53.38 135 +53.38 900 +53.65 900 +53.65 135 +54.08 135 +54.08 900 +54.30 900 +54.30 135 +54.68 135 +54.68 900 +54.93 900 +54.93 135 +55.32 135 +55.32 900 +55.57 900 +55.57 135 +61.08 135 + +[END COURSE DATA] + diff --git a/src/test/workouts/fightclub.erg b/src/test/workouts/fightclub.erg new file mode 100644 index 000000000..1e3fbccbe --- /dev/null +++ b/src/test/workouts/fightclub.erg @@ -0,0 +1,155 @@ +[COURSE HEADER] +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = The Sufferfest - FLIGHT CLUB +FILE NAME = FIGHT_CLUB.ERG +FTP = 300 +MINUTES WATTS +[END COURSE HEADER] +[COURSE DATA] + +0.00 135 +1.03 135 +1.03 135 +3.98 135 +3.98 244 +6.17 244 +6.17 354 +7.77 354 +7.77 463 +9.63 463 +9.63 900 +9.87 900 +9.87 463 +10.58 463 +10.58 900 +10.82 900 +10.82 463 +11.25 463 +11.25 900 +11.48 900 +11.48 463 +12.40 463 +12.40 900 +12.62 900 +12.62 463 +13.78 463 +13.78 135 +15.50 135 +15.50 572 +16.58 572 +16.58 900 +16.82 900 +16.82 572 +17.87 572 +17.87 900 +18.08 900 +18.08 572 +19.58 572 +19.58 681 +20.35 681 +20.35 900 +20.58 900 +20.58 681 +21.25 681 +21.25 900 +21.48 900 +21.48 681 +22.25 681 +22.25 135 +25.65 135 +25.65 572 +26.80 572 +26.80 900 +27.03 900 +27.03 572 +27.72 572 +27.72 900 +27.93 900 +27.93 572 +29.85 572 +29.85 681 +30.65 681 +30.65 900 +30.87 900 +30.87 681 +31.73 681 +31.73 900 +31.95 900 +31.95 681 +32.40 681 +32.40 900 +32.63 900 +32.63 135 +36.08 135 +36.08 572 +37.08 572 +37.08 900 +37.30 900 +37.30 572 +38.95 572 +38.95 900 +39.18 900 +39.18 572 +39.57 572 +39.57 900 +39.68 900 +39.68 572 +40.47 572 +40.47 681 +40.83 681 +40.83 900 +41.07 900 +41.07 681 +41.70 681 +41.70 900 +41.93 900 +41.93 681 +42.67 681 +42.67 900 +42.80 900 +42.80 681 +43.05 681 +43.05 135 +46.32 135 +46.32 572 +46.87 572 +46.87 900 +47.08 900 +47.08 572 +47.55 572 +47.55 900 +47.78 900 +47.78 572 +48.80 572 +48.80 900 +49.00 900 +49.00 572 +49.85 572 +49.85 900 +49.98 900 +49.98 572 +50.17 572 +50.17 900 +50.52 900 +50.52 681 +51.00 681 +51.00 900 +51.22 900 +51.22 681 +51.70 681 +51.70 900 +51.82 900 +51.82 681 +52.35 681 +52.35 900 +52.57 900 +52.57 681 +53.12 681 +53.12 900 +53.53 900 +53.53 135 +59.05 135 + +[END COURSE DATA] + diff --git a/src/test/workouts/hunted.erg b/src/test/workouts/hunted.erg new file mode 100644 index 000000000..ec12cb4cd --- /dev/null +++ b/src/test/workouts/hunted.erg @@ -0,0 +1,89 @@ +[COURSE HEADER] +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = The Sufferfest - THE HUNTED +FILE NAME = THE_HUNTED.ERG +FTP = 300 +MINUTES WATTS +[END COURSE HEADER] +[COURSE DATA] + +0.00 244 +2.82 244 +2.82 354 +5.63 354 +5.63 408 +6.73 408 +6.73 463 +8.15 463 +8.15 518 +9.03 518 +9.03 791 +9.53 791 +9.53 572 +14.82 572 +14.82 244 +17.65 244 +17.65 572 +22.17 572 +22.17 681 +22.67 681 +22.67 572 +24.08 572 +24.08 627 +24.60 627 +24.60 681 +25.22 681 +25.22 572 +28.42 572 +28.42 681 +30.25 681 +30.25 736 +31.12 736 +31.12 627 +33.77 627 +33.77 900 +33.93 900 +33.93 681 +35.42 681 +35.42 736 +37.83 736 +37.83 244 +43.80 244 +43.80 518 +44.22 518 +44.22 572 +44.82 572 +44.82 518 +47.12 518 +47.12 572 +47.47 572 +47.47 518 +49.87 518 +49.87 518 +50.70 518 +50.70 791 +50.87 791 +50.87 518 +51.57 518 +51.57 791 +51.90 791 +51.90 518 +52.45 518 +52.45 791 +52.95 791 +52.95 518 +53.32 518 +53.32 791 +53.98 791 +53.98 518 +54.17 518 +54.17 791 +55.03 791 +55.03 791 +55.58 791 +55.58 244 +60.53 244 + +[END COURSE DATA] + diff --git a/src/test/workouts/localhero.erg b/src/test/workouts/localhero.erg new file mode 100644 index 000000000..ba81e31e8 --- /dev/null +++ b/src/test/workouts/localhero.erg @@ -0,0 +1,125 @@ +[COURSE HEADER] +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = The Sufferfest - LOCAL HERO +FILE NAME = LOCAL_HERO.ERG +FTP =300 +MINUTES WATTS +[END COURSE HEADER] +[COURSE DATA] + +0.00 244 +2.38 244 +2.38 354 +8.33 354 +8.33 463 +8.87 463 +8.87 518 +9.33 518 +9.33 572 +10.32 572 +10.32 463 +11.37 463 +11.37 681 +12.10 681 +12.10 736 +12.35 736 +12.35 354 +14.00 354 +14.00 572 +15.05 572 +15.05 627 +16.05 627 +16.05 681 +17.97 681 +17.97 627 +19.02 627 +19.02 572 +20.07 572 +20.07 244 +22.27 244 +22.27 572 +23.30 572 +23.30 627 +24.28 627 +24.28 681 +26.32 681 +26.32 627 +27.30 627 +27.30 572 +28.50 572 +28.50 244 +30.72 244 +30.72 572 +31.70 572 +31.70 627 +32.67 627 +32.67 681 +34.72 681 +34.72 627 +35.72 627 +35.72 572 +36.58 572 +36.58 244 +39.70 244 +39.70 627 +41.03 627 +41.03 681 +42.67 681 +42.67 244 +44.83 244 +44.83 681 +47.88 681 +47.88 244 +50.00 244 +50.00 681 +53.00 681 +53.00 244 +55.25 244 +55.25 791 +55.47 791 +55.47 681 +58.30 681 +58.30 244 +60.48 244 +60.48 681 +63.47 681 +63.47 244 +65.15 244 +65.15 572 +66.15 572 +66.15 681 +66.93 681 +66.93 900 +67.27 900 +67.27 244 +69.05 244 +69.05 572 +70.03 572 +70.03 681 +70.60 681 +70.60 900 +70.88 900 +70.88 244 +71.73 244 +71.73 572 +72.73 572 +72.73 681 +73.45 681 +73.45 900 +73.72 900 +73.72 244 +74.73 244 +74.73 572 +75.75 572 +75.75 681 +76.40 681 +76.40 900 +76.63 900 +76.63 244 +77.43 244 +77.43 135 +84.02 135 + +[END COURSE DATA] + diff --git a/src/test/workouts/revolver.erg b/src/test/workouts/revolver.erg new file mode 100644 index 000000000..1cc151ee2 --- /dev/null +++ b/src/test/workouts/revolver.erg @@ -0,0 +1,87 @@ +[COURSE HEADER] +VERSION = 2 +UNITS = ENGLISH +DESCRIPTION = The Sufferfest - REVOLVER +FILE NAME = REVOLVER.ERG +FTP = 300 +MINUTES WATTS +[END COURSE HEADER] +[COURSE DATA] + +0.00 135 +1.52 135 +1.52 244 +5.55 244 +5.55 354 +7.30 354 +7.30 572 +9.47 572 +9.47 244 +10.15 244 +10.15 900 +11.17 900 +11.17 135 +12.23 135 +12.23 900 +13.27 900 +13.27 135 +14.27 135 +14.27 900 +15.32 900 +15.32 135 +16.33 135 +16.33 900 +17.38 900 +17.38 135 +18.47 135 +18.47 900 +19.52 900 +19.52 135 +20.52 135 +20.52 900 +21.53 900 +21.53 135 +22.58 135 +22.58 900 +23.57 900 +23.57 135 +24.58 135 +24.58 900 +25.58 900 +25.58 135 +26.58 135 +26.58 900 +27.65 900 +27.65 135 +28.68 135 +28.68 900 +30.00 900 +30.00 135 +30.97 135 +30.97 900 +31.98 900 +31.98 135 +33.00 135 +33.00 900 +34.02 900 +34.02 135 +35.05 135 +35.05 900 +36.05 900 +36.05 135 +37.10 135 +37.10 900 +38.17 900 +38.17 135 +39.18 135 +39.18 900 +40.22 900 +40.22 135 +41.23 135 +41.23 900 +42.23 900 +42.23 135 +48.10 135 + +[END COURSE DATA] + diff --git a/src/xml/train-layout.xml b/src/xml/train-layout.xml index 527be3c25..678ae7e56 100644 --- a/src/xml/train-layout.xml +++ b/src/xml/train-layout.xml @@ -1,86 +1,122 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +