map now working
This commit is contained in:
@@ -25,6 +25,33 @@ def simplify_track(
|
||||
return [p for (p, _, _), keep in zip(gps_pts, mask) if keep]
|
||||
|
||||
|
||||
def preview_coords(
|
||||
points: list[DataPoint],
|
||||
max_points: int = 20,
|
||||
) -> list[list[float]] | None:
|
||||
"""Return a small list of [lat, lon] pairs for card thumbnail rendering.
|
||||
|
||||
Uses a coarser RDP pass, then subsamples to at most max_points.
|
||||
Returns None if there is no GPS data.
|
||||
"""
|
||||
gps = [(p.lat, p.lon) for p in points if p.lat is not None and p.lon is not None]
|
||||
if len(gps) < 2:
|
||||
return None
|
||||
|
||||
# Coarse RDP (larger epsilon = fewer points)
|
||||
coords = [[lon, lat] for lat, lon in gps]
|
||||
mask = rdp(coords, epsilon=0.001, return_mask=True)
|
||||
reduced = [gps[i] for i, keep in enumerate(mask) if keep]
|
||||
|
||||
# Subsample if still too many
|
||||
if len(reduced) > max_points:
|
||||
step = len(reduced) / max_points
|
||||
reduced = [reduced[int(i * step)] for i in range(max_points)]
|
||||
reduced.append(gps[-1]) # always include the last point
|
||||
|
||||
return [[round(lat, 5), round(lon, 5)] for lat, lon in reduced]
|
||||
|
||||
|
||||
def build_geojson(
|
||||
points: list[DataPoint],
|
||||
activity_id: str,
|
||||
|
||||
@@ -7,7 +7,7 @@ from pathlib import Path
|
||||
|
||||
from bincio.extract.metrics import ComputedMetrics
|
||||
from bincio.extract.models import LapData, ParsedActivity
|
||||
from bincio.extract.simplify import build_geojson
|
||||
from bincio.extract.simplify import build_geojson, preview_coords
|
||||
from bincio.extract.timeseries import build_timeseries
|
||||
|
||||
|
||||
@@ -119,6 +119,8 @@ def build_summary(
|
||||
"privacy": privacy,
|
||||
"detail_url": f"activities/{activity_id}.json",
|
||||
"track_url": f"activities/{activity_id}.geojson" if has_gps else None,
|
||||
# Small track preview for card thumbnails — no separate fetch needed
|
||||
"preview_coords": preview_coords(activity.points) if has_gps else None,
|
||||
}
|
||||
|
||||
|
||||
|
||||
+141
-9
@@ -1,4 +1,10 @@
|
||||
"""bincio render — CLI command (stub, Astro stage TBD)."""
|
||||
"""bincio render — build or serve the Astro static site."""
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
import click
|
||||
from rich.console import Console
|
||||
@@ -6,13 +12,139 @@ from rich.console import Console
|
||||
console = Console()
|
||||
|
||||
|
||||
def _find_site_dir(explicit: Optional[str]) -> Path:
|
||||
"""Locate the Astro project directory."""
|
||||
if explicit:
|
||||
p = Path(explicit).expanduser().resolve()
|
||||
if not (p / "package.json").exists():
|
||||
raise click.UsageError(f"No package.json found in --site-dir {p}")
|
||||
return p
|
||||
|
||||
# Search upward from cwd: ./site, ../site (for when cwd is bincio_data/)
|
||||
for candidate in [Path.cwd() / "site", Path.cwd().parent / "site"]:
|
||||
if (candidate / "package.json").exists():
|
||||
return candidate
|
||||
|
||||
raise click.UsageError(
|
||||
"Could not find the Astro site directory. "
|
||||
"Run from the project root or pass --site-dir."
|
||||
)
|
||||
|
||||
|
||||
def _find_data_dir(explicit: Optional[str], config_path: Optional[str]) -> Path:
|
||||
"""Resolve the BAS data directory."""
|
||||
if explicit:
|
||||
return Path(explicit).expanduser().resolve()
|
||||
|
||||
if config_path and Path(config_path).exists():
|
||||
import yaml
|
||||
raw = yaml.safe_load(Path(config_path).read_text())
|
||||
out = raw.get("output", {}).get("dir")
|
||||
if out:
|
||||
return Path(out).expanduser().resolve()
|
||||
|
||||
# Default: ./bincio_data next to cwd
|
||||
default = Path.cwd() / "bincio_data"
|
||||
if default.exists():
|
||||
return default
|
||||
|
||||
raise click.UsageError(
|
||||
"Could not find the BAS data directory. "
|
||||
"Run `bincio extract` first, or pass --data-dir."
|
||||
)
|
||||
|
||||
|
||||
def _ensure_npm(site: Path) -> None:
|
||||
"""Run `npm install` if node_modules is missing or stale."""
|
||||
if not (site / "node_modules").exists():
|
||||
console.print("Running [cyan]npm install[/cyan]…")
|
||||
subprocess.run(["npm", "install"], cwd=site, check=True)
|
||||
|
||||
|
||||
def _link_data(site: Path, data: Path) -> None:
|
||||
"""Symlink the BAS data store into site/public/data."""
|
||||
public_data = site / "public" / "data"
|
||||
if public_data.is_symlink():
|
||||
if public_data.resolve() == data:
|
||||
return # already correct
|
||||
public_data.unlink()
|
||||
elif public_data.exists():
|
||||
console.print(
|
||||
f"[yellow]Warning:[/yellow] {public_data} exists and is not a symlink — "
|
||||
"remove it manually if you want bincio to manage it."
|
||||
)
|
||||
return
|
||||
public_data.symlink_to(data)
|
||||
console.print(f"Linked data: [cyan]{data}[/cyan] → [cyan]{public_data}[/cyan]")
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.option("--config", "config_path", default="site_config.yaml")
|
||||
@click.option("--out", "out_dir", default="./site/dist")
|
||||
@click.option("--serve", is_flag=True, help="Start dev server with hot reload.")
|
||||
@click.option("--config", "config_path", default=None,
|
||||
help="Path to extract_config.yaml (reads output.dir from it).")
|
||||
@click.option("--data-dir", default=None,
|
||||
help="BAS data store directory (output of bincio extract).")
|
||||
@click.option("--site-dir", default=None,
|
||||
help="Astro project directory (default: ./site).")
|
||||
@click.option("--out", "out_dir", default=None,
|
||||
help="Build output directory (default: site/dist).")
|
||||
@click.option("--serve", is_flag=True,
|
||||
help="Start dev server with hot reload instead of building.")
|
||||
@click.option("--deploy", default=None, metavar="TARGET",
|
||||
help="Deploy target: 'github'.")
|
||||
def render(config_path: str, out_dir: str, serve: bool, deploy: str | None) -> None:
|
||||
"""Generate static site from BAS data store (Astro stage — coming soon)."""
|
||||
console.print("[yellow]bincio render is not yet implemented.[/yellow]")
|
||||
console.print("The web renderer (Astro + MapLibre + Observable Plot) is next.")
|
||||
help="Deploy after build. Currently supports: github.")
|
||||
def render(
|
||||
config_path: Optional[str],
|
||||
data_dir: Optional[str],
|
||||
site_dir: Optional[str],
|
||||
out_dir: Optional[str],
|
||||
serve: bool,
|
||||
deploy: Optional[str],
|
||||
) -> None:
|
||||
"""Build (or serve) the BincioActivity static site from a BAS data store."""
|
||||
|
||||
site = _find_site_dir(site_dir)
|
||||
data = _find_data_dir(data_dir, config_path)
|
||||
|
||||
console.print(f"Site: [cyan]{site}[/cyan]")
|
||||
console.print(f"Data: [cyan]{data}[/cyan]")
|
||||
|
||||
_ensure_npm(site)
|
||||
_link_data(site, data)
|
||||
|
||||
env = {**os.environ, "BINCIO_DATA_DIR": str(data)}
|
||||
|
||||
if serve:
|
||||
console.print("Starting [cyan]astro dev[/cyan]…")
|
||||
subprocess.run(["npm", "run", "dev"], cwd=site, env=env)
|
||||
return
|
||||
|
||||
# Build
|
||||
cmd = ["npm", "run", "build"]
|
||||
if out_dir:
|
||||
# Pass outDir via Astro CLI flag
|
||||
cmd = ["npx", "astro", "build", "--outDir", str(Path(out_dir).resolve())]
|
||||
|
||||
console.print("Running [cyan]astro build[/cyan]…")
|
||||
result = subprocess.run(cmd, cwd=site, env=env)
|
||||
if result.returncode != 0:
|
||||
console.print("[red]Build failed.[/red]")
|
||||
sys.exit(result.returncode)
|
||||
|
||||
dist = Path(out_dir).resolve() if out_dir else site / "dist"
|
||||
console.print(f"\n[green]Build complete.[/green] Output: [cyan]{dist}[/cyan]")
|
||||
|
||||
if deploy == "github":
|
||||
_deploy_github(site, dist)
|
||||
|
||||
|
||||
def _deploy_github(site: Path, dist: Path) -> None:
|
||||
"""Push dist/ to the gh-pages branch."""
|
||||
console.print("Deploying to [cyan]GitHub Pages[/cyan]…")
|
||||
# Requires npx gh-pages or git subtree push
|
||||
result = subprocess.run(
|
||||
["npx", "gh-pages", "-d", str(dist)],
|
||||
cwd=site,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
console.print(
|
||||
"[yellow]Tip:[/yellow] install gh-pages with `npm install -g gh-pages`"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user