import warnings
import os
# 屏蔽libpng、matplotlib多余警告
os.environ["QT_LOGGING_RULES"] = "*.warning=false"
warnings.filterwarnings("ignore")

import tkinter as tk
from tkinter import ttk, messagebox
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import json

# 字体修复（Windows兼容）
plt.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei"]
plt.rcParams["axes.unicode_minus"] = False

DATA_FILE = "score_data.json"

class ScoreChartApp:
    def __init__(self, root):
        self.root = root
        self.root.title("成绩走势图工具")
        self.root.geometry("900x650")

        self.score_list = self.load_data()

        # 左侧面板
        frame_left = ttk.Frame(root, padding=10)
        frame_left.pack(side=tk.LEFT, fill=tk.Y)

        ttk.Label(frame_left, text="考试名称：").pack(anchor="w")
        self.entry_name = ttk.Entry(frame_left, width=20)
        self.entry_name.pack(pady=3)

        ttk.Label(frame_left, text="分数：").pack(anchor="w")
        self.entry_score = ttk.Entry(frame_left, width=20)
        self.entry_score.pack(pady=3)

        ttk.Button(frame_left, text="添加成绩", command=self.add_score).pack(pady=5, fill=tk.X)
        ttk.Button(frame_left, text="刷新图表", command=self.draw_chart).pack(pady=3, fill=tk.X)
        ttk.Button(frame_left, text="清空所有数据", command=self.clear_all).pack(pady=3, fill=tk.X)

        # 绘图区域
        self.fig, self.ax = plt.subplots(figsize=(7, 5), dpi=100)
        self.canvas = FigureCanvasTkAgg(self.fig, master=root)
        self.canvas_widget = self.canvas.get_tk_widget()
        self.canvas_widget.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=5, pady=5)

        self.draw_chart()

    def load_data(self):
        if os.path.exists(DATA_FILE):
            try:
                with open(DATA_FILE, "r", encoding="utf-8") as f:
                    return json.load(f)
            except:
                return []
        return []

    def save_data(self):
        with open(DATA_FILE, "w", encoding="utf-8") as f:
            json.dump(self.score_list, f, ensure_ascii=False, indent=2)

    def add_score(self):
        exam_name = self.entry_name.get().strip()
        score_text = self.entry_score.get().strip()
        if not exam_name or not score_text:
            messagebox.showwarning("提示", "考试名称和分数不能为空！")
            return
        try:
            score = float(score_text)
            if not (0 <= score <= 100):
                messagebox.showwarning("提示", "分数范围0~100！")
                return
        except ValueError:
            messagebox.showerror("错误", "分数必须是数字！")
            return

        self.score_list.append({"exam": exam_name, "score": score})
        self.save_data()
        self.entry_name.delete(0, tk.END)
        self.entry_score.delete(0, tk.END)
        self.draw_chart()
        messagebox.showinfo("成功", "成绩添加完成！")

    def draw_chart(self):
        self.ax.clear()
        if len(self.score_list) == 0:
            self.ax.text(0.5, 0.5, "暂无成绩数据，请录入成绩", ha="center", va="center", transform=self.ax.transAxes, fontsize=14)
        else:
            names = [item["exam"] for item in self.score_list]
            scores = [item["score"] for item in self.score_list]
            self.ax.plot(names, scores, marker="o", color="#2E86AB", linewidth=2, markersize=6)
            self.ax.set_title("成绩变化走势图", fontsize=14)
            self.ax.set_ylabel("分数")
            self.ax.grid(alpha=0.3)
            self.ax.set_ylim(0, 105)
            plt.setp(self.ax.get_xticklabels(), rotation=30, ha="right")
        self.fig.tight_layout()
        self.canvas.draw()

    def clear_all(self):
        if messagebox.askyesno("确认", "确定删除全部成绩数据？无法恢复！"):
            self.score_list = []
            self.save_data()
            self.draw_chart()

if __name__ == "__main__":
    window = tk.Tk()
    app = ScoreChartApp(window)
    window.mainloop()