extract core functionality into static function

...so that we can use BestIntervalDialog::findBests elsewhere in the code.
This commit is contained in:
Sean Rhea
2010-01-18 11:54:42 -08:00
parent 16f3032b3f
commit e2deb1fc99
2 changed files with 63 additions and 50 deletions

View File

@@ -117,15 +117,9 @@ intervalDuration(const RideFilePoint *start, const RideFilePoint *stop, const Ri
return stop->secs - start->secs + ride->recIntSecs();
}
struct BestInterval
{
double start, stop, avg;
BestInterval(double start, double stop, double avg) :
start(start), stop(stop), avg(avg) {}
};
static bool
intervalsOverlap(const BestInterval &a, const BestInterval &b)
intervalsOverlap(const BestIntervalDialog::BestInterval &a,
const BestIntervalDialog::BestInterval &b)
{
if ((a.start <= b.start) && (a.stop > b.start))
return true;
@@ -136,7 +130,8 @@ intervalsOverlap(const BestInterval &a, const BestInterval &b)
struct CompareBests {
// Sort by decreasing power and increasing start time.
bool operator()(const BestInterval &a, const BestInterval &b) const {
bool operator()(const BestIntervalDialog::BestInterval &a,
const BestIntervalDialog::BestInterval &b) const {
if (a.avg > b.avg)
return true;
if (b.avg < a.avg)
@@ -165,48 +160,8 @@ BestIntervalDialog::findClicked()
return;
}
QList<const RideFilePoint*> window;
QList<BestInterval> bests;
double secsDelta = ride->recIntSecs();
double totalWatts = 0.0;
// We're looking for intervals with durations in [windowSizeSecs, windowSizeSecs + secsDelta).
foreach (const RideFilePoint *point, ride->dataPoints()) {
// Discard points until interval duration is < windowSizeSecs + secsDelta.
while (!window.empty() && (intervalDuration(window.first(), point, ride) >= windowSizeSecs + secsDelta)) {
totalWatts -= window.first()->watts;
window.takeFirst();
}
// Add points until interval duration is >= windowSizeSecs.
totalWatts += point->watts;
window.append(point);
double duration = intervalDuration(window.first(), window.last(), ride);
assert(duration < windowSizeSecs + secsDelta);
if (duration >= windowSizeSecs) {
double start = window.first()->secs;
double stop = start + duration;
double avg = totalWatts * secsDelta / duration;
bests.append(BestInterval(start, stop, avg));
}
}
std::sort(bests.begin(), bests.end(), CompareBests());
QList<BestInterval> results;
while (!bests.empty() && (results.size() < maxIntervals)) {
BestInterval candidate = bests.takeFirst();
bool overlaps = false;
foreach (const BestInterval &existing, results) {
if (intervalsOverlap(candidate, existing)) {
overlaps = true;
break;
}
}
if (!overlaps)
results.append(candidate);
}
findBests(ride, windowSizeSecs, maxIntervals, results);
// clear the table
clearResultsTable(resultsTable);
@@ -291,6 +246,53 @@ BestIntervalDialog::findClicked()
resultsTable->setColumnWidth(2,200);
}
void
BestIntervalDialog::findBests(const RideFile *ride, double windowSizeSecs,
int maxIntervals, QList<BestInterval> &results)
{
QList<BestInterval> bests;
double secsDelta = ride->recIntSecs();
double totalWatts = 0.0;
QList<const RideFilePoint*> window;
// We're looking for intervals with durations in [windowSizeSecs, windowSizeSecs + secsDelta).
foreach (const RideFilePoint *point, ride->dataPoints()) {
// Discard points until interval duration is < windowSizeSecs + secsDelta.
while (!window.empty() && (intervalDuration(window.first(), point, ride) >= windowSizeSecs + secsDelta)) {
totalWatts -= window.first()->watts;
window.takeFirst();
}
// Add points until interval duration is >= windowSizeSecs.
totalWatts += point->watts;
window.append(point);
double duration = intervalDuration(window.first(), window.last(), ride);
assert(duration < windowSizeSecs + secsDelta);
if (duration >= windowSizeSecs) {
double start = window.first()->secs;
double stop = start + duration;
double avg = totalWatts * secsDelta / duration;
bests.append(BestInterval(start, stop, avg));
}
}
std::sort(bests.begin(), bests.end(), CompareBests());
while (!bests.empty() && (results.size() < maxIntervals)) {
BestInterval candidate = bests.takeFirst();
bool overlaps = false;
foreach (const BestInterval &existing, results) {
if (intervalsOverlap(candidate, existing)) {
overlaps = true;
break;
}
}
if (!overlaps)
results.append(candidate);
}
}
void
BestIntervalDialog::doneClicked()
{

View File

@@ -22,14 +22,25 @@
#include <QtGui>
class MainWindow;
class RideFile;
class BestIntervalDialog : public QDialog
{
Q_OBJECT
public:
struct BestInterval {
double start, stop, avg;
BestInterval(double start, double stop, double avg) :
start(start), stop(stop), avg(avg) {}
};
BestIntervalDialog(MainWindow *mainWindow);
static void findBests(const RideFile *ride, double windowSizeSecs,
int maxIntervals, QList<BestInterval> &results);
private slots:
void findClicked();
void doneClicked();