]> git.localhorst.tv Git - alttp.git/commitdiff
fix backend score calculations
authorDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 27 Nov 2025 09:25:11 +0000 (10:25 +0100)
committerDaniel Karbach <daniel.karbach@localhorst.tv>
Thu, 27 Nov 2025 09:25:11 +0000 (10:25 +0100)
app/Http/Controllers/ResultController.php
app/Models/Result.php
app/Models/Round.php
app/Models/Tournament.php

index cca1887bc9d78b6e97d4b2711c2d4534ea6764cb..14f92de4492080581bb2af53801cfa0153ffc289 100644 (file)
@@ -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();
        }
 
index 317a35405cbc8233b6d474a815da8f948dc92ca0..fd71c9ec639c85a4f9becf25c1ef84030fb14917 100644 (file)
@@ -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']);
                }
index 05195776bc0e487c8aee7dc7e5307b57f5ccade5..b88aac9ca792e0d8ab234fa385e832570d3819f1 100644 (file)
@@ -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);
                                }
                        }
                }
index ed3836894eb3a5a27380050d466f5eaa0a4f132b..74f2956c6006b9207ab918005eb47960f0be1872 100644 (file)
@@ -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';
        }