Spaces:
Running on Zero
Running on Zero
| """Deterministic scripted BUILD/FIX JSON for the MockBackend. | |
| Each petition maps to a category by keyword; each category emits a complete | |
| BUILD JSON string (parsed by mind/validate.py exactly like real backend | |
| output), with names and blurbs varied by a crc32 seed of the petition — same | |
| petition in, same permit out, so demos replay exactly. The category library | |
| exercises every building kind. | |
| fix_script reads the candidate ids and report numbers back out of the | |
| rendered fix prompt (the "- F1: desc (predicted index 41)" lines from | |
| mind/prompts.py — keep the two in lockstep) and picks the best predicted | |
| index, so mock fixes cite real numbers too. | |
| """ | |
| from __future__ import annotations | |
| import json | |
| import random | |
| import re | |
| import zlib | |
| NAME_MAX = 24 | |
| BLURB_MAX = 140 | |
| def _seed_for(petition: str) -> int: | |
| return zlib.crc32(" ".join(petition.lower().split()).encode("utf-8")) & 0x7FFFFFFF | |
| def _entry(kind: str, name: str, near=None, floors=None, hue=None) -> dict: | |
| return {"kind": kind, "name": name[:NAME_MAX], "near": near, "floors": floors, "hue": hue} | |
| def _plan(blurb: str, buildings: list[dict]) -> dict: | |
| return { | |
| "intent": "build", | |
| "blurb": blurb[:BLURB_MAX], | |
| "buildings": buildings[:3], | |
| "decline_reason": None, | |
| } | |
| _STOP_WORDS = { | |
| "a", "an", "the", "please", "build", "make", "made", "add", "want", | |
| "wants", "need", "needs", "near", "for", "with", "of", "in", "on", "to", | |
| "and", "my", "me", "us", "we", "i", "new", "some", "little", "big", | |
| } | |
| def _petition_name(petition: str, suffix: str = "House") -> str: | |
| words = [w for w in re.findall(r"[A-Za-z]+", petition) if w.lower() not in _STOP_WORDS] | |
| base = " ".join(w.capitalize() for w in words[:2]) | |
| name = f"{base} {suffix}".strip() | |
| return (name[:NAME_MAX].rstrip() or f"Petition {suffix}")[:NAME_MAX] | |
| _CAFES = ("Cafe Luna", "The Brass Kettle", "Marigold Coffee", "The Daily Grind", "Cafe Fig") | |
| _HOUSES = ("Wren Cottage", "Maple End", "The Little Blue", "Juniper House", "Quince Cottage") | |
| _APTS = ("Linden Court", "The Beacon Flats", "Harbor House", "The Gables", "Rookery Flats") | |
| _TOWERS = ("Meridian Tower", "The Spindle", "Apex Tower", "Cobalt Point", "The Needle") | |
| _PARKS = ("Dapple Green", "Whistle Park", "Petal Commons", "Old Elm Green") | |
| _STADIUMS = ("The Civic Bowl", "Tin Cup Stadium", "The Roaring Yard") | |
| _CHURCHES = ("The Quiet Spire", "St. Alder's", "Lantern Chapel") | |
| _SCHOOLS = ("Alder Primary", "Hilltop School", "The Brightwork School") | |
| _HOSPITALS = ("Riverside General", "St. Junia Hospital", "Bluebell General") | |
| _FACTORIES = ("The Tin Works", "Cobalt Works", "The Bottling Hall") | |
| _MARKETS = ("Penny Market", "The Mercantile", "Six Crows Market") | |
| _BANKS = ("The Counting House", "First Acorn Bank", "The Strongbox") | |
| _SHOPS = ("The Odd Shelf", "Tortoise & Finch", "The Blue Awning") | |
| _NEARS = ("downtown", "the park", "Main St", "1st Ave") | |
| def _district(petition: str, rng: random.Random) -> dict: | |
| flats, cafe, shop = rng.choice(_APTS), rng.choice(_CAFES), rng.choice(_SHOPS) | |
| buildings = [ | |
| _entry("apartments", flats, "downtown", rng.randint(4, 7), rng.choice((25, 35, 200))), | |
| _entry("cafe", cafe, "downtown", 1, rng.choice((30, 40, 50))), | |
| ] | |
| if rng.random() < 0.7: | |
| buildings.append(_entry("shop", shop, "downtown", 1, rng.choice((10, 180, 320)))) | |
| blurb = rng.choice(( | |
| f"Zoning approved: a new block downtown — {flats} rising with {cafe} on the corner.", | |
| f"A whole block takes shape: {flats}, {cafe}, and room for more.", | |
| )) | |
| return _plan(blurb, buildings) | |
| def _river(petition: str, rng: random.Random) -> dict: | |
| park, cafe = rng.choice(_PARKS), rng.choice(("The Ferry Light", "Pier Nine Cafe", "The Eddy")) | |
| blurb = rng.choice(( | |
| f"The waterfront gets its due: {park} on the bank, {cafe} watching the water.", | |
| f"Permits issued by the river — {park}, and {cafe} for the crossing crowd.", | |
| )) | |
| return _plan(blurb, [ | |
| _entry("park", park, "the river"), | |
| _entry("cafe", cafe, "the river", 1, rng.choice((35, 45))), | |
| ]) | |
| def _cafe(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_CAFES) | |
| near = rng.choice(_NEARS) | |
| blurb = rng.choice(( | |
| f"{name} opens near {near} — pastries at dawn, lamplight at dusk.", | |
| f"Permit granted: {name}, sidewalk tables facing the street.", | |
| )) | |
| return _plan(blurb, [_entry("cafe", name, near, 1, rng.choice((30, 40, 50)))]) | |
| def _house(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_HOUSES) | |
| blurb = rng.choice(( | |
| f"{name} gets its lot — a porch, a chimney, a light in the window.", | |
| f"A home is granted: {name}, keys cut while the paint dries.", | |
| )) | |
| return _plan(blurb, [_entry("house", name, rng.choice(_NEARS), rng.randint(1, 2), rng.choice((20, 35, 200, 350)))]) | |
| def _apartments(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_APTS) | |
| blurb = rng.choice(( | |
| f"{name} approved — {rng.randint(4, 7)} floors of new neighbors.", | |
| f"Housing first: {name} will fill with families by the weekend.", | |
| )) | |
| return _plan(blurb, [_entry("apartments", name, rng.choice(_NEARS), rng.randint(4, 7), rng.choice((25, 200, 160)))]) | |
| def _tower(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_TOWERS) | |
| blurb = rng.choice(( | |
| f"{name} cleared for the skyline — cranes by morning.", | |
| f"Downtown grows up: {name}, {rng.randint(8, 16)} floors against the horizon.", | |
| )) | |
| return _plan(blurb, [_entry("tower", name, "downtown", rng.randint(8, 16), rng.choice((210, 220, 35)))]) | |
| def _park(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_PARKS) | |
| blurb = rng.choice(( | |
| f"Green space wins: {name}, benches and old trees included.", | |
| f"{name} is set aside — the city keeps a place to breathe.", | |
| )) | |
| return _plan(blurb, [_entry("park", name, rng.choice(_NEARS))]) | |
| def _stadium(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_STADIUMS) | |
| blurb = rng.choice(( | |
| f"{name} approved — floodlights, roar, and a home team to be named.", | |
| f"Game on: {name} takes the big lot.", | |
| )) | |
| return _plan(blurb, [_entry("stadium", name, "downtown", 1, rng.choice((10, 210)))]) | |
| def _church(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_CHURCHES) | |
| blurb = f"{name} is granted its steeple — bells on the hour." | |
| return _plan(blurb, [_entry("church", name, rng.choice(_NEARS), 1, rng.choice((40, 350)))]) | |
| def _school(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_SCHOOLS) | |
| blurb = rng.choice(( | |
| f"{name} chartered — chalk dust and a morning bell.", | |
| f"The city invests in small citizens: {name} opens soon.", | |
| )) | |
| return _plan(blurb, [_entry("school", name, rng.choice(_NEARS), rng.randint(1, 2), 200)]) | |
| def _hospital(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_HOSPITALS) | |
| blurb = f"{name} approved — the city will be looked after." | |
| return _plan(blurb, [_entry("hospital", name, rng.choice(_NEARS), rng.randint(3, 6), 200)]) | |
| def _bank(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_BANKS) | |
| blurb = f"{name} chartered downtown — marble face, careful ledgers." | |
| return _plan(blurb, [_entry("bank", name, "downtown", rng.randint(2, 4), 210)]) | |
| def _factory(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_FACTORIES) | |
| blurb = rng.choice(( | |
| f"{name} zoned for the edge of town — jobs by the shift.", | |
| f"Industry arrives: {name}, smokestack and all.", | |
| )) | |
| return _plan(blurb, [_entry("factory", name, "the river", rng.randint(1, 2), 30)]) | |
| def _market(petition: str, rng: random.Random) -> dict: | |
| name = rng.choice(_MARKETS) | |
| blurb = rng.choice(( | |
| f"{name} licensed — stalls up by Saturday.", | |
| f"Permit granted: {name}, the street will smell of bread.", | |
| )) | |
| return _plan(blurb, [_entry("market", name, rng.choice(_NEARS), 1, rng.choice((35, 15)))]) | |
| def _default(petition: str, rng: random.Random) -> dict: | |
| name = _petition_name(petition) | |
| blurb = f"City hall reads the petition twice, nods, and grants {name}." | |
| return _plan(blurb, [_entry("house", name, rng.choice(_NEARS), rng.randint(1, 2), rng.choice((20, 200, 320)))]) | |
| # Order matters: most specific first; "house" is the safety net before default. | |
| _CATEGORIES: tuple[tuple[re.Pattern[str], object], ...] = ( | |
| (re.compile(r"\b(districts?|downtown|neighbou?rhoods?|blocks?|quarters?|villages?|towns?|suburbs?|expand|grow)\b", re.I), _district), | |
| (re.compile(r"\b(rivers?|riverside|waterfront|bridges?|docks?|harbou?rs?|piers?|ferry)\b", re.I), _river), | |
| (re.compile(r"\b(caf[eé]s?|coffee|espresso|diners?|restaurants?|baker(?:y|ies)|bistros?|tea|ramen|pizz\w*|brunch|noodles?)\b", re.I), _cafe), | |
| (re.compile(r"\b(apartments?|condos?|flats?|hotels?|housing|lofts?)\b", re.I), _apartments), | |
| (re.compile(r"\b(towers?|offices?|skyscrapers?|high-?rises?|headquarters|startups?)\b", re.I), _tower), | |
| (re.compile(r"\b(stadiums?|arenas?|sports?|football|soccer|baseball|matches?)\b", re.I), _stadium), | |
| (re.compile(r"\b(church(?:es)?|temples?|chapels?|mosques?|cathedrals?|shrines?)\b", re.I), _church), | |
| (re.compile(r"\b(schools?|librar(?:y|ies)|universit(?:y|ies)|colleges?|academ(?:y|ies)|kids|children)\b", re.I), _school), | |
| (re.compile(r"\b(hospitals?|clinics?|doctors?|medical|health)\b", re.I), _hospital), | |
| (re.compile(r"\b(banks?|finance|credit|vaults?)\b", re.I), _bank), | |
| (re.compile(r"\b(factor(?:y|ies)|industr\w*|plants?|warehouses?|mills?|workshops?)\b", re.I), _factory), | |
| (re.compile(r"\b(markets?|malls?|grocer\w*|supermarkets?|shops?|stores?|boutiques?|bazaars?|pharmac\w*)\b", re.I), _market), | |
| (re.compile(r"\b(parks?|gardens?|greens?|trees?|playgrounds?|plazas?|squares?|fountains?)\b", re.I), _park), | |
| (re.compile(r"\b(houses?|homes?|cottages?|bungalows?|cabins?|townhouses?)\b", re.I), _house), | |
| ) | |
| def build_script(petition: str) -> str: | |
| """The full BUILD JSON string for a petition. Deterministic: same | |
| petition (modulo case/whitespace) always yields the same permit.""" | |
| petition = (petition or "").strip() or "a small building" | |
| rng = random.Random(_seed_for(petition)) | |
| for pattern, builder in _CATEGORIES: | |
| if pattern.search(petition): | |
| return json.dumps(builder(petition, rng), ensure_ascii=False) # type: ignore[operator] | |
| return json.dumps(_default(petition, rng), ensure_ascii=False) | |
| _CANDIDATE_LINE_RE = re.compile(r"-\s*(F\d+):\s*([^\n(]*)\(predicted index (\d+)\)") | |
| _TRAFFIC_INDEX_RE = re.compile(r'"traffic_index"\s*:\s*(\d+)') | |
| _WORST_RE = re.compile(r'"worst"\s*:\s*"([^"]{1,48})"') | |
| def fix_script(prompt: str) -> str: | |
| """The FIX JSON string, built from the candidates/numbers rendered into | |
| the fix prompt by mind/prompts.py. Picks the lowest predicted index.""" | |
| text = str(prompt or "") | |
| m = _WORST_RE.search(text) | |
| worst = m.group(1) if m else "the worst crossing" | |
| ti = _TRAFFIC_INDEX_RE.search(text) | |
| pairs = _CANDIDATE_LINE_RE.findall(text) | |
| if pairs: | |
| cid, desc, pred = min(pairs, key=lambda p: int(p[2])) | |
| desc = " ".join(desc.split()).rstrip(" ,") or "the engine's bypass" | |
| if ti: | |
| diagnosis = ( | |
| f"Index {ti.group(1)} with {worst} over capacity; " | |
| f"{cid} ({desc}) brings the predicted index to {pred}." | |
| ) | |
| else: | |
| diagnosis = f"{worst} is over capacity; {cid} ({desc}) brings the predicted index to {pred}." | |
| else: | |
| m = re.search(r"\b(F\d+)\b", text) | |
| cid = m.group(1) if m else "F1" | |
| diagnosis = f"{worst} runs over capacity; applying {cid}." | |
| blurb = f"CITY ENGINEER: relief ordered for {worst}." | |
| return json.dumps( | |
| {"diagnosis": diagnosis[:160], "choice": cid, "blurb": blurb[:120]}, | |
| ensure_ascii=False, | |
| ) | |