vehicle-path2 1.0.14 → 2.0.0

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.
Files changed (40) hide show
  1. package/README.md +168 -168
  2. package/dist/core/algorithms/pathFinding.d.ts +2 -2
  3. package/dist/core/algorithms/vehicleMovement.d.ts +29 -20
  4. package/dist/core/engine.d.ts +160 -0
  5. package/dist/core/index.d.ts +3 -2
  6. package/dist/core/types/api.d.ts +9 -0
  7. package/dist/core/types/movement.d.ts +2 -3
  8. package/dist/core/types/vehicle.d.ts +4 -2
  9. package/dist/core.cjs +1 -1
  10. package/dist/core.js +33 -541
  11. package/dist/index.d.ts +4 -34
  12. package/dist/utils/event-emitter.d.ts +4 -6
  13. package/dist/vehicle-path.cjs +1 -1
  14. package/dist/vehicle-path.js +729 -59
  15. package/package.json +83 -103
  16. package/dist/animation-loop-bZEm2pMN.js +0 -37
  17. package/dist/animation-loop-fC2LjxCd.cjs +0 -1
  18. package/dist/react/dsl-hooks/useInitialMovement.d.ts +0 -24
  19. package/dist/react/dsl-hooks/useMovementSequence.d.ts +0 -27
  20. package/dist/react/dsl-hooks/useSceneDefinition.d.ts +0 -22
  21. package/dist/react/hooks/useAnimation.d.ts +0 -47
  22. package/dist/react/hooks/useMovementQueue.d.ts +0 -53
  23. package/dist/react/hooks/useScene.d.ts +0 -78
  24. package/dist/react/hooks/useVehicleSimulation.d.ts +0 -128
  25. package/dist/react/hooks/useVehicles.d.ts +0 -55
  26. package/dist/react/index.d.ts +0 -48
  27. package/dist/react/providers/useVehicleEvents.d.ts +0 -78
  28. package/dist/react.cjs +0 -1
  29. package/dist/react.js +0 -18
  30. package/dist/useVehicleEvents-BZVmIugl.cjs +0 -3
  31. package/dist/useVehicleEvents-CabztfQ4.js +0 -940
  32. package/dist/utils/animation-loop.d.ts +0 -105
  33. package/dist/utils/dsl-parser.d.ts +0 -151
  34. package/dist/utils/index.d.ts +0 -15
  35. package/dist/utils/type-converters.d.ts +0 -40
  36. package/dist/utils/vehicle-helpers.d.ts +0 -8
  37. package/dist/utils.cjs +0 -1
  38. package/dist/utils.js +0 -17
  39. package/dist/vehicle-helpers-BgD4BTAJ.js +0 -275
  40. package/dist/vehicle-helpers-DrnYWjm3.cjs +0 -7
