diff --git a/pxy_dashboard/middleware.py b/pxy_dashboard/middleware.py index 001d34d..7d8b116 100644 --- a/pxy_dashboard/middleware.py +++ b/pxy_dashboard/middleware.py @@ -136,6 +136,10 @@ EXEMPT_URLS += [ re.compile(r"^api/stewards/health$"), ] +EXEMPT_URLS += [ + re.compile(r"^simulations/mvp/?$"), +] + class LoginRequiredMiddleware(MiddlewareMixin): diff --git a/pxy_simulations/templates/pxy_simulations/simulation_mvp.html b/pxy_simulations/templates/pxy_simulations/simulation_mvp.html index dfc8ae3..4a0ac5c 100644 --- a/pxy_simulations/templates/pxy_simulations/simulation_mvp.html +++ b/pxy_simulations/templates/pxy_simulations/simulation_mvp.html @@ -228,6 +228,34 @@ statusEl.textContent = text; } + function applyQueryParams() { + const params = new URLSearchParams(window.location.search); + const lat = params.get("lat"); + const lon = params.get("lon"); + const dist = params.get("dist"); + const residents = params.get("residents"); + const services = params.get("services"); + const speed = params.get("speed"); + const radius = params.get("radius"); + const auto = params.get("auto"); + + if (lat) inputLat.value = lat; + if (lon) inputLon.value = lon; + if (dist) inputDist.value = dist; + if (residents) inputResidents.value = residents; + if (services) inputServices.value = services; + if (speed) inputSpeed.value = speed; + if (radius) inputRadius.value = radius; + + if (auto === "1") { + setTimeout(() => { + btnNew.click(); + }, 400); + } + } + + applyQueryParams(); + function mercatorToLon(x) { return (x / R) * (180 / Math.PI); } diff --git a/pxy_stewards/api/views.py b/pxy_stewards/api/views.py index 8d00121..57d0a65 100644 --- a/pxy_stewards/api/views.py +++ b/pxy_stewards/api/views.py @@ -2,6 +2,7 @@ import json import os from datetime import timedelta from typing import Any, Dict, Optional +from urllib.parse import urlencode from django.http import JsonResponse, HttpRequest from django.utils import timezone @@ -10,6 +11,7 @@ from django.views.decorators.http import require_GET, require_http_methods from pxy_stewards.models import Stewardship, StewardBlessing, StewardSignal from pxy_stewards.utils import encode_geohash +from core.urlbuild import public_url STEWARD_TTL_HOURS = int(os.getenv("STEWARD_TTL_HOURS", "168")) @@ -123,6 +125,18 @@ def _activation_buttons() -> list: return buttons +def _simulation_url(request: HttpRequest, steward: Stewardship) -> str: + lat = steward.lat if steward.lat is not None else 19.4326 + lon = steward.lon if steward.lon is not None else -99.1332 + params = { + "lat": f"{lat:.6f}", + "lon": f"{lon:.6f}", + "dist": "700", + "auto": "1", + } + return f"{public_url('/simulations/mvp/', request)}?{urlencode(params)}" + + @csrf_exempt @require_http_methods(["POST"]) def steward_handle(request: HttpRequest): @@ -233,15 +247,17 @@ def steward_handle(request: HttpRequest): ends_at__gt=timezone.now(), ).count() remaining = int((steward.expires_at - timezone.now()).total_seconds() / 3600) if steward.expires_at else 0 + sim_url = _simulation_url(request, steward) text = ( f"Steward status\n" f"Cell: {steward.geohash}\n" f"Target bot: {steward.target_bot}\n" f"Energy: {steward.energy}/{STEWARD_ENERGY_MAX}\n" f"Blessings active: {active_bless}\n" - f"Power window: {remaining}h" + f"Power window: {remaining}h\n" + f"Simulation: {sim_url}" ) - return _render_text(text) + return _render_text(text, buttons=[{"label": "Open Simulation", "kind": "open_url", "url": sim_url}]) if cmd == "bless": if steward.status != Stewardship.STATUS_ACTIVE or not steward.geohash: