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.rating_system.auto_calculate()

        # 更新表格显示
        effective_score = self.rating_system.effective_scores.get(piece_id, "计算中...")
        self.tree.insert(
            "", "end",
            values=(
                piece_id,
                ", ".join(map(str, scores)),
                effective_score
            )
        )

        # 清空输入框
        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()