119 lines
3.9 KiB
Python
119 lines
3.9 KiB
Python
"""输出层: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)
|