Files
gaokao-volunteer-system/scripts/legacy/gaokao-visual-report.py
Hermes Agent 3f46811e49
Some checks failed
CI / pytest (Python 3.10) (push) Has been cancelled
CI / pytest (Python 3.11) (push) Has been cancelled
CI / pytest (Python 3.12) (push) Has been cancelled
release: cut v2.1
2026-06-13 14:49:58 +08:00

339 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
高考志愿填报可视化报告生成器
支持:雷达图、热力图、对比表、风险检测
"""
from datetime import datetime
def generate_student_radar(student_profile):
"""
生成考生画像雷达图数据
"""
scores = {
"兴趣匹配度": student_profile.get("interest_match", 0),
"能力匹配度": student_profile.get("ability_match", 0),
"就业匹配度": student_profile.get("employment_match", 0),
"家庭适配度": student_profile.get("family_match", 0),
}
# 综合得分计算
weighted_score = (
scores["兴趣匹配度"] * 0.3 +
scores["能力匹配度"] * 0.3 +
scores["就业匹配度"] * 0.25 +
scores["家庭适配度"] * 0.15
)
# 生成ASCII雷达图
radar_chart = f"""
┌─────────────────────────────────────────────────────────────────┐
│ 🎯 {student_profile.get('name', '考生')} 画像雷达图 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 兴趣匹配度 │
{scores['兴趣匹配度']:>3}/10 │
│ │ │
{min(scores['能力匹配度'], 10):>2}/10 ─────────┼───────── {min(scores['就业匹配度'], 10):>2}/10 │
│ 能力匹配度 │ 就业匹配度 │
│ │ │
│ 【{weighted_score:.1f}/10】 │
│ 综合得分 │
│ │ │
{scores['家庭适配度']:>3}/10 │
│ 家庭适配度 │
│ │
├─────────────────────────────────────────────────────────────────┤
│ 评分说明: │
│ • 兴趣匹配:基于霍兰德职业兴趣测试结果 │
│ • 能力匹配:学科成绩与专业要求的匹配度 │
│ • 就业匹配:专业就业前景评估 │
│ • 家庭适配:经济条件、地域要求的符合度 │
└─────────────────────────────────────────────────────────────────┘
"""
return radar_chart, weighted_score
def generate_school_comparison(volunteer_list):
"""
生成院校对比决策表
"""
table = """
┌──────────────────────────────────────────────────────────────────────┐
│ 🎯 志愿方案可视化对比 │
├────────────┬────────────┬──────────┬─────────┬─────────┬───────────┤
│ 志愿类型 │ 院校 │ 专业 │ 录取概率│ 匹配指数│ 推荐指数 │
├────────────┼────────────┼──────────┼─────────┼─────────┼───────────┤
"""
for idx, vol in enumerate(volunteer_list, 1):
v_type = vol.get('type', '')
emoji = {'': '🔴', '': '🟡', '': '🟢'}.get(v_type, '')
prob_bar = '' * int(vol.get('probability', 0) / 10) + '' * (10 - int(vol.get('probability', 0) / 10))
match_score = vol.get('match_score', 0)
stars = '' * int(match_score / 20) + '' * (5 - int(match_score / 20))
table += f"""{emoji} {v_type:>2} {idx:>2}{vol.get('school', '待定'):<10}{vol.get('major', '待定'):<8}{prob_bar}{match_score:>3}{stars}
├────────────┼────────────┼──────────┼─────────┼─────────┼───────────┤
"""
table += """│ │
│ 图例: │
│ 录取概率 █████ 90%+ ████░ 80%+ ███░░ 60%+ ██░░░ 40%+ █░░░░ <20%
│ 匹配指数 90-100 完美 80-90 高度 70-80 中度 <70 需谨慎 │
└──────────────────────────────────────────────────────────────────┘
"""
return table
def generate_major_heatmap(majors):
"""
生成专业匹配度热力图
"""
heatmap = """
┌──────────────────────────────────────────────────────────────────────┐
│ 🔥 兴趣-专业匹配度热力图 │
├──────────────────────────────────────────────────────────────────────┤
│ │
"""
for major in majors:
name = major.get('name', '')
score = major.get('match_score', 0)
# 生成热力条
if score >= 90:
bar = '' * 20
status = '强烈推荐'
elif score >= 80:
bar = '' * 17 + '' * 3
status = '推荐选择'
elif score >= 70:
bar = '' * 14 + '' * 6
status = '可以考虑'
elif score >= 60:
bar = '' * 11 + '' * 9
status = '谨慎考虑'
elif score >= 40:
bar = '' * 8 + '' * 12
status = '不太建议'
else:
bar = '' * 5 + '' * 15
status = '不推荐'
heatmap += f"{name:<12} {bar} {score:>3}% {status:<12}\n"
heatmap += """│ │
│ 热力指数:████ 90-100% ████ 80-90% ███░ 70-80% ██░░ 60-70%
│ █░░░ 30-60% ░░░░ <30% (不推荐) │
└──────────────────────────────────────────────────────────────────────┘
"""
return heatmap
def detect_risks(student_profile, volunteer_list):
"""
智能风险检测
"""
risks = []
# 检查位次差距
for vol in volunteer_list:
if vol.get('type') == '':
if vol.get('probability', 0) < 30:
risks.append({
'level': 'warning',
'item': f"{vol.get('school')}录取概率过低",
'desc': f"录取概率仅{vol.get('probability')}%,需要增加相近备选"
})
# 检查学科匹配
weak_subjects = student_profile.get('weak_subjects', [])
for vol in volunteer_list:
required = vol.get('required_subjects', [])
for subj in required:
if subj in weak_subjects:
risks.append({
'level': 'danger',
'item': f"{vol.get('school')}-{vol.get('major')}学科不匹配",
'desc': f"该专业需要{subj},但考生{subj}为弱项"
})
# 检查梯度合理性
types_count = {'': 0, '': 0, '': 0}
for vol in volunteer_list:
v_type = vol.get('type', '')
types_count[v_type] = types_count.get(v_type, 0) + 1
total = len(volunteer_list)
if total > 0:
if types_count[''] / total < 0.2:
risks.append({
'level': 'danger',
'item': '保底志愿不足',
'desc': f"保底志愿仅占{types_count['']/total*100:.0f}%建议至少30%"
})
# 生成风险报告
risk_report = """
┌──────────────────────────────────────────────────────────────────────┐
│ 🚦 志愿填报风险检测报告 │
├──────────────────────────────────────────────────────────────────────┤
│ │
"""
danger_list = [r for r in risks if r['level'] == 'danger']
warning_list = [r for r in risks if r['level'] == 'warning']
if danger_list:
risk_report += "│ 🔴 高风险项目(必须修改): │\n"
for risk in danger_list:
risk_report += f"│ ✗ {risk['item']:<30}\n"
risk_report += f"│ → {risk['desc']:<50}\n"
risk_report += "│ │\n"
if warning_list:
risk_report += "│ 🟡 中风险项目(建议调整): │\n"
for risk in warning_list:
risk_report += f"│ ⚠ {risk['item']:<30}\n"
risk_report += f"│ → {risk['desc']:<50}\n"
risk_report += "│ │\n"
if not risks:
risk_report += "│ 🟢 恭喜!未检测到高风险项目,当前方案可以安全填报 │\n"
risk_report += """│ │
└──────────────────────────────────────────────────────────────────────┘
"""
return risk_report, risks
def generate_volunteer_report(student_data, volunteer_list):
"""
生成完整可视化报告
"""
report = f"""
# 高考志愿填报可视化报告
**生成时间**{datetime.now().strftime('%Y年%m月%d%H:%M')}
**考生姓名**{student_data.get('name', '未知')}
**考生省份**{student_data.get('province', '未知')}
**高考总分**{student_data.get('score', 0)}
**全省位次**{student_data.get('rank', 0)}
---
## 一、考生画像雷达图
"""
# 生成雷达图
radar, total_score = generate_student_radar(student_data)
report += radar
report += f"\n**综合匹配指数**{total_score:.1f}/10\n\n"
# 生成院校对比表
report += "## 二、志愿方案可视化对比\n\n"
report += generate_school_comparison(volunteer_list)
report += "\n\n"
# 生成专业热力图
majors = []
for vol in volunteer_list:
majors.append({
'name': vol.get('major', '未知'),
'match_score': vol.get('match_score', 0)
})
report += "## 三、专业匹配度热力图\n\n"
report += generate_major_heatmap(majors)
report += "\n\n"
# 风险检测
report += "## 四、风险检测报告\n\n"
risk_report, risks = detect_risks(student_data, volunteer_list)
report += risk_report
report += "\n\n"
# 建议总结
report += """## 五、填报建议总结
基于以上分析,给出以下建议:
| 建议类型 | 具体内容 |
|---------|---------|
| ✅ 推荐选择 | [根据匹配度最高的志愿填写] |
| ⚠️ 谨慎考虑 | [根据风险提示填写] |
| ❌ 不建议 | [根据不匹配项填写] |
---
*本报告由智能志愿填报系统生成数据基于2025年历史录取信息*
"""
return report
# 示例使用
if __name__ == "__main__":
# 示例考生数据
student = {
'name': '李明',
'province': '浙江省',
'score': 612,
'rank': 15230,
'interest_match': 85, # 兴趣匹配度
'ability_match': 90, # 能力匹配度
'employment_match': 88, # 就业匹配度
'family_match': 95, # 家庭适配度
'weak_subjects': ['化学', '语文']
}
# 示例志愿列表
volunteers = [
{
'school': '浙江大学',
'major': '计算机类',
'type': '',
'probability': 35,
'match_score': 95,
'required_subjects': ['数学', '物理']
},
{
'school': '杭州电子科技大学',
'major': '计算机类',
'type': '',
'probability': 70,
'match_score': 92,
'required_subjects': ['数学', '物理']
},
{
'school': '浙江工业大学',
'major': '软件工程',
'type': '',
'probability': 80,
'match_score': 88,
'required_subjects': ['数学']
},
{
'school': '浙江理工大学',
'major': '软件工程',
'type': '',
'probability': 95,
'match_score': 82,
'required_subjects': ['数学']
}
]
# 生成报告
report = generate_volunteer_report(student, volunteers)
# 输出到文件
output_file = f"/tmp/gaokao_visual_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
with open(output_file, 'w', encoding='utf-8') as f:
f.write(report)
print(f"报告已生成:{output_file}")
print("\n报告预览:")
print(report)