| """ |
| Loads sprint scenario data from JSON file. |
| Uses module-level cache so disk is read only once. |
| """ |
| from __future__ import annotations |
| import json |
| import os |
| from pathlib import Path |
| from typing import Optional |
| from functools import lru_cache |
|
|
| from sprint_env.tasks import Task, Developer, TaskType, TaskStatus |
|
|
| DEFAULT_DATA_PATH = Path(__file__).parent.parent / "data" / "sprint_data.json" |
|
|
| |
| _DATA_CACHE: Optional[dict] = None |
|
|
|
|
| def load_sprint_data(data_path: Optional[str] = None) -> dict: |
| global _DATA_CACHE |
| if _DATA_CACHE is not None: |
| return _DATA_CACHE |
| path = Path(data_path or os.getenv("SPRINT_DATA_PATH", DEFAULT_DATA_PATH)) |
| if not path.exists(): |
| raise FileNotFoundError(f"Sprint data file not found: {path}") |
| with open(path, "r") as f: |
| _DATA_CACHE = json.load(f) |
| return _DATA_CACHE |
|
|
|
|
| def get_scenario_names(data_path: Optional[str] = None) -> list[str]: |
| return list(load_sprint_data(data_path)["scenarios"].keys()) |
|
|
|
|
| def build_scenario( |
| scenario_name: str, data_path: Optional[str] = None |
| ) -> tuple[list[Task], list[Developer], dict]: |
| data = load_sprint_data(data_path) |
| scenarios = data["scenarios"] |
|
|
| if scenario_name not in scenarios: |
| available = list(scenarios.keys()) |
| raise ValueError(f"Unknown scenario '{scenario_name}'. Available: {available}") |
|
|
| scenario = scenarios[scenario_name] |
| meta = { |
| "description": scenario.get("description", ""), |
| "difficulty": scenario.get("difficulty", "unknown"), |
| } |
|
|
| developers = [ |
| Developer( |
| id=d["id"], name=d["name"], skill=d["skill"], |
| capacity=d["capacity"], productivity=d.get("productivity", 1.0), |
| ) |
| for d in scenario["developers"] |
| ] |
|
|
| tasks = [ |
| Task( |
| id=t["id"], name=t["name"], task_type=TaskType(t["task_type"]), |
| priority=t["priority"], effort=t["effort"], deadline=t["deadline"], |
| required_skill=t["required_skill"], status=TaskStatus.BACKLOG, |
| ) |
| for t in scenario["tasks"] |
| ] |
|
|
| return tasks, developers, meta |