From d5010f5494c694da424ef4190e0d0d6a4283b6be Mon Sep 17 00:00:00 2001 From: Daniel Karbach Date: Thu, 27 Nov 2025 10:25:11 +0100 Subject: [PATCH] fix backend score calculations --- app/Http/Controllers/ResultController.php | 28 ++++++++++++----- app/Models/Result.php | 35 ++++++++++++++------- app/Models/Round.php | 38 +++++++++++++---------- app/Models/Tournament.php | 6 +++- 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/app/Http/Controllers/ResultController.php b/app/Http/Controllers/ResultController.php index cca1887..14f92de 100644 --- a/app/Http/Controllers/ResultController.php +++ b/app/Http/Controllers/ResultController.php @@ -98,18 +98,26 @@ class ResultController extends Controller 'time' => 'numeric', ]); + $round = Round::findOrFail($result->round_id); + if (isset($validatedData['disqualified'])) $result->disqualified = $validatedData['disqualified']; if (isset($validatedData['forfeit'])) $result->forfeit = $validatedData['forfeit']; if (isset($validatedData['time'])) $result->time = $validatedData['time']; $result->save(); + ResultChanged::dispatch($result); + Protocol::resultModified( - $result->round->tournament, + $round->tournament, $result, $request->user(), ); - ResultChanged::dispatch($result); + $round->load('results'); + $round->updatePlacement(); + if ($round->tournament->hasScoreboard()) { + $round->tournament->updatePlacement(); + } return $result->toJson(); } @@ -117,36 +125,40 @@ class ResultController extends Controller public function unverify(Request $request, Result $result) { $this->authorize('unverify', $result); + $round = Round::findOrFail($result->round_id); + $result->verified_at = null; $result->verified_by()->associate(null); $result->save(); + ResultChanged::dispatch($result); + Protocol::resultUnverified( - $result->round->tournament, + $round->tournament, $result, $request->user(), ); - ResultChanged::dispatch($result); - return $result->toJson(); } public function verify(Request $request, Result $result) { $this->authorize('verify', $result); + $round = Round::findOrFail($result->round_id); + $result->verified_at = now(); $result->verified_by()->associate($request->user()); $result->save(); + ResultChanged::dispatch($result); + Protocol::resultVerified( - $result->round->tournament, + $round->tournament, $result, $request->user(), ); - ResultChanged::dispatch($result); - return $result->toJson(); } diff --git a/app/Models/Result.php b/app/Models/Result.php index 317a354..fd71c9e 100644 --- a/app/Models/Result.php +++ b/app/Models/Result.php @@ -11,9 +11,9 @@ class Result extends Model use HasFactory; - public static function compareResult(Result $a, Result $b) { - $a_time = !$a->forfeit ? $a->time : 0; - $b_time = !$b->forfeit ? $b->time : 0; + public static function compareResult(Result $a, Result $b): int { + $a_time = $a->getEffectiveTime(); + $b_time = $b->getEffectiveTime(); if ($a_time) { if ($b_time) { if ($a_time < $b_time) return -1; @@ -25,31 +25,44 @@ class Result extends Model if ($b_time) { return 1; } + if ($a->disqualified) { + if ($b->disqualified) { + return static::compareUsername($a, $b); + } + return 1; + } + if ($b->disqualified) { + return -1; + } if ($a->forfeit) { if ($b->forfeit) { return static::compareUsername($a, $b); } - return -1; + return 1; } if ($b->forfeit) { - return 1; + return -1; } return static::compareUsername($a, $b); } - public static function compareUsername(Result $a, Result $b) { + public static function compareUsername(Result $a, Result $b): int { return strcasecmp($a->user->username, $b->user->username); } - public function formatTime() { + public function formatTime(): string { $hours = floor($this->time / 60 / 60); $minutes = floor(($this->time / 60) % 60); $seconds = floor($this->time % 60); return sprintf('%d:%02d:%02d', $hours, $minutes, $seconds); } - public function updateResult($time, $forfeit) { + public function getEffectiveTime(): float { + return ($this->disqualified || $this->forfeit) ? 0 : $this->time; + } + + public function updateResult($time, $forfeit): void { $this->time = $time; $this->forfeit = $forfeit; $this->save(); @@ -58,7 +71,7 @@ class Result extends Model } } - public function updatePlacement($score, $placement) { + public function updatePlacement($score, $placement): void { $this->score = $score; $this->placement = $placement; $this->save(); @@ -68,9 +81,9 @@ class Result extends Model } - public function hideResult(User $user = null) { + public function hideResult(User $user = null): void { if (!$user || $this->user_id != $user->id) { - $this->makeHidden(['forfeit', 'placement', 'score', 'time', 'vod']); + $this->makeHidden(['disqualified', 'forfeit', 'placement', 'score', 'time', 'vod']); } else { $this->makeHidden(['placement', 'score']); } diff --git a/app/Models/Round.php b/app/Models/Round.php index 0519577..b88aac9 100644 --- a/app/Models/Round.php +++ b/app/Models/Round.php @@ -26,7 +26,7 @@ class Round extends Model public function isComplete() { if (count($this->tournament->participants) == 0) return false; - if ($this->tournament->type == 'open-async') return false; + if (!$this->tournament->hasFixedRunners()) return false; if (count($this->results) == 0) return false; foreach ($this->tournament->getRunners() as $participant) { $result = $participant->findResult($this); @@ -35,8 +35,8 @@ class Round extends Model return true; } - public function updatePlacement() { - if ($this->tournament->type == 'open-async') { + public function updatePlacement(): void { + if (!$this->tournament->hasFixedRunners()) { $results = $this->results->sort([Result::class, 'compareResult']); $reversed = $results->reverse(); @@ -44,18 +44,20 @@ class Round extends Model $bonus = 1; $lastResult = null; foreach ($reversed as $result) { - $betterThanLast = is_null($lastResult) || $result->time < $lastResult; - if (!$result->forfeit && $betterThanLast) { + $betterThanLast = is_null($lastResult) || $result->getEffectiveTime() < $lastResult; + if (!$result->disqualified && !$result->forfeit && $betterThanLast) { $running += $bonus; - $lastResult = $result->time; + $lastResult = $result->getEffectiveTime(); $bonus = 1; } else { ++$bonus; } - if (!$result->forfeit) { - $result->updatePlacement($running, count($results) - $running + 1); - } else { + if ($result->disqualified) { + $result->updatePlacement(0, count($results) + 1); + } elseif ($result->forfeit) { $result->updatePlacement(0, count($results)); + } else { + $result->updatePlacement($running, count($results) - $running + 1); } } } else { @@ -75,8 +77,8 @@ class Round extends Model $mapped = array_map(function ($p) { return ['participant' => $p, 'result' => $p->findResult($this)]; }, $runners); - $filtered = array_filter($mapped, function($r) { - return $r['result'] && ($r['result']->time || $r['result']->forfeit); + $filtered = array_filter($mapped, function ($r) { + return $r['result'] && ($r['result']->time || $r['result']->forfeit || $r['result']->disqualified); }); $reversed = array_reverse($filtered); @@ -84,18 +86,20 @@ class Round extends Model $bonus = 1; $lastResult = null; foreach ($reversed as $r) { - $betterThanLast = is_null($lastResult) || $r['result']->time < $lastResult; - if (!$r['result']->forfeit && $betterThanLast) { + $betterThanLast = is_null($lastResult) || $r['result']->getEffectiveTime() < $lastResult; + if (!$r['result']->disqualified && !$r['result']->forfeit && $betterThanLast) { $running += $bonus; - $lastResult = $r['result']->time; + $lastResult = $r['result']->getEffectiveTime(); $bonus = 1; } else { ++$bonus; } - if (!$r['result']->forfeit) { - $r['result']->updatePlacement($running, count($filtered) - $running + 1); - } else { + if ($r['result']->disqualified) { + $r['result']->updatePlacement(0, count($filtered) + 1); + } elseif ($r['result']->forfeit) { $r['result']->updatePlacement(0, count($filtered)); + } else { + $r['result']->updatePlacement($running, count($filtered) - $running + 1); } } } diff --git a/app/Models/Tournament.php b/app/Models/Tournament.php index ed38368..74f2956 100644 --- a/app/Models/Tournament.php +++ b/app/Models/Tournament.php @@ -17,6 +17,10 @@ class Tournament extends Model { } + public function hasFixedRunners(): bool { + return in_array($this->type, ['signup-async']); + } + public function getRunners() { $runners = []; foreach ($this->participants as $participant) { @@ -27,7 +31,7 @@ class Tournament extends Model { return $runners; } - public function hasScoreboard() { + public function hasScoreboard(): bool { return $this->type == 'signup-async'; } -- 2.47.3