import tkinter as tk
from tkinter import ttk, messagebox
import math

class MathFormulaApp:
    def __init__(self, root):
        self.root = root
        self.root.title("数学公式查询系统")
        self.root.geometry("1200x800")
        
        # 定义公式数据
        self.formulas = {
            "代数": [
                {
                    "name": "一元二次方程求根公式",
                    "formula": "x = [-b ± √(b² - 4ac)] / 2a",
                    "description": "对于方程 ax² + bx + c = 0 (a ≠ 0)\n判别式 Δ = b² - 4ac\nΔ > 0: 两个不相等的实数根\nΔ = 0: 两个相等的实数根\nΔ < 0: 无实数根"
                },
                {
                    "name": "完全平方公式",
                    "formula": "(a + b)² = a² + 2ab + b²\n(a - b)² = a² - 2ab + b²",
                    "description": "用于展开或因式分解完全平方形式"
                },
                {
                    "name": "平方差公式",
                    "formula": "a² - b² = (a + b)(a - b)",
                    "description": "用于因式分解平方差形式"
                },
                {
                    "name": "立方和与立方差",
                    "formula": "a³ + b³ = (a + b)(a² - ab + b²)\na³ - b³ = (a - b)(a² + ab + b²)",
                    "description": "立方和与立方差的因式分解公式"
                },
                {
                    "name": "韦达定理",
                    "formula": "x₁ + x₂ = -b/a\nx₁ · x₂ = c/a",
                    "description": "一元二次方程 ax² + bx + c = 0 根与系数的关系"
                }
            ],
            "几何": [
                {
                    "name": "勾股定理",
                    "formula": "a² + b² = c²",
                    "description": "直角三角形中，两直角边的平方和等于斜边的平方"
                },
                {
                    "name": "圆面积公式",
                    "formula": "S = πr²",
                    "description": "圆的面积等于圆周率乘以半径的平方"
                },
                {
                    "name": "圆周长公式",
                    "formula": "C = 2πr = πd",
                    "description": "圆的周长等于2倍圆周率乘以半径"
                },
                {
                    "name": "三角形面积公式",
                    "formula": "S = (1/2) × 底 × 高\nS = √[s(s-a)(s-b)(s-c)] (海伦公式)\n其中 s = (a+b+c)/2",
                    "description": "三角形的面积计算公式，海伦公式适用于已知三边的情况"
                },
                {
                    "name": "梯形面积公式",
                    "formula": "S = (a + b) × h / 2",
                    "description": "梯形的面积等于上底加下底乘以高除以2"
                }
            ],
            "三角函数": [
                {
                    "name": "正弦定理",
                    "formula": "a/sinA = b/sinB = c/sinC = 2R",
                    "description": "三角形中，各边与其对角的正弦值之比相等，等于外接圆直径"
                },
                {
                    "name": "余弦定理",
                    "formula": "a² = b² + c² - 2bc·cosA\nb² = a² + c² - 2ac·cosB\nc² = a² + b² - 2ab·cosC",
                    "description": "三角形任意一边的平方等于其他两边平方和减去这两边与它们夹角的余弦的积的两倍"
                },
                {
                    "name": "基本恒等式",
                    "formula": "sin²θ + cos²θ = 1\ntanθ = sinθ/cosθ\ncotθ = cosθ/sinθ",
                    "description": "三角函数的基本恒等关系"
                },
                {
                    "name": "和角公式",
                    "formula": "sin(α±β) = sinαcosβ ± cosαsinβ\ncos(α±β) = cosαcosβ ∓ sinαsinβ\ntan(α±β) = (tanα ± tanβ)/(1 ∓ tanαtanβ)",
                    "description": "两角和与差的三角函数公式"
                },
                {
                    "name": "倍角公式",
                    "formula": "sin2θ = 2sinθcosθ\ncos2θ = cos²θ - sin²θ = 2cos²θ - 1 = 1 - 2sin²θ\ntan2θ = 2tanθ/(1 - tan²θ)",
                    "description": "二倍角的三角函数公式"
                }
            ],
            "微积分": [
                {
                    "name": "导数定义",
                    "formula": "f'(x) = lim[h→0] [f(x+h) - f(x)]/h",
                    "description": "函数在某点的导数表示该点切线的斜率"
                },
                {
                    "name": "基本导数公式",
                    "formula": "(xⁿ)' = nx^(n-1)\n(sinx)' = cosx\n(cosx)' = -sinx\n(eˣ)' = eˣ\n(lnx)' = 1/x",
                    "description": "常见函数的导数公式"
                },
                {
                    "name": "不定积分",
                    "formula": "∫xⁿdx = x^(n+1)/(n+1) + C (n≠-1)\n∫1/x dx = ln|x| + C\n∫eˣdx = eˣ + C",
                    "description": "基本不定积分公式"
                },
                {
                    "name": "定积分",
                    "formula": "∫[a,b] f(x)dx = F(b) - F(a)\n其中 F'(x) = f(x)",
                    "description": "牛顿-莱布尼茨公式，连接定积分与原函数"
                },
                {
                    "name": "泰勒展开",
                    "formula": "f(x) = Σ[n=0→∞] f⁽ⁿ⁾(a)(x-a)ⁿ/n!",
                    "description": "将函数在某点展开为幂级数形式"
                }
            ],
            "概率统计": [
                {
                    "name": "条件概率",
                    "formula": "P(A|B) = P(A∩B)/P(B)",
                    "description": "事件B发生的条件下事件A发生的概率"
                },
                {
                    "name": "贝叶斯公式",
                    "formula": "P(A|B) = P(B|A)P(A)/P(B)",
                    "description": "用于计算后验概率的重要公式"
                },
                {
                    "name": "期望值",
                    "formula": "E(X) = Σxᵢpᵢ (离散型)\nE(X) = ∫xf(x)dx (连续型)",
                    "description": "随机变量的加权平均值"
                },
                {
                    "name": "方差公式",
                    "formula": "Var(X) = E[(X-μ)²] = E(X²) - [E(X)]²",
                    "description": "衡量随机变量离散程度的指标"
                },
                {
                    "name": "正态分布",
                    "formula": "f(x) = 1/[σ√(2π)] · e^[-(x-μ)²/(2σ²)]",
                    "description": "最重要的概率分布，μ为均值，σ为标准差"
                }
            ]
        }
        
        self.current_category = "代数"
        self.search_results = []
        self.is_searching = False
        
        self.create_widgets()
    
    def create_widgets(self):
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 左侧面板 - 分类导航
        left_frame = ttk.LabelFrame(main_frame, text="公式分类", padding="10")
        left_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), padx=(0, 10))
        
        # 分类按钮
        categories = list(self.formulas.keys())
        self.category_vars = {}
        for i, category in enumerate(categories):
            btn = ttk.Button(left_frame, text=category, 
                           command=lambda cat=category: self.select_category(cat),
                           width=15)
            btn.grid(row=i, column=0, pady=5)
            self.category_vars[category] = btn
        
        # 右侧面板
        right_frame = ttk.Frame(main_frame)
        right_frame.grid(row=0, column=1, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 搜索区域
        search_frame = ttk.Frame(right_frame)
        search_frame.grid(row=0, column=0, sticky=(tk.W, tk.E), pady=(0, 10))
        
        ttk.Label(search_frame, text="搜索公式:").pack(side=tk.LEFT, padx=5)
        self.search_var = tk.StringVar()
        self.search_var.trace('w', self.on_search_change)
        search_entry = ttk.Entry(search_frame, textvariable=self.search_var, width=40)
        search_entry.pack(side=tk.LEFT, padx=5)
        
        ttk.Button(search_frame, text="搜索", command=self.search_formulas).pack(side=tk.LEFT, padx=5)
        ttk.Button(search_frame, text="清除搜索", command=self.clear_search).pack(side=tk.LEFT, padx=5)
        
        # 公式列表
        list_frame = ttk.LabelFrame(right_frame, text="公式列表", padding="10")
        list_frame.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S), pady=(0, 10))
        
        # 创建列表框和滚动条
        list_scroll = ttk.Scrollbar(list_frame)
        list_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        
        self.formula_listbox = tk.Listbox(list_frame, yscrollcommand=list_scroll.set,
                                         height=12, font=('微软雅黑', 11))
        self.formula_listbox.pack(fill=tk.BOTH, expand=True)
        list_scroll.config(command=self.formula_listbox.yview)
        
        self.formula_listbox.bind('<<ListboxSelect>>', self.on_formula_select)
        
        # 公式详情显示区域
        detail_frame = ttk.LabelFrame(right_frame, text="公式详情", padding="10")
        detail_frame.grid(row=2, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        
        # 公式名称
        self.name_label = ttk.Label(detail_frame, text="", font=('微软雅黑', 16, 'bold'))
        self.name_label.pack(anchor=tk.W, pady=(0, 10))
        
        # 公式内容
        formula_display_frame = ttk.Frame(detail_frame, relief=tk.SUNKEN, borderwidth=2)
        formula_display_frame.pack(fill=tk.X, pady=(0, 10))
        
        self.formula_text = tk.Text(formula_display_frame, height=4, wrap=tk.WORD,
                                   font=('Courier New', 18, 'bold'), bg='#FFF8DC',
                                   relief=tk.FLAT, padx=10, pady=10)
        self.formula_text.pack(fill=tk.X)
        self.formula_text.config(state=tk.DISABLED)
        
        # 公式说明
        desc_frame = ttk.Frame(detail_frame)
        desc_frame.pack(fill=tk.BOTH, expand=True)
        
        ttk.Label(desc_frame, text="公式说明:", font=('微软雅黑', 12)).pack(anchor=tk.W)
        
        self.description_text = tk.Text(desc_frame, height=6, wrap=tk.WORD,
                                       font=('微软雅黑', 11), bg='white',
                                       relief=tk.SUNKEN, borderwidth=2, padx=10, pady=10)
        self.description_text.pack(fill=tk.BOTH, expand=True)
        self.description_text.config(state=tk.DISABLED)
        
        # 复制按钮
        button_frame = ttk.Frame(detail_frame)
        button_frame.pack(fill=tk.X, pady=(10, 0))
        
        ttk.Button(button_frame, text="复制公式", command=self.copy_formula).pack(side=tk.LEFT, padx=5)
        ttk.Button(button_frame, text="复制说明", command=self.copy_description).pack(side=tk.LEFT, padx=5)
        
        # 配置权重
        self.root.columnconfigure(0, weight=1)
        self.root.rowconfigure(0, weight=1)
        main_frame.columnconfigure(1, weight=1)
        main_frame.rowconfigure(0, weight=1)
        right_frame.columnconfigure(0, weight=1)
        right_frame.rowconfigure(1, weight=1)
        right_frame.rowconfigure(2, weight=1)
        
        # 初始加载第一个分类
        self.select_category("代数")
    
    def select_category(self, category):
        """选择分类"""
        self.current_category = category
        self.is_searching = False
        self.search_var.set("")
        
        # 更新按钮样式
        for cat, btn in self.category_vars.items():
            if cat == category:
                btn.state(['pressed'])
            else:
                btn.state(['!pressed'])
        
        # 更新公式列表
        self.update_formula_list()
    
    def update_formula_list(self):
        """更新公式列表"""
        self.formula_listbox.delete(0, tk.END)
        
        if self.is_searching:
            formulas = self.search_results
        else:
            formulas = self.formulas[self.current_category]
        
        for formula in formulas:
            self.formula_listbox.insert(tk.END, formula["name"])
        
        # 默认选中第一个
        if formulas:
            self.formula_listbox.selection_set(0)
            self.display_formula(formulas[0])
    
    def on_formula_select(self, event):
        """公式选择事件"""
        selection = self.formula_listbox.curselection()
        if selection:
            index = selection[0]
            
            if self.is_searching:
                formulas = self.search_results
            else:
                formulas = self.formulas[self.current_category]
            
            if index < len(formulas):
                self.display_formula(formulas[index])
    
    def display_formula(self, formula):
        """显示公式详情"""
        self.name_label.config(text=formula["name"])
        
        # 更新公式文本
        self.formula_text.config(state=tk.NORMAL)
        self.formula_text.delete(1.0, tk.END)
        self.formula_text.insert(1.0, formula["formula"])
        self.formula_text.config(state=tk.DISABLED)
        
        # 更新说明文本
        self.description_text.config(state=tk.NORMAL)
        self.description_text.delete(1.0, tk.END)
        self.description_text.insert(1.0, formula["description"])
        self.description_text.config(state=tk.DISABLED)
        
        self.current_formula = formula
    
    def search_formulas(self):
        """搜索公式"""
        keyword = self.search_var.get().strip().lower()
        if not keyword:
            messagebox.showinfo("提示", "请输入搜索关键词")
            return
        
        self.search_results = []
        
        for category, formulas in self.formulas.items():
            for formula in formulas:
                if (keyword in formula["name"].lower() or 
                    keyword in formula["formula"].lower() or 
                    keyword in formula["description"].lower()):
                    self.search_results.append(formula)
        
        if self.search_results:
            self.is_searching = True
            self.update_formula_list()
            messagebox.showinfo("搜索结果", f"找到 {len(self.search_results)} 个匹配的公式")
        else:
            messagebox.showinfo("搜索结果", "未找到匹配的公式")
    
    def on_search_change(self, *args):
        """搜索框内容变化时的实时搜索"""
        keyword = self.search_var.get().strip()
        if keyword:
            self.search_formulas()
        elif self.is_searching:
            self.clear_search()
    
    def clear_search(self):
        """清除搜索"""
        self.search_var.set("")
        self.is_searching = False
        self.update_formula_list()
    
    def copy_formula(self):
        """复制公式到剪贴板"""
        if hasattr(self, 'current_formula'):
            self.root.clipboard_clear()
            self.root.clipboard_append(self.current_formula["formula"])
            messagebox.showinfo("成功", "公式已复制到剪贴板")
    
    def copy_description(self):
        """复制说明到剪贴板"""
        if hasattr(self, 'current_formula'):
            self.root.clipboard_clear()
            self.root.clipboard_append(self.current_formula["description"])
            messagebox.showinfo("成功", "公式说明已复制到剪贴板")

def main():
    root = tk.Tk()
    app = MathFormulaApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()