@rxflow/manhattan 0.0.2 → 0.0.3
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/cjs/geometry/Line.d.ts +21 -0
- package/cjs/geometry/Line.d.ts.map +1 -0
- package/cjs/geometry/Line.js +88 -0
- package/cjs/geometry/Point.d.ts +49 -0
- package/cjs/geometry/Point.d.ts.map +1 -0
- package/cjs/geometry/Point.js +94 -0
- package/cjs/geometry/Rectangle.d.ts +41 -0
- package/cjs/geometry/Rectangle.d.ts.map +1 -0
- package/cjs/geometry/Rectangle.js +65 -0
- package/cjs/geometry/collision.d.ts +15 -0
- package/cjs/geometry/collision.d.ts.map +1 -0
- package/cjs/geometry/collision.js +81 -0
- package/cjs/geometry/index.d.ts +5 -0
- package/cjs/geometry/index.d.ts.map +1 -0
- package/cjs/geometry/index.js +45 -0
- package/cjs/getManHattanPath.d.ts +53 -0
- package/cjs/getManHattanPath.d.ts.map +1 -0
- package/cjs/getManHattanPath.js +449 -0
- package/cjs/index.d.ts +16 -0
- package/cjs/index.d.ts.map +1 -0
- package/cjs/index.js +117 -0
- package/cjs/obstacle/ObstacleMap.d.ts +66 -0
- package/cjs/obstacle/ObstacleMap.d.ts.map +1 -0
- package/cjs/obstacle/ObstacleMap.js +328 -0
- package/cjs/obstacle/QuadTree.d.ts +119 -0
- package/cjs/obstacle/QuadTree.d.ts.map +1 -0
- package/cjs/obstacle/QuadTree.js +334 -0
- package/cjs/obstacle/index.d.ts +2 -0
- package/cjs/obstacle/index.d.ts.map +1 -0
- package/cjs/obstacle/index.js +12 -0
- package/cjs/options/defaults.d.ts +16 -0
- package/cjs/options/defaults.d.ts.map +1 -0
- package/cjs/options/defaults.js +39 -0
- package/cjs/options/index.d.ts +4 -0
- package/cjs/options/index.d.ts.map +1 -0
- package/cjs/options/index.js +38 -0
- package/cjs/options/resolver.d.ts +10 -0
- package/cjs/options/resolver.d.ts.map +1 -0
- package/cjs/options/resolver.js +248 -0
- package/cjs/options/types.d.ts +210 -0
- package/cjs/options/types.d.ts.map +1 -0
- package/cjs/options/types.js +5 -0
- package/cjs/pathfinder/PathCache.d.ts +92 -0
- package/cjs/pathfinder/PathCache.d.ts.map +1 -0
- package/cjs/pathfinder/PathCache.js +249 -0
- package/cjs/pathfinder/SortedSet.d.ts +35 -0
- package/cjs/pathfinder/SortedSet.d.ts.map +1 -0
- package/cjs/pathfinder/SortedSet.js +95 -0
- package/cjs/pathfinder/findRoute.d.ts +8 -0
- package/cjs/pathfinder/findRoute.d.ts.map +1 -0
- package/cjs/pathfinder/findRoute.js +395 -0
- package/cjs/pathfinder/index.d.ts +4 -0
- package/cjs/pathfinder/index.d.ts.map +1 -0
- package/cjs/pathfinder/index.js +44 -0
- package/cjs/svg/index.d.ts +3 -0
- package/cjs/svg/index.d.ts.map +1 -0
- package/cjs/svg/index.js +31 -0
- package/cjs/svg/pathConverter.d.ts +23 -0
- package/cjs/svg/pathConverter.d.ts.map +1 -0
- package/cjs/svg/pathConverter.js +285 -0
- package/cjs/svg/pathParser.d.ts +11 -0
- package/cjs/svg/pathParser.d.ts.map +1 -0
- package/cjs/svg/pathParser.js +76 -0
- package/cjs/utils/AdaptiveStepCalculator.d.ts +90 -0
- package/cjs/utils/AdaptiveStepCalculator.d.ts.map +1 -0
- package/cjs/utils/AdaptiveStepCalculator.js +224 -0
- package/cjs/utils/ErrorRecovery.d.ts +182 -0
- package/cjs/utils/ErrorRecovery.d.ts.map +1 -0
- package/cjs/utils/ErrorRecovery.js +413 -0
- package/cjs/utils/GlobalGrid.d.ts +99 -0
- package/cjs/utils/GlobalGrid.d.ts.map +1 -0
- package/cjs/utils/GlobalGrid.js +224 -0
- package/cjs/utils/PerformanceMonitor.d.ts +139 -0
- package/cjs/utils/PerformanceMonitor.d.ts.map +1 -0
- package/cjs/utils/PerformanceMonitor.js +305 -0
- package/cjs/utils/direction.d.ts +24 -0
- package/cjs/utils/direction.d.ts.map +1 -0
- package/cjs/utils/direction.js +54 -0
- package/cjs/utils/getAnchorPoints.d.ts +15 -0
- package/cjs/utils/getAnchorPoints.d.ts.map +1 -0
- package/cjs/utils/getAnchorPoints.js +71 -0
- package/cjs/utils/grid.d.ts +42 -0
- package/cjs/utils/grid.d.ts.map +1 -0
- package/cjs/utils/grid.js +73 -0
- package/cjs/utils/heuristics.d.ts +61 -0
- package/cjs/utils/heuristics.d.ts.map +1 -0
- package/cjs/utils/heuristics.js +141 -0
- package/cjs/utils/index.d.ts +14 -0
- package/cjs/utils/index.d.ts.map +1 -0
- package/cjs/utils/index.js +148 -0
- package/cjs/utils/node.d.ts +27 -0
- package/cjs/utils/node.d.ts.map +1 -0
- package/cjs/utils/node.js +36 -0
- package/cjs/utils/pathProcessing.d.ts +45 -0
- package/cjs/utils/pathProcessing.d.ts.map +1 -0
- package/cjs/utils/pathProcessing.js +270 -0
- package/cjs/utils/pathValidation.d.ts +11 -0
- package/cjs/utils/pathValidation.d.ts.map +1 -0
- package/cjs/utils/pathValidation.js +129 -0
- package/cjs/utils/rect.d.ts +9 -0
- package/cjs/utils/rect.d.ts.map +1 -0
- package/cjs/utils/rect.js +110 -0
- package/cjs/utils/route.d.ts +19 -0
- package/cjs/utils/route.d.ts.map +1 -0
- package/cjs/utils/route.js +92 -0
- package/esm/geometry/Line.d.ts +21 -0
- package/esm/geometry/Line.d.ts.map +1 -0
- package/esm/geometry/Point.d.ts +49 -0
- package/esm/geometry/Point.d.ts.map +1 -0
- package/esm/geometry/Rectangle.d.ts +41 -0
- package/esm/geometry/Rectangle.d.ts.map +1 -0
- package/esm/geometry/collision.d.ts +15 -0
- package/esm/geometry/collision.d.ts.map +1 -0
- package/esm/geometry/index.d.ts +5 -0
- package/esm/geometry/index.d.ts.map +1 -0
- package/esm/getManHattanPath.d.ts +53 -0
- package/esm/getManHattanPath.d.ts.map +1 -0
- package/esm/index.d.ts +16 -0
- package/esm/index.d.ts.map +1 -0
- package/esm/obstacle/ObstacleMap.d.ts +66 -0
- package/esm/obstacle/ObstacleMap.d.ts.map +1 -0
- package/esm/obstacle/QuadTree.d.ts +119 -0
- package/esm/obstacle/QuadTree.d.ts.map +1 -0
- package/esm/obstacle/index.d.ts +2 -0
- package/esm/obstacle/index.d.ts.map +1 -0
- package/esm/options/defaults.d.ts +16 -0
- package/esm/options/defaults.d.ts.map +1 -0
- package/esm/options/index.d.ts +4 -0
- package/esm/options/index.d.ts.map +1 -0
- package/esm/options/resolver.d.ts +10 -0
- package/esm/options/resolver.d.ts.map +1 -0
- package/esm/options/types.d.ts +210 -0
- package/esm/options/types.d.ts.map +1 -0
- package/esm/pathfinder/PathCache.d.ts +92 -0
- package/esm/pathfinder/PathCache.d.ts.map +1 -0
- package/esm/pathfinder/SortedSet.d.ts +35 -0
- package/esm/pathfinder/SortedSet.d.ts.map +1 -0
- package/esm/pathfinder/findRoute.d.ts +8 -0
- package/esm/pathfinder/findRoute.d.ts.map +1 -0
- package/esm/pathfinder/index.d.ts +4 -0
- package/esm/pathfinder/index.d.ts.map +1 -0
- package/esm/svg/index.d.ts +3 -0
- package/esm/svg/index.d.ts.map +1 -0
- package/esm/svg/pathConverter.d.ts +23 -0
- package/esm/svg/pathConverter.d.ts.map +1 -0
- package/esm/svg/pathParser.d.ts +11 -0
- package/esm/svg/pathParser.d.ts.map +1 -0
- package/esm/utils/AdaptiveStepCalculator.d.ts +90 -0
- package/esm/utils/AdaptiveStepCalculator.d.ts.map +1 -0
- package/esm/utils/ErrorRecovery.d.ts +182 -0
- package/esm/utils/ErrorRecovery.d.ts.map +1 -0
- package/esm/utils/GlobalGrid.d.ts +99 -0
- package/esm/utils/GlobalGrid.d.ts.map +1 -0
- package/esm/utils/PerformanceMonitor.d.ts +139 -0
- package/esm/utils/PerformanceMonitor.d.ts.map +1 -0
- package/esm/utils/direction.d.ts +24 -0
- package/esm/utils/direction.d.ts.map +1 -0
- package/esm/utils/getAnchorPoints.d.ts +15 -0
- package/esm/utils/getAnchorPoints.d.ts.map +1 -0
- package/esm/utils/grid.d.ts +42 -0
- package/esm/utils/grid.d.ts.map +1 -0
- package/esm/utils/heuristics.d.ts +61 -0
- package/esm/utils/heuristics.d.ts.map +1 -0
- package/esm/utils/index.d.ts +14 -0
- package/esm/utils/index.d.ts.map +1 -0
- package/esm/utils/node.d.ts +27 -0
- package/esm/utils/node.d.ts.map +1 -0
- package/esm/utils/pathProcessing.d.ts +45 -0
- package/esm/utils/pathProcessing.d.ts.map +1 -0
- package/esm/utils/pathValidation.d.ts +11 -0
- package/esm/utils/pathValidation.d.ts.map +1 -0
- package/esm/utils/rect.d.ts +9 -0
- package/esm/utils/rect.d.ts.map +1 -0
- package/esm/utils/route.d.ts +19 -0
- package/esm/utils/route.d.ts.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.defaultGlobalGrid = exports.GlobalGrid = void 0;
|
|
7
|
+
var _geometry = require("../geometry");
|
|
8
|
+
/**
|
|
9
|
+
* GlobalGrid class for consistent path alignment
|
|
10
|
+
* Feature: manhattan-optimization
|
|
11
|
+
*
|
|
12
|
+
* This class ensures all paths align to a unified global grid,
|
|
13
|
+
* solving the path overlap problem where paths should share segments.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Global grid configuration
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* GlobalGrid class for managing grid alignment
|
|
22
|
+
*
|
|
23
|
+
* Key features:
|
|
24
|
+
* - Uses a fixed global origin (0, 0) for consistent alignment across all paths
|
|
25
|
+
* - Supports configurable step sizes
|
|
26
|
+
* - Provides methods for snapping points to grid
|
|
27
|
+
* - Ensures path segments can properly overlap when they should
|
|
28
|
+
*/
|
|
29
|
+
class GlobalGrid {
|
|
30
|
+
/** Grid origin point */
|
|
31
|
+
origin;
|
|
32
|
+
|
|
33
|
+
/** Grid step size in X direction */
|
|
34
|
+
stepX;
|
|
35
|
+
|
|
36
|
+
/** Grid step size in Y direction */
|
|
37
|
+
stepY;
|
|
38
|
+
constructor(config) {
|
|
39
|
+
this.origin = config.origin ?? new _geometry.Point(0, 0);
|
|
40
|
+
this.stepX = config.stepX;
|
|
41
|
+
this.stepY = config.stepY;
|
|
42
|
+
|
|
43
|
+
// Validate step sizes
|
|
44
|
+
if (this.stepX <= 0 || this.stepY <= 0) {
|
|
45
|
+
throw new Error('Grid step sizes must be positive');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Create a GlobalGrid with uniform step size
|
|
51
|
+
*/
|
|
52
|
+
static uniform(step, origin) {
|
|
53
|
+
return new GlobalGrid({
|
|
54
|
+
stepX: step,
|
|
55
|
+
stepY: step,
|
|
56
|
+
origin
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Snap a single value to the grid
|
|
62
|
+
*/
|
|
63
|
+
snapValue(value, step, originOffset = 0) {
|
|
64
|
+
const adjusted = value - originOffset;
|
|
65
|
+
const snapped = Math.round(adjusted / step) * step;
|
|
66
|
+
return snapped + originOffset;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Snap a point to the global grid
|
|
71
|
+
*/
|
|
72
|
+
snapToGrid(point) {
|
|
73
|
+
return new _geometry.Point(this.snapValue(point.x, this.stepX, this.origin.x), this.snapValue(point.y, this.stepY, this.origin.y));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Snap a point to grid and apply precision rounding
|
|
78
|
+
*/
|
|
79
|
+
snapToGridWithPrecision(point, precision) {
|
|
80
|
+
return this.snapToGrid(point).round(precision);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if a point is on the grid (within tolerance)
|
|
85
|
+
*/
|
|
86
|
+
isOnGrid(point, tolerance = 0.001) {
|
|
87
|
+
const snapped = this.snapToGrid(point);
|
|
88
|
+
return Math.abs(point.x - snapped.x) < tolerance && Math.abs(point.y - snapped.y) < tolerance;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get the nearest grid point in a specific direction
|
|
93
|
+
*/
|
|
94
|
+
getNearestGridPoint(point, direction) {
|
|
95
|
+
const adjustedX = point.x - this.origin.x;
|
|
96
|
+
const adjustedY = point.y - this.origin.y;
|
|
97
|
+
let snappedX;
|
|
98
|
+
let snappedY;
|
|
99
|
+
switch (direction) {
|
|
100
|
+
case 'up':
|
|
101
|
+
snappedX = Math.round(adjustedX / this.stepX) * this.stepX;
|
|
102
|
+
snappedY = Math.floor(adjustedY / this.stepY) * this.stepY;
|
|
103
|
+
break;
|
|
104
|
+
case 'down':
|
|
105
|
+
snappedX = Math.round(adjustedX / this.stepX) * this.stepX;
|
|
106
|
+
snappedY = Math.ceil(adjustedY / this.stepY) * this.stepY;
|
|
107
|
+
break;
|
|
108
|
+
case 'left':
|
|
109
|
+
snappedX = Math.floor(adjustedX / this.stepX) * this.stepX;
|
|
110
|
+
snappedY = Math.round(adjustedY / this.stepY) * this.stepY;
|
|
111
|
+
break;
|
|
112
|
+
case 'right':
|
|
113
|
+
snappedX = Math.ceil(adjustedX / this.stepX) * this.stepX;
|
|
114
|
+
snappedY = Math.round(adjustedY / this.stepY) * this.stepY;
|
|
115
|
+
break;
|
|
116
|
+
case 'nearest':
|
|
117
|
+
default:
|
|
118
|
+
snappedX = Math.round(adjustedX / this.stepX) * this.stepX;
|
|
119
|
+
snappedY = Math.round(adjustedY / this.stepY) * this.stepY;
|
|
120
|
+
break;
|
|
121
|
+
}
|
|
122
|
+
return new _geometry.Point(snappedX + this.origin.x, snappedY + this.origin.y);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get all grid points within a rectangle
|
|
127
|
+
*/
|
|
128
|
+
getGridPointsInRect(minX, minY, maxX, maxY) {
|
|
129
|
+
const points = [];
|
|
130
|
+
|
|
131
|
+
// Snap bounds to grid
|
|
132
|
+
const startX = this.snapValue(minX, this.stepX, this.origin.x);
|
|
133
|
+
const startY = this.snapValue(minY, this.stepY, this.origin.y);
|
|
134
|
+
const endX = this.snapValue(maxX, this.stepX, this.origin.x);
|
|
135
|
+
const endY = this.snapValue(maxY, this.stepY, this.origin.y);
|
|
136
|
+
for (let x = startX; x <= endX; x += this.stepX) {
|
|
137
|
+
for (let y = startY; y <= endY; y += this.stepY) {
|
|
138
|
+
points.push(new _geometry.Point(x, y));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return points;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Calculate the grid distance between two points
|
|
146
|
+
* (number of grid steps, not actual distance)
|
|
147
|
+
*/
|
|
148
|
+
gridDistance(p1, p2) {
|
|
149
|
+
const dx = Math.abs(p2.x - p1.x) / this.stepX;
|
|
150
|
+
const dy = Math.abs(p2.y - p1.y) / this.stepY;
|
|
151
|
+
return {
|
|
152
|
+
x: Math.round(dx),
|
|
153
|
+
y: Math.round(dy),
|
|
154
|
+
total: Math.round(dx) + Math.round(dy)
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Snap an array of points to the grid
|
|
160
|
+
*/
|
|
161
|
+
snapPathToGrid(points) {
|
|
162
|
+
return points.map(p => this.snapToGrid(p));
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Snap path to grid and remove duplicate consecutive points
|
|
167
|
+
*/
|
|
168
|
+
snapAndSimplifyPath(points, tolerance = 0.001) {
|
|
169
|
+
if (points.length === 0) return [];
|
|
170
|
+
const snapped = this.snapPathToGrid(points);
|
|
171
|
+
const simplified = [snapped[0]];
|
|
172
|
+
for (let i = 1; i < snapped.length; i++) {
|
|
173
|
+
const prev = simplified[simplified.length - 1];
|
|
174
|
+
const curr = snapped[i];
|
|
175
|
+
|
|
176
|
+
// Skip if same as previous point
|
|
177
|
+
if (Math.abs(prev.x - curr.x) < tolerance && Math.abs(prev.y - curr.y) < tolerance) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
simplified.push(curr);
|
|
181
|
+
}
|
|
182
|
+
return simplified;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get grid offset for a direction
|
|
187
|
+
*/
|
|
188
|
+
getDirectionOffset(direction) {
|
|
189
|
+
switch (direction) {
|
|
190
|
+
case 'up':
|
|
191
|
+
return new _geometry.Point(0, -this.stepY);
|
|
192
|
+
case 'down':
|
|
193
|
+
return new _geometry.Point(0, this.stepY);
|
|
194
|
+
case 'left':
|
|
195
|
+
return new _geometry.Point(-this.stepX, 0);
|
|
196
|
+
case 'right':
|
|
197
|
+
return new _geometry.Point(this.stepX, 0);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Clone this grid with optional overrides
|
|
203
|
+
*/
|
|
204
|
+
clone(overrides) {
|
|
205
|
+
return new GlobalGrid({
|
|
206
|
+
stepX: overrides?.stepX ?? this.stepX,
|
|
207
|
+
stepY: overrides?.stepY ?? this.stepY,
|
|
208
|
+
origin: overrides?.origin ?? this.origin.clone()
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Create a string representation for debugging
|
|
214
|
+
*/
|
|
215
|
+
toString() {
|
|
216
|
+
return `GlobalGrid(origin: ${this.origin.toString()}, stepX: ${this.stepX}, stepY: ${this.stepY})`;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Default global grid instance with step size 10
|
|
222
|
+
*/
|
|
223
|
+
exports.GlobalGrid = GlobalGrid;
|
|
224
|
+
const defaultGlobalGrid = exports.defaultGlobalGrid = GlobalGrid.uniform(10);
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PerformanceMonitor - 性能监控器
|
|
3
|
+
*
|
|
4
|
+
* 提供路径计算的性能监控和调试信息
|
|
5
|
+
* - 计时功能
|
|
6
|
+
* - 指标收集(迭代次数、查询次数等)
|
|
7
|
+
* - 指标导出和日志
|
|
8
|
+
*
|
|
9
|
+
* Feature: manhattan-optimization
|
|
10
|
+
* Requirements: 3.5, 5.5
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* 性能指标接口
|
|
14
|
+
*/
|
|
15
|
+
export interface PerformanceMetrics {
|
|
16
|
+
/** 路径查找耗时(毫秒) */
|
|
17
|
+
pathfindingTime: number;
|
|
18
|
+
/** A* 迭代次数 */
|
|
19
|
+
iterations: number;
|
|
20
|
+
/** 障碍物查询次数 */
|
|
21
|
+
obstacleQueries: number;
|
|
22
|
+
/** 缓存命中率 */
|
|
23
|
+
cacheHitRate: number;
|
|
24
|
+
/** 路径点数量 */
|
|
25
|
+
pathPointCount: number;
|
|
26
|
+
/** 开始时间戳 */
|
|
27
|
+
startTime?: number;
|
|
28
|
+
/** 结束时间戳 */
|
|
29
|
+
endTime?: number;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* 日志级别
|
|
33
|
+
*/
|
|
34
|
+
export type LogLevel = 'error' | 'warn' | 'info' | 'debug';
|
|
35
|
+
/**
|
|
36
|
+
* 性能监控配置
|
|
37
|
+
*/
|
|
38
|
+
export interface PerformanceMonitorConfig {
|
|
39
|
+
/** 是否启用日志 */
|
|
40
|
+
enableLogging: boolean;
|
|
41
|
+
/** 是否启用指标收集 */
|
|
42
|
+
enableMetrics: boolean;
|
|
43
|
+
/** 日志级别 */
|
|
44
|
+
logLevel: LogLevel;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* 默认性能监控配置
|
|
48
|
+
*/
|
|
49
|
+
export declare const DEFAULT_PERFORMANCE_MONITOR_CONFIG: PerformanceMonitorConfig;
|
|
50
|
+
/**
|
|
51
|
+
* 性能监控器
|
|
52
|
+
*/
|
|
53
|
+
export declare class PerformanceMonitor {
|
|
54
|
+
private config;
|
|
55
|
+
private metrics;
|
|
56
|
+
private activeTimers;
|
|
57
|
+
private globalCounters;
|
|
58
|
+
constructor(config?: Partial<PerformanceMonitorConfig>);
|
|
59
|
+
/**
|
|
60
|
+
* 开始监控
|
|
61
|
+
*/
|
|
62
|
+
startMonitoring(label: string): void;
|
|
63
|
+
/**
|
|
64
|
+
* 结束监控并记录
|
|
65
|
+
*/
|
|
66
|
+
endMonitoring(label: string): PerformanceMetrics;
|
|
67
|
+
/**
|
|
68
|
+
* 记录迭代次数
|
|
69
|
+
*/
|
|
70
|
+
recordIterations(label: string, count: number): void;
|
|
71
|
+
/**
|
|
72
|
+
* 增加障碍物查询计数
|
|
73
|
+
*/
|
|
74
|
+
incrementObstacleQueries(label: string, count?: number): void;
|
|
75
|
+
/**
|
|
76
|
+
* 记录路径点数量
|
|
77
|
+
*/
|
|
78
|
+
recordPathPointCount(label: string, count: number): void;
|
|
79
|
+
/**
|
|
80
|
+
* 记录缓存命中
|
|
81
|
+
*/
|
|
82
|
+
recordCacheHit(): void;
|
|
83
|
+
/**
|
|
84
|
+
* 记录缓存未命中
|
|
85
|
+
*/
|
|
86
|
+
recordCacheMiss(): void;
|
|
87
|
+
/**
|
|
88
|
+
* 计算缓存命中率
|
|
89
|
+
*/
|
|
90
|
+
private calculateCacheHitRate;
|
|
91
|
+
/**
|
|
92
|
+
* 获取指定标签的指标
|
|
93
|
+
*/
|
|
94
|
+
getMetrics(label: string): PerformanceMetrics | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* 获取所有指标
|
|
97
|
+
*/
|
|
98
|
+
getAllMetrics(): Map<string, PerformanceMetrics>;
|
|
99
|
+
/**
|
|
100
|
+
* 清除指标
|
|
101
|
+
*/
|
|
102
|
+
clearMetrics(): void;
|
|
103
|
+
/**
|
|
104
|
+
* 导出为日志字符串
|
|
105
|
+
*/
|
|
106
|
+
exportToLog(): string;
|
|
107
|
+
/**
|
|
108
|
+
* 获取摘要统计
|
|
109
|
+
*/
|
|
110
|
+
getSummary(): {
|
|
111
|
+
totalTime: number;
|
|
112
|
+
avgTime: number;
|
|
113
|
+
maxTime: number;
|
|
114
|
+
minTime: number;
|
|
115
|
+
totalIterations: number;
|
|
116
|
+
cacheHitRate: number;
|
|
117
|
+
};
|
|
118
|
+
/**
|
|
119
|
+
* 内部日志方法
|
|
120
|
+
*/
|
|
121
|
+
private log;
|
|
122
|
+
/**
|
|
123
|
+
* 更新配置
|
|
124
|
+
*/
|
|
125
|
+
updateConfig(config: Partial<PerformanceMonitorConfig>): void;
|
|
126
|
+
/**
|
|
127
|
+
* 获取当前配置
|
|
128
|
+
*/
|
|
129
|
+
getConfig(): PerformanceMonitorConfig;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 获取全局性能监控器
|
|
133
|
+
*/
|
|
134
|
+
export declare function getGlobalPerformanceMonitor(): PerformanceMonitor;
|
|
135
|
+
/**
|
|
136
|
+
* 重置全局性能监控器
|
|
137
|
+
*/
|
|
138
|
+
export declare function resetGlobalPerformanceMonitor(): void;
|
|
139
|
+
//# sourceMappingURL=PerformanceMonitor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PerformanceMonitor.d.ts","sourceRoot":"","sources":["../../src/utils/PerformanceMonitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,iBAAiB;IACjB,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc;IACd,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc;IACd,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY;IACZ,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY;IACZ,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;AAE1D;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,aAAa;IACb,aAAa,EAAE,OAAO,CAAA;IACtB,eAAe;IACf,aAAa,EAAE,OAAO,CAAA;IACtB,WAAW;IACX,QAAQ,EAAE,QAAQ,CAAA;CACnB;AAED;;GAEG;AACH,eAAO,MAAM,kCAAkC,EAAE,wBAIhD,CAAA;AAeD;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,OAAO,CAA6C;IAC5D,OAAO,CAAC,YAAY,CAAiC;IACrD,OAAO,CAAC,cAAc,CAMrB;gBAEW,MAAM,GAAE,OAAO,CAAC,wBAAwB,CAAM;IAO1D;;OAEG;IACH,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAepC;;OAEG;IACH,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB;IAsBhD;;OAEG;IACH,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IASpD;;OAEG;IACH,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,SAAI,GAAG,IAAI;IASxD;;OAEG;IACH,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IASxD;;OAEG;IACH,cAAc,IAAI,IAAI;IAMtB;;OAEG;IACH,eAAe,IAAI,IAAI;IAKvB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAK7B;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAIzD;;OAEG;IACH,aAAa,IAAI,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC;IAIhD;;OAEG;IACH,YAAY,IAAI,IAAI;IASpB;;OAEG;IACH,WAAW,IAAI,MAAM;IAoBrB;;OAEG;IACH,UAAU,IAAI;QACZ,SAAS,EAAE,MAAM,CAAA;QACjB,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;QACf,OAAO,EAAE,MAAM,CAAA;QACf,eAAe,EAAE,MAAM,CAAA;QACvB,YAAY,EAAE,MAAM,CAAA;KACrB;IAwBD;;OAEG;IACH,OAAO,CAAC,GAAG;IAyBX;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,wBAAwB,CAAC,GAAG,IAAI;IAI7D;;OAEG;IACH,SAAS,IAAI,wBAAwB;CAGtC;AAOD;;GAEG;AACH,wBAAgB,2BAA2B,IAAI,kBAAkB,CAKhE;AAED;;GAEG;AACH,wBAAgB,6BAA6B,IAAI,IAAI,CAEpD"}
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.PerformanceMonitor = exports.DEFAULT_PERFORMANCE_MONITOR_CONFIG = void 0;
|
|
7
|
+
exports.getGlobalPerformanceMonitor = getGlobalPerformanceMonitor;
|
|
8
|
+
exports.resetGlobalPerformanceMonitor = resetGlobalPerformanceMonitor;
|
|
9
|
+
/**
|
|
10
|
+
* PerformanceMonitor - 性能监控器
|
|
11
|
+
*
|
|
12
|
+
* 提供路径计算的性能监控和调试信息
|
|
13
|
+
* - 计时功能
|
|
14
|
+
* - 指标收集(迭代次数、查询次数等)
|
|
15
|
+
* - 指标导出和日志
|
|
16
|
+
*
|
|
17
|
+
* Feature: manhattan-optimization
|
|
18
|
+
* Requirements: 3.5, 5.5
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 性能指标接口
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* 日志级别
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* 性能监控配置
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* 默认性能监控配置
|
|
35
|
+
*/
|
|
36
|
+
const DEFAULT_PERFORMANCE_MONITOR_CONFIG = exports.DEFAULT_PERFORMANCE_MONITOR_CONFIG = {
|
|
37
|
+
enableLogging: false,
|
|
38
|
+
enableMetrics: false,
|
|
39
|
+
logLevel: 'info'
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* 创建空的性能指标
|
|
44
|
+
*/
|
|
45
|
+
function createEmptyMetrics() {
|
|
46
|
+
return {
|
|
47
|
+
pathfindingTime: 0,
|
|
48
|
+
iterations: 0,
|
|
49
|
+
obstacleQueries: 0,
|
|
50
|
+
cacheHitRate: 0,
|
|
51
|
+
pathPointCount: 0
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 性能监控器
|
|
57
|
+
*/
|
|
58
|
+
class PerformanceMonitor {
|
|
59
|
+
config;
|
|
60
|
+
metrics = new Map();
|
|
61
|
+
activeTimers = new Map();
|
|
62
|
+
globalCounters = {
|
|
63
|
+
totalCacheHits: 0,
|
|
64
|
+
totalCacheQueries: 0
|
|
65
|
+
};
|
|
66
|
+
constructor(config = {}) {
|
|
67
|
+
this.config = {
|
|
68
|
+
...DEFAULT_PERFORMANCE_MONITOR_CONFIG,
|
|
69
|
+
...config
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* 开始监控
|
|
75
|
+
*/
|
|
76
|
+
startMonitoring(label) {
|
|
77
|
+
if (!this.config.enableMetrics) return;
|
|
78
|
+
const startTime = performance.now();
|
|
79
|
+
this.activeTimers.set(label, startTime);
|
|
80
|
+
|
|
81
|
+
// 初始化指标
|
|
82
|
+
this.metrics.set(label, {
|
|
83
|
+
...createEmptyMetrics(),
|
|
84
|
+
startTime
|
|
85
|
+
});
|
|
86
|
+
this.log('debug', `[PerformanceMonitor] Started monitoring: ${label}`);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* 结束监控并记录
|
|
91
|
+
*/
|
|
92
|
+
endMonitoring(label) {
|
|
93
|
+
const endTime = performance.now();
|
|
94
|
+
const startTime = this.activeTimers.get(label);
|
|
95
|
+
if (!startTime) {
|
|
96
|
+
this.log('warn', `[PerformanceMonitor] No active timer for: ${label}`);
|
|
97
|
+
return createEmptyMetrics();
|
|
98
|
+
}
|
|
99
|
+
const metrics = this.metrics.get(label) || createEmptyMetrics();
|
|
100
|
+
metrics.pathfindingTime = endTime - startTime;
|
|
101
|
+
metrics.endTime = endTime;
|
|
102
|
+
metrics.cacheHitRate = this.calculateCacheHitRate();
|
|
103
|
+
this.metrics.set(label, metrics);
|
|
104
|
+
this.activeTimers.delete(label);
|
|
105
|
+
this.log('info', `[PerformanceMonitor] ${label}: ${metrics.pathfindingTime.toFixed(2)}ms, ${metrics.iterations} iterations, ${metrics.pathPointCount} points`);
|
|
106
|
+
return metrics;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* 记录迭代次数
|
|
111
|
+
*/
|
|
112
|
+
recordIterations(label, count) {
|
|
113
|
+
if (!this.config.enableMetrics) return;
|
|
114
|
+
const metrics = this.metrics.get(label);
|
|
115
|
+
if (metrics) {
|
|
116
|
+
metrics.iterations = count;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 增加障碍物查询计数
|
|
122
|
+
*/
|
|
123
|
+
incrementObstacleQueries(label, count = 1) {
|
|
124
|
+
if (!this.config.enableMetrics) return;
|
|
125
|
+
const metrics = this.metrics.get(label);
|
|
126
|
+
if (metrics) {
|
|
127
|
+
metrics.obstacleQueries += count;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* 记录路径点数量
|
|
133
|
+
*/
|
|
134
|
+
recordPathPointCount(label, count) {
|
|
135
|
+
if (!this.config.enableMetrics) return;
|
|
136
|
+
const metrics = this.metrics.get(label);
|
|
137
|
+
if (metrics) {
|
|
138
|
+
metrics.pathPointCount = count;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* 记录缓存命中
|
|
144
|
+
*/
|
|
145
|
+
recordCacheHit() {
|
|
146
|
+
if (!this.config.enableMetrics) return;
|
|
147
|
+
this.globalCounters.totalCacheHits++;
|
|
148
|
+
this.globalCounters.totalCacheQueries++;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* 记录缓存未命中
|
|
153
|
+
*/
|
|
154
|
+
recordCacheMiss() {
|
|
155
|
+
if (!this.config.enableMetrics) return;
|
|
156
|
+
this.globalCounters.totalCacheQueries++;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* 计算缓存命中率
|
|
161
|
+
*/
|
|
162
|
+
calculateCacheHitRate() {
|
|
163
|
+
if (this.globalCounters.totalCacheQueries === 0) return 0;
|
|
164
|
+
return this.globalCounters.totalCacheHits / this.globalCounters.totalCacheQueries;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* 获取指定标签的指标
|
|
169
|
+
*/
|
|
170
|
+
getMetrics(label) {
|
|
171
|
+
return this.metrics.get(label);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* 获取所有指标
|
|
176
|
+
*/
|
|
177
|
+
getAllMetrics() {
|
|
178
|
+
return new Map(this.metrics);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* 清除指标
|
|
183
|
+
*/
|
|
184
|
+
clearMetrics() {
|
|
185
|
+
this.metrics.clear();
|
|
186
|
+
this.activeTimers.clear();
|
|
187
|
+
this.globalCounters = {
|
|
188
|
+
totalCacheHits: 0,
|
|
189
|
+
totalCacheQueries: 0
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* 导出为日志字符串
|
|
195
|
+
*/
|
|
196
|
+
exportToLog() {
|
|
197
|
+
const lines = ['=== Performance Metrics ==='];
|
|
198
|
+
for (const [label, metrics] of this.metrics) {
|
|
199
|
+
lines.push(`\n[${label}]`);
|
|
200
|
+
lines.push(` Time: ${metrics.pathfindingTime.toFixed(2)}ms`);
|
|
201
|
+
lines.push(` Iterations: ${metrics.iterations}`);
|
|
202
|
+
lines.push(` Obstacle Queries: ${metrics.obstacleQueries}`);
|
|
203
|
+
lines.push(` Path Points: ${metrics.pathPointCount}`);
|
|
204
|
+
lines.push(` Cache Hit Rate: ${(metrics.cacheHitRate * 100).toFixed(1)}%`);
|
|
205
|
+
}
|
|
206
|
+
lines.push('\n=== Global Stats ===');
|
|
207
|
+
lines.push(` Total Cache Queries: ${this.globalCounters.totalCacheQueries}`);
|
|
208
|
+
lines.push(` Total Cache Hits: ${this.globalCounters.totalCacheHits}`);
|
|
209
|
+
lines.push(` Overall Cache Hit Rate: ${(this.calculateCacheHitRate() * 100).toFixed(1)}%`);
|
|
210
|
+
return lines.join('\n');
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* 获取摘要统计
|
|
215
|
+
*/
|
|
216
|
+
getSummary() {
|
|
217
|
+
let totalTime = 0;
|
|
218
|
+
let maxTime = 0;
|
|
219
|
+
let minTime = Infinity;
|
|
220
|
+
let totalIterations = 0;
|
|
221
|
+
for (const metrics of this.metrics.values()) {
|
|
222
|
+
totalTime += metrics.pathfindingTime;
|
|
223
|
+
maxTime = Math.max(maxTime, metrics.pathfindingTime);
|
|
224
|
+
minTime = Math.min(minTime, metrics.pathfindingTime);
|
|
225
|
+
totalIterations += metrics.iterations;
|
|
226
|
+
}
|
|
227
|
+
const count = this.metrics.size;
|
|
228
|
+
return {
|
|
229
|
+
totalTime,
|
|
230
|
+
avgTime: count > 0 ? totalTime / count : 0,
|
|
231
|
+
maxTime: count > 0 ? maxTime : 0,
|
|
232
|
+
minTime: count > 0 && minTime !== Infinity ? minTime : 0,
|
|
233
|
+
totalIterations,
|
|
234
|
+
cacheHitRate: this.calculateCacheHitRate()
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* 内部日志方法
|
|
240
|
+
*/
|
|
241
|
+
log(level, message) {
|
|
242
|
+
if (!this.config.enableLogging) return;
|
|
243
|
+
const levels = ['error', 'warn', 'info', 'debug'];
|
|
244
|
+
const configLevelIndex = levels.indexOf(this.config.logLevel);
|
|
245
|
+
const messageLevelIndex = levels.indexOf(level);
|
|
246
|
+
if (messageLevelIndex <= configLevelIndex) {
|
|
247
|
+
switch (level) {
|
|
248
|
+
case 'error':
|
|
249
|
+
console.error(message);
|
|
250
|
+
break;
|
|
251
|
+
case 'warn':
|
|
252
|
+
console.warn(message);
|
|
253
|
+
break;
|
|
254
|
+
case 'info':
|
|
255
|
+
console.info(message);
|
|
256
|
+
break;
|
|
257
|
+
case 'debug':
|
|
258
|
+
console.debug(message);
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* 更新配置
|
|
266
|
+
*/
|
|
267
|
+
updateConfig(config) {
|
|
268
|
+
this.config = {
|
|
269
|
+
...this.config,
|
|
270
|
+
...config
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* 获取当前配置
|
|
276
|
+
*/
|
|
277
|
+
getConfig() {
|
|
278
|
+
return {
|
|
279
|
+
...this.config
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* 全局性能监控器实例(可选使用)
|
|
286
|
+
*/
|
|
287
|
+
exports.PerformanceMonitor = PerformanceMonitor;
|
|
288
|
+
let globalMonitor = null;
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* 获取全局性能监控器
|
|
292
|
+
*/
|
|
293
|
+
function getGlobalPerformanceMonitor() {
|
|
294
|
+
if (!globalMonitor) {
|
|
295
|
+
globalMonitor = new PerformanceMonitor();
|
|
296
|
+
}
|
|
297
|
+
return globalMonitor;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* 重置全局性能监控器
|
|
302
|
+
*/
|
|
303
|
+
function resetGlobalPerformanceMonitor() {
|
|
304
|
+
globalMonitor = null;
|
|
305
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Point } from '../geometry';
|
|
2
|
+
import type { ResolvedOptions } from '../options';
|
|
3
|
+
import type { Grid } from './grid';
|
|
4
|
+
/**
|
|
5
|
+
* Get direction angle from start point to end point
|
|
6
|
+
* Corrects for grid deformation between start and end
|
|
7
|
+
*/
|
|
8
|
+
export declare function getDirectionAngle(start: Point, end: Point, directionCount: number, grid: Grid, options: ResolvedOptions): number;
|
|
9
|
+
/**
|
|
10
|
+
* Get the change in direction between two direction angles
|
|
11
|
+
*/
|
|
12
|
+
export declare function getDirectionChange(angle1: number, angle2: number): number;
|
|
13
|
+
/**
|
|
14
|
+
* Fix direction offsets according to current grid
|
|
15
|
+
*/
|
|
16
|
+
export declare function getGridOffsets(grid: Grid, options: ResolvedOptions): {
|
|
17
|
+
cost: number;
|
|
18
|
+
offsetX: number;
|
|
19
|
+
offsetY: number;
|
|
20
|
+
angle?: number | undefined;
|
|
21
|
+
gridOffsetX?: number | undefined;
|
|
22
|
+
gridOffsetY?: number | undefined;
|
|
23
|
+
}[];
|
|
24
|
+
//# sourceMappingURL=direction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"direction.d.ts","sourceRoot":"","sources":["../../src/utils/direction.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAyBlC;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,KAAK,EACZ,GAAG,EAAE,KAAK,EACV,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,IAAI,EACV,OAAO,EAAE,eAAe,GACvB,MAAM,CAKR;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAGzE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,eAAe;;;;;;;IASlE"}
|