ConditionService.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. <?php
  2. namespace App\Module\Game\Services;
  3. use App\Module\Fund\Logic\User as FundLogic;
  4. use App\Module\Game\Enums\CONDITION_OPERATOR;
  5. use App\Module\Game\Enums\CONDITION_TYPE;
  6. use App\Module\Game\Models\GameConditionGroup;
  7. use App\Module\Game\Dtos\ConditionGroupDto;
  8. use App\Module\Game\Models\GameConditionItem;
  9. use App\Module\GameItems\Services\ItemService;
  10. use App\Module\Pet\Services\PetService;
  11. use Illuminate\Support\Facades\Log;
  12. /**
  13. * 条件服务类
  14. *
  15. * 提供条件组相关的服务,包括检查用户是否满足条件等功能
  16. */
  17. class ConditionService
  18. {
  19. /**
  20. * 获取条件组信息
  21. *
  22. * @param int|string $conditionGroupCode 条件组ID或编码
  23. * @param bool $withItems 是否包含条件项
  24. * @return ConditionGroupDto|null 条件组DTO,不存在时返回null
  25. */
  26. public static function getConditionGroup($conditionGroupCode, bool $withItems = true): ?ConditionGroupDto
  27. {
  28. try {
  29. // 获取条件组
  30. $conditionGroup = is_numeric($conditionGroupCode)
  31. ? GameConditionGroup::with($withItems ? ['conditionItems'] : [])->find($conditionGroupCode)
  32. : GameConditionGroup::with($withItems ? ['conditionItems'] : [])->where('code', $conditionGroupCode)->first();
  33. if (!$conditionGroup) {
  34. return null;
  35. }
  36. return ConditionGroupDto::fromModel($conditionGroup, $withItems);
  37. } catch (\Exception $e) {
  38. Log::error('获取条件组失败', [
  39. 'condition_group_code' => $conditionGroupCode,
  40. 'error' => $e->getMessage()
  41. ]);
  42. return null;
  43. }
  44. }
  45. /**
  46. * 检查用户是否满足条件组的条件
  47. *
  48. * @param int $userId 用户ID
  49. * @param string|int $conditionGroupCode 条件组编码或ID
  50. * @return array 检查结果,包含success字段表示是否满足条件,message字段表示错误信息
  51. */
  52. public static function checkCondition(int $userId, $conditionGroupCode): array
  53. {
  54. try {
  55. // 获取条件组
  56. $conditionGroup = is_numeric($conditionGroupCode)
  57. ? GameConditionGroup::find($conditionGroupCode)
  58. : GameConditionGroup::where('code', $conditionGroupCode)->first();
  59. if (!$conditionGroup) {
  60. return [
  61. 'success' => false,
  62. 'message' => "条件组不存在: {$conditionGroupCode}"
  63. ];
  64. }
  65. // 获取条件组中的所有条件项
  66. $conditionItems = $conditionGroup->conditionItems;
  67. if ($conditionItems->isEmpty()) {
  68. return [
  69. 'success' => true,
  70. 'message' => '条件组中没有条件项'
  71. ];
  72. }
  73. // 根据逻辑类型检查条件
  74. $logicType = $conditionGroup->logic_type;
  75. $failedConditions = [];
  76. foreach ($conditionItems as $item) {
  77. $checkResult = self::checkConditionItem($userId, $item);
  78. if ($logicType == GameConditionGroup::LOGIC_TYPE_ALL && !$checkResult['success']) {
  79. // 全部满足模式下,有一个不满足就返回失败
  80. return [
  81. 'success' => false,
  82. 'message' => $checkResult['message'],
  83. 'condition_item' => $item->id,
  84. 'details' => $checkResult
  85. ];
  86. } elseif ($logicType == GameConditionGroup::LOGIC_TYPE_ANY && $checkResult['success']) {
  87. // 任一满足模式下,有一个满足就返回成功
  88. return [
  89. 'success' => true,
  90. 'message' => '满足条件',
  91. 'condition_item' => $item->id,
  92. 'details' => $checkResult
  93. ];
  94. }
  95. if (!$checkResult['success']) {
  96. $failedConditions[] = [
  97. 'condition_item' => $item->id,
  98. 'details' => $checkResult
  99. ];
  100. }
  101. }
  102. // 处理最终结果
  103. if ($logicType == GameConditionGroup::LOGIC_TYPE_ALL) {
  104. // 全部满足模式下,走到这里说明全部满足
  105. return [
  106. 'success' => true,
  107. 'message' => '满足所有条件'
  108. ];
  109. } else {
  110. // 任一满足模式下,走到这里说明没有一个满足
  111. return [
  112. 'success' => false,
  113. 'message' => '不满足任何条件',
  114. 'failed_conditions' => $failedConditions
  115. ];
  116. }
  117. } catch (\Exception $e) {
  118. Log::error('检查条件失败', [
  119. 'user_id' => $userId,
  120. 'condition_group' => $conditionGroupCode,
  121. 'error' => $e->getMessage()
  122. ]);
  123. return [
  124. 'success' => false,
  125. 'message' => '检查条件时发生错误: ' . $e->getMessage()
  126. ];
  127. }
  128. }
  129. /**
  130. * 检查单个条件项
  131. *
  132. * @param int $userId 用户ID
  133. * @param GameConditionItem $conditionItem 条件项
  134. * @return array 检查结果
  135. */
  136. protected static function checkConditionItem(int $userId, GameConditionItem $conditionItem): array
  137. {
  138. switch ($conditionItem->condition_type) {
  139. case CONDITION_TYPE::LAND_LEVEL->value:
  140. return self::checkLandLevelCondition($userId, $conditionItem);
  141. case CONDITION_TYPE::HOUSE_LEVEL->value:
  142. return self::checkHouseLevelCondition($userId, $conditionItem);
  143. case CONDITION_TYPE::PET_LEVEL->value:
  144. return self::checkPetLevelCondition($userId, $conditionItem);
  145. case CONDITION_TYPE::ITEM_COUNT->value:
  146. return self::checkItemCountCondition($userId, $conditionItem);
  147. case CONDITION_TYPE::CURRENCY_COUNT->value:
  148. return self::checkCurrencyCountCondition($userId, $conditionItem);
  149. default:
  150. return [
  151. 'success' => false,
  152. 'message' => "不支持的条件类型: {$conditionItem->condition_type}"
  153. ];
  154. }
  155. }
  156. /**
  157. * 检查土地等级条件
  158. *
  159. * @param int $userId 用户ID
  160. * @param GameConditionItem $conditionItem 条件项
  161. * @return array 检查结果
  162. */
  163. protected static function checkLandLevelCondition(int $userId, GameConditionItem $conditionItem): array
  164. {
  165. try {
  166. // 获取用户指定类型的土地
  167. $landType = $conditionItem->target_id;
  168. $lands = \App\Module\Farm\Services\LandService::getUserLands($userId);
  169. // 计算指定类型的土地数量
  170. $count = 0;
  171. foreach ($lands as $land) {
  172. if ($land->landType == $landType) {
  173. $count++;
  174. }
  175. }
  176. // 执行比较
  177. $result = CONDITION_OPERATOR::compare($count, $conditionItem->value, $conditionItem->operator);
  178. if ($result) {
  179. return [
  180. 'success' => true,
  181. 'message' => "土地等级条件满足",
  182. 'actual' => $count,
  183. 'expected' => $conditionItem->value,
  184. 'operator' => $conditionItem->getOperatorSymbol()
  185. ];
  186. } else {
  187. return [
  188. 'success' => false,
  189. 'message' => "土地等级条件不满足,需要 {$conditionItem->getOperatorSymbol()} {$conditionItem->value},实际 {$count}",
  190. 'actual' => $count,
  191. 'expected' => $conditionItem->value,
  192. 'operator' => $conditionItem->getOperatorSymbol()
  193. ];
  194. }
  195. } catch (\Exception $e) {
  196. Log::error('检查土地等级条件失败', [
  197. 'user_id' => $userId,
  198. 'condition_item' => $conditionItem->id,
  199. 'error' => $e->getMessage()
  200. ]);
  201. return [
  202. 'success' => false,
  203. 'message' => '检查土地等级条件时发生错误: ' . $e->getMessage()
  204. ];
  205. }
  206. }
  207. /**
  208. * 检查房屋等级条件
  209. *
  210. * @param int $userId 用户ID
  211. * @param GameConditionItem $conditionItem 条件项
  212. * @return array 检查结果
  213. */
  214. protected static function checkHouseLevelCondition(int $userId, GameConditionItem $conditionItem): array
  215. {
  216. try {
  217. // 获取用户房屋等级
  218. $farmUser = \App\Module\Farm\Models\FarmUser::where('user_id', $userId)->first();
  219. if (!$farmUser) {
  220. return [
  221. 'success' => false,
  222. 'message' => "用户没有房屋"
  223. ];
  224. }
  225. $houseLevel = $farmUser->house_level;
  226. // 执行比较
  227. $result = CONDITION_OPERATOR::compare($houseLevel, $conditionItem->value, $conditionItem->operator);
  228. if ($result) {
  229. return [
  230. 'success' => true,
  231. 'message' => "房屋等级条件满足",
  232. 'actual' => $houseLevel,
  233. 'expected' => $conditionItem->value,
  234. 'operator' => $conditionItem->getOperatorSymbol()
  235. ];
  236. } else {
  237. return [
  238. 'success' => false,
  239. 'message' => "房屋等级条件不满足,需要 {$conditionItem->getOperatorSymbol()} {$conditionItem->value},实际 {$houseLevel}",
  240. 'actual' => $houseLevel,
  241. 'expected' => $conditionItem->value,
  242. 'operator' => $conditionItem->getOperatorSymbol()
  243. ];
  244. }
  245. } catch (\Exception $e) {
  246. Log::error('检查房屋等级条件失败', [
  247. 'user_id' => $userId,
  248. 'condition_item' => $conditionItem->id,
  249. 'error' => $e->getMessage()
  250. ]);
  251. return [
  252. 'success' => false,
  253. 'message' => '检查房屋等级条件时发生错误: ' . $e->getMessage()
  254. ];
  255. }
  256. }
  257. /**
  258. * 检查宠物等级条件
  259. *
  260. * @param int $userId 用户ID
  261. * @param GameConditionItem $conditionItem 条件项
  262. * @return array 检查结果
  263. */
  264. protected static function checkPetLevelCondition(int $userId, GameConditionItem $conditionItem): array
  265. {
  266. try {
  267. // 获取用户宠物
  268. $petId = $conditionItem->target_id;
  269. $userPet = PetService::getUserPet($userId, $petId);
  270. if (!$userPet) {
  271. return [
  272. 'success' => false,
  273. 'message' => "用户没有该宠物"
  274. ];
  275. }
  276. $petLevel = $userPet->level;
  277. // 执行比较
  278. $result = CONDITION_OPERATOR::compare($petLevel, $conditionItem->value, $conditionItem->operator);
  279. if ($result) {
  280. return [
  281. 'success' => true,
  282. 'message' => "宠物等级条件满足",
  283. 'actual' => $petLevel,
  284. 'expected' => $conditionItem->value,
  285. 'operator' => $conditionItem->getOperatorSymbol()
  286. ];
  287. } else {
  288. return [
  289. 'success' => false,
  290. 'message' => "宠物等级条件不满足,需要 {$conditionItem->getOperatorSymbol()} {$conditionItem->value},实际 {$petLevel}",
  291. 'actual' => $petLevel,
  292. 'expected' => $conditionItem->value,
  293. 'operator' => $conditionItem->getOperatorSymbol()
  294. ];
  295. }
  296. } catch (\Exception $e) {
  297. Log::error('检查宠物等级条件失败', [
  298. 'user_id' => $userId,
  299. 'condition_item' => $conditionItem->id,
  300. 'error' => $e->getMessage()
  301. ]);
  302. return [
  303. 'success' => false,
  304. 'message' => '检查宠物等级条件时发生错误: ' . $e->getMessage()
  305. ];
  306. }
  307. }
  308. /**
  309. * 检查物品持有数条件
  310. *
  311. * @param int $userId 用户ID
  312. * @param GameConditionItem $conditionItem 条件项
  313. * @return array 检查结果
  314. */
  315. protected static function checkItemCountCondition(int $userId, GameConditionItem $conditionItem): array
  316. {
  317. try {
  318. // 获取用户物品
  319. $itemId = $conditionItem->target_id;
  320. $userItems = ItemService::getUserItems($userId, ['item_id' => $itemId]);
  321. // 计算物品总数
  322. $totalQuantity = 0;
  323. foreach ($userItems as $userItem) {
  324. $totalQuantity += $userItem->quantity;
  325. }
  326. // 执行比较
  327. $result = CONDITION_OPERATOR::compare($totalQuantity, $conditionItem->value, $conditionItem->operator);
  328. if ($result) {
  329. return [
  330. 'success' => true,
  331. 'message' => "物品持有数条件满足",
  332. 'actual' => $totalQuantity,
  333. 'expected' => $conditionItem->value,
  334. 'operator' => $conditionItem->getOperatorSymbol()
  335. ];
  336. } else {
  337. return [
  338. 'success' => false,
  339. 'message' => "物品持有数条件不满足,需要 {$conditionItem->getOperatorSymbol()} {$conditionItem->value},实际 {$totalQuantity}",
  340. 'actual' => $totalQuantity,
  341. 'expected' => $conditionItem->value,
  342. 'operator' => $conditionItem->getOperatorSymbol()
  343. ];
  344. }
  345. } catch (\Exception $e) {
  346. Log::error('检查物品持有数条件失败', [
  347. 'user_id' => $userId,
  348. 'condition_item' => $conditionItem->id,
  349. 'error' => $e->getMessage()
  350. ]);
  351. return [
  352. 'success' => false,
  353. 'message' => '检查物品持有数条件时发生错误: ' . $e->getMessage()
  354. ];
  355. }
  356. }
  357. /**
  358. * 检查代币持有数条件
  359. *
  360. * @param int $userId 用户ID
  361. * @param GameConditionItem $conditionItem 条件项
  362. * @return array 检查结果
  363. */
  364. protected static function checkCurrencyCountCondition(int $userId, GameConditionItem $conditionItem): array
  365. {
  366. try {
  367. // 获取用户货币账户
  368. $currencyId = $conditionItem->target_id;
  369. $account = FundLogic::get_account($userId, $currencyId);
  370. // 检查账户是否存在
  371. if ($account === false) {
  372. return [
  373. 'success' => false,
  374. 'message' => "用户没有该货币账户"
  375. ];
  376. }
  377. $balance = $account->balance;
  378. // 执行比较
  379. $result = CONDITION_OPERATOR::compare($balance, $conditionItem->value, $conditionItem->operator);
  380. if ($result) {
  381. return [
  382. 'success' => true,
  383. 'message' => "代币持有数条件满足",
  384. 'actual' => $balance,
  385. 'expected' => $conditionItem->value,
  386. 'operator' => $conditionItem->getOperatorSymbol()
  387. ];
  388. } else {
  389. return [
  390. 'success' => false,
  391. 'message' => "代币持有数条件不满足,需要 {$conditionItem->getOperatorSymbol()} {$conditionItem->value},实际 {$balance}",
  392. 'actual' => $balance,
  393. 'expected' => $conditionItem->value,
  394. 'operator' => $conditionItem->getOperatorSymbol()
  395. ];
  396. }
  397. } catch (\Exception $e) {
  398. Log::error('检查代币持有数条件失败', [
  399. 'user_id' => $userId,
  400. 'condition_item' => $conditionItem->id,
  401. 'error' => $e->getMessage()
  402. ]);
  403. return [
  404. 'success' => false,
  405. 'message' => '检查代币持有数条件时发生错误: ' . $e->getMessage()
  406. ];
  407. }
  408. }
  409. }