stack_linear_chart_common.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "statistics/view/stack_linear_chart_common.h"
  8. #include "data/data_statistics_chart.h"
  9. #include "statistics/chart_lines_filter_controller.h"
  10. #include "statistics/statistics_common.h"
  11. namespace Statistic {
  12. PiePartData PiePartsPercentage(
  13. const std::vector<float64> &sums,
  14. float64 totalSum,
  15. bool round) {
  16. auto result = PiePartData();
  17. result.parts.reserve(sums.size());
  18. auto stackedPercentage = 0.;
  19. auto sumPercDiffs = 0.;
  20. auto maxPercDiff = 0.;
  21. auto minPercDiff = 0.;
  22. auto maxPercDiffIndex = int(-1);
  23. auto minPercDiffIndex = int(-1);
  24. auto roundedPercentagesSum = 0.;
  25. result.pieHasSinglePart = false;
  26. constexpr auto kPerChar = '%';
  27. for (auto k = 0; k < sums.size(); k++) {
  28. const auto rawPercentage = totalSum ? (sums[k] / totalSum) : 0.;
  29. const auto rounded = round
  30. ? (0.01 * std::round(rawPercentage * 100.))
  31. : rawPercentage;
  32. roundedPercentagesSum += rounded;
  33. const auto diff = rawPercentage - rounded;
  34. sumPercDiffs += diff;
  35. const auto diffAbs = std::abs(diff);
  36. if (maxPercDiff < diffAbs) {
  37. maxPercDiff = diffAbs;
  38. maxPercDiffIndex = k;
  39. }
  40. if (minPercDiff < diffAbs) {
  41. minPercDiff = diffAbs;
  42. minPercDiffIndex = k;
  43. }
  44. stackedPercentage += rounded;
  45. result.parts.push_back({
  46. rounded,
  47. stackedPercentage * 360. - 180.,
  48. QString::number(int(rounded * 100)) + kPerChar,
  49. });
  50. result.pieHasSinglePart |= (rounded == 1.);
  51. }
  52. if (round) {
  53. const auto index = (roundedPercentagesSum > 1.)
  54. ? maxPercDiffIndex
  55. : minPercDiffIndex;
  56. if (index >= 0) {
  57. result.parts[index].roundedPercentage += sumPercDiffs;
  58. result.parts[index].percentageText = QString::number(
  59. int(result.parts[index].roundedPercentage * 100)) + kPerChar;
  60. const auto angleShrink = (sumPercDiffs) * 360.;
  61. for (auto &part : result.parts) {
  62. part.stackedAngle += angleShrink;
  63. }
  64. }
  65. }
  66. return result;
  67. }
  68. PiePartData PiePartsPercentageByIndices(
  69. const Data::StatisticalChart &chartData,
  70. const std::shared_ptr<LinesFilterController> &linesFilter,
  71. const Limits &xIndices) {
  72. auto sums = std::vector<float64>();
  73. sums.reserve(chartData.lines.size());
  74. auto totalSum = 0.;
  75. for (const auto &line : chartData.lines) {
  76. auto sum = ChartValue(0);
  77. for (auto i = xIndices.min; i <= xIndices.max; i++) {
  78. sum += line.y[i];
  79. }
  80. if (linesFilter) {
  81. sum *= linesFilter->alpha(line.id);
  82. }
  83. totalSum += sum;
  84. sums.push_back(sum);
  85. }
  86. return PiePartsPercentage(sums, totalSum, true);
  87. }
  88. } // namespace Statistic