sari-madi / data_layer.py
Zakeertechie3's picture
Update data_layer.py
3a3ddca verified
Raw
History Blame Contribute Delete
3.95 kB
import csv
import json
from shapely.geometry import shape, Point
WARDS_GEOJSON = "wards.geojson"
WARD_CONTACTS = "ward_contacts.csv"
CATEGORY_ROUTING = {
"pothole": ["AE", "AEE", "EE"],
"road_damage": ["AE", "AEE", "EE"],
"road_blocking": ["AE", "AEE", "EE"],
"footpath": ["AE", "AEE", "EE"],
"streetlight": ["AE", "AEE", "EE"],
"garbage": ["Jr. Health Insp", "Sr. Health Insp"],
"drain": ["Jr. Health Insp", "Sr. Health Insp", "AE"],
"waterlogging": ["AE", "AEE", "EE"],
"stray_animal": ["Animal Husbandry"],
"dead_animal": ["Animal Husbandry", "Jr. Health Insp"],
"other": ["AE", "Jr. Health Insp", "JC"],
}
CATEGORY_LABELS = {
"pothole": "Pothole",
"road_damage": "Road damage",
"road_blocking": "Road blocked by debris",
"footpath": "Broken footpath",
"streetlight": "Streetlight not working",
"garbage": "Garbage / illegal dumping",
"drain": "Blocked or open drain",
"waterlogging": "Waterlogging",
"stray_animal": "Stray animal",
"dead_animal": "Dead animal",
"other": "Other civic issue",
}
class WardIndex:
def __init__(self):
self.polygons = []
self.contacts = {}
self._load_geojson()
self._load_contacts()
def _load_geojson(self):
with open(WARDS_GEOJSON, encoding="utf-8") as f:
data = json.load(f)
for feat in data["features"]:
ward_no = feat["properties"]["ward_no"]
geom = shape(feat["geometry"])
self.polygons.append((ward_no, geom))
def _load_contacts(self):
with open(WARD_CONTACTS, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
ward_no = int(row["ward_no"])
self.contacts[ward_no] = {
"ward_name": row["ward_name"],
"zone": row["zone"],
"constituency": row["constituency"],
"officers": json.loads(row["officers_json"]),
}
def find_ward(self, lat, lng):
point = Point(lng, lat)
for ward_no, geom in self.polygons:
if geom.contains(point):
return ward_no
return None
def is_in_bengaluru(self, lat, lng):
point = Point(lng, lat)
for _, geom in self.polygons:
if geom.contains(point):
return True
return False
def get_ward_info(self, ward_no):
return self.contacts.get(ward_no)
def route_officer(self, ward_no, category):
info = self.contacts.get(ward_no)
if info is None:
return None
officers = info["officers"]
chain = CATEGORY_ROUTING.get(category, CATEGORY_ROUTING["other"])
for role in chain:
officer = officers.get(role)
if officer and officer.get("name") and officer.get("phone"):
return {
"role": role,
"name": officer["name"],
"phone": officer["phone"],
}
for role, officer in officers.items():
if officer and officer.get("name") and officer.get("phone"):
return {
"role": role,
"name": officer["name"],
"phone": officer["phone"],
}
return None
def resolve(ward_index, lat, lng, category):
ward_no = ward_index.find_ward(lat, lng)
if ward_no is None:
return None
info = ward_index.get_ward_info(ward_no)
officer = ward_index.route_officer(ward_no, category)
return {
"ward_no": ward_no,
"ward_name": info["ward_name"] if info else "",
"zone": info["zone"] if info else "",
"constituency": info["constituency"] if info else "",
"officer": officer,
"category_label": CATEGORY_LABELS.get(category, CATEGORY_LABELS["other"]),
}