Files
scrum-poker-internal/app/Services/Rooms/RoundService.php
T
2026-08-20 23:00:47 +02:00

116 lines
3.2 KiB
PHP

<?php
namespace App\Services\Rooms;
use App\Enums\RoomStateChange;
use App\Events\RoomStateChanged;
use App\Models\Room;
use App\Models\Vote;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
class RoundService
{
public function reset(Room $room): void
{
$stateVersion = DB::transaction(function () use ($room): int {
$lockedRoom = Room::query()
->lockForUpdate()
->findOrFail($room->id);
$this->ensureRoomIsOpen($lockedRoom);
Vote::query()
->where('room_id', $lockedRoom->id)
->where('round', $lockedRoom->current_round)
->delete();
$lockedRoom->update([
'revealed_at' => null,
'last_activity_at' => now(),
'state_version' => $lockedRoom->state_version + 1,
]);
return $lockedRoom->state_version;
});
RoomStateChanged::dispatch(
$room->id,
$stateVersion,
RoomStateChange::VotesReset,
);
}
public function reveal(Room $room): void
{
$stateVersion = DB::transaction(function () use ($room): int {
$lockedRoom = Room::query()
->lockForUpdate()
->findOrFail($room->id);
$this->ensureRoomIsOpen($lockedRoom);
if ($lockedRoom->revealed_at !== null) {
throw ValidationException::withMessages([
'room' => 'Die Karten sind bereits aufgedeckt.',
]);
}
$lockedRoom->update([
'revealed_at' => now(),
'last_activity_at' => now(),
'state_version' => $lockedRoom->state_version + 1,
]);
return $lockedRoom->state_version;
});
RoomStateChanged::dispatch(
$room->id,
$stateVersion,
RoomStateChange::CardsRevealed,
);
}
public function startNext(Room $room): void
{
$stateVersion = DB::transaction(function () use ($room): int {
$lockedRoom = Room::query()
->lockForUpdate()
->findOrFail($room->id);
$this->ensureRoomIsOpen($lockedRoom);
if ($lockedRoom->revealed_at === null) {
throw ValidationException::withMessages([
'room' => 'Die aktuelle Runde muss zuerst aufgedeckt werden.',
]);
}
$lockedRoom->update([
'current_round' => $lockedRoom->current_round + 1,
'revealed_at' => null,
'last_activity_at' => now(),
'state_version' => $lockedRoom->state_version + 1,
]);
return $lockedRoom->state_version;
});
RoomStateChanged::dispatch(
$room->id,
$stateVersion,
RoomStateChange::NextRound,
);
}
private function ensureRoomIsOpen(Room $room): void
{
if ($room->isClosed()) {
throw ValidationException::withMessages([
'room' => 'Dieser Raum ist geschlossen.',
]);
}
}
}