From b5ce92a04540a978f9b98f637e343c817732a6c6 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Fri, 14 Aug 2015 22:10:29 +0100 Subject: [PATCH] Formula config() function and test charts .. added config(cv) .. config(pmax) etc .. also added some test charts including one that just displays configuration --- src/DataFilter.cpp | 124 +++++++++++++++++++++++++++-- src/DataFilter.h | 1 + src/DataFilter.l | 4 + src/DataFilter.y | 7 +- src/LTMTool.cpp | 11 +++ test/charts/Accumulated Stress.xml | 3 + test/charts/Config Chart.xml | 3 + test/charts/Sport Mix.xml | 3 + 8 files changed, 150 insertions(+), 6 deletions(-) create mode 100644 test/charts/Accumulated Stress.xml create mode 100644 test/charts/Config Chart.xml create mode 100644 test/charts/Sport Mix.xml diff --git a/src/DataFilter.cpp b/src/DataFilter.cpp index 90cf2647b..550d770f7 100644 --- a/src/DataFilter.cpp +++ b/src/DataFilter.cpp @@ -25,6 +25,10 @@ #include "PMCData.h" #include +#include "Zones.h" +#include "PaceZones.h" +#include "HrZones.h" + #include "DataFilter_yacc.h" // LEXER VARIABLES WE INTERACT WITH @@ -113,7 +117,7 @@ void Leaf::print(Leaf *leaf, int level) leaf->print(leaf->lvalue.l, level+1); leaf->print(leaf->rvalue.l, level+1); break; - case Leaf::Function : qDebug()<<"function"<function<<"series="<<*(leaf->series->lvalue.n); + case Leaf::Function : qDebug()<<"function"<function<<"parm="<<*(leaf->series->lvalue.n); if (leaf->lvalue.l) leaf->print(leaf->lvalue.l, level+1); break; case Leaf::Conditional : qDebug()<<"cond"; @@ -238,7 +242,8 @@ void Leaf::validateFilter(DataFilter *df, Leaf *leaf) // is the symbol valid? QRegExp bestValidSymbols("^(apower|power|hr|cadence|speed|torque|vam|xpower|np|wpk)$", Qt::CaseInsensitive); QRegExp tizValidSymbols("^(power|hr)$", Qt::CaseInsensitive); - QString symbol = *(leaf->series->lvalue.n); + QRegExp configValidSymbols("^(cp|w\\'|pmax|cv|d\\'|scv|sd\\'|height|weight|lthr|maxhr|rhr|units)$", Qt::CaseInsensitive); + QString symbol = leaf->series->lvalue.n->toLower(); if (leaf->function == "sts" || leaf->function == "lts" || leaf->function == "sb" || leaf->function == "rr") { @@ -254,10 +259,15 @@ void Leaf::validateFilter(DataFilter *df, Leaf *leaf) if (leaf->function == "tiz" && !tizValidSymbols.exactMatch(symbol)) DataFiltererrors << QString(QObject::tr("invalid data series for tiz(): %1")).arg(symbol); - // now set the series type - leaf->seriesType = nameToSeries(symbol); - } + if (leaf->function == "config" && !configValidSymbols.exactMatch(symbol)) + DataFiltererrors << QString(QObject::tr("invalid data series for config(): %1")).arg(symbol); + if (leaf->function == "best" || leaf->function == "tiz") { + // now set the series type used as parameter 1 to best/tiz + leaf->seriesType = nameToSeries(symbol); + } + + } } break; @@ -521,7 +531,111 @@ Result Leaf::eval(Context *context, DataFilter *df, Leaf *leaf, RideItem *m) if (leaf->function == "rr") return Result(pmcData->rr(m->dateTime.date())); } + if (leaf->function == "config") { + // + // Get CP and W' estimates for date of ride + // + double CP = 0; + double WPRIME = 0; + double PMAX = 0; + int zoneRange; + + if (context->athlete->zones()) { + + // if range is -1 we need to fall back to a default value + zoneRange = context->athlete->zones()->whichRange(m->dateTime.date()); + CP = zoneRange >= 0 ? context->athlete->zones()->getCP(zoneRange) : 0; + WPRIME = zoneRange >= 0 ? context->athlete->zones()->getWprime(zoneRange) : 0; + PMAX = zoneRange >= 0 ? context->athlete->zones()->getPmax(zoneRange) : 0; + + // did we override CP in metadata ? + int oCP = m->getText("CP","0").toInt(); + int oW = m->getText("W'","0").toInt(); + int oPMAX = m->getText("Pmax","0").toInt(); + if (oCP) CP=oCP; + if (oW) WPRIME=oW; + if (oPMAX) PMAX=oPMAX; + } + + // + // LTHR, MaxHR, RHR + // + int hrZoneRange = context->athlete->hrZones() ? + context->athlete->hrZones()->whichRange(m->dateTime.date()) + : -1; + + int LTHR = hrZoneRange != -1 ? context->athlete->hrZones()->getLT(hrZoneRange) : 0; + int RHR = hrZoneRange != -1 ? context->athlete->hrZones()->getRestHr(hrZoneRange) : 0; + int MaxHR = hrZoneRange != -1 ? context->athlete->hrZones()->getMaxHr(hrZoneRange) : 0; + + // + // CV' D' + // + int paceZoneRange = context->athlete->paceZones(false) ? + context->athlete->paceZones(false)->whichRange(m->dateTime.date()) : + -1; + + double CV = (paceZoneRange != -1) ? context->athlete->paceZones(false)->getCV(paceZoneRange) : 0.0; + double DPRIME = 0; //XXX(paceZoneRange != -1) ? context->athlete->paceZones(false)->getDPrime(paceZoneRange) : 0.0; + + int spaceZoneRange = context->athlete->paceZones(true) ? + context->athlete->paceZones(true)->whichRange(m->dateTime.date()) : + -1; + double SCV = (spaceZoneRange != -1) ? context->athlete->paceZones(true)->getCV(spaceZoneRange) : 0.0; + double SDPRIME = 0; //XXX (spaceZoneRange != -1) ? context->athlete->paceZones(true)->getDPrime(spaceZoneRange) : 0.0; + + // + // HEIGHT and WEIGHT + // + double HEIGHT = m->getText("Height","0").toDouble(); + if (HEIGHT == 0) HEIGHT = context->athlete->getHeight(NULL); + double WEIGHT = m->getWeight(); + + QString symbol = leaf->series->lvalue.n->toLower(); + + if (symbol == "cp") { + return Result(CP); + } + if (symbol == "w'") { + return Result(WPRIME); + } + if (symbol == "pmax") { + return Result(PMAX); + } + if (symbol == "scv") { + return Result(SCV); + } + if (symbol == "sd'") { + return Result(SDPRIME); + } + if (symbol == "cv") { + return Result(CV); + } + if (symbol == "d'") { + return Result(DPRIME); + } + if (symbol == "lthr") { + return Result(LTHR); + } + if (symbol == "rhr") { + return Result(RHR); + } + if (symbol == "maxhr") { + return Result(MaxHR); + } + if (symbol == "weight") { + return Result(WEIGHT); + } + if (symbol == "height") { + return Result(HEIGHT); + } + if (symbol == "units") { + return Result(context->athlete->useMetricUnits ? 1 : 0); + } + } + + // get here for tiz and best switch (leaf->lvalue.l->type) { default: diff --git a/src/DataFilter.h b/src/DataFilter.h index ee176c126..9b06c67a1 100644 --- a/src/DataFilter.h +++ b/src/DataFilter.h @@ -73,6 +73,7 @@ class Leaf { int op; QString function; + Leaf *series; // is a symbol bool dynamic; RideFile::SeriesType seriesType; // for ridefilecache diff --git a/src/DataFilter.l b/src/DataFilter.l index 698edefe0..6ed69b88b 100644 --- a/src/DataFilter.l +++ b/src/DataFilter.l @@ -52,6 +52,7 @@ [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; +[Cc][Oo][Nn][Ff][Ii][Gg] strcpy(DataFilterlval.function, "config"); return CONFIG; "&&" DataFilterlval.op = AND; return AND; [Aa][nN][Dd] DataFilterlval.op = AND; return AND; @@ -72,6 +73,9 @@ "Max_W'_Expended" return SYMBOL; /* special case */ "W'_Work" return SYMBOL; /* special case */ "W'bal_TAU" return SYMBOL; /* special case */ +[Ww]\' return SYMBOL; /* special case */ +[Dd]\' return SYMBOL; /* special case */ +[Ss][Dd]\' return SYMBOL; /* special case */ [a-zA-Z0-9][a-zA-Z0-9_%™]+ return SYMBOL; /* symbols can start with 0-9 */ diff --git a/src/DataFilter.y b/src/DataFilter.y index 1f8cc74db..83165d39a 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 RR +%token BEST TIZ STS LTS SB RR CONFIG // comparative operators %token Q COL @@ -205,6 +205,11 @@ value : symbol { $$ = $1; } $$->series = $3; $$->lvalue.l = NULL; } + | CONFIG '(' symbol ')' { $$ = new Leaf(); $$->type = Leaf::Function; + $$->function = QString($1); + $$->series = $3; + $$->lvalue.l = NULL; + } ; %% diff --git a/src/LTMTool.cpp b/src/LTMTool.cpp index b3d1401db..ff4bfa20e 100644 --- a/src/LTMTool.cpp +++ b/src/LTMTool.cpp @@ -1737,6 +1737,17 @@ EditMetricDetailDialog::EditMetricDetailDialog(Context *context, LTMTool *ltmToo QStringList names = context->tab->rideNavigator()->logicalHeadings; // add functions ... + list << "config(cp)"; + list << "config(w')"; + list << "config(pmax)"; + list << "config(cv)"; + list << "config(scv)"; + list << "config(height)"; + list << "config(weight)"; + list << "config(lthr)"; + list << "config(maxhr)"; + list << "config(rhr)"; + list << "config(units)"; list << "ctl"; list << "tsb"; list << "atl"; diff --git a/test/charts/Accumulated Stress.xml b/test/charts/Accumulated Stress.xml new file mode 100644 index 000000000..690f7996b --- /dev/null +++ b/test/charts/Accumulated Stress.xml @@ -0,0 +1,3 @@ + + "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AAAAAAAAAAQAAAAAAAAAA///////////Af//Nzdvb6enAAAAAAAAP/AAAAAAAAAAAAAAAf//AAAAAAAAAAAAAAAAAAAAAAAAAA4Q/////wAAAAoAAAAAAAAAAAAAAAAMADIAIABQAGEAcgBtAAAAAAAAAAAAAA4QAQAAAAD/////AAABYABEAHUAcgBhAHQAaQBvAG4ACgAKACMAIAB0AHkAcABlACAAaQBuACAAYQAgAGYAbwByAG0AdQBsAGEAIAB0AG8AIAB1AHMAZQAKACMAIABmAG8AcgAgAGUALgBnAC4AIABUAFMAUwAgAC8AIABEAHUAcgBhAHQAaQBvAG4ACgAjACAAYQBzACAAeQBvAHUAIAB0AHkAcABlACAAdABoAGUAIABhAHYAYQBpAGwAYQBiAGwAZQAgAG0AZQB0AHIAaQBjAHMACgAjACAAdwBpAGwAbAAgAGIAZQAgAG8AZgBmAGUAcgBlAGQAIABiAHkAIABhAHUAdABvAGMAbwBtAHAAbABlAHQAZQAKACMAIABhAGwAbAAgAGwAaQBuAGUAcwAgAGIAZQBnAGkAbgBuAGkAbgBnACAAdwBpAHQAaAAgACMAIABhAHIAZQAgAGMAbwBtAG0AZQBuAHQAcwAuAAoAAAAEAAAAcgBmAGkAbAB0AGUAcgA6AGkAcwBSAHUAbgA9ADAAIABhAG4AZAAgAGkAcwBTAHcAaQBtAD0AMAAgAGEAbgBkACAAUgBvAHUAdABlACAAYgBlAGcAaQBuAHMAVwBpAHQAaAAgACIAQgBpAGwAbABpAG4AIgAAAAgA/////wAAAAAAAAAOAFIAZQBmAGYAaQBuAGcAAAAOAHMAZQBjAG8AbgBkAHMAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAEAAAAAAAAAAT//////////wH//1VVqqoAAAAAAAAAAD/wAAAAAAAAAAAAAAH//wAAAAAAAAAAAAAAAAEAAAAAAAAOEP////8AAAAKAAAAAAAAAAAAAAAADAAyACAAUABhAHIAbQAAAAAAAAAAAAAOEAAAAAAA/////wAAAXYAIwAgAFIAZQBmAGYAaQBuAGcACgAKAEQAdQByAGEAdABpAG8AbgAKAAoAIwAgAHQAeQBwAGUAIABpAG4AIABhACAAZgBvAHIAbQB1AGwAYQAgAHQAbwAgAHUAcwBlAAoAIwAgAGYAbwByACAAZQAuAGcALgAgAFQAUwBTACAALwAgAEQAdQByAGEAdABpAG8AbgAKACMAIABhAHMAIAB5AG8AdQAgAHQAeQBwAGUAIAB0AGgAZQAgAGEAdgBhAGkAbABhAGIAbABlACAAbQBlAHQAcgBpAGMAcwAKACMAIAB3AGkAbABsACAAYgBlACAAbwBmAGYAZQByAGUAZAAgAGIAeQAgAGEAdQB0AG8AYwBvAG0AcABsAGUAdABlAAoAIwAgAGEAbABsACAAbABpAG4AZQBzACAAYgBlAGcAaQBuAG4AaQBuAGcAIAB3AGkAdABoACAAIwAgAGEAcgBlACAAYwBvAG0AbQBlAG4AdABzAC4ACgAAAAQAAAA2AGYAaQBsAHQAZQByADoAVwBvAHIAawBvAHUAdABfAEMAbwBkAGUAIAA9ACAAIgBSAEUARgAiAAAAAAAD" + diff --git a/test/charts/Config Chart.xml b/test/charts/Config Chart.xml new file mode 100644 index 000000000..4ec7e0845 --- /dev/null +++ b/test/charts/Config Chart.xml @@ -0,0 +1,3 @@ + + "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OgAAAAgA/////wAAAAAAAAAEAEMAUAAAAAoAVwBhAHQAdABzAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAABAAAAAAAAAAD//////////8B////////f38AAAAAAAA/8AAAAAAAAAAAAAAB//8AAAAAAAAAAAAAAAAAAAAD5wAADhD/////AAAACgAAAAAAAAAAAAAAAAwAMgAgAFAAYQByAG0AAAAAAAAAAAAADhABAAAAAP////8AAAAWAGMAbwBuAGYAaQBnACgAQwBQACkACgAAAAIAAAAOAHMAZQBhAHIAYwBoADoAAAAIAP////8AAAAAAAAABABXACcAAAAMAEoAbwB1AGwAZQBzAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAABAAAAAAAAAAD//////////8B//9VVaqqAAAAAAAAAAA/8AAAAAAAAAAAAAAB//8AAAAAAAAAAAAAAAAAAAAD5wAADhD/////AAAACgAAAAAAAAAAAAAAAAwAMgAgAFAAYQByAG0AAAAAAAAAAAAADhABAAAAAP////8AAAAWAGMAbwBuAGYAaQBnACgAdwAnACkACgAAAAIAAAAOAHMAZQBhAHIAYwBoADoAAAAIAP////8AAAAAAAAACABQAE0AYQB4AAAACgBXAGEAdAB0AHMAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAEAAAAAAAAAAP//////////wH//1VV//9/fwAAAAAAAD/wAAAAAAAAAAAAAAH//wAAAAAAAAAAAAAAAAAAAAAAAAAOEP////8AAAAKAAAAAAAAAAAAAAAADAAyACAAUABhAHIAbQAAAAAAAAAAAAAOEAAAAAAA/////wAAABoAYwBvAG4AZgBpAGcAKABQAG0AYQB4ACkACgAAAAIAAAAOAHMAZQBhAHIAYwBoADoAAAAAAAM=" + diff --git a/test/charts/Sport Mix.xml b/test/charts/Sport Mix.xml new file mode 100644 index 000000000..07a9a4b42 --- /dev/null +++ b/test/charts/Sport Mix.xml @@ -0,0 +1,3 @@ + + "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" +