@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/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
- 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
+ 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
- export{Se as Constants,se as CustomRouteBuilder,P as DeadReckoningEngine,w as DeviationDetector,de as ETAEngine,h as FEATURES,pe as GeofencingEngine,ie as InstructionEditor,D as KalmanFilter2D,m as LicenseManager,he as NavCore,G as NavigationFSM,ae as OSRMDirectionsProvider,L as OffRouteFSM,le as OpenRouteServiceProvider,Q as ParallelRoadResolver,N as RouteSnapper,ce as ValhallaDirectionsProvider,ue as VoiceTriggerEngine,re as advancePredictor,ee as applyBearingSmoothing,oe as applyGpsCorrection,V as blendBearing,K as buildForwardCumulativeDistances,j as buildReverseCumulativeDistances,Z as calculateDynamicCorridor,Me as calculateRobustBearing,Ae as computeDeadReckoningOnRoute,B as destinationPoint,we as geoGetBearing,R as getBearingBetweenPoints,_e as getSpeedAdaptiveAlpha,y as haversineDistance,W as interpolatePoint,me as kalmanUpdate2D,E as normalizeAngle,ze as pointAtOffset,H as projectPointOnSegment,ne as resolveNextInstruction,te as validateProgressUpdate};
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
+ export{Se as Constants,se as CustomRouteBuilder,P as DeadReckoningEngine,w as DeviationDetector,de as ETAEngine,h as FEATURES,pe as GeofencingEngine,ie as InstructionEditor,D as KalmanFilter2D,R as LicenseManager,he as NavCore,G as NavigationFSM,ae as OSRMDirectionsProvider,L as OffRouteFSM,le as OpenRouteServiceProvider,Q as ParallelRoadResolver,N as RouteSnapper,ce as ValhallaDirectionsProvider,ue as VoiceTriggerEngine,re as advancePredictor,ee as applyBearingSmoothing,oe as applyGpsCorrection,B as blendBearing,K as buildForwardCumulativeDistances,j as buildReverseCumulativeDistances,Z as calculateDynamicCorridor,_e as calculateRobustBearing,Me as computeDeadReckoningOnRoute,W as destinationPoint,we as geoGetBearing,E as getBearingBetweenPoints,Oe as getSpeedAdaptiveAlpha,b as haversineDistance,H as interpolatePoint,me as kalmanUpdate2D,C as normalizeAngle,ze as pointAtOffset,U as projectPointOnSegment,ne as resolveNextInstruction,te as validateProgressUpdate};
package/dist/pro.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as Coordinate, i as NavInstruction, g as NavCoreState } from './NavCore.d-BuXR5DO7.mjs';
1
+ import { C as Coordinate, i as NavInstruction, g as NavCoreState } from './NavCore-DzTPBxIc.mjs';
2
2
 
3
3
  /**
4
4
  * ParallelRoadResolver
package/dist/pro.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { C as Coordinate, i as NavInstruction, g as NavCoreState } from './NavCore.d-BuXR5DO7.js';
1
+ import { C as Coordinate, i as NavInstruction, g as NavCoreState } from './NavCore-DzTPBxIc.js';
2
2
 
3
3
  /**
4
4
  * ParallelRoadResolver
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ingissa/navcore-core",
3
- "version": "1.0.3",
4
- "description": "NavCore navigation engine — zero runtime dependencies. Framework-agnostic. Works in browsers, React Native, Node.js, and CI/CD.",
3
+ "version": "1.0.4",
4
+ "description": "NavCore navigation engine - zero runtime dependencies. Framework-agnostic. Works in browsers, React Native, Node.js, and CI/CD.",
5
5
  "author": "Ingissa <8abnav@gmail.com>",
6
6
  "license": "Commercial",
7
7
  "homepage": "https://navcore-web.vercel.app/",
@@ -26,24 +26,24 @@
26
26
  "off-route",
27
27
  "turn-by-turn"
28
28
  ],
29
- "main": "dist/index.cjs",
29
+ "main": "dist/index.js",
30
30
  "module": "dist/index.mjs",
31
31
  "types": "dist/index.d.ts",
32
32
  "exports": {
33
33
  ".": {
34
34
  "types": "./dist/index.d.ts",
35
35
  "import": "./dist/index.mjs",
36
- "require": "./dist/index.cjs"
36
+ "require": "./dist/index.js"
37
37
  },
38
38
  "./core": {
39
39
  "types": "./dist/core.d.ts",
40
40
  "import": "./dist/core.mjs",
41
- "require": "./dist/core.cjs"
41
+ "require": "./dist/core.js"
42
42
  },
43
43
  "./pro": {
44
44
  "types": "./dist/pro.d.ts",
45
45
  "import": "./dist/pro.mjs",
46
- "require": "./dist/pro.cjs"
46
+ "require": "./dist/pro.js"
47
47
  }
48
48
  },
49
49
  "files": [