/* Statistics Report Generator Header * * Copyright (c) 2011-2018 Mark Watkins * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of the source code * for more details. */ #ifndef SUMMARY_H #define SUMMARY_H #include #include #include #include #include #include #include "SleepLib/schema.h" #include "SleepLib/machine.h" //! \brief Type of calculation on one statistics row enum StatCalcType { SC_UNDEFINED=0, SC_COLUMNHEADERS, SC_HEADING, SC_SUBHEADING, SC_MEDIAN, SC_AVG, SC_WAVG, SC_90P, SC_MIN, SC_MAX, SC_CPH, SC_SPH, SC_AHI, SC_HOURS, SC_COMPLIANCE, SC_DAYS, SC_ABOVE, SC_BELOW }; /*! \struct StatisticsRow \brief Describes a single row on the statistics page */ struct StatisticsRow { StatisticsRow() { calc=SC_UNDEFINED; } StatisticsRow(QString src, QString calc, QString type) { this->src = src; this->calc = lookupCalc(calc); this->type = lookupType(type); } StatisticsRow(QString src, StatCalcType calc, MachineType type) { this->src = src; this->calc = calc; this->type = type; } StatisticsRow(const StatisticsRow ©) { src=copy.src; calc=copy.calc; type=copy.type; } QString src; StatCalcType calc; MachineType type; //! \brief Looks up calculation type for this row StatCalcType lookupCalc(QString calc) { if (calc.compare("avg",Qt::CaseInsensitive)==0) { return SC_AVG; } else if (calc.compare("w-avg",Qt::CaseInsensitive)==0) { return SC_WAVG; } else if (calc.compare("median",Qt::CaseInsensitive)==0) { return SC_MEDIAN; } else if (calc.compare("90%",Qt::CaseInsensitive)==0) { return SC_90P; } else if (calc.compare("min", Qt::CaseInsensitive)==0) { return SC_MIN; } else if (calc.compare("max", Qt::CaseInsensitive)==0) { return SC_MAX; } else if (calc.compare("cph", Qt::CaseInsensitive)==0) { return SC_CPH; } else if (calc.compare("sph", Qt::CaseInsensitive)==0) { return SC_SPH; } else if (calc.compare("ahi", Qt::CaseInsensitive)==0) { return SC_AHI; } else if (calc.compare("hours", Qt::CaseInsensitive)==0) { return SC_HOURS; } else if (calc.compare("compliance", Qt::CaseInsensitive)==0) { return SC_COMPLIANCE; } else if (calc.compare("days", Qt::CaseInsensitive)==0) { return SC_DAYS; } else if (calc.compare("heading", Qt::CaseInsensitive)==0) { return SC_HEADING; } else if (calc.compare("subheading", Qt::CaseInsensitive)==0) { return SC_SUBHEADING; } return SC_UNDEFINED; } //! \brief Look up machine type MachineType lookupType(QString type) { if (type.compare("cpap", Qt::CaseInsensitive)==0) { return MT_CPAP; } else if (type.compare("oximeter", Qt::CaseInsensitive)==0) { return MT_OXIMETER; } else if (type.compare("sleepstage", Qt::CaseInsensitive)==0) { return MT_SLEEPSTAGE; } return MT_UNKNOWN; } ChannelID channel() { return schema::channel[src].id(); } QString value(QDate start, QDate end); }; //! \class Prescription (Machine) setting class RXItem { public: RXItem() { machine = nullptr; ahi = rdi = 0; highlight = 0; hours = 0; } RXItem(const RXItem & copy) { start = copy.start; end = copy.end; days = copy.days; s_count = copy.s_count; s_sum = copy.s_sum; ahi = copy.ahi; rdi = copy.rdi; hours = copy.hours; machine = copy.machine; relief = copy.relief; mode = copy.mode; pressure = copy.pressure; dates = copy.dates; highlight = copy.highlight; } RXItem& operator=(const RXItem& other) = default; inline quint64 count(ChannelID id) const { QHash::const_iterator it = s_count.find(id); if (it == s_count.end()) return 0; return it.value(); } inline double sum(ChannelID id) const{ QHash::const_iterator it = s_sum.find(id); if (it == s_sum.end()) return 0; return it.value(); } QDate start; QDate end; int days; QHash s_count; QHash s_sum; quint64 ahi; quint64 rdi; double hours; Machine * machine; QString relief; QString mode; QString pressure; QMap dates; short highlight; }; class Statistics : public QObject { Q_OBJECT public: explicit Statistics(QObject *parent = 0); void loadRXChanges(); void saveRXChanges(); void updateRXChanges(); QString GenerateHTML(); QString UpdateRecordsBox(); static void printReport(QWidget *parent = nullptr); protected: QString getUserInfo(); QString getRDIorAHIText(); QString htmlNoData(); QString generateHeader(bool showheader); QString generateFooter(bool showinfo=true); QString GenerateMachineList(); QString GenerateRXChanges(); QString GenerateCPAPUsage(); // Using a map to maintain order QList rows; QMap calcnames; QMap machinenames; QMap rxitems; QList record_best_ahi; QList record_worst_ahi; signals: public slots: }; #endif // SUMMARY_H