| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218 |
- <?php
- namespace App\Module\Game\Logics;
- use App\Module\Game\Dtos\RewardGroupDto;
- use App\Module\Game\Dtos\RewardItemDto;
- use App\Module\Game\Logics\Reward\Item;
- use App\Module\Game\Services\PityService;
- use App\Module\Game\Models\GameRewardItem;
- use Illuminate\Support\Facades\Log;
- /**
- * 独立概率模式奖励处理
- */
- class IndependentProbabilityReward
- {
- /**
- * 处理独立概率模式奖励
- *
- * @param RewardGroupDto $groupDto 奖励组DTO
- * @param int|null $userId 用户ID(用于保底机制)
- * @return RewardItemDto[] 要发放的奖励项
- */
- public static function process(RewardGroupDto $groupDto, ?int $userId = null): array
- {
- $items = $groupDto->items;
- // 应用保底机制调整(如果有用户ID)
- if ($userId > 0) {
- $items = self::applyPityAdjustments($userId, $items);
- }
- // 如果不是随机发放,返回所有命中的奖励项
- if (!$groupDto->isRandom) {
- // 如果不是随机发放,返回所有奖励项
- if (!$groupDto->isRandom) {
- return array_map([Item::class, 'processQuantity' ], $items);
- }
- }
- // 随机发放:按概率选择指定数量的奖励项
- return self::processRandomSelection($groupDto, $items);
- }
- /**
- * 处理所有奖励项(非随机模式)
- *
- * @param array $items 奖励项列表
- * @return RewardItemDto[] 要发放的奖励项
- * @deprecated 不是随机模式,直接处理
- */
- private static function processAllItems(array $items): array
- {
- $selectedItems = [];
- /**
- * @var \App\Module\Game\Dtos\RewardItemDto $item
- */
- foreach ($items as $item) {
- // 必中项直接添加
- if ($item->isGuaranteed) {
- $selectedItems[] = Item::processQuantity($item);
- continue;
- }
- // 检查是否有概率设置
- $probability = $item->probability ?? 0;
- if ($probability <= 0) {
- continue; // 概率为0或未设置,跳过
- }
- // 生成随机数判断是否命中;
- // if (self::checkProbabilityHit($probability)) {
- // $selectedItems[] = Item::processQuantity($item);
- // }
- // 非随机模式 不随机了
- $selectedItems[] = Item::processQuantity($item);
- }
- return $selectedItems;
- }
- /**
- * 处理随机选择(独立概率模式下的随机数量限制)
- *
- * @param RewardGroupDto $groupDto 奖励组DTO
- * @param array $items 奖励项列表
- * @return RewardItemDto[] 要发放的奖励项
- */
- private static function processRandomSelection(RewardGroupDto $groupDto, array $items): array
- {
- $randomCount = $groupDto->randomCount;
- // 分离必中项和普通项
- $guaranteedItems = [];
- $normalItems = [];
- foreach ($items as $item) {
- if ($item->isGuaranteed) {
- $guaranteedItems[] = $item;
- } else {
- $normalItems[] = $item;
- }
- }
- // 先处理必中项
- $selectedItems = [];
- foreach ($guaranteedItems as $item) {
- $selectedItems[] = Item::processQuantity($item);
- }
- // 如果必中项数量已经达到或超过随机数量,直接返回必中项
- if (count($selectedItems) >= $randomCount) {
- return array_slice($selectedItems, 0, $randomCount);
- }
- // 计算剩余需要选择的数量
- $remainingCount = $randomCount - count($selectedItems);
- // 如果没有普通项,直接返回必中项
- if (empty($normalItems)) {
- return $selectedItems;
- }
- // 对普通项进行概率判断,收集所有命中的项
- $hitItems = [];
- foreach (range(1, $remainingCount * 5) as $lun) {
- foreach ($normalItems as $item) {
- $probability = $item->probability ?? 0;
- if ($probability <= 0) {
- continue; // 概率为0或未设置,跳过
- }
- // 生成随机数判断是否命中
- if (self::checkProbabilityHit($probability)) {
- $hitItems[] = $item;
- }
- }
- if (count($hitItems) >= $remainingCount) {
- break;
- }
- }
- // 如果命中的项数量不超过剩余需要的数量,全部添加
- if (count($hitItems) <= $remainingCount) {
- foreach ($hitItems as $item) {
- $selectedItems[] = Item::processQuantity($item);
- }
- } else {
- // 如果命中的项数量超过剩余需要的数量,随机选择
- shuffle($hitItems);
- $selectedHitItems = array_slice($hitItems, 0, $remainingCount);
- foreach ($selectedHitItems as $item) {
- $selectedItems[] = Item::processQuantity($item);
- }
- }
- return $selectedItems;
- }
- /**
- * 检查概率是否命中
- */
- private static function checkProbabilityHit(float $probability): bool
- {
- if ($probability <= 0) {
- return false;
- }
- if ($probability >= 100) {
- return true;
- }
- $random = mt_rand(1, 10000) / 100; // 生成0.01-100.00的随机数
- return $random <= $probability;
- }
- /**
- * 处理奖励项数量(支持随机数量)
- * @deprecated
- */
- private static function processQuantity(RewardItemDto $item): RewardItemDto
- {
- return Item::processQuantity($item);
- }
- /**
- * 应用保底机制调整
- */
- private static function applyPityAdjustments(int $userId, array $items): array
- {
- try {
- // 将DTO转换为模型集合以便保底服务处理
- $rewardItemModels = collect($items)->map(function ($itemDto) {
- return GameRewardItem::find($itemDto->id);
- })->filter();
- // 应用保底机制调整概率
- $adjustedItems = PityService::applyPityAdjustments($userId, $rewardItemModels);
- // 将调整后的模型转换回DTO
- return $adjustedItems->map(function ($model) {
- return RewardItemDto::fromModel($model);
- })->toArray();
- } catch (\Exception $e) {
- Log::warning("独立概率模式:保底机制调整失败", [
- 'userId' => $userId,
- 'error' => $e->getMessage()
- ]);
- return $items; // 返回原始项目
- }
- }
- }
|