mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-15 05:32:21 +00:00
post merge master in release_3.0.0dev fixups.
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user