unified framework for reading in different ride

file types (raw, srm, and csv)
This commit is contained in:
Sean C. Rhea
2007-09-17 18:10:32 +00:00
parent 07f375c0cc
commit 964279728b
14 changed files with 563 additions and 226 deletions

View File

@@ -1,63 +0,0 @@
//
// C++ Implementation: csv
//
// Description:
//
//
// Author: Justin F. Knotzke <jknotzke@shampoo.ca>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#include "CsvData.h"
#include <QTextStream>
#include "RawFile.h"
#include <iostream>
#include <algorithm>
#include <vector>
void CsvData::readCsvFile(QFile &file, RawFile *rawFile)
{
QTextStream stream( &file );
QString line;
std::vector<double> vec;
double previousSecs = 0.0;
//Flush the first line.
line = stream.readLine();
while ( !stream.atEnd() )
{
line = stream.readLine();
//Parse the line here
secs = line.section(',', 0, 0).toDouble();
kph = line.section(',', 2, 2).toDouble();
watts = line.section(',', 3, 3).toInt();
km = line.section(',', 4, 4).toDouble();
cad = line.section(',', 5, 5).toInt();
hr = line.section(',', 6, 6).toInt();
interval = line.section(',', 7, 7).toInt();
//To figure out the mean recording interval
vec.push_back(secs - previousSecs);
previousSecs = secs;
//For the power histogram
if (rawFile->powerHist.contains(watts))
rawFile->powerHist[watts] +=secs;
else
rawFile->powerHist[watts] = secs;
//Assume that all CSV files have km/h
RawFilePoint *p1 = new RawFilePoint(
secs, 0, kph * 0.621371192 , watts,
km * 0.621371192, cad, hr, interval);
rawFile->points.append(p1);
}
//Sort it
std::sort(vec.begin(), vec.end());
int size = vec.size();
//Then grab the middle value (the mean) and covert to milliseconds
rawFile->rec_int_ms = int(vec[size/2] * 60 * 1000);
}

View File

@@ -1,29 +0,0 @@
//
// C++ Interface: csv
//
// Description:
//
//
// Author: Justin F. Knotzke <jknotzke@shampoo.ca>, (C) 2007
//
// Copyright: See COPYING file that comes with this distribution
//
//
#ifndef _csv_h
#define _csv_h
#include <QDate>
class QFile;
class RawFile;
class CsvData
{
public:
int cad, hr, watts, interval;
double kph, km, secs;
QDateTime startTime;
double recint;
void readCsvFile(QFile &file, RawFile *rawFile);
};
#endif // _srm_h

122
src/gui/CsvRideFile.cpp Normal file
View File

