Skip to content

Commit

Permalink
Merge pull request #11407 from nanaya/percentile-refactor
Browse files Browse the repository at this point in the history
Split percentile calculation to its own function
  • Loading branch information
notbakaneko authored Aug 7, 2024
2 parents 1712c3c + 6a74fd1 commit 35a0a71
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 24 deletions.
50 changes: 26 additions & 24 deletions app/Models/DailyChallengeUserStats.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

namespace App\Models;

use App\Models\Multiplayer\PlaylistItemUserHighScore;
use Carbon\CarbonImmutable;
use Ds\Set;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
Expand Down Expand Up @@ -52,27 +53,19 @@ public static function calculate(CarbonImmutable $date): void
return;
}

$highScores = $playlist
$highScoresByUserId = $playlist
->highScores()
->where('total_score', '>', 0)
->orderBy('total_score', 'DESC')
->get();
$count = $highScores->count();
// these variables are only used if there's anything in the array
if ($count > 0) {
$top50p = $highScores[max(0, (int) ($count * 0.5) - 1)]->total_score;
$top10p = $highScores[max(0, (int) ($count * 0.1) - 1)]->total_score;
}
$highScoresByUserId = [];
foreach ($highScores as $highScore) {
$highScoresByUserId[$highScore->user_id] = $highScore;
}
->get()
->keyBy('user_id');
$statsByUserId = static
::where('last_weekly_streak', '>=', $previousWeek->subDays(1))
->orWhereIn('user_id', array_keys($highScoresByUserId))
->orWhereIn('user_id', $highScoresByUserId->keys())
->get()
->keyBy('user_id');
$userIds = new Set([...$statsByUserId->keys(), ...array_keys($highScoresByUserId)]);
$percentile = $playlist->scorePercentile();

$userIds = new Set([...$statsByUserId->keys(), ...$highScoresByUserId->keys()]);
foreach ($userIds as $userId) {
$stats = $statsByUserId[$userId] ?? new static([
'user_id' => $userId,
Expand All @@ -86,15 +79,7 @@ public static function calculate(CarbonImmutable $date): void
previousWeek: $previousWeek,
);

if ($highScore !== null && $stats->last_percentile_calculation < $startTime) {
if ($highScore->total_score >= $top10p) {
$stats->top_10p_placements += 1;
}
if ($highScore->total_score >= $top50p) {
$stats->top_50p_placements += 1;
}
$stats->last_percentile_calculation = $startTime;
}
$stats->updatePercentile($percentile, $highScore, $startTime);

$stats->save();
}
Expand Down Expand Up @@ -152,4 +137,21 @@ public function updateStreak(
}
}
}

private function updatePercentile(
array $playlistPercentile,
?PlaylistItemUserHighScore $highScore,
CarbonImmutable $startTime
): void {
if ($highScore === null || $this->last_percentile_calculation >= $startTime) {
return;
}

foreach ($playlistPercentile as $p => $totalScore) {
if ($highScore->total_score >= $totalScore) {
$this->{"top_{$p}_placements"}++;
}
}
$this->last_percentile_calculation = $startTime;
}
}
18 changes: 18 additions & 0 deletions app/Models/Multiplayer/PlaylistItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,24 @@ public function save(array $options = [])
return parent::save($options);
}

public function scorePercentile(): array
{
$scores = $this->highScores()
->where('total_score', '>', 0)
->orderBy('total_score', 'DESC')
->pluck('total_score');
$count = count($scores);

return $count === 0
? [
'10p' => 0,
'50p' => 0,
] : [
'10p' => $scores[max(0, (int) ($count * 0.1) - 1)],
'50p' => $scores[max(0, (int) ($count * 0.5) - 1)],
];
}

private function assertValidMaxAttempts()
{
if ($this->max_attempts === null) {
Expand Down

0 comments on commit 35a0a71

Please sign in to comment.