diff --git a/app/Console/Commands/RefreshAnalytics.php b/app/Console/Commands/RefreshAnalytics.php index beceedfa..5ce47089 100644 --- a/app/Console/Commands/RefreshAnalytics.php +++ b/app/Console/Commands/RefreshAnalytics.php @@ -5,6 +5,7 @@ namespace App\Console\Commands; use App\Jobs\ProcessAnalytic; +use App\Models\Season; use App\Support\Analytics\AnalyticInterface; use Illuminate\Console\Command; use Illuminate\Support\Facades\Storage; @@ -20,7 +21,9 @@ class RefreshAnalytics extends Command public function handle(): int { $availableAnalytics = Storage::disk('stats')->files(); + $seasons = Season::all(); + // ALL foreach ($availableAnalytics as $availableAnalytic) { $analytic = 'App\Support\Analytics\Stats\\'.Str::before($availableAnalytic, '.php'); @@ -28,13 +31,30 @@ public function handle(): int $analyticClass = new $analytic(); $startTime = time(); - $this->output->writeln('Processing: '.$analyticClass->title()); + $this->output->writeln('Processing (All Seasons): '.$analyticClass->title()); ProcessAnalytic::dispatchSync($analyticClass); $this->output->writeln('Processed in '.(time() - $startTime).' seconds.'); } + // Seasons + $seasons->each(function (Season $season) use ($availableAnalytics) { + foreach ($availableAnalytics as $availableAnalytic) { + $analytic = 'App\Support\Analytics\Stats\\'.Str::before($availableAnalytic, '.php'); + + /** @var AnalyticInterface $analyticClass */ + $analyticClass = new $analytic($season); + + $startTime = time(); + $this->output->writeln('Processing (' . $season->name . '): '.$analyticClass->title()); + + ProcessAnalytic::dispatchSync($analyticClass); + + $this->output->writeln('Processed in '.(time() - $startTime).' seconds.'); + } + }); + return CommandAlias::SUCCESS; } } diff --git a/app/Jobs/ProcessAnalytic.php b/app/Jobs/ProcessAnalytic.php index 2d3eb6c5..20de6bda 100644 --- a/app/Jobs/ProcessAnalytic.php +++ b/app/Jobs/ProcessAnalytic.php @@ -33,7 +33,7 @@ public function __construct( public function handle(): void { DB::transaction(function () { - Analytic::purgeKey($this->analytic->key()); + Analytic::purgeKey($this->analytic->key(), $this->analytic->season); $results = $this->analytic->results(1000); @@ -76,6 +76,7 @@ private function handleGameResults(?Collection $games): void $analytic->key = $this->analytic->key(); $analytic->value = (float) $game->{$this->analytic->property()}; $analytic->game()->associate($game); + $analytic->season()->associate($this->analytic->season); $analytic->saveOrFail(); }); } @@ -89,6 +90,7 @@ private function handleGamePlayerResults(?Collection $gamePlayers): void $analytic->value = (float) $gamePlayer->{$this->analytic->property()}; $analytic->game()->associate($gamePlayer->game); $analytic->player()->associate($gamePlayer->player); + $analytic->season()->associate($this->analytic->season); $analytic->saveOrFail(); }); } @@ -101,6 +103,7 @@ private function handleServiceRecordResults(?Collection $serviceRecords): void $analytic->key = $this->analytic->key(); $analytic->value = (float) $serviceRecord->{$this->analytic->property()}; $analytic->player()->associate($serviceRecord->player); + $analytic->season()->associate($this->analytic->season); $analytic->saveOrFail(); }); } @@ -113,6 +116,7 @@ private function handleMapResults(?Collection $maps): void $analytic->key = $this->analytic->key(); $analytic->value = (float) $map->{$this->analytic->property()}; $analytic->map()->associate($map); + $analytic->season()->associate($this->analytic->season); $analytic->saveOrFail(); }); } diff --git a/app/Models/Analytic.php b/app/Models/Analytic.php index 2b4feb27..5f050963 100644 --- a/app/Models/Analytic.php +++ b/app/Models/Analytic.php @@ -34,12 +34,15 @@ * @property string $key * @property ?int $game_id * @property ?int $player_id + * @property ?int $map_id + * @property ?int $season_id * @property float $value * @property Carbon $created_at * @property Carbon $updated_at * @property-read ?Game $game * @property-read ?Player $player * @property-read ?Map $map + * @property-read ?Season $season * @property-read AnalyticInterface $stat * * @method static AnalyticFactory factory(...$parameters) @@ -80,11 +83,17 @@ public static function getStatFromEnum(?AnalyticKey $key): AnalyticInterface }; } - public static function purgeKey(string $key): void + public static function purgeKey(string $key, ?Season $season = null): void { - self::query() - ->where('key', $key) - ->delete(); + $query = self::query()->where('key', $key); + + if ($season) { + $query->where('season_id', $season->id); + } else { + $query->whereNull('season_id'); + } + + $query->delete(); } public function game(): BelongsTo @@ -101,4 +110,9 @@ public function map(): BelongsTo { return $this->belongsTo(Map::class); } + + public function season(): BelongsTo + { + return $this->belongsTo(Season::class); + } } diff --git a/app/Support/Analytics/AnalyticInterface.php b/app/Support/Analytics/AnalyticInterface.php index 58680b7b..12e7592e 100644 --- a/app/Support/Analytics/AnalyticInterface.php +++ b/app/Support/Analytics/AnalyticInterface.php @@ -6,11 +6,14 @@ use App\Enums\AnalyticType; use App\Models\Analytic; +use App\Models\Season; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; interface AnalyticInterface { + public function __construct(?Season $season = null); + public function type(): AnalyticType; public function key(): string; diff --git a/app/Support/Analytics/BaseGameStat.php b/app/Support/Analytics/BaseGameStat.php index 2343decc..3c207c72 100644 --- a/app/Support/Analytics/BaseGameStat.php +++ b/app/Support/Analytics/BaseGameStat.php @@ -6,10 +6,16 @@ use App\Enums\AnalyticType; use App\Models\GamePlayer; +use App\Models\Season; use Illuminate\Database\Eloquent\Builder; class BaseGameStat { + public function __construct(public readonly ?Season $season = null) + { + // + } + public function type(): AnalyticType { return AnalyticType::GAME(); diff --git a/app/Support/Analytics/BaseMapStat.php b/app/Support/Analytics/BaseMapStat.php index 2861cd9c..17656322 100644 --- a/app/Support/Analytics/BaseMapStat.php +++ b/app/Support/Analytics/BaseMapStat.php @@ -6,10 +6,16 @@ use App\Enums\AnalyticType; use App\Models\Map; +use App\Models\Season; use Illuminate\Database\Eloquent\Builder; class BaseMapStat { + public function __construct(public readonly ?Season $season = null) + { + // + } + public function type(): AnalyticType { return AnalyticType::MAP(); diff --git a/app/Support/Analytics/BaseOnlyGameStat.php b/app/Support/Analytics/BaseOnlyGameStat.php index b71b4f28..11ebd8d6 100644 --- a/app/Support/Analytics/BaseOnlyGameStat.php +++ b/app/Support/Analytics/BaseOnlyGameStat.php @@ -6,10 +6,16 @@ use App\Enums\AnalyticType; use App\Models\Game; +use App\Models\Season; use Illuminate\Database\Eloquent\Builder; class BaseOnlyGameStat { + public function __construct(public readonly ?Season $season = null) + { + // + } + public function type(): AnalyticType { return AnalyticType::ONLY_GAME(); diff --git a/app/Support/Analytics/BasePlayerStat.php b/app/Support/Analytics/BasePlayerStat.php index 7b7c6a41..104d47f2 100644 --- a/app/Support/Analytics/BasePlayerStat.php +++ b/app/Support/Analytics/BasePlayerStat.php @@ -5,11 +5,17 @@ namespace App\Support\Analytics; use App\Enums\AnalyticType; +use App\Models\Season; use App\Models\ServiceRecord; use Illuminate\Database\Eloquent\Builder; class BasePlayerStat { + public function __construct(public readonly ?Season $season = null) + { + // + } + public function type(): AnalyticType { return AnalyticType::PLAYER(); diff --git a/app/Support/Analytics/Stats/BestAccuracyServiceRecord.php b/app/Support/Analytics/Stats/BestAccuracyServiceRecord.php index 39e6bf8e..1717d990 100644 --- a/app/Support/Analytics/Stats/BestAccuracyServiceRecord.php +++ b/app/Support/Analytics/Stats/BestAccuracyServiceRecord.php @@ -45,16 +45,24 @@ public function displayProperty(Analytic $analytic): string public function results(int $limit = 10): ?Collection { - return $this->builder() + $seasonKey = $this->season?->key; + + $query = $this->builder() ->select('service_records.*') ->with(['player']) ->leftJoin('players', 'players.id', '=', 'service_records.player_id') ->where('is_cheater', false) ->where('mode', Mode::MATCHMADE_PVP) - ->whereNull('season_number') ->where('total_matches', '>=', 1000) ->orderByDesc($this->property()) - ->limit($limit) - ->get(); + ->limit($limit); + + if ($seasonKey) { + $query->where('season_key', $seasonKey); + } else { + $query->whereNull('season_key'); + } + + return $query->get(); } } diff --git a/database/migrations/2023_05_29_120051_add_season_id_to_analytics.php b/database/migrations/2023_05_29_120051_add_season_id_to_analytics.php new file mode 100644 index 00000000..0197c674 --- /dev/null +++ b/database/migrations/2023_05_29_120051_add_season_id_to_analytics.php @@ -0,0 +1,25 @@ +foreignIdFor(Season::class)->after('map_id')->nullable()->constrained(); + }); + } + + public function down(): void + { + Schema::table('analytics', function (Blueprint $table) { + $table->dropForeignIdFor(Season::class); + }); + } +};