diff --git a/Telegram/SourceFiles/data/data_statistics_chart.h b/Telegram/SourceFiles/data/data_statistics_chart.h index 5a29ebef79..2354e9e4de 100644 --- a/Telegram/SourceFiles/data/data_statistics_chart.h +++ b/Telegram/SourceFiles/data/data_statistics_chart.h @@ -30,14 +30,15 @@ struct StatisticalChart { [[nodiscard]] int findIndex(int left, int right, float64 v) const; struct Line final { - std::vector y; + std::vector y; Statistic::SegmentTree segmentTree; int id = 0; QString idString; QString name; - int maxValue = 0; - int minValue = std::numeric_limits::max(); + Statistic::ChartValue maxValue = 0; + Statistic::ChartValue minValue = + std::numeric_limits::max(); QString colorKey; QColor color; QColor colorDark; @@ -55,8 +56,9 @@ struct StatisticalChart { float64 max = 0.; } defaultZoomXIndex; - int maxValue = 0; - int minValue = std::numeric_limits::max(); + Statistic::ChartValue maxValue = 0; + Statistic::ChartValue minValue = + std::numeric_limits::max(); float64 oneDayPercentage = 0.; diff --git a/Telegram/SourceFiles/statistics/chart_rulers_data.cpp b/Telegram/SourceFiles/statistics/chart_rulers_data.cpp index 1b4e9c33ad..4f9471c8ce 100644 --- a/Telegram/SourceFiles/statistics/chart_rulers_data.cpp +++ b/Telegram/SourceFiles/statistics/chart_rulers_data.cpp @@ -12,17 +12,17 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Statistic { namespace { -constexpr auto kMinLines = int(2); -constexpr auto kMaxLines = int(6); +constexpr auto kMinLines = ChartValue(2); +constexpr auto kMaxLines = ChartValue(6); constexpr auto kStep = 5.; -[[nodiscard]] int Round(int maxValue) { - const auto k = int(maxValue / kStep); +[[nodiscard]] ChartValue Round(ChartValue maxValue) { + const auto k = ChartValue(maxValue / kStep); return (k % 10 == 0) ? maxValue : ((maxValue / 10 + 1) * 10); } -[[nodiscard]] QString Format(int absoluteValue) { - constexpr auto kTooMuch = int(10'000); +[[nodiscard]] QString Format(ChartValue absoluteValue) { + constexpr auto kTooMuch = ChartValue(10'000); return (absoluteValue >= kTooMuch) ? Lang::FormatCountToShort(absoluteValue).string : QString::number(absoluteValue); @@ -31,8 +31,8 @@ constexpr auto kStep = 5.; } // namespace ChartRulersData::ChartRulersData( - int newMaxHeight, - int newMinHeight, + ChartValue newMaxHeight, + ChartValue newMinHeight, bool useMinHeight, float64 rightRatio, Fn leftCustomCaption, @@ -42,11 +42,13 @@ ChartRulersData::ChartRulersData( ? Round(newMaxHeight) : newMaxHeight; - const auto step = std::max(1, int(std::ceil(v / kStep))); + const auto step = std::max( + ChartValue(1), + ChartValue(std::ceil(v / kStep))); auto n = kMaxLines; if (v < kMaxLines) { - n = std::max(2, v + 1); + n = std::max(2, int(v + 1)); } else if (v / 2 < kMaxLines) { n = v / 2 + 1; if (v % 2 != 0) { @@ -87,11 +89,11 @@ ChartRulersData::ChartRulersData( } lines.resize(n); - const auto diffAbsoluteValue = int((n - 1) * step); + const auto diffAbsoluteValue = ChartValue((n - 1) * step); const auto skipFloatValues = (step / rightRatio) < 1; for (auto i = 0; i < n; i++) { auto &line = lines[i]; - const auto value = int(i * step); + const auto value = ChartValue(i * step); line.absoluteValue = newMinHeight + value; line.relativeValue = 1. - value / float64(diffAbsoluteValue); line.caption = leftCustomCaption @@ -103,7 +105,7 @@ ChartRulersData::ChartRulersData( ? rightCustomCaption(line.absoluteValue) : (!skipFloatValues) ? Format(v) - : ((v - int(v)) < 0.01) + : ((v - ChartValue(v)) < 0.01) ? Format(v) : QString(); } @@ -112,8 +114,8 @@ ChartRulersData::ChartRulersData( } void ChartRulersData::computeRelative( - int newMaxHeight, - int newMinHeight) { + ChartValue newMaxHeight, + ChartValue newMinHeight) { for (auto &line : lines) { line.relativeValue = 1. - ((line.absoluteValue - newMinHeight) @@ -121,10 +123,10 @@ void ChartRulersData::computeRelative( } } -int ChartRulersData::LookupHeight(int maxValue) { +ChartValue ChartRulersData::LookupHeight(ChartValue maxValue) { const auto v = (maxValue > 100) ? Round(maxValue) : maxValue; - const auto step = int(std::ceil(v / kStep)); + const auto step = ChartValue(std::ceil(v / kStep)); return step * kStep; } diff --git a/Telegram/SourceFiles/statistics/chart_rulers_data.h b/Telegram/SourceFiles/statistics/chart_rulers_data.h index 4b5d63202d..fef960c350 100644 --- a/Telegram/SourceFiles/statistics/chart_rulers_data.h +++ b/Telegram/SourceFiles/statistics/chart_rulers_data.h @@ -7,23 +7,25 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "statistics/statistics_types.h" + namespace Statistic { struct ChartRulersData final { public: ChartRulersData( - int newMaxHeight, - int newMinHeight, + ChartValue newMaxHeight, + ChartValue newMinHeight, bool useMinHeight, float64 rightRatio, Fn leftCustomCaption = nullptr, Fn rightCustomCaption = nullptr); void computeRelative( - int newMaxHeight, - int newMinHeight); + ChartValue newMaxHeight, + ChartValue newMinHeight); - [[nodiscard]] static int LookupHeight(int maxValue); + [[nodiscard]] static ChartValue LookupHeight(ChartValue maxValue); struct Line final { float64 absoluteValue = 0.; diff --git a/Telegram/SourceFiles/statistics/chart_widget.cpp b/Telegram/SourceFiles/statistics/chart_widget.cpp index 93d225c705..823481e6b7 100644 --- a/Telegram/SourceFiles/statistics/chart_widget.cpp +++ b/Telegram/SourceFiles/statistics/chart_widget.cpp @@ -1157,7 +1157,7 @@ void ChartWidget::setupDetails() { return; } const auto maxAbsoluteValue = [&] { - auto maxValue = 0; + auto maxValue = ChartValue(0); for (const auto &l : _chartData.lines) { maxValue = std::max(l.maxValue, maxValue); } diff --git a/Telegram/SourceFiles/statistics/segment_tree.cpp b/Telegram/SourceFiles/statistics/segment_tree.cpp index f19f8b8d6b..51c2082ed6 100644 --- a/Telegram/SourceFiles/statistics/segment_tree.cpp +++ b/Telegram/SourceFiles/statistics/segment_tree.cpp @@ -14,7 +14,7 @@ constexpr auto kMinArraySize = size_t(30); } // namespace -SegmentTree::SegmentTree(std::vector array) +SegmentTree::SegmentTree(std::vector array) : _array(std::move(array)) { if (_array.size() < kMinArraySize) { return; @@ -28,7 +28,7 @@ SegmentTree::SegmentTree(std::vector array) build(1, 0, _array.size()); } -void SegmentTree::build(int v, int from, int size) { +void SegmentTree::build(ChartValue v, int from, int size) { _heap[v].from = from; _heap[v].to = (from + size - 1); @@ -48,9 +48,9 @@ void SegmentTree::build(int v, int from, int size) { } } -int SegmentTree::rMaxQ(int from, int to) { +ChartValue SegmentTree::rMaxQ(int from, int to) { if (_array.size() < kMinArraySize) { - auto max = 0; + auto max = ChartValue(0); from = std::max(from, 0); to = std::min(to, int(_array.size() - 1)); for (auto i = from; i <= to; i++) { @@ -61,7 +61,7 @@ int SegmentTree::rMaxQ(int from, int to) { return rMaxQ(1, from, to); } -int SegmentTree::rMaxQ(int v, int from, int to) { +ChartValue SegmentTree::rMaxQ(ChartValue v, int from, int to) { const auto &n = _heap[v]; // If you did a range update that contained this node, // you can infer the Min value without going down the tree. @@ -84,9 +84,9 @@ int SegmentTree::rMaxQ(int v, int from, int to) { return 0; } -int SegmentTree::rMinQ(int from, int to) { +ChartValue SegmentTree::rMinQ(int from, int to) { if (_array.size() < kMinArraySize) { - auto min = std::numeric_limits::max(); + auto min = std::numeric_limits::max(); from = std::max(from, 0); to = std::min(to, int(_array.size() - 1)); for (auto i = from; i <= to; i++) { @@ -97,7 +97,7 @@ int SegmentTree::rMinQ(int from, int to) { return rMinQ(1, from, to); } -int SegmentTree::rMinQ(int v, int from, int to) { +ChartValue SegmentTree::rMinQ(ChartValue v, int from, int to) { const auto &n = _heap[v]; // If you did a range update that contained this node, // you can infer the Min value without going down the tree. @@ -117,10 +117,10 @@ int SegmentTree::rMinQ(int v, int from, int to) { return std::min(leftMin, rightMin); } - return std::numeric_limits::max(); + return std::numeric_limits::max(); } -void SegmentTree::propagate(int v) { +void SegmentTree::propagate(ChartValue v) { auto &n = _heap[v]; if (n.pendingVal) { @@ -131,7 +131,7 @@ void SegmentTree::propagate(int v) { } } -void SegmentTree::change(SegmentTree::Node &n, int value) { +void SegmentTree::change(SegmentTree::Node &n, ChartValue value) { n.pendingVal = { value, true }; n.sum = n.size() * value; n.max = value; diff --git a/Telegram/SourceFiles/statistics/segment_tree.h b/Telegram/SourceFiles/statistics/segment_tree.h index e67adc76aa..f83b16dd4f 100644 --- a/Telegram/SourceFiles/statistics/segment_tree.h +++ b/Telegram/SourceFiles/statistics/segment_tree.h @@ -7,12 +7,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "statistics/statistics_types.h" + namespace Statistic { class SegmentTree final { public: SegmentTree() = default; - SegmentTree(std::vector array); + SegmentTree(std::vector array); [[nodiscard]] bool empty() const { return _array.empty(); @@ -21,20 +23,20 @@ public: return !empty(); } - [[nodiscard]] int rMaxQ(int from, int to); - [[nodiscard]] int rMinQ(int from, int to); + [[nodiscard]] ChartValue rMaxQ(int from, int to); + [[nodiscard]] ChartValue rMinQ(int from, int to); private: struct Node final { - int sum = 0; - int max = 0; - int min = 0; + ChartValue sum = 0; + ChartValue max = 0; + ChartValue min = 0; struct PendingVal { [[nodiscard]] explicit operator bool() const { return available; } - int value = 0; + ChartValue value = 0; bool available = false; }; PendingVal pendingVal; @@ -47,12 +49,12 @@ private: } }; - void build(int v, int from, int size); - void propagate(int v); - void change(Node &n, int value); + void build(ChartValue v, int from, int size); + void propagate(ChartValue v); + void change(Node &n, ChartValue value); - [[nodiscard]] int rMaxQ(int v, int from, int to); - [[nodiscard]] int rMinQ(int v, int from, int to); + [[nodiscard]] ChartValue rMaxQ(ChartValue v, int from, int to); + [[nodiscard]] ChartValue rMinQ(ChartValue v, int from, int to); [[nodiscard]] bool contains(int from1, int to1, int from2, int to2) const; [[nodiscard]] bool intersects( @@ -61,7 +63,7 @@ private: int from2, int to2) const; - std::vector _array; + std::vector _array; std::vector _heap; }; diff --git a/Telegram/SourceFiles/statistics/statistics_data_deserialize.cpp b/Telegram/SourceFiles/statistics/statistics_data_deserialize.cpp index ac649cf133..7f47a396ae 100644 --- a/Telegram/SourceFiles/statistics/statistics_data_deserialize.cpp +++ b/Telegram/SourceFiles/statistics/statistics_data_deserialize.cpp @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/debug_log.h" #include "data/data_statistics_chart.h" +#include "statistics/statistics_types.h" #include #include @@ -61,7 +62,7 @@ Data::StatisticalChart StatisticalChartFromJSON(const QByteArray &json) { line.isHiddenOnStart = ranges::contains(hiddenLines, columnId); line.y.resize(length); for (auto i = 0; i < length; i++) { - const auto value = int(base::SafeRound( + const auto value = ChartValue(base::SafeRound( array.at(i + 1).toDouble())); line.y[i] = value; if (value > line.maxValue) { diff --git a/Telegram/SourceFiles/statistics/statistics_types.h b/Telegram/SourceFiles/statistics/statistics_types.h new file mode 100644 index 0000000000..5d04d34422 --- /dev/null +++ b/Telegram/SourceFiles/statistics/statistics_types.h @@ -0,0 +1,14 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +namespace Statistic { + +using ChartValue = int64; + +} // namespace Statistic diff --git a/Telegram/SourceFiles/statistics/view/abstract_chart_view.cpp b/Telegram/SourceFiles/statistics/view/abstract_chart_view.cpp index d2c8e6baef..4b5f2929ae 100644 --- a/Telegram/SourceFiles/statistics/view/abstract_chart_view.cpp +++ b/Telegram/SourceFiles/statistics/view/abstract_chart_view.cpp @@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_statistics_chart.h" #include "statistics/chart_lines_filter_controller.h" +#include "statistics/statistics_types.h" namespace Statistic { @@ -71,11 +72,11 @@ AbstractChartView::HeightLimits DefaultHeightLimits( const std::shared_ptr &linesFilter, Data::StatisticalChart &chartData, Limits xIndices) { - auto minValue = std::numeric_limits::max(); - auto maxValue = 0; + auto minValue = std::numeric_limits::max(); + auto maxValue = ChartValue(0); - auto minValueFull = std::numeric_limits::max(); - auto maxValueFull = 0; + auto minValueFull = std::numeric_limits::max(); + auto maxValueFull = ChartValue(0); for (auto &l : chartData.lines) { if (!linesFilter->isEnabled(l.id)) { continue; @@ -83,11 +84,11 @@ AbstractChartView::HeightLimits DefaultHeightLimits( const auto r = ratios.ratio(l.id); const auto lineMax = l.segmentTree.rMaxQ(xIndices.min, xIndices.max); const auto lineMin = l.segmentTree.rMinQ(xIndices.min, xIndices.max); - maxValue = std::max(int(lineMax * r), maxValue); - minValue = std::min(int(lineMin * r), minValue); + maxValue = std::max(ChartValue(lineMax * r), maxValue); + minValue = std::min(ChartValue(lineMin * r), minValue); - maxValueFull = std::max(int(l.maxValue * r), maxValueFull); - minValueFull = std::min(int(l.minValue * r), minValueFull); + maxValueFull = std::max(ChartValue(l.maxValue * r), maxValueFull); + minValueFull = std::min(ChartValue(l.minValue * r), minValueFull); } if (maxValue == minValue) { maxValue = chartData.maxValue; diff --git a/Telegram/SourceFiles/statistics/view/bar_chart_view.cpp b/Telegram/SourceFiles/statistics/view/bar_chart_view.cpp index 8beeaa5091..f796e0294a 100644 --- a/Telegram/SourceFiles/statistics/view/bar_chart_view.cpp +++ b/Telegram/SourceFiles/statistics/view/bar_chart_view.cpp @@ -256,9 +256,9 @@ AbstractChartView::HeightLimits BarChartView::heightLimits( if (_cachedHeightLimits.ySum.empty()) { _cachedHeightLimits.ySum.reserve(chartData.x.size()); - auto maxValueFull = 0; + auto maxValueFull = ChartValue(0); for (auto i = 0; i < chartData.x.size(); i++) { - auto sum = 0; + auto sum = ChartValue(0); for (const auto &line : chartData.lines) { if (linesFilterController()->isEnabled(line.id)) { sum += line.y[i]; @@ -276,7 +276,7 @@ AbstractChartView::HeightLimits BarChartView::heightLimits( _cachedHeightLimits.ySumSegmentTree.rMaxQ( xIndices.min, xIndices.max), - 1); + ChartValue(1)); return { .full = _cachedHeightLimits.full, .ranged = { 0., float64(max) }, diff --git a/Telegram/SourceFiles/statistics/view/bar_chart_view.h b/Telegram/SourceFiles/statistics/view/bar_chart_view.h index 44c1a7a6e8..3105e0dae3 100644 --- a/Telegram/SourceFiles/statistics/view/bar_chart_view.h +++ b/Telegram/SourceFiles/statistics/view/bar_chart_view.h @@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "statistics/segment_tree.h" #include "statistics/statistics_common.h" +#include "statistics/statistics_types.h" #include "statistics/view/abstract_chart_view.h" #include "ui/effects/animation_value.h" @@ -48,7 +49,7 @@ private: struct { Limits full; - std::vector ySum; + std::vector ySum; SegmentTree ySumSegmentTree; } _cachedHeightLimits; diff --git a/Telegram/SourceFiles/statistics/view/stack_linear_chart_common.cpp b/Telegram/SourceFiles/statistics/view/stack_linear_chart_common.cpp index a2ca3ff01d..b7727bd714 100644 --- a/Telegram/SourceFiles/statistics/view/stack_linear_chart_common.cpp +++ b/Telegram/SourceFiles/statistics/view/stack_linear_chart_common.cpp @@ -81,7 +81,7 @@ PiePartData PiePartsPercentageByIndices( sums.reserve(chartData.lines.size()); auto totalSum = 0.; for (const auto &line : chartData.lines) { - auto sum = 0; + auto sum = ChartValue(0); for (auto i = xIndices.min; i <= xIndices.max; i++) { sum += line.y[i]; } diff --git a/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.cpp b/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.cpp index dc3e00d043..a4e4a7c87d 100644 --- a/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.cpp +++ b/Telegram/SourceFiles/statistics/view/stack_linear_chart_view.cpp @@ -165,8 +165,8 @@ void StackLinearChartView::prepareZoom( _transition.zoomedOutXIndices = c.xIndices; _transition.zoomedOutXPercentage = c.xPercentageLimits; } else if (step == TransitionStep::PrepareToZoomIn) { - const auto &[zoomedStart, zoomedEnd] = - _transition.zoomedOutXIndices; + const auto &[zoomedStart, zoomedEnd] + = _transition.zoomedOutXIndices; _transition.lines = std::vector( c.chartData.lines.size(), Transition::TransitionLine()); @@ -624,7 +624,7 @@ void StackLinearChartView::paintZoomed(QPainter &p, const PaintContext &c) { if (selectedLineIndex >= 0) { const auto &line = c.chartData.lines[selectedLineIndex]; - auto sum = 0; + auto sum = ChartValue(0); for (auto i = zoomedStart; i <= zoomedEnd; i++) { sum += line.y[i]; } @@ -669,8 +669,8 @@ void StackLinearChartView::paintZoomedFooter( 0); const auto next = std::clamp(i + offset, zoomedStart, zoomedEnd); - const auto xPointPercentage = - (xPercentage[next] - xPercentage[zoomedStart]) + const auto xPointPercentage + = (xPercentage[next] - xPercentage[zoomedStart]) / (xPercentage[zoomedEnd] - xPercentage[zoomedStart]); const auto xPoint = leftStart + width * xPointPercentage; diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 3a8f8ef349..524aba51be 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -205,6 +205,7 @@ PRIVATE statistics/statistics_data_deserialize.h statistics/statistics_format_values.cpp statistics/statistics_format_values.h + statistics/statistics_types.h statistics/view/abstract_chart_view.cpp statistics/view/abstract_chart_view.h statistics/view/bar_chart_view.cpp