vehicle-path2 1.0.7 → 1.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/react.cjs +1 -1
- package/dist/react.js +1 -1
- package/dist/useVehicleEvents-B7Z-9Hn2.cjs +3 -0
- package/dist/useVehicleEvents-t_p-Bwhj.js +944 -0
- package/dist/utils.cjs +1 -1
- package/dist/utils.js +1 -1
- package/dist/{vehicle-helpers-BXX3GPzk.js → vehicle-helpers-BYb2Ibex.js} +76 -76
- package/dist/{vehicle-helpers-82D2V4MI.cjs → vehicle-helpers-bgHGBdo9.cjs} +5 -5
- package/dist/vehicle-path.cjs +1 -1
- package/dist/vehicle-path.js +2 -2
- package/package.json +1 -1
- package/dist/useVehicleEvents-CCCiLoAw.cjs +0 -3
- package/dist/useVehicleEvents-DcNmJGRn.js +0 -941
package/dist/utils.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./vehicle-helpers-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./vehicle-helpers-bgHGBdo9.cjs"),t=require("./animation-loop-fC2LjxCd.cjs");exports.VehicleEventEmitter=e.VehicleEventEmitter;exports.generateMovementDSL=e.generateMovementDSL;exports.generateSceneDSL=e.generateSceneDSL;exports.generateVehiclesDSL=e.generateVehiclesDSL;exports.getNextGotoVehicleId=e.getNextGotoVehicleId;exports.getNextStartVehicleId=e.getNextStartVehicleId;exports.parseAllDSL=e.parseAllDSL;exports.parseMovementDSL=e.parseMovementDSL;exports.parseSceneDSL=e.parseSceneDSL;exports.parseVehiclesDSL=e.parseVehiclesDSL;exports.validateAndCreateVehicles=e.validateAndCreateVehicles;exports.createAnimationLoop=t.createAnimationLoop;exports.useAnimationLoop=t.useAnimationLoop;
|
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { V as t, g as s, a as r, b as o, c as n, d as i, p as c, e as S, f as l, h as p, v as L } from "./vehicle-helpers-
|
|
1
|
+
import { V as t, g as s, a as r, b as o, c as n, d as i, p as c, e as S, f as l, h as p, v as L } from "./vehicle-helpers-BYb2Ibex.js";
|
|
2
2
|
import { c as m, u as D } from "./animation-loop-bZEm2pMN.js";
|
|
3
3
|
export {
|
|
4
4
|
t as VehicleEventEmitter,
|
|
@@ -7,9 +7,9 @@ class S {
|
|
|
7
7
|
* @param callback - Function to call when event is emitted
|
|
8
8
|
* @returns Unsubscribe function
|
|
9
9
|
*/
|
|
10
|
-
on(
|
|
11
|
-
return this.listeners.has(
|
|
12
|
-
this.listeners.get(
|
|
10
|
+
on(e, t) {
|
|
11
|
+
return this.listeners.has(e) || this.listeners.set(e, /* @__PURE__ */ new Set()), this.listeners.get(e).add(t), () => {
|
|
12
|
+
this.listeners.get(e)?.delete(t);
|
|
13
13
|
};
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
@@ -17,12 +17,12 @@ class S {
|
|
|
17
17
|
* @param event - The event type to emit
|
|
18
18
|
* @param data - The event data
|
|
19
19
|
*/
|
|
20
|
-
emit(
|
|
21
|
-
this.listeners.get(
|
|
20
|
+
emit(e, t) {
|
|
21
|
+
this.listeners.get(e)?.forEach((s) => {
|
|
22
22
|
try {
|
|
23
|
-
s(
|
|
23
|
+
s(t);
|
|
24
24
|
} catch (o) {
|
|
25
|
-
console.error(`Error in event listener for "${
|
|
25
|
+
console.error(`Error in event listener for "${e}":`, o);
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
}
|
|
@@ -30,29 +30,29 @@ class S {
|
|
|
30
30
|
* Remove all listeners for a specific event, or all events if no event specified
|
|
31
31
|
* @param event - Optional event type to clear listeners for
|
|
32
32
|
*/
|
|
33
|
-
off(
|
|
34
|
-
|
|
33
|
+
off(e) {
|
|
34
|
+
e ? this.listeners.delete(e) : this.listeners.clear();
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Get the number of listeners for a specific event
|
|
38
38
|
* @param event - The event type
|
|
39
39
|
* @returns Number of listeners
|
|
40
40
|
*/
|
|
41
|
-
listenerCount(
|
|
42
|
-
return this.listeners.get(
|
|
41
|
+
listenerCount(e) {
|
|
42
|
+
return this.listeners.get(e)?.size ?? 0;
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
45
|
function P(i) {
|
|
46
|
-
const
|
|
46
|
+
const e = [], t = [], s = [], o = i.trim().split(`
|
|
47
47
|
`);
|
|
48
|
-
let
|
|
48
|
+
let d = 0;
|
|
49
49
|
for (const n of o) {
|
|
50
|
-
|
|
50
|
+
d++;
|
|
51
51
|
const r = n.trim();
|
|
52
52
|
if (!r || r.startsWith("#")) continue;
|
|
53
53
|
const a = r.match(/^(\w+)\s*:\s*\((-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\)\s*->\s*\((-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\)/);
|
|
54
54
|
if (a) {
|
|
55
|
-
|
|
55
|
+
e.push({
|
|
56
56
|
id: a[1],
|
|
57
57
|
start: [parseFloat(a[2]), parseFloat(a[3])],
|
|
58
58
|
end: [parseFloat(a[4]), parseFloat(a[5])]
|
|
@@ -66,38 +66,38 @@ function P(i) {
|
|
|
66
66
|
to: c[4]
|
|
67
67
|
};
|
|
68
68
|
if (c[2]) {
|
|
69
|
-
const f = parseFloat(c[2]);
|
|
70
|
-
l.fromPosition =
|
|
69
|
+
const f = parseFloat(c[2]), h = c[3] === "%";
|
|
70
|
+
l.fromPosition = h ? f / 100 : f, l.fromIsPercentage = h;
|
|
71
71
|
}
|
|
72
72
|
if (c[5]) {
|
|
73
|
-
const f = parseFloat(c[5]);
|
|
74
|
-
l.toPosition =
|
|
73
|
+
const f = parseFloat(c[5]), h = c[6] === "%";
|
|
74
|
+
l.toPosition = h ? f / 100 : f, l.toIsPercentage = h;
|
|
75
75
|
}
|
|
76
|
-
|
|
76
|
+
t.push(l);
|
|
77
77
|
continue;
|
|
78
78
|
}
|
|
79
|
-
r.match(/^\w+\s+start\s+/) || r.match(/^\w+\s+goto\s+/) || s.push(`Line ${
|
|
79
|
+
r.match(/^\w+\s+start\s+/) || r.match(/^\w+\s+goto\s+/) || s.push(`Line ${d}: Unable to parse "${r}"`);
|
|
80
80
|
}
|
|
81
81
|
return {
|
|
82
82
|
data: {
|
|
83
|
-
lines:
|
|
84
|
-
connections:
|
|
83
|
+
lines: e,
|
|
84
|
+
connections: t.length > 0 ? t : void 0
|
|
85
85
|
},
|
|
86
86
|
errors: s
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
function v(i) {
|
|
90
|
-
const
|
|
90
|
+
const e = [], t = [], s = i.trim().split(`
|
|
91
91
|
`);
|
|
92
92
|
let o = 0;
|
|
93
|
-
for (const
|
|
93
|
+
for (const d of s) {
|
|
94
94
|
o++;
|
|
95
|
-
const n =
|
|
95
|
+
const n = d.trim();
|
|
96
96
|
if (!n || n.startsWith("#")) continue;
|
|
97
97
|
const r = n.match(/^(\w+)\s+start\s+(\w+)\s+(\d+(?:\.\d+)?)(%?)/);
|
|
98
98
|
if (r) {
|
|
99
99
|
const a = parseFloat(r[3]), c = r[4] === "%";
|
|
100
|
-
|
|
100
|
+
e.push({
|
|
101
101
|
id: r[1],
|
|
102
102
|
lineId: r[2],
|
|
103
103
|
// API uses 0-1 for percentage, DSL uses 0-100
|
|
@@ -106,20 +106,20 @@ function v(i) {
|
|
|
106
106
|
});
|
|
107
107
|
continue;
|
|
108
108
|
}
|
|
109
|
-
n.match(/^\w+\s*:\s*\(/) || n.match(/^\w+.*->\s*\w+/) || n.match(/^\w+\s+goto\s+/) || n.match(/^\w+\s+start/) &&
|
|
109
|
+
n.match(/^\w+\s*:\s*\(/) || n.match(/^\w+.*->\s*\w+/) || n.match(/^\w+\s+goto\s+/) || n.match(/^\w+\s+start/) && t.push(`Line ${o}: Invalid vehicle start format "${n}"`);
|
|
110
110
|
}
|
|
111
111
|
return {
|
|
112
|
-
data:
|
|
113
|
-
errors:
|
|
112
|
+
data: e,
|
|
113
|
+
errors: t
|
|
114
114
|
};
|
|
115
115
|
}
|
|
116
116
|
function w(i) {
|
|
117
|
-
const
|
|
117
|
+
const e = [], t = [], s = i.trim().split(`
|
|
118
118
|
`);
|
|
119
119
|
let o = 0;
|
|
120
|
-
for (const
|
|
120
|
+
for (const d of s) {
|
|
121
121
|
o++;
|
|
122
|
-
const n =
|
|
122
|
+
const n = d.trim();
|
|
123
123
|
if (!n || n.startsWith("#")) continue;
|
|
124
124
|
const r = n.match(/^(\w+)\s+goto\s+(\w+)\s+(\d+(?:\.\d+)?)(%?)/);
|
|
125
125
|
if (r) {
|
|
@@ -130,26 +130,26 @@ function w(i) {
|
|
|
130
130
|
try {
|
|
131
131
|
l = JSON.parse(f[1]);
|
|
132
132
|
} catch {
|
|
133
|
-
|
|
133
|
+
t.push(`Line ${o}: Invalid JSON payload "${f[1]}"`);
|
|
134
134
|
}
|
|
135
|
-
const
|
|
136
|
-
|
|
135
|
+
const h = parseFloat(r[3]), u = r[4] === "%";
|
|
136
|
+
e.push({
|
|
137
137
|
vehicleId: r[1],
|
|
138
138
|
targetLineId: r[2],
|
|
139
139
|
// API uses 0-1 for percentage, DSL uses 0-100
|
|
140
140
|
// For absolute offsets, keep the raw value
|
|
141
|
-
targetPosition: u ?
|
|
141
|
+
targetPosition: u ? h / 100 : h,
|
|
142
142
|
isPercentage: u,
|
|
143
143
|
wait: c || void 0,
|
|
144
144
|
payload: l
|
|
145
145
|
});
|
|
146
146
|
continue;
|
|
147
147
|
}
|
|
148
|
-
n.match(/^\w+\s*:\s*\(/) || n.match(/^\w+.*->\s*\w+/) || n.match(/^\w+\s+start\s+/) || n.match(/^\w+\s+goto/) &&
|
|
148
|
+
n.match(/^\w+\s*:\s*\(/) || n.match(/^\w+.*->\s*\w+/) || n.match(/^\w+\s+start\s+/) || n.match(/^\w+\s+goto/) && t.push(`Line ${o}: Invalid goto command format "${n}"`);
|
|
149
149
|
}
|
|
150
150
|
return {
|
|
151
|
-
data:
|
|
152
|
-
errors:
|
|
151
|
+
data: e,
|
|
152
|
+
errors: t
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
155
|
function y(i) {
|
|
@@ -163,48 +163,48 @@ function m(i) {
|
|
|
163
163
|
return Array.isArray(i) ? { x: i[0], y: i[1] } : i;
|
|
164
164
|
}
|
|
165
165
|
function M(i) {
|
|
166
|
-
const
|
|
167
|
-
for (const
|
|
168
|
-
const s = m(
|
|
169
|
-
|
|
166
|
+
const e = [];
|
|
167
|
+
for (const t of i.lines) {
|
|
168
|
+
const s = m(t.start), o = m(t.end);
|
|
169
|
+
e.push(`${t.id} : (${Math.round(s.x)}, ${Math.round(s.y)}) -> (${Math.round(o.x)}, ${Math.round(o.y)})`);
|
|
170
170
|
}
|
|
171
|
-
if (i.lines.length > 0 && i.connections && i.connections.length > 0 &&
|
|
172
|
-
for (const
|
|
173
|
-
let s =
|
|
174
|
-
|
|
171
|
+
if (i.lines.length > 0 && i.connections && i.connections.length > 0 && e.push(""), i.connections)
|
|
172
|
+
for (const t of i.connections) {
|
|
173
|
+
let s = t.from;
|
|
174
|
+
t.fromPosition !== void 0 && (t.fromIsPercentage !== !1 ? s += ` ${t.fromPosition * 100}%` : s += ` ${t.fromPosition}`), s += " -> ", s += t.to, t.toPosition !== void 0 && (t.toIsPercentage !== !1 ? s += ` ${t.toPosition * 100}%` : s += ` ${t.toPosition}`), e.push(s);
|
|
175
175
|
}
|
|
176
|
-
return
|
|
176
|
+
return e.join(`
|
|
177
177
|
`);
|
|
178
178
|
}
|
|
179
179
|
function x(i) {
|
|
180
|
-
return i.map((
|
|
181
|
-
const
|
|
182
|
-
return
|
|
180
|
+
return i.map((e) => {
|
|
181
|
+
const t = e.position ?? 0;
|
|
182
|
+
return e.isPercentage !== !1 ? `${e.id} start ${e.lineId} ${t * 100}%` : `${e.id} start ${e.lineId} ${t}`;
|
|
183
183
|
}).join(`
|
|
184
184
|
`);
|
|
185
185
|
}
|
|
186
186
|
function V(i) {
|
|
187
|
-
return i.map((
|
|
188
|
-
const
|
|
189
|
-
let o =
|
|
190
|
-
return o += ` goto ${
|
|
187
|
+
return i.map((e) => {
|
|
188
|
+
const t = e.targetPosition ?? 1, s = e.isPercentage !== !1;
|
|
189
|
+
let o = e.vehicleId;
|
|
190
|
+
return o += ` goto ${e.targetLineId}`, s ? o += ` ${t * 100}%` : o += ` ${t}`, e.wait && (o += " --wait"), e.payload !== void 0 && (o += ` --payload ${JSON.stringify(e.payload)}`), o;
|
|
191
191
|
}).join(`
|
|
192
192
|
`);
|
|
193
193
|
}
|
|
194
|
-
function N(i,
|
|
195
|
-
const s = [], o = [],
|
|
194
|
+
function N(i, e, t = 0) {
|
|
195
|
+
const s = [], o = [], d = /* @__PURE__ */ new Set();
|
|
196
196
|
for (const n of i) {
|
|
197
|
-
if (
|
|
197
|
+
if (d.has(n.vehicleId)) {
|
|
198
198
|
o.push(`Duplicate vehicle ID: ${n.vehicleId}`);
|
|
199
199
|
continue;
|
|
200
200
|
}
|
|
201
|
-
|
|
202
|
-
const r =
|
|
201
|
+
d.add(n.vehicleId);
|
|
202
|
+
const r = e.find((p) => p.id === n.lineId);
|
|
203
203
|
if (!r) {
|
|
204
204
|
o.push(`Vehicle ${n.vehicleId}: Line "${n.lineId}" not found`);
|
|
205
205
|
continue;
|
|
206
206
|
}
|
|
207
|
-
const a = g(r.start, r.end), c = Math.max(0, a -
|
|
207
|
+
const a = g(r.start, r.end), c = Math.max(0, a - t);
|
|
208
208
|
let l;
|
|
209
209
|
if (n.isPercentage) {
|
|
210
210
|
if (n.offset < 0 || n.offset > 1) {
|
|
@@ -219,14 +219,14 @@ function N(i, t, e = 0) {
|
|
|
219
219
|
}
|
|
220
220
|
l = Math.min(n.offset, c);
|
|
221
221
|
}
|
|
222
|
-
const f = $(r, l, !1),
|
|
222
|
+
const f = $(r, l, !1), h = {
|
|
223
223
|
lineId: n.lineId,
|
|
224
224
|
position: f,
|
|
225
225
|
absoluteOffset: l
|
|
226
226
|
}, u = I(
|
|
227
227
|
n.lineId,
|
|
228
228
|
l,
|
|
229
|
-
|
|
229
|
+
t,
|
|
230
230
|
r
|
|
231
231
|
);
|
|
232
232
|
s.push({
|
|
@@ -235,31 +235,31 @@ function N(i, t, e = 0) {
|
|
|
235
235
|
offset: n.offset,
|
|
236
236
|
isPercentage: n.isPercentage,
|
|
237
237
|
state: "idle",
|
|
238
|
-
rear:
|
|
238
|
+
rear: h,
|
|
239
239
|
front: u
|
|
240
240
|
});
|
|
241
241
|
}
|
|
242
242
|
return { vehicles: s, errors: o };
|
|
243
243
|
}
|
|
244
244
|
function b(i) {
|
|
245
|
-
const
|
|
245
|
+
const e = i.map((s) => {
|
|
246
246
|
const o = s.vehicleId.match(/^v(\d+)$/);
|
|
247
247
|
return o ? parseInt(o[1]) : 0;
|
|
248
248
|
}).filter((s) => s > 0);
|
|
249
|
-
return `v${(
|
|
249
|
+
return `v${(e.length > 0 ? Math.max(...e) : 0) + 1}`;
|
|
250
250
|
}
|
|
251
|
-
function F(i,
|
|
252
|
-
if (
|
|
251
|
+
function F(i, e) {
|
|
252
|
+
if (e.length === 0) return null;
|
|
253
253
|
if (i.length === 0)
|
|
254
|
-
return
|
|
255
|
-
const
|
|
256
|
-
for (const s of
|
|
257
|
-
|
|
254
|
+
return e[0].id;
|
|
255
|
+
const t = /* @__PURE__ */ new Map();
|
|
256
|
+
for (const s of e)
|
|
257
|
+
t.set(s.id, 0);
|
|
258
258
|
for (const s of i) {
|
|
259
|
-
const o =
|
|
260
|
-
|
|
259
|
+
const o = t.get(s.vehicleId) || 0;
|
|
260
|
+
t.set(s.vehicleId, o + 1);
|
|
261
261
|
}
|
|
262
|
-
return
|
|
262
|
+
return e[0].id;
|
|
263
263
|
}
|
|
264
264
|
export {
|
|
265
265
|
S as V,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"use strict";const m=require("./core.cjs");class
|
|
2
|
-
`);let
|
|
3
|
-
`);let o=0;for(const
|
|
4
|
-
`);let o=0;for(const
|
|
1
|
+
"use strict";const m=require("./core.cjs");class v{listeners=new Map;on(e,t){return this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t),()=>{this.listeners.get(e)?.delete(t)}}emit(e,t){this.listeners.get(e)?.forEach(s=>{try{s(t)}catch(o){console.error(`Error in event listener for "${e}":`,o)}})}off(e){e?this.listeners.delete(e):this.listeners.clear()}listenerCount(e){return this.listeners.get(e)?.size??0}}function g(i){const e=[],t=[],s=[],o=i.trim().split(`
|
|
2
|
+
`);let d=0;for(const n of o){d++;const r=n.trim();if(!r||r.startsWith("#"))continue;const a=r.match(/^(\w+)\s*:\s*\((-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\)\s*->\s*\((-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\)/);if(a){e.push({id:a[1],start:[parseFloat(a[2]),parseFloat(a[3])],end:[parseFloat(a[4]),parseFloat(a[5])]});continue}const c=r.match(/^(\w+)(?:\s+(\d+(?:\.\d+)?)(%?))??\s*->\s*(\w+)(?:\s+(\d+(?:\.\d+)?)(%?))?/);if(c){const l={from:c[1],to:c[4]};if(c[2]){const f=parseFloat(c[2]),h=c[3]==="%";l.fromPosition=h?f/100:f,l.fromIsPercentage=h}if(c[5]){const f=parseFloat(c[5]),h=c[6]==="%";l.toPosition=h?f/100:f,l.toIsPercentage=h}t.push(l);continue}r.match(/^\w+\s+start\s+/)||r.match(/^\w+\s+goto\s+/)||s.push(`Line ${d}: Unable to parse "${r}"`)}return{data:{lines:e,connections:t.length>0?t:void 0},errors:s}}function I(i){const e=[],t=[],s=i.trim().split(`
|
|
3
|
+
`);let o=0;for(const d of s){o++;const n=d.trim();if(!n||n.startsWith("#"))continue;const r=n.match(/^(\w+)\s+start\s+(\w+)\s+(\d+(?:\.\d+)?)(%?)/);if(r){const a=parseFloat(r[3]),c=r[4]==="%";e.push({id:r[1],lineId:r[2],position:c?a/100:a,isPercentage:c});continue}n.match(/^\w+\s*:\s*\(/)||n.match(/^\w+.*->\s*\w+/)||n.match(/^\w+\s+goto\s+/)||n.match(/^\w+\s+start/)&&t.push(`Line ${o}: Invalid vehicle start format "${n}"`)}return{data:e,errors:t}}function $(i){const e=[],t=[],s=i.trim().split(`
|
|
4
|
+
`);let o=0;for(const d of s){o++;const n=d.trim();if(!n||n.startsWith("#"))continue;const r=n.match(/^(\w+)\s+goto\s+(\w+)\s+(\d+(?:\.\d+)?)(%?)/);if(r){const a=n.slice(r[0].length),c=a.includes("--wait");let l;const f=a.match(/--payload\s+(\{.*\})/);if(f)try{l=JSON.parse(f[1])}catch{t.push(`Line ${o}: Invalid JSON payload "${f[1]}"`)}const h=parseFloat(r[3]),u=r[4]==="%";e.push({vehicleId:r[1],targetLineId:r[2],targetPosition:u?h/100:h,isPercentage:u,wait:c||void 0,payload:l});continue}n.match(/^\w+\s*:\s*\(/)||n.match(/^\w+.*->\s*\w+/)||n.match(/^\w+\s+start\s+/)||n.match(/^\w+\s+goto/)&&t.push(`Line ${o}: Invalid goto command format "${n}"`)}return{data:e,errors:t}}function L(i){return{scene:g(i),vehicles:I(i),movements:$(i)}}function p(i){return Array.isArray(i)?{x:i[0],y:i[1]}:i}function w(i){const e=[];for(const t of i.lines){const s=p(t.start),o=p(t.end);e.push(`${t.id} : (${Math.round(s.x)}, ${Math.round(s.y)}) -> (${Math.round(o.x)}, ${Math.round(o.y)})`)}if(i.lines.length>0&&i.connections&&i.connections.length>0&&e.push(""),i.connections)for(const t of i.connections){let s=t.from;t.fromPosition!==void 0&&(t.fromIsPercentage!==!1?s+=` ${t.fromPosition*100}%`:s+=` ${t.fromPosition}`),s+=" -> ",s+=t.to,t.toPosition!==void 0&&(t.toIsPercentage!==!1?s+=` ${t.toPosition*100}%`:s+=` ${t.toPosition}`),e.push(s)}return e.join(`
|
|
5
5
|
`)}function S(i){return i.map(e=>{const t=e.position??0;return e.isPercentage!==!1?`${e.id} start ${e.lineId} ${t*100}%`:`${e.id} start ${e.lineId} ${t}`}).join(`
|
|
6
6
|
`)}function M(i){return i.map(e=>{const t=e.targetPosition??1,s=e.isPercentage!==!1;let o=e.vehicleId;return o+=` goto ${e.targetLineId}`,s?o+=` ${t*100}%`:o+=` ${t}`,e.wait&&(o+=" --wait"),e.payload!==void 0&&(o+=` --payload ${JSON.stringify(e.payload)}`),o}).join(`
|
|
7
|
-
`)}function V(i,e,t=0){const s=[],o=[],
|
|
7
|
+
`)}function V(i,e,t=0){const s=[],o=[],d=new Set;for(const n of i){if(d.has(n.vehicleId)){o.push(`Duplicate vehicle ID: ${n.vehicleId}`);continue}d.add(n.vehicleId);const r=e.find(P=>P.id===n.lineId);if(!r){o.push(`Vehicle ${n.vehicleId}: Line "${n.lineId}" not found`);continue}const a=m.distance(r.start,r.end),c=Math.max(0,a-t);let l;if(n.isPercentage){if(n.offset<0||n.offset>1){o.push(`Vehicle ${n.vehicleId}: Offset ${n.offset} must be between 0 and 1 for percentage`);continue}l=n.offset*c}else{if(n.offset<0||n.offset>a){o.push(`Vehicle ${n.vehicleId}: Offset ${n.offset} exceeds line length ${a.toFixed(2)}`);continue}l=Math.min(n.offset,c)}const f=m.getPointOnLineByOffset(r,l,!1),h={lineId:n.lineId,position:f,absoluteOffset:l},u=m.calculateInitialFrontPosition(n.lineId,l,t,r);s.push({id:n.vehicleId,lineId:n.lineId,offset:n.offset,isPercentage:n.isPercentage,state:"idle",rear:h,front:u})}return{vehicles:s,errors:o}}function y(i){const e=i.map(s=>{const o=s.vehicleId.match(/^v(\d+)$/);return o?parseInt(o[1]):0}).filter(s=>s>0);return`v${(e.length>0?Math.max(...e):0)+1}`}function D(i,e){if(e.length===0)return null;if(i.length===0)return e[0].id;const t=new Map;for(const s of e)t.set(s.id,0);for(const s of i){const o=t.get(s.vehicleId)||0;t.set(s.vehicleId,o+1)}return e[0].id}exports.VehicleEventEmitter=v;exports.generateMovementDSL=M;exports.generateSceneDSL=w;exports.generateVehiclesDSL=S;exports.getNextGotoVehicleId=D;exports.getNextStartVehicleId=y;exports.parseAllDSL=L;exports.parseMovementDSL=$;exports.parseSceneDSL=g;exports.parseVehiclesDSL=I;exports.validateAndCreateVehicles=V;
|
package/dist/vehicle-path.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs"),i=require("./vehicle-helpers-
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./core.cjs"),i=require("./vehicle-helpers-bgHGBdo9.cjs"),n=require("./animation-loop-fC2LjxCd.cjs"),t=require("./useVehicleEvents-B7Z-9Hn2.cjs");exports.arcLengthToSegmentPosition=e.arcLengthToSegmentPosition;exports.buildArcLengthTable=e.buildArcLengthTable;exports.buildGraph=e.buildGraph;exports.calculateBezierArcLength=e.calculateBezierArcLength;exports.calculateFrontAxlePosition=e.calculateFrontAxlePosition;exports.calculateInitialFrontPosition=e.calculateInitialFrontPosition;exports.calculatePositionOnCurve=e.calculatePositionOnCurve;exports.calculatePositionOnLine=e.calculatePositionOnLine;exports.createBezierCurve=e.createBezierCurve;exports.createInitialMovementState=e.createInitialMovementState;exports.distance=e.distance;exports.distanceToT=e.distanceToT;exports.findPath=e.findPath;exports.getArcLength=e.getArcLength;exports.getCumulativeArcLength=e.getCumulativeArcLength;exports.getLineLength=e.getLineLength;exports.getPointOnBezier=e.getPointOnBezier;exports.getPointOnLine=e.getPointOnLine;exports.getPointOnLineByOffset=e.getPointOnLineByOffset;exports.getPositionFromOffset=e.getPositionFromOffset;exports.handleArrival=e.handleArrival;exports.initializeAllVehicles=e.initializeAllVehicles;exports.initializeMovingVehicle=e.initializeMovingVehicle;exports.normalize=e.normalize;exports.prepareCommandPath=e.prepareCommandPath;exports.resolveFromLineOffset=e.resolveFromLineOffset;exports.resolveToLineOffset=e.resolveToLineOffset;exports.updateAxlePosition=e.updateAxlePosition;exports.VehicleEventEmitter=i.VehicleEventEmitter;exports.generateMovementDSL=i.generateMovementDSL;exports.generateSceneDSL=i.generateSceneDSL;exports.generateVehiclesDSL=i.generateVehiclesDSL;exports.getNextGotoVehicleId=i.getNextGotoVehicleId;exports.getNextStartVehicleId=i.getNextStartVehicleId;exports.parseAllDSL=i.parseAllDSL;exports.parseMovementDSL=i.parseMovementDSL;exports.parseSceneDSL=i.parseSceneDSL;exports.parseVehiclesDSL=i.parseVehiclesDSL;exports.validateAndCreateVehicles=i.validateAndCreateVehicles;exports.createAnimationLoop=n.createAnimationLoop;exports.useAnimationLoop=n.useAnimationLoop;exports.VehicleEventContext=t.VehicleEventContext;exports.VehicleEventProvider=t.VehicleEventProvider;exports.useAnimation=t.useAnimation;exports.useCreateVehicleEventEmitter=t.useCreateVehicleEventEmitter;exports.useInitialMovement=t.useInitialMovement;exports.useMovement=t.useMovementQueue;exports.useMovementQueue=t.useMovementQueue;exports.useMovementSequence=t.useMovementSequence;exports.useScene=t.useScene;exports.useSceneDefinition=t.useSceneDefinition;exports.useVehicleEvent=t.useVehicleEvent;exports.useVehicleEventEmitter=t.useVehicleEventEmitter;exports.useVehicleMovement=t.useAnimation;exports.useVehicleSimulation=t.useVehicleSimulation;exports.useVehicles=t.useVehicles;
|
package/dist/vehicle-path.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { arcLengthToSegmentPosition as i, buildArcLengthTable as a, buildGraph as n, calculateBezierArcLength as s, calculateFrontAxlePosition as o, calculateInitialFrontPosition as l, calculatePositionOnCurve as r, calculatePositionOnLine as c, createBezierCurve as u, createInitialMovementState as h, distance as m, distanceToT as v, findPath as g, getArcLength as L, getCumulativeArcLength as V, getLineLength as d, getPointOnBezier as f, getPointOnLine as S, getPointOnLineByOffset as p, getPositionFromOffset as A, handleArrival as P, initializeAllVehicles as x, initializeMovingVehicle as E, normalize as M, prepareCommandPath as O, resolveFromLineOffset as D, resolveToLineOffset as C, updateAxlePosition as z } from "./core.js";
|
|
2
|
-
import { V as I, g as T, a as B, b as F, c as G, d as N, p as j, e as k, f as q, h as y, v as Q } from "./vehicle-helpers-
|
|
2
|
+
import { V as I, g as T, a as B, b as F, c as G, d as N, p as j, e as k, f as q, h as y, v as Q } from "./vehicle-helpers-BYb2Ibex.js";
|
|
3
3
|
import { c as H, u as J } from "./animation-loop-bZEm2pMN.js";
|
|
4
|
-
import { V as R, a as U, u as W, b as X, c as Y, d as Z, d as _, e as $, f as ee, g as te, h as ie, i as ae, u as ne, j as se, k as oe } from "./useVehicleEvents-
|
|
4
|
+
import { V as R, a as U, u as W, b as X, c as Y, d as Z, d as _, e as $, f as ee, g as te, h as ie, i as ae, u as ne, j as se, k as oe } from "./useVehicleEvents-t_p-Bwhj.js";
|
|
5
5
|
export {
|
|
6
6
|
R as VehicleEventContext,
|
|
7
7
|
I as VehicleEventEmitter,
|
package/package.json
CHANGED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use strict";const o=require("react"),R=require("./core.cjs"),A=require("./vehicle-helpers-82D2V4MI.cjs"),te=require("react/jsx-runtime");function G(s){return Array.isArray(s)?{x:s[0],y:s[1]}:s}function K(s){return{id:s.id,start:G(s.start),end:G(s.end)}}function U(s){const i=s.fromIsPercentage!==!1,x=s.toIsPercentage!==!1;return{fromLineId:s.from,toLineId:s.to,fromOffset:s.fromPosition,fromIsPercentage:s.fromPosition!==void 0?i:void 0,toOffset:s.toPosition,toIsPercentage:s.toPosition!==void 0?x:void 0}}function H(s){const i=s.position??0,x=s.isPercentage!==!1;return{vehicleId:s.id,lineId:s.lineId,offset:i,isPercentage:x}}function J(s){const i=s.isPercentage!==!1,x=s.targetPosition??1;return{vehicleId:s.vehicleId,targetLineId:s.targetLineId,targetOffset:x,isPercentage:i,awaitConfirmation:s.wait,payload:s.payload}}function se(s){const i=[],x=new Set;for(const r of s.lines)x.has(r.id)&&i.push(`Duplicate line ID: ${r.id}`),x.add(r.id);if(s.connections)for(const r of s.connections){x.has(r.from)||i.push(`Connection references non-existent line: ${r.from}`),x.has(r.to)||i.push(`Connection references non-existent line: ${r.to}`);const m=r.fromIsPercentage!==!1,t=r.toIsPercentage!==!1;!m&&r.fromPosition===void 0&&i.push("fromPosition is required when fromIsPercentage is false"),!t&&r.toPosition===void 0&&i.push("toPosition is required when toIsPercentage is false"),r.fromPosition!==void 0&&(m&&(r.fromPosition<0||r.fromPosition>1)?i.push(`Invalid fromPosition: ${r.fromPosition} (must be 0-1 for percentage)`):!m&&r.fromPosition<0&&i.push(`Invalid fromPosition: ${r.fromPosition} (must be >= 0 for absolute distance)`)),r.toPosition!==void 0&&(t&&(r.toPosition<0||r.toPosition>1)?i.push(`Invalid toPosition: ${r.toPosition} (must be 0-1 for percentage)`):!t&&r.toPosition<0&&i.push(`Invalid toPosition: ${r.toPosition} (must be >= 0 for absolute distance)`))}return{valid:i.length===0,errors:i}}function B(){const[s,i]=o.useState([]),[x,r]=o.useState([]),[m,t]=o.useState(null),f=o.useCallback((n,h)=>{i(n),r(h),t(null)},[]),C=o.useCallback(n=>{const h=se(n);if(!h.valid)return t(h.errors.join("; ")),{success:!1,errors:h.errors};const l=n.lines.map(K),g=n.connections?.map(U)||[];return f(l,g),{success:!0}},[f]),D=o.useCallback(n=>{if(s.some(l=>l.id===n.id)){const l=`Line with ID '${n.id}' already exists`;return t(l),{success:!1,error:l}}return i(l=>[...l,K(n)]),t(null),{success:!0}},[s]),q=o.useCallback((n,h)=>{if(s.findIndex(g=>g.id===n)===-1){const g=`Line with ID '${n}' not found`;return t(g),{success:!1,error:g}}return i(g=>g.map(S=>S.id!==n?S:{...S,start:h.start?G(h.start):S.start,end:h.end?G(h.end):S.end})),t(null),{success:!0}},[s]),w=o.useCallback(n=>{if(!s.some(l=>l.id===n)){const l=`Line with ID '${n}' not found`;return t(l),{success:!1,error:l}}return i(l=>l.filter(g=>g.id!==n)),r(l=>l.filter(g=>g.fromLineId!==n&&g.toLineId!==n)),t(null),{success:!0}},[s]),V=o.useCallback(n=>{const h=s.some(d=>d.id===n.from),l=s.some(d=>d.id===n.to);if(!h){const d=`Line '${n.from}' not found`;return t(d),{success:!1,error:d}}if(!l){const d=`Line '${n.to}' not found`;return t(d),{success:!1,error:d}}const g=n.fromIsPercentage!==!1,S=n.toIsPercentage!==!1;if(!g&&n.fromPosition===void 0){const d="fromPosition is required when fromIsPercentage is false";return t(d),{success:!1,error:d}}if(!S&&n.toPosition===void 0){const d="toPosition is required when toIsPercentage is false";return t(d),{success:!1,error:d}}if(x.some(d=>d.fromLineId===n.from&&d.toLineId===n.to)){const d=`Connection from '${n.from}' to '${n.to}' already exists`;return t(d),{success:!1,error:d}}return r(d=>[...d,U(n)]),t(null),{success:!0}},[s,x]),p=o.useCallback((n,h,l)=>{const g=x.findIndex(e=>e.fromLineId===n&&e.toLineId===h);if(g===-1){const e=`Connection from '${n}' to '${h}' not found`;return t(e),{success:!1,error:e}}const S=x[g],Q=l.fromIsPercentage??S.fromIsPercentage,d=l.toIsPercentage??S.toIsPercentage;let $;l.fromOffset!==void 0?$=l.fromOffset:S.fromOffset!==void 0&&($=S.fromOffset);let b;if(l.toOffset!==void 0?b=l.toOffset:S.toOffset!==void 0&&(b=S.toOffset),$!==void 0){if(Q!==!1&&($<0||$>1)){const e=`Invalid fromOffset: ${$} (must be 0-1 for percentage)`;return t(e),{success:!1,error:e}}if(Q===!1&&$<0){const e=`Invalid fromOffset: ${$} (must be >= 0 for absolute distance)`;return t(e),{success:!1,error:e}}}if(b!==void 0){if(d!==!1&&(b<0||b>1)){const e=`Invalid toOffset: ${b} (must be 0-1 for percentage)`;return t(e),{success:!1,error:e}}if(d===!1&&b<0){const e=`Invalid toOffset: ${b} (must be >= 0 for absolute distance)`;return t(e),{success:!1,error:e}}}if(Q===!1&&$===void 0){const e="fromOffset is required when fromIsPercentage is false";return t(e),{success:!1,error:e}}if(d===!1&&b===void 0){const e="toOffset is required when toIsPercentage is false";return t(e),{success:!1,error:e}}const j={from:n,to:h,fromPosition:$,fromIsPercentage:Q,toPosition:b,toIsPercentage:d};return r(e=>e.map((c,u)=>u===g?U(j):c)),t(null),{success:!0}},[x]),P=o.useCallback((n,h)=>{if(!x.some(g=>g.fromLineId===n&&g.toLineId===h)){const g=`Connection from '${n}' to '${h}' not found`;return t(g),{success:!1,error:g}}return r(g=>g.filter(S=>!(S.fromLineId===n&&S.toLineId===h))),t(null),{success:!0}},[x]),a=o.useCallback(()=>{i([]),r([]),t(null)},[]);return{lines:s,curves:x,setScene:C,addLine:D,updateLine:q,removeLine:w,addConnection:V,updateConnection:p,removeConnection:P,clear:a,error:m,_loadScene:f}}function W({lines:s,wheelbase:i}){const[x,r]=o.useState([]),[m,t]=o.useState(null),f=o.useRef([]),C=o.useCallback(p=>{f.current=p,r(p),t(null)},[]),D=o.useCallback(p=>{const P=Array.isArray(p)?p:[p],a=[];for(const g of P)f.current.some(Q=>Q.id===g.id)&&a.push(`Vehicle with ID '${g.id}' already exists`);if(a.length>0)return t(a.join("; ")),{success:!1,errors:a};const n=P.map(H),{vehicles:h,errors:l}=A.validateAndCreateVehicles(n,s,i);return l.length>0?(t(l.join("; ")),{success:!1,errors:l}):(f.current=[...f.current,...h],r(f.current),t(null),{success:!0})},[s,i]),q=o.useCallback((p,P)=>{const a=f.current.findIndex(b=>b.id===p);if(a===-1){const b=`Vehicle with ID '${p}' not found`;return t(b),{success:!1,error:b}}const n=f.current[a];if(n.state!=="idle"){const b=`Cannot update vehicle '${p}' while it is ${n.state}. Vehicle must be idle.`;return t(b),{success:!1,error:b}}const h=P.lineId??n.lineId;if(!s.find(b=>b.id===h)){const b=`Line '${h}' not found`;return t(b),{success:!1,error:b}}let g,S;P.lineId!==void 0&&P.position===void 0?(g=0,S=!0):P.position!==void 0?(g=P.position,S=P.isPercentage??!0):(g=n.offset,S=n.isPercentage);const Q={vehicleId:p,lineId:h,offset:g,isPercentage:S},{vehicles:d,errors:$}=A.validateAndCreateVehicles([Q],s,i);return $.length>0?(t($.join("; ")),{success:!1,error:$.join("; ")}):(f.current=f.current.map((b,j)=>j===a?d[0]:b),r(f.current),t(null),{success:!0})},[s,i]),w=o.useCallback(p=>{if(!f.current.some(a=>a.id===p)){const a=`Vehicle with ID '${p}' not found`;return t(a),{success:!1,error:a}}return f.current=f.current.filter(a=>a.id!==p),r(f.current),t(null),{success:!0}},[]),V=o.useCallback(()=>{f.current=[],r([]),t(null)},[]);return{vehicles:x,addVehicles:D,updateVehicle:q,removeVehicle:w,clear:V,error:m,_loadVehicles:C}}function X({vehicles:s,lines:i}){const[x,r]=o.useState(new Map),[m,t]=o.useState(null),f=o.useRef(new Map),C=o.useCallback(()=>f.current,[]),D=o.useCallback(V=>{f.current=V,r(V),t(null)},[]),q=o.useCallback((V,p)=>{if(!s.some(d=>d.id===V)){const d=`Vehicle '${V}' not found`;return t(d),{success:!1,error:d}}const a=i.find(d=>d.id===p.targetLineId);if(!a){const d=`Line '${p.targetLineId}' not found`;return t(d),{success:!1,error:d}}const n=p.isPercentage!==!1,h=R.distance(a.start,a.end);if(!n&&p.targetPosition===void 0){const d="targetPosition is required when isPercentage is false";return t(d),{success:!1,error:d}}const l=p.targetPosition??1;if(n){if(l<0||l>1){const d=`Invalid targetPosition: ${l} (must be 0-1 for percentage)`;return t(d),{success:!1,error:d}}}else{if(l<0){const d=`Invalid targetPosition: ${l} (must be >= 0 for absolute distance)`;return t(d),{success:!1,error:d}}if(l>h){const d=`Position ${l} exceeds line length ${h}`;return t(d),{success:!1,error:d}}}const g=J({vehicleId:V,...p}),S=new Map(f.current),Q=S.get(V)||[];return S.set(V,[...Q,g]),f.current=S,r(S),t(null),{success:!0}},[s,i]),w=o.useCallback(V=>{if(V!==void 0){if(!s.some(a=>a.id===V)){const a=`Vehicle '${V}' not found`;return t(a),{success:!1,error:a}}const P=new Map(f.current);P.delete(V),f.current=P,r(P)}else f.current=new Map,r(new Map);return t(null),{success:!0}},[s]);return{vehicleQueues:x,getVehicleQueues:C,queueMovement:q,clearQueue:w,error:m,_loadQueues:D}}function Z({vehicles:s,lines:i,vehicleQueues:x,getVehicleQueues:r,wheelbase:m,tangentMode:t,curves:f,eventEmitter:C}){const[D,q]=o.useState([]),w=o.useRef([]),V=o.useCallback(e=>{typeof e=="function"?q(c=>{const u=e(c);return w.current=u,u}):(w.current=e,q(e))},[]),p=o.useCallback(()=>w.current,[]),P=o.useMemo(()=>({wheelbase:m,tangentMode:t}),[m,t]),a=o.useMemo(()=>new Map(i.map(e=>[e.id,e])),[i]),n=o.useRef(new Map);o.useEffect(()=>{const{movingVehicles:e,stateMap:c}=R.initializeAllVehicles(s,a);n.current=c;const u=setTimeout(()=>{V(e)},0);return()=>clearTimeout(u)},[s,a]);const h=o.useRef(null);o.useEffect(()=>{i.length>0&&(h.current=R.buildGraph(i,f,P))},[i,f,P]);const l=o.useRef(0),g=o.useRef(!1),S=o.useCallback(e=>{if(!g.current)return!1;let c=!1;for(const[,M]of n.current)if(M.vehicle.state==="moving"){c=!0;break}if(!c)return!1;const u=[];for(const[M,I]of n.current){if(I.vehicle.state!=="moving"||!I.execution)continue;const v=I.execution;let E;if(v.front.currentSegmentIndex<v.path.segments.length){const k=v.path.segments[v.front.currentSegmentIndex];if(k.type==="line"){const L=a.get(k.lineId);L&&(E=Math.sqrt(Math.pow(L.end.x-L.start.x,2)+Math.pow(L.end.y-L.start.y,2)))}}const T=R.updateAxlePosition(I.vehicle.rear,v.rear,v.path,e,a,v.curveDataMap),y=R.updateAxlePosition(I.vehicle.front,v.front,v.path,e,a,v.curveDataMap,E);if(I.vehicle={...I.vehicle,rear:T.axleState,front:y.axleState},I.execution.rear=T.execution,I.execution.front=y.execution,T.completed){const k={linesMap:a,config:P,vehicleQueues:x,curves:f,graphRef:h,prepareCommandPath:R.prepareCommandPath,onCommandComplete:F=>u.push({type:"commandComplete",data:F}),onCommandStart:F=>u.push({type:"commandStart",data:F})},L=R.handleArrival(I,k);I.vehicle=L.vehicle,L.newExecution!==void 0&&(I.execution=L.newExecution),L.vehicle.state!=="moving"&&u.push({type:"stateChange",data:{vehicleId:M,from:"moving",to:L.vehicle.state}});const O=L.vehicle.rear.position,_=L.vehicle.front.position;u.push({type:"positionUpdate",data:{vehicleId:M,rear:O,front:_,center:{x:(O.x+_.x)/2,y:(O.y+_.y)/2},angle:Math.atan2(_.y-O.y,_.x-O.x)}})}}if(V(M=>M.map(I=>{const v=n.current.get(I.id);return v?v.vehicle:I})),C&&u.length>0){const M=l.current;setTimeout(()=>{l.current===M&&u.forEach(({type:I,data:v})=>{C.emit(I,v)})},0)}for(const[,M]of n.current)if(M.vehicle.state==="moving")return!0;return g.current=!1,!1},[a,f,P,x,C]),Q=o.useCallback(()=>{const e=h.current;if(!e)return!1;const c=r?r():x,u=[];let M=!1;for(const[I,v]of n.current){const E=v.vehicle;if(E.state==="moving")continue;const T=c.get(I);if(!T||T.length===0)continue;const y=T[0],k={graph:e,linesMap:a,curves:f,config:P},L=R.prepareCommandPath(E,y,k);if(!L){console.warn(`No path found for vehicle ${I}`);continue}const O=R.calculateFrontAxlePosition(L.path,0,0,m);n.current.set(I,{...v,execution:{path:L.path,curveDataMap:L.curveDataMap,currentCommandIndex:0,rear:{currentSegmentIndex:0,segmentDistance:0},front:O?{currentSegmentIndex:O.segmentIndex,segmentDistance:O.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}},vehicle:{...E,state:"moving"}}),M=!0,u.push({id:I,fromState:E.state,command:y,startPosition:{lineId:E.rear.lineId,absoluteOffset:E.rear.absoluteOffset,position:E.rear.position}})}if(!M)return!1;if(g.current=!0,V(I=>I.map(v=>{const E=n.current.get(v.id);return E?E.vehicle:v})),C&&u.length>0){const I=l.current;setTimeout(()=>{l.current===I&&u.forEach(({id:v,fromState:E,command:T,startPosition:y})=>{C.emit("commandStart",{vehicleId:v,command:T,commandIndex:0,startPosition:y}),C.emit("stateChange",{vehicleId:v,from:E,to:"moving"})})},0)}return!0},[a,f,x,r,P,m,C]),d=o.useCallback(()=>{l.current++,g.current=!1;const{movingVehicles:e,stateMap:c}=R.initializeAllVehicles(s,a);n.current=c,V(e)},[s,a]),$=o.useCallback(e=>{const c=s.find(v=>v.id===e);if(!c||!a.get(c.lineId))return;const M=R.initializeMovingVehicle(c),I=R.createInitialMovementState(M);n.current.set(e,I),V(v=>v.map(E=>E.id===e?M:E))},[s,a]),b=o.useCallback(e=>{const c=n.current.get(e);if(!c||c.vehicle.state!=="waiting")return!1;const u=x.get(e),M=c.execution;if(!M)return!1;const I=M.currentCommandIndex+1;if(u&&I<u.length){const v=h.current;if(v){const E=u[I],T={graph:v,linesMap:a,curves:f,config:P},y=R.prepareCommandPath(c.vehicle,E,T);if(y){const k=R.calculateFrontAxlePosition(y.path,0,0,m);if(c.execution={path:y.path,curveDataMap:y.curveDataMap,currentCommandIndex:I,rear:{currentSegmentIndex:0,segmentDistance:0},front:k?{currentSegmentIndex:k.segmentIndex,segmentDistance:k.segmentDistance}:{currentSegmentIndex:0,segmentDistance:0}},c.vehicle={...c.vehicle,state:"moving"},V(L=>L.map(O=>O.id===e?c.vehicle:O)),C){const L=l.current;setTimeout(()=>{l.current===L&&C.emit("stateChange",{vehicleId:e,from:"waiting",to:"moving"})},0)}return!0}}}if(c.vehicle={...c.vehicle,state:"idle"},c.execution=null,V(v=>v.map(E=>E.id===e?c.vehicle:E)),C){const v=l.current;setTimeout(()=>{l.current===v&&C.emit("stateChange",{vehicleId:e,from:"waiting",to:"idle"})},0)}return!0},[x,a,f,P,m,C]),j=o.useCallback(()=>{for(const[,e]of n.current)if(e.vehicle.state==="moving")return!0;return!1},[]);return{movingVehicles:D,getMovingVehicles:p,prepare:Q,tick:S,reset:d,resetVehicle:$,continueVehicle:b,isMoving:j,isPrepared:g.current}}function re({wheelbase:s,tangentMode:i="proportional-40",eventEmitter:x}){const r=B(),m=W({lines:r.lines,wheelbase:s}),t=X({vehicles:m.vehicles,lines:r.lines,curves:r.curves}),f=Z({vehicles:m.vehicles,lines:r.lines,vehicleQueues:t.vehicleQueues,getVehicleQueues:t.getVehicleQueues,wheelbase:s,tangentMode:i,curves:r.curves,eventEmitter:x}),C=o.useCallback(e=>m.vehicles.filter(c=>c.lineId===e||c.rear.lineId===e),[m.vehicles]),D=o.useCallback(e=>C(e).length>0,[C]),q=o.useCallback(e=>{const c=r.addLine(e);return c.success?{success:!0}:{success:!1,error:c.error}},[r]),w=o.useCallback((e,c)=>{const u=r.updateLine(e,c);return u.success?{success:!0}:{success:!1,error:u.error}},[r]),V=o.useCallback(e=>{const c=[],u=C(e);u.length>0&&(c.push({type:"vehicle_on_removed_line",message:`${u.length} vehicle(s) are on line '${e}'`,details:{lineId:e,vehicleIds:u.map(v=>v.id)}}),u.forEach(v=>{m.removeVehicle(v.id),t.clearQueue(v.id)}));const M=r.curves.filter(v=>v.fromLineId===e||v.toLineId===e);M.length>0&&c.push({type:"orphaned_connection",message:`${M.length} connection(s) will be removed`,details:{lineId:e,connectionCount:M.length}});const I=r.removeLine(e);return I.success?{success:!0,warnings:c.length>0?c:void 0}:{success:!1,error:I.error}},[r,C,m,t]),p=o.useCallback(()=>{r.clear(),m.clear(),t.clearQueue()},[r,m,t]),P=o.useCallback((e,c,u)=>{const M=r.addConnection({from:e,to:c,fromPosition:u?.fromOffset,fromIsPercentage:u?.fromIsPercentage,toPosition:u?.toOffset,toIsPercentage:u?.toIsPercentage});return M.success?{success:!0}:{success:!1,error:M.error}},[r]),a=o.useCallback((e,c,u)=>{const M=r.updateConnection(e,c,u);return M.success?{success:!0}:{success:!1,error:M.error}},[r]),n=o.useCallback((e,c)=>{const u=r.removeConnection(e,c);return u.success?{success:!0}:{success:!1,error:u.error}},[r]),h=o.useCallback(e=>{const c=m.addVehicles(e);return c.success?{success:!0}:{success:!1,error:c.errors?.join("; ")}},[m]),l=o.useCallback((e,c)=>{const u=m.updateVehicle(e,c);return u.success?{success:!0}:{success:!1,error:u.error}},[m]),g=o.useCallback(e=>{const c=[],u=t.vehicleQueues.get(e);u&&u.length>0&&(c.push({type:"movement_queue_cleared",message:`${u.length} queued movement(s) will be cleared for vehicle '${e}'`,details:{vehicleId:e}}),t.clearQueue(e));const M=m.removeVehicle(e);return M.success?{success:!0,warnings:c.length>0?c:void 0}:{success:!1,error:M.error}},[m,t]),S=o.useCallback(()=>{m.clear(),t.clearQueue()},[m,t]),Q=o.useCallback(e=>{const c={targetLineId:e.lineId,targetPosition:e.position??1,isPercentage:e.isPercentage,wait:e.wait,payload:e.payload},u=t.queueMovement(e.id,c);return u.success?{success:!0}:{success:!1,error:u.error}},[t]),d=o.useCallback(e=>{const c=t.clearQueue(e);return c.success?{success:!0}:{success:!1,error:c.error}},[t]),$=o.useCallback(e=>{const c=[],u=[],{scene:M,vehicles:I,movements:v}=A.parseAllDSL(e);M.errors.length>0&&u.push(...M.errors),I.errors.length>0&&u.push(...I.errors),v.errors.length>0&&u.push(...v.errors);const E=M.data.lines.map(K),T=(M.data.connections||[]).map(U),y=I.data.map(H),{vehicles:k,errors:L}=A.validateAndCreateVehicles(y,E,s);L.length>0&&u.push(...L);const O=new Map;for(const _ of v.data){const F=O.get(_.vehicleId)||[];F.push(J(_)),O.set(_.vehicleId,F)}return r._loadScene(E,T),m._loadVehicles(k),t._loadQueues(O),u.length>0&&c.push({type:"dsl_parse_error",message:`DSL loading had ${u.length} error(s)`,details:{errors:u}}),{success:!0,warnings:c.length>0?c:void 0}},[r,m,t,s]),b=o.useCallback(e=>{const c=[],u=[],M=e.lines.map(K),I=(e.connections||[]).map(U),v=(e.vehicles||[]).map(H),{vehicles:E,errors:T}=A.validateAndCreateVehicles(v,M,s);T.length>0&&u.push(...T);const y=new Map;for(const k of e.movements||[]){const L=y.get(k.vehicleId)||[];L.push(J({vehicleId:k.vehicleId,targetLineId:k.targetLineId,targetPosition:k.targetPosition,isPercentage:k.isPercentage,wait:k.wait,payload:k.payload})),y.set(k.vehicleId,L)}return r._loadScene(M,I),m._loadVehicles(E),t._loadQueues(y),u.length>0&&c.push({type:"dsl_parse_error",message:`JSON loading had ${u.length} error(s)`,details:{errors:u}}),{success:!0,warnings:c.length>0?c:void 0}},[r,m,t,s]),j=o.useMemo(()=>r.error||m.error||t.error,[r.error,m.error,t.error]);return{lines:r.lines,curves:r.curves,vehicles:m.vehicles,movingVehicles:f.movingVehicles,getMovingVehicles:f.getMovingVehicles,vehicleQueues:t.vehicleQueues,error:j,addLine:q,updateLine:w,removeLine:V,clearScene:p,connect:P,updateConnection:a,disconnect:n,addVehicles:h,updateVehicle:l,removeVehicle:g,clearVehicles:S,goto:Q,clearQueue:d,prepare:f.prepare,tick:f.tick,reset:f.reset,resetVehicle:f.resetVehicle,continueVehicle:f.continueVehicle,isMoving:f.isMoving,loadFromDSL:$,loadFromJSON:b,getVehiclesOnLine:C,hasVehiclesOnLine:D}}function z(s){return s.map(i=>({id:i.id,start:i.start,end:i.end}))}function N(s){return s.map(i=>({from:i.fromLineId,to:i.toLineId,fromPosition:i.fromOffset,fromIsPercentage:i.fromIsPercentage,toPosition:i.toOffset,toIsPercentage:i.toIsPercentage}))}function ne(){const[s,i]=o.useState(""),[x,r]=o.useState(null),{lines:m,curves:t,setScene:f}=B(),C=o.useRef(!1),D=o.useRef("");o.useEffect(()=>{D.current=s},[s]),o.useEffect(()=>{if(C.current)return;const p={lines:z(m),connections:t.length>0?N(t):void 0},P=A.generateSceneDSL(p);P!==D.current&&(C.current=!0,i(P),setTimeout(()=>{C.current=!1},50))},[m,t]);const q=o.useCallback(p=>{C.current=!0,i(p);try{const{data:P,errors:a}=A.parseSceneDSL(p);a.length>0&&r(a.join("; "));const n=f(P);!n.success&&n.errors?r(h=>h?`${h}; ${n.errors.join("; ")}`:n.errors.join("; ")):a.length===0&&r(null)}catch(P){r(P instanceof Error?P.message:"Invalid scene definition")}setTimeout(()=>{C.current=!1},50)},[f]),w=o.useCallback(p=>{const P=typeof p=="function"?p(m):p,a=N(t);f({lines:z(P),connections:a.length>0?a:void 0});const n={lines:z(P),connections:a.length>0?a:void 0},h=A.generateSceneDSL(n);C.current=!0,i(h),setTimeout(()=>{C.current=!1},50)},[m,t,f]),V=o.useCallback(p=>{const P=typeof p=="function"?p(t):p,a=N(P);f({lines:z(m),connections:a.length>0?a:void 0});const n={lines:z(m),connections:a.length>0?a:void 0},h=A.generateSceneDSL(n);C.current=!0,i(h),setTimeout(()=>{C.current=!1},50)},[m,t,f]);return{lines:m,curves:t,sceneDefinitionText:s,sceneError:x,isDebouncing:!1,debounceKey:0,setLines:w,setCurves:V,setSceneDefinitionText:q}}function oe({lines:s,wheelbase:i}){const[x,r]=o.useState(""),[m,t]=o.useState(null),{vehicles:f,addVehicles:C,clear:D,error:q}=W({lines:s,wheelbase:i}),w=o.useRef(!1),V=o.useCallback(p=>{w.current=!0,r(p);try{const{data:P,errors:a}=A.parseVehiclesDSL(p),n=[...a];D();for(const h of P){const l=C(h);!l.success&&l.errors&&n.push(...l.errors)}n.length>0?t(n.join(`
|
|
2
|
-
`)):t(null)}catch(P){t(P instanceof Error?P.message:"Invalid initial movement")}setTimeout(()=>{w.current=!1},50)},[C,D]);return{vehicles:f,initialMovementText:x,movementError:m||q,isDebouncing:!1,debounceKey:0,setInitialMovementText:V}}function ce({lines:s,vehicles:i}){const[x,r]=o.useState(""),[m,t]=o.useState([]),[f,C]=o.useState(null),{vehicleQueues:D,queueMovement:q,clearQueue:w,error:V}=X({vehicles:i,lines:s}),p=o.useRef(!1),P=o.useCallback(a=>{p.current=!0,r(a);try{const{data:n,errors:h}=A.parseMovementDSL(a),l=[...h];w();for(const g of n){const S=q(g.vehicleId,{targetLineId:g.targetLineId,targetPosition:g.targetPosition,isPercentage:g.isPercentage,wait:g.wait,payload:g.payload});!S.success&&S.error&&l.push(S.error)}t(n),l.length>0?C(l.join(`
|
|
3
|
-
`)):C(null)}catch(n){C(n instanceof Error?n.message:"Invalid movement sequence"),t([])}setTimeout(()=>{p.current=!1},50)},[q,w]);return{movementSequenceText:x,gotoCommands:m,vehicleQueues:D,sequenceError:f||V,isDebouncing:!1,debounceKey:0,setMovementSequenceText:P}}const Y=o.createContext(null);function ee(){const s=o.useContext(Y);if(!s)throw new Error("useVehicleEventEmitter must be used within a VehicleEventProvider");return s}function ie(){return o.useMemo(()=>new A.VehicleEventEmitter,[])}function ae(s,i,x=[]){const r=ee();o.useEffect(()=>r.on(s,i),[r,s,...x])}function ue({children:s}){const i=o.useMemo(()=>new A.VehicleEventEmitter,[]);return te.jsx(Y.Provider,{value:i,children:s})}exports.VehicleEventContext=Y;exports.VehicleEventProvider=ue;exports.useAnimation=Z;exports.useCreateVehicleEventEmitter=ie;exports.useInitialMovement=oe;exports.useMovementQueue=X;exports.useMovementSequence=ce;exports.useScene=B;exports.useSceneDefinition=ne;exports.useVehicleEvent=ae;exports.useVehicleEventEmitter=ee;exports.useVehicleSimulation=re;exports.useVehicles=W;
|