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