Rename car_number to number, time_ms to best_time_ms, update participant statuses, and redesign leaderboard with broadcast-style UI

This commit is contained in:
ut-masekela
2026-03-25 03:32:33 +02:00
parent a63ea60860
commit adc85b2b88
6 changed files with 232 additions and 212 deletions

View File

@@ -11,26 +11,40 @@ class Participant extends Model
protected $fillable = [
'name',
'car_number',
'time_ms',
'number',
'best_time_ms',
'status',
];
protected $casts = [
'car_number' => 'integer',
'time_ms' => 'integer',
'number' => 'integer',
'best_time_ms' => 'integer',
];
/**
* Format time_ms as mm:ss.ms (e.g., 01:23.456)
*/
const STATUS_READY = 'ready';
const STATUS_RUNNING = 'running';
const STATUS_FINISHED = 'finished';
const STATUS_PIT = 'pit';
const STATUS_DNF = 'dnf';
public static function statuses(): array
{
return [
self::STATUS_READY => 'READY',
self::STATUS_RUNNING => 'RUNNING',
self::STATUS_FINISHED => 'FINISHED',
self::STATUS_PIT => 'IN PIT',
self::STATUS_DNF => 'DNF',
];
}
public function getFormattedTimeAttribute(): ?string
{
if ($this->time_ms === null) {
if ($this->best_time_ms === null) {
return null;
}
$totalMs = $this->time_ms;
$totalMs = $this->best_time_ms;
$minutes = floor($totalMs / 60000);
$seconds = floor(($totalMs % 60000) / 1000);
$milliseconds = $totalMs % 1000;
@@ -38,20 +52,14 @@ public function getFormattedTimeAttribute(): ?string
return sprintf('%02d:%02d.%03d', $minutes, $seconds, $milliseconds);
}
/**
* Scope to get ranked participants (fastest first, null times last)
*/
public function scopeRanked($query)
public function getStatusLabelAttribute(): string
{
return $query->orderByRaw('CASE WHEN time_ms IS NULL THEN 1 ELSE 0 END')
->orderBy('time_ms', 'asc');
return self::statuses()[$this->status] ?? strtoupper($this->status);
}
/**
* Scope to get only completed participants
*/
public function scopeCompleted($query)
public function scopeRanked($query)
{
return $query->where('status', 'completed');
return $query->orderByRaw('CASE WHEN best_time_ms IS NULL THEN 1 ELSE 0 END')
->orderBy('best_time_ms', 'asc');
}
}