diff --git a/analysis/rankings.py b/analysis/rankings.py deleted file mode 100644 index 131380d..0000000 --- a/analysis/rankings.py +++ /dev/null @@ -1,82 +0,0 @@ -import json -import os -from typing import List, Dict, Any - -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -CAREER_DB_PATH = os.path.join(BASE_DIR, "career_stats.json") - - -def load_career_db() -> Dict: - """Load career database with proper error handling.""" - if not os.path.exists(CAREER_DB_PATH): - raise FileNotFoundError(f"Career database not found at: {CAREER_DB_PATH}\nPlease build it first from the GUI.") - - try: - with open(CAREER_DB_PATH, "r", encoding="utf-8") as f: - return json.load(f) - except json.JSONDecodeError: - raise ValueError("Career database is corrupted. Please rebuild it.") - except Exception as e: - raise RuntimeError(f"Failed to load career database: {e}") - - -def top_players_by_tag( - tag: str, - players_only: List[Dict] = None, - career_db: Dict = None, - limit: int = 10 -) -> List[Dict]: - """ - Return top players for a given identity tag. - - If players_only is provided → only rank within current match lineup (recommended for GUI). - Otherwise → rank across entire career database. - """ - if players_only is not None: - # Use only the current match players (live stats) - players = players_only[:] - else: - # Full career database - db = career_db or load_career_db() - players = list(db["players"].values()) - - if not players: - return [] - - # Filter players who have this tag - tagged_players = [ - p for p in players - if tag in p.get("identity_tags", []) - ] - - if not tagged_players: - return [] - - # Define scoring function based on tag - def get_score(p: Dict) -> float: - norm = p.get("normalized", {}) - career = p.get("career", {}) - - if tag == "Slayer": - return norm.get("slayer_index", 0) - elif tag == "Objective Specialist": - return norm.get("objective_index", 0) - elif tag == "Sharpshooter": - return career.get("accuracy", 0) - elif tag == "Anchor": - return norm.get("survivability_index", 0) - elif tag == "Aggressor": - return norm.get("kills_per_map", 0) - elif tag == "Clutch": - return norm.get("win_rate", 0) - elif tag == "Consistent": - # Could add variance logic if stored - return norm.get("kills_per_map", 0) - else: - # Default fallback - return career.get("KD", 0) - - # Sort by score descending - tagged_players.sort(key=get_score, reverse=True) - - return tagged_players[:limit] \ No newline at end of file diff --git a/analysis/rankings1.py b/analysis/rankings1.py deleted file mode 100644 index 93833d4..0000000 --- a/analysis/rankings1.py +++ /dev/null @@ -1,38 +0,0 @@ -import json -import os - -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -CAREER_DB = os.path.join(BASE_DIR, "career_stats.json") - -def load_db(): - with open(CAREER_DB, "r", encoding="utf-8") as f: - return json.load(f) - -def top_players_by_tag(tag, limit=10): - db = load_db() - players = db["players"] - - ranked = [ - p for p in players.values() - if tag in p.get("identity_tags", []) - ] - - # Sort by slayer_index for Slayers, objective_index for Objective Specialists, etc. - def score(p): - norm = p["normalized"] - if tag == "Slayer": - return norm["slayer_index"] - if tag == "Objective Specialist": - return norm["objective_index"] - if tag == "Sharpshooter": - return p["career"]["accuracy"] - if tag == "Anchor": - return norm["survivability_index"] - if tag == "Aggressor": - return norm["kills_per_map"] - if tag == "Clutch": - return norm["win_rate"] - return p["career"]["KD"] - - ranked.sort(key=score, reverse=True) - return ranked[:limit] \ No newline at end of file diff --git a/analysis/storylines.py b/analysis/storylines.py deleted file mode 100644 index f8b75e2..0000000 --- a/analysis/storylines.py +++ /dev/null @@ -1,54 +0,0 @@ -from team_identity import team_identity - -def matchup_storyline(team_a: str, team_b: str) -> str: - """Generate rich, caster-ready storyline with talking points and predictive flavor.""" - A = team_identity(team_a) - B = team_identity(team_b) - - story = [f"🎙️ MATCH STORYLINE: {team_a} vs {team_b}\n"] - - # Slayer Power - slayer_a = A["tag_counts"].get("Slayer", 0) - slayer_b = B["tag_counts"].get("Slayer", 0) - if slayer_a > slayer_b: - story.append(f"• {team_a} brings **superior slayer firepower** ({slayer_a} tagged Slayers vs {slayer_b}).") - elif slayer_b > slayer_a: - story.append(f"• {team_b} brings **superior slayer firepower** ({slayer_b} tagged Slayers vs {slayer_a}).") - else: - story.append(f"• Both teams have equal slayer power — this could come down to execution.") - - # Objective Control - obj_a = A["tag_counts"].get("Objective Specialist", 0) - obj_b = B["tag_counts"].get("Objective Specialist", 0) - if obj_a > obj_b: - story.append(f"• {team_a} has **deeper objective presence** and map control potential.") - elif obj_b > obj_a: - story.append(f"• {team_b} has **deeper objective presence** and map control potential.") - - # Anchor / Stability - if A["tag_counts"].get("Anchor", 0) >= 1 and B["tag_counts"].get("Anchor", 0) == 0: - story.append(f"• {team_a} has a clear **anchor advantage** — expect a rock-solid backline.") - elif B["tag_counts"].get("Anchor", 0) >= 1 and A["tag_counts"].get("Anchor", 0) == 0: - story.append(f"• {team_b} has a clear **anchor advantage** — expect a rock-solid backline.") - - # Experience / Rookie Factor - vet_a = A["tag_counts"].get("Veteran", 0) - rook_a = A["tag_counts"].get("Rookie", 0) - vet_b = B["tag_counts"].get("Veteran", 0) - rook_b = B["tag_counts"].get("Rookie", 0) - if rook_a >= 2 and vet_b >= 2: - story.append(f"• {team_a} is young and hungry — {team_b} brings veteran experience. Classic youth vs experience matchup.") - - # Direct Exploit Lines - if "Weak objective presence" in A["weaknesses"] and "Strong objective depth" in B["strengths"]: - story.append(f"🔥 {team_b} is perfectly positioned to **exploit {team_a}'s weak objective play**.") - if "Weak objective presence" in B["weaknesses"] and "Strong objective depth" in A["strengths"]: - story.append(f"🔥 {team_a} is perfectly positioned to **exploit {team_b}'s weak objective play**.") - - # Final prediction flavor - story.append("\n**Caster Talking Points Summary:**") - story.append(f"• Watch for early slayer duels — the team that wins the Slayer battle usually controls the pace.") - story.append(f"• Objective maps will heavily favor the side with more Objective Specialists.") - story.append(f"• This matchup has high upset potential if the younger team executes cleanly.") - - return "\n".join(story) \ No newline at end of file diff --git a/analysis/storylines1.py b/analysis/storylines1.py deleted file mode 100644 index ab6e0b4..0000000 --- a/analysis/storylines1.py +++ /dev/null @@ -1,29 +0,0 @@ -from team_identity import team_identity - -def matchup_storyline(team_a, team_b): - A = team_identity(team_a) - B = team_identity(team_b) - - story = [] - - story.append(f"MATCH STORYLINE: {team_a} vs {team_b}\n") - - # Style comparison - if A["tag_counts"].get("Slayer", 0) > B["tag_counts"].get("Slayer", 0): - story.append(f"{team_a} brings stronger slayer power.") - elif B["tag_counts"].get("Slayer", 0) > A["tag_counts"].get("Slayer", 0): - story.append(f"{team_b} brings stronger slayer power.") - - if A["tag_counts"].get("Objective Specialist", 0) > B["tag_counts"].get("Objective Specialist", 0): - story.append(f"{team_a} has deeper objective presence.") - elif B["tag_counts"].get("Objective Specialist", 0) > A["tag_counts"].get("Objective Specialist", 0): - story.append(f"{team_b} has deeper objective presence.") - - # Strength vs weakness - if "Weak objective presence" in A["weaknesses"] and "Strong objective depth" in B["strengths"]: - story.append(f"{team_b} may exploit {team_a}'s weak objective play.") - - if "Weak objective presence" in B["weaknesses"] and "Strong objective depth" in A["strengths"]: - story.append(f"{team_a} may exploit {team_b}'s weak objective play.") - - return "\n".join(story) \ No newline at end of file diff --git a/analysis/team_identity.py b/analysis/team_identity.py deleted file mode 100644 index cd23b26..0000000 --- a/analysis/team_identity.py +++ /dev/null @@ -1,77 +0,0 @@ -import json -import os -from collections import Counter - -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -CAREER_DB_PATH = os.path.join(BASE_DIR, "career_stats.json") - -def load_career_db(): - """Load career database with proper error handling.""" - if not os.path.exists(CAREER_DB_PATH): - raise FileNotFoundError(f"Career database not found at: {CAREER_DB_PATH}\nPlease build it first.") - - try: - with open(CAREER_DB_PATH, "r", encoding="utf-8") as f: - return json.load(f) - except json.JSONDecodeError: - raise ValueError("Career database is corrupted. Please rebuild it.") - except Exception as e: - raise RuntimeError(f"Failed to load career database: {e}") - - -def team_identity(team_name: str): - """Generate team identity summary based on career tags.""" - db = load_career_db() - players = db.get("players", {}) - - # Find all players who have ever played for this team - team_players = [ - p for p in players.values() - if team_name in p.get("team_history", []) - ] - - if not team_players: - return { - "team": team_name, - "players": [], - "tag_counts": {}, - "strengths": ["No players found with this team in history"], - "weaknesses": [] - } - - # Count all identity tags across the team - all_tags = [tag for p in team_players for tag in p.get("identity_tags", [])] - tag_counts = Counter(all_tags) - - strengths = [] - weaknesses = [] - - # --- Strengths --- - if tag_counts.get("Slayer", 0) >= 2: - strengths.append("High slayer firepower") - if tag_counts.get("Objective Specialist", 0) >= 2: - strengths.append("Strong objective control") - if tag_counts.get("Anchor", 0) >= 1: - strengths.append("Reliable anchor/backline") - if tag_counts.get("Playmaker", 0) >= 1: - strengths.append("Creative playmaking") - if tag_counts.get("Consistent", 0) >= 2: - strengths.append("Very consistent performers") - - # --- Weaknesses --- - if tag_counts.get("Objective Specialist", 0) == 0: - weaknesses.append("Lacking objective specialists") - if tag_counts.get("Sharpshooter", 0) == 0: - weaknesses.append("No dedicated sharpshooter") - if tag_counts.get("Anchor", 0) == 0: - weaknesses.append("Weak backline stability") - if tag_counts.get("Veteran", 0) == 0 and tag_counts.get("Rookie", 0) >= 2: - weaknesses.append("Very inexperienced roster") - - return { - "team": team_name, - "players": team_players, # kept for potential future use - "tag_counts": dict(tag_counts), - "strengths": strengths or ["Balanced roster — no dominant strength"], - "weaknesses": weaknesses or ["No major weaknesses identified"] - } \ No newline at end of file diff --git a/analysis/team_identity1.py b/analysis/team_identity1.py deleted file mode 100644 index 1f5bab7..0000000 --- a/analysis/team_identity1.py +++ /dev/null @@ -1,46 +0,0 @@ -import json -import os - -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -CAREER_DB = os.path.join(BASE_DIR, "career_stats.json") - -def load_db(): - with open(CAREER_DB, "r", encoding="utf-8") as f: - return json.load(f) - -def team_identity(team_name): - db = load_db() - players = db["players"] - - team_players = [ - p for p in players.values() - if team_name in p.get("team_history", []) - ] - - tag_counts = {} - for p in team_players: - for tag in p.get("identity_tags", []): - tag_counts[tag] = tag_counts.get(tag, 0) + 1 - - strengths = [] - weaknesses = [] - - if tag_counts.get("Slayer", 0) >= 2: - strengths.append("High slayer power") - if tag_counts.get("Objective Specialist", 0) >= 2: - strengths.append("Strong objective depth") - if tag_counts.get("Anchor", 0) >= 1: - strengths.append("Stable backline") - - if tag_counts.get("Objective Specialist", 0) == 0: - weaknesses.append("Weak objective presence") - if tag_counts.get("Sharpshooter", 0) == 0: - weaknesses.append("No true sharpshooter") - - return { - "team": team_name, - "players": team_players, - "tag_counts": tag_counts, - "strengths": strengths, - "weaknesses": weaknesses - } \ No newline at end of file