@@ -0,0 +1,122 @@
/*
* Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "CsvRideFile.h"
#include <QRegExp>
#include <QTextStream>
#include <algorithm> // for std::sort
#include <assert.h>
#include "math.h"
#define MILES_TO_KM 1.609344
static int csvFileReaderRegistered =
CombinedFileReader::instance().registerReader("csv", new CsvFileReader());
RideFile *CsvFileReader::openRideFile(QFile &file, QStringList &errors) const
{
QRegExp rideTime("^.*/(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)_"
"(\\d\\d)_(\\d\\d)_(\\d\\d)\\.csv$");
if (rideTime.indexIn(file.fileName()) == -1) {
errors << ("file name does not encode ride time: \""
+ file.fileName() + "\"");
return NULL;
}
QDateTime datetime(QDate(rideTime.cap(1).toInt(),
rideTime.cap(2).toInt(),
rideTime.cap(3).toInt()),
QTime(rideTime.cap(4).toInt(),
rideTime.cap(5).toInt(),
rideTime.cap(6).toInt()));
QRegExp metricUnits("(km|kph)", Qt::CaseInsensitive);
QRegExp englishUnits("(miles|mph)", Qt::CaseInsensitive);
QRegExp sample("^\\s*"
"(\\d+|\\d+\\.\\d+)\\s*,\\s*"
"(\\d+|\\d+\\.\\d+)\\s*,\\s*"
"(\\d+|\\d+\\.\\d+)\\s*,\\s*"
"(\\d+|\\d+\\.\\d+)\\s*,\\s*"
"(\\d+|\\d+\\.\\d+)\\s*,\\s*"
"(\\d+|\\d+\\.\\d+)\\s*,\\s*"
"(\\d+|\\d+\\.\\d+)\\s*,\\s*"
"(\\d+)\\s*$");
bool metric;
if (!file.open(QFile::ReadOnly)) {
errors << ("Could not open ride file: \""
+ file.fileName() + "\"");
return NULL;
}
int lineno = 1;
QTextStream is(&file);
RideFile *rideFile = new RideFile();
while (!is.atEnd()) {
QString line = is.readLine();
if (lineno == 1) {
if (metricUnits.indexIn(line) != -1)
metric = true;
else if (englishUnits.indexIn(line) != -1)
metric = false;
else {
errors << ("Can't find units in first line: \"" + line + "\"");
delete rideFile;
file.close();
return NULL;
}
}
else if (sample.indexIn(line) != -1) {
assert(sample.numCaptures() == 8);
double minutes = sample.cap(1).toDouble();
double nm = sample.cap(2).toDouble();
double kph = sample.cap(3).toDouble();
double watts = sample.cap(4).toDouble();
double km = sample.cap(5).toDouble();
double cad = sample.cap(6).toDouble();
double hr = sample.cap(7).toDouble();
int interval = sample.cap(8).toInt();
if (!metric) {
km *= MILES_TO_KM;
kph *= MILES_TO_KM;
}
rideFile->appendPoint(minutes * 60.0, cad, hr, km,
kph, nm, watts, interval);
}
else {
errors << ("Couldn't parse line: \"" + line + "\"");
}
++lineno;
}
// To estimate the recording interval, take the median of the
// first 1000 samples and round to nearest millisecond.
int n = rideFile->dataPoints().size();
n = qMin(n, 1000);
if (n >= 2) {
double *secs = new double[n-1];
for (int i = 0; i < n-1; ++i) {
double now = rideFile->dataPoints()[i]->secs;
double then = rideFile->dataPoints()[i+1]->secs;
secs[i] = then - now;
}
std::sort(secs, secs + n - 1);
int mid = n / 2 - 1;
double recint = round(secs[mid] * 1000.0) / 1000.0;
rideFile->setRecIntSecs(recint);
}
rideFile->setStartTime(datetime);
file.close();
return rideFile;
}

29
src/gui/CsvRideFile.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _CsvRideFile_h
#define _CsvRideFile_h
#include "RideFile.h"
struct CsvFileReader : public RideFileReader {
virtual RideFile *openRideFile(QFile &file, QStringList &errors) const;
};
#endif // _CsvRideFile_h

View File

@@ -20,7 +20,7 @@ HEADERS += \
AllPlot.h \
ChooseCyclistDialog.h \
CpintPlot.h \
CsvData.h \
CsvRideFile.h \
DatePickerDialog.h \
DownloadRideDialog.h \
LogTimeScaleDraw.h \
@@ -28,7 +28,10 @@ HEADERS += \
MainWindow.h \
PowerHist.h \
RawFile.h \
RawRideFile.h \
RideFile.h \
RideItem.h \
SrmRideFile.h \
TimeUtils.h \
Zones.h
@@ -36,7 +39,7 @@ SOURCES += \
AllPlot.cpp \
ChooseCyclistDialog.cpp \
CpintPlot.cpp \
CsvData.cpp \
CsvRideFile.cpp \
DatePickerDialog.cpp \
DownloadRideDialog.cpp \
LogTimeScaleDraw.cpp \
@@ -44,7 +47,10 @@ SOURCES += \
MainWindow.cpp \
PowerHist.cpp \
RawFile.cpp \
RawRideFile.cpp \
RideFile.cpp \
RideItem.cpp \
SrmRideFile.cpp \
TimeUtils.cpp \
Zones.cpp \
\

View File

