vehicle-path2 1.0.2 → 1.0.4

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