编辑代码

import json
from datetime import datetime
import os

# 完整的硬件数据库
components = {
    "CPU": [
        {"name": "Intel i5-12400F", "price": 1199, "socket": "LGA1700", "TDP": 65},
        {"name": "AMD Ryzen 5 5600X", "price": 1349, "socket": "AM4", "TDP": 65},
        {"name": "Intel i7-12700K", "price": 2599, "socket": "LGA1700", "TDP": 125}
    ],
    "主板": [
        {"name": "华硕 B660M-PLUS", "price": 999, "socket": "LGA1700", "memory_type": "DDR4"},
        {"name": "微星 B550 TOMAHAWK", "price": 1199, "socket": "AM4", "memory_type": "DDR4"},
        {"name": "技嘉 Z690 AORUS", "price": 2899, "socket": "LGA1700", "memory_type": "DDR5"}
    ],
    "内存": [
        {"name": "金士顿 16GB DDR4 3200", "price": 399, "type": "DDR4"},
        {"name": "芝奇 32GB DDR4 3600", "price": 1299, "type": "DDR4"},
        {"name": "芝奇 32GB DDR5 6000", "price": 2299, "type": "DDR5"}
    ],
    "显卡": [
        {"name": "RTX 3060 12GB", "price": 2499, "length": 242, "power": 170},
        {"name": "RX 6700 XT 12GB", "price": 2999, "length": 267, "power": 220},
        {"name": "RTX 3080 10GB", "price": 5499, "length": 320, "power": 320}
    ],
    "硬盘": [
        {"name": "三星 980 1TB NVMe", "price": 799},
        {"name": "西数 SN770 2TB", "price": 1499}
    ],
    "电源": [
        {"name": "航嘉 MVP K650", "price": 499, "wattage": 650},
        {"name": "海盗船 RM850x", "price": 999, "wattage": 850},
        {"name": "海韵 PRIME TX-1000", "price": 1999, "wattage": 1000}
    ],
    "机箱": [
        {"name": "先马 黑洞", "price": 299, "max_gpu_length": 310, "cooler_height": 165},
        {"name": "联力 包豪斯", "price": 899, "max_gpu_length": 420, "cooler_height": 185}
    ]
}

class CompatibilityChecker:
    @staticmethod
    def check_cpu_motherboard(cpu, motherboard):
        return cpu["socket"] == motherboard["socket"]

    @staticmethod
    def check_memory_motherboard(memory, motherboard):
        return memory["type"] == motherboard["memory_type"]

    @staticmethod
    def check_gpu_case(gpu, case):
        return gpu["length"] <= case["max_gpu_length"]

    @staticmethod
    def calculate_power_requirements(components):
        total_power = 0
        power_map = {
            "CPU": 1.5,
            "显卡": 1.2,
            "主板": 50,
            "内存": 10,
            "硬盘": 10
        }
        for cat, item in components.items():
            if cat in power_map:
                if cat == "CPU":
                    total_power += item["TDP"] * power_map[cat]
                else:
                    total_power += item.get("power", power_map[cat])
        return int(total_power * 1.2)  # 20%余量

