resolveForMatch($matchId); if (!$templateRow) { $template = require __DIR__ . '/../../config/templates/ltv26_scoresheet.php'; } else { $template = json_decode($templateRow['config_json'], true); $template = is_array($template) ? $template : []; $template['image'] = $templateRow['image_path']; $template['width'] = (int) $templateRow['page_width']; $template['height'] = (int) $templateRow['page_height']; } $match = $this->match($db, $matchId); $sets = $this->rows($db, 'SELECT * FROM match_sets WHERE match_id = :id ORDER BY set_number', $matchId); $homePlayers = $this->players($db, (int) $match['home_team_id']); $awayPlayers = $this->players($db, (int) $match['away_team_id']); $signatures = $this->rows($db, 'SELECT * FROM referee_signatures WHERE match_id = :id ORDER BY signed_at DESC', $matchId); header('Content-Type: text/html; charset=utf-8'); header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0'); if ($templateRow) { $payload = json_encode(['match_id' => $matchId, 'template_id' => $templateRow['id'], 'time' => time()]); $db->prepare( 'INSERT INTO match_sheet_exports (match_id, sheet_template_id, export_type, export_hash) VALUES (:match_id, :sheet_template_id, "html", :export_hash)' )->execute([ 'match_id' => $matchId, 'sheet_template_id' => $templateRow['id'], 'export_hash' => hash('sha256', $payload), ]); } echo $this->html($template, $match, $sets, $homePlayers, $awayPlayers, $signatures); } private function html(array $template, array $match, array $sets, array $homePlayers, array $awayPlayers, array $signatures): string { $fields = [ 'tournament' => $match['tournament_name'], 'match_code' => '#' . $match['id'], 'date' => $match['scheduled_at'] ? date('d/m/Y', strtotime($match['scheduled_at'])) : '', 'time' => $match['scheduled_at'] ? date('H:i', strtotime($match['scheduled_at'])) : '', 'court' => $match['court_name'] ?? '', 'home_team' => $match['home_team'], 'away_team' => $match['away_team'], 'home_sets' => (string) $match['home_sets'], 'away_sets' => (string) $match['away_sets'], 'referee_signature' => $signatures[0]['signer_name'] ?? '', ]; $items = []; foreach ($fields as $key => $value) { if (isset($template['fields'][$key])) { $items[] = $this->box($template, $template['fields'][$key], $value); } } foreach ($sets as $index => $set) { if (!isset($template['result_rows'][$index], $template['result_columns'])) { continue; } $row = $template['result_rows'][$index]; $cols = $template['result_columns']; $items[] = $this->box($template, ['x' => $cols['home_pt']['x'], 'y' => $row['y'], 'w' => $cols['home_pt']['w'], 'size' => 11, 'align' => 'center'], (string) $set['home_points']); $items[] = $this->box($template, ['x' => $cols['set']['x'], 'y' => $row['y'], 'w' => $cols['set']['w'], 'size' => 11, 'align' => 'center'], $set['home_points'] . ' - ' . $set['away_points']); $items[] = $this->box($template, ['x' => $cols['away_pt']['x'], 'y' => $row['y'], 'w' => $cols['away_pt']['w'], 'size' => 11, 'align' => 'center'], (string) $set['away_points']); } if (!empty($template['home_players'])) { $items = array_merge($items, $this->playerBoxes($template, $template['home_players'], $homePlayers)); } if (!empty($template['away_players'])) { $items = array_merge($items, $this->playerBoxes($template, $template['away_players'], $awayPlayers)); } $image = htmlspecialchars($template['image'], ENT_QUOTES); return 'Planilla LTV 26' . '' . '
' . 'Planilla' . implode('', $items) . '
'; } private function box(array $template, array $box, string $value): string { $align = $box['align'] ?? 'left'; $valign = $box['valign'] ?? 'top'; $translate = match ($valign) { 'middle' => 'translateY(-50%)', 'bottom' => 'translateY(-100%)', default => 'none', }; $style = sprintf( 'left:%s%%;top:%s%%;width:%s%%;font-size:%spx;text-align:%s;transform:%s', ($box['x'] / $template['width']) * 100, ($box['y'] / $template['height']) * 100, ($box['w'] / $template['width']) * 100, $box['size'], $align, $translate ); return '' . htmlspecialchars($value) . ''; } private function playerBoxes(array $template, array $config, array $players): array { foreach (['x', 'y', 'row_h', 'number_w', 'name_w', 'size'] as $required) { if (!isset($config[$required])) { return []; } } $items = []; foreach (array_slice($players, 0, 14) as $index => $player) { $y = $config['y'] + ($index * $config['row_h']); $items[] = $this->box($template, ['x' => $config['x'], 'y' => $y, 'w' => $config['number_w'], 'size' => $config['size'], 'align' => 'center'], (string) ($player['jersey_number'] ?? '')); $items[] = $this->box($template, ['x' => $config['x'] + $config['number_w'], 'y' => $y, 'w' => $config['name_w'], 'size' => $config['size']], $player['first_name'] . ' ' . $player['last_name']); } return $items; } private function match(\PDO $db, int $matchId): array { $stmt = $db->prepare( 'SELECT m.*, tr.name tournament_name, ht.name home_team, at.name away_team, c.name court_name FROM matches m JOIN tournaments tr ON tr.id = m.tournament_id JOIN teams ht ON ht.id = m.home_team_id JOIN teams at ON at.id = m.away_team_id LEFT JOIN courts c ON c.id = m.court_id WHERE m.id = :id' ); $stmt->execute(['id' => $matchId]); return $stmt->fetch() ?: []; } private function players(\PDO $db, int $teamId): array { $stmt = $db->prepare('SELECT * FROM players WHERE team_id = :id ORDER BY jersey_number, last_name'); $stmt->execute(['id' => $teamId]); return $stmt->fetchAll(); } private function rows(\PDO $db, string $sql, int $matchId): array { $stmt = $db->prepare($sql); $stmt->execute(['id' => $matchId]); return $stmt->fetchAll(); } }