DisasterRemovalLogic.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. <?php
  2. namespace App\Module\Farm\Logics;
  3. use App\Module\Farm\Enums\DISASTER_TYPE;
  4. use App\Module\GameItems\Services\ItemService;
  5. use Illuminate\Support\Facades\Log;
  6. use UCore\Db\Helper;
  7. use UCore\Exception\LogicException;
  8. /**
  9. * 灾害去除逻辑类
  10. *
  11. * 处理各种类型的灾害去除操作,包括概率计算、状态验证和物品消耗
  12. */
  13. class DisasterRemovalLogic
  14. {
  15. /**
  16. * 灾害类型与物品属性的映射关系
  17. */
  18. private const DISASTER_ITEM_ATTRIBUTES = [
  19. DISASTER_TYPE::DROUGHT->value => 'fram_drought_rate', // 干旱 -> 浇水概率
  20. DISASTER_TYPE::PEST->value => 'fram_pesticide_rate', // 虫害 -> 除虫概率
  21. DISASTER_TYPE::WEED->value => 'fram_weedicide_rate', // 杂草 -> 除草概率
  22. ];
  23. /**
  24. * 灾害类型与操作名称的映射关系
  25. */
  26. private const DISASTER_ACTION_NAMES = [
  27. DISASTER_TYPE::DROUGHT->value => '浇水',
  28. DISASTER_TYPE::PEST->value => '除虫',
  29. DISASTER_TYPE::WEED->value => '除草',
  30. ];
  31. /**
  32. * 尝试去除指定类型的灾害
  33. *
  34. * 注意:此方法假设所有验证已经通过,专注于业务逻辑处理
  35. *
  36. * @param int $userId 用户ID
  37. * @param int $landId 土地ID
  38. * @param int $itemId 物品ID
  39. * @param int $disasterType 灾害类型
  40. * @param string $sourceType 消耗来源类型
  41. * @return array 操作结果
  42. * @throws LogicException
  43. */
  44. public function removeDisaster(int $userId, int $landId, int $itemId, int $disasterType, string $sourceType): array
  45. {
  46. // 检查事务状态
  47. Helper::check_tr();
  48. // 获取物品成功率
  49. $successRate = $this->getItemSuccessRate($itemId, $disasterType);
  50. // 进行概率判断
  51. if (!$this->rollSuccess($successRate)) {
  52. // 失败时仍然消耗物品
  53. $this->consumeItem($userId, $itemId, $landId, $sourceType);
  54. $actionName = self::DISASTER_ACTION_NAMES[$disasterType];
  55. throw new LogicException("{$actionName}失败,请再次尝试");
  56. }
  57. // 执行灾害清理
  58. $result = $this->clearDisasterFromCrop($userId, $landId, $disasterType);
  59. if (!$result) {
  60. throw new LogicException("灾害清理失败,请检查土地状态或作物生长阶段");
  61. }
  62. // 消耗物品
  63. $this->consumeItem($userId, $itemId, $landId, $sourceType);
  64. $actionName = self::DISASTER_ACTION_NAMES[$disasterType];
  65. Log::info("用户{$actionName}成功", [
  66. 'user_id' => $userId,
  67. 'land_id' => $landId,
  68. 'item_id' => $itemId,
  69. 'disaster_type' => $disasterType,
  70. 'success_rate' => $successRate
  71. ]);
  72. return [
  73. 'success' => true,
  74. 'message' => "{$actionName}成功",
  75. 'disaster_type' => $disasterType,
  76. 'success_rate' => $successRate
  77. ];
  78. }
  79. /**
  80. * 获取物品的成功率
  81. *
  82. * @param int $itemId 物品ID
  83. * @param int $disasterType 灾害类型
  84. * @return int 成功率(百分比)
  85. */
  86. private function getItemSuccessRate(int $itemId, int $disasterType): int
  87. {
  88. $attributeName = self::DISASTER_ITEM_ATTRIBUTES[$disasterType];
  89. return ItemService::getItemNumericAttribute($itemId, $attributeName, 0);
  90. }
  91. /**
  92. * 进行概率判断
  93. *
  94. * @param int $successRate 成功率(百分比,100=100%)
  95. * @return bool 是否成功
  96. */
  97. private function rollSuccess(int $successRate): bool
  98. {
  99. if ($successRate <= 0) {
  100. return false;
  101. }
  102. if ($successRate >= 100) {
  103. return true;
  104. }
  105. $randomNumber = mt_rand(1, 100);
  106. return $randomNumber <= $successRate;
  107. }
  108. /**
  109. * 从作物中清理指定类型的灾害
  110. *
  111. * @param int $userId 用户ID
  112. * @param int $landId 土地ID
  113. * @param int $disasterType 灾害类型
  114. * @return bool 是否成功
  115. */
  116. private function clearDisasterFromCrop(int $userId, int $landId, int $disasterType): bool
  117. {
  118. try {
  119. $cropLogic = new CropLogic();
  120. return $cropLogic->clearDisaster($userId, $landId, $disasterType);
  121. } catch (\Exception $e) {
  122. Log::error('清理灾害失败', [
  123. 'user_id' => $userId,
  124. 'land_id' => $landId,
  125. 'disaster_type' => $disasterType,
  126. 'error' => $e->getMessage(),
  127. 'trace' => $e->getTraceAsString()
  128. ]);
  129. return false;
  130. }
  131. }
  132. /**
  133. * 消耗物品
  134. *
  135. * @param int $userId 用户ID
  136. * @param int $itemId 物品ID
  137. * @param int $landId 土地ID
  138. * @param string $sourceType 消耗来源类型
  139. * @throws LogicException
  140. */
  141. private function consumeItem(int $userId, int $itemId, int $landId, string $sourceType): void
  142. {
  143. ItemService::consumeItem($userId, $itemId, null, 1, [
  144. 'source_type' => $sourceType,
  145. 'source_id' => $landId,
  146. 'details' => ['land_id' => $landId]
  147. ]);
  148. }
  149. }