From 169bd9c4e08da48bbc8f866314e89c12c34dd386 Mon Sep 17 00:00:00 2001 From: Mark Liversedge Date: Sun, 12 Jul 2020 09:12:46 +0100 Subject: [PATCH] Datafilter String Support - 1 of 4 .. Strings and vectors of strings are useful for plotting bar charts or wherever category variables are needed, they are also useful when working with xdata names and metadata within ride files. .. Full support for strings will be introduced over the next 4 commits, including this one (1 of 4): 1 - Basics - Create, Assign, Coerce, isString 2 - Operators - Logical, Math etc 3 - Functions - sort, uniq, aggregate etc 4 - String Functions - cat, split, toupper/lower etc .. Will wait until all 4 commits are completed and string support is feature complete before updating the wiki. --- src/Charts/LTMPlot.cpp | 2 +- src/Charts/OverviewItems.cpp | 4 +- src/Charts/UserChart.cpp | 4 +- src/Charts/UserChartData.cpp | 2 +- src/Core/DataFilter.cpp | 884 ++++++++++++++++++----------------- src/Core/DataFilter.h | 57 ++- src/Core/UserData.cpp | 2 +- src/Gui/SearchFilterBox.cpp | 2 +- src/Metrics/PMCData.cpp | 2 +- src/Metrics/UserMetric.cpp | 6 +- 10 files changed, 516 insertions(+), 449 deletions(-) diff --git a/src/Charts/LTMPlot.cpp b/src/Charts/LTMPlot.cpp index ff2137571..f7d31dbf2 100644 --- a/src/Charts/LTMPlot.cpp +++ b/src/Charts/LTMPlot.cpp @@ -2841,7 +2841,7 @@ LTMPlot::createFormulaData(Context *context, LTMSettings *settings, MetricDetail // PARSE + EVALUATE Result res = parser.evaluate(ride, NULL); - if (res.isNumber) value = res.number; + if (res.isNumber) value = res.number(); // check values are bounded to stop QWT going berserk if (std::isnan(value) || std::isinf(value)) value = 0; diff --git a/src/Charts/OverviewItems.cpp b/src/Charts/OverviewItems.cpp index efbba5ce6..b1c7d71f3 100644 --- a/src/Charts/OverviewItems.cpp +++ b/src/Charts/OverviewItems.cpp @@ -429,7 +429,7 @@ KPIOverviewItem::setData(RideItem *item) Result res = parser.evaluate(item, NULL); // set to zero for daft values - value = QString("%1").arg(res.number); + value = QString("%1").arg(res.number()); if (value == "nan") value =""; value=Utils::removeDP(value); @@ -448,7 +448,7 @@ KPIOverviewItem::setDateRange(DateRange dr) Result res = parser.evaluate(dr, datafilter); // set to zero for daft values - value = QString("%1").arg(res.number); + value = QString("%1").arg(res.number()); if (value == "nan") value =""; value=Utils::removeDP(value); diff --git a/src/Charts/UserChart.cpp b/src/Charts/UserChart.cpp index 325c7a879..57290eebb 100644 --- a/src/Charts/UserChart.cpp +++ b/src/Charts/UserChart.cpp @@ -159,8 +159,8 @@ UserChart::setRide(RideItem *item) // cast so we can work with it UserChartData *ucd = static_cast(series.user1); ucd->compute(ride, Specification(), dr); - series.xseries = ucd->x.vector; - series.yseries = ucd->y.vector; + series.xseries = ucd->x.asNumeric(); + series.yseries = ucd->y.asNumeric(); // data now generated so can add curve chart->addCurve(series.name, series.xseries, series.yseries, series.xname, series.yname, diff --git a/src/Charts/UserChartData.cpp b/src/Charts/UserChartData.cpp index c1fbfa71b..7991ad716 100644 --- a/src/Charts/UserChartData.cpp +++ b/src/Charts/UserChartData.cpp @@ -67,7 +67,7 @@ UserChartData::compute(RideItem *item, Specification spec, DateRange dr) // is it relevant ? if (frelevant) { relevant = root->eval(rt, frelevant, 0, 0, const_cast(item), NULL, NULL, spec, dr); - if (relevant.number == 0) return; + if (relevant.number() == 0) return; } // process samples, if there are any and a function exists diff --git a/src/Core/DataFilter.cpp b/src/Core/DataFilter.cpp index d4771f2ee..4200cf3cc 100644 --- a/src/Core/DataFilter.cpp +++ b/src/Core/DataFilter.cpp @@ -301,6 +301,9 @@ static struct { { "sort", 2 }, // sort(ascend|descend, list) - returns sorted list { "uniq", 1 }, // uniq(list) - returns only uniq values in the list, stable and preserves order + { "isNumber", 1 }, // is the passed thing a number or list of numbers ? + { "isString", 1 }, // is the passed thing a string or list of strings ? + // add new ones above this line { "", -1 } }; @@ -1278,14 +1281,27 @@ void Leaf::print(int level, DataFilterRuntime *df) case Leaf::Symbol : { Result value = df->symbols.value(*lvalue.n), Result(11); - qDebug()<<"symbol"<<*lvalue.n<lvalue.l->lvalue.n); df->symbols.insert(symbol, Result(0)); - // validate rhs is numeric - bool rhsType = Leaf::isNumber(df, leaf->rvalue.l); - if (!rhsType) { - DataFiltererrors << QString(tr("variables must be numeric.")); - leaf->inerror = true; - } - // assign to symbol[i] - must be to a user symbol } else if (leaf->lvalue.l->type == Leaf::Index) { @@ -2564,13 +2573,6 @@ void Leaf::validateFilter(Context *context, DataFilterRuntime *df, Leaf *leaf) leaf->inerror = true; } - // validate rhs is numeric - bool rhsType = Leaf::isNumber(df, leaf->rvalue.l); - if (!rhsType) { - DataFiltererrors << QString(tr("variables must be numeric.")); - leaf->inerror = true; - } - // validate the lhs anyway validateFilter(context, df, leaf->lvalue.l); @@ -2851,7 +2853,7 @@ QStringList DataFilter::parseFilter(Context *context, QString query, QStringList // evaluate each ride... Result result = treeRoot->eval(&rt, treeRoot, 0, 0,item, NULL); - if (result.isNumber && result.number) { + if (result.isNumber && result.number()) { filenames << item->fileName; } } @@ -2877,7 +2879,7 @@ DataFilter::dynamicParse() // evaluate each ride... Result result = treeRoot->eval(&rt, treeRoot, 0, 0, item, NULL); - if (result.isNumber && result.number) + if (result.isNumber && result.number()) filenames << item->fileName; } emit results(filenames); @@ -2936,19 +2938,19 @@ void Result::vectorize(int count) { - if (vector.count() >= count) return; + if (asNumeric().count() >= count) return; // ok, so must have at least 1 element to repeat - if (vector.count() == 0) vector << number; + if (asNumeric().count() == 0) asNumeric() << number(); // repeat for size int it=0; - int n=vector.count(); + int n=asNumeric().count(); // repeat whatever we have - while (vector.count() < count) { - vector << vector[it]; - number += vector[it]; + while (asNumeric().count() < count) { + asNumeric() << asNumeric()[it]; + number() += asNumeric()[it]; // loop thru wot we have it++; if (it == n) it=0; @@ -2992,19 +2994,19 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem case AND : { Result left = eval(df, leaf->lvalue.l,x, it, m, p, c, s, d); - if (left.isNumber && left.number) { + if (left.isNumber && left.number()) { Result right = eval(df, leaf->rvalue.l,x, it, m, p, c, s, d); - if (right.isNumber && right.number) return Result(true); + if (right.isNumber && right.number()) return Result(true); } return Result(false); } case OR : { Result left = eval(df, leaf->lvalue.l,x, it, m, p, c, s, d); - if (left.isNumber && left.number) return Result(true); + if (left.isNumber && left.number()) return Result(true); Result right = eval(df, leaf->rvalue.l,x, it, m, p, c, s, d); - if (right.isNumber && right.number) return Result(true); + if (right.isNumber && right.number()) return Result(true); return Result(false); } @@ -3043,6 +3045,14 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem return res; } + if (leaf->function == "isNumber") { + return eval(df, leaf->fparms[0],x, it, m, p, c, s, d).isNumber; + } + + if (leaf->function == "isString") { + return !eval(df, leaf->fparms[0],x, it, m, p, c, s, d).isNumber; + } + if (leaf->function == "exists") { // get symbol name QString symbol = *(leaf->fparms[0]->lvalue.s); @@ -3071,7 +3081,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // so work out the date range QDate earliest(1900,01,01); - DateRange ourdaterange(earliest.addDays(from.number), earliest.addDays(to.number)); + DateRange ourdaterange(earliest.addDays(from.number()), earliest.addDays(to.number())); // return the expression, evaluated using our daterange return eval(df, leaf->fparms[2],x, it, m, p, c, s, ourdaterange); @@ -3200,31 +3210,43 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // bool(expr) if (leaf->function == "bool") { Result r=eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (r.number != 0) return Result(1); + if (r.number() != 0) return Result(1); else return Result(0); } // c (concat into a vector) + // since we now support string and numeric values and vectors + // we create a numeric vector by default. + // If any values are found that are strings we convert all values + // to strings avoid double looping if (leaf->function == "c") { // the return value of a vector is always its sum // so we need to keep that up to date too Result returning(0); + // first evaluate all the parameters + // so we can iterate over them + QVector results; + bool asstring=false; for(int i=0; ifparms.count(); i++) { - Result r=eval(df, leaf->fparms[i],x, it, m, p, c, s, d); - if (r.vector.count()) { - returning.vector.append(r.vector); - returning.number += r.number; - } else if (r.isNumber) { - returning.vector.append(r.number); - returning.number += r.number; + Result r = eval(df, leaf->fparms[i],x, it, m, p, c, s, d); + results << r; + if (!r.isNumber) asstring=true; + } + + // now iterate and store + if (asstring) returning.isNumber = false; + for(int i=0; ifunction == "seq") { Result returning(0); - double start= eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number; - double stop= eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number; - double step= eval(df, leaf->fparms[2],x, it, m, p, c, s, d).number; + double start= eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number(); + double stop= eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number(); + double step= eval(df, leaf->fparms[2],x, it, m, p, c, s, d).number(); if (step == 0) return returning; // nope! if (start > stop && step >0) return returning; // nope @@ -3244,15 +3266,15 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // ok lets go if (step > 0) { while(start <= stop) { - returning.vector.append(start); + returning.asNumeric().append(start); start += step; - returning.number += start; + returning.number() += start; } } else { while (start >= stop) { - returning.vector.append(start); + returning.asNumeric().append(start); start += step; - returning.number += start; + returning.number() += start; } } @@ -3264,14 +3286,14 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->function == "rep") { Result returning(0); - double value= eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number; - double count= eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number; + double value= eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number(); + double count= eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number(); if (count <= 0) return returning; while (count >0) { - returning.vector.append(value); - returning.number += value; + returning.asNumeric().append(value); + returning.number() += value; count--; } return returning; @@ -3281,11 +3303,11 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->function == "rev") { Result returning(0); Result value= eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (value.vector.count() > 0){ - for(int i=value.vector.count()-1; i>=0; i--) { - double v = value.vector.at(i); - returning.vector << v; - returning.number += v; + if (value.asNumeric().count() > 0){ + for(int i=value.asNumeric().count()-1; i>=0; i--) { + double v = value.asNumeric().at(i); + returning.asNumeric() << v; + returning.number() += v; } } return returning; @@ -3293,7 +3315,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // length if (leaf->function == "length") { - double len = eval(df, leaf->fparms[0],x, it, m, p, c, s, d).vector.count(); + double len = eval(df, leaf->fparms[0],x, it, m, p, c, s, d).asNumeric().count(); //fprintf(stderr, "len: %f\n",len); fflush(stderr); return Result(len); } @@ -3303,13 +3325,13 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result returning(0); Result v = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (v.vector.count() == 0) return Result(v.number); + if (v.asNumeric().count() == 0) return Result(v.number()); double cumsum = 0; - for(int i=0; i < v.vector.count(); i++) { - cumsum += v.vector[i]; - returning.number += cumsum; - returning.vector << cumsum; + for(int i=0; i < v.asNumeric().count(); i++) { + cumsum += v.asNumeric()[i]; + returning.number() += cumsum; + returning.asNumeric() << cumsum; } return returning; } @@ -3327,19 +3349,19 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result returning(0); // lets bin - if (bins.vector.count() > 1 && values.vector.count() > 1) { + if (bins.asNumeric().count() > 1 && values.asNumeric().count() > 1) { // returns a vector with same number of bins as the bins vector - returning.vector.fill(0, bins.vector.size()); + returning.asNumeric().fill(0, bins.asNumeric().size()); // loop across the values updating the count for the relevant bin - for(int i=0; i=0; bin--) { - if (value > bins.vector.at(bin)) { - returning.vector[bin]++; + for(int bin=bins.asNumeric().count()-1; bin>=0; bin--) { + if (value > bins.asNumeric().at(bin)) { + returning.asNumeric()[bin]++; break; } } @@ -3361,31 +3383,31 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // anything other than a vector makes no sense, so // lets turn a number into a vector of 1 value - if (v.vector.count()==0) v.vector << v.number; - if (by.vector.count()==0) by.vector << by.number; + if (v.asNumeric().count()==0) v.asNumeric() << v.number(); + if (by.asNumeric().count()==0) by.asNumeric() << by.number(); // state as we loop through a group - double last=by.vector[0]; // we setup for very first group + double last=by.asNumeric()[0]; // we setup for very first group double count=0, value=0; bool first=true; - for(int byit=0,it=0; it < v.vector.count(); byit++,it++) { + for(int byit=0,it=0; it < v.asNumeric().count(); byit++,it++) { // repeat by, in cases where fewer entries than in // the vector being aggregated - if (byit >= by.vector.count()) byit=0; + if (byit >= by.asNumeric().count()) byit=0; // add last and reset for next group - if (last != by.vector[byit]) { - returning.number += value; // sum - returning.vector << value; + if (last != by.asNumeric()[byit]) { + returning.number() += value; // sum + returning.asNumeric() << value; value=0; count=0; first=true; // first in group } // update the aggregate for this group - double xx = v.vector[it]; + double xx = v.asNumeric()[it]; count++; // mean @@ -3412,13 +3434,13 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem } // on to the next - last = by.vector[byit]; + last = by.asNumeric()[byit]; first = false; } // the last - returning.number += value; // sum - returning.vector << value; + returning.number() += value; // sum + returning.asNumeric() << value; return returning; } @@ -3434,34 +3456,34 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // where to place it? -1 on end (not passed as a parameter) int pos=-1; - if (leaf->fparms.count() == 3) pos = eval(df, leaf->fparms[2],x, it, m, p, c, s, d).number; + if (leaf->fparms.count() == 3) pos = eval(df, leaf->fparms[2],x, it, m, p, c, s, d).number(); // check for bounds - if (pos <0 || pos >current.vector.count()) pos=-1; + if (pos <0 || pos >current.asNumeric().count()) pos=-1; // ok, what to append Result append = eval(df, leaf->fparms[1],x, it, m, p, c, s, d); // do it... - if (append.vector.count()) { + if (append.asNumeric().count()) { - if (pos==-1) current.vector.append(append.vector); + if (pos==-1) current.asNumeric().append(append.asNumeric()); else { // insert at pos - for(int i=0; isymbols.insert(symbol, current); - return Result(current.vector.count()); + return Result(current.asNumeric().count()); } // remove @@ -3474,25 +3496,25 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result current = df->symbols.value(symbol); // where to place it? -1 on end (not passed as a parameter) - long pos = eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number; + long pos = eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number(); // ok, what to append - long count = eval(df, leaf->fparms[2],x, it, m, p, c, s, d).number; + long count = eval(df, leaf->fparms[2],x, it, m, p, c, s, d).number(); // check.. and return unchanged if out of bounds - if (pos < 0 || pos > current.vector.count() || pos+count >current.vector.count()) { - return Result(current.vector.count()); + if (pos < 0 || pos > current.asNumeric().count() || pos+count >current.asNumeric().count()) { + return Result(current.asNumeric().count()); } // so lets do it // do it... - current.vector.remove(pos, count); + current.asNumeric().remove(pos, count); // update value df->symbols.insert(symbol, current); - return Result(current.vector.count()); + return Result(current.asNumeric().count()); } // mid @@ -3503,19 +3525,19 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // mid (a, pos, count) // where to place it? -1 on end (not passed as a parameter) Result v = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - long pos = eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number; - long count = eval(df, leaf->fparms[2],x, it, m, p, c, s, d).number; + long pos = eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number(); + long count = eval(df, leaf->fparms[2],x, it, m, p, c, s, d).number(); // check.. and return unchanged if out of bounds - if (pos < 0 || pos > v.vector.count() || pos+count >v.vector.count()) { + if (pos < 0 || pos > v.asNumeric().count() || pos+count >v.asNumeric().count()) { return returning; } // so lets do it- remember to sum - returning.vector = v.vector.mid(pos, count); - returning.number = 0; - for(int i=0; iseriesType == RideFile::wbal || leaf->seriesType == RideFile::none) { // W'Bal and W'Bal time - returning.vector = leaf->seriesType == RideFile::wbal ? m->ride()->wprimeData()->ydata() : m->ride()->wprimeData()->xdata(false); - for(int i=0; iseriesType == RideFile::wbal ? m->ride()->wprimeData()->ydata() : m->ride()->wprimeData()->xdata(false); + for(int i=0; iseriesType == RideFile::none) returning.vector[i] = returning.vector.at(i) * 60.0; + if (leaf->seriesType == RideFile::none) returning.asNumeric()[i] = returning.asNumeric().at(i) * 60.0; // calculate sum for both - returning.number += returning.vector.at(i); // sum + returning.number() += returning.asNumeric().at(i); // sum } } else { @@ -3559,8 +3581,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem while(it.hasNext()) { struct RideFilePoint *p = it.next(); double value=p->value(leaf->seriesType); - returning.number += value; - returning.vector.append(value); + returning.number() += value; + returning.asNumeric().append(value); } } } @@ -3588,10 +3610,10 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // start to stop Result b = eval(df, leaf->fparms[1],x, it, m, p, c, s, d); - QDate start = earliest.addDays(b.number); + QDate start = earliest.addDays(b.number()); Result e = eval(df, leaf->fparms[2],x, it, m, p, c, s, d); - QDate stop = earliest.addDays(e.number); + QDate stop = earliest.addDays(e.number()); spec.setDateRange(DateRange(start,stop)); @@ -3599,7 +3621,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // start to today Result b = eval(df, leaf->fparms[1],x, it, m, p, c, s, d); - QDate start = earliest.addDays(b.number); + QDate start = earliest.addDays(b.number()); QDate stop = QDate::currentDate(); spec.setDateRange(DateRange(start,stop)); @@ -3620,8 +3642,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem double value=0; if(wantdate) value= QDate(1900,01,01).daysTo(ride->dateTime.date()); else value = ride->getForSymbol(df->lookupMap.value(symbol,"")); - returning.number += value; - returning.vector.append(value); + returning.number() += value; + returning.asNumeric().append(value); } return returning; } @@ -3664,8 +3686,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (wantdate) value = earliest.daysTo(date); else value = m->context->athlete->measures->getFieldValue(group,date,field); - returning.number += value; - returning.vector << value; + returning.number() += value; + returning.asNumeric() << value; } return returning; } @@ -3684,7 +3706,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // offset by one in the parameters list if (leaf->seriesType != RideFile::none) { po=1; - duration = eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number; + duration = eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number(); } FilterSet fs; @@ -3699,10 +3721,10 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // start to stop Result b = eval(df, leaf->fparms[1+po],x, it, m, p, c, s, d); - QDate start = earliest.addDays(b.number); + QDate start = earliest.addDays(b.number()); Result e = eval(df, leaf->fparms[2+po],x, it, m, p, c, s, d); - QDate stop = earliest.addDays(e.number); + QDate stop = earliest.addDays(e.number()); spec.setDateRange(DateRange(start,stop)); @@ -3710,7 +3732,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // start to today Result b = eval(df, leaf->fparms[1+po],x, it, m, p, c, s, d); - QDate start = earliest.addDays(b.number); + QDate start = earliest.addDays(b.number()); QDate stop = QDate::currentDate(); spec.setDateRange(DateRange(start,stop)); @@ -3720,8 +3742,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem } // get the cache, for the selected date range - returning.vector = RideFileCache::getAllBestsFor(m->context, leaf->seriesType, duration, spec); - for(int i=0; icontext, leaf->seriesType, duration, spec); + for(int i=0; ifileCache()->meanMaxArray(RideFile::watts); - for(int i=0; ifileCache()->meanMaxArray(RideFile::watts); + for(int i=0; ifileCache()->meanMaxArray(leaf->seriesType); + } else returning.asNumeric() = m->fileCache()->meanMaxArray(leaf->seriesType); } else { @@ -3760,23 +3782,23 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result start = eval(df, leaf->fparms[1],x, it, m, p, c, s, d); Result stop = eval(df, leaf->fparms[2],x, it, m, p, c, s, d); - from = earliest.addDays(start.number); - to = earliest.addDays(stop.number); + from = earliest.addDays(start.number()); + to = earliest.addDays(stop.number()); } // use a season meanmax RideFileCache bestsCache(m->context, from, to, false, QStringList(), true, NULL); // get meanmax, unless its efforts, where we do rather more... - if (symbol != "efforts") returning.vector = bestsCache.meanMaxArray(leaf->seriesType); + if (symbol != "efforts") returning.asNumeric() = bestsCache.meanMaxArray(leaf->seriesType); else { // get power anyway - returning.vector = bestsCache.meanMaxArray(RideFile::watts); + returning.asNumeric() = bestsCache.meanMaxArray(RideFile::watts); // need more than 2 entries - if (returning.vector.count() > 3) { + if (returning.asNumeric().count() > 3) { // we need to return an index to use to filter values // in the meanmax array; remove sub-maximals by @@ -3785,10 +3807,10 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // get data to filter QVector t; - t.resize(returning.vector.size()); + t.resize(returning.asNumeric().size()); for (int i=0; i p = returning.vector; + QVector p = returning.asNumeric(); QVector w = bestsCache.meanMaxDates(leaf->seriesType); t.remove(0); p.remove(0); @@ -3884,9 +3906,9 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // we keep t[0] as it gets removed in // all cases below, saves a bit of // torturous logic later - returning.vector.clear(); - returning.vector << 0;// it gets removed - for(int i=0; i 0) returning.vector << i; + returning.asNumeric().clear(); + returning.asNumeric() << 0;// it gets removed + for(int i=0; i 0) returning.asNumeric() << i; } } } @@ -3894,10 +3916,10 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // really annoying that it starts from 0s not 1s, this is a legacy // bug that we cannot fix easily, but this is new, so lets not // have that damned 0s 0w entry! - if (returning.vector.count()>0) returning.vector.remove(0); + if (returning.asNumeric().count()>0) returning.asNumeric().remove(0); // compute the sum, ugh. - for(int i=0; ifparms.count() == 2) { // calculate a meanmax curve using the passed x and y values @@ -3916,15 +3938,15 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem double offset=0; double maxx=0, lastx=0; bool interpolate=false; - for(int i=0; i < xvector.vector.count(); i++) { + for(int i=0; i < xvector.asNumeric().count(); i++) { // truncate y values if x values are missing - if (i >= yvector.vector.count()) break; + if (i >= yvector.asNumeric().count()) break; // set the offset - if (i==0 && xvector.vector.at(0) > 0) offset=xvector.vector.at(0); + if (i==0 && xvector.asNumeric().at(0) > 0) offset=xvector.asNumeric().at(0); - double xv = xvector.vector.at(i) - offset; + double xv = xvector.asNumeric().at(i) - offset; if (xv >= 24*3600) break; // thats enough 24hr activity is long enough if (xv >=0) { @@ -3933,7 +3955,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (xv-lastx > 0) interpolate = true; // we discard negative values of x - double yv = yvector.vector.at(i); + double yv = yvector.asNumeric().at(i); if (yv <0) yv=0; // add into x and y @@ -3992,8 +4014,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem for(int i=1; i0) { - returning.vector << value; - returning.number += value; + returning.asNumeric() << value; + returning.number() += value; } } } @@ -4014,7 +4036,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result yvector = eval(df, leaf->fparms[2],x, it, m, p, c, s, d); Result xvalues = eval(df, leaf->fparms[3],x, it, m, p, c, s, d); - int n = yvector.vector.count() < xvector.vector.count() ? yvector.vector.count() : xvector.vector.count(); + int n = yvector.asNumeric().count() < xvector.asNumeric().count() ? yvector.asNumeric().count() : xvector.asNumeric().count(); if (n >2) { @@ -4025,17 +4047,17 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem else if (algo == "steffen") interpolation = gsl_interp_alloc (gsl_interp_akima,n); else interpolation = gsl_interp_alloc (gsl_interp_linear,n); // linear is the fallback, always - gsl_interp_init(interpolation, xvector.vector.constData(), yvector.vector.constData(), n); + gsl_interp_init(interpolation, xvector.asNumeric().constData(), yvector.asNumeric().constData(), n); gsl_interp_accel *accelerator = gsl_interp_accel_alloc(); // truncate ydata as we will refill them - for(int i=0; ifparms[0],x, it, m, p, c, s, d).number; - double to = eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number; + double from = eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number(); + double to = eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number(); Result y =eval(df, leaf->fparms[2],x, it, m, p, c, s, d); // if in doubt just return it unchanged. - if (y.vector.count() < 3 || from <= 0 || to <= 0 || from == to) return y; + if (y.asNumeric().count() < 3 || from <= 0 || to <= 0 || from == to) return y; // lets prepare data for libsamplerate SRC_DATA data; float *input, *output, *source, *target; - float insamples = y.vector.count(); - float outsamples = 1+ ((y.vector.count() * from) / to); // 1+ for rounding up + float insamples = y.asNumeric().count(); + float outsamples = 1+ ((y.asNumeric().count() * from) / to); // 1+ for rounding up // allocate memory source = input = (float*)malloc(sizeof(float) * insamples); target = output = (float*)malloc(sizeof(float) * outsamples); // create the input array (float not double) - for(int i=0; ifileCache()->distributionArray(leaf->seriesType).count(); double delta = RideFileCache::binsize(leaf->seriesType); for (double it=0; it fileCache()->distributionArray(leaf->seriesType); - for(int i=0; ifileCache()->distributionArray(leaf->seriesType); + for(int i=0; iseriesType).count(); double delta = RideFileCache::binsize(leaf->seriesType); for (double it=0; it seriesType); - for(int i=0; iseriesType); + for(int i=0; ifparms[1],x, it, m, p, c, s, d); - QVector r = Utils::argsort(v.vector, ascending); + QVector r = Utils::argsort(v.asNumeric(), ascending); // put the index into the result we are returning. foreach(int x, r) { - returning.vector << static_cast(x); - returning.number += x; + returning.asNumeric() << static_cast(x); + returning.number() += x; } return returning; @@ -4192,12 +4214,12 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // use the utils function to actually do it Result v = eval(df, leaf->fparms[1],x, it, m, p, c, s, d); - QVector r = Utils::rank(v.vector, ascending); + QVector r = Utils::rank(v.asNumeric(), ascending); // put the index into the result we are returning. foreach(int x, r) { - returning.number += x; - returning.vector << static_cast(x); + returning.number() += x; + returning.asNumeric() << static_cast(x); } return returning; @@ -4214,13 +4236,13 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // use the utils function to actually do it Result v = eval(df, leaf->fparms[1],x, it, m, p, c, s, d); - if (ascending) qSort(v.vector); - else qSort(v.vector.begin(), v.vector.end(), doubledescend); + if (ascending) qSort(v.asNumeric()); + else qSort(v.asNumeric().begin(), v.asNumeric().end(), doubledescend); // put the index into the result we are returning. - foreach(double x, v.vector) { - returning.number += x; - returning.vector << x; + foreach(double x, v.asNumeric()) { + returning.number() += x; + returning.asNumeric() << x; } return returning; @@ -4233,12 +4255,12 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // evaluate all the lists Result v = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - QVector index = Utils::arguniq(v.vector); + QVector index = Utils::arguniq(v.asNumeric()); for(int idx=0; idxfparms[0],x, it, m, p, c, s, d); - QVector r = Utils::arguniq(v.vector); + QVector r = Utils::arguniq(v.asNumeric()); for(int i=0; ifparms[0]->lvalue.n); Result current = df->symbols.value(symbol); - long len = current.vector.count(); - QVector index = Utils::arguniq(current.vector); + long len = current.asNumeric().count(); + QVector index = Utils::arguniq(current.asNumeric()); // sort all the lists in place int count=0; @@ -4279,15 +4301,15 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result current = df->symbols.value(symbol); // diff length? - if (current.vector.count() != len) { + if (current.asNumeric().count() != len) { fprintf(stderr, "multiuniq list '%s': not the same length, ignored\n", symbol.toStdString().c_str()); fflush(stderr); continue; } // ok so now we can adjust QVector replace; - for(int idx=0; idxsymbols.insert(symbol, current); @@ -4311,8 +4333,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (df->chart->seriesinfo[i].name == symbol) { // woop! QString data=*(leaf->fparms[1]->lvalue.n); - if (data == "x") returning.vector = df->chart->seriesinfo[i].xseries; - if (data == "y") returning.vector = df->chart->seriesinfo[i].yseries; + if (data == "x") returning.asNumeric() = df->chart->seriesinfo[i].xseries; + if (data == "y") returning.asNumeric() = df->chart->seriesinfo[i].yseries; // z d t still todo XXX } } @@ -4328,26 +4350,26 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result value= eval(df, leaf->fparms[1],x, it, m, p, c, s, d); // empty list - error - if (list.vector.count() == 0) return returning; + if (list.asNumeric().count() == 0) return returning; // lets do it with std::lower_bound then - QVector::const_iterator i = std::lower_bound(list.vector.begin(), list.vector.end(), value.number, comparedouble()); + QVector::const_iterator i = std::lower_bound(list.asNumeric().begin(), list.asNumeric().end(), value.number(), comparedouble()); - if (i == list.vector.end()) return Result(list.vector.size()); - return Result(i - list.vector.begin()); + if (i == list.asNumeric().end()) return Result(list.asNumeric().size()); + return Result(i - list.asNumeric().begin()); } // random if (leaf->function == "random") { - int n= eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number; // how many ? + int n= eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number(); // how many ? Result returning(0); // Random number function based on the GNU Scientific Library while(n>0) { double random = gsl_rng_uniform(df->owner->r); // Generate it! - returning.number += random; - returning.vector << random; + returning.number() += random; + returning.asNumeric() << random; n--; } return returning; @@ -4361,26 +4383,26 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result quantiles= eval(df, leaf->fparms[1],x, it, m, p, c, s, d); Result returning(0); - if (v.vector.count() > 0) { + if (v.asNumeric().count() > 0) { // sort the vector first - qSort(v.vector); + qSort(v.asNumeric()); - if (quantiles.vector.count() ==0) { - double quantile = quantiles.number; + if (quantiles.asNumeric().count() ==0) { + double quantile = quantiles.number(); if (quantile < 0) quantile=0; if (quantile > 1) quantile=1; - double value = gsl_stats_quantile_from_sorted_data(v.vector.constData(), 1, v.vector.count(), quantile); - returning.number = value; + double value = gsl_stats_quantile_from_sorted_data(v.asNumeric().constData(), 1, v.asNumeric().count(), quantile); + returning.number() = value; } else { - for (int i=0; i 1) quantile=1; - double value = gsl_stats_quantile_from_sorted_data(v.vector.constData(), 1, v.vector.count(), quantile); - returning.number += value; - returning.vector << value; + double value = gsl_stats_quantile_from_sorted_data(v.asNumeric().constData(), 1, v.asNumeric().count(), quantile); + returning.number() += value; + returning.asNumeric() << value; } } } @@ -4400,8 +4422,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // get first and argsort it symbol = *(leaf->fparms[1]->lvalue.n); Result current = df->symbols.value(symbol); - long len = current.vector.count(); - QVector index = Utils::argsort(current.vector, ascending); + long len = current.asNumeric().count(); + QVector index = Utils::argsort(current.asNumeric(), ascending); // sort all the lists in place int count=0; @@ -4411,15 +4433,15 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result current = df->symbols.value(symbol); // diff length? - if (current.vector.count() != len) { + if (current.asNumeric().count() != len) { fprintf(stderr, "multisort list '%s': not the same length, ignored\n", symbol.toStdString().c_str()); fflush(stderr); continue; } // ok so now we can adjust - QVector replace = current.vector; - for(int idx=0; idx replace = current.asNumeric(); + for(int idx=0; idxsymbols.insert(symbol, current); @@ -4435,13 +4457,13 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result list= eval(df, leaf->fparms[0],x, it, m, p, c, s, d); Result count= eval(df, leaf->fparms[1],x, it, m, p, c, s, d); - int n=count.number; - if (n > list.vector.count()) n=list.vector.count(); + int n=count.number(); + if (n > list.asNumeric().count()) n=list.asNumeric().count(); if (n<=0) return Result(0);// nope - returning.vector = list.vector.mid(0, n); - for(int i=0; ifparms[0],x, it, m, p, c, s, d); Result count= eval(df, leaf->fparms[1],x, it, m, p, c, s, d); - int n=count.number; - if (n > list.vector.count()) n=list.vector.count(); + int n=count.number(); + if (n > list.asNumeric().count()) n=list.asNumeric().count(); if (n<=0) return Result(0);// nope - returning.vector = list.vector.mid(list.vector.count()-n, n); - for(int i=0; ifparms[0],x, it, m, p, c, s, d); // lhs might also be a symbol // need a vector, always - if (!value.vector.count()) return returning; + if (!value.asNumeric().count()) return returning; // loop and evaluate, non-zero we keep, zero we lose - for(int i=0; ifparms[1],x, i, m, p, c, s, d).number; + for(int i=0; ifparms[1],x, i, m, p, c, s, d).number(); // we want it - returning.vector << r; - returning.number += r; + returning.asNumeric() << r; + returning.number() += r; } return returning; } @@ -4497,12 +4519,12 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result v2 = eval(df,leaf->fparms[1],x, it, m, p, c, s, d); // lhs might also be a symbol // lets search - for(int i=0; ifparms[0],x, it, m, p, c, s, d); // lhs might also be a symbol - if (v.vector.count() > 0) { - for (int i=0; i < v.vector.count(); i++) { - if (v.vector[i] != 0) { - returning.vector << i; - returning.number += i; + if (v.asNumeric().count() > 0) { + for (int i=0; i < v.asNumeric().count(); i++) { + if (v.asNumeric()[i] != 0) { + returning.asNumeric() << i; + returning.number() += i; } } } @@ -4546,11 +4568,11 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // evaluate expression to get value/vector Result value = eval(df,leaf->fparms[i],x, it, m, p, c, s, d); - if (value.vector.count() > 0) { - for(int ii=0; ii 0) { + for(int ii=0; iifparms[1]->lvalue.n) == "sma") { QString type = *(leaf->fparms[2]->lvalue.n); - int window = eval(df,leaf->fparms[3],x, it, m, p, c, s, d).number; + int window = eval(df,leaf->fparms[3],x, it, m, p, c, s, d).number(); Result data = eval(df,leaf->fparms[0],x, it, m, p, c, s, d); int pos=2; // fallback @@ -4577,19 +4599,19 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (type=="forward") pos=1; if (type=="centered") pos=2; - returning.vector = Utils::smooth_sma(data.vector, pos, window); + returning.asNumeric() = Utils::smooth_sma(data.asNumeric(), pos, window); } else if (*(leaf->fparms[1]->lvalue.n) == "ewma") { // exponentially weighted moving average - double alpha = eval(df,leaf->fparms[2],x, it, m, p, c, s, d).number; + double alpha = eval(df,leaf->fparms[2],x, it, m, p, c, s, d).number(); Result data = eval(df,leaf->fparms[0],x, it, m, p, c, s, d); - returning.vector = Utils::smooth_ewma(data.vector, alpha); + returning.asNumeric() = Utils::smooth_ewma(data.asNumeric(), alpha); } // sum. ugh. - for(int i=0; ifunction == "lm") { Result returning(0); - returning.vector << 0 << -1 << -1 ; // assume failure + returning.asNumeric() << 0 << -1 << -1 ; // assume failure Leaf *formula = leaf->fparms[0]; Result xv = eval(df,leaf->fparms[1],x, it, m, p, c, s, d); Result yv = eval(df,leaf->fparms[2],x, it, m, p, c, s, d); // check ok to proceed - if (xv.vector.count() < 3 || xv.vector.count() != yv.vector.count()) return returning; + if (xv.asNumeric().count() < 3 || xv.asNumeric().count() != yv.asNumeric().count()) return returning; // use the power duration model using for a data filter expression DFModel model(m, formula, df); - bool success = model.fitData(xv.vector, yv.vector); + bool success = model.fitData(xv.asNumeric(), yv.asNumeric()); if (success) { // first entry is sucess - returning.vector[0] = 1; + returning.asNumeric()[0] = 1; // second entry is RMSE double sume2=0, sum=0; - for(int index=0; indexfunction == "lr") { Result returning(0); - returning.vector << 0 << 0 << 0 << 0; // set slope, intercept, r2 and see to 0 + returning.asNumeric() << 0 << 0 << 0 << 0; // set slope, intercept, r2 and see to 0 Result xv = eval(df,leaf->fparms[0],x, it, m, p, c, s, d); Result yv = eval(df,leaf->fparms[1],x, it, m, p, c, s, d); // check ok to proceed - if (xv.vector.count() < 2 || xv.vector.count() != yv.vector.count()) return returning; + if (xv.asNumeric().count() < 2 || xv.asNumeric().count() != yv.asNumeric().count()) return returning; // use the generic calculator, its quick and easy GenericCalculator calc; calc.initialise(); - for (int i=0; i< xv.vector.count(); i++) - calc.addPoint(QPointF(xv.vector[i], yv.vector[i])); + for (int i=0; i< xv.asNumeric().count(); i++) + calc.addPoint(QPointF(xv.asNumeric()[i], yv.asNumeric()[i])); calc.finalise(); // extract LR results - returning.vector[0]=calc.m; - returning.vector[1]=calc.b; - returning.vector[2]=calc.r2; - returning.vector[3]=calc.see; - returning.number = calc.m + calc.b + calc.r2 + calc.see; // sum + returning.asNumeric()[0]=calc.m; + returning.asNumeric()[1]=calc.b; + returning.asNumeric()[2]=calc.r2; + returning.asNumeric()[3]=calc.see; + returning.number() = calc.m + calc.b + calc.r2 + calc.see; // sum return returning; } @@ -4673,14 +4695,14 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // get y vector Result yv = eval(df,leaf->fparms[0],x, it, m, p, c, s, d); - int n = yv.vector.count(); + int n = yv.asNumeric().count(); int xn = leaf->fparms.count()-1; // first parm is yvector gsl_matrix *X = gsl_matrix_calloc(n, xn); gsl_vector *Y = gsl_vector_alloc(n); gsl_vector *coeff = gsl_vector_alloc(xn); // the coefficients we want to return // setup the y vector - for (int i = 0; i < n; i++) gsl_vector_set(Y, i, yv.vector[i]); + for (int i = 0; i < n; i++) gsl_vector_set(Y, i, yv.asNumeric()[i]); // populate the x matrix, 1 column per predictor, n rows of datavalues // if xvector is too small, we pad with 0 values - no repeating here ?fix later? @@ -4688,7 +4710,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result xv = eval(df,leaf->fparms[xi],x, it, m, p, c, s, d); for (int i=0; i < n; i++) { double value=0; - if (i < xv.vector.count()) value= xv.vector[i]; + if (i < xv.asNumeric().count()) value= xv.asNumeric()[i]; gsl_matrix_set(X, i, xi-1, value); } } @@ -4702,8 +4724,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // covariance matrix for now, may look to pass them back later for (int i = 0; i < xn; i++) { double value= gsl_vector_get(coeff, i); - returning.vector << value; - returning.number += value; + returning.asNumeric() << value; + returning.number() += value; } gsl_matrix_free(X); @@ -4720,14 +4742,14 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // array Result v = eval(df,leaf->fparms[0],x, it, m, p, c, s, d); Statistic calc; - return calc.variance(v.vector, v.vector.count()); + return calc.variance(v.asNumeric(), v.asNumeric().count()); } if (leaf->function == "stddev") { // array Result v = eval(df,leaf->fparms[0],x, it, m, p, c, s, d); Statistic calc; - return calc.standarddeviation(v.vector, v.vector.count()); + return calc.standarddeviation(v.asNumeric(), v.asNumeric().count()); } // pmc @@ -4754,8 +4776,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (series == "rr") value = pmcData->rr()[si]; if (series == "sb") value = pmcData->sb()[si]; - returning.vector << value; - returning.number += value; + returning.asNumeric() << value; + returning.number() += value; } si++; @@ -4792,8 +4814,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (value == "cp") x = banister->data[si].perf ? (banister->data[si].perf * 261.0 / 100.0) : 0; if (value == "date") x = earliest.daysTo(QDateTime(date, QTime(0,0,0))); - returning.vector << x; - returning.number += x; + returning.asNumeric() << x; + returning.number() += x; } si++; @@ -4811,14 +4833,14 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->fparms.count() != 1) return returning; Result v = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (v.vector.count()) { - for(int i=0; ifparms.count() != 1) return returning; Result v = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (v.vector.count()) { - for(int i=0; ifparms.count() != 1) return returning; Result v = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (v.vector.count()) { - for(int i=0; ifparms.count() != 1) return returning; Result v = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (v.vector.count()) { - for(int i=0; ilvalue.l,x, it, m, p, c, s, d).number; // duration will be zero if string + duration = eval(df, leaf->lvalue.l,x, it, m, p, c, s, d).number(); // duration will be zero if string } break; @@ -5002,14 +5024,14 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem } Result v = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (v.vector.count()) { - for(int i=0; ifparms) { - sum += eval(df, l,x, it, m, p, c, s, d).number; // for vectors number is sum + sum += eval(df, l,x, it, m, p, c, s, d).number(); // for vectors number is sum } return Result(sum); } @@ -5033,8 +5055,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem foreach(Leaf *l, leaf->fparms) { Result res = eval(df, l,x, it, m, p, c, s, d); // for vectors number is sum - sum += res.number; - if (res.vector.count()) count += res.vector.count(); + sum += res.number(); + if (res.asNumeric().count()) count += res.asNumeric().count(); else count++; } return count ? Result(sum/double(count)) : Result(0); @@ -5047,18 +5069,18 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // collect the values foreach(Leaf *l, leaf->fparms) { Result res = eval(df, l,x, it, m, p, c, s, d); // for vectors number is sum - if (res.vector.count()) vector.vector.append(res.vector); - else vector.vector << res.number; + if (res.asNumeric().count()) vector.asNumeric().append(res.asNumeric()); + else vector.asNumeric() << res.number(); } - if (vector.vector.count() < 1) return Result(0); - if (vector.vector.count() == 1) return Result(vector.vector.at(0)); + if (vector.asNumeric().count() < 1) return Result(0); + if (vector.asNumeric().count() == 1) return Result(vector.asNumeric().at(0)); // sort and find the one in the middle - qSort(vector.vector); + qSort(vector.asNumeric()); // let gsl do it - double median = gsl_stats_median_from_sorted_data(vector.vector.constData(), 1, vector.vector.count()); + double median = gsl_stats_median_from_sorted_data(vector.asNumeric().constData(), 1, vector.asNumeric().count()); return Result(median); } break; @@ -5069,13 +5091,13 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // collect the values foreach(Leaf *l, leaf->fparms) { Result res = eval(df, l,x, it, m, p, c, s, d); // for vectors number is sum - if (res.vector.count()) vector.vector.append(res.vector); - else vector.vector << res.number; + if (res.asNumeric().count()) vector.asNumeric().append(res.asNumeric()); + else vector.asNumeric() << res.number(); } // lets get a count going QMap counter; - foreach(double value, vector.vector){ + foreach(double value, vector.asNumeric()){ int now = counter.value(value, 0); now++; counter.insert(value, now); @@ -5112,15 +5134,15 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem foreach(Leaf *l, leaf->fparms) { Result res = eval(df, l,x, it, m, p, c, s, d); - if (res.vector.count()) { - foreach(double x, res.vector) { + if (res.asNumeric().count()) { + foreach(double x, res.asNumeric()) { if (set && x>max) max=x; else if (!set) { set=true; max=x; } } } else { - if (set && res.number>max) max=res.number; - else if (!set) { set=true; max=res.number; } + if (set && res.number()>max) max=res.number(); + else if (!set) { set=true; max=res.number(); } } } return Result(max); @@ -5133,15 +5155,15 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem foreach(Leaf *l, leaf->fparms) { Result res = eval(df, l,x, it, m, p, c, s, d); - if (res.vector.count()) { - foreach(double x, res.vector) { + if (res.asNumeric().count()) { + foreach(double x, res.asNumeric()) { if (set && xfparms) { Result res = eval(df, l,x, it, m, p, c, s, d); - if (res.vector.count()) count += res.vector.count(); + if (res.asNumeric().count()) count += res.asNumeric().count(); else count++; } return Result(count); @@ -5195,7 +5217,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // what we looking for ? QString parm = leaf->fparms[1]->type == Leaf::Symbol ? *leaf->fparms[1]->lvalue.n : ""; bool toDuration = parm == "" ? true : false; - double duration = toDuration ? eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number : 0; + double duration = toDuration ? eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number() : 0; if (fnum == 30) { @@ -5286,8 +5308,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (parm == "date") { v1=dfrom; v2=dto; } } - returning.number += v1+v2; - returning.vector << v1 << v2; + returning.number() += v1+v2; + returning.asNumeric() << v1 << v2; } } return returning; @@ -5312,26 +5334,26 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // evaluate the parameter Result ex = eval(df, leaf->fparms[i],x, it, m, p, c, s, d); - if (ex.vector.count()) { + if (ex.asNumeric().count()) { // tiz a vector - foreach(double x, ex.vector) { + foreach(double x, ex.asNumeric()) { // did it get selected? Result which = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (which.number) { - returning.vector << x; - returning.number += x; + if (which.number()) { + returning.asNumeric() << x; + returning.number() += x; } } } else { // does the parameter get selected ? - Result which = eval(df, leaf->fparms[0], ex.number, it, m, p, c, s); //XXX it should be local index - if (which.number) { - returning.vector << ex.number; - returning.number += ex.number; + Result which = eval(df, leaf->fparms[0], ex.number(), it, m, p, c, s); //XXX it should be local index + if (which.number()) { + returning.asNumeric() << ex.number(); + returning.number() += ex.number(); } } } @@ -5346,7 +5368,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->fparms.count() < 3) return returning; else returning = eval(df, leaf->fparms[2],x, it, m, p, c, s, d); - if (returning.number) { + if (returning.number()) { // symbol we are setting QString symbol = *(leaf->fparms[0]->lvalue.n); @@ -5372,7 +5394,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem override = f->metricOverrides.value(o_symbol); // clear and reset override value for this metric - override.insert("value", QString("%1").arg(r.number)); // add metric value + override.insert("value", QString("%1").arg(r.number())); // add metric value // update overrides for this metric in the main QMap f->metricOverrides.insert(o_symbol, override); @@ -5390,9 +5412,9 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // are we using the right types ? if (r.isNumber && isnumeric) { - f->setTag(o_symbol, QString("%1").arg(r.number)); + f->setTag(o_symbol, QString("%1").arg(r.number())); } else if (!r.isNumber && !isnumeric) { - f->setTag(o_symbol, r.string); + f->setTag(o_symbol, r.string()); } else { // nope return Result(0); // not changing it ! @@ -5416,7 +5438,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->fparms.count() < 2) return returning; else returning = eval(df, leaf->fparms[1],x, it, m, p, c, s, d); - if (returning.number) { + if (returning.number()) { // symbol we are setting QString symbol = *(leaf->fparms[0]->lvalue.n); @@ -5490,7 +5512,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->fparms.count() != 2) return Result(0); - return Result (60*VDOTCalculator::eqvTime(eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number, 1000*eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number)); + return Result (60*VDOTCalculator::eqvTime(eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number(), 1000*eval(df, leaf->fparms[1],x, it, m, p, c, s, d).number())); } break; @@ -5499,7 +5521,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->fparms.count() != 1 || m->fileCache() == NULL) return Result(0); - return Result (m->fileCache()->bestTime(eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number)); + return Result (m->fileCache()->bestTime(eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number())); } case 37 : @@ -5556,7 +5578,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->fparms.count() != 1) return returning; else returning = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); - if (returning.number) { + if (returning.number()) { // ack ! we need to autoprocess, so open the ride RideFile *f = m->ride(); @@ -5580,7 +5602,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem if (leaf->fparms.count() < 2) return returning; else returning = eval(df, leaf->fparms[1],x, it, m, p, c, s, d); - if (returning.number) { + if (returning.number()) { // processor we are running QString dp_name = *(leaf->fparms[0]->lvalue.n); @@ -5641,7 +5663,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result days = eval(df, leaf->fparms[0],x, it, m, p, c, s, d); if (!days.isNumber) return Result(0); // invalid date - QDate date = QDate(1900,01,01).addDays(days.number); + QDate date = QDate(1900,01,01).addDays(days.number()); if (!date.isValid()) return Result(0); // invalid date if (leaf->fparms[1]->type != String) return Result(0); @@ -5715,8 +5737,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem foreach(IntervalItem *i, m->intervals()) { if (i->istest()) { double value= wantduration ? i->getForSymbol("workout_time") : i->getForSymbol("average_power"); - returning.number += value; - returning.vector << value; + returning.number() += value; + returning.asNumeric() << value; } } } else { @@ -5724,8 +5746,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Performance onday = m->context->athlete->rideCache->estimator->getPerformanceForDate(m->dateTime.date(), false); //XXX fixme for runs if (onday.duration >0) { double value = wantduration ? onday.duration : onday.power; - returning.number += value; - returning.vector << value; + returning.number() += value; + returning.asNumeric() << value; } } @@ -5752,8 +5774,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem foreach(IntervalItem *i, ride->intervals()) { if (i->istest()) { double value= wantduration ? i->getForSymbol("workout_time") : i->getForSymbol("average_power"); - returning.number += value; - returning.vector << value; + returning.number() += value; + returning.asNumeric() << value; } } } @@ -5765,8 +5787,8 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem foreach(Performance p, perfs) { if (p.submaximal == false && p.run == false && p.when >= d.from && p.when <= d.to) { // XXX fixme p.run == false double value = wantduration ? p.duration : p.power; - returning.number += value; - returning.vector << value; + returning.number() += value; + returning.asNumeric() << value; } } } @@ -5775,7 +5797,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem } } break; - case 63 : { return Result(sqrt(eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number)); } // SQRT(x) + case 63 : { return Result(sqrt(eval(df, leaf->fparms[0],x, it, m, p, c, s, d).number())); } // SQRT(x) default: return Result(0); @@ -5945,10 +5967,10 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result lhs = eval(df, leaf->lvalue.l,x, it, m, p, c, s, d); // unary minus - if (leaf->op == '-') return Result(lhs.number * -1); + if (leaf->op == '-') return Result(lhs.number() * -1); // unary not - if (leaf->op == '!') return Result(!lhs.number); + if (leaf->op == '!') return Result(!lhs.number()); // unknown return(Result(0)); @@ -5967,7 +5989,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // if elvis we only evaluate rhs if we are null Result rhs; - if (leaf->op != ELVIS || lhs.number == 0) { + if (leaf->op != ELVIS || lhs.number() == 0) { rhs = eval(df, leaf->rvalue.l,x, it, m, p, c, s, d); } @@ -5979,14 +6001,11 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // LHS MUST be a symbol... if (leaf->lvalue.l->type == Leaf::Symbol || leaf->lvalue.l->type == Leaf::Index) { - // get value to assign from rhs - Result value(rhs.isNumber ? rhs : Result(0)); - if (leaf->lvalue.l->type == Leaf::Symbol) { // update the symbol value QString symbol = *(leaf->lvalue.l->lvalue.n); - df->symbols.insert(symbol, value); + df->symbols.insert(symbol, rhs); } else { @@ -6002,27 +6021,25 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result sym = df->symbols.value(symbol); QVector selected; - if (indexes.vector.count()) selected=indexes.vector; - else selected << indexes.number; + if (indexes.asNumeric().count()) selected=indexes.asNumeric(); + else selected << indexes.number(); for(int i=0; i< selected.count(); i++) { int index=static_cast(selected[i]); // resize if need to - if (sym.vector.count() <= index) { - sym.vector.resize(index+1); - } + if (sym.isNumber && sym.asNumeric().count() <= index) { sym.asNumeric().resize(index+1); } // add value - sym.vector[index] = value.number; + sym.asNumeric()[index] = rhs.number(); //XXX todo for string arrays } // update df->symbols.insert(symbol, sym); } } - return value; + return rhs; } // shouldn't get here! return Result(RideFile::NA); @@ -6045,17 +6062,17 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem // its a vector operation... - if (lhs.vector.count() || rhs.vector.count()) { + if (lhs.asNumeric().count() || rhs.asNumeric().count()) { - int size = lhs.vector.count() > rhs.vector.count() ? lhs.vector.count() : rhs.vector.count(); + int size = lhs.asNumeric().count() > rhs.asNumeric().count() ? lhs.asNumeric().count() : rhs.asNumeric().count(); // coerce both into a vector of matching size lhs.vectorize(size); rhs.vectorize(size); for(int i=0; iop) { @@ -6065,17 +6082,17 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem case MULTIPLY: value = left * right; break; case POW: value = pow(left,right); break; } - returning.vector << value; - returning.number += value; + returning.asNumeric() << value; + returning.number() += value; } } else { switch (leaf->op) { - case ADD: returning.number = lhs.number + rhs.number; break; - case SUBTRACT: returning.number = lhs.number - rhs.number; break; - case DIVIDE: returning.number = rhs.number ? lhs.number / rhs.number : 0; break; - case MULTIPLY: returning.number = lhs.number * rhs.number; break; - case POW: returning.number = pow(lhs.number, rhs.number); break; + case ADD: returning.number() = lhs.number() + rhs.number(); break; + case SUBTRACT: returning.number() = lhs.number() - rhs.number(); break; + case DIVIDE: returning.number() = rhs.number() ? lhs.number() / rhs.number() : 0; break; + case MULTIPLY: returning.number() = lhs.number() * rhs.number(); break; + case POW: returning.number() = pow(lhs.number(), rhs.number()); break; } } } @@ -6085,40 +6102,40 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem case EQ: { - if (lhs.isNumber) return Result(lhs.number == rhs.number); - else return Result(lhs.string == rhs.string); + if (lhs.isNumber) return Result(lhs.number() == rhs.number()); + else return Result(lhs.string() == rhs.string()); } break; case NEQ: { - if (lhs.isNumber) return Result(lhs.number != rhs.number); - else return Result(lhs.string != rhs.string); + if (lhs.isNumber) return Result(lhs.number() != rhs.number()); + else return Result(lhs.string() != rhs.string()); } break; case LT: { - if (lhs.isNumber) return Result(lhs.number < rhs.number); - else return Result(lhs.string < rhs.string); + if (lhs.isNumber) return Result(lhs.number() < rhs.number()); + else return Result(lhs.string() < rhs.string()); } break; case LTE: { - if (lhs.isNumber) return Result(lhs.number <= rhs.number); - else return Result(lhs.string <= rhs.string); + if (lhs.isNumber) return Result(lhs.number() <= rhs.number()); + else return Result(lhs.string() <= rhs.string()); } break; case GT: { - if (lhs.isNumber) return Result(lhs.number > rhs.number); - else return Result(lhs.string > rhs.string); + if (lhs.isNumber) return Result(lhs.number() > rhs.number()); + else return Result(lhs.string() > rhs.string()); } break; case GTE: { - if (lhs.isNumber) return Result(lhs.number >= rhs.number); - else return Result(lhs.string >= rhs.string); + if (lhs.isNumber) return Result(lhs.number() >= rhs.number()); + else return Result(lhs.string() >= rhs.string()); } break; @@ -6126,27 +6143,27 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem { // it was evaluated above, which is kinda cheating // but its optimal and this is a special case. - if (lhs.isNumber && lhs.number) return Result(lhs.number); - else return Result(rhs.number); + if (lhs.isNumber && lhs.number()) return Result(lhs.number()); + else return Result(rhs.number()); } case MATCHES: - if (!lhs.isNumber && !rhs.isNumber) return Result(QRegExp(rhs.string).exactMatch(lhs.string)); + if (!lhs.isNumber && !rhs.isNumber) return Result(QRegExp(rhs.string()).exactMatch(lhs.string())); else return Result(false); break; case ENDSWITH: - if (!lhs.isNumber && !rhs.isNumber) return Result(lhs.string.endsWith(rhs.string)); + if (!lhs.isNumber && !rhs.isNumber) return Result(lhs.string().endsWith(rhs.string())); else return Result(false); break; case BEGINSWITH: - if (!lhs.isNumber && !rhs.isNumber) return Result(lhs.string.startsWith(rhs.string)); + if (!lhs.isNumber && !rhs.isNumber) return Result(lhs.string().startsWith(rhs.string())); else return Result(false); break; case CONTAINS: { - if (!lhs.isNumber && !rhs.isNumber) return Result(lhs.string.contains(rhs.string) ? true : false); + if (!lhs.isNumber && !rhs.isNumber) return Result(lhs.string().contains(rhs.string()) ? true : false); else return Result(false); } break; @@ -6169,7 +6186,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem case 0 : { Result cond = eval(df, leaf->cond.l,x, it, m, p, c, s, d); - if (cond.isNumber && cond.number) return eval(df, leaf->lvalue.l,x, it, m, p, c, s, d); + if (cond.isNumber && cond.number()) return eval(df, leaf->lvalue.l,x, it, m, p, c, s, d); else { // conditional may not have an else clause! @@ -6187,7 +6204,7 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem timer.start(); Result returning(0); - while (count++ < maxwhile && eval(df, leaf->cond.l,x, it, m, p, c, s, d).number) { + while (count++ < maxwhile && eval(df, leaf->cond.l,x, it, m, p, c, s, d).number()) { returning = eval(df, leaf->lvalue.l,x, it, m, p, c, s, d); } @@ -6209,24 +6226,24 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result value = eval(df,leaf->lvalue.l,x, it, m, p, c, s, d); // lhs might also be a symbol // are we returning the value or a vector of values? - if (index.vector.count()) { + if (index.asNumeric().count()) { Result returning(0); // a range - for(int i=0; i= value.vector.count()) continue; // ignore out of bounds - returning.vector << value.vector[ii]; - returning.number += value.vector[ii]; + for(int i=0; i= value.asNumeric().count()) continue; // ignore out of bounds + returning.asNumeric() << value.asNumeric()[ii]; + returning.number() += value.asNumeric()[ii]; } return returning; } else { // a single value - if (index.number < 0 || index.number >= value.vector.count()) return Result(0); - return Result(value.vector[index.number]); + if (index.number() < 0 || index.number() >= value.asNumeric().count()) return Result(0); + return Result(value.asNumeric()[index.number()]); } } @@ -6239,17 +6256,17 @@ Result Leaf::eval(DataFilterRuntime *df, Leaf *leaf, float x, long it, RideItem Result value = eval(df,leaf->lvalue.l,x, it, m, p, c, s, d); // lhs might also be a symbol // need a vector, always - if (!value.vector.count()) return returning; + if (!value.asNumeric().count()) return returning; // loop and evaluate, non-zero we keep, zero we lose - for(int i=0; ifparms[0],x, i, m, p, c, s, d).number; + for(int i=0; ifparms[0],x, i, m, p, c, s, d).number(); // we want it if (boolresult != 0) { - returning.vector << x; - returning.number += x; + returning.asNumeric() << x; + returning.number() += x; } } @@ -6295,14 +6312,14 @@ DFModel::f(double t, const double *parms) for (int i=0; i< parameters.count(); i++) df->symbols.insert(parameters[i], Result(parms[i])); // calulcate - return formula->eval(df, formula, t, 0, item, NULL, NULL, Specification(), DateRange()).number; + return formula->eval(df, formula, t, 0, item, NULL, NULL, Specification(), DateRange()).number(); } double DFModel::y(double t) const { // calculate using current runtime - return formula->eval(df, formula, t, 0, item, NULL, NULL, Specification(), DateRange()).number; + return formula->eval(df, formula, t, 0, item, NULL, NULL, Specification(), DateRange()).number(); } bool @@ -6313,7 +6330,10 @@ DFModel::fitData(QVector&x, QVector&y) // unpack starting parameters QVector startingparms; - foreach(QString symbol, parameters) startingparms << df->symbols.value(symbol).number; + foreach(QString symbol, parameters) { + Result p =df->symbols.value(symbol); + startingparms << p.number(); + } // get access to lmfit, single threaded :( lm_control_struct control = lm_control_double; diff --git a/src/Core/DataFilter.h b/src/Core/DataFilter.h index 7433cd26c..17fa605e4 100644 --- a/src/Core/DataFilter.h +++ b/src/Core/DataFilter.h @@ -29,6 +29,7 @@ #include #include "RideCache.h" #include "RideFile.h" //for SeriesType +#include "Utils.h" //for SeriesType #include @@ -43,18 +44,64 @@ class Result { public: // construct a result - Result (double value) : isNumber(true), string(""), number(value) {} - Result (QString value) : isNumber(false), string(value), number(0.0f) {} - Result () : isNumber(true), string(""), number(0) {} + Result (double value) : isNumber(true), string_(""), number_(value) {} + Result (QString value) : isNumber(false), string_(value), number_(0.0f) {} + Result () : isNumber(true), string_(""), number_(0) {} // vectorize, turn into vector of size n void vectorize(int size); // we can't use QString with union bool isNumber; // if true, value is numeric - QString string; - double number; + bool isVector() const { return vector.count() > 0 || strings.count() > 0; } + + // return as number or string, coerce if needed + double &number() { + if (!isNumber) { + if (!isVector()) number_ = string_.toDouble(); + else asNumeric(); // this will coerce and crucially compute sum + } + return number_; + } + + QString &string() { if (isNumber) string_ = Utils::removeDP("%1").arg(number_); return string_; } + + // coerce strings to numbers + QVector&asNumeric() { + if (!isNumber) { + if (strings.count() == vector.count()) return vector; + else { + vector.clear(); + number_=0; + for(int i=0; i &asString() { + if (isNumber) { + if (strings.count() == vector.count()) return strings; + else { + strings.clear(); + for(int i=0; i vector; + QVector strings; + }; class DataFilterRuntime; diff --git a/src/Core/UserData.cpp b/src/Core/UserData.cpp index 318e90e02..cf5d0b14d 100644 --- a/src/Core/UserData.cpp +++ b/src/Core/UserData.cpp @@ -359,7 +359,7 @@ UserData::setRideItem(RideItem*m) // run through each sample and create an equivalent foreach(RideFilePoint *p, rideItem->ride()->dataPoints()) { Result res = parser.evaluate(rideItem, p); - vector << res.number; + vector << res.number(); } // cache for next time ! diff --git a/src/Gui/SearchFilterBox.cpp b/src/Gui/SearchFilterBox.cpp index 1b55795c1..207d6da6e 100644 --- a/src/Gui/SearchFilterBox.cpp +++ b/src/Gui/SearchFilterBox.cpp @@ -89,7 +89,7 @@ SearchFilterBox::matches(Context *context, QString filter) DataFilter df(NULL, context, spec); foreach(RideItem *item, context->athlete->rideCache->rides()) { Result res = df.evaluate(item, NULL); - if (res.isNumber && res.number) + if (res.isNumber && res.number()) returning << item->fileName; } } diff --git a/src/Metrics/PMCData.cpp b/src/Metrics/PMCData.cpp index 7b53f5e54..fb180b71b 100644 --- a/src/Metrics/PMCData.cpp +++ b/src/Metrics/PMCData.cpp @@ -256,7 +256,7 @@ void PMCData::refresh() // although metrics are cleansed, we check here because development // builds have a rideDB.json that has nan and inf values in it. double value = 0;; - if (fromDataFilter) value = expr->eval(df, expr, 0, 0, item).number; + if (fromDataFilter) value = expr->eval(df, expr, 0, 0, item).number(); else value = item->getForSymbol(metricName_); if (!std::isinf(value) && !std::isnan(value)) { diff --git a/src/Metrics/UserMetric.cpp b/src/Metrics/UserMetric.cpp index 074d74357..e7e7ae968 100644 --- a/src/Metrics/UserMetric.cpp +++ b/src/Metrics/UserMetric.cpp @@ -185,7 +185,7 @@ UserMetric::isRelevantForRide(const RideItem *item) const if (item->context && root) { if (frelevant) { Result res = root->eval(rt, frelevant, 0, 0, const_cast(item), NULL, NULL); - return res.number; + return res.number(); } else return true; } @@ -262,14 +262,14 @@ UserMetric::compute(RideItem *item, Specification spec, const QHasheval(rt, fvalue, 0, 0, const_cast(item), NULL, c, spec); - setValue(v.number); + setValue(v.number()); } //qDebug()<<"COUNT"; // count? if (fcount) { Result n = root->eval(rt, fcount, 0, 0, const_cast(item), NULL, c, spec); - setCount(n.number); + setCount(n.number()); } //qDebug()<