diff --git a/src/Computrainer3dpFile.cpp b/src/Computrainer3dpFile.cpp new file mode 100644 index 000000000..9d056e443 --- /dev/null +++ b/src/Computrainer3dpFile.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2007 Sean C. Rhea (srhea@srhea.net), + * Justin F. Knotzke (jknotzke@shampoo.ca) + * Copyright (c) 2009 Greg Lonnon (greg.lonnon@gmail.com) + * + * 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 "Computrainer3dpFile.h" +#include +#include +#include +#include +#include // for std::sort +#include +#include "math.h" +#include +#include +#include "Units.h" +#include + +typedef unsigned char ubyte; + +static int Computrainer3dpFileReaderRegistered = + RideFileFactory::instance().registerReader("3dp", + new + Computrainer3dpFileReader + ()); + +RideFile *Computrainer3dpFileReader::openRideFile(QFile & file, + QStringList & errors) + const +{ + if (!file.open(QFile::ReadOnly)) { + errors << ("Could not open ride file: \"" + file.fileName() + + "\""); + return NULL; + } + + RideFile *rideFile = new RideFile(); + QDataStream is(&file); + + is.setByteOrder(QDataStream::LittleEndian); + + // looks like the first part is a header... ignore it. + is.skipRawData(4); + char perfStr[5]; + + is.readRawData(perfStr, 4); + perfStr[4] = NULL; + is.skipRawData(0x8); + char userName[65]; + is.readRawData(userName, 65); + ubyte age; + is >> age; + is.skipRawData(6); + float weight; + is >> weight; + int upperHR; + is >> upperHR; + int lowerHR; + is >> lowerHR; + int year; + is >> year; + ubyte month; + is >> month; + ubyte day; + is >> day; + ubyte hour; + is >> hour; + ubyte minute; + is >> minute; + int numberSamples; + is >> numberSamples; + // go back to the start, and go to the start of the data samples + file.seek(0); + is.skipRawData(0xf8); + for (; numberSamples; numberSamples--) { + ubyte hr; + is >> hr; + ubyte cad; + is >> cad; + unsigned short watts; + is >> watts; + float speed; + is >> speed; + speed = speed * KM_PER_MILE * 100; + int ms; + is >> ms; + is.skipRawData(4); + float miles; + is >> miles; + float km = miles * KM_PER_MILE; + is.skipRawData(0x1c); + rideFile->appendPoint((double) ms / 1000, (double) cad, + (double) hr, km, speed, 0.0, watts, 0, 0, 0); + + } + QDateTime dateTime; + QDate date; + QTime time; + date.setDate(year, month, day); + time.setHMS(hour, minute, 0, 0); + dateTime.setDate(date); + dateTime.setTime(time); + + rideFile->setStartTime(dateTime); + + int n = rideFile->dataPoints().size(); + n = qMin(n, 1000); + if (n >= 2) { + QVector < double >secs(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.begin(), secs.end()); + int mid = n / 2 - 1; + double recint = round(secs[mid] * 1000.0) / 1000.0; + rideFile->setRecIntSecs(recint); + } + rideFile->setDeviceType("Computrainer 3DP"); + file.close(); + return rideFile; +} diff --git a/src/Computrainer3dpFile.h b/src/Computrainer3dpFile.h new file mode 100644 index 000000000..45aada646 --- /dev/null +++ b/src/Computrainer3dpFile.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2009 Greg Lonnon (greg.lonnon@gmail.com) + * + * 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 _GC_COMPUTRAINER3DP_H +#define _GC_COMPUTRAINER3DP_H + +#include "RideFile.h" + +struct Computrainer3dpFileReader : public RideFileReader { + virtual RideFile *openRideFile(QFile &file, QStringList &errors) const; +}; + +#endif // _GC_COMPUTRAINER3DP_H diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 7ef6af2b1..e7f48932d 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -537,11 +537,11 @@ MainWindow::importFile() if (quarqInterpreterInstalled()) { fileNames = QFileDialog::getOpenFileNames( this, tr("Import from File"), lastDir, - tr("All Support Formats (*.raw *.csv *.srm *.tcx *.hrm *.wko *.qla);;Raw Powertap Files (*.raw);;Comma Separated Variable (*.csv);;SRM training files (*.srm);;Garmin Training Centre (*.tcx);;Polar Precision (*.hrm);;WKO+ Files (*.wko);;Quarq ANT+ Files (*.qla);;All files (*.*)")); + tr("All Support Formats (*.raw *.csv *.srm *.tcx *.hrm *.wko *.3dp *.qla);;Raw Powertap Files (*.raw);;Comma Separated Variable (*.csv);;SRM training files (*.srm);;Garmin Training Centre (*.tcx);;Polar Precision (*.hrm);;WKO+ Files (*.wko);;Computrainer 3dp (*.3dp);;Quarq ANT+ Files (*.qla);;All files (*.*)")); } else { fileNames = QFileDialog::getOpenFileNames( this, tr("Import from File"), lastDir, - tr("All Support Formats (*.raw *.csv *.srm *.tcx *.hrm *.wko);;Raw Powertap Files (*.raw);;Comma Separated Variable (*.csv);;SRM training files (*.srm);;Garmin Training Centre (*.tcx);;Polar Precision (*.hrm);;WKO+ Files (*.wko);;All files (*.*)")); + tr("All Support Formats (*.raw *.csv *.srm *.tcx *.hrm *.wko *.3dp);;Raw Powertap Files (*.raw);;Comma Separated Variable (*.csv);;SRM training files (*.srm);;Garmin Training Centre (*.tcx);;Polar Precision (*.hrm);;WKO+ Files (*.wko);;Computrainer 3dp (*.3dp);;All files (*.*)")); } diff --git a/src/RideImportWizard.cpp b/src/RideImportWizard.cpp index ad762da6c..ebb3a4235 100644 --- a/src/RideImportWizard.cpp +++ b/src/RideImportWizard.cpp @@ -227,9 +227,9 @@ RideImportWizard::process() // is it one we understand ? QRegExp suffixes; if (quarqInterpreterInstalled()) - suffixes.setPattern("^(raw|srm|csv|tcx|qla|hrm|wko)$"); + suffixes.setPattern("^(raw|srm|csv|tcx|qla|hrm|wko|3dp)$"); else - suffixes.setPattern("^(raw|srm|csv|tcx|hrm|wko)$"); + suffixes.setPattern("^(raw|srm|csv|tcx|hrm|wko|3dp)$"); suffixes.setCaseSensitivity(Qt::CaseInsensitive); diff --git a/src/src.pro b/src/src.pro index f87da3e4e..37f96ee24 100644 --- a/src/src.pro +++ b/src/src.pro @@ -48,6 +48,7 @@ HEADERS += \ BestIntervalDialog.h \ ChooseCyclistDialog.h \ CommPort.h \ + Computrainer3dpFile.h \ ConfigDialog.h \ CpintPlot.h \ CriticalPowerWindow.h \ @@ -97,7 +98,7 @@ HEADERS += \ WkoRideFile.h \ XmlRideFile.h \ Zones.h \ - srm.h + srm.h \ SOURCES += \ AllPlot.cpp \ @@ -107,6 +108,7 @@ SOURCES += \ BikeScore.cpp \ ChooseCyclistDialog.cpp \ CommPort.cpp \ + Computrainer3dpFile.cpp \ ConfigDialog.cpp \ CpintPlot.cpp \ CriticalPowerWindow.cpp \ @@ -154,7 +156,7 @@ SOURCES += \ XmlRideFile.cpp \ Zones.cpp \ main.cpp \ - srm.cpp + srm.cpp \ RESOURCES = application.qrc