godverse_town.py marries a donor OSM cache's roads[] with thriftgod's DealGod-scraped shop census (2,928 real AU secondhand shops) -> <town>_godverse.json, schema v2 unchanged. First artifact newtown_godverse boots clean (?plansrc=osm&town=newtown_godverse). Lane brief + asks (Draco ruling, per-town bookmarks, enterShop selector) in docs/LANES/LANE_G_GODVERSE.md + G-progress.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
52 lines
2.4 KiB
Python
52 lines
2.4 KiB
Python
#!/usr/bin/env python3
|
|
"""Lane G — GODVERSE town adapter: thriftgod's REAL shop census -> a procity-town-cache/2.
|
|
|
|
Marries the two halves: roads[] come from an existing OSM cache (Lane E's build_towns.py),
|
|
shops[] come from thriftgod's Postgres (the real-business census DealGod scraped). Result:
|
|
walk the town's actual streets past its actual secondhand shops.
|
|
|
|
python3 pipeline/godverse_town.py newtown_real newtown_godverse # roads-donor key, out key
|
|
|
|
Runs on ultra (needs the local `thriftgod` PG + psycopg2 — the thriftgod server's own deps).
|
|
"""
|
|
import json, os, sys
|
|
|
|
import psycopg2, psycopg2.extras
|
|
|
|
DONOR, OUT = sys.argv[1], sys.argv[2]
|
|
HERE = os.path.dirname(os.path.abspath(__file__))
|
|
TOWNS = os.path.join(HERE, '..', 'web', 'assets', 'towns')
|
|
|
|
# thriftgod shop_type -> procity SHOP_TYPES (registry.js is the vocabulary of record)
|
|
TYPE_MAP = {'music': 'record', 'charity': 'opshop', 'second_hand': 'opshop', 'antiques': 'opshop',
|
|
'books': 'book', 'toys': 'toy', 'video_games': 'video', 'games': 'toy',
|
|
'pawnbroker': 'pawn', 'market': 'dept'}
|
|
|
|
donor = json.load(open(os.path.join(TOWNS, f'{DONOR}.json')))
|
|
bb = donor['bbox']
|
|
db = psycopg2.connect(os.environ.get('THRIFTGOD_DSN', 'dbname=thriftgod'))
|
|
c = db.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
|
c.execute("""SELECT id, name, shop_type, lat, lng, suburb FROM shop
|
|
WHERE lat BETWEEN %s AND %s AND lng BETWEEN %s AND %s ORDER BY id""",
|
|
(bb['minLat'], bb['maxLat'], bb['minLon'], bb['maxLon']))
|
|
shops = [{'id': r['id'], 'name': r['name'],
|
|
'type': TYPE_MAP.get(r['shop_type'], 'opshop'),
|
|
'lat': float(r['lat']), 'lon': float(r['lng']),
|
|
'suburb': (r['suburb'] or '').split('|')[0]} for r in c.fetchall()]
|
|
|
|
out = dict(donor)
|
|
out.update({
|
|
'key': OUT,
|
|
'town': donor['town'],
|
|
'source': 'godverse+osm', # shops = thriftgod census, roads = OSM (donor)
|
|
'generator': 'pipeline/godverse_town.py',
|
|
'attribution': donor['attribution'] + ' · shop census: GODVERSE/thriftgod',
|
|
'shops': shops,
|
|
'counts': {**donor.get('counts', {}), 'shops': len(shops)},
|
|
})
|
|
dst = os.path.join(TOWNS, f'{OUT}.json')
|
|
json.dump(out, open(dst, 'w'), indent=1)
|
|
types = {}
|
|
for s in shops: types[s['type']] = types.get(s['type'], 0) + 1
|
|
print(f"{OUT}: {len(shops)} REAL shops ({types}) + {len(out.get('roads', []))} OSM roads -> {dst}")
|