@ingissa/navcore-core 1.0.3 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Coordinate, g as NavCoreState } from './NavCore.d-BuXR5DO7.js';
2
- export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, o as destinationPoint, p as geoGetBearing, q as haversineDistance } from './NavCore.d-BuXR5DO7.js';
1
+ import { C as Coordinate, g as NavCoreState } from './NavCore-DzTPBxIc.js';
2
+ export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, o as destinationPoint, p as geoGetBearing, q as haversineDistance } from './NavCore-DzTPBxIc.js';
3
3
 
4
4
  /**
5
5
  * Bearing and angular math utilities.
@@ -281,6 +281,10 @@ interface OSRMConfig {
281
281
  profile?: 'driving' | 'cycling' | 'walking';
282
282
  /** Max waypoints per API request (OSRM supports unlimited, but chunking keeps requests fast) */
283
283
  maxWaypointsPerChunk?: number;
284
+ /** Optional fetch implementation for tests, React Native, or custom runtimes */
285
+ fetchFn?: typeof fetch;
286
+ /** Request timeout in milliseconds. Set to 0 to disable. */
287
+ timeoutMs?: number;
284
288
  }
285
289
  declare class OSRMDirectionsProvider implements DirectionsProvider {
286
290
  private readonly config;
@@ -288,6 +292,7 @@ declare class OSRMDirectionsProvider implements DirectionsProvider {
288
292
  getRoute(waypoints: Coordinate[], options?: DirectionsOptions): Promise<DirectionsResult>;
289
293
  private fetchRoute;
290
294
  private fetchChunked;
295
+ private fetchWithTimeout;
291
296
  }
292
297
 
293
298
  /**
@@ -310,6 +315,10 @@ interface ValhallaConfig {
310
315
  apiKey?: string;
311
316
  /** Max waypoints per chunk (default: 50) */
312
317
  maxWaypointsPerChunk?: number;
318
+ /** Optional fetch implementation for tests, React Native, or custom runtimes */
319
+ fetchFn?: typeof fetch;
320
+ /** Request timeout in milliseconds. Set to 0 to disable. */
321
+ timeoutMs?: number;
313
322
  }
314
323
  declare class ValhallaDirectionsProvider implements DirectionsProvider {
315
324
  private readonly config;
@@ -319,7 +328,11 @@ declare class ValhallaDirectionsProvider implements DirectionsProvider {
319
328
  private fetchRoute;
320
329
  /** Decode Valhalla's encoded polyline6 format */
321
330
  private decodePolyline;
331
+ private stitchGeometry;
332
+ private sameCoordinate;
333
+ private shapeIndex;
322
334
  private fetchChunked;
335
+ private fetchWithTimeout;
323
336
  }
324
337
 
325
338
  /**
@@ -341,6 +354,10 @@ interface ORSConfig {
341
354
  baseUrl?: string;
342
355
  /** Max waypoints per request (ORS limit: 50) */
343
356
  maxWaypointsPerChunk?: number;
357
+ /** Optional fetch implementation for tests, React Native, or custom runtimes */
358
+ fetchFn?: typeof fetch;
359
+ /** Request timeout in milliseconds. Set to 0 to disable. */
360
+ timeoutMs?: number;
344
361
  }
