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

def draw_score_chart():
    """绘制成绩走势图"""
    # 获取输入的成绩数据
    score_input = entry_scores.get("1.0", tk.END).strip()
    # 获取考试次数/标签
    exam_labels_input = entry_labels.get("1.0", tk.END).strip()
    
    # 校验成绩输入（仅允许数字、逗号、换行）
    if not re.match(r'^[\d\,\n\s\.]+$', score_input):
        messagebox.showerror("输入错误", "成绩只能输入数字，多个成绩用逗号/换行分隔！")
        return
    
    # 处理成绩数据（拆分、转换为数字）
    score_list = re.split(r'[,|\n|\s]+', score_input)
    score_list = [s for s in score_list if s.strip()]  # 去除空值
    if not score_list:
        messagebox.showwarning("提示", "请先输入/生成成绩数据！")
        return
    
    try:
        scores = [float(score) for score in score_list]
    except ValueError:
        messagebox.showerror("输入错误", "成绩必须是有效的数字！")
        return
    
    # 处理考试标签（无输入则用默认序号）
    if exam_labels_input:
        exam_labels = re.split(r'[,|\n|\s]+', exam_labels_input)
        exam_labels = [label.strip() for label in exam_labels if label.strip()]
        # 标签数量不足时，补充默认序号
        if len(exam_labels) < len(scores):
            exam_labels += [f"考试{i+1}" for i in range(len(exam_labels), len(scores))]
    else:
        exam_labels = [f"考试{i+1}" for i in range(len(scores))]
    # 标签数量超过成绩时，截断
    exam_labels = exam_labels[:len(scores)]
    
    # 清空之前的图表
    for widget in frame_chart.winfo_children():
        widget.destroy()
    
    # 创建 matplotlib 图表
    fig, ax = plt.subplots(figsize=(8, 5), dpi=100)
    # 绘制折线图（成绩走势），添加标记点
    ax.plot(exam_labels, scores, marker='o', color='#2E86AB', linewidth=2, markersize=6)
    # 填充折线下方区域，增强视觉效果
    ax.fill_between(exam_labels, scores, alpha=0.2, color='#2E86AB')
    
    # 设置图表样式
    ax.set_title('成绩走势分析', fontsize=14, fontweight='bold', pad=20)
    ax.set_xlabel('考试次数/阶段', fontsize=12)
    ax.set_ylabel('成绩', fontsize=12)
    ax.grid(True, linestyle='--', alpha=0.7)  # 添加网格
    ax.set_ylim(0, 100)  # 成绩范围限定 0-100 分
    
    # 适配中文显示（避免乱码）
    plt.rcParams['font.sans-serif'] = ['SimHei']  # 黑体
    plt.rcParams['axes.unicode_minus'] = False    # 解决负号显示问题
    
    # 将图表嵌入 Tkinter 窗口
    canvas = FigureCanvasTkAgg(fig, master=frame_chart)
    canvas.draw()
    canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

def generate_random_scores():
    """随机生成成绩数据"""
    try:
        # 获取用户设置的考试次数，默认8次
        exam_count = int(entry_exam_count.get().strip())
        if exam_count < 1 or exam_count > 20:
            messagebox.showwarning("提示", "考试次数请设置为1-20之间的整数！")
            return
    except ValueError:
        messagebox.showerror("输入错误", "考试次数必须是整数！")
        return
    
    # 生成随机成绩（60-100分，保留1位小数，模拟真实成绩）
    random_scores = [round(random.uniform(60, 100), 1) for _ in range(exam_count)]
    # 转换为字符串，用逗号分隔
    scores_str = ", ".join([str(score) for score in random_scores])
    
    # 生成对应的考试标签
    labels_str = ", ".join([f"考试{i+1}" for i in range(exam_count)])
    
    # 清空输入框并填充随机数据
    entry_scores.delete("1.0", tk.END)
    entry_scores.insert(tk.END, scores_str)
    entry_labels.delete("1.0", tk.END)
    entry_labels.insert(tk.END, labels_str)
    
    # 自动绘制走势图
    draw_score_chart()

# 主窗口配置
root = tk.Tk()
root.title("随机成绩走势图生成器")
root.geometry("900x700")
root.resizable(True, True)

# 1. 输入区域
frame_input = ttk.LabelFrame(root, text="数据设置", padding=10)
frame_input.pack(fill=tk.X, padx=20, pady=10)

# 考试次数设置
label_exam_count = ttk.Label(frame_input, text="考试次数（1-20）：")
label_exam_count.grid(row=0, column=0, sticky=tk.W, pady=5)
entry_exam_count = ttk.Entry(frame_input, width=10)
entry_exam_count.grid(row=0, column=1, sticky=tk.W, pady=5)
entry_exam_count.insert(0, "8")  # 默认8次考试

# 随机生成按钮
btn_generate = ttk.Button(frame_input, text="随机生成成绩", command=generate_random_scores)
btn_generate.grid(row=0, column=2, padx=10, pady=5)

# 成绩输入框
label_scores = ttk.Label(frame_input, text="成绩数据（可手动修改）：")
label_scores.grid(row=1, column=0, sticky=tk.W, pady=5)
entry_scores = tk.Text(frame_input, width=60, height=3)
entry_scores.grid(row=2, column=0, columnspan=3, pady=5)

# 考试标签输入框
label_labels = ttk.Label(frame_input, text="考试标签（可手动修改）：")
label_labels.grid(row=3, column=0, sticky=tk.W, pady=5)
entry_labels = tk.Text(frame_input, width=60, height=2)
entry_labels.grid(row=4, column=0, columnspan=3, pady=5)

# 手动绘图按钮
btn_draw = ttk.Button(frame_input, text="重新绘制走势图", command=draw_score_chart)
btn_draw.grid(row=5, column=0, columnspan=3, pady=10)

# 2. 图表展示区域
frame_chart = ttk.LabelFrame(root, text="成绩走势图", padding=10)
frame_chart.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)

# 初始生成随机成绩并绘图
generate_random_scores()

# 运行主循环
root.mainloop()