| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393 |
- <?php
- namespace App\Module\Activity\Logics;
- use App\Module\Activity\Dtos\ActivityConfigDto;
- use App\Module\Activity\Dtos\ActivityParticipationDto;
- use App\Module\Activity\Enums\ACTIVITY_STATUS;
- use App\Module\Activity\Enums\PARTICIPATION_STATUS;
- use App\Module\Activity\Enums\REWARD_STATUS;
- use App\Module\Activity\Events\ActivityCompletedEvent;
- use App\Module\Activity\Events\ActivityProgressUpdatedEvent;
- use App\Module\Activity\Events\ActivityRewardClaimedEvent;
- use App\Module\Activity\Events\UserParticipatedEvent;
- use App\Module\Activity\Models\ActivityConfig;
- use App\Module\Activity\Models\ActivityCondition;
- use App\Module\Activity\Models\ActivityParticipation;
- use App\Module\Activity\Models\UserActivityData;
- use App\Module\Game\Enums\REWARD_SOURCE_TYPE;
- use Exception;
- use Illuminate\Support\Facades\Event;
- use Illuminate\Support\Facades\Log;
- /**
- * 活动逻辑类
- */
- class ActivityLogic
- {
- /**
- * 获取活动详情
- *
- * @param int $activityId 活动ID
- * @param bool $withConditions 是否包含条件
- * @return ActivityConfigDto|null
- */
- public function getActivityDetail(int $activityId, bool $withConditions = false): ?ActivityConfigDto
- {
- $query = ActivityConfig::query();
- if ($withConditions) {
- $query->with('conditions');
- }
- $activity = $query->find($activityId);
- if (!$activity) {
- return null;
- }
- return ActivityConfigDto::fromModel($activity, $withConditions);
- }
- /**
- * 获取用户可参与的活动列表
- *
- * @param int $userId 用户ID
- * @return array
- */
- public function getUserAvailableActivities(int $userId): array
- {
- // 获取进行中的活动
- $activities = ActivityConfig::where('status', ACTIVITY_STATUS::IN_PROGRESS)
- ->where('start_time', '<=', now())
- ->where('end_time', '>=', now())
- ->orderBy('display_order', 'desc')
- ->get();
- $result = [];
- foreach ($activities as $activity) {
- // 检查用户是否已参与且完成或失败
- $participation = ActivityParticipation::where('user_id', $userId)
- ->where('activity_id', $activity->id)
- ->whereIn('completion_status', [PARTICIPATION_STATUS::COMPLETED, PARTICIPATION_STATUS::FAILED])
- ->first();
- // 如果用户已完成或失败,则跳过
- if ($participation) {
- continue;
- }
- // 检查参与条件
- if ($this->checkParticipationConditions($userId, $activity->id)) {
- $result[] = ActivityConfigDto::fromModel($activity);
- }
- }
- return $result;
- }
- /**
- * 参与活动
- *
- * @param int $userId 用户ID
- * @param int $activityId 活动ID
- * @return ActivityParticipationDto
- * @throws Exception
- */
- public function participateActivity(int $userId, int $activityId): ActivityParticipationDto
- {
- // 获取活动信息
- $activity = ActivityConfig::findOrFail($activityId);
- // 检查活动状态
- if ($activity->status !== ACTIVITY_STATUS::IN_PROGRESS) {
- throw new Exception('活动未开始或已结束');
- }
- // 检查活动时间
- $now = now();
- if ($activity->start_time > $now || $activity->end_time < $now) {
- throw new Exception('不在活动时间范围内');
- }
- // 检查用户是否已参与且完成或失败
- $existingParticipation = ActivityParticipation::where('user_id', $userId)
- ->where('activity_id', $activityId)
- ->whereIn('completion_status', [PARTICIPATION_STATUS::COMPLETED, PARTICIPATION_STATUS::FAILED])
- ->first();
- if ($existingParticipation) {
- throw new Exception('您已完成或失败此活动,无法再次参与');
- }
- // 检查参与条件
- if (!$this->checkParticipationConditions($userId, $activityId)) {
- throw new Exception('不满足活动参与条件');
- }
- // 检查事务是否已开启
- \UCore\Db\Helper::check_tr();
- // 查找或创建参与记录
- $participation = ActivityParticipation::firstOrNew([
- 'user_id' => $userId,
- 'activity_id' => $activityId,
- ]);
- $isNewParticipation = !$participation->exists;
- // 设置参与记录属性
- $participation->participate_time = $now;
- $participation->reward_status = REWARD_STATUS::NOT_CLAIMED;
- $participation->completion_status = PARTICIPATION_STATUS::IN_PROGRESS;
- $participation->save();
- // 创建或更新用户活动数据
- $userData = UserActivityData::firstOrNew([
- 'user_id' => $userId,
- 'activity_id' => $activityId,
- ]);
- if (!$userData->exists) {
- $userData->progress = 0;
- $userData->progress_data = [];
- }
- $userData->last_update = $now;
- $userData->save();
- // 如果是新参与,触发用户参与活动事件
- if ($isNewParticipation) {
- Event::dispatch(new UserParticipatedEvent($userId, $activityId));
- }
- // 返回参与记录DTO
- return ActivityParticipationDto::fromModel($participation);
- }
- /**
- * 更新活动进度
- *
- * @param int $userId 用户ID
- * @param int $activityId 活动ID
- * @param int $progress 进度值
- * @param array|null $progressData 进度数据
- * @return bool
- * @throws Exception
- */
- public function updateActivityProgress(int $userId, int $activityId, int $progress, ?array $progressData = null): bool
- {
- // 获取用户参与记录
- $participation = ActivityParticipation::where('user_id', $userId)
- ->where('activity_id', $activityId)
- ->first();
- if (!$participation) {
- throw new Exception('用户未参与此活动');
- }
- if ($participation->completion_status !== PARTICIPATION_STATUS::IN_PROGRESS) {
- throw new Exception('活动已完成或失败,无法更新进度');
- }
- // 检查事务是否已开启
- \UCore\Db\Helper::check_tr();
- // 更新用户活动数据
- $userData = UserActivityData::firstOrNew([
- 'user_id' => $userId,
- 'activity_id' => $activityId,
- ]);
- $oldProgress = $userData->progress;
- $userData->progress = $progress;
- if ($progressData !== null) {
- $userData->progress_data = $progressData;
- }
- $userData->last_update = now();
- $userData->save();
- // 检查是否满足完成条件
- $isCompleted = $this->checkCompletionConditions($userId, $activityId);
- if ($isCompleted) {
- // 更新参与记录为已完成
- $participation->completion_status = PARTICIPATION_STATUS::COMPLETED;
- $participation->completion_time = now();
- $participation->save();
- // 触发活动完成事件
- Event::dispatch(new ActivityCompletedEvent($userId, $activityId));
- }
- // 触发活动进度更新事件
- Event::dispatch(new ActivityProgressUpdatedEvent($userId, $activityId, $oldProgress, $progress));
- return true;
- }
- /**
- * 领取活动奖励
- *
- * @param int $userId 用户ID
- * @param int $activityId 活动ID
- * @return bool
- * @throws Exception
- */
- public function claimActivityReward(int $userId, int $activityId): bool
- {
- // 获取用户参与记录
- $participation = ActivityParticipation::where('user_id', $userId)
- ->where('activity_id', $activityId)
- ->first();
- if (!$participation) {
- throw new Exception('用户未参与此活动');
- }
- if ($participation->completion_status !== PARTICIPATION_STATUS::COMPLETED) {
- throw new Exception('活动未完成,无法领取奖励');
- }
- if ($participation->reward_status === REWARD_STATUS::CLAIMED) {
- throw new Exception('奖励已领取');
- }
- // 检查事务是否已开启
- \UCore\Db\Helper::check_tr();
- // 获取活动信息
- $activity = ActivityConfig::findOrFail($activityId);
- // 更新参与记录为已领取
- $participation->reward_status = REWARD_STATUS::CLAIMED;
- $participation->save();
- // 发放奖励
- $rewardResult = $this->grantActivityReward($userId, $activity);
- // 触发奖励领取事件
- Event::dispatch(new ActivityRewardClaimedEvent($userId, $activityId, $rewardResult));
- return true;
- }
- /**
- * 检查参与条件
- *
- * @param int $userId 用户ID
- * @param int $activityId 活动ID
- * @return bool
- */
- private function checkParticipationConditions(int $userId, int $activityId): bool
- {
- // 获取活动的参与条件
- $conditions = ActivityCondition::where('activity_id', $activityId)
- ->where('is_participation_condition', true)
- ->get();
- // 如果没有参与条件,则默认可以参与
- if ($conditions->isEmpty()) {
- return true;
- }
- // 检查每个条件
- foreach ($conditions as $condition) {
- // 根据条件类型进行检查
- $conditionChecker = new ConditionLogic();
- if (!$conditionChecker->checkCondition($userId, $condition)) {
- return false;
- }
- }
- return true;
- }
- /**
- * 检查完成条件
- *
- * @param int $userId 用户ID
- * @param int $activityId 活动ID
- * @return bool
- */
- private function checkCompletionConditions(int $userId, int $activityId): bool
- {
- // 获取活动的完成条件
- $conditions = ActivityCondition::where('activity_id', $activityId)
- ->where('is_completion_condition', true)
- ->get();
- // 如果没有完成条件,则默认已完成
- if ($conditions->isEmpty()) {
- return true;
- }
- // 检查每个条件
- foreach ($conditions as $condition) {
- // 根据条件类型进行检查
- $conditionChecker = new ConditionLogic();
- if (!$conditionChecker->checkCondition($userId, $condition)) {
- return false;
- }
- }
- return true;
- }
- /**
- * 发放活动奖励
- *
- * @param int $userId 用户ID
- * @param ActivityConfig $activity 活动配置
- * @return array 奖励结果
- */
- private function grantActivityReward(int $userId, ActivityConfig $activity): array
- {
- $result = [
- 'success' => true,
- 'rewards' => []
- ];
- // 如果活动配置了奖励组
- if ($activity->reward_group_id || $activity->reward_group_code) {
- try {
- // 使用奖励组服务发放奖励
- $rewardGroupId = $activity->reward_group_id;
- $rewardGroupCode = $activity->reward_group_code;
- // 调用奖励组服务
- $rewardService = new \App\Module\Game\Services\RewardService();
- $rewardResult = $rewardService::grantReward(
- $userId,
- $rewardGroupId ?: $rewardGroupCode,
- REWARD_SOURCE_TYPE::ACTIVITY,
- $activity->id
- );
- if ($rewardResult->success) {
- $result['rewards'] = $rewardResult->items;
- } else {
- Log::error('活动奖励发放失败', [
- 'user_id' => $userId,
- 'activity_id' => $activity->id,
- 'error' => $rewardResult->errorMessage
- ]);
- $result['success'] = false;
- $result['error'] = $rewardResult->errorMessage;
- }
- } catch (Exception $e) {
- Log::error('活动奖励发放异常', [
- 'user_id' => $userId,
- 'activity_id' => $activity->id,
- 'error' => $e->getMessage()
- ]);
- $result['success'] = false;
- $result['error'] = $e->getMessage();
- }
- }
- return $result;
- }
- }
|