mirror of
https://github.com/GoldenCheetah/GoldenCheetah.git
synced 2026-04-13 12:42:20 +00:00
* Changed the UI of CPPage to inline-editing of all values in all tables * Added a sports-specific selector for the model (cp2, cp3, ext, manual) * Allowed to create new ranges either manually or based on the estimated values of the model * Added option to reset each ranges values to those of the selected model * Added message to create a new range if todays estimate differs from those of the currently active one * Refined semi automatic power zones * Added a dialog to inspect and accept only some values while adoption * Added info messages * when the model does not provide FTP or PMAX * that AeTP is only a very rough estimate * Added a tolerance in comparison before proposing new values * Using the following order for defaults when adding a new manual range * selected row * last row * predefined defaults * Zones-Tab: To prevent crashes, a message is shown instead of the real interface if a metric refresh is ongoing * Changed Pace- and HR-Tabs to use inline editing * Moved the unittests into the same structure as the sourcecode * Added a simple (incomplete) unittest for kphToPace * Improved setting the column width * En-/Disabling the action buttons (add, delete, ...) based on the contents state * Changed the layout to prevent jumping widgets when showing / hiding buttons * Fixed compiler warnings from Visual-C++ * Adopt dialog: Refined layout * Fixed the unit of "From BPM" on HR-Page * Set the default mode to manual Fixes #1381
230 lines
7.4 KiB
C++
230 lines
7.4 KiB
C++
/*
|
|
* Copyright (c) 2006 Sean C. Rhea (srhea@srhea.net)
|
|
*
|
|
* 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
|
|
*/
|
|
|
|
#ifndef _Zones_h
|
|
#define _Zones_h
|
|
#include "GoldenCheetah.h"
|
|
#include "Athlete.h"
|
|
|
|
#include <QtCore>
|
|
|
|
// A zone "scheme" defines how power zones
|
|
// are calculated as a percentage of CP
|
|
// The default is to use Coggan percentages
|
|
// but this can be overriden in power.zones
|
|
struct ZoneScheme {
|
|
QList <int> zone_default;
|
|
QList <bool> zone_default_is_pct;
|
|
QList <QString> zone_default_name;
|
|
QList <QString> zone_default_desc;
|
|
int nzones_default;
|
|
};
|
|
|
|
// A zone "info" defines a *single zone*
|
|
// in absolute watts terms e.g.
|
|
// "L4" "Threshold" is between 270w and 315w
|
|
struct ZoneInfo {
|
|
QString name, desc;
|
|
int lo, hi;
|
|
ZoneInfo(const QString &n, const QString &d, int l, int h) :
|
|
name(n), desc(d), lo(l), hi(h) {}
|
|
|
|
// used by std::sort
|
|
bool operator< (ZoneInfo right) const {
|
|
return ((lo < right.lo) || ((lo == right.lo) && (hi < right.hi)));
|
|
}
|
|
};
|
|
|
|
// A zone "range" defines the power zones
|
|
// that are active for a *specific date period*
|
|
// e.g. between 01/01/2008 and 01/04/2008
|
|
// my CP was 290 and I chose to setup
|
|
// 7 zoneinfos from Active Recovery through
|
|
// to muscular Endurance
|
|
struct ZoneRange {
|
|
QDate begin, end;
|
|
int cp;
|
|
int aet;
|
|
int ftp;
|
|
int wprime; // aka awc
|
|
int pmax;
|
|
QList<ZoneInfo> zones;
|
|
bool zonesSetFromCP;
|
|
ZoneRange(const QDate &b, const QDate &e) :
|
|
begin(b), end(e), cp(0), aet(0), ftp(0), wprime(0), pmax(0), zonesSetFromCP(false) {}
|
|
ZoneRange(const QDate &b, const QDate &e, int _cp, int _aet, int _ftp, int _wprime, int pmax) :
|
|
begin(b), end(e), cp(_cp), aet(_aet), ftp(_ftp), wprime(_wprime), pmax(pmax), zonesSetFromCP(false) {}
|
|
|
|
// used by std::sort
|
|
bool operator< (ZoneRange right) const {
|
|
return (((! right.begin.isNull()) &&
|
|
(begin.isNull() || begin < right.begin )) ||
|
|
((begin == right.begin) && (! end.isNull()) &&
|
|
( right.end.isNull() || end < right.end )));
|
|
}
|
|
};
|
|
|
|
|
|
class Zones : public QObject
|
|
{
|
|
Q_OBJECT
|
|
G_OBJECT
|
|
|
|
|
|
private:
|
|
|
|
// Sport
|
|
QString sport_;
|
|
|
|
// Scheme
|
|
bool defaults_from_user;
|
|
ZoneScheme scheme;
|
|
|
|
// CP History
|
|
QList<ZoneRange> ranges;
|
|
|
|
// utility
|
|
QString err, warning, fileName_;
|
|
void setZonesFromCP(ZoneRange &range);
|
|
|
|
public:
|
|
|
|
Zones(QString sport="Bike") : sport_(sport), defaults_from_user(false) {
|
|
initializeZoneParameters();
|
|
}
|
|
|
|
//
|
|
// Zone settings - Scheme (& default scheme)
|
|
//
|
|
ZoneScheme getScheme() const { return scheme; }
|
|
void setScheme(ZoneScheme x) { scheme = x; }
|
|
|
|
// get defaults from the current scheme
|
|
QString getDefaultZoneName(int z) const;
|
|
QString getDefaultZoneDesc(int z) const;
|
|
|
|
// set zone parameters to either user-specified defaults
|
|
// or to defaults using Coggan's coefficients
|
|
void initializeZoneParameters();
|
|
|
|
// Sport
|
|
QString sport() { return sport_; }
|
|
|
|
//
|
|
// Zone history - Ranges
|
|
//
|
|
// How many ranges in our history
|
|
int getRangeSize() const;
|
|
|
|
// Add ranges
|
|
void addZoneRange(QDate _start, QDate _end, int _cp, int _aet, int _ftp, int _wprime, int _pmax);
|
|
int addZoneRange(QDate _start, int _cp, int _aet, int _ftp, int _wprime, int _pmax);
|
|
void addZoneRange();
|
|
|
|
// Get / Set ZoneRange details
|
|
ZoneRange getZoneRange(int rnum) { return ranges[rnum]; }
|
|
void setZoneRange(int rnum, ZoneRange x) { ranges[rnum] = x; }
|
|
|
|
// get and set CP for a given range
|
|
int getCP(int rnum) const;
|
|
void setCP(int rnum, int cp);
|
|
int getAeT(int rnum) const;
|
|
void setAeT(int rnum, int aet);
|
|
int getFTP(int rnum) const;
|
|
void setFTP(int rnum, int ftp);
|
|
int getWprime(int rnum) const;
|
|
void setWprime(int rnum, int wprime);
|
|
int getPmax(int rnum) const;
|
|
void setPmax(int rnum, int pmax);
|
|
|
|
// calculate and then set zoneinfo for a given range
|
|
void setZonesFromCP(int rnum);
|
|
|
|
// delete the range rnum, and adjust dates on adjacent zone; return
|
|
// the range number of the range extended to cover the deleted zone
|
|
int deleteRange(const int rnum);
|
|
|
|
//
|
|
// read and write power.zones
|
|
//
|
|
bool read(QFile &file);
|
|
void write(QDir home);
|
|
const QString &fileName() const { return fileName_; }
|
|
const QString &errorString() const { return err; }
|
|
const QString &warningString() const { return warning; }
|
|
|
|
|
|
//
|
|
// Typical APIs to get details of ranges and zones
|
|
//
|
|
|
|
// which range is active for a particular date
|
|
int whichRange(const QDate &date) const;
|
|
|
|
// which zone is the power value in for a given range
|
|
// will return -1 if not in any zone
|
|
int whichZone(int range, double value) const;
|
|
|
|
// how many zones are there for a given range
|
|
int numZones(int range) const;
|
|
|
|
// get zoneinfo for a given range and zone
|
|
void zoneInfo(int range, int zone,
|
|
QString &name, QString &description,
|
|
int &low, int &high) const;
|
|
|
|
QString summarize(int rnum, QVector<double> &time_in_zone, QColor color = QColor(Qt::darkGray)) const;
|
|
|
|
// get all highs/lows for zones (plot shading uses these)
|
|
int lowsFromCP(QList <int> *lows, int CP) const;
|
|
QList <int> getZoneLows(int rnum) const;
|
|
QList <int> getZoneHighs(int rnum) const;
|
|
QList <QString> getZoneNames(int rnum) const;
|
|
QList <QString> getZoneDescriptions(int rnum) const;
|
|
|
|
// get/set range start and end date
|
|
QDate getStartDate(int rnum) const;
|
|
QDate getEndDate(int rnum) const;
|
|
QString getStartDateString(int rnum) const;
|
|
QString getEndDateString(int rnum) const;
|
|
void setEndDate(int rnum, QDate date);
|
|
void setStartDate(int rnum, QDate date);
|
|
|
|
// When was this last updated?
|
|
QDateTime modificationTime;
|
|
|
|
// calculate a CRC for the zones data - used to see if zones
|
|
// data is changed since last referenced in Metric code
|
|
// could also be used in Configuration pages (later)
|
|
quint16 getFingerprint() const;
|
|
|
|
// this is the fingerprint for a specific DATE so that we
|
|
// can be more granular -- did the zone config for the date of
|
|
// a particular ride change ?
|
|
quint16 getFingerprint(QDate date) const;
|
|
|
|
// USE_CP_FOR_FTP setting differenciated by sport
|
|
QString useCPforFTPSetting() const;
|
|
|
|
QString useCPModelSetting() const;
|
|
};
|
|
|
|
QColor zoneColor(int zone, int num_zones);
|
|
|
|
#endif // _Zones_h
|