samaan / ml /gap_analyzer.py
Copilot Sync Bot
Sync backend from main branch
26c9046
from __future__ import annotations
from collections import defaultdict
from typing import Dict, List, Tuple
from models.village import InfrastructureCategory, InfrastructureStatus, Village, InfrastructureItem
BASELINE_ITEMS = {
InfrastructureCategory.EDUCATION: ["primary school", "secondary school", "anganwadi"],
InfrastructureCategory.HEALTHCARE: ["phc", "asha worker", "ambulance access"],
InfrastructureCategory.SANITATION: ["odf status", "public toilets", "solid waste management"],
InfrastructureCategory.CONNECTIVITY: ["paved road", "mobile signal", "internet access"],
InfrastructureCategory.WATER: ["piped water supply", "hand pump", "water quality tested"],
InfrastructureCategory.ELECTRICITY: ["grid connection", "street lights", "solar backup"],
InfrastructureCategory.SKILL: ["iti/vocational centre access", "shg activity"],
InfrastructureCategory.LIVELIHOOD: ["mgnrega enrolment", "market access"],
}
def evaluate_village_gap(village: Village, items: List[InfrastructureItem]) -> Tuple[float, Dict[str, int], List[str]]:
gap_summary: Dict[str, int] = defaultdict(int)
interventions: List[str] = []
weighted_gaps = 0.0
total_expected = sum(len(v) for v in BASELINE_ITEMS.values())
for category, expected_items in BASELINE_ITEMS.items():
category_items = [item for item in items if item.category == category]
existing_names = {item.item_name.lower().strip() for item in category_items if item.status == InfrastructureStatus.PRESENT}
for item_name in expected_items:
if item_name not in existing_names:
gap_summary[category.value] += 1
interventions.append(f"Strengthen {category.value}: {item_name}")
weighted_gaps += 1.0
degraded_count = sum(1 for item in category_items if item.status in {InfrastructureStatus.ABSENT, InfrastructureStatus.DEGRADED})
gap_summary[category.value] += degraded_count
weighted_gaps += degraded_count * 0.6
sc_factor = 1.0 + (village.sc_population_pct / 100.0)
score = min(100.0, round((weighted_gaps / max(total_expected, 1)) * 100.0 * sc_factor, 2))
if village.sc_population_pct >= 50:
interventions.insert(0, "Prioritize SC-majority service delivery and access improvements")
if not interventions:
interventions.append("Village infrastructure meets baseline expectations")
return score, dict(gap_summary), interventions[:10]