TestAutoSkillsOptimization.php 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. <?php
  2. namespace App\Console\Commands;
  3. use Illuminate\Console\Command;
  4. use App\Module\Pet\Logic\PetAutoSkillLogic;
  5. use App\Module\Pet\Models\PetActiveSkill;
  6. use App\Module\Pet\Models\PetUser;
  7. use App\Module\Farm\Models\FarmLand;
  8. use App\Module\Farm\Models\FarmCrop;
  9. use App\Module\Farm\Enums\DISASTER_TYPE;
  10. use App\Module\GameItems\Models\ItemUser;
  11. use Illuminate\Support\Facades\DB;
  12. /**
  13. * 测试自动技能优化功能
  14. */
  15. class TestAutoSkillsOptimization extends Command
  16. {
  17. /**
  18. * 命令签名
  19. */
  20. protected $signature = 'test:auto-skills-optimization {user_id=1} {--skill=all : 测试的技能类型 (weeding|watering|pest_control|all)}';
  21. /**
  22. * 命令描述
  23. */
  24. protected $description = '测试自动技能功能处理多个灾害的优化 (除草、浇水、杀虫)';
  25. /**
  26. * 技能配置映射
  27. */
  28. private $skillConfigs = [
  29. 'weeding' => [
  30. 'disaster_type' => DISASTER_TYPE::WEED,
  31. 'item_id' => 22, // 除草剂
  32. 'skill_name' => \App\Module\Pet\Enums\PET_SKILL_NAME::AUTO_WEEDING,
  33. 'method' => 'processAutoWeeding',
  34. 'display_name' => '除草'
  35. ],
  36. 'watering' => [
  37. 'disaster_type' => DISASTER_TYPE::DROUGHT,
  38. 'item_id' => 24, // 洒水壶
  39. 'skill_name' => \App\Module\Pet\Enums\PET_SKILL_NAME::AUTO_WATERING,
  40. 'method' => 'processAutoWatering',
  41. 'display_name' => '浇水'
  42. ],
  43. 'pest_control' => [
  44. 'disaster_type' => DISASTER_TYPE::PEST,
  45. 'item_id' => 23, // 杀虫剂
  46. 'skill_name' => \App\Module\Pet\Enums\PET_SKILL_NAME::AUTO_PEST_CONTROL,
  47. 'method' => 'processAutoPestControl',
  48. 'display_name' => '杀虫'
  49. ]
  50. ];
  51. /**
  52. * 执行命令
  53. */
  54. public function handle(): int
  55. {
  56. $userId = (int) $this->argument('user_id');
  57. $skillType = $this->option('skill');
  58. $this->info("开始测试用户 {$userId} 的自动技能优化功能");
  59. try {
  60. if ($skillType === 'all') {
  61. $this->testAllSkills($userId);
  62. } else {
  63. $this->testSingleSkill($userId, $skillType);
  64. }
  65. $this->info("\n✅ 所有测试完成!");
  66. return 0;
  67. } catch (\Exception $e) {
  68. $this->error('测试失败: ' . $e->getMessage());
  69. $this->error('堆栈跟踪: ' . $e->getTraceAsString());
  70. return 1;
  71. }
  72. }
  73. /**
  74. * 测试所有技能
  75. */
  76. private function testAllSkills(int $userId): void
  77. {
  78. foreach ($this->skillConfigs as $skillType => $config) {
  79. $this->info("\n" . str_repeat('=', 60));
  80. $this->info("🧪 测试 {$config['display_name']} 技能");
  81. $this->info(str_repeat('=', 60));
  82. $this->testSingleSkill($userId, $skillType);
  83. }
  84. }
  85. /**
  86. * 测试单个技能
  87. */
  88. private function testSingleSkill(int $userId, string $skillType): void
  89. {
  90. if (!isset($this->skillConfigs[$skillType])) {
  91. $this->error("不支持的技能类型: {$skillType}");
  92. return;
  93. }
  94. $config = $this->skillConfigs[$skillType];
  95. // 1. 创建测试数据
  96. $this->createTestData($userId, $skillType, $config);
  97. // 2. 执行自动技能
  98. $this->executeAutoSkill($userId, $skillType, $config);
  99. // 3. 验证结果
  100. $this->verifyResults($userId, $skillType, $config);
  101. }
  102. /**
  103. * 创建测试数据
  104. */
  105. private function createTestData(int $userId, string $skillType, array $config): void
  106. {
  107. $this->info("📝 创建{$config['display_name']}测试数据...");
  108. DB::beginTransaction();
  109. try {
  110. // 查找宠物
  111. $pet = PetUser::where('user_id', $userId)->first();
  112. if (!$pet) {
  113. $this->warn("用户 {$userId} 没有宠物,跳过测试");
  114. DB::rollback();
  115. return;
  116. }
  117. // 查找有作物的土地
  118. $land = FarmLand::where('user_id', $userId)
  119. ->where('has_crop', true)
  120. ->first();
  121. if (!$land) {
  122. $this->warn("用户 {$userId} 没有种植作物的土地,跳过测试");
  123. DB::rollback();
  124. return;
  125. }
  126. // 获取作物并添加多个指定类型的灾害
  127. $crop = FarmCrop::where('land_id', $land->id)->first();
  128. if (!$crop) {
  129. $this->warn("土地 {$land->id} 没有作物,跳过测试");
  130. DB::rollback();
  131. return;
  132. }
  133. // 清除现有的同类型灾害
  134. $disasters = $crop->disasters ?? [];
  135. $disasters = array_filter($disasters, function($disaster) use ($config) {
  136. return ($disaster['type'] ?? 0) != $config['disaster_type']->value;
  137. });
  138. // 添加3个新的指定类型灾害
  139. for ($i = 1; $i <= 3; $i++) {
  140. $disasters[] = [
  141. 'id' => time() + $i,
  142. 'type' => $config['disaster_type']->value,
  143. 'status' => 'active',
  144. 'created_at' => now()->subMinutes(30 - $i * 5)->toDateTimeString()
  145. ];
  146. }
  147. $crop->disasters = $disasters;
  148. $crop->save();
  149. // 确保用户有足够的道具
  150. $userItem = ItemUser::where('user_id', $userId)
  151. ->where('item_id', $config['item_id'])
  152. ->first();
  153. if (!$userItem) {
  154. ItemUser::create([
  155. 'user_id' => $userId,
  156. 'item_id' => $config['item_id'],
  157. 'quantity' => 10
  158. ]);
  159. } else {
  160. $userItem->quantity = 10;
  161. $userItem->save();
  162. }
  163. // 创建或更新激活的技能
  164. $activeSkill = PetActiveSkill::where('pet_id', $pet->id)
  165. ->where('skill_name', $config['skill_name']->value)
  166. ->first();
  167. if (!$activeSkill) {
  168. PetActiveSkill::create([
  169. 'pet_id' => $pet->id,
  170. 'skill_id' => 1,
  171. 'skill_name' => $config['skill_name']->value,
  172. 'start_time' => now()->subMinutes(10),
  173. 'end_time' => now()->addHours(3),
  174. 'status' => 'active',
  175. 'last_check_time' => now()->subMinutes(5)
  176. ]);
  177. }
  178. DB::commit();
  179. $this->info("✅ 测试数据创建完成:");
  180. $this->info(" - 宠物ID: {$pet->id}");
  181. $this->info(" - 土地ID: {$land->id}");
  182. $this->info(" - 作物ID: {$crop->id}");
  183. $this->info(" - {$config['display_name']}灾害数量: 3个");
  184. $this->info(" - 道具数量: 10个");
  185. } catch (\Exception $e) {
  186. DB::rollback();
  187. throw $e;
  188. }
  189. }
  190. /**
  191. * 执行自动技能
  192. */
  193. private function executeAutoSkill(int $userId, string $skillType, array $config): void
  194. {
  195. $this->info("🚀 执行自动{$config['display_name']}...");
  196. $pet = PetUser::where('user_id', $userId)->first();
  197. $activeSkill = PetActiveSkill::where('pet_id', $pet->id)
  198. ->where('skill_name', $config['skill_name']->value)
  199. ->first();
  200. if (!$activeSkill) {
  201. throw new \Exception("没有找到激活的自动{$config['display_name']}技能");
  202. }
  203. DB::beginTransaction();
  204. $autoSkillLogic = new PetAutoSkillLogic();
  205. $method = $config['method'];
  206. $autoSkillLogic->$method($activeSkill);
  207. DB::commit();
  208. $this->info("✅ 自动{$config['display_name']}执行完成");
  209. }
  210. /**
  211. * 验证结果
  212. */
  213. private function verifyResults(int $userId, string $skillType, array $config): void
  214. {
  215. $this->info("🔍 验证{$config['display_name']}结果...");
  216. $land = FarmLand::where('user_id', $userId)
  217. ->where('has_crop', true)
  218. ->first();
  219. if (!$land) {
  220. $this->warn('没有找到有作物的土地');
  221. return;
  222. }
  223. $crop = FarmCrop::where('land_id', $land->id)->first();
  224. if (!$crop) {
  225. $this->warn('没有找到作物');
  226. return;
  227. }
  228. // 统计剩余的活跃灾害
  229. $activeDisasters = array_filter($crop->disasters ?? [], function($disaster) use ($config) {
  230. return ($disaster['type'] ?? 0) == $config['disaster_type']->value &&
  231. ($disaster['status'] ?? '') === 'active';
  232. });
  233. $clearedDisasters = array_filter($crop->disasters ?? [], function($disaster) use ($config) {
  234. return ($disaster['type'] ?? 0) == $config['disaster_type']->value &&
  235. ($disaster['status'] ?? '') === 'cleared';
  236. });
  237. // 检查道具消耗
  238. $userItem = ItemUser::where('user_id', $userId)
  239. ->where('item_id', $config['item_id'])
  240. ->first();
  241. $this->info("📊 验证结果:");
  242. $this->info(" - 剩余活跃{$config['display_name']}灾害: " . count($activeDisasters) . "个");
  243. $this->info(" - 已清除{$config['display_name']}灾害: " . count($clearedDisasters) . "个");
  244. $this->info(" - 剩余道具数量: " . ($userItem ? $userItem->quantity : 0));
  245. if (count($activeDisasters) == 0) {
  246. $this->info("✅ 优化成功!所有{$config['display_name']}灾害都被清除了");
  247. } else {
  248. $this->warn("⚠️ 还有{$config['display_name']}灾害未被清除,可能是道具不足");
  249. }
  250. }
  251. }