import tkinter as tk
from tkinter import ttk, messagebox
import random
import time

# 练习文本库
TEXT_LIST = [
    "The quick brown fox jumps over the lazy dog. A fast movement can surprise anyone nearby.",
    "Programming is the art of telling a computer what to do step by step with clear logic.",
    "Life is not about waiting for the storm to pass but learning how to dance in the rain.",
    "Python is easy to learn, powerful programming language with simple and clean syntax.",
    "Practice makes perfect, consistent typing training will greatly improve your input speed.",
    "Never give up on your dreams, small progress every day leads to huge changes in future.",
    "Technology changes the world, we should keep learning new skills to keep up with times."
]

class TypingPracticeApp:
    def __init__(self, root):
        self.root = root
        self.root.title("打字练习工具")
        self.root.geometry("900x600")
        self.root.resizable(False, False)

        # 全局变量
        self.start_time = None
        self.is_start = False
        self.target_text = ""
        self.correct_count = 0
        self.total_input = 0

        self.create_widgets()
        self.reset_game()

    def create_widgets(self):
        # 顶部信息栏
        info_frame = tk.Frame(self.root)
        info_frame.pack(fill="x", padx=20, pady=10)

        self.label_time = tk.Label(info_frame, text="用时：0 s", font=("微软雅黑", 12))
        self.label_time.pack(side="left", padx=10)

        self.label_speed = tk.Label(info_frame, text="速度：0 WPM", font=("微软雅黑", 12))
        self.label_speed.pack(side="left", padx=10)

        self.label_correct = tk.Label(info_frame, text="正确率：100%", font=("微软雅黑", 12))
        self.label_correct.pack(side="left", padx=10)

        # 目标文本显示框
        tk.Label(self.root, text="对照文本：", font=("微软雅黑", 13)).pack(anchor="w", padx=20)
        self.text_target = tk.Text(self.root, height=6, font=("Consolas", 14), wrap="word")
        self.text_target.pack(fill="x", padx=20)
        self.text_target.config(state="disabled")

        # 输入框
        tk.Label(self.root, text="在此输入：", font=("微软雅黑", 13)).pack(anchor="w", padx=20, pady=(10,0))
        self.text_input = tk.Text(self.root, height=6, font=("Consolas", 14), wrap="word")
        self.text_input.pack(fill="x", padx=20)
        self.text_input.bind("<KeyRelease>", self.check_input)

        # 按钮区域
        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=20)
        ttk.Button(btn_frame, text="重新开始", command=self.reset_game, width=12).grid(row=0, column=0, padx=10)
        ttk.Button(btn_frame, text="换一段文本", command=self.change_text, width=12).grid(row=0, column=1, padx=10)
        ttk.Button(btn_frame, text="查看成绩", command=self.show_result, width=12).grid(row=0, column=2, padx=10)

        # 标签颜色配置
        self.text_input.tag_config("right", foreground="green")
        self.text_input.tag_config("wrong", foreground="red")

    def reset_game(self):
        """重置所有数据，重新开始"""
        self.start_time = None
        self.is_start = False
        self.correct_count = 0
        self.total_input = 0
        self.label_time.config(text="用时：0 s")
        self.label_speed.config(text="速度：0 WPM")
        self.label_correct.config(text="正确率：100%")
        self.text_input.delete(1.0, tk.END)
        self.change_text()

    def change_text(self):
        """更换随机文本"""
        self.target_text = random.choice(TEXT_LIST)
        self.text_target.config(state="normal")
        self.text_target.delete(1.0, tk.END)
        self.text_target.insert(1.0, self.target_text)
        self.text_target.config(state="disabled")
        self.text_input.delete(1.0, tk.END)
        self.start_time = None
        self.is_start = False

    def check_input(self, event):
        """实时校验输入文字，上色并计时"""
        input_content = self.text_input.get(1.0, tk.END).strip("\n")
        # 首次输入启动计时
        if not self.is_start and len(input_content) > 0:
            self.start_time = time.time()
            self.is_start = True

        # 清空原有颜色标签
        self.text_input.tag_remove("right", "1.0", tk.END)
        self.text_input.tag_remove("wrong", "1.0", tk.END)

        self.correct_count = 0
        self.total_input = len(input_content)
        min_len = min(len(input_content), len(self.target_text))

        # 逐字符对比上色
        for i in range(min_len):
            pos = f"1.{i}"
            if input_content[i] == self.target_text[i]:
                self.correct_count += 1
                self.text_input.tag_add("right", pos, f"1.{i+1}")
            else:
                self.text_input.tag_add("wrong", pos, f"1.{i+1}")

        # 更新数据面板
        self.update_data()

        # 全部输入完成弹窗提示
        if input_content == self.target_text:
            self.show_result()

    def update_data(self):
        """更新时间、速度、正确率"""
        if not self.is_start or self.start_time is None:
            return
        # 用时
        use_time = time.time() - self.start_time
        self.label_time.config(text=f"用时：{round(use_time, 1)} s")
        # 正确率
        if self.total_input > 0:
            accuracy = self.correct_count / self.total_input * 100
            self.label_correct.config(text=f"正确率：{round(accuracy, 1)}%")
        else:
            self.label_correct.config(text="正确率：100%")
        # WPM打字速度（英文标准：单词数/分钟）
        words = self.correct_count / 5
        wpm = words / (use_time / 60) if use_time > 0 else 0
        self.label_speed.config(text=f"速度：{round(wpm, 1)} WPM")

    def show_result(self):
        """弹出成绩窗口"""
        if not self.is_start:
            messagebox.showinfo("提示", "请先输入文字开始练习！")
            return
        use_time = time.time() - self.start_time
        if self.total_input == 0:
            return
        accuracy = self.correct_count / self.total_input * 100
        words = self.correct_count / 5
        wpm = words / (use_time / 60)

        msg = f"===== 本次打字成绩 =====\n" \
              f"总输入字符：{self.total_input}\n" \
              f"正确字符数：{self.correct_count}\n" \
              f"正确率：{round(accuracy, 2)}%\n" \
              f"总用时：{round(use_time, 2)} 秒\n" \
              f"打字速度：{round(wpm, 2)} WPM"
        messagebox.showinfo("练习完成", msg)

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