Last active
June 15, 2026 19:07
-
-
Save live-by-unix/0812d4aa973f3a332f39a207ef43217d to your computer and use it in GitHub Desktop.
This is a quick python file (needing os, sys, copy, datetime, numpy, pandas) that calculates the chances of different countries winning the world cup. You may change data values. Under MIT license. Run with python3 wincup.py
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
| MIT License | |
| Copyright (c) 2026 live-by-unix | |
| Permission is hereby granted, free of charge, to any person obtaining a copy | |
| of this software and associated documentation files (the "Software"), to deal | |
| in the Software without restriction, including without limitation the rights | |
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
| copies of the Software, and to permit persons to whom the Software is | |
| furnished to do so, subject to the following conditions: | |
| The above copyright notice and this permission notice shall be included in all | |
| copies or substantial portions of the Software. | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
| SOFTWARE. |
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
| import os | |
| import sys | |
| import copy | |
| from datetime import datetime | |
| import numpy as np | |
| import pandas as pd | |
| # ========================================== | |
| # 1. ACCURATE INTERNATIONAL FORM DATA METRICS | |
| # ========================================== | |
| # Ratings are scaled where ~1.00 is the expected tournament baseline average. | |
| # High attack + low defense = elite team profile. | |
| BASE_TEAMS = { | |
| # Europe (UEFA) | |
| "France": {"att": 1.65, "def": 0.72}, "England": {"att": 1.60, "def": 0.70}, | |
| "Spain": {"att": 1.55, "def": 0.75}, "Germany": {"att": 1.50, "def": 0.82}, | |
| "Portugal": {"att": 1.52, "def": 0.78}, "Italy": {"att": 1.25, "def": 0.65}, | |
| "Netherlands": {"att": 1.35, "def": 0.80}, "Belgium": {"att": 1.30, "def": 0.88}, | |
| "Croatia": {"att": 1.15, "def": 0.78}, "Denmark": {"att": 1.10, "def": 0.82}, | |
| "Switzerland": {"att": 1.12, "def": 0.80}, "Austria": {"att": 1.18, "def": 0.85}, | |
| "Ukraine": {"att": 1.05, "def": 0.95}, "Turkey": {"att": 1.12, "def": 1.02}, | |
| "Poland": {"att": 1.02, "def": 1.05}, "Hungary": {"att": 0.98, "def": 0.95}, | |
| # South America (CONMEBOL) | |
| "Argentina": {"att": 1.68, "def": 0.64}, "Brazil": {"att": 1.58, "def": 0.74}, | |
| "Uruguay": {"att": 1.42, "def": 0.76}, "Colombia": {"att": 1.38, "def": 0.81}, | |
| "Ecuador": {"att": 1.10, "def": 0.75}, "Chile": {"att": 0.95, "def": 0.98}, | |
| # North America (CONCACAF) | |
| "USA": {"att": 1.18, "def": 0.88}, "Mexico": {"att": 1.12, "def": 0.94}, | |
| "Canada": {"att": 1.14, "def": 1.02}, "Panama": {"att": 0.90, "def": 1.05}, | |
| "Costa Rica": {"att": 0.85, "def": 1.12}, | |
| # Africa (CAF) | |
| "Morocco": {"att": 1.28, "def": 0.68}, "Senegal": {"att": 1.22, "def": 0.82}, | |
| "Nigeria": {"att": 1.26, "def": 1.04}, "Egypt": {"att": 1.08, "def": 0.88}, | |
| "Ivory Coast": {"att": 1.15, "def": 0.92}, "Tunisia": {"att": 0.82, "def": 0.90}, | |
| "Algeria": {"att": 1.06, "def": 0.94}, | |
| # Asia (AFC) | |
| "Japan": {"att": 1.32, "def": 0.80}, "South Korea": {"att": 1.20, "def": 0.96}, | |
| "Iran": {"att": 1.05, "def": 0.88}, "Australia": {"att": 1.02, "def": 0.94}, | |
| "Saudi Arabia": {"att": 0.88, "def": 1.14}, "Qatar": {"att": 0.86, "def": 1.20}, | |
| "Uzbekistan": {"att": 0.82, "def": 1.05}, | |
| # Oceania & Intercontinental Play-offs | |
| "New Zealand": {"att": 0.72, "def": 1.25}, "Peru": {"att": 0.92, "def": 1.02}, | |
| "Paraguay": {"att": 0.84, "def": 0.88}, "Ghana": {"att": 1.04, "def": 1.12}, | |
| "Cameroon": {"att": 0.98, "def": 1.06}, "Jamaica": {"att": 0.92, "def": 1.14} | |
| } | |
| TEAMS = dict(list(BASE_TEAMS.items())[:48]) | |
| # Slice all 48 teams cleanly into 12 groups of 4 to prevent formatting mismatches | |
| all_allocated_teams = list(TEAMS.keys()) | |
| group_names = [chr(i) for i in range(65, 77)] # Groups A through L | |
| GROUPS = {group_names[i]: all_allocated_teams[i*4:(i+1)*4] for i in range(12)} | |
| # ========================================== | |
| # 2. CALIBRATED MATCH SIMULATION ENGINE | |
| # ========================================== | |
| def simulate_match_poisson(home_team, away_team, current_teams): | |
| """ | |
| Calculates expected goals using normalized international parameters. | |
| Avg expected goals per match settles accurately between 2.4 and 2.7. | |
| """ | |
| # Global adjustment constant representing average international xG per team | |
| global_baseline_xg = 1.22 | |
| home_xg = max(0.05, current_teams[home_team]["att"] * current_teams[away_team]["def"] * global_baseline_xg) | |
| away_xg = max(0.05, current_teams[away_team]["att"] * current_teams[home_team]["def"] * global_baseline_xg) | |
| return np.random.poisson(home_xg), np.random.poisson(away_xg) | |
| def simulate_knockout_match(home_team, away_team, current_teams): | |
| """Handles elimination scenarios with extra time and balanced penalty variables.""" | |
| h_g, a_g = simulate_match_poisson(home_team, away_team, current_teams) | |
| if h_g != a_g: | |
| return home_team if h_g > a_g else away_team | |
| # Extra Time (scaled down to 30 minutes of play) | |
| et_h_g = np.random.poisson(current_teams[home_team]["att"] * current_teams[away_team]["def"] * 0.30) | |
| et_a_g = np.random.poisson(current_teams[away_team]["att"] * current_teams[home_team]["def"] * 0.30) | |
| if et_h_g != et_a_g: | |
| return home_team if et_h_g > et_a_g else away_team | |
| # Penalties (50/50 absolute performance breaker) | |
| return home_team if np.random.rand() > 0.5 else away_team | |
| def run_full_tournament(current_teams): | |
| standings_data = {team: [0, 0, 0] for team in current_teams} # Matrix layout: [Points, Goal Diff, Goals For] | |
| # Round-Robin Group Stage Loop | |
| for g_lbl, g_teams in GROUPS.items(): | |
| for i in range(len(g_teams)): | |
| for j in range(i + 1, len(g_teams)): | |
| t1, t2 = g_teams[i], g_teams[j] | |
| g1, g2 = simulate_match_poisson(t1, t2, current_teams) | |
| # Goal Difference adjustments | |
| standings_data[t1][1] += (g1 - g2) | |
| standings_data[t2][1] += (g2 - g1) | |
| # Goals scored tracking | |
| standings_data[t1][2] += g1 | |
| standings_data[t2][2] += g2 | |
| # Point assignment | |
| if g1 > g2: | |
| standings_data[t1][0] += 3 | |
| elif g2 > g1: | |
| standings_data[t2][0] += 3 | |
| else: | |
| standings_data[t1][0] += 1 | |
| standings_data[t2][0] += 1 | |
| # Safe Sorting System utilizing array index lookups to avoid crash exceptions | |
| group_ranks = {} | |
| for g_lbl, g_teams in GROUPS.items(): | |
| sub_list = [(t, standings_data[t]) for t in g_teams] | |
| sub_list.sort(key=lambda x: (x[1][0], x[1][1], x[1][2]), reverse=True) | |
| group_ranks[g_lbl] = sub_list | |
| # EXPLICIT STRING EXTRACTION ROUTINE (Prevents list-unpacking tuple data type crash) | |
| auto_qualified = [group_ranks[g][0][0] for g in group_ranks] # Group Winners | |
| runners_up = [group_ranks[g][1][0] for g in group_ranks] # Group Runners-Up | |
| third_places = [] | |
| for g in group_ranks: | |
| third_places.append((group_ranks[g][2][0], group_ranks[g][2][1])) | |
| third_places.sort(key=lambda x: (x[1][0], x[1][1], x[1][2]), reverse=True) | |
| wildcards = [item[0] for item in third_places[:8]] # Extract top 8 wildcard strings safely | |
| knockout_pool = auto_qualified + runners_up + wildcards | |
| np.random.shuffle(knockout_pool) # Shuffle to simulate random bracket placements | |
| # Progressive Knockout Tree Elimination Structure | |
| current_bracket = knockout_pool | |
| while len(current_bracket) > 1: | |
| next_bracket = [] | |
| for i in range(0, len(current_bracket), 2): | |
| winner = simulate_knockout_match(current_bracket[i], current_bracket[i+1], current_teams) | |
| next_bracket.append(winner) | |
| current_bracket = next_bracket | |
| return current_bracket[0] | |
| # ========================================== | |
| # 3. RUNTIME PIPELINE EXECUTION | |
| # ========================================== | |
| if __name__ == "__main__": | |
| print("\n" + "="*60) | |
| print(" 2026 FIFA WORLD CUP HIGH-PRECISION SIMULATOR ") | |
| print("="*60) | |
| try: | |
| user_input = input("Enter the number of tournament runs (e.g., 100000): ").strip() | |
| sim_runs = int(user_input) | |
| if sim_runs <= 0: | |
| raise ValueError | |
| except ValueError: | |
| print("!! Input Error. Defaulting to 20,000 runs for stability.") | |
| sim_runs = 20000 | |
| print(f"\nProcessing {sim_runs:,} tournament iterations across the calibrated engine...") | |
| championship_registry = {team: 0 for team in TEAMS} | |
| for _ in range(sim_runs): | |
| champ = run_full_tournament(TEAMS) | |
| championship_registry[champ] += 1 | |
| # Process outputs via Pandas DataFrames | |
| df = pd.DataFrame(list(championship_registry.items()), columns=["Country", "Titles"]) | |
| df["Win Chance %"] = round((df["Titles"] / sim_runs) * 100, 3) | |
| df = df.sort_values(by="Win Chance %", ascending=False).reset_index(drop=True) | |
| df.index += 1 | |
| print("\n🏆 STATISTICALLY CALIBRATED WIN PROBABILITIES (TOP 15) 🏆") | |
| print("-" * 55) | |
| print(f"{'Rank':<6}{'Country':<25}{'Win Chance':<15}") | |
| print("-" * 55) | |
| for idx, row in df.head(15).iterrows(): | |
| country_name = row['Country'] | |
| # Print with standard alignment; all special character markers have been removed | |
| print(f"{idx:<6} {country_name:<23}{row['Win Chance %']:>10}%") | |
| print("-" * 55) | |
| absolute_favorite = df.iloc[0]['Country'] | |
| favorite_odds = df.iloc[0]['Win Chance %'] | |
| print(f"\n🔮 PREDICTION: Based on mathematical form tracking, the team most likely to win the 2026 World Cup is {absolute_favorite.upper()} with a {favorite_odds}% success probability.\n") |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
To install all deps, run
pip install numpy pandas matplotlib # or pip3