matamata 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- matamata-0.0.1/.github/workflows/ci.yml +28 -0
- matamata-0.0.1/.gitignore +47 -0
- matamata-0.0.1/.pylintrc +15 -0
- matamata-0.0.1/LICENSE +21 -0
- matamata-0.0.1/PKG-INFO +149 -0
- matamata-0.0.1/README.md +126 -0
- matamata-0.0.1/docs/apply-after.json +57 -0
- matamata-0.0.1/docs/apply-after.png +0 -0
- matamata-0.0.1/docs/apply-before.json +41 -0
- matamata-0.0.1/docs/apply-before.png +0 -0
- matamata-0.0.1/docs/copa-rio-de-la-plata.png +0 -0
- matamata-0.0.1/docs/facup-drawn.png +0 -0
- matamata-0.0.1/docs/facup-pending-draw.png +0 -0
- matamata-0.0.1/docs/flags.png +0 -0
- matamata-0.0.1/docs/format.md +194 -0
- matamata-0.0.1/docs/index.md +417 -0
- matamata-0.0.1/docs/knockout-8-table.png +0 -0
- matamata-0.0.1/docs/knockout-8.png +0 -0
- matamata-0.0.1/docs/libertadores-2026.png +0 -0
- matamata-0.0.1/docs/schema.json +89 -0
- matamata-0.0.1/examples/copa-rio-de-la-plata-2026.json +63 -0
- matamata-0.0.1/examples/copa_rio_host.py +61 -0
- matamata-0.0.1/examples/crest_data.json +6 -0
- matamata-0.0.1/examples/crests/athletic.png +0 -0
- matamata-0.0.1/examples/crests/estudiantes.svg +38 -0
- matamata-0.0.1/examples/crests/internacional.svg +112 -0
- matamata-0.0.1/examples/crests/platense.svg +68 -0
- matamata-0.0.1/examples/example_data.json +4 -0
- matamata-0.0.1/examples/facup-drawn.json +65 -0
- matamata-0.0.1/examples/facup-pending-draw.json +52 -0
- matamata-0.0.1/examples/knockout-8.json +68 -0
- matamata-0.0.1/examples/libertadores-2026.json +112 -0
- matamata-0.0.1/examples/libertadores_host.py +50 -0
- matamata-0.0.1/lint.sh +16 -0
- matamata-0.0.1/mkdocs.yml +14 -0
- matamata-0.0.1/pyproject.toml +38 -0
- matamata-0.0.1/src/matamata/__init__.py +22 -0
- matamata-0.0.1/src/matamata/__main__.py +66 -0
- matamata-0.0.1/src/matamata/diagram.py +302 -0
- matamata-0.0.1/src/matamata/layout.py +154 -0
- matamata-0.0.1/src/matamata/model.py +181 -0
- matamata-0.0.1/src/matamata/parse.py +196 -0
- matamata-0.0.1/src/matamata/render.py +127 -0
- matamata-0.0.1/src/matamata/render_html.py +70 -0
- matamata-0.0.1/tests/conftest.py +29 -0
- matamata-0.0.1/tests/golden/facup-drawn.html +109 -0
- matamata-0.0.1/tests/golden/facup-drawn.svg +85 -0
- matamata-0.0.1/tests/golden/facup-pending-draw.html +109 -0
- matamata-0.0.1/tests/golden/facup-pending-draw.svg +83 -0
- matamata-0.0.1/tests/golden/knockout-8.html +109 -0
- matamata-0.0.1/tests/golden/knockout-8.svg +87 -0
- matamata-0.0.1/tests/golden/libertadores-2026.html +109 -0
- matamata-0.0.1/tests/golden/libertadores-2026.svg +95 -0
- matamata-0.0.1/tests/test_apply.py +255 -0
- matamata-0.0.1/tests/test_model.py +526 -0
- matamata-0.0.1/tests/test_render.py +151 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v4
|
|
18
|
+
|
|
19
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
20
|
+
uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
|
|
24
|
+
- name: Install
|
|
25
|
+
run: pip install -e ".[dev]"
|
|
26
|
+
|
|
27
|
+
- name: Run tests
|
|
28
|
+
run: pytest -q
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Byte-compiled / optimized files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.eggs/
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# Test / tooling caches
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.ruff_cache/
|
|
20
|
+
.mypy_cache/
|
|
21
|
+
.coverage
|
|
22
|
+
htmlcov/
|
|
23
|
+
|
|
24
|
+
# Editor / OS
|
|
25
|
+
.idea/
|
|
26
|
+
.vscode/
|
|
27
|
+
*.swp
|
|
28
|
+
.DS_Store
|
|
29
|
+
|
|
30
|
+
# Generated diagrams: ignore stray renders, but keep the curated docs images
|
|
31
|
+
# (used by the README), the versioned test goldens, and the example crest assets.
|
|
32
|
+
*.svg
|
|
33
|
+
*.png
|
|
34
|
+
!docs/*.png
|
|
35
|
+
!tests/golden/*.svg
|
|
36
|
+
!examples/crests/*.svg
|
|
37
|
+
!examples/crests/*.png
|
|
38
|
+
|
|
39
|
+
# MkDocs build output (`mkdocs serve` / `mkdocs build`)
|
|
40
|
+
/site/
|
|
41
|
+
|
|
42
|
+
# Local, unversioned scratch space (personal notes, drafts — never committed)
|
|
43
|
+
/.local/
|
|
44
|
+
|
|
45
|
+
# Agent guidance and settings: machine- and workflow-specific, kept local only
|
|
46
|
+
/CLAUDE.md
|
|
47
|
+
/.claude/
|
matamata-0.0.1/.pylintrc
ADDED
matamata-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Aníbal Pacheco
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
matamata-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: matamata
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Model tournament knockout stages in JSON format and render the schedule in SVG or html table format
|
|
5
|
+
License: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
8
|
+
Classifier: Operating System :: OS Independent
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: jsonschema; extra == 'dev'
|
|
14
|
+
Requires-Dist: mkdocs; extra == 'dev'
|
|
15
|
+
Requires-Dist: pytest; extra == 'dev'
|
|
16
|
+
Provides-Extra: lint
|
|
17
|
+
Requires-Dist: black; extra == 'lint'
|
|
18
|
+
Requires-Dist: isort; extra == 'lint'
|
|
19
|
+
Requires-Dist: mypy; extra == 'lint'
|
|
20
|
+
Requires-Dist: pylint; extra == 'lint'
|
|
21
|
+
Requires-Dist: types-jsonschema; extra == 'lint'
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# matamata
|
|
25
|
+
|
|
26
|
+
[](https://github.com/anibalpacheco/matamata/actions/workflows/ci.yml)
|
|
27
|
+
[](LICENSE)
|
|
28
|
+
|
|
29
|
+
Model a **tournament knockout stage** in a small **JSON "language"** and render
|
|
30
|
+
the schedule in **SVG** or **HTML table** format.
|
|
31
|
+
|
|
32
|
+
**matamata** also lets a host system map documents representing championship
|
|
33
|
+
knockout stages onto its own business objects (e.g. a Championship or Cup entity) and persist
|
|
34
|
+
them apart from any presentation concern — updating results means editing a document,
|
|
35
|
+
never the code.
|
|
36
|
+
|
|
37
|
+
Example rendered from
|
|
38
|
+
[`examples/libertadores-2026.json`](examples/libertadores-2026.json):
|
|
39
|
+
|
|
40
|
+

|
|
41
|
+
|
|
42
|
+
## Quickstart
|
|
43
|
+
|
|
44
|
+
Requires Python ≥ 3.10. No runtime dependencies.
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
git clone https://github.com/anibalpacheco/matamata.git
|
|
48
|
+
cd matamata
|
|
49
|
+
python -m venv .venv && source .venv/bin/activate
|
|
50
|
+
pip install -e .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Render a self-contained example to an SVG file:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# via the installed command
|
|
57
|
+
matamata examples/knockout-8.json -o knockout.svg
|
|
58
|
+
|
|
59
|
+
# or via the module, writing to stdout
|
|
60
|
+
python -m matamata examples/knockout-8.json > knockout.svg
|
|
61
|
+
|
|
62
|
+
# or as an HTML table, the layout for small screens
|
|
63
|
+
matamata examples/knockout-8.json -o knockout.html
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Open the resulting file in a browser to view the schedule. To render your own cup,
|
|
67
|
+
point the command at any JSON file that follows [`docs/format.md`](docs/format.md).
|
|
68
|
+
|
|
69
|
+
Use it from Python:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from matamata import load_stage, render_svg
|
|
73
|
+
|
|
74
|
+
svg = render_svg(load_stage("examples/knockout-8.json"))
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
To use it in your own project instead, install straight from GitHub:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install git+https://github.com/anibalpacheco/matamata.git
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Examples
|
|
84
|
+
|
|
85
|
+
Both examples are rendered from the JSON files in [`examples/`](examples/).
|
|
86
|
+
|
|
87
|
+
The Copa Libertadores example above shows two-legged ties — each leg's goals are
|
|
88
|
+
shown, shootouts appear in parentheses, and the winner of each tie is emphasized. The
|
|
89
|
+
first quarterfinal is **host-resolved**: its legs carry only a `ref`, so its teams and
|
|
90
|
+
scores come from `get_match` (see
|
|
91
|
+
[`examples/libertadores_host.py`](examples/libertadores_host.py)) rather than from the
|
|
92
|
+
document. Played ties take their team names from the legs; the final is a single match —
|
|
93
|
+
one leg, so just one goal figure per side — with its `winnerof` links wiring the
|
|
94
|
+
advancement tree.
|
|
95
|
+
|
|
96
|
+
Single matches ([`knockout-8.json`](examples/knockout-8.json)) — one goal figure per
|
|
97
|
+
side, with shootouts in parentheses. Sides that have not been resolved yet fall back to
|
|
98
|
+
placeholders such as "Winner SF2":
|
|
99
|
+
|
|
100
|
+

|
|
101
|
+
|
|
102
|
+
## The format
|
|
103
|
+
|
|
104
|
+
The document is plain JSON, so any system can store and exchange it natively, and the
|
|
105
|
+
language is designed so a match can evolve from a **placeholder** (e.g. "winner
|
|
106
|
+
of QF1") into a **reference to a real match entity** — each leg can carry a `ref` to
|
|
107
|
+
the real game, resolved dynamically by the host — without changing the language. The
|
|
108
|
+
advancement tree is laid out **deterministically**: coordinates are
|
|
109
|
+
computed directly and the SVG is emitted as a string, with no layout engine and no
|
|
110
|
+
heavy dependencies.
|
|
111
|
+
|
|
112
|
+
See [`docs/format.md`](docs/format.md) for the full specification and
|
|
113
|
+
[`docs/schema.json`](docs/schema.json) for the JSON Schema. Worked examples live in
|
|
114
|
+
[`examples/`](examples/).
|
|
115
|
+
|
|
116
|
+
Minimal example:
|
|
117
|
+
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"tournament": "Copa Libertadores",
|
|
121
|
+
"season": "2026",
|
|
122
|
+
"rounds": [
|
|
123
|
+
{
|
|
124
|
+
"name": "Final",
|
|
125
|
+
"matches": [
|
|
126
|
+
{
|
|
127
|
+
"id": "final",
|
|
128
|
+
"legs": [
|
|
129
|
+
{ "team1": "Flamengo", "goals1": 1, "team2": "Nacional", "goals2": 2 }
|
|
130
|
+
],
|
|
131
|
+
"winner": 2
|
|
132
|
+
}
|
|
133
|
+
]
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Documentation
|
|
140
|
+
|
|
141
|
+
[docs/index.md](docs/index.md) is the manual: rendering from the CLI and from Python
|
|
142
|
+
(e.g. a Django view), feeding live data from your own database through
|
|
143
|
+
`KnockoutStage`, updating the stored document with `apply_results` — including a
|
|
144
|
+
before/after walkthrough of one call — and running the test suite.
|
|
145
|
+
|
|
146
|
+
## Status
|
|
147
|
+
|
|
148
|
+
Working: the language spec, JSON Schema, Python renderer, CLI and tests are in place,
|
|
149
|
+
and the package is installable from GitHub.
|
matamata-0.0.1/README.md
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# matamata
|
|
2
|
+
|
|
3
|
+
[](https://github.com/anibalpacheco/matamata/actions/workflows/ci.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
Model a **tournament knockout stage** in a small **JSON "language"** and render
|
|
7
|
+
the schedule in **SVG** or **HTML table** format.
|
|
8
|
+
|
|
9
|
+
**matamata** also lets a host system map documents representing championship
|
|
10
|
+
knockout stages onto its own business objects (e.g. a Championship or Cup entity) and persist
|
|
11
|
+
them apart from any presentation concern — updating results means editing a document,
|
|
12
|
+
never the code.
|
|
13
|
+
|
|
14
|
+
Example rendered from
|
|
15
|
+
[`examples/libertadores-2026.json`](examples/libertadores-2026.json):
|
|
16
|
+
|
|
17
|
+

|
|
18
|
+
|
|
19
|
+
## Quickstart
|
|
20
|
+
|
|
21
|
+
Requires Python ≥ 3.10. No runtime dependencies.
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://github.com/anibalpacheco/matamata.git
|
|
25
|
+
cd matamata
|
|
26
|
+
python -m venv .venv && source .venv/bin/activate
|
|
27
|
+
pip install -e .
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Render a self-contained example to an SVG file:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# via the installed command
|
|
34
|
+
matamata examples/knockout-8.json -o knockout.svg
|
|
35
|
+
|
|
36
|
+
# or via the module, writing to stdout
|
|
37
|
+
python -m matamata examples/knockout-8.json > knockout.svg
|
|
38
|
+
|
|
39
|
+
# or as an HTML table, the layout for small screens
|
|
40
|
+
matamata examples/knockout-8.json -o knockout.html
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Open the resulting file in a browser to view the schedule. To render your own cup,
|
|
44
|
+
point the command at any JSON file that follows [`docs/format.md`](docs/format.md).
|
|
45
|
+
|
|
46
|
+
Use it from Python:
|
|
47
|
+
|
|
48
|
+
```python
|
|
49
|
+
from matamata import load_stage, render_svg
|
|
50
|
+
|
|
51
|
+
svg = render_svg(load_stage("examples/knockout-8.json"))
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
To use it in your own project instead, install straight from GitHub:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install git+https://github.com/anibalpacheco/matamata.git
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
Both examples are rendered from the JSON files in [`examples/`](examples/).
|
|
63
|
+
|
|
64
|
+
The Copa Libertadores example above shows two-legged ties — each leg's goals are
|
|
65
|
+
shown, shootouts appear in parentheses, and the winner of each tie is emphasized. The
|
|
66
|
+
first quarterfinal is **host-resolved**: its legs carry only a `ref`, so its teams and
|
|
67
|
+
scores come from `get_match` (see
|
|
68
|
+
[`examples/libertadores_host.py`](examples/libertadores_host.py)) rather than from the
|
|
69
|
+
document. Played ties take their team names from the legs; the final is a single match —
|
|
70
|
+
one leg, so just one goal figure per side — with its `winnerof` links wiring the
|
|
71
|
+
advancement tree.
|
|
72
|
+
|
|
73
|
+
Single matches ([`knockout-8.json`](examples/knockout-8.json)) — one goal figure per
|
|
74
|
+
side, with shootouts in parentheses. Sides that have not been resolved yet fall back to
|
|
75
|
+
placeholders such as "Winner SF2":
|
|
76
|
+
|
|
77
|
+

|
|
78
|
+
|
|
79
|
+
## The format
|
|
80
|
+
|
|
81
|
+
The document is plain JSON, so any system can store and exchange it natively, and the
|
|
82
|
+
language is designed so a match can evolve from a **placeholder** (e.g. "winner
|
|
83
|
+
of QF1") into a **reference to a real match entity** — each leg can carry a `ref` to
|
|
84
|
+
the real game, resolved dynamically by the host — without changing the language. The
|
|
85
|
+
advancement tree is laid out **deterministically**: coordinates are
|
|
86
|
+
computed directly and the SVG is emitted as a string, with no layout engine and no
|
|
87
|
+
heavy dependencies.
|
|
88
|
+
|
|
89
|
+
See [`docs/format.md`](docs/format.md) for the full specification and
|
|
90
|
+
[`docs/schema.json`](docs/schema.json) for the JSON Schema. Worked examples live in
|
|
91
|
+
[`examples/`](examples/).
|
|
92
|
+
|
|
93
|
+
Minimal example:
|
|
94
|
+
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"tournament": "Copa Libertadores",
|
|
98
|
+
"season": "2026",
|
|
99
|
+
"rounds": [
|
|
100
|
+
{
|
|
101
|
+
"name": "Final",
|
|
102
|
+
"matches": [
|
|
103
|
+
{
|
|
104
|
+
"id": "final",
|
|
105
|
+
"legs": [
|
|
106
|
+
{ "team1": "Flamengo", "goals1": 1, "team2": "Nacional", "goals2": 2 }
|
|
107
|
+
],
|
|
108
|
+
"winner": 2
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Documentation
|
|
117
|
+
|
|
118
|
+
[docs/index.md](docs/index.md) is the manual: rendering from the CLI and from Python
|
|
119
|
+
(e.g. a Django view), feeding live data from your own database through
|
|
120
|
+
`KnockoutStage`, updating the stored document with `apply_results` — including a
|
|
121
|
+
before/after walkthrough of one call — and running the test suite.
|
|
122
|
+
|
|
123
|
+
## Status
|
|
124
|
+
|
|
125
|
+
Working: the language spec, JSON Schema, Python renderer, CLI and tests are in place,
|
|
126
|
+
and the package is installable from GitHub.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tournament": "Champions League",
|
|
3
|
+
"season": "2025/26",
|
|
4
|
+
"rounds": [
|
|
5
|
+
{
|
|
6
|
+
"name": "Semifinals",
|
|
7
|
+
"matches": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sf1",
|
|
10
|
+
"team1": "Real Madrid",
|
|
11
|
+
"team2": "Barcelona",
|
|
12
|
+
"legs": [
|
|
13
|
+
{
|
|
14
|
+
"goals1": 1,
|
|
15
|
+
"goals2": 0
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"goals1": 0,
|
|
19
|
+
"goals2": 1,
|
|
20
|
+
"pen1": 4,
|
|
21
|
+
"pen2": 2
|
|
22
|
+
}
|
|
23
|
+
],
|
|
24
|
+
"winner": 1
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"id": "sf2",
|
|
28
|
+
"team1": "Bayern München",
|
|
29
|
+
"team2": "Manchester City",
|
|
30
|
+
"winner": 2,
|
|
31
|
+
"legs": [
|
|
32
|
+
{
|
|
33
|
+
"goals1": 0,
|
|
34
|
+
"goals2": 2
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"goals1": 1,
|
|
38
|
+
"goals2": 1
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"name": "Final",
|
|
46
|
+
"matches": [
|
|
47
|
+
{
|
|
48
|
+
"id": "f",
|
|
49
|
+
"winnerof1": "sf1",
|
|
50
|
+
"winnerof2": "sf2",
|
|
51
|
+
"team2": "Manchester City",
|
|
52
|
+
"team1": "Real Madrid"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tournament": "Champions League",
|
|
3
|
+
"season": "2025/26",
|
|
4
|
+
"rounds": [
|
|
5
|
+
{
|
|
6
|
+
"name": "Semifinals",
|
|
7
|
+
"matches": [
|
|
8
|
+
{
|
|
9
|
+
"id": "sf1",
|
|
10
|
+
"team1": "Real Madrid",
|
|
11
|
+
"team2": "Barcelona",
|
|
12
|
+
"legs": [
|
|
13
|
+
{ "goals1": 1, "goals2": 0 },
|
|
14
|
+
{}
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": "sf2",
|
|
19
|
+
"team1": "Bayern München",
|
|
20
|
+
"team2": "Manchester City",
|
|
21
|
+
"winner": 2,
|
|
22
|
+
"legs": [
|
|
23
|
+
{ "goals1": 0, "goals2": 2 },
|
|
24
|
+
{ "goals1": 1, "goals2": 1 }
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "Final",
|
|
31
|
+
"matches": [
|
|
32
|
+
{
|
|
33
|
+
"id": "f",
|
|
34
|
+
"winnerof1": "sf1",
|
|
35
|
+
"winnerof2": "sf2",
|
|
36
|
+
"team2": "Manchester City"
|
|
37
|
+
}
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|