added weekly summary

This commit is contained in:
Sean C. Rhea
2007-04-24 17:55:40 +00:00
parent efee14f2fd
commit 2f0f0d61bf
5 changed files with 125 additions and 80 deletions

View File

@@ -1,34 +1,7 @@
- Sort ride into tree list, don't just append
- For cpint, calculate a value for every whole second, using the same or next
largest actual time value from the actual data. That way, SRM and PT
values will align
- Pop up an "importing rides" thermometer when importing
- Remember last settings for showPower, showHr, etc.
- Add interval summary to ride summary
- Switch x-axis from minutes to miles
- Add units to ride summary
- Add weekly summary
- Add cpint
- Power distribution histogram: Rob Carlsen said:
I believe that it displays the percentage of time that you've spent in
various power ranges, however you can change that to display the
absolute time you've spent in each range. the default is 20 watt
increments, but the recommendation in the book is to decrease the
granularity to 10 watt increments for better estimation of your FTP.
i thought that using this chart to estimate FTP would only be useful
when there were MANY workout files compiled, rather than looking at
one workout. all the charts on the "athlete home page" of WKO+ seem to
display a collection of past workouts, usually about the last 28 days.
- Power and HR zones

View File

@@ -87,7 +87,7 @@ MainWindow::MainWindow(const QDir &home) :
tabWidget = new QTabWidget;
rideSummary = new QTextEdit;
rideSummary->setReadOnly(true);
tabWidget->addTab(rideSummary, "Ride Summary");
tabWidget->addTab(rideSummary, tr("Ride Summary"));
/////////////////////////// Ride Plot Tab ///////////////////////////
@@ -121,15 +121,15 @@ MainWindow::MainWindow(const QDir &home) :
QHBoxLayout *smoothLayout = new QHBoxLayout;
QLabel *smoothLabel = new QLabel(tr("Smoothing (secs)"), window);
smoothLineEdit = new QLineEdit(window);
smoothLineEdit->setFixedWidth(30);
smoothLineEdit->setFixedWidth(40);
smoothLayout->addWidget(smoothLabel);
smoothLayout->addWidget(smoothLineEdit);
smoothSlider = new QSlider(Qt::Horizontal);
smoothSlider->setTickPosition(QSlider::TicksBelow);
smoothSlider->setTickInterval(1);
smoothSlider->setTickInterval(10);
smoothSlider->setMinimum(2);
smoothSlider->setMaximum(60);
smoothSlider->setMaximum(600);
smoothLineEdit->setValidator(new QIntValidator(smoothSlider->minimum(),
smoothSlider->maximum(),
smoothLineEdit));
@@ -213,6 +213,12 @@ MainWindow::MainWindow(const QDir &home) :
tabWidget->addTab(window, "Power Histogram");
//////////////////////// Power Histogram Tab ////////////////////////
weeklySummary = new QTextEdit;
weeklySummary->setReadOnly(true);
tabWidget->addTab(weeklySummary, tr("Weekly Summary"));
////////////////////////////// Signals //////////////////////////////
connect(treeWidget, SIGNAL(itemSelectionChanged()),
@@ -432,6 +438,55 @@ MainWindow::rideSelected()
if (tabWidget->currentIndex() == 2)
cpintPlot->calculate(ride->fileName, ride->dateTime);
powerHist->setData(ride->raw);
QDate wstart = ride->dateTime.date();
wstart = wstart.addDays(Qt::Monday - wstart.dayOfWeek());
assert(wstart.dayOfWeek() == Qt::Monday);
QDate wend = wstart.addDays(7);
double weeklySeconds = 0.0;
double weeklyDistance = 0.0;
double weeklyWork = 0.0;
for (int i = 0; i < allRides->childCount(); ++i) {
if (allRides->child(i)->type() == RIDE_TYPE) {
RideItem *item = (RideItem*) allRides->child(i);
if ((item->dateTime.date() >= wstart)
&& (item->dateTime.date() < wend)) {
weeklySeconds += item->secsMovingOrPedaling();
weeklyDistance += item->totalDistance();
weeklyWork += item->totalWork();
}
}
}
int minutes = ((int) round(weeklySeconds)) / 60;
int hours = (int) minutes / 60;
minutes %= 60;
const char *dateFormat = "MM/dd/yyyy";
weeklySummary->setHtml(tr(
"<center>"
"<h2>Week of %1 through %2</h2>"
"<h2>Summary</h2>"
"<p>"
"<table align=\"center\" width=\"60%\" border=0>"
"<tr><td>Total time riding:</td>"
" <td align=\"right\">%3:%4</td></tr>"
"<tr><td>Total distance (miles):</td>"
" <td align=\"right\">%5</td></tr>"
"<tr><td>Total work (kJ):</td>"
" <td align=\"right\">%6</td></tr>"
"</table>"
"</center>"
)
.arg(wstart.toString(dateFormat))
.arg(wstart.addDays(6).toString(dateFormat))
.arg(hours)
.arg(minutes, 2, 10, QLatin1Char('0'))
.arg((unsigned) round(weeklyDistance))
.arg((unsigned) round(weeklyWork))
);
return;
}
}

