torneos/app/Services/DemoScoresheetSeeder.php

192 lines
8.8 KiB
PHP

<?php
namespace App\Services;
use App\Core\Database;
use PDO;
final class DemoScoresheetSeeder
{
private PDO $db;
public function __construct()
{
$this->db = Database::connection();
}
public function seed(int $tournamentId, bool $force = false): array
{
if (!$force && $this->hasDemo($tournamentId)) {
return ['created' => false, 'message' => 'El torneo ya tiene demo de planilla'];
}
$this->db->beginTransaction();
try {
$homeTeamId = $this->team($tournamentId, 'Demo A', 'DT Demo A');
$awayTeamId = $this->team($tournamentId, 'Demo B', 'DT Demo B');
$homePlayers = $this->players($homeTeamId, 'A');
$awayPlayers = $this->players($awayTeamId, 'B');
$matchId = $this->match($tournamentId, $homeTeamId, $awayTeamId);
$this->sets($matchId, $homeTeamId);
$this->sheetDetails($matchId, $homeTeamId, $homePlayers[0], 'DT Demo A', 'Observaciones demo equipo A');
$this->sheetDetails($matchId, $awayTeamId, $awayPlayers[0], 'DT Demo B', 'Observaciones demo equipo B');
$this->libero($matchId, $homeTeamId, $homePlayers[11]);
$this->libero($matchId, $awayTeamId, $awayPlayers[11]);
$this->rotations($matchId, $homeTeamId, array_slice($homePlayers, 0, 6));
$this->rotations($matchId, $awayTeamId, array_slice($awayPlayers, 0, 6));
$this->signature($matchId);
$this->events($matchId, $homeTeamId, $awayTeamId);
$this->db->commit();
return ['created' => true, 'match_id' => $matchId, 'home_team_id' => $homeTeamId, 'away_team_id' => $awayTeamId];
} catch (\Throwable $e) {
$this->db->rollBack();
throw $e;
}
}
private function hasDemo(int $tournamentId): bool
{
$stmt = $this->db->prepare('SELECT id FROM teams WHERE tournament_id = :id AND name IN ("Demo A", "Demo B") LIMIT 1');
$stmt->execute(['id' => $tournamentId]);
return (bool) $stmt->fetch();
}
private function team(int $tournamentId, string $name, string $coach): int
{
$stmt = $this->db->prepare('SELECT id FROM teams WHERE tournament_id = :tournament_id AND name = :name');
$stmt->execute(['tournament_id' => $tournamentId, 'name' => $name]);
$row = $stmt->fetch();
if ($row) {
return (int) $row['id'];
}
$stmt = $this->db->prepare(
'INSERT INTO teams (tournament_id, name, coach_name, registration_token)
VALUES (:tournament_id, :name, :coach_name, :registration_token)'
);
$stmt->execute([
'tournament_id' => $tournamentId,
'name' => $name,
'coach_name' => $coach,
'registration_token' => bin2hex(random_bytes(16)),
]);
return (int) $this->db->lastInsertId();
}
private function players(int $teamId, string $prefix): array
{
$ids = [];
$positions = ['Armador', 'Opuesto', 'Central', 'Punta', 'Punta', 'Central', 'Universal', 'Universal', 'Punta', 'Central', 'Opuesto', 'Libero'];
for ($i = 1; $i <= 12; $i++) {
$doc = "DEMO-$prefix-$i";
$stmt = $this->db->prepare('SELECT id FROM players WHERE team_id = :team_id AND document_id = :doc');
$stmt->execute(['team_id' => $teamId, 'doc' => $doc]);
$row = $stmt->fetch();
if ($row) {
$ids[] = (int) $row['id'];
continue;
}
$stmt = $this->db->prepare(
'INSERT INTO players (team_id, first_name, last_name, document_id, birth_date, jersey_number, position)
VALUES (:team_id, :first_name, :last_name, :document_id, "1998-01-01", :jersey_number, :position)'
);
$stmt->execute([
'team_id' => $teamId,
'first_name' => "Jugador$prefix",
'last_name' => str_pad((string) $i, 2, '0', STR_PAD_LEFT),
'document_id' => $doc,
'jersey_number' => $i,
'position' => $positions[$i - 1],
]);
$ids[] = (int) $this->db->lastInsertId();
}
return $ids;
}
private function match(int $tournamentId, int $homeTeamId, int $awayTeamId): int
{
$stmt = $this->db->prepare('SELECT id FROM matches WHERE tournament_id = :tournament_id AND home_team_id = :home AND away_team_id = :away LIMIT 1');
$stmt->execute(['tournament_id' => $tournamentId, 'home' => $homeTeamId, 'away' => $awayTeamId]);
$row = $stmt->fetch();
if ($row) {
return (int) $row['id'];
}
$stmt = $this->db->prepare(
'INSERT INTO matches (tournament_id, phase, scheduled_at, home_team_id, away_team_id, status, winner_team_id, home_sets, away_sets)
VALUES (:tournament_id, "demo", NOW(), :home, :away, "finished", :winner, 3, 1)'
);
$stmt->execute(['tournament_id' => $tournamentId, 'home' => $homeTeamId, 'away' => $awayTeamId, 'winner' => $homeTeamId]);
return (int) $this->db->lastInsertId();
}
private function sets(int $matchId, int $winnerTeamId): void
{
$scores = [[25, 21], [22, 25], [25, 18], [25, 23]];
foreach ($scores as $index => [$home, $away]) {
$stmt = $this->db->prepare(
'INSERT INTO match_sets (match_id, set_number, home_points, away_points, winner_team_id)
VALUES (:match_id, :set_number, :home, :away, :winner)
ON DUPLICATE KEY UPDATE home_points = VALUES(home_points), away_points = VALUES(away_points), winner_team_id = VALUES(winner_team_id)'
);
$stmt->execute([
'match_id' => $matchId,
'set_number' => $index + 1,
'home' => $home,
'away' => $away,
'winner' => $home > $away ? $winnerTeamId : null,
]);
}
}
private function sheetDetails(int $matchId, int $teamId, int $captainId, string $coach, string $observations): void
{
$stmt = $this->db->prepare(
'INSERT INTO match_sheet_details (match_id, team_id, captain_player_id, coach_name, observations)
VALUES (:match_id, :team_id, :captain, :coach, :observations)
ON DUPLICATE KEY UPDATE captain_player_id = VALUES(captain_player_id), coach_name = VALUES(coach_name), observations = VALUES(observations)'
);
$stmt->execute(['match_id' => $matchId, 'team_id' => $teamId, 'captain' => $captainId, 'coach' => $coach, 'observations' => $observations]);
}
private function libero(int $matchId, int $teamId, int $playerId): void
{
$this->db->prepare(
'INSERT IGNORE INTO match_liberos (match_id, team_id, player_id, set_number, is_starting)
VALUES (:match_id, :team_id, :player_id, 1, 1)'
)->execute(['match_id' => $matchId, 'team_id' => $teamId, 'player_id' => $playerId]);
}
private function rotations(int $matchId, int $teamId, array $players): void
{
foreach ($players as $index => $playerId) {
$this->db->prepare(
'INSERT INTO rotations (match_id, team_id, set_number, position_number, player_id)
VALUES (:match_id, :team_id, 1, :position, :player_id)
ON DUPLICATE KEY UPDATE player_id = VALUES(player_id)'
)->execute(['match_id' => $matchId, 'team_id' => $teamId, 'position' => $index + 1, 'player_id' => $playerId]);
}
}
private function signature(int $matchId): void
{
$payload = ['match_id' => $matchId, 'signer_name' => 'Arbitro Demo', 'role' => 'principal'];
$this->db->prepare(
'INSERT INTO referee_signatures (match_id, signer_name, role, signature_hash, signed_payload)
VALUES (:match_id, "Arbitro Demo", "principal", :hash, :payload)
ON DUPLICATE KEY UPDATE signature_hash = VALUES(signature_hash), signed_payload = VALUES(signed_payload)'
)->execute(['match_id' => $matchId, 'hash' => hash('sha256', json_encode($payload)), 'payload' => json_encode($payload)]);
}
private function events(int $matchId, int $homeTeamId, int $awayTeamId): void
{
foreach ([['point', $homeTeamId, 1, 25, 21], ['timeout', $awayTeamId, 1, 18, 16], ['yellow_card', $awayTeamId, 2, 10, 9]] as [$type, $teamId, $set, $home, $away]) {
$this->db->prepare(
'INSERT INTO match_events (match_id, set_number, team_id, event_type, points_home, points_away, notes)
VALUES (:match_id, :set_number, :team_id, :event_type, :home, :away, "Demo planilla")'
)->execute(['match_id' => $matchId, 'set_number' => $set, 'team_id' => $teamId, 'event_type' => $type, 'home' => $home, 'away' => $away]);
}
}
}