mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-13 08:08:42 +00:00
@@ -165,7 +165,6 @@ void PMCData::refresh()
|
||||
// back to null date if not set, just to get round date arithmetic
|
||||
if (start_ == QDate(9999,12,31)) start_ = QDate();
|
||||
|
||||
QVector<double> expected_stress;
|
||||
// We got a valid range ?
|
||||
if (start_ != QDate() && end_ != QDate() && start_ < end_) {
|
||||
|
||||
@@ -183,7 +182,7 @@ void PMCData::refresh()
|
||||
planned_sb_.resize(days_+1); // for SB tomorrow!
|
||||
planned_rr_.resize(days_);
|
||||
|
||||
expected_stress.resize(days_);
|
||||
expected_stress_.resize(days_);
|
||||
expected_lts_.resize(days_);
|
||||
expected_sts_.resize(days_);
|
||||
expected_sb_.resize(days_+1); // for SB tomorrow!
|
||||
@@ -221,7 +220,6 @@ void PMCData::refresh()
|
||||
//
|
||||
// STEP TWO What are the seedings and ride values
|
||||
//
|
||||
bool sbToday = appsettings->cvalue(context->athlete->cyclist, GC_SB_TODAY).toInt();
|
||||
const double lte = (double)exp(-1.0/ltsDays_);
|
||||
const double ste = (double)exp(-1.0/stsDays_);
|
||||
|
||||
@@ -238,7 +236,7 @@ void PMCData::refresh()
|
||||
planned_sb_.fill(0);
|
||||
planned_rr_.fill(0);
|
||||
|
||||
expected_stress.fill(0);
|
||||
expected_stress_.fill(0);
|
||||
expected_lts_.fill(0);
|
||||
expected_sts_.fill(0);
|
||||
expected_sb_.fill(0);
|
||||
@@ -294,11 +292,11 @@ void PMCData::refresh()
|
||||
}
|
||||
} else if (start_.addDays(offset).daysTo(QDate::currentDate()) < 0) {
|
||||
if (item->planned) {
|
||||
expected_stress[offset] += value;
|
||||
expected_stress_[offset] += value;
|
||||
}
|
||||
} else {
|
||||
if (! item->planned) {
|
||||
expected_stress[offset] += value;
|
||||
expected_stress_[offset] += value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -306,14 +304,14 @@ void PMCData::refresh()
|
||||
}
|
||||
if (todayOffset > -1) {
|
||||
// Special case today: Use actual stress if available, otherwise planned
|
||||
expected_stress[todayOffset] = (todayActualStress > 0) ? todayActualStress : todayPlannedStress;
|
||||
expected_stress_[todayOffset] = (todayActualStress > 0) ? todayActualStress : todayPlannedStress;
|
||||
}
|
||||
|
||||
delete df;
|
||||
|
||||
calculateMetrics(days_, stress_, lts_, sts_, sb_, rr_);
|
||||
calculateMetrics(days_, planned_stress_, planned_lts_, planned_sts_, planned_sb_, planned_rr_);
|
||||
calculateMetrics(days_, expected_stress, expected_lts_, expected_sts_, expected_sb_, expected_rr_);
|
||||
calculateMetrics(days_, expected_stress_, expected_lts_, expected_sts_, expected_sb_, expected_rr_);
|
||||
|
||||
//qDebug()<<"refresh PMC in="<<timer.elapsed()<<"ms";
|
||||
|
||||
|
||||
@@ -68,6 +68,18 @@ class PMCData : public QObject {
|
||||
QVector<double> &sb() { return sb_; }
|
||||
QVector<double> &rr() { return rr_; }
|
||||
|
||||
QVector<double> &plannedStress() { return planned_stress_; }
|
||||
QVector<double> &plannedLts() { return planned_lts_; }
|
||||
QVector<double> &plannedSts() { return planned_sts_; }
|
||||
QVector<double> &plannedSb() { return planned_sb_; }
|
||||
QVector<double> &plannedRr() { return planned_rr_; }
|
||||
|
||||
QVector<double> &expectedStress() { return expected_stress_; }
|
||||
QVector<double> &expectedLts() { return expected_lts_; }
|
||||
QVector<double> &expectedSts() { return expected_sts_; }
|
||||
QVector<double> &expectedSb() { return expected_sb_; }
|
||||
QVector<double> &expectedRr() { return expected_rr_; }
|
||||
|
||||
// index into the arrays
|
||||
int indexOf(QDate) ;
|
||||
|
||||
@@ -129,7 +141,7 @@ class PMCData : public QObject {
|
||||
int days_;
|
||||
QVector<double> stress_, lts_, sts_, sb_, rr_;
|
||||
QVector<double> planned_stress_, planned_lts_, planned_sts_, planned_sb_, planned_rr_;
|
||||
QVector<double> expected_lts_, expected_sts_, expected_sb_, expected_rr_;
|
||||
QVector<double> expected_stress_, expected_lts_, expected_sts_, expected_sb_, expected_rr_;
|
||||
|
||||
bool isstale; // needs refreshing
|
||||
|
||||
|
||||
@@ -2090,7 +2090,7 @@ Bindings::rideFileCacheMeanmax(RideFileCache* cache) const
|
||||
}
|
||||
|
||||
PyObject*
|
||||
Bindings::seasonPmc(bool all, QString metric) const
|
||||
Bindings::seasonPmc(bool all, QString metric, QString type) const
|
||||
{
|
||||
Context *context = python->contexts.value(threadid()).context;
|
||||
|
||||
@@ -2150,11 +2150,25 @@ Bindings::seasonPmc(bool all, QString metric) const
|
||||
// just copy
|
||||
for(unsigned int k=0; k<size; k++) {
|
||||
|
||||
PyList_SET_ITEM(stress, k, PyFloat_FromDouble(pmcData.stress()[k]));
|
||||
PyList_SET_ITEM(lts, k, PyFloat_FromDouble(pmcData.lts()[k]));
|
||||
PyList_SET_ITEM(sts, k, PyFloat_FromDouble(pmcData.sts()[k]));
|
||||
PyList_SET_ITEM(sb, k, PyFloat_FromDouble(pmcData.sb()[k]));
|
||||
PyList_SET_ITEM(rr, k, PyFloat_FromDouble(pmcData.rr()[k]));
|
||||
if (type == "Planned") {
|
||||
PyList_SET_ITEM(stress, k, PyFloat_FromDouble(pmcData.plannedStress()[k]));
|
||||
PyList_SET_ITEM(lts, k, PyFloat_FromDouble(pmcData.plannedLts()[k]));
|
||||
PyList_SET_ITEM(sts, k, PyFloat_FromDouble(pmcData.plannedSts()[k]));
|
||||
PyList_SET_ITEM(sb, k, PyFloat_FromDouble(pmcData.plannedSb()[k]));
|
||||
PyList_SET_ITEM(rr, k, PyFloat_FromDouble(pmcData.plannedRr()[k]));
|
||||
} else if (type == "Expected") {
|
||||
PyList_SET_ITEM(stress, k, PyFloat_FromDouble(pmcData.expectedStress()[k]));
|
||||
PyList_SET_ITEM(lts, k, PyFloat_FromDouble(pmcData.expectedLts()[k]));
|
||||
PyList_SET_ITEM(sts, k, PyFloat_FromDouble(pmcData.expectedSts()[k]));
|
||||
PyList_SET_ITEM(sb, k, PyFloat_FromDouble(pmcData.expectedSb()[k]));
|
||||
PyList_SET_ITEM(rr, k, PyFloat_FromDouble(pmcData.expectedRr()[k]));
|
||||
} else {
|
||||
PyList_SET_ITEM(stress, k, PyFloat_FromDouble(pmcData.stress()[k]));
|
||||
PyList_SET_ITEM(lts, k, PyFloat_FromDouble(pmcData.lts()[k]));
|
||||
PyList_SET_ITEM(sts, k, PyFloat_FromDouble(pmcData.sts()[k]));
|
||||
PyList_SET_ITEM(sb, k, PyFloat_FromDouble(pmcData.sb()[k]));
|
||||
PyList_SET_ITEM(rr, k, PyFloat_FromDouble(pmcData.rr()[k]));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -2165,11 +2179,25 @@ Bindings::seasonPmc(bool all, QString metric) const
|
||||
// day today
|
||||
if (start.addDays(k) >= range.from && start.addDays(k) <= range.to) {
|
||||
|
||||
PyList_SET_ITEM(stress, index, PyFloat_FromDouble(pmcData.stress()[k]));
|
||||
PyList_SET_ITEM(lts, index, PyFloat_FromDouble(pmcData.lts()[k]));
|
||||
PyList_SET_ITEM(sts, index, PyFloat_FromDouble(pmcData.sts()[k]));
|
||||
PyList_SET_ITEM(sb, index, PyFloat_FromDouble(pmcData.sb()[k]));
|
||||
PyList_SET_ITEM(rr, index, PyFloat_FromDouble(pmcData.rr()[k]));
|
||||
if (type == "Planned") {
|
||||
PyList_SET_ITEM(stress, index, PyFloat_FromDouble(pmcData.plannedStress()[k]));
|
||||
PyList_SET_ITEM(lts, index, PyFloat_FromDouble(pmcData.plannedLts()[k]));
|
||||
PyList_SET_ITEM(sts, index, PyFloat_FromDouble(pmcData.plannedSts()[k]));
|
||||
PyList_SET_ITEM(sb, index, PyFloat_FromDouble(pmcData.plannedSb()[k]));
|
||||
PyList_SET_ITEM(rr, index, PyFloat_FromDouble(pmcData.plannedRr()[k]));
|
||||
} else if (type == "Expected") {
|
||||
PyList_SET_ITEM(stress, index, PyFloat_FromDouble(pmcData.expectedStress()[k]));
|
||||
PyList_SET_ITEM(lts, index, PyFloat_FromDouble(pmcData.expectedLts()[k]));
|
||||
PyList_SET_ITEM(sts, index, PyFloat_FromDouble(pmcData.expectedSts()[k]));
|
||||
PyList_SET_ITEM(sb, index, PyFloat_FromDouble(pmcData.expectedSb()[k]));
|
||||
PyList_SET_ITEM(rr, index, PyFloat_FromDouble(pmcData.expectedRr()[k]));
|
||||
} else {
|
||||
PyList_SET_ITEM(stress, index, PyFloat_FromDouble(pmcData.stress()[k]));
|
||||
PyList_SET_ITEM(lts, index, PyFloat_FromDouble(pmcData.lts()[k]));
|
||||
PyList_SET_ITEM(sts, index, PyFloat_FromDouble(pmcData.sts()[k]));
|
||||
PyList_SET_ITEM(sb, index, PyFloat_FromDouble(pmcData.sb()[k]));
|
||||
PyList_SET_ITEM(rr, index, PyFloat_FromDouble(pmcData.rr()[k]));
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ class Bindings {
|
||||
PyObject* activityMetrics(bool compare=false) const;
|
||||
PyObject* seasonMetrics(bool all=false, QString filter=QString(), bool compare=false) const;
|
||||
PythonDataSeries *metrics(QString metric, bool all=false, QString filter=QString()) const;
|
||||
PyObject* seasonPmc(bool all=false, QString metric=QString("BikeStress")) const;
|
||||
PyObject* seasonPmc(bool all=false, QString metric=QString("BikeStress"), QString type=QString("Actual")) const;
|
||||
PyObject* seasonMeasures(bool all=false, QString group=QString("Body")) const;
|
||||
|
||||
// working with meanmax data
|
||||
|
||||
@@ -369,7 +369,7 @@ public:
|
||||
PyObject* activityMetrics(bool compare=false) /TransferBack/;
|
||||
PyObject* seasonMetrics(bool all=false, QString filter=QString(), bool compare=false) /TransferBack/;
|
||||
PythonDataSeries *metrics(QString metric, bool all=false, QString filter=QString()) /TransferBack/;
|
||||
PyObject* seasonPmc(bool all=false, QString metric=QString("BikeStress")) /TransferBack/;
|
||||
PyObject* seasonPmc(bool all=false, QString metric=QString("BikeStress"), QString type=QString("Actual")) /TransferBack/;
|
||||
PyObject* seasonMeasures(bool all=false, QString group=QString("Body")) /TransferBack/;
|
||||
|
||||
// working with meanmax data
|
||||
|
||||
@@ -678,19 +678,24 @@ static PyObject *meth_Bindings_seasonPmc(PyObject *sipSelf, PyObject *sipArgs, P
|
||||
::QString a1def = QString("BikeStress");
|
||||
::QString* a1 = &a1def;
|
||||
int a1State = 0;
|
||||
::QString a2def = QString("Actual");
|
||||
::QString* a2 = &a2def;
|
||||
int a2State = 0;
|
||||
::Bindings *sipCpp;
|
||||
|
||||
static const char *sipKwdList[] = {
|
||||
sipName_all,
|
||||
sipName_metric,
|
||||
sipName_type,
|
||||
};
|
||||
|
||||
if (sipParseKwdArgs(&sipParseErr, sipArgs, sipKwds, sipKwdList, NULL, "B|bJ1", &sipSelf, sipType_Bindings, &sipCpp, &a0, sipType_QString,&a1, &a1State))
|
||||
if (sipParseKwdArgs(&sipParseErr, sipArgs, sipKwds, sipKwdList, NULL, "B|bJ1J1", &sipSelf, sipType_Bindings, &sipCpp, &a0, sipType_QString,&a1, &a1State, sipType_QString,&a2, &a2State))
|
||||
{
|
||||
PyObject * sipRes;
|
||||
|
||||
sipRes = sipCpp->seasonPmc(a0,*a1);
|
||||
sipRes = sipCpp->seasonPmc(a0,*a1,*a2);
|
||||
sipReleaseType(a1,sipType_QString,a1State);
|
||||
sipReleaseType(a2,sipType_QString,a2State);
|
||||
|
||||
return sipRes;
|
||||
}
|
||||
|
||||
@@ -210,8 +210,8 @@ RTool::RTool()
|
||||
{ "GC.season.intervals", (DL_FUNC) &RTool::seasonIntervals, 2 },
|
||||
{ "GC.season.meanmax", (DL_FUNC) &RTool::seasonMeanmax, 3 },
|
||||
{ "GC.season.peaks", (DL_FUNC) &RTool::seasonPeaks, 5 },
|
||||
// return a data.frame of pmc series (all=FALSE, metric="BikeStress")
|
||||
{ "GC.season.pmc", (DL_FUNC) &RTool::pmc, 2 },
|
||||
// return a data.frame of pmc series (all=FALSE, metric="BikeStress", type="Actual")
|
||||
{ "GC.season.pmc", (DL_FUNC) &RTool::pmc, 3 },
|
||||
// return a data.frame of measure fields (all=FALSE, group="Body")
|
||||
{ "GC.season.measures", (DL_FUNC) &RTool::measures, 2 },
|
||||
{ "GC.chart.set", (DL_FUNC) &RTool::setChart, 6 },
|
||||
@@ -305,7 +305,7 @@ RTool::RTool()
|
||||
"GC.season <- function(all=FALSE, compare=FALSE) { .Call(\"GC.season\", all, compare) }\n"
|
||||
"GC.season.metrics <- function(all=FALSE, filter=\"\", compare=FALSE) { .Call(\"GC.season.metrics\", all, filter, compare) }\n"
|
||||
"GC.season.intervals <- function(type=NULL, compare=FALSE) { .Call(\"GC.season.intervals\", type, compare) }\n"
|
||||
"GC.season.pmc <- function(all=FALSE, metric=\"BikeStress\") { .Call(\"GC.season.pmc\", all, metric) }\n"
|
||||
"GC.season.pmc <- function(all=FALSE, metric=\"BikeStress\", type=\"Actual\") { .Call(\"GC.season.pmc\", all, metric, type) }\n"
|
||||
"GC.season.measures <- function(all=FALSE, group=\"Body\") { .Call(\"GC.season.measures\", all, group) }\n"
|
||||
"GC.season.meanmax <- function(all=FALSE, filter=\"\", compare=FALSE) { .Call(\"GC.season.meanmax\", all, filter, compare) }\n"
|
||||
// find peaks does a few validation checks on the R side
|
||||
@@ -317,7 +317,7 @@ RTool::RTool()
|
||||
"}\n"
|
||||
// these 2 added for backward compatibility, may be deprecated
|
||||
"GC.metrics <- function(all=FALSE, filter=\"\", compare=FALSE) { .Call(\"GC.season.metrics\", all, filter, compare) }\n"
|
||||
"GC.pmc <- function(all=FALSE, metric=\"BikeStress\") { .Call(\"GC.season.pmc\", all, metric) }\n"
|
||||
"GC.pmc <- function(all=FALSE, metric=\"BikeStress\", type=\"Actual\") { .Call(\"GC.season.pmc\", all, metric, type) }\n"
|
||||
|
||||
// charts
|
||||
"GC.setChart <- function(title=\"\", type=1, animate=FALSE, legpos=2, stack=FALSE, orientation=2) { .Call(\"GC.chart.set\", title, type, animate, legpos ,stack, orientation)}\n"
|
||||
@@ -3330,7 +3330,7 @@ RTool::activityMetrics(SEXP pCompare)
|
||||
}
|
||||
|
||||
SEXP
|
||||
RTool::pmc(SEXP pAll, SEXP pMetric)
|
||||
RTool::pmc(SEXP pAll, SEXP pMetric, SEXP pType)
|
||||
{
|
||||
// parse parameters
|
||||
// p1 - all=TRUE|FALSE - return all metrics or just within
|
||||
@@ -3342,6 +3342,10 @@ RTool::pmc(SEXP pAll, SEXP pMetric)
|
||||
pMetric = Rf_coerceVector(pMetric, STRSXP);
|
||||
QString metric (CHAR(STRING_ELT(pMetric,0)));
|
||||
|
||||
// p3 - type="Actual" - PMC type: Actual/Planned/Expected
|
||||
pMetric = Rf_coerceVector(pType, STRSXP);
|
||||
QString type (CHAR(STRING_ELT(pType,0)));
|
||||
|
||||
// return a dataframe with PMC data for all or the current season
|
||||
// XXX uses the default half-life
|
||||
if (rtool->context) {
|
||||
@@ -3416,11 +3420,25 @@ RTool::pmc(SEXP pAll, SEXP pMetric)
|
||||
if (all) {
|
||||
|
||||
// just copy
|
||||
for(unsigned int k=0; k<size; k++) REAL(stress)[k] = pmcData.stress()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(lts)[k] = pmcData.lts()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(sts)[k] = pmcData.sts()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(sb)[k] = pmcData.sb()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(rr)[k] = pmcData.rr()[k];
|
||||
if (type == "Planned") {
|
||||
for(unsigned int k=0; k<size; k++) REAL(stress)[k] = pmcData.plannedStress()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(lts)[k] = pmcData.plannedLts()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(sts)[k] = pmcData.plannedSts()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(sb)[k] = pmcData.plannedSb()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(rr)[k] = pmcData.plannedRr()[k];
|
||||
} else if (type == "Expected") {
|
||||
for(unsigned int k=0; k<size; k++) REAL(stress)[k] = pmcData.expectedStress()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(lts)[k] = pmcData.expectedLts()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(sts)[k] = pmcData.expectedSts()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(sb)[k] = pmcData.expectedSb()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(rr)[k] = pmcData.expectedRr()[k];
|
||||
} else {
|
||||
for(unsigned int k=0; k<size; k++) REAL(stress)[k] = pmcData.stress()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(lts)[k] = pmcData.lts()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(sts)[k] = pmcData.sts()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(sb)[k] = pmcData.sb()[k];
|
||||
for(unsigned int k=0; k<size; k++) REAL(rr)[k] = pmcData.rr()[k];
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
@@ -3430,11 +3448,25 @@ RTool::pmc(SEXP pAll, SEXP pMetric)
|
||||
// day today
|
||||
if (day >= from && day <= to) {
|
||||
|
||||
REAL(stress)[index] = pmcData.stress()[k];
|
||||
REAL(lts)[index] = pmcData.lts()[k];
|
||||
REAL(sts)[index] = pmcData.sts()[k];
|
||||
REAL(sb)[index] = pmcData.sb()[k];
|
||||
REAL(rr)[index] = pmcData.rr()[k];
|
||||
if (type == "Planned") {
|
||||
REAL(stress)[index] = pmcData.plannedStress()[k];
|
||||
REAL(lts)[index] = pmcData.plannedLts()[k];
|
||||
REAL(sts)[index] = pmcData.plannedSts()[k];
|
||||
REAL(sb)[index] = pmcData.plannedSb()[k];
|
||||
REAL(rr)[index] = pmcData.plannedRr()[k];
|
||||
} else if (type == "Expected") {
|
||||
REAL(stress)[index] = pmcData.expectedStress()[k];
|
||||
REAL(lts)[index] = pmcData.expectedLts()[k];
|
||||
REAL(sts)[index] = pmcData.expectedSts()[k];
|
||||
REAL(sb)[index] = pmcData.expectedSb()[k];
|
||||
REAL(rr)[index] = pmcData.expectedRr()[k];
|
||||
} else {
|
||||
REAL(stress)[index] = pmcData.stress()[k];
|
||||
REAL(lts)[index] = pmcData.lts()[k];
|
||||
REAL(sts)[index] = pmcData.sts()[k];
|
||||
REAL(sb)[index] = pmcData.sb()[k];
|
||||
REAL(rr)[index] = pmcData.rr()[k];
|
||||
}
|
||||
index++;
|
||||
}
|
||||
day++;
|
||||
|
||||
@@ -70,7 +70,7 @@ class RTool {
|
||||
static SEXP seasonIntervals(SEXP type, SEXP compare);
|
||||
static SEXP seasonMeanmax(SEXP all, SEXP filter, SEXP compare);
|
||||
static SEXP seasonPeaks(SEXP all, SEXP filter, SEXP compare, SEXP series, SEXP duration);
|
||||
static SEXP pmc(SEXP all, SEXP metric);
|
||||
static SEXP pmc(SEXP all, SEXP metric, SEXP type);
|
||||
static SEXP measures(SEXP all, SEXP group);
|
||||
|
||||
// charts
|
||||
|
||||
Reference in New Issue
Block a user