Files
GoldenCheetah/src/FileIO/FixMoxy.cpp
Mark Liversedge a38696e25d Data Processor 'On Save' and Snippets
.. a data processor can now be configured to run on save

.. in addition, the data processor is now passed the operation
   that is triggering it: "Manual", "ADD", "UPDATE", "DELETE",
   "IMPORT".

.. a new data processor has been added to write a JSON file to
   the snippet directory (added to the athlete structure).

.. this is so we can output a snippet every time an activity is
   added, updated or deleted (i.e. runs "on save").

.. these JSON snippets can be used to update external datastores
   where coaches use other analytic software but don't want to
   manually sync GC changes with there external stores.
2016-11-12 22:36:44 +00:00

163 lines
5.3 KiB
C++

/*
* Copyright (c) 2015 Mark Liversedge
*
* 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 "DataProcessor.h"
#include "LTMOutliers.h"
#include "Settings.h"
#include "Units.h"
#include "HelpWhatsThis.h"
#include <algorithm>
#include <QVector>
#include <QCheckBox>
// Config widget used by the Preferences/Options config panes
class FixMoxy;
class FixMoxyConfig : public DataProcessorConfig
{
Q_DECLARE_TR_FUNCTIONS(FixMoxyConfig)
friend class ::FixMoxy;
protected:
QHBoxLayout *layout;
QLabel *paLabel;
QLabel *percentLabel;
QLineEdit *pa;
QCheckBox *cadConv;
QCheckBox *spdConv;
public:
FixMoxyConfig(QWidget *parent) : DataProcessorConfig(parent) {
HelpWhatsThis *help = new HelpWhatsThis(parent);
parent->setWhatsThis(help->getWhatsThisText(HelpWhatsThis::MenuBar_Edit_FixMoxy));
layout = new QHBoxLayout(this);
layout->setContentsMargins(0,0,0,0);
setContentsMargins(0,0,0,0);
paLabel = new QLabel(tr("Field Adjustment"));
cadConv = new QCheckBox(tr("Cadence to SMO2"));
spdConv = new QCheckBox(tr("Speed to tHb"));
layout->addWidget(paLabel);
layout->addWidget(cadConv);
layout->addWidget(spdConv);
layout->addStretch();
}
//~FixMoxyConfig() {} // deliberately not declared since Qt will delete
// the widget and its children when the config pane is deleted
QString explain() {
return(QString(tr("When recording from the Moxy or BSX Insight in Speed and"
" cadence mode the SmO2 and tHb data is sent as"
" cadence and speed respectively. This tool will"
" update the activity file to move the values from speed"
" and cadence into the Moxy series."
)));
}
void readConfig() {
bool isCad = appsettings->value(NULL, GC_CAD2SMO2, Qt::Checked).toBool();
bool isSpd = appsettings->value(NULL, GC_SPD2THB, Qt::Checked).toBool();
cadConv->setCheckState(isCad ? Qt::Checked : Qt::Unchecked);
spdConv->setCheckState(isSpd ? Qt::Checked : Qt::Unchecked);
}
void saveConfig() {
appsettings->setValue(GC_CAD2SMO2, cadConv->checkState());
appsettings->setValue(GC_SPD2THB, spdConv->checkState());
}
};
// RideFile Dataprocessor -- used to handle gaps in recording
// by inserting interpolated/zero samples
// to ensure dataPoints are contiguous in time
//
class FixMoxy : public DataProcessor {
Q_DECLARE_TR_FUNCTIONS(FixMoxy)
public:
FixMoxy() {}
~FixMoxy() {}
// the processor
bool postProcess(RideFile *, DataProcessorConfig* config, QString op);
// the config widget
DataProcessorConfig* processorConfig(QWidget *parent) {
return new FixMoxyConfig(parent);
}
// Localized Name
QString name() {
return tr("Set SmO2/tHb from Speed and Cadence");
}
};
static bool FixMoxyAdded = DataProcessorFactory::instance().registerProcessor(QString("Fix Moxy"), new FixMoxy());
bool
FixMoxy::postProcess(RideFile *ride, DataProcessorConfig *config=0, QString op="")
{
Q_UNUSED(config);
bool isCad;
bool isSpd;
if (config == NULL) { // being called automatically
isCad = appsettings->value(NULL, GC_CAD2SMO2, Qt::Checked).toBool();
isSpd = appsettings->value(NULL, GC_SPD2THB, Qt::Checked).toBool();
} else { // being called manually
isCad = ((FixMoxyConfig*)(config))->cadConv->checkState();
isSpd = ((FixMoxyConfig*)(config))->spdConv->checkState();
}
// does this ride have power?
if ((isSpd && ride->areDataPresent()->kph == false) ||
(isCad && ride->areDataPresent()->cad == false))
return false;
// apply the change
ride->command->startLUW("Fix Moxy");
for (int i=0; i<ride->dataPoints().count(); i++) {
RideFilePoint *point = ride->dataPoints()[i];
if (isCad) {
ride->command->setPointValue(i, RideFile::smo2, point->cad);
ride->command->setPointValue(i, RideFile::cad, 0.00f);
}
if (isSpd) {
ride->command->setPointValue(i, RideFile::thb, point->kph);
ride->command->setPointValue(i, RideFile::kph, 0.00f);
}
}
// shift the data present flags
if (isCad) {
ride->command->setDataPresent(RideFile::cad, false);
ride->command->setDataPresent(RideFile::smo2, true);
}
if (isSpd) {
ride->command->setDataPresent(RideFile::thb, true);
ride->command->setDataPresent(RideFile::kph, false);
}
ride->command->endLUW();
return true;
}