mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-02-15 00:49:55 +00:00
FitRideFile: Add Calibration Event parsing
This commit is contained in:
@@ -805,6 +805,7 @@ AllPlot::recalc()
|
||||
|
||||
setYMax();
|
||||
refreshIntervalMarkers();
|
||||
refreshCalibrationMarkers();
|
||||
refreshZoneLabels();
|
||||
|
||||
//replot();
|
||||
@@ -843,6 +844,36 @@ AllPlot::refreshIntervalMarkers()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AllPlot::refreshCalibrationMarkers()
|
||||
{
|
||||
foreach(QwtPlotMarker *mrk, cal_mrk) {
|
||||
mrk->detach();
|
||||
delete mrk;
|
||||
}
|
||||
cal_mrk.clear();
|
||||
|
||||
if (rideItem->ride()) {
|
||||
foreach(const RideFileCalibration &calibration, rideItem->ride()->calibrations()) {
|
||||
QwtPlotMarker *mrk = new QwtPlotMarker;
|
||||
cal_mrk.append(mrk);
|
||||
mrk->attach(this);
|
||||
mrk->setLineStyle(QwtPlotMarker::VLine);
|
||||
mrk->setLabelAlignment(Qt::AlignRight | Qt::AlignTop);
|
||||
mrk->setLinePen(QPen(GColor(CCALIBRATIONMARKER), 0, Qt::DashDotLine));
|
||||
QwtText text("\n\n"+calibration.name);
|
||||
text.setFont(QFont("Helvetica", 9, QFont::Bold));
|
||||
text.setColor(GColor(CCALIBRATIONMARKER));
|
||||
if (!bydist)
|
||||
mrk->setValue(calibration.start / 60.0, 0.0);
|
||||
else
|
||||
mrk->setValue((context->athlete->useMetricUnits ? 1 : MILES_PER_KM) *
|
||||
rideItem->ride()->timeToDistance(calibration.start), 0.0);
|
||||
mrk->setLabel(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AllPlot::setYMax()
|
||||
{
|
||||
@@ -1180,6 +1211,7 @@ AllPlot::setDataFromPlot(AllPlot *plot, int startidx, int stopidx)
|
||||
|
||||
|
||||
refreshIntervalMarkers();
|
||||
refreshCalibrationMarkers();
|
||||
refreshZoneLabels();
|
||||
|
||||
//if (this->legend()) this->legend()->show();
|
||||
|
||||
@@ -61,6 +61,7 @@ class AllPlot : public QwtPlot
|
||||
bool shadeZones() const;
|
||||
void refreshZoneLabels();
|
||||
void refreshIntervalMarkers();
|
||||
void refreshCalibrationMarkers();
|
||||
void setAxisTitle(int axis, QString label);
|
||||
|
||||
// refresh data / plot parameters
|
||||
@@ -116,6 +117,7 @@ class AllPlot : public QwtPlot
|
||||
// plot objects
|
||||
QwtPlotGrid *grid;
|
||||
QVector<QwtPlotMarker*> d_mrk;
|
||||
QVector<QwtPlotMarker*> cal_mrk;
|
||||
QwtPlotMarker *allMarker1;
|
||||
QwtPlotMarker *allMarker2;
|
||||
QwtPlotCurve *wattsCurve;
|
||||
|
||||
@@ -110,6 +110,7 @@ void GCColor::setupColors()
|
||||
{ tr("Alternate Power"), "CALTPOWER", Qt::magenta },
|
||||
{ tr("Left Balance"), "CBALANCELEFT", QColor(178,0,0) },
|
||||
{ tr("Right Balance"), "CBALANCERIGHT", QColor(128,0,50) },
|
||||
{ tr("Plot Markers"), "COLORCALIBRATIONMARKER", QColor(40,40,40) },
|
||||
{ "", "", QColor(0,0,0) },
|
||||
};
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ class ColorEngine : public QObject
|
||||
#define GColor(x) GCColor::getColor(x)
|
||||
|
||||
// Define how many cconfigurable metric colors are available
|
||||
#define CNUMOFCFGCOLORS 70
|
||||
#define CNUMOFCFGCOLORS 71
|
||||
|
||||
#define CPLOTBACKGROUND 0
|
||||
#define CRIDEPLOTBACKGROUND 1
|
||||
@@ -171,5 +171,6 @@ class ColorEngine : public QObject
|
||||
#define CALTPOWER 67
|
||||
#define CBALANCELEFT 68
|
||||
#define CBALANCERIGHT 69
|
||||
#define CCALIBRATIONMARKER 70
|
||||
|
||||
#endif
|
||||
|
||||
@@ -68,6 +68,7 @@ struct FitFileReaderState
|
||||
QMap<int, FitDefinition> local_msg_types;
|
||||
QSet<int> unknown_record_fields, unknown_global_msg_nums, unknown_base_type;
|
||||
int interval;
|
||||
int calibration;
|
||||
int devices;
|
||||
bool stopped;
|
||||
int last_event_type;
|
||||
@@ -76,7 +77,7 @@ struct FitFileReaderState
|
||||
|
||||
FitFileReaderState(QFile &file, QStringList &errors) :
|
||||
file(file), errors(errors), rideFile(NULL), start_time(0),
|
||||
last_time(0), last_distance(0.00f), interval(0), devices(0), stopped(true),
|
||||
last_time(0), last_distance(0.00f), interval(0), calibration(0), devices(0), stopped(true),
|
||||
last_event_type(-1), last_event(-1), last_msg_type(-1)
|
||||
{
|
||||
}
|
||||
@@ -251,8 +252,10 @@ struct FitFileReaderState
|
||||
}
|
||||
|
||||
void decodeEvent(const FitDefinition &def, int, const std::vector<fit_value_t> values) {
|
||||
int time = -1;
|
||||
int event = -1;
|
||||
int event_type = -1;
|
||||
qint16 data16 = -1;
|
||||
int i = 0;
|
||||
foreach(const FitField &field, def.fields) {
|
||||
fit_value_t value = values[i++];
|
||||
@@ -261,10 +264,15 @@ struct FitFileReaderState
|
||||
continue;
|
||||
|
||||
switch (field.num) {
|
||||
case 253: //time = value + qbase_time.toTime_t();
|
||||
case 253: // timestamp field (s)
|
||||
time = value + qbase_time.toTime_t();
|
||||
break;
|
||||
case 0: event = value; break;
|
||||
case 1: event_type = value; break;
|
||||
case 0: // event field
|
||||
event = value; break;
|
||||
case 1: // event_type field
|
||||
event_type = value; break;
|
||||
case 2: // data16 field
|
||||
data16 = value; break;
|
||||
default: ; // do nothing
|
||||
}
|
||||
}
|
||||
@@ -292,7 +300,19 @@ struct FitFileReaderState
|
||||
stopped = true;
|
||||
break;
|
||||
default:
|
||||
errors << QString("Unknown event type %1").arg(event_type);
|
||||
errors << QString("Unknown timer event type %1").arg(event_type);
|
||||
}
|
||||
}
|
||||
else if (event == 36) { // Calibration event
|
||||
int secs = (start_time==0?0:time-start_time);
|
||||
switch (event_type) {
|
||||
case 3: // marker
|
||||
++calibration;
|
||||
rideFile->addCalibration(secs, data16, QString("Calibration %1 (%2)").arg(calibration).arg(data16));
|
||||
qDebug() << "marker" << secs << data16;
|
||||
break;
|
||||
default:
|
||||
errors << QString("Unknown calibration event type %1").arg(event_type);
|
||||
}
|
||||
}
|
||||
// printf("event type %d\n", event_type);
|
||||
@@ -375,8 +395,10 @@ struct FitFileReaderState
|
||||
case 13: temperature = value; break;
|
||||
case 29: // ACCUMULATED_POWER
|
||||
break;
|
||||
case 30: lrbalance = (value & 0x80 ? 100 - (value & 0x7F) : value & 0x7F);break;
|
||||
|
||||
case 30: lrbalance = (value & 0x80 ? 100 - (value & 0x7F) : value & 0x7F);
|
||||
break;
|
||||
case 31: // GPS Accuracy
|
||||
break;
|
||||
default: unknown_record_fields.insert(field.num);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@
|
||||
\"NAME\" return NAME;
|
||||
\"START\" return START;
|
||||
\"STOP\" return STOP;
|
||||
\"CALIBRATIONS\" return CALIBRATIONS;
|
||||
\"VALUE\" return VALUE;
|
||||
\"REFERENCES\" return REFERENCES;
|
||||
\"SAMPLES\" return SAMPLES;
|
||||
\"SECS\" return SECS;
|
||||
|
||||
@@ -43,6 +43,7 @@ static RideFile *JsonRide;
|
||||
// term state data is held in these variables
|
||||
static RideFilePoint JsonPoint;
|
||||
static RideFileInterval JsonInterval;
|
||||
static RideFileCalibration JsonCalibration;
|
||||
static QString JsonString,
|
||||
JsonTagKey, JsonTagValue,
|
||||
JsonOverName, JsonOverKey, JsonOverValue;
|
||||
@@ -108,6 +109,7 @@ static QString unprotect(const QString string)
|
||||
%token RIDE STARTTIME RECINTSECS DEVICETYPE IDENTIFIER
|
||||
%token OVERRIDES
|
||||
%token TAGS INTERVALS NAME START STOP
|
||||
%token CALIBRATIONS VALUE
|
||||
%token REFERENCES
|
||||
%token SAMPLES SECS KM WATTS NM CAD KPH HR ALTITUDE LAT LON HEADWIND SLOPE TEMP LRBALANCE
|
||||
|
||||
@@ -136,6 +138,7 @@ rideelement: starttime
|
||||
| overrides
|
||||
| tags
|
||||
| intervals
|
||||
| calibrations
|
||||
| references
|
||||
| samples
|
||||
;
|
||||
@@ -194,6 +197,22 @@ interval: '{' NAME ':' string ',' { JsonInterval.name = JsonString; }
|
||||
JsonInterval = RideFileInterval();
|
||||
}
|
||||
|
||||
/*
|
||||
* Calibrations
|
||||
*/
|
||||
calibrations: CALIBRATIONS ':' '[' calibration_list ']' ;
|
||||
calibration_list: calibration | calibration_list ',' calibration ;
|
||||
calibration: '{' NAME ':' string ',' { JsonCalibration.name = JsonString; }
|
||||
START ':' number ',' { JsonCalibration.start = JsonNumber; }
|
||||
VALUE ':' number { JsonCalibration.value = JsonNumber; }
|
||||
'}'
|
||||
{ JsonRide->addCalibration(JsonCalibration.start,
|
||||
JsonCalibration.value,
|
||||
JsonCalibration.name);
|
||||
JsonCalibration = RideFileCalibration();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Ride references
|
||||
*/
|
||||
@@ -403,6 +422,26 @@ JsonFileReader::writeRideFile(Context *, const RideFile *ride, QFile &file) cons
|
||||
out <<"\n\t\t]";
|
||||
}
|
||||
|
||||
//
|
||||
// CALIBRATION
|
||||
//
|
||||
if (!ride->calibrations().empty()) {
|
||||
|
||||
out << ",\n\t\t\"CALIBRATIONS\":[\n";
|
||||
bool first = true;
|
||||
|
||||
foreach (RideFileCalibration i, ride->calibrations()) {
|
||||
if (first) first=false;
|
||||
else out << ",\n";
|
||||
|
||||
out << "\t\t\t{ ";
|
||||
out << "\"NAME\":\"" << protect(i.name) << "\"";
|
||||
out << ", \"START\": " << QString("%1").arg(i.start);
|
||||
out << ", \"VALUE\": " << QString("%1").arg(i.value) << " }";
|
||||
}
|
||||
out <<"\n\t\t]";
|
||||
}
|
||||
|
||||
//
|
||||
// SAMPLES
|
||||
//
|
||||
|
||||
@@ -74,6 +74,19 @@ struct RideFileInterval
|
||||
bool operator< (RideFileInterval right) const { return start < right.start; }
|
||||
};
|
||||
|
||||
struct RideFileCalibration
|
||||
{
|
||||
double start;
|
||||
int value;
|
||||
QString name;
|
||||
RideFileCalibration() : start(0.0), value(0) {}
|
||||
RideFileCalibration(double start, int value, QString name) :
|
||||
start(start), value(value), name(name) {}
|
||||
|
||||
// order bu start time
|
||||
bool operator< (RideFileCalibration right) const { return start < right.start; }
|
||||
};
|
||||
|
||||
class RideFile : public QObject // QObject to emit signals
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -145,6 +158,12 @@ class RideFile : public QObject // QObject to emit signals
|
||||
void fillInIntervals();
|
||||
int intervalBegin(const RideFileInterval &interval) const;
|
||||
|
||||
// Working with CAIBRATIONS
|
||||
const QList<RideFileCalibration> &calibrations() const { return calibrations_; }
|
||||
void addCalibration(double start, int value, const QString &name) {
|
||||
calibrations_.append(RideFileCalibration(start, value, name));
|
||||
}
|
||||
|
||||
// Index offset calculations
|
||||
double timeToDistance(double) const; // get distance in km at time in secs
|
||||
int timeIndex(double) const; // get index offset for time in secs
|
||||
@@ -206,6 +225,7 @@ class RideFile : public QObject // QObject to emit signals
|
||||
QString deviceType_;
|
||||
QString fileFormat_;
|
||||
QList<RideFileInterval> intervals_;
|
||||
QList<RideFileCalibration> calibrations_;
|
||||
QMap<QString,QString> tags_;
|
||||
EditorData *data;
|
||||
double weight_; // cached to save calls to getWeight();
|
||||
|
||||
Reference in New Issue
Block a user