某 FZ 软件学员站 —— 后台评分图「隐藏条件」挖掘
用途
某 FZ 软件学员站,界面"操作导航与评价 → 过程细目"只显示步骤的状态图标与「总分 / 评判依据」,
而真正决定"这一步何时能起评、必须满足哪些前置、何时算运行结束"的隐藏条件只存在于训练工程
目录下的后台评分图 *.escg 里,界面完全不暴露。
本 Skill 把这套"挖掘隐藏条件"的方法固化,供任意 agent 复用:解压 .escg → 提取 5 类隐藏条件
→ 按交付口径剔除扣分类 → 输出每工况一个红字高亮的 xlsx(可打印、可裁切)+ 汇总索引。
何时使用
- 用户要"某工况 / 某事故的隐藏条件 / 起评条件 / 必要条件 / 前置条件 / 运行结束条件 / 得分时限"——
不限具体装置或事故,只要是某 FZ 软件训练工程下的后台.escg即可。 - 用户要"把若干工况的隐藏条件放一个文件夹对比 / 汇总"。
- 用户要把这套过程沉淀成可复用能力。
- 注意区分:本 Skill 是后台
.escg逆向,与"界面实时报警抓取"(见下"不属于本 Skill")是两件事。
不属于本 Skill(易混,别用错)
- 界面实时报警(
AL.窗口"运行报警"按钮 → dataGridView1)是仿真运行时的动态报警队列,
用 UIAValuePattern读 cell,与.escg静态条件无关。该能力在配套的「学员站评分细目导出」Skill 里。 - 过程细目界面抓取(学员站"评分系统"窗口)用真实鼠标点击 + UIA,亦在配套的「学员站评分细目导出」Skill 里。
- 本 Skill 只处理后台
.escg文件,无需学员站运行,纯离线解析。
快速开始
cd <本 Skill 目录>
source ./scripts/_env.sh # 探测 WB_PY(venv / 受管 / 系统 Python)
ensure_pydeps # 幂等:建 .venv + 装 openpyxl(见 scripts/requirements.txt)
# 1) 自动发现 Graphs 目录下全部 .escg,逐工况输出 -> ./工况隐藏条件/
"$WB_PY" ./scripts/extract_hidden_conds.py --outdir "./工况隐藏条件" --base "<训练工程>/Jnjd/Graphs"
# 只跑名称含"事故"的工况: --match "*事故*"
# 只跑名称含"关联"的工况: --match "*关联*"
# 2) 全部工况合并进一个工作簿(首 sheet 汇总 + 每工况一 sheet)
"$WB_PY" ./scripts/extract_gaoya_conds.py --out "./全部工况_过程细目_含隐藏条件.xlsx" --base "<训练工程>/Jnjd/Graphs"
环境说明(跨机器可移植,禁止写死绝对路径):scripts/_env.sh 自动探测 Python / venv / Node,
不含任何机器专属路径;WB_PY 优先取 skills/.venv,其次受管 venv,最后系统 python。
ensure_pydeps 在首次运行时创建 skills/.venv 并安装 scripts/requirements.txt 中的依赖。
BASE 目录:某 FZ 软件训练工程因安装位置而异,请用 --base 显式指定其下的 .../Jnjd/Graphs 目录;
脚本内也保留中性自动发现(扫描 */Jnjd/Graphs)。两个脚本均不预设任何装置 / 事故清单,
运行时自动发现该目录下全部 *.escg 并逐一处理;用 --match 通配符(如 *事故* / *关联*)可只跑其中一部分。
数据格式与解压(致命前提)
- 文件头 12 字节(offset 4–12 为 raw/comp size uint32),
data[12:]用
zlib.decompressobj().decompress(raw[12:])解压,按 GBK 解码。 - 解压后是合法 XML,可直接
xml.etree.ElementTree.fromstring。
⚠️ 解压陷阱(曾导致假阴性,务必照做)
- 必须
zlib.decompressobj().decompress(raw[12:])。
裸zlib.decompress(raw[12:])遇不完整流抛zlib.error: incomplete or truncated stream,
若被try/except: continue吞掉,文件会被静默跳过,误判"后台搜不到某条件"。 - 不要给
decompress()传max_length(会截断,最长文件 ~720 KB 虽未触发但属隐患,已全量移除)。
XML 树结构(关键)
CanvasManager > Canvas有 2 个 Canvas:- Canvas[0] 可视化:
Graphs > GradeProcess(大项,Text=名称)> GradeStep > StepData。 - Canvas[1] 流程逻辑:
PlanStep / LLink(本 Skill 不解析流向,只取条件)。 - 顶层
StepDatas > SetpData:步骤真数据 ——StepId / Description / StepType(Step=操作,Quality=质量) / Score。 - 每个 SetpData 都含
ConditionManager子节点,其下Condtions段按@ID分四类(这是核心): Condition ID="S{n}"(仅 1 条)—— 起评条件:本步激活/起评必须满足。Condtions[@ID="Necessary"]—— 必要条件(隐藏项):起评后本步完成必须满足,界面不显示。Condtions[@ID="Start"]—— 前置完成条件:本步起评前必须先完成的前置(如先开某阀)。Condtions[@ID="RunEnd"]—— 运行结束条件:Flag=Last,判定本步/评分态退出(如"某压力控制 0.5MPa")。- Flag 分布:Last / And / Or(多条件默认 And 组合)。
- 大项级隐藏起评条件:
GradeProcess(Canvas[0])本身也有ConditionManager,藏大项整体激活前提
(如"某操作 → 某位号.PV ≥ 某值 [DELAY 600s]")。按GradeProcess.Text对齐大项标题行填入,别只扫 SetpData。 - 得分时间限制:
SetpData > Score的ID属性里写LmtTimeX(...)(见 references/lmtdef.md)。
TimeType/DurationSeconds在内层 Condition 上(不在外层 Condtions)。
表达式提取
Left/Right的ID是位号;Logic映射到> ≥ < ≤ = ≠(见脚本LOGIC字典)。- 多条件用
且连接;带TimeType(非 None)时附[AFTER 180s] / [DELAY 600s] / [WITHIN Xs]。
交付口径(扣分类剔除)
- 判定扣分类 → 整步
continue剔除(仅保留大项标题行占位): Cumulative="True"(累积计分,几乎全是"某参数低低/高高扣分" −0.1 分/单位、上限 20 分);ScoreID 以-开头(定值负分)。- 得分时限只算
LmtTimeX()限时衰减函数一类;Cumulative累积计分不算,默认剔除。 - 隐藏列红字(
00C00000)+ 大项标题黄底(FFF2CC)。
工况范围(自动发现,无需预设)
- 本 Skill 不绑定任何装置或事故。两个脚本在运行时自动发现
--base指定的.../Jnjd/Graphs
目录下全部*.escg文件,逐一解压提取隐藏条件——换一套训练工程、换一种装置,直接指--base即可,
代码与文件名清单均无需改动。 - 用
--match通配符可只处理其中一部分(如--match "*事故*"仅跑事故类、--match "*关联*"仅跑关联类)。 - 输出文件名直接取
.escg的真实文件名(去扩展名),如某事故A_过程细目_含隐藏条件.xlsx、
某关联工况_过程细目_含隐藏条件.xlsx等随训练工程而定(名称即训练工程下的真实场景名)。 - ⚠️ 个别配置文件(如
moditem.ini)可能只列部分场景且不同步,不可靠;以 Graphs 目录.escg为准。 - 不同训练工程含隐藏条件步骤数差异很大,以实际产出 xlsx 的"含隐藏条件步骤数"列验收,无需预设固定数值。
位号归一化(跨工况对比时才需要,单工况隐藏条件提取可不做)
- 阀位号
Fx ≡ 阀名 Vx、温度位号Tx → Vx、泵位号P-x ≡ Px;须吞A/B泵后缀
(关闭PxA出口阀与关闭P-x出口阀应归一为同一动作,否则被拆成两条)。 - 阀体与"后手阀"不合并;停泵 ≠ 关出口阀。
- 仅在"找多个事故共同项"时用,见配套的「学员站评分细目导出」Skill。
输出格式
每工况 xlsx(如 某事故_过程细目_含隐藏条件.xlsx),列:
大项 / 步骤序号 / 描述 / 类型 / 分值 / 评判依据 / 起评条件(S) / 必要条件(Necessary) /
前置完成条件(Start) / 运行结束条件(RunEnd) / 得分时间限制。
- 大项标题行:黄底 + 该大项级隐藏条件(S/Necessary/Start/RunEnd)。
- 隐藏列(S/Necessary/Start/RunEnd/时限)非空 → 红字加粗。
- 汇总索引 全部事故_隐藏条件汇总.xlsx:每事故 总步数 / 剔除扣分步 / 保留行数 / 含深层隐藏条件步骤数。
bundled scripts
scripts/extract_hidden_conds.py— 通用批量提取:自动发现 Graphs 目录全部.escg,逐工况输出一个 xlsx + 汇总索引(--outdir/--base/--match)。scripts/extract_gaoya_conds.py— 通用合并提取:自动发现全部.escg,合并进一个工作簿(首 sheet「全部工况」汇总 + 每工况一 sheet;--out/--base/--match)。references/lmtdef.md— LmtTimeX 函数权威定义与全库分布。
关键坑速查
| 坑 | 正确做法 |
|---|---|
.escg 解压 |
zlib.decompressobj().decompress(raw[12:]),不裸 decompress、不传 max_length |
| 编码 | 解压后 .decode('gbk');Fun.ini 也是 GBK |
| 条件不全 | 必须扫 ConditionManager 全部 Condtions 段(S/Necessary/Start/RunEnd),不只取第一条 Condition |
| 漏大项级条件 | 同时扫 GradeProcess.ConditionManager(按 Text 对齐大项标题) |
| 扣分类误入 | Cumulative="True" 或 Score 以 - 开头 → 整步剔除 |
| 工况不全 | 脚本自动发现 Graphs 目录下全部 .escg,不预设事故清单;如需只跑一类用 --match "*事故*" 等通配符 |
| BASE 路径 | 用 --base 显式指定训练工程下的 .../Jnjd/Graphs,勿硬编码某次训练会话目录 |
| 时限两类 | LmtTime 限时衰减(要)+ Cumulative 累积(剔除) |
验收自检
- 运行
extract_hidden_conds.py后,每个工况 xlsx 的"必要条件/前置/运行结束"列有红字内容。 全部工况_隐藏条件汇总.xlsx显示:带限时步的工况 含隐藏步骤数 >0;纯起评类工况 = 0(仅起评S,正常)。- 抽查一个含
LmtTimeP的工况,"得分时间限制"列有"限时衰减:…"文本。 - 无
Cumulative/-开头的扣分行混入(grep 校验)。