Files
MyClub/scripts/manual_facr_templates.py
T
Tomas Dvorak dfc079288f hot fix #1
2026-01-26 08:13:18 +01:00

201 lines
6.5 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import argparse
import json
from pathlib import Path
from typing import List, Dict
from openpyxl import Workbook
from openpyxl.styles import Font
from openpyxl.utils import get_column_letter
MATCH_FIELDS: List[Dict[str, str]] = [
{
"name": "competition_code",
"label": "Kód soutěže",
"help": "Např. A1A. Použije se, pokud není vyplněno competition_external_id.",
},
{
"name": "competition_external_id",
"label": "External ID soutěže (UUID)",
"help": "UUID soutěže z odkazu na fotbal.cz. Má přednost před competition_code.",
},
{"name": "round", "label": "Kolo", "help": "Např. 2. kolo, 10. kolo atd."},
{
"name": "is_home",
"label": "Domácí / venku",
"help": "Hodnota home/away (nebo 1/0, true/false, yes/no).",
},
{"name": "opponent_name", "label": "Soupeř", "help": "Název soupeře."},
{
"name": "opponent_club_link",
"label": "Odkaz na klub soupeře",
"help": "URL na klub soupeře z fotbal.cz z URL se přečte UUID pro loga.",
},
{
"name": "external_match_id",
"label": "External ID zápasu (UUID)",
"help": "UUID zápasu; pokud není, vezme se UUID z match_link.",
},
{
"name": "kickoff_date",
"label": "Datum výkopu (YYYY-MM-DD)",
"help": "Datum zápasu, např. 2025-03-15.",
},
{
"name": "kickoff_time",
"label": "Čas výkopu (HH:MM)",
"help": "Čas zápasu, např. 17:00.",
},
{
"name": "score_fulltime",
"label": "Konečný stav",
"help": "Např. 2:1. Může být prázdné pro budoucí zápasy.",
},
{
"name": "score_halftime",
"label": "Poločasu",
"help": "Např. 1:0. Volitelné.",
},
{
"name": "match_link",
"label": "Odkaz na zápas",
"help": "URL na detail zápasu na is.fotbal.cz.",
},
{"name": "venue", "label": "Hřiště", "help": "Název hřiště / stadionu."},
{"name": "note", "label": "Poznámka", "help": "Libovolná poznámka k zápasu."},
]
TABLE_FIELDS: List[Dict[str, str]] = [
{
"name": "competition_code",
"label": "Kód soutěže",
"help": "Např. A1A. Použije se, pokud není vyplněno competition_external_id.",
},
{
"name": "competition_external_id",
"label": "External ID soutěže (UUID)",
"help": "UUID soutěže z odkazu na fotbal.cz. Má přednost před competition_code.",
},
{"name": "rank", "label": "Pořadí", "help": "Pozice v tabulce, např. 1."},
{"name": "team_name", "label": "Tým", "help": "Název týmu."},
{
"name": "team_club_link",
"label": "Odkaz na klub týmu",
"help": "URL na klub z fotbal.cz z URL se přečte UUID pro loga.",
},
{"name": "played", "label": "Zápasy", "help": "Počet odehraných zápasů."},
{"name": "wins", "label": "Výhry", "help": "Počet výher."},
{"name": "draws", "label": "Remízy", "help": "Počet remíz."},
{"name": "losses", "label": "Prohry", "help": "Počet proher."},
{
"name": "score",
"label": "Skóre",
"help": "Souhrnné skóre ve formátu góly:inkasované, např. 45:17.",
},
{"name": "points", "label": "Body", "help": "Počet bodů v tabulce."},
]
def _auto_width(sheet):
for column_cells in sheet.columns:
max_length = 0
column = column_cells[0].column
for cell in column_cells:
value = str(cell.value) if cell.value is not None else ""
if len(value) > max_length:
max_length = len(value)
adjusted = max(max_length + 2, 12)
sheet.column_dimensions[get_column_letter(column)].width = adjusted
def generate_workbook(output_dir: Path) -> None:
wb = Workbook()
ws_matches = wb.active
ws_matches.title = "matches"
ws_matches.append([f["name"] for f in MATCH_FIELDS])
for cell in ws_matches[1]:
cell.font = Font(bold=True)
_auto_width(ws_matches)
ws_tables = wb.create_sheet(title="tables")
ws_tables.append([f["name"] for f in TABLE_FIELDS])
for cell in ws_tables[1]:
cell.font = Font(bold=True)
_auto_width(ws_tables)
path = output_dir / "manual_facr_templates.xlsx"
wb.save(path)
def generate_forms_spec(output_dir: Path) -> None:
spec = {
"matches_form": {
"title": "Manuální zápasy (FAČR)",
"description": "Formulář pro ruční zadání zápasů ve struktuře odpovídající CSV/XLSX/JSON importu.",
"fields": [
{
"name": f["name"],
"label": f["label"],
"help_text": f["help"],
"type": "text",
"required": f["name"]
in {"competition_code", "competition_external_id", "is_home", "opponent_name"},
}
for f in MATCH_FIELDS
],
},
"tables_form": {
"title": "Manuální tabulky (FAČR)",
"description": "Formulář pro ruční zadání tabulek soutěží ve struktuře odpovídající CSV/XLSX/JSON importu.",
"fields": [
{
"name": f["name"],
"label": f["label"],
"help_text": f["help"],
"type": "text",
"required": f["name"]
in {"competition_code", "competition_external_id", "rank", "team_name"},
}
for f in TABLE_FIELDS
],
},
}
path = output_dir / "manual_facr_google_forms.json"
path.write_text(json.dumps(spec, ensure_ascii=False, indent=2), encoding="utf-8")
def main() -> None:
parser = argparse.ArgumentParser(
description=(
"Generate manual FACR Excel templates (matches/tables) and a Google Forms "
"field specification from a single schema."
)
)
parser.add_argument(
"--output-dir",
type=str,
default=None,
help=(
"Output directory for generated files. "
"Defaults to <project_root>/static/manual-facr."
),
)
args = parser.parse_args()
if args.output_dir:
output_dir = Path(args.output_dir)
else:
output_dir = Path(__file__).resolve().parents[1] / "static" / "manual-facr"
output_dir.mkdir(parents=True, exist_ok=True)
generate_workbook(output_dir)
generate_forms_spec(output_dir)
if __name__ == "__main__":
main()