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()<