vehicle-path2 1.0.2 → 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.
@@ -1,3 +0,0 @@
1
- "use strict";const o=require("react"),O=require("./core.cjs"),q=require("./vehicle-helpers-82D2V4MI.cjs"),te=require("react/jsx-runtime");function F(r){return Array.isArray(r)?{x:r[0],y:r[1]}:r}function z(r){return{id:r.id,start:F(r.start),end:F(r.end)}}function j(r){const i=r.fromIsPercentage!==!1,C=r.toIsPercentage!==!1;return{fromLineId:r.from,toLineId:r.to,fromOffset:r.fromPosition,fromIsPercentage:r.fromPosition!==void 0?i:void 0,toOffset:r.toPosition,toIsPercentage:r.toPosition!==void 0?C:void 0}}function N(r){const i=r.position??0,C=r.isPercentage!==!1;return{vehicleId:r.id,lineId:r.lineId,offset:i,isPercentage:C}}function H(r){const i=r.isPercentage!==!1,C=r.targetPosition??1;return{vehicleId:r.vehicleId,targetLineId:r.targetLineId,targetOffset:C,isPercentage:i,awaitConfirmation:r.wait,payload:r.payload}}function se(r){const i=[],C=new Set;for(const s of r.lines)C.has(s.id)&&i.push(`Duplicate line ID: ${s.id}`),C.add(s.id);if(r.connections)for(const s of r.connections){C.has(s.from)||i.push(`Connection references non-existent line: ${s.from}`),C.has(s.to)||i.push(`Connection references non-existent line: ${s.to}`);const d=s.fromIsPercentage!==!1,t=s.toIsPercentage!==!1;!d&&s.fromPosition===void 0&&i.push("fromPosition is required when fromIsPercentage is false"),!t&&s.toPosition===void 0&&i.push("toPosition is required when toIsPercentage is false"),s.fromPosition!==void 0&&(d&&(s.fromPosition<0||s.fromPosition>1)?i.push(`Invalid fromPosition: ${s.fromPosition} (must be 0-1 for percentage)`):!d&&s.fromPosition<0&&i.push(`Invalid fromPosition: ${s.fromPosition} (must be >= 0 for absolute distance)`)),s.toPosition!==void 0&&(t&&(s.toPosition<0||s.toPosition>1)?i.push(`Invalid toPosition: ${s.toPosition} (must be 0-1 for percentage)`):!t&&s.toPosition<0&&i.push(`Invalid toPosition: ${s.toPosition} (must be >= 0 for absolute distance)`))}return{valid:i.length===0,errors:i}}function J(){const[r,i]=o.useState([]),[C,s]=o.useState([]),[d,t]=o.useState(null),f=o.useCallback((n,P)=>{i(n),s(P),t(null)},[]),w=o.useCallback(n=>{const P=se(n);if(!P.valid)return t(P.errors.join("; ")),{success:!1,errors:P.errors};const c=n.lines.map(z),g=n.connections?.map(j)||[];return f(c,g),{success:!0}},[f]),$=o.useCallback(n=>{if(r.some(c=>c.id===n.id)){const c=`Line with ID '${n.id}' already exists`;return t(c),{success:!1,error:c}}return i(c=>[...c,z(n)]),t(null),{success:!0}},[r]),M=o.useCallback((n,P)=>{if(r.findIndex(g=>g.id===n)===-1){const g=`Line with ID '${n}' not found`;return t(g),{success:!1,error:g}}return i(g=>g.map(b=>b.id!==n?b:{...b,start:P.start?F(P.start):b.start,end:P.end?F(P.end):b.end})),t(null),{success:!0}},[r]),x=o.useCallback(n=>{if(!r.some(c=>c.id===n)){const c=`Line with ID '${n}' not found`;return t(c),{success:!1,error:c}}return i(c=>c.filter(g=>g.id!==n)),s(c=>c.filter(g=>g.fromLineId!==n&&g.toLineId!==n)),t(null),{success:!0}},[r]),L=o.useCallback(n=>{const P=r.some(a=>a.id===n.from),c=r.some(a=>a.id===n.to);if(!P){const a=`Line '${n.from}' not found`;return t(a),{success:!1,error:a}}if(!c){const a=`Line '${n.to}' not found`;return t(a),{success:!1,error:a}}const g=n.fromIsPercentage!==!1,b=n.toIsPercentage!==!1;if(!g&&n.fromPosition===void 0){const a="fromPosition is required when fromIsPercentage is false";return t(a),{success:!1,error:a}}if(!b&&n.toPosition===void 0){const a="toPosition is required when toIsPercentage is false";return t(a),{success:!1,error:a}}if(C.some(a=>a.fromLineId===n.from&&a.toLineId===n.to)){const a=`Connection from '${n.from}' to '${n.to}' already exists`;return t(a),{success:!1,error:a}}return s(a=>[...a,j(n)]),t(null),{success:!0}},[r,C]),m=o.useCallback((n,P,c)=>{const g=C.findIndex(e=>e.fromLineId===n&&e.toLineId===P);if(g===-1){const e=`Connection from '${n}' to '${P}' not found`;return t(e),{success:!1,error:e}}const b=C[g],V=c.fromIsPercentage??b.fromIsPercentage,a=c.toIsPercentage??b.toIsPercentage;let E;c.fromOffset!==void 0?E=c.fromOffset:b.fromOffset!==void 0&&(E=b.fromOffset);let h;if(c.toOffset!==void 0?h=c.toOffset:b.toOffset!==void 0&&(h=b.toOffset),E!==void 0){if(V!==!1&&(E<0||E>1)){const e=`Invalid fromOffset: ${E} (must be 0-1 for percentage)`;return t(e),{success:!1,error:e}}if(V===!1&&E<0){const e=`Invalid fromOffset: ${E} (must be >= 0 for absolute distance)`;return t(e),{success:!1,error:e}}}if(h!==void 0){if(a!==!1&&(h<0||h>1)){const e=`Invalid toOffset: ${h} (must be 0-1 for percentage)`;return t(e),{success:!1,error:e}}if(a===!1&&h<0){const e=`Invalid toOffset: ${h} (must be >= 0 for absolute distance)`;return t(e),{success:!1,error:e}}}if(V===!1&&E===void 0){const e="fromOffset is required when fromIsPercentage is false";return t(e),{success:!1,error:e}}if(a===!1&&h===void 0){const e="toOffset is required when toIsPercentage is false";return t(e),{success:!1,error:e}}const I={from:n,to:P,fromPosition:E,fromIsPercentage:V,toPosition:h,toIsPercentage:a};return s(e=>e.map((u,l)=>l===g?j(I):u)),t(null),{success:!0}},[C]),v=o.useCallback((n,P)=>{if(!C.some(g=>g.fromLineId===n&&g.toLineId===P)){const g=`Connection from '${n}' to '${P}' not found`;return t(g),{success:!1,error:g}}return s(g=>g.filter(b=>!(b.fromLineId===n&&b.toLineId===P))),t(null),{success:!0}},[C]),p=o.useCallback(()=>{i([]),s([]),t(null)},[]);return{lines:r,curves:C,setScene:w,addLine:$,updateLine:M,removeLine:x,addConnection:L,updateConnection:m,removeConnection:v,clear:p,error:d,_loadScene:f}}function B({lines:r,wheelbase:i}){const[C,s]=o.useState([]),[d,t]=o.useState(null),f=o.useRef([]),w=o.useCallback(m=>{f.current=m,s(m),t(null)},[]),$=o.useCallback(m=>{const v=Array.isArray(m)?m:[m],p=[];for(const g of v)f.current.some(V=>V.id===g.id)&&p.push(`Vehicle with ID '${g.id}' already exists`);if(p.length>0)return t(p.join("; ")),{success:!1,errors:p};const n=v.map(N),{vehicles:P,errors:c}=q.validateAndCreateVehicles(n,r,i);return c.length>0?(t(c.join("; ")),{success:!1,errors:c}):(f.current=[...f.current,...P],s(f.current),t(null),{success:!0})},[r,i]),M=o.useCallback((m,v)=>{const p=f.current.findIndex(h=>h.id===m);if(p===-1){const h=`Vehicle with ID '${m}' not found`;return t(h),{success:!1,error:h}}const n=f.current[p];if(n.state!=="idle"){const h=`Cannot update vehicle '${m}' while it is ${n.state}. Vehicle must be idle.`;return t(h),{success:!1,error:h}}const P=v.lineId??n.lineId;if(!r.find(h=>h.id===P)){const h=`Line '${P}' not found`;return t(h),{success:!1,error:h}}let g,b;v.lineId!==void 0&&v.position===void 0?(g=0,b=!0):v.position!==void 0?(g=v.position,b=v.isPercentage??!0):(g=n.offset,b=n.isPercentage);const V={vehicleId:m,lineId:P,offset:g,isPercentage:b},{vehicles:a,errors:E}=q.validateAndCreateVehicles([V],r,i);return E.length>0?(t(E.join("; ")),{success:!1,error:E.join("; ")}):(f.current=f.current.map((h,I)=>I===p?a[0]:h),s(f.current),t(null),{success:!0})},[r,i]),x=o.useCallback(m=>{if(!f.current.some(p=>p.id===m)){const p=`Vehicle with ID '${m}' not found`;return t(p),{success:!1,error:p}}return f.current=f.current.filter(p=>p.id!==m),s(f.current),t(null),{success:!0}},[]),L=o.useCallback(()=>{f.current=[],s([]),t(null)},[]);return{vehicles:C,addVehicles:$,updateVehicle:M,removeVehicle:x,clear:L,error:d,_loadVehicles:w}}function W({vehicles:r,lines:i}){const[C,s]=o.useState(new Map),[d,t]=o.useState(null),f=o.useCallback(M=>{s(M),t(null)},[]),w=o.useCallback((M,x)=>{if(!r.some(c=>c.id===M)){const c=`Vehicle '${M}' not found`;return t(c),{success:!1,error:c}}const m=i.find(c=>c.id===x.targetLineId);if(!m){const c=`Line '${x.targetLineId}' not found`;return t(c),{success:!1,error:c}}const v=x.isPercentage!==!1,p=O.distance(m.start,m.end);if(!v&&x.targetPosition===void 0){const c="targetPosition is required when isPercentage is false";return t(c),{success:!1,error:c}}const n=x.targetPosition??1;if(v){if(n<0||n>1){const c=`Invalid targetPosition: ${n} (must be 0-1 for percentage)`;return t(c),{success:!1,error:c}}}else{if(n<0){const c=`Invalid targetPosition: ${n} (must be >= 0 for absolute distance)`;return t(c),{success:!1,error:c}}if(n>p){const c=`Position ${n} exceeds line length ${p}`;return t(c),{success:!1,error:c}}}const P=H({vehicleId:M,...x});return s(c=>{const g=new Map(c),b=g.get(M)||[];return g.set(M,[...b,P]),g}),t(null),{success:!0}},[r,i]),$=o.useCallback(M=>{if(M!==void 0){if(!r.some(L=>L.id===M)){const L=`Vehicle '${M}' not found`;return t(L),{success:!1,error:L}}s(L=>{const m=new Map(L);return m.delete(M),m})}else s(new Map);return t(null),{success:!0}},[r]);return{vehicleQueues:C,queueMovement:w,clearQueue:$,error:d,_loadQueues:f}}function Z({vehicles:r,lines:i,vehicleQueues:C,wheelbase:s,tangentMode:d,curves:t,eventEmitter:f}){const[w,$]=o.useState([]),M=o.useMemo(()=>({wheelbase:s,tangentMode:d}),[s,d]),x=o.useMemo(()=>new Map(i.map(V=>[V.id,V])),[i]),L=o.useRef(new Map);o.useEffect(()=>{const{movingVehicles:V,stateMap:a}=O.initializeAllVehicles(r,x);L.current=a;const E=setTimeout(()=>{$(V)},0);return()=>clearTimeout(E)},[r,x]);const m=o.useRef(null);o.useEffect(()=>{i.length>0&&(m.current=O.buildGraph(i,t,M))},[i,t,M]);const v=o.useRef(0),p=o.useRef(!1),n=o.useCallback(V=>{if(!p.current)return!1;let a=!1;for(const[,h]of L.current)if(h.vehicle.state==="moving"){a=!0;break}if(!a)return!1;const E=[];for(const[h,I]of L.current){if(I.vehicle.state!=="moving"||!I.execution)continue;const e=I.execution;let u;if(e.front.currentSegmentIndex<e.path.segments.length){const y=e.path.segments[e.front.currentSegmentIndex];if(y.type==="line"){const S=x.get(y.lineId);S&&(u=Math.sqrt(Math.pow(S.end.x-S.start.x,2)+Math.pow(S.end.y-S.start.y,2)))}}const l=O.updateAxlePosition(I.vehicle.rear,e.rear,e.path,V,x,e.curveDataMap),k=O.updateAxlePosition(I.vehicle.front,e.front,e.path,V,x,e.curveDataMap,u);if(I.vehicle={...I.vehicle,rear:l.axleState,front:k.axleState},I.execution.rear=l.execution,I.execution.front=k.execution,l.completed){const y={linesMap:x,config:M,vehicleQueues:C,curves:t,graphRef:m,prepareCommandPath:O.prepareCommandPath,onCommandComplete:Q=>E.push({type:"commandComplete",data:Q}),onCommandStart:Q=>E.push({type:"commandStart",data:Q})},S=O.handleArrival(I,y);I.vehicle=S.vehicle,S.newExecution!==void 0&&(I.execution=S.newExecution),S.vehicle.state!=="moving"&&E.push({type:"stateChange",data:{vehicleId:h,from:"moving",to:S.vehicle.state}});const D=S.vehicle.rear.position,T=S.vehicle.front.position;E.push({type:"positionUpdate",data:{vehicleId:h,rear:D,front:T,center:{x:(D.x+T.x)/2,y:(D.y+T.y)/2},angle:Math.atan2(T.y-D.y,T.x-D.x)}})}}if($(h=>h.map(I=>{const e=L.current.get(I.id);return e?e.vehicle:I})),f&&E.length>0){const h=v.current;setTimeout(()=>{v.current===h&&E.forEach(({type:I,data:e})=>{f.emit(I,e)})},0)}for(const[,h]of L.current)if(h.vehicle.state==="moving")return!0;return!1},[x,t,M,C,f]),P=o.useCallback(()=>{if(p.current)return!0;const V=m.current;if(!V)return!1;const a=[];let E=!1;for(const[h,I]of L.current){const e=I.vehicle,u=C.get(h);if(!u||u.length===0)continue;const l=u[0],k={graph:V,linesMap:x,curves:t,config:M},y=O.prepareCommandPath(e,l,k);if(!y){console.warn(`No path found for vehicle ${h}`);continue}const S=O.calculateFrontAxlePosition(y.path,0,0,s);L.current.set(h,{...I,execution:{path:y.path,curveDataMap:y.curveDataMap,currentCommandIndex:0,rear:{currentSegmentIndex:0,segmentDistance:0},front:S?{currentSegmentIndex:S.segmentIndex,segmentDistance:S.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}},vehicle:{...e,state:"moving"}}),E=!0,e.state!=="moving"&&a.push({id:h,fromState:e.state,command:l,startPosition:{lineId:e.rear.lineId,absoluteOffset:e.rear.absoluteOffset,position:e.rear.position}})}if(!E)return!1;if(p.current=!0,$(h=>h.map(I=>{const e=L.current.get(I.id);return e?e.vehicle:I})),f&&a.length>0){const h=v.current;setTimeout(()=>{v.current===h&&a.forEach(({id:I,fromState:e,command:u,startPosition:l})=>{f.emit("commandStart",{vehicleId:I,command:u,commandIndex:0,startPosition:l}),f.emit("stateChange",{vehicleId:I,from:e,to:"moving"})})},0)}return!0},[x,t,C,M,s,f]),c=o.useCallback(()=>{v.current++,p.current=!1;const{movingVehicles:V,stateMap:a}=O.initializeAllVehicles(r,x);L.current=a,$(V)},[r,x]),g=o.useCallback(V=>{const a=L.current.get(V);if(!a||a.vehicle.state!=="waiting")return!1;const E=C.get(V),h=a.execution;if(!h)return!1;const I=h.currentCommandIndex+1;if(E&&I<E.length){const e=m.current;if(e){const u=E[I],l={graph:e,linesMap:x,curves:t,config:M},k=O.prepareCommandPath(a.vehicle,u,l);if(k){const y=O.calculateFrontAxlePosition(k.path,0,0,s);if(a.execution={path:k.path,curveDataMap:k.curveDataMap,currentCommandIndex:I,rear:{currentSegmentIndex:0,segmentDistance:0},front:y?{currentSegmentIndex:y.segmentIndex,segmentDistance:y.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}},a.vehicle={...a.vehicle,state:"moving"},$(S=>S.map(D=>D.id===V?a.vehicle:D)),f){const S=v.current;setTimeout(()=>{v.current===S&&f.emit("stateChange",{vehicleId:V,from:"waiting",to:"moving"})},0)}return!0}}}if(a.vehicle={...a.vehicle,state:"idle"},a.execution=null,$(e=>e.map(u=>u.id===V?a.vehicle:u)),f){const e=v.current;setTimeout(()=>{v.current===e&&f.emit("stateChange",{vehicleId:V,from:"waiting",to:"idle"})},0)}return!0},[C,x,t,M,s,f]),b=o.useCallback(()=>{for(const[,V]of L.current)if(V.vehicle.state==="moving")return!0;return!1},[]);return{movingVehicles:w,prepare:P,tick:n,reset:c,continueVehicle:g,isMoving:b,isPrepared:p.current}}function re({wheelbase:r,tangentMode:i="proportional-40",eventEmitter:C}){const s=J(),d=B({lines:s.lines,wheelbase:r}),t=W({vehicles:d.vehicles,lines:s.lines,curves:s.curves}),f=Z({vehicles:d.vehicles,lines:s.lines,vehicleQueues:t.vehicleQueues,wheelbase:r,tangentMode:i,curves:s.curves,eventEmitter:C}),w=o.useCallback(e=>d.vehicles.filter(u=>u.lineId===e||u.rear.lineId===e),[d.vehicles]),$=o.useCallback(e=>w(e).length>0,[w]),M=o.useCallback(e=>{const u=s.addLine(e);return u.success?{success:!0}:{success:!1,error:u.error}},[s]),x=o.useCallback((e,u)=>{const l=s.updateLine(e,u);return l.success?{success:!0}:{success:!1,error:l.error}},[s]),L=o.useCallback(e=>{const u=[],l=w(e);l.length>0&&(u.push({type:"vehicle_on_removed_line",message:`${l.length} vehicle(s) are on line '${e}'`,details:{lineId:e,vehicleIds:l.map(S=>S.id)}}),l.forEach(S=>{d.removeVehicle(S.id),t.clearQueue(S.id)}));const k=s.curves.filter(S=>S.fromLineId===e||S.toLineId===e);k.length>0&&u.push({type:"orphaned_connection",message:`${k.length} connection(s) will be removed`,details:{lineId:e,connectionCount:k.length}});const y=s.removeLine(e);return y.success?{success:!0,warnings:u.length>0?u:void 0}:{success:!1,error:y.error}},[s,w,d,t]),m=o.useCallback(()=>{s.clear(),d.clear(),t.clearQueue()},[s,d,t]),v=o.useCallback((e,u,l)=>{const k=s.addConnection({from:e,to:u,fromPosition:l?.fromOffset,fromIsPercentage:l?.fromIsPercentage,toPosition:l?.toOffset,toIsPercentage:l?.toIsPercentage});return k.success?{success:!0}:{success:!1,error:k.error}},[s]),p=o.useCallback((e,u,l)=>{const k=s.updateConnection(e,u,l);return k.success?{success:!0}:{success:!1,error:k.error}},[s]),n=o.useCallback((e,u)=>{const l=s.removeConnection(e,u);return l.success?{success:!0}:{success:!1,error:l.error}},[s]),P=o.useCallback(e=>{const u=d.addVehicles(e);return u.success?{success:!0}:{success:!1,error:u.errors?.join("; ")}},[d]),c=o.useCallback((e,u)=>{const l=d.updateVehicle(e,u);return l.success?{success:!0}:{success:!1,error:l.error}},[d]),g=o.useCallback(e=>{const u=[],l=t.vehicleQueues.get(e);l&&l.length>0&&(u.push({type:"movement_queue_cleared",message:`${l.length} queued movement(s) will be cleared for vehicle '${e}'`,details:{vehicleId:e}}),t.clearQueue(e));const k=d.removeVehicle(e);return k.success?{success:!0,warnings:u.length>0?u:void 0}:{success:!1,error:k.error}},[d,t]),b=o.useCallback(()=>{d.clear(),t.clearQueue()},[d,t]),V=o.useCallback(e=>{const u={targetLineId:e.lineId,targetPosition:e.position??1,isPercentage:e.isPercentage,wait:e.wait,payload:e.payload},l=t.queueMovement(e.id,u);return l.success?{success:!0}:{success:!1,error:l.error}},[t]),a=o.useCallback(e=>{const u=t.clearQueue(e);return u.success?{success:!0}:{success:!1,error:u.error}},[t]),E=o.useCallback(e=>{const u=[],l=[],{scene:k,vehicles:y,movements:S}=q.parseAllDSL(e);k.errors.length>0&&l.push(...k.errors),y.errors.length>0&&l.push(...y.errors),S.errors.length>0&&l.push(...S.errors);const D=k.data.lines.map(z),T=(k.data.connections||[]).map(j),Q=y.data.map(N),{vehicles:A,errors:_}=q.validateAndCreateVehicles(Q,D,r);_.length>0&&l.push(..._);const U=new Map;for(const G of S.data){const Y=U.get(G.vehicleId)||[];Y.push(H(G)),U.set(G.vehicleId,Y)}return s._loadScene(D,T),d._loadVehicles(A),t._loadQueues(U),l.length>0&&u.push({type:"dsl_parse_error",message:`DSL loading had ${l.length} error(s)`,details:{errors:l}}),{success:!0,warnings:u.length>0?u:void 0}},[s,d,t,r]),h=o.useCallback(e=>{const u=[],l=[],k=e.lines.map(z),y=(e.connections||[]).map(j),S=(e.vehicles||[]).map(N),{vehicles:D,errors:T}=q.validateAndCreateVehicles(S,k,r);T.length>0&&l.push(...T);const Q=new Map;for(const A of e.movements||[]){const _=Q.get(A.vehicleId)||[];_.push(H({vehicleId:A.vehicleId,targetLineId:A.targetLineId,targetPosition:A.targetPosition,isPercentage:A.isPercentage,wait:A.wait,payload:A.payload})),Q.set(A.vehicleId,_)}return s._loadScene(k,y),d._loadVehicles(D),t._loadQueues(Q),l.length>0&&u.push({type:"dsl_parse_error",message:`JSON loading had ${l.length} error(s)`,details:{errors:l}}),{success:!0,warnings:u.length>0?u:void 0}},[s,d,t,r]),I=o.useMemo(()=>s.error||d.error||t.error,[s.error,d.error,t.error]);return{lines:s.lines,curves:s.curves,vehicles:d.vehicles,movingVehicles:f.movingVehicles,vehicleQueues:t.vehicleQueues,error:I,addLine:M,updateLine:x,removeLine:L,clearScene:m,connect:v,updateConnection:p,disconnect:n,addVehicles:P,updateVehicle:c,removeVehicle:g,clearVehicles:b,goto:V,clearQueue:a,prepare:f.prepare,tick:f.tick,reset:f.reset,continueVehicle:f.continueVehicle,isMoving:f.isMoving,loadFromDSL:E,loadFromJSON:h,getVehiclesOnLine:w,hasVehiclesOnLine:$}}function R(r){return r.map(i=>({id:i.id,start:i.start,end:i.end}))}function K(r){return r.map(i=>({from:i.fromLineId,to:i.toLineId,fromPosition:i.fromOffset,fromIsPercentage:i.fromIsPercentage,toPosition:i.toOffset,toIsPercentage:i.toIsPercentage}))}function ne(){const[r,i]=o.useState(""),[C,s]=o.useState(null),{lines:d,curves:t,setScene:f}=J(),w=o.useRef(!1),$=o.useRef("");o.useEffect(()=>{$.current=r},[r]),o.useEffect(()=>{if(w.current)return;const m={lines:R(d),connections:t.length>0?K(t):void 0},v=q.generateSceneDSL(m);v!==$.current&&(w.current=!0,i(v),setTimeout(()=>{w.current=!1},50))},[d,t]);const M=o.useCallback(m=>{w.current=!0,i(m);try{const{data:v,errors:p}=q.parseSceneDSL(m);p.length>0&&s(p.join("; "));const n=f(v);!n.success&&n.errors?s(P=>P?`${P}; ${n.errors.join("; ")}`:n.errors.join("; ")):p.length===0&&s(null)}catch(v){s(v instanceof Error?v.message:"Invalid scene definition")}setTimeout(()=>{w.current=!1},50)},[f]),x=o.useCallback(m=>{const v=typeof m=="function"?m(d):m,p=K(t);f({lines:R(v),connections:p.length>0?p:void 0});const n={lines:R(v),connections:p.length>0?p:void 0},P=q.generateSceneDSL(n);w.current=!0,i(P),setTimeout(()=>{w.current=!1},50)},[d,t,f]),L=o.useCallback(m=>{const v=typeof m=="function"?m(t):m,p=K(v);f({lines:R(d),connections:p.length>0?p:void 0});const n={lines:R(d),connections:p.length>0?p:void 0},P=q.generateSceneDSL(n);w.current=!0,i(P),setTimeout(()=>{w.current=!1},50)},[d,t,f]);return{lines:d,curves:t,sceneDefinitionText:r,sceneError:C,isDebouncing:!1,debounceKey:0,setLines:x,setCurves:L,setSceneDefinitionText:M}}function oe({lines:r,wheelbase:i}){const[C,s]=o.useState(""),[d,t]=o.useState(null),{vehicles:f,addVehicles:w,clear:$,error:M}=B({lines:r,wheelbase:i}),x=o.useRef(!1),L=o.useCallback(m=>{x.current=!0,s(m);try{const{data:v,errors:p}=q.parseVehiclesDSL(m),n=[...p];$();for(const P of v){const c=w(P);!c.success&&c.errors&&n.push(...c.errors)}n.length>0?t(n.join(`
2
- `)):t(null)}catch(v){t(v instanceof Error?v.message:"Invalid initial movement")}setTimeout(()=>{x.current=!1},50)},[w,$]);return{vehicles:f,initialMovementText:C,movementError:d||M,isDebouncing:!1,debounceKey:0,setInitialMovementText:L}}function ce({lines:r,vehicles:i}){const[C,s]=o.useState(""),[d,t]=o.useState([]),[f,w]=o.useState(null),{vehicleQueues:$,queueMovement:M,clearQueue:x,error:L}=W({vehicles:i,lines:r}),m=o.useRef(!1),v=o.useCallback(p=>{m.current=!0,s(p);try{const{data:n,errors:P}=q.parseMovementDSL(p),c=[...P];x();for(const g of n){const b=M(g.vehicleId,{targetLineId:g.targetLineId,targetPosition:g.targetPosition,isPercentage:g.isPercentage,wait:g.wait,payload:g.payload});!b.success&&b.error&&c.push(b.error)}t(n),c.length>0?w(c.join(`
3
- `)):w(null)}catch(n){w(n instanceof Error?n.message:"Invalid movement sequence"),t([])}setTimeout(()=>{m.current=!1},50)},[M,x]);return{movementSequenceText:C,gotoCommands:d,vehicleQueues:$,sequenceError:f||L,isDebouncing:!1,debounceKey:0,setMovementSequenceText:v}}const X=o.createContext(null);function ee(){const r=o.useContext(X);if(!r)throw new Error("useVehicleEventEmitter must be used within a VehicleEventProvider");return r}function ie(){return o.useMemo(()=>new q.VehicleEventEmitter,[])}function ae(r,i,C=[]){const s=ee();o.useEffect(()=>s.on(r,i),[s,r,...C])}function ue({children:r}){const i=o.useMemo(()=>new q.VehicleEventEmitter,[]);return te.jsx(X.Provider,{value:i,children:r})}exports.VehicleEventContext=X;exports.VehicleEventProvider=ue;exports.useAnimation=Z;exports.useCreateVehicleEventEmitter=ie;exports.useInitialMovement=oe;exports.useMovementQueue=W;exports.useMovementSequence=ce;exports.useScene=J;exports.useSceneDefinition=ne;exports.useVehicleEvent=ae;exports.useVehicleEventEmitter=ee;exports.useVehicleSimulation=re;exports.useVehicles=B;