class PCConfigurator:
    def __init__(self):
        self.selected_components = {}
        self.total_price = 0
        self.compatibility_rules = CompatibilityChecker()
    
    def show_menu(self):
        print("\n=== 电脑配置器 ===")
        print("1. 添加组件")
        print("2. 移除组件")
        print("3. 查看当前配置")
        print("4. 生成报价单")
        print("5. 保存配置")
        print("6. 加载配置")
        print("7. 退出程序")
    
    def show_components(self, category):
        print(f"\n可选{category}列表:")
        for idx, item in enumerate(components[category], 1):
            print(f"{idx}. {item['name']} - ¥{item['price']}")
            # 显示关键参数
            if category == "CPU":
                print(f"   插槽: {item['socket']}, TDP: {item['TDP']}W")
            elif category == "主板":
                print(f"   插槽: {item['socket']}, 内存类型: {item['memory_type']}")
            elif category == "内存":
                print(f"   类型: {item['type']}")
            elif category == "显卡":
                print(f"   长度: {item['length']}mm, 功耗: {item['power']}W")
            elif category == "电源":
                print(f"   功率: {item['wattage']}W")
            elif category == "机箱":
                print(f"   最大显卡长度: {item['max_gpu_length']}mm")

    def add_component(self):
        print("\n选择要添加的组件类型:")
        categories = list(components.keys())
        for idx, cat in enumerate(categories, 1):
            print(f"{idx}. {cat}")
        
        try:
            choice = int(input("请输入数字选择类型:")) - 1
            selected_cat = categories[choice]
            
            self.show_components(selected_cat)
            comp_choice = int(input("请选择具体型号:")) - 1
            selected = components[selected_cat][comp_choice]
            
            # 兼容性检查
            if not self.check_compatibility(selected_cat, selected):
                return
            
            self.selected_components[selected_cat] = selected
            self.total_price += selected["price"]
            print(f"✓ 已添加:{selected['name']}")
            
            # 如果是电源,显示功率信息
            if selected_cat == "电源":
                required = self.compatibility_rules.calculate_power_requirements(self.selected_components)
                print(f"当前系统推荐功率:{required}W")
                
        except (ValueError, IndexError):
            print("× 无效的输入!")

    def check_compatibility(self, category, new_component):
        # CPU与主板兼容性检查
        if category == "CPU" and "主板" in self.selected_components:
            if not self.compatibility_rules.check_cpu_motherboard(new_component, self.selected_components["主板"]):
                print("× 错误:CPU与已选主板不兼容!")
                return False
        
        # 主板与CPU兼容性检查(当先选主板时)
        if category == "主板" and "CPU" in self.selected_components:
            if not self.compatibility_rules.check_cpu_motherboard(self.selected_components["CPU"], new_component):
                print("× 错误:主板与已选CPU不兼容!")
                return False
        
        # 主板与内存兼容性检查
        if category == "内存" and "主板" in self.selected_components:
            if not self.compatibility_rules.check_memory_motherboard(new_component, self.selected_components["主板"]):
                print("× 错误:内存与主板不兼容!")
                return False
        
        # 显卡与机箱兼容性检查
        if category == "显卡" and "机箱" in self.selected_components:
            if not self.compatibility_rules.check_gpu_case(new_component, self.selected_components["机箱"]):
                print(f"× 错误:显卡长度({new_component['length']}mm)超过机箱限制({self.selected_components['机箱']['max_gpu_length']}mm)!")
                return False
        
        # 电源功率检查
        if category == "电源":
            required = self.compatibility_rules.calculate_power_requirements(self.selected_components)
            if new_component["wattage"] < required:
                print(f"⚠ 警告:电源功率不足!系统需要约{required}W,当前选择{new_component['wattage']}W")
                confirm = input("仍要添加吗?(y/n): ").lower()
                if confirm != 'y':
                    return False
        
        return True

    def remove_component(self):
        if not self.selected_components:
            print("当前没有已选组件!")
            return
        
        print("\n已选组件列表:")
        items = list(self.selected_components.items())
        for idx, (cat, item) in enumerate(items, 1):
            print(f"{idx}. {cat}: {item['name']}{item['price']}")
        
        try:
            choice = int(input("请输入要移除的编号:")) - 1
            removed = items[choice]
            del self.selected_components[removed[0]]
            self.total_price -= removed[1]["price"]
            print(f"✓ 已移除:{removed[1]['name']}")
        except (ValueError, IndexError):
            print("× 无效的输入!")

    def show_current_config(self):
        print("\n当前配置:")
        for cat, item in self.selected_components.items():
            print(f"- {cat}: {item['name']}{item['price']}")
            # 显示关键参数
            if cat == "CPU":
                print(f"  插槽: {item['socket']}, TDP: {item['TDP']}W")
            elif cat == "主板":
                print(f"  插槽: {item['socket']}, 内存类型: {item['memory_type']}")
            elif cat == "显卡":
                print(f"  长度: {item['length']}mm, 功耗: {item['power']}W")
        
        print(f"\n总计价格:¥{self.total_price}")
        
        # 显示电源建议
        if "电源" not in self.selected_components and any(c in self.selected_components for c in ["CPU", "显卡"]):
            required = self.compatibility_rules.calculate_power_requirements(self.selected_components)
            print(f"⚠ 建议电源功率:至少{required}W")

    def generate_quote(self):
        # 检查必需组件
        required_components = ["CPU", "主板", "内存", "硬盘", "电源"]
        missing = [c for c in required_components if c not in self.selected_components]
        if missing:
            print(f"× 配置不完整!缺少必要组件:{', '.join(missing)}")
            return
        
        # 生成报价单时进行最终兼容性检查
        if "显卡" in self.selected_components and "机箱" not in self.selected_components:
            print("⚠ 警告:未选择机箱,无法验证显卡兼容性!")
            confirm = input("仍要生成报价单吗?(y/n): ").lower()
            if confirm != 'y':
                return
        
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        filename = f"电脑报价单_{timestamp}.txt"
        
        with open(filename, "w", encoding="utf-8") as f:
            f.write("=== 电脑装机报价单 ===\n\n")
            f.write("配置清单:\n")
            for cat, item in self.selected_components.items():
                f.write(f"- {cat}: {item['name']}{item['price']}\n")
            
            # 添加兼容性信息
            f.write("\n兼容性信息:\n")
            if "CPU" in self.selected_components and "主板" in self.selected_components:
                f.write(f"✓ CPU与主板兼容 ({self.selected_components['CPU']['socket']})\n")
            if "内存" in self.selected_components and "主板" in self.selected_components:
                f.write(f"✓ 内存与主板兼容 ({self.selected_components['内存']['type']})\n")
            if "显卡" in self.selected_components and "机箱" in self.selected_components:
                f.write(f"✓ 显卡与机箱兼容 (长度: {self.selected_components['显卡']['length']}mm ≤ {self.selected_components['机箱']['max_gpu_length']}mm)\n")
            
            # 电源信息
            if "电源" in self.selected_components:
                required = self.compatibility_rules.calculate_power_requirements(self.selected_components)
                f.write(f"\n电源信息:\n")
                f.write(f"- 已选电源: {self.selected_components['电源']['wattage']}W\n")
                f.write(f"- 系统估算功耗: {required}W (含20%余量)\n")
                if self.selected_components['电源']['wattage'] < required:
                    f.write("⚠ 警告:电源功率不足!\n")
                else:
                    f.write("✓ 电源功率充足\n")
            
            f.write(f"\n总价:¥{self.total_price}\n")
            f.write("生成时间:" + datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        
        print(f"\n✓ 报价单已生成到 {filename}")

    def save_config(self):
        if not self.selected_components:
            print("× 当前没有配置可保存!")
            return
        
        filename = input("请输入保存文件名(不含扩展名):") + ".json"
        config_data = {
            "components": {k: v["name"] for k, v in self.selected_components.items()},
            "total_price": self.total_price,
            "metadata": {
                "created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                "version": "1.0"
            }
        }
        
        try:
            with open(filename, "w", encoding="utf-8") as f:
                json.dump(config_data, f, indent=2, ensure_ascii=False)
            print(f"✓ 配置已保存到 {filename}")
        except Exception as e:
            print(f"× 保存失败:{str(e)}")

    def load_config(self):
        filename = input("请输入要加载的文件名(含扩展名):")
        if not os.path.exists(filename):
            print("× 文件不存在!")
            return
        
        try:
            with open(filename, "r", encoding="utf-8") as f:
                config_data = json.load(f)
            
            # 清空当前配置
            self.selected_components = {}
            self.total_price = 0
            
            # 重新加载组件
            for cat, name in config_data["components"].items():
                found = False
                for item in components[cat]:
                    if item["name"] == name:
                        self.selected_components[cat] = item
                        self.total_price += item["price"]
                        found = True
                        break
                
                if not found:
                    print(f"× 警告:组件 {cat} - {name} 不在当前数据库中")
            
            print("✓ 配置加载成功!")
            if "metadata" in config_data:
                print(f"原始创建时间:{config_data['metadata']['created_at']}")
        except Exception as e:
            print(f"× 加载失败:{str(e)}")

    def run(self):
        print("=== 电脑装机配置工具 ===")
        print("提示:建议按顺序选择 CPU → 主板 → 内存 → 电源 → 其他组件")
        
        while True:
            self.show_menu()
            choice = input("请输入操作编号:")
            
            if choice == "1":
                self.add_component()
            elif choice == "2":
                self.remove_component()
            elif choice == "3":
                self.show_current_config()
            elif choice == "4":
                self.generate_quote()
            elif choice == "5":
                self.save_config()
            elif choice == "6":
                self.load_config()
            elif choice == "7":
                print("感谢使用电脑装机配置工具!")
                break
            else:
                print("× 无效的输入,请重新选择!")

if __name__ == "__main__":
    configurator = PCConfigurator()
    configurator.run()