Last active
July 12, 2021 13:58
-
-
Save Debilski/6381cea13341b23d6915de781274aa99 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"from dataclasses import dataclass\n", | |
"import json\n", | |
"from urllib.request import urlopen\n", | |
"from typing import Tuple" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Euro 2020/21 prediction template" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Load the data about which matches were played from this URL." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"DATA_URL = \"https://raw.githubusercontent.com/lsv/uefa-euro-2020/master/data.json\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"dict_keys(['stadiums', 'tvchannels', 'teams', 'groups', 'knockoutphases'])" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"DATA = json.loads(urlopen(DATA_URL).read())\n", | |
"DATA.keys()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Some peeking. What does that data look like?" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[{'id': 'BEL',\n", | |
" 'name': 'Belgium',\n", | |
" 'rank': 1,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇧🇪',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/6/65/Flag_of_Belgium.svg',\n", | |
" 'slackcode': ':flag-be:'}},\n", | |
" {'id': 'ITA',\n", | |
" 'name': 'Italy',\n", | |
" 'rank': 2,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇮🇹',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/en/0/03/Flag_of_Italy.svg',\n", | |
" 'slackcode': ':flag-it:'}},\n", | |
" {'id': 'ENG',\n", | |
" 'name': 'England',\n", | |
" 'rank': 3,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🏴\\U000e0067\\U000e0062\\U000e0065\\U000e006e\\U000e0067\\U000e007f',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/en/b/be/Flag_of_England.svg',\n", | |
" 'slackcode': ':flag-england:'}},\n", | |
" {'id': 'GER',\n", | |
" 'name': 'Germany',\n", | |
" 'rank': 4,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇩🇪',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/en/b/ba/Flag_of_Germany.svg',\n", | |
" 'slackcode': ':flag-de:'}},\n", | |
" {'id': 'ESP',\n", | |
" 'name': 'Spain',\n", | |
" 'rank': 5,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇪🇸',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/en/9/9a/Flag_of_Spain.svg',\n", | |
" 'slackcode': ':flag-es:'}},\n", | |
" {'id': 'UKR',\n", | |
" 'name': 'Ukraine',\n", | |
" 'rank': 6,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇺🇦',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/4/49/Flag_of_Ukraine.svg',\n", | |
" 'slackcode': ':flag-ua:'}},\n", | |
" {'id': 'FRA',\n", | |
" 'name': 'France',\n", | |
" 'rank': 7,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇫🇷',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/en/c/c3/Flag_of_France.svg',\n", | |
" 'slackcode': ':flag-fr:'}},\n", | |
" {'id': 'POL',\n", | |
" 'name': 'Poland',\n", | |
" 'rank': 8,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇵🇱',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/en/1/12/Flag_of_Poland.svg',\n", | |
" 'slackcode': ':flag-pl:'}},\n", | |
" {'id': 'SUI',\n", | |
" 'name': 'Switzerland',\n", | |
" 'rank': 9,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇨🇭',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/f/f3/Flag_of_Switzerland.svg',\n", | |
" 'slackcode': ':flag-ch:'}},\n", | |
" {'id': 'CRO',\n", | |
" 'name': 'Croatia',\n", | |
" 'rank': 10,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇭🇷',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/1/1b/Flag_of_Croatia.svg',\n", | |
" 'slackcode': ':flag-hr:'}},\n", | |
" {'id': 'NED',\n", | |
" 'name': 'Netherlands',\n", | |
" 'rank': 11,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇳🇱',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/2/20/Flag_of_the_Netherlands.svg',\n", | |
" 'slackcode': ':flag-nl:'}},\n", | |
" {'id': 'RUS',\n", | |
" 'name': 'Russia',\n", | |
" 'rank': 12,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇷🇺',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/en/f/f3/Flag_of_Russia.svg',\n", | |
" 'slackcode': ':flag-ru:'}},\n", | |
" {'id': 'POR',\n", | |
" 'name': 'Portugal',\n", | |
" 'rank': 13,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇵🇹',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/5/5c/Flag_of_Portugal.svg',\n", | |
" 'slackcode': ':flag-pt:'}},\n", | |
" {'id': 'TUR',\n", | |
" 'name': 'Turkey',\n", | |
" 'rank': 14,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇹🇷',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/b/b4/Flag_of_Turkey.svg',\n", | |
" 'slackcode': ':flag-tr:'}},\n", | |
" {'id': 'DEN',\n", | |
" 'name': 'Denmark',\n", | |
" 'rank': 15,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇩🇰',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/9/9c/Flag_of_Denmark.svg',\n", | |
" 'slackcode': ':flag-dk:'}},\n", | |
" {'id': 'AUT',\n", | |
" 'name': 'Austria',\n", | |
" 'rank': 16,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇦🇹',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/4/41/Flag_of_Austria.svg',\n", | |
" 'slackcode': ':flag-at:'}},\n", | |
" {'id': 'SWE',\n", | |
" 'name': 'Sweden',\n", | |
" 'rank': 17,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇸🇪',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/en/4/4c/Flag_of_Sweden.svg',\n", | |
" 'slackcode': ':flag-se:'}},\n", | |
" {'id': 'CZE',\n", | |
" 'name': 'Czech Republic',\n", | |
" 'rank': 18,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇨🇿',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/c/cb/Flag_of_the_Czech_Republic.svg',\n", | |
" 'slackcode': ':flag-cz:'}},\n", | |
" {'id': 'WAL',\n", | |
" 'name': 'Wales',\n", | |
" 'rank': 19,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🏴\\U000e0067\\U000e0062\\U000e0077\\U000e006c\\U000e0073\\U000e007f',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/a/a9/Flag_of_Wales_%281959%E2%80%93present%29.svg',\n", | |
" 'slackcode': ':flag-wales:'}},\n", | |
" {'id': 'FIN',\n", | |
" 'name': 'Finland',\n", | |
" 'rank': 20,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇫🇮',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/b/bc/Flag_of_Finland.svg',\n", | |
" 'slackcode': ':flag-fi:'}},\n", | |
" {'id': 'MAC',\n", | |
" 'name': 'North Macedonia',\n", | |
" 'rank': 30,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇲🇰',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/7/79/Flag_of_North_Macedonia.svg',\n", | |
" 'slackcode': ':flag-mk:'}},\n", | |
" {'id': 'SLO',\n", | |
" 'name': 'Slovakia',\n", | |
" 'rank': 22,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇸🇰',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/e/e6/Flag_of_Slovakia.svg',\n", | |
" 'slackcode': ':flag-sk:'}},\n", | |
" {'id': 'SCO',\n", | |
" 'name': 'Scotland',\n", | |
" 'rank': 29,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🏴\\U000e0067\\U000e0062\\U000e0073\\U000e0063\\U000e0074\\U000e007f',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/1/10/Flag_of_Scotland.svg',\n", | |
" 'slackcode': ':flag-scotland:'}},\n", | |
" {'id': 'HUN',\n", | |
" 'name': 'Hungary',\n", | |
" 'rank': 31,\n", | |
" 'disciplinary': 0,\n", | |
" 'flag': {'unicode': '🇭🇺',\n", | |
" 'url': 'https://upload.wikimedia.org/wikipedia/commons/c/c1/Flag_of_Hungary.svg',\n", | |
" 'slackcode': ':flag-hu:'}}]" | |
] | |
}, | |
"execution_count": 4, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"DATA['teams']" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[{'id': 'a',\n", | |
" 'name': 'Group A',\n", | |
" 'winner': 'ITA',\n", | |
" 'runnerup': 'WAL',\n", | |
" 'thirdplace': 'SUI',\n", | |
" 'fourthplace': 'TUR',\n", | |
" 'matches': [{'id': 1,\n", | |
" 'name': '1',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'TUR',\n", | |
" 'away_team': 'ITA',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 3,\n", | |
" 'date': '2021-06-11T21:00:00+02:00',\n", | |
" 'stadium': 'STA',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 2,\n", | |
" 'name': '2',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'WAL',\n", | |
" 'away_team': 'SUI',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-12T15:00:00+02:00',\n", | |
" 'stadium': 'OLY',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 13,\n", | |
" 'name': '13',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'TUR',\n", | |
" 'away_team': 'WAL',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-16T18:00:00+02:00',\n", | |
" 'stadium': 'OLY',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 14,\n", | |
" 'name': '14',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'ITA',\n", | |
" 'away_team': 'SUI',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-16T21:00:00+02:00',\n", | |
" 'stadium': 'STA',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 25,\n", | |
" 'name': '25',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'SUI',\n", | |
" 'away_team': 'TUR',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-20T18:00:00+02:00',\n", | |
" 'stadium': 'OLY',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'},\n", | |
" {'id': 26,\n", | |
" 'name': '26',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'ITA',\n", | |
" 'away_team': 'WAL',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-20T18:00:00+02:00',\n", | |
" 'stadium': 'STA',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'}]},\n", | |
" {'id': 'b',\n", | |
" 'name': 'Group B',\n", | |
" 'winner': 'BEL',\n", | |
" 'runnerup': 'DEN',\n", | |
" 'thirdplace': 'FIN',\n", | |
" 'fourthplace': 'RUS',\n", | |
" 'matches': [{'id': 3,\n", | |
" 'name': '3',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'DEN',\n", | |
" 'away_team': 'FIN',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-12T18:00:00+02:00',\n", | |
" 'stadium': 'PAR',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 4,\n", | |
" 'name': '4',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'BEL',\n", | |
" 'away_team': 'RUS',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-12T21:00:00+02:00',\n", | |
" 'stadium': 'KRE',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 15,\n", | |
" 'name': '15',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'FIN',\n", | |
" 'away_team': 'RUS',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-16T15:00:00+02:00',\n", | |
" 'stadium': 'KRE',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 16,\n", | |
" 'name': '16',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'DEN',\n", | |
" 'away_team': 'BEL',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-17T18:00:00+02:00',\n", | |
" 'stadium': 'PAR',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 27,\n", | |
" 'name': '27',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'RUS',\n", | |
" 'away_team': 'DEN',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 4,\n", | |
" 'date': '2021-06-21T21:00:00+02:00',\n", | |
" 'stadium': 'PAR',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'},\n", | |
" {'id': 28,\n", | |
" 'name': '28',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'FIN',\n", | |
" 'away_team': 'BEL',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-21T21:00:00+02:00',\n", | |
" 'stadium': 'KRE',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'}]},\n", | |
" {'id': 'c',\n", | |
" 'name': 'Group C',\n", | |
" 'winner': 'NED',\n", | |
" 'runnerup': 'AUT',\n", | |
" 'thirdplace': 'UKR',\n", | |
" 'fourthplace': 'MAC',\n", | |
" 'matches': [{'id': 6,\n", | |
" 'name': '6',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'AUT',\n", | |
" 'away_team': 'MAC',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-13T18:00:00+02:00',\n", | |
" 'stadium': 'NAT',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 5,\n", | |
" 'name': '5',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'NED',\n", | |
" 'away_team': 'UKR',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-13T21:00:00+02:00',\n", | |
" 'stadium': 'JOH',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 18,\n", | |
" 'name': '18',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'UKR',\n", | |
" 'away_team': 'MAC',\n", | |
" 'home_result': 2,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-17T15:00:00+02:00',\n", | |
" 'stadium': 'NAT',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 17,\n", | |
" 'name': '17',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'NED',\n", | |
" 'away_team': 'AUT',\n", | |
" 'home_result': 2,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-17T21:00:00+02:00',\n", | |
" 'stadium': 'JOH',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 29,\n", | |
" 'name': '29',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'MAC',\n", | |
" 'away_team': 'NED',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 3,\n", | |
" 'date': '2021-06-21T18:00:00+02:00',\n", | |
" 'stadium': 'JOH',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'},\n", | |
" {'id': 30,\n", | |
" 'name': '30',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'UKR',\n", | |
" 'away_team': 'AUT',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-21T18:00:00+02:00',\n", | |
" 'stadium': 'NAT',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'}]},\n", | |
" {'id': 'd',\n", | |
" 'name': 'Group D',\n", | |
" 'winner': 'ENG',\n", | |
" 'runnerup': 'CRO',\n", | |
" 'thirdplace': 'CZE',\n", | |
" 'fourthplace': 'SCO',\n", | |
" 'matches': [{'id': 7,\n", | |
" 'name': '7',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'ENG',\n", | |
" 'away_team': 'CRO',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-13T15:00:00+02:00',\n", | |
" 'stadium': 'WEM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 8,\n", | |
" 'name': '8',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'SCO',\n", | |
" 'away_team': 'CZE',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-14T15:00:00+02:00',\n", | |
" 'stadium': 'HAM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 19,\n", | |
" 'name': '19',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'CRO',\n", | |
" 'away_team': 'CZE',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-18T18:00:00+02:00',\n", | |
" 'stadium': 'HAM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 20,\n", | |
" 'name': '20',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'ENG',\n", | |
" 'away_team': 'SCO',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-18T21:00:00+02:00',\n", | |
" 'stadium': 'WEM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 31,\n", | |
" 'name': '31',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'CRO',\n", | |
" 'away_team': 'SCO',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-22T21:00:00+02:00',\n", | |
" 'stadium': 'HAM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'},\n", | |
" {'id': 32,\n", | |
" 'name': '32',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'CZE',\n", | |
" 'away_team': 'ENG',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-22T21:00:00+02:00',\n", | |
" 'stadium': 'WEM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'}]},\n", | |
" {'id': 'e',\n", | |
" 'name': 'Group E',\n", | |
" 'winner': 'SWE',\n", | |
" 'runnerup': 'ESP',\n", | |
" 'thirdplace': 'SLO',\n", | |
" 'fourthplace': 'POL',\n", | |
" 'matches': [{'id': 10,\n", | |
" 'name': '10',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'POL',\n", | |
" 'away_team': 'SLO',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-14T18:00:00+02:00',\n", | |
" 'stadium': 'KRE',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 9,\n", | |
" 'name': '9',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'ESP',\n", | |
" 'away_team': 'SWE',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-14T21:00:00+02:00',\n", | |
" 'stadium': 'CAR',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 21,\n", | |
" 'name': '21',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'SWE',\n", | |
" 'away_team': 'SLO',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-18T15:00:00+02:00',\n", | |
" 'stadium': 'KRE',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 22,\n", | |
" 'name': '22',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'ESP',\n", | |
" 'away_team': 'POL',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-19T21:00:00+02:00',\n", | |
" 'stadium': 'CAR',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 33,\n", | |
" 'name': '33',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'SLO',\n", | |
" 'away_team': 'ESP',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 5,\n", | |
" 'date': '2021-06-23T18:00:00+02:00',\n", | |
" 'stadium': 'CAR',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'},\n", | |
" {'id': 34,\n", | |
" 'name': '34',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'SWE',\n", | |
" 'away_team': 'POL',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-23T18:00:00+02:00',\n", | |
" 'stadium': 'KRE',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'}]},\n", | |
" {'id': 'f',\n", | |
" 'name': 'Group F',\n", | |
" 'winner': 'FRA',\n", | |
" 'runnerup': 'GER',\n", | |
" 'thirdplace': 'POR',\n", | |
" 'fourthplace': 'HUN',\n", | |
" 'matches': [{'id': 11,\n", | |
" 'name': '11',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'HUN',\n", | |
" 'away_team': 'POR',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 3,\n", | |
" 'date': '2021-06-15T18:00:00+02:00',\n", | |
" 'stadium': 'PUS',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 12,\n", | |
" 'name': '12',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'FRA',\n", | |
" 'away_team': 'GER',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 0,\n", | |
" 'date': '2021-06-15T21:00:00+02:00',\n", | |
" 'stadium': 'ALL',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '1'},\n", | |
" {'id': 23,\n", | |
" 'name': '23',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'HUN',\n", | |
" 'away_team': 'FRA',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 1,\n", | |
" 'date': '2021-06-19T15:00:00+02:00',\n", | |
" 'stadium': 'PUS',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 24,\n", | |
" 'name': '24',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'POR',\n", | |
" 'away_team': 'GER',\n", | |
" 'home_result': 2,\n", | |
" 'away_result': 4,\n", | |
" 'date': '2021-06-19T18:00:00+02:00',\n", | |
" 'stadium': 'ALL',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '2'},\n", | |
" {'id': 35,\n", | |
" 'name': '35',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'POR',\n", | |
" 'away_team': 'FRA',\n", | |
" 'home_result': 2,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-23T21:00:00+02:00',\n", | |
" 'stadium': 'PUS',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'},\n", | |
" {'id': 36,\n", | |
" 'name': '36',\n", | |
" 'matchtype': 'group',\n", | |
" 'home_team': 'GER',\n", | |
" 'away_team': 'HUN',\n", | |
" 'home_result': 2,\n", | |
" 'away_result': 2,\n", | |
" 'date': '2021-06-23T21:00:00+02:00',\n", | |
" 'stadium': 'ALL',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '3'}]}]" | |
] | |
}, | |
"execution_count": 5, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"DATA['groups']" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'round16': {'id': 'round16',\n", | |
" 'name': 'Round of 16',\n", | |
" 'matches': [{'id': 37,\n", | |
" 'name': '37',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'group': 'a'},\n", | |
" 'away_team': {'qualificationtype': 'runnerup', 'group': 'c'}},\n", | |
" 'home_team': 'ITA',\n", | |
" 'away_team': 'AUT',\n", | |
" 'home_result': 2,\n", | |
" 'away_result': 1,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'ITA',\n", | |
" 'date': '2021-06-26T21:00:00+02:00',\n", | |
" 'stadium': 'WEM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '4'},\n", | |
" {'id': 38,\n", | |
" 'name': '38',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'runnerup',\n", | |
" 'group': 'a'},\n", | |
" 'away_team': {'qualificationtype': 'runnerup', 'group': 'b'}},\n", | |
" 'home_team': 'WAL',\n", | |
" 'away_team': 'DEN',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 4,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'DEN',\n", | |
" 'date': '2021-06-26T18:00:00+02:00',\n", | |
" 'stadium': 'JOH',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '4'},\n", | |
" {'id': 39,\n", | |
" 'name': '39',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'group': 'b'},\n", | |
" 'away_team': {'qualificationtype': 'thirdplace', 'group': 'A/D/E/F'}},\n", | |
" 'home_team': 'BEL',\n", | |
" 'away_team': 'POR',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 0,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'BEL',\n", | |
" 'date': '2021-06-27T21:00:00+02:00',\n", | |
" 'stadium': 'CAR',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '4'},\n", | |
" {'id': 40,\n", | |
" 'name': '40',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'group': 'c'},\n", | |
" 'away_team': {'qualificationtype': 'thirdplace', 'group': 'D/E/F'}},\n", | |
" 'home_team': 'NED',\n", | |
" 'away_team': 'CZE',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 2,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'CZE',\n", | |
" 'date': '2021-06-27T18:00:00+02:00',\n", | |
" 'stadium': 'PUS',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '4'},\n", | |
" {'id': 41,\n", | |
" 'name': '41',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'group': 'f'},\n", | |
" 'away_team': {'qualificationtype': 'thirdplace', 'group': 'A/B/C'}},\n", | |
" 'home_team': 'FRA',\n", | |
" 'away_team': 'SUI',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 3,\n", | |
" 'home_penalty': 4,\n", | |
" 'away_penalty': 5,\n", | |
" 'winner': 'SUI',\n", | |
" 'date': '2021-06-28T21:00:00+02:00',\n", | |
" 'stadium': 'NAT',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '4'},\n", | |
" {'id': 42,\n", | |
" 'name': '42',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'runnerup',\n", | |
" 'group': 'd'},\n", | |
" 'away_team': {'qualificationtype': 'runnerup', 'group': 'e'}},\n", | |
" 'home_team': 'CRO',\n", | |
" 'away_team': 'ESP',\n", | |
" 'home_result': 3,\n", | |
" 'away_result': 5,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'ESP',\n", | |
" 'date': '2021-06-28T18:00:00+02:00',\n", | |
" 'stadium': 'PAR',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '4'},\n", | |
" {'id': 43,\n", | |
" 'name': '43',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'group': 'e'},\n", | |
" 'away_team': {'qualificationtype': 'thirdplace', 'group': 'A/B/C/D'}},\n", | |
" 'home_team': 'SWE',\n", | |
" 'away_team': 'UKR',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 2,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'UKR',\n", | |
" 'date': '2021-06-29T21:00:00+02:00',\n", | |
" 'stadium': 'HAM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '4'},\n", | |
" {'id': 44,\n", | |
" 'name': '44',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'group': 'd'},\n", | |
" 'away_team': {'qualificationtype': 'runnerup', 'group': 'f'}},\n", | |
" 'home_team': 'ENG',\n", | |
" 'away_team': 'GER',\n", | |
" 'home_result': 2,\n", | |
" 'away_result': 0,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'ENG',\n", | |
" 'date': '2021-06-29T18:00:00+02:00',\n", | |
" 'stadium': 'WEM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '4'}]},\n", | |
" 'round8': {'id': 'round8',\n", | |
" 'name': 'Quarter-finals (Round of 8)',\n", | |
" 'matches': [{'id': 45,\n", | |
" 'name': '45',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'match': 41},\n", | |
" 'away_team': {'qualificationtype': 'winner', 'match': 42}},\n", | |
" 'home_team': 'SUI',\n", | |
" 'away_team': 'ESP',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 1,\n", | |
" 'home_penalty': 1,\n", | |
" 'away_penalty': 3,\n", | |
" 'winner': 'ESP',\n", | |
" 'date': '2021-07-02T18:00:00+02:00',\n", | |
" 'stadium': 'KRE',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '5'},\n", | |
" {'id': 46,\n", | |
" 'name': '46',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'match': 39},\n", | |
" 'away_team': {'qualificationtype': 'winner', 'match': 37}},\n", | |
" 'home_team': 'BEL',\n", | |
" 'away_team': 'ITA',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 2,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'ITA',\n", | |
" 'date': '2021-07-02T21:00:00+02:00',\n", | |
" 'stadium': 'ALL',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '5'},\n", | |
" {'id': 47,\n", | |
" 'name': '47',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'match': 40},\n", | |
" 'away_team': {'qualificationtype': 'winner', 'match': 38}},\n", | |
" 'home_team': 'CZE',\n", | |
" 'away_team': 'DEN',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 2,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': 'DEN',\n", | |
" 'date': '2021-07-03T18:00:00+02:00',\n", | |
" 'stadium': 'OLY',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '5'},\n", | |
" {'id': 48,\n", | |
" 'name': '48',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'match': 43},\n", | |
" 'away_team': {'qualificationtype': 'winner', 'match': 44}},\n", | |
" 'home_team': 'UKR',\n", | |
" 'away_team': 'ENG',\n", | |
" 'home_result': 0,\n", | |
" 'away_result': 4,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': None,\n", | |
" 'date': '2021-07-03T21:00:00+02:00',\n", | |
" 'stadium': 'STA',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '5'}]},\n", | |
" 'round4': {'id': 'round4',\n", | |
" 'name': 'Semi-finals (Round of 4)',\n", | |
" 'matches': [{'id': 49,\n", | |
" 'name': '49',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'match': 46},\n", | |
" 'away_team': {'qualificationtype': 'winner', 'match': 45}},\n", | |
" 'home_team': 'ESP',\n", | |
" 'away_team': 'ITA',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 1,\n", | |
" 'home_penalty': 2,\n", | |
" 'away_penalty': 4,\n", | |
" 'winner': 'ITA',\n", | |
" 'date': '2021-07-06T21:00:00+02:00',\n", | |
" 'stadium': 'WEM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '6'},\n", | |
" {'id': 50,\n", | |
" 'name': '50',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'match': 48},\n", | |
" 'away_team': {'qualificationtype': 'winner', 'match': 47}},\n", | |
" 'home_team': 'DEN',\n", | |
" 'away_team': 'ENG',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 2,\n", | |
" 'home_penalty': None,\n", | |
" 'away_penalty': None,\n", | |
" 'winner': None,\n", | |
" 'date': '2021-07-07T21:00:00+02:00',\n", | |
" 'stadium': 'WEM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '6'}]},\n", | |
" 'round2': {'id': 'round2',\n", | |
" 'name': 'Final',\n", | |
" 'matches': [{'id': 51,\n", | |
" 'name': '51',\n", | |
" 'matchtype': 'knockout',\n", | |
" 'teams_found': True,\n", | |
" 'qualification': {'home_team': {'qualificationtype': 'winner',\n", | |
" 'match': 49},\n", | |
" 'away_team': {'qualificationtype': 'winner', 'match': 50}},\n", | |
" 'home_team': 'ITA',\n", | |
" 'away_team': 'ENG',\n", | |
" 'home_result': 1,\n", | |
" 'away_result': 1,\n", | |
" 'home_penalty': 3,\n", | |
" 'away_penalty': 2,\n", | |
" 'winner': 'ITA',\n", | |
" 'date': '2021-07-11T21:00:00+02:00',\n", | |
" 'stadium': 'WEM',\n", | |
" 'tvchannels': [],\n", | |
" 'finished': True,\n", | |
" 'matchday': '7'}]}}" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"DATA['knockoutphases']" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Use some fancy Python dataclasses to handle the data" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"@dataclass\n", | |
"class Team:\n", | |
" id: str\n", | |
" name: str\n", | |
" flag: str" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"@dataclass\n", | |
"class Match:\n", | |
" home_team: str\n", | |
" away_team: str\n", | |
" result_no_pen: Tuple[int]\n", | |
" result_penalty: Tuple[int] = (None, None)\n", | |
" @property\n", | |
" def result(self) -> Tuple[int]:\n", | |
" return (\n", | |
" self.result_no_pen[0] + (self.result_penalty[0] or 0),\n", | |
" self.result_no_pen[1] + (self.result_penalty[1] or 0)\n", | |
" )\n", | |
" def __repr__(self):\n", | |
" return f\"{self.home_team}:{self.away_team} {self.result}\"" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"teams = {\n", | |
" t['id']: Team(t['id'], t['name'], t['flag']['unicode'])\n", | |
" for t in DATA['teams']\n", | |
"}" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"{'BEL': Team(id='BEL', name='Belgium', flag='🇧🇪'),\n", | |
" 'ITA': Team(id='ITA', name='Italy', flag='🇮🇹'),\n", | |
" 'ENG': Team(id='ENG', name='England', flag='🏴\\U000e0067\\U000e0062\\U000e0065\\U000e006e\\U000e0067\\U000e007f'),\n", | |
" 'GER': Team(id='GER', name='Germany', flag='🇩🇪'),\n", | |
" 'ESP': Team(id='ESP', name='Spain', flag='🇪🇸'),\n", | |
" 'UKR': Team(id='UKR', name='Ukraine', flag='🇺🇦'),\n", | |
" 'FRA': Team(id='FRA', name='France', flag='🇫🇷'),\n", | |
" 'POL': Team(id='POL', name='Poland', flag='🇵🇱'),\n", | |
" 'SUI': Team(id='SUI', name='Switzerland', flag='🇨🇭'),\n", | |
" 'CRO': Team(id='CRO', name='Croatia', flag='🇭🇷'),\n", | |
" 'NED': Team(id='NED', name='Netherlands', flag='🇳🇱'),\n", | |
" 'RUS': Team(id='RUS', name='Russia', flag='🇷🇺'),\n", | |
" 'POR': Team(id='POR', name='Portugal', flag='🇵🇹'),\n", | |
" 'TUR': Team(id='TUR', name='Turkey', flag='🇹🇷'),\n", | |
" 'DEN': Team(id='DEN', name='Denmark', flag='🇩🇰'),\n", | |
" 'AUT': Team(id='AUT', name='Austria', flag='🇦🇹'),\n", | |
" 'SWE': Team(id='SWE', name='Sweden', flag='🇸🇪'),\n", | |
" 'CZE': Team(id='CZE', name='Czech Republic', flag='🇨🇿'),\n", | |
" 'WAL': Team(id='WAL', name='Wales', flag='🏴\\U000e0067\\U000e0062\\U000e0077\\U000e006c\\U000e0073\\U000e007f'),\n", | |
" 'FIN': Team(id='FIN', name='Finland', flag='🇫🇮'),\n", | |
" 'MAC': Team(id='MAC', name='North Macedonia', flag='🇲🇰'),\n", | |
" 'SLO': Team(id='SLO', name='Slovakia', flag='🇸🇰'),\n", | |
" 'SCO': Team(id='SCO', name='Scotland', flag='🏴\\U000e0067\\U000e0062\\U000e0073\\U000e0063\\U000e0074\\U000e007f'),\n", | |
" 'HUN': Team(id='HUN', name='Hungary', flag='🇭🇺')}" | |
] | |
}, | |
"execution_count": 10, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"teams" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"group_matches = [\n", | |
" Match(m['home_team'], m['away_team'], (m['home_result'], m['away_result']))\n", | |
" for g in DATA['groups']\n", | |
" for m in g['matches']\n", | |
"]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[TUR:ITA (0, 3),\n", | |
" WAL:SUI (1, 1),\n", | |
" TUR:WAL (0, 2),\n", | |
" ITA:SUI (3, 0),\n", | |
" SUI:TUR (3, 1),\n", | |
" ITA:WAL (1, 0),\n", | |
" DEN:FIN (0, 1),\n", | |
" BEL:RUS (3, 0),\n", | |
" FIN:RUS (0, 1),\n", | |
" DEN:BEL (1, 2),\n", | |
" RUS:DEN (1, 4),\n", | |
" FIN:BEL (0, 2),\n", | |
" AUT:MAC (3, 1),\n", | |
" NED:UKR (3, 2),\n", | |
" UKR:MAC (2, 1),\n", | |
" NED:AUT (2, 0),\n", | |
" MAC:NED (0, 3),\n", | |
" UKR:AUT (0, 1),\n", | |
" ENG:CRO (1, 0),\n", | |
" SCO:CZE (0, 2),\n", | |
" CRO:CZE (1, 1),\n", | |
" ENG:SCO (0, 0),\n", | |
" CRO:SCO (3, 1),\n", | |
" CZE:ENG (0, 1),\n", | |
" POL:SLO (1, 2),\n", | |
" ESP:SWE (0, 0),\n", | |
" SWE:SLO (1, 0),\n", | |
" ESP:POL (1, 1),\n", | |
" SLO:ESP (0, 5),\n", | |
" SWE:POL (3, 2),\n", | |
" HUN:POR (0, 3),\n", | |
" FRA:GER (1, 0),\n", | |
" HUN:FRA (1, 1),\n", | |
" POR:GER (2, 4),\n", | |
" POR:FRA (2, 2),\n", | |
" GER:HUN (2, 2)]" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"group_matches" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"knockout_matches = [\n", | |
" Match(m['home_team'], m['away_team'], (m['home_result'], m['away_result']), (m['home_penalty'], m['away_penalty']))\n", | |
" for round_name, round_data in DATA['knockoutphases'].items()\n", | |
" for m in round_data['matches']\n", | |
"]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"[ITA:AUT (2, 1),\n", | |
" WAL:DEN (0, 4),\n", | |
" BEL:POR (1, 0),\n", | |
" NED:CZE (0, 2),\n", | |
" FRA:SUI (7, 8),\n", | |
" CRO:ESP (3, 5),\n", | |
" SWE:UKR (1, 2),\n", | |
" ENG:GER (2, 0),\n", | |
" SUI:ESP (2, 4),\n", | |
" BEL:ITA (1, 2),\n", | |
" CZE:DEN (1, 2),\n", | |
" UKR:ENG (0, 4),\n", | |
" ESP:ITA (3, 5),\n", | |
" DEN:ENG (1, 2),\n", | |
" ITA:ENG (4, 3)]" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"knockout_matches" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Finally, we need a function that evaluates our predictions:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def evaluate(match: Match, predict_fn, log=True):\n", | |
" \"\"\" Takes a match and a prediction function and returns\n", | |
" the number of points given to the prediction.\n", | |
" \"\"\"\n", | |
" result = match.result\n", | |
" res_diff = result[0] - result[1]\n", | |
" predicted = predict_fn(match.home_team, match.away_team)\n", | |
" pred_diff = predicted[0] - predicted[1]\n", | |
" \n", | |
" if result == predicted:\n", | |
" points = 4\n", | |
" elif res_diff == pred_diff and res_diff != 0:\n", | |
" points = 3\n", | |
" elif res_diff == pred_diff and res_diff == 0:\n", | |
" points = 2\n", | |
" elif (res_diff > 0 and pred_diff > 0) or (res_diff < 0 and pred_diff < 0):\n", | |
" points = 2\n", | |
" else:\n", | |
" points = 0\n", | |
" if log:\n", | |
" print(f\"Evaluating match {match}. Your prediction: {predicted}. {points} points.\")\n", | |
" return points" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Model prediction" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"We are blindly following the ranking in table 9 from https://www.zeileis.org/assets/posts/2021-06-10-euro2020paper/euro2020-hybridforecasts.pdf \n", | |
"\n", | |
"We will assume that the higher team wins against the lower team 1:0. (NB. we are ignoring the fact that the table is actually telling us the chance of a team to win the Euros and not what its chances are to win against another team. But it’s the only table in the paper that comes with flags *and* numbers and we’re lazy and don’t read the rest of the paper.)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The teams from the paper." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 16, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"hybrid_paper_teams = ['FRA', 'ENG', 'ESP', 'POR', 'GER', 'BEL', \n", | |
" 'ITA', 'NED', 'DEN', 'CRO', 'SUI', 'AUT',\n", | |
" 'POL', 'SWE', 'TUR', 'WAL', 'SCO', 'RUS',\n", | |
" 'CZE', 'UKR', 'SLO', 'FIN', 'MAC', 'HUN']" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"hybrid_paper_ranking = {t:rank for rank, t in enumerate(hybrid_paper_teams)}" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Our prediction function." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def predict(t1, t2):\n", | |
" # simple rule: the team with the better (= lower) ranking in the paper\n", | |
" # wins by 1:0\n", | |
" rk1 = hybrid_paper_ranking[t1]\n", | |
" rk2 = hybrid_paper_ranking[t2]\n", | |
" if rk1 < rk2:\n", | |
" return (1, 0)\n", | |
" else:\n", | |
" return (0, 1)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Match points" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"*** Group matches ***\n", | |
"Evaluating match TUR:ITA (0, 3). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match WAL:SUI (1, 1). Your prediction: (0, 1). 0 points.\n", | |
"Evaluating match TUR:WAL (0, 2). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match ITA:SUI (3, 0). Your prediction: (1, 0). 2 points.\n", | |
"Evaluating match SUI:TUR (3, 1). Your prediction: (1, 0). 2 points.\n", | |
"Evaluating match ITA:WAL (1, 0). Your prediction: (1, 0). 4 points.\n", | |
"Evaluating match DEN:FIN (0, 1). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match BEL:RUS (3, 0). Your prediction: (1, 0). 2 points.\n", | |
"Evaluating match FIN:RUS (0, 1). Your prediction: (0, 1). 4 points.\n", | |
"Evaluating match DEN:BEL (1, 2). Your prediction: (0, 1). 3 points.\n", | |
"Evaluating match RUS:DEN (1, 4). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match FIN:BEL (0, 2). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match AUT:MAC (3, 1). Your prediction: (1, 0). 2 points.\n", | |
"Evaluating match NED:UKR (3, 2). Your prediction: (1, 0). 3 points.\n", | |
"Evaluating match UKR:MAC (2, 1). Your prediction: (1, 0). 3 points.\n", | |
"Evaluating match NED:AUT (2, 0). Your prediction: (1, 0). 2 points.\n", | |
"Evaluating match MAC:NED (0, 3). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match UKR:AUT (0, 1). Your prediction: (0, 1). 4 points.\n", | |
"Evaluating match ENG:CRO (1, 0). Your prediction: (1, 0). 4 points.\n", | |
"Evaluating match SCO:CZE (0, 2). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match CRO:CZE (1, 1). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match ENG:SCO (0, 0). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match CRO:SCO (3, 1). Your prediction: (1, 0). 2 points.\n", | |
"Evaluating match CZE:ENG (0, 1). Your prediction: (0, 1). 4 points.\n", | |
"Evaluating match POL:SLO (1, 2). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match ESP:SWE (0, 0). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match SWE:SLO (1, 0). Your prediction: (1, 0). 4 points.\n", | |
"Evaluating match ESP:POL (1, 1). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match SLO:ESP (0, 5). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match SWE:POL (3, 2). Your prediction: (0, 1). 0 points.\n", | |
"Evaluating match HUN:POR (0, 3). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match FRA:GER (1, 0). Your prediction: (1, 0). 4 points.\n", | |
"Evaluating match HUN:FRA (1, 1). Your prediction: (0, 1). 0 points.\n", | |
"Evaluating match POR:GER (2, 4). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match POR:FRA (2, 2). Your prediction: (0, 1). 0 points.\n", | |
"Evaluating match GER:HUN (2, 2). Your prediction: (1, 0). 0 points.\n", | |
"Group stage score: 61 points.\n", | |
"\n", | |
"*** Knockout matches ***\n", | |
"Evaluating match ITA:AUT (2, 1). Your prediction: (1, 0). 3 points.\n", | |
"Evaluating match WAL:DEN (0, 4). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match BEL:POR (1, 0). Your prediction: (0, 1). 0 points.\n", | |
"Evaluating match NED:CZE (0, 2). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match FRA:SUI (7, 8). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match CRO:ESP (3, 5). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match SWE:UKR (1, 2). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match ENG:GER (2, 0). Your prediction: (1, 0). 2 points.\n", | |
"Evaluating match SUI:ESP (2, 4). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match BEL:ITA (1, 2). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match CZE:DEN (1, 2). Your prediction: (0, 1). 3 points.\n", | |
"Evaluating match UKR:ENG (0, 4). Your prediction: (0, 1). 2 points.\n", | |
"Evaluating match ESP:ITA (3, 5). Your prediction: (1, 0). 0 points.\n", | |
"Evaluating match DEN:ENG (1, 2). Your prediction: (0, 1). 3 points.\n", | |
"Evaluating match ITA:ENG (4, 3). Your prediction: (0, 1). 0 points.\n", | |
"Knockout stage score: 19 points.\n" | |
] | |
} | |
], | |
"source": [ | |
"print(\"*** Group matches ***\")\n", | |
"\n", | |
"group_score = sum(evaluate(m, predict) for m in group_matches)\n", | |
"print(f\"Group stage score: {group_score} points.\")\n", | |
"\n", | |
" \n", | |
"print()\n", | |
"print(\"*** Knockout matches ***\")\n", | |
"\n", | |
"knockout_score = sum(evaluate(m, predict) for m in knockout_matches)\n", | |
"print(f\"Knockout stage score: {knockout_score} points.\")" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Bonus points" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"The group firsts from that list would have been: FRA, ENG, ~ESP~, BEL, ITA, NED" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"group_firsts_score = 4 * 5" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"I’m too lazy to simulate the whole knock-out stage to predict the semi-finalists. We’ll just take the top 4 from the ranking: ~FRA~, ENG, ~ESP~, ~POR~" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"semi_finalists_score = 4 * 1" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"### Total score" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 22, | |
"metadata": {}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"104" | |
] | |
}, | |
"execution_count": 22, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"group_score + knockout_score + group_firsts_score + semi_finalists_score" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "base", | |
"language": "python", | |
"name": "base" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.8.6" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 4 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment