Added Time in Pace Zones to RideSummary in Trends Compared Mode

For Date Ranges and Intervals, only when activities are homogeneous
to select the correct Pace Zones
Also enabled Time in Power Zones only when activities are homogeneouse
to select the correct Power Zones
This commit is contained in:
Alejandro Martinez
2016-01-01 17:38:20 -03:00
parent e55d1af0f2
commit 9f06d48c42

View File

@@ -1673,6 +1673,18 @@ RideSummaryWindow::htmlCompareSummary() const
<< "wcptime_in_zone_L3"
<< "wcptime_in_zone_L4";
static const QStringList paceTimeInZones = QStringList()
<< "time_in_zone_P1"
<< "time_in_zone_P2"
<< "time_in_zone_P3"
<< "time_in_zone_P4"
<< "time_in_zone_P5"
<< "time_in_zone_P6"
<< "time_in_zone_P7"
<< "time_in_zone_P8"
<< "time_in_zone_P9"
<< "time_in_zone_P10";
if (ridesummary) {
//
@@ -1803,17 +1815,27 @@ RideSummaryWindow::htmlCompareSummary() const
summary += "</table>";
}
// Counts of activity types to select Power and Pace Zones
int nActivities=0, nRides=0, nRuns=0, nSwims=0;
foreach (RideItem *metrics, intervalMetrics) {
nActivities++;
if (metrics->isRun) nRuns++;
else if (metrics->isSwim) nSwims++;
else nRides++;
}
//
// TIME IN POWER ZONES (we can't do w'bal compare at present)
//
if (context->athlete->zones(false)) { // use my zones
// when all rides or all runs, use zones accordingly
if (((nActivities==nRides) || (nActivities==nRuns)) &&
context->athlete->zones(nActivities==nRuns)) {
// get from end if period
int rangeidx = context->athlete->zones(false)->whichRange(QDate::currentDate()); // use current zone names et al
int rangeidx = context->athlete->zones(nActivities==nRuns)->whichRange(QDate::currentDate()); // use current zone names et al
if (rangeidx > -1) {
// get the list of zones
ZoneRange range = const_cast<Zones*>(context->athlete->zones(false))->getZoneRange(rangeidx);
ZoneRange range = const_cast<Zones*>(context->athlete->zones(nActivities==nRuns))->getZoneRange(rangeidx);
QList<ZoneInfo> zones = range.zones;
// we've got a range and a count of zones so all is well
@@ -1949,6 +1971,80 @@ RideSummaryWindow::htmlCompareSummary() const
}
}
//
// TIME IN PACE ZONES
// when all runs or all swims, use zones accordingly
if (((nActivities==nRuns) || (nActivities==nSwims)) &&
context->athlete->zones(nActivities==nSwims)) {
// get from end if period
int rangeidx = context->athlete->paceZones(nActivities==nSwims)->whichRange(QDate::currentDate()); // use current zone names et al
if (rangeidx > -1) {
// get the list of zones
PaceZoneRange range = const_cast<PaceZones*>(context->athlete->paceZones(nActivities==nSwims))->getZoneRange(rangeidx);
QList<PaceZoneInfo> zones = range.zones;
// we've got a range and a count of zones so all is well
// we need to throw up a table of time in zone for each interval
summary += tr("<h3>Pace Zones</h3>");
summary += "<table align=\"center\" width=\"80%\" border=\"0\">";
// lets get some headings
summary += "<tr><td></td>"; // ne need to have a heading for the interval name
summary += "<td bgcolor='" + bgColor.name() + "'>&nbsp;</td>"; // spacing
foreach (PaceZoneInfo zone, zones) {
summary += QString("<td colspan=\"2\" align=\"center\"><b>%1 (%2)</b></td>").arg(zone.desc).arg(zone.name);
summary += "<td bgcolor='" + bgColor.name() + "'>&nbsp;</td>"; // spacing
}
summary += "</tr>";
// now the summary
int counter = 0;
int rows = 0;
foreach (RideItem *metrics, intervalMetrics) {
// only ones that are checked
if (!context->compareIntervals[counter].isChecked()) {
counter++;
continue;
}
if (rows%2) summary += "<tr bgcolor='" + altColor.name() + "'>";
else summary += "<tr>";
summary += "<td nowrap='yes'><font color='" + context->compareIntervals[counter].color.name() + "'>" + context->compareIntervals[counter].name + "</font></td>";
summary += "<td bgcolor='" + bgColor.name() + "'>&nbsp;</td>"; // spacing
int idx=0;
foreach (PaceZoneInfo zone, zones) {
int timeZone = metrics->getForSymbol(paceTimeInZones[idx]);
int dt = timeZone - intervalMetrics[0]->getForSymbol(paceTimeInZones[idx]);
idx++;
// time and then +time
summary += QString("<td align=\"center\">%1</td>").arg(time_to_string(timeZone));
if (counter) summary += QString("<td align=\"center\">%1%2</td>")
.arg(dt>0 ? "+" : "-")
.arg(time_to_string(fabs(dt)));
else summary += "<td></td>";
summary += "<td bgcolor='" + bgColor.name() + "'>&nbsp;</td>"; // spacing
}
summary += "</tr>";
rows++; counter++;
}
// done
summary += "</table>";
}
}
} else { // DATE RANGE COMPARE
@@ -2069,17 +2165,29 @@ RideSummaryWindow::htmlCompareSummary() const
summary += "</table>";
}
// Counts of activity types to select Power and Pace Zones
int nActivities=0, nRides=0, nRuns=0, nSwims=0;
foreach (CompareDateRange dr, context->compareDateRanges) {
int a, b, r, s;
dr.context->athlete->rideCache->getRideTypeCounts(dr.specification, a, b, r, s);
nActivities += a;
nRides += b;
nRuns += r;
nSwims += s;
}
//
// TIME IN POWER ZONES AND W'BAL ZONES
//
if (context->athlete->zones(false)) { // use my zones
// when all rides or all runs, use zones accordingly
if (((nActivities==nRides) || (nActivities==nRuns)) &&
context->athlete->zones(nActivities==nRuns)) {
// get from end if period
int rangeidx = context->athlete->zones(false)->whichRange(QDate::currentDate()); // use current zone names et al
int rangeidx = context->athlete->zones(nActivities==nRuns)->whichRange(QDate::currentDate()); // use current zone names et al
if (rangeidx > -1) {
// get the list of zones
ZoneRange range = const_cast<Zones*>(context->athlete->zones(false))->getZoneRange(rangeidx);
ZoneRange range = const_cast<Zones*>(context->athlete->zones(nActivities==nRuns))->getZoneRange(rangeidx);
QList<ZoneInfo> zones = range.zones;
// we've got a range and a count of zones so all is well
@@ -2280,6 +2388,80 @@ RideSummaryWindow::htmlCompareSummary() const
}
}
//
// TIME IN PACE ZONES
// when all runs or all swims, use zones accordingly
if (((nActivities==nRuns) || (nActivities==nSwims)) &&
context->athlete->zones(nActivities==nSwims)) {
// get from end if period
int rangeidx = context->athlete->paceZones(nActivities==nSwims)->whichRange(QDate::currentDate()); // use current zone names et al
if (rangeidx > -1) {
// get the list of zones
PaceZoneRange range = const_cast<PaceZones*>(context->athlete->paceZones(nActivities==nSwims))->getZoneRange(rangeidx);
QList<PaceZoneInfo> zones = range.zones;
// we've got a range and a count of zones so all is well
// we need to throw up a table of time in zone for each interval
summary += tr("<h3>Pace Zones</h3>");
summary += "<table align=\"center\" width=\"80%\" border=\"0\">";
// lets get some headings
summary += "<tr><td></td>"; // ne need to have a heading for the interval name
summary += "<td bgcolor='" + bgColor.name() + "'>&nbsp;</td>"; // spacing
foreach (PaceZoneInfo zone, zones) {
summary += QString("<td colspan=\"2\" align=\"center\"><b>%1 (%2)</b></td>").arg(zone.desc).arg(zone.name);
summary += "<td bgcolor='" + bgColor.name() + "'>&nbsp;</td>"; // spacing
}
summary += "</tr>";
// now the summary
int counter = 0;
foreach (CompareDateRange dr, context->compareDateRanges) {
// skip if not checked
if (!dr.isChecked()) continue;
if (counter%2) summary += "<tr bgcolor='" + altColor.name() + "'>";
else summary += "<tr>";
summary += "<td>" + dr.name + "</td>";
summary += "<td bgcolor='" + bgColor.name() + "'>&nbsp;</td>"; // spacing
int idx=0;
foreach (PaceZoneInfo zone, zones) {
int timeZone = dr.context->athlete->rideCache->getAggregate(paceTimeInZones[idx], dr.specification,
context->athlete->useMetricUnits, true).toDouble();
int dt = timeZone - context->compareDateRanges[0].context->athlete->rideCache->getAggregate(paceTimeInZones[idx],
context->compareDateRanges[0].specification,
context->athlete->useMetricUnits, true).toDouble();
idx++;
// time and then +time
summary += QString("<td align=\"center\">%1</td>").arg(time_to_string(timeZone));
if (counter) summary += QString("<td align=\"center\">%1%2</td>")
.arg(dt>0 ? "+" : "-")
.arg(time_to_string(fabs(dt)));
else summary += "<td></td>";
summary += "<td bgcolor='" + bgColor.name() + "'>&nbsp;</td>"; // spacing
}
summary += "</tr>";
counter++;
}
// done
summary += "</table>";
}
}
}
// add the usual disclaimers etc at the bottom