150 lines
5.3 KiB
PHP
150 lines
5.3 KiB
PHP
<?php
|
|
|
|
namespace App\Services;
|
|
|
|
use App\Models\Torneo;
|
|
use App\Models\Evento;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class TournamentService
|
|
{
|
|
/**
|
|
* Calcula la tabla de posiciones de un torneo.
|
|
*
|
|
* @param int $idTorneo
|
|
* @param bool $onlyRegular Si true, solo toma partidos de fase regular
|
|
* @return array
|
|
*/
|
|
public function getStandings(int $idTorneo, bool $onlyRegular = true): array
|
|
{
|
|
$torneo = Torneo::with('equipos.club')->findOrFail($idTorneo);
|
|
$stats = [];
|
|
|
|
foreach ($torneo->equipos as $equipo) {
|
|
$groupName = $equipo->pivot->grupo ?: ($equipo->categoria . ' ' . $equipo->division);
|
|
|
|
$stats[$groupName][$equipo->id_equipo] = [
|
|
'id' => $equipo->id_equipo,
|
|
'nombre' => $equipo->club->nombre ?? 'Equipo',
|
|
'logo' => $equipo->club->imagen ?? null,
|
|
'categoria' => $equipo->categoria,
|
|
'pj' => 0,
|
|
'pg' => 0,
|
|
'pp' => 0,
|
|
'tf' => 0,
|
|
'tc' => 0,
|
|
'pts' => 0,
|
|
];
|
|
}
|
|
|
|
$query = Evento::where('id_torneo', $idTorneo)
|
|
->whereNotNull('marcador_local')
|
|
->whereNotNull('marcador_visitante');
|
|
|
|
if ($onlyRegular) {
|
|
$query->where('fase', Evento::FASE_REGULAR);
|
|
}
|
|
|
|
$matches = $query->get();
|
|
|
|
foreach ($matches as $m) {
|
|
$localGroup = null;
|
|
$visitGroup = null;
|
|
|
|
foreach ($stats as $group => $teams) {
|
|
if (isset($teams[$m->id_equipo_local])) $localGroup = $group;
|
|
if (isset($teams[$m->id_equipo_visitante])) $visitGroup = $group;
|
|
}
|
|
|
|
if (!$localGroup || !$visitGroup) continue;
|
|
|
|
$stats[$localGroup][$m->id_equipo_local]['pj']++;
|
|
$stats[$localGroup][$m->id_equipo_local]['tf'] += $m->marcador_local;
|
|
$stats[$localGroup][$m->id_equipo_local]['tc'] += $m->marcador_visitante;
|
|
|
|
$stats[$visitGroup][$m->id_equipo_visitante]['pj']++;
|
|
$stats[$visitGroup][$m->id_equipo_visitante]['tf'] += $m->marcador_visitante;
|
|
$stats[$visitGroup][$m->id_equipo_visitante]['tc'] += $m->marcador_local;
|
|
|
|
if ($m->marcador_local > $m->marcador_visitante) {
|
|
$stats[$localGroup][$m->id_equipo_local]['pg']++;
|
|
$stats[$localGroup][$m->id_equipo_local]['pts'] += 2;
|
|
$stats[$visitGroup][$m->id_equipo_visitante]['pp']++;
|
|
$stats[$visitGroup][$m->id_equipo_visitante]['pts'] += 1;
|
|
} elseif ($m->marcador_visitante > $m->marcador_local) {
|
|
$stats[$visitGroup][$m->id_equipo_visitante]['pg']++;
|
|
$stats[$visitGroup][$m->id_equipo_visitante]['pts'] += 2;
|
|
$stats[$localGroup][$m->id_equipo_local]['pp']++;
|
|
$stats[$localGroup][$m->id_equipo_local]['pts'] += 1;
|
|
} else {
|
|
$stats[$localGroup][$m->id_equipo_local]['pts'] += 1;
|
|
$stats[$visitGroup][$m->id_equipo_visitante]['pts'] += 1;
|
|
}
|
|
}
|
|
|
|
foreach ($stats as $group => &$teams) {
|
|
usort($teams, function($a, $b) {
|
|
if ($b['pts'] !== $a['pts']) return $b['pts'] - $a['pts'];
|
|
$diffA = $a['tf'] - $a['tc'];
|
|
$diffB = $b['tf'] - $b['tc'];
|
|
if ($diffB !== $diffA) return $diffB - $diffA;
|
|
return $b['tf'] - $a['tf'];
|
|
});
|
|
}
|
|
|
|
return $stats;
|
|
}
|
|
|
|
public function getPlayoffBrackets(int $idTorneo): array
|
|
{
|
|
$playoffs = Evento::where('id_torneo', $idTorneo)
|
|
->where('fase', '>', Evento::FASE_REGULAR)
|
|
->with(['equipoLocal.club', 'equipoVisitante.club'])
|
|
->orderBy('fase')
|
|
->orderBy('numero_partido_bracket')
|
|
->orderBy('fecha_evento')
|
|
->get();
|
|
|
|
$bracket = [
|
|
Evento::FASE_CUARTOS => collect(),
|
|
Evento::FASE_SEMIS => collect(),
|
|
Evento::FASE_FINAL => collect(),
|
|
];
|
|
|
|
// Agrupar por fase y número de llave (bracket)
|
|
$grouped = $playoffs->groupBy(function($item) {
|
|
return $item->fase . '-' . $item->numero_partido_bracket;
|
|
});
|
|
|
|
foreach ($grouped as $key => $matches) {
|
|
$first = $matches->first();
|
|
$fase = $first->fase;
|
|
$nro = $first->numero_partido_bracket;
|
|
|
|
$winsLocal = 0;
|
|
$winsVisit = 0;
|
|
$finished = 0;
|
|
|
|
foreach ($matches as $m) {
|
|
if ($m->marcador_local !== null && $m->marcador_visitante !== null) {
|
|
$finished++;
|
|
if ($m->marcador_local > $m->marcador_visitante) $winsLocal++;
|
|
elseif ($m->marcador_visitante > $m->marcador_local) $winsVisit++;
|
|
}
|
|
}
|
|
|
|
$bracket[$fase][$nro] = [
|
|
'matches' => $matches,
|
|
'wins_local' => $winsLocal,
|
|
'wins_visitante' => $winsVisit,
|
|
'total_partidos' => $matches->count(),
|
|
'terminados' => $finished,
|
|
'equipo_local' => $first->equipoLocal,
|
|
'equipo_visitante' => $first->equipoVisitante,
|
|
];
|
|
}
|
|
|
|
return $bracket;
|
|
}
|
|
}
|