mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-14 00:28:42 +00:00
Will now read, interpret, and include any appropriately named .srm files in
the user's directory. Ride summary, ride plot, and power histogram all work fine, but opening the CP intervals graph causes a crash if any such files exist. Also need to add a menu item to import .srm files that renames them to the proper form (date-time.srm).
This commit is contained in:
@@ -5,9 +5,10 @@
|
||||
TEMPLATE = app
|
||||
TARGET +=
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += /usr/local/include/qwt ../lib
|
||||
INCLUDEPATH += /home/srhea/src/qwt-20060130/include ../lib ../srm
|
||||
CONFIG += static
|
||||
LIBS += /usr/local/lib/libqwt.a ../lib/libgc.a
|
||||
LIBS += /home/srhea/src/qwt-20060130/lib/libqwt.a ../lib/libgc.a
|
||||
LIBS += ../srm/libsrm.a
|
||||
LIBS += -lm -lz
|
||||
macx {
|
||||
LIBS += -framework Carbon
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#define RIDE_TYPE 1
|
||||
|
||||
static char *rideFileRegExp = ("^(\\d\\d\\d\\d)_(\\d\\d)_(\\d\\d)"
|
||||
"_(\\d\\d)_(\\d\\d)_(\\d\\d)\\.raw$");
|
||||
"_(\\d\\d)_(\\d\\d)_(\\d\\d)\\.(raw|srm)$");
|
||||
|
||||
MainWindow::MainWindow(const QDir &home) :
|
||||
home(home), settings(GC_SETTINGS_CO, GC_SETTINGS_APP)
|
||||
@@ -70,13 +70,13 @@ MainWindow::MainWindow(const QDir &home) :
|
||||
|
||||
QRegExp rx(rideFileRegExp);
|
||||
QStringList filters;
|
||||
filters << "*.raw";
|
||||
filters << "*.raw" << "*.srm";
|
||||
QTreeWidgetItem *last = NULL;
|
||||
QStringListIterator i(home.entryList(filters, QDir::Files));
|
||||
while (i.hasNext()) {
|
||||
QString name = i.next();
|
||||
if (rx.exactMatch(name)) {
|
||||
assert(rx.numCaptures() == 6);
|
||||
assert(rx.numCaptures() == 7);
|
||||
QDate date(rx.cap(1).toInt(), rx.cap(2).toInt(),rx.cap(3).toInt());
|
||||
QTime time(rx.cap(4).toInt(), rx.cap(5).toInt(),rx.cap(6).toInt());
|
||||
QDateTime dt(date, time);
|
||||
|
||||
@@ -19,8 +19,11 @@
|
||||
*/
|
||||
|
||||
#include "RawFile.h"
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <QMessageBox>
|
||||
#include "srm.h"
|
||||
|
||||
extern "C" {
|
||||
#include "pt.h"
|
||||
}
|
||||
@@ -93,19 +96,43 @@ error_cb(const char *msg, void *context)
|
||||
state->errors.append(QString(msg));
|
||||
}
|
||||
|
||||
RawFile *RawFile::readFile(const QFile &file, QStringList &errors)
|
||||
RawFile *RawFile::readFile(QFile &file, QStringList &errors)
|
||||
{
|
||||
RawFile *result = new RawFile(file.fileName());
|
||||
if (!result->file.open(QIODevice::ReadOnly)) {
|
||||
delete result;
|
||||
return NULL;
|
||||
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 = (unsigned) round(data.recint); // TODO
|
||||
|
||||
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 (!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 = state.rec_int;
|
||||
}
|
||||
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 = state.rec_int;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,7 @@ class RawFile
|
||||
int rec_int;
|
||||
QList<RawFilePoint*> points;
|
||||
QMap<double,double> powerHist;
|
||||
static RawFile *readFile(const QFile &file, QStringList &errors);
|
||||
static RawFile *readFile(QFile &file, QStringList &errors);
|
||||
};
|
||||
|
||||
#endif // _GC_RawFile_h
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#############################################################################
|
||||
# Makefile for building: srm
|
||||
# Generated by qmake (2.01a) (Qt 4.2.0) on: Sun Apr 8 18:34:58 2007
|
||||
# Makefile for building: libsrm.a
|
||||
# Generated by qmake (2.01a) (Qt 4.2.0) on: Mon Apr 9 13:27:14 2007
|
||||
# Project: srm.pro
|
||||
# Template: app
|
||||
# Template: lib
|
||||
# Command: /usr/bin/qmake -unix -o Makefile srm.pro
|
||||
#############################################################################
|
||||
|
||||
@@ -13,14 +13,11 @@ CXX = g++
|
||||
LEX = flex
|
||||
YACC = yacc
|
||||
DEFINES = -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED
|
||||
CFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES)
|
||||
CXXFLAGS = -pipe -O2 -Wall -W -D_REENTRANT $(DEFINES)
|
||||
CFLAGS = -pipe -O2 -fPIC -Wall -W -D_REENTRANT $(DEFINES)
|
||||
CXXFLAGS = -pipe -O2 -fPIC -Wall -W -D_REENTRANT $(DEFINES)
|
||||
LEXFLAGS =
|
||||
YACCFLAGS = -d
|
||||
INCPATH = -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I.
|
||||
LINK = g++
|
||||
LFLAGS =
|
||||
LIBS = $(SUBLIBS) -L/usr/lib -lQtGui -L/build/buildd/qt4-x11-4.2.0/lib -L/usr/X11R6/lib -laudio -lXt -lpng -lSM -lICE -lXrender -lXrandr -lXfixes -lXcursor -lXinerama -lfreetype -lXext -lX11 -lQtCore -lfontconfig -lz -lm -lglib-2.0 -ldl -lpthread
|
||||
AR = ar cqs
|
||||
RANLIB =
|
||||
QMAKE = /usr/bin/qmake
|
||||
@@ -57,6 +54,8 @@ DIST = /usr/share/qt4/mkspecs/common/unix.conf \
|
||||
/usr/share/qt4/mkspecs/features/default_pre.prf \
|
||||
/usr/share/qt4/mkspecs/features/release.prf \
|
||||
/usr/share/qt4/mkspecs/features/default_post.prf \
|
||||
/usr/share/qt4/mkspecs/features/static.prf \
|
||||
/usr/share/qt4/mkspecs/features/staticlib.prf \
|
||||
/usr/share/qt4/mkspecs/features/warn_on.prf \
|
||||
/usr/share/qt4/mkspecs/features/qt.prf \
|
||||
/usr/share/qt4/mkspecs/features/unix/thread.prf \
|
||||
@@ -66,7 +65,7 @@ DIST = /usr/share/qt4/mkspecs/common/unix.conf \
|
||||
srm.pro
|
||||
QMAKE_TARGET = srm
|
||||
DESTDIR =
|
||||
TARGET = srm
|
||||
TARGET = libsrm.a
|
||||
|
||||
first: all
|
||||
####### Implicit rules
|
||||
@@ -90,10 +89,14 @@ first: all
|
||||
|
||||
####### Build rules
|
||||
|
||||
all: Makefile $(TARGET)
|
||||
all: Makefile $(TARGET)
|
||||
|
||||
staticlib: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS) $(OBJCOMP)
|
||||
-$(DEL_FILE) $(TARGET)
|
||||
$(AR) $(TARGET) $(OBJECTS)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
$(LINK) $(LFLAGS) -o $(TARGET) $(OBJECTS) $(OBJCOMP) $(LIBS)
|
||||
|
||||
Makefile: srm.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mkspecs/common/unix.conf \
|
||||
/usr/share/qt4/mkspecs/common/g++.conf \
|
||||
@@ -105,6 +108,8 @@ Makefile: srm.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mk
|
||||
/usr/share/qt4/mkspecs/features/default_pre.prf \
|
||||
/usr/share/qt4/mkspecs/features/release.prf \
|
||||
/usr/share/qt4/mkspecs/features/default_post.prf \
|
||||
/usr/share/qt4/mkspecs/features/static.prf \
|
||||
/usr/share/qt4/mkspecs/features/staticlib.prf \
|
||||
/usr/share/qt4/mkspecs/features/warn_on.prf \
|
||||
/usr/share/qt4/mkspecs/features/qt.prf \
|
||||
/usr/share/qt4/mkspecs/features/unix/thread.prf \
|
||||
@@ -124,6 +129,8 @@ Makefile: srm.pro /usr/share/qt4/mkspecs/linux-g++/qmake.conf /usr/share/qt4/mk
|
||||
/usr/share/qt4/mkspecs/features/default_pre.prf:
|
||||
/usr/share/qt4/mkspecs/features/release.prf:
|
||||
/usr/share/qt4/mkspecs/features/default_post.prf:
|
||||
/usr/share/qt4/mkspecs/features/static.prf:
|
||||
/usr/share/qt4/mkspecs/features/staticlib.prf:
|
||||
/usr/share/qt4/mkspecs/features/warn_on.prf:
|
||||
/usr/share/qt4/mkspecs/features/qt.prf:
|
||||
/usr/share/qt4/mkspecs/features/unix/thread.prf:
|
||||
@@ -137,7 +144,7 @@ qmake: FORCE
|
||||
|
||||
dist:
|
||||
@$(CHK_DIR_EXISTS) .tmp/srm1.0.0 || $(MKDIR) .tmp/srm1.0.0
|
||||
$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/srm1.0.0/ && $(COPY_FILE) --parents srm.cpp .tmp/srm1.0.0/ && (cd `dirname .tmp/srm1.0.0` && $(TAR) srm1.0.0.tar srm1.0.0 && $(COMPRESS) srm1.0.0.tar) && $(MOVE) `dirname .tmp/srm1.0.0`/srm1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/srm1.0.0
|
||||
$(COPY_FILE) --parents $(SOURCES) $(DIST) .tmp/srm1.0.0/ && $(COPY_FILE) --parents srm.h .tmp/srm1.0.0/ && $(COPY_FILE) --parents srm.cpp .tmp/srm1.0.0/ && (cd `dirname .tmp/srm1.0.0` && $(TAR) srm1.0.0.tar srm1.0.0 && $(COMPRESS) srm1.0.0.tar) && $(MOVE) `dirname .tmp/srm1.0.0`/srm1.0.0.tar.gz . && $(DEL_FILE) -r .tmp/srm1.0.0
|
||||
|
||||
|
||||
yaccclean:
|
||||
|
||||
107
src/srm/srm.cpp
107
src/srm/srm.cpp
@@ -3,9 +3,7 @@
|
||||
// (http://www.stephanmantler.com/?page_id=86).
|
||||
//
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDate>
|
||||
#include <QFile>
|
||||
#include "srm.h"
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
@@ -32,18 +30,23 @@ static quint32 readLong(QDataStream &in)
|
||||
return htonl(value); // SRM uses big endian
|
||||
}
|
||||
|
||||
struct marker
|
||||
{
|
||||
int start, end;
|
||||
};
|
||||
|
||||
struct blockhdr
|
||||
{
|
||||
QDateTime dt;
|
||||
quint16 chunkcnt;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
bool readSrmFile(QFile &file, SrmData &data, QStringList &errorStrings)
|
||||
{
|
||||
assert(argc > 1);
|
||||
QFile file(argv[1]);
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
assert(false);
|
||||
if (!file.open(QFile::ReadOnly)) {
|
||||
errorStrings << QString("can't open file %1").arg(file.fileName());
|
||||
return false;
|
||||
}
|
||||
QDataStream in(&file);
|
||||
|
||||
char magic[5];
|
||||
@@ -65,13 +68,13 @@ int main(int argc, char *argv[])
|
||||
in.readRawData(comment, sizeof(comment) - 1);
|
||||
comment[commentlen - 1] = '\0';
|
||||
|
||||
double recint = ((double) recint1) / recint2;
|
||||
unsigned recintms = (unsigned) round(recint * 1000.0);
|
||||
data.recint = ((double) recint1) / recint2;
|
||||
unsigned recintms = (unsigned) round(data.recint * 1000.0);
|
||||
|
||||
printf("magic=%s\n", magic);
|
||||
printf("wheelcirc=%d\n", wheelcirc);
|
||||
printf("dayssince1880=%d\n", dayssince1880);
|
||||
printf("recint=%f sec\n", recint);
|
||||
printf("recint=%f sec\n", data.recint);
|
||||
printf("blockcnt=%d\n", blockcnt);
|
||||
printf("markercnt=%d\n", markercnt);
|
||||
printf("commentlen=%d\n", commentlen);
|
||||
@@ -82,6 +85,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
printf("date=%s\n", date.toString().toAscii().constData());
|
||||
|
||||
marker *markers = new marker[markercnt + 1];
|
||||
for (int i = 0; i <= markercnt; ++i) {
|
||||
char mcomment[256];
|
||||
in.readRawData(mcomment, sizeof(mcomment) - 1);
|
||||
@@ -95,6 +99,8 @@ int main(int argc, char *argv[])
|
||||
quint16 avgcad = readShort(in);
|
||||
quint16 avgspeed = readShort(in);
|
||||
quint16 pwc150 = readShort(in);
|
||||
markers[i].start = start;
|
||||
markers[i].end = end;
|
||||
|
||||
printf("marker %d:\n", i);
|
||||
printf(" mcomment=%s\n", mcomment);
|
||||
@@ -129,7 +135,15 @@ int main(int argc, char *argv[])
|
||||
printf("slope=%d\n", slope);
|
||||
printf("datacnt=%d\n", datacnt);
|
||||
|
||||
for (int i = 0, blknum = 0, blkidx = 0; i < datacnt; ++i) {
|
||||
assert(blockcnt > 0);
|
||||
|
||||
int blknum = 0, blkidx = 0, mrknum = 0, interval = 0;
|
||||
double km = 0.0, secs = 0.0;
|
||||
|
||||
if (markercnt > 0)
|
||||
mrknum = 1;
|
||||
|
||||
for (int i = 0; i < datacnt; ++i) {
|
||||
quint8 ps[3];
|
||||
in.readRawData((char*) ps, sizeof(ps));
|
||||
quint8 cad = readByte(in);
|
||||
@@ -137,17 +151,76 @@ int main(int argc, char *argv[])
|
||||
double kph = (((((unsigned) ps[1]) & 0xf0) << 3)
|
||||
| (ps[0] & 0x7f)) * 3.0 / 26.0;
|
||||
unsigned watts = (ps[1] & 0x0f) | (ps[2] << 0x4);
|
||||
QDateTime dt = blockhdrs[blknum].dt.addMSecs(recintms * blkidx);
|
||||
printf(" %s %5.1f %4d %3d %3d\n",
|
||||
dt.toString().toAscii().constData(), kph, watts, hr, cad);
|
||||
if (i == 0) {
|
||||
data.startTime = blockhdrs[blknum].dt;
|
||||
printf("startTime=%s\n",
|
||||
data.startTime.toString().toAscii().constData());
|
||||
}
|
||||
if (i == markers[mrknum].end) {
|
||||
++interval;
|
||||
++mrknum;
|
||||
}
|
||||
|
||||
if ((i > 0) && (i == markers[mrknum].start))
|
||||
++interval;
|
||||
|
||||
km += data.recint * kph / 3600.0;
|
||||
|
||||
SrmDataPoint *point = new SrmDataPoint;
|
||||
point->cad = cad;
|
||||
point->hr = hr;
|
||||
point->watts = watts;
|
||||
point->interval = interval;
|
||||
point->kph = kph;
|
||||
point->km = km;
|
||||
point->secs = secs;
|
||||
data.dataPoints.append(point);
|
||||
|
||||
printf("%5.1f %5.1f %5.1f %4d %3d %3d %2d\n",
|
||||
secs, km, kph, watts, hr, cad, interval);
|
||||
|
||||
++blkidx;
|
||||
if (blkidx == blockhdrs[blknum].chunkcnt) {
|
||||
if ((blkidx == blockhdrs[blknum].chunkcnt) && (blknum + 1 < blockcnt)) {
|
||||
QDateTime end = blockhdrs[blknum].dt.addMSecs(
|
||||
recintms * blockhdrs[blknum].chunkcnt);
|
||||
++blknum;
|
||||
blkidx = 0;
|
||||
QDateTime start = blockhdrs[blknum].dt;
|
||||
qint64 endms =
|
||||
((qint64) end.toTime_t()) * 1000 + end.time().msec();
|
||||
qint64 startms =
|
||||
((qint64) start.toTime_t()) * 1000 + start.time().msec();
|
||||
qint64 diff = startms - endms;
|
||||
if (diff < 0) {
|
||||
errorStrings << QString("ERROR: time goes backwards by %1 ms"
|
||||
" on trans " "to block %2"
|
||||
).arg(diff).arg(blknum);
|
||||
secs += data.recint; // for lack of a better option
|
||||
}
|
||||
else {
|
||||
// printf("jumping forward %lld ms\n", diff);
|
||||
secs += diff / 1000.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
secs += data.recint;
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
int main(int argc, char *argv[]) {
|
||||
assert(argc > 1);
|
||||
QFile file(argv[1]);
|
||||
QStringList errorStrings;
|
||||
SrmData data;
|
||||
if (readSrmFile(file, data, errorStrings))
|
||||
return 0;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
31
src/srm/srm.h
Normal file
31
src/srm/srm.h
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
#ifndef _srm_h
|
||||
#define _srm_h
|
||||
|
||||
#include <QDataStream>
|
||||
#include <QDate>
|
||||
#include <QFile>
|
||||
#include <QStringList>
|
||||
|
||||
struct SrmDataPoint
|
||||
{
|
||||
int cad, hr, watts, interval;
|
||||
double kph, km, secs;
|
||||
};
|
||||
|
||||
struct SrmData
|
||||
{
|
||||
QDateTime startTime;
|
||||
double recint;
|
||||
QList<SrmDataPoint*> dataPoints;
|
||||
~SrmData() {
|
||||
QListIterator<SrmDataPoint*> i(dataPoints);
|
||||
while (i.hasNext())
|
||||
delete i.next();
|
||||
}
|
||||
};
|
||||
|
||||
bool readSrmFile(QFile &file, SrmData &data, QStringList &errorStrings);
|
||||
|
||||
#endif // _srm_h
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
# Automatically generated by qmake (2.01a) Sun Apr 8 17:19:06 2007
|
||||
######################################################################
|
||||
|
||||
TEMPLATE = app
|
||||
TEMPLATE = lib
|
||||
TARGET =
|
||||
DEPENDPATH += .
|
||||
INCLUDEPATH += .
|
||||
|
||||
CXXFLAGS += -std=c99
|
||||
CONFIG += static
|
||||
LIBS += -lm
|
||||
|
||||
# Input
|
||||
HEADERS += srm.h
|
||||
SOURCES += srm.cpp
|
||||
|
||||
|
||||
Reference in New Issue
Block a user