TaskConditionService.php 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419
  1. <?php
  2. namespace App\Module\Task\Services;
  3. use App\Module\Task\Enums\TASK_STATUS;
  4. use App\Module\Task\Models\TaskAchievementCondition;
  5. use App\Module\Task\Models\TaskCondition;
  6. use App\Module\Task\Repositorys\TaskAchievementConditionRepository;
  7. use App\Module\Task\Repositorys\TaskConditionRepository;
  8. use App\Module\Task\Repositorys\TaskUserProgressRepository;
  9. use App\Module\Task\Repositorys\TaskUserTaskRepository;
  10. use Illuminate\Support\Facades\Log;
  11. /**
  12. * 任务条件服务类
  13. *
  14. * 提供任务条件相关的服务,包括条件验证、进度更新等功能。
  15. * 该类主要处理任务条件的逻辑,与TaskProgressService配合使用。
  16. */
  17. class TaskConditionService
  18. {
  19. /**
  20. * 任务条件数据仓库
  21. *
  22. * @var TaskConditionRepository
  23. */
  24. protected $conditionRepository;
  25. /**
  26. * 任务达成条件数据仓库
  27. *
  28. * @var TaskAchievementConditionRepository
  29. */
  30. protected $achievementConditionRepository;
  31. /**
  32. * 用户任务数据仓库
  33. *
  34. * @var TaskUserTaskRepository
  35. */
  36. protected $userTaskRepository;
  37. /**
  38. * 用户任务进度数据仓库
  39. *
  40. * @var TaskUserProgressRepository
  41. */
  42. protected $userProgressRepository;
  43. /**
  44. * 构造函数
  45. *
  46. * @param TaskConditionRepository $conditionRepository
  47. * @param TaskAchievementConditionRepository $achievementConditionRepository
  48. * @param TaskUserTaskRepository $userTaskRepository
  49. * @param TaskUserProgressRepository $userProgressRepository
  50. */
  51. public function __construct(
  52. TaskConditionRepository $conditionRepository,
  53. TaskAchievementConditionRepository $achievementConditionRepository,
  54. TaskUserTaskRepository $userTaskRepository,
  55. TaskUserProgressRepository $userProgressRepository
  56. ) {
  57. $this->conditionRepository = $conditionRepository;
  58. $this->achievementConditionRepository = $achievementConditionRepository;
  59. $this->userTaskRepository = $userTaskRepository;
  60. $this->userProgressRepository = $userProgressRepository;
  61. }
  62. /**
  63. * 获取所有可用的任务条件
  64. *
  65. * @return array 条件列表
  66. */
  67. public function getAllConditions(): array
  68. {
  69. return $this->conditionRepository->getActiveConditions();
  70. }
  71. /**
  72. * 获取任务的所有达成条件
  73. *
  74. * @param int $taskId 任务ID
  75. * @param string|null $conditionType 条件类型(prerequisite=前置条件,progress=进度条件)
  76. * @return array 达成条件列表
  77. */
  78. public function getTaskConditions(int $taskId, ?string $conditionType = null): array
  79. {
  80. return $this->achievementConditionRepository->getConditionsByTaskId($taskId, $conditionType);
  81. }
  82. /**
  83. * 验证任务前置条件
  84. *
  85. * @param int $userId 用户ID
  86. * @param int $taskId 任务ID
  87. * @return array 验证结果
  88. */
  89. public function validatePrerequisiteConditions(int $userId, int $taskId): array
  90. {
  91. try {
  92. // 获取任务的前置条件
  93. $prerequisites = $this->getTaskConditions($taskId, 'prerequisite');
  94. if (empty($prerequisites)) {
  95. return [
  96. 'success' => true,
  97. 'message' => '无前置条件',
  98. ];
  99. }
  100. // 验证每个前置条件
  101. $failedConditions = [];
  102. foreach ($prerequisites as $prerequisite) {
  103. $condition = $this->conditionRepository->find($prerequisite['condition_id']);
  104. if (!$condition) {
  105. continue;
  106. }
  107. // 获取条件处理器类
  108. $handlerClass = $condition->handler_class;
  109. if (!class_exists($handlerClass)) {
  110. Log::error('条件处理器类不存在', [
  111. 'condition_id' => $condition->id,
  112. 'handler_class' => $handlerClass,
  113. ]);
  114. continue;
  115. }
  116. // 实例化条件处理器
  117. $handler = new $handlerClass();
  118. // 验证条件
  119. $isValid = $handler->validate($userId, $prerequisite['condition_params']);
  120. if (!$isValid) {
  121. $failedConditions[] = [
  122. 'condition_id' => $condition->id,
  123. 'name' => $condition->name,
  124. 'description' => $condition->description,
  125. ];
  126. }
  127. }
  128. if (!empty($failedConditions)) {
  129. return [
  130. 'success' => false,
  131. 'message' => '前置条件未满足',
  132. 'failed_conditions' => $failedConditions,
  133. ];
  134. }
  135. return [
  136. 'success' => true,
  137. 'message' => '前置条件已满足',
  138. ];
  139. } catch (\Exception $e) {
  140. Log::error('验证前置条件失败', [
  141. 'user_id' => $userId,
  142. 'task_id' => $taskId,
  143. 'error' => $e->getMessage(),
  144. ]);
  145. return [
  146. 'success' => false,
  147. 'message' => '验证前置条件失败: ' . $e->getMessage(),
  148. ];
  149. }
  150. }
  151. /**
  152. * 更新任务进度条件
  153. *
  154. * @param int $userId 用户ID
  155. * @param string $conditionCode 条件代码
  156. * @param array $params 条件参数
  157. * @param int $increment 增量值
  158. * @return array 更新结果
  159. */
  160. public function updateProgressCondition(int $userId, string $conditionCode, array $params, int $increment = 1): array
  161. {
  162. try {
  163. // 获取条件
  164. $condition = $this->conditionRepository->getByCode($conditionCode);
  165. if (!$condition) {
  166. throw new \Exception('条件不存在');
  167. }
  168. // 获取使用该条件的任务达成条件
  169. $achievementConditions = $condition->achievementConditions()
  170. ->where('condition_type', 'progress')
  171. ->get();
  172. if ($achievementConditions->isEmpty()) {
  173. return [
  174. 'success' => true,
  175. 'message' => '无相关任务进度需要更新',
  176. 'updated_tasks' => [],
  177. ];
  178. }
  179. // 获取条件处理器类
  180. $handlerClass = $condition->handler_class;
  181. if (!class_exists($handlerClass)) {
  182. throw new \Exception('条件处理器类不存在');
  183. }
  184. // 实例化条件处理器
  185. $handler = new $handlerClass();
  186. // 更新任务进度
  187. $updatedTasks = [];
  188. foreach ($achievementConditions as $achievementCondition) {
  189. // 获取用户任务
  190. $userTask = $this->userTaskRepository->getUserTask($userId, $achievementCondition->task_id);
  191. if (!$userTask || $userTask->status !== TASK_STATUS::IN_PROGRESS->value) {
  192. continue;
  193. }
  194. // 检查条件参数是否匹配
  195. if (!$handler->isMatch($params, $achievementCondition->condition_params)) {
  196. continue;
  197. }
  198. // 获取用户任务进度
  199. $userProgress = $this->userProgressRepository->getUserProgress($userId, $achievementCondition->id);
  200. // 如果进度记录不存在,创建新记录
  201. if (!$userProgress) {
  202. $userProgress = $this->userProgressRepository->createUserProgress([
  203. 'user_id' => $userId,
  204. 'task_id' => $achievementCondition->task_id,
  205. 'achievement_condition_id' => $achievementCondition->id,
  206. 'current_value' => 0,
  207. 'target_value' => $achievementCondition->target_value,
  208. ]);
  209. }
  210. // 更新进度值
  211. $newValue = $userProgress->current_value + $increment;
  212. if ($newValue > $userProgress->target_value) {
  213. $newValue = $userProgress->target_value;
  214. }
  215. $userProgress->current_value = $newValue;
  216. $userProgress->save();
  217. // 计算任务总进度
  218. $this->calculateTaskTotalProgress($userId, $achievementCondition->task_id);
  219. $updatedTasks[] = [
  220. 'task_id' => $achievementCondition->task_id,
  221. 'condition_id' => $achievementCondition->id,
  222. 'current_value' => $newValue,
  223. 'target_value' => $userProgress->target_value,
  224. 'progress' => min(100, round($newValue / $userProgress->target_value * 100)),
  225. ];
  226. }
  227. return [
  228. 'success' => true,
  229. 'message' => '任务进度更新成功',
  230. 'updated_tasks' => $updatedTasks,
  231. ];
  232. } catch (\Exception $e) {
  233. Log::error('更新任务进度失败', [
  234. 'user_id' => $userId,
  235. 'condition_code' => $conditionCode,
  236. 'params' => $params,
  237. 'increment' => $increment,
  238. 'error' => $e->getMessage(),
  239. ]);
  240. return [
  241. 'success' => false,
  242. 'message' => '更新任务进度失败: ' . $e->getMessage(),
  243. ];
  244. }
  245. }
  246. /**
  247. * 计算任务总进度
  248. *
  249. * @param int $userId 用户ID
  250. * @param int $taskId 任务ID
  251. * @return array 计算结果
  252. */
  253. public function calculateTaskTotalProgress(int $userId, int $taskId): array
  254. {
  255. try {
  256. // 获取用户任务
  257. $userTask = $this->userTaskRepository->getUserTask($userId, $taskId);
  258. if (!$userTask || $userTask->status !== TASK_STATUS::IN_PROGRESS->value) {
  259. throw new \Exception('任务不存在或状态不正确');
  260. }
  261. // 获取任务的进度条件
  262. $progressConditions = $this->getTaskConditions($taskId, 'progress');
  263. if (empty($progressConditions)) {
  264. throw new \Exception('任务没有进度条件');
  265. }
  266. // 计算总进度
  267. $totalProgress = 0;
  268. $completedConditions = 0;
  269. foreach ($progressConditions as $condition) {
  270. // 获取用户任务进度
  271. $userProgress = $this->userProgressRepository->getUserProgress($userId, $condition['id']);
  272. if (!$userProgress) {
  273. continue;
  274. }
  275. // 计算条件进度百分比
  276. $conditionProgress = min(100, round($userProgress->current_value / $userProgress->target_value * 100));
  277. // 如果条件是必要条件,累加进度
  278. if ($condition['is_required']) {
  279. $totalProgress += $conditionProgress;
  280. }
  281. // 如果条件已完成,增加完成条件计数
  282. if ($conditionProgress >= 100) {
  283. $completedConditions++;
  284. }
  285. }
  286. // 计算平均进度
  287. $requiredConditions = array_filter($progressConditions, function ($condition) {
  288. return $condition['is_required'];
  289. });
  290. $requiredCount = count($requiredConditions);
  291. if ($requiredCount > 0) {
  292. $totalProgress = round($totalProgress / $requiredCount);
  293. } else {
  294. $totalProgress = 0;
  295. }
  296. // 更新用户任务进度
  297. $userTask->progress = $totalProgress;
  298. $userTask->save();
  299. return [
  300. 'success' => true,
  301. 'message' => '任务总进度计算成功',
  302. 'progress' => $totalProgress,
  303. 'completed_conditions' => $completedConditions,
  304. 'total_conditions' => count($progressConditions),
  305. ];
  306. } catch (\Exception $e) {
  307. Log::error('计算任务总进度失败', [
  308. 'user_id' => $userId,
  309. 'task_id' => $taskId,
  310. 'error' => $e->getMessage(),
  311. ]);
  312. return [
  313. 'success' => false,
  314. 'message' => '计算任务总进度失败: ' . $e->getMessage(),
  315. ];
  316. }
  317. }
  318. /**
  319. * 重置任务进度
  320. *
  321. * @param int $userId 用户ID
  322. * @param int $taskId 任务ID
  323. * @return array 重置结果
  324. */
  325. public function resetTaskProgress(int $userId, int $taskId): array
  326. {
  327. try {
  328. // 获取用户任务
  329. $userTask = $this->userTaskRepository->getUserTask($userId, $taskId);
  330. if (!$userTask) {
  331. throw new \Exception('任务不存在');
  332. }
  333. // 获取任务的进度条件
  334. $progressConditions = $this->getTaskConditions($taskId, 'progress');
  335. // 重置每个条件的进度
  336. foreach ($progressConditions as $condition) {
  337. $userProgress = $this->userProgressRepository->getUserProgress($userId, $condition['id']);
  338. if ($userProgress) {
  339. $userProgress->current_value = 0;
  340. $userProgress->save();
  341. }
  342. }
  343. // 重置用户任务进度
  344. $userTask->progress = 0;
  345. $userTask->status = TASK_STATUS::IN_PROGRESS->value;
  346. $userTask->completed_at = null;
  347. $userTask->rewarded_at = null;
  348. $userTask->save();
  349. return [
  350. 'success' => true,
  351. 'message' => '任务进度重置成功',
  352. ];
  353. } catch (\Exception $e) {
  354. Log::error('重置任务进度失败', [
  355. 'user_id' => $userId,
  356. 'task_id' => $taskId,
  357. 'error' => $e->getMessage(),
  358. ]);
  359. return [
  360. 'success' => false,
  361. 'message' => '重置任务进度失败: ' . $e->getMessage(),
  362. ];
  363. }
  364. }
  365. }