post merge master in release_3.0.0dev fixups.

This commit is contained in:
Mark Liversedge
2011-02-27 11:36:14 +00:00
6 changed files with 78 additions and 29 deletions

View File

@@ -660,7 +660,7 @@ struct BinFileReaderState
foreach(int num, unknown_format_identifiers) {
errors << QString("unknow format identifier %1; ignoring it").arg(num);
}
foreach(int num, unused_record_types) {
/*foreach(int num, unused_record_types) {
errors << QString("unused record type \"%1\" (%2)\n").arg(global_record_types[num].toAscii().constData())
.arg(num);
}
@@ -673,7 +673,7 @@ struct BinFileReaderState
.arg(global_record_types[record_type].toAscii().constData())
.arg(record_type);
}
}
}*/
foreach(int num, unexpected_record_types) {
errors << QString("unexpected record type %1 (%2)\n").arg(global_record_types[num]).arg(num);
}

View File

@@ -62,7 +62,7 @@ CriticalPowerWindow::CriticalPowerWindow(const QDir &home, MainWindow *parent) :
//cpintAllValue->setFixedWidth(width);
//cpintCPValue->setFixedWidth(width); // so lines up nicely
cpintTimeValue->setReadOnly(true);
cpintTimeValue->setReadOnly(false);
cpintTodayValue->setReadOnly(true);
cpintAllValue->setReadOnly(true);
cpintCPValue->setReadOnly(true);
@@ -93,6 +93,8 @@ CriticalPowerWindow::CriticalPowerWindow(const QDir &home, MainWindow *parent) :
connect(picker, SIGNAL(moved(const QPoint &)),
SLOT(pickerMoved(const QPoint &)));
connect(cpintTimeValue, SIGNAL(editingFinished()),
this, SLOT(cpintTimeValueEntered()));
connect(cpintSetCPButton, SIGNAL(clicked()),
this, SLOT(cpintSetCPButtonClicked()));
connect(cComboSeason, SIGNAL(currentIndexChanged(int)),
@@ -183,19 +185,16 @@ curve_to_point(double x, const QwtPlotCurve *curve)
}
void
CriticalPowerWindow::pickerMoved(const QPoint &pos)
CriticalPowerWindow::updateCpint(double minutes)
{
double minutes = cpintPlot->invTransform(QwtPlot::xBottom, pos.x());
cpintTimeValue->setText(interval_to_str(60.0*minutes));
// current ride
{
unsigned watts = curve_to_point(minutes, cpintPlot->getThisCurve());
QString label;
if (watts > 0)
label = QString(cpintPlot->energyMode() ? "%1 kJ" : "%1 watts").arg(watts);
label = QString(cpintPlot->energyMode() ? "%1 kJ" : "%1 watts").arg(watts);
else
label = tr("no data");
label = tr("no data");
cpintTodayValue->setText(label);
}
@@ -204,9 +203,9 @@ CriticalPowerWindow::pickerMoved(const QPoint &pos)
unsigned watts = curve_to_point(minutes, cpintPlot->getCPCurve());
QString label;
if (watts > 0)
label = QString(cpintPlot->energyMode() ? "%1 kJ" : "%1 watts").arg(watts);
label = QString(cpintPlot->energyMode() ? "%1 kJ" : "%1 watts").arg(watts);
else
label = tr("no data");
label = tr("no data");
cpintCPValue->setText(label);
}
@@ -215,7 +214,7 @@ CriticalPowerWindow::pickerMoved(const QPoint &pos)
QString label;
int index = (int) ceil(minutes * 60);
if (cpintPlot->getBests().count() > index) {
QDate date = cpintPlot->getBestDates()[index];
QDate date = cpintPlot->getBestDates()[index];
unsigned watts = cpintPlot->getBests()[index];
if (cpintPlot->energyMode())
label = QString("%1 kJ (%2)").arg(watts * minutes * 60.0 / 1000.0, 0, 'f', 0);
@@ -223,12 +222,28 @@ CriticalPowerWindow::pickerMoved(const QPoint &pos)
label = QString("%1 watts (%2)").arg(watts);
label = label.arg(date.isValid() ? date.toString(tr("MM/dd/yyyy")) : tr("no date"));
}
else
label = tr("no data");
else {
label = tr("no data");
}
cpintAllValue->setText(label);
}
}
void
CriticalPowerWindow::cpintTimeValueEntered()
{
double minutes = str_to_interval(cpintTimeValue->text()) / 60.0;
updateCpint(minutes);
}
void
CriticalPowerWindow::pickerMoved(const QPoint &pos)
{
double minutes = cpintPlot->invTransform(QwtPlot::xBottom, pos.x());
cpintTimeValue->setText(interval_to_str(60.0*minutes));
updateCpint(minutes);
}
void CriticalPowerWindow::addSeasons()
{
QFile seasonFile(home.absolutePath() + "/seasons.xml");

View File

@@ -51,13 +51,16 @@ class CriticalPowerWindow : public GcWindow
void setMode(int x) { yAxisCombo->setCurrentIndex(x); }
protected slots:
void cpintTimeValueEntered();
void cpintSetCPButtonClicked();
void pickerMoved(const QPoint &pos);
void rideSelected();
void seasonSelected(int season);
void setEnergyMode(int index);
private:
void updateCpint(double minutes);
protected:
QDir home;

View File

@@ -167,26 +167,43 @@ bool readRideInformationBlock(RideFile* rideFile, const QByteArray& block) {
return true;
}
struct RideFilePoint readSinglePoint(const QByteArray& record, const double& timeInSeconds, const double& recordingIntervalInSeconds,
const float& startDistance = 0.0f, const float& lastDistance = 0.0f) {
float distance = readFloatFromByteArray(record);
float relativeDistance = distance - startDistance;
quint8 heartRate = readByteFromByteArray(record.mid(4));
quint8 cadence = readByteFromByteArray(record.mid(5));
quint16 powerX10 = readUnsignedShortFromByteArray(record.mid(6));
double power = powerX10 / 10.0;
double speed = (relativeDistance - lastDistance) / recordingIntervalInSeconds;
struct RideFilePoint point(timeInSeconds, cadence, heartRate, relativeDistance / 1000.0, speed * 3.6, 0.0, power, 0.0, 0.0, 0.0, 0.0, 0);
return point;
}
bool readRideData(RideFile *rideFile, const QByteArray& block, const int nrOfRecords, const qint16 version) {
const int dataRecordSize = (version == 100) ? TACX_RIDE_DATA_BLOCK_SIZE : TACX_RIDE_DATA_BLOCK_SIZE + 8;
double seconds = rideFile->recIntSecs();
struct RideFilePoint firstDataPoint = readSinglePoint(block, seconds, rideFile->recIntSecs());
float startDistance = firstDataPoint.km * 1000.0;
float lastDistance = 0.0f;
for(int i = 0; i < nrOfRecords; i++, seconds += rideFile->recIntSecs()) {
const QByteArray& record = block.mid(i * dataRecordSize);
struct RideFilePoint nextDataPoint = readSinglePoint(record, seconds, rideFile->recIntSecs(), startDistance, lastDistance);
lastDistance = nextDataPoint.km * 1000.0;
float distance = readFloatFromByteArray(record);
quint8 heartRate = readByteFromByteArray(record.mid(4));
quint8 cadence = readByteFromByteArray(record.mid(5));
quint16 powerX10 = readUnsignedShortFromByteArray(record.mid(6));
double power = powerX10 / 10.0;
double speed = (distance - lastDistance) / rideFile->recIntSecs();
rideFile->appendPoint(seconds, cadence, heartRate, distance / 1000.0, speed * 3.6, 0.0, power, 0.0, 0.0, 0.0, 0.0, 0);
lastDistance = distance;
rideFile->appendPoint(nextDataPoint.secs, nextDataPoint.cad,
nextDataPoint.hr, nextDataPoint.km,
nextDataPoint.kph, nextDataPoint.nm,
nextDataPoint.watts, nextDataPoint.alt,
nextDataPoint.lon, nextDataPoint.lat,
nextDataPoint.headwind, nextDataPoint.interval);
}
return true;
}

View File

@@ -18,11 +18,12 @@
#include "TimeUtils.h"
#include <math.h>
#include <QRegExpValidator>
QString time_to_string(double secs)
{
QString result;
unsigned rounded = (unsigned) round(secs);
unsigned rounded = static_cast<unsigned>(round(secs));
bool needs_colon = false;
if (rounded >= 3600) {
result += QString("%1").arg(rounded / 3600);
@@ -38,12 +39,24 @@ QString time_to_string(double secs)
return result;
}
QString interval_to_str(double secs)
double str_to_interval(QString s)
{
QRegExp rx("(\\d+\\s*h)?\\s*(\\d{1,2}\\s*m)?\\s*(\\d{1,2})(\\.\\d+)?\\s*s");
rx.indexIn(s);
QString hour = rx.cap(1);
QString min = rx.cap(2);
QString sec = rx.cap(3) + rx.cap(4);
hour.chop(1);
min.chop(1);
return 3600.0 * hour.toUInt() + 60.0 * min.toUInt() + sec.toDouble();
}
QString interval_to_str(double secs)
{
if (secs < 60.0)
return QString("%1s").arg(secs, 0, 'f', 2, QLatin1Char('0'));
QString result;
unsigned rounded = (unsigned) round(secs);
unsigned rounded = static_cast<unsigned>(round(secs));
bool needs_colon = false;
if (rounded >= 3600) {
result += QString("%1h").arg(rounded / 3600);

View File

@@ -24,6 +24,7 @@
#include <QString>
QString interval_to_str(double secs); // output like 1h 2m 3s
double str_to_interval(QString s); // convert 1h 2m 3s -> 3123.0 , e.g.
QString time_to_string(double secs); // output like 1:02:03
/* takes a string containing an ISO 8601 timestamp and converts it to local time