vehicle-path2 1.0.14 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +168 -168
- package/dist/core/algorithms/pathFinding.d.ts +2 -2
- package/dist/core/algorithms/vehicleMovement.d.ts +29 -20
- package/dist/core/engine.d.ts +160 -0
- package/dist/core/index.d.ts +3 -2
- package/dist/core/types/api.d.ts +9 -0
- package/dist/core/types/movement.d.ts +2 -3
- package/dist/core/types/vehicle.d.ts +4 -2
- package/dist/core.cjs +1 -1
- package/dist/core.js +33 -541
- package/dist/index.d.ts +4 -34
- package/dist/utils/event-emitter.d.ts +4 -6
- package/dist/vehicle-path.cjs +1 -1
- package/dist/vehicle-path.js +729 -59
- package/package.json +83 -103
- package/dist/animation-loop-bZEm2pMN.js +0 -37
- package/dist/animation-loop-fC2LjxCd.cjs +0 -1
- package/dist/react/dsl-hooks/useInitialMovement.d.ts +0 -24
- package/dist/react/dsl-hooks/useMovementSequence.d.ts +0 -27
- package/dist/react/dsl-hooks/useSceneDefinition.d.ts +0 -22
- package/dist/react/hooks/useAnimation.d.ts +0 -47
- package/dist/react/hooks/useMovementQueue.d.ts +0 -53
- package/dist/react/hooks/useScene.d.ts +0 -78
- package/dist/react/hooks/useVehicleSimulation.d.ts +0 -128
- package/dist/react/hooks/useVehicles.d.ts +0 -55
- package/dist/react/index.d.ts +0 -48
- package/dist/react/providers/useVehicleEvents.d.ts +0 -78
- package/dist/react.cjs +0 -1
- package/dist/react.js +0 -18
- package/dist/useVehicleEvents-BZVmIugl.cjs +0 -3
- package/dist/useVehicleEvents-CabztfQ4.js +0 -940
- package/dist/utils/animation-loop.d.ts +0 -105
- package/dist/utils/dsl-parser.d.ts +0 -151
- package/dist/utils/index.d.ts +0 -15
- package/dist/utils/type-converters.d.ts +0 -40
- package/dist/utils/vehicle-helpers.d.ts +0 -8
- package/dist/utils.cjs +0 -1
- package/dist/utils.js +0 -17
- package/dist/vehicle-helpers-BgD4BTAJ.js +0 -275
- package/dist/vehicle-helpers-DrnYWjm3.cjs +0 -7
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Animation Loop Utility
|
|
3
|
-
*
|
|
4
|
-
* A simple utility for creating animation loops with start/pause/stop controls.
|
|
5
|
-
* Uses requestAnimationFrame for smooth animations.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { createAnimationLoop } from 'vehicle-path/utils'
|
|
10
|
-
*
|
|
11
|
-
* const { start, pause, stop, isRunning } = createAnimationLoop({
|
|
12
|
-
* onTick: (deltaTime) => {
|
|
13
|
-
* // Update animation state
|
|
14
|
-
* tick(velocity)
|
|
15
|
-
* },
|
|
16
|
-
* onComplete: () => {
|
|
17
|
-
* console.log('Animation complete!')
|
|
18
|
-
* }
|
|
19
|
-
* })
|
|
20
|
-
*
|
|
21
|
-
* // Start the animation
|
|
22
|
-
* start()
|
|
23
|
-
*
|
|
24
|
-
* // Pause (can resume with start())
|
|
25
|
-
* pause()
|
|
26
|
-
*
|
|
27
|
-
* // Stop completely (resets state)
|
|
28
|
-
* stop()
|
|
29
|
-
* ```
|
|
30
|
-
*/
|
|
31
|
-
export interface AnimationLoopOptions {
|
|
32
|
-
/**
|
|
33
|
-
* Called on each animation frame
|
|
34
|
-
* @param deltaTime - Time elapsed since last frame in milliseconds
|
|
35
|
-
* @returns true to continue, false to complete the animation
|
|
36
|
-
*/
|
|
37
|
-
onTick: (deltaTime: number) => boolean | void;
|
|
38
|
-
/**
|
|
39
|
-
* Called when the animation completes (onTick returns false)
|
|
40
|
-
*/
|
|
41
|
-
onComplete?: () => void;
|
|
42
|
-
/**
|
|
43
|
-
* Called when the animation starts
|
|
44
|
-
*/
|
|
45
|
-
onStart?: () => void;
|
|
46
|
-
/**
|
|
47
|
-
* Called when the animation pauses
|
|
48
|
-
*/
|
|
49
|
-
onPause?: () => void;
|
|
50
|
-
/**
|
|
51
|
-
* Called when the animation stops
|
|
52
|
-
*/
|
|
53
|
-
onStop?: () => void;
|
|
54
|
-
}
|
|
55
|
-
export interface AnimationLoopControls {
|
|
56
|
-
/**
|
|
57
|
-
* Start or resume the animation
|
|
58
|
-
*/
|
|
59
|
-
start: () => void;
|
|
60
|
-
/**
|
|
61
|
-
* Pause the animation (can be resumed with start())
|
|
62
|
-
*/
|
|
63
|
-
pause: () => void;
|
|
64
|
-
/**
|
|
65
|
-
* Stop the animation completely
|
|
66
|
-
*/
|
|
67
|
-
stop: () => void;
|
|
68
|
-
/**
|
|
69
|
-
* Check if the animation is currently running
|
|
70
|
-
*/
|
|
71
|
-
isRunning: () => boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Check if the animation is paused
|
|
74
|
-
*/
|
|
75
|
-
isPaused: () => boolean;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Create an animation loop with start/pause/stop controls
|
|
79
|
-
*
|
|
80
|
-
* @param options - Animation loop configuration
|
|
81
|
-
* @returns Control functions for the animation loop
|
|
82
|
-
*/
|
|
83
|
-
export declare function createAnimationLoop(options: AnimationLoopOptions): AnimationLoopControls;
|
|
84
|
-
/**
|
|
85
|
-
* React hook for using animation loop with automatic cleanup
|
|
86
|
-
*
|
|
87
|
-
* @example
|
|
88
|
-
* ```typescript
|
|
89
|
-
* import { useAnimationLoop } from 'vehicle-path/utils'
|
|
90
|
-
*
|
|
91
|
-
* function MyComponent() {
|
|
92
|
-
* const { start, pause, stop, isRunning } = useAnimationLoop({
|
|
93
|
-
* onTick: (deltaTime) => tick(velocity),
|
|
94
|
-
* onComplete: () => setFinished(true)
|
|
95
|
-
* })
|
|
96
|
-
*
|
|
97
|
-
* return (
|
|
98
|
-
* <button onClick={isRunning() ? pause : start}>
|
|
99
|
-
* {isRunning() ? 'Pause' : 'Start'}
|
|
100
|
-
* </button>
|
|
101
|
-
* )
|
|
102
|
-
* }
|
|
103
|
-
* ```
|
|
104
|
-
*/
|
|
105
|
-
export declare function useAnimationLoop(options: AnimationLoopOptions): AnimationLoopControls;
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DSL Parser Utilities
|
|
3
|
-
*
|
|
4
|
-
* These utilities convert DSL text into API-compatible types that can be used
|
|
5
|
-
* with the programmatic hooks (useScene, useVehicles, useMovement).
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { parseSceneDSL, parseVehiclesDSL, parseMovementDSL } from 'vehicle-path/utils'
|
|
10
|
-
*
|
|
11
|
-
* const sceneConfig = parseSceneDSL(`
|
|
12
|
-
* line001 : (100, 100) -> (700, 100)
|
|
13
|
-
* line002 : (700, 100) -> (700, 400)
|
|
14
|
-
* line001 -> line002
|
|
15
|
-
* `)
|
|
16
|
-
* setScene(sceneConfig)
|
|
17
|
-
*
|
|
18
|
-
* const vehicles = parseVehiclesDSL(`
|
|
19
|
-
* v1 start line001 0%
|
|
20
|
-
* v2 start line002 50%
|
|
21
|
-
* `)
|
|
22
|
-
* vehicles.forEach(v => addVehicle(v))
|
|
23
|
-
*
|
|
24
|
-
* const movements = parseMovementDSL(`
|
|
25
|
-
* v1 goto line002 100%
|
|
26
|
-
* `)
|
|
27
|
-
* movements.forEach(m => queueMovement(m.vehicleId, m))
|
|
28
|
-
* ```
|
|
29
|
-
*/
|
|
30
|
-
import type { SceneConfig, VehicleInput, GotoCommandInput } from '../core/types/api';
|
|
31
|
-
/**
|
|
32
|
-
* Parse result with errors for validation feedback
|
|
33
|
-
*/
|
|
34
|
-
export interface ParseResult<T> {
|
|
35
|
-
data: T;
|
|
36
|
-
errors: string[];
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Movement command parsed from DSL (includes vehicleId for routing)
|
|
40
|
-
*/
|
|
41
|
-
export interface MovementCommand extends GotoCommandInput {
|
|
42
|
-
vehicleId: string;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Parse scene DSL into SceneConfig for useScene.setScene()
|
|
46
|
-
*
|
|
47
|
-
* DSL Format:
|
|
48
|
-
* ```
|
|
49
|
-
* # Lines
|
|
50
|
-
* line001 : (100, 100) -> (700, 100)
|
|
51
|
-
* line002 : (700, 100) -> (700, 400)
|
|
52
|
-
*
|
|
53
|
-
* # Connections (curves)
|
|
54
|
-
* line001 -> line002
|
|
55
|
-
* line001 80% -> line002 20%
|
|
56
|
-
* ```
|
|
57
|
-
*
|
|
58
|
-
* @param text - DSL text to parse
|
|
59
|
-
* @returns ParseResult containing SceneConfig and any parsing errors
|
|
60
|
-
*/
|
|
61
|
-
export declare function parseSceneDSL(text: string): ParseResult<SceneConfig>;
|
|
62
|
-
/**
|
|
63
|
-
* Parse vehicle DSL into VehicleInput[] for useVehicles.addVehicles()
|
|
64
|
-
*
|
|
65
|
-
* DSL Format:
|
|
66
|
-
* ```
|
|
67
|
-
* v1 start line001 0%
|
|
68
|
-
* v2 start line002 50%
|
|
69
|
-
* v3 start line001 100 # absolute offset
|
|
70
|
-
* ```
|
|
71
|
-
*
|
|
72
|
-
* @param text - DSL text to parse
|
|
73
|
-
* @returns ParseResult containing VehicleInput[] and any parsing errors
|
|
74
|
-
*/
|
|
75
|
-
export declare function parseVehiclesDSL(text: string): ParseResult<VehicleInput[]>;
|
|
76
|
-
/**
|
|
77
|
-
* Parse movement DSL into MovementCommand[] for useMovement.queueMovement()
|
|
78
|
-
*
|
|
79
|
-
* DSL Format:
|
|
80
|
-
* ```
|
|
81
|
-
* v1 goto line001 100%
|
|
82
|
-
* v2 goto line001 0% --payload {"orderId": "123"}
|
|
83
|
-
* v1 goto line003 100% --payload {"message": "hello"}
|
|
84
|
-
* ```
|
|
85
|
-
*
|
|
86
|
-
* @param text - DSL text to parse
|
|
87
|
-
* @returns ParseResult containing MovementCommand[] and any parsing errors
|
|
88
|
-
*/
|
|
89
|
-
export declare function parseMovementDSL(text: string): ParseResult<MovementCommand[]>;
|
|
90
|
-
/**
|
|
91
|
-
* Parse all DSL types from a single text block
|
|
92
|
-
*
|
|
93
|
-
* This is useful when you have a combined DSL that includes scene, vehicles, and movements.
|
|
94
|
-
*
|
|
95
|
-
* @param text - Combined DSL text to parse
|
|
96
|
-
* @returns Object containing parsed scene, vehicles, and movements with errors
|
|
97
|
-
*/
|
|
98
|
-
export declare function parseAllDSL(text: string): {
|
|
99
|
-
scene: ParseResult<SceneConfig>;
|
|
100
|
-
vehicles: ParseResult<VehicleInput[]>;
|
|
101
|
-
movements: ParseResult<MovementCommand[]>;
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Generate scene DSL from SceneConfig
|
|
105
|
-
*
|
|
106
|
-
* @param config - SceneConfig from programmatic API
|
|
107
|
-
* @returns DSL text representation
|
|
108
|
-
*
|
|
109
|
-
* @example
|
|
110
|
-
* ```typescript
|
|
111
|
-
* const dsl = generateSceneDSL({
|
|
112
|
-
* lines: [{ id: 'line001', start: [100, 100], end: [500, 100] }],
|
|
113
|
-
* connections: [{ from: 'line001', to: 'line002' }]
|
|
114
|
-
* })
|
|
115
|
-
* // Returns:
|
|
116
|
-
* // line001 : (100, 100) -> (500, 100)
|
|
117
|
-
* //
|
|
118
|
-
* // line001 -> line002
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
export declare function generateSceneDSL(config: SceneConfig): string;
|
|
122
|
-
/**
|
|
123
|
-
* Generate vehicles DSL from VehicleInput[]
|
|
124
|
-
*
|
|
125
|
-
* @param vehicles - Array of VehicleInput from programmatic API
|
|
126
|
-
* @returns DSL text representation
|
|
127
|
-
*
|
|
128
|
-
* @example
|
|
129
|
-
* ```typescript
|
|
130
|
-
* const dsl = generateVehiclesDSL([
|
|
131
|
-
* { id: 'v1', lineId: 'line001', position: 0.5, isPercentage: true }
|
|
132
|
-
* ])
|
|
133
|
-
* // Returns: "v1 start line001 50%"
|
|
134
|
-
* ```
|
|
135
|
-
*/
|
|
136
|
-
export declare function generateVehiclesDSL(vehicles: VehicleInput[]): string;
|
|
137
|
-
/**
|
|
138
|
-
* Generate movement DSL from MovementCommand[]
|
|
139
|
-
*
|
|
140
|
-
* @param commands - Array of MovementCommand from programmatic API
|
|
141
|
-
* @returns DSL text representation
|
|
142
|
-
*
|
|
143
|
-
* @example
|
|
144
|
-
* ```typescript
|
|
145
|
-
* const dsl = generateMovementDSL([
|
|
146
|
-
* { vehicleId: 'v1', targetLineId: 'line002', targetPosition: 1.0 }
|
|
147
|
-
* ])
|
|
148
|
-
* // Returns: "v1 goto line002 100%"
|
|
149
|
-
* ```
|
|
150
|
-
*/
|
|
151
|
-
export declare function generateMovementDSL(commands: MovementCommand[]): string;
|
package/dist/utils/index.d.ts
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utils Layer - Optional utilities
|
|
3
|
-
*
|
|
4
|
-
* This layer contains utilities that are optional and can be replaced with
|
|
5
|
-
* your own implementations. Includes DSL parser, event emitter, animation loop, etc.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* import { parseSceneDSL, VehicleEventEmitter, createAnimationLoop } from 'vehicle-path/utils'
|
|
10
|
-
* ```
|
|
11
|
-
*/
|
|
12
|
-
export { VehicleEventEmitter, type VehicleEventMap, type VehicleEventType, type VehicleEventCallback, type VehiclePositionUpdate, type Unsubscribe, type CommandStartInfo } from './event-emitter';
|
|
13
|
-
export { parseSceneDSL, parseVehiclesDSL, parseMovementDSL, parseAllDSL, generateSceneDSL, generateVehiclesDSL, generateMovementDSL, type ParseResult, type MovementCommand } from './dsl-parser';
|
|
14
|
-
export { createAnimationLoop, useAnimationLoop, type AnimationLoopOptions, type AnimationLoopControls } from './animation-loop';
|
|
15
|
-
export { validateAndCreateVehicles, getNextStartVehicleId, getNextGotoVehicleId } from './vehicle-helpers';
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Type Converters
|
|
3
|
-
*
|
|
4
|
-
* Convert API types to internal types. Used by hooks and loadFromDSL.
|
|
5
|
-
*/
|
|
6
|
-
import type { SceneLineInput, SceneConnectionInput, CoordinateInput, VehicleInput } from '../core/types/api';
|
|
7
|
-
import type { Line, Curve } from '../core/types/geometry';
|
|
8
|
-
import type { VehicleStart, GotoCommand } from '../core/types/vehicle';
|
|
9
|
-
/**
|
|
10
|
-
* Convert coordinate input to Point
|
|
11
|
-
*/
|
|
12
|
-
export declare function toPoint(coord: CoordinateInput): {
|
|
13
|
-
x: number;
|
|
14
|
-
y: number;
|
|
15
|
-
};
|
|
16
|
-
/**
|
|
17
|
-
* Convert SceneLineInput to internal Line type
|
|
18
|
-
*/
|
|
19
|
-
export declare function toLine(input: SceneLineInput): Line;
|
|
20
|
-
/**
|
|
21
|
-
* Convert SceneConnectionInput to internal Curve type
|
|
22
|
-
* Note: Percentage values are stored as 0-1 (same as API format)
|
|
23
|
-
*/
|
|
24
|
-
export declare function toCurve(input: SceneConnectionInput): Curve;
|
|
25
|
-
/**
|
|
26
|
-
* Convert VehicleInput to internal VehicleStart format
|
|
27
|
-
* Note: Percentage values are stored as 0-1 (same as API format)
|
|
28
|
-
*/
|
|
29
|
-
export declare function toVehicleStart(input: VehicleInput): VehicleStart;
|
|
30
|
-
/**
|
|
31
|
-
* Convert GotoCommand input (with optional fields) to internal GotoCommand format (all required)
|
|
32
|
-
* Note: Percentage values are stored as 0-1 (same as API format)
|
|
33
|
-
*/
|
|
34
|
-
export declare function toGotoCommand(cmd: {
|
|
35
|
-
vehicleId: string;
|
|
36
|
-
targetLineId: string;
|
|
37
|
-
targetPosition?: number;
|
|
38
|
-
isPercentage?: boolean;
|
|
39
|
-
payload?: unknown;
|
|
40
|
-
}): GotoCommand;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { Line } from '../core/types/geometry';
|
|
2
|
-
import type { Vehicle, VehicleStart, GotoCommand } from '../core/types/vehicle';
|
|
3
|
-
export declare function validateAndCreateVehicles(vehicleStarts: VehicleStart[], lines: Line[], wheelbase?: number): {
|
|
4
|
-
vehicles: Vehicle[];
|
|
5
|
-
errors: string[];
|
|
6
|
-
};
|
|
7
|
-
export declare function getNextStartVehicleId(existingVehicles: VehicleStart[]): string;
|
|
8
|
-
export declare function getNextGotoVehicleId(existingCommands: GotoCommand[], vehicles: Vehicle[]): string | null;
|
package/dist/utils.cjs
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./vehicle-helpers-DrnYWjm3.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
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
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-BgD4BTAJ.js";
|
|
2
|
-
import { c as m, u as D } from "./animation-loop-bZEm2pMN.js";
|
|
3
|
-
export {
|
|
4
|
-
t as VehicleEventEmitter,
|
|
5
|
-
m as createAnimationLoop,
|
|
6
|
-
s as generateMovementDSL,
|
|
7
|
-
r as generateSceneDSL,
|
|
8
|
-
o as generateVehiclesDSL,
|
|
9
|
-
n as getNextGotoVehicleId,
|
|
10
|
-
i as getNextStartVehicleId,
|
|
11
|
-
c as parseAllDSL,
|
|
12
|
-
S as parseMovementDSL,
|
|
13
|
-
l as parseSceneDSL,
|
|
14
|
-
p as parseVehiclesDSL,
|
|
15
|
-
D as useAnimationLoop,
|
|
16
|
-
L as validateAndCreateVehicles
|
|
17
|
-
};
|
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
import { distance as g, getPointOnLineByOffset as $, calculateInitialFrontPosition as I } from "./core.js";
|
|
2
|
-
class S {
|
|
3
|
-
listeners = /* @__PURE__ */ new Map();
|
|
4
|
-
/**
|
|
5
|
-
* Subscribe to an event
|
|
6
|
-
* @param event - The event type to listen for
|
|
7
|
-
* @param callback - Function to call when event is emitted
|
|
8
|
-
* @returns Unsubscribe function
|
|
9
|
-
*/
|
|
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
|
-
};
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Emit an event to all subscribers
|
|
17
|
-
* @param event - The event type to emit
|
|
18
|
-
* @param data - The event data
|
|
19
|
-
*/
|
|
20
|
-
emit(e, t) {
|
|
21
|
-
this.listeners.get(e)?.forEach((s) => {
|
|
22
|
-
try {
|
|
23
|
-
s(t);
|
|
24
|
-
} catch (o) {
|
|
25
|
-
console.error(`Error in event listener for "${e}":`, o);
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Remove all listeners for a specific event, or all events if no event specified
|
|
31
|
-
* @param event - Optional event type to clear listeners for
|
|
32
|
-
*/
|
|
33
|
-
off(e) {
|
|
34
|
-
e ? this.listeners.delete(e) : this.listeners.clear();
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Get the number of listeners for a specific event
|
|
38
|
-
* @param event - The event type
|
|
39
|
-
* @returns Number of listeners
|
|
40
|
-
*/
|
|
41
|
-
listenerCount(e) {
|
|
42
|
-
return this.listeners.get(e)?.size ?? 0;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function P(i) {
|
|
46
|
-
const e = [], t = [], s = [], o = i.trim().split(`
|
|
47
|
-
`);
|
|
48
|
-
let d = 0;
|
|
49
|
-
for (const n of o) {
|
|
50
|
-
d++;
|
|
51
|
-
const r = n.trim();
|
|
52
|
-
if (!r || r.startsWith("#")) continue;
|
|
53
|
-
const a = r.match(/^(\w+)\s*:\s*\((-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\)\s*->\s*\((-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)\)/);
|
|
54
|
-
if (a) {
|
|
55
|
-
e.push({
|
|
56
|
-
id: a[1],
|
|
57
|
-
start: [parseFloat(a[2]), parseFloat(a[3])],
|
|
58
|
-
end: [parseFloat(a[4]), parseFloat(a[5])]
|
|
59
|
-
});
|
|
60
|
-
continue;
|
|
61
|
-
}
|
|
62
|
-
const c = r.match(/^(\w+)(?:\s+(\d+(?:\.\d+)?)(%?))??\s*->\s*(\w+)(?:\s+(\d+(?:\.\d+)?)(%?))?/);
|
|
63
|
-
if (c) {
|
|
64
|
-
const l = {
|
|
65
|
-
from: c[1],
|
|
66
|
-
to: c[4]
|
|
67
|
-
};
|
|
68
|
-
if (c[2]) {
|
|
69
|
-
const f = parseFloat(c[2]), h = c[3] === "%";
|
|
70
|
-
l.fromPosition = h ? f / 100 : f, l.fromIsPercentage = h;
|
|
71
|
-
}
|
|
72
|
-
if (c[5]) {
|
|
73
|
-
const f = parseFloat(c[5]), h = c[6] === "%";
|
|
74
|
-
l.toPosition = h ? f / 100 : f, l.toIsPercentage = h;
|
|
75
|
-
}
|
|
76
|
-
t.push(l);
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
r.match(/^\w+\s+start\s+/) || r.match(/^\w+\s+goto\s+/) || s.push(`Line ${d}: Unable to parse "${r}"`);
|
|
80
|
-
}
|
|
81
|
-
return {
|
|
82
|
-
data: {
|
|
83
|
-
lines: e,
|
|
84
|
-
connections: t.length > 0 ? t : void 0
|
|
85
|
-
},
|
|
86
|
-
errors: s
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
function v(i) {
|
|
90
|
-
const e = [], t = [], s = i.trim().split(`
|
|
91
|
-
`);
|
|
92
|
-
let o = 0;
|
|
93
|
-
for (const d of s) {
|
|
94
|
-
o++;
|
|
95
|
-
const n = d.trim();
|
|
96
|
-
if (!n || n.startsWith("#")) continue;
|
|
97
|
-
const r = n.match(/^(\w+)\s+start\s+(\w+)\s+(\d+(?:\.\d+)?)(%?)/);
|
|
98
|
-
if (r) {
|
|
99
|
-
const a = parseFloat(r[3]), c = r[4] === "%";
|
|
100
|
-
e.push({
|
|
101
|
-
id: r[1],
|
|
102
|
-
lineId: r[2],
|
|
103
|
-
// API uses 0-1 for percentage, DSL uses 0-100
|
|
104
|
-
position: c ? a / 100 : a,
|
|
105
|
-
isPercentage: c
|
|
106
|
-
});
|
|
107
|
-
continue;
|
|
108
|
-
}
|
|
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
|
-
}
|
|
111
|
-
return {
|
|
112
|
-
data: e,
|
|
113
|
-
errors: t
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
function w(i) {
|
|
117
|
-
const e = [], t = [], s = i.trim().split(`
|
|
118
|
-
`);
|
|
119
|
-
let o = 0;
|
|
120
|
-
for (const d of s) {
|
|
121
|
-
o++;
|
|
122
|
-
const n = d.trim();
|
|
123
|
-
if (!n || n.startsWith("#")) continue;
|
|
124
|
-
const r = n.match(/^(\w+)\s+goto\s+(\w+)\s+(\d+(?:\.\d+)?)(%?)/);
|
|
125
|
-
if (r) {
|
|
126
|
-
const a = n.slice(r[0].length);
|
|
127
|
-
let c;
|
|
128
|
-
const l = a.match(/--payload\s+(\{.*\})/);
|
|
129
|
-
if (l)
|
|
130
|
-
try {
|
|
131
|
-
c = JSON.parse(l[1]);
|
|
132
|
-
} catch {
|
|
133
|
-
t.push(`Line ${o}: Invalid JSON payload "${l[1]}"`);
|
|
134
|
-
}
|
|
135
|
-
const f = parseFloat(r[3]), h = r[4] === "%";
|
|
136
|
-
e.push({
|
|
137
|
-
vehicleId: r[1],
|
|
138
|
-
targetLineId: r[2],
|
|
139
|
-
// API uses 0-1 for percentage, DSL uses 0-100
|
|
140
|
-
// For absolute offsets, keep the raw value
|
|
141
|
-
targetPosition: h ? f / 100 : f,
|
|
142
|
-
isPercentage: h,
|
|
143
|
-
payload: c
|
|
144
|
-
});
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
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}"`);
|
|
148
|
-
}
|
|
149
|
-
return {
|
|
150
|
-
data: e,
|
|
151
|
-
errors: t
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
function y(i) {
|
|
155
|
-
return {
|
|
156
|
-
scene: P(i),
|
|
157
|
-
vehicles: v(i),
|
|
158
|
-
movements: w(i)
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
function u(i) {
|
|
162
|
-
return Array.isArray(i) ? { x: i[0], y: i[1] } : i;
|
|
163
|
-
}
|
|
164
|
-
function M(i) {
|
|
165
|
-
const e = [];
|
|
166
|
-
for (const t of i.lines) {
|
|
167
|
-
const s = u(t.start), o = u(t.end);
|
|
168
|
-
e.push(`${t.id} : (${Math.round(s.x)}, ${Math.round(s.y)}) -> (${Math.round(o.x)}, ${Math.round(o.y)})`);
|
|
169
|
-
}
|
|
170
|
-
if (i.lines.length > 0 && i.connections && i.connections.length > 0 && e.push(""), i.connections)
|
|
171
|
-
for (const t of i.connections) {
|
|
172
|
-
let s = t.from;
|
|
173
|
-
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);
|
|
174
|
-
}
|
|
175
|
-
return e.join(`
|
|
176
|
-
`);
|
|
177
|
-
}
|
|
178
|
-
function x(i) {
|
|
179
|
-
return i.map((e) => {
|
|
180
|
-
const t = e.position ?? 0;
|
|
181
|
-
return e.isPercentage !== !1 ? `${e.id} start ${e.lineId} ${t * 100}%` : `${e.id} start ${e.lineId} ${t}`;
|
|
182
|
-
}).join(`
|
|
183
|
-
`);
|
|
184
|
-
}
|
|
185
|
-
function V(i) {
|
|
186
|
-
return i.map((e) => {
|
|
187
|
-
const t = e.targetPosition ?? 1, s = e.isPercentage !== !1;
|
|
188
|
-
let o = e.vehicleId;
|
|
189
|
-
return o += ` goto ${e.targetLineId}`, s ? o += ` ${t * 100}%` : o += ` ${t}`, e.payload !== void 0 && (o += ` --payload ${JSON.stringify(e.payload)}`), o;
|
|
190
|
-
}).join(`
|
|
191
|
-
`);
|
|
192
|
-
}
|
|
193
|
-
function N(i, e, t = 0) {
|
|
194
|
-
const s = [], o = [], d = /* @__PURE__ */ new Set();
|
|
195
|
-
for (const n of i) {
|
|
196
|
-
if (d.has(n.vehicleId)) {
|
|
197
|
-
o.push(`Duplicate vehicle ID: ${n.vehicleId}`);
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
d.add(n.vehicleId);
|
|
201
|
-
const r = e.find((p) => p.id === n.lineId);
|
|
202
|
-
if (!r) {
|
|
203
|
-
o.push(`Vehicle ${n.vehicleId}: Line "${n.lineId}" not found`);
|
|
204
|
-
continue;
|
|
205
|
-
}
|
|
206
|
-
const a = g(r.start, r.end), c = Math.max(0, a - t);
|
|
207
|
-
let l;
|
|
208
|
-
if (n.isPercentage) {
|
|
209
|
-
if (n.offset < 0 || n.offset > 1) {
|
|
210
|
-
o.push(`Vehicle ${n.vehicleId}: Offset ${n.offset} must be between 0 and 1 for percentage`);
|
|
211
|
-
continue;
|
|
212
|
-
}
|
|
213
|
-
l = n.offset * c;
|
|
214
|
-
} else {
|
|
215
|
-
if (n.offset < 0 || n.offset > a) {
|
|
216
|
-
o.push(`Vehicle ${n.vehicleId}: Offset ${n.offset} exceeds line length ${a.toFixed(2)}`);
|
|
217
|
-
continue;
|
|
218
|
-
}
|
|
219
|
-
l = Math.min(n.offset, c);
|
|
220
|
-
}
|
|
221
|
-
const f = $(r, l, !1), h = {
|
|
222
|
-
lineId: n.lineId,
|
|
223
|
-
position: f,
|
|
224
|
-
absoluteOffset: l
|
|
225
|
-
}, m = I(
|
|
226
|
-
n.lineId,
|
|
227
|
-
l,
|
|
228
|
-
t,
|
|
229
|
-
r
|
|
230
|
-
);
|
|
231
|
-
s.push({
|
|
232
|
-
id: n.vehicleId,
|
|
233
|
-
lineId: n.lineId,
|
|
234
|
-
offset: n.offset,
|
|
235
|
-
isPercentage: n.isPercentage,
|
|
236
|
-
state: "idle",
|
|
237
|
-
rear: h,
|
|
238
|
-
front: m
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
return { vehicles: s, errors: o };
|
|
242
|
-
}
|
|
243
|
-
function b(i) {
|
|
244
|
-
const e = i.map((s) => {
|
|
245
|
-
const o = s.vehicleId.match(/^v(\d+)$/);
|
|
246
|
-
return o ? parseInt(o[1]) : 0;
|
|
247
|
-
}).filter((s) => s > 0);
|
|
248
|
-
return `v${(e.length > 0 ? Math.max(...e) : 0) + 1}`;
|
|
249
|
-
}
|
|
250
|
-
function F(i, e) {
|
|
251
|
-
if (e.length === 0) return null;
|
|
252
|
-
if (i.length === 0)
|
|
253
|
-
return e[0].id;
|
|
254
|
-
const t = /* @__PURE__ */ new Map();
|
|
255
|
-
for (const s of e)
|
|
256
|
-
t.set(s.id, 0);
|
|
257
|
-
for (const s of i) {
|
|
258
|
-
const o = t.get(s.vehicleId) || 0;
|
|
259
|
-
t.set(s.vehicleId, o + 1);
|
|
260
|
-
}
|
|
261
|
-
return e[0].id;
|
|
262
|
-
}
|
|
263
|
-
export {
|
|
264
|
-
S as V,
|
|
265
|
-
M as a,
|
|
266
|
-
x as b,
|
|
267
|
-
F as c,
|
|
268
|
-
b as d,
|
|
269
|
-
w as e,
|
|
270
|
-
P as f,
|
|
271
|
-
V as g,
|
|
272
|
-
v as h,
|
|
273
|
-
y as p,
|
|
274
|
-
N as v
|
|
275
|
-
};
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";const u=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 p(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 g(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(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);let c;const l=a.match(/--payload\s+(\{.*\})/);if(l)try{c=JSON.parse(l[1])}catch{t.push(`Line ${o}: Invalid JSON payload "${l[1]}"`)}const f=parseFloat(r[3]),h=r[4]==="%";e.push({vehicleId:r[1],targetLineId:r[2],targetPosition:h?f/100:f,isPercentage:h,payload:c});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:p(i),vehicles:g(i),movements:I(i)}}function m(i){return Array.isArray(i)?{x:i[0],y:i[1]}:i}function S(i){const e=[];for(const t of i.lines){const s=m(t.start),o=m(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
|
-
`)}function w(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
|
-
`)}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.payload!==void 0&&(o+=` --payload ${JSON.stringify(e.payload)}`),o}).join(`
|
|
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=u.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=u.getPointOnLineByOffset(r,l,!1),h={lineId:n.lineId,position:f,absoluteOffset:l},$=u.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:$})}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=S;exports.generateVehiclesDSL=w;exports.getNextGotoVehicleId=D;exports.getNextStartVehicleId=y;exports.parseAllDSL=L;exports.parseMovementDSL=I;exports.parseSceneDSL=p;exports.parseVehiclesDSL=g;exports.validateAndCreateVehicles=V;
|