summaryrefslogtreecommitdiffstats
path: root/stats/pieseries.cpp
diff options
context:
space:
mode:
authorGravatar Berthold Stoeger <bstoeger@mail.tuwien.ac.at>2021-01-20 14:36:59 +0100
committerGravatar Dirk Hohndel <dirk@hohndel.org>2021-02-13 13:02:54 -0800
commit18a5b5b5930247ed880cfbe8f94778b4c19b0bb2 (patch)
treecdaf28e252a7e512774379e2f12e981e1f68ccb3 /stats/pieseries.cpp
parent622e9ba373f898a0d51fc009f3615d83ffd3a7fc (diff)
downloadsubsurface-18a5b5b5930247ed880cfbe8f94778b4c19b0bb2.tar.gz
statistics: use dive instead of count bins
If we want to make bar charts selectable (when clicking on a bar select the dives the bar represents), then we must store the dives behind bars. Therefore, use dive-based bins instead of count based bins in bar charts and pie charts. This gave some churn because every structure where a count is stored has to be changed to store a vector of dives. Try to use move semantics where possible to avoid duplication of dive lists. On a positive note, the count_dives() function of the binners can now be removed, since it is unused. Signed-off-by: Berthold Stoeger <bstoeger@mail.tuwien.ac.at>
Diffstat (limited to 'stats/pieseries.cpp')
-rw-r--r--stats/pieseries.cpp43
1 files changed, 25 insertions, 18 deletions
diff --git a/stats/pieseries.cpp b/stats/pieseries.cpp
index d837abe5a..f8c5aa980 100644
--- a/stats/pieseries.cpp
+++ b/stats/pieseries.cpp
@@ -16,14 +16,15 @@ static const double pieBorderWidth = 1.0;
static const double innerLabelRadius = 0.75; // 1.0 = at outer border of pie
static const double outerLabelRadius = 1.01; // 1.0 = at outer border of pie
-PieSeries::Item::Item(StatsView &view, const QString &name, int from, int count, int totalCount,
+PieSeries::Item::Item(StatsView &view, const QString &name, int from, std::vector<dive *> divesIn, int totalCount,
int bin_nr, int numBins) :
name(name),
- count(count)
+ dives(std::move(divesIn))
{
QFont f; // make configurable
QLocale loc;
+ int count = (int)dives.size();
angleFrom = static_cast<double>(from) / totalCount;
angleTo = static_cast<double>(from + count) / totalCount;
double meanAngle = M_PI / 2.0 - (from + count / 2.0) / totalCount * M_PI * 2.0; // Note: "-" because we go CW.
@@ -74,7 +75,7 @@ void PieSeries::Item::highlight(ChartPieItem &item, int bin_nr, bool highlight,
}
PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const QString &categoryName,
- const std::vector<std::pair<QString, int>> &data, bool keepOrder) :
+ std::vector<std::pair<QString, std::vector<dive *>>> data, bool keepOrder) :
StatsSeries(view, xAxis, yAxis),
item(view.createChartItem<ChartPieItem>(ChartZValue::Series, pieBorderWidth)),
categoryName(categoryName),
@@ -89,8 +90,8 @@ PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const
// Easier to read than std::accumulate
totalCount = 0;
- for (const auto &[name, count]: data)
- totalCount += count;
+ for (const auto &[name, dives]: data)
+ totalCount += (int)dives.size();
// First of all, sort from largest to smalles slice. Instead
// of sorting the initial array, sort a list of indices, so that
@@ -102,19 +103,19 @@ PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const
// - do a lexicographic sort by (count, idx) so that for equal counts the order is preserved.
std::sort(sorted.begin(), sorted.end(),
[&data](int idx1, int idx2)
- { return std::make_tuple(-data[idx1].second, idx1) <
- std::make_tuple(-data[idx2].second, idx2); });
+ { return std::make_tuple(-data[idx1].second.size(), idx1) <
+ std::make_tuple(-data[idx2].second.size(), idx2); });
auto it = std::find_if(sorted.begin(), sorted.end(),
[count=totalCount, &data](int idx)
- { return data[idx].second * 100 / count < smallest_slice_percentage; });
+ { return (int)data[idx].second.size() * 100 / count < smallest_slice_percentage; });
if (it - sorted.begin() < min_slices) {
// Take minimum amount of slices below 50%...
int sum = 0;
for (auto it2 = sorted.begin(); it2 != it; ++it2)
- sum += data[*it2].second;
+ sum += (int)data[*it2].second.size();
while(it != sorted.end() && sum * 2 < totalCount && it - sorted.begin() < min_slices) {
- sum += data[*it].second;
+ sum += (int)data[*it].second.size();
++it;
}
}
@@ -135,18 +136,24 @@ PieSeries::PieSeries(StatsView &view, StatsAxis *xAxis, StatsAxis *yAxis, const
items.reserve(numBins);
int act = 0;
for (auto it2 = sorted.begin(); it2 != it; ++it2) {
- int count = data[*it2].second;
- items.emplace_back(view, data[*it2].first, act, count, totalCount, (int)items.size(), numBins);
+ int count = (int)data[*it2].second.size();
+ items.emplace_back(view, data[*it2].first, act, std::move(data[*it2].second),
+ totalCount, (int)items.size(), numBins);
act += count;
}
// Register the items of the "other" group.
if (it != sorted.end()) {
+ std::vector<dive *> otherDives;
+ otherDives.reserve(totalCount - act);
other.reserve(sorted.end() - it);
- for (auto it2 = it; it2 != sorted.end(); ++it2)
- other.push_back({ data[*it2].first, data[*it2].second });
+ for (auto it2 = it; it2 != sorted.end(); ++it2) {
+ other.push_back({ data[*it2].first, (int)data[*it2].second.size() });
+ for (dive *d: data[*it2].second)
+ otherDives.push_back(d);
+ }
QString name = StatsTranslations::tr("other (%1 items)").arg(other.size());
- items.emplace_back(view, name, act, totalCount - act, totalCount, (int)items.size(), numBins);
+ items.emplace_back(view, name, act, std::move(otherDives), totalCount, (int)items.size(), numBins);
}
}
@@ -212,15 +219,15 @@ std::vector<QString> PieSeries::makeInfo(int idx) const
// This is the "other" bin. Format all these items and an overview item.
res.reserve(other.size() + 1);
res.push_back(QString("%1: %2").arg(StatsTranslations::tr("other"),
- makePercentageLine(items[idx].count, totalCount)));
+ makePercentageLine((int)items[idx].dives.size(), totalCount)));
for (const OtherItem &item: other)
res.push_back(QString("%1: %2").arg(item.name,
- makePercentageLine(item.count, totalCount)));
+ makePercentageLine((int)item.count, totalCount)));
} else {
// A "normal" item.
res.reserve(2);
res.push_back(QStringLiteral("%1: %2").arg(categoryName, items[idx].name));
- res.push_back(makePercentageLine(items[idx].count, totalCount));
+ res.push_back(makePercentageLine((int)items[idx].dives.size(), totalCount));
}
return res;
}