vehicle-path2 1.0.0 → 1.0.2

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