Files
cobol-java-v3/report/generator.py
T

106 lines
4.5 KiB
Python

import json
from pathlib import Path
from data.diff_result import VerificationRun
class ReportGenerator:
def generate_json(self, run: VerificationRun, p: Path) -> Path:
d = {"program": run.program, "status": run.status, "exit_code": run.exit_code,
"timestamp": run.timestamp, "duration_s": run.duration_s,
"fields_matched": run.fields_matched, "fields_mismatched": run.fields_mismatched,
"runner": run.runner, "branch_rate": run.branch_rate, "llm_cost": run.llm_cost,
"field_results": [{"field_name": fr.field_name, "status": fr.status,
"cobol_value": fr.cobol_value, "java_value": fr.java_value,
"suggestion": fr.suggestion} for fr in run.field_results]}
p.write_text(json.dumps(d, indent=2))
return p
def generate_html(self, run: VerificationRun, p: Path) -> Path:
rows = "".join(
f'<tr class="{"pass" if fr.status == "PASS" else "fail"}"><td>{fr.field_name}'
f'</td><td>{fr.status}</td><td>{fr.cobol_value}</td><td>{fr.java_value}</td>'
f'<td>{fr.suggestion}</td></tr>'
for fr in run.field_results)
# 覆盖率卡片
coverage_html = ""
if run.paragraph_rate > 0 or run.branch_rate > 0:
mode = "静态+动态" if run.branch_rate > 0 else "仅静态"
pcolor = "green" if run.paragraph_rate >= 1.0 else "orange"
bcolor = "green" if run.branch_rate >= 0.9 else "orange"
coverage_html = f"""
<h2>覆盖率</h2>
<table border=1 cellpadding=4>
<tr><td>方式</td><td>{mode}</td></tr>
<tr><td>段落覆盖率</td><td style="color:{pcolor}">{run.paragraph_rate:.0%}</td></tr>
<tr><td>分支覆盖率</td><td style="color:{bcolor}">{run.branch_rate:.0%}</td></tr>
<tr><td>决策点覆盖率</td><td>{run.decision_rate:.0%}</td></tr>
</table>"""
# HINA 卡片
hina_html = ""
if run.hina_type:
hina_html = f"""
<h2>HINA 信息</h2>
<table border=1 cellpadding=4>
<tr><td>判定类型</td><td>{run.hina_type}</td></tr>
<tr><td>确信度</td><td>{run.hina_confidence:.0%}</td></tr>
</table>"""
# 质量评分卡片
quality_html = ""
if run.quality_score > 0:
color = "green" if run.quality_score >= 0.8 else "orange"
quality_html = f"""
<h2>质量评分</h2>
<div style="font-size:2rem;color:{color};font-weight:bold">{run.quality_score:.0%}</div>"""
# 重试历史卡片
retry_html = ""
if run.total_retry > 0:
retry_html = f"""
<h2>重试历史</h2>
<table border=1 cellpadding=4>
<tr><td>heal_retry</td><td>{run.heal_retry}</td></tr>
<tr><td>simple_retry</td><td>{run.simple_retry}</td></tr>
<tr><td>total_retry</td><td>{run.total_retry}</td></tr>
</table>"""
warn_html = ""
if run.quality_warn:
warn_html = f'<div style="background:#fff3cd;padding:1rem;margin:1rem 0">{run.quality_warn}</div>'
html = f"""<!DOCTYPE html>
<html><head><meta charset=utf-8><title>{run.program}</title>
<style>
body{{font-family:monospace;max-width:900px;margin:2rem auto}}
.pass{{background:#e6ffe6}}.fail{{background:#ffe6e6}}
pre{{background:#f0f0f0;padding:1rem}}
table{{border-collapse:collapse}} td,th{{padding:6px 12px}}
</style></head><body>
<h1>{run.program}</h1>
<pre>Status: {run.status} | Runner: {run.runner} | {run.fields_matched} matched | {run.duration_s:.0f}s</pre>
{warn_html}
<h2>字段比对</h2>
<table border=1 cellpadding=4>
<tr><th>Field</th><th>Status</th><th>COBOL</th><th>Java</th><th>Suggestion</th></tr>
{rows}</table>
{coverage_html}
{hina_html}
{quality_html}
{retry_html}
</body></html>"""
p.write_text(html)
return p
def generate_machine_json(self, run: VerificationRun, p: Path) -> Path:
d = {"program": run.program, "status": run.status, "exit_code": run.exit_code,
"timestamp": run.timestamp, "duration_s": run.duration_s, "runner": run.runner,
"branch_rate": run.branch_rate, "paragraph_rate": run.paragraph_rate,
"decision_rate": run.decision_rate, "quality_score": run.quality_score,
"hina_type": run.hina_type, "hina_confidence": run.hina_confidence,
"heal_retry": run.heal_retry, "simple_retry": run.simple_retry,
"total_retry": run.total_retry}
p.write_text(json.dumps(d))
return p