#!/bin/bash # -------------------------------------------------------------------------- # verify-oneway.sh — يتحقق أن محرك التوجيه يحترم اتجاهات السير # # يختار طرقاً موسومة oneway=yes من البيانات نفسها، ويطلب مساراً على كل منها # في الاتجاهين. على طريق أحادي سليم يجب أن تختلف المسافتان (العودة تحتاج # التفافاً). التطابق التام = المحرك يتجاهل oneway. # # السبب المعتاد للفشل: سقوط قاعدة "!car_access → 0" من custom_model. # التفاصيل الكاملة: docs/ROUTING_ONEWAY_AR.md # # bash infrastructure/scripts/verify-oneway.sh # # متغيّرات: GH_URL (افتراضي http://localhost:8989)، BBOX، SAMPLES # -------------------------------------------------------------------------- set -uo pipefail APP_DIR="${APP_DIR:-/home/hamzadoctor/app}" GH_URL="${GH_URL:-http://localhost:8989}" PBF="${PBF:-${APP_DIR}/infrastructure/osm-data/master_map.osm.pbf}" BBOX="${BBOX:-36.055,32.100,36.072,32.116}" # lon1,lat1,lon2,lat2 SAMPLES="${SAMPLES:-8}" command -v osmium >/dev/null || { echo "❌ osmium غير مثبّت: apt-get install -y osmium-tool"; exit 2; } [ -f "$PBF" ] || { echo "❌ الملف غير موجود: $PBF"; exit 2; } curl -fsS "$GH_URL/health" >/dev/null || { echo "❌ المحرك لا يستجيب على $GH_URL"; exit 2; } TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT osmium extract -b "$BBOX" "$PBF" -o "$TMP/area.pbf" --overwrite >/dev/null 2>&1 osmium tags-filter "$TMP/area.pbf" w/oneway=yes -o "$TMP/ow.pbf" --overwrite >/dev/null 2>&1 osmium export -f geojson "$TMP/ow.pbf" -o "$TMP/ow.geojson" --overwrite >/dev/null 2>&1 GH_URL="$GH_URL" SAMPLES="$SAMPLES" python3 - "$TMP/ow.geojson" <<'PY' import json, os, sys, urllib.request gh = os.environ["GH_URL"] want = int(os.environ["SAMPLES"]) def route(a, b): u = f"{gh}/route?point={a}&point={b}&profile=car" try: return round(json.load(urllib.request.urlopen(u, timeout=20))["paths"][0]["distance"]) except Exception: return None feats = json.load(open(sys.argv[1]))["features"] print("═" * 60) print(" فحص احترام اتجاهات السير — " + gh) print("═" * 60) tested = identical = 0 for f in feats: if tested >= want: break g = f["geometry"] if g["type"] != "LineString" or len(g["coordinates"]) < 2: continue c = g["coordinates"] a = f"{c[0][1]:.7f},{c[0][0]:.7f}" b = f"{c[-1][1]:.7f},{c[-1][0]:.7f}" fwd, rev = route(a, b), route(b, a) if fwd is None or rev is None or fwd == 0: continue tested += 1 name = (f["properties"].get("name") or "بلا اسم")[:24] # المعيار هو الاختلاف لا نسبته: الالتفاف قد يكون صغيراً نسبياً على مقطع طويل ok = fwd != rev identical += (not ok) print(f" {name:24} ذهاب:{fwd:6d}م عودة:{rev:6d}م {'✅' if ok else '❌ متطابق'}") print() if tested == 0: print("⚠️ لم يُعثر على طرق أحادية صالحة للاختبار — راجع BBOX أو البيانات.") sys.exit(2) if identical: print(f"❌ فشل: {identical} من {tested} طريقاً أحادياً يُخترق — المحرك يتجاهل oneway.") print(" الأرجح: سقوط قاعدة '!car_access → 0' من custom_model في config.yml") print(" اقرأ: docs/ROUTING_ONEWAY_AR.md") sys.exit(1) print(f"✅ نجح: {tested} طريقاً أحادياً، كلها محترمة الاتجاه.") PY