Remove obsolete analysis folder and legacy module duplicates
This commit is contained in:
parent
b69e4b4d47
commit
4261a4b2f9
6 changed files with 0 additions and 326 deletions
|
|
@ -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]
|
|
||||||
|
|
@ -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]
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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"]
|
|
||||||
}
|
|
||||||
|
|
@ -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
|
|
||||||
}
|
|
||||||
Loading…
Reference in a new issue