#!/usr/bin/env python3 import argparse import json import os from collections import Counter import psycopg2 DB_NAME = "data_centers" POINT_TABLE = "public.master_data_centers" def connect(): return psycopg2.connect( host=os.environ["PGWEB_HOST"], port=os.environ["PGWEB_PORT"], user=os.environ["PGWEB_USER"], password=os.environ["PGWEB_PASSWORD"], dbname=DB_NAME, ) def load_points(conn): with conn.cursor() as cur: cur.execute( f""" select master_id, source, coalesce(operator, '') as operator, coalesce(name, '') as name, coalesce(city, '') as city, coalesce(state, '') as state, longitude, latitude, coalesce(curated_id, '') as curated_id, coalesce(osm_id, '') as osm_id, coalesce(match_method, '') as match_method, coalesce(geoid, '') as geoid from {POINT_TABLE} where longitude is not null and latitude is not null """ ) rows = cur.fetchall() points = [] for row in rows: points.append( { "id": row[0], "source": row[1], "operator": row[2], "name": row[3], "city": row[4], "state": row[5], "lon": float(row[6]), "lat": float(row[7]), "curated_id": row[8], "osm_id": row[9], "match_method": row[10], "geoid": row[11], } ) return points def compute_center(points): if not points: return 39.5, -98.35 lat = sum(p["lat"] for p in points) / len(points) lon = sum(p["lon"] for p in points) / len(points) return lat, lon def build_stats(points): by_source = Counter(p["source"] or "(blank)" for p in points) by_match = Counter(p["match_method"] or "(none)" for p in points) return { "total": len(points), "by_source": dict(sorted(by_source.items(), key=lambda x: x[0])), "by_match_method": dict(sorted(by_match.items(), key=lambda x: x[0])), } def render_html(points, center_lat, center_lon, output_path): stats = build_stats(points) points_json = json.dumps(points) stats_json = json.dumps(stats) html = f"""