import tkinter as tk
from tkinter import ttk, messagebox
import math
import random
import time
import threading
import winsound

class MultiPageCalculator:
    def __init__(self, root):
        self.root = root
        self.root.title("多功能计算器应用")
        self.root.geometry("700x750")
        
        # 当前主题状态
        self.current_theme = "light"
        
        # 定时器相关
        self.timer_running = False
        self.timer_thread = None
        self.start_time = None
        self.timer_duration = 1200  # 20分钟 = 1200秒
        self.remaining_time = 1200  # 初始化剩余时间
        
        # 创建主容器
        main_container = tk.Frame(root)
        main_container.pack(fill='both', expand=True, padx=10, pady=10)
        
        # 创建顶部导航栏
        self.create_navbar(main_container)
        
        # 创建定时器状态显示
        self.create_timer_display(main_container)
        
        # 创建页面容器
        self.page_container = tk.Frame(main_container)
        self.page_container.pack(fill='both', expand=True, pady=10)
        
        # 创建页面框架
        self.pages = {}
        page_classes = [BasicCalculatorPage, ScientificCalculatorPage, 
                       ProgrammerCalculatorPage, UnitConverterPage,
                       TwentyFourGamePage, PianoPage]
        
        for page_class in page_classes:
            page = page_class(self.page_container, self)
            self.pages[page.page_name] = page
        
        # 显示基本计算器页面
        self.show_page("basic")
        
        # 设置默认主题
        self.apply_light_theme()
        
        # 启动定时器
        self.start_timer()
    
    def create_navbar(self, parent):
        """创建导航栏"""
        navbar = tk.Frame(parent, height=50)
        navbar.pack(fill='x', pady=(0, 10))
        
        # 导航按钮
        nav_buttons = [
            ("基本计算", "basic"),
            ("科学计算", "scientific"),
            ("程序员计算", "programmer"),
            ("单位转换", "converter"),
            ("24点游戏", "24game"),
            ("电子琴", "piano")
        ]
        
        for text, page_name in nav_buttons:
            btn = tk.Button(navbar, text=text, font=('Arial', 9),
                          command=lambda pn=page_name: self.show_page(pn))
            btn.pack(side='left', padx=3, fill='y')
        
        # 主题切换按钮
        self.theme_btn = tk.Button(navbar, text="夜间模式", font=('Arial', 9),
                                  command=self.toggle_theme)
        self.theme_btn.pack(side='right', padx=5)
    
    def create_timer_display(self, parent):
        """创建定时器状态显示"""
        timer_frame = tk.Frame(parent, height=30)
        timer_frame.pack(fill='x', pady=(0, 5))
        
        self.timer_label = tk.Label(timer_frame, text="定时器: 20:00", 
                                   font=('Arial', 10, 'bold'), fg='blue')
        self.timer_label.pack()
        
        # 定时器控制按钮
        control_frame = tk.Frame(timer_frame)
        control_frame.pack()
        
        tk.Button(control_frame, text="重新开始", font=('Arial', 8),
                 command=self.restart_timer).pack(side='left', padx=2)
        tk.Button(control_frame, text="暂停/继续", font=('Arial', 8),
                 command=self.toggle_timer).pack(side='left', padx=2)
    
    def start_timer(self):
        """启动定时器线程"""
        if not self.timer_running:
            self.timer_running = True
            self.start_time = time.time()
            self.timer_thread = threading.Thread(target=self.timer_worker, daemon=True)
            self.timer_thread.start()
    
    def toggle_timer(self):
        """切换定时器状态"""
        self.timer_running = not self.timer_running
        if self.timer_running:
            self.start_time = time.time() - (self.timer_duration - self.remaining_time)
    
    def restart_timer(self):
        """重新启动定时器"""
        self.timer_running = True
        self.start_time = time.time()
        self.remaining_time = self.timer_duration
    
    def timer_worker(self):
        """定时器工作线程"""
        while True:
            if self.timer_running and self.start_time:
                elapsed = time.time() - self.start_time
                self.remaining_time = max(0, self.timer_duration - elapsed)
                
                # 更新显示
                minutes = int(self.remaining_time // 60)
                seconds = int(self.remaining_time % 60)
                
                # 在主线程中更新GUI
                self.root.after(0, self.update_timer_display, minutes, seconds)
                
                # 检查是否到达20分钟
                if elapsed >= self.timer_duration:
                    self.root.after(0, self.show_timer_notification)
                    self.restart_timer()  # 自动重新开始
                
            time.sleep(1)
    
    def update_timer_display(self, minutes, seconds):
        """更新定时器显示"""
        self.timer_label.config(text=f"定时器: {minutes:02d}:{seconds:02d}")
    
    def show_timer_notification(self):
        """显示定时器通知"""
        try:
            # 尝试播放系统提示音
            winsound.MessageBeep()
        except:
            pass
        
        # 显示消息框
        messagebox.showinfo("时间提醒", "⏰ 20分钟时间到！\n\n请注意休息，保护眼睛！")
        
        # 闪烁窗口
        for _ in range(3):
            self.root.attributes('-topmost', 1)
            time.sleep(0.1)
            self.root.attributes('-topmost', 0)
            time.sleep(0.1)
    
    def show_page(self, page_name):
        """显示指定页面"""
        for page in self.pages.values():
            page.pack_forget()
        self.pages[page_name].pack(fill='both', expand=True)
    
    def toggle_theme(self):
        """切换主题"""
        if self.current_theme == "light":
            self.apply_dark_theme()
            self.theme_btn.configure(text="日间模式")
            self.current_theme = "dark"
        else:
            self.apply_light_theme()
            self.theme_btn.configure(text="夜间模式")
            self.current_theme = "light"
        
        # 通知所有页面切换主题
        for page in self.pages.values():
            page.on_theme_changed(self.current_theme)
    
    def apply_light_theme(self):
        """应用浅色主题"""
        self.root.configure(bg='#f0f0f0')
        self.timer_label.configure(bg='#f0f0f0', fg='blue')
    
    def apply_dark_theme(self):
        """应用深色主题"""
        self.root.configure(bg='#2b2b2b')
        self.timer_label.configure(bg='#2b2b2b', fg='cyan')

class CalculatorPage(tk.Frame):
    """计算器页面基类"""
    def __init__(self, parent, app):
        super().__init__(parent)
        self.app = app
        self.history = []
        
    def on_theme_changed(self, theme):
        """主题变化时的回调"""
        if theme == "light":
            self.configure(bg='#f0f0f0')
        else:
            self.configure(bg='#2b2b2b')

class BasicCalculatorPage(CalculatorPage):
    """基本计算器页面"""
    page_name = "basic"
    
    def __init__(self, parent, app):
        super().__init__(parent, app)
        self.create_widgets()
    
    def create_widgets(self):
        """创建界面组件"""
        # 显示区域
        display_frame = tk.Frame(self)
        display_frame.pack(fill='x', pady=10)
        
        self.display_var = tk.StringVar(value="0")
        display_entry = tk.Entry(display_frame, textvariable=self.display_var,
                               font=('Arial', 20), justify='right',
                               bd=5, relief='sunken')
        display_entry.pack(fill='x', padx=5)
        display_entry.config(state='readonly')
        
        # 历史记录
        history_frame = tk.LabelFrame(self, text="历史记录")
        history_frame.pack(fill='both', expand=True, pady=(0, 10))
        
        self.history_text = tk.Text(history_frame, height=8, font=('Arial', 10),
                                   state='disabled')
        self.history_text.pack(fill='both', expand=True, padx=5, pady=5)
        
        # 按钮区域
        buttons_frame = tk.Frame(self)
        buttons_frame.pack(fill='both', expand=True)
        
        # 按钮布局
        button_layout = [
            ['C', 'CE', '⌫', '/'],
            ['7', '8', '9', '*'],
            ['4', '5', '6', '-'],
            ['1', '2', '3', '+'],
            ['0', '.', '=', '√']
        ]
        
        for row_idx, row_buttons in enumerate(button_layout):
            row_frame = tk.Frame(buttons_frame)
            row_frame.pack(fill='both', expand=True, pady=2)
            
            for col_idx, btn_text in enumerate(row_buttons):
                btn = tk.Button(row_frame, text=btn_text, font=('Arial', 12),
                              command=lambda t=btn_text: self.on_button_click(t))
                btn.pack(side='left', expand=True, fill='both', padx=2)
    
    def on_button_click(self, value):
        """处理按钮点击"""
        current = self.display_var.get()
        
        if value == 'C':
            self.display_var.set("0")
        elif value == 'CE':
            self.display_var.set("0")
        elif value == '⌫':
            if current != "0":
                new_val = current[:-1]
                self.display_var.set(new_val if new_val else "0")
        elif value == '=':
            self.calculate()
        elif value == '√':
            self.display_var.set("sqrt(" + current)
        else:
            if current == "0":
                self.display_var.set(value)
            else:
                self.display_var.set(current + value)
    
    def calculate(self):
        """执行计算"""
        expression = self.display_var.get()
        if not expression or expression == "0":
            return
        
        try:
            # 安全检查
            expression = expression.replace('√', 'math.sqrt')
            
            # 计算
            result = eval(expression, {"__builtins__": None}, {"math": math})
            
            # 格式化结果
            if isinstance(result, float) and result.is_integer():
                result = int(result)
            
            # 显示结果
            self.display_var.set(str(result))
            
            # 添加到历史记录
            self.add_to_history(f"{expression} = {result}")
            
        except Exception as e:
            self.display_var.set("错误")
            self.add_to_history(f"{expression} = 错误: {str(e)}")
    
    def add_to_history(self, entry):
        """添加到历史记录"""
        self.history.append(entry)
        self.history_text.config(state='normal')
        self.history_text.insert('end', f"• {entry}\n")
        self.history_text.see('end')
        self.history_text.config(state='disabled')
        
        # 限制历史记录数量
        if len(self.history) > 20:
            self.history.pop(0)
            self.history_text.config(state='normal')
            self.history_text.delete('1.0', '2.0')
            self.history_text.config(state='disabled')

class ScientificCalculatorPage(CalculatorPage):
    """科学计算器页面"""
    page_name = "scientific"
    
    def __init__(self, parent, app):
        super().__init__(parent, app)
        self.create_widgets()
    
    def create_widgets(self):
        """创建科学计算器界面"""
        # 显示区域
        display_frame = tk.Frame(self)
        display_frame.pack(fill='x', pady=10)
        
        self.display_var = tk.StringVar(value="0")
        display_entry = tk.Entry(display_frame, textvariable=self.display_var,
                               font=('Arial', 20), justify='right',
                               bd=5, relief='sunken')
        display_entry.pack(fill='x', padx=5)
        display_entry.config(state='readonly')
        
        # 按钮区域
        buttons_frame = tk.Frame(self)
        buttons_frame.pack(fill='both', expand=True)
        
        # 科学计算器按钮布局
        button_layout = [
            ['sin', 'cos', 'tan', 'log', 'ln', 'e^x'],
            ['sinh', 'cosh', 'tanh', 'x^y', '√', 'x^2'],
            ['π', 'e', 'deg', 'rad', '!', 'abs'],
            ['C', 'CE', '⌫', '/', '(', ')'],
            ['7', '8', '9', '*', 'asin', 'acos'],
            ['4', '5', '6', '-', 'atan', 'log10'],
            ['1', '2', '3', '+', 'exp', 'mod'],
            ['0', '.', '=', '+/-', '1/x', '|x|']
        ]
        
        for row_idx, row_buttons in enumerate(button_layout):
            row_frame = tk.Frame(buttons_frame)
            row_frame.pack(fill='both', expand=True, pady=1)
            
            for col_idx, btn_text in enumerate(row_buttons):
                btn = tk.Button(row_frame, text=btn_text, font=('Arial', 10),
                              command=lambda t=btn_text: self.on_button_click(t))
                btn.pack(side='left', expand=True, fill='both', padx=1)
    
    def on_button_click(self, value):
        """处理科学计算器按钮点击"""
        current = self.display_var.get()
        
        if value == 'C':
            self.display_var.set("0")
        elif value == 'CE':
            self.display_var.set("0")
        elif value == '⌫':
            if current != "0":
                new_val = current[:-1]
                self.display_var.set(new_val if new_val else "0")
        elif value == '=':
            self.calculate()
        elif value == '+/-':
            if current and current != "0":
                if current[0] == '-':
                    self.display_var.set(current[1:])
                else:
                    self.display_var.set('-' + current)
        elif value in ['sin', 'cos', 'tan', 'sinh', 'cosh', 'tanh',
                      'asin', 'acos', 'atan', 'log', 'ln', 'log10',
                      'exp', 'sqrt', 'abs', 'deg', 'rad']:
            self.display_var.set(value + "(" + (current if current != "0" else ""))
        elif value == 'x^y':
            self.display_var.set(current + "**")
        elif value == 'x^2':
            self.display_var.set(current + "**2")
        elif value == 'e^x':
            self.display_var.set("math.exp(" + (current if current != "0" else ""))
        elif value == '!':
            self.display_var.set("math.factorial(" + (current if current != "0" else ""))
        elif value == 'π':
            self.display_var.set(current + ("*" if current != "0" else "") + "math.pi")
        elif value == 'e':
            self.display_var.set(current + ("*" if current != "0" else "") + "math.e")
        elif value == 'mod':
            self.display_var.set(current + "%")
        elif value == '1/x':
            self.display_var.set("1/(" + (current if current != "0" else "") + ")")
        elif value == '|x|':
            self.display_var.set("abs(" + (current if current != "0" else ""))
        else:
            if current == "0":
                self.display_var.set(value)
            else:
                self.display_var.set(current + value)
    
    def calculate(self):
        """执行科学计算"""
        expression = self.display_var.get()
        if not expression or expression == "0":
            return
        
        try:
            # 替换科学函数
            expression = expression.replace('sin(', 'math.sin(')
            expression = expression.replace('cos(', 'math.cos(')
            expression = expression.replace('tan(', 'math.tan(')
            expression = expression.replace('asin(', 'math.asin(')
            expression = expression.replace('acos(', 'math.acos(')
            expression = expression.replace('atan(', 'math.atan(')
            expression = expression.replace('sinh(', 'math.sinh(')
            expression = expression.replace('cosh(', 'math.cosh(')
            expression = expression.replace('tanh(', 'math.tanh(')
            expression = expression.replace('log(', 'math.log10(')
            expression = expression.replace('ln(', 'math.log(')
            expression = expression.replace('log10(', 'math.log10(')
            expression = expression.replace('exp(', 'math.exp(')
            expression = expression.replace('sqrt(', 'math.sqrt(')
            expression = expression.replace('abs(', 'math.fabs(')
            expression = expression.replace('factorial(', 'math.factorial(')
            
            # 特殊处理度/弧度转换
            expression = expression.replace('deg(', 'math.radians(')
            expression = expression.replace('rad(', 'math.degrees(')
            
            # 计算
            result = eval(expression, {"__builtins__": None}, {"math": math})
            
            # 格式化结果
            if isinstance(result, float):
                if result.is_integer():
                    result = int(result)
                else:
                    # 限制小数位数
                    result = round(result, 10)
            
            # 显示结果
            self.display_var.set(str(result))
            
        except Exception as e:
            self.display_var.set("错误")

class ProgrammerCalculatorPage(CalculatorPage):
    """程序员计算器页面"""
    page_name = "programmer"
    
    def __init__(self, parent, app):
        super().__init__(parent, app)
        self.current_base = "DEC"  # DEC, HEX, BIN, OCT
        self.create_widgets()
    
    def create_widgets(self):
        """创建程序员计算器界面"""
        # 进制选择
        base_frame = tk.Frame(self)
        base_frame.pack(fill='x', pady=(0, 10))
        
        self.base_var = tk.StringVar(value=self.current_base)
        bases = [("DEC", "十进制"), ("HEX", "十六进制"), ("BIN", "二进制"), ("OCT", "八进制")]
        
        for base, label in bases:
            rb = tk.Radiobutton(base_frame, text=label, variable=self.base_var,
                               value=base, command=self.on_base_changed)
            rb.pack(side='left', padx=5)
        
        # 显示区域
        display_frame = tk.Frame(self)
        display_frame.pack(fill='x', pady=10)
        
        self.display_var = tk.StringVar(value="0")
        display_entry = tk.Entry(display_frame, textvariable=self.display_var,
                               font=('Arial', 20), justify='right',
                               bd=5, relief='sunken')
        display_entry.pack(fill='x', padx=5)
        display_entry.config(state='readonly')
        
        # 程序员特定按钮
        buttons_frame = tk.Frame(self)
        buttons_frame.pack(fill='both', expand=True)
        
        # 程序员计算器按钮布局
        button_layout = [
            ['C', 'CE', '⌫', 'AND', 'OR', 'XOR'],
            ['7', '8', '9', 'NOT', '<<', '>>'],
            ['4', '5', '6', '~', '&', '|'],
            ['1', '2', '3', '-', '^', 'mod'],
            ['0', '.', '=', '+', '(', ')']
        ]
        
        for row_idx, row_buttons in enumerate(button_layout):
            row_frame = tk.Frame(buttons_frame)
            row_frame.pack(fill='both', expand=True, pady=2)
            
            for col_idx, btn_text in enumerate(row_buttons):
                btn = tk.Button(row_frame, text=btn_text, font=('Arial', 10),
                              command=lambda t=btn_text: self.on_button_click(t))
                btn.pack(side='left', expand=True, fill='both', padx=1)
    
    def on_base_changed(self):
        """进制变化处理"""
        self.current_base = self.base_var.get()
        current = self.display_var.get()
        
        if current and current != "0":
            try:
                if self.current_base == "DEC":
                    # 从当前进制转换为十进制
                    if self.current_base == "HEX":
                        value = int(current, 16)
                    elif self.current_base == "BIN":
                        value = int(current, 2)
                    elif self.current_base == "OCT":
                        value = int(current, 8)
                    else:
                        value = int(current)
                    self.display_var.set(str(value))
            except:
                self.display_var.set("0")
    
    def on_button_click(self, value):
        """处理程序员计算器按钮点击"""
        current = self.display_var.get()
        
        if value == 'C':
            self.display_var.set("0")
        elif value == 'CE':
            self.display_var.set("0")
        elif value == '⌫':
            if current != "0":
                new_val = current[:-1]
                self.display_var.set(new_val if new_val else "0")
        elif value == '=':
            self.calculate()
        elif value in ['AND', 'OR', 'XOR', 'NOT', '<<', '>>', '~', '&', '|', '^']:
            self.display_var.set(current + " " + value.lower() + " ")
        else:
            if current == "0":
                self.display_var.set(value)
            else:
                self.display_var.set(current + value)
    
    def calculate(self):
        """执行程序员计算"""
        expression = self.display_var.get()
        if not expression or expression == "0":
            return
        
        try:
            # 处理位运算
            expression = expression.replace(' and ', ' & ')
            expression = expression.replace(' or ', ' | ')
            expression = expression.replace(' xor ', ' ^ ')
            expression = expression.replace(' not ', ' ~ ')
            expression = expression.replace(' << ', ' << ')
            expression = expression.replace(' >> ', ' >> ')
            
            # 计算
            result = eval(expression, {"__builtins__": None})
            
            # 根据当前进制格式化结果
            if self.current_base == "HEX":
                result_str = hex(result)[2:].upper()
            elif self.current_base == "BIN":
                result_str = bin(result)[2:]
            elif self.current_base == "OCT":
                result_str = oct(result)[2:]
            else:
                result_str = str(result)
            
            self.display_var.set(result_str)
            
        except Exception as e:
            self.display_var.set("错误")

class UnitConverterPage(CalculatorPage):
    """单位转换页面"""
    page_name = "converter"
    
    def __init__(self, parent, app):
        super().__init__(parent, app)
        self.create_widgets()
    
    def create_widgets(self):
        """创建单位转换界面"""
        # 转换类型选择
        type_frame = tk.LabelFrame(self, text="转换类型")
        type_frame.pack(fill='x', pady=10)
        
        self.conversion_type = tk.StringVar(value="长度")
        types = ["长度", "重量", "温度", "时间", "数据存储"]
        
        for conv_type in types:
            rb = tk.Radiobutton(type_frame, text=conv_type, variable=self.conversion_type,
                               value=conv_type, command=self.on_type_changed)
            rb.pack(side='left', padx=10)
        
        # 输入区域
        input_frame = tk.Frame(self)
        input_frame.pack(fill='x', pady=10)
        
        tk.Label(input_frame, text="输入值:", font=('Arial', 12)).pack(side='left', padx=5)
        self.input_var = tk.StringVar(value="0")
        self.input_entry = tk.Entry(input_frame, textvariable=self.input_var,
                                   font=('Arial', 12), width=15)
        self.input_entry.pack(side='left', padx=5)
        
        # 单位选择
        unit_frame = tk.Frame(self)
        unit_frame.pack(fill='x', pady=10)
        
        # 从单位
        tk.Label(unit_frame, text="从:", font=('Arial', 12)).grid(row=0, column=0, padx=5)
        self.from_unit_var = tk.StringVar()
        self.from_unit_menu = ttk.Combobox(unit_frame, textvariable=self.from_unit_var,
                                          state='readonly', width=15)
        self.from_unit_menu.grid(row=0, column=1, padx=5)
        
        # 转换箭头
        tk.Label(unit_frame, text="→", font=('Arial', 16)).grid(row=0, column=2, padx=20)
        
        # 到单位
        tk.Label(unit_frame, text="到:", font=('Arial', 12)).grid(row=0, column=3, padx=5)
        self.to_unit_var = tk.StringVar()
        self.to_unit_menu = ttk.Combobox(unit_frame, textvariable=self.to_unit_var,
                                        state='readonly', width=15)
        self.to_unit_menu.grid(row=0, column=4, padx=5)
        
        # 转换按钮
        convert_btn = tk.Button(unit_frame, text="转换", font=('Arial', 12),
                              command=self.convert_units)
        convert_btn.grid(row=0, column=5, padx=20)
        
        # 结果显示
        result_frame = tk.Frame(self)
        result_frame.pack(fill='x', pady=20)
        
        self.result_var = tk.StringVar(value="结果将显示在这里")
        result_label = tk.Label(result_frame, textvariable=self.result_var,
                              font=('Arial', 14), fg='blue')
        result_label.pack()
        
        # 初始化单位列表
        self.update_unit_lists()
    
    def on_type_changed(self):
        """转换类型变化时更新单位列表"""
        self.update_unit_lists()
    
    def update_unit_lists(self):
        """根据转换类型更新单位列表"""
        conversion_type = self.conversion_type.get()
        
        unit_conversions = {
            "长度": ["米", "千米", "厘米", "毫米", "英里", "英尺", "英寸", "码"],
            "重量": ["千克", "克", "毫克", "磅", "盎司", "吨"],
            "温度": ["摄氏度", "华氏度", "开尔文"],
            "时间": ["秒", "分钟", "小时", "天", "周", "月", "年"],
            "数据存储": ["字节", "千字节", "兆字节", "千兆字节", "太字节"]
        }
        
        units = unit_conversions.get(conversion_type, ["米", "千米"])
        self.from_unit_menu['values'] = units
        self.to_unit_menu['values'] = units
        
        if units:
            self.from_unit_var.set(units[0])
            self.to_unit_var.set(units[1])
    
    def convert_units(self):
        """执行单位转换"""
        try:
            value = float(self.input_var.get())
            from_unit = self.from_unit_var.get()
            to_unit = self.to_unit_var.get()
            conv_type = self.conversion_type.get()
            
            result = self.perform_conversion(value, from_unit, to_unit, conv_type)
            
            if result is not None:
                self.result_var.set(f"{value} {from_unit} = {result:.6f} {to_unit}")
            else:
                self.result_var.set("转换错误: 不支持的单位")
        except ValueError:
            self.result_var.set("错误: 请输入有效数字")
        except Exception as e:
            self.result_var.set(f"转换错误: {str(e)}")
    
    def perform_conversion(self, value, from_unit, to_unit, conv_type):
        """执行具体的单位转换计算"""
        if conv_type == "长度":
            to_meter = {
                "米": 1, "千米": 1000, "厘米": 0.01, "毫米": 0.001,
                "英里": 1609.344, "英尺": 0.3048, "英寸": 0.0254, "码": 0.9144
            }
            value_in_meters = value * to_meter[from_unit]
            return value_in_meters / to_meter[to_unit]
        
        elif conv_type == "重量":
            to_kg = {
                "千克": 1, "克": 0.001, "毫克": 0.000001,
                "磅": 0.453592, "盎司": 0.0283495, "吨": 1000
            }
            value_in_kg = value * to_kg[from_unit]
            return value_in_kg / to_kg[to_unit]
        
        elif conv_type == "温度":
            if from_unit == to_unit:
                return value
            
            if from_unit == "摄氏度":
                celsius = value
            elif from_unit == "华氏度":
                celsius = (value - 32) * 5/9
            elif from_unit == "开尔文":
                celsius = value - 273.15
            else:
                return None
            
            if to_unit == "摄氏度":
                return celsius
            elif to_unit == "华氏度":
                return celsius * 9/5 + 32
            elif to_unit == "开尔文":
                return celsius + 273.15
        
        elif conv_type == "时间":
            to_second = {
                "秒": 1, "分钟": 60, "小时": 3600, "天": 86400,
                "周": 604800, "月": 2629800, "年": 31557600
            }
            value_in_seconds = value * to_second[from_unit]
            return value_in_seconds / to_second[to_unit]
        
        elif conv_type == "数据存储":
            to_byte = {
                "字节": 1, "千字节": 1024, "兆字节": 1024**2,
                "千兆字节": 1024**3, "太字节": 1024**4
            }
            value_in_bytes = value * to_byte[from_unit]
            return value_in_bytes / to_byte[to_unit]
        
        return None

class TwentyFourGamePage(CalculatorPage):
    """24点游戏页面"""
    page_name = "24game"
    
    def __init__(self, parent, app):
        super().__init__(parent, app)
        self.numbers = []
        self.solutions = []
        self.create_widgets()
        self.new_game()
    
    def create_widgets(self):
        """创建24点游戏界面"""
        # 游戏标题
        title_frame = tk.Frame(self)
        title_frame.pack(fill='x', pady=10)
        
        tk.Label(title_frame, text="24点游戏", font=('Arial', 16, 'bold'), 
                fg='blue').pack()
        
        # 规则说明
        rules_label = tk.Label(self, text="规则: 使用4个数字和加减乘除运算，得到结果24", 
                              font=('Arial', 10))
        rules_label.pack(pady=5)
        
        # 数字显示
        self.numbers_frame = tk.Frame(self, height=100, relief='ridge', bd=2)
        self.numbers_frame.pack(fill='x', pady=10, padx=20)
        
        self.number_labels = []
        for i in range(4):
            label = tk.Label(self.numbers_frame, text="?", font=('Arial', 24, 'bold'),
                           width=5, height=2, relief='raised')
            label.pack(side='left', expand=True, padx=10, pady=10)
            self.number_labels.append(label)
        
        # 输入区域
        input_frame = tk.Frame(self)
        input_frame.pack(fill='x', pady=10)
        
        tk.Label(input_frame, text="你的算式:", font=('Arial', 12)).pack(side='left', padx=5)
        self.expression_var = tk.StringVar()
        expression_entry = tk.Entry(input_frame, textvariable=self.expression_var,
                                  font=('Arial', 12), width=30)
        expression_entry.pack(side='left', padx=5)
        
        # 控制按钮
        control_frame = tk.Frame(self)
        control_frame.pack(fill='x', pady=10)
        
        tk.Button(control_frame, text="提交答案", font=('Arial', 10),
                 command=self.check_answer).pack(side='left', padx=5)
        tk.Button(control_frame, text="新游戏", font=('Arial', 10),
                 command=self.new_game).pack(side='left', padx=5)
        tk.Button(control_frame, text="显示答案", font=('Arial', 10),
                 command=self.show_solution).pack(side='left', padx=5)
        
        # 结果显示
        self.result_var = tk.StringVar(value="等待输入...")
        result_label = tk.Label(self, textvariable=self.result_var, 
                              font=('Arial', 12), fg='green')
        result_label.pack(pady=5)
        
        # 答案列表
        self.answers_text = tk.Text(self, height=6, font=('Arial', 10), state='disabled')
        self.answers_text.pack(fill='both', expand=True, pady=10, padx=20)
    
    def new_game(self):
        """开始新游戏"""
        # 生成4个1-13的随机数
        self.numbers = [random.randint(1, 13) for _ in range(4)]
        
        # 更新显示
        for i, label in enumerate(self.number_labels):
            label.config(text=str(self.numbers[i]))
        
        # 清空输入和结果
        self.expression_var.set("")
        self.result_var.set("等待输入...")
        self.answers_text.config(state='normal')
        self.answers_text.delete('1.0', 'end')
        self.answers_text.config(state='disabled')
        
        # 计算所有可能的解法
        self.solutions = self.find_solutions(self.numbers)
        
        if not self.solutions:
            self.result_var.set("这组数字无解，自动重新生成...")
            self.after(1000, self.new_game)
    
    def find_solutions(self, numbers):
        """查找所有可能的24点解法"""
        solutions = []
        nums = [str(n) for n in numbers]
        
        # 生成所有数字排列
        from itertools import permutations
        num_perms = set(permutations(nums))
        
        # 生成所有运算符组合
        operators = ['+', '-', '*', '/']
        from itertools import product
        op_combs = list(product(operators, repeat=3))
        
        # 尝试所有可能的表达式结构
        structures = [
            '(({0}{4}{1}){5}{2}){6}{3}',
            '({0}{4}({1}{5}{2})){6}{3}',
            '{0}{4}(({1}{5}{2}){6}{3})',
            '{0}{4}({1}{5}({2}{6}{3}))',
            '({0}{4}{1}){5}({2}{6}{3})'
        ]
        
        for nums in num_perms:
            for ops in op_combs:
                for struct in structures:
                    try:
                        expr = struct.format(nums[0], nums[1], nums[2], nums[3],
                                           ops[0], ops[1], ops[2])
                        result = eval(expr)
                        if abs(result - 24) < 0.000001:  # 浮点数容差
                            solutions.append(expr)
                    except ZeroDivisionError:
                        continue
        
        return list(set(solutions))[:10]  # 最多显示10个解
    
    def check_answer(self):
        """检查用户答案"""
        expression = self.expression_var.get().strip()
        if not expression:
            self.result_var.set("请输入算式")
            return
        
        try:
            # 检查是否使用了所有数字
            used_numbers = []
            for num_str in expression:
                if num_str.isdigit():
                    if num_str == '1' and len(expression) > 1:
                        # 处理10以上的数字
                        pass
                    else:
                        used_numbers.append(int(num_str))
            
            # 检查数字是否匹配
            nums_copy = self.numbers.copy()
            for num in used_numbers:
                if num in nums_copy:
                    nums_copy.remove(num)
                else:
                    self.result_var.set(f"错误: 必须使用所有4个数字")
                    return
            
            # 计算表达式
            result = eval(expression)
            
            if abs(result - 24) < 0.000001:
                self.result_var.set("✓ 正确！结果是24")
                # 显示祝贺
                self.show_congratulations()
            else:
                self.result_var.set(f"✗ 错误: 结果是{result:.2f}，不是24")
                
        except Exception as e:
            self.result_var.set(f"错误: 无效表达式 - {str(e)}")
    
    def show_solution(self):
        """显示答案"""
        self.answers_text.config(state='normal')
        self.answers_text.delete('1.0', 'end')
        
        if self.solutions:
            self.answers_text.insert('end', "可能的解法:\n")
            for i, sol in enumerate(self.solutions[:5], 1):
                self.answers_text.insert('end', f"{i}. {sol} = 24\n")
        else:
            self.answers_text.insert('end', "这组数字无解")
        
        self.answers_text.see('1.0')
        self.answers_text.config(state='disabled')
    
    def show_congratulations(self):
        """显示祝贺动画"""
        for _ in range(3):
            for label in self.number_labels:
                original_bg = label.cget('bg')
                label.configure(bg='yellow')
                self.app.root.update()
                time.sleep(0.1)
                label.configure(bg=original_bg)
                self.app.root.update()
                time.sleep(0.1)

class PianoPage(CalculatorPage):
    """电子琴页面"""
    page_name = "piano"
    
    def __init__(self, parent, app):
        super().__init__(parent, app)
        self.keys = []
        self.notes = ['C', 'D', 'E', 'F', 'G', 'A', 'B']
        self.octave = 4
        self.create_widgets()
    
    def create_widgets(self):
        """创建电子琴界面"""
        # 标题
        title_frame = tk.Frame(self)
        title_frame.pack(fill='x', pady=10)
        
        tk.Label(title_frame, text="简易电子琴", font=('Arial', 16, 'bold'), 
                fg='purple').pack()
        
        # 控制面板
        control_frame = tk.Frame(self)
        control_frame.pack(fill='x', pady=10)
        
        tk.Label(control_frame, text="音阶:", font=('Arial', 10)).pack(side='left', padx=5)
        self.octave_var = tk.StringVar(value="4")
        octave_spin = tk.Spinbox(control_frame, from_=1, to=7, textvariable=self.octave_var,
                                width=5, font=('Arial', 10), command=self.update_octave)
        octave_spin.pack(side='left', padx=5)
        
        tk.Button(control_frame, text="播放示例", font=('Arial', 10),
                 command=self.play_example).pack(side='left', padx=20)
        tk.Button(control_frame, text="停止", font=('Arial', 10),
                 command=self.stop_sound).pack(side='left', padx=5)
        
        # 键盘区域
        keyboard_frame = tk.Frame(self, height=200, relief='ridge', bd=2)
        keyboard_frame.pack(fill='x', pady=20, padx=20)
        
        # 创建白键
        white_keys_frame = tk.Frame(keyboard_frame)
        white_keys_frame.pack()
        
        for i, note in enumerate(self.notes):
            key = tk.Button(white_keys_frame, text=f"{note}\n({note}{self.octave})", 
                          width=8, height=10, font=('Arial', 9),
                          bg='white', fg='black',
                          command=lambda n=note: self.play_note(n))
            key.pack(side='left', padx=1)
            self.keys.append(('white', key, note))
        
        # 创建黑键
        black_keys_frame = tk.Frame(keyboard_frame)
        black_keys_frame.pack()
        
        black_key_positions = [1, 2, 4, 5, 6]  # 在哪些白键后面放黑键
        black_notes = ['C#', 'D#', 'F#', 'G#', 'A#']
        
        for i in range(len(self.notes)):
            if i in black_key_positions:
                # 添加占位符保持对齐
                tk.Frame(black_keys_frame, width=8*7).pack(side='left')
                
                # 创建黑键
                note_idx = black_key_positions.index(i)
                key = tk.Button(black_keys_frame, text=f"{black_notes[note_idx]}", 
                              width=5, height=6, font=('Arial', 8),
                              bg='black', fg='white',
                              command=lambda n=black_notes[note_idx]: self.play_note(n))
                key.pack(side='left', padx=0)
                self.keys.append(('black', key, black_notes[note_idx]))
        
        # 当前播放状态
        self.status_var = tk.StringVar(value="点击琴键或使用键盘播放音乐")
        status_label = tk.Label(self, textvariable=self.status_var, 
                              font=('Arial', 10), fg='blue')
        status_label.pack(pady=5)
        
        # 键盘绑定
        self.setup_keyboard_bindings()
    
    def update_octave(self):
        """更新音阶"""
        try:
            self.octave = int(self.octave_var.get())
            # 更新白键标签
            for key_type, key_widget, note in self.keys:
                if key_type == 'white':
                    key_widget.config(text=f"{note}\n({note}{self.octave})")
        except:
            self.octave = 4
            self.octave_var.set("4")
    
    def setup_keyboard_bindings(self):
        """设置键盘绑定"""
        # 白键: A, S, D, F, G, H, J
        key_mappings = {
            'a': 'C', 's': 'D', 'd': 'E', 'f': 'F',
            'g': 'G', 'h': 'A', 'j': 'B',
            'w': 'C#', 'e': 'D#', 't': 'F#', 'y': 'G#', 'u': 'A#'
        }
        
        for key, note in key_mappings.items():
            self.app.root.bind(f'<KeyPress-{key}>', lambda e, n=note: self.play_note(n))
            self.app.root.bind(f'<KeyRelease-{key}>', lambda e, n=note: self.release_note(n))
    
    def play_note(self, note):
        """播放音符"""
        try:
            # 计算频率
            frequency = self.get_frequency(note, self.octave)
            
            # 播放声音
            duration = 500  # 毫秒
            winsound.Beep(int(frequency), duration)
            
            # 更新状态
            self.status_var.set(f"正在播放: {note}{self.octave} ({frequency:.0f}Hz)")
            
            # 高亮按键
            self.highlight_key(note)
            
        except Exception as e:
            self.status_var.set(f"播放错误: {str(e)}")
    
    def get_frequency(self, note, octave):
        """获取音符频率"""
        # 标准频率: A4 = 440Hz
        notes = {'C': 0, 'C#': 1, 'D': 2, 'D#': 3, 'E': 4, 
                'F': 5, 'F#': 6, 'G': 7, 'G#': 8, 'A': 9, 'A#': 10, 'B': 11}
        
        if note not in notes:
            note = note[0]  # 如果是升降号，取基本音
        
        # 计算半音数
        semitones = (octave - 4) * 12 + notes[note]
        
        # 计算频率: f = 440 * 2^(n/12)
        frequency = 440 * (2 ** (semitones / 12))
        
        return frequency
    
    def highlight_key(self, note):
        """高亮按键"""
        for key_type, key_widget, key_note in self.keys:
            if key_note == note:
                original_color = key_widget.cget('bg')
                if key_type == 'white':
                    key_widget.configure(bg='lightblue')
                else:
                    key_widget.configure(bg='darkblue')
                
                # 300ms后恢复颜色
                self.app.root.after(300, lambda w=key_widget, c=original_color: w.configure(bg=c))
                break
    
    def release_note(self, note):
        """释放音符（键盘按键释放时调用）"""
        pass  # 可以在这里实现延音效果
    
    def play_example(self):
        """播放示例音乐"""
        example_notes = ['C', 'D', 'E', 'F', 'G', 'A', 'B', 'C']
        self.status_var.set("播放示例: 音阶")
        
        def play_sequence():
            for note in example_notes:
                self.play_note(note)
                time.sleep(0.3)
            self.status_var.set("示例播放完成")
        
        # 在新线程中播放
        threading.Thread(target=play_sequence, daemon=True).start()
    
    def stop_sound(self):
        """停止声音（在Windows上有限制）"""
        self.status_var.set("已停止")

# 主程序
if __name__ == "__main__":
    root = tk.Tk()
    app = MultiPageCalculator(root)
    root.mainloop()
