Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

CompanyStatsOverview.php 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. <?php
  2. namespace App\Filament\Pages\Widgets\Companies\Charts;
  3. use App\Models\Company;
  4. use Filament\Widgets\StatsOverviewWidget;
  5. class CompanyStatsOverview extends StatsOverviewWidget
  6. {
  7. protected static ?int $sort = 0;
  8. /**
  9. * Holt's Linear Trend Method
  10. */
  11. protected function holtLinearTrend($data, $alpha, $beta): array
  12. {
  13. $level = $data[0];
  14. $trend = $data[1] - $data[0];
  15. $forecast = [];
  16. foreach ($data as $iValue) {
  17. $prev_level = $level;
  18. $level = $alpha * $iValue + (1 - $alpha) * ($prev_level + $trend);
  19. $trend = $beta * ($level - $prev_level) + (1 - $beta) * $trend;
  20. $forecast[] = $level + $trend;
  21. }
  22. return $forecast;
  23. }
  24. /**
  25. * Adjusts the alpha and beta parameters based on the model's performance
  26. */
  27. protected function adjustTrendParameters($data, $alpha, $beta): array
  28. {
  29. $minError = PHP_INT_MAX;
  30. $bestAlpha = $alpha;
  31. $bestBeta = $beta;
  32. // try different alpha and beta values within a reasonable range
  33. for ($testAlpha = 0.1; $testAlpha <= 1; $testAlpha += 0.1) {
  34. for ($testBeta = 0.1; $testBeta <= 1; $testBeta += 0.1) {
  35. $forecast = $this->holtLinearTrend($data, $testAlpha, $testBeta);
  36. $error = $this->calculateError($data, $forecast);
  37. if ($error < $minError) {
  38. $minError = $error;
  39. $bestAlpha = $testAlpha;
  40. $bestBeta = $testBeta;
  41. }
  42. }
  43. }
  44. return [$bestAlpha, $bestBeta];
  45. }
  46. /**
  47. * Calculates the sum of squared errors between the actual data and the forecast
  48. */
  49. protected function calculateError($data, $forecast): float
  50. {
  51. $error = 0;
  52. for ($i = 0, $iMax = count($data); $i < $iMax; $i++) {
  53. $error += ($data[$i] - $forecast[$i]) ** 2;
  54. }
  55. return $error;
  56. }
  57. /**
  58. * Chart Options
  59. */
  60. protected function getCards(): array
  61. {
  62. // Define constants
  63. $alpha = 0.8;
  64. $beta = 0.2;
  65. // Define time variables
  66. $startOfYear = today()->startOfYear();
  67. $today = today();
  68. // Get Company Data
  69. $companyData = Company::selectRaw("COUNT(*) as aggregate, YEARWEEK(created_at, 3) as week")
  70. ->whereBetween('created_at', [$startOfYear, $today])
  71. ->groupByRaw('week')
  72. ->get();
  73. // Initialize weeks
  74. $weeks = [];
  75. for ($week = $startOfYear->copy(); $week->lte($today); $week->addWeek()) {
  76. $weeks[$week->format('oW')] = 0;
  77. }
  78. // Get Weekly Data for Company Data
  79. $weeklyData = collect($weeks)->mapWithKeys(static function ($value, $week) use ($companyData) {
  80. $matchingData = $companyData->firstWhere('week', $week);
  81. return [$week => $matchingData->aggregate ?? 0];
  82. });
  83. // Calculate total companies per week
  84. $totalCompanies = $weeklyData->reduce(static function ($carry, $value) {
  85. $carry[] = ($carry ? end($carry) : 0) + $value;
  86. return $carry;
  87. }, []);
  88. // Calculate new companies and percentage change per week
  89. $newCompanies = [0];
  90. $weeklyPercentageChange = [0];
  91. for ($i = 1, $iMax = count($totalCompanies); $i < $iMax; $i++) {
  92. $newCompanies[] = $totalCompanies[$i] - $totalCompanies[$i - 1];
  93. $weeklyPercentageChange[] = ($newCompanies[$i] / $totalCompanies[$i - 1]) * 100;
  94. }
  95. // Calculate average weekly growth rate
  96. $totalWeeks = $startOfYear->diffInWeeks($today);
  97. $averageWeeklyGrowthRate = round(array_sum($weeklyPercentageChange) / $totalWeeks, 2);
  98. $weeklyDataArray = $weeklyData->values()->toArray();
  99. // Adjust alpha and beta parameters
  100. [$alpha, $beta] = $this->adjustTrendParameters($weeklyDataArray, $alpha, $beta);
  101. // Calculate Holt's Linear Trend Forecast for next week
  102. $holtForecast = $this->holtLinearTrend($weeklyDataArray, $alpha, $beta);
  103. $expectedNewCompanies = round(end($holtForecast));
  104. // Company Stats Overview Cards
  105. return [
  106. StatsOverviewWidget\Card::make("New Companies Forecast (Holt's Linear Trend)", $expectedNewCompanies),
  107. StatsOverviewWidget\Card::make('Average Weekly Growth Rate', $averageWeeklyGrowthRate . '%'),
  108. StatsOverviewWidget\Card::make('Personal Companies', Company::sum('personal_company')),
  109. ];
  110. }
  111. }