# -*- coding: utf-8 -*- """ 用【同缸径的真实数据值域】作为官方值域的代理, 评估生成候选的保守程度。 为什么用代理: 官方图册是双栏排版, pdftotext 后左右栏交错, 正则解析多次尝试均不可靠 (把真实数据都判成越界 = 解析错误)。而【真实型号】是最可靠的一手证据: 某缸径的真实型号里从未出现过的取值, 生成它就是推测。 判定口径 (保守): 某候选的每个参数值, 是否都在【同缸径的真实型号】中出现过? - 全部出现过 → 属"组合缺失", 补全风险低 - 有值从未出现 → 属"引入新值", 补全风险高 (需人工/AI 核对官方图册) """ import csv, io, os, collections CAT = r'D:/开发/OnebotCatalog/onebot-data/catalog' DIMS = ['stroke', 'rod', 'orient', 'sensor', 'mount', 'style', 'pos', 'type'] def main(): rows = list(csv.DictReader(io.open(os.path.join(CAT, 'csv', 'ULP.csv'), encoding='utf-8-sig'))) real = [r for r in rows if r['step_file'] != 'PLACEHOLDER.step'] gen = [r for r in rows if r['step_file'] == 'PLACEHOLDER.step'] dims = [d for d in DIMS if d in rows[0]] # 每个缸径的真实取值集合 domain = collections.defaultdict(lambda: collections.defaultdict(set)) for r in real: for d in dims: if r[d] != '': domain[r['size']][d].add(r[d]) print('=' * 74) print('真实数据里各缸径的取值域 (作为官方值域的代理)') print('=' * 74) for b in sorted(domain, key=int): parts = [f'{d}={sorted(domain[b][d])}' for d in dims if domain[b][d]] n = sum(1 for r in real if r['size'] == b) print(f' ULP{b:>3s} ({n:3d} 个真实型号)') for p in parts: print(f' {p}') # 评估生成候选 safe, risky = 0, 0 risky_detail = collections.Counter() risky_models = [] for r in gen: b = r['size'] novel = [f'{d}={r[d]}' for d in dims if r[d] != '' and r[d] not in domain.get(b, {}).get(d, set())] if novel: risky += 1 for x in novel: risky_detail[f'ULP{b} {x}'] += 1 if len(risky_models) < 5: risky_models.append((r['model_code'], novel)) else: safe += 1 print() print('=' * 74) print(f'生成候选 {len(gen)} 个的保守度评估') print('=' * 74) print(f' 低风险 (全部取值在同缸径真实数据中出现过): {safe} ({safe*100//len(gen)}%)') print(f' 高风险 (含该缸径从未出现的取值) : {risky} ({risky*100//len(gen)}%)') if risky_detail: print('\n 高风险取值 TOP15 (该缸径真实数据里从未出现):') for k, v in risky_detail.most_common(15): print(f' {k:28s} {v:5d} 个候选') print('\n 高风险样本:') for mc, novel in risky_models: print(f' {mc:18s} 新值 {novel}') if __name__ == '__main__': main()