#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 验证Excel文件与JSON文件的同步状态 """ import json import pandas as pd from pathlib import Path def load_json_data(): """加载JSON数据""" json_file = Path('../enemies.json') try: with open(json_file, 'r', encoding='utf-8') as f: return json.load(f) except Exception as e: print(f"❌ 加载JSON文件失败: {e}") return None def load_excel_data(): """加载Excel数据""" excel_file = Path('敌人配置表.xlsx') if not excel_file.exists(): print(f"❌ Excel文件不存在: {excel_file}") return None try: # 读取所有工作表 excel_data = pd.read_excel(excel_file, sheet_name=None) return excel_data except Exception as e: print(f"❌ 加载Excel文件失败: {e}") return None def verify_basic_config(json_data, excel_data): """验证基础配置""" print("\n🔍 验证敌人基础配置...") json_enemies = {enemy['id']: enemy for enemy in json_data.get('enemies', [])} excel_basic = excel_data.get('敌人基础配置') if excel_basic is None: print("❌ Excel中缺少'敌人基础配置'工作表") return False success = True for _, row in excel_basic.iterrows(): enemy_id = row['敌人ID'] if enemy_id not in json_enemies: print(f"❌ Excel中的敌人ID '{enemy_id}' 在JSON中不存在") success = False continue json_enemy = json_enemies[enemy_id] # 验证关键字段 checks = [ ('敌人名称', json_enemy['name']), ('敌人类型', json_enemy['type']), ('生命值', json_enemy['stats']['health']), ('攻击力', json_enemy['stats']['attack']), ('防御力', json_enemy['stats']['defense']), ('移动速度', json_enemy['stats']['speed']) ] for field, expected in checks: actual = row[field] if actual != expected: print(f"⚠️ {enemy_id} 的 {field}: Excel={actual}, JSON={expected}") success = False if success: print("✅ 敌人基础配置验证通过") return success def verify_visual_config(json_data, excel_data): """验证视觉配置""" print("\n🎬 验证视觉配置...") json_enemies = {enemy['id']: enemy for enemy in json_data.get('enemies', [])} excel_visual = excel_data.get('视觉配置') if excel_visual is None: print("❌ Excel中缺少'视觉配置'工作表") return False success = True animation_count = 0 for _, row in excel_visual.iterrows(): enemy_id = row['敌人ID'] if enemy_id not in json_enemies: continue json_visual = json_enemies[enemy_id].get('visualConfig', {}) # 验证精灵路径 sprite_path = row['精灵路径'] expected_sprite = json_visual.get('spritePath', '') if sprite_path != expected_sprite: print(f"⚠️ {enemy_id} 精灵路径不匹配: Excel={sprite_path}, JSON={expected_sprite}") success = False # 检查动画路径格式 if '@EnemyAni' in sprite_path: animation_count += 1 print(f" ✅ {enemy_id}: {sprite_path}") else: print(f" ⚠️ {enemy_id}: 动画路径格式不正确 - {sprite_path}") success = False # 验证动画配置 animations = json_visual.get('animations', {}) animation_fields = ['待机动画', '行走动画', '攻击动画', '死亡动画'] animation_keys = ['idle', 'walk', 'attack', 'death'] for field, key in zip(animation_fields, animation_keys): excel_anim = row[field] json_anim = animations.get(key, '') if excel_anim != json_anim: print(f"⚠️ {enemy_id} {field}不匹配: Excel={excel_anim}, JSON={json_anim}") success = False print(f"\n📊 动画配置统计: {animation_count}/11 个敌人配置了EnemyAni动画路径") if success: print("✅ 视觉配置验证通过") return success def verify_combat_config(json_data, excel_data): """验证战斗配置""" print("\n⚔️ 验证战斗配置...") json_enemies = {enemy['id']: enemy for enemy in json_data.get('enemies', [])} excel_combat = excel_data.get('战斗配置') if excel_combat is None: print("❌ Excel中缺少'战斗配置'工作表") return False success = True attack_types = set() for _, row in excel_combat.iterrows(): enemy_id = row['敌人ID'] if enemy_id not in json_enemies: continue json_combat = json_enemies[enemy_id].get('combat', {}) # 验证攻击类型 attack_type = row['攻击类型'] expected_type = json_combat.get('attackType', 'melee') attack_types.add(attack_type) if attack_type != expected_type: print(f"⚠️ {enemy_id} 攻击类型不匹配: Excel={attack_type}, JSON={expected_type}") success = False # 验证武器类型 weapon_type = row['武器类型'] expected_weapon = json_combat.get('weaponType', 'none') if weapon_type != expected_weapon: print(f"⚠️ {enemy_id} 武器类型不匹配: Excel={weapon_type}, JSON={expected_weapon}") success = False print(f"\n📊 攻击类型统计: {', '.join(sorted(attack_types))}") if success: print("✅ 战斗配置验证通过") return success def verify_movement_config(json_data, excel_data): """验证移动配置""" print("\n🚶 验证移动配置...") json_enemies = {enemy['id']: enemy for enemy in json_data.get('enemies', [])} excel_movement = excel_data.get('移动配置') if excel_movement is None: print("❌ Excel中缺少'移动配置'工作表") return False success = True move_types = set() for _, row in excel_movement.iterrows(): enemy_id = row['敌人ID'] if enemy_id not in json_enemies: continue json_movement = json_enemies[enemy_id].get('movement', {}) # 验证移动类型 move_type = row['移动类型'] expected_type = json_movement.get('moveType', 'straight') move_types.add(move_type) if move_type != expected_type: print(f"⚠️ {enemy_id} 移动类型不匹配: Excel={move_type}, JSON={expected_type}") success = False # 验证移动模式 pattern = row['移动模式'] expected_pattern = json_movement.get('pattern', 'walk_forward') if pattern != expected_pattern: print(f"⚠️ {enemy_id} 移动模式不匹配: Excel={pattern}, JSON={expected_pattern}") success = False print(f"\n📊 移动类型统计: {', '.join(sorted(move_types))}") if success: print("✅ 移动配置验证通过") return success def main(): """主函数""" print("🔍 开始验证Excel与JSON文件的同步状态...") # 加载数据 json_data = load_json_data() excel_data = load_excel_data() if not json_data or not excel_data: return False print(f"\n📊 数据概览:") print(f" JSON敌人数量: {len(json_data.get('enemies', []))}") print(f" Excel工作表数量: {len(excel_data)}") print(f" Excel工作表: {', '.join(excel_data.keys())}") # 执行验证 all_passed = True all_passed &= verify_basic_config(json_data, excel_data) all_passed &= verify_visual_config(json_data, excel_data) all_passed &= verify_combat_config(json_data, excel_data) all_passed &= verify_movement_config(json_data, excel_data) # 总结 print("\n" + "="*50) if all_passed: print("🎉 验证完成!Excel文件与JSON文件完全同步") print("\n✅ 同步成功的内容:") print(" 📋 敌人基础信息 (ID、名称、属性)") print(" 🎬 动画配置 (@EnemyAni路径和动画状态)") print(" ⚔️ 战斗配置 (攻击类型、武器、投射物)") print(" 🚶 移动配置 (移动模式和类型)") print(" 🔊 音频配置") print(" 🎯 特殊能力和BOSS配置") print("\n🎯 Excel配置表现在包含了完整的动画和战斗配置!") return True else: print("❌ 验证失败!发现数据不一致") return False if __name__ == '__main__': success = main() if not success: print("\n❌ 验证过程中发现问题,请检查上述错误信息")