diff --git a/src/DataFilter.cpp b/src/DataFilter.cpp index 2197e7dc8..16f231a08 100644 --- a/src/DataFilter.cpp +++ b/src/DataFilter.cpp @@ -217,7 +217,7 @@ void Leaf::validateFilter(DataFilter *df, Leaf *leaf) QRegExp tizValidSymbols("^(power|hr)$", Qt::CaseInsensitive); QString symbol = *(leaf->series->lvalue.n); - if (leaf->function == "sts" || leaf->function == "lts" || leaf->function == "sb") { + if (leaf->function == "sts" || leaf->function == "lts" || leaf->function == "sb" || leaf->function == "rr") { // does the symbol exist though ? QString lookup = df->lookupMap.value(symbol, ""); @@ -423,7 +423,7 @@ double Leaf::eval(Context *context, DataFilter *df, Leaf *leaf, RideItem *m) double duration; // pmc data ... - if (leaf->function == "sts" || leaf->function == "lts" || leaf->function == "sb") { + if (leaf->function == "sts" || leaf->function == "lts" || leaf->function == "sb" || leaf->function == "rr") { // get metric technical name QString symbol = *(leaf->series->lvalue.n); @@ -433,6 +433,7 @@ double Leaf::eval(Context *context, DataFilter *df, Leaf *leaf, RideItem *m) if (leaf->function == "sts") return pmcData->sts(m->dateTime.date()); if (leaf->function == "lts") return pmcData->lts(m->dateTime.date()); if (leaf->function == "sb") return pmcData->sb(m->dateTime.date()); + if (leaf->function == "rr") return pmcData->rr(m->dateTime.date()); } diff --git a/src/DataFilter.l b/src/DataFilter.l index deaec8940..9c9e38881 100644 --- a/src/DataFilter.l +++ b/src/DataFilter.l @@ -49,6 +49,7 @@ [Ll][Tt][Ss] strcpy(DataFilterlval.function, "lts"); return LTS; [Ss][Tt][Ss] strcpy(DataFilterlval.function, "sts"); return STS; [Ss][Bb] strcpy(DataFilterlval.function, "sb"); return SB; +[Rr][Rr] strcpy(DataFilterlval.function, "rr"); return RR; "&&" DataFilterlval.op = AND; return AND; [Aa][nN][Dd] DataFilterlval.op = AND; return AND; diff --git a/src/DataFilter.y b/src/DataFilter.y index 97426146a..8fe0624fe 100644 --- a/src/DataFilter.y +++ b/src/DataFilter.y @@ -54,7 +54,7 @@ extern Leaf *root; // root node for parsed statement // Constants can be a string or a number %token DF_STRING DF_INTEGER DF_FLOAT -%token BEST TIZ STS LTS SB +%token BEST TIZ STS LTS SB RR // comparative operators %token EQ NEQ LT LTE GT GTE @@ -175,6 +175,11 @@ value : symbol { $$ = $1; } $$->series = $3; $$->lvalue.l = NULL; } + | RR '(' symbol ')' { $$ = new Leaf(); $$->type = Leaf::Function; + $$->function = QString($1); + $$->series = $3; + $$->lvalue.l = NULL; + } | SB '(' symbol ')' { $$ = new Leaf(); $$->type = Leaf::Function; $$->function = QString($1); $$->series = $3; diff --git a/src/LTMPlot.cpp b/src/LTMPlot.cpp index 72970044c..8ae7df1b7 100644 --- a/src/LTMPlot.cpp +++ b/src/LTMPlot.cpp @@ -2651,6 +2651,8 @@ LTMPlot::createPMCData(Context *context, LTMSettings *settings, MetricDetail met stressType = STRESS_STS; else if (metricDetail.symbol.endsWith("sb")) stressType = STRESS_SB; + else if (metricDetail.symbol.endsWith("lr")) + stressType = STRESS_RR; } else { @@ -2707,6 +2709,9 @@ LTMPlot::createPMCData(Context *context, LTMSettings *settings, MetricDetail met case STRESS_SB: value = pmcData->sb(date); break; + case STRESS_RR: + value = pmcData->rr(date); + break; default: value = 0; break; diff --git a/src/PMCData.cpp b/src/PMCData.cpp index c2438ac2d..f9652ae4f 100644 --- a/src/PMCData.cpp +++ b/src/PMCData.cpp @@ -125,6 +125,7 @@ void PMCData::refresh() lts_.resize(days_); sts_.resize(days_); sb_.resize(days_+1); // for SB tomorrow! + rr_.resize(days_); // for SB tomorrow! } else { @@ -136,6 +137,7 @@ void PMCData::refresh() lts_.resize(0); sts_.resize(0); sb_.resize(0); + rr_.resize(0); // give up return; @@ -154,6 +156,7 @@ void PMCData::refresh() lts_.fill(0); sts_.fill(0); sb_.fill(0); + rr_.fill(0); // add the seeded values from seasons foreach(Season x, context->athlete->seasons->seasons) { @@ -176,11 +179,13 @@ void PMCData::refresh() } // - // STEP THREE Calculate sts/lts and sb + // STEP THREE Calculate sts/lts, sb and rr // double lastLTS=0.0f; double lastSTS=0.0f; + double rollingStress=0; + for(int day=0; day < days_; day++) { // not seeded @@ -200,6 +205,17 @@ void PMCData::refresh() sts_[day] *= -1; } + // rolling stress for STS days + if (day && day <= stsDays_) { + // just starting out + rollingStress += lts_[day] - lts_[day-1]; + rr_[day] = rollingStress; + } else if (day) { + rollingStress += lts_[day] - lts_[day-1]; + rollingStress -= lts_[day-stsDays_] - lts_[day-stsDays_-1]; + rr_[day] = rollingStress; + } + // SB (stress balance) long term - short term // We allow it to be shown today or tomorrow where // most (sane/thinking) folks usually show SB on the following day @@ -264,3 +280,13 @@ PMCData::sb(QDate date) if (index == -1) return 0.0f; else return sb_[index]; } + +double +PMCData::rr(QDate date) +{ + refresh(); + + int index=indexOf(date); + if (index == -1) return 0.0f; + else return rr_[index]; +} diff --git a/src/PMCData.h b/src/PMCData.h index 93d23c057..764a83f0a 100644 --- a/src/PMCData.h +++ b/src/PMCData.h @@ -63,6 +63,7 @@ class PMCData : public QObject { QVector <s() { return lts_; } QVector &sts() { return sts_; } QVector &sb() { return sb_; } + QVector &rr() { return rr_; } // index into the arrays int indexOf(QDate) ; @@ -72,6 +73,7 @@ class PMCData : public QObject { double sts(QDate); double stress(QDate); double sb(QDate); + double rr(QDate); public slots: @@ -95,7 +97,7 @@ class PMCData : public QObject { // data QDate start_, end_; int days_; - QVector stress_, lts_, sts_, sb_; + QVector stress_, lts_, sts_, sb_, rr_; bool isstale; // needs refreshing };