Files
maps-saas/infrastructure/scripts/build-valhalla-tiles.sh
T

180 lines
6.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# ============================================================================
# بناء حزمة التوجيه المحلية (Valhalla Routing Package) للأردن
# ============================================================================
# English:
# Builds an on-device Valhalla routing package for Jordan from the same OSM
# data used by the server-side GraphHopper engine, with real SRTM elevation
# baked into every edge (grade/ascend/descend), admin street context, and a
# tile extract tar that the tactical app downloads and routes against 100%
# offline via valhalla-mobile.
#
# Output: infrastructure/osm-data/routing-packages/
# - jordan-valhalla-<version>.tar (valhalla_tiles.tar + admins.sqlite)
# - jordan-routing-manifest.json (version, sha256, sizeBytes, builtAt)
#
# Runs in two modes:
# 1. Host mode : ./infrastructure/scripts/build-valhalla-tiles.sh (needs docker)
# 2. Container : docker compose --profile tiles run --rm valhalla-tiles
# ============================================================================
set -euo pipefail
VERSION="${JORDAN_ROUTING_VERSION:-jordan-1.0.0-$(date +%Y%m%d)}"
VALHALLA_IMG="ghcr.io/valhalla/valhalla:latest"
# Jordan bounding box with a small buffer so border corridors connect cleanly.
S=29.05; W=34.75; N=32.80; E=39.45
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
ROOT="$( cd "$SCRIPT_DIR/../.." && pwd )"
IN_CONTAINER=false
if [ -f /.dockerenv ] || [ "${VALHALLA_IN_CONTAINER:-0}" = "1" ]; then
IN_CONTAINER=true
fi
if [ "$IN_CONTAINER" = true ]; then
# Compose mounts ./infrastructure/osm-data at /data
DATA_DIR="/data"
else
DATA_DIR="$ROOT/infrastructure/osm-data"
fi
OUT_DIR="$DATA_DIR/routing-packages"
WORK_DIR="$DATA_DIR/valhalla-work"
MASTER_PBF="$DATA_DIR/master_map.osm.pbf"
log() { echo "🧭 $1"; }
run_vh() {
# Run a command inside the valhalla toolchain (locally or through docker).
if [ "$IN_CONTAINER" = true ]; then
bash -c "$1"
else
docker run --rm -v "$DATA_DIR":/data -w /data --entrypoint bash "$VALHALLA_IMG" -lc "$1"
fi
}
if [ ! -f "$MASTER_PBF" ]; then
echo "❌ master_map.osm.pbf not found at: $MASTER_PBF" >&2
echo " ضع ملف OSM المدمج في infrastructure/osm-data/master_map.osm.pbf أولاً." >&2
exit 1
fi
mkdir -p "$OUT_DIR" "$WORK_DIR"
log "[1/6] Cutting Jordan extract ($W,$S → $E,$N) ..."
if run_vh 'command -v osmium >/dev/null 2>&1' 2>/dev/null; then
run_vh "osmium extract --bbox $W,$S,$E,$N --strategy smart --overwrite \
/data/master_map.osm.pbf -o /data/valhalla-work/jordan_routing.osm.pbf"
else
log " osmium غير متوفر — جاري استخدام مستخرج Geofabrik للأردن (نفس مصدر OSM)."
curl -fL --retry 3 "https://download.geofabrik.de/asia/jordan-latest.osm.pbf" \
-o "$WORK_DIR/jordan_routing.osm.pbf"
fi
log "[2/6] Generating config + downloading SRTM elevation for Jordan ..."
run_vh '
set -euo pipefail
cd /data/valhalla-work
mkdir -p /data/valhalla-work/valhalla_tiles /data/valhalla-work/elevation
valhalla_build_config \
--mjolnir-tile-dir /data/valhalla-work/valhalla_tiles \
--mjolnir-concurrency "$(nproc)" \
--mjolnir-tile-extract /data/valhalla-work/valhalla_tiles.tar \
--mjolnir-admin /data/valhalla-work/admins.sqlite \
--additional-data-elevation /data/valhalla-work/elevation \
> /data/valhalla-work/valhalla.json
# SRTM 30m elevation for Jordan bbox
valhalla_build_elevation -c /data/valhalla-work/valhalla.json -b 34.75,29.05,39.45,32.80 || true
'
log "[3/6] Building admin database (governorate/street context) ..."
run_vh 'valhalla_build_admins --config /data/valhalla-work/valhalla.json /data/valhalla-work/jordan_routing.osm.pbf'
log "[4/6] Building routing graph tiles (roads + oneway + elevation grades) ..."
run_vh 'valhalla_build_tiles --config /data/valhalla-work/valhalla.json -j "$(nproc)" /data/valhalla-work/jordan_routing.osm.pbf'
log "[5/6] Creating tile extract (tar) and verifying a test route ..."
run_vh '
set -euo pipefail
cd /data/valhalla-work
rm -f /data/valhalla-work/valhalla_tiles.tar
valhalla_build_extract --config /data/valhalla-work/valhalla.json -v --overwrite
# فحص سلامة: عمان ← العقبة يجب أن ينجح بالكامل على الغراف المحلي.
valhalla_service /data/valhalla-work/valhalla.json route \
"{\"locations\":[{\"lat\":31.9539,\"lon\":35.9106},{\"lat\":29.5320,\"lon\":35.0060}],\"costing\":\"auto\",\"units\":\"kilometers\",\"directions_options\":{\"language\":\"ar\"}}" \
> /data/valhalla-work/test_route.json 2>/dev/null || true
python3 - <<'PY'
import json, sys
try:
with open("/data/valhalla-work/test_route.json") as f:
d = json.load(f)
t = d.get("trip", {})
status = t.get("status")
msg = t.get("status_message", "unknown error")
if status == 0:
dist = round(t.get("summary", {}).get("length", 0), 1)
maneuvers = sum(len(l.get("maneuvers", [])) for l in t.get("legs", []))
print(f" ✅ test route OK: {dist} km | {maneuvers} maneuvers")
else:
print(f" ⚠️ test route status: {status} ({msg})")
except Exception as e:
print(f" ℹ️ test route check note: {e}")
PY
'
log "[5.5/6] Extracting road graph (jordan_roads.db) for on-device SQLite routing ..."
PY_SCRIPT="$SCRIPT_DIR/extract_roads_graph.py"
if [ ! -f "$PY_SCRIPT" ] && [ -f "$DATA_DIR/../infrastructure/scripts/extract_roads_graph.py" ]; then
PY_SCRIPT="$DATA_DIR/../infrastructure/scripts/extract_roads_graph.py"
fi
if [ -f "$PY_SCRIPT" ]; then
python3 "$PY_SCRIPT" "$WORK_DIR/jordan_routing.osm.pbf" "$WORK_DIR/jordan_roads.db" || true
fi
log "[6/6] Packaging + manifest ..."
FINAL_TAR="$OUT_DIR/jordan-valhalla-$VERSION.tar"
rm -f "$FINAL_TAR"
PACK_ITEMS="valhalla_tiles.tar admins.sqlite"
if [ -f "$WORK_DIR/jordan_roads.db" ]; then
PACK_ITEMS="$PACK_ITEMS jordan_roads.db"
log " Included jordan_roads.db in package."
fi
tar -cf "$FINAL_TAR" -C "$WORK_DIR" $PACK_ITEMS
if [ "$IN_CONTAINER" = false ]; then
SIZE=$(stat -f%z "$FINAL_TAR" 2>/dev/null || stat -c%s "$FINAL_TAR")
SHA256=$(shasum -a 256 "$FINAL_TAR" | awk '{print $1}')
else
SIZE=$(wc -c < "$FINAL_TAR" | tr -d " ")
SHA256=$(sha256sum "$FINAL_TAR" | awk "{print \$1}")
fi
cat > "$OUT_DIR/jordan-routing-manifest.json" <<MANIFEST
{
"packageId": "jordan-valhalla-routing",
"version": "$VERSION",
"fileName": "jordan-valhalla-$VERSION.tar",
"sizeBytes": $SIZE,
"sha256": "$SHA256",
"engine": "valhalla",
"elevation": "srtm-30m",
"bbox": {"south": $S, "west": $W, "north": $N, "east": $E},
"builtAt": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
}
MANIFEST
chmod -R a+rwX "$OUT_DIR" 2>/dev/null || true
rm -rf "$WORK_DIR"
echo ""
echo "✅ Done. حزمة التوجيه المحلية جاهزة:"
ls -lh "$FINAL_TAR" "$OUT_DIR/jordan-routing-manifest.json"