345
362
  declare class OpenRouteServiceProvider implements DirectionsProvider {
346
363
  private readonly config;
@@ -349,6 +366,9 @@ declare class OpenRouteServiceProvider implements DirectionsProvider {
349
366
  private profileFromOptions;
350
367
  private fetchRoute;
351
368
  private fetchChunked;
369
+ private stepRange;
370
+ private bearingFromGeometry;
371
+ private fetchWithTimeout;
352
372
  }
353
373
 
354
374
  /**
@@ -454,35 +474,35 @@ declare const MIN_LOOK_AHEAD_METERS = 20;
454
474
  declare const MAX_LOOK_AHEAD_METERS = 100;
455
475
  declare const ARRIVAL_THRESHOLD_METERS = 30;
456
476
 
457
- declare const constants_d_ARRIVAL_THRESHOLD_METERS: typeof ARRIVAL_THRESHOLD_METERS;
458
- declare const constants_d_BASE_CORRIDOR_METERS: typeof BASE_CORRIDOR_METERS;
459
- declare const constants_d_BEARING_ALIGNMENT_THRESHOLD: typeof BEARING_ALIGNMENT_THRESHOLD;
460
- declare const constants_d_BEARING_MIN_SPEED_MPS: typeof BEARING_MIN_SPEED_MPS;
461
- declare const constants_d_BEARING_MISMATCH_PENALTY: typeof BEARING_MISMATCH_PENALTY;
462
- declare const constants_d_BEARING_MISMATCH_THRESHOLD: typeof BEARING_MISMATCH_THRESHOLD;
463
- declare const constants_d_BEARING_SMOOTHING_ALPHA: typeof BEARING_SMOOTHING_ALPHA;
464
- declare const constants_d_BETA_CORRECTION: typeof BETA_CORRECTION;
465
- declare const constants_d_DETOUR_COMMIT_MS: typeof DETOUR_COMMIT_MS;
466
- declare const constants_d_DR_MAX_AGE_MS: typeof DR_MAX_AGE_MS;
467
- declare const constants_d_GPS_ACCURACY_FACTOR: typeof GPS_ACCURACY_FACTOR;
468
- declare const constants_d_GPS_AGE_CAP_SECONDS: typeof GPS_AGE_CAP_SECONDS;
469
- declare const constants_d_GPS_STALE_MS: typeof GPS_STALE_MS;
470
- declare const constants_d_INERTIA_PENALTY: typeof INERTIA_PENALTY;
471
- declare const constants_d_INERTIA_SEGMENT_DIST: typeof INERTIA_SEGMENT_DIST;
472
- declare const constants_d_LOOK_AHEAD_SECONDS: typeof LOOK_AHEAD_SECONDS;
473
- declare const constants_d_MANEUVER_TRIGGER_DIST: typeof MANEUVER_TRIGGER_DIST;
474
- declare const constants_d_MAX_CORRIDOR_METERS: typeof MAX_CORRIDOR_METERS;
475
- declare const constants_d_MAX_LOOK_AHEAD_METERS: typeof MAX_LOOK_AHEAD_METERS;
476
- declare const constants_d_MAX_SNAP_DISTANCE: typeof MAX_SNAP_DISTANCE;
477
- declare const constants_d_MIN_LOOK_AHEAD_METERS: typeof MIN_LOOK_AHEAD_METERS;
478
- declare const constants_d_OFF_ROUTE_CONFIRM_MS: typeof OFF_ROUTE_CONFIRM_MS;
479
- declare const constants_d_REJOIN_CONFIRM_MS: typeof REJOIN_CONFIRM_MS;
480
- declare const constants_d_REJOIN_COOLDOWN_MS: typeof REJOIN_COOLDOWN_MS;
481
- declare const constants_d_SNAP_WINDOW_SIZE: typeof SNAP_WINDOW_SIZE;
482
- declare const constants_d_SPEED_CORRIDOR_FACTOR: typeof SPEED_CORRIDOR_FACTOR;
483
- declare const constants_d_STARTUP_GRACE_MS: typeof STARTUP_GRACE_MS;
484
- declare namespace constants_d {
485
- export { constants_d_ARRIVAL_THRESHOLD_METERS as ARRIVAL_THRESHOLD_METERS, constants_d_BASE_CORRIDOR_METERS as BASE_CORRIDOR_METERS, constants_d_BEARING_ALIGNMENT_THRESHOLD as BEARING_ALIGNMENT_THRESHOLD, constants_d_BEARING_MIN_SPEED_MPS as BEARING_MIN_SPEED_MPS, constants_d_BEARING_MISMATCH_PENALTY as BEARING_MISMATCH_PENALTY, constants_d_BEARING_MISMATCH_THRESHOLD as BEARING_MISMATCH_THRESHOLD, constants_d_BEARING_SMOOTHING_ALPHA as BEARING_SMOOTHING_ALPHA, constants_d_BETA_CORRECTION as BETA_CORRECTION, constants_d_DETOUR_COMMIT_MS as DETOUR_COMMIT_MS, constants_d_DR_MAX_AGE_MS as DR_MAX_AGE_MS, constants_d_GPS_ACCURACY_FACTOR as GPS_ACCURACY_FACTOR, constants_d_GPS_AGE_CAP_SECONDS as GPS_AGE_CAP_SECONDS, constants_d_GPS_STALE_MS as GPS_STALE_MS, constants_d_INERTIA_PENALTY as INERTIA_PENALTY, constants_d_INERTIA_SEGMENT_DIST as INERTIA_SEGMENT_DIST, constants_d_LOOK_AHEAD_SECONDS as LOOK_AHEAD_SECONDS, constants_d_MANEUVER_TRIGGER_DIST as MANEUVER_TRIGGER_DIST, constants_d_MAX_CORRIDOR_METERS as MAX_CORRIDOR_METERS, constants_d_MAX_LOOK_AHEAD_METERS as MAX_LOOK_AHEAD_METERS, constants_d_MAX_SNAP_DISTANCE as MAX_SNAP_DISTANCE, constants_d_MIN_LOOK_AHEAD_METERS as MIN_LOOK_AHEAD_METERS, constants_d_OFF_ROUTE_CONFIRM_MS as OFF_ROUTE_CONFIRM_MS, constants_d_REJOIN_CONFIRM_MS as REJOIN_CONFIRM_MS, constants_d_REJOIN_COOLDOWN_MS as REJOIN_COOLDOWN_MS, constants_d_SNAP_WINDOW_SIZE as SNAP_WINDOW_SIZE, constants_d_SPEED_CORRIDOR_FACTOR as SPEED_CORRIDOR_FACTOR, constants_d_STARTUP_GRACE_MS as STARTUP_GRACE_MS };
477
+ declare const constants_ARRIVAL_THRESHOLD_METERS: typeof ARRIVAL_THRESHOLD_METERS;
478
+ declare const constants_BASE_CORRIDOR_METERS: typeof BASE_CORRIDOR_METERS;
479
+ declare const constants_BEARING_ALIGNMENT_THRESHOLD: typeof BEARING_ALIGNMENT_THRESHOLD;
480
+ declare const constants_BEARING_MIN_SPEED_MPS: typeof BEARING_MIN_SPEED_MPS;
481
+ declare const constants_BEARING_MISMATCH_PENALTY: typeof BEARING_MISMATCH_PENALTY;
482
+ declare const constants_BEARING_MISMATCH_THRESHOLD: typeof BEARING_MISMATCH_THRESHOLD;
483
+ declare const constants_BEARING_SMOOTHING_ALPHA: typeof BEARING_SMOOTHING_ALPHA;
484
+ declare const constants_BETA_CORRECTION: typeof BETA_CORRECTION;
485
+ declare const constants_DETOUR_COMMIT_MS: typeof DETOUR_COMMIT_MS;
486
+ declare const constants_DR_MAX_AGE_MS: typeof DR_MAX_AGE_MS;
487
+ declare const constants_GPS_ACCURACY_FACTOR: typeof GPS_ACCURACY_FACTOR;
488
+ declare const constants_GPS_AGE_CAP_SECONDS: typeof GPS_AGE_CAP_SECONDS;
489
+ declare const constants_GPS_STALE_MS: typeof GPS_STALE_MS;
490
+ declare const constants_INERTIA_PENALTY: typeof INERTIA_PENALTY;
491
+ declare const constants_INERTIA_SEGMENT_DIST: typeof INERTIA_SEGMENT_DIST;
492
+ declare const constants_LOOK_AHEAD_SECONDS: typeof LOOK_AHEAD_SECONDS;
493
+ declare const constants_MANEUVER_TRIGGER_DIST: typeof MANEUVER_TRIGGER_DIST;
494
+ declare const constants_MAX_CORRIDOR_METERS: typeof MAX_CORRIDOR_METERS;
495
+ declare const constants_MAX_LOOK_AHEAD_METERS: typeof MAX_LOOK_AHEAD_METERS;
496
+ declare const constants_MAX_SNAP_DISTANCE: typeof MAX_SNAP_DISTANCE;
497
+ declare const constants_MIN_LOOK_AHEAD_METERS: typeof MIN_LOOK_AHEAD_METERS;
498
+ declare const constants_OFF_ROUTE_CONFIRM_MS: typeof OFF_ROUTE_CONFIRM_MS;
499
+ declare const constants_REJOIN_CONFIRM_MS: typeof REJOIN_CONFIRM_MS;
500
+ declare const constants_REJOIN_COOLDOWN_MS: typeof REJOIN_COOLDOWN_MS;
501
+ declare const constants_SNAP_WINDOW_SIZE: typeof SNAP_WINDOW_SIZE;
502
+ declare const constants_SPEED_CORRIDOR_FACTOR: typeof SPEED_CORRIDOR_FACTOR;
503
+ declare const constants_STARTUP_GRACE_MS: typeof STARTUP_GRACE_MS;
504
+ declare namespace constants {
505
+ export { constants_ARRIVAL_THRESHOLD_METERS as ARRIVAL_THRESHOLD_METERS, constants_BASE_CORRIDOR_METERS as BASE_CORRIDOR_METERS, constants_BEARING_ALIGNMENT_THRESHOLD as BEARING_ALIGNMENT_THRESHOLD, constants_BEARING_MIN_SPEED_MPS as BEARING_MIN_SPEED_MPS, constants_BEARING_MISMATCH_PENALTY as BEARING_MISMATCH_PENALTY, constants_BEARING_MISMATCH_THRESHOLD as BEARING_MISMATCH_THRESHOLD, constants_BEARING_SMOOTHING_ALPHA as BEARING_SMOOTHING_ALPHA, constants_BETA_CORRECTION as BETA_CORRECTION, constants_DETOUR_COMMIT_MS as DETOUR_COMMIT_MS, constants_DR_MAX_AGE_MS as DR_MAX_AGE_MS, constants_GPS_ACCURACY_FACTOR as GPS_ACCURACY_FACTOR, constants_GPS_AGE_CAP_SECONDS as GPS_AGE_CAP_SECONDS, constants_GPS_STALE_MS as GPS_STALE_MS, constants_INERTIA_PENALTY as INERTIA_PENALTY, constants_INERTIA_SEGMENT_DIST as INERTIA_SEGMENT_DIST, constants_LOOK_AHEAD_SECONDS as LOOK_AHEAD_SECONDS, constants_MANEUVER_TRIGGER_DIST as MANEUVER_TRIGGER_DIST, constants_MAX_CORRIDOR_METERS as MAX_CORRIDOR_METERS, constants_MAX_LOOK_AHEAD_METERS as MAX_LOOK_AHEAD_METERS, constants_MAX_SNAP_DISTANCE as MAX_SNAP_DISTANCE, constants_MIN_LOOK_AHEAD_METERS as MIN_LOOK_AHEAD_METERS, constants_OFF_ROUTE_CONFIRM_MS as OFF_ROUTE_CONFIRM_MS, constants_REJOIN_CONFIRM_MS as REJOIN_CONFIRM_MS, constants_REJOIN_COOLDOWN_MS as REJOIN_COOLDOWN_MS, constants_SNAP_WINDOW_SIZE as SNAP_WINDOW_SIZE, constants_SPEED_CORRIDOR_FACTOR as SPEED_CORRIDOR_FACTOR, constants_STARTUP_GRACE_MS as STARTUP_GRACE_MS };
486
506
  }
487
507
 
488
- export { type BuildOptions, type CameraOptions, constants_d as Constants, Coordinate, CustomRouteBuilder, type CustomWaypoint, type DirectionsLeg, type DirectionsManeuver, type DirectionsOptions, type DirectionsProvider, type DirectionsResult, type DirectionsStep, type Kalman2DState, KalmanFilter2D, type MapRendererAdapter, type ORSConfig, type ORSProfile, type OSRMConfig, OSRMDirectionsProvider, OpenRouteServiceProvider, RouteSnapper, type RouteStyle, type SnapResult, type SnapperOptions, type ValhallaConfig, type ValhallaCostingModel, ValhallaDirectionsProvider, type VehicleStyle, type WaypointOptions, buildForwardCumulativeDistances, buildReverseCumulativeDistances, getBearingBetweenPoints, interpolatePoint, kalmanUpdate2D, normalizeAngle, projectPointOnSegment };
508
+ export { type BuildOptions, type CameraOptions, constants as Constants, Coordinate, CustomRouteBuilder, type CustomWaypoint, type DirectionsLeg, type DirectionsManeuver, type DirectionsOptions, type DirectionsProvider, type DirectionsResult, type DirectionsStep, type Kalman2DState, KalmanFilter2D, type MapRendererAdapter, type ORSConfig, type ORSProfile, type OSRMConfig, OSRMDirectionsProvider, OpenRouteServiceProvider, RouteSnapper, type RouteStyle, type SnapResult, type SnapperOptions, type ValhallaConfig, type ValhallaCostingModel, ValhallaDirectionsProvider, type VehicleStyle, type WaypointOptions, buildForwardCumulativeDistances, buildReverseCumulativeDistances, getBearingBetweenPoints, interpolatePoint, kalmanUpdate2D, normalizeAngle, projectPointOnSegment };
package/dist/core.js CHANGED
@@ -1,7 +1,7 @@
1
- 'use strict';var H=Object.defineProperty;var $=(i,t)=>{for(var e in t)H(i,e,{get:t[e],enumerable:true});};function f(i,t,e,n){let r=(e-i)*(Math.PI/180),s=(n-t)*(Math.PI/180),l=Math.sin(r/2)*Math.sin(r/2)+Math.cos(i*(Math.PI/180))*Math.cos(e*(Math.PI/180))*Math.sin(s/2)*Math.sin(s/2);return 6371e3*(2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l)))}function X(i,t,e,n){let r=n/6371e3,s=e*(Math.PI/180),l=i*(Math.PI/180),p=t*(Math.PI/180),a=Math.asin(Math.sin(l)*Math.cos(r)+Math.cos(l)*Math.sin(r)*Math.cos(s));return [((p+Math.atan2(Math.sin(s)*Math.sin(r)*Math.cos(l),Math.cos(r)-Math.sin(l)*Math.sin(a)))*180/Math.PI+540)%360-180,a*180/Math.PI]}function j(i,t){let e=i[1]*(Math.PI/180),n=i[0]*(Math.PI/180),r=t[1]*(Math.PI/180),s=t[0]*(Math.PI/180),l=Math.sin(s-n)*Math.cos(r),p=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n),a=Math.atan2(l,p)*(180/Math.PI);return a=(a+360)%360,a}function v(i){let t=i%360;return t>180?t-360:t<-180?t+360:t}function S(i,t){let e=i[1]*(Math.PI/180),n=i[0]*(Math.PI/180),r=t[1]*(Math.PI/180),s=t[0]*(Math.PI/180),l=Math.sin(s-n)*Math.cos(r),p=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n);return (Math.atan2(l,p)*180/Math.PI+360)%360}function Y(i,t,e){let n=(r,s,l)=>r+(s-r)*l;return [n(i[0],t[0],e),n(i[1],t[1],e)]}function A(i,t,e){let[n,r]=i,[s,l]=t,[p,a]=e,d=p-s,u=a-l,o=d*d+u*u;if(o===0)return t;let c=((n-s)*d+(r-l)*u)/o;return c=Math.max(0,Math.min(1,c)),[s+c*d,l+c*u]}function J(i){let t=new Float64Array(i.length);for(let e=1;e<i.length;e++)t[e]=t[e-1]+f(i[e-1][1],i[e-1][0],i[e][1],i[e][0]);return t}function q(i){let t=new Float64Array(i.length);for(let e=i.length-2;e>=0;e--)t[e]=t[e+1]+f(i[e][1],i[e][0],i[e+1][1],i[e+1][0]);return t}function L(i,t,e,n,r,s=1e-5,l=5e-5){i.x+=i.vx*r,i.y+=i.vy*r,i.P+=s;let p=l*Math.max(1,n/5),a=i.P/(i.P+p),d=t-i.x,u=e-i.y;return i.x+=a*d,i.y+=a*u,r>0&&(i.vx=d/r*a,i.vy=u/r*a),i.P=(1-a)*i.P,i}var x=class{constructor(t=1e-5,e=5e-5){this.lastTimestamp=0;this.Q=t,this.rBase=e,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(t,e,n){this.state={x:t,y:e,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(t,e,n,r){if(this.lastTimestamp===0)return this.init(t,e,r),[t,e];let s=Math.max(.001,(r-this.lastTimestamp)/1e3);return this.lastTimestamp=r,L(this.state,t,e,n,s,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var B={};$(B,{ARRIVAL_THRESHOLD_METERS:()=>Ct,BASE_CORRIDOR_METERS:()=>z,BEARING_ALIGNMENT_THRESHOLD:()=>rt,BEARING_MIN_SPEED_MPS:()=>ot,BEARING_MISMATCH_PENALTY:()=>V,BEARING_MISMATCH_THRESHOLD:()=>F,BEARING_SMOOTHING_ALPHA:()=>nt,BETA_CORRECTION:()=>mt,DETOUR_COMMIT_MS:()=>pt,DR_MAX_AGE_MS:()=>it,GPS_ACCURACY_FACTOR:()=>tt,GPS_AGE_CAP_SECONDS:()=>dt,GPS_STALE_MS:()=>ut,INERTIA_PENALTY:()=>U,INERTIA_SEGMENT_DIST:()=>W,LOOK_AHEAD_SECONDS:()=>yt,MANEUVER_TRIGGER_DIST:()=>ht,MAX_CORRIDOR_METERS:()=>Q,MAX_LOOK_AHEAD_METERS:()=>gt,MAX_SNAP_DISTANCE:()=>k,MIN_LOOK_AHEAD_METERS:()=>ft,OFF_ROUTE_CONFIRM_MS:()=>st,REJOIN_CONFIRM_MS:()=>at,REJOIN_COOLDOWN_MS:()=>ct,SNAP_WINDOW_SIZE:()=>et,SPEED_CORRIDOR_FACTOR:()=>Z,STARTUP_GRACE_MS:()=>lt});var z=25,Q=60,Z=1.2,tt=.5,k=80,F=90,V=500,U=200,W=5,et=25,nt=.3,ot=1.5,rt=55,it=5e3,st=2e3,at=1500,ct=12e3,lt=3e3,pt=4e3,ut=3e3,dt=10,ht=25,mt=.15,yt=3,ft=20,gt=100,Ct=30;var bt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},E=class{constructor(t){this.options={...bt,...t};}snap(t,e,n,r,s,l,p,a=null,d=null){let u=e.length,o=p,c=1/0,h=1/0,w=e[p]??[0,0];for(let C=0;C<=r;C++){let m=n+C;if(m>u-2)if(s&&l>u*.7)m=m%(u-1);else break;if(m<0||m>=u-1)continue;let T=e[m],N=e[m+1],b=A(t,T,N),R=f(t[1],t[0],b[1],b[0]);if(R>this.options.maxSnapDistance*2)continue;let g=R;if(this.options.useBearingPenalty&&a!==null){let G=S(T,N);Math.abs(v(a-G))>90&&(g+=500);}this.options.useInertiaPenalty&&d!==null&&Math.abs(m-d)>=5&&(g+=200),g<c&&(c=g,h=R,o=m,w=b);}return {idx:o,dist:h,proj:w}}};var P=class{constructor(t){this.config={baseUrl:t.baseUrl.replace(/\/$/,""),profile:t.profile??"driving",maxWaypointsPerChunk:t.maxWaypointsPerChunk??100};}async getRoute(t,e){if(t.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=e?.profile??this.config.profile;return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}async fetchRoute(t,e,n){let r=t.map(u=>`${u[0]},${u[1]}`).join(";"),s=n?.steps!==false?"true":"false",l=`${this.config.baseUrl}/route/v1/${e}/${r}?overview=full&geometries=geojson&steps=${s}&annotations=false`,p=await fetch(l);if(!p.ok)throw new Error(`[OSRM] HTTP ${p.status}: ${p.statusText}`);let a=await p.json();if(a.code!=="Ok"||!a.routes?.length)throw new Error(`[OSRM] No route found: ${a.code}`);let d=a.routes[0];return {geometry:d.geometry.coordinates,distance:d.distance,duration:d.duration,legs:(d.legs??[]).map(u=>({distance:u.distance,duration:u.duration,steps:(u.steps??[]).map(o=>({distance:o.distance,duration:o.duration,geometry:o.geometry?.coordinates??[],maneuver:{type:o.maneuver?.type??"unknown",modifier:o.maneuver?.modifier,location:o.maneuver?.location??[0,0],bearingBefore:o.maneuver?.bearing_before??0,bearingAfter:o.maneuver?.bearing_after??0,instruction:o.name??void 0},name:o.name}))})),raw:a}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var _=class{constructor(t){this.config={baseUrl:t.baseUrl.replace(/\/$/,""),costing:t.costing??"auto",apiKey:t.apiKey??"",maxWaypointsPerChunk:t.maxWaypointsPerChunk??50};}async getRoute(t,e){if(t.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(e?.profile);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileToCosting(t){switch(t){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(t,e,n){let r=t.map(c=>({lon:c[0],lat:c[1],type:"break"})),s=JSON.stringify({locations:r,costing:e,directions_options:{units:"kilometers"}}),l={"Content-Type":"application/json","User-Agent":"NavCoreSDK/1.0.0 (React Native; Expo; bab-bou-jeloud-demo)"};this.config.apiKey&&(l.api_key=this.config.apiKey);let p=await fetch(`${this.config.baseUrl}/route`,{method:"POST",headers:l,body:s});if(!p.ok){let c=await p.text();throw new Error(`[Valhalla] HTTP ${p.status}: ${c}`)}let a=await p.json(),d=this.decodePolyline(a.trip?.legs?.[0]?.shape??""),u=a.trip?.summary??{},o=(a.trip?.legs??[]).map(c=>({distance:(c.summary?.length??0)*1e3,duration:c.summary?.time??0,steps:(c.maneuvers??[]).map(h=>({distance:(h.length??0)*1e3,duration:h.time??0,geometry:[],maneuver:{type:h.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:h.begin_heading??0,bearingAfter:h.end_heading??0,instruction:h.instruction},name:h.street_names?.[0]}))}));return {geometry:d,distance:(u.length??0)*1e3,duration:u.time??0,legs:o,raw:a}}decodePolyline(t,e=6){let n=Math.pow(10,e),r=[],s=0,l=0,p=0;for(;s<t.length;){let a=0,d=0,u;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let o=(d&1)!==0?~(d>>1):d>>1;l+=o,a=0,d=0;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let c=(d&1)!==0?~(d>>1):d>>1;p+=c,r.push([p/n,l/n]);}return r}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var Rt="https://api.openrouteservice.org/v2/directions";var D=class{constructor(t){this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??Rt,maxWaypointsPerChunk:t.maxWaypointsPerChunk??50};}async getRoute(t,e){if(t.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(e);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileFromOptions(t){switch(t?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(t,e,n){let r=JSON.stringify({coordinates:t,instructions:n?.steps!==false,language:n?.language??"en"}),s=await fetch(`${this.config.baseUrl}/${e}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:r});if(!s.ok){let o=await s.text();throw new Error(`[ORS] HTTP ${s.status}: ${o}`)}let l=await s.json(),p=l.features?.[0];if(!p)throw new Error("[ORS] No route returned");let a=p.properties?.summary??{},u=(p.properties?.segments??[]).map(o=>({distance:o.distance??0,duration:o.duration??0,steps:(o.steps??[]).map(c=>({distance:c.distance??0,duration:c.duration??0,geometry:[],maneuver:{type:c.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:0,bearingAfter:0,instruction:c.instruction},name:c.name}))}));return {geometry:p.geometry?.coordinates??[],distance:a.distance??0,duration:a.duration??0,legs:u,raw:l}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var vt=0;function K(){return `wp_${Date.now()}_${++vt}`}var M=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=K();return this.waypoints.push({id:n,coord:t,options:e}),n}insertWaypoint(t,e){let n=this.waypoints.findIndex(s=>s.id===e);if(n===-1)throw new Error(`Waypoint ${e} not found`);let r=K();return this.waypoints.splice(n+1,0,{id:r,coord:t,options:void 0}),r}removeWaypoint(t){let e=this.waypoints.findIndex(n=>n.id===t);if(e===-1)throw new Error(`Waypoint ${t} not found`);this.waypoints.splice(e,1);}moveWaypoint(t,e){let n=this.waypoints.find(r=>r.id===t);if(!n)throw new Error(`Waypoint ${t} not found`);n.coord=e;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(t="OVERLAP_1",e=25){let n=this.waypoints.map(p=>p.coord);if(n.length<=e)return [n];let s=e-(t==="OVERLAP_2"?2:1),l=[];for(let p=0;p<n.length;p+=s){let a=n.slice(p,p+e);if(l.push(a),p+e>=n.length)break}return l}buildStraightLine(){return {geometry:this.waypoints.map(t=>t.coord),waypoints:[...this.waypoints]}}fromGPX(t){this.waypoints=[];let e=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=e.exec(t))!==null;){let r=parseFloat(n[1]),s=parseFloat(n[2]);isFinite(r)&&isFinite(s)&&this.addWaypoint([s,r]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
1
+ 'use strict';var $=Object.defineProperty;var q=(s,t)=>{for(var e in t)$(s,e,{get:t[e],enumerable:true});};function R(s,t,e,n){let o=(e-s)*(Math.PI/180),i=(n-t)*(Math.PI/180),l=Math.sin(o/2)*Math.sin(o/2)+Math.cos(s*(Math.PI/180))*Math.cos(e*(Math.PI/180))*Math.sin(i/2)*Math.sin(i/2);return 6371e3*(2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l)))}function X(s,t,e,n){let o=n/6371e3,i=e*(Math.PI/180),l=s*(Math.PI/180),a=t*(Math.PI/180),c=Math.asin(Math.sin(l)*Math.cos(o)+Math.cos(l)*Math.sin(o)*Math.cos(i));return [((a+Math.atan2(Math.sin(i)*Math.sin(o)*Math.cos(l),Math.cos(o)-Math.sin(l)*Math.sin(c)))*180/Math.PI+540)%360-180,c*180/Math.PI]}function j(s,t){let e=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),o=t[1]*(Math.PI/180),i=t[0]*(Math.PI/180),l=Math.sin(i-n)*Math.cos(o),a=Math.cos(e)*Math.sin(o)-Math.sin(e)*Math.cos(o)*Math.cos(i-n),c=Math.atan2(l,a)*(180/Math.PI);return c=(c+360)%360,c}function v(s){let t=s%360;return t>180?t-360:t<-180?t+360:t}function x(s,t){let e=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),o=t[1]*(Math.PI/180),i=t[0]*(Math.PI/180),l=Math.sin(i-n)*Math.cos(o),a=Math.cos(e)*Math.sin(o)-Math.sin(e)*Math.cos(o)*Math.cos(i-n);return (Math.atan2(l,a)*180/Math.PI+360)%360}function Y(s,t,e){let n=(o,i,l)=>o+(i-o)*l;return [n(s[0],t[0],e),n(s[1],t[1],e)]}function _(s,t,e){let[n,o]=s,[i,l]=t,[a,c]=e,h=a-i,u=c-l,r=h*h+u*u;if(r===0)return t;let p=((n-i)*h+(o-l)*u)/r;return p=Math.max(0,Math.min(1,p)),[i+p*h,l+p*u]}function J(s){let t=new Float64Array(s.length);for(let e=1;e<s.length;e++)t[e]=t[e-1]+R(s[e-1][1],s[e-1][0],s[e][1],s[e][0]);return t}function z(s){let t=new Float64Array(s.length);for(let e=s.length-2;e>=0;e--)t[e]=t[e+1]+R(s[e][1],s[e][0],s[e+1][1],s[e+1][0]);return t}function k(s,t,e,n,o,i=1e-5,l=5e-5){s.x+=s.vx*o,s.y+=s.vy*o,s.P+=i;let a=l*Math.max(1,n/5),c=s.P/(s.P+a),h=t-s.x,u=e-s.y;return s.x+=c*h,s.y+=c*u,o>0&&(s.vx=h/o*c,s.vy=u/o*c),s.P=(1-c)*s.P,s}var P=class{constructor(t=1e-5,e=5e-5){this.lastTimestamp=0;this.Q=t,this.rBase=e,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(t,e,n){this.state={x:t,y:e,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(t,e,n,o){if(this.lastTimestamp===0)return this.init(t,e,o),[t,e];let i=Math.max(.001,(o-this.lastTimestamp)/1e3);return this.lastTimestamp=o,k(this.state,t,e,n,i,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var K={};q(K,{ARRIVAL_THRESHOLD_METERS:()=>Ct,BASE_CORRIDOR_METERS:()=>Q,BEARING_ALIGNMENT_THRESHOLD:()=>it,BEARING_MIN_SPEED_MPS:()=>rt,BEARING_MISMATCH_PENALTY:()=>W,BEARING_MISMATCH_THRESHOLD:()=>V,BEARING_SMOOTHING_ALPHA:()=>ot,BETA_CORRECTION:()=>ft,DETOUR_COMMIT_MS:()=>pt,DR_MAX_AGE_MS:()=>st,GPS_ACCURACY_FACTOR:()=>et,GPS_AGE_CAP_SECONDS:()=>dt,GPS_STALE_MS:()=>ht,INERTIA_PENALTY:()=>G,INERTIA_SEGMENT_DIST:()=>B,LOOK_AHEAD_SECONDS:()=>yt,MANEUVER_TRIGGER_DIST:()=>mt,MAX_CORRIDOR_METERS:()=>Z,MAX_LOOK_AHEAD_METERS:()=>bt,MAX_SNAP_DISTANCE:()=>U,MIN_LOOK_AHEAD_METERS:()=>gt,OFF_ROUTE_CONFIRM_MS:()=>at,REJOIN_CONFIRM_MS:()=>ct,REJOIN_COOLDOWN_MS:()=>lt,SNAP_WINDOW_SIZE:()=>nt,SPEED_CORRIDOR_FACTOR:()=>tt,STARTUP_GRACE_MS:()=>ut});var Q=25,Z=60,tt=1.2,et=.5,U=80,V=90,W=500,G=200,B=5,nt=25,ot=.3,rt=1.5,it=55,st=5e3,at=2e3,ct=1500,lt=12e3,ut=3e3,pt=4e3,ht=3e3,dt=10,mt=25,ft=.15,yt=3,gt=20,bt=100,Ct=30;var Mt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},D=class{constructor(t){this.options={...Mt,...t};}snap(t,e,n,o,i,l,a,c=null,h=null){let u=e.length,r=a,p=1/0,g=1/0,f=e[a]??[0,0];for(let d=0;d<=o;d++){let y=n+d;if(y>u-2)if(i&&l>u*.7)y=y%(u-1);else break;if(y<0||y>=u-1)continue;let m=e[y],M=e[y+1],b=_(t,m,M),E=R(t[1],t[0],b[1],b[0]);if(E>this.options.maxSnapDistance*2)continue;let A=E;if(this.options.useBearingPenalty&&c!==null){let S=x(m,M);Math.abs(v(c-S))>90&&(A+=500);}this.options.useInertiaPenalty&&h!==null&&Math.abs(y-h)>=5&&(A+=200),A<p&&(p=A,g=E,r=y,f=b);}if(!Number.isFinite(g)){let d=Math.min(Math.max(a,0),Math.max(0,u-2)),y=e[d],m=e[d+1];y&&m?(f=_(t,y,m),g=R(t[1],t[0],f[1],f[0]),r=d):(f=e[Math.min(Math.max(a,0),u-1)]??t,g=R(t[1],t[0],f[1],f[0]),r=0);}return {idx:r,dist:g,proj:f}}};var O=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[OSRM] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:t.baseUrl.replace(/\/$/,""),profile:t.profile??"driving",maxWaypointsPerChunk:t.maxWaypointsPerChunk??100,fetchFn:e,timeoutMs:t.timeoutMs??15e3};}async getRoute(t,e){if(t.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=e?.profile??this.config.profile;return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}async fetchRoute(t,e,n){let o=t.map(u=>`${u[0]},${u[1]}`).join(";"),i=n?.steps!==false?"true":"false",l=`${this.config.baseUrl}/route/v1/${e}/${o}?overview=full&geometries=geojson&steps=${i}&annotations=false`,a=await this.fetchWithTimeout(l);if(!a.ok)throw new Error(`[OSRM] HTTP ${a.status}: ${a.statusText}`);let c=await a.json();if(c.code!=="Ok"||!c.routes?.length)throw new Error(`[OSRM] No route found: ${c.code}`);let h=c.routes[0];return {geometry:h.geometry.coordinates,distance:h.distance,duration:h.duration,legs:(h.legs??[]).map(u=>({distance:u.distance,duration:u.duration,steps:(u.steps??[]).map(r=>({distance:r.distance,duration:r.duration,geometry:r.geometry?.coordinates??[],maneuver:{type:r.maneuver?.type??"unknown",modifier:r.maneuver?.modifier,location:r.maneuver?.location??[0,0],bearingBefore:r.maneuver?.bearing_before??0,bearingAfter:r.maneuver?.bearing_after??0,instruction:r.name??void 0},name:r.name}))})),raw:c}}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[OSRM] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var I=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[Valhalla] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:t.baseUrl.replace(/\/$/,""),costing:t.costing??"auto",apiKey:t.apiKey??"",maxWaypointsPerChunk:t.maxWaypointsPerChunk??50,fetchFn:e,timeoutMs:t.timeoutMs??15e3};}async getRoute(t,e){if(t.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(e?.profile);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileToCosting(t){switch(t){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(t,e,n){let o=t.map(d=>({lon:d[0],lat:d[1],type:"break"})),i=JSON.stringify({locations:o,costing:e,directions_options:{units:"kilometers"}}),l={"Content-Type":"application/json","User-Agent":"NavCoreSDK/1.0.0 (React Native; Expo; bab-bou-jeloud-demo)"};this.config.apiKey&&(l.api_key=this.config.apiKey);let a=await this.fetchWithTimeout(`${this.config.baseUrl}/route`,{method:"POST",headers:l,body:i});if(!a.ok){let d=await a.text();throw new Error(`[Valhalla] HTTP ${a.status}: ${d}`)}let c=await a.json(),h=c.trip?.legs??[],u=h.map(d=>this.decodePolyline(d.shape??"")),r=this.stitchGeometry(u),p=r.length>0?r:t,g=c.trip?.summary??{},f=h.map((d,y)=>({distance:(d.summary?.length??0)*1e3,duration:d.summary?.time??0,steps:(d.maneuvers??[]).map(m=>{let M=u[y]??[],b=this.shapeIndex(m.begin_shape_index,0),E=this.shapeIndex(m.end_shape_index,b),A=M.length>0?M.slice(b,Math.max(b,E)+1):[],S=t[Math.min(y,t.length-1)],L=A[0]??M[b]??S;return {distance:(m.length??0)*1e3,duration:m.time??0,geometry:A,maneuver:{type:m.type?.toString()??"unknown",modifier:void 0,location:L,bearingBefore:m.begin_heading??0,bearingAfter:m.end_heading??0,instruction:m.instruction},name:m.street_names?.[0]}})}));return {geometry:p,distance:(g.length??0)*1e3,duration:g.time??0,legs:f,raw:c}}decodePolyline(t,e=6){let n=Math.pow(10,e),o=[],i=0,l=0,a=0;for(;i<t.length;){let c=0,h=0,u;do u=t.charCodeAt(i++)-63,h|=(u&31)<<c,c+=5;while(u>=32);let r=(h&1)!==0?~(h>>1):h>>1;l+=r,c=0,h=0;do u=t.charCodeAt(i++)-63,h|=(u&31)<<c,c+=5;while(u>=32);let p=(h&1)!==0?~(h>>1):h>>1;a+=p,o.push([a/n,l/n]);}return o}stitchGeometry(t){let e=[];for(let n of t){if(n.length===0)continue;let o=n[0],i=e[e.length-1];i&&this.sameCoordinate(i,o)?e.push(...n.slice(1)):e.push(...n);}return e}sameCoordinate(t,e){return Math.abs(t[0]-e[0])<1e-9&&Math.abs(t[1]-e[1])<1e-9}shapeIndex(t,e){return typeof t=="number"&&Number.isFinite(t)&&t>=0?Math.floor(t):e}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[Valhalla] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var Rt="https://api.openrouteservice.org/v2/directions",At=50,Et=15e3,w=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[ORS] fetch is not available. Pass config.fetchFn in this runtime.");this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??Rt,maxWaypointsPerChunk:t.maxWaypointsPerChunk??At,fetchFn:e,timeoutMs:t.timeoutMs??Et};}async getRoute(t,e){if(t.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(e);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileFromOptions(t){switch(t?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(t,e,n){let o=JSON.stringify({coordinates:t,instructions:n?.steps!==false,language:n?.language??"en"}),i=await this.fetchWithTimeout(`${this.config.baseUrl}/${e}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:o});if(!i.ok){let p=await i.text();throw new Error(`[ORS] HTTP ${i.status}: ${p}`)}let l=await i.json(),a=l.features?.[0];if(!a)throw new Error("[ORS] No route returned");let c=a.properties?.summary??{},h=a.properties?.segments??[],u=a.geometry?.coordinates??[],r=h.map((p,g)=>({distance:p.distance??0,duration:p.duration??0,steps:(p.steps??[]).map(f=>{let[d,y]=this.stepRange(f.way_points),m=u.slice(d,Math.max(d,y)+1),M=t[Math.min(g,t.length-1)],b=m[0]??u[d]??M;return {distance:f.distance??0,duration:f.duration??0,geometry:m,maneuver:{type:f.type?.toString()??"unknown",modifier:void 0,location:b,bearingBefore:this.bearingFromGeometry(m,false),bearingAfter:this.bearingFromGeometry(m,true),instruction:f.instruction},name:f.name}})}));return {geometry:u,distance:c.distance??0,duration:c.duration??0,legs:r,raw:l}}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}stepRange(t){if(!Array.isArray(t))return [0,0];let e=typeof t[0]=="number"&&Number.isFinite(t[0])?Math.max(0,Math.floor(t[0])):0,n=typeof t[1]=="number"&&Number.isFinite(t[1])?Math.max(e,Math.floor(t[1])):e;return [e,n]}bearingFromGeometry(t,e){if(t.length<2)return 0;let n=e?t[t.length-2]:t[0],o=e?t[t.length-1]:t[1];return !n||!o?0:x(n,o)}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[ORS] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var xt=0;function H(){return `wp_${Date.now()}_${++xt}`}var T=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=H();return this.waypoints.push({id:n,coord:t,options:e}),n}insertWaypoint(t,e){let n=this.waypoints.findIndex(i=>i.id===e);if(n===-1)throw new Error(`Waypoint ${e} not found`);let o=H();return this.waypoints.splice(n+1,0,{id:o,coord:t,options:void 0}),o}removeWaypoint(t){let e=this.waypoints.findIndex(n=>n.id===t);if(e===-1)throw new Error(`Waypoint ${t} not found`);this.waypoints.splice(e,1);}moveWaypoint(t,e){let n=this.waypoints.find(o=>o.id===t);if(!n)throw new Error(`Waypoint ${t} not found`);n.coord=e;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(t="OVERLAP_1",e=25){let n=this.waypoints.map(a=>a.coord);if(n.length<=e)return [n];let i=e-(t==="OVERLAP_2"?2:1),l=[];for(let a=0;a<n.length;a+=i){let c=n.slice(a,a+e);if(l.push(c),a+e>=n.length)break}return l}buildStraightLine(){return {geometry:this.waypoints.map(t=>t.coord),waypoints:[...this.waypoints]}}fromGPX(t){this.waypoints=[];let e=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=e.exec(t))!==null;){let o=parseFloat(n[1]),i=parseFloat(n[2]);isFinite(o)&&isFinite(i)&&this.addWaypoint([i,o]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
2
2
  <gpx version="1.1" creator="NavCore SDK">
3
3
  ${this.waypoints.map(e=>` <wpt lat="${e.coord[1]}" lon="${e.coord[0]}">`+(e.options?.name?`
4
4
  <name>${e.options.name}</name>`:"")+`
5
5
  </wpt>`).join(`
6
6
  `)}
7
- </gpx>`}fromGeoJSON(t){if(this.waypoints=[],t.type==="FeatureCollection"&&t.features){for(let e of t.features)if(e.geometry.type==="Point"){let n=e.geometry.coordinates;this.addWaypoint(n);}else if(e.geometry.type==="LineString"){let n=e.geometry.coordinates;for(let r of n)this.addWaypoint(r);}}}toGeoJSON(){let t=this.waypoints.map((n,r)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:r,name:n.options?.name??null,silent:n.options?.silent??false}})),e={type:"Feature",geometry:{type:"LineString",coordinates:this.waypoints.map(n=>n.coord)},properties:{type:"route"}};return {type:"FeatureCollection",features:[...t,e]}}clear(){this.waypoints=[];}};var O={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",PROGRESS_TRACKING:"progress_tracking",ROUTE_OFFSET:"route_offset",DEAD_RECKONING:"dead_reckoning",ADVANCED_BEARING:"advanced_bearing",COMPOUND_DEVIATION:"compound_deviation",PARALLEL_ROAD_RESOLUTION:"parallel_road_resolution",U_TURN_PROTECTION:"u_turn_protection",VOICE_TRIGGERS:"voice_triggers",ETA:"eta",GEOFENCING:"geofencing",NAV_AI:"nav_ai"};var y=class y{constructor(t){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;t&&(this.tryValidateSync(t)||this.validate(t)),this.promoteToActive();}static getActive(){return y.activeManager}static clearActive(){y.activeManager=null;}promoteToActive(){let t=y.activeManager;(t===null||t.status!=="VALID"||this.status==="VALID")&&(y.activeManager=this);}tryValidateSync(t){return t==="eyJ0IjoicHJvIiwiZXhwIjo0OTMyNzAzMTU2MDAwLCJiaWQiOiJkZXYuYnlwYXNzIiwiZiI6WyIqIl19.MEQCIH4E4QNu9PuVsXHSnYmcqpCLk4QitiIH9hhY0Zm+YO5gAiAE7X3c47YQLUj7WPSGKw9Y7W2kBUR5GCnOMBwdBsYGgg=="?typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)?(this.status="VALID",this.payload={t:"pro",exp:4932703156e3,bid:"dev.bypass",f:["*"]},this.extractFeatures(),console.log("\u{1F511} [NavCore] Development bypass key validated synchronously. Plan: pro"),true):(console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,true):false}async validate(t){if(this.tryValidateSync(t))return this.status;try{let[e,n]=t.split(".");if(!e||!n)return this.status="INVALID",this.status;let r=atob(e);if(this.payload=JSON.parse(r),!this.payload||this.payload.exp<Date.now())return this.status="EXPIRED",this.status;if(!await this.verifySignature(e,n))return this.status="INVALID",this.status;if(this.payload?.bid==="dev.bypass"&&!(typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)))return console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,this.status;this.status="VALID",this.extractFeatures(),this.promoteToActive(),console.log(`\u{1F511} [NavCore] License validation complete. Plan: ${this.isProEnabled()?"pro":"core"}`);}catch{this.status="INVALID";}return this.status}extractFeatures(){if(this.enabledFeatures.clear(),!!this.payload){if(Array.isArray(this.payload.f))for(let t of this.payload.f)this.enabledFeatures.add(t);this.payload.t==="pro"&&this.enabledFeatures.add("*");}}hasFeature(t){return this.status!=="VALID"?false:this.enabledFeatures.has("*")?true:this.enabledFeatures.has(t)}warnOnce(t){this.warnedFeatures.has(t)||(console.warn(`[NavCore] Feature '${t}' requires a Pro license`),this.warnedFeatures.add(t));}isProEnabled(){return this.hasFeature("*")}isAIEnabled(){return this.hasFeature(O.NAV_AI)}getStatus(){return this.status}getPayload(){return this.payload}getEnabledFeatures(){return Array.from(this.enabledFeatures)}async verifySignature(t,e){try{if(typeof crypto>"u"||!crypto.subtle)return !1;let r=new TextEncoder().encode(t),s=Uint8Array.from(atob(e),a=>a.charCodeAt(0)),l=Uint8Array.from(atob(y.PUBLIC_KEY_SPKI),a=>a.charCodeAt(0)),p=await crypto.subtle.importKey("spki",l,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},p,s,r)}catch{return false}}};y.activeManager=null,y.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var I=y;exports.Constants=B;exports.CustomRouteBuilder=M;exports.FEATURES=O;exports.KalmanFilter2D=x;exports.LicenseManager=I;exports.OSRMDirectionsProvider=P;exports.OpenRouteServiceProvider=D;exports.RouteSnapper=E;exports.ValhallaDirectionsProvider=_;exports.buildForwardCumulativeDistances=J;exports.buildReverseCumulativeDistances=q;exports.destinationPoint=X;exports.geoGetBearing=j;exports.getBearingBetweenPoints=S;exports.haversineDistance=f;exports.interpolatePoint=Y;exports.kalmanUpdate2D=L;exports.normalizeAngle=v;exports.projectPointOnSegment=A;
7
+ </gpx>`}fromGeoJSON(t){if(this.waypoints=[],t.type==="FeatureCollection"&&t.features){for(let e of t.features)if(e.geometry.type==="Point"){let n=e.geometry.coordinates;this.addWaypoint(n);}else if(e.geometry.type==="LineString"){let n=e.geometry.coordinates;for(let o of n)this.addWaypoint(o);}}}toGeoJSON(){let t=this.waypoints.map((n,o)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:o,name:n.options?.name??null,silent:n.options?.silent??false}})),e={type:"Feature",geometry:{type:"LineString",coordinates:this.waypoints.map(n=>n.coord)},properties:{type:"route"}};return {type:"FeatureCollection",features:[...t,e]}}clear(){this.waypoints=[];}};var F={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",PROGRESS_TRACKING:"progress_tracking",ROUTE_OFFSET:"route_offset",DEAD_RECKONING:"dead_reckoning",ADVANCED_BEARING:"advanced_bearing",COMPOUND_DEVIATION:"compound_deviation",PARALLEL_ROAD_RESOLUTION:"parallel_road_resolution",U_TURN_PROTECTION:"u_turn_protection",VOICE_TRIGGERS:"voice_triggers",ETA:"eta",GEOFENCING:"geofencing",NAV_AI:"nav_ai"};var C=class C{constructor(t){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;t&&(this.tryValidateSync(t)||this.validate(t)),this.promoteToActive();}static getActive(){return C.activeManager}static clearActive(){C.activeManager=null;}promoteToActive(){let t=C.activeManager;(t===null||t.status!=="VALID"||this.status==="VALID")&&(C.activeManager=this);}tryValidateSync(t){return t==="eyJ0IjoicHJvIiwiZXhwIjo0OTMyNzAzMTU2MDAwLCJiaWQiOiJkZXYuYnlwYXNzIiwiZiI6WyIqIl19.MEQCIH4E4QNu9PuVsXHSnYmcqpCLk4QitiIH9hhY0Zm+YO5gAiAE7X3c47YQLUj7WPSGKw9Y7W2kBUR5GCnOMBwdBsYGgg=="?typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)?(this.status="VALID",this.payload={t:"pro",exp:4932703156e3,bid:"dev.bypass",f:["*"]},this.extractFeatures(),console.log("\u{1F511} [NavCore] Development bypass key validated synchronously. Plan: pro"),true):(console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,true):false}async validate(t){if(this.tryValidateSync(t))return this.status;try{let[e,n]=t.split(".");if(!e||!n)return this.status="INVALID",this.status;let o=atob(e);if(this.payload=JSON.parse(o),!this.payload||this.payload.exp<Date.now())return this.status="EXPIRED",this.status;if(!await this.verifySignature(e,n))return this.status="INVALID",this.status;if(this.payload?.bid==="dev.bypass"&&!(typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)))return console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,this.status;this.status="VALID",this.extractFeatures(),this.promoteToActive(),console.log(`\u{1F511} [NavCore] License validation complete. Plan: ${this.isProEnabled()?"pro":"core"}`);}catch{this.status="INVALID";}return this.status}extractFeatures(){if(this.enabledFeatures.clear(),!!this.payload){if(Array.isArray(this.payload.f))for(let t of this.payload.f)this.enabledFeatures.add(t);this.payload.t==="pro"&&this.enabledFeatures.add("*");}}hasFeature(t){return this.status!=="VALID"?false:this.enabledFeatures.has("*")?true:this.enabledFeatures.has(t)}warnOnce(t){this.warnedFeatures.has(t)||(console.warn(`[NavCore] Feature '${t}' requires a Pro license`),this.warnedFeatures.add(t));}isProEnabled(){return this.hasFeature("*")}isAIEnabled(){return this.hasFeature(F.NAV_AI)}getStatus(){return this.status}getPayload(){return this.payload}getEnabledFeatures(){return Array.from(this.enabledFeatures)}async verifySignature(t,e){try{if(typeof crypto>"u"||!crypto.subtle)return !1;let o=new TextEncoder().encode(t),i=Uint8Array.from(atob(e),c=>c.charCodeAt(0)),l=Uint8Array.from(atob(C.PUBLIC_KEY_SPKI),c=>c.charCodeAt(0)),a=await crypto.subtle.importKey("spki",l,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},a,i,o)}catch{return false}}};C.activeManager=null,C.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var N=C;exports.Constants=K;exports.CustomRouteBuilder=T;exports.FEATURES=F;exports.KalmanFilter2D=P;exports.LicenseManager=N;exports.OSRMDirectionsProvider=O;exports.OpenRouteServiceProvider=w;exports.RouteSnapper=D;exports.ValhallaDirectionsProvider=I;exports.buildForwardCumulativeDistances=J;exports.buildReverseCumulativeDistances=z;exports.destinationPoint=X;exports.geoGetBearing=j;exports.getBearingBetweenPoints=x;exports.haversineDistance=R;exports.interpolatePoint=Y;exports.kalmanUpdate2D=k;exports.normalizeAngle=v;exports.projectPointOnSegment=_;
package/dist/core.mjs CHANGED
@@ -1,7 +1,7 @@
1
- var H=Object.defineProperty;var $=(i,t)=>{for(var e in t)H(i,e,{get:t[e],enumerable:true});};function f(i,t,e,n){let r=(e-i)*(Math.PI/180),s=(n-t)*(Math.PI/180),l=Math.sin(r/2)*Math.sin(r/2)+Math.cos(i*(Math.PI/180))*Math.cos(e*(Math.PI/180))*Math.sin(s/2)*Math.sin(s/2);return 6371e3*(2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l)))}function X(i,t,e,n){let r=n/6371e3,s=e*(Math.PI/180),l=i*(Math.PI/180),p=t*(Math.PI/180),a=Math.asin(Math.sin(l)*Math.cos(r)+Math.cos(l)*Math.sin(r)*Math.cos(s));return [((p+Math.atan2(Math.sin(s)*Math.sin(r)*Math.cos(l),Math.cos(r)-Math.sin(l)*Math.sin(a)))*180/Math.PI+540)%360-180,a*180/Math.PI]}function j(i,t){let e=i[1]*(Math.PI/180),n=i[0]*(Math.PI/180),r=t[1]*(Math.PI/180),s=t[0]*(Math.PI/180),l=Math.sin(s-n)*Math.cos(r),p=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n),a=Math.atan2(l,p)*(180/Math.PI);return a=(a+360)%360,a}function v(i){let t=i%360;return t>180?t-360:t<-180?t+360:t}function S(i,t){let e=i[1]*(Math.PI/180),n=i[0]*(Math.PI/180),r=t[1]*(Math.PI/180),s=t[0]*(Math.PI/180),l=Math.sin(s-n)*Math.cos(r),p=Math.cos(e)*Math.sin(r)-Math.sin(e)*Math.cos(r)*Math.cos(s-n);return (Math.atan2(l,p)*180/Math.PI+360)%360}function Y(i,t,e){let n=(r,s,l)=>r+(s-r)*l;return [n(i[0],t[0],e),n(i[1],t[1],e)]}function A(i,t,e){let[n,r]=i,[s,l]=t,[p,a]=e,d=p-s,u=a-l,o=d*d+u*u;if(o===0)return t;let c=((n-s)*d+(r-l)*u)/o;return c=Math.max(0,Math.min(1,c)),[s+c*d,l+c*u]}function J(i){let t=new Float64Array(i.length);for(let e=1;e<i.length;e++)t[e]=t[e-1]+f(i[e-1][1],i[e-1][0],i[e][1],i[e][0]);return t}function q(i){let t=new Float64Array(i.length);for(let e=i.length-2;e>=0;e--)t[e]=t[e+1]+f(i[e][1],i[e][0],i[e+1][1],i[e+1][0]);return t}function L(i,t,e,n,r,s=1e-5,l=5e-5){i.x+=i.vx*r,i.y+=i.vy*r,i.P+=s;let p=l*Math.max(1,n/5),a=i.P/(i.P+p),d=t-i.x,u=e-i.y;return i.x+=a*d,i.y+=a*u,r>0&&(i.vx=d/r*a,i.vy=u/r*a),i.P=(1-a)*i.P,i}var x=class{constructor(t=1e-5,e=5e-5){this.lastTimestamp=0;this.Q=t,this.rBase=e,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(t,e,n){this.state={x:t,y:e,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(t,e,n,r){if(this.lastTimestamp===0)return this.init(t,e,r),[t,e];let s=Math.max(.001,(r-this.lastTimestamp)/1e3);return this.lastTimestamp=r,L(this.state,t,e,n,s,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var B={};$(B,{ARRIVAL_THRESHOLD_METERS:()=>Ct,BASE_CORRIDOR_METERS:()=>z,BEARING_ALIGNMENT_THRESHOLD:()=>rt,BEARING_MIN_SPEED_MPS:()=>ot,BEARING_MISMATCH_PENALTY:()=>V,BEARING_MISMATCH_THRESHOLD:()=>F,BEARING_SMOOTHING_ALPHA:()=>nt,BETA_CORRECTION:()=>mt,DETOUR_COMMIT_MS:()=>pt,DR_MAX_AGE_MS:()=>it,GPS_ACCURACY_FACTOR:()=>tt,GPS_AGE_CAP_SECONDS:()=>dt,GPS_STALE_MS:()=>ut,INERTIA_PENALTY:()=>U,INERTIA_SEGMENT_DIST:()=>W,LOOK_AHEAD_SECONDS:()=>yt,MANEUVER_TRIGGER_DIST:()=>ht,MAX_CORRIDOR_METERS:()=>Q,MAX_LOOK_AHEAD_METERS:()=>gt,MAX_SNAP_DISTANCE:()=>k,MIN_LOOK_AHEAD_METERS:()=>ft,OFF_ROUTE_CONFIRM_MS:()=>st,REJOIN_CONFIRM_MS:()=>at,REJOIN_COOLDOWN_MS:()=>ct,SNAP_WINDOW_SIZE:()=>et,SPEED_CORRIDOR_FACTOR:()=>Z,STARTUP_GRACE_MS:()=>lt});var z=25,Q=60,Z=1.2,tt=.5,k=80,F=90,V=500,U=200,W=5,et=25,nt=.3,ot=1.5,rt=55,it=5e3,st=2e3,at=1500,ct=12e3,lt=3e3,pt=4e3,ut=3e3,dt=10,ht=25,mt=.15,yt=3,ft=20,gt=100,Ct=30;var bt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},E=class{constructor(t){this.options={...bt,...t};}snap(t,e,n,r,s,l,p,a=null,d=null){let u=e.length,o=p,c=1/0,h=1/0,w=e[p]??[0,0];for(let C=0;C<=r;C++){let m=n+C;if(m>u-2)if(s&&l>u*.7)m=m%(u-1);else break;if(m<0||m>=u-1)continue;let T=e[m],N=e[m+1],b=A(t,T,N),R=f(t[1],t[0],b[1],b[0]);if(R>this.options.maxSnapDistance*2)continue;let g=R;if(this.options.useBearingPenalty&&a!==null){let G=S(T,N);Math.abs(v(a-G))>90&&(g+=500);}this.options.useInertiaPenalty&&d!==null&&Math.abs(m-d)>=5&&(g+=200),g<c&&(c=g,h=R,o=m,w=b);}return {idx:o,dist:h,proj:w}}};var P=class{constructor(t){this.config={baseUrl:t.baseUrl.replace(/\/$/,""),profile:t.profile??"driving",maxWaypointsPerChunk:t.maxWaypointsPerChunk??100};}async getRoute(t,e){if(t.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=e?.profile??this.config.profile;return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}async fetchRoute(t,e,n){let r=t.map(u=>`${u[0]},${u[1]}`).join(";"),s=n?.steps!==false?"true":"false",l=`${this.config.baseUrl}/route/v1/${e}/${r}?overview=full&geometries=geojson&steps=${s}&annotations=false`,p=await fetch(l);if(!p.ok)throw new Error(`[OSRM] HTTP ${p.status}: ${p.statusText}`);let a=await p.json();if(a.code!=="Ok"||!a.routes?.length)throw new Error(`[OSRM] No route found: ${a.code}`);let d=a.routes[0];return {geometry:d.geometry.coordinates,distance:d.distance,duration:d.duration,legs:(d.legs??[]).map(u=>({distance:u.distance,duration:u.duration,steps:(u.steps??[]).map(o=>({distance:o.distance,duration:o.duration,geometry:o.geometry?.coordinates??[],maneuver:{type:o.maneuver?.type??"unknown",modifier:o.maneuver?.modifier,location:o.maneuver?.location??[0,0],bearingBefore:o.maneuver?.bearing_before??0,bearingAfter:o.maneuver?.bearing_after??0,instruction:o.name??void 0},name:o.name}))})),raw:a}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var _=class{constructor(t){this.config={baseUrl:t.baseUrl.replace(/\/$/,""),costing:t.costing??"auto",apiKey:t.apiKey??"",maxWaypointsPerChunk:t.maxWaypointsPerChunk??50};}async getRoute(t,e){if(t.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(e?.profile);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileToCosting(t){switch(t){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(t,e,n){let r=t.map(c=>({lon:c[0],lat:c[1],type:"break"})),s=JSON.stringify({locations:r,costing:e,directions_options:{units:"kilometers"}}),l={"Content-Type":"application/json","User-Agent":"NavCoreSDK/1.0.0 (React Native; Expo; bab-bou-jeloud-demo)"};this.config.apiKey&&(l.api_key=this.config.apiKey);let p=await fetch(`${this.config.baseUrl}/route`,{method:"POST",headers:l,body:s});if(!p.ok){let c=await p.text();throw new Error(`[Valhalla] HTTP ${p.status}: ${c}`)}let a=await p.json(),d=this.decodePolyline(a.trip?.legs?.[0]?.shape??""),u=a.trip?.summary??{},o=(a.trip?.legs??[]).map(c=>({distance:(c.summary?.length??0)*1e3,duration:c.summary?.time??0,steps:(c.maneuvers??[]).map(h=>({distance:(h.length??0)*1e3,duration:h.time??0,geometry:[],maneuver:{type:h.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:h.begin_heading??0,bearingAfter:h.end_heading??0,instruction:h.instruction},name:h.street_names?.[0]}))}));return {geometry:d,distance:(u.length??0)*1e3,duration:u.time??0,legs:o,raw:a}}decodePolyline(t,e=6){let n=Math.pow(10,e),r=[],s=0,l=0,p=0;for(;s<t.length;){let a=0,d=0,u;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let o=(d&1)!==0?~(d>>1):d>>1;l+=o,a=0,d=0;do u=t.charCodeAt(s++)-63,d|=(u&31)<<a,a+=5;while(u>=32);let c=(d&1)!==0?~(d>>1):d>>1;p+=c,r.push([p/n,l/n]);}return r}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var Rt="https://api.openrouteservice.org/v2/directions";var D=class{constructor(t){this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??Rt,maxWaypointsPerChunk:t.maxWaypointsPerChunk??50};}async getRoute(t,e){if(t.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(e);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileFromOptions(t){switch(t?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(t,e,n){let r=JSON.stringify({coordinates:t,instructions:n?.steps!==false,language:n?.language??"en"}),s=await fetch(`${this.config.baseUrl}/${e}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:r});if(!s.ok){let o=await s.text();throw new Error(`[ORS] HTTP ${s.status}: ${o}`)}let l=await s.json(),p=l.features?.[0];if(!p)throw new Error("[ORS] No route returned");let a=p.properties?.summary??{},u=(p.properties?.segments??[]).map(o=>({distance:o.distance??0,duration:o.duration??0,steps:(o.steps??[]).map(c=>({distance:c.distance??0,duration:c.duration??0,geometry:[],maneuver:{type:c.type?.toString()??"unknown",modifier:void 0,location:t[0],bearingBefore:0,bearingAfter:0,instruction:c.instruction},name:c.name}))}));return {geometry:p.geometry?.coordinates??[],distance:a.distance??0,duration:a.duration??0,legs:u,raw:l}}async fetchChunked(t,e,n){let r=this.config.maxWaypointsPerChunk,s=[];for(let o=0;o<t.length;o+=r-1){let c=t.slice(o,o+r);if(c.length<2||(s.push(c),o+r>=t.length))break}let l=await Promise.all(s.map(o=>this.fetchRoute(o,e,n))),p=[],a=0,d=0,u=[];for(let o=0;o<l.length;o++){let c=l[o];p.push(...o===0?c.geometry:c.geometry.slice(1)),a+=c.distance,d+=c.duration,u.push(...c.legs);}return {geometry:p,distance:a,duration:d,legs:u,raw:l.map(o=>o.raw)}}};var vt=0;function K(){return `wp_${Date.now()}_${++vt}`}var M=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=K();return this.waypoints.push({id:n,coord:t,options:e}),n}insertWaypoint(t,e){let n=this.waypoints.findIndex(s=>s.id===e);if(n===-1)throw new Error(`Waypoint ${e} not found`);let r=K();return this.waypoints.splice(n+1,0,{id:r,coord:t,options:void 0}),r}removeWaypoint(t){let e=this.waypoints.findIndex(n=>n.id===t);if(e===-1)throw new Error(`Waypoint ${t} not found`);this.waypoints.splice(e,1);}moveWaypoint(t,e){let n=this.waypoints.find(r=>r.id===t);if(!n)throw new Error(`Waypoint ${t} not found`);n.coord=e;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(t="OVERLAP_1",e=25){let n=this.waypoints.map(p=>p.coord);if(n.length<=e)return [n];let s=e-(t==="OVERLAP_2"?2:1),l=[];for(let p=0;p<n.length;p+=s){let a=n.slice(p,p+e);if(l.push(a),p+e>=n.length)break}return l}buildStraightLine(){return {geometry:this.waypoints.map(t=>t.coord),waypoints:[...this.waypoints]}}fromGPX(t){this.waypoints=[];let e=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=e.exec(t))!==null;){let r=parseFloat(n[1]),s=parseFloat(n[2]);isFinite(r)&&isFinite(s)&&this.addWaypoint([s,r]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
1
+ var $=Object.defineProperty;var q=(s,t)=>{for(var e in t)$(s,e,{get:t[e],enumerable:true});};function R(s,t,e,n){let o=(e-s)*(Math.PI/180),i=(n-t)*(Math.PI/180),l=Math.sin(o/2)*Math.sin(o/2)+Math.cos(s*(Math.PI/180))*Math.cos(e*(Math.PI/180))*Math.sin(i/2)*Math.sin(i/2);return 6371e3*(2*Math.atan2(Math.sqrt(l),Math.sqrt(1-l)))}function X(s,t,e,n){let o=n/6371e3,i=e*(Math.PI/180),l=s*(Math.PI/180),a=t*(Math.PI/180),c=Math.asin(Math.sin(l)*Math.cos(o)+Math.cos(l)*Math.sin(o)*Math.cos(i));return [((a+Math.atan2(Math.sin(i)*Math.sin(o)*Math.cos(l),Math.cos(o)-Math.sin(l)*Math.sin(c)))*180/Math.PI+540)%360-180,c*180/Math.PI]}function j(s,t){let e=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),o=t[1]*(Math.PI/180),i=t[0]*(Math.PI/180),l=Math.sin(i-n)*Math.cos(o),a=Math.cos(e)*Math.sin(o)-Math.sin(e)*Math.cos(o)*Math.cos(i-n),c=Math.atan2(l,a)*(180/Math.PI);return c=(c+360)%360,c}function v(s){let t=s%360;return t>180?t-360:t<-180?t+360:t}function x(s,t){let e=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),o=t[1]*(Math.PI/180),i=t[0]*(Math.PI/180),l=Math.sin(i-n)*Math.cos(o),a=Math.cos(e)*Math.sin(o)-Math.sin(e)*Math.cos(o)*Math.cos(i-n);return (Math.atan2(l,a)*180/Math.PI+360)%360}function Y(s,t,e){let n=(o,i,l)=>o+(i-o)*l;return [n(s[0],t[0],e),n(s[1],t[1],e)]}function _(s,t,e){let[n,o]=s,[i,l]=t,[a,c]=e,h=a-i,u=c-l,r=h*h+u*u;if(r===0)return t;let p=((n-i)*h+(o-l)*u)/r;return p=Math.max(0,Math.min(1,p)),[i+p*h,l+p*u]}function J(s){let t=new Float64Array(s.length);for(let e=1;e<s.length;e++)t[e]=t[e-1]+R(s[e-1][1],s[e-1][0],s[e][1],s[e][0]);return t}function z(s){let t=new Float64Array(s.length);for(let e=s.length-2;e>=0;e--)t[e]=t[e+1]+R(s[e][1],s[e][0],s[e+1][1],s[e+1][0]);return t}function k(s,t,e,n,o,i=1e-5,l=5e-5){s.x+=s.vx*o,s.y+=s.vy*o,s.P+=i;let a=l*Math.max(1,n/5),c=s.P/(s.P+a),h=t-s.x,u=e-s.y;return s.x+=c*h,s.y+=c*u,o>0&&(s.vx=h/o*c,s.vy=u/o*c),s.P=(1-c)*s.P,s}var P=class{constructor(t=1e-5,e=5e-5){this.lastTimestamp=0;this.Q=t,this.rBase=e,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(t,e,n){this.state={x:t,y:e,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(t,e,n,o){if(this.lastTimestamp===0)return this.init(t,e,o),[t,e];let i=Math.max(.001,(o-this.lastTimestamp)/1e3);return this.lastTimestamp=o,k(this.state,t,e,n,i,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var K={};q(K,{ARRIVAL_THRESHOLD_METERS:()=>Ct,BASE_CORRIDOR_METERS:()=>Q,BEARING_ALIGNMENT_THRESHOLD:()=>it,BEARING_MIN_SPEED_MPS:()=>rt,BEARING_MISMATCH_PENALTY:()=>W,BEARING_MISMATCH_THRESHOLD:()=>V,BEARING_SMOOTHING_ALPHA:()=>ot,BETA_CORRECTION:()=>ft,DETOUR_COMMIT_MS:()=>pt,DR_MAX_AGE_MS:()=>st,GPS_ACCURACY_FACTOR:()=>et,GPS_AGE_CAP_SECONDS:()=>dt,GPS_STALE_MS:()=>ht,INERTIA_PENALTY:()=>G,INERTIA_SEGMENT_DIST:()=>B,LOOK_AHEAD_SECONDS:()=>yt,MANEUVER_TRIGGER_DIST:()=>mt,MAX_CORRIDOR_METERS:()=>Z,MAX_LOOK_AHEAD_METERS:()=>bt,MAX_SNAP_DISTANCE:()=>U,MIN_LOOK_AHEAD_METERS:()=>gt,OFF_ROUTE_CONFIRM_MS:()=>at,REJOIN_CONFIRM_MS:()=>ct,REJOIN_COOLDOWN_MS:()=>lt,SNAP_WINDOW_SIZE:()=>nt,SPEED_CORRIDOR_FACTOR:()=>tt,STARTUP_GRACE_MS:()=>ut});var Q=25,Z=60,tt=1.2,et=.5,U=80,V=90,W=500,G=200,B=5,nt=25,ot=.3,rt=1.5,it=55,st=5e3,at=2e3,ct=1500,lt=12e3,ut=3e3,pt=4e3,ht=3e3,dt=10,mt=25,ft=.15,yt=3,gt=20,bt=100,Ct=30;var Mt={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},D=class{constructor(t){this.options={...Mt,...t};}snap(t,e,n,o,i,l,a,c=null,h=null){let u=e.length,r=a,p=1/0,g=1/0,f=e[a]??[0,0];for(let d=0;d<=o;d++){let y=n+d;if(y>u-2)if(i&&l>u*.7)y=y%(u-1);else break;if(y<0||y>=u-1)continue;let m=e[y],M=e[y+1],b=_(t,m,M),E=R(t[1],t[0],b[1],b[0]);if(E>this.options.maxSnapDistance*2)continue;let A=E;if(this.options.useBearingPenalty&&c!==null){let S=x(m,M);Math.abs(v(c-S))>90&&(A+=500);}this.options.useInertiaPenalty&&h!==null&&Math.abs(y-h)>=5&&(A+=200),A<p&&(p=A,g=E,r=y,f=b);}if(!Number.isFinite(g)){let d=Math.min(Math.max(a,0),Math.max(0,u-2)),y=e[d],m=e[d+1];y&&m?(f=_(t,y,m),g=R(t[1],t[0],f[1],f[0]),r=d):(f=e[Math.min(Math.max(a,0),u-1)]??t,g=R(t[1],t[0],f[1],f[0]),r=0);}return {idx:r,dist:g,proj:f}}};var O=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[OSRM] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:t.baseUrl.replace(/\/$/,""),profile:t.profile??"driving",maxWaypointsPerChunk:t.maxWaypointsPerChunk??100,fetchFn:e,timeoutMs:t.timeoutMs??15e3};}async getRoute(t,e){if(t.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=e?.profile??this.config.profile;return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}async fetchRoute(t,e,n){let o=t.map(u=>`${u[0]},${u[1]}`).join(";"),i=n?.steps!==false?"true":"false",l=`${this.config.baseUrl}/route/v1/${e}/${o}?overview=full&geometries=geojson&steps=${i}&annotations=false`,a=await this.fetchWithTimeout(l);if(!a.ok)throw new Error(`[OSRM] HTTP ${a.status}: ${a.statusText}`);let c=await a.json();if(c.code!=="Ok"||!c.routes?.length)throw new Error(`[OSRM] No route found: ${c.code}`);let h=c.routes[0];return {geometry:h.geometry.coordinates,distance:h.distance,duration:h.duration,legs:(h.legs??[]).map(u=>({distance:u.distance,duration:u.duration,steps:(u.steps??[]).map(r=>({distance:r.distance,duration:r.duration,geometry:r.geometry?.coordinates??[],maneuver:{type:r.maneuver?.type??"unknown",modifier:r.maneuver?.modifier,location:r.maneuver?.location??[0,0],bearingBefore:r.maneuver?.bearing_before??0,bearingAfter:r.maneuver?.bearing_after??0,instruction:r.name??void 0},name:r.name}))})),raw:c}}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[OSRM] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var I=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[Valhalla] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:t.baseUrl.replace(/\/$/,""),costing:t.costing??"auto",apiKey:t.apiKey??"",maxWaypointsPerChunk:t.maxWaypointsPerChunk??50,fetchFn:e,timeoutMs:t.timeoutMs??15e3};}async getRoute(t,e){if(t.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(e?.profile);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileToCosting(t){switch(t){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(t,e,n){let o=t.map(d=>({lon:d[0],lat:d[1],type:"break"})),i=JSON.stringify({locations:o,costing:e,directions_options:{units:"kilometers"}}),l={"Content-Type":"application/json","User-Agent":"NavCoreSDK/1.0.0 (React Native; Expo; bab-bou-jeloud-demo)"};this.config.apiKey&&(l.api_key=this.config.apiKey);let a=await this.fetchWithTimeout(`${this.config.baseUrl}/route`,{method:"POST",headers:l,body:i});if(!a.ok){let d=await a.text();throw new Error(`[Valhalla] HTTP ${a.status}: ${d}`)}let c=await a.json(),h=c.trip?.legs??[],u=h.map(d=>this.decodePolyline(d.shape??"")),r=this.stitchGeometry(u),p=r.length>0?r:t,g=c.trip?.summary??{},f=h.map((d,y)=>({distance:(d.summary?.length??0)*1e3,duration:d.summary?.time??0,steps:(d.maneuvers??[]).map(m=>{let M=u[y]??[],b=this.shapeIndex(m.begin_shape_index,0),E=this.shapeIndex(m.end_shape_index,b),A=M.length>0?M.slice(b,Math.max(b,E)+1):[],S=t[Math.min(y,t.length-1)],L=A[0]??M[b]??S;return {distance:(m.length??0)*1e3,duration:m.time??0,geometry:A,maneuver:{type:m.type?.toString()??"unknown",modifier:void 0,location:L,bearingBefore:m.begin_heading??0,bearingAfter:m.end_heading??0,instruction:m.instruction},name:m.street_names?.[0]}})}));return {geometry:p,distance:(g.length??0)*1e3,duration:g.time??0,legs:f,raw:c}}decodePolyline(t,e=6){let n=Math.pow(10,e),o=[],i=0,l=0,a=0;for(;i<t.length;){let c=0,h=0,u;do u=t.charCodeAt(i++)-63,h|=(u&31)<<c,c+=5;while(u>=32);let r=(h&1)!==0?~(h>>1):h>>1;l+=r,c=0,h=0;do u=t.charCodeAt(i++)-63,h|=(u&31)<<c,c+=5;while(u>=32);let p=(h&1)!==0?~(h>>1):h>>1;a+=p,o.push([a/n,l/n]);}return o}stitchGeometry(t){let e=[];for(let n of t){if(n.length===0)continue;let o=n[0],i=e[e.length-1];i&&this.sameCoordinate(i,o)?e.push(...n.slice(1)):e.push(...n);}return e}sameCoordinate(t,e){return Math.abs(t[0]-e[0])<1e-9&&Math.abs(t[1]-e[1])<1e-9}shapeIndex(t,e){return typeof t=="number"&&Number.isFinite(t)&&t>=0?Math.floor(t):e}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[Valhalla] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var Rt="https://api.openrouteservice.org/v2/directions",At=50,Et=15e3,w=class{constructor(t){let e=t.fetchFn??globalThis.fetch?.bind(globalThis);if(!e)throw new Error("[ORS] fetch is not available. Pass config.fetchFn in this runtime.");this.config={apiKey:t.apiKey,profile:t.profile??"driving-car",baseUrl:t.baseUrl??Rt,maxWaypointsPerChunk:t.maxWaypointsPerChunk??At,fetchFn:e,timeoutMs:t.timeoutMs??Et};}async getRoute(t,e){if(t.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(e);return t.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(t,n,e):this.fetchChunked(t,n,e)}profileFromOptions(t){switch(t?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(t,e,n){let o=JSON.stringify({coordinates:t,instructions:n?.steps!==false,language:n?.language??"en"}),i=await this.fetchWithTimeout(`${this.config.baseUrl}/${e}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:o});if(!i.ok){let p=await i.text();throw new Error(`[ORS] HTTP ${i.status}: ${p}`)}let l=await i.json(),a=l.features?.[0];if(!a)throw new Error("[ORS] No route returned");let c=a.properties?.summary??{},h=a.properties?.segments??[],u=a.geometry?.coordinates??[],r=h.map((p,g)=>({distance:p.distance??0,duration:p.duration??0,steps:(p.steps??[]).map(f=>{let[d,y]=this.stepRange(f.way_points),m=u.slice(d,Math.max(d,y)+1),M=t[Math.min(g,t.length-1)],b=m[0]??u[d]??M;return {distance:f.distance??0,duration:f.duration??0,geometry:m,maneuver:{type:f.type?.toString()??"unknown",modifier:void 0,location:b,bearingBefore:this.bearingFromGeometry(m,false),bearingAfter:this.bearingFromGeometry(m,true),instruction:f.instruction},name:f.name}})}));return {geometry:u,distance:c.distance??0,duration:c.duration??0,legs:r,raw:l}}async fetchChunked(t,e,n){let o=this.config.maxWaypointsPerChunk,i=[];for(let r=0;r<t.length;r+=o-1){let p=t.slice(r,r+o);if(p.length<2||(i.push(p),r+o>=t.length))break}let l=await Promise.all(i.map(r=>this.fetchRoute(r,e,n))),a=[],c=0,h=0,u=[];for(let r=0;r<l.length;r++){let p=l[r];a.push(...r===0?p.geometry:p.geometry.slice(1)),c+=p.distance,h+=p.duration,u.push(...p.legs);}return {geometry:a,distance:c,duration:h,legs:u,raw:l.map(r=>r.raw)}}stepRange(t){if(!Array.isArray(t))return [0,0];let e=typeof t[0]=="number"&&Number.isFinite(t[0])?Math.max(0,Math.floor(t[0])):0,n=typeof t[1]=="number"&&Number.isFinite(t[1])?Math.max(e,Math.floor(t[1])):e;return [e,n]}bearingFromGeometry(t,e){if(t.length<2)return 0;let n=e?t[t.length-2]:t[0],o=e?t[t.length-1]:t[1];return !n||!o?0:x(n,o)}async fetchWithTimeout(t,e){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(t,e);let n=new AbortController,o=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(t,{...e,signal:n.signal})}catch(i){throw i.name==="AbortError"?new Error(`[ORS] Request timed out after ${this.config.timeoutMs}ms`):i}finally{clearTimeout(o);}}};var xt=0;function H(){return `wp_${Date.now()}_${++xt}`}var T=class{constructor(){this.waypoints=[];}addWaypoint(t,e){let n=H();return this.waypoints.push({id:n,coord:t,options:e}),n}insertWaypoint(t,e){let n=this.waypoints.findIndex(i=>i.id===e);if(n===-1)throw new Error(`Waypoint ${e} not found`);let o=H();return this.waypoints.splice(n+1,0,{id:o,coord:t,options:void 0}),o}removeWaypoint(t){let e=this.waypoints.findIndex(n=>n.id===t);if(e===-1)throw new Error(`Waypoint ${t} not found`);this.waypoints.splice(e,1);}moveWaypoint(t,e){let n=this.waypoints.find(o=>o.id===t);if(!n)throw new Error(`Waypoint ${t} not found`);n.coord=e;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(t="OVERLAP_1",e=25){let n=this.waypoints.map(a=>a.coord);if(n.length<=e)return [n];let i=e-(t==="OVERLAP_2"?2:1),l=[];for(let a=0;a<n.length;a+=i){let c=n.slice(a,a+e);if(l.push(c),a+e>=n.length)break}return l}buildStraightLine(){return {geometry:this.waypoints.map(t=>t.coord),waypoints:[...this.waypoints]}}fromGPX(t){this.waypoints=[];let e=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=e.exec(t))!==null;){let o=parseFloat(n[1]),i=parseFloat(n[2]);isFinite(o)&&isFinite(i)&&this.addWaypoint([i,o]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
2
2
  <gpx version="1.1" creator="NavCore SDK">
3
3
  ${this.waypoints.map(e=>` <wpt lat="${e.coord[1]}" lon="${e.coord[0]}">`+(e.options?.name?`
4
4
  <name>${e.options.name}</name>`:"")+`
5
5
  </wpt>`).join(`
6
6
  `)}
7
- </gpx>`}fromGeoJSON(t){if(this.waypoints=[],t.type==="FeatureCollection"&&t.features){for(let e of t.features)if(e.geometry.type==="Point"){let n=e.geometry.coordinates;this.addWaypoint(n);}else if(e.geometry.type==="LineString"){let n=e.geometry.coordinates;for(let r of n)this.addWaypoint(r);}}}toGeoJSON(){let t=this.waypoints.map((n,r)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:r,name:n.options?.name??null,silent:n.options?.silent??false}})),e={type:"Feature",geometry:{type:"LineString",coordinates:this.waypoints.map(n=>n.coord)},properties:{type:"route"}};return {type:"FeatureCollection",features:[...t,e]}}clear(){this.waypoints=[];}};var O={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",PROGRESS_TRACKING:"progress_tracking",ROUTE_OFFSET:"route_offset",DEAD_RECKONING:"dead_reckoning",ADVANCED_BEARING:"advanced_bearing",COMPOUND_DEVIATION:"compound_deviation",PARALLEL_ROAD_RESOLUTION:"parallel_road_resolution",U_TURN_PROTECTION:"u_turn_protection",VOICE_TRIGGERS:"voice_triggers",ETA:"eta",GEOFENCING:"geofencing",NAV_AI:"nav_ai"};var y=class y{constructor(t){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;t&&(this.tryValidateSync(t)||this.validate(t)),this.promoteToActive();}static getActive(){return y.activeManager}static clearActive(){y.activeManager=null;}promoteToActive(){let t=y.activeManager;(t===null||t.status!=="VALID"||this.status==="VALID")&&(y.activeManager=this);}tryValidateSync(t){return t==="eyJ0IjoicHJvIiwiZXhwIjo0OTMyNzAzMTU2MDAwLCJiaWQiOiJkZXYuYnlwYXNzIiwiZiI6WyIqIl19.MEQCIH4E4QNu9PuVsXHSnYmcqpCLk4QitiIH9hhY0Zm+YO5gAiAE7X3c47YQLUj7WPSGKw9Y7W2kBUR5GCnOMBwdBsYGgg=="?typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)?(this.status="VALID",this.payload={t:"pro",exp:4932703156e3,bid:"dev.bypass",f:["*"]},this.extractFeatures(),console.log("\u{1F511} [NavCore] Development bypass key validated synchronously. Plan: pro"),true):(console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,true):false}async validate(t){if(this.tryValidateSync(t))return this.status;try{let[e,n]=t.split(".");if(!e||!n)return this.status="INVALID",this.status;let r=atob(e);if(this.payload=JSON.parse(r),!this.payload||this.payload.exp<Date.now())return this.status="EXPIRED",this.status;if(!await this.verifySignature(e,n))return this.status="INVALID",this.status;if(this.payload?.bid==="dev.bypass"&&!(typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)))return console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,this.status;this.status="VALID",this.extractFeatures(),this.promoteToActive(),console.log(`\u{1F511} [NavCore] License validation complete. Plan: ${this.isProEnabled()?"pro":"core"}`);}catch{this.status="INVALID";}return this.status}extractFeatures(){if(this.enabledFeatures.clear(),!!this.payload){if(Array.isArray(this.payload.f))for(let t of this.payload.f)this.enabledFeatures.add(t);this.payload.t==="pro"&&this.enabledFeatures.add("*");}}hasFeature(t){return this.status!=="VALID"?false:this.enabledFeatures.has("*")?true:this.enabledFeatures.has(t)}warnOnce(t){this.warnedFeatures.has(t)||(console.warn(`[NavCore] Feature '${t}' requires a Pro license`),this.warnedFeatures.add(t));}isProEnabled(){return this.hasFeature("*")}isAIEnabled(){return this.hasFeature(O.NAV_AI)}getStatus(){return this.status}getPayload(){return this.payload}getEnabledFeatures(){return Array.from(this.enabledFeatures)}async verifySignature(t,e){try{if(typeof crypto>"u"||!crypto.subtle)return !1;let r=new TextEncoder().encode(t),s=Uint8Array.from(atob(e),a=>a.charCodeAt(0)),l=Uint8Array.from(atob(y.PUBLIC_KEY_SPKI),a=>a.charCodeAt(0)),p=await crypto.subtle.importKey("spki",l,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},p,s,r)}catch{return false}}};y.activeManager=null,y.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var I=y;export{B as Constants,M as CustomRouteBuilder,O as FEATURES,x as KalmanFilter2D,I as LicenseManager,P as OSRMDirectionsProvider,D as OpenRouteServiceProvider,E as RouteSnapper,_ as ValhallaDirectionsProvider,J as buildForwardCumulativeDistances,q as buildReverseCumulativeDistances,X as destinationPoint,j as geoGetBearing,S as getBearingBetweenPoints,f as haversineDistance,Y as interpolatePoint,L as kalmanUpdate2D,v as normalizeAngle,A as projectPointOnSegment};
7
+ </gpx>`}fromGeoJSON(t){if(this.waypoints=[],t.type==="FeatureCollection"&&t.features){for(let e of t.features)if(e.geometry.type==="Point"){let n=e.geometry.coordinates;this.addWaypoint(n);}else if(e.geometry.type==="LineString"){let n=e.geometry.coordinates;for(let o of n)this.addWaypoint(o);}}}toGeoJSON(){let t=this.waypoints.map((n,o)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:o,name:n.options?.name??null,silent:n.options?.silent??false}})),e={type:"Feature",geometry:{type:"LineString",coordinates:this.waypoints.map(n=>n.coord)},properties:{type:"route"}};return {type:"FeatureCollection",features:[...t,e]}}clear(){this.waypoints=[];}};var F={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",PROGRESS_TRACKING:"progress_tracking",ROUTE_OFFSET:"route_offset",DEAD_RECKONING:"dead_reckoning",ADVANCED_BEARING:"advanced_bearing",COMPOUND_DEVIATION:"compound_deviation",PARALLEL_ROAD_RESOLUTION:"parallel_road_resolution",U_TURN_PROTECTION:"u_turn_protection",VOICE_TRIGGERS:"voice_triggers",ETA:"eta",GEOFENCING:"geofencing",NAV_AI:"nav_ai"};var C=class C{constructor(t){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;t&&(this.tryValidateSync(t)||this.validate(t)),this.promoteToActive();}static getActive(){return C.activeManager}static clearActive(){C.activeManager=null;}promoteToActive(){let t=C.activeManager;(t===null||t.status!=="VALID"||this.status==="VALID")&&(C.activeManager=this);}tryValidateSync(t){return t==="eyJ0IjoicHJvIiwiZXhwIjo0OTMyNzAzMTU2MDAwLCJiaWQiOiJkZXYuYnlwYXNzIiwiZiI6WyIqIl19.MEQCIH4E4QNu9PuVsXHSnYmcqpCLk4QitiIH9hhY0Zm+YO5gAiAE7X3c47YQLUj7WPSGKw9Y7W2kBUR5GCnOMBwdBsYGgg=="?typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)?(this.status="VALID",this.payload={t:"pro",exp:4932703156e3,bid:"dev.bypass",f:["*"]},this.extractFeatures(),console.log("\u{1F511} [NavCore] Development bypass key validated synchronously. Plan: pro"),true):(console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,true):false}async validate(t){if(this.tryValidateSync(t))return this.status;try{let[e,n]=t.split(".");if(!e||!n)return this.status="INVALID",this.status;let o=atob(e);if(this.payload=JSON.parse(o),!this.payload||this.payload.exp<Date.now())return this.status="EXPIRED",this.status;if(!await this.verifySignature(e,n))return this.status="INVALID",this.status;if(this.payload?.bid==="dev.bypass"&&!(typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)))return console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,this.status;this.status="VALID",this.extractFeatures(),this.promoteToActive(),console.log(`\u{1F511} [NavCore] License validation complete. Plan: ${this.isProEnabled()?"pro":"core"}`);}catch{this.status="INVALID";}return this.status}extractFeatures(){if(this.enabledFeatures.clear(),!!this.payload){if(Array.isArray(this.payload.f))for(let t of this.payload.f)this.enabledFeatures.add(t);this.payload.t==="pro"&&this.enabledFeatures.add("*");}}hasFeature(t){return this.status!=="VALID"?false:this.enabledFeatures.has("*")?true:this.enabledFeatures.has(t)}warnOnce(t){this.warnedFeatures.has(t)||(console.warn(`[NavCore] Feature '${t}' requires a Pro license`),this.warnedFeatures.add(t));}isProEnabled(){return this.hasFeature("*")}isAIEnabled(){return this.hasFeature(F.NAV_AI)}getStatus(){return this.status}getPayload(){return this.payload}getEnabledFeatures(){return Array.from(this.enabledFeatures)}async verifySignature(t,e){try{if(typeof crypto>"u"||!crypto.subtle)return !1;let o=new TextEncoder().encode(t),i=Uint8Array.from(atob(e),c=>c.charCodeAt(0)),l=Uint8Array.from(atob(C.PUBLIC_KEY_SPKI),c=>c.charCodeAt(0)),a=await crypto.subtle.importKey("spki",l,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},a,i,o)}catch{return false}}};C.activeManager=null,C.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var N=C;export{K as Constants,T as CustomRouteBuilder,F as FEATURES,P as KalmanFilter2D,N as LicenseManager,O as OSRMDirectionsProvider,w as OpenRouteServiceProvider,D as RouteSnapper,I as ValhallaDirectionsProvider,J as buildForwardCumulativeDistances,z as buildReverseCumulativeDistances,X as destinationPoint,j as geoGetBearing,x as getBearingBetweenPoints,R as haversineDistance,Y as interpolatePoint,k as kalmanUpdate2D,v as normalizeAngle,_ as projectPointOnSegment};
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Coordinate } from './NavCore.d-BuXR5DO7.mjs';
2
- export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, d as LifecycleContext, e as LifecycleEvent, N as NavCore, f as NavCoreOptions, g as NavCoreState, h as NavGpsUpdate, i as NavInstruction, j as NavLifecycleState, k as NavigationFSM, O as OffRouteContext, l as OffRouteEvent, m as OffRouteFSM, n as OffRouteState, R as RejoinTarget, T as TempRoute, o as destinationPoint, p as geoGetBearing, q as haversineDistance, r as resolveNextInstruction } from './NavCore.d-BuXR5DO7.mjs';
1
+ import { C as Coordinate } from './NavCore-DzTPBxIc.mjs';
2
+ export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, d as LifecycleContext, e as LifecycleEvent, N as NavCore, f as NavCoreOptions, g as NavCoreState, h as NavGpsUpdate, i as NavInstruction, j as NavLifecycleState, k as NavigationFSM, O as OffRouteContext, l as OffRouteEvent, m as OffRouteFSM, n as OffRouteState, R as RejoinTarget, T as TempRoute, o as destinationPoint, p as geoGetBearing, q as haversineDistance, r as resolveNextInstruction } from './NavCore-DzTPBxIc.mjs';
3
3
  export { BuildOptions, CameraOptions, Constants, CustomRouteBuilder, CustomWaypoint, DirectionsLeg, DirectionsManeuver, DirectionsOptions, DirectionsProvider, DirectionsResult, DirectionsStep, Kalman2DState, KalmanFilter2D, MapRendererAdapter, ORSConfig, ORSProfile, OSRMConfig, OSRMDirectionsProvider, OpenRouteServiceProvider, RouteSnapper, RouteStyle, SnapResult, SnapperOptions, ValhallaConfig, ValhallaCostingModel, ValhallaDirectionsProvider, VehicleStyle, WaypointOptions, buildForwardCumulativeDistances, buildReverseCumulativeDistances, getBearingBetweenPoints, interpolatePoint, kalmanUpdate2D, normalizeAngle, projectPointOnSegment } from './core.mjs';
4
4
  export { DeadReckoningEngine, DeviationDetector, ETAEngine, ETAOptions, ETAResult, GeofenceEvent, GeofenceEventType, GeofenceType, GeofencingEngine, GeofencingOptions, InstructionEditor, InstructionType, ParallelRoadResolver, ParallelRoadResolverOptions, ResolvedCandidate, RichInstruction, SnapCandidate, VoiceCue, VoicePriority, VoiceTriggerEngine, VoiceTriggerOptions, ZoneDefinition, calculateDynamicCorridor, computeDeadReckoningOnRoute } from './pro.mjs';
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { C as Coordinate } from './NavCore.d-BuXR5DO7.js';
2
- export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, d as LifecycleContext, e as LifecycleEvent, N as NavCore, f as NavCoreOptions, g as NavCoreState, h as NavGpsUpdate, i as NavInstruction, j as NavLifecycleState, k as NavigationFSM, O as OffRouteContext, l as OffRouteEvent, m as OffRouteFSM, n as OffRouteState, R as RejoinTarget, T as TempRoute, o as destinationPoint, p as geoGetBearing, q as haversineDistance, r as resolveNextInstruction } from './NavCore.d-BuXR5DO7.js';
1
+ import { C as Coordinate } from './NavCore-DzTPBxIc.js';
2
+ export { F as FEATURES, a as FeatureKey, L as LicenseManager, b as LicensePayload, c as LicenseStatus, d as LifecycleContext, e as LifecycleEvent, N as NavCore, f as NavCoreOptions, g as NavCoreState, h as NavGpsUpdate, i as NavInstruction, j as NavLifecycleState, k as NavigationFSM, O as OffRouteContext, l as OffRouteEvent, m as OffRouteFSM, n as OffRouteState, R as RejoinTarget, T as TempRoute, o as destinationPoint, p as geoGetBearing, q as haversineDistance, r as resolveNextInstruction } from './NavCore-DzTPBxIc.js';
3
3
  export { BuildOptions, CameraOptions, Constants, CustomRouteBuilder, CustomWaypoint, DirectionsLeg, DirectionsManeuver, DirectionsOptions, DirectionsProvider, DirectionsResult, DirectionsStep, Kalman2DState, KalmanFilter2D, MapRendererAdapter, ORSConfig, ORSProfile, OSRMConfig, OSRMDirectionsProvider, OpenRouteServiceProvider, RouteSnapper, RouteStyle, SnapResult, SnapperOptions, ValhallaConfig, ValhallaCostingModel, ValhallaDirectionsProvider, VehicleStyle, WaypointOptions, buildForwardCumulativeDistances, buildReverseCumulativeDistances, getBearingBetweenPoints, interpolatePoint, kalmanUpdate2D, normalizeAngle, projectPointOnSegment } from './core.js';
4
4
  export { DeadReckoningEngine, DeviationDetector, ETAEngine, ETAOptions, ETAResult, GeofenceEvent, GeofenceEventType, GeofenceType, GeofencingEngine, GeofencingOptions, InstructionEditor, InstructionType, ParallelRoadResolver, ParallelRoadResolverOptions, ResolvedCandidate, RichInstruction, SnapCandidate, VoiceCue, VoicePriority, VoiceTriggerEngine, VoiceTriggerOptions, ZoneDefinition, calculateDynamicCorridor, computeDeadReckoningOnRoute } from './pro.js';
5
5
 
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- 'use strict';var Ne=Object.defineProperty;var Pe=(s,e)=>{for(var t in e)Ne(s,t,{get:e[t],enumerable:true});};function y(s,e,t,n){let i=(t-s)*(Math.PI/180),r=(n-e)*(Math.PI/180),o=Math.sin(i/2)*Math.sin(i/2)+Math.cos(s*(Math.PI/180))*Math.cos(t*(Math.PI/180))*Math.sin(r/2)*Math.sin(r/2);return 6371e3*(2*Math.atan2(Math.sqrt(o),Math.sqrt(1-o)))}function B(s,e,t,n){let i=n/6371e3,r=t*(Math.PI/180),o=s*(Math.PI/180),c=e*(Math.PI/180),a=Math.asin(Math.sin(o)*Math.cos(i)+Math.cos(o)*Math.sin(i)*Math.cos(r));return [((c+Math.atan2(Math.sin(r)*Math.sin(i)*Math.cos(o),Math.cos(i)-Math.sin(o)*Math.sin(a)))*180/Math.PI+540)%360-180,a*180/Math.PI]}function we(s,e){let t=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),i=e[1]*(Math.PI/180),r=e[0]*(Math.PI/180),o=Math.sin(r-n)*Math.cos(i),c=Math.cos(t)*Math.sin(i)-Math.sin(t)*Math.cos(i)*Math.cos(r-n),a=Math.atan2(o,c)*(180/Math.PI);return a=(a+360)%360,a}function E(s){let e=s%360;return e>180?e-360:e<-180?e+360:e}function R(s,e){let t=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),i=e[1]*(Math.PI/180),r=e[0]*(Math.PI/180),o=Math.sin(r-n)*Math.cos(i),c=Math.cos(t)*Math.sin(i)-Math.sin(t)*Math.cos(i)*Math.cos(r-n);return (Math.atan2(o,c)*180/Math.PI+360)%360}function W(s,e,t){let n=(i,r,o)=>i+(r-i)*o;return [n(s[0],e[0],t),n(s[1],e[1],t)]}function H(s,e,t){let[n,i]=s,[r,o]=e,[c,a]=t,u=c-r,d=a-o,l=u*u+d*d;if(l===0)return e;let p=((n-r)*u+(i-o)*d)/l;return p=Math.max(0,Math.min(1,p)),[r+p*u,o+p*d]}function K(s){let e=new Float64Array(s.length);for(let t=1;t<s.length;t++)e[t]=e[t-1]+y(s[t-1][1],s[t-1][0],s[t][1],s[t][0]);return e}function j(s){let e=new Float64Array(s.length);for(let t=s.length-2;t>=0;t--)e[t]=e[t+1]+y(s[t][1],s[t][0],s[t+1][1],s[t+1][0]);return e}function me(s,e,t,n,i,r=1e-5,o=5e-5){s.x+=s.vx*i,s.y+=s.vy*i,s.P+=r;let c=o*Math.max(1,n/5),a=s.P/(s.P+c),u=e-s.x,d=t-s.y;return s.x+=a*u,s.y+=a*d,i>0&&(s.vx=u/i*a,s.vy=d/i*a),s.P=(1-a)*s.P,s}var D=class{constructor(e=1e-5,t=5e-5){this.lastTimestamp=0;this.Q=e,this.rBase=t,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(e,t,n){this.state={x:e,y:t,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(e,t,n,i){if(this.lastTimestamp===0)return this.init(e,t,i),[e,t];let r=Math.max(.001,(i-this.lastTimestamp)/1e3);return this.lastTimestamp=i,me(this.state,e,t,n,r,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var Se={};Pe(Se,{ARRIVAL_THRESHOLD_METERS:()=>Ce,BASE_CORRIDOR_METERS:()=>k,BEARING_ALIGNMENT_THRESHOLD:()=>xe,BEARING_MIN_SPEED_MPS:()=>z,BEARING_MISMATCH_PENALTY:()=>ye,BEARING_MISMATCH_THRESHOLD:()=>J,BEARING_SMOOTHING_ALPHA:()=>U,BETA_CORRECTION:()=>be,DETOUR_COMMIT_MS:()=>Ue,DR_MAX_AGE_MS:()=>Y,GPS_ACCURACY_FACTOR:()=>ge,GPS_AGE_CAP_SECONDS:()=>ve,GPS_STALE_MS:()=>Ie,INERTIA_PENALTY:()=>Re,INERTIA_SEGMENT_DIST:()=>Ee,LOOK_AHEAD_SECONDS:()=>Be,MANEUVER_TRIGGER_DIST:()=>Ve,MAX_CORRIDOR_METERS:()=>$,MAX_LOOK_AHEAD_METERS:()=>He,MAX_SNAP_DISTANCE:()=>q,MIN_LOOK_AHEAD_METERS:()=>We,OFF_ROUTE_CONFIRM_MS:()=>Fe,REJOIN_CONFIRM_MS:()=>Ge,REJOIN_COOLDOWN_MS:()=>Le,SNAP_WINDOW_SIZE:()=>X,SPEED_CORRIDOR_FACTOR:()=>fe,STARTUP_GRACE_MS:()=>ke});var k=25,$=60,fe=1.2,ge=.5,q=80,J=90,ye=500,Re=200,Ee=5,X=25,U=.3,z=1.5,xe=55,Y=5e3,Fe=2e3,Ge=1500,Le=12e3,ke=3e3,Ue=4e3,Ie=3e3,ve=10,Ve=25,be=.15,Be=3,We=20,He=100,Ce=30;var Ke={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},N=class{constructor(e){this.options={...Ke,...e};}snap(e,t,n,i,r,o,c,a=null,u=null){let d=t.length,l=c,p=1/0,f=1/0,I=t[c]??[0,0];for(let v=0;v<=i;v++){let g=n+v;if(g>d-2)if(r&&o>d*.7)g=g%(d-1);else break;if(g<0||g>=d-1)continue;let b=t[g],x=t[g+1],S=H(e,b,x),O=y(e[1],e[0],S[1],S[0]);if(O>this.options.maxSnapDistance*2)continue;let C=O;if(this.options.useBearingPenalty&&a!==null){let T=R(b,x);Math.abs(E(a-T))>90&&(C+=500);}this.options.useInertiaPenalty&&u!==null&&Math.abs(g-u)>=5&&(C+=200),C<p&&(p=C,f=O,l=g,I=S);}return {idx:l,dist:f,proj:I}}};var h={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",PROGRESS_TRACKING:"progress_tracking",ROUTE_OFFSET:"route_offset",DEAD_RECKONING:"dead_reckoning",ADVANCED_BEARING:"advanced_bearing",COMPOUND_DEVIATION:"compound_deviation",PARALLEL_ROAD_RESOLUTION:"parallel_road_resolution",U_TURN_PROTECTION:"u_turn_protection",VOICE_TRIGGERS:"voice_triggers",ETA:"eta",GEOFENCING:"geofencing",NAV_AI:"nav_ai"};var A=class A{constructor(e){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;e&&(this.tryValidateSync(e)||this.validate(e)),this.promoteToActive();}static getActive(){return A.activeManager}static clearActive(){A.activeManager=null;}promoteToActive(){let e=A.activeManager;(e===null||e.status!=="VALID"||this.status==="VALID")&&(A.activeManager=this);}tryValidateSync(e){return e==="eyJ0IjoicHJvIiwiZXhwIjo0OTMyNzAzMTU2MDAwLCJiaWQiOiJkZXYuYnlwYXNzIiwiZiI6WyIqIl19.MEQCIH4E4QNu9PuVsXHSnYmcqpCLk4QitiIH9hhY0Zm+YO5gAiAE7X3c47YQLUj7WPSGKw9Y7W2kBUR5GCnOMBwdBsYGgg=="?typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)?(this.status="VALID",this.payload={t:"pro",exp:4932703156e3,bid:"dev.bypass",f:["*"]},this.extractFeatures(),console.log("\u{1F511} [NavCore] Development bypass key validated synchronously. Plan: pro"),true):(console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,true):false}async validate(e){if(this.tryValidateSync(e))return this.status;try{let[t,n]=e.split(".");if(!t||!n)return this.status="INVALID",this.status;let i=atob(t);if(this.payload=JSON.parse(i),!this.payload||this.payload.exp<Date.now())return this.status="EXPIRED",this.status;if(!await this.verifySignature(t,n))return this.status="INVALID",this.status;if(this.payload?.bid==="dev.bypass"&&!(typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)))return console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,this.status;this.status="VALID",this.extractFeatures(),this.promoteToActive(),console.log(`\u{1F511} [NavCore] License validation complete. Plan: ${this.isProEnabled()?"pro":"core"}`);}catch{this.status="INVALID";}return this.status}extractFeatures(){if(this.enabledFeatures.clear(),!!this.payload){if(Array.isArray(this.payload.f))for(let e of this.payload.f)this.enabledFeatures.add(e);this.payload.t==="pro"&&this.enabledFeatures.add("*");}}hasFeature(e){return this.status!=="VALID"?false:this.enabledFeatures.has("*")?true:this.enabledFeatures.has(e)}warnOnce(e){this.warnedFeatures.has(e)||(console.warn(`[NavCore] Feature '${e}' requires a Pro license`),this.warnedFeatures.add(e));}isProEnabled(){return this.hasFeature("*")}isAIEnabled(){return this.hasFeature(h.NAV_AI)}getStatus(){return this.status}getPayload(){return this.payload}getEnabledFeatures(){return Array.from(this.enabledFeatures)}async verifySignature(e,t){try{if(typeof crypto>"u"||!crypto.subtle)return !1;let i=new TextEncoder().encode(e),r=Uint8Array.from(atob(t),a=>a.charCodeAt(0)),o=Uint8Array.from(atob(A.PUBLIC_KEY_SPKI),a=>a.charCodeAt(0)),c=await crypto.subtle.importKey("spki",o,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},c,r,i)}catch{return false}}};A.activeManager=null,A.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var m=A;var je={bearingPenalty:80,bearingMismatchThresholdDeg:60,inertiaPenalty:40,inertiaSegmentDist:3},Q=class{constructor(e){this.warned=false;this.options={...je,...e};}resolve(e,t=null,n=null){let i=m.getActive();return (!i||!i.isProEnabled())&&(this.warned||(console.warn("[NavCore] ParallelRoadResolver and U-turn protection require a Pro license. Falling back to core distance snapping."),this.warned=true)),e.map(r=>this.score(r,t,n)).sort((r,o)=>r.score-o.score)}resolveBest(e,t=null,n=null){return e.length===0?null:this.resolve(e,t,n)[0]??null}score(e,t,n){let i=e.distanceMetres,r=null,o=false,c=m.getActive(),a=c&&c.isProEnabled();if(t!==null&&a){let u=R(e.segA,e.segB),d=Math.abs(E(t-u));r=d,d>this.options.bearingMismatchThresholdDeg&&(i+=this.options.bearingPenalty);}return n!==null&&a&&Math.abs(e.segmentIndex-n)>=this.options.inertiaSegmentDist&&(i+=this.options.inertiaPenalty,o=true),{...e,score:i,bearingDeltaDeg:r,inertiaPenaltyApplied:o}}isLikelyUTurn(e,t,n){let i=R(t,n);return Math.abs(E(e-i))>this.options.bearingMismatchThresholdDeg}};function Ae(s,e,t,n,i=5e3){if(!s||e<.5)return {predictedCoord:s?.coord??[0,0],isActive:false,ageMs:0};let r=n-s.ts;if(r>i||r<0)return {predictedCoord:s.coord,isActive:false,ageMs:r};let o=e*(r/1e3);return {predictedCoord:B(s.coord[1],s.coord[0],t,o),isActive:true,ageMs:r}}var P=class{constructor(e=5e3){this.anchor=null;this.warned=false;this.maxAgeMs=e;}setAnchor(e,t,n){this.anchor={coord:e,idx:t,ts:n};}predict(e,t,n){let i=m.getActive();return !i||!i.hasFeature(h.DEAD_RECKONING)?(this.warned||(i?i.warnOnce(h.DEAD_RECKONING):console.warn(`[NavCore] Feature '${h.DEAD_RECKONING}' requires a Pro license`),this.warned=true),{predictedCoord:this.anchor?.coord??[0,0],isActive:false,ageMs:0}):(this.warned=false,Ae(this.anchor,e,t,n,this.maxAgeMs))}clearAnchor(){this.anchor=null;}getAnchor(){return this.anchor}};function Oe(s,e,t,n,i=null){let r=Math.max(0,t),o=1/0,c=e[r]??[0,0],a=Math.min(t+n,e.length-1);for(let u=Math.max(0,t);u<a;u++){let d=e[u],l=e[u+1],[p,f]=s,[I,v]=d,[g,b]=l,x=g-I,S=b-v,O=x*x+S*S,C;if(O===0)C=d;else {let _=((p-I)*x+(f-v)*S)/O;_=Math.max(0,Math.min(1,_)),C=[I+_*x,v+_*S];}let T=y(s[1],s[0],C[1],C[0]);if(i!==null&&T<o*1.5){let _=R(d,l);if(Math.abs(E(i-_))>120)continue}T<o&&(o=T,r=u,c=C);}return {segmentIndex:r,distance:o,projection:c}}var w=class{constructor(){this.warned=false;}evaluate(e,t,n,i,r,o,c){let a=m.getActive();if(!a||!a.hasFeature(h.COMPOUND_DEVIATION))return this.warned||(a?a.warnOnce(h.COMPOUND_DEVIATION):console.warn(`[NavCore] Feature '${h.COMPOUND_DEVIATION}' requires a Pro license`),this.warned=true),{distanceToRoute:i.distance,outsideCorridor:false,bearingMismatch:false,movingAway:false,confirmed:false};this.warned=false;let u=i.distance>o,d=false;if(t!==null&&i.segmentIndex<r.length-1){let f=R(r[i.segmentIndex],r[i.segmentIndex+1]);d=Math.abs(E(t-f))>90;}let l=false;if(c!==null&&n>1.5){let f=r[Math.min(i.segmentIndex+2,r.length-1)];l=y(e[1],e[0],f[1],f[0])>c+5;}let p=u&&(d||l);return {distanceToRoute:i.distance,outsideCorridor:u,bearingMismatch:d,movingAway:l,confirmed:p}}};function Z(s,e=null,t=25,n=60,i=1.2,r=.5){let o=t+s*i;return e!==null&&e>0&&(o+=e*r),Math.min(o,n)}function _e(s,e=.3){return s<1.5?e*.5:s>20?Math.min(.9,e*2):e}function Me(s,e,t=3){let n=Math.min(e+t,s.length-1);return e>=s.length-1||e===n?e>0?R(s[e-1],s[e]):0:R(s[e],s[n])}function V(s,e,t){let n=E(e-s);return (s+t*n+360)%360}function ee(s,e,t,n,i,r=.3){let o=_e(n,r),c=Me(e,t);if(i!==null&&n>1.5){let a=V(s,i,o*.3);return V(a,c,o)}return V(s,c,o)}function te(s,e,t,n,i){return e<s||e>s+30||n>i?s:e}var $e=20,qe=60,Je=3;function ne(s,e,t,n,i,r,o,c=0){if(!e||e.length===0||t>=e.length)return {nextIdx:t,instruction:null,wasTriggered:false};let a=t;for(;a<e.length;){let g=e[a],b=s>g.geometryIndex+30,x=g.cumulativeOffset!==void 0&&o>g.cumulativeOffset+15;if(!b&&!x)break;a++;}if(a>=e.length)return {nextIdx:a,instruction:null,wasTriggered:false};let u=e[a],d=u.cumulativeOffset!==void 0?Math.max(0,u.cumulativeOffset-o):y(i[1],i[0],u.location[1],u.location[0]),l=Math.min(qe,Math.max($e,c*Je)),p=s<=u.geometryIndex+2,I=d<=l&&p,v=false;if(I){let g=true,b=u.bearingAfter??(u.geometryIndex<n.length-1?R(n[u.geometryIndex],n[u.geometryIndex+1]):null),x=u.bearingBefore??(u.geometryIndex>0?R(n[u.geometryIndex-1],n[u.geometryIndex]):null);x!==null&&b!==null&&r!==null&&Math.abs(E(b-x))>30&&Math.abs(E(r-b))>55&&(g=false),g&&(v=true);}return {nextIdx:a,instruction:u,wasTriggered:v}}var Xe=0;function F(){return `instr_${Date.now()}_${++Xe}`}var ie=class{constructor(){this.instructions=[];}addTurn(e,t,n,i){return this.instructions.push({id:F(),type:"turn",location:e,text:t,instruction:t,geometryIndex:n,silent:i?.silent,meta:i?.meta}),this}addExamPoint(e,t,n,i){return this.instructions.push({id:F(),type:"exam_point",location:e,text:t,instruction:t,geometryIndex:n,severity:i?.severity??"info",silent:i?.silent,meta:i?.meta}),this}addCheckpoint(e,t,n){return this.instructions.push({id:F(),type:"checkpoint",location:e,text:"",instruction:"",geometryIndex:t,silent:true,meta:n}),this}addDepart(e,t="Start navigation"){let n={id:F(),type:"depart",location:e,text:t,instruction:t,geometryIndex:0};return this.instructions.unshift(n),this}addArrive(e,t="You have arrived"){return this.instructions.push({id:F(),type:"arrive",location:e,text:t,instruction:t,geometryIndex:Number.MAX_SAFE_INTEGER}),this}update(e,t){let n=this.instructions.findIndex(i=>i.id===e);if(n===-1)throw new Error(`[InstructionEditor] Instruction ${e} not found`);return this.instructions[n]={...this.instructions[n],...t},this}remove(e){let t=this.instructions.findIndex(n=>n.id===e);if(t===-1)throw new Error(`[InstructionEditor] Instruction ${e} not found`);return this.instructions.splice(t,1),this}reorder(e,t){let n=this.instructions.findIndex(r=>r.id===e);if(n===-1)throw new Error(`[InstructionEditor] Instruction ${e} not found`);let[i]=this.instructions.splice(n,1);return this.instructions.splice(Math.max(0,t),0,i),this}sort(){return this.instructions.sort((e,t)=>e.geometryIndex-t.geometryIndex),this}clear(){return this.instructions=[],this}attachToCumulative(e){let t=m.getActive();if(!t||!t.isProEnabled())return console.warn("[NavCore] InstructionEditor requires a Pro license. Fluent editing is disabled."),this;if(e.length<2)return this;let n=[0];for(let i=1;i<e.length;i++){let r=e[i-1],o=e[i];n.push(n[i-1]+y(r[1],r[0],o[1],o[0]));}for(let i of this.instructions){let r=Math.min(i.geometryIndex,e.length-1);i.cumulativeOffset=n[r]??0,r>0&&r<e.length-1&&(i.bearingBefore=R(e[r-1],e[r]),i.bearingAfter=R(e[r],e[r+1]));}return this}toArray(){let e=m.getActive();return !e||!e.isProEnabled()?(console.warn("[NavCore] InstructionEditor.toArray() requires a Pro license. Returning empty instruction set."),[]):this.instructions.map(({id:t,type:n,severity:i,meta:r,...o})=>o)}toRichArray(){return [...this.instructions]}get size(){return this.instructions.length}};function re(s,e,t){return s+e*t}function oe(s,e,t=.15){let n=e-s;return s+t*n}function ze(s,e,t){if(t.length===0)return [0,0];if(s<=0)return t[0];let n=e[e.length-1]??0;if(s>=n)return t[t.length-1];let i=0,r=e.length-1;for(;i<r-1;){let d=i+r>>1;e[d]<=s?i=d:r=d;}let o=e[i],a=e[r]-o;if(a===0)return t[i];let u=(s-o)/a;return W(t[i],t[r],u)}var G=class{constructor(){this._state="IDLE";this._context={resumeIndex:null};}get state(){return this._state}get context(){return {...this._context}}dispatch(e){switch(this._state){case "IDLE":e.type==="ROUTE_LOADED"&&(this._state="OVERVIEW"),e.type==="USER_START_NAVIGATION"&&(this._state="APPROACHING_ROUTE");break;case "OVERVIEW":e.type==="USER_START_NAVIGATION"&&(this._state="APPROACHING_ROUTE");break;case "APPROACHING_ROUTE":e.type==="ROUTE_JOINED"&&(this._state="ON_ROUTE",this._context.resumeIndex=e.data.index),e.type==="NAVIGATION_FINISHED"&&(this._state="IDLE");break;case "ON_ROUTE":e.type==="NAVIGATION_FINISHED"&&(this._state="IDLE"),e.type==="ROUTE_JOINED"&&(this._context.resumeIndex=e.data.index);break}return (e.type==="RESET"||e.type==="CANCEL_NAVIGATION")&&(this._state="IDLE",this._context={resumeIndex:null}),{state:this._state,context:{...this._context}}}reset(){this._state="IDLE",this._context={resumeIndex:null};}};var M={deviationSegmentIdx:null,deviationStartMs:null,tempRoute:null,rejoinTarget:null,lastRerouteMs:null,rejoinedAtMs:null,rejoinDwellFrames:0,failureReason:null},Te=2e3,Ye=3,L=class{constructor(){this._state="ON_ROUTE";this._context={...M};}get state(){return this._state}get context(){return {...this._context}}dispatch(e,t){let n=t??Date.now();switch(this._state){case "ON_ROUTE":e.type==="DEVIATION_SUSPECTED"&&(this._state="DEVIATING",this._context.deviationSegmentIdx=e.deviationSegmentIdx,this._context.deviationStartMs=n);break;case "DEVIATING":e.type==="DEVIATION_CONFIRMED"&&(this._context.deviationStartMs!==null?n-this._context.deviationStartMs:0)>=Te&&(this._state="OFF_ROUTE",this._context.deviationSegmentIdx=e.deviationSegmentIdx),(e.type==="RESUME"||e.type==="RESET")&&(this._state="ON_ROUTE",e.type==="RESET"?this._context={...M}:(this._context.deviationSegmentIdx=null,this._context.deviationStartMs=null));break;case "OFF_ROUTE":e.type==="REROUTE_STARTED"&&(this._state="REROUTING",this._context.lastRerouteMs=n),e.type==="RESET"&&(this._state="ON_ROUTE",this._context={...M});break;case "REROUTING":e.type==="REROUTE_SUCCESS"&&(this._state="REJOINING",this._context.tempRoute=e.tempRoute,this._context.rejoinTarget=e.rejoinTarget),e.type==="REROUTE_FAILED"&&(this._state="FAILED",this._context.failureReason=e.reason);break;case "REJOINING":e.type==="REJOIN_DETECTED"&&this._context.rejoinDwellFrames++,(e.type==="REJOIN_CONFIRMED"||this._context.rejoinDwellFrames>=Ye)&&(this._state="REJOINED",this._context.rejoinedAtMs=n,this._context.rejoinDwellFrames=0),e.type==="RESET"&&(this._state="ON_ROUTE",this._context={...M});break;case "REJOINED":e.type==="RESUME"&&(this._state="ON_ROUTE",this._context.tempRoute=null,this._context.rejoinTarget=null,this._context.rejoinedAtMs=null,this._context.deviationSegmentIdx=null,this._context.deviationStartMs=null),e.type==="RESET"&&(this._state="ON_ROUTE",this._context={...M});break;case "FAILED":e.type==="RESET"&&(this._state="ON_ROUTE",this._context={...M});break}return {state:this._state,context:{...this._context}}}reset(){this._state="ON_ROUTE",this._context={...M};}isDeviationConfirmed(e=Date.now()){return this._context.deviationStartMs?e-this._context.deviationStartMs>=Te:false}};var Qe=0;function De(){return `wp_${Date.now()}_${++Qe}`}var se=class{constructor(){this.waypoints=[];}addWaypoint(e,t){let n=De();return this.waypoints.push({id:n,coord:e,options:t}),n}insertWaypoint(e,t){let n=this.waypoints.findIndex(r=>r.id===t);if(n===-1)throw new Error(`Waypoint ${t} not found`);let i=De();return this.waypoints.splice(n+1,0,{id:i,coord:e,options:void 0}),i}removeWaypoint(e){let t=this.waypoints.findIndex(n=>n.id===e);if(t===-1)throw new Error(`Waypoint ${e} not found`);this.waypoints.splice(t,1);}moveWaypoint(e,t){let n=this.waypoints.find(i=>i.id===e);if(!n)throw new Error(`Waypoint ${e} not found`);n.coord=t;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(e="OVERLAP_1",t=25){let n=this.waypoints.map(c=>c.coord);if(n.length<=t)return [n];let r=t-(e==="OVERLAP_2"?2:1),o=[];for(let c=0;c<n.length;c+=r){let a=n.slice(c,c+t);if(o.push(a),c+t>=n.length)break}return o}buildStraightLine(){return {geometry:this.waypoints.map(e=>e.coord),waypoints:[...this.waypoints]}}fromGPX(e){this.waypoints=[];let t=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=t.exec(e))!==null;){let i=parseFloat(n[1]),r=parseFloat(n[2]);isFinite(i)&&isFinite(r)&&this.addWaypoint([r,i]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
1
+ 'use strict';var Ne=Object.defineProperty;var Pe=(s,e)=>{for(var t in e)Ne(s,t,{get:e[t],enumerable:true});};function b(s,e,t,n){let i=(t-s)*(Math.PI/180),r=(n-e)*(Math.PI/180),o=Math.sin(i/2)*Math.sin(i/2)+Math.cos(s*(Math.PI/180))*Math.cos(t*(Math.PI/180))*Math.sin(r/2)*Math.sin(r/2);return 6371e3*(2*Math.atan2(Math.sqrt(o),Math.sqrt(1-o)))}function W(s,e,t,n){let i=n/6371e3,r=t*(Math.PI/180),o=s*(Math.PI/180),c=e*(Math.PI/180),a=Math.asin(Math.sin(o)*Math.cos(i)+Math.cos(o)*Math.sin(i)*Math.cos(r));return [((c+Math.atan2(Math.sin(r)*Math.sin(i)*Math.cos(o),Math.cos(i)-Math.sin(o)*Math.sin(a)))*180/Math.PI+540)%360-180,a*180/Math.PI]}function we(s,e){let t=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),i=e[1]*(Math.PI/180),r=e[0]*(Math.PI/180),o=Math.sin(r-n)*Math.cos(i),c=Math.cos(t)*Math.sin(i)-Math.sin(t)*Math.cos(i)*Math.cos(r-n),a=Math.atan2(o,c)*(180/Math.PI);return a=(a+360)%360,a}function C(s){let e=s%360;return e>180?e-360:e<-180?e+360:e}function E(s,e){let t=s[1]*(Math.PI/180),n=s[0]*(Math.PI/180),i=e[1]*(Math.PI/180),r=e[0]*(Math.PI/180),o=Math.sin(r-n)*Math.cos(i),c=Math.cos(t)*Math.sin(i)-Math.sin(t)*Math.cos(i)*Math.cos(r-n);return (Math.atan2(o,c)*180/Math.PI+360)%360}function H(s,e,t){let n=(i,r,o)=>i+(r-i)*o;return [n(s[0],e[0],t),n(s[1],e[1],t)]}function U(s,e,t){let[n,i]=s,[r,o]=e,[c,a]=t,l=c-r,d=a-o,u=l*l+d*d;if(u===0)return e;let p=((n-r)*l+(i-o)*d)/u;return p=Math.max(0,Math.min(1,p)),[r+p*l,o+p*d]}function K(s){let e=new Float64Array(s.length);for(let t=1;t<s.length;t++)e[t]=e[t-1]+b(s[t-1][1],s[t-1][0],s[t][1],s[t][0]);return e}function j(s){let e=new Float64Array(s.length);for(let t=s.length-2;t>=0;t--)e[t]=e[t+1]+b(s[t][1],s[t][0],s[t+1][1],s[t+1][0]);return e}function me(s,e,t,n,i,r=1e-5,o=5e-5){s.x+=s.vx*i,s.y+=s.vy*i,s.P+=r;let c=o*Math.max(1,n/5),a=s.P/(s.P+c),l=e-s.x,d=t-s.y;return s.x+=a*l,s.y+=a*d,i>0&&(s.vx=l/i*a,s.vy=d/i*a),s.P=(1-a)*s.P,s}var D=class{constructor(e=1e-5,t=5e-5){this.lastTimestamp=0;this.Q=e,this.rBase=t,this.state={x:0,y:0,vx:0,vy:0,P:1};}init(e,t,n){this.state={x:e,y:t,vx:0,vy:0,P:1},this.lastTimestamp=n;}update(e,t,n,i){if(this.lastTimestamp===0)return this.init(e,t,i),[e,t];let r=Math.max(.001,(i-this.lastTimestamp)/1e3);return this.lastTimestamp=i,me(this.state,e,t,n,r,this.Q,this.rBase),[this.state.x,this.state.y]}getPosition(){return [this.state.x,this.state.y]}getState(){return {...this.state}}reset(){this.state={x:0,y:0,vx:0,vy:0,P:1},this.lastTimestamp=0;}};var Se={};Pe(Se,{ARRIVAL_THRESHOLD_METERS:()=>Ce,BASE_CORRIDOR_METERS:()=>k,BEARING_ALIGNMENT_THRESHOLD:()=>Ee,BEARING_MIN_SPEED_MPS:()=>z,BEARING_MISMATCH_PENALTY:()=>ye,BEARING_MISMATCH_THRESHOLD:()=>J,BEARING_SMOOTHING_ALPHA:()=>V,BETA_CORRECTION:()=>ve,DETOUR_COMMIT_MS:()=>ke,DR_MAX_AGE_MS:()=>Y,GPS_ACCURACY_FACTOR:()=>ge,GPS_AGE_CAP_SECONDS:()=>Ie,GPS_STALE_MS:()=>xe,INERTIA_PENALTY:()=>Re,INERTIA_SEGMENT_DIST:()=>be,LOOK_AHEAD_SECONDS:()=>Be,MANEUVER_TRIGGER_DIST:()=>Ve,MAX_CORRIDOR_METERS:()=>$,MAX_LOOK_AHEAD_METERS:()=>He,MAX_SNAP_DISTANCE:()=>q,MIN_LOOK_AHEAD_METERS:()=>We,OFF_ROUTE_CONFIRM_MS:()=>Fe,REJOIN_CONFIRM_MS:()=>Ge,REJOIN_COOLDOWN_MS:()=>Le,SNAP_WINDOW_SIZE:()=>X,SPEED_CORRIDOR_FACTOR:()=>fe,STARTUP_GRACE_MS:()=>Ue});var k=25,$=60,fe=1.2,ge=.5,q=80,J=90,ye=500,Re=200,be=5,X=25,V=.3,z=1.5,Ee=55,Y=5e3,Fe=2e3,Ge=1500,Le=12e3,Ue=3e3,ke=4e3,xe=3e3,Ie=10,Ve=25,ve=.15,Be=3,We=20,He=100,Ce=30;var Ke={useBearingPenalty:true,useInertiaPenalty:true,maxSnapDistance:80},N=class{constructor(e){this.options={...Ke,...e};}snap(e,t,n,i,r,o,c,a=null,l=null){let d=t.length,u=c,p=1/0,x=1/0,y=t[c]??[0,0];for(let m=0;m<=i;m++){let g=n+m;if(g>d-2)if(r&&o>d*.7)g=g%(d-1);else break;if(g<0||g>=d-1)continue;let f=t[g],I=t[g+1],v=U(e,f,I),M=b(e[1],e[0],v[1],v[0]);if(M>this.options.maxSnapDistance*2)continue;let S=M;if(this.options.useBearingPenalty&&a!==null){let _=E(f,I);Math.abs(C(a-_))>90&&(S+=500);}this.options.useInertiaPenalty&&l!==null&&Math.abs(g-l)>=5&&(S+=200),S<p&&(p=S,x=M,u=g,y=v);}if(!Number.isFinite(x)){let m=Math.min(Math.max(c,0),Math.max(0,d-2)),g=t[m],f=t[m+1];g&&f?(y=U(e,g,f),x=b(e[1],e[0],y[1],y[0]),u=m):(y=t[Math.min(Math.max(c,0),d-1)]??e,x=b(e[1],e[0],y[1],y[0]),u=0);}return {idx:u,dist:x,proj:y}}};var h={GPS_SMOOTHING:"gps_smoothing",BASIC_SNAPPING:"basic_snapping",PROGRESS_TRACKING:"progress_tracking",ROUTE_OFFSET:"route_offset",DEAD_RECKONING:"dead_reckoning",ADVANCED_BEARING:"advanced_bearing",COMPOUND_DEVIATION:"compound_deviation",PARALLEL_ROAD_RESOLUTION:"parallel_road_resolution",U_TURN_PROTECTION:"u_turn_protection",VOICE_TRIGGERS:"voice_triggers",ETA:"eta",GEOFENCING:"geofencing",NAV_AI:"nav_ai"};var O=class O{constructor(e){this.status="MISSING";this.payload=null;this.enabledFeatures=new Set;this.warnedFeatures=new Set;e&&(this.tryValidateSync(e)||this.validate(e)),this.promoteToActive();}static getActive(){return O.activeManager}static clearActive(){O.activeManager=null;}promoteToActive(){let e=O.activeManager;(e===null||e.status!=="VALID"||this.status==="VALID")&&(O.activeManager=this);}tryValidateSync(e){return e==="eyJ0IjoicHJvIiwiZXhwIjo0OTMyNzAzMTU2MDAwLCJiaWQiOiJkZXYuYnlwYXNzIiwiZiI6WyIqIl19.MEQCIH4E4QNu9PuVsXHSnYmcqpCLk4QitiIH9hhY0Zm+YO5gAiAE7X3c47YQLUj7WPSGKw9Y7W2kBUR5GCnOMBwdBsYGgg=="?typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)?(this.status="VALID",this.payload={t:"pro",exp:4932703156e3,bid:"dev.bypass",f:["*"]},this.extractFeatures(),console.log("\u{1F511} [NavCore] Development bypass key validated synchronously. Plan: pro"),true):(console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,true):false}async validate(e){if(this.tryValidateSync(e))return this.status;try{let[t,n]=e.split(".");if(!t||!n)return this.status="INVALID",this.status;let i=atob(t);if(this.payload=JSON.parse(i),!this.payload||this.payload.exp<Date.now())return this.status="EXPIRED",this.status;if(!await this.verifySignature(t,n))return this.status="INVALID",this.status;if(this.payload?.bid==="dev.bypass"&&!(typeof __DEV__<"u"&&__DEV__||typeof window<"u"&&(window.location?.hostname==="localhost"||window.location?.hostname==="127.0.0.1"||window.location?.hostname?.startsWith("192.168.")||window.location?.hostname?.endsWith(".local"))||typeof process<"u"&&(process.env?.NODE_ENV==="development"||process.env?.NODE_ENV==="test"||process.env?.VITEST==="true"||process.env?.JEST_WORKER_ID!==void 0)))return console.warn("[NavCore] Development bypass key is restricted to local development environments."),this.status="INVALID",this.payload=null,this.status;this.status="VALID",this.extractFeatures(),this.promoteToActive(),console.log(`\u{1F511} [NavCore] License validation complete. Plan: ${this.isProEnabled()?"pro":"core"}`);}catch{this.status="INVALID";}return this.status}extractFeatures(){if(this.enabledFeatures.clear(),!!this.payload){if(Array.isArray(this.payload.f))for(let e of this.payload.f)this.enabledFeatures.add(e);this.payload.t==="pro"&&this.enabledFeatures.add("*");}}hasFeature(e){return this.status!=="VALID"?false:this.enabledFeatures.has("*")?true:this.enabledFeatures.has(e)}warnOnce(e){this.warnedFeatures.has(e)||(console.warn(`[NavCore] Feature '${e}' requires a Pro license`),this.warnedFeatures.add(e));}isProEnabled(){return this.hasFeature("*")}isAIEnabled(){return this.hasFeature(h.NAV_AI)}getStatus(){return this.status}getPayload(){return this.payload}getEnabledFeatures(){return Array.from(this.enabledFeatures)}async verifySignature(e,t){try{if(typeof crypto>"u"||!crypto.subtle)return !1;let i=new TextEncoder().encode(e),r=Uint8Array.from(atob(t),a=>a.charCodeAt(0)),o=Uint8Array.from(atob(O.PUBLIC_KEY_SPKI),a=>a.charCodeAt(0)),c=await crypto.subtle.importKey("spki",o,{name:"ECDSA",namedCurve:"P-256"},!0,["verify"]);return await crypto.subtle.verify({name:"ECDSA",hash:{name:"SHA-256"}},c,r,i)}catch{return false}}};O.activeManager=null,O.PUBLIC_KEY_SPKI="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEk6onJmJkWtRFusiSS69dcdONX4xL2Snm4AZO+dYjSynfJiL4x7trEy80MImLftknBWT/qI0z7ox4Q7VNL3te6A==";var R=O;var je={bearingPenalty:80,bearingMismatchThresholdDeg:60,inertiaPenalty:40,inertiaSegmentDist:3},Q=class{constructor(e){this.warned=false;this.options={...je,...e};}resolve(e,t=null,n=null){let i=R.getActive();return (!i||!i.isProEnabled())&&(this.warned||(console.warn("[NavCore] ParallelRoadResolver and U-turn protection require a Pro license. Falling back to core distance snapping."),this.warned=true)),e.map(r=>this.score(r,t,n)).sort((r,o)=>r.score-o.score)}resolveBest(e,t=null,n=null){return e.length===0?null:this.resolve(e,t,n)[0]??null}score(e,t,n){let i=e.distanceMetres,r=null,o=false,c=R.getActive(),a=c&&c.isProEnabled();if(t!==null&&a){let l=E(e.segA,e.segB),d=Math.abs(C(t-l));r=d,d>this.options.bearingMismatchThresholdDeg&&(i+=this.options.bearingPenalty);}return n!==null&&a&&Math.abs(e.segmentIndex-n)>=this.options.inertiaSegmentDist&&(i+=this.options.inertiaPenalty,o=true),{...e,score:i,bearingDeltaDeg:r,inertiaPenaltyApplied:o}}isLikelyUTurn(e,t,n){let i=E(t,n);return Math.abs(C(e-i))>this.options.bearingMismatchThresholdDeg}};function Me(s,e,t,n,i=5e3){if(!s||e<.5)return {predictedCoord:s?.coord??[0,0],isActive:false,ageMs:0};let r=n-s.ts;if(r>i||r<0)return {predictedCoord:s.coord,isActive:false,ageMs:r};let o=e*(r/1e3);return {predictedCoord:W(s.coord[1],s.coord[0],t,o),isActive:true,ageMs:r}}var P=class{constructor(e=5e3){this.anchor=null;this.warned=false;this.maxAgeMs=e;}setAnchor(e,t,n){this.anchor={coord:e,idx:t,ts:n};}predict(e,t,n){let i=R.getActive();return !i||!i.hasFeature(h.DEAD_RECKONING)?(this.warned||(i?i.warnOnce(h.DEAD_RECKONING):console.warn(`[NavCore] Feature '${h.DEAD_RECKONING}' requires a Pro license`),this.warned=true),{predictedCoord:this.anchor?.coord??[0,0],isActive:false,ageMs:0}):(this.warned=false,Me(this.anchor,e,t,n,this.maxAgeMs))}clearAnchor(){this.anchor=null;}getAnchor(){return this.anchor}};function Ae(s,e,t,n,i=null){let r=Math.max(0,t),o=1/0,c=e[r]??[0,0],a=Math.min(t+n,e.length-1);for(let l=Math.max(0,t);l<a;l++){let d=e[l],u=e[l+1],[p,x]=s,[y,m]=d,[g,f]=u,I=g-y,v=f-m,M=I*I+v*v,S;if(M===0)S=d;else {let A=((p-y)*I+(x-m)*v)/M;A=Math.max(0,Math.min(1,A)),S=[y+A*I,m+A*v];}let _=b(s[1],s[0],S[1],S[0]);if(i!==null&&_<o*1.5){let A=E(d,u);if(Math.abs(C(i-A))>120)continue}_<o&&(o=_,r=l,c=S);}return {segmentIndex:r,distance:o,projection:c}}var w=class{constructor(){this.warned=false;}evaluate(e,t,n,i,r,o,c){let a=R.getActive();if(!a||!a.hasFeature(h.COMPOUND_DEVIATION))return this.warned||(a?a.warnOnce(h.COMPOUND_DEVIATION):console.warn(`[NavCore] Feature '${h.COMPOUND_DEVIATION}' requires a Pro license`),this.warned=true),{distanceToRoute:i.distance,outsideCorridor:false,bearingMismatch:false,movingAway:false,confirmed:false};this.warned=false;let l=i.distance>o,d=false;if(t!==null&&i.segmentIndex<r.length-1){let x=E(r[i.segmentIndex],r[i.segmentIndex+1]);d=Math.abs(C(t-x))>90;}let u=false;if(c!==null&&n>1.5){let x=r[Math.min(i.segmentIndex+2,r.length-1)];u=b(e[1],e[0],x[1],x[0])>c+5;}let p=l&&(d||u);return {distanceToRoute:i.distance,outsideCorridor:l,bearingMismatch:d,movingAway:u,confirmed:p}}};function Z(s,e=null,t=25,n=60,i=1.2,r=.5){let o=t+s*i;return e!==null&&e>0&&(o+=e*r),Math.min(o,n)}function Oe(s,e=.3){return s<1.5?e*.5:s>20?Math.min(.9,e*2):e}function _e(s,e,t=3){let n=Math.min(e+t,s.length-1);return e>=s.length-1||e===n?e>0?E(s[e-1],s[e]):0:E(s[e],s[n])}function B(s,e,t){let n=C(e-s);return (s+t*n+360)%360}function ee(s,e,t,n,i,r=.3){let o=Oe(n,r),c=_e(e,t);if(i!==null&&n>1.5){let a=B(s,i,o*.3);return B(a,c,o)}return B(s,c,o)}function te(s,e,t,n,i){return e<s||e>s+30||n>i?s:e}var $e=20,qe=60,Je=3;function ne(s,e,t,n,i,r,o,c=0){if(!e||e.length===0||t>=e.length)return {nextIdx:t,instruction:null,wasTriggered:false};let a=t;for(;a<e.length;){let g=e[a],f=s>g.geometryIndex+30,I=g.cumulativeOffset!==void 0&&o>g.cumulativeOffset+15;if(!f&&!I)break;a++;}if(a>=e.length)return {nextIdx:a,instruction:null,wasTriggered:false};let l=e[a],d=l.cumulativeOffset!==void 0?Math.max(0,l.cumulativeOffset-o):b(i[1],i[0],l.location[1],l.location[0]),u=Math.min(qe,Math.max($e,c*Je)),p=s<=l.geometryIndex+2,y=d<=u&&p,m=false;if(y){let g=true,f=l.bearingAfter??(l.geometryIndex<n.length-1?E(n[l.geometryIndex],n[l.geometryIndex+1]):null),I=l.bearingBefore??(l.geometryIndex>0?E(n[l.geometryIndex-1],n[l.geometryIndex]):null);I!==null&&f!==null&&r!==null&&Math.abs(C(f-I))>30&&Math.abs(C(r-f))>55&&(g=false),g&&(m=true);}return {nextIdx:a,instruction:l,wasTriggered:m}}var Xe=0;function F(){return `instr_${Date.now()}_${++Xe}`}var ie=class{constructor(){this.instructions=[];}addTurn(e,t,n,i){return this.instructions.push({id:F(),type:"turn",location:e,text:t,instruction:t,geometryIndex:n,silent:i?.silent,meta:i?.meta}),this}addExamPoint(e,t,n,i){return this.instructions.push({id:F(),type:"exam_point",location:e,text:t,instruction:t,geometryIndex:n,severity:i?.severity??"info",silent:i?.silent,meta:i?.meta}),this}addCheckpoint(e,t,n){return this.instructions.push({id:F(),type:"checkpoint",location:e,text:"",instruction:"",geometryIndex:t,silent:true,meta:n}),this}addDepart(e,t="Start navigation"){let n={id:F(),type:"depart",location:e,text:t,instruction:t,geometryIndex:0};return this.instructions.unshift(n),this}addArrive(e,t="You have arrived"){return this.instructions.push({id:F(),type:"arrive",location:e,text:t,instruction:t,geometryIndex:Number.MAX_SAFE_INTEGER}),this}update(e,t){let n=this.instructions.findIndex(i=>i.id===e);if(n===-1)throw new Error(`[InstructionEditor] Instruction ${e} not found`);return this.instructions[n]={...this.instructions[n],...t},this}remove(e){let t=this.instructions.findIndex(n=>n.id===e);if(t===-1)throw new Error(`[InstructionEditor] Instruction ${e} not found`);return this.instructions.splice(t,1),this}reorder(e,t){let n=this.instructions.findIndex(r=>r.id===e);if(n===-1)throw new Error(`[InstructionEditor] Instruction ${e} not found`);let[i]=this.instructions.splice(n,1);return this.instructions.splice(Math.max(0,t),0,i),this}sort(){return this.instructions.sort((e,t)=>e.geometryIndex-t.geometryIndex),this}clear(){return this.instructions=[],this}attachToCumulative(e){let t=R.getActive();if(!t||!t.isProEnabled())return console.warn("[NavCore] InstructionEditor requires a Pro license. Fluent editing is disabled."),this;if(e.length<2)return this;let n=[0];for(let i=1;i<e.length;i++){let r=e[i-1],o=e[i];n.push(n[i-1]+b(r[1],r[0],o[1],o[0]));}for(let i of this.instructions){let r=Math.min(i.geometryIndex,e.length-1);i.cumulativeOffset=n[r]??0,r>0&&r<e.length-1&&(i.bearingBefore=E(e[r-1],e[r]),i.bearingAfter=E(e[r],e[r+1]));}return this}toArray(){let e=R.getActive();return !e||!e.isProEnabled()?(console.warn("[NavCore] InstructionEditor.toArray() requires a Pro license. Returning empty instruction set."),[]):this.instructions.map(({id:t,type:n,severity:i,meta:r,...o})=>o)}toRichArray(){return [...this.instructions]}get size(){return this.instructions.length}};function re(s,e,t){return s+e*t}function oe(s,e,t=.15){let n=e-s;return s+t*n}function ze(s,e,t){if(t.length===0)return [0,0];if(s<=0)return t[0];let n=e[e.length-1]??0;if(s>=n)return t[t.length-1];let i=0,r=e.length-1;for(;i<r-1;){let d=i+r>>1;e[d]<=s?i=d:r=d;}let o=e[i],a=e[r]-o;if(a===0)return t[i];let l=(s-o)/a;return H(t[i],t[r],l)}var G=class{constructor(){this._state="IDLE";this._context={resumeIndex:null};}get state(){return this._state}get context(){return {...this._context}}dispatch(e){switch(this._state){case "IDLE":e.type==="ROUTE_LOADED"&&(this._state="OVERVIEW"),e.type==="USER_START_NAVIGATION"&&(this._state="APPROACHING_ROUTE");break;case "OVERVIEW":e.type==="USER_START_NAVIGATION"&&(this._state="APPROACHING_ROUTE");break;case "APPROACHING_ROUTE":e.type==="ROUTE_JOINED"&&(this._state="ON_ROUTE",this._context.resumeIndex=e.data.index),e.type==="NAVIGATION_FINISHED"&&(this._state="IDLE");break;case "ON_ROUTE":e.type==="NAVIGATION_FINISHED"&&(this._state="IDLE"),e.type==="ROUTE_JOINED"&&(this._context.resumeIndex=e.data.index);break}return (e.type==="RESET"||e.type==="CANCEL_NAVIGATION")&&(this._state="IDLE",this._context={resumeIndex:null}),{state:this._state,context:{...this._context}}}reset(){this._state="IDLE",this._context={resumeIndex:null};}};var T={deviationSegmentIdx:null,deviationStartMs:null,tempRoute:null,rejoinTarget:null,lastRerouteMs:null,rejoinedAtMs:null,rejoinDwellFrames:0,failureReason:null},Te=2e3,Ye=3,L=class{constructor(){this._state="ON_ROUTE";this._context={...T};}get state(){return this._state}get context(){return {...this._context}}dispatch(e,t){let n=t??Date.now();switch(this._state){case "ON_ROUTE":e.type==="DEVIATION_SUSPECTED"&&(this._state="DEVIATING",this._context.deviationSegmentIdx=e.deviationSegmentIdx,this._context.deviationStartMs=n);break;case "DEVIATING":e.type==="DEVIATION_CONFIRMED"&&(this._context.deviationStartMs!==null?n-this._context.deviationStartMs:0)>=Te&&(this._state="OFF_ROUTE",this._context.deviationSegmentIdx=e.deviationSegmentIdx),(e.type==="RESUME"||e.type==="RESET")&&(this._state="ON_ROUTE",e.type==="RESET"?this._context={...T}:(this._context.deviationSegmentIdx=null,this._context.deviationStartMs=null));break;case "OFF_ROUTE":e.type==="REROUTE_STARTED"&&(this._state="REROUTING",this._context.lastRerouteMs=n),e.type==="RESET"&&(this._state="ON_ROUTE",this._context={...T});break;case "REROUTING":e.type==="REROUTE_SUCCESS"&&(this._state="REJOINING",this._context.tempRoute=e.tempRoute,this._context.rejoinTarget=e.rejoinTarget),e.type==="REROUTE_FAILED"&&(this._state="FAILED",this._context.failureReason=e.reason);break;case "REJOINING":e.type==="REJOIN_DETECTED"&&this._context.rejoinDwellFrames++,(e.type==="REJOIN_CONFIRMED"||this._context.rejoinDwellFrames>=Ye)&&(this._state="REJOINED",this._context.rejoinedAtMs=n,this._context.rejoinDwellFrames=0),e.type==="RESET"&&(this._state="ON_ROUTE",this._context={...T});break;case "REJOINED":e.type==="RESUME"&&(this._state="ON_ROUTE",this._context.tempRoute=null,this._context.rejoinTarget=null,this._context.rejoinedAtMs=null,this._context.deviationSegmentIdx=null,this._context.deviationStartMs=null),e.type==="RESET"&&(this._state="ON_ROUTE",this._context={...T});break;case "FAILED":e.type==="RESET"&&(this._state="ON_ROUTE",this._context={...T});break}return {state:this._state,context:{...this._context}}}reset(){this._state="ON_ROUTE",this._context={...T};}isDeviationConfirmed(e=Date.now()){return this._context.deviationStartMs?e-this._context.deviationStartMs>=Te:false}};var Qe=0;function De(){return `wp_${Date.now()}_${++Qe}`}var se=class{constructor(){this.waypoints=[];}addWaypoint(e,t){let n=De();return this.waypoints.push({id:n,coord:e,options:t}),n}insertWaypoint(e,t){let n=this.waypoints.findIndex(r=>r.id===t);if(n===-1)throw new Error(`Waypoint ${t} not found`);let i=De();return this.waypoints.splice(n+1,0,{id:i,coord:e,options:void 0}),i}removeWaypoint(e){let t=this.waypoints.findIndex(n=>n.id===e);if(t===-1)throw new Error(`Waypoint ${e} not found`);this.waypoints.splice(t,1);}moveWaypoint(e,t){let n=this.waypoints.find(i=>i.id===e);if(!n)throw new Error(`Waypoint ${e} not found`);n.coord=t;}getWaypoints(){return this.waypoints}get size(){return this.waypoints.length}chunk(e="OVERLAP_1",t=25){let n=this.waypoints.map(c=>c.coord);if(n.length<=t)return [n];let r=t-(e==="OVERLAP_2"?2:1),o=[];for(let c=0;c<n.length;c+=r){let a=n.slice(c,c+t);if(o.push(a),c+t>=n.length)break}return o}buildStraightLine(){return {geometry:this.waypoints.map(e=>e.coord),waypoints:[...this.waypoints]}}fromGPX(e){this.waypoints=[];let t=/<(?:trkpt|wpt|rtept)\s+lat="([^"]+)"\s+lon="([^"]+)"/g,n;for(;(n=t.exec(e))!==null;){let i=parseFloat(n[1]),r=parseFloat(n[2]);isFinite(i)&&isFinite(r)&&this.addWaypoint([r,i]);}}toGPX(){return `<?xml version="1.0" encoding="UTF-8"?>
2
2
  <gpx version="1.1" creator="NavCore SDK">
3
3
  ${this.waypoints.map(t=>` <wpt lat="${t.coord[1]}" lon="${t.coord[0]}">`+(t.options?.name?`
4
4
  <name>${t.options.name}</name>`:"")+`
5
5
  </wpt>`).join(`
6
6
  `)}
7
- </gpx>`}fromGeoJSON(e){if(this.waypoints=[],e.type==="FeatureCollection"&&e.features){for(let t of e.features)if(t.geometry.type==="Point"){let n=t.geometry.coordinates;this.addWaypoint(n);}else if(t.geometry.type==="LineString"){let n=t.geometry.coordinates;for(let i of n)this.addWaypoint(i);}}}toGeoJSON(){let e=this.waypoints.map((n,i)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:i,name:n.options?.name??null,silent:n.options?.silent??false}})),t={type:"Feature",geometry:{type:"LineString",coordinates:this.waypoints.map(n=>n.coord)},properties:{type:"route"}};return {type:"FeatureCollection",features:[...e,t]}}clear(){this.waypoints=[];}};var ae=class{constructor(e){this.config={baseUrl:e.baseUrl.replace(/\/$/,""),profile:e.profile??"driving",maxWaypointsPerChunk:e.maxWaypointsPerChunk??100};}async getRoute(e,t){if(e.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=t?.profile??this.config.profile;return e.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(e,n,t):this.fetchChunked(e,n,t)}async fetchRoute(e,t,n){let i=e.map(d=>`${d[0]},${d[1]}`).join(";"),r=n?.steps!==false?"true":"false",o=`${this.config.baseUrl}/route/v1/${t}/${i}?overview=full&geometries=geojson&steps=${r}&annotations=false`,c=await fetch(o);if(!c.ok)throw new Error(`[OSRM] HTTP ${c.status}: ${c.statusText}`);let a=await c.json();if(a.code!=="Ok"||!a.routes?.length)throw new Error(`[OSRM] No route found: ${a.code}`);let u=a.routes[0];return {geometry:u.geometry.coordinates,distance:u.distance,duration:u.duration,legs:(u.legs??[]).map(d=>({distance:d.distance,duration:d.duration,steps:(d.steps??[]).map(l=>({distance:l.distance,duration:l.duration,geometry:l.geometry?.coordinates??[],maneuver:{type:l.maneuver?.type??"unknown",modifier:l.maneuver?.modifier,location:l.maneuver?.location??[0,0],bearingBefore:l.maneuver?.bearing_before??0,bearingAfter:l.maneuver?.bearing_after??0,instruction:l.name??void 0},name:l.name}))})),raw:a}}async fetchChunked(e,t,n){let i=this.config.maxWaypointsPerChunk,r=[];for(let l=0;l<e.length;l+=i-1){let p=e.slice(l,l+i);if(p.length<2||(r.push(p),l+i>=e.length))break}let o=await Promise.all(r.map(l=>this.fetchRoute(l,t,n))),c=[],a=0,u=0,d=[];for(let l=0;l<o.length;l++){let p=o[l];c.push(...l===0?p.geometry:p.geometry.slice(1)),a+=p.distance,u+=p.duration,d.push(...p.legs);}return {geometry:c,distance:a,duration:u,legs:d,raw:o.map(l=>l.raw)}}};var ce=class{constructor(e){this.config={baseUrl:e.baseUrl.replace(/\/$/,""),costing:e.costing??"auto",apiKey:e.apiKey??"",maxWaypointsPerChunk:e.maxWaypointsPerChunk??50};}async getRoute(e,t){if(e.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(t?.profile);return e.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(e,n,t):this.fetchChunked(e,n,t)}profileToCosting(e){switch(e){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(e,t,n){let i=e.map(p=>({lon:p[0],lat:p[1],type:"break"})),r=JSON.stringify({locations:i,costing:t,directions_options:{units:"kilometers"}}),o={"Content-Type":"application/json","User-Agent":"NavCoreSDK/1.0.0 (React Native; Expo; bab-bou-jeloud-demo)"};this.config.apiKey&&(o.api_key=this.config.apiKey);let c=await fetch(`${this.config.baseUrl}/route`,{method:"POST",headers:o,body:r});if(!c.ok){let p=await c.text();throw new Error(`[Valhalla] HTTP ${c.status}: ${p}`)}let a=await c.json(),u=this.decodePolyline(a.trip?.legs?.[0]?.shape??""),d=a.trip?.summary??{},l=(a.trip?.legs??[]).map(p=>({distance:(p.summary?.length??0)*1e3,duration:p.summary?.time??0,steps:(p.maneuvers??[]).map(f=>({distance:(f.length??0)*1e3,duration:f.time??0,geometry:[],maneuver:{type:f.type?.toString()??"unknown",modifier:void 0,location:e[0],bearingBefore:f.begin_heading??0,bearingAfter:f.end_heading??0,instruction:f.instruction},name:f.street_names?.[0]}))}));return {geometry:u,distance:(d.length??0)*1e3,duration:d.time??0,legs:l,raw:a}}decodePolyline(e,t=6){let n=Math.pow(10,t),i=[],r=0,o=0,c=0;for(;r<e.length;){let a=0,u=0,d;do d=e.charCodeAt(r++)-63,u|=(d&31)<<a,a+=5;while(d>=32);let l=(u&1)!==0?~(u>>1):u>>1;o+=l,a=0,u=0;do d=e.charCodeAt(r++)-63,u|=(d&31)<<a,a+=5;while(d>=32);let p=(u&1)!==0?~(u>>1):u>>1;c+=p,i.push([c/n,o/n]);}return i}async fetchChunked(e,t,n){let i=this.config.maxWaypointsPerChunk,r=[];for(let l=0;l<e.length;l+=i-1){let p=e.slice(l,l+i);if(p.length<2||(r.push(p),l+i>=e.length))break}let o=await Promise.all(r.map(l=>this.fetchRoute(l,t,n))),c=[],a=0,u=0,d=[];for(let l=0;l<o.length;l++){let p=o[l];c.push(...l===0?p.geometry:p.geometry.slice(1)),a+=p.distance,u+=p.duration,d.push(...p.legs);}return {geometry:c,distance:a,duration:u,legs:d,raw:o.map(l=>l.raw)}}};var Ze="https://api.openrouteservice.org/v2/directions";var le=class{constructor(e){this.config={apiKey:e.apiKey,profile:e.profile??"driving-car",baseUrl:e.baseUrl??Ze,maxWaypointsPerChunk:e.maxWaypointsPerChunk??50};}async getRoute(e,t){if(e.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(t);return e.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(e,n,t):this.fetchChunked(e,n,t)}profileFromOptions(e){switch(e?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(e,t,n){let i=JSON.stringify({coordinates:e,instructions:n?.steps!==false,language:n?.language??"en"}),r=await fetch(`${this.config.baseUrl}/${t}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:i});if(!r.ok){let l=await r.text();throw new Error(`[ORS] HTTP ${r.status}: ${l}`)}let o=await r.json(),c=o.features?.[0];if(!c)throw new Error("[ORS] No route returned");let a=c.properties?.summary??{},d=(c.properties?.segments??[]).map(l=>({distance:l.distance??0,duration:l.duration??0,steps:(l.steps??[]).map(p=>({distance:p.distance??0,duration:p.duration??0,geometry:[],maneuver:{type:p.type?.toString()??"unknown",modifier:void 0,location:e[0],bearingBefore:0,bearingAfter:0,instruction:p.instruction},name:p.name}))}));return {geometry:c.geometry?.coordinates??[],distance:a.distance??0,duration:a.duration??0,legs:d,raw:o}}async fetchChunked(e,t,n){let i=this.config.maxWaypointsPerChunk,r=[];for(let l=0;l<e.length;l+=i-1){let p=e.slice(l,l+i);if(p.length<2||(r.push(p),l+i>=e.length))break}let o=await Promise.all(r.map(l=>this.fetchRoute(l,t,n))),c=[],a=0,u=0,d=[];for(let l=0;l<o.length;l++){let p=o[l];c.push(...l===0?p.geometry:p.geometry.slice(1)),a+=p.distance,u+=p.duration,d.push(...p.legs);}return {geometry:c,distance:a,duration:u,legs:d,raw:o.map(l=>l.raw)}}};var et={earlyTriggerMeters:120,lateTriggerMeters:20,reannounceMeters:300},ue=class{constructor(e){this.instructions=[];this.triggeredIds=new Set;this.reannouncedIds=new Set;this.options={...et,...e};}setInstructions(e){this.instructions=[...e],this.triggeredIds.clear(),this.reannouncedIds.clear();}update(e){let t=m.getActive();if(!t||!t.hasFeature(h.VOICE_TRIGGERS))return t?t.warnOnce(h.VOICE_TRIGGERS):console.warn(`[NavCore] Feature '${h.VOICE_TRIGGERS}' requires a Pro license`),null;let{distanceToNextInstruction:n,nextInstructionIndex:i}=e;if(i===null||n===null||i>=this.instructions.length)return null;let r=this.instructions[i],o=this.instrId(i),c=n;if(this.triggeredIds.has(o))return this.options.reannounceMeters>0&&!this.reannouncedIds.has(o)&&c<=this.options.reannounceMeters&&c>this.options.earlyTriggerMeters?(this.reannouncedIds.add(o),this.makeCue(r,c,"low")):null;if(c>this.options.earlyTriggerMeters)return null;if(c<-this.options.lateTriggerMeters)return this.triggeredIds.add(o),null;this.triggeredIds.add(o);let a=c<30?"urgent":c<60?"high":"normal";return this.makeCue(r,c,a)}onInstruction(e,t){let n=m.getActive();if(!n||!n.hasFeature(h.VOICE_TRIGGERS))return n?n.warnOnce(h.VOICE_TRIGGERS):console.warn(`[NavCore] Feature '${h.VOICE_TRIGGERS}' requires a Pro license`),{instruction:e,text:"",distanceMetres:0,priority:"normal",triggerId:"bypass"};let i=t.distanceToNextInstruction??0;return this.makeCue(e,i,"high")}reset(){this.triggeredIds.clear(),this.reannouncedIds.clear();}instrId(e){let t=this.instructions[e];return `${e}_${t?.geometryIndex??0}`}makeCue(e,t,n){return {instruction:e,text:e.text??e.instruction??"",distanceMetres:Math.max(0,t),priority:n,triggerId:`${e.geometryIndex}_${t.toFixed(0)}`}}};var tt={speedWindowSize:6,minimumSpeedMs:.5,fallbackSpeedMs:8.33},de=class{constructor(e){this.speedSamples=[];this.options={...tt,...e},this.lastReliableSpeed=this.options.fallbackSpeedMs;}update(e){let t=m.getActive();if(!t||!t.hasFeature(h.ETA))return t?t.warnOnce(h.ETA):console.warn(`[NavCore] Feature '${h.ETA}' requires a Pro license`),{etaSeconds:0,etaMs:0,distanceRemainingM:0,averageSpeedMs:0,isReliable:false};let n=e.distanceToDestination??0,i=e.currentSpeed??0;this.speedSamples.push(i),this.speedSamples.length>this.options.speedWindowSize&&this.speedSamples.shift();let r=this.rollingAverage();r>=this.options.minimumSpeedMs&&(this.lastReliableSpeed=r);let o=r>=this.options.minimumSpeedMs?r:this.lastReliableSpeed,c=this.speedSamples.length>=Math.ceil(this.options.speedWindowSize/2)&&o>0&&n>0,a=o>0?n/o:0;return {etaSeconds:Math.round(a),etaMs:Date.now()+a*1e3,distanceRemainingM:n,averageSpeedMs:r,isReliable:c}}reset(){this.speedSamples=[],this.lastReliableSpeed=this.options.fallbackSpeedMs;}rollingAverage(){return this.speedSamples.length===0?0:this.speedSamples.reduce((t,n)=>t+n,0)/this.speedSamples.length}};var nt={dwellThresholdMs:1e4},pe=class{constructor(e){this.fences=new Map;this.states=new Map;if(this.options={...nt,...e},this.options.zones)for(let t of this.options.zones)t.type==="circle"&&t.center&&t.radiusMeters?this.addCircle(t.id,t.name,t.center,t.radiusMeters,t.meta):t.type==="polygon"&&t.coords&&this.addPolygon(t.id,t.name,t.coords,t.meta);}addCircle(e,t,n,i,r){return this.fences.set(e,{kind:"circle",id:e,name:t,center:n,radiusM:i,meta:r}),this.states.set(e,{inside:false,enteredAtMs:null}),e}addPolygon(e,t,n,i){if(n.length<3)throw new Error("[Geofencing] Polygon requires at least 3 coordinates");return this.fences.set(e,{kind:"polygon",id:e,name:t,coords:n,meta:i}),this.states.set(e,{inside:false,enteredAtMs:null}),e}remove(e){this.fences.delete(e),this.states.delete(e);}clear(){this.fences.clear(),this.states.clear();}listIds(){return Array.from(this.fences.keys())}update(e){let t=m.getActive();if(!t||!t.hasFeature(h.GEOFENCING))return t?t.warnOnce(h.GEOFENCING):console.warn(`[NavCore] Feature '${h.GEOFENCING}' requires a Pro license`),[];if(!e)return [];let n=[],i=Date.now();for(let[r,o]of this.fences){let c=this.states.get(r),a=this.contains(o,e);if(!c.inside&&a){c.inside=true,c.enteredAtMs=i;let u={id:r,name:o.name,type:"enter",coord:e,meta:o.meta};n.push(u),this.options.onEvent?.(u);}else if(c.inside&&!a){c.inside=false;let u=c.enteredAtMs?i-c.enteredAtMs:0;c.enteredAtMs=null;let d={id:r,name:o.name,type:"exit",coord:e,dwellMs:u,meta:o.meta};n.push(d),this.options.onEvent?.(d);}else if(c.inside&&c.enteredAtMs!==null){let u=i-c.enteredAtMs;if(u>=this.options.dwellThresholdMs){let d={id:r,name:o.name,type:"dwell",coord:e,dwellMs:u,meta:o.meta};n.push(d),this.options.onEvent?.(d),c.enteredAtMs=i;}}}return n}isInside(e,t){let n=this.fences.get(e);return n?this.contains(n,t):false}contains(e,t){return e.kind==="circle"?y(t[1],t[0],e.center[1],e.center[0])<=e.radiusM:this.pointInPolygon(t,e.coords)}pointInPolygon(e,t){let[n,i]=e,r=false,o=t.length;for(let c=0,a=o-1;c<o;a=c++){let[u,d]=t[c],[l,p]=t[a];d>i!=p>i&&n<(l-u)*(i-d)/(p-d)+u&&(r=!r);}return r}};var he=class{constructor(e){this.route=[];this.instructions=[];this.forwardCum=new Float64Array(0);this.reverseCum=new Float64Array(0);this.snappedCoord=null;this.rawGpsCoord=null;this.bearing=0;this.rawGpsBearing=null;this.routeIndex=0;this.maxProgressIdx=0;this.prevSegment=null;this.distanceToRoute=0;this.corridor=25;this.prevDistToNext=null;this.currentSpeed=0;this.lastGpsTimestamp=0;this.instrIdx=0;this.linearOffset=0;this.hasArrived=false;this.listeners=new Map;this.options={licenseKey:e?.licenseKey??"",isCircuit:e?.isCircuit??false,kalmanQ:e?.kalmanQ??1e-5,kalmanRBase:e?.kalmanRBase??5e-5,baseCorridorMeters:e?.baseCorridorMeters??25,maxCorridorMeters:e?.maxCorridorMeters??60,arrivalThresholdMeters:e?.arrivalThresholdMeters??30,bearingSmoothingAlpha:e?.bearingSmoothingAlpha??.3},this.kalman=new D(this.options.kalmanQ,this.options.kalmanRBase),this.snapper=new N({useBearingPenalty:true,useInertiaPenalty:true}),this.deadReckoning=new P,this.deviationDetector=new w,this.lifecycleFSM=new G,this.offRouteFSM=new L,this.license=new m(this.options.licenseKey);}has(e){let t=this.license.hasFeature(e);return t||this.license.warnOnce(e),t}setRoute(e,t){this.route=e,this.instructions=t??[],this.forwardCum=K(e),this.reverseCum=j(e),this.routeIndex=0,this.maxProgressIdx=0,this.prevSegment=null,this.instrIdx=0,this.linearOffset=0,this.hasArrived=false,this.snappedCoord=null,this.prevDistToNext=null,this.lifecycleFSM.dispatch({type:"ROUTE_LOADED"}),this.emit("routeLoaded",{routeLength:e.length});}startNavigation(){this.lifecycleFSM.dispatch({type:"USER_START_NAVIGATION"}),this.emit("navigationStarted");}update(e){if(this.rawGpsCoord=e.coord,this.rawGpsBearing=e.bearing,this.currentSpeed=e.speed,this.lastGpsTimestamp=e.timestamp,this.route.length<2)return this.getState();let[t,n]=this.kalman.update(e.coord[0],e.coord[1],e.accuracy??10,e.timestamp),i=[t,n],r=Math.max(0,this.routeIndex-2),o=this.snapper.snap(i,this.route,r,25,this.options.isCircuit,this.maxProgressIdx,this.routeIndex,e.bearing,this.prevSegment);this.corridor=Z(e.speed,e.accuracy,this.options.baseCorridorMeters,this.options.maxCorridorMeters);let c=te(this.routeIndex,o.idx,this.route,o.dist,80);if(this.prevSegment=this.routeIndex,this.routeIndex=c,this.maxProgressIdx=Math.max(this.maxProgressIdx,c),this.snappedCoord=o.proj,this.distanceToRoute=o.dist,this.forwardCum.length>c){let a=this.forwardCum[c]??0;this.linearOffset=oe(this.linearOffset,a,.15);}if(this.has(h.ADVANCED_BEARING)?this.bearing=ee(this.bearing,this.route,this.routeIndex,e.speed,e.bearing,this.options.bearingSmoothingAlpha):e.bearing!==null&&(this.bearing=e.bearing),this.has(h.COMPOUND_DEVIATION)&&(this.offRouteFSM.state==="ON_ROUTE"||this.offRouteFSM.state==="DEVIATING")){let a=Oe(i,this.route,r,25),u=this.deviationDetector.evaluate(i,e.bearing,e.speed,a,this.route,this.corridor,this.prevDistToNext);if(a.segmentIndex<this.route.length-1){let d=this.route[Math.min(a.segmentIndex+2,this.route.length-1)];this.prevDistToNext=y(i[1],i[0],d[1],d[0]);}u.confirmed?this.offRouteFSM.state==="ON_ROUTE"?this.offRouteFSM.dispatch({type:"DEVIATION_SUSPECTED",deviationSegmentIdx:a.segmentIndex}):this.offRouteFSM.isDeviationConfirmed()&&(this.offRouteFSM.dispatch({type:"DEVIATION_CONFIRMED",deviationSegmentIdx:a.segmentIndex}),this.emit("deviation",{anchorIndex:a.segmentIndex,ghostCoord:o.proj})):this.offRouteFSM.state==="DEVIATING"&&this.offRouteFSM.dispatch({type:"RESUME"});}else this.has(h.COMPOUND_DEVIATION)||(o.dist>this.corridor&&this.offRouteFSM.state==="ON_ROUTE"?(this.offRouteFSM.dispatch({type:"DEVIATION_SUSPECTED",deviationSegmentIdx:o.idx}),this.emit("deviation",{anchorIndex:o.idx,ghostCoord:o.proj})):o.dist<=this.corridor&&this.offRouteFSM.state!=="ON_ROUTE"&&this.offRouteFSM.dispatch({type:"RESUME"}));if(this.lifecycleFSM.state==="APPROACHING_ROUTE"&&o.dist<this.corridor&&this.lifecycleFSM.dispatch({type:"ROUTE_JOINED",data:{index:o.idx}}),this.instructions.length>0){let a=ne(this.routeIndex,this.instructions,this.instrIdx,this.route,i,e.bearing,this.linearOffset,e.speed);a.nextIdx!==this.instrIdx&&(this.instrIdx=a.nextIdx),a.wasTriggered&&a.instruction&&(this.emit("instruction",a.instruction),this.instrIdx=a.nextIdx+1);}if(!this.hasArrived&&this.route.length>0){let a=this.route[this.route.length-1],u=y(i[1],i[0],a[1],a[0]),d=this.options.isCircuit?this.routeIndex>=this.route.length*.8:true;u<this.options.arrivalThresholdMeters&&d&&(this.hasArrived=true,this.lifecycleFSM.dispatch({type:"NAVIGATION_FINISHED"}),this.emit("arrival"));}return this.has(h.DEAD_RECKONING)&&this.deadReckoning.setAnchor(o.proj,o.idx,e.timestamp),this.getState()}tick(e){if(this.has(h.DEAD_RECKONING)){let t=this.deadReckoning.predict(this.currentSpeed,this.bearing,e);t.isActive&&(this.snappedCoord=t.predictedCoord);}if(this.lastGpsTimestamp>0){let t=(e-this.lastGpsTimestamp)/1e3;t>0&&t<10&&(this.linearOffset=re(this.linearOffset,this.currentSpeed,t));}return this.getState()}getState(){let e=this.route.length>0&&this.reverseCum.length>this.routeIndex?this.reverseCum[this.routeIndex]??null:null,t=this.instrIdx<this.instructions.length?(()=>{let i=this.instructions[this.instrIdx];return i.cumulativeOffset!==void 0?Math.max(0,i.cumulativeOffset-this.linearOffset):null})():null,n=this.lastGpsTimestamp>0?Date.now()-this.lastGpsTimestamp:0;return {snappedCoord:this.snappedCoord,rawGpsCoord:this.rawGpsCoord,bearing:this.bearing,rawGpsBearing:this.rawGpsBearing,routeIndex:this.routeIndex,distanceToRoute:this.distanceToRoute,corridor:this.corridor,isOffRoute:this.offRouteFSM.state!=="ON_ROUTE"&&this.offRouteFSM.state!=="DEVIATING",progressIndex:this.routeIndex,hasArrived:this.hasArrived,offRouteState:this.offRouteFSM.state,lifecycleState:this.lifecycleFSM.state,distanceToDestination:e,distanceToNextInstruction:t,nextInstructionIndex:this.instrIdx<this.instructions.length?this.instrIdx:null,currentSpeed:this.currentSpeed,isGpsStale:n>3e3,gpsAgeMs:n,licenseStatus:this.license.getStatus()}}destroy(){this.listeners.clear(),this.route=[],this.instructions=[],this.kalman.reset(),this.deadReckoning.clearAnchor(),this.lifecycleFSM.reset(),this.offRouteFSM.reset();}on(e,t){this.listeners.has(e)||this.listeners.set(e,[]),this.listeners.get(e).push(t);}off(e,t){let n=this.listeners.get(e);if(n){let i=n.indexOf(t);i>=0&&n.splice(i,1);}}emit(e,...t){let n=this.listeners.get(e);if(n)for(let i of n)i(...t);}getLicenseManager(){return this.license}getRoute(){return this.route}getInstructions(){return this.instructions}getOffRouteFSM(){return this.offRouteFSM}getLifecycleFSM(){return this.lifecycleFSM}};
8
- exports.Constants=Se;exports.CustomRouteBuilder=se;exports.DeadReckoningEngine=P;exports.DeviationDetector=w;exports.ETAEngine=de;exports.FEATURES=h;exports.GeofencingEngine=pe;exports.InstructionEditor=ie;exports.KalmanFilter2D=D;exports.LicenseManager=m;exports.NavCore=he;exports.NavigationFSM=G;exports.OSRMDirectionsProvider=ae;exports.OffRouteFSM=L;exports.OpenRouteServiceProvider=le;exports.ParallelRoadResolver=Q;exports.RouteSnapper=N;exports.ValhallaDirectionsProvider=ce;exports.VoiceTriggerEngine=ue;exports.advancePredictor=re;exports.applyBearingSmoothing=ee;exports.applyGpsCorrection=oe;exports.blendBearing=V;exports.buildForwardCumulativeDistances=K;exports.buildReverseCumulativeDistances=j;exports.calculateDynamicCorridor=Z;exports.calculateRobustBearing=Me;exports.computeDeadReckoningOnRoute=Ae;exports.destinationPoint=B;exports.geoGetBearing=we;exports.getBearingBetweenPoints=R;exports.getSpeedAdaptiveAlpha=_e;exports.haversineDistance=y;exports.interpolatePoint=W;exports.kalmanUpdate2D=me;exports.normalizeAngle=E;exports.pointAtOffset=ze;exports.projectPointOnSegment=H;exports.resolveNextInstruction=ne;exports.validateProgressUpdate=te;
7
+ </gpx>`}fromGeoJSON(e){if(this.waypoints=[],e.type==="FeatureCollection"&&e.features){for(let t of e.features)if(t.geometry.type==="Point"){let n=t.geometry.coordinates;this.addWaypoint(n);}else if(t.geometry.type==="LineString"){let n=t.geometry.coordinates;for(let i of n)this.addWaypoint(i);}}}toGeoJSON(){let e=this.waypoints.map((n,i)=>({type:"Feature",geometry:{type:"Point",coordinates:n.coord},properties:{id:n.id,order:i,name:n.options?.name??null,silent:n.options?.silent??false}})),t={type:"Feature",geometry:{type:"LineString",coordinates:this.waypoints.map(n=>n.coord)},properties:{type:"route"}};return {type:"FeatureCollection",features:[...e,t]}}clear(){this.waypoints=[];}};var ae=class{constructor(e){let t=e.fetchFn??globalThis.fetch?.bind(globalThis);if(!t)throw new Error("[OSRM] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:e.baseUrl.replace(/\/$/,""),profile:e.profile??"driving",maxWaypointsPerChunk:e.maxWaypointsPerChunk??100,fetchFn:t,timeoutMs:e.timeoutMs??15e3};}async getRoute(e,t){if(e.length<2)throw new Error("[OSRM] At least 2 waypoints required");let n=t?.profile??this.config.profile;return e.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(e,n,t):this.fetchChunked(e,n,t)}async fetchRoute(e,t,n){let i=e.map(d=>`${d[0]},${d[1]}`).join(";"),r=n?.steps!==false?"true":"false",o=`${this.config.baseUrl}/route/v1/${t}/${i}?overview=full&geometries=geojson&steps=${r}&annotations=false`,c=await this.fetchWithTimeout(o);if(!c.ok)throw new Error(`[OSRM] HTTP ${c.status}: ${c.statusText}`);let a=await c.json();if(a.code!=="Ok"||!a.routes?.length)throw new Error(`[OSRM] No route found: ${a.code}`);let l=a.routes[0];return {geometry:l.geometry.coordinates,distance:l.distance,duration:l.duration,legs:(l.legs??[]).map(d=>({distance:d.distance,duration:d.duration,steps:(d.steps??[]).map(u=>({distance:u.distance,duration:u.duration,geometry:u.geometry?.coordinates??[],maneuver:{type:u.maneuver?.type??"unknown",modifier:u.maneuver?.modifier,location:u.maneuver?.location??[0,0],bearingBefore:u.maneuver?.bearing_before??0,bearingAfter:u.maneuver?.bearing_after??0,instruction:u.name??void 0},name:u.name}))})),raw:a}}async fetchChunked(e,t,n){let i=this.config.maxWaypointsPerChunk,r=[];for(let u=0;u<e.length;u+=i-1){let p=e.slice(u,u+i);if(p.length<2||(r.push(p),u+i>=e.length))break}let o=await Promise.all(r.map(u=>this.fetchRoute(u,t,n))),c=[],a=0,l=0,d=[];for(let u=0;u<o.length;u++){let p=o[u];c.push(...u===0?p.geometry:p.geometry.slice(1)),a+=p.distance,l+=p.duration,d.push(...p.legs);}return {geometry:c,distance:a,duration:l,legs:d,raw:o.map(u=>u.raw)}}async fetchWithTimeout(e,t){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(e,t);let n=new AbortController,i=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(e,{...t,signal:n.signal})}catch(r){throw r.name==="AbortError"?new Error(`[OSRM] Request timed out after ${this.config.timeoutMs}ms`):r}finally{clearTimeout(i);}}};var ce=class{constructor(e){let t=e.fetchFn??globalThis.fetch?.bind(globalThis);if(!t)throw new Error("[Valhalla] fetch is not available. Pass config.fetchFn in this runtime.");this.config={baseUrl:e.baseUrl.replace(/\/$/,""),costing:e.costing??"auto",apiKey:e.apiKey??"",maxWaypointsPerChunk:e.maxWaypointsPerChunk??50,fetchFn:t,timeoutMs:e.timeoutMs??15e3};}async getRoute(e,t){if(e.length<2)throw new Error("[Valhalla] At least 2 waypoints required");let n=this.profileToCosting(t?.profile);return e.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(e,n,t):this.fetchChunked(e,n,t)}profileToCosting(e){switch(e){case "cycling":return "bicycle";case "walking":return "pedestrian";default:return this.config.costing}}async fetchRoute(e,t,n){let i=e.map(m=>({lon:m[0],lat:m[1],type:"break"})),r=JSON.stringify({locations:i,costing:t,directions_options:{units:"kilometers"}}),o={"Content-Type":"application/json","User-Agent":"NavCoreSDK/1.0.0 (React Native; Expo; bab-bou-jeloud-demo)"};this.config.apiKey&&(o.api_key=this.config.apiKey);let c=await this.fetchWithTimeout(`${this.config.baseUrl}/route`,{method:"POST",headers:o,body:r});if(!c.ok){let m=await c.text();throw new Error(`[Valhalla] HTTP ${c.status}: ${m}`)}let a=await c.json(),l=a.trip?.legs??[],d=l.map(m=>this.decodePolyline(m.shape??"")),u=this.stitchGeometry(d),p=u.length>0?u:e,x=a.trip?.summary??{},y=l.map((m,g)=>({distance:(m.summary?.length??0)*1e3,duration:m.summary?.time??0,steps:(m.maneuvers??[]).map(f=>{let I=d[g]??[],v=this.shapeIndex(f.begin_shape_index,0),M=this.shapeIndex(f.end_shape_index,v),S=I.length>0?I.slice(v,Math.max(v,M)+1):[],_=e[Math.min(g,e.length-1)],A=S[0]??I[v]??_;return {distance:(f.length??0)*1e3,duration:f.time??0,geometry:S,maneuver:{type:f.type?.toString()??"unknown",modifier:void 0,location:A,bearingBefore:f.begin_heading??0,bearingAfter:f.end_heading??0,instruction:f.instruction},name:f.street_names?.[0]}})}));return {geometry:p,distance:(x.length??0)*1e3,duration:x.time??0,legs:y,raw:a}}decodePolyline(e,t=6){let n=Math.pow(10,t),i=[],r=0,o=0,c=0;for(;r<e.length;){let a=0,l=0,d;do d=e.charCodeAt(r++)-63,l|=(d&31)<<a,a+=5;while(d>=32);let u=(l&1)!==0?~(l>>1):l>>1;o+=u,a=0,l=0;do d=e.charCodeAt(r++)-63,l|=(d&31)<<a,a+=5;while(d>=32);let p=(l&1)!==0?~(l>>1):l>>1;c+=p,i.push([c/n,o/n]);}return i}stitchGeometry(e){let t=[];for(let n of e){if(n.length===0)continue;let i=n[0],r=t[t.length-1];r&&this.sameCoordinate(r,i)?t.push(...n.slice(1)):t.push(...n);}return t}sameCoordinate(e,t){return Math.abs(e[0]-t[0])<1e-9&&Math.abs(e[1]-t[1])<1e-9}shapeIndex(e,t){return typeof e=="number"&&Number.isFinite(e)&&e>=0?Math.floor(e):t}async fetchChunked(e,t,n){let i=this.config.maxWaypointsPerChunk,r=[];for(let u=0;u<e.length;u+=i-1){let p=e.slice(u,u+i);if(p.length<2||(r.push(p),u+i>=e.length))break}let o=await Promise.all(r.map(u=>this.fetchRoute(u,t,n))),c=[],a=0,l=0,d=[];for(let u=0;u<o.length;u++){let p=o[u];c.push(...u===0?p.geometry:p.geometry.slice(1)),a+=p.distance,l+=p.duration,d.push(...p.legs);}return {geometry:c,distance:a,duration:l,legs:d,raw:o.map(u=>u.raw)}}async fetchWithTimeout(e,t){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(e,t);let n=new AbortController,i=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(e,{...t,signal:n.signal})}catch(r){throw r.name==="AbortError"?new Error(`[Valhalla] Request timed out after ${this.config.timeoutMs}ms`):r}finally{clearTimeout(i);}}};var Ze="https://api.openrouteservice.org/v2/directions",et=50,tt=15e3,le=class{constructor(e){let t=e.fetchFn??globalThis.fetch?.bind(globalThis);if(!t)throw new Error("[ORS] fetch is not available. Pass config.fetchFn in this runtime.");this.config={apiKey:e.apiKey,profile:e.profile??"driving-car",baseUrl:e.baseUrl??Ze,maxWaypointsPerChunk:e.maxWaypointsPerChunk??et,fetchFn:t,timeoutMs:e.timeoutMs??tt};}async getRoute(e,t){if(e.length<2)throw new Error("[ORS] At least 2 waypoints required");let n=this.profileFromOptions(t);return e.length<=this.config.maxWaypointsPerChunk?this.fetchRoute(e,n,t):this.fetchChunked(e,n,t)}profileFromOptions(e){switch(e?.profile){case "cycling":return "cycling-regular";case "walking":return "foot-walking";default:return this.config.profile}}async fetchRoute(e,t,n){let i=JSON.stringify({coordinates:e,instructions:n?.steps!==false,language:n?.language??"en"}),r=await this.fetchWithTimeout(`${this.config.baseUrl}/${t}/geojson`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:this.config.apiKey},body:i});if(!r.ok){let p=await r.text();throw new Error(`[ORS] HTTP ${r.status}: ${p}`)}let o=await r.json(),c=o.features?.[0];if(!c)throw new Error("[ORS] No route returned");let a=c.properties?.summary??{},l=c.properties?.segments??[],d=c.geometry?.coordinates??[],u=l.map((p,x)=>({distance:p.distance??0,duration:p.duration??0,steps:(p.steps??[]).map(y=>{let[m,g]=this.stepRange(y.way_points),f=d.slice(m,Math.max(m,g)+1),I=e[Math.min(x,e.length-1)],v=f[0]??d[m]??I;return {distance:y.distance??0,duration:y.duration??0,geometry:f,maneuver:{type:y.type?.toString()??"unknown",modifier:void 0,location:v,bearingBefore:this.bearingFromGeometry(f,false),bearingAfter:this.bearingFromGeometry(f,true),instruction:y.instruction},name:y.name}})}));return {geometry:d,distance:a.distance??0,duration:a.duration??0,legs:u,raw:o}}async fetchChunked(e,t,n){let i=this.config.maxWaypointsPerChunk,r=[];for(let u=0;u<e.length;u+=i-1){let p=e.slice(u,u+i);if(p.length<2||(r.push(p),u+i>=e.length))break}let o=await Promise.all(r.map(u=>this.fetchRoute(u,t,n))),c=[],a=0,l=0,d=[];for(let u=0;u<o.length;u++){let p=o[u];c.push(...u===0?p.geometry:p.geometry.slice(1)),a+=p.distance,l+=p.duration,d.push(...p.legs);}return {geometry:c,distance:a,duration:l,legs:d,raw:o.map(u=>u.raw)}}stepRange(e){if(!Array.isArray(e))return [0,0];let t=typeof e[0]=="number"&&Number.isFinite(e[0])?Math.max(0,Math.floor(e[0])):0,n=typeof e[1]=="number"&&Number.isFinite(e[1])?Math.max(t,Math.floor(e[1])):t;return [t,n]}bearingFromGeometry(e,t){if(e.length<2)return 0;let n=t?e[e.length-2]:e[0],i=t?e[e.length-1]:e[1];return !n||!i?0:E(n,i)}async fetchWithTimeout(e,t){if(this.config.timeoutMs<=0||typeof AbortController>"u")return this.config.fetchFn(e,t);let n=new AbortController,i=setTimeout(()=>n.abort(),this.config.timeoutMs);try{return await this.config.fetchFn(e,{...t,signal:n.signal})}catch(r){throw r.name==="AbortError"?new Error(`[ORS] Request timed out after ${this.config.timeoutMs}ms`):r}finally{clearTimeout(i);}}};var nt={earlyTriggerMeters:120,lateTriggerMeters:20,reannounceMeters:300},ue=class{constructor(e){this.instructions=[];this.triggeredIds=new Set;this.reannouncedIds=new Set;this.options={...nt,...e};}setInstructions(e){this.instructions=[...e],this.triggeredIds.clear(),this.reannouncedIds.clear();}update(e){let t=R.getActive();if(!t||!t.hasFeature(h.VOICE_TRIGGERS))return t?t.warnOnce(h.VOICE_TRIGGERS):console.warn(`[NavCore] Feature '${h.VOICE_TRIGGERS}' requires a Pro license`),null;let{distanceToNextInstruction:n,nextInstructionIndex:i}=e;if(i===null||n===null||i>=this.instructions.length)return null;let r=this.instructions[i],o=this.instrId(i),c=n;if(this.triggeredIds.has(o))return this.options.reannounceMeters>0&&!this.reannouncedIds.has(o)&&c<=this.options.reannounceMeters&&c>this.options.earlyTriggerMeters?(this.reannouncedIds.add(o),this.makeCue(r,c,"low")):null;if(c>this.options.earlyTriggerMeters)return null;if(c<-this.options.lateTriggerMeters)return this.triggeredIds.add(o),null;this.triggeredIds.add(o);let a=c<30?"urgent":c<60?"high":"normal";return this.makeCue(r,c,a)}onInstruction(e,t){let n=R.getActive();if(!n||!n.hasFeature(h.VOICE_TRIGGERS))return n?n.warnOnce(h.VOICE_TRIGGERS):console.warn(`[NavCore] Feature '${h.VOICE_TRIGGERS}' requires a Pro license`),{instruction:e,text:"",distanceMetres:0,priority:"normal",triggerId:"bypass"};let i=t.distanceToNextInstruction??0;return this.makeCue(e,i,"high")}reset(){this.triggeredIds.clear(),this.reannouncedIds.clear();}instrId(e){let t=this.instructions[e];return `${e}_${t?.geometryIndex??0}`}makeCue(e,t,n){return {instruction:e,text:e.text??e.instruction??"",distanceMetres:Math.max(0,t),priority:n,triggerId:`${e.geometryIndex}_${t.toFixed(0)}`}}};var it={speedWindowSize:6,minimumSpeedMs:.5,fallbackSpeedMs:8.33},de=class{constructor(e){this.speedSamples=[];this.options={...it,...e},this.lastReliableSpeed=this.options.fallbackSpeedMs;}update(e){let t=R.getActive();if(!t||!t.hasFeature(h.ETA))return t?t.warnOnce(h.ETA):console.warn(`[NavCore] Feature '${h.ETA}' requires a Pro license`),{etaSeconds:0,etaMs:0,distanceRemainingM:0,averageSpeedMs:0,isReliable:false};let n=e.distanceToDestination??0,i=e.currentSpeed??0;this.speedSamples.push(i),this.speedSamples.length>this.options.speedWindowSize&&this.speedSamples.shift();let r=this.rollingAverage();r>=this.options.minimumSpeedMs&&(this.lastReliableSpeed=r);let o=r>=this.options.minimumSpeedMs?r:this.lastReliableSpeed,c=this.speedSamples.length>=Math.ceil(this.options.speedWindowSize/2)&&o>0&&n>0,a=o>0?n/o:0;return {etaSeconds:Math.round(a),etaMs:Date.now()+a*1e3,distanceRemainingM:n,averageSpeedMs:r,isReliable:c}}reset(){this.speedSamples=[],this.lastReliableSpeed=this.options.fallbackSpeedMs;}rollingAverage(){return this.speedSamples.length===0?0:this.speedSamples.reduce((t,n)=>t+n,0)/this.speedSamples.length}};var rt={dwellThresholdMs:1e4},pe=class{constructor(e){this.fences=new Map;this.states=new Map;if(this.options={...rt,...e},this.options.zones)for(let t of this.options.zones)t.type==="circle"&&t.center&&t.radiusMeters?this.addCircle(t.id,t.name,t.center,t.radiusMeters,t.meta):t.type==="polygon"&&t.coords&&this.addPolygon(t.id,t.name,t.coords,t.meta);}addCircle(e,t,n,i,r){return this.fences.set(e,{kind:"circle",id:e,name:t,center:n,radiusM:i,meta:r}),this.states.set(e,{inside:false,enteredAtMs:null}),e}addPolygon(e,t,n,i){if(n.length<3)throw new Error("[Geofencing] Polygon requires at least 3 coordinates");return this.fences.set(e,{kind:"polygon",id:e,name:t,coords:n,meta:i}),this.states.set(e,{inside:false,enteredAtMs:null}),e}remove(e){this.fences.delete(e),this.states.delete(e);}clear(){this.fences.clear(),this.states.clear();}listIds(){return Array.from(this.fences.keys())}update(e){let t=R.getActive();if(!t||!t.hasFeature(h.GEOFENCING))return t?t.warnOnce(h.GEOFENCING):console.warn(`[NavCore] Feature '${h.GEOFENCING}' requires a Pro license`),[];if(!e)return [];let n=[],i=Date.now();for(let[r,o]of this.fences){let c=this.states.get(r),a=this.contains(o,e);if(!c.inside&&a){c.inside=true,c.enteredAtMs=i;let l={id:r,name:o.name,type:"enter",coord:e,meta:o.meta};n.push(l),this.options.onEvent?.(l);}else if(c.inside&&!a){c.inside=false;let l=c.enteredAtMs?i-c.enteredAtMs:0;c.enteredAtMs=null;let d={id:r,name:o.name,type:"exit",coord:e,dwellMs:l,meta:o.meta};n.push(d),this.options.onEvent?.(d);}else if(c.inside&&c.enteredAtMs!==null){let l=i-c.enteredAtMs;if(l>=this.options.dwellThresholdMs){let d={id:r,name:o.name,type:"dwell",coord:e,dwellMs:l,meta:o.meta};n.push(d),this.options.onEvent?.(d),c.enteredAtMs=i;}}}return n}isInside(e,t){let n=this.fences.get(e);return n?this.contains(n,t):false}contains(e,t){return e.kind==="circle"?b(t[1],t[0],e.center[1],e.center[0])<=e.radiusM:this.pointInPolygon(t,e.coords)}pointInPolygon(e,t){let[n,i]=e,r=false,o=t.length;for(let c=0,a=o-1;c<o;a=c++){let[l,d]=t[c],[u,p]=t[a];d>i!=p>i&&n<(u-l)*(i-d)/(p-d)+l&&(r=!r);}return r}};var he=class{constructor(e){this.route=[];this.instructions=[];this.forwardCum=new Float64Array(0);this.reverseCum=new Float64Array(0);this.snappedCoord=null;this.rawGpsCoord=null;this.bearing=0;this.rawGpsBearing=null;this.routeIndex=0;this.maxProgressIdx=0;this.prevSegment=null;this.distanceToRoute=0;this.corridor=25;this.prevDistToNext=null;this.currentSpeed=0;this.lastGpsTimestamp=0;this.instrIdx=0;this.linearOffset=0;this.hasArrived=false;this.listeners=new Map;this.options={licenseKey:e?.licenseKey??"",isCircuit:e?.isCircuit??false,kalmanQ:e?.kalmanQ??1e-5,kalmanRBase:e?.kalmanRBase??5e-5,baseCorridorMeters:e?.baseCorridorMeters??25,maxCorridorMeters:e?.maxCorridorMeters??60,arrivalThresholdMeters:e?.arrivalThresholdMeters??30,bearingSmoothingAlpha:e?.bearingSmoothingAlpha??.3},this.kalman=new D(this.options.kalmanQ,this.options.kalmanRBase),this.snapper=new N({useBearingPenalty:true,useInertiaPenalty:true}),this.deadReckoning=new P,this.deviationDetector=new w,this.lifecycleFSM=new G,this.offRouteFSM=new L,this.license=new R(this.options.licenseKey);}canUse(e){return this.license.hasFeature(e)}setRoute(e,t){this.route=e,this.instructions=t??[],this.forwardCum=K(e),this.reverseCum=j(e),this.routeIndex=0,this.maxProgressIdx=0,this.prevSegment=null,this.instrIdx=0,this.linearOffset=0,this.hasArrived=false,this.snappedCoord=null,this.prevDistToNext=null,this.lifecycleFSM.dispatch({type:"ROUTE_LOADED"}),this.emit("routeLoaded",{routeLength:e.length});}startNavigation(){this.lifecycleFSM.dispatch({type:"USER_START_NAVIGATION"}),this.emit("navigationStarted");}update(e){if(this.rawGpsCoord=e.coord,this.rawGpsBearing=e.bearing,this.currentSpeed=e.speed,this.lastGpsTimestamp=e.timestamp,this.route.length<2)return this.getState();let[t,n]=this.kalman.update(e.coord[0],e.coord[1],e.accuracy??10,e.timestamp),i=[t,n],r=Math.max(0,this.routeIndex-2),o=this.snapper.snap(i,this.route,r,25,this.options.isCircuit,this.maxProgressIdx,this.routeIndex,e.bearing,this.prevSegment);this.corridor=Z(e.speed,e.accuracy,this.options.baseCorridorMeters,this.options.maxCorridorMeters);let c=te(this.routeIndex,o.idx,this.route,o.dist,80);if(this.prevSegment=this.routeIndex,this.routeIndex=c,this.maxProgressIdx=Math.max(this.maxProgressIdx,c),this.snappedCoord=o.proj,this.distanceToRoute=o.dist,this.forwardCum.length>c){let a=this.forwardCum[c]??0;this.linearOffset=oe(this.linearOffset,a,.15);}if(this.canUse(h.ADVANCED_BEARING)?this.bearing=ee(this.bearing,this.route,this.routeIndex,e.speed,e.bearing,this.options.bearingSmoothingAlpha):e.bearing!==null&&(this.bearing=e.bearing),this.canUse(h.COMPOUND_DEVIATION)&&(this.offRouteFSM.state==="ON_ROUTE"||this.offRouteFSM.state==="DEVIATING")){let a=Ae(i,this.route,r,25),l=this.deviationDetector.evaluate(i,e.bearing,e.speed,a,this.route,this.corridor,this.prevDistToNext);if(a.segmentIndex<this.route.length-1){let d=this.route[Math.min(a.segmentIndex+2,this.route.length-1)];this.prevDistToNext=b(i[1],i[0],d[1],d[0]);}l.confirmed?this.offRouteFSM.state==="ON_ROUTE"?this.offRouteFSM.dispatch({type:"DEVIATION_SUSPECTED",deviationSegmentIdx:a.segmentIndex}):this.offRouteFSM.isDeviationConfirmed()&&(this.offRouteFSM.dispatch({type:"DEVIATION_CONFIRMED",deviationSegmentIdx:a.segmentIndex}),this.emit("deviation",{anchorIndex:a.segmentIndex,ghostCoord:o.proj})):this.offRouteFSM.state==="DEVIATING"&&this.offRouteFSM.dispatch({type:"RESUME"});}else o.dist>this.corridor&&this.offRouteFSM.state==="ON_ROUTE"?(this.offRouteFSM.dispatch({type:"DEVIATION_SUSPECTED",deviationSegmentIdx:o.idx}),this.emit("deviation",{anchorIndex:o.idx,ghostCoord:o.proj})):o.dist<=this.corridor&&this.offRouteFSM.state!=="ON_ROUTE"&&this.offRouteFSM.dispatch({type:"RESUME"});if(this.lifecycleFSM.state==="APPROACHING_ROUTE"&&o.dist<this.corridor&&this.lifecycleFSM.dispatch({type:"ROUTE_JOINED",data:{index:o.idx}}),this.instructions.length>0){let a=ne(this.routeIndex,this.instructions,this.instrIdx,this.route,i,e.bearing,this.linearOffset,e.speed);a.nextIdx!==this.instrIdx&&(this.instrIdx=a.nextIdx),a.wasTriggered&&a.instruction&&(this.emit("instruction",a.instruction),this.instrIdx=a.nextIdx+1);}if(!this.hasArrived&&this.route.length>0){let a=this.route[this.route.length-1],l=b(i[1],i[0],a[1],a[0]),d=this.options.isCircuit?this.routeIndex>=this.route.length*.8:true;l<this.options.arrivalThresholdMeters&&d&&(this.hasArrived=true,this.lifecycleFSM.dispatch({type:"NAVIGATION_FINISHED"}),this.emit("arrival"));}return this.canUse(h.DEAD_RECKONING)&&this.deadReckoning.setAnchor(o.proj,o.idx,e.timestamp),this.getState()}tick(e){if(this.canUse(h.DEAD_RECKONING)){let t=this.deadReckoning.predict(this.currentSpeed,this.bearing,e);t.isActive&&(this.snappedCoord=t.predictedCoord);}if(this.lastGpsTimestamp>0){let t=(e-this.lastGpsTimestamp)/1e3;t>0&&t<10&&(this.linearOffset=re(this.linearOffset,this.currentSpeed,t));}return this.getState()}getState(){let e=this.route.length>0&&this.reverseCum.length>this.routeIndex?this.reverseCum[this.routeIndex]??null:null,t=this.instrIdx<this.instructions.length?(()=>{let i=this.instructions[this.instrIdx];return i.cumulativeOffset!==void 0?Math.max(0,i.cumulativeOffset-this.linearOffset):null})():null,n=this.lastGpsTimestamp>0?Date.now()-this.lastGpsTimestamp:0;return {snappedCoord:this.snappedCoord,rawGpsCoord:this.rawGpsCoord,bearing:this.bearing,rawGpsBearing:this.rawGpsBearing,routeIndex:this.routeIndex,distanceToRoute:this.distanceToRoute,corridor:this.corridor,isOffRoute:this.offRouteFSM.state!=="ON_ROUTE",progressIndex:this.routeIndex,hasArrived:this.hasArrived,offRouteState:this.offRouteFSM.state,lifecycleState:this.lifecycleFSM.state,distanceToDestination:e,distanceToNextInstruction:t,nextInstructionIndex:this.instrIdx<this.instructions.length?this.instrIdx:null,currentSpeed:this.currentSpeed,isGpsStale:n>3e3,gpsAgeMs:n,licenseStatus:this.license.getStatus()}}destroy(){this.listeners.clear(),this.route=[],this.instructions=[],this.kalman.reset(),this.deadReckoning.clearAnchor(),this.lifecycleFSM.reset(),this.offRouteFSM.reset();}on(e,t){this.listeners.has(e)||this.listeners.set(e,[]),this.listeners.get(e).push(t);}off(e,t){let n=this.listeners.get(e);if(n){let i=n.indexOf(t);i>=0&&n.splice(i,1);}}emit(e,...t){let n=this.listeners.get(e);if(n)for(let i of n)i(...t);}getLicenseManager(){return this.license}getRoute(){return this.route}getInstructions(){return this.instructions}getOffRouteFSM(){return this.offRouteFSM}getLifecycleFSM(){return this.lifecycleFSM}};
8
+ exports.Constants=Se;exports.CustomRouteBuilder=se;exports.DeadReckoningEngine=P;exports.DeviationDetector=w;exports.ETAEngine=de;exports.FEATURES=h;exports.GeofencingEngine=pe;exports.InstructionEditor=ie;exports.KalmanFilter2D=D;exports.LicenseManager=R;exports.NavCore=he;exports.NavigationFSM=G;exports.OSRMDirectionsProvider=ae;exports.OffRouteFSM=L;exports.OpenRouteServiceProvider=le;exports.ParallelRoadResolver=Q;exports.RouteSnapper=N;exports.ValhallaDirectionsProvider=ce;exports.VoiceTriggerEngine=ue;exports.advancePredictor=re;exports.applyBearingSmoothing=ee;exports.applyGpsCorrection=oe;exports.blendBearing=B;exports.buildForwardCumulativeDistances=K;exports.buildReverseCumulativeDistances=j;exports.calculateDynamicCorridor=Z;exports.calculateRobustBearing=_e;exports.computeDeadReckoningOnRoute=Me;exports.destinationPoint=W;exports.geoGetBearing=we;exports.getBearingBetweenPoints=E;exports.getSpeedAdaptiveAlpha=Oe;exports.haversineDistance=b;exports.interpolatePoint=H;exports.kalmanUpdate2D=me;exports.normalizeAngle=C;exports.pointAtOffset=ze;exports.projectPointOnSegment=U;exports.resolveNextInstruction=ne;exports.validateProgressUpdate=te;