@@ -26,6 +26,7 @@
#include "PowerHist.h"
#include "RawFile.h"
#include "RideItem.h"
#include "RideFile.h"
#include "Settings.h"
#include "TimeUtils.h"
#include "Zones.h"
@@ -50,14 +51,9 @@ static char *rideFileRegExp = ("^(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)"
QString
MainWindow::notesFileName(QString rideFileName) {
if (rideFileName.endsWith(".raw"))
return rideFileName.left(rideFileName.length() - 4) + ".notes";
else if (rideFileName.endsWith(".srm"))
return rideFileName.left(rideFileName.length() - 4) + ".notes";
else if ( rideFileName.endsWith (".csv"))
return rideFileName.left ( rideFileName.length() - 4) + ".notes";
else
assert(false);
int i = rideFileName.lastIndexOf(".");
assert(i >= 0);
return rideFileName.left(i) + ".notes";
}
MainWindow::MainWindow(const QDir &home) :
@@ -100,10 +96,8 @@ MainWindow::MainWindow(const QDir &home) :
splitter->addWidget(treeWidget);
QRegExp rx(rideFileRegExp);
QStringList filters;
filters << "*.raw" << "*.srm"<<"*.csv";
QTreeWidgetItem *last = NULL;
QStringListIterator i(home.entryList(filters, QDir::Files));
QStringListIterator i(CombinedFileReader::instance().listRideFiles(home));
while (i.hasNext()) {
QString name = i.next();
if (rx.exactMatch(name)) {
@@ -585,10 +579,12 @@ MainWindow::rideSelected()
RideItem *ride = (RideItem*) which;
rideSummary->setHtml(ride->htmlSummary());
rideSummary->setAlignment(Qt::AlignCenter);
allPlot->setData(ride->raw);
if (ride->raw)
allPlot->setData(ride->raw);
if (tabWidget->currentIndex() == 2)
cpintPlot->calculate(ride->fileName, ride->dateTime);
powerHist->setData(ride->raw);
if (ride->raw)
powerHist->setData(ride->raw);
QDate wstart = ride->dateTime.date();
wstart = wstart.addDays(Qt::Monday - wstart.dayOfWeek());

View File

@@ -19,132 +19,33 @@
*/
#include "RawFile.h"
#include <math.h>
#include "RideFile.h"
#include <assert.h>
#include <QMessageBox>
#include "srm.h"
#include "CsvData.h"
#include <math.h>
extern "C" {
#include "pt.h"
}
struct RawFileReadState
{
QList<RawFilePoint*> &points;
QMap<double,double> &powerHist;
QStringList &errors;
double last_secs, last_miles;
unsigned last_interval;
time_t start_since_epoch;
unsigned rec_int;
RawFileReadState(QList<RawFilePoint*> &points,
QMap<double,double> &powerHist,
QStringList &errors) :
points(points), powerHist(powerHist), errors(errors), last_secs(0.0),
last_miles(0.0), last_interval(0), start_since_epoch(0), rec_int(0) {}
};
static void
config_cb(unsigned /*interval*/, unsigned rec_int,
unsigned /*wheel_sz_mm*/, void *context)
{
RawFileReadState *state = (RawFileReadState*) context;
// Assume once set, rec_int should never change.
assert((state->rec_int == 0) || (state->rec_int == rec_int));
state->rec_int = rec_int;
}
static void
time_cb(struct tm *, time_t since_epoch, void *context)
{
RawFileReadState *state = (RawFileReadState*) context;
if (state->start_since_epoch == 0)
state->start_since_epoch = since_epoch;
double secs = since_epoch - state->start_since_epoch;
RawFilePoint *point = new RawFilePoint(secs, -1.0, -1.0, -1.0,
state->last_miles, 0, 0,
state->last_interval);
state->points.append(point);
state->last_secs = secs;
}
static void
data_cb(double secs, double nm, double mph, double watts, double miles,
unsigned cad, unsigned hr, unsigned interval, void *context)
{
RawFileReadState *state = (RawFileReadState*) context;
RawFilePoint *point = new RawFilePoint(secs, nm, mph, watts, miles,
cad, hr, interval);
state->points.append(point);
state->last_secs = secs;
state->last_miles = miles;
state->last_interval = interval;
double sum = state->rec_int * 0.021;
if (watts >= 0.0) {
if (state->powerHist.contains(watts)) {
sum += state->powerHist.value(watts);
state->powerHist.remove(watts);
}
state->powerHist.insert(watts, sum);
}
}
static void
error_cb(const char *msg, void *context)
{
RawFileReadState *state = (RawFileReadState*) context;
state->errors.append(QString(msg));
}
#define KM_TO_MILES 0.62137119
RawFile *RawFile::readFile(QFile &file, QStringList &errors)
{
RideFile *rideFile =
CombinedFileReader::instance().openRideFile(file, errors);
if (!rideFile)
return NULL;
RawFile *result = new RawFile(file.fileName());
if (file.fileName().indexOf(".srm") == file.fileName().size() - 4) {
SrmData data;
if (!readSrmFile(file, data, errors)) {
delete result;
return NULL;
}
result->startTime = data.startTime;
result->rec_int_ms = (unsigned) round(data.recint * 1000.0);
QListIterator<SrmDataPoint*> i(data.dataPoints);
while (i.hasNext()) {
SrmDataPoint *p1 = i.next();
RawFilePoint *p2 = new RawFilePoint(
p1->secs, 0, p1->kph * 0.62137119, p1->watts,
p1->km * 0.62137119, p1->cad, p1->hr, p1->interval);
if (result->powerHist.contains(p2->watts))
result->powerHist[p2->watts] += data.recint;
else
result->powerHist[p2->watts] = data.recint;
result->points.append(p2);
}
}
else if (file.fileName().indexOf(".csv") == file.fileName().size() - 4)
{
CsvData data;
if (!file.open(QFile::ReadOnly)) {
errors << QString("can't open file %1").arg(file.fileName());
return false;
}
data.readCsvFile(file, result);
}
else {
if (!result->file.open(QIODevice::ReadOnly)) {
delete result;
return NULL;
}
FILE *f = fdopen(result->file.handle(), "r");
assert(f);
RawFileReadState state(result->points, result->powerHist, errors);
pt_read_raw(f, 0 /* not compat */, &state, config_cb,
time_cb, data_cb, error_cb);
result->rec_int_ms = (unsigned) round(state.rec_int * 1.26 * 1000.0);
result->startTime = rideFile->startTime();
result->rec_int_ms = (unsigned) round(rideFile->recIntSecs() * 1000.0);
QListIterator<RideFilePoint*> i(rideFile->dataPoints());
while (i.hasNext()) {
const RideFilePoint *p1 = i.next();
RawFilePoint *p2 = new RawFilePoint(
p1->secs, p1->nm, p1->kph * KM_TO_MILES, p1->watts,
p1->km * KM_TO_MILES, (int) p1->cad, (int) p1->hr, p1->interval);
if (result->powerHist.contains(p2->watts))
result->powerHist[p2->watts] += rideFile->recIntSecs();
else
result->powerHist[p2->watts] = rideFile->recIntSecs();
result->points.append(p2);
}
return result;
}

107
src/gui/RawRideFile.cpp Normal file
View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "RawRideFile.h"
#include "pt.h"
#include <assert.h>
#include <math.h>
#define MILES_TO_KM 1.609344
static int rawFileReaderRegistered =
CombinedFileReader::instance().registerReader("raw", new RawFileReader());
struct ReadState
{
RideFile *rideFile;
QStringList &errors;
double last_secs, last_miles;
unsigned last_interval;
time_t start_since_epoch;
unsigned rec_int;
ReadState(RideFile *rideFile,
QStringList &errors) :
rideFile(rideFile), errors(errors), last_secs(0.0),
last_miles(0.0), last_interval(0), start_since_epoch(0), rec_int(0) {}
};
static void
config_cb(unsigned interval, unsigned rec_int,
unsigned wheel_sz_mm, void *context)
{
(void) interval;
(void) wheel_sz_mm;
ReadState *state = (ReadState*) context;
// Assume once set, rec_int should never change.
double recIntSecs = rec_int * 1.26;
assert((state->rideFile->recIntSecs() == 0.0)
|| (state->rideFile->recIntSecs() == recIntSecs));
state->rideFile->setRecIntSecs(recIntSecs);
}
static void
time_cb(struct tm *, time_t since_epoch, void *context)
{
ReadState *state = (ReadState*) context;
if (state->start_since_epoch == 0)
state->start_since_epoch = since_epoch;
double secs = since_epoch - state->start_since_epoch;
state->rideFile->appendPoint(secs, 0.0, 0.0,
state->last_miles * MILES_TO_KM, 0.0,
0.0, 0.0, state->last_interval);
state->last_secs = secs;
}
static void
data_cb(double secs, double nm, double mph, double watts, double miles,
unsigned cad, unsigned hr, unsigned interval, void *context)
{
if (nm < 0.0) nm = 0.0;
if (mph < 0.0) mph = 0.0;
if (watts < 0.0) watts = 0.0;
ReadState *state = (ReadState*) context;
state->rideFile->appendPoint(secs, cad, hr, miles * MILES_TO_KM,
mph * MILES_TO_KM, nm, watts, interval);
state->last_secs = secs;
state->last_miles = miles;
state->last_interval = interval;
}
static void
error_cb(const char *msg, void *context)
{
ReadState *state = (ReadState*) context;
state->errors.append(QString(msg));
}
RideFile *RawFileReader::openRideFile(QFile &file, QStringList &errors) const
{
RideFile *rideFile = new RideFile;
if (!file.open(QIODevice::ReadOnly)) {
delete rideFile;
return NULL;
}
FILE *f = fdopen(file.handle(), "r");
assert(f);
ReadState state(rideFile, errors);
pt_read_raw(f, 0 /* not compat */, &state, config_cb,
time_cb, data_cb, error_cb);
return rideFile;
}

29
src/gui/RawRideFile.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _RawRideFile_h
#define _RawRideFile_h
#include "RideFile.h"
struct RawFileReader : public RideFileReader {
virtual RideFile *openRideFile(QFile &file, QStringList &errors) const;
};
#endif // _RawRideFile_h

61
src/gui/RideFile.cpp Normal file
View File

@@ -0,0 +1,61 @@
/*
* Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "RideFile.h"
#include <assert.h>
CombinedFileReader *CombinedFileReader::instance_;
CombinedFileReader &CombinedFileReader::instance()
{
if (!instance_)
instance_ = new CombinedFileReader();
return *instance_;
}
int CombinedFileReader::registerReader(const QString &suffix,
RideFileReader *reader)
{
assert(!readFuncs_.contains(suffix));
readFuncs_.insert(suffix, reader);
return 1;
}
RideFile *CombinedFileReader::openRideFile(QFile &file,
QStringList &errors) const
{
QString suffix = file.fileName();
int dot = suffix.lastIndexOf(".");
assert(dot >= 0);
suffix.remove(0, dot + 1);
RideFileReader *reader = readFuncs_.value(suffix);
assert(reader);
return reader->openRideFile(file, errors);
}
QStringList CombinedFileReader::listRideFiles(const QDir &dir) const
{
QStringList filters;
QMapIterator<QString,RideFileReader*> i(readFuncs_);
while (i.hasNext()) {
i.next();
filters << ("*." + i.key());
}
return dir.entryList(filters, QDir::Files, QDir::Name);
}

97
src/gui/RideFile.h Normal file
View File

@@ -0,0 +1,97 @@
/*
* Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _RideFile_h
#define _RideFile_h
#include <QDate>
#include <QDir>
#include <QFile>
#include <QList>
#include <QMap>
struct RideFilePoint
{
double secs, cad, hr, km, kph, nm, watts;
int interval;
RideFilePoint() : secs(0.0), cad(0.0), hr(0.0), km(0.0), kph(0.0),
nm(0.0), watts(0.0), interval(0) {}
RideFilePoint(double secs, double cad, double hr, double km, double kph,
double nm, double watts, int interval) :
secs(secs), cad(cad), hr(hr), km(km), kph(kph), nm(nm),
watts(watts), interval(interval) {}
};
class RideFile
{
private:
QDateTime startTime_; // time of day that the ride started
double recIntSecs_; // recording interval in seconds
QList<RideFilePoint*> dataPoints_;
public:
RideFile() : recIntSecs_(0.0) {}
RideFile(const QDateTime &startTime, double recIntSecs) :
startTime_(startTime), recIntSecs_(recIntSecs) {}
virtual ~RideFile() {
QListIterator<RideFilePoint*> i(dataPoints_);
while (i.hasNext())
delete i.next();
}
const QDateTime &startTime() const { return startTime_; }
double recIntSecs() const { return recIntSecs_; }
const QList<RideFilePoint*> dataPoints() const { return dataPoints_; }
void setStartTime(const QDateTime &value) { startTime_ = value; }
void setRecIntSecs(double value) { recIntSecs_ = value; }
void appendPoint(double secs, double cad, double hr, double km,
double kph, double nm, double watts, int interval) {
dataPoints_.append(new RideFilePoint(secs, cad, hr, km, kph,
nm, watts, interval));
}
};
struct RideFileReader {
virtual ~RideFileReader() {}
virtual RideFile *openRideFile(QFile &file, QStringList &errors) const = 0;
};
class CombinedFileReader : public RideFileReader {
private:
static CombinedFileReader *instance_;
QMap<QString,RideFileReader*> readFuncs_;
CombinedFileReader() {}
public:
static CombinedFileReader &instance();
int registerReader(const QString &suffix, RideFileReader *reader);
virtual RideFile *openRideFile(QFile &file, QStringList &errors) const;
QStringList listRideFiles(const QDir &dir) const;
};
#endif // _RideFile_h

View File

@@ -131,6 +131,8 @@ double RideItem::timeInZone(int zone)
{
if (summary.isEmpty())
htmlSummary();
if (!raw)
return 0.0;
assert(zone_range >= 0);
assert(zone < num_zones);
return time_in_zone[zone];
@@ -143,6 +145,14 @@ RideItem::htmlSummary()
QFile file(path + "/" + fileName);
QStringList errors;
raw = RawFile::readFile(file, errors);
if (!raw) {
summary = ("<p>Couldn't read file \"" +
file.fileName() + "\":");
QListIterator<QString> i(errors);
while (i.hasNext())
summary += "<br>" + i.next();
return summary;
}
summary = ("<p><center><h2>"
+ dateTime.toString("dddd MMMM d, yyyy, h:mm AP")
+ "</h2><p><h2>Summary</h2>");

42
src/gui/SrmRideFile.cpp Normal file
View File

@@ -0,0 +1,42 @@
/*
* Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "SrmRideFile.h"
#include "srm.h"
#define PI 3.14159265
static int srmFileReaderRegistered =
CombinedFileReader::instance().registerReader("srm", new SrmFileReader());
RideFile *SrmFileReader::openRideFile(QFile &file, QStringList &errors) const
{
SrmData srmData;
if (!readSrmFile(file, srmData, errors))
return NULL;
RideFile *rideFile = new RideFile(srmData.startTime, srmData.recint);
QListIterator<SrmDataPoint*> i(srmData.dataPoints);
while (i.hasNext()) {
SrmDataPoint *p = i.next();
double nm = p->watts / 2.0 / PI / p->cad * 60.0;
rideFile->appendPoint(p->secs, p->cad, p->hr, p->km,
p->kph, nm, p->watts, p->interval);
}
return rideFile;
}

29
src/gui/SrmRideFile.h Normal file
View File

@@ -0,0 +1,29 @@
/*
* Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _SrmRideFile_h
#define _SrmRideFile_h
#include "RideFile.h"
struct SrmFileReader : public RideFileReader {
virtual RideFile *openRideFile(QFile &file, QStringList &errors) const;
};
#endif // _SrmRideFile_h