mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-07 07:33:52 +02:00
Added usage of segment tree in Data class for statistics.
This commit is contained in:
parent
b5b70beea0
commit
78e553b724
2 changed files with 190 additions and 0 deletions
|
@ -11,4 +11,145 @@ namespace Data {
|
||||||
namespace {
|
namespace {
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
void StatisticalChart::measure() {
|
||||||
|
if (x.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto n = x.size();
|
||||||
|
const auto start = x.front();
|
||||||
|
const auto end = x.back();
|
||||||
|
|
||||||
|
xPercentage.clear();
|
||||||
|
xPercentage.resize(n);
|
||||||
|
if (n == 1) {
|
||||||
|
xPercentage[0] = 1;
|
||||||
|
} else {
|
||||||
|
for (auto i = 0; i < n; i++) {
|
||||||
|
xPercentage[i] = (x[i] - start) / float64(end - start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto i = 0; i < lines.size(); i++) {
|
||||||
|
if (lines[i].maxValue > maxValue) {
|
||||||
|
maxValue = lines[i].maxValue;
|
||||||
|
}
|
||||||
|
if (lines[i].minValue < minValue) {
|
||||||
|
minValue = lines[i].minValue;
|
||||||
|
}
|
||||||
|
lines[i].segmentTree = Statistic::SegmentTree(lines[i].y);
|
||||||
|
}
|
||||||
|
|
||||||
|
daysLookup.clear();
|
||||||
|
const auto dateCount = int((end - start) / timeStep) + 10;
|
||||||
|
daysLookup.reserve(dateCount);
|
||||||
|
constexpr auto kOneDay = 3600 * 24 * 1000;
|
||||||
|
const auto formatter = u"MMM d"_q;
|
||||||
|
for (auto i = 0; i < dateCount; i++) {
|
||||||
|
const auto r = (start + (i * timeStep)) / 1000;
|
||||||
|
const auto dateTime = QDateTime::fromSecsSinceEpoch(r);
|
||||||
|
if (timeStep == 1) {
|
||||||
|
daysLookup.push_back(
|
||||||
|
QString(((i < 10) ? u"0%1:00"_q : u"%1:00"_q).arg(i)));
|
||||||
|
} else if (timeStep < kOneDay) {
|
||||||
|
daysLookup.push_back(u"%1:%2"_q
|
||||||
|
.arg(dateTime.time().hour(), 2, 10, QChar('0'))
|
||||||
|
.arg(dateTime.time().minute(), 2, 10, QChar('0')));
|
||||||
|
} else {
|
||||||
|
const auto date = dateTime.date();
|
||||||
|
daysLookup.push_back(QLocale().toString(date, formatter));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oneDayPercentage = timeStep / float64(end - start);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString StatisticalChart::getDayString(int i) const {
|
||||||
|
return daysLookup[int((x[i] - x[0]) / timeStep)];
|
||||||
|
}
|
||||||
|
|
||||||
|
int StatisticalChart::findStartIndex(float v) const {
|
||||||
|
if (v == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const auto n = int(xPercentage.size());
|
||||||
|
|
||||||
|
if (n < 2) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
auto left = 0;
|
||||||
|
auto right = n - 1;
|
||||||
|
|
||||||
|
while (left <= right) {
|
||||||
|
const auto middle = (right + left) >> 1;
|
||||||
|
if (v < xPercentage[middle]
|
||||||
|
&& (middle == 0 || v > xPercentage[middle - 1])) {
|
||||||
|
return middle;
|
||||||
|
}
|
||||||
|
if (v == xPercentage[middle]) {
|
||||||
|
return middle;
|
||||||
|
}
|
||||||
|
if (v < xPercentage[middle]) {
|
||||||
|
right = middle - 1;
|
||||||
|
} else if (v > xPercentage[middle]) {
|
||||||
|
left = middle + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StatisticalChart::findEndIndex(int left, float v) const {
|
||||||
|
const auto n = int(xPercentage.size());
|
||||||
|
if (v == 1.) {
|
||||||
|
return n - 1;
|
||||||
|
}
|
||||||
|
auto right = n - 1;
|
||||||
|
|
||||||
|
while (left <= right) {
|
||||||
|
const auto middle = (right + left) >> 1;
|
||||||
|
if (v > xPercentage[middle]
|
||||||
|
&& (middle == n - 1 || v < xPercentage[middle + 1])) {
|
||||||
|
return middle;
|
||||||
|
}
|
||||||
|
if (v == xPercentage[middle]) {
|
||||||
|
return middle;
|
||||||
|
}
|
||||||
|
if (v < xPercentage[middle]) {
|
||||||
|
right = middle - 1;
|
||||||
|
} else if (v > xPercentage[middle]) {
|
||||||
|
left = middle + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int StatisticalChart::findIndex(int left, int right, float v) const {
|
||||||
|
const auto n = int(xPercentage.size());
|
||||||
|
|
||||||
|
if (v <= xPercentage[left]) {
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
if (v >= xPercentage[right]) {
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (left <= right) {
|
||||||
|
const auto middle = (right + left) >> 1;
|
||||||
|
if (v > xPercentage[middle]
|
||||||
|
&& (middle == n - 1 || v < xPercentage[middle + 1])) {
|
||||||
|
return middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v == xPercentage[middle]) {
|
||||||
|
return middle;
|
||||||
|
}
|
||||||
|
if (v < xPercentage[middle]) {
|
||||||
|
right = middle - 1;
|
||||||
|
} else if (v > xPercentage[middle]) {
|
||||||
|
left = middle + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return right;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Data
|
} // namespace Data
|
||||||
|
|
|
@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "statistics/segment_tree.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
|
||||||
struct StatisticsMessageInteractionInfo final {
|
struct StatisticsMessageInteractionInfo final {
|
||||||
|
@ -33,7 +35,54 @@ struct StatisticsInviterInfo final {
|
||||||
int addedMemberCount = 0;
|
int addedMemberCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct StatisticalChart {
|
||||||
|
StatisticalChart() = default;
|
||||||
|
|
||||||
|
[[nodiscard]] bool empty() const {
|
||||||
|
return lines.empty();
|
||||||
|
}
|
||||||
|
[[nodiscard]] explicit operator bool() const {
|
||||||
|
return !empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
void measure();
|
||||||
|
|
||||||
|
[[nodiscard]] QString getDayString(int i) const;
|
||||||
|
|
||||||
|
[[nodiscard]] int findStartIndex(float v) const;
|
||||||
|
[[nodiscard]] int findEndIndex(int left, float v) const;
|
||||||
|
[[nodiscard]] int findIndex(int left, int right, float v) const;
|
||||||
|
|
||||||
|
struct Line final {
|
||||||
|
std::vector<int> y;
|
||||||
|
|
||||||
|
Statistic::SegmentTree segmentTree;
|
||||||
|
QString id;
|
||||||
|
QString name;
|
||||||
|
int maxValue = 0;
|
||||||
|
int minValue = std::numeric_limits<int>::max();
|
||||||
|
int colorKey = 0;
|
||||||
|
QColor color;
|
||||||
|
QColor colorDark;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<float64> x;
|
||||||
|
std::vector<float64> xPercentage;
|
||||||
|
std::vector<QString> daysLookup;
|
||||||
|
|
||||||
|
std::vector<Line> lines;
|
||||||
|
|
||||||
|
int maxValue = 0;
|
||||||
|
int minValue = std::numeric_limits<int>::max();
|
||||||
|
|
||||||
|
float64 oneDayPercentage = 0.;
|
||||||
|
|
||||||
|
float64 timeStep = 0.;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct StatisticalGraph final {
|
struct StatisticalGraph final {
|
||||||
|
StatisticalChart chart;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StatisticalValue final {
|
struct StatisticalValue final {
|
||||||
|
|
Loading…
Add table
Reference in a new issue