mirror of
https://github.com/subsurface/subsurface.git
synced 2024-11-28 05:00:20 +00:00
divesummary: add DiveSummary class to shared and backend
Create DiveSummary class in backend-shared and make the DiveSummary calculation results available to QML. This adds a loop over all dives (could have been done with a model, but the models available to mobile are very limited, so use the basic way). [Dirk Hohndel: renamed the results variable and combined a couple of commits] Signed-off-by: jan Iversen <jan@casacondor.com> Signed-off-by: Dirk Hohndel <dirk@hohndel.org>
This commit is contained in:
parent
bb13065a75
commit
6cd46bee06
6 changed files with 222 additions and 1 deletions
|
@ -1,6 +1,7 @@
|
|||
# backend functionality shared between Desktop (UI) and Mobile (QML)
|
||||
|
||||
set(BACKEND_SRCS
|
||||
divesummary.cpp
|
||||
exportfuncs.cpp
|
||||
exportfuncs.h
|
||||
plannershared.cpp
|
||||
|
|
169
backend-shared/divesummary.cpp
Normal file
169
backend-shared/divesummary.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "divesummary.h"
|
||||
#include "core/qthelper.h"
|
||||
#include "core/settings/qPrefUnit.h"
|
||||
|
||||
#include <QDateTime>
|
||||
|
||||
QStringList diveSummary::diveSummaryText;
|
||||
|
||||
timestamp_t diveSummary::firstDive, diveSummary::lastDive;
|
||||
int diveSummary::dives[2], diveSummary::divesEAN[2], diveSummary::divesDeep[2], diveSummary::diveplans[2];
|
||||
long diveSummary::divetime[2], diveSummary::depth[2], diveSummary::sac[2];
|
||||
long diveSummary::divetimeMax[2], diveSummary::depthMax[2], diveSummary::sacMin[2];
|
||||
|
||||
void diveSummary::summaryCalculation(int primaryPeriod, int secondaryPeriod)
|
||||
{
|
||||
QDateTime localTime;
|
||||
|
||||
// Calculate Start of the 2 periods.
|
||||
timestamp_t now, primaryStart, secondaryStart;
|
||||
now = QDateTime::currentMSecsSinceEpoch() / 1000L + gettimezoneoffset();
|
||||
primaryStart = (primaryPeriod == 0) ? 0 : now - primaryPeriod * 30 * 24 * 60 * 60;
|
||||
secondaryStart = (secondaryPeriod == 0) ? 0 : now - secondaryPeriod * 30 * 24 * 60 * 60;
|
||||
|
||||
// Loop over all dives and sum up data
|
||||
loopDives(primaryStart, secondaryStart);
|
||||
|
||||
// prepare stringlist
|
||||
diveSummaryText.clear();
|
||||
diveSummaryText << "??" << "??" << "??" << "??" << "??" <<
|
||||
"??" << "??" << "??" <<
|
||||
"?:??" << "?:??" << "?:??" <<
|
||||
"?:??" << "?:??" << "?:??" <<
|
||||
"??" << "??" << "??" << "??" << "??" <<
|
||||
"??" << "??" << "??" << "??" << "??";
|
||||
|
||||
// set oldest/newest date
|
||||
if (firstDive) {
|
||||
localTime = QDateTime::fromMSecsSinceEpoch(1000 * firstDive, Qt::UTC);
|
||||
localTime.setTimeSpec(Qt::UTC);
|
||||
diveSummaryText[0] = QStringLiteral("%1").arg(localTime.date().toString(prefs.date_format_short));
|
||||
}
|
||||
if (lastDive) {
|
||||
localTime = QDateTime::fromMSecsSinceEpoch(1000 * lastDive, Qt::UTC);
|
||||
localTime.setTimeSpec(Qt::UTC);
|
||||
diveSummaryText[1] = QStringLiteral("%1").arg(localTime.date().toString(prefs.date_format_short));
|
||||
}
|
||||
|
||||
// and add data
|
||||
buildStringList(0);
|
||||
buildStringList(1);
|
||||
}
|
||||
|
||||
void diveSummary::loopDives(timestamp_t primaryStart, timestamp_t secondaryStart)
|
||||
{
|
||||
struct dive *dive;
|
||||
int i;
|
||||
|
||||
// Clear summary data
|
||||
firstDive = lastDive = 0;
|
||||
dives[0] = dives[1] = divesEAN[0] = divesEAN[1] = 0;
|
||||
divesDeep[0] = divesDeep[1] = diveplans[0] = diveplans[1] = 0;
|
||||
divetime[0] = divetime[1] = depth[0] = depth[1] = 0;
|
||||
sac[0] = sac[1] = 0;
|
||||
divetimeMax[0] = divetimeMax[1] = depthMax[0] = depthMax[1] = 0;
|
||||
sacMin[0] = sacMin[1] = 99999;
|
||||
|
||||
for_each_dive (i, dive) {
|
||||
// remember time of oldest and newest dive
|
||||
if (i == 0)
|
||||
firstDive = dive->when;
|
||||
if (dive->when > lastDive)
|
||||
lastDive = dive->when;
|
||||
|
||||
// check if dive is newer than primaryStart (add to first column)
|
||||
if (dive->when > primaryStart) {
|
||||
if (is_dc_planner(&dive->dc))
|
||||
diveplans[0]++;
|
||||
else
|
||||
calculateDive(0, dive);
|
||||
}
|
||||
|
||||
// check if dive is newer than secondaryStart (add to second column)
|
||||
if (dive->when > secondaryStart) {
|
||||
if (is_dc_planner(&dive->dc))
|
||||
diveplans[1]++;
|
||||
else
|
||||
calculateDive(1, dive);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void diveSummary::calculateDive(int inx, struct dive *dive)
|
||||
{
|
||||
long temp;
|
||||
|
||||
// one more real dive
|
||||
dives[inx]++;
|
||||
|
||||
// sum dive in minutes and check for new max.
|
||||
temp = dive->duration.seconds / 60;
|
||||
divetime[inx] += temp;
|
||||
if (temp > divetimeMax[inx])
|
||||
divetimeMax[inx] = temp;
|
||||
|
||||
// sum depth in meters, check for new max. and if dive is a deep dive
|
||||
temp = dive->maxdepth.mm / 1000;
|
||||
depth[inx] += temp;
|
||||
if (temp > depthMax[inx])
|
||||
depthMax[inx] = temp;
|
||||
if (temp > 39)
|
||||
divesDeep[inx]++;
|
||||
|
||||
// sum SAC in liters, check for new max.
|
||||
temp = dive->sac / 1000;
|
||||
sac[inx] += temp;
|
||||
if (temp < sacMin[inx])
|
||||
sacMin[inx] = temp;
|
||||
|
||||
// EAN dive ?
|
||||
for (int j = 0; j < dive->cylinders.nr; ++j) {
|
||||
if (dive->cylinders.cylinders[j].gasmix.o2.permille > 210)
|
||||
divesEAN[inx]++;
|
||||
}
|
||||
}
|
||||
|
||||
void diveSummary::buildStringList(int inx)
|
||||
{
|
||||
int temp1, temp2;
|
||||
QString tempStr;
|
||||
|
||||
if (!dives[inx])
|
||||
return;
|
||||
|
||||
// dives
|
||||
diveSummaryText[2+inx] = QStringLiteral("%1").arg(dives[inx]);
|
||||
diveSummaryText[4+inx] = QStringLiteral("%1").arg(divesEAN[inx]);
|
||||
diveSummaryText[6+inx] = QStringLiteral("%1").arg(divesDeep[inx]);
|
||||
|
||||
// time
|
||||
temp1 = divetime[inx] / 60;
|
||||
temp2 = divetime[inx] - temp1 * 60;
|
||||
if (temp1 >= 100)
|
||||
diveSummaryText[8+inx] = QStringLiteral("%1h").arg(temp1);
|
||||
else
|
||||
diveSummaryText[8+inx] = QStringLiteral("%1:%2").arg(temp1).arg(temp2);
|
||||
temp1 = divetimeMax[inx] / 60;
|
||||
temp2 = divetimeMax[inx] - temp1 * 60;
|
||||
diveSummaryText[10+inx] = QStringLiteral("%1:%2").arg(temp1).arg(temp2);
|
||||
temp2 = divetime[inx] / dives[inx];
|
||||
temp1 = temp2 / 60;
|
||||
temp2 = temp2 - temp1 * 60;
|
||||
diveSummaryText[12+inx] = QStringLiteral("%1:%2").arg(temp1).arg(temp2);
|
||||
|
||||
// depth
|
||||
tempStr = (qPrefUnits::length() == units::METERS) ? "m" : "ft";
|
||||
diveSummaryText[14+inx] = QStringLiteral("%1%2").arg(depthMax[inx]).arg(tempStr);
|
||||
temp1 = depth[inx] / dives[inx];
|
||||
diveSummaryText[16+inx] = QStringLiteral("%1%2").arg(temp1).arg(tempStr);
|
||||
|
||||
// SAC
|
||||
tempStr = (qPrefUnits::volume() == units::LITER) ? "l/min" : "cuft/min";
|
||||
diveSummaryText[18+inx] = QStringLiteral("%1 %2").arg(sacMin[inx]).arg(tempStr);
|
||||
temp1 = depth[inx] / dives[inx];
|
||||
diveSummaryText[20+inx] = QStringLiteral("%1%2").arg(temp1).arg(tempStr);
|
||||
|
||||
// Diveplan(s)
|
||||
diveSummaryText[22+inx] = QStringLiteral("%1").arg(diveplans[inx]);
|
||||
}
|
28
backend-shared/divesummary.h
Normal file
28
backend-shared/divesummary.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#ifndef DIVESUMMARY_H
|
||||
#define DIVESUMMARY_H
|
||||
#include <QStringList>
|
||||
#include "core/dive.h"
|
||||
|
||||
|
||||
class diveSummary {
|
||||
|
||||
public:
|
||||
static void summaryCalculation(int primaryPeriod, int secondaryPeriod);
|
||||
|
||||
static QStringList diveSummaryText;
|
||||
|
||||
private:
|
||||
diveSummary() {}
|
||||
|
||||
static void loopDives(timestamp_t primaryStart, timestamp_t secondaryStart);
|
||||
static void calculateDive(int inx, struct dive *dive);
|
||||
static void buildStringList(int inx);
|
||||
|
||||
static timestamp_t firstDive, lastDive;
|
||||
static int dives[2], divesEAN[2], divesDeep[2], diveplans[2];
|
||||
static long divetime[2], depth[2], sac[2];
|
||||
static long divetimeMax[2], depthMax[2], sacMin[2];
|
||||
static long divetimeAvg[2], depthAvg[2], sacAvg[2];
|
||||
};
|
||||
#endif // DIVESUMMARY_H
|
|
@ -1,6 +1,5 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "qmlinterface.h"
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
QMLInterface *QMLInterface::instance()
|
||||
|
@ -92,4 +91,15 @@ void QMLInterface::setup(QQmlContext *ct)
|
|||
instance(), &QMLInterface::verbatim_planChanged);
|
||||
connect(qPrefDivePlanner::instance(), &qPrefDivePlanner::display_variationsChanged,
|
||||
instance(), &QMLInterface::display_variationsChanged);
|
||||
|
||||
// calculate divesummary first time.
|
||||
// this is needed in order to load the divesummary page
|
||||
diveSummary::summaryCalculation(0, 3);
|
||||
}
|
||||
|
||||
|
||||
void QMLInterface::summaryCalculation(int primaryPeriod, int secondaryPeriod)
|
||||
{
|
||||
diveSummary::summaryCalculation(primaryPeriod, secondaryPeriod);
|
||||
emit diveSummaryTextChanged(diveSummary::diveSummaryText);
|
||||
}
|
||||
|
|
|
@ -7,9 +7,12 @@
|
|||
#include "core/settings/qPrefTechnicalDetails.h"
|
||||
#include "qt-models/diveplannermodel.h"
|
||||
#include "backend-shared/plannershared.h"
|
||||
#include "backend-shared/divesummary.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QQmlContext>
|
||||
#include <QStringList>
|
||||
|
||||
// This class is a pure interface class and may not contain any implementation code
|
||||
// Allowed are:
|
||||
// header
|
||||
|
@ -74,6 +77,8 @@ class QMLInterface : public QObject {
|
|||
Q_PROPERTY(bool verbatim_plan READ verbatim_plan WRITE set_verbatim_plan NOTIFY verbatim_planChanged);
|
||||
Q_PROPERTY(bool display_variations READ display_variations WRITE set_display_variations NOTIFY display_variationsChanged);
|
||||
|
||||
Q_PROPERTY(QStringList diveSummaryText READ diveSummaryText NOTIFY diveSummaryTextChanged);
|
||||
|
||||
public:
|
||||
static QMLInterface *instance();
|
||||
|
||||
|
@ -163,6 +168,9 @@ public:
|
|||
};
|
||||
Q_ENUM(DIVE_MODE);
|
||||
|
||||
// Function to calculate dive summary
|
||||
Q_INVOKABLE void summaryCalculation(int primaryPeriod, int secondaryPeriod);
|
||||
|
||||
public:
|
||||
CLOUD_STATUS cloud_verification_status() { return (CLOUD_STATUS)prefs.cloud_verification_status; }
|
||||
DURATION duration_units() { return (DURATION)prefs.units.duration_units; }
|
||||
|
@ -209,6 +217,8 @@ public:
|
|||
bool verbatim_plan() { return prefs.verbatim_plan; }
|
||||
bool display_variations() { return prefs.display_variations; }
|
||||
|
||||
const QStringList &diveSummaryText() { return diveSummary::diveSummaryText; }
|
||||
|
||||
public slots:
|
||||
void set_cloud_verification_status(CLOUD_STATUS value) { qPrefCloudStorage::set_cloud_verification_status(value); }
|
||||
void set_duration_units(DURATION value) { qPrefUnits::set_duration_units((units::DURATION)value); }
|
||||
|
@ -301,6 +311,7 @@ signals:
|
|||
void verbatim_planChanged(bool value);
|
||||
void display_variationsChanged(bool value);
|
||||
|
||||
void diveSummaryTextChanged(QStringList);
|
||||
private:
|
||||
QMLInterface() {}
|
||||
};
|
||||
|
|
|
@ -108,6 +108,7 @@ SOURCES += ../../subsurface-mobile-main.cpp \
|
|||
../../core/subsurface-qt/CylinderObjectHelper.cpp \
|
||||
../../core/subsurface-qt/DiveObjectHelper.cpp \
|
||||
../../core/subsurface-qt/DiveListNotifier.cpp \
|
||||
../../backend-shared/divesummary.cpp \
|
||||
../../backend-shared/exportfuncs.cpp \
|
||||
../../backend-shared/plannershared.cpp \
|
||||
../../mobile-widgets/qmlinterface.cpp \
|
||||
|
@ -242,6 +243,7 @@ HEADERS += \
|
|||
../../core/subsurface-qt/CylinderObjectHelper.h \
|
||||
../../core/subsurface-qt/DiveObjectHelper.h \
|
||||
../../core/subsurface-qt/DiveListNotifier.h \
|
||||
../../backend-shared/divesummary.h \
|
||||
../../backend-shared/exportfuncs.h \
|
||||
../../backend-shared/plannershared.h \
|
||||
../../mobile-widgets/qmlinterface.h \
|
||||
|
|
Loading…
Reference in a new issue