railwise-ai 1.2.32 → 1.2.34
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/agent-pack/README.md +16 -0
- package/agent-pack/assets/agent/chief_manager.md +69 -0
- package/agent-pack/assets/agent/commercial_specialist.md +47 -0
- package/agent-pack/assets/agent/data_analyst.md +54 -0
- package/agent-pack/assets/agent/docs.md +38 -0
- package/agent-pack/assets/agent/duplicate-pr.md +25 -0
- package/agent-pack/assets/agent/qa_inspector.md +58 -0
- package/agent-pack/assets/agent/qa_reviewer.md +57 -0
- package/agent-pack/assets/agent/solution_architect.md +53 -0
- package/agent-pack/assets/agent/technical_writer.md +61 -0
- package/agent-pack/assets/agent/translator.md +34 -0
- package/agent-pack/assets/agent/triage.md +139 -0
- package/agent-pack/assets/command/ai-deps.md +24 -0
- package/agent-pack/assets/command/bid-intel.md +29 -0
- package/agent-pack/assets/command/bid-prepare.md +24 -0
- package/agent-pack/assets/command/commit.md +37 -0
- package/agent-pack/assets/command/daily-report.md +26 -0
- package/agent-pack/assets/command/data-check.md +22 -0
- package/agent-pack/assets/command/emergency-response.md +66 -0
- package/agent-pack/assets/command/issues.md +23 -0
- package/agent-pack/assets/command/learn.md +42 -0
- package/agent-pack/assets/command/monthly-report.md +35 -0
- package/agent-pack/assets/command/payment-reminder.md +27 -0
- package/agent-pack/assets/command/plan-draft.md +28 -0
- package/agent-pack/assets/command/review-response.md +23 -0
- package/agent-pack/assets/command/rmslop.md +15 -0
- package/agent-pack/assets/command/safety-check.md +20 -0
- package/agent-pack/assets/command/spellcheck.md +5 -0
- package/agent-pack/assets/command/trend-analysis.md +38 -0
- package/agent-pack/assets/command/weekly-report.md +28 -0
- package/agent-pack/assets/lib/os_api.ts +100 -0
- package/agent-pack/assets/skill/adjustment-report/SKILL.md +88 -0
- package/agent-pack/assets/skill/approval-flow-intelligence/SKILL.md +123 -0
- package/agent-pack/assets/skill/bidding-knowledge/SKILL.md +98 -0
- package/agent-pack/assets/skill/bun-file-io/SKILL.md +42 -0
- package/agent-pack/assets/skill/business-finance/SKILL.md +91 -0
- package/agent-pack/assets/skill/business-operations-analytics/SKILL.md +120 -0
- package/agent-pack/assets/skill/cad-bim-review/SKILL.md +84 -0
- package/agent-pack/assets/skill/canvas-design/SKILL.md +141 -0
- package/agent-pack/assets/skill/construction-monitoring/SKILL.md +89 -0
- package/agent-pack/assets/skill/customer-portal-brief/SKILL.md +121 -0
- package/agent-pack/assets/skill/data-analysis/SKILL.md +79 -0
- package/agent-pack/assets/skill/di-bao-monitoring/SKILL.md +680 -0
- package/agent-pack/assets/skill/di-bao-monitoring/agents/openai.yaml +4 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/crossing-static-level-input-template.csv +2 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/crossing-total-station-input-template.csv +2 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/crossing-total-station-report-template.md +59 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/daily-report-template.md +90 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/data-input-template.csv +2 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/initial-value-report-template.md +92 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/monthly-report-template.md +103 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/plan-template.md +673 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/point-alias-map-template.json +25 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/project-brief-template.md +59 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/project-summary-template.md +154 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/warning-notice-template.md +58 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets/weekly-report-template.md +49 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets//345/256/214/346/225/264/346/212/245/350/241/250/346/250/241/346/235/277.xlsx +0 -0
- package/agent-pack/assets/skill/di-bao-monitoring/assets//345/277/253/346/212/245/346/250/241/346/235/277.xlsx +0 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/crossing-static-level-report.md +115 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/crossing-total-station-report.md +206 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/data-processing.md +170 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/elevated-line.md +319 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/initial-and-summary-workflow.md +222 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/key-difficulties.md +216 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/monitoring-catalog.md +80 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/phase0-intake.md +169 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/phase1-drafting.md +185 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/phase2-internal-review.md +166 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/report-workflow.md +181 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/review-checklist.md +140 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/review-response-template.md +87 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/scoping-and-pricing.md +214 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/source-analysis.md +137 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/technical-standards.md +188 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/toc-template-A.md +142 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/toc-template-B.md +100 -0
- package/agent-pack/assets/skill/di-bao-monitoring/references/warning-workflow.md +63 -0
- package/agent-pack/assets/skill/di-bao-monitoring/scripts/build_crossing_total_station_xlsx.py +2438 -0
- package/agent-pack/assets/skill/di-bao-monitoring/scripts/evaluate_alarms.py +215 -0
- package/agent-pack/assets/skill/di-bao-monitoring/scripts/fetch_adjusted_total_station.py +946 -0
- package/agent-pack/assets/skill/di-bao-monitoring/scripts/fetch_shhh_static_level.py +556 -0
- package/agent-pack/assets/skill/di-bao-monitoring/scripts/run_crossing_4h_report.sh +141 -0
- package/agent-pack/assets/skill/di-bao-monitoring/scripts/summarize_crossing_total_station.py +303 -0
- package/agent-pack/assets/skill/docx-generation/SKILL.md +141 -0
- package/agent-pack/assets/skill/excel-operations/SKILL.md +121 -0
- package/agent-pack/assets/skill/frontend-design/SKILL.md +151 -0
- package/agent-pack/assets/skill/humanizer/SKILL.md +90 -0
- package/agent-pack/assets/skill/monitoring-design/SKILL.md +100 -0
- package/agent-pack/assets/skill/operational-monitoring/SKILL.md +135 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/checklists/archive-self-check.md +54 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/schemas/convergence-result-table.csv +5 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/schemas/horizontal-result-table.csv +3 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/schemas/settlement-result-table.csv +7 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/scripts/init-archive-tree.sh +65 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/control-network-report.md +102 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/daily-log.md +47 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/i-angle-check.md +38 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/monitoring-scheme.md +234 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/period-report.md +95 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/point-acceptance-record.md +51 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/point-installation-record.md +38 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/summary-report.md +89 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/warning-bulletin.md +61 -0
- package/agent-pack/assets/skill/operational-monitoring/assets/templates/weekly-monthly-report.md +46 -0
- package/agent-pack/assets/skill/operational-monitoring/references/archive-and-delivery.md +146 -0
- package/agent-pack/assets/skill/operational-monitoring/references/baseline-network.md +131 -0
- package/agent-pack/assets/skill/operational-monitoring/references/convergence-monitoring.md +134 -0
- package/agent-pack/assets/skill/operational-monitoring/references/data-processing.md +178 -0
- package/agent-pack/assets/skill/operational-monitoring/references/horizontal-displacement.md +128 -0
- package/agent-pack/assets/skill/operational-monitoring/references/monitoring-points.md +132 -0
- package/agent-pack/assets/skill/operational-monitoring/references/monitoring-scheme.md +178 -0
- package/agent-pack/assets/skill/operational-monitoring/references/period-report.md +108 -0
- package/agent-pack/assets/skill/operational-monitoring/references/regulations-and-frequency.md +127 -0
- package/agent-pack/assets/skill/operational-monitoring/references/settlement-monitoring.md +116 -0
- package/agent-pack/assets/skill/operational-monitoring/references/summary-report.md +128 -0
- package/agent-pack/assets/skill/operational-monitoring/references/warning-and-disposal.md +118 -0
- package/agent-pack/assets/skill/ops-monitoring/SKILL.md +93 -0
- package/agent-pack/assets/skill/railwise-knowledge-curation/SKILL.md +92 -0
- package/agent-pack/assets/skill/report-dibao/SKILL.md +60 -0
- package/agent-pack/assets/skill/report-writing/SKILL.md +103 -0
- package/agent-pack/assets/skill/resource-dispatch-intelligence/SKILL.md +125 -0
- package/agent-pack/assets/skill/standard-reference/SKILL.md +101 -0
- package/agent-pack/assets/skill/weekly-work-intelligence/SKILL.md +123 -0
- package/agent-pack/assets/template/adjustment-trend.json +53 -0
- package/agent-pack/assets/template/bid-technical-proposal.json +42 -0
- package/agent-pack/assets/template/compliance-review.json +35 -0
- package/agent-pack/assets/template/daily-monitor-report.json +34 -0
- package/agent-pack/assets/template/field-data-qa.json +47 -0
- package/agent-pack/assets/template/monitoring-plan.json +28 -0
- package/agent-pack/assets/template/monthly-monitor-report.json +47 -0
- package/agent-pack/assets/template/project-ppt.json +47 -0
- package/agent-pack/assets/template/review-response.json +28 -0
- package/agent-pack/assets/template/schema.json +72 -0
- package/agent-pack/assets/template/weekly-monitor-report.json +33 -0
- package/agent-pack/assets/theme/mytheme.json +223 -0
- package/agent-pack/assets/tool/angle_convert.ts +151 -0
- package/agent-pack/assets/tool/axial_force.ts +186 -0
- package/agent-pack/assets/tool/chart_generator.ts +185 -0
- package/agent-pack/assets/tool/control_network.ts +413 -0
- package/agent-pack/assets/tool/coord_transform.ts +333 -0
- package/agent-pack/assets/tool/cpiii_adjustment.ts +446 -0
- package/agent-pack/assets/tool/cross_section.ts +356 -0
- package/agent-pack/assets/tool/deformation_rate.ts +234 -0
- package/agent-pack/assets/tool/distance_calculator.ts +239 -0
- package/agent-pack/assets/tool/excel_export.ts +494 -0
- package/agent-pack/assets/tool/format_parser.ts +181 -0
- package/agent-pack/assets/tool/github-pr-search.ts +57 -0
- package/agent-pack/assets/tool/github-pr-search.txt +10 -0
- package/agent-pack/assets/tool/github-triage.ts +113 -0
- package/agent-pack/assets/tool/github-triage.txt +6 -0
- package/agent-pack/assets/tool/inclinometer.ts +248 -0
- package/agent-pack/assets/tool/monitoring_csv.ts +120 -0
- package/agent-pack/assets/tool/os_contract_query.ts +63 -0
- package/agent-pack/assets/tool/os_dibao_project_files.ts +75 -0
- package/agent-pack/assets/tool/os_file_download_ref.ts +48 -0
- package/agent-pack/assets/tool/os_file_preview.ts +46 -0
- package/agent-pack/assets/tool/os_gbrain_think.ts +31 -0
- package/agent-pack/assets/tool/os_ppt_generate.ts +37 -0
- package/agent-pack/assets/tool/os_project_context.ts +24 -0
- package/agent-pack/assets/tool/os_report_publish.ts +28 -0
- package/agent-pack/assets/tool/os_wiki_ingest.ts +38 -0
- package/agent-pack/assets/tool/os_wiki_query.ts +26 -0
- package/agent-pack/assets/tool/pile_stakeout.ts +299 -0
- package/agent-pack/assets/tool/report_export.ts +279 -0
- package/agent-pack/assets/tool/shield_guidance.ts +311 -0
- package/agent-pack/assets/tool/standard_query.ts +391 -0
- package/agent-pack/assets/tool/survey_calculator.ts +415 -0
- package/agent-pack/assets/tool/water_level.ts +209 -0
- package/agent-pack/bin/install.js +183 -0
- package/agent-pack/package.json +695 -0
- package/package.json +14 -8
- package/postinstall.mjs +53 -22
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
/// <reference path="../env.d.ts" />
|
|
2
|
+
import { tool } from "nb-railwise/tool"
|
|
3
|
+
|
|
4
|
+
// ============================================================
|
|
5
|
+
// Tunnel / excavation cross-section analysis tools
|
|
6
|
+
// ============================================================
|
|
7
|
+
|
|
8
|
+
// ============================================================
|
|
9
|
+
// Tool: Convergence calculation from monitoring pairs
|
|
10
|
+
// ============================================================
|
|
11
|
+
|
|
12
|
+
export const convergence_calc = tool({
|
|
13
|
+
description:
|
|
14
|
+
"收敛量计算:根据隧道断面上对称测点对的坐标,计算净空收敛量(水平收敛、拱顶沉降等)。地铁隧道健康监测和施工监测中的核心分析工具。data_analyst 在处理隧道断面监测数据时必须调用此工具。",
|
|
15
|
+
args: {
|
|
16
|
+
sectionId: tool.schema.string().describe("断面编号"),
|
|
17
|
+
chainage: tool.schema.string().optional().describe("里程桩号,如 K12+345.678"),
|
|
18
|
+
initialPairs: tool.schema
|
|
19
|
+
.array(
|
|
20
|
+
tool.schema.object({
|
|
21
|
+
pairId: tool.schema.string().describe("测点对编号,如 H1(水平收敛对1)"),
|
|
22
|
+
pointA: tool.schema.object({
|
|
23
|
+
x: tool.schema.number().describe("A点X坐标(m)"),
|
|
24
|
+
y: tool.schema.number().describe("A点Y坐标(m)"),
|
|
25
|
+
}),
|
|
26
|
+
pointB: tool.schema.object({
|
|
27
|
+
x: tool.schema.number().describe("B点X坐标(m)"),
|
|
28
|
+
y: tool.schema.number().describe("B点Y坐标(m)"),
|
|
29
|
+
}),
|
|
30
|
+
}),
|
|
31
|
+
)
|
|
32
|
+
.min(1)
|
|
33
|
+
.describe("初始观测(基准)的测点对坐标"),
|
|
34
|
+
currentPairs: tool.schema
|
|
35
|
+
.array(
|
|
36
|
+
tool.schema.object({
|
|
37
|
+
pairId: tool.schema.string().describe("测点对编号(与初始观测对应)"),
|
|
38
|
+
pointA: tool.schema.object({
|
|
39
|
+
x: tool.schema.number().describe("A点X坐标(m)"),
|
|
40
|
+
y: tool.schema.number().describe("A点Y坐标(m)"),
|
|
41
|
+
}),
|
|
42
|
+
pointB: tool.schema.object({
|
|
43
|
+
x: tool.schema.number().describe("B点X坐标(m)"),
|
|
44
|
+
y: tool.schema.number().describe("B点Y坐标(m)"),
|
|
45
|
+
}),
|
|
46
|
+
}),
|
|
47
|
+
)
|
|
48
|
+
.min(1)
|
|
49
|
+
.describe("本期观测的测点对坐标"),
|
|
50
|
+
crownInitial: tool.schema
|
|
51
|
+
.object({
|
|
52
|
+
x: tool.schema.number().describe("拱顶X坐标(m)"),
|
|
53
|
+
y: tool.schema.number().describe("拱顶Y坐标(m)"),
|
|
54
|
+
})
|
|
55
|
+
.optional()
|
|
56
|
+
.describe("拱顶初始坐标(若提供则计算拱顶沉降)"),
|
|
57
|
+
crownCurrent: tool.schema
|
|
58
|
+
.object({
|
|
59
|
+
x: tool.schema.number().describe("拱顶X坐标(m)"),
|
|
60
|
+
y: tool.schema.number().describe("拱顶Y坐标(m)"),
|
|
61
|
+
})
|
|
62
|
+
.optional()
|
|
63
|
+
.describe("拱顶本期坐标"),
|
|
64
|
+
alertThreshold: tool.schema.number().positive().optional().describe("收敛报警值(mm)"),
|
|
65
|
+
},
|
|
66
|
+
async execute(args) {
|
|
67
|
+
// Build initial pair map
|
|
68
|
+
const initialMap = new Map(args.initialPairs.map((p) => [p.pairId, p]))
|
|
69
|
+
|
|
70
|
+
const convergences = args.currentPairs.map((curr) => {
|
|
71
|
+
const init = initialMap.get(curr.pairId)
|
|
72
|
+
if (!init)
|
|
73
|
+
return {
|
|
74
|
+
pair_id: curr.pairId,
|
|
75
|
+
error: `未找到对应的初始观测数据`,
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const initDist = Math.sqrt((init.pointB.x - init.pointA.x) ** 2 + (init.pointB.y - init.pointA.y) ** 2)
|
|
79
|
+
const currDist = Math.sqrt((curr.pointB.x - curr.pointA.x) ** 2 + (curr.pointB.y - curr.pointA.y) ** 2)
|
|
80
|
+
const convergence = (initDist - currDist) * 1000 // mm, positive = converging
|
|
81
|
+
const rate = initDist > 0 ? (convergence / (initDist * 1000)) * 100 : 0
|
|
82
|
+
|
|
83
|
+
let status = "🟢 正常"
|
|
84
|
+
if (args.alertThreshold) {
|
|
85
|
+
const ratio = Math.abs(convergence) / args.alertThreshold
|
|
86
|
+
if (ratio >= 1.0) status = "🔴 超限"
|
|
87
|
+
else if (ratio >= 0.85) status = "🟠 接近阈值"
|
|
88
|
+
else if (ratio >= 0.7) status = "🟡 关注"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
pair_id: curr.pairId,
|
|
93
|
+
initial_distance_m: Number(initDist.toFixed(4)),
|
|
94
|
+
current_distance_m: Number(currDist.toFixed(4)),
|
|
95
|
+
convergence_mm: Number(convergence.toFixed(3)),
|
|
96
|
+
convergence_rate_pct: Number(rate.toFixed(4)),
|
|
97
|
+
status,
|
|
98
|
+
}
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
// Crown settlement
|
|
102
|
+
let crownSettlement: Record<string, unknown> | undefined
|
|
103
|
+
if (args.crownInitial && args.crownCurrent) {
|
|
104
|
+
const dy = (args.crownCurrent.y - args.crownInitial.y) * 1000 // mm
|
|
105
|
+
const dx = (args.crownCurrent.x - args.crownInitial.x) * 1000 // mm
|
|
106
|
+
const total = Math.sqrt(dx * dx + dy * dy)
|
|
107
|
+
|
|
108
|
+
let status = "🟢 正常"
|
|
109
|
+
if (args.alertThreshold) {
|
|
110
|
+
const ratio = Math.abs(dy) / args.alertThreshold
|
|
111
|
+
if (ratio >= 1.0) status = "🔴 超限"
|
|
112
|
+
else if (ratio >= 0.85) status = "🟠 接近阈值"
|
|
113
|
+
else if (ratio >= 0.7) status = "🟡 关注"
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
crownSettlement = {
|
|
117
|
+
vertical_mm: Number(dy.toFixed(3)),
|
|
118
|
+
horizontal_mm: Number(dx.toFixed(3)),
|
|
119
|
+
total_mm: Number(total.toFixed(3)),
|
|
120
|
+
direction: dy < 0 ? "沉降" : "上抬",
|
|
121
|
+
status,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const maxConvergence = convergences
|
|
126
|
+
.filter((c) => "convergence_mm" in c)
|
|
127
|
+
.reduce(
|
|
128
|
+
(max, c) => {
|
|
129
|
+
const val = Math.abs((c as { convergence_mm: number }).convergence_mm)
|
|
130
|
+
return val > max.value ? { pair_id: c.pair_id, value: val } : max
|
|
131
|
+
},
|
|
132
|
+
{ pair_id: "", value: 0 },
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
return JSON.stringify({
|
|
136
|
+
section_id: args.sectionId,
|
|
137
|
+
chainage: args.chainage ?? "未指定",
|
|
138
|
+
convergences,
|
|
139
|
+
crown_settlement: crownSettlement,
|
|
140
|
+
max_convergence: {
|
|
141
|
+
pair_id: maxConvergence.pair_id,
|
|
142
|
+
value_mm: maxConvergence.value,
|
|
143
|
+
},
|
|
144
|
+
message: `✅ 断面 ${args.sectionId} 收敛分析完成:最大收敛 ${maxConvergence.pair_id}(${maxConvergence.value.toFixed(3)}mm)${crownSettlement ? `,拱顶${(crownSettlement as { direction: string }).direction} ${Math.abs(crownSettlement.vertical_mm as number).toFixed(3)}mm` : ""}`,
|
|
145
|
+
})
|
|
146
|
+
},
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
// ============================================================
|
|
150
|
+
// Tool: Cross-section profile comparison
|
|
151
|
+
// ============================================================
|
|
152
|
+
|
|
153
|
+
export const profile_comparison = tool({
|
|
154
|
+
description:
|
|
155
|
+
"断面轮廓对比分析:将隧道/基坑实测断面轮廓与设计轮廓进行对比,计算各点的超欠挖量和净空余量。适用于隧道开挖断面检测、盾构管片姿态分析。",
|
|
156
|
+
args: {
|
|
157
|
+
sectionId: tool.schema.string().describe("断面编号"),
|
|
158
|
+
designProfile: tool.schema
|
|
159
|
+
.array(
|
|
160
|
+
tool.schema.object({
|
|
161
|
+
angle: tool.schema.number().describe("从拱顶顺时针方向的角度(度),0=拱顶,180=仰拱"),
|
|
162
|
+
radius: tool.schema.number().positive().describe("设计半径/距中心距离(m)"),
|
|
163
|
+
}),
|
|
164
|
+
)
|
|
165
|
+
.min(3)
|
|
166
|
+
.describe("设计断面轮廓(极坐标表示:角度+半径)"),
|
|
167
|
+
measuredProfile: tool.schema
|
|
168
|
+
.array(
|
|
169
|
+
tool.schema.object({
|
|
170
|
+
angle: tool.schema.number().describe("测量方向角(度)"),
|
|
171
|
+
radius: tool.schema.number().positive().describe("实测距中心距离(m)"),
|
|
172
|
+
}),
|
|
173
|
+
)
|
|
174
|
+
.min(3)
|
|
175
|
+
.describe("实测断面轮廓"),
|
|
176
|
+
overbreakLimit: tool.schema.number().positive().default(150).describe("允许超挖限值(mm),默认150mm"),
|
|
177
|
+
underbreakLimit: tool.schema.number().positive().default(0).describe("允许欠挖限值(mm),默认0mm(不允许欠挖)"),
|
|
178
|
+
},
|
|
179
|
+
async execute(args) {
|
|
180
|
+
// Sort design profile by angle for interpolation
|
|
181
|
+
const design = [...args.designProfile].sort((a, b) => a.angle - b.angle)
|
|
182
|
+
|
|
183
|
+
// Interpolate design radius at given angle
|
|
184
|
+
function designRadius(angle: number): number {
|
|
185
|
+
const normAngle = ((angle % 360) + 360) % 360
|
|
186
|
+
for (let i = 0; i < design.length - 1; i++) {
|
|
187
|
+
if (normAngle >= design[i]!.angle && normAngle <= design[i + 1]!.angle) {
|
|
188
|
+
const ratio = (normAngle - design[i]!.angle) / (design[i + 1]!.angle - design[i]!.angle)
|
|
189
|
+
return design[i]!.radius + ratio * (design[i + 1]!.radius - design[i]!.radius)
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
// Wrap around or nearest
|
|
193
|
+
return design[0]!.radius
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const comparisons = args.measuredProfile.map((m) => {
|
|
197
|
+
const dRadius = designRadius(m.angle)
|
|
198
|
+
const diff = (m.radius - dRadius) * 1000 // mm, positive = overbreak
|
|
199
|
+
const isOverbreak = diff > 0
|
|
200
|
+
const isUnderbreak = diff < 0
|
|
201
|
+
|
|
202
|
+
let status = "🟢 合格"
|
|
203
|
+
if (isOverbreak && diff > args.overbreakLimit) {
|
|
204
|
+
status = "🔴 超挖超限"
|
|
205
|
+
} else if (isUnderbreak && Math.abs(diff) > args.underbreakLimit) {
|
|
206
|
+
status = "🔴 欠挖"
|
|
207
|
+
} else if (isOverbreak) {
|
|
208
|
+
status = "🟡 超挖(限内)"
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
angle_deg: m.angle,
|
|
213
|
+
design_radius_m: Number(dRadius.toFixed(4)),
|
|
214
|
+
measured_radius_m: Number(m.radius.toFixed(4)),
|
|
215
|
+
deviation_mm: Number(diff.toFixed(1)),
|
|
216
|
+
type: isOverbreak ? "超挖" : isUnderbreak ? "欠挖" : "吻合",
|
|
217
|
+
status,
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
const overbreakPoints = comparisons.filter((c) => c.type === "超挖")
|
|
222
|
+
const underbreakPoints = comparisons.filter((c) => c.type === "欠挖")
|
|
223
|
+
const maxOverbreak =
|
|
224
|
+
overbreakPoints.length > 0
|
|
225
|
+
? overbreakPoints.reduce((max, c) => (c.deviation_mm > max.deviation_mm ? c : max), overbreakPoints[0]!)
|
|
226
|
+
: null
|
|
227
|
+
const maxUnderbreak =
|
|
228
|
+
underbreakPoints.length > 0
|
|
229
|
+
? underbreakPoints.reduce(
|
|
230
|
+
(max, c) => (Math.abs(c.deviation_mm) > Math.abs(max.deviation_mm) ? c : max),
|
|
231
|
+
underbreakPoints[0]!,
|
|
232
|
+
)
|
|
233
|
+
: null
|
|
234
|
+
|
|
235
|
+
const avgDeviation = comparisons.reduce((s, c) => s + c.deviation_mm, 0) / comparisons.length
|
|
236
|
+
const failCount = comparisons.filter((c) => c.status.includes("超限") || c.status.includes("欠挖")).length
|
|
237
|
+
|
|
238
|
+
return JSON.stringify({
|
|
239
|
+
section_id: args.sectionId,
|
|
240
|
+
measured_points: comparisons.length,
|
|
241
|
+
overbreak_count: overbreakPoints.length,
|
|
242
|
+
underbreak_count: underbreakPoints.length,
|
|
243
|
+
fail_count: failCount,
|
|
244
|
+
average_deviation_mm: Number(avgDeviation.toFixed(1)),
|
|
245
|
+
max_overbreak: maxOverbreak
|
|
246
|
+
? {
|
|
247
|
+
angle_deg: maxOverbreak.angle_deg,
|
|
248
|
+
deviation_mm: maxOverbreak.deviation_mm,
|
|
249
|
+
}
|
|
250
|
+
: null,
|
|
251
|
+
max_underbreak: maxUnderbreak
|
|
252
|
+
? {
|
|
253
|
+
angle_deg: maxUnderbreak.angle_deg,
|
|
254
|
+
deviation_mm: maxUnderbreak.deviation_mm,
|
|
255
|
+
}
|
|
256
|
+
: null,
|
|
257
|
+
details: comparisons,
|
|
258
|
+
assessment:
|
|
259
|
+
failCount === 0
|
|
260
|
+
? `✅ 断面 ${args.sectionId} 开挖轮廓合格:${overbreakPoints.length}处超挖均在限值内,无欠挖`
|
|
261
|
+
: `❌ 断面 ${args.sectionId} 有 ${failCount} 处不合格(超挖超限或欠挖),需处理`,
|
|
262
|
+
message: `断面 ${args.sectionId}:${comparisons.length}个测点,超挖 ${overbreakPoints.length}处,欠挖 ${underbreakPoints.length}处,${failCount === 0 ? "全部合格" : `${failCount}处不合格`}`,
|
|
263
|
+
})
|
|
264
|
+
},
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
// ============================================================
|
|
268
|
+
// Tool: Section clearance check
|
|
269
|
+
// ============================================================
|
|
270
|
+
|
|
271
|
+
export const clearance_check = tool({
|
|
272
|
+
description:
|
|
273
|
+
"限界(建筑净空)检查:对比隧道实测断面与限界要求,判断是否侵入建筑限界。运营隧道健康监测中用于结构变形是否影响行车安全的关键判定。",
|
|
274
|
+
args: {
|
|
275
|
+
sectionId: tool.schema.string().describe("断面编号"),
|
|
276
|
+
gaugeProfile: tool.schema
|
|
277
|
+
.array(
|
|
278
|
+
tool.schema.object({
|
|
279
|
+
angle: tool.schema.number().describe("方向角(度)"),
|
|
280
|
+
minRadius: tool.schema.number().positive().describe("该方向上的最小净空要求(m)"),
|
|
281
|
+
}),
|
|
282
|
+
)
|
|
283
|
+
.min(3)
|
|
284
|
+
.describe("限界轮廓(极坐标,定义各方向最小净空)"),
|
|
285
|
+
measuredProfile: tool.schema
|
|
286
|
+
.array(
|
|
287
|
+
tool.schema.object({
|
|
288
|
+
angle: tool.schema.number().describe("测量方向角(度)"),
|
|
289
|
+
radius: tool.schema.number().positive().describe("实测距中心距离(m)"),
|
|
290
|
+
}),
|
|
291
|
+
)
|
|
292
|
+
.min(3)
|
|
293
|
+
.describe("实测断面轮廓"),
|
|
294
|
+
safetyMargin: tool.schema.number().default(50).describe("安全余量(mm),低于此值发出预警,默认50mm"),
|
|
295
|
+
},
|
|
296
|
+
async execute(args) {
|
|
297
|
+
const gauge = [...args.gaugeProfile].sort((a, b) => a.angle - b.angle)
|
|
298
|
+
|
|
299
|
+
function gaugeRadius(angle: number): number {
|
|
300
|
+
const norm = ((angle % 360) + 360) % 360
|
|
301
|
+
for (let i = 0; i < gauge.length - 1; i++) {
|
|
302
|
+
if (norm >= gauge[i]!.angle && norm <= gauge[i + 1]!.angle) {
|
|
303
|
+
const ratio = (norm - gauge[i]!.angle) / (gauge[i + 1]!.angle - gauge[i]!.angle)
|
|
304
|
+
return gauge[i]!.minRadius + ratio * (gauge[i + 1]!.minRadius - gauge[i]!.minRadius)
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
return gauge[0]!.minRadius
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const checks = args.measuredProfile.map((m) => {
|
|
311
|
+
const minR = gaugeRadius(m.angle)
|
|
312
|
+
const margin = (m.radius - minR) * 1000 // mm
|
|
313
|
+
|
|
314
|
+
let status: string
|
|
315
|
+
if (margin < 0) {
|
|
316
|
+
status = "🔴 侵入限界"
|
|
317
|
+
} else if (margin < args.safetyMargin) {
|
|
318
|
+
status = "🟠 余量不足"
|
|
319
|
+
} else {
|
|
320
|
+
status = "🟢 合格"
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return {
|
|
324
|
+
angle_deg: m.angle,
|
|
325
|
+
gauge_min_radius_m: Number(minR.toFixed(4)),
|
|
326
|
+
measured_radius_m: Number(m.radius.toFixed(4)),
|
|
327
|
+
margin_mm: Number(margin.toFixed(1)),
|
|
328
|
+
status,
|
|
329
|
+
}
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
const violations = checks.filter((c) => c.margin_mm < 0)
|
|
333
|
+
const warnings = checks.filter((c) => c.margin_mm >= 0 && c.margin_mm < args.safetyMargin)
|
|
334
|
+
const minMargin = checks.reduce((min, c) => (c.margin_mm < min.margin_mm ? c : min), checks[0]!)
|
|
335
|
+
|
|
336
|
+
return JSON.stringify({
|
|
337
|
+
section_id: args.sectionId,
|
|
338
|
+
total_points: checks.length,
|
|
339
|
+
violations: violations.length,
|
|
340
|
+
warnings: warnings.length,
|
|
341
|
+
min_margin: {
|
|
342
|
+
angle_deg: minMargin.angle_deg,
|
|
343
|
+
margin_mm: minMargin.margin_mm,
|
|
344
|
+
status: minMargin.status,
|
|
345
|
+
},
|
|
346
|
+
details: checks,
|
|
347
|
+
assessment:
|
|
348
|
+
violations.length > 0
|
|
349
|
+
? `🔴 断面 ${args.sectionId} 有 ${violations.length} 处侵入建筑限界!最小余量 ${minMargin.margin_mm.toFixed(1)}mm(${minMargin.angle_deg}°方向),必须立即处理!`
|
|
350
|
+
: warnings.length > 0
|
|
351
|
+
? `🟠 断面 ${args.sectionId} 有 ${warnings.length} 处净空余量不足 ${args.safetyMargin}mm,需密切关注`
|
|
352
|
+
: `✅ 断面 ${args.sectionId} 建筑限界检查通过,最小余量 ${minMargin.margin_mm.toFixed(1)}mm`,
|
|
353
|
+
message: `限界检查 ${args.sectionId}:${violations.length > 0 ? `🔴 ${violations.length}处侵限` : warnings.length > 0 ? `🟠 ${warnings.length}处余量不足` : "✅ 全部通过"},最小余量 ${minMargin.margin_mm.toFixed(1)}mm`,
|
|
354
|
+
})
|
|
355
|
+
},
|
|
356
|
+
})
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/// <reference path="../env.d.ts" />
|
|
2
|
+
import { tool } from "nb-railwise/tool"
|
|
3
|
+
|
|
4
|
+
// ============================================================
|
|
5
|
+
// Deformation rate analysis & trend prediction
|
|
6
|
+
// ============================================================
|
|
7
|
+
|
|
8
|
+
// ============================================================
|
|
9
|
+
// Tool: Deformation rate calculation
|
|
10
|
+
// ============================================================
|
|
11
|
+
|
|
12
|
+
export const deformation_rate = tool({
|
|
13
|
+
description:
|
|
14
|
+
"变形速率计算与趋势分析。根据监测点的时间-变形量序列,计算各期变形速率、累计变形量,并用线性回归进行趋势预测。城市轨道监测中判断变形是否收敛的核心分析工具。data_analyst 在分析自动化监测数据趋势时必须调用此工具。",
|
|
15
|
+
args: {
|
|
16
|
+
pointId: tool.schema.string().describe("监测点编号"),
|
|
17
|
+
data: tool.schema
|
|
18
|
+
.array(
|
|
19
|
+
tool.schema.object({
|
|
20
|
+
date: tool.schema.string().describe("观测日期,格式 YYYY-MM-DD 或 YYYY-MM-DD HH:mm"),
|
|
21
|
+
value: tool.schema.number().describe("累计变形量(mm),正值表示沉降/收敛方向"),
|
|
22
|
+
}),
|
|
23
|
+
)
|
|
24
|
+
.min(2)
|
|
25
|
+
.describe("按时间顺序排列的监测数据序列"),
|
|
26
|
+
alertThreshold: tool.schema.number().positive().optional().describe("报警控制值(mm),若提供则输出预警分析"),
|
|
27
|
+
rateThreshold: tool.schema.number().positive().optional().describe("速率控制值(mm/d),若提供则判断速率是否超限"),
|
|
28
|
+
predictionDays: tool.schema.number().int().positive().default(7).describe("向前预测天数,默认7天"),
|
|
29
|
+
},
|
|
30
|
+
async execute(args) {
|
|
31
|
+
const n = args.data.length
|
|
32
|
+
|
|
33
|
+
// Parse dates to day offsets
|
|
34
|
+
const t0 = new Date(args.data[0]!.date).getTime()
|
|
35
|
+
const days = args.data.map((d) => (new Date(d.date).getTime() - t0) / 86400000)
|
|
36
|
+
const values = args.data.map((d) => d.value)
|
|
37
|
+
|
|
38
|
+
// Period-by-period rates
|
|
39
|
+
const rates: Array<{ period: string; rate_mm_per_day: number; increment_mm: number; days: number }> = []
|
|
40
|
+
for (let i = 1; i < n; i++) {
|
|
41
|
+
const dt = days[i]! - days[i - 1]!
|
|
42
|
+
const dv = values[i]! - values[i - 1]!
|
|
43
|
+
const rate = dt > 0 ? dv / dt : 0
|
|
44
|
+
rates.push({
|
|
45
|
+
period: `${args.data[i - 1]!.date} → ${args.data[i]!.date}`,
|
|
46
|
+
rate_mm_per_day: Number(rate.toFixed(4)),
|
|
47
|
+
increment_mm: Number(dv.toFixed(4)),
|
|
48
|
+
days: Number(dt.toFixed(2)),
|
|
49
|
+
})
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Overall statistics
|
|
53
|
+
const totalDays = days[n - 1]! - days[0]!
|
|
54
|
+
const totalDeformation = values[n - 1]! - values[0]!
|
|
55
|
+
const avgRate = totalDays > 0 ? totalDeformation / totalDays : 0
|
|
56
|
+
const latestValue = values[n - 1]!
|
|
57
|
+
const latestRate = rates.length > 0 ? rates[rates.length - 1]!.rate_mm_per_day : 0
|
|
58
|
+
|
|
59
|
+
// Linear regression: y = a + b*x
|
|
60
|
+
const meanX = days.reduce((s, v) => s + v, 0) / n
|
|
61
|
+
const meanY = values.reduce((s, v) => s + v, 0) / n
|
|
62
|
+
const ssxy = days.reduce((s, x, i) => s + (x - meanX) * (values[i]! - meanY), 0)
|
|
63
|
+
const ssxx = days.reduce((s, x) => s + (x - meanX) * (x - meanX), 0)
|
|
64
|
+
const b = ssxx > 0 ? ssxy / ssxx : 0
|
|
65
|
+
const a = meanY - b * meanX
|
|
66
|
+
|
|
67
|
+
// R² (coefficient of determination)
|
|
68
|
+
const ssyy = values.reduce((s, y) => s + (y - meanY) * (y - meanY), 0)
|
|
69
|
+
const r2 = ssyy > 0 ? (ssxy * ssxy) / (ssxx * ssyy) : 0
|
|
70
|
+
|
|
71
|
+
// Residual standard error
|
|
72
|
+
const residuals = values.map((y, i) => y - (a + b * days[i]!))
|
|
73
|
+
const rmse = Math.sqrt(residuals.reduce((s, r) => s + r * r, 0) / Math.max(n - 2, 1))
|
|
74
|
+
|
|
75
|
+
// Prediction
|
|
76
|
+
const lastDay = days[n - 1]!
|
|
77
|
+
const predictions = Array.from({ length: args.predictionDays }, (_, i) => {
|
|
78
|
+
const predDay = lastDay + i + 1
|
|
79
|
+
const predDate = new Date(t0 + predDay * 86400000)
|
|
80
|
+
const predValue = a + b * predDay
|
|
81
|
+
return {
|
|
82
|
+
date: predDate.toISOString().slice(0, 10),
|
|
83
|
+
predicted_mm: Number(predValue.toFixed(4)),
|
|
84
|
+
day_offset: Number(predDay.toFixed(1)),
|
|
85
|
+
}
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
// Stability assessment
|
|
89
|
+
const last3Rates = rates.slice(-3).map((r) => Math.abs(r.rate_mm_per_day))
|
|
90
|
+
const avgLast3Rate = last3Rates.length > 0 ? last3Rates.reduce((s, v) => s + v, 0) / last3Rates.length : 0
|
|
91
|
+
|
|
92
|
+
let stability: string
|
|
93
|
+
if (avgLast3Rate < 0.01) {
|
|
94
|
+
stability = "✅ 已收敛:近期速率趋近于零,变形基本稳定"
|
|
95
|
+
} else if (avgLast3Rate < 0.05) {
|
|
96
|
+
stability = "🟢 趋于收敛:变形速率逐渐减小"
|
|
97
|
+
} else if (Math.abs(latestRate) > Math.abs(avgRate) * 1.5) {
|
|
98
|
+
stability = "🔴 加速变形:最新速率明显大于平均速率,需加密监测"
|
|
99
|
+
} else if (avgLast3Rate < Math.abs(avgRate)) {
|
|
100
|
+
stability = "🟡 减速变形:速率有所减小但尚未收敛,继续监测"
|
|
101
|
+
} else {
|
|
102
|
+
stability = "🟠 等速变形:速率基本稳定,关注发展趋势"
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Alert analysis
|
|
106
|
+
let alertAnalysis: Record<string, unknown> | undefined
|
|
107
|
+
if (args.alertThreshold) {
|
|
108
|
+
const ratio = Math.abs(latestValue) / args.alertThreshold
|
|
109
|
+
const predMax = Math.max(...predictions.map((p) => Math.abs(p.predicted_mm)))
|
|
110
|
+
const predRatio = predMax / args.alertThreshold
|
|
111
|
+
const daysToThreshold = b !== 0 ? (args.alertThreshold * Math.sign(b) - a) / b - lastDay : Infinity
|
|
112
|
+
|
|
113
|
+
alertAnalysis = {
|
|
114
|
+
current_ratio_pct: Number((ratio * 100).toFixed(1)),
|
|
115
|
+
predicted_max_ratio_pct: Number((predRatio * 100).toFixed(1)),
|
|
116
|
+
estimated_days_to_threshold:
|
|
117
|
+
daysToThreshold > 0 && isFinite(daysToThreshold)
|
|
118
|
+
? Number(daysToThreshold.toFixed(1))
|
|
119
|
+
: "不会达到(趋势方向相反或速率为零)",
|
|
120
|
+
alert_level:
|
|
121
|
+
ratio >= 1.0 ? "🔴 已超阈值" : ratio >= 0.85 ? "🟠 接近阈值" : ratio >= 0.7 ? "🟡 需关注" : "🟢 正常",
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Rate threshold check
|
|
126
|
+
let rateAlert: string | undefined
|
|
127
|
+
if (args.rateThreshold) {
|
|
128
|
+
rateAlert =
|
|
129
|
+
Math.abs(latestRate) > args.rateThreshold
|
|
130
|
+
? `🔴 最新速率 ${Math.abs(latestRate).toFixed(4)} mm/d 超过限值 ${args.rateThreshold} mm/d`
|
|
131
|
+
: `🟢 最新速率 ${Math.abs(latestRate).toFixed(4)} mm/d 在限值 ${args.rateThreshold} mm/d 内`
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return JSON.stringify({
|
|
135
|
+
point_id: args.pointId,
|
|
136
|
+
data_count: n,
|
|
137
|
+
monitoring_duration_days: Number(totalDays.toFixed(1)),
|
|
138
|
+
latest_value_mm: latestValue,
|
|
139
|
+
total_deformation_mm: Number(totalDeformation.toFixed(4)),
|
|
140
|
+
average_rate_mm_per_day: Number(avgRate.toFixed(4)),
|
|
141
|
+
latest_rate_mm_per_day: latestRate,
|
|
142
|
+
rates,
|
|
143
|
+
regression: {
|
|
144
|
+
equation: `y = ${a.toFixed(4)} + ${b.toFixed(4)} × t`,
|
|
145
|
+
slope_mm_per_day: Number(b.toFixed(4)),
|
|
146
|
+
intercept_mm: Number(a.toFixed(4)),
|
|
147
|
+
r_squared: Number(r2.toFixed(4)),
|
|
148
|
+
rmse_mm: Number(rmse.toFixed(4)),
|
|
149
|
+
},
|
|
150
|
+
predictions,
|
|
151
|
+
stability_assessment: stability,
|
|
152
|
+
alert_analysis: alertAnalysis,
|
|
153
|
+
rate_alert: rateAlert,
|
|
154
|
+
message: `✅ ${args.pointId} 变形分析:累计 ${latestValue}mm,最新速率 ${latestRate}mm/d,${stability}`,
|
|
155
|
+
})
|
|
156
|
+
},
|
|
157
|
+
})
|
|
158
|
+
|
|
159
|
+
// ============================================================
|
|
160
|
+
// Tool: Multi-point deformation comparison
|
|
161
|
+
// ============================================================
|
|
162
|
+
|
|
163
|
+
export const deformation_comparison = tool({
|
|
164
|
+
description:
|
|
165
|
+
"多测点变形对比分析。同时对比多个监测点的变形量和速率,找出最大变形点、异常点。用于编制监测日报/周报中的断面对比分析。",
|
|
166
|
+
args: {
|
|
167
|
+
points: tool.schema
|
|
168
|
+
.array(
|
|
169
|
+
tool.schema.object({
|
|
170
|
+
id: tool.schema.string().describe("测点编号"),
|
|
171
|
+
latestValue: tool.schema.number().describe("最新累计变形量(mm)"),
|
|
172
|
+
previousValue: tool.schema.number().describe("上期累计变形量(mm)"),
|
|
173
|
+
daysBetween: tool.schema.number().positive().describe("两期间隔天数"),
|
|
174
|
+
}),
|
|
175
|
+
)
|
|
176
|
+
.min(1)
|
|
177
|
+
.describe("各监测点数据"),
|
|
178
|
+
alertThreshold: tool.schema.number().positive().optional().describe("统一报警控制值(mm)"),
|
|
179
|
+
rateThreshold: tool.schema.number().positive().optional().describe("速率控制值(mm/d)"),
|
|
180
|
+
},
|
|
181
|
+
async execute(args) {
|
|
182
|
+
const analyzed = args.points.map((p) => {
|
|
183
|
+
const increment = p.latestValue - p.previousValue
|
|
184
|
+
const rate = increment / p.daysBetween
|
|
185
|
+
const absVal = Math.abs(p.latestValue)
|
|
186
|
+
|
|
187
|
+
let status = "🟢 正常"
|
|
188
|
+
if (args.alertThreshold) {
|
|
189
|
+
const ratio = absVal / args.alertThreshold
|
|
190
|
+
if (ratio >= 1.0) status = "🔴 超限"
|
|
191
|
+
else if (ratio >= 0.85) status = "🟠 接近阈值"
|
|
192
|
+
else if (ratio >= 0.7) status = "🟡 关注"
|
|
193
|
+
}
|
|
194
|
+
if (args.rateThreshold && Math.abs(rate) > args.rateThreshold) {
|
|
195
|
+
status = "🔴 速率超限"
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
point_id: p.id,
|
|
200
|
+
latest_mm: p.latestValue,
|
|
201
|
+
increment_mm: Number(increment.toFixed(4)),
|
|
202
|
+
rate_mm_per_day: Number(rate.toFixed(4)),
|
|
203
|
+
status,
|
|
204
|
+
}
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
// Sort by absolute latest value descending
|
|
208
|
+
const sorted = [...analyzed].sort((a, b) => Math.abs(b.latest_mm) - Math.abs(a.latest_mm))
|
|
209
|
+
const maxPoint = sorted[0]!
|
|
210
|
+
const alertCount = analyzed.filter((a) => a.status.includes("超限") || a.status.includes("接近")).length
|
|
211
|
+
|
|
212
|
+
const avgDeformation = analyzed.reduce((s, a) => s + Math.abs(a.latest_mm), 0) / analyzed.length
|
|
213
|
+
const maxRate = analyzed.reduce(
|
|
214
|
+
(max, a) => (Math.abs(a.rate_mm_per_day) > Math.abs(max.rate_mm_per_day) ? a : max),
|
|
215
|
+
analyzed[0]!,
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
return JSON.stringify({
|
|
219
|
+
total_points: analyzed.length,
|
|
220
|
+
alert_count: alertCount,
|
|
221
|
+
max_deformation: {
|
|
222
|
+
point_id: maxPoint.point_id,
|
|
223
|
+
value_mm: maxPoint.latest_mm,
|
|
224
|
+
},
|
|
225
|
+
max_rate: {
|
|
226
|
+
point_id: maxRate.point_id,
|
|
227
|
+
rate_mm_per_day: maxRate.rate_mm_per_day,
|
|
228
|
+
},
|
|
229
|
+
average_deformation_mm: Number(avgDeformation.toFixed(4)),
|
|
230
|
+
details: sorted,
|
|
231
|
+
message: `✅ ${analyzed.length}个测点对比:最大变形 ${maxPoint.point_id}(${maxPoint.latest_mm}mm),最大速率 ${maxRate.point_id}(${maxRate.rate_mm_per_day}mm/d),${alertCount}个测点预警`,
|
|
232
|
+
})
|
|
233
|
+
},
|
|
234
|
+
})
|