vehicle-path2 1.0.1 → 1.0.3
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/README.md +9 -0
- package/dist/core.cjs +1 -1
- package/dist/core.js +7 -6
- package/dist/react/hooks/useAnimation.d.ts +3 -1
- package/dist/react/hooks/useMovementQueue.d.ts +2 -0
- package/dist/react.cjs +1 -1
- package/dist/react.js +1 -1
- package/dist/useVehicleEvents-GQ7zeGg6.cjs +3 -0
- package/dist/useVehicleEvents-Lf_yySwI.js +924 -0
- package/dist/utils/type-converters.d.ts +3 -0
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +1 -1
- package/dist/{vehicle-helpers-DIcksrtO.cjs → vehicle-helpers-82D2V4MI.cjs} +1 -1
- package/dist/{vehicle-helpers-_72KxCqO.js → vehicle-helpers-BXX3GPzk.js} +3 -3
- package/dist/vehicle-path.cjs +1 -1
- package/dist/vehicle-path.js +2 -2
- package/package.json +1 -1
- package/dist/useVehicleEvents-B2JQFNjc.js +0 -923
- package/dist/useVehicleEvents-CBymulau.cjs +0 -3
package/README.md
CHANGED
|
@@ -35,6 +35,15 @@ function App() {
|
|
|
35
35
|
|
|
36
36
|
## API
|
|
37
37
|
|
|
38
|
+
### Format Posisi
|
|
39
|
+
|
|
40
|
+
Semua nilai posisi menggunakan format **0-1** untuk persentase:
|
|
41
|
+
- `0` = 0% (awal line)
|
|
42
|
+
- `0.5` = 50% (tengah line)
|
|
43
|
+
- `1` = 100% (ujung line)
|
|
44
|
+
|
|
45
|
+
Untuk posisi absolut (dalam satuan koordinat), gunakan `isPercentage: false`.
|
|
46
|
+
|
|
38
47
|
### Setup
|
|
39
48
|
|
|
40
49
|
```ts
|
package/dist/core.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function p(e,t){const s=t.x-e.x,n=t.y-e.y;return Math.sqrt(s*s+n*n)}function P(e,t){const s=t.x-e.x,n=t.y-e.y,o=Math.sqrt(s*s+n*n);return o===0?{x:0,y:0}:{x:s/o,y:n/o}}function V(e,t){return t*(e==="proportional-40"?.4:.5522)}function C(e,t,s,n=!1,o){const{wheelbase:c,tangentMode:r}=s;let i;o?.fromOffset!==void 0?i=D(e,o.fromOffset,o.fromIsPercentage??!1):i=e.end;let l;o?.toOffset!==void 0?l=D(t,o.toOffset,o.toIsPercentage??!1):l=t.start;const d=P(e.start,e.end),f=n?{x:i.x-d.x*c,y:i.y-d.y*c}:i,u=P(e.start,e.end),g=P(t.start,t.end),I=p(f,l),v=V(r,I),a=n?{x:f.x-u.x*v,y:f.y-u.y*v}:{x:f.x+u.x*v,y:f.y+u.y*v},m={x:l.x-g.x*v,y:l.y-g.y*v};return{p0:f,p1:a,p2:m,p3:l}}function B(e,t){return{x:e.start.x+(e.end.x-e.start.x)*t,y:e.start.y+(e.end.y-e.start.y)*t}}function D(e,t,s){const n=p(e.start,e.end);let o;return s?o=t
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function p(e,t){const s=t.x-e.x,n=t.y-e.y;return Math.sqrt(s*s+n*n)}function P(e,t){const s=t.x-e.x,n=t.y-e.y,o=Math.sqrt(s*s+n*n);return o===0?{x:0,y:0}:{x:s/o,y:n/o}}function V(e,t){return t*(e==="proportional-40"?.4:.5522)}function C(e,t,s,n=!1,o){const{wheelbase:c,tangentMode:r}=s;let i;o?.fromOffset!==void 0?i=D(e,o.fromOffset,o.fromIsPercentage??!1):i=e.end;let l;o?.toOffset!==void 0?l=D(t,o.toOffset,o.toIsPercentage??!1):l=t.start;const d=P(e.start,e.end),f=n?{x:i.x-d.x*c,y:i.y-d.y*c}:i,u=P(e.start,e.end),g=P(t.start,t.end),I=p(f,l),v=V(r,I),a=n?{x:f.x-u.x*v,y:f.y-u.y*v}:{x:f.x+u.x*v,y:f.y+u.y*v},m={x:l.x-g.x*v,y:l.y-g.y*v};return{p0:f,p1:a,p2:m,p3:l}}function B(e,t){return{x:e.start.x+(e.end.x-e.start.x)*t,y:e.start.y+(e.end.y-e.start.y)*t}}function D(e,t,s){const n=p(e.start,e.end);let o;return s?o=t:o=n>0?t/n:0,o=Math.max(0,Math.min(1,o)),B(e,o)}function w(e,t){const{p0:s,p1:n,p2:o,p3:c}=e,r=1-t,i=r*r,l=i*r,d=t*t,f=d*t;return{x:l*s.x+3*i*t*n.x+3*r*d*o.x+f*c.x,y:l*s.y+3*i*t*n.y+3*r*d*o.y+f*c.y}}function H(e,t,s=10){return p(e,t)<=s}function q(e,t=100){const s=[{t:0,distance:0}];let n=e.p0,o=0;for(let c=1;c<=t;c++){const r=c/t,i=w(e,r);o+=p(n,i),s.push({t:r,distance:o}),n=i}return s}function F(e,t){if(t<=0)return 0;const s=e[e.length-1].distance;if(t>=s)return 1;let n=0,o=e.length-1;for(;n<o-1;){const f=Math.floor((n+o)/2);e[f].distance<t?n=f:o=f}const c=e[n].distance,r=e[o].distance,i=e[n].t,l=e[o].t;if(r===c)return i;const d=(t-c)/(r-c);return i+d*(l-i)}function J(e){return e[e.length-1].distance}function j(e,t=100){let s=0,n=e.p0;for(let o=1;o<=t;o++){const c=o/t,r=w(e,c);s+=p(n,r),n=r}return s}function S(e,t,s,n,o){const c=p(e.start,e.end),r=c-o;if(r<=0)return c;let i;if(t===void 0)i=n;else if(s)i=t;else return Math.max(o,Math.min(t,c));return o+i*r}function T(e,t,s,n,o){const r=p(e.start,e.end)-o;if(r<=0)return 0;let i;if(t===void 0)i=n;else if(s)i=t;else return Math.max(0,Math.min(t,r));return i*r}function U(e,t,s){const n=new Map,o=new Map,c=new Map;for(const r of e)o.set(r.id,r),c.set(r.id,p(r.start,r.end)),n.set(r.id,[]);for(let r=0;r<t.length;r++){const i=t[r],l=o.get(i.fromLineId),d=o.get(i.toLineId);if(!l||!d)continue;const f=S(l,i.fromOffset,i.fromIsPercentage,1,s.wheelbase),u=T(d,i.toOffset,i.toIsPercentage,0,s.wheelbase),g=C(l,d,s,!1,{fromOffset:f,fromIsPercentage:!1,toOffset:u,toIsPercentage:!1}),I=j(g),v={curveIndex:r,fromLineId:i.fromLineId,toLineId:i.toLineId,fromOffset:f,toOffset:u,curveLength:I};n.get(i.fromLineId).push(v)}return{adjacency:n,lines:o,lineLengths:c}}function K(e,t,s,n,o=!1){const{adjacency:c,lines:r,lineLengths:i}=e;if(!r.get(s))return null;const d=i.get(s),f=o?n/100*d:n,u=[],g=new Map,I=(a,m)=>`${a}:${Math.round(m)}`;if(t.lineId===s&&f>=t.offset){const a=f-t.offset;return{segments:[{type:"line",lineId:t.lineId,startOffset:t.offset,endOffset:f,length:a}],totalDistance:a}}const v=c.get(t.lineId)||[];for(const a of v){if(a.fromOffset<t.offset)continue;const m=a.fromOffset-t.offset,L=m+a.curveLength,x={type:"line",lineId:t.lineId,startOffset:t.offset,endOffset:a.fromOffset,length:m},h={type:"curve",curveIndex:a.curveIndex,startOffset:0,endOffset:a.curveLength,length:a.curveLength};u.push({lineId:a.toLineId,entryOffset:a.toOffset,totalDistance:L,path:[x,h]})}for(u.sort((a,m)=>a.totalDistance-m.totalDistance);u.length>0;){const a=u.shift(),m=I(a.lineId,a.entryOffset),L=g.get(m);if(L!==void 0&&L<=a.totalDistance)continue;if(g.set(m,a.totalDistance),a.lineId===s){const h=Math.abs(f-a.entryOffset);if(f>=a.entryOffset){const y={type:"line",lineId:s,startOffset:a.entryOffset,endOffset:f,length:h};return{segments:[...a.path,y],totalDistance:a.totalDistance+h}}}const x=c.get(a.lineId)||[];for(const h of x){if(h.fromOffset<a.entryOffset)continue;const y=h.fromOffset-a.entryOffset,A=a.totalDistance+y+h.curveLength,W=I(h.toLineId,h.toOffset),z=g.get(W);if(z!==void 0&&z<=A)continue;const _={type:"line",lineId:a.lineId,startOffset:a.entryOffset,endOffset:h.fromOffset,length:y},E={type:"curve",curveIndex:h.curveIndex,startOffset:0,endOffset:h.curveLength,length:h.curveLength};u.push({lineId:h.toLineId,entryOffset:h.toOffset,totalDistance:A,path:[...a.path,_,E]})}u.sort((h,y)=>h.totalDistance-y.totalDistance)}return null}function b(e,t){const s=Math.sqrt(Math.pow(e.end.x-e.start.x,2)+Math.pow(e.end.y-e.start.y,2)),n=s>0?t/s:0;return{x:e.start.x+(e.end.x-e.start.x)*Math.min(1,Math.max(0,n)),y:e.start.y+(e.end.y-e.start.y)*Math.min(1,Math.max(0,n))}}function G(e){return Math.sqrt(Math.pow(e.end.x-e.start.x,2)+Math.pow(e.end.y-e.start.y,2))}function N(e,t,s){let n=0;for(let o=0;o<t;o++)n+=e.segments[o].length;return n+=s,n}function $(e,t){let s=0;for(let n=0;n<e.segments.length;n++){const o=e.segments[n],c=s+o.length;if(t<c)return{segmentIndex:n,segmentDistance:t-s};if(t===c)return n+1<e.segments.length?{segmentIndex:n+1,segmentDistance:0}:{segmentIndex:n,segmentDistance:o.length};s+=o.length}return null}function k(e,t,s,n){const c=N(e,t,s)+n;return $(e,c)}function X(e,t,s,n){const o=Math.sqrt(Math.pow(n.end.x-n.start.x,2)+Math.pow(n.end.y-n.start.y,2));let c=t+s;c=Math.min(c,o);const r=b(n,c);return{lineId:e,position:r,absoluteOffset:c}}function Q(e,t){return{...e,state:"idle"}}function R(e){return{vehicle:e,execution:null}}function Y(e,t){const s=[],n=new Map;for(const o of e){if(!t.get(o.lineId))continue;const r=Q(o);s.push(r);const i=R(r);n.set(o.id,i)}return{movingVehicles:s,stateMap:n}}function O(e,t){return{position:b(e,t),lineId:e.id,absoluteOffset:t}}function M(e,t){const s=F(e.arcLengthTable,t);return{position:w(e.bezier,s)}}function Z(e,t,s,n,o,c,r){const i=s.segments[t.currentSegmentIndex],l=t.segmentDistance+n;if(l>=i.length){const f=l-i.length,u=t.currentSegmentIndex+1;if(u>=s.segments.length){if(r!==void 0&&i.type==="line"){const a=o.get(i.lineId),m=i.startOffset+l;if(m<=r){const x=O(a,m);return{axleState:{...e,...x},execution:{...t,segmentDistance:l},completed:!1}}const L=O(a,r);return{axleState:{...e,...L},execution:{...t,segmentDistance:r-i.startOffset},completed:!0}}const v=i.type==="line"?O(o.get(i.lineId),i.endOffset):M(c.get(i.curveIndex),i.length);return{axleState:{...e,...v},execution:{...t,segmentDistance:i.length},completed:!0}}const g=s.segments[u],I=g.type==="line"?O(o.get(g.lineId),g.startOffset+f):M(c.get(g.curveIndex),f);return{axleState:{...e,...I},execution:{currentSegmentIndex:u,segmentDistance:f},completed:!1}}const d=i.type==="line"?O(o.get(i.lineId),i.startOffset+l):M(c.get(i.curveIndex),l);return{axleState:{...e,...d},execution:{...t,segmentDistance:l},completed:!1}}function ee(e,t,s,n){const o=new Map;for(const c of e.segments)if(c.type==="curve"&&c.curveIndex!==void 0){const r=t[c.curveIndex];if(r){const i=s.get(r.fromLineId),l=s.get(r.toLineId);if(i&&l){const d=S(i,r.fromOffset,r.fromIsPercentage,1,n.wheelbase),f=T(l,r.toOffset,r.toIsPercentage,0,n.wheelbase),u=C(i,l,n,!1,{fromOffset:d,fromIsPercentage:!1,toOffset:f,toIsPercentage:!1}),g=q(u);o.set(c.curveIndex,{bezier:u,arcLengthTable:g})}}}return o}function te(e,t,s){const{graph:n,linesMap:o,curves:c,config:r}=s,i=o.get(t.targetLineId);if(!i)return null;const d=G(i)-r.wheelbase;if(d<=0)return null;const f=t.isPercentage?t.targetOffset*d:Math.min(t.targetOffset,d),u=K(n,{lineId:e.rear.lineId,offset:e.rear.absoluteOffset},t.targetLineId,f,!1);if(!u)return null;const g=ee(u,c,o,r);return{path:u,curveDataMap:g}}function ne(e,t){const s=e.execution,n=t.vehicleQueues.get(e.vehicle.id),o=n?.[s.currentCommandIndex];if(o&&t.onCommandComplete&&t.onCommandComplete({vehicleId:e.vehicle.id,command:o,finalPosition:{lineId:e.vehicle.rear.lineId,absoluteOffset:e.vehicle.rear.absoluteOffset,position:e.vehicle.rear.position},payload:o.payload}),o?.awaitConfirmation)return{handled:!0,vehicle:{...e.vehicle,state:"waiting"},newExecution:s,isWaiting:!0};const c=s.currentCommandIndex+1;if(n&&c<n.length){const i=n[c],l=t.graphRef.current;if(l){const d={graph:l,linesMap:t.linesMap,curves:t.curves,config:t.config},f=t.prepareCommandPath(e.vehicle,i,d);if(f){const u=k(f.path,0,0,t.config.wheelbase);t.onCommandStart&&t.onCommandStart({vehicleId:e.vehicle.id,command:i,commandIndex:c,startPosition:{lineId:e.vehicle.rear.lineId,absoluteOffset:e.vehicle.rear.absoluteOffset,position:e.vehicle.rear.position}});const g={path:f.path,curveDataMap:f.curveDataMap,currentCommandIndex:c,rear:{currentSegmentIndex:0,segmentDistance:0},front:u?{currentSegmentIndex:u.segmentIndex,segmentDistance:u.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}};return{handled:!0,vehicle:{...e.vehicle,state:"moving"},newExecution:g}}}}return{handled:!0,vehicle:{...e.vehicle,state:"idle"},newExecution:null}}exports.arcLengthToSegmentPosition=$;exports.buildArcLengthTable=q;exports.buildGraph=U;exports.calculateBezierArcLength=j;exports.calculateFrontAxlePosition=k;exports.calculateInitialFrontPosition=X;exports.calculatePositionOnCurve=M;exports.calculatePositionOnLine=O;exports.calculateTangentLength=V;exports.createBezierCurve=C;exports.createInitialMovementState=R;exports.distance=p;exports.distanceToT=F;exports.findPath=K;exports.getArcLength=J;exports.getCumulativeArcLength=N;exports.getLineLength=G;exports.getPointOnBezier=w;exports.getPointOnLine=B;exports.getPointOnLineByOffset=D;exports.getPositionFromOffset=b;exports.handleArrival=ne;exports.initializeAllVehicles=Y;exports.initializeMovingVehicle=Q;exports.isPointNearPoint=H;exports.normalize=P;exports.prepareCommandPath=te;exports.resolveFromLineOffset=S;exports.resolveToLineOffset=T;exports.updateAxlePosition=Z;
|
package/dist/core.js
CHANGED
|
@@ -34,7 +34,7 @@ function K(e, t) {
|
|
|
34
34
|
function S(e, t, o) {
|
|
35
35
|
const n = v(e.start, e.end);
|
|
36
36
|
let s;
|
|
37
|
-
return o ? s = t
|
|
37
|
+
return o ? s = t : s = n > 0 ? t / n : 0, s = Math.max(0, Math.min(1, s)), K(e, s);
|
|
38
38
|
}
|
|
39
39
|
function D(e, t) {
|
|
40
40
|
const { p0: o, p1: n, p2: s, p3: c } = e, i = 1 - t, r = i * i, l = r * i, d = t * t, a = d * t;
|
|
@@ -91,7 +91,7 @@ function b(e, t, o, n, s) {
|
|
|
91
91
|
r = t;
|
|
92
92
|
else
|
|
93
93
|
return Math.max(s, Math.min(t, c));
|
|
94
|
-
return s + r
|
|
94
|
+
return s + r * i;
|
|
95
95
|
}
|
|
96
96
|
function A(e, t, o, n, s) {
|
|
97
97
|
const i = v(e.start, e.end) - s;
|
|
@@ -104,7 +104,7 @@ function A(e, t, o, n, s) {
|
|
|
104
104
|
r = t;
|
|
105
105
|
else
|
|
106
106
|
return Math.max(0, Math.min(t, i));
|
|
107
|
-
return r
|
|
107
|
+
return r * i;
|
|
108
108
|
}
|
|
109
109
|
function X(e, t, o) {
|
|
110
110
|
const n = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map();
|
|
@@ -113,7 +113,7 @@ function X(e, t, o) {
|
|
|
113
113
|
for (let i = 0; i < t.length; i++) {
|
|
114
114
|
const r = t[i], l = s.get(r.fromLineId), d = s.get(r.toLineId);
|
|
115
115
|
if (!l || !d) continue;
|
|
116
|
-
const a = b(l, r.fromOffset, r.fromIsPercentage,
|
|
116
|
+
const a = b(l, r.fromOffset, r.fromIsPercentage, 1, o.wheelbase), u = A(d, r.toOffset, r.toIsPercentage, 0, o.wheelbase), g = T(
|
|
117
117
|
l,
|
|
118
118
|
d,
|
|
119
119
|
o,
|
|
@@ -397,7 +397,8 @@ function H(e, t, o, n) {
|
|
|
397
397
|
r,
|
|
398
398
|
i.fromOffset,
|
|
399
399
|
i.fromIsPercentage,
|
|
400
|
-
|
|
400
|
+
1,
|
|
401
|
+
// Default: 100% = 1.0
|
|
401
402
|
n.wheelbase
|
|
402
403
|
), a = A(
|
|
403
404
|
l,
|
|
@@ -431,7 +432,7 @@ function te(e, t, o) {
|
|
|
431
432
|
if (!r) return null;
|
|
432
433
|
const d = N(r) - i.wheelbase;
|
|
433
434
|
if (d <= 0) return null;
|
|
434
|
-
const a = t.isPercentage ? t.targetOffset
|
|
435
|
+
const a = t.isPercentage ? t.targetOffset * d : Math.min(t.targetOffset, d), u = G(
|
|
435
436
|
n,
|
|
436
437
|
{ lineId: e.rear.lineId, offset: e.rear.absoluteOffset },
|
|
437
438
|
t.targetLineId,
|
|
@@ -6,6 +6,8 @@ export interface UseAnimationProps {
|
|
|
6
6
|
vehicles: Vehicle[];
|
|
7
7
|
lines: Line[];
|
|
8
8
|
vehicleQueues: Map<string, GotoCommand[]>;
|
|
9
|
+
/** Get current queues immediately (bypasses React state timing) */
|
|
10
|
+
getVehicleQueues?: () => Map<string, GotoCommand[]>;
|
|
9
11
|
wheelbase: number;
|
|
10
12
|
tangentMode: TangentMode;
|
|
11
13
|
curves: import('../../core/types/geometry').Curve[];
|
|
@@ -32,7 +34,7 @@ export interface UseAnimationProps {
|
|
|
32
34
|
* }
|
|
33
35
|
* ```
|
|
34
36
|
*/
|
|
35
|
-
export declare function useAnimation({ vehicles, lines, vehicleQueues, wheelbase, tangentMode, curves, eventEmitter }: UseAnimationProps): {
|
|
37
|
+
export declare function useAnimation({ vehicles, lines, vehicleQueues, getVehicleQueues, wheelbase, tangentMode, curves, eventEmitter }: UseAnimationProps): {
|
|
36
38
|
movingVehicles: Vehicle[];
|
|
37
39
|
prepare: () => boolean;
|
|
38
40
|
tick: (distance: number) => boolean;
|
|
@@ -9,6 +9,8 @@ export interface UseMovementQueueProps {
|
|
|
9
9
|
export interface UseMovementQueueResult {
|
|
10
10
|
/** Queue of commands per vehicle */
|
|
11
11
|
vehicleQueues: Map<string, GotoCommand[]>;
|
|
12
|
+
/** Get current queues immediately (bypasses React state timing) */
|
|
13
|
+
getVehicleQueues: () => Map<string, GotoCommand[]>;
|
|
12
14
|
/** Queue a movement command for a vehicle */
|
|
13
15
|
queueMovement: (vehicleId: string, input: GotoCommandInput) => {
|
|
14
16
|
success: boolean;
|
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-GQ7zeGg6.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-Lf_yySwI.js";
|
|
2
2
|
export {
|
|
3
3
|
t as VehicleEventContext,
|
|
4
4
|
i as VehicleEventProvider,
|
|
@@ -0,0 +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(`
|
|
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
|
+
`)):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;
|