"""输出层:JSON输出(按文件分组入出力 + 工作存储区分)""" import json from pathlib import Path _INVERSE_OP = {'>': '<=', '<': '>=', '=': '<>', '>=': '<', '<=': '>'} def _scenario_text(path_cons): parts = [] for c in path_cons: if len(c) != 4: continue field, op, val, want = c if op == 'not_in': desc = f"{field} not in {val}" if want else f"{field} in {val}" elif not want: desc = f"{field} {_INVERSE_OP.get(op, '?' + op)} {val}" else: desc = f"{field} {op} {val}" parts.append(desc) return ', '.join(parts) def output_json(records, outpath, roles=None, fd_fields=None, field_to_fd=None, open_dir=None, path_cons_list=None): outpath.parent.mkdir(parents=True, exist_ok=True) if not roles: with open(outpath, 'w', encoding='utf-8') as f: json.dump(records, f, ensure_ascii=False, indent=2) return # FD direction lookup out = [] for i, rec in enumerate(records): inp = {} out_exp = {} ws = {} # Group by FD if fd_fields and field_to_fd: for fd_name, fds_set in fd_fields.items(): direction = (open_dir or {}).get(fd_name, '') inp_block = {} out_block = {} for fname in fds_set: if fname not in rec: continue r = roles.get(fname, 'unused') val = rec[fname] if direction in ('INPUT', 'I-O') and r in ('input', 'inout'): inp_block[fname] = val if direction in ('OUTPUT', 'I-O') and r in ('output', 'inout'): out_block[fname] = val if inp_block: inp[fd_name] = inp_block if out_block: out_exp[fd_name] = out_block # Working-storage: not belonging to any FD for name, val in rec.items(): if not field_to_fd or name not in field_to_fd: ws[name] = val entry = { 'input': inp, 'expected_output': out_exp, 'working_storage': ws, } if path_cons_list and i < len(path_cons_list): text = _scenario_text(path_cons_list[i]) if text: entry['scenario'] = text out.append(entry) with open(outpath, 'w', encoding='utf-8') as f: json.dump(out, f, ensure_ascii=False, indent=2) def output_input_files(records, outdir, stem, roles, fd_fields, field_to_fd, open_dir): """按 FD 名拆分出力入力 JSON 文件。 每个 INPUT / I-O 方向 FD 生成一个文件:{stem}_{fd_name}.json 内容为路径数 × 记录,每条只含该 FD 的入力字段值。 """ input_fds = {} for fd_name, fds_set in fd_fields.items(): direction = (open_dir or {}).get(fd_name, '') if direction not in ('INPUT', 'I-O'): continue has_input = any(roles.get(fname, 'unused') in ('input', 'inout') for fname in fds_set) if not has_input: continue input_fds[fd_name] = fds_set if not input_fds: return outdir.mkdir(parents=True, exist_ok=True) for fd_name, fds_set in input_fds.items(): fd_records = [] direction = (open_dir or {}).get(fd_name, '') for rec in records: fd_rec = {} for fname in fds_set: r = roles.get(fname, 'unused') if direction in ('INPUT', 'I-O') and r in ('input', 'inout'): if fname in rec: fd_rec[fname] = rec[fname] if fd_rec: fd_records.append(fd_rec) outpath = outdir / f'{stem}_{fd_name}.json' with open(outpath, 'w', encoding='utf-8') as f: json.dump(fd_records, f, ensure_ascii=False, indent=2)