2017-04-27 18:25:32 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
2016-04-05 05:02:03 +00:00
|
|
|
#include "qt-models/yearlystatisticsmodel.h"
|
2018-06-03 20:15:19 +00:00
|
|
|
#include "core/qthelper.h"
|
2016-04-05 05:02:03 +00:00
|
|
|
#include "core/metrics.h"
|
|
|
|
#include "core/statistics.h"
|
2022-09-03 08:37:58 +00:00
|
|
|
#include "core/string-format.h"
|
2019-06-27 05:42:09 +00:00
|
|
|
#include "core/dive.h" // For NUM_DIVEMODE
|
2015-05-28 21:12:11 +00:00
|
|
|
|
|
|
|
class YearStatisticsItem : public TreeItem {
|
2018-09-14 19:25:00 +00:00
|
|
|
Q_DECLARE_TR_FUNCTIONS(YearStatisticsItem)
|
2015-05-28 21:12:11 +00:00
|
|
|
public:
|
|
|
|
enum {
|
|
|
|
YEAR,
|
|
|
|
DIVES,
|
|
|
|
TOTAL_TIME,
|
|
|
|
AVERAGE_TIME,
|
|
|
|
SHORTEST_TIME,
|
|
|
|
LONGEST_TIME,
|
|
|
|
AVG_DEPTH,
|
2018-12-16 19:52:34 +00:00
|
|
|
AVG_MAX_DEPTH,
|
2015-05-28 21:12:11 +00:00
|
|
|
MIN_DEPTH,
|
|
|
|
MAX_DEPTH,
|
|
|
|
AVG_SAC,
|
|
|
|
MIN_SAC,
|
|
|
|
MAX_SAC,
|
|
|
|
AVG_TEMP,
|
|
|
|
MIN_TEMP,
|
|
|
|
MAX_TEMP,
|
|
|
|
COLUMNS
|
|
|
|
};
|
|
|
|
|
|
|
|
QVariant data(int column, int role) const;
|
2019-03-19 19:09:33 +00:00
|
|
|
YearStatisticsItem(const stats_t &interval);
|
2015-05-28 21:12:11 +00:00
|
|
|
|
|
|
|
private:
|
|
|
|
stats_t stats_interval;
|
|
|
|
};
|
|
|
|
|
2019-03-19 19:09:33 +00:00
|
|
|
YearStatisticsItem::YearStatisticsItem(const stats_t &interval) : stats_interval(interval)
|
2015-05-28 21:12:11 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant YearStatisticsItem::data(int column, int role) const
|
|
|
|
{
|
|
|
|
if (role == Qt::FontRole) {
|
|
|
|
QFont font = defaultModelFont();
|
|
|
|
font.setBold(stats_interval.is_year);
|
|
|
|
return font;
|
|
|
|
} else if (role != Qt::DisplayRole) {
|
2024-05-01 21:16:00 +00:00
|
|
|
return QVariant();
|
2015-05-28 21:12:11 +00:00
|
|
|
}
|
|
|
|
switch (column) {
|
|
|
|
case YEAR:
|
|
|
|
if (stats_interval.is_trip) {
|
2024-05-01 21:16:00 +00:00
|
|
|
return QString::fromStdString(stats_interval.location);
|
2015-05-28 21:12:11 +00:00
|
|
|
} else {
|
2024-05-01 21:16:00 +00:00
|
|
|
return stats_interval.period;
|
2015-05-28 21:12:11 +00:00
|
|
|
}
|
|
|
|
case DIVES:
|
2024-05-01 21:16:00 +00:00
|
|
|
return stats_interval.selection_size;
|
2015-05-28 21:12:11 +00:00
|
|
|
case TOTAL_TIME:
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_dive_duration_string(stats_interval.total_time.seconds, tr("h"), tr("min"), tr("sec"), " ");
|
2015-05-28 21:12:11 +00:00
|
|
|
case AVERAGE_TIME:
|
2024-05-01 21:16:00 +00:00
|
|
|
return formatMinutes(stats_interval.total_time.seconds / stats_interval.selection_size);
|
2015-05-28 21:12:11 +00:00
|
|
|
case SHORTEST_TIME:
|
2024-05-01 21:16:00 +00:00
|
|
|
return formatMinutes(stats_interval.shortest_time.seconds);
|
2015-05-28 21:12:11 +00:00
|
|
|
case LONGEST_TIME:
|
2024-05-01 21:16:00 +00:00
|
|
|
return formatMinutes(stats_interval.longest_time.seconds);
|
2015-05-28 21:12:11 +00:00
|
|
|
case AVG_DEPTH:
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_depth_string(stats_interval.avg_depth);
|
2018-12-16 19:52:34 +00:00
|
|
|
case AVG_MAX_DEPTH:
|
|
|
|
if (stats_interval.selection_size)
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_depth_string(stats_interval.combined_max_depth.mm / stats_interval.selection_size);
|
2018-12-16 19:52:34 +00:00
|
|
|
break;
|
2015-05-28 21:12:11 +00:00
|
|
|
case MIN_DEPTH:
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_depth_string(stats_interval.min_depth);
|
2015-05-28 21:12:11 +00:00
|
|
|
case MAX_DEPTH:
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_depth_string(stats_interval.max_depth);
|
2015-05-28 21:12:11 +00:00
|
|
|
case AVG_SAC:
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_volume_string(stats_interval.avg_sac);
|
2015-05-28 21:12:11 +00:00
|
|
|
case MIN_SAC:
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_volume_string(stats_interval.min_sac);
|
2015-05-28 21:12:11 +00:00
|
|
|
case MAX_SAC:
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_volume_string(stats_interval.max_sac);
|
2015-05-28 21:12:11 +00:00
|
|
|
case AVG_TEMP:
|
2018-02-18 20:55:57 +00:00
|
|
|
if (stats_interval.combined_temp.mkelvin && stats_interval.combined_count) {
|
|
|
|
temperature_t avg_temp;
|
|
|
|
avg_temp.mkelvin = stats_interval.combined_temp.mkelvin / stats_interval.combined_count;
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_temperature_string(avg_temp);
|
2015-05-28 21:12:11 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case MIN_TEMP:
|
2018-02-18 20:55:57 +00:00
|
|
|
if (stats_interval.min_temp.mkelvin)
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_temperature_string(stats_interval.min_temp);
|
2015-05-28 21:12:11 +00:00
|
|
|
break;
|
|
|
|
case MAX_TEMP:
|
2018-02-18 20:55:57 +00:00
|
|
|
if (stats_interval.max_temp.mkelvin)
|
2024-05-01 21:16:00 +00:00
|
|
|
return get_temperature_string(stats_interval.max_temp);
|
2015-05-28 21:12:11 +00:00
|
|
|
break;
|
|
|
|
}
|
2024-05-01 21:16:00 +00:00
|
|
|
return QVariant();
|
2015-05-28 21:12:11 +00:00
|
|
|
}
|
|
|
|
|
2016-03-07 06:43:20 +00:00
|
|
|
YearlyStatisticsModel::YearlyStatisticsModel(QObject *parent) : TreeModel(parent)
|
2015-05-28 21:12:11 +00:00
|
|
|
{
|
|
|
|
columns = COLUMNS;
|
|
|
|
update_yearly_stats();
|
|
|
|
}
|
|
|
|
|
|
|
|
QVariant YearlyStatisticsModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
|
|
{
|
|
|
|
QVariant val;
|
|
|
|
if (role == Qt::FontRole)
|
|
|
|
val = defaultModelFont();
|
|
|
|
|
|
|
|
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
|
|
|
|
switch (section) {
|
|
|
|
case YEAR:
|
|
|
|
val = tr("Year \n > Month / Trip");
|
|
|
|
break;
|
|
|
|
case DIVES:
|
|
|
|
val = tr("#");
|
|
|
|
break;
|
|
|
|
case TOTAL_TIME:
|
|
|
|
val = tr("Duration \n Total");
|
|
|
|
break;
|
|
|
|
case AVERAGE_TIME:
|
|
|
|
val = tr("\nAverage");
|
|
|
|
break;
|
|
|
|
case SHORTEST_TIME:
|
|
|
|
val = tr("\nShortest");
|
|
|
|
break;
|
|
|
|
case LONGEST_TIME:
|
|
|
|
val = tr("\nLongest");
|
|
|
|
break;
|
|
|
|
case AVG_DEPTH:
|
|
|
|
val = QString(tr("Depth (%1)\n Average")).arg(get_depth_unit());
|
|
|
|
break;
|
2018-12-16 19:52:34 +00:00
|
|
|
case AVG_MAX_DEPTH:
|
|
|
|
val = tr("\nAverage maximum");
|
|
|
|
break;
|
2015-05-28 21:12:11 +00:00
|
|
|
case MIN_DEPTH:
|
|
|
|
val = tr("\nMinimum");
|
|
|
|
break;
|
|
|
|
case MAX_DEPTH:
|
|
|
|
val = tr("\nMaximum");
|
|
|
|
break;
|
|
|
|
case AVG_SAC:
|
|
|
|
val = QString(tr("SAC (%1)\n Average")).arg(get_volume_unit());
|
|
|
|
break;
|
|
|
|
case MIN_SAC:
|
|
|
|
val = tr("\nMinimum");
|
|
|
|
break;
|
|
|
|
case MAX_SAC:
|
|
|
|
val = tr("\nMaximum");
|
|
|
|
break;
|
|
|
|
case AVG_TEMP:
|
|
|
|
val = QString(tr("Temp. (%1)\n Average").arg(get_temp_unit()));
|
|
|
|
break;
|
|
|
|
case MIN_TEMP:
|
|
|
|
val = tr("\nMinimum");
|
|
|
|
break;
|
|
|
|
case MAX_TEMP:
|
|
|
|
val = tr("\nMaximum");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
void YearlyStatisticsModel::update_yearly_stats()
|
|
|
|
{
|
2019-03-10 02:27:51 +00:00
|
|
|
QString label;
|
|
|
|
temperature_t t_range_min,t_range_max;
|
2024-05-01 21:16:00 +00:00
|
|
|
stats_summary stats = calculate_stats_summary(false);
|
2015-05-28 21:12:11 +00:00
|
|
|
|
2024-05-01 21:16:00 +00:00
|
|
|
int month = 0;
|
|
|
|
for (const auto &s: stats.stats_yearly) {
|
|
|
|
YearStatisticsItem *item = new YearStatisticsItem(s);
|
|
|
|
size_t combined_months = 0;
|
|
|
|
while (combined_months < s.selection_size) {
|
2018-10-06 08:58:12 +00:00
|
|
|
combined_months += stats.stats_monthly[month].selection_size;
|
2019-03-19 19:09:33 +00:00
|
|
|
YearStatisticsItem *iChild = new YearStatisticsItem(stats.stats_monthly[month]);
|
2015-05-28 21:12:11 +00:00
|
|
|
item->children.append(iChild);
|
|
|
|
iChild->parent = item;
|
|
|
|
month++;
|
|
|
|
}
|
|
|
|
rootItem->children.append(item);
|
2018-07-25 19:23:19 +00:00
|
|
|
item->parent = rootItem.get();
|
2015-05-28 21:12:11 +00:00
|
|
|
}
|
|
|
|
|
2024-05-01 21:16:00 +00:00
|
|
|
if (stats.stats_by_trip[0].is_trip == true) {
|
2019-03-19 19:09:33 +00:00
|
|
|
YearStatisticsItem *item = new YearStatisticsItem(stats.stats_by_trip[0]);
|
2024-05-01 21:16:00 +00:00
|
|
|
for (auto it = std::next(stats.stats_by_trip.begin()); it != stats.stats_by_trip.end(); ++it) {
|
|
|
|
YearStatisticsItem *iChild = new YearStatisticsItem(*it);
|
2015-05-28 21:12:11 +00:00
|
|
|
item->children.append(iChild);
|
|
|
|
iChild->parent = item;
|
|
|
|
}
|
|
|
|
rootItem->children.append(item);
|
2018-07-25 19:23:19 +00:00
|
|
|
item->parent = rootItem.get();
|
2015-05-28 21:12:11 +00:00
|
|
|
}
|
2016-01-17 19:18:36 +00:00
|
|
|
|
|
|
|
/* Show the statistic sorted by dive type */
|
2024-05-01 21:16:00 +00:00
|
|
|
if (stats.stats_by_type[0].selection_size) {
|
2019-03-19 19:09:33 +00:00
|
|
|
YearStatisticsItem *item = new YearStatisticsItem(stats.stats_by_type[0]);
|
2024-05-01 21:16:00 +00:00
|
|
|
for (auto it = std::next(stats.stats_by_type.begin()); it != stats.stats_by_type.end(); ++it) {
|
|
|
|
if (it->selection_size == 0)
|
2016-01-17 19:18:36 +00:00
|
|
|
continue;
|
2024-05-01 21:16:00 +00:00
|
|
|
YearStatisticsItem *iChild = new YearStatisticsItem(*it);
|
2016-01-17 19:18:36 +00:00
|
|
|
item->children.append(iChild);
|
|
|
|
iChild->parent = item;
|
|
|
|
}
|
|
|
|
rootItem->children.append(item);
|
2018-07-25 19:23:19 +00:00
|
|
|
item->parent = rootItem.get();
|
2016-01-17 19:18:36 +00:00
|
|
|
}
|
2019-03-10 02:27:51 +00:00
|
|
|
|
|
|
|
/* Show the statistic sorted by dive depth */
|
2024-05-01 21:16:00 +00:00
|
|
|
if (stats.stats_by_depth[0].selection_size) {
|
2019-03-19 19:09:33 +00:00
|
|
|
YearStatisticsItem *item = new YearStatisticsItem(stats.stats_by_depth[0]);
|
2024-05-01 21:16:00 +00:00
|
|
|
int i = 0;
|
|
|
|
for (auto it = std::next(stats.stats_by_depth.begin()); it != stats.stats_by_depth.end(); ++it) {
|
|
|
|
if (it->selection_size) {
|
|
|
|
QString label = QString(tr("%1 - %2")).arg(get_depth_string(i * (STATS_DEPTH_BUCKET * 1000), true, false),
|
|
|
|
get_depth_string((i + 1) * (STATS_DEPTH_BUCKET * 1000), true, false));
|
|
|
|
it->location = label.toStdString();
|
|
|
|
YearStatisticsItem *iChild = new YearStatisticsItem(*it);
|
2019-03-10 02:27:51 +00:00
|
|
|
item->children.append(iChild);
|
|
|
|
iChild->parent = item;
|
|
|
|
}
|
2024-05-01 21:16:00 +00:00
|
|
|
i++;
|
|
|
|
}
|
2019-03-10 02:27:51 +00:00
|
|
|
rootItem->children.append(item);
|
|
|
|
item->parent = rootItem.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Show the statistic sorted by dive temperature */
|
2024-05-01 21:16:00 +00:00
|
|
|
if (stats.stats_by_temp[0].selection_size) {
|
2019-03-19 19:09:33 +00:00
|
|
|
YearStatisticsItem *item = new YearStatisticsItem(stats.stats_by_temp[0]);
|
2024-05-01 21:16:00 +00:00
|
|
|
int i = 0;
|
|
|
|
for (auto it = std::next(stats.stats_by_temp.begin()); it != stats.stats_by_temp.end(); ++it) {
|
|
|
|
if (it->selection_size) {
|
|
|
|
t_range_min.mkelvin = C_to_mkelvin(i * STATS_TEMP_BUCKET);
|
|
|
|
t_range_max.mkelvin = C_to_mkelvin((i + 1) * STATS_TEMP_BUCKET);
|
2019-03-10 02:27:51 +00:00
|
|
|
label = QString(tr("%1 - %2")).arg(get_temperature_string(t_range_min, true),
|
|
|
|
get_temperature_string(t_range_max, true));
|
2024-05-01 21:16:00 +00:00
|
|
|
it->location = label.toStdString();
|
|
|
|
YearStatisticsItem *iChild = new YearStatisticsItem(*it);
|
2019-03-10 02:27:51 +00:00
|
|
|
item->children.append(iChild);
|
|
|
|
iChild->parent = item;
|
|
|
|
}
|
2024-05-01 21:16:00 +00:00
|
|
|
i++;
|
|
|
|
}
|
2019-03-10 02:27:51 +00:00
|
|
|
rootItem->children.append(item);
|
|
|
|
item->parent = rootItem.get();
|
|
|
|
}
|
2015-05-28 21:12:11 +00:00
|
|
|
}
|