2
This commit is contained in:
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Torneo;
|
||||
use App\Models\Equipo;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class FixtureService
|
||||
{
|
||||
/**
|
||||
* Genera un fixture Round-Robin para los equipos de un torneo.
|
||||
*
|
||||
* @param Torneo $torneo
|
||||
* @param string $fechaInicio 'Y-m-d'
|
||||
* @param int $diasEntreJornadas
|
||||
* @param string $sedeDefault
|
||||
* @param bool $dobleRueda Si true, genera ida y vuelta
|
||||
* @return array Array de arrays con los datos de cada evento a crear
|
||||
*/
|
||||
public function generarRoundRobin(
|
||||
Torneo $torneo,
|
||||
string $fechaInicio,
|
||||
int $diasEntreJornadas = 7,
|
||||
?string $sedeDefault = '',
|
||||
bool $dobleRueda = false
|
||||
): array {
|
||||
$equipos = $torneo->equipos()->get()->values()->toArray();
|
||||
$n = count($equipos);
|
||||
|
||||
if ($n < 2) {
|
||||
throw new \InvalidArgumentException('Se necesitan al menos 2 equipos para generar un fixture.');
|
||||
}
|
||||
|
||||
// Si número impar, agregar BYE
|
||||
$hayBye = false;
|
||||
if ($n % 2 !== 0) {
|
||||
$equipos[] = null; // BYE
|
||||
$n++;
|
||||
$hayBye = true;
|
||||
}
|
||||
|
||||
$mitad = $n / 2;
|
||||
$jornadas = $n - 1;
|
||||
$partidos = [];
|
||||
$fechaActual = Carbon::parse($fechaInicio);
|
||||
|
||||
// Algoritmo Round-Robin: fijar el primer equipo, rotar el resto
|
||||
$lista = range(0, $n - 1);
|
||||
|
||||
for ($jornada = 0; $jornada < $jornadas; $jornada++) {
|
||||
$jornadaPartidos = [];
|
||||
|
||||
for ($i = 0; $i < $mitad; $i++) {
|
||||
$localIdx = $lista[$i];
|
||||
$visitanteIdx= $lista[$n - 1 - $i];
|
||||
|
||||
// Si alguno es BYE (null), saltar
|
||||
if ($equipos[$localIdx] === null || $equipos[$visitanteIdx] === null) continue;
|
||||
|
||||
$local = $equipos[$localIdx];
|
||||
$visitante = $equipos[$visitanteIdx];
|
||||
|
||||
// Alternar localía: en jornadas pares, invertir
|
||||
if ($jornada % 2 === 1) {
|
||||
[$local, $visitante] = [$visitante, $local];
|
||||
}
|
||||
|
||||
$jornadaPartidos[] = [
|
||||
'id_equipo_local' => $local['id_equipo'],
|
||||
'id_equipo_visitante' => $visitante['id_equipo'],
|
||||
'fecha_evento' => $fechaActual->format('Y-m-d'),
|
||||
'hora_inicio' => '20:00:00',
|
||||
'hora_fin' => '22:00:00',
|
||||
'sede' => $sedeDefault,
|
||||
'id_torneo' => $torneo->id,
|
||||
'nombre_evento' => null, // se genera automáticamente
|
||||
'precio' => 0,
|
||||
'jornada' => $jornada + 1,
|
||||
];
|
||||
}
|
||||
|
||||
$partidos = array_merge($partidos, $jornadaPartidos);
|
||||
$fechaActual->addDays($diasEntreJornadas);
|
||||
|
||||
// Rotar la lista (el primer elemento fijo)
|
||||
$rotatable = array_slice($lista, 1);
|
||||
array_push($rotatable, array_shift($rotatable));
|
||||
$lista = array_merge([$lista[0]], $rotatable);
|
||||
}
|
||||
|
||||
// Doble rueda: agregar vuelta con localías invertidas
|
||||
if ($dobleRueda && !empty($partidos)) {
|
||||
$vuelta = [];
|
||||
foreach ($partidos as $p) {
|
||||
$vuelta[] = array_merge($p, [
|
||||
'id_equipo_local' => $p['id_equipo_visitante'],
|
||||
'id_equipo_visitante' => $p['id_equipo_local'],
|
||||
'fecha_evento' => Carbon::parse($p['fecha_evento'])->addDays($jornadas * $diasEntreJornadas)->format('Y-m-d'),
|
||||
'jornada' => $p['jornada'] + $jornadas,
|
||||
]);
|
||||
}
|
||||
$partidos = array_merge($partidos, $vuelta);
|
||||
}
|
||||
|
||||
return $partidos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Persiste el fixture generado como Evento records en la DB.
|
||||
*/
|
||||
public function persistirFixture(array $partidos, Torneo $torneo): int
|
||||
{
|
||||
$contador = 0;
|
||||
foreach ($partidos as $p) {
|
||||
$local = Equipo::with('club')->find($p['id_equipo_local']);
|
||||
$visitante = Equipo::with('club')->find($p['id_equipo_visitante']);
|
||||
|
||||
$nombreEvento = ($local->club->nombre ?? '?') . ' vs ' . ($visitante->club->nombre ?? '?');
|
||||
|
||||
\App\Models\Evento::create([
|
||||
'id_evento' => uniqid('ev_'),
|
||||
'nombre_evento' => $nombreEvento,
|
||||
'id_equipo_local' => $p['id_equipo_local'],
|
||||
'id_equipo_visitante' => $p['id_equipo_visitante'],
|
||||
'fecha_evento' => $p['fecha_evento'],
|
||||
'hora_inicio' => $p['hora_inicio'],
|
||||
'hora_fin' => $p['hora_fin'],
|
||||
'sede' => $p['sede'] ?: null,
|
||||
'id_torneo' => $torneo->id,
|
||||
'precio' => $p['precio'] ?? 0,
|
||||
]);
|
||||
|
||||
$contador++;
|
||||
}
|
||||
return $contador;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user