@@ -1,940 +0,0 @@
1
- import { useState as _, useCallback as p, useRef as A, useMemo as G, useEffect as K, createContext as ae, useContext as le } from "react";
2
- import { distance as fe, initializeAllVehicles as te, buildGraph as de, updateAxlePosition as re, handleArrival as me, prepareCommandPath as B, calculateFrontAxlePosition as se, initializeMovingVehicle as ge, createInitialMovementState as he } from "./core.js";
3
- import { v as N, p as ve, a as W, f as pe, h as Pe, e as Ie, V as ne } from "./vehicle-helpers-BgD4BTAJ.js";
4
- import { jsx as xe } from "react/jsx-runtime";
5
- function J(t) {
6
- return Array.isArray(t) ? { x: t[0], y: t[1] } : t;
7
- }
8
- function H(t) {
9
- return {
10
- id: t.id,
11
- start: J(t.start),
12
- end: J(t.end)
13
- };
14
- }
15
- function U(t) {
16
- const o = t.fromIsPercentage !== !1, V = t.toIsPercentage !== !1;
17
- return {
18
- fromLineId: t.from,
19
- toLineId: t.to,
20
- // No conversion needed - internal format is now 0-1 (same as API)
21
- fromOffset: t.fromPosition,
22
- fromIsPercentage: t.fromPosition !== void 0 ? o : void 0,
23
- toOffset: t.toPosition,
24
- toIsPercentage: t.toPosition !== void 0 ? V : void 0
25
- };
26
- }
27
- function Y(t) {
28
- const o = t.position ?? 0, V = t.isPercentage !== !1;
29
- return {
30
- vehicleId: t.id,
31
- lineId: t.lineId,
32
- // No conversion needed - internal format is now 0-1 (same as API)
33
- offset: o,
34
- isPercentage: V
35
- };
36
- }
37
- function Z(t) {
38
- const o = t.isPercentage !== !1, V = t.targetPosition ?? 1;
39
- return {
40
- vehicleId: t.vehicleId,
41
- targetLineId: t.targetLineId,
42
- // No conversion needed - internal format is now 0-1 (same as API)
43
- targetOffset: V,
44
- isPercentage: o,
45
- payload: t.payload
46
- };
47
- }
48
- function Me(t) {
49
- const o = [], V = /* @__PURE__ */ new Set();
50
- for (const r of t.lines)
51
- V.has(r.id) && o.push(`Duplicate line ID: ${r.id}`), V.add(r.id);
52
- if (t.connections)
53
- for (const r of t.connections) {
54
- V.has(r.from) || o.push(`Connection references non-existent line: ${r.from}`), V.has(r.to) || o.push(`Connection references non-existent line: ${r.to}`);
55
- const m = r.fromIsPercentage !== !1, e = r.toIsPercentage !== !1;
56
- !m && r.fromPosition === void 0 && o.push("fromPosition is required when fromIsPercentage is false"), !e && r.toPosition === void 0 && o.push("toPosition is required when toIsPercentage is false"), r.fromPosition !== void 0 && (m && (r.fromPosition < 0 || r.fromPosition > 1) ? o.push(`Invalid fromPosition: ${r.fromPosition} (must be 0-1 for percentage)`) : !m && r.fromPosition < 0 && o.push(`Invalid fromPosition: ${r.fromPosition} (must be >= 0 for absolute distance)`)), r.toPosition !== void 0 && (e && (r.toPosition < 0 || r.toPosition > 1) ? o.push(`Invalid toPosition: ${r.toPosition} (must be 0-1 for percentage)`) : !e && r.toPosition < 0 && o.push(`Invalid toPosition: ${r.toPosition} (must be >= 0 for absolute distance)`));
57
- }
58
- return { valid: o.length === 0, errors: o };
59
- }
60
- function oe() {
61
- const [t, o] = _([]), [V, r] = _([]), [m, e] = _(null), f = p((s, v) => {
62
- o(s), r(v), e(null);
63
- }, []), M = p((s) => {
64
- const v = Me(s);
65
- if (!v.valid)
66
- return e(v.errors.join("; ")), { success: !1, errors: v.errors };
67
- const u = s.lines.map(H), h = s.connections?.map(U) || [];
68
- return f(u, h), { success: !0 };
69
- }, [f]), O = p((s) => {
70
- if (t.some((u) => u.id === s.id)) {
71
- const u = `Line with ID '${s.id}' already exists`;
72
- return e(u), { success: !1, error: u };
73
- }
74
- return o((u) => [...u, H(s)]), e(null), { success: !0 };
75
- }, [t]), T = p((s, v) => {
76
- if (t.findIndex((h) => h.id === s) === -1) {
77
- const h = `Line with ID '${s}' not found`;
78
- return e(h), { success: !1, error: h };
79
- }
80
- return o((h) => h.map((L) => L.id !== s ? L : {
81
- ...L,
82
- start: v.start ? J(v.start) : L.start,
83
- end: v.end ? J(v.end) : L.end
84
- })), e(null), { success: !0 };
85
- }, [t]), y = p((s) => {
86
- if (!t.some((u) => u.id === s)) {
87
- const u = `Line with ID '${s}' not found`;
88
- return e(u), { success: !1, error: u };
89
- }
90
- return o((u) => u.filter((h) => h.id !== s)), r((u) => u.filter((h) => h.fromLineId !== s && h.toLineId !== s)), e(null), { success: !0 };
91
- }, [t]), C = p((s) => {
92
- const v = t.some((d) => d.id === s.from), u = t.some((d) => d.id === s.to);
93
- if (!v) {
94
- const d = `Line '${s.from}' not found`;
95
- return e(d), { success: !1, error: d };
96
- }
97
- if (!u) {
98
- const d = `Line '${s.to}' not found`;
99
- return e(d), { success: !1, error: d };
100
- }
101
- const h = s.fromIsPercentage !== !1, L = s.toIsPercentage !== !1;
102
- if (!h && s.fromPosition === void 0) {
103
- const d = "fromPosition is required when fromIsPercentage is false";
104
- return e(d), { success: !1, error: d };
105
- }
106
- if (!L && s.toPosition === void 0) {
107
- const d = "toPosition is required when toIsPercentage is false";
108
- return e(d), { success: !1, error: d };
109
- }
110
- if (V.some((d) => d.fromLineId === s.from && d.toLineId === s.to)) {
111
- const d = `Connection from '${s.from}' to '${s.to}' already exists`;
112
- return e(d), { success: !1, error: d };
113
- }
114
- return r((d) => [...d, U(s)]), e(null), { success: !0 };
115
- }, [t, V]), P = p((s, v, u) => {
116
- const h = V.findIndex((l) => l.fromLineId === s && l.toLineId === v);
117
- if (h === -1) {
118
- const l = `Connection from '${s}' to '${v}' not found`;
119
- return e(l), { success: !1, error: l };
120
- }
121
- const L = V[h], Q = u.fromIsPercentage ?? L.fromIsPercentage, d = u.toIsPercentage ?? L.toIsPercentage;
122
- let D;
123
- u.fromOffset !== void 0 ? D = u.fromOffset : L.fromOffset !== void 0 && (D = L.fromOffset);
124
- let w;
125
- if (u.toOffset !== void 0 ? w = u.toOffset : L.toOffset !== void 0 && (w = L.toOffset), D !== void 0) {
126
- if (Q !== !1 && (D < 0 || D > 1)) {
127
- const l = `Invalid fromOffset: ${D} (must be 0-1 for percentage)`;
128
- return e(l), { success: !1, error: l };
129
- }
130
- if (Q === !1 && D < 0) {
131
- const l = `Invalid fromOffset: ${D} (must be >= 0 for absolute distance)`;
132
- return e(l), { success: !1, error: l };
133
- }
134
- }
135
- if (w !== void 0) {
136
- if (d !== !1 && (w < 0 || w > 1)) {
137
- const l = `Invalid toOffset: ${w} (must be 0-1 for percentage)`;
138
- return e(l), { success: !1, error: l };
139
- }
140
- if (d === !1 && w < 0) {
141
- const l = `Invalid toOffset: ${w} (must be >= 0 for absolute distance)`;
142
- return e(l), { success: !1, error: l };
143
- }
144
- }
145
- if (Q === !1 && D === void 0) {
146
- const l = "fromOffset is required when fromIsPercentage is false";
147
- return e(l), { success: !1, error: l };
148
- }
149
- if (d === !1 && w === void 0) {
150
- const l = "toOffset is required when toIsPercentage is false";
151
- return e(l), { success: !1, error: l };
152
- }
153
- const k = {
154
- from: s,
155
- to: v,
156
- fromPosition: D,
157
- fromIsPercentage: Q,
158
- toPosition: w,
159
- toIsPercentage: d
160
- };
161
- return r((l) => l.map(
162
- (n, i) => i === h ? U(k) : n
163
- )), e(null), { success: !0 };
164
- }, [V]), I = p((s, v) => {
165
- if (!V.some((h) => h.fromLineId === s && h.toLineId === v)) {
166
- const h = `Connection from '${s}' to '${v}' not found`;
167
- return e(h), { success: !1, error: h };
168
- }
169
- return r((h) => h.filter((L) => !(L.fromLineId === s && L.toLineId === v))), e(null), { success: !0 };
170
- }, [V]), c = p(() => {
171
- o([]), r([]), e(null);
172
- }, []);
173
- return {
174
- lines: t,
175
- curves: V,
176
- setScene: M,
177
- addLine: O,
178
- updateLine: T,
179
- removeLine: y,
180
- addConnection: C,
181
- updateConnection: P,
182
- removeConnection: I,
183
- clear: c,
184
- error: m,
185
- _loadScene: f
186
- };
187
- }
188
- function ce({ lines: t, wheelbase: o }) {
189
- const [V, r] = _([]), [m, e] = _(null), f = A([]), M = p((P) => {
190
- f.current = P, r(P), e(null);
191
- }, []), O = p((P) => {
192
- const I = Array.isArray(P) ? P : [P], c = [];
193
- for (const h of I)
194
- f.current.some((Q) => Q.id === h.id) && c.push(`Vehicle with ID '${h.id}' already exists`);
195
- if (c.length > 0)
196
- return e(c.join("; ")), { success: !1, errors: c };
197
- const s = I.map(Y), { vehicles: v, errors: u } = N(
198
- s,
199
- t,
200
- o
201
- );
202
- return u.length > 0 ? (e(u.join("; ")), { success: !1, errors: u }) : (f.current = [...f.current, ...v], r(f.current), e(null), { success: !0 });
203
- }, [t, o]), T = p((P, I) => {
204
- const c = f.current.findIndex((w) => w.id === P);
205
- if (c === -1) {
206
- const w = `Vehicle with ID '${P}' not found`;
207
- return e(w), { success: !1, error: w };
208
- }
209
- const s = f.current[c];
210
- if (s.state !== "idle") {
211
- const w = `Cannot update vehicle '${P}' while it is ${s.state}. Vehicle must be idle.`;
212
- return e(w), { success: !1, error: w };
213
- }
214
- const v = I.lineId ?? s.lineId;
215
- if (!t.find((w) => w.id === v)) {
216
- const w = `Line '${v}' not found`;
217
- return e(w), { success: !1, error: w };
218
- }
219
- let h, L;
220
- I.lineId !== void 0 && I.position === void 0 ? (h = 0, L = !0) : I.position !== void 0 ? (h = I.position, L = I.isPercentage ?? !0) : (h = s.offset, L = s.isPercentage);
221
- const Q = {
222
- vehicleId: P,
223
- lineId: v,
224
- offset: h,
225
- isPercentage: L
226
- }, { vehicles: d, errors: D } = N(
227
- [Q],
228
- t,
229
- o
230
- );
231
- return D.length > 0 ? (e(D.join("; ")), { success: !1, error: D.join("; ") }) : (f.current = f.current.map(
232
- (w, k) => k === c ? d[0] : w
233
- ), r(f.current), e(null), { success: !0 });
234
- }, [t, o]), y = p((P) => {
235
- if (!f.current.some((c) => c.id === P)) {
236
- const c = `Vehicle with ID '${P}' not found`;
237
- return e(c), { success: !1, error: c };
238
- }
239
- return f.current = f.current.filter((c) => c.id !== P), r(f.current), e(null), { success: !0 };
240
- }, []), C = p(() => {
241
- f.current = [], r([]), e(null);
242
- }, []);
243
- return {
244
- vehicles: V,
245
- addVehicles: O,
246
- updateVehicle: T,
247
- removeVehicle: y,
248
- clear: C,
249
- error: m,
250
- _loadVehicles: M
251
- };
252
- }
253
- function ie({ vehicles: t, lines: o }) {
254
- const [V, r] = _(/* @__PURE__ */ new Map()), [m, e] = _(null), f = A(/* @__PURE__ */ new Map()), M = p(() => f.current, []), O = p((C) => {
255
- f.current = C, r(C), e(null);
256
- }, []), T = p((C, P) => {
257
- if (!t.some((d) => d.id === C)) {
258
- const d = `Vehicle '${C}' not found`;
259
- return e(d), { success: !1, error: d };
260
- }
261
- const c = o.find((d) => d.id === P.targetLineId);
262
- if (!c) {
263
- const d = `Line '${P.targetLineId}' not found`;
264
- return e(d), { success: !1, error: d };
265
- }
266
- const s = P.isPercentage !== !1, v = fe(c.start, c.end);
267
- if (!s && P.targetPosition === void 0) {
268
- const d = "targetPosition is required when isPercentage is false";
269
- return e(d), { success: !1, error: d };
270
- }
271
- const u = P.targetPosition ?? 1;
272
- if (s) {
273
- if (u < 0 || u > 1) {
274
- const d = `Invalid targetPosition: ${u} (must be 0-1 for percentage)`;
275
- return e(d), { success: !1, error: d };
276
- }
277
- } else {
278
- if (u < 0) {
279
- const d = `Invalid targetPosition: ${u} (must be >= 0 for absolute distance)`;
280
- return e(d), { success: !1, error: d };
281
- }
282
- if (u > v) {
283
- const d = `Position ${u} exceeds line length ${v}`;
284
- return e(d), { success: !1, error: d };
285
- }
286
- }
287
- const h = Z({ vehicleId: C, ...P }), L = new Map(f.current), Q = L.get(C) || [];
288
- return L.set(C, [...Q, h]), f.current = L, r(L), e(null), { success: !0 };
289
- }, [t, o]), y = p((C) => {
290
- if (C !== void 0) {
291
- if (!t.some((c) => c.id === C)) {
292
- const c = `Vehicle '${C}' not found`;
293
- return e(c), { success: !1, error: c };
294
- }
295
- const I = new Map(f.current);
296
- I.delete(C), f.current = I, r(I);
297
- } else
298
- f.current = /* @__PURE__ */ new Map(), r(/* @__PURE__ */ new Map());
299
- return e(null), { success: !0 };
300
- }, [t]);
301
- return {
302
- vehicleQueues: V,
303
- getVehicleQueues: M,
304
- queueMovement: T,
305
- clearQueue: y,
306
- error: m,
307
- _loadQueues: O
308
- };
309
- }
310
- function Ve({
311
- vehicles: t,
312
- lines: o,
313
- vehicleQueues: V,
314
- getVehicleQueues: r,
315
- wheelbase: m,
316
- tangentMode: e,
317
- curves: f,
318
- eventEmitter: M
319
- }) {
320
- const [O, T] = _([]), y = A([]), C = p((l) => {
321
- typeof l == "function" ? T((n) => {
322
- const i = l(n);
323
- return y.current = i, i;
324
- }) : (y.current = l, T(l));
325
- }, []), P = p(() => y.current, []), I = G(() => ({
326
- wheelbase: m,
327
- tangentMode: e
328
- }), [m, e]), c = G(
329
- () => new Map(o.map((l) => [l.id, l])),
330
- [o]
331
- ), s = A(/* @__PURE__ */ new Map());
332
- K(() => {
333
- const { movingVehicles: l, stateMap: n } = te(t, c);
334
- s.current = n;
335
- const i = setTimeout(() => {
336
- C(l);
337
- }, 0);
338
- return () => clearTimeout(i);
339
- }, [t, c]);
340
- const v = A(null);
341
- K(() => {
342
- o.length > 0 && (v.current = de(o, f, I));
343
- }, [o, f, I]);
344
- const u = A(0), h = A(!1), L = p((l) => {
345
- if (!h.current) return !1;
346
- let n = !1;
347
- for (const [, a] of s.current)
348
- if (a.vehicle.state === "moving") {
349
- n = !0;
350
- break;
351
- }
352
- if (!n)
353
- return !1;
354
- const i = [];
355
- for (const [a, g] of s.current) {
356
- if (g.vehicle.state !== "moving" || !g.execution) continue;
357
- const x = g.execution;
358
- let S;
359
- if (x.front.currentSegmentIndex < x.path.segments.length) {
360
- const j = x.path.segments[x.front.currentSegmentIndex];
361
- if (j.type === "line") {
362
- const $ = c.get(j.lineId);
363
- $ && (S = Math.sqrt(
364
- Math.pow($.end.x - $.start.x, 2) + Math.pow($.end.y - $.start.y, 2)
365
- ));
366
- }
367
- }
368
- const b = re(
369
- g.vehicle.rear,
370
- x.rear,
371
- x.path,
372
- l,
373
- c,
374
- x.curveDataMap
375
- ), q = re(
376
- g.vehicle.front,
377
- x.front,
378
- x.path,
379
- l,
380
- c,
381
- x.curveDataMap,
382
- S
383
- );
384
- if (g.vehicle = {
385
- ...g.vehicle,
386
- rear: b.axleState,
387
- front: q.axleState
388
- }, g.execution.rear = b.execution, g.execution.front = q.execution, b.completed) {
389
- const $ = me(g, {
390
- linesMap: c,
391
- config: I,
392
- vehicleQueues: V,
393
- curves: f,
394
- graphRef: v,
395
- prepareCommandPath: B,
396
- onCommandComplete: (F) => i.push({ type: "commandComplete", data: F }),
397
- onCommandStart: (F) => i.push({ type: "commandStart", data: F })
398
- });
399
- g.vehicle = $.vehicle, $.newExecution !== void 0 && (g.execution = $.newExecution), $.vehicle.state !== "moving" && i.push({
400
- type: "stateChange",
401
- data: { vehicleId: a, from: "moving", to: $.vehicle.state }
402
- });
403
- const E = $.vehicle.rear.position, R = $.vehicle.front.position;
404
- i.push({
405
- type: "positionUpdate",
406
- data: {
407
- vehicleId: a,
408
- rear: E,
409
- front: R,
410
- center: { x: (E.x + R.x) / 2, y: (E.y + R.y) / 2 },
411
- angle: Math.atan2(R.y - E.y, R.x - E.x)
412
- }
413
- });
414
- }
415
- }
416
- if (C((a) => a.map((g) => {
417
- const x = s.current.get(g.id);
418
- return x ? x.vehicle : g;
419
- })), M && i.length > 0) {
420
- const a = u.current;
421
- setTimeout(() => {
422
- u.current === a && i.forEach(({ type: g, data: x }) => {
423
- M.emit(g, x);
424
- });
425
- }, 0);
426
- }
427
- for (const [, a] of s.current)
428
- if (a.vehicle.state === "moving")
429
- return !0;
430
- return h.current = !1, !1;
431
- }, [c, f, I, V, M]), Q = p(() => {
432
- const l = v.current;
433
- if (!l) return !1;
434
- const n = r ? r() : V, i = [];
435
- let a = !1;
436
- for (const [g, x] of s.current) {
437
- const S = x.vehicle;
438
- if (S.state === "moving") continue;
439
- const b = n.get(g);
440
- if (!b || b.length === 0) continue;
441
- const q = b[0], $ = B(S, q, { graph: l, linesMap: c, curves: f, config: I });
442
- if (!$) {
443
- console.warn(`No path found for vehicle ${g}`);
444
- continue;
445
- }
446
- const E = se($.path, 0, 0, m);
447
- s.current.set(g, {
448
- ...x,
449
- execution: {
450
- path: $.path,
451
- curveDataMap: $.curveDataMap,
452
- currentCommandIndex: 0,
453
- rear: { currentSegmentIndex: 0, segmentDistance: 0 },
454
- front: E ? { currentSegmentIndex: E.segmentIndex, segmentDistance: E.segmentDistance } : { currentSegmentIndex: 0, segmentDistance: 0 }
455
- },
456
- vehicle: { ...S, state: "moving" }
457
- }), a = !0, i.push({
458
- id: g,
459
- fromState: S.state,
460
- command: q,
461
- startPosition: {
462
- lineId: S.rear.lineId,
463
- absoluteOffset: S.rear.absoluteOffset,
464
- position: S.rear.position
465
- }
466
- });
467
- }
468
- if (!a) return !1;
469
- if (h.current = !0, C((g) => g.map((x) => {
470
- const S = s.current.get(x.id);
471
- return S ? S.vehicle : x;
472
- })), M && i.length > 0) {
473
- const g = u.current;
474
- setTimeout(() => {
475
- u.current === g && i.forEach(({ id: x, fromState: S, command: b, startPosition: q }) => {
476
- M.emit("commandStart", {
477
- vehicleId: x,
478
- command: b,
479
- commandIndex: 0,
480
- startPosition: q
481
- }), M.emit("stateChange", {
482
- vehicleId: x,
483
- from: S,
484
- to: "moving"
485
- });
486
- });
487
- }, 0);
488
- }
489
- return !0;
490
- }, [c, f, V, r, I, m, M]), d = p(() => {
491
- u.current++, h.current = !1;
492
- const { movingVehicles: l, stateMap: n } = te(t, c);
493
- s.current = n, C(l);
494
- }, [t, c]), D = p((l) => {
495
- const n = t.find((x) => x.id === l);
496
- if (!n || !c.get(n.lineId)) return;
497
- const a = ge(n), g = he(a);
498
- s.current.set(l, g), C((x) => x.map(
499
- (S) => S.id === l ? a : S
500
- ));
501
- }, [t, c]), w = p((l) => {
502
- const n = s.current.get(l);
503
- if (!n || n.vehicle.state !== "waiting")
504
- return !1;
505
- const i = V.get(l), a = n.execution;
506
- if (!a) return !1;
507
- const g = a.currentCommandIndex + 1;
508
- if (i && g < i.length) {
509
- const x = v.current;
510
- if (x) {
511
- const S = i[g], b = { graph: x, linesMap: c, curves: f, config: I }, q = B(n.vehicle, S, b);
512
- if (q) {
513
- const j = se(q.path, 0, 0, m);
514
- if (n.execution = {
515
- path: q.path,
516
- curveDataMap: q.curveDataMap,
517
- currentCommandIndex: g,
518
- rear: { currentSegmentIndex: 0, segmentDistance: 0 },
519
- front: j ? { currentSegmentIndex: j.segmentIndex, segmentDistance: j.segmentDistance } : { currentSegmentIndex: 0, segmentDistance: 0 }
520
- }, n.vehicle = { ...n.vehicle, state: "moving" }, C(($) => $.map((E) => E.id === l ? n.vehicle : E)), M) {
521
- const $ = u.current;
522
- setTimeout(() => {
523
- u.current === $ && M.emit("stateChange", {
524
- vehicleId: l,
525
- from: "waiting",
526
- to: "moving"
527
- });
528
- }, 0);
529
- }
530
- return !0;
531
- }
532
- }
533
- }
534
- if (n.vehicle = { ...n.vehicle, state: "idle" }, n.execution = null, C((x) => x.map((S) => S.id === l ? n.vehicle : S)), M) {
535
- const x = u.current;
536
- setTimeout(() => {
537
- u.current === x && M.emit("stateChange", {
538
- vehicleId: l,
539
- from: "waiting",
540
- to: "idle"
541
- });
542
- }, 0);
543
- }
544
- return !0;
545
- }, [V, c, f, I, m, M]), k = p(() => {
546
- for (const [, l] of s.current)
547
- if (l.vehicle.state === "moving")
548
- return !0;
549
- return !1;
550
- }, []);
551
- return {
552
- movingVehicles: O,
553
- getMovingVehicles: P,
554
- prepare: Q,
555
- tick: L,
556
- reset: d,
557
- resetVehicle: D,
558
- continueVehicle: w,
559
- isMoving: k,
560
- isPrepared: h.current
561
- };
562
- }
563
- function ye({
564
- wheelbase: t,
565
- tangentMode: o = "proportional-40",
566
- eventEmitter: V
567
- }) {
568
- const r = oe(), m = ce({ lines: r.lines, wheelbase: t }), e = ie({
569
- vehicles: m.vehicles,
570
- lines: r.lines,
571
- curves: r.curves
572
- }), f = Ve({
573
- vehicles: m.vehicles,
574
- lines: r.lines,
575
- vehicleQueues: e.vehicleQueues,
576
- getVehicleQueues: e.getVehicleQueues,
577
- wheelbase: t,
578
- tangentMode: o,
579
- curves: r.curves,
580
- eventEmitter: V
581
- }), M = p((n) => m.vehicles.filter((i) => i.lineId === n || i.rear.lineId === n), [m.vehicles]), O = p((n) => M(n).length > 0, [M]), T = p((n) => {
582
- const i = r.addLine(n);
583
- return i.success ? { success: !0 } : { success: !1, error: i.error };
584
- }, [r]), y = p((n, i) => {
585
- const a = r.updateLine(n, i);
586
- return a.success ? { success: !0 } : { success: !1, error: a.error };
587
- }, [r]), C = p((n) => {
588
- const i = [], a = M(n);
589
- a.length > 0 && (i.push({
590
- type: "vehicle_on_removed_line",
591
- message: `${a.length} vehicle(s) are on line '${n}'`,
592
- details: {
593
- lineId: n,
594
- vehicleIds: a.map((S) => S.id)
595
- }
596
- }), a.forEach((S) => {
597
- m.removeVehicle(S.id), e.clearQueue(S.id);
598
- }));
599
- const g = r.curves.filter(
600
- (S) => S.fromLineId === n || S.toLineId === n
601
- );
602
- g.length > 0 && i.push({
603
- type: "orphaned_connection",
604
- message: `${g.length} connection(s) will be removed`,
605
- details: {
606
- lineId: n,
607
- connectionCount: g.length
608
- }
609
- });
610
- const x = r.removeLine(n);
611
- return x.success ? {
612
- success: !0,
613
- warnings: i.length > 0 ? i : void 0
614
- } : { success: !1, error: x.error };
615
- }, [r, M, m, e]), P = p(() => {
616
- r.clear(), m.clear(), e.clearQueue();
617
- }, [r, m, e]), I = p((n, i, a) => {
618
- const g = r.addConnection({
619
- from: n,
620
- to: i,
621
- fromPosition: a?.fromOffset,
622
- fromIsPercentage: a?.fromIsPercentage,
623
- toPosition: a?.toOffset,
624
- toIsPercentage: a?.toIsPercentage
625
- });
626
- return g.success ? { success: !0 } : { success: !1, error: g.error };
627
- }, [r]), c = p((n, i, a) => {
628
- const g = r.updateConnection(n, i, a);
629
- return g.success ? { success: !0 } : { success: !1, error: g.error };
630
- }, [r]), s = p((n, i) => {
631
- const a = r.removeConnection(n, i);
632
- return a.success ? { success: !0 } : { success: !1, error: a.error };
633
- }, [r]), v = p((n) => {
634
- const i = m.addVehicles(n);
635
- return i.success ? { success: !0 } : { success: !1, error: i.errors?.join("; ") };
636
- }, [m]), u = p((n, i) => {
637
- const a = m.updateVehicle(n, i);
638
- return a.success ? { success: !0 } : { success: !1, error: a.error };
639
- }, [m]), h = p((n) => {
640
- const i = [], a = e.vehicleQueues.get(n);
641
- a && a.length > 0 && (i.push({
642
- type: "movement_queue_cleared",
643
- message: `${a.length} queued movement(s) will be cleared for vehicle '${n}'`,
644
- details: {
645
- vehicleId: n
646
- }
647
- }), e.clearQueue(n));
648
- const g = m.removeVehicle(n);
649
- return g.success ? {
650
- success: !0,
651
- warnings: i.length > 0 ? i : void 0
652
- } : { success: !1, error: g.error };
653
- }, [m, e]), L = p(() => {
654
- m.clear(), e.clearQueue();
655
- }, [m, e]), Q = p((n) => {
656
- const i = {
657
- targetLineId: n.lineId,
658
- targetPosition: n.position ?? 1,
659
- isPercentage: n.isPercentage,
660
- payload: n.payload
661
- }, a = e.queueMovement(n.id, i);
662
- return a.success ? { success: !0 } : { success: !1, error: a.error };
663
- }, [e]), d = p((n) => {
664
- const i = e.clearQueue(n);
665
- return i.success ? { success: !0 } : { success: !1, error: i.error };
666
- }, [e]), D = p((n) => {
667
- e.clearQueue(n), f.resetVehicle(n);
668
- }, [e, f]), w = p((n) => {
669
- const i = [], a = [], { scene: g, vehicles: x, movements: S } = ve(n);
670
- g.errors.length > 0 && a.push(...g.errors), x.errors.length > 0 && a.push(...x.errors), S.errors.length > 0 && a.push(...S.errors);
671
- const b = g.data.lines.map(H), q = (g.data.connections || []).map(U), j = x.data.map(Y), { vehicles: $, errors: E } = N(j, b, t);
672
- E.length > 0 && a.push(...E);
673
- const R = /* @__PURE__ */ new Map();
674
- for (const F of S.data) {
675
- const ee = R.get(F.vehicleId) || [];
676
- ee.push(Z(F)), R.set(F.vehicleId, ee);
677
- }
678
- return r._loadScene(b, q), m._loadVehicles($), e._loadQueues(R), a.length > 0 && i.push({
679
- type: "dsl_parse_error",
680
- message: `DSL loading had ${a.length} error(s)`,
681
- details: { errors: a }
682
- }), {
683
- success: !0,
684
- warnings: i.length > 0 ? i : void 0
685
- };
686
- }, [r, m, e, t]), k = p((n) => {
687
- const i = [], a = [], g = n.lines.map(H), x = (n.connections || []).map(U), S = (n.vehicles || []).map(Y), { vehicles: b, errors: q } = N(S, g, t);
688
- q.length > 0 && a.push(...q);
689
- const j = /* @__PURE__ */ new Map();
690
- for (const $ of n.movements || []) {
691
- const E = j.get($.vehicleId) || [];
692
- E.push(Z({
693
- vehicleId: $.vehicleId,
694
- targetLineId: $.targetLineId,
695
- targetPosition: $.targetPosition,
696
- isPercentage: $.isPercentage,
697
- payload: $.payload
698
- })), j.set($.vehicleId, E);
699
- }
700
- return r._loadScene(g, x), m._loadVehicles(b), e._loadQueues(j), a.length > 0 && i.push({
701
- type: "dsl_parse_error",
702
- message: `JSON loading had ${a.length} error(s)`,
703
- details: { errors: a }
704
- }), {
705
- success: !0,
706
- warnings: i.length > 0 ? i : void 0
707
- };
708
- }, [r, m, e, t]), l = G(() => r.error || m.error || e.error, [r.error, m.error, e.error]);
709
- return {
710
- // State
711
- lines: r.lines,
712
- curves: r.curves,
713
- vehicles: m.vehicles,
714
- movingVehicles: f.movingVehicles,
715
- getMovingVehicles: f.getMovingVehicles,
716
- vehicleQueues: e.vehicleQueues,
717
- error: l,
718
- // Scene operations
719
- addLine: T,
720
- updateLine: y,
721
- removeLine: C,
722
- clearScene: P,
723
- // Connection operations
724
- connect: I,
725
- updateConnection: c,
726
- disconnect: s,
727
- // Vehicle operations
728
- addVehicles: v,
729
- updateVehicle: u,
730
- removeVehicle: h,
731
- clearVehicles: L,
732
- // Movement operations
733
- goto: Q,
734
- clearQueue: d,
735
- // Animation (delegated to useVehicleMovement)
736
- prepare: f.prepare,
737
- tick: f.tick,
738
- reset: f.reset,
739
- resetVehicle: D,
740
- // Uses wrapper that also clears queue
741
- continueVehicle: f.continueVehicle,
742
- isMoving: f.isMoving,
743
- // DSL Loading
744
- loadFromDSL: w,
745
- // JSON Loading
746
- loadFromJSON: k,
747
- // Utility
748
- getVehiclesOnLine: M,
749
- hasVehiclesOnLine: O
750
- };
751
- }
752
- function z(t) {
753
- return t.map((o) => ({
754
- id: o.id,
755
- start: o.start,
756
- end: o.end
757
- }));
758
- }
759
- function X(t) {
760
- return t.map((o) => ({
761
- from: o.fromLineId,
762
- to: o.toLineId,
763
- // No conversion needed - internal format is now 0-1 (same as API)
764
- fromPosition: o.fromOffset,
765
- fromIsPercentage: o.fromIsPercentage,
766
- toPosition: o.toOffset,
767
- toIsPercentage: o.toIsPercentage
768
- }));
769
- }
770
- function Ee() {
771
- const [t, o] = _(""), [V, r] = _(null), { lines: m, curves: e, setScene: f } = oe(), M = A(!1), O = A("");
772
- K(() => {
773
- O.current = t;
774
- }, [t]), K(() => {
775
- if (M.current)
776
- return;
777
- const P = {
778
- lines: z(m),
779
- connections: e.length > 0 ? X(e) : void 0
780
- }, I = W(P);
781
- I !== O.current && (M.current = !0, o(I), setTimeout(() => {
782
- M.current = !1;
783
- }, 50));
784
- }, [m, e]);
785
- const T = p((P) => {
786
- M.current = !0, o(P);
787
- try {
788
- const { data: I, errors: c } = pe(P);
789
- c.length > 0 && r(c.join("; "));
790
- const s = f(I);
791
- !s.success && s.errors ? r((v) => v ? `${v}; ${s.errors.join("; ")}` : s.errors.join("; ")) : c.length === 0 && r(null);
792
- } catch (I) {
793
- r(I instanceof Error ? I.message : "Invalid scene definition");
794
- }
795
- setTimeout(() => {
796
- M.current = !1;
797
- }, 50);
798
- }, [f]), y = p((P) => {
799
- const I = typeof P == "function" ? P(m) : P, c = X(e);
800
- f({
801
- lines: z(I),
802
- connections: c.length > 0 ? c : void 0
803
- });
804
- const s = {
805
- lines: z(I),
806
- connections: c.length > 0 ? c : void 0
807
- }, v = W(s);
808
- M.current = !0, o(v), setTimeout(() => {
809
- M.current = !1;
810
- }, 50);
811
- }, [m, e, f]), C = p((P) => {
812
- const I = typeof P == "function" ? P(e) : P, c = X(I);
813
- f({
814
- lines: z(m),
815
- connections: c.length > 0 ? c : void 0
816
- });
817
- const s = {
818
- lines: z(m),
819
- connections: c.length > 0 ? c : void 0
820
- }, v = W(s);
821
- M.current = !0, o(v), setTimeout(() => {
822
- M.current = !1;
823
- }, 50);
824
- }, [m, e, f]);
825
- return {
826
- lines: m,
827
- curves: e,
828
- sceneDefinitionText: t,
829
- sceneError: V,
830
- isDebouncing: !1,
831
- // No debouncing - parsing is immediate
832
- debounceKey: 0,
833
- // Kept for API compatibility
834
- setLines: y,
835
- setCurves: C,
836
- setSceneDefinitionText: T
837
- };
838
- }
839
- function De({ lines: t, wheelbase: o }) {
840
- const [V, r] = _(""), [m, e] = _(null), { vehicles: f, addVehicles: M, clear: O, error: T } = ce({ lines: t, wheelbase: o }), y = A(!1), C = p((P) => {
841
- y.current = !0, r(P);
842
- try {
843
- const { data: I, errors: c } = Pe(P), s = [...c];
844
- O();
845
- for (const v of I) {
846
- const u = M(v);
847
- !u.success && u.errors && s.push(...u.errors);
848
- }
849
- s.length > 0 ? e(s.join(`
850
- `)) : e(null);
851
- } catch (I) {
852
- e(I instanceof Error ? I.message : "Invalid initial movement");
853
- }
854
- setTimeout(() => {
855
- y.current = !1;
856
- }, 50);
857
- }, [M, O]);
858
- return {
859
- vehicles: f,
860
- initialMovementText: V,
861
- movementError: m || T,
862
- isDebouncing: !1,
863
- // No debouncing - parsing is immediate
864
- debounceKey: 0,
865
- // Kept for API compatibility
866
- setInitialMovementText: C
867
- };
868
- }
869
- function Oe({ lines: t, vehicles: o }) {
870
- const [V, r] = _(""), [m, e] = _([]), [f, M] = _(null), { vehicleQueues: O, queueMovement: T, clearQueue: y, error: C } = ie({
871
- vehicles: o,
872
- lines: t
873
- }), P = A(!1), I = p((c) => {
874
- P.current = !0, r(c);
875
- try {
876
- const { data: s, errors: v } = Ie(c), u = [...v];
877
- y();
878
- for (const h of s) {
879
- const L = T(h.vehicleId, {
880
- targetLineId: h.targetLineId,
881
- targetPosition: h.targetPosition,
882
- isPercentage: h.isPercentage,
883
- payload: h.payload
884
- });
885
- !L.success && L.error && u.push(L.error);
886
- }
887
- e(s), u.length > 0 ? M(u.join(`
888
- `)) : M(null);
889
- } catch (s) {
890
- M(s instanceof Error ? s.message : "Invalid movement sequence"), e([]);
891
- }
892
- setTimeout(() => {
893
- P.current = !1;
894
- }, 50);
895
- }, [T, y]);
896
- return {
897
- movementSequenceText: V,
898
- gotoCommands: m,
899
- vehicleQueues: O,
900
- sequenceError: f || C,
901
- isDebouncing: !1,
902
- // No debouncing - parsing is immediate
903
- debounceKey: 0,
904
- // Kept for API compatibility
905
- setMovementSequenceText: I
906
- };
907
- }
908
- const ue = ae(null);
909
- function Se() {
910
- const t = le(ue);
911
- if (!t)
912
- throw new Error("useVehicleEventEmitter must be used within a VehicleEventProvider");
913
- return t;
914
- }
915
- function Te() {
916
- return G(() => new ne(), []);
917
- }
918
- function qe(t, o, V = []) {
919
- const r = Se();
920
- K(() => r.on(t, o), [r, t, ...V]);
921
- }
922
- function be({ children: t }) {
923
- const o = G(() => new ne(), []);
924
- return /* @__PURE__ */ xe(ue.Provider, { value: o, children: t });
925
- }
926
- export {
927
- ue as V,
928
- be as a,
929
- Te as b,
930
- De as c,
931
- ie as d,
932
- Oe as e,
933
- oe as f,
934
- Ee as g,
935
- qe as h,
936
- Se as i,
937
- ye as j,
938
- ce as k,
939
- Ve as u
940
- };