Spaces:
Paused
Paused
File size: 5,252 Bytes
29fd274 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | import json
from pathlib import Path
from app.models import Match, TeamInfo
from app.services.cricket import ReplayData
from app.services.sample_data import demo_matches
class MatchRepository:
def __init__(self, data_dir: Path):
self._data = {match.match_id: match for match in demo_matches()}
self._metadata = {
"demo-t20-northern-coastal": Match(
match_id="demo-t20-northern-coastal", tournament="MatchLens Demo T20 Cup",
match_number="Match 14 of 24", teams=(TeamInfo(name="Northern Strikers", code="NS"), TeamInfo(name="Coastal Kings", code="CK")),
venue="Harbour Oval, Demo City", match_date="2026-10-18",
)
}
self._load_cricsheet(data_dir)
def _load_cricsheet(self, data_dir: Path) -> None:
if not data_dir.exists():
return
for path in data_dir.glob("*.json"):
try:
payload = json.loads(path.read_text(encoding="utf-8"))
parsed = parse_cricsheet(payload, path.stem)
self._data[parsed.match_id] = parsed
self._metadata[parsed.match_id] = metadata_from_cricsheet(payload, parsed)
except (OSError, ValueError, KeyError, TypeError):
continue
def all(self) -> list[Match]:
return list(self._metadata.values())
def get(self, match_id: str) -> ReplayData:
if match_id not in self._data:
raise KeyError(match_id)
return self._data[match_id]
def metadata(self, match_id: str) -> Match:
if match_id not in self._metadata:
raise KeyError(match_id)
return self._metadata[match_id]
def parse_cricsheet(payload: dict, match_id: str = "cricsheet-match") -> ReplayData:
info = payload["info"]
teams = info["teams"]
innings_data = payload["innings"]
innings = innings_data[1] if len(innings_data) > 1 else innings_data[0]
target = 0
if len(innings_data) > 1:
target = 1 + sum(
delivery["runs"]["total"]
for over_data in innings_data[0]["overs"]
for delivery in over_data["deliveries"]
)
deliveries = []
index = 0
for over_data in innings["overs"]:
over = over_data["over"]
for delivery in over_data["deliveries"]:
index += 1
runs = delivery["runs"]
extras_data = delivery.get("extras", {})
extras = sum(extras_data.values())
wicket_data = delivery.get("wickets", [])
wicket = wicket_data[0] if wicket_data else None
deliveries.append({
"index": index, "over": over, "ball_in_over": len([d for d in deliveries if d["over"] == over]) + 1,
"over_label": f"{over}.{len([d for d in deliveries if d['over'] == over]) + 1}",
"bowler": delivery["bowler"], "striker": delivery["batter"], "non_striker": delivery["non_striker"],
"runs_off_bat": runs["batter"], "extras": extras, "total_runs": runs["total"],
"is_legal": not any(name in extras_data for name in ("wides", "noballs")),
"outcome": "wicket" if wicket else ("wide" if "wides" in extras_data else ("no_ball" if "noballs" in extras_data else "run")),
"wicket": {"batter": wicket["player_out"], "kind": wicket["kind"]} if wicket else None,
"commentary": f"{runs['total']} run(s)",
})
from app.models import BallEvent
outcome = info.get("outcome", {})
winner = outcome.get("winner")
by_data = outcome.get("by", {})
if winner:
if "runs" in by_data:
r = by_data["runs"]
result_str = f"{winner} won by {r} run{'s' if r > 1 else ''}"
elif "wickets" in by_data:
w = by_data["wickets"]
result_str = f"{winner} won by {w} wicket{'s' if w > 1 else ''}"
else:
result_str = f"{winner} won"
elif outcome.get("result") == "tie":
result_str = "Match tied"
elif outcome.get("result") == "no result":
result_str = "No result"
else:
result_str = "Match completed"
return ReplayData(
match_id=match_id,
batting_team=innings["team"], bowling_team=next(team for team in teams if team != innings["team"]),
target=target, deliveries=[BallEvent.model_validate(item) for item in deliveries],
batting_order=list(dict.fromkeys([d.striker for d in [BallEvent.model_validate(item) for item in deliveries]])),
result=result_str,
balls_per_innings=int(info.get("overs", 20)) * int(info.get("balls_per_over", 6)),
)
def metadata_from_cricsheet(payload: dict, parsed: ReplayData) -> Match:
info = payload["info"]
teams = list(info["teams"])
return Match(
match_id=parsed.match_id, tournament=str(info.get("event", {}).get("name", "Cricket match")),
match_number=str(info.get("event", {}).get("match_number", "")),
teams=(TeamInfo(name=teams[0], code=teams[0][:3].upper()), TeamInfo(name=teams[1], code=teams[1][:3].upper())),
venue=str(info.get("venue", "Unknown venue")), match_date=str(info.get("dates", [""])[0]),
is_demo=False,
)
|