-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmap_writer.py
More file actions
76 lines (61 loc) · 2.62 KB
/
Copy pathmap_writer.py
File metadata and controls
76 lines (61 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
"""Write the active POI map configuration safely."""
from __future__ import annotations
import json
from pathlib import Path
from threading import Lock
from typing import Any
REPO_ROOT = Path(__file__).resolve().parent
MAP_ROOT = REPO_ROOT / "threejs-poi-map-demo"
MAP_IMAGES_ROOT = MAP_ROOT / "images"
MAP_CONFIG_PATH = MAP_ROOT / "config.js"
GROUND_MAP_PATH = MAP_IMAGES_ROOT / "ground-map.png"
_config_lock = Lock()
_ground_map_lock = Lock()
def write_active_map(
*,
latitude: float,
longitude: float,
radius_m: int,
mood: str,
mood_text: str,
recommendation: str,
pois: list[dict[str, Any]],
ground_map_url: str | None = None,
) -> None:
"""Atomically replace the active, location-scoped map data.
A map represents one user location at a time. Replacing the JSON payload
prevents stale POIs from earlier locations from leaking outside its radius.
"""
MAP_IMAGES_ROOT.mkdir(parents=True, exist_ok=True)
payload = {
"origin": {"lat": latitude, "lon": longitude},
"radius_m": radius_m,
"mood": mood,
# The raw text the user typed/spoke, as opposed to `mood` (the short resolved
# label like "hungry" used for prompt-building). The mood textarea restores
# from this on page load -- without it, the full-page reload after every real
# search re-parsed index.html's hardcoded default textarea content and silently
# overwrote whatever the user had actually typed.
"mood_text": mood_text,
"recommendation": recommendation,
"pois": pois,
"ground_map_url": ground_map_url,
}
source = "window.POI_MAP_CONFIG = " + json.dumps(payload, indent=2, ensure_ascii=False) + ";\n"
temporary_path = MAP_CONFIG_PATH.with_suffix(".tmp")
with _config_lock:
temporary_path.write_text(source, encoding="utf-8")
temporary_path.replace(MAP_CONFIG_PATH)
def write_ground_map_image(image_bytes: bytes) -> None:
"""Atomically replace the ground-plane satellite/street overlay image."""
MAP_IMAGES_ROOT.mkdir(parents=True, exist_ok=True)
temporary_path = GROUND_MAP_PATH.with_suffix(".tmp")
with _ground_map_lock:
temporary_path.write_bytes(image_bytes)
temporary_path.replace(GROUND_MAP_PATH)
def image_path_for(poi_id: str) -> Path:
safe_id = "".join(character.lower() if character.isalnum() else "-" for character in poi_id)
safe_id = "-".join(part for part in safe_id.split("-") if part)[:72] or "poi"
return MAP_IMAGES_ROOT / f"generated-{safe_id}.png"
def map_image_url(path: Path) -> str:
return path.resolve().relative_to(MAP_ROOT.resolve()).as_posix()