214 lines
7.8 KiB
Python
214 lines
7.8 KiB
Python
import tkinter as tk
|
|
from tkinter import ttk, messagebox, scrolledtext
|
|
import numpy as np
|
|
from collections import defaultdict
|
|
|
|
|
|
class AutoArtRatingSystem:
|
|
"""全自动艺术评分系统核心逻辑"""
|
|
|
|
def __init__(self):
|
|
self.scores = {} # {作品ID: [评分1, 评分2, ...]}
|
|
self.effective_scores = {} # {作品ID: 有效得分}
|
|
self.ranked_works = [] # [(作品ID, 得分), ...] 按得分降序排列
|
|
self.judge_stats = {} # {评委ID: {'平均打分':..., '得分范围':..., '离散程度':..., '异常评分':...}}
|
|
|
|
def auto_calculate(self):
|
|
"""自动执行所有统计分析"""
|
|
if not self.scores:
|
|
return
|
|
|
|
# 1. 计算有效得分(自动去掉最高最低分)
|
|
self.effective_scores = {
|
|
pid: round(
|
|
sum(sorted(score_list)[1:-1]) / max(1, len(score_list) - 2),
|
|
2
|
|
)
|
|
for pid, score_list in self.scores.items()
|
|
}
|
|
|
|
# 2. 自动生成作品排名
|
|
self.ranked_works = sorted(
|
|
self.effective_scores.items(),
|
|
key=lambda x: x[1],
|
|
reverse=True
|
|
)
|
|
|
|
# 3. 自动分析评委打分
|
|
judge_scores = defaultdict(list)
|
|
for pid, score_list in self.scores.items():
|
|
for judge_idx, score in enumerate(score_list):
|
|
judge_id = f"评委{judge_idx + 1}"
|
|
judge_scores[judge_id].append(score)
|
|
|
|
self.judge_stats = {}
|
|
for judge_id, score_list in judge_scores.items():
|
|
avg = round(np.mean(score_list), 2)
|
|
score_range = f"{min(score_list)}-{max(score_list)}"
|
|
std_dev = round(np.std(score_list), 2)
|
|
|
|
# 自动识别异常评分(超出均值±1.5标准差)
|
|
threshold = 1.5 * std_dev
|
|
outliers = [
|
|
s for s in score_list
|
|
if not (avg - threshold <= s <= avg + threshold)
|
|
]
|
|
self.judge_stats[judge_id] = {
|
|
'平均打分': avg,
|
|
'得分范围': score_range,
|
|
'离散程度': std_dev,
|
|
'异常评分': outliers if outliers else "无"
|
|
}
|
|
|
|
def get_report(self):
|
|
"""获取完整统计报告"""
|
|
self.auto_calculate()
|
|
report = "=== 自动艺术评分统计报告 ===\n\n"
|
|
|
|
# 1. 有效得分详情
|
|
report += "【有效得分计算】\n"
|
|
for pid, score in self.effective_scores.items():
|
|
raw_scores = self.scores[pid]
|
|
report += f"作品 {pid}: 原始评分[{', '.join(map(str, raw_scores))}] "
|
|
report += f"→ 有效得分{score}\n"
|
|
report += "\n"
|
|
|
|
# 2. 作品排名
|
|
report += "【作品最终排名】\n"
|
|
for rank, (pid, score) in enumerate(self.ranked_works, 1):
|
|
report += f"第{rank}名: 作品{pid} ({score}分)\n"
|
|
report += "\n"
|
|
|
|
# 3. 评委分析
|
|
report += "【评委评分分析】\n"
|
|
for judge_id, stats in self.judge_stats.items():
|
|
report += f"{judge_id}:\n"
|
|
report += f" • 平均打分: {stats['平均打分']}\n"
|
|
report += f" • 得分范围: {stats['得分范围']}\n"
|
|
report += f" • 离散程度: {stats['离散程度']}\n"
|
|
outliers = stats['异常评分']
|
|
outliers_str = ', '.join(map(str, outliers)) if isinstance(outliers, list) else outliers
|
|
report += f" • 异常评分: {outliers_str}\n\n"
|
|
return report
|
|
|
|
|
|
class AutoRatingApp:
|
|
"""全自动艺术评分系统GUI界面"""
|
|
|
|
def __init__(self, root):
|
|
self.root = root
|
|
self.root.title("全自动艺术评分系统")
|
|
self.root.geometry("900x700")
|
|
|
|
self.rating_system = AutoArtRatingSystem()
|
|
|
|
# 输入区域
|
|
input_frame = ttk.LabelFrame(root, text="评分数据输入")
|
|
input_frame.pack(fill="x", padx=10, pady=5)
|
|
|
|
# 作品ID输入
|
|
ttk.Label(input_frame, text="作品ID:").grid(row=0, column=0, padx=5, sticky="e")
|
|
self.piece_id = tk.StringVar()
|
|
ttk.Entry(input_frame, textvariable=self.piece_id, width=10).grid(row=0, column=1, padx=5)
|
|
|
|
# 评委评分输入
|
|
ttk.Label(input_frame, text="评委评分(空格分隔):").grid(row=0, column=2, padx=5, sticky="e")
|
|
self.scores_input = tk.StringVar()
|
|
ttk.Entry(input_frame, textvariable=self.scores_input, width=40).grid(row=0, column=3, padx=5)
|
|
|
|
# 添加按钮
|
|
ttk.Button(input_frame, text="添加评分", command=self.add_score).grid(row=0, column=4, padx=10)
|
|
|
|
# 数据展示区
|
|
data_frame = ttk.LabelFrame(root, text="当前评分数据")
|
|
data_frame.pack(fill="both", expand=True, padx=10, pady=5)
|
|
|
|
# 数据表格
|
|
columns = ("作品ID", "评委评分", "有效得分")
|
|
self.tree = ttk.Treeview(data_frame, columns=columns, show="headings")
|
|
for col in columns:
|
|
self.tree.heading(col, text=col)
|
|
self.tree.column(col, width=150 if col == "评委评分" else 100)
|
|
self.tree.pack(fill="both", expand=True)
|
|
|
|
# 报告区域
|
|
report_frame = ttk.LabelFrame(root, text="自动统计报告")
|
|
report_frame.pack(fill="both", expand=True, padx=10, pady=5)
|
|
|
|
self.report_text = scrolledtext.ScrolledText(report_frame, wrap=tk.WORD, width=80, height=15)
|
|
self.report_text.pack(fill="both", expand=True)
|
|
|
|
# 底部按钮
|
|
btn_frame = tk.Frame(root)
|
|
btn_frame.pack(fill="x", padx=10, pady=5)
|
|
|
|
ttk.Button(btn_frame, text="清除所有数据", command=self.clear_data).pack(side="left", padx=5)
|
|
ttk.Button(btn_frame, text="刷新报告", command=self.update_report).pack(side="right", padx=5)
|
|
|
|
def validate_input(self):
|
|
"""自动验证输入数据"""
|
|
piece_id = self.piece_id.get().strip()
|
|
score_str = self.scores_input.get().strip()
|
|
|
|
if not piece_id:
|
|
messagebox.showerror("错误", "作品ID不能为空")
|
|
return None
|
|
if piece_id in self.rating_system.scores:
|
|
messagebox.showerror("错误", f"作品 {piece_id} 已存在")
|
|
return None
|
|
try:
|
|
scores = list(map(float, score_str.split()))
|
|
if len(scores) < 3:
|
|
messagebox.showerror("错误", "至少需要3个评委评分")
|
|
return None
|
|
if any(s < 0 or s > 100 for s in scores):
|
|
messagebox.showerror("错误", "评分必须在0-100之间")
|
|
return None
|
|
return piece_id, scores
|
|
except ValueError:
|
|
messagebox.showerror("错误", "评分必须是数字,用空格分隔")
|
|
return None
|
|
|
|
def add_score(self):
|
|
"""添加评分数据并自动更新统计"""
|
|
data = self.validate_input()
|
|
if not data:
|
|
return
|
|
piece_id, scores = data
|
|
self.rating_system.scores[piece_id] = scores
|
|
|
|
# 更新表格显示
|
|
self.tree.insert(
|
|
"", "end",
|
|
values=(
|
|
piece_id,
|
|
", ".join(map(str, scores)),
|
|
self.rating_system.effective_scores.get(piece_id, "计算中...")
|
|
)
|
|
)
|
|
|
|
# 清空输入框
|
|
self.piece_id.set("")
|
|
self.scores_input.set("")
|
|
|
|
# 自动更新报告
|
|
self.update_report()
|
|
|
|
def update_report(self):
|
|
"""自动更新统计报告"""
|
|
self.report_text.delete(1.0, tk.END)
|
|
self.report_text.insert(tk.END, self.rating_system.get_report())
|
|
|
|
def clear_data(self):
|
|
"""清除所有数据并重置界面"""
|
|
self.rating_system = AutoArtRatingSystem()
|
|
self.tree.delete(*self.tree.get_children())
|
|
self.report_text.delete(1.0, tk.END)
|
|
messagebox.showinfo("提示", "所有数据已清除")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
root = tk.Tk()
|
|
app = AutoRatingApp(root)
|
|
root.mainloop()
|