View File

@@ -65,6 +65,7 @@ class MainWindow : public QMainWindow
QTreeWidget *treeWidget;
QTabWidget *tabWidget;
QTextEdit *rideSummary;
QTextEdit *weeklySummary;
AllPlot *allPlot;
CpintPlot *cpintPlot;
QLabel *cpintTimeLabel;

View File

@@ -62,28 +62,20 @@ static void summarize(QString &intervals,
unsigned last_interval,
double time_start, double time_end,
double mile_start, double mile_end,
unsigned &int_watts_cnt,
double &int_watts_sum,
unsigned &int_hr_cnt,
double &int_hr_sum,
unsigned &int_cad_cnt,
double &int_cad_sum,
unsigned &int_mph_cnt,
double &int_mph_sum)
{
double dur = round(time_end - time_start);
double len = mile_end - mile_start;
double minutes = (int) (dur/60.0);
double seconds = dur - (60 * minutes);
double watts_avg = (int_watts_cnt == 0) ? 0
: (int) (int_watts_sum / int_watts_cnt);
double hr_avg = (int_hr_cnt == 0) ? 0
: (int) (int_hr_sum / int_hr_cnt);
double cad_avg = (int_cad_cnt == 0) ? 0
: (int) (int_cad_sum / int_cad_cnt);
double mph_avg = (int_mph_cnt == 0) ? 0
: (int) (int_mph_sum / int_mph_cnt);
double energy = watts_avg / 1000.0 * dur;
double watts_avg = int_watts_sum / dur;
double hr_avg = int_hr_sum / dur;
double cad_avg = int_cad_sum / dur;
double mph_avg = int_mph_sum / dur;
double energy = int_watts_sum / 1000.0; // watts_avg / 1000.0 * dur;
intervals += "<tr><td align=\"center\">%1</td>";
intervals += "<td align=\"center\">%2:%3</td>";
@@ -103,10 +95,31 @@ static void summarize(QString &intervals,
intervals = intervals.arg(cad_avg, 0, 'f', 0);
intervals = intervals.arg(mph_avg, 0, 'f', 1);
int_watts_cnt = 0; int_watts_sum = 0.0;
int_hr_cnt = 0; int_hr_sum = 0.0;
int_cad_cnt = 0; int_cad_sum = 0.0;
int_mph_cnt = 0; int_mph_sum = 0.0;
int_watts_sum = 0.0;
int_hr_sum = 0.0;
int_cad_sum = 0.0;
int_mph_sum = 0.0;
}
double RideItem::secsMovingOrPedaling()
{
if (summary.isEmpty())
htmlSummary();
return secs_moving_or_pedaling;
}
double RideItem::totalDistance()
{
if (summary.isEmpty())
htmlSummary();
return total_distance;
}
double RideItem::totalWork()
{
if (summary.isEmpty())
htmlSummary();
return total_work;
}
QString
@@ -124,7 +137,7 @@ RideItem::htmlSummary()
return summary;
}
double secs_moving_or_pedaling = 0.0;
secs_moving_or_pedaling = 0.0;
double secs_moving = 0.0;
double total_watts = 0.0;
double secs_watts = 0.0;
@@ -137,13 +150,9 @@ RideItem::htmlSummary()
QString intervals = "";
unsigned last_interval = UINT_MAX;
double int_watts_sum = 0.0;
unsigned int_watts_cnt = 0;
double int_hr_sum = 0.0;
unsigned int_hr_cnt = 0;
double int_cad_sum = 0.0;
unsigned int_cad_cnt = 0;
double int_mph_sum = 0.0;
unsigned int_mph_cnt = 0;
double time_start, time_end, mile_start, mile_end;
@@ -155,10 +164,8 @@ RideItem::htmlSummary()
if (last_interval != UINT_MAX) {
summarize(intervals, last_interval, time_start,
time_end, mile_start, mile_end,
int_watts_cnt, int_watts_sum, int_hr_cnt,
int_hr_sum, int_cad_cnt, int_cad_sum,
int_mph_cnt, int_mph_sum);
time_end, mile_start, mile_end, int_watts_sum,
int_hr_sum, int_cad_sum, int_mph_sum);
}
last_interval = point->interval;
@@ -174,24 +181,20 @@ RideItem::htmlSummary()
if (point->watts >= 0.0) {
total_watts += point->watts * secs_delta;
secs_watts += secs_delta;
int_watts_sum += point->watts;
int_watts_cnt += 1;
int_watts_sum += point->watts * secs_delta;
}
if (point->hr > 0) {
total_hr += point->hr * secs_delta;
secs_hr += secs_delta;
int_hr_sum += point->hr;
int_hr_cnt += 1;
int_hr_sum += point->hr * secs_delta;
}
if (point->cad > 0) {
total_cad += point->cad * secs_delta;
secs_cad += secs_delta;
int_cad_sum += point->cad;
int_cad_cnt += 1;
int_cad_sum += point->cad * secs_delta;
}
if (point->mph >= 0) {
int_mph_sum += point->mph;
int_mph_cnt += 1;
int_mph_sum += point->mph * secs_delta;
}
mile_end = point->miles;
@@ -199,14 +202,15 @@ RideItem::htmlSummary()
}
summarize(intervals, last_interval, time_start,
time_end, mile_start, mile_end,
int_watts_cnt, int_watts_sum, int_hr_cnt,
int_hr_sum, int_cad_cnt, int_cad_sum,
int_mph_cnt, int_mph_sum);
time_end, mile_start, mile_end, int_watts_sum,
int_hr_sum, int_cad_sum, int_mph_sum);
avg_watts = (secs_watts == 0.0) ? 0.0
: round(total_watts / secs_watts);
total_distance = raw->points.back()->miles;
total_work = total_watts / 1000.0;
summary += "<p><table align=\"center\" width=\"60%\" border=0>";
summary += "<tr><td>Total workout time:</td><td align=\"right\">" +
time_to_string(raw->points.back()->secs);
@@ -214,10 +218,10 @@ RideItem::htmlSummary()
time_to_string(secs_moving_or_pedaling) + "</td></tr>";
summary += QString("<tr><td>Total distance (miles):</td>"
"<td align=\"right\">%1</td></tr>")
.arg(raw->points.back()->miles, 0, 'f', 1);
.arg(total_distance, 0, 'f', 1);
summary += QString("<tr><td>Total work (kJ):</td>"
"<td align=\"right\">%1</td></tr>")
.arg((unsigned) (avg_watts / 1000.0 * secs_moving_or_pedaling));
.arg((unsigned) round(total_work));
summary += QString("<tr><td>Average speed (mph):</td>"
"<td align=\"right\">%1</td></tr>")
.arg(((secs_moving == 0.0) ? 0.0

View File

@@ -25,17 +25,29 @@
class RawFile;
struct RideItem : public QTreeWidgetItem {
QString path;
QString fileName;
QDateTime dateTime;
QString summary;
RawFile *raw;
class RideItem : public QTreeWidgetItem {
RideItem(QTreeWidgetItem *parent, int type, QString path,
QString fileName, const QDateTime &dateTime);
protected:
QString htmlSummary();
double secs_moving_or_pedaling;
double total_distance;
double total_work;
public:
QString path;
QString fileName;
QDateTime dateTime;
QString summary;
RawFile *raw;
RideItem(QTreeWidgetItem *parent, int type, QString path,
QString fileName, const QDateTime &dateTime);
QString htmlSummary();
double secsMovingOrPedaling();
double totalDistance();
double totalWork();
};
#endif // _GC_RideItem_h