# -*- coding: utf-8 -*- """ 量化"参数组合缺口": 合法组合 (域 + 规则内) vs 库中已有变体, 以及补全的规模。 对每个系列: - 现有变体数 - 笛卡尔积规模 (各参数值域相乘) - 规则过滤后的合法组合数 (复用 C# Configurator 同语义的规则求值) - 缺口 = 合法组合 - 已覆盖 这决定"补全组合数据"的可行性与数据量。 """ import json, io, itertools CAT = r'D:/开发/OnebotCatalog/release/web_2026.08/catalog.json' d = json.load(io.open(CAT, encoding='utf-8-sig')) def S(v): return '' if v is None else str(v) def eq(a, b): return S(a).lower() == S(b).lower() def cond_match(c, params): """规则条件求值 (与 app.js condMatches / C# CondMatches 同语义)。""" if not c: return True val = params.get(c['Param']) if val is None: return False op = c['Op'] cv = c['Value'] if op == 'eq': return eq(val, cv) if op == 'ne': return not eq(val, cv) if op == 'in': return isinstance(cv, list) and any(eq(val, x) for x in cv) try: a, b = float(S(val)), float(S(cv)) except ValueError: return False return {'gt': a > b, 'ge': a >= b, 'lt': a < b, 'le': a <= b}.get(op, False) def rule_violated(rules, params): for r in rules or []: if cond_match(r.get('If'), params) and not cond_match(r.get('Then'), params): return True return False print(f'{"系列":7s} {"现有":>6s} {"笛卡尔":>9s} {"规则内":>9s} {"缺口":>9s} {"倍数":>5s}') print('-' * 62) tot_exist = tot_gap = 0 rows = [] for s in d['series']: vs = s.get('variants') or [] if not vs: continue params = s['parameters'] doms = [] for p in params: vals = p.get('values') or [] if not vals: doms = None break doms.append(vals) if doms is None: rows.append((s['code'], len(vs), None, None, None)) continue cart = 1 for vals in doms: cart *= len(vals) # 规则过滤 (笛卡尔过大时抽样估算) legal = 0 if cart <= 400000: for combo in itertools.product(*doms): prm = {p['code']: v for p, v in zip(params, combo)} if not rule_violated(s.get('rules'), prm): legal += 1 else: legal = None # 太大, 跳过精确统计 gap = (legal - len(vs)) if legal is not None else None rows.append((s['code'], len(vs), cart, legal, gap)) if legal is not None: tot_exist += len(vs) tot_gap += max(0, gap) for code, n, cart, legal, gap in sorted(rows, key=lambda x: -(x[4] or -1)): c = f'{cart:,}' if cart else '—' l = f'{legal:,}' if legal else '—' g = f'{gap:,}' if gap is not None else '—' mult = f'{legal/n:.1f}x' if legal and n else '—' flag = ' <-- 缺口大' if gap and gap > 50000 else '' print(f'{code:7s} {n:6d} {c:>9s} {l:>9s} {g:>9s} {mult:>5s}{flag}') print(f'\n合计: 现有 {tot_exist:,} 变体, 缺口 {tot_gap:,} 组合') print(f'补全后约 {tot_exist + tot_gap:,} 变体 (是现在的 {(tot_exist+tot_gap)/tot_exist:.1f} 倍)')