@caoguo/maplibre-pipeline 0.0.1
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/burst/index.cjs +708 -0
- package/dist/burst/index.cjs.map +1 -0
- package/dist/burst/index.d.cts +74 -0
- package/dist/burst/index.d.ts +74 -0
- package/dist/burst/index.js +4 -0
- package/dist/burst/index.js.map +1 -0
- package/dist/burstClass-CGMjcAYy.d.cts +161 -0
- package/dist/burstClass-Cf2p71LE.d.ts +161 -0
- package/dist/chunk-CDEYJ67B.js +80 -0
- package/dist/chunk-CDEYJ67B.js.map +1 -0
- package/dist/chunk-GCDA7KJM.js +289 -0
- package/dist/chunk-GCDA7KJM.js.map +1 -0
- package/dist/chunk-GEJRE2OR.js +351 -0
- package/dist/chunk-GEJRE2OR.js.map +1 -0
- package/dist/chunk-HCT6NSNS.js +532 -0
- package/dist/chunk-HCT6NSNS.js.map +1 -0
- package/dist/chunk-HIRNJVCV.js +13 -0
- package/dist/chunk-HIRNJVCV.js.map +1 -0
- package/dist/chunk-J3AEVXT4.js +164 -0
- package/dist/chunk-J3AEVXT4.js.map +1 -0
- package/dist/chunk-QVY4WJLM.js +256 -0
- package/dist/chunk-QVY4WJLM.js.map +1 -0
- package/dist/chunk-VA2TQWL3.js +340 -0
- package/dist/chunk-VA2TQWL3.js.map +1 -0
- package/dist/chunk-YBLESEN4.js +133 -0
- package/dist/chunk-YBLESEN4.js.map +1 -0
- package/dist/chunk-YS2ICFVK.js +101 -0
- package/dist/chunk-YS2ICFVK.js.map +1 -0
- package/dist/graph/index.cjs +382 -0
- package/dist/graph/index.cjs.map +1 -0
- package/dist/graph/index.d.cts +211 -0
- package/dist/graph/index.d.ts +211 -0
- package/dist/graph/index.js +4 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/health/index.cjs +348 -0
- package/dist/health/index.cjs.map +1 -0
- package/dist/health/index.d.cts +210 -0
- package/dist/health/index.d.ts +210 -0
- package/dist/health/index.js +3 -0
- package/dist/health/index.js.map +1 -0
- package/dist/index.cjs +2295 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/leakage/index.cjs +358 -0
- package/dist/leakage/index.cjs.map +1 -0
- package/dist/leakage/index.d.cts +212 -0
- package/dist/leakage/index.d.ts +212 -0
- package/dist/leakage/index.js +3 -0
- package/dist/leakage/index.js.map +1 -0
- package/dist/nlpg/index.cjs +136 -0
- package/dist/nlpg/index.cjs.map +1 -0
- package/dist/nlpg/index.d.cts +51 -0
- package/dist/nlpg/index.d.ts +51 -0
- package/dist/nlpg/index.js +3 -0
- package/dist/nlpg/index.js.map +1 -0
- package/dist/style/index.cjs +379 -0
- package/dist/style/index.cjs.map +1 -0
- package/dist/style/index.d.cts +119 -0
- package/dist/style/index.d.ts +119 -0
- package/dist/style/index.js +4 -0
- package/dist/style/index.js.map +1 -0
- package/dist/topology/index.cjs +317 -0
- package/dist/topology/index.cjs.map +1 -0
- package/dist/topology/index.d.cts +69 -0
- package/dist/topology/index.d.ts +69 -0
- package/dist/topology/index.js +4 -0
- package/dist/topology/index.js.map +1 -0
- package/dist/types/index.cjs +15 -0
- package/dist/types/index.cjs.map +1 -0
- package/dist/types/index.d.cts +214 -0
- package/dist/types/index.d.ts +214 -0
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
// src/health/healthScorer.ts
|
|
2
|
+
var DEFAULT_WEIGHTS = {
|
|
3
|
+
age: 0.25,
|
|
4
|
+
material: 0.2,
|
|
5
|
+
soil: 0.15,
|
|
6
|
+
history: 0.2,
|
|
7
|
+
pressure: 0.1,
|
|
8
|
+
protection: 0.1
|
|
9
|
+
};
|
|
10
|
+
var MATERIAL_RISK = {
|
|
11
|
+
cast_iron: 0.85,
|
|
12
|
+
// 铸铁 = 高风险(旧管网)
|
|
13
|
+
ductile_iron: 0.2,
|
|
14
|
+
// 球墨铸铁
|
|
15
|
+
steel: 0.4,
|
|
16
|
+
pe: 0.1,
|
|
17
|
+
pvc: 0.15,
|
|
18
|
+
concrete: 0.3,
|
|
19
|
+
hdpe: 0.05,
|
|
20
|
+
copper: 0.1,
|
|
21
|
+
unknown: 0.5
|
|
22
|
+
};
|
|
23
|
+
function scorePipeHealth(input, weights = DEFAULT_WEIGHTS) {
|
|
24
|
+
const dims = {
|
|
25
|
+
age: scoreAge(input, weights.age),
|
|
26
|
+
material: scoreMaterial(input, weights.material),
|
|
27
|
+
soil: scoreSoil(input, weights.soil),
|
|
28
|
+
history: scoreHistory(input, weights.history),
|
|
29
|
+
pressure: scorePressure(input, weights.pressure),
|
|
30
|
+
protection: scoreProtection(input, weights.protection)
|
|
31
|
+
};
|
|
32
|
+
const total = dims.age.score * dims.age.weight + dims.material.score * dims.material.weight + dims.soil.score * dims.soil.weight + dims.history.score * dims.history.weight + dims.pressure.score * dims.pressure.weight + dims.protection.score * dims.protection.weight;
|
|
33
|
+
let final = total;
|
|
34
|
+
if (input.status === "damaged") final *= 0.5;
|
|
35
|
+
else if (input.status === "under_repair") final *= 0.7;
|
|
36
|
+
else if (input.status === "abandoned") final = 0;
|
|
37
|
+
return {
|
|
38
|
+
score: Math.round(final),
|
|
39
|
+
level: toLevel(final),
|
|
40
|
+
dimensions: dims
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
function toLevel(score) {
|
|
44
|
+
if (score >= 80) return "excellent";
|
|
45
|
+
if (score >= 60) return "good";
|
|
46
|
+
if (score >= 40) return "fair";
|
|
47
|
+
if (score >= 20) return "poor";
|
|
48
|
+
return "critical";
|
|
49
|
+
}
|
|
50
|
+
function scoreAge(input, weight) {
|
|
51
|
+
if (!input.installDate) {
|
|
52
|
+
return { score: 50, weight, reason: "\u672A\u77E5\u5B89\u88C5\u65E5\u671F\uFF0C\u6309\u4E2D\u7B49\u8BA1" };
|
|
53
|
+
}
|
|
54
|
+
const ageYears = (Date.now() - new Date(input.installDate).getTime()) / (365.25 * 24 * 3600 * 1e3);
|
|
55
|
+
if (ageYears < 0) return { score: 100, weight, reason: "\u672A\u6765\u65E5\u671F\uFF0C\u89C6\u4E3A\u4F18\u79C0" };
|
|
56
|
+
if (ageYears < 5) return { score: 100, weight, reason: "\u65B0\u5EFA\u7BA1\u7EBF (<5\u5E74)" };
|
|
57
|
+
if (ageYears < 15) return { score: 85, weight, reason: "\u8F83\u65B0 (5-15\u5E74)" };
|
|
58
|
+
if (ageYears < 25) return { score: 65, weight, reason: "\u4E2D\u9F84 (15-25\u5E74)" };
|
|
59
|
+
if (ageYears < 40) return { score: 40, weight, reason: "\u8001\u9F84 (25-40\u5E74)" };
|
|
60
|
+
if (ageYears < 60) return { score: 20, weight, reason: "\u8D85\u671F (>40\u5E74)" };
|
|
61
|
+
return { score: 5, weight, reason: "\u8D85\u671F (>60\u5E74)" };
|
|
62
|
+
}
|
|
63
|
+
function scoreMaterial(input, weight) {
|
|
64
|
+
if (!input.material) {
|
|
65
|
+
return { score: 50, weight, reason: "\u672A\u77E5\u6750\u8D28\uFF0C\u6309\u4E2D\u7B49\u8BA1" };
|
|
66
|
+
}
|
|
67
|
+
const risk = MATERIAL_RISK[input.material] ?? 0.5;
|
|
68
|
+
const score = Math.round((1 - risk) * 100);
|
|
69
|
+
const labels = {
|
|
70
|
+
cast_iron: "\u94F8\u94C1\uFF08\u9AD8\u98CE\u9669\uFF09",
|
|
71
|
+
ductile_iron: "\u7403\u58A8\u94F8\u94C1",
|
|
72
|
+
steel: "\u94A2",
|
|
73
|
+
pe: "PE\uFF08\u4F4E\u98CE\u9669\uFF09",
|
|
74
|
+
pvc: "PVC",
|
|
75
|
+
concrete: "\u6DF7\u51DD\u571F",
|
|
76
|
+
hdpe: "HDPE\uFF08\u6700\u4F73\uFF09",
|
|
77
|
+
copper: "\u94DC",
|
|
78
|
+
unknown: "\u672A\u77E5"
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
score,
|
|
82
|
+
weight,
|
|
83
|
+
reason: labels[input.material] ?? input.material
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function scoreSoil(input, weight) {
|
|
87
|
+
const c = input.soilCorrosion ?? 0.5;
|
|
88
|
+
const score = Math.round((1 - c) * 100);
|
|
89
|
+
return {
|
|
90
|
+
score,
|
|
91
|
+
weight,
|
|
92
|
+
reason: c === 0.5 && !input.soilCorrosion ? "\u65E0\u571F\u58E4\u6570\u636E\uFF0C\u6309\u5E73\u5747\u8BA1" : `\u571F\u58E4\u8150\u8680\u6307\u6570 ${c.toFixed(2)}`
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function scoreHistory(input, weight) {
|
|
96
|
+
const fail = input.failureCount ?? 0;
|
|
97
|
+
if (fail === 0) return { score: 100, weight, reason: "\u5386\u53F2\u65E0\u6545\u969C" };
|
|
98
|
+
if (fail === 1) return { score: 75, weight, reason: "\u5386\u53F2 1 \u6B21\u6545\u969C" };
|
|
99
|
+
if (fail === 2) return { score: 50, weight, reason: "\u5386\u53F2 2 \u6B21\u6545\u969C" };
|
|
100
|
+
if (fail === 3) return { score: 25, weight, reason: "\u5386\u53F2 3 \u6B21\u6545\u969C" };
|
|
101
|
+
return { score: 0, weight, reason: `\u5386\u53F2 \u2265${fail} \u6B21\u6545\u969C` };
|
|
102
|
+
}
|
|
103
|
+
function scorePressure(input, weight) {
|
|
104
|
+
if (!input.pressure) {
|
|
105
|
+
return { score: 75, weight, reason: "\u65E0\u538B\u529B\u6570\u636E\uFF0C\u6309\u4E2D\u7B49\u504F\u597D\u8BA1" };
|
|
106
|
+
}
|
|
107
|
+
if (!input.ratedPressure) {
|
|
108
|
+
return { score: 75, weight, reason: "\u4EC5\u77E5\u5F53\u524D\u538B\u529B" };
|
|
109
|
+
}
|
|
110
|
+
const ratio = input.pressure / input.ratedPressure;
|
|
111
|
+
if (ratio < 0.5) return { score: 60, weight, reason: "\u538B\u529B\u504F\u4F4E (\u4F7F\u7528\u7387 <50%)" };
|
|
112
|
+
if (ratio < 0.8) return { score: 90, weight, reason: "\u538B\u529B\u6B63\u5E38 (\u4F7F\u7528\u7387 50-80%)" };
|
|
113
|
+
if (ratio < 1) return { score: 75, weight, reason: "\u538B\u529B\u504F\u9AD8 (\u4F7F\u7528\u7387 80-100%)" };
|
|
114
|
+
if (ratio < 1.2) return { score: 30, weight, reason: "\u538B\u529B\u8D85\u9650 (100-120%)" };
|
|
115
|
+
return { score: 0, weight, reason: "\u538B\u529B\u4E25\u91CD\u8D85\u9650 (>120%)" };
|
|
116
|
+
}
|
|
117
|
+
function scoreProtection(input, weight) {
|
|
118
|
+
if (input.hasCathodicProtection === true) {
|
|
119
|
+
return { score: 90, weight, reason: "\u6709\u9634\u6781\u4FDD\u62A4" };
|
|
120
|
+
}
|
|
121
|
+
if (input.hasCathodicProtection === false) {
|
|
122
|
+
return { score: 30, weight, reason: "\u65E0\u9634\u6781\u4FDD\u62A4" };
|
|
123
|
+
}
|
|
124
|
+
return { score: 50, weight, reason: "\u9634\u4FDD\u72B6\u6001\u672A\u77E5" };
|
|
125
|
+
}
|
|
126
|
+
function scorePipes(inputs, weights = DEFAULT_WEIGHTS) {
|
|
127
|
+
return inputs.map((i) => scorePipeHealth(i, weights));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/health/riskHeatmap.ts
|
|
131
|
+
function aggregateHeatmap(points, options = {}) {
|
|
132
|
+
const cell = options.cellSize ?? 500;
|
|
133
|
+
const agg = options.aggregation ?? "average";
|
|
134
|
+
if (points.length === 0) return [];
|
|
135
|
+
const refLat = points[0].lat;
|
|
136
|
+
const refLng = points[0].lng;
|
|
137
|
+
const mPerDegLat = 110540;
|
|
138
|
+
const mPerDegLng = 111320 * Math.cos(refLat * Math.PI / 180);
|
|
139
|
+
const grid = /* @__PURE__ */ new Map();
|
|
140
|
+
for (const p of points) {
|
|
141
|
+
const x = (p.lng - refLng) * mPerDegLng;
|
|
142
|
+
const y = (p.lat - refLat) * mPerDegLat;
|
|
143
|
+
const cx = Math.floor(x / cell);
|
|
144
|
+
const cy = Math.floor(y / cell);
|
|
145
|
+
const key = `${cx}:${cy}`;
|
|
146
|
+
const cur = grid.get(key);
|
|
147
|
+
if (!cur) {
|
|
148
|
+
grid.set(key, {
|
|
149
|
+
acc: p.healthScore,
|
|
150
|
+
count: 1,
|
|
151
|
+
minS: p.healthScore,
|
|
152
|
+
maxS: p.healthScore,
|
|
153
|
+
lng: p.lng,
|
|
154
|
+
lat: p.lat
|
|
155
|
+
});
|
|
156
|
+
} else {
|
|
157
|
+
cur.acc += p.healthScore;
|
|
158
|
+
cur.count += 1;
|
|
159
|
+
if (p.healthScore < cur.minS) cur.minS = p.healthScore;
|
|
160
|
+
if (p.healthScore > cur.maxS) cur.maxS = p.healthScore;
|
|
161
|
+
cur.lng = (cur.lng * (cur.count - 1) + p.lng) / cur.count;
|
|
162
|
+
cur.lat = (cur.lat * (cur.count - 1) + p.lat) / cur.count;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const cells = [];
|
|
166
|
+
for (const v of grid.values()) {
|
|
167
|
+
let score;
|
|
168
|
+
if (agg === "min") score = v.minS;
|
|
169
|
+
else if (agg === "max") score = v.maxS;
|
|
170
|
+
else score = v.acc / v.count;
|
|
171
|
+
cells.push({
|
|
172
|
+
lng: v.lng,
|
|
173
|
+
lat: v.lat,
|
|
174
|
+
healthScore: Math.round(score),
|
|
175
|
+
pipeCount: v.count
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return cells;
|
|
179
|
+
}
|
|
180
|
+
function heatmapToGeoJSON(cells) {
|
|
181
|
+
return {
|
|
182
|
+
type: "FeatureCollection",
|
|
183
|
+
features: cells.map((c) => ({
|
|
184
|
+
type: "Feature",
|
|
185
|
+
geometry: { type: "Point", coordinates: [c.lng, c.lat] },
|
|
186
|
+
properties: {
|
|
187
|
+
healthScore: c.healthScore,
|
|
188
|
+
pipeCount: c.pipeCount
|
|
189
|
+
}
|
|
190
|
+
}))
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function prioritizeMaintenance(pipes, topN = 10) {
|
|
194
|
+
return [...pipes].sort((a, b) => a.healthScore - b.healthScore).slice(0, topN);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/health/PipelineHealth.ts
|
|
198
|
+
var PipelineHealth = class {
|
|
199
|
+
map;
|
|
200
|
+
dataset;
|
|
201
|
+
cellSize;
|
|
202
|
+
layerPrefix;
|
|
203
|
+
listeners = /* @__PURE__ */ new Set();
|
|
204
|
+
lastResult = null;
|
|
205
|
+
layerIds = [];
|
|
206
|
+
constructor(options) {
|
|
207
|
+
this.map = options.map;
|
|
208
|
+
this.dataset = options.dataset;
|
|
209
|
+
this.cellSize = options.cellSize ?? 500;
|
|
210
|
+
this.layerPrefix = options.layerPrefix ?? "cg-health";
|
|
211
|
+
}
|
|
212
|
+
/** 评估全网管线健康度 */
|
|
213
|
+
evaluate(weights = DEFAULT_WEIGHTS) {
|
|
214
|
+
const t0 = typeof performance !== "undefined" ? performance.now() : Date.now();
|
|
215
|
+
const nodeById = new Map(this.dataset.nodes.map((n) => [n.id, n]));
|
|
216
|
+
const scores = this.dataset.pipes.map((p) => {
|
|
217
|
+
const input = {
|
|
218
|
+
installDate: p.properties?.installDate,
|
|
219
|
+
material: p.properties?.material,
|
|
220
|
+
failureCount: void 0,
|
|
221
|
+
pressure: p.properties?.pressure,
|
|
222
|
+
ratedPressure: p.properties?.ratedPressure,
|
|
223
|
+
hasCathodicProtection: void 0,
|
|
224
|
+
status: p.properties?.status
|
|
225
|
+
};
|
|
226
|
+
return { pipeId: p.id, score: scorePipeHealth(input, weights) };
|
|
227
|
+
});
|
|
228
|
+
const points = scores.flatMap((s, i) => {
|
|
229
|
+
const pipe = this.dataset.pipes[i];
|
|
230
|
+
const from = nodeById.get(pipe.fromNode);
|
|
231
|
+
const to = nodeById.get(pipe.toNode);
|
|
232
|
+
if (!from || !to) return [];
|
|
233
|
+
return [
|
|
234
|
+
{
|
|
235
|
+
lng: (from.lng + to.lng) / 2,
|
|
236
|
+
lat: (from.lat + to.lat) / 2,
|
|
237
|
+
healthScore: s.score.score
|
|
238
|
+
}
|
|
239
|
+
];
|
|
240
|
+
});
|
|
241
|
+
const heatmap = aggregateHeatmap(points, { cellSize: this.cellSize });
|
|
242
|
+
const maintenance = prioritizeMaintenance(
|
|
243
|
+
scores.flatMap((s, i) => {
|
|
244
|
+
const pipe = this.dataset.pipes[i];
|
|
245
|
+
const from = nodeById.get(pipe.fromNode);
|
|
246
|
+
const to = nodeById.get(pipe.toNode);
|
|
247
|
+
if (!from || !to) return [];
|
|
248
|
+
return [
|
|
249
|
+
{
|
|
250
|
+
id: pipe.id,
|
|
251
|
+
healthScore: s.score.score,
|
|
252
|
+
lng: (from.lng + to.lng) / 2,
|
|
253
|
+
lat: (from.lat + to.lat) / 2,
|
|
254
|
+
label: pipe.id
|
|
255
|
+
}
|
|
256
|
+
];
|
|
257
|
+
})
|
|
258
|
+
);
|
|
259
|
+
const durationMs = (typeof performance !== "undefined" ? performance.now() : Date.now()) - t0;
|
|
260
|
+
const result = { scores, heatmap, maintenance, durationMs };
|
|
261
|
+
this.lastResult = result;
|
|
262
|
+
this.renderHeatmap(result);
|
|
263
|
+
for (const l of this.listeners) l(result);
|
|
264
|
+
return result;
|
|
265
|
+
}
|
|
266
|
+
/** 清空图层 */
|
|
267
|
+
clear() {
|
|
268
|
+
for (const id of this.layerIds) {
|
|
269
|
+
this.map.removeLayer(id);
|
|
270
|
+
}
|
|
271
|
+
this.layerIds = [];
|
|
272
|
+
}
|
|
273
|
+
/** 销毁 */
|
|
274
|
+
destroy() {
|
|
275
|
+
this.clear();
|
|
276
|
+
this.listeners.clear();
|
|
277
|
+
this.lastResult = null;
|
|
278
|
+
}
|
|
279
|
+
/** 订阅结果 */
|
|
280
|
+
onResult(fn) {
|
|
281
|
+
this.listeners.add(fn);
|
|
282
|
+
return () => this.listeners.delete(fn);
|
|
283
|
+
}
|
|
284
|
+
/** 取最后一次结果 */
|
|
285
|
+
getLastResult() {
|
|
286
|
+
return this.lastResult;
|
|
287
|
+
}
|
|
288
|
+
renderHeatmap(result) {
|
|
289
|
+
this.clear();
|
|
290
|
+
const mlMap = this.map.instance;
|
|
291
|
+
const data = heatmapToGeoJSON(result.heatmap);
|
|
292
|
+
const sourceId = `${this.layerPrefix}-heat-src`;
|
|
293
|
+
const layerId = `${this.layerPrefix}-heat-point`;
|
|
294
|
+
if (!mlMap.getSource(sourceId)) mlMap.addSource(sourceId, data);
|
|
295
|
+
try {
|
|
296
|
+
mlMap.addLayer({
|
|
297
|
+
id: layerId,
|
|
298
|
+
type: "heatmap",
|
|
299
|
+
source: sourceId,
|
|
300
|
+
paint: {
|
|
301
|
+
"heatmap-weight": [
|
|
302
|
+
"interpolate",
|
|
303
|
+
["linear"],
|
|
304
|
+
["get", "healthScore"],
|
|
305
|
+
0,
|
|
306
|
+
1,
|
|
307
|
+
50,
|
|
308
|
+
0.5,
|
|
309
|
+
100,
|
|
310
|
+
0
|
|
311
|
+
],
|
|
312
|
+
"heatmap-intensity": 1,
|
|
313
|
+
"heatmap-color": [
|
|
314
|
+
"interpolate",
|
|
315
|
+
["linear"],
|
|
316
|
+
["heatmap-density"],
|
|
317
|
+
0,
|
|
318
|
+
"rgba(34,197,94,0)",
|
|
319
|
+
0.2,
|
|
320
|
+
"rgba(34,197,94,0.5)",
|
|
321
|
+
0.5,
|
|
322
|
+
"rgba(245,158,11,0.7)",
|
|
323
|
+
0.8,
|
|
324
|
+
"rgba(239,68,68,0.8)",
|
|
325
|
+
1,
|
|
326
|
+
"rgba(127,29,29,0.9)"
|
|
327
|
+
],
|
|
328
|
+
"heatmap-radius": 25,
|
|
329
|
+
"heatmap-opacity": 0.7
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
this.layerIds.push(layerId);
|
|
333
|
+
} catch {
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
export { DEFAULT_WEIGHTS, PipelineHealth, aggregateHeatmap, heatmapToGeoJSON, prioritizeMaintenance, scorePipeHealth, scorePipes };
|
|
339
|
+
//# sourceMappingURL=chunk-VA2TQWL3.js.map
|
|
340
|
+
//# sourceMappingURL=chunk-VA2TQWL3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/health/healthScorer.ts","../src/health/riskHeatmap.ts","../src/health/PipelineHealth.ts"],"names":[],"mappings":"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","file":"chunk-VA2TQWL3.js","sourcesContent":["/**\n * 管线健康度评分(healthScorer)\n *\n * 6 维加权评分(PRD §4.4.2):\n * health_score = age (0.25) + material (0.20) + soil (0.15) +\n * history (0.20) + pressure (0.10) + protection (0.10)\n *\n * 每维 0-100,最终加权求和。\n * 评分模型可解释:每个维度的评分依据清晰可见。\n */\n\nimport type { PipeMaterial, PipeStatus } from '../types';\n\nexport interface PipeHealthInput {\n /** 安装日期 ISO */\n installDate?: string;\n /** 材质 */\n material?: PipeMaterial;\n /** 当前故障次数 */\n failureCount?: number;\n /** 当前压力(MPa) */\n pressure?: number;\n /** 最高允许压力(MPa) */\n ratedPressure?: number;\n /** 是否阴极保护 */\n hasCathodicProtection?: boolean;\n /** 土壤腐蚀指数 0-1(无数据时 0.5) */\n soilCorrosion?: number;\n /** 状态(damaged / under_repair 直接影响评分) */\n status?: PipeStatus;\n}\n\nexport interface PipeHealthScore {\n /** 总分 0-100 */\n score: number;\n /** 等级 */\n level: 'excellent' | 'good' | 'fair' | 'poor' | 'critical';\n /** 6 维细分 */\n dimensions: {\n age: { score: number; weight: number; reason: string };\n material: { score: number; weight: number; reason: string };\n soil: { score: number; weight: number; reason: string };\n history: { score: number; weight: number; reason: string };\n pressure: { score: number; weight: number; reason: string };\n protection: { score: number; weight: number; reason: string };\n };\n}\n\n/** 默认权重 */\nexport const DEFAULT_WEIGHTS = {\n age: 0.25,\n material: 0.2,\n soil: 0.15,\n history: 0.2,\n pressure: 0.1,\n protection: 0.1,\n};\n\nconst MATERIAL_RISK: Record<PipeMaterial, number> = {\n cast_iron: 0.85, // 铸铁 = 高风险(旧管网)\n ductile_iron: 0.2, // 球墨铸铁\n steel: 0.4,\n pe: 0.1,\n pvc: 0.15,\n concrete: 0.3,\n hdpe: 0.05,\n copper: 0.1,\n unknown: 0.5,\n};\n\n/**\n * 计算单根管线的健康度\n */\nexport function scorePipeHealth(input: PipeHealthInput, weights = DEFAULT_WEIGHTS): PipeHealthScore {\n const dims = {\n age: scoreAge(input, weights.age),\n material: scoreMaterial(input, weights.material),\n soil: scoreSoil(input, weights.soil),\n history: scoreHistory(input, weights.history),\n pressure: scorePressure(input, weights.pressure),\n protection: scoreProtection(input, weights.protection),\n };\n\n const total =\n dims.age.score * dims.age.weight +\n dims.material.score * dims.material.weight +\n dims.soil.score * dims.soil.weight +\n dims.history.score * dims.history.weight +\n dims.pressure.score * dims.pressure.weight +\n dims.protection.score * dims.protection.weight;\n\n // 损坏或维修中额外惩罚\n let final = total;\n if (input.status === 'damaged') final *= 0.5;\n else if (input.status === 'under_repair') final *= 0.7;\n else if (input.status === 'abandoned') final = 0;\n\n return {\n score: Math.round(final),\n level: toLevel(final),\n dimensions: dims,\n };\n}\n\nfunction toLevel(score: number): PipeHealthScore['level'] {\n if (score >= 80) return 'excellent';\n if (score >= 60) return 'good';\n if (score >= 40) return 'fair';\n if (score >= 20) return 'poor';\n return 'critical';\n}\n\nfunction scoreAge(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['age'] {\n if (!input.installDate) {\n return { score: 50, weight, reason: '未知安装日期,按中等计' };\n }\n const ageYears = (Date.now() - new Date(input.installDate).getTime()) / (365.25 * 24 * 3600 * 1000);\n if (ageYears < 0) return { score: 100, weight, reason: '未来日期,视为优秀' };\n if (ageYears < 5) return { score: 100, weight, reason: '新建管线 (<5年)' };\n if (ageYears < 15) return { score: 85, weight, reason: '较新 (5-15年)' };\n if (ageYears < 25) return { score: 65, weight, reason: '中龄 (15-25年)' };\n if (ageYears < 40) return { score: 40, weight, reason: '老龄 (25-40年)' };\n if (ageYears < 60) return { score: 20, weight, reason: '超期 (>40年)' };\n return { score: 5, weight, reason: '超期 (>60年)' };\n}\n\nfunction scoreMaterial(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['material'] {\n if (!input.material) {\n return { score: 50, weight, reason: '未知材质,按中等计' };\n }\n const risk = MATERIAL_RISK[input.material] ?? 0.5;\n const score = Math.round((1 - risk) * 100);\n const labels: Record<string, string> = {\n cast_iron: '铸铁(高风险)',\n ductile_iron: '球墨铸铁',\n steel: '钢',\n pe: 'PE(低风险)',\n pvc: 'PVC',\n concrete: '混凝土',\n hdpe: 'HDPE(最佳)',\n copper: '铜',\n unknown: '未知',\n };\n return {\n score,\n weight,\n reason: labels[input.material] ?? input.material,\n };\n}\n\nfunction scoreSoil(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['soil'] {\n const c = input.soilCorrosion ?? 0.5;\n const score = Math.round((1 - c) * 100);\n return {\n score,\n weight,\n reason: c === 0.5 && !input.soilCorrosion ? '无土壤数据,按平均计' : `土壤腐蚀指数 ${c.toFixed(2)}`,\n };\n}\n\nfunction scoreHistory(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['history'] {\n const fail = input.failureCount ?? 0;\n if (fail === 0) return { score: 100, weight, reason: '历史无故障' };\n if (fail === 1) return { score: 75, weight, reason: '历史 1 次故障' };\n if (fail === 2) return { score: 50, weight, reason: '历史 2 次故障' };\n if (fail === 3) return { score: 25, weight, reason: '历史 3 次故障' };\n return { score: 0, weight, reason: `历史 ≥${fail} 次故障` };\n}\n\nfunction scorePressure(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['pressure'] {\n if (!input.pressure) {\n return { score: 75, weight, reason: '无压力数据,按中等偏好计' };\n }\n if (!input.ratedPressure) {\n return { score: 75, weight, reason: '仅知当前压力' };\n }\n const ratio = input.pressure / input.ratedPressure;\n if (ratio < 0.5) return { score: 60, weight, reason: '压力偏低 (使用率 <50%)' };\n if (ratio < 0.8) return { score: 90, weight, reason: '压力正常 (使用率 50-80%)' };\n if (ratio < 1.0) return { score: 75, weight, reason: '压力偏高 (使用率 80-100%)' };\n if (ratio < 1.2) return { score: 30, weight, reason: '压力超限 (100-120%)' };\n return { score: 0, weight, reason: '压力严重超限 (>120%)' };\n}\n\nfunction scoreProtection(input: PipeHealthInput, weight: number): PipeHealthScore['dimensions']['protection'] {\n if (input.hasCathodicProtection === true) {\n return { score: 90, weight, reason: '有阴极保护' };\n }\n if (input.hasCathodicProtection === false) {\n return { score: 30, weight, reason: '无阴极保护' };\n }\n return { score: 50, weight, reason: '阴保状态未知' };\n}\n\n/**\n * 批量评分(按需遍历)\n */\nexport function scorePipes(inputs: PipeHealthInput[], weights = DEFAULT_WEIGHTS): PipeHealthScore[] {\n return inputs.map((i) => scorePipeHealth(i, weights));\n}\n","/**\n * 风险热力图(riskHeatmap)\n *\n * 把 scorePipeHealth 输出按地理网格聚合,输出每个网格的平均分/最高风险,\n * 用于地图热力图(heat-map layer)。\n *\n * 输入:管线数组 [{ lng, lat, healthScore }]\n * 输出:GeoJSON FeatureCollection<Point>(含 healthScore 属性)\n */\n\nexport interface HeatmapCell {\n lng: number;\n lat: number;\n healthScore: number;\n /** 网格内管段数 */\n pipeCount: number;\n}\n\nexport interface PipeHealthPoint {\n lng: number;\n lat: number;\n healthScore: number;\n}\n\nexport interface RiskHeatmapOptions {\n /** 网格尺寸(m),默认 500 */\n cellSize?: number;\n /** 聚合方式 */\n aggregation?: 'average' | 'min' | 'max';\n}\n\nexport function aggregateHeatmap(\n points: PipeHealthPoint[],\n options: RiskHeatmapOptions = {}\n): HeatmapCell[] {\n const cell = options.cellSize ?? 500;\n const agg = options.aggregation ?? 'average';\n\n // 经纬度 → 米近似(以第一个点为原点)\n if (points.length === 0) return [];\n\n const refLat = points[0].lat;\n const refLng = points[0].lng;\n const mPerDegLat = 110_540;\n const mPerDegLng = 111_320 * Math.cos((refLat * Math.PI) / 180);\n\n const grid = new Map<string, { acc: number; count: number; minS: number; maxS: number; lng: number; lat: number }>();\n for (const p of points) {\n const x = (p.lng - refLng) * mPerDegLng;\n const y = (p.lat - refLat) * mPerDegLat;\n const cx = Math.floor(x / cell);\n const cy = Math.floor(y / cell);\n const key = `${cx}:${cy}`;\n const cur = grid.get(key);\n if (!cur) {\n grid.set(key, {\n acc: p.healthScore,\n count: 1,\n minS: p.healthScore,\n maxS: p.healthScore,\n lng: p.lng,\n lat: p.lat,\n });\n } else {\n cur.acc += p.healthScore;\n cur.count += 1;\n if (p.healthScore < cur.minS) cur.minS = p.healthScore;\n if (p.healthScore > cur.maxS) cur.maxS = p.healthScore;\n cur.lng = (cur.lng * (cur.count - 1) + p.lng) / cur.count;\n cur.lat = (cur.lat * (cur.count - 1) + p.lat) / cur.count;\n }\n }\n\n const cells: HeatmapCell[] = [];\n for (const v of grid.values()) {\n let score: number;\n if (agg === 'min') score = v.minS;\n else if (agg === 'max') score = v.maxS;\n else score = v.acc / v.count;\n cells.push({\n lng: v.lng,\n lat: v.lat,\n healthScore: Math.round(score),\n pipeCount: v.count,\n });\n }\n return cells;\n}\n\nexport function heatmapToGeoJSON(cells: HeatmapCell[]): GeoJSON.FeatureCollection<GeoJSON.Point> {\n return {\n type: 'FeatureCollection',\n features: cells.map((c) => ({\n type: 'Feature',\n geometry: { type: 'Point', coordinates: [c.lng, c.lat] },\n properties: {\n healthScore: c.healthScore,\n pipeCount: c.pipeCount,\n },\n })),\n };\n}\n\n/** 优先维护建议列表(风险最高的 Top N 管线) */\nexport function prioritizeMaintenance(\n pipes: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>,\n topN = 10\n) {\n return [...pipes].sort((a, b) => a.healthScore - b.healthScore).slice(0, topN);\n}\n","/**\n * PipelineHealth 组件类(地图集成层)\n */\n\nimport type { Map as CaoguoMap } from '@caoguo/maplibre';\nimport { scorePipeHealth, type PipeHealthInput, type PipeHealthScore, DEFAULT_WEIGHTS } from './healthScorer';\nimport { aggregateHeatmap, heatmapToGeoJSON, type HeatmapCell, prioritizeMaintenance } from './riskHeatmap';\nimport type { PipelineTopologyDataset } from '../types';\n\nexport interface PipelineHealthOptions {\n map: CaoguoMap;\n dataset: PipelineTopologyDataset;\n cellSize?: number;\n layerPrefix?: string;\n}\n\nexport interface HealthResult {\n /** 全部管段评分 */\n scores: Array<{ pipeId: string; score: PipeHealthScore }>;\n /** 热力图聚合格 */\n heatmap: HeatmapCell[];\n /** 优先维护建议 */\n maintenance: Array<{ id: string; healthScore: number; lng: number; lat: number; label?: string }>;\n /** 计算耗时 */\n durationMs: number;\n}\n\ntype Listener = (r: HealthResult) => void;\n\n/**\n * 管线健康评估组件\n */\nexport class PipelineHealth {\n private map: CaoguoMap;\n private dataset: PipelineTopologyDataset;\n private cellSize: number;\n private layerPrefix: string;\n private listeners = new Set<Listener>();\n private lastResult: HealthResult | null = null;\n private layerIds: string[] = [];\n\n constructor(options: PipelineHealthOptions) {\n this.map = options.map;\n this.dataset = options.dataset;\n this.cellSize = options.cellSize ?? 500;\n this.layerPrefix = options.layerPrefix ?? 'cg-health';\n }\n\n /** 评估全网管线健康度 */\n evaluate(weights = DEFAULT_WEIGHTS): HealthResult {\n const t0 = (typeof performance !== 'undefined' ? performance.now() : Date.now());\n const nodeById = new Map(this.dataset.nodes.map((n) => [n.id, n] as const));\n\n const scores = this.dataset.pipes.map((p) => {\n const input: PipeHealthInput = {\n installDate: p.properties?.installDate,\n material: p.properties?.material,\n failureCount: undefined,\n pressure: p.properties?.pressure,\n ratedPressure: p.properties?.ratedPressure,\n hasCathodicProtection: undefined,\n status: p.properties?.status,\n };\n return { pipeId: p.id, score: scorePipeHealth(input, weights) };\n });\n\n const points = scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n healthScore: s.score.score,\n },\n ];\n });\n\n const heatmap = aggregateHeatmap(points, { cellSize: this.cellSize });\n const maintenance = prioritizeMaintenance(\n scores.flatMap((s, i) => {\n const pipe = this.dataset.pipes[i];\n const from = nodeById.get(pipe.fromNode);\n const to = nodeById.get(pipe.toNode);\n if (!from || !to) return [];\n return [\n {\n id: pipe.id,\n healthScore: s.score.score,\n lng: (from.lng + to.lng) / 2,\n lat: (from.lat + to.lat) / 2,\n label: pipe.id,\n },\n ];\n })\n );\n\n const durationMs =\n (typeof performance !== 'undefined' ? performance.now() : Date.now()) - t0;\n\n const result: HealthResult = { scores, heatmap, maintenance, durationMs };\n this.lastResult = result;\n this.renderHeatmap(result);\n for (const l of this.listeners) l(result);\n return result;\n }\n\n /** 清空图层 */\n clear(): void {\n for (const id of this.layerIds) {\n this.map.removeLayer(id);\n }\n this.layerIds = [];\n }\n\n /** 销毁 */\n destroy(): void {\n this.clear();\n this.listeners.clear();\n this.lastResult = null;\n }\n\n /** 订阅结果 */\n onResult(fn: Listener): () => void {\n this.listeners.add(fn);\n return () => this.listeners.delete(fn);\n }\n\n /** 取最后一次结果 */\n getLastResult(): HealthResult | null {\n return this.lastResult;\n }\n\n private renderHeatmap(result: HealthResult): void {\n this.clear();\n const mlMap = (this.map as unknown as {\n instance: {\n addSource: (id: string, source: unknown) => void;\n addLayer: (layer: unknown) => void;\n getSource: (id: string) => unknown;\n };\n }).instance;\n const data = heatmapToGeoJSON(result.heatmap);\n const sourceId = `${this.layerPrefix}-heat-src`;\n const layerId = `${this.layerPrefix}-heat-point`;\n if (!mlMap.getSource(sourceId)) mlMap.addSource(sourceId, data);\n try {\n mlMap.addLayer({\n id: layerId,\n type: 'heatmap',\n source: sourceId,\n paint: {\n 'heatmap-weight': [\n 'interpolate',\n ['linear'],\n ['get', 'healthScore'],\n 0, 1,\n 50, 0.5,\n 100, 0,\n ] as unknown,\n 'heatmap-intensity': 1,\n 'heatmap-color': [\n 'interpolate',\n ['linear'],\n ['heatmap-density'],\n 0, 'rgba(34,197,94,0)',\n 0.2, 'rgba(34,197,94,0.5)',\n 0.5, 'rgba(245,158,11,0.7)',\n 0.8, 'rgba(239,68,68,0.8)',\n 1, 'rgba(127,29,29,0.9)',\n ] as unknown,\n 'heatmap-radius': 25,\n 'heatmap-opacity': 0.7,\n },\n });\n this.layerIds.push(layerId);\n } catch {\n // ignore\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// src/nlpg/pipelineNlp.ts
|
|
2
|
+
var PATTERNS = [
|
|
3
|
+
{ intent: "burst", re: /(爆管|破裂|泄漏|故障|事故|爆裂)/, confidence: 0.95 },
|
|
4
|
+
{ intent: "valve", re: /(阀门|闸).*?(关闭|关|合)|(?:关闭|关|合).*?(阀门|闸)/, confidence: 0.9 },
|
|
5
|
+
{ intent: "material_age", re: /(\d+)\s*年.*?(铸铁|钢|PE|PVC|铜)/, confidence: 0.85 },
|
|
6
|
+
{ intent: "material_age", re: /(铸铁|钢|PE|PVC|铜).*?(\d+)\s*年/, confidence: 0.85 },
|
|
7
|
+
{ intent: "pressure", re: /压力.*?(低于|高于|小于|大于|<|>|>=|<=|低|高)\s*(\d+\.?\d*)/, confidence: 0.85 },
|
|
8
|
+
{ intent: "nearby", re: /(\d+)\s*(米|m|公里|km).*?(学校|医院|工厂|消防|政府|小区)/, confidence: 0.85 },
|
|
9
|
+
{ intent: "alarm_cluster", re: /报警|告警/, confidence: 0.8 }
|
|
10
|
+
];
|
|
11
|
+
var TYPE_REGEX = [
|
|
12
|
+
{ type: "gas", re: /燃气|煤气|天然气/ },
|
|
13
|
+
{ type: "water", re: /供水|自来水|水管/ },
|
|
14
|
+
{ type: "drainage", re: /排水|污水|雨水/ },
|
|
15
|
+
{ type: "heating", re: /供热|暖气|热力/ },
|
|
16
|
+
{ type: "power", re: /电力|电缆|高压/ },
|
|
17
|
+
{ type: "telecom", re: /通信|光纤|光缆/ }
|
|
18
|
+
];
|
|
19
|
+
var MATERIAL_REGEX = [
|
|
20
|
+
{ key: "cast_iron", cname: "\u94F8\u94C1", re: /铸铁/ },
|
|
21
|
+
{ key: "ductile_iron", cname: "\u7403\u58A8\u94F8\u94C1", re: /球墨/ },
|
|
22
|
+
{ key: "steel", cname: "\u94A2", re: /钢/ },
|
|
23
|
+
{ key: "pe", cname: "PE", re: /PE/ },
|
|
24
|
+
{ key: "pvc", cname: "PVC", re: /PVC/ },
|
|
25
|
+
{ key: "concrete", cname: "\u6DF7\u51DD\u571F", re: /混凝土/ },
|
|
26
|
+
{ key: "hdpe", cname: "HDPE", re: /HDPE/ },
|
|
27
|
+
{ key: "copper", cname: "\u94DC", re: /铜/ }
|
|
28
|
+
];
|
|
29
|
+
var REGION_REGEX = /(朝阳区|海淀区|江岸区|江汉区|硚口区|汉阳区|武昌区|青山区|洪山区|东西湖区|黄陂区|新洲区|江夏区|蔡甸区|汉南区)/;
|
|
30
|
+
function parsePipelineQuery(query) {
|
|
31
|
+
let best = { intent: "unknown", confidence: 0 };
|
|
32
|
+
for (const p of PATTERNS) {
|
|
33
|
+
const m = query.match(p.re);
|
|
34
|
+
if (m) {
|
|
35
|
+
const c = p.confidence * (1 + 0.05 * (m[0].length / query.length));
|
|
36
|
+
if (c > best.confidence) best = { intent: p.intent, confidence: Math.min(c, 1) };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
const filters = {};
|
|
40
|
+
for (const t of TYPE_REGEX) {
|
|
41
|
+
if (t.re.test(query)) {
|
|
42
|
+
filters.pipelineType = t.type;
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
for (const m of MATERIAL_REGEX) {
|
|
47
|
+
if (m.re.test(query)) {
|
|
48
|
+
filters.material = m.key;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const ageMatch = query.match(/(\d+)\s*年/);
|
|
53
|
+
if (ageMatch) {
|
|
54
|
+
const years = parseInt(ageMatch[1]);
|
|
55
|
+
if (best.intent === "material_age") {
|
|
56
|
+
if (/超[过于]/.test(query) || /[以]?上/.test(query)) filters.minAgeYears = years;
|
|
57
|
+
else if (/内|以下|不超/.test(query)) filters.maxAgeYears = years;
|
|
58
|
+
else filters.minAgeYears = years;
|
|
59
|
+
} else {
|
|
60
|
+
filters.minAgeYears = years;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const pressureMatch = query.match(/(\d+\.?\d*)\s*(MPa|mpa)/);
|
|
64
|
+
if (pressureMatch) {
|
|
65
|
+
const v = parseFloat(pressureMatch[1]);
|
|
66
|
+
if (/低|小于|小于等于|</.test(query)) filters.maxPressure = v;
|
|
67
|
+
else if (/高|大于|大于等于|>/.test(query)) filters.minPressure = v;
|
|
68
|
+
else filters.maxPressure = v;
|
|
69
|
+
} else if (/压力/.test(query)) {
|
|
70
|
+
filters.maxPressure = 0.2;
|
|
71
|
+
}
|
|
72
|
+
const distMatch = query.match(/(\d+)\s*(公里|km|千米|米|m)/);
|
|
73
|
+
if (distMatch) {
|
|
74
|
+
let d = parseInt(distMatch[1]);
|
|
75
|
+
const unit = distMatch[2];
|
|
76
|
+
if (/公里|km|千米/.test(unit)) d *= 1e3;
|
|
77
|
+
filters.radius = d;
|
|
78
|
+
}
|
|
79
|
+
if (/昨天/.test(query)) filters.timeWindow = "1d";
|
|
80
|
+
else if (/今天/.test(query)) filters.timeWindow = "1d";
|
|
81
|
+
else if (/最近一周|过去一周|7\s*天/.test(query)) filters.timeWindow = "7d";
|
|
82
|
+
else if (/最近一个月/.test(query)) filters.timeWindow = "30d";
|
|
83
|
+
const regionMatch = query.match(REGION_REGEX);
|
|
84
|
+
if (regionMatch) filters.region = regionMatch[1];
|
|
85
|
+
return {
|
|
86
|
+
intent: best.intent,
|
|
87
|
+
filters,
|
|
88
|
+
description: buildDescription(best.intent, filters),
|
|
89
|
+
confidence: best.confidence
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function buildDescription(intent, f) {
|
|
93
|
+
const desc = [];
|
|
94
|
+
if (intent === "burst") desc.push("\u89E6\u53D1\u7206\u7BA1\u63A8\u6F14");
|
|
95
|
+
else if (intent === "valve") desc.push("\u67E5\u8BE2\u9600\u95E8\u5173\u95ED\u5F71\u54CD");
|
|
96
|
+
else if (intent === "material_age") {
|
|
97
|
+
const matName = MATERIAL_REGEX.find((m) => m.key === f.material)?.cname ?? f.material ?? "";
|
|
98
|
+
desc.push(`\u7B5B\u9009${matName}\u7BA1${f.minAgeYears ?? "?"}\u5E74\u4EE5\u4E0A`);
|
|
99
|
+
} else if (intent === "pressure") desc.push(`\u7B5B\u9009\u538B\u529B${f.maxPressure ?? ""}MPa\u4EE5\u4E0B`);
|
|
100
|
+
else if (intent === "nearby") desc.push(`${f.radius}m\u5185\u67E5\u627EPOI`);
|
|
101
|
+
else if (intent === "alarm_cluster") desc.push(`\u67E5\u8BE2${f.timeWindow ?? "1d"}\u5185\u62A5\u8B66\u805A\u96C6`);
|
|
102
|
+
if (f.pipelineType) desc.push(`[${f.pipelineType}]`);
|
|
103
|
+
if (f.region) desc.push(`\u533A\u57DF:${f.region}`);
|
|
104
|
+
return desc.join(" ");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/nlpg/pipelineNlpClass.ts
|
|
108
|
+
var PipelineNlp = class {
|
|
109
|
+
burstSimulator;
|
|
110
|
+
onIntent;
|
|
111
|
+
constructor(options = {}) {
|
|
112
|
+
this.burstSimulator = options.burstSimulator;
|
|
113
|
+
this.onIntent = options.onIntent;
|
|
114
|
+
}
|
|
115
|
+
/** 解析并按意图触发动作 */
|
|
116
|
+
query(text) {
|
|
117
|
+
const result = parsePipelineQuery(text);
|
|
118
|
+
if (this.onIntent) this.onIntent(result.intent, result);
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
/** 仅解析不触发动作 */
|
|
122
|
+
parse(text) {
|
|
123
|
+
return parsePipelineQuery(text);
|
|
124
|
+
}
|
|
125
|
+
/** 关联 BurstSimulator */
|
|
126
|
+
setBurstSimulator(sim) {
|
|
127
|
+
this.burstSimulator = sim;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export { PipelineNlp, parsePipelineQuery };
|
|
132
|
+
//# sourceMappingURL=chunk-YBLESEN4.js.map
|
|
133
|
+
//# sourceMappingURL=chunk-YBLESEN4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/nlpg/pipelineNlp.ts","../src/nlpg/pipelineNlpClass.ts"],"names":[],"mappings":"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","file":"chunk-YBLESEN4.js","sourcesContent":["/**\n * NLPG 管网场景扩展(Phase 1)\n */\nimport type { PipelineType } from '../types';\n\nexport type PipelineNlpIntent =\n | 'burst'\n | 'valve'\n | 'material_age'\n | 'pressure'\n | 'nearby'\n | 'alarm_cluster'\n | 'unknown';\n\nexport interface PipelineNlpFilters {\n pipelineType?: PipelineType;\n material?: string;\n minAgeYears?: number;\n maxAgeYears?: number;\n minPressure?: number;\n maxPressure?: number;\n radius?: number;\n timeWindow?: '1h' | '1d' | '7d' | '30d';\n region?: string;\n}\n\nexport interface PipelineNlpResult {\n intent: PipelineNlpIntent;\n filters: PipelineNlpFilters;\n description: string;\n confidence: number;\n}\n\nconst PATTERNS: Array<{ intent: PipelineNlpIntent; re: RegExp; confidence: number }> = [\n { intent: 'burst', re: /(爆管|破裂|泄漏|故障|事故|爆裂)/, confidence: 0.95 },\n { intent: 'valve', re: /(阀门|闸).*?(关闭|关|合)|(?:关闭|关|合).*?(阀门|闸)/, confidence: 0.9 },\n { intent: 'material_age', re: /(\\d+)\\s*年.*?(铸铁|钢|PE|PVC|铜)/, confidence: 0.85 },\n { intent: 'material_age', re: /(铸铁|钢|PE|PVC|铜).*?(\\d+)\\s*年/, confidence: 0.85 },\n { intent: 'pressure', re: /压力.*?(低于|高于|小于|大于|<|>|>=|<=|低|高)\\s*(\\d+\\.?\\d*)/, confidence: 0.85 },\n { intent: 'nearby', re: /(\\d+)\\s*(米|m|公里|km).*?(学校|医院|工厂|消防|政府|小区)/, confidence: 0.85 },\n { intent: 'alarm_cluster', re: /报警|告警/, confidence: 0.8 },\n];\n\nconst TYPE_REGEX: Array<{ type: PipelineType; re: RegExp }> = [\n { type: 'gas', re: /燃气|煤气|天然气/ },\n { type: 'water', re: /供水|自来水|水管/ },\n { type: 'drainage', re: /排水|污水|雨水/ },\n { type: 'heating', re: /供热|暖气|热力/ },\n { type: 'power', re: /电力|电缆|高压/ },\n { type: 'telecom', re: /通信|光纤|光缆/ },\n];\n\nconst MATERIAL_REGEX: Array<{ key: string; re: RegExp; cname: string }> = [\n { key: 'cast_iron', cname: '铸铁', re: /铸铁/ },\n { key: 'ductile_iron', cname: '球墨铸铁', re: /球墨/ },\n { key: 'steel', cname: '钢', re: /钢/ },\n { key: 'pe', cname: 'PE', re: /PE/ },\n { key: 'pvc', cname: 'PVC', re: /PVC/ },\n { key: 'concrete', cname: '混凝土', re: /混凝土/ },\n { key: 'hdpe', cname: 'HDPE', re: /HDPE/ },\n { key: 'copper', cname: '铜', re: /铜/ },\n];\n\nconst REGION_REGEX = /(朝阳区|海淀区|江岸区|江汉区|硚口区|汉阳区|武昌区|青山区|洪山区|东西湖区|黄陂区|新洲区|江夏区|蔡甸区|汉南区)/;\n\nexport function parsePipelineQuery(query: string): PipelineNlpResult {\n let best: { intent: PipelineNlpIntent; confidence: number } = { intent: 'unknown', confidence: 0 };\n for (const p of PATTERNS) {\n const m = query.match(p.re);\n if (m) {\n const c = p.confidence * (1 + 0.05 * (m[0].length / query.length));\n if (c > best.confidence) best = { intent: p.intent, confidence: Math.min(c, 1) };\n }\n }\n\n const filters: PipelineNlpFilters = {};\n for (const t of TYPE_REGEX) {\n if (t.re.test(query)) {\n filters.pipelineType = t.type;\n break;\n }\n }\n for (const m of MATERIAL_REGEX) {\n if (m.re.test(query)) {\n filters.material = m.key;\n break;\n }\n }\n const ageMatch = query.match(/(\\d+)\\s*年/);\n if (ageMatch) {\n const years = parseInt(ageMatch[1]);\n if (best.intent === 'material_age') {\n if (/超[过于]/.test(query) || /[以]?上/.test(query)) filters.minAgeYears = years;\n else if (/内|以下|不超/.test(query)) filters.maxAgeYears = years;\n else filters.minAgeYears = years;\n } else {\n filters.minAgeYears = years;\n }\n }\n const pressureMatch = query.match(/(\\d+\\.?\\d*)\\s*(MPa|mpa)/);\n if (pressureMatch) {\n const v = parseFloat(pressureMatch[1]);\n if (/低|小于|小于等于|</.test(query)) filters.maxPressure = v;\n else if (/高|大于|大于等于|>/.test(query)) filters.minPressure = v;\n else filters.maxPressure = v;\n } else if (/压力/.test(query)) {\n filters.maxPressure = 0.2; // 默认低压阈值\n }\n const distMatch = query.match(/(\\d+)\\s*(公里|km|千米|米|m)/);\n if (distMatch) {\n let d = parseInt(distMatch[1]);\n const unit = distMatch[2];\n if (/公里|km|千米/.test(unit)) d *= 1000;\n filters.radius = d;\n }\n if (/昨天/.test(query)) filters.timeWindow = '1d';\n else if (/今天/.test(query)) filters.timeWindow = '1d';\n else if (/最近一周|过去一周|7\\s*天/.test(query)) filters.timeWindow = '7d';\n else if (/最近一个月/.test(query)) filters.timeWindow = '30d';\n const regionMatch = query.match(REGION_REGEX);\n if (regionMatch) filters.region = regionMatch[1];\n\n return {\n intent: best.intent,\n filters,\n description: buildDescription(best.intent, filters),\n confidence: best.confidence,\n };\n}\n\nfunction buildDescription(intent: PipelineNlpIntent, f: PipelineNlpFilters): string {\n const desc: string[] = [];\n if (intent === 'burst') desc.push('触发爆管推演');\n else if (intent === 'valve') desc.push('查询阀门关闭影响');\n else if (intent === 'material_age') {\n const matName = MATERIAL_REGEX.find((m) => m.key === f.material)?.cname ?? f.material ?? '';\n desc.push(`筛选${matName}管${f.minAgeYears ?? '?'}年以上`);\n } else if (intent === 'pressure') desc.push(`筛选压力${f.maxPressure ?? ''}MPa以下`);\n else if (intent === 'nearby') desc.push(`${f.radius}m内查找POI`);\n else if (intent === 'alarm_cluster') desc.push(`查询${f.timeWindow ?? '1d'}内报警聚集`);\n if (f.pipelineType) desc.push(`[${f.pipelineType}]`);\n if (f.region) desc.push(`区域:${f.region}`);\n return desc.join(' ');\n}\n","/**\n * PipelineNlp 组件类(占位 stub)\n *\n * 包装 parsePipelineQuery + 与 BurstSimulator 路由集成\n */\n\nimport { parsePipelineQuery, type PipelineNlpResult, type PipelineNlpIntent } from './pipelineNlp';\nimport type { BurstSimulator } from '../burst/burstClass';\n\nexport interface PipelineNlpOptions {\n burstSimulator?: BurstSimulator;\n onIntent?: (intent: PipelineNlpIntent, result: PipelineNlpResult) => void;\n}\n\nexport class PipelineNlp {\n private burstSimulator?: BurstSimulator;\n private onIntent?: PipelineNlpOptions['onIntent'];\n\n constructor(options: PipelineNlpOptions = {}) {\n this.burstSimulator = options.burstSimulator;\n this.onIntent = options.onIntent;\n }\n\n /** 解析并按意图触发动作 */\n query(text: string): PipelineNlpResult {\n const result = parsePipelineQuery(text);\n if (this.onIntent) this.onIntent(result.intent, result);\n return result;\n }\n\n /** 仅解析不触发动作 */\n parse(text: string): PipelineNlpResult {\n return parsePipelineQuery(text);\n }\n\n /** 关联 BurstSimulator */\n setBurstSimulator(sim: BurstSimulator): void {\n this.burstSimulator = sim;\n }\n}\n"]}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { PIPELINE_TYPE_COLORS, PIPELINE_TYPE_LABELS, PIPE_STATUS_COLORS, PIPE_STATUS_META, PIPE_MATERIAL_COLORS, HEALTH_LEVEL_COLORS, HEALTH_LEVEL_LABELS } from './chunk-QVY4WJLM.js';
|
|
2
|
+
|
|
3
|
+
// src/style/legend.ts
|
|
4
|
+
function legendByType() {
|
|
5
|
+
return {
|
|
6
|
+
title: "\u7BA1\u7EBF\u7C7B\u578B",
|
|
7
|
+
items: Object.keys(PIPELINE_TYPE_COLORS).map((k) => ({
|
|
8
|
+
label: PIPELINE_TYPE_LABELS[k],
|
|
9
|
+
color: PIPELINE_TYPE_COLORS[k]
|
|
10
|
+
}))
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function legendByDiameter() {
|
|
14
|
+
return {
|
|
15
|
+
title: "\u7BA1\u5F84\uFF08mm\uFF09",
|
|
16
|
+
items: [
|
|
17
|
+
{ label: "\u226450 \u652F\u7BA1", color: "#4ade80" },
|
|
18
|
+
{ label: "50-150 \u914D\u6C34/\u914D\u6C14", color: "#60a5fa" },
|
|
19
|
+
{ label: "150-300 \u5E72\u7BA1", color: "#f59e0b" },
|
|
20
|
+
{ label: "300-600 \u4E3B\u7BA1", color: "#ef4444" },
|
|
21
|
+
{ label: "\u2265600 \u4E3B\u5E72", color: "#7f1d1d" }
|
|
22
|
+
]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function legendByStatus() {
|
|
26
|
+
return {
|
|
27
|
+
title: "\u7BA1\u6BB5\u72B6\u6001",
|
|
28
|
+
items: Object.keys(PIPE_STATUS_COLORS).map(
|
|
29
|
+
(k) => {
|
|
30
|
+
const meta = PIPE_STATUS_META[k];
|
|
31
|
+
return {
|
|
32
|
+
label: meta.label,
|
|
33
|
+
color: PIPE_STATUS_COLORS[k],
|
|
34
|
+
style: meta.animation === "dashed" ? "dashed" : "solid"
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
)
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function legendByMaterial() {
|
|
41
|
+
return {
|
|
42
|
+
title: "\u7BA1\u6750",
|
|
43
|
+
items: Object.entries(PIPE_MATERIAL_COLORS).map(([k, v]) => ({
|
|
44
|
+
label: materialLabel(k),
|
|
45
|
+
color: v
|
|
46
|
+
}))
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
function legendByHealth() {
|
|
50
|
+
return {
|
|
51
|
+
title: "\u5065\u5EB7\u7B49\u7EA7",
|
|
52
|
+
items: Object.entries(HEALTH_LEVEL_COLORS).map(([k, v]) => ({
|
|
53
|
+
label: `${HEALTH_LEVEL_LABELS[k]}\uFF08${healthRangeLabel(k)}\uFF09`,
|
|
54
|
+
color: v
|
|
55
|
+
}))
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function materialLabel(k) {
|
|
59
|
+
const map = {
|
|
60
|
+
cast_iron: "\u94F8\u94C1",
|
|
61
|
+
ductile_iron: "\u7403\u58A8\u94F8\u94C1",
|
|
62
|
+
steel: "\u94A2",
|
|
63
|
+
pe: "PE",
|
|
64
|
+
pvc: "PVC",
|
|
65
|
+
concrete: "\u6DF7\u51DD\u571F",
|
|
66
|
+
hdpe: "HDPE",
|
|
67
|
+
copper: "\u94DC",
|
|
68
|
+
unknown: "\u672A\u77E5"
|
|
69
|
+
};
|
|
70
|
+
return map[k] ?? k;
|
|
71
|
+
}
|
|
72
|
+
function healthRangeLabel(k) {
|
|
73
|
+
const map = {
|
|
74
|
+
excellent: "80-100",
|
|
75
|
+
good: "60-80",
|
|
76
|
+
fair: "40-60",
|
|
77
|
+
poor: "20-40",
|
|
78
|
+
critical: "0-20"
|
|
79
|
+
};
|
|
80
|
+
return map[k] ?? "";
|
|
81
|
+
}
|
|
82
|
+
function buildLegend(mode) {
|
|
83
|
+
switch (mode) {
|
|
84
|
+
case "type":
|
|
85
|
+
return legendByType();
|
|
86
|
+
case "diameter":
|
|
87
|
+
return legendByDiameter();
|
|
88
|
+
case "status":
|
|
89
|
+
return legendByStatus();
|
|
90
|
+
case "material":
|
|
91
|
+
return legendByMaterial();
|
|
92
|
+
case "health":
|
|
93
|
+
return legendByHealth();
|
|
94
|
+
default:
|
|
95
|
+
return legendByType();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export { buildLegend, legendByDiameter, legendByHealth, legendByMaterial, legendByStatus, legendByType };
|
|
100
|
+
//# sourceMappingURL=chunk-YS2ICFVK.js.map
|
|
101
|
+
//# sourceMappingURL=chunk-YS2ICFVK.js.map
|