新需求-活动需求-盲盒转盘调通盘-调试-优化错误
This commit is contained in:
@@ -200,33 +200,39 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
if ($poolInfo['code'] !== 1) {
|
if ($poolInfo['code'] !== 1) {
|
||||||
return $poolInfo;
|
return $poolInfo;
|
||||||
}
|
}
|
||||||
$totalRemaining = $poolInfo['data']['total_remaining'];
|
$totalRemaining = $poolInfo['data']['total_remaining'];//奖池剩余数量
|
||||||
$periods = $poolInfo['data']['periods'];
|
$periods = $poolInfo['data']['periods']; //奖池期数
|
||||||
$totalDrawTimes = $poolInfo['data']['total_draw_times'];
|
$totalDrawTimes = $poolInfo['data']['total_draw_times']; //总抽奖次数
|
||||||
|
|
||||||
// 2. 获取可用礼物
|
// 2. 获取可用礼物
|
||||||
$availableGifts = $this->getAvailableGifts($bag_data['id'], $totalDrawTimes);
|
$availableGifts = $this->getAvailableGifts($bag_data['id'], $totalDrawTimes);
|
||||||
if (empty($availableGifts)) {
|
if (empty($availableGifts)) {
|
||||||
$availableGifts = $this->resetPoolAndReload($bag_data['id']);
|
$availableGifts = $this->resetPoolAndReload($bag_data['id']); //重置奖池并重新加载
|
||||||
if (empty($availableGifts)) {
|
if (empty($availableGifts)) {
|
||||||
throw new \Exception('重置奖池后仍无可用礼物');
|
throw new \Exception('重置奖池后仍无可用礼物');
|
||||||
}
|
}
|
||||||
|
$totalDrawTimes = 0;//总抽奖次数重置
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. 预加载礼物信息(减少后续查询)
|
// 3. 预加载礼物信息(减少后续查询)
|
||||||
$giftInfoMap = $this->preloadGiftInfo($availableGifts);
|
$giftInfoMap = $this->preloadGiftInfo($availableGifts);
|
||||||
|
|
||||||
// 4. 处理奖池重置逻辑
|
// 4. 处理奖池重置逻辑 - 优化版本
|
||||||
$needGiftNum = count($toarray) * $num; //总需要的礼物数
|
$needGiftNum = count($toarray) * $num; //总需要的礼物数
|
||||||
$remaining_available_gifts=[];
|
$remaining_available_gifts = [];
|
||||||
if ($totalRemaining - $needGiftNum <= 0) {//奖池剩余数量-需要的礼物数小于0
|
$remainingGiftCount = array_sum(array_column($availableGifts, 'remaining_number'));
|
||||||
$remaining_available_gifts = $availableGifts; //剩余可用礼物
|
|
||||||
$availableGifts = $this->resetPoolAndReload($bag_data['id']); //重置奖池并重新加载
|
if ($remainingGiftCount < $needGiftNum) {
|
||||||
|
// 如果当前奖池礼物不足以满足需求
|
||||||
|
// 保存当前剩余礼物作为上期剩余
|
||||||
|
$remaining_available_gifts = $availableGifts;
|
||||||
|
|
||||||
|
// 重置奖池
|
||||||
|
$availableGifts = $this->resetPoolAndReload($bag_data['id']);
|
||||||
if (empty($availableGifts)) {
|
if (empty($availableGifts)) {
|
||||||
throw new \Exception('重置奖池后仍无可用礼物');
|
throw new \Exception('重置奖池后仍无可用礼物');
|
||||||
}
|
}
|
||||||
$totalDrawTimes = 0;
|
$totalDrawTimes = 0; // 总抽奖次数重置
|
||||||
$num = abs($totalRemaining - $num);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 使用Alias Method预计算抽奖结果(O(1)复杂度)
|
// 5. 使用Alias Method预计算抽奖结果(O(1)复杂度)
|
||||||
@@ -269,82 +275,95 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
&$currentXlhPeriodsNum,
|
&$currentXlhPeriodsNum,
|
||||||
$remaining_available_gifts
|
$remaining_available_gifts
|
||||||
) {
|
) {
|
||||||
//计算$remaining_available_gifts 里面 remaining_number 的累加
|
|
||||||
$remaining_num = 0;
|
|
||||||
foreach ($remaining_available_gifts as $key=>$value) {
|
|
||||||
$remaining_num += $value['remaining_number'];
|
|
||||||
}
|
|
||||||
if($remaining_num > $num){
|
|
||||||
$availableGifts = $remaining_available_gifts;
|
|
||||||
$remaining_available_gifts = [];
|
|
||||||
}
|
|
||||||
$precomputedResults = [];
|
$precomputedResults = [];
|
||||||
$precomputedResultss = [];
|
$precomputedResultss = [];
|
||||||
$giftBagIdToGift = [];
|
|
||||||
|
|
||||||
// 构建Alias表
|
// 计算上期剩余礼物总数
|
||||||
$aliasTable = $this->buildAliasTable($availableGifts);
|
$remainingGiftCount = array_sum(array_column($remaining_available_gifts, 'remaining_number'));
|
||||||
$remaining_num = 0;
|
$needGiftNum = count($toarray) * $num;
|
||||||
foreach ($toarray as $giftUserId) {
|
$newGiftsNeeded = max(0, $needGiftNum - $remainingGiftCount); // 计算还需要多少礼物从新奖池中抽取
|
||||||
if (!empty($remaining_available_gifts)) {
|
|
||||||
foreach ($remaining_available_gifts as $key=>$value) {
|
// 先从上期剩余礼物中分配
|
||||||
$remaining_num += $value['remaining_number'];
|
if (!empty($remaining_available_gifts)) {
|
||||||
$gift = $giftInfoMap[$value['foreign_id']] ?? null;
|
$aliasTableForRemaining = $this->buildAliasTable($remaining_available_gifts);
|
||||||
for ($j = 0; $j < $value['remaining_number']; $j++) {
|
|
||||||
|
foreach ($toarray as $giftUserId) {
|
||||||
|
// 为每个用户先分配上期剩余礼物
|
||||||
|
$userRemainingAllocation = floor($remainingGiftCount / count($toarray));
|
||||||
|
if (count($toarray) > 0) { // 防止除零错误
|
||||||
|
$extraGifts = $remainingGiftCount % count($toarray);
|
||||||
|
if (array_search($giftUserId, $toarray) < $extraGifts) {
|
||||||
|
$userRemainingAllocation++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($i = 0; $i < $userRemainingAllocation; $i++) {
|
||||||
|
$selectedGift = $this->selectGiftWithAliasMethod($aliasTableForRemaining);
|
||||||
|
if ($selectedGift) {
|
||||||
|
$gift = $giftInfoMap[$selectedGift['foreign_id']] ?? null;
|
||||||
$precomputedResults[] = [
|
$precomputedResults[] = [
|
||||||
'gift_user_id' => $giftUserId,
|
'gift_user_id' => $giftUserId,
|
||||||
'gift_bag_detail' => $value,
|
'gift_bag_detail' => $selectedGift,
|
||||||
|
'gift' => $gift,
|
||||||
|
'draw_times' => $totalDrawTimes,
|
||||||
|
'periods' => $periods,
|
||||||
|
];
|
||||||
|
$precomputedResultss[] = [
|
||||||
|
'gift_user_id' => $giftUserId,
|
||||||
|
'gift_bag_detail' => $selectedGift,
|
||||||
'gift' => $gift,
|
'gift' => $gift,
|
||||||
'draw_times' => $totalDrawTimes,
|
'draw_times' => $totalDrawTimes,
|
||||||
'periods' => $periods,
|
'periods' => $periods,
|
||||||
'j' => $j,
|
|
||||||
];
|
];
|
||||||
$totalDrawTimes++;
|
$totalDrawTimes++;
|
||||||
$currentXlhPeriodsNum++;
|
$currentXlhPeriodsNum++;
|
||||||
|
|
||||||
|
// 更新Alias表
|
||||||
|
$this->updateAliasTable($aliasTableForRemaining, $selectedGift['id']);
|
||||||
}
|
}
|
||||||
unset($remaining_available_gifts[$key]);
|
|
||||||
}
|
}
|
||||||
$numm = $num;
|
|
||||||
}else{
|
|
||||||
$numm = $num+$remaining_num;
|
|
||||||
}
|
}
|
||||||
for ($i = 0; $i < $numm; $i++) {
|
}
|
||||||
// 使用Alias Method选择礼物(O(1)复杂度)
|
|
||||||
$selectedGift = $this->selectGiftWithAliasMethod($aliasTable);
|
// 再从新奖池中分配剩余所需礼物
|
||||||
if (!$selectedGift) {
|
if ($newGiftsNeeded > 0 && !empty($availableGifts)) {
|
||||||
return [];
|
$aliasTableForNew = $this->buildAliasTable($availableGifts);
|
||||||
|
|
||||||
|
foreach ($toarray as $giftUserId) {
|
||||||
|
// 计算每个用户需要从新奖池获得的礼物数量
|
||||||
|
$userNewAllocation = floor($newGiftsNeeded / count($toarray));
|
||||||
|
if (count($toarray) > 0) {
|
||||||
|
$extraGifts = $newGiftsNeeded % count($toarray);
|
||||||
|
if (array_search($giftUserId, $toarray) < $extraGifts) {
|
||||||
|
$userNewAllocation++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取礼物信息(从预加载的map中获取,避免查询)
|
for ($i = 0; $i < $userNewAllocation; $i++) {
|
||||||
$giftId = $selectedGift['foreign_id'];
|
$selectedGift = $this->selectGiftWithAliasMethod($aliasTableForNew);
|
||||||
$gift = $giftInfoMap[$giftId] ?? null;
|
if ($selectedGift) {
|
||||||
// if (!$gift) {
|
$gift = $giftInfoMap[$selectedGift['foreign_id']] ?? null;
|
||||||
// continue;
|
$precomputedResults[] = [
|
||||||
// }
|
'gift_user_id' => $giftUserId,
|
||||||
|
'gift_bag_detail' => $selectedGift,
|
||||||
|
'gift' => $gift,
|
||||||
|
'draw_times' => $totalDrawTimes,
|
||||||
|
'periods' => $periods,
|
||||||
|
];
|
||||||
|
$precomputedResultss[] = [
|
||||||
|
'gift_user_id' => $giftUserId,
|
||||||
|
'gift_bag_detail' => $selectedGift,
|
||||||
|
'gift' => $gift,
|
||||||
|
'draw_times' => $totalDrawTimes,
|
||||||
|
'periods' => $periods,
|
||||||
|
];
|
||||||
|
$totalDrawTimes++;
|
||||||
|
$currentXlhPeriodsNum++;
|
||||||
|
|
||||||
$precomputedResults[] = [
|
// 更新Alias表
|
||||||
'gift_user_id' => $giftUserId,
|
$this->updateAliasTable($aliasTableForNew, $selectedGift['id']);
|
||||||
'gift_bag_detail' => $selectedGift,
|
}
|
||||||
'gift' => $gift,
|
}
|
||||||
'draw_times' => $totalDrawTimes,
|
|
||||||
'periods' => $periods,
|
|
||||||
'i' => $i,
|
|
||||||
];
|
|
||||||
$precomputedResultss[] = [
|
|
||||||
'gift_user_id' => $giftUserId,
|
|
||||||
'gift_bag_detail' => $selectedGift,
|
|
||||||
'gift' => $gift,
|
|
||||||
'draw_times' => $totalDrawTimes,
|
|
||||||
'periods' => $periods,
|
|
||||||
'i' => $i,
|
|
||||||
];
|
|
||||||
|
|
||||||
$totalDrawTimes++;
|
|
||||||
$currentXlhPeriodsNum++;
|
|
||||||
|
|
||||||
// 更新Alias表(模拟库存减少)
|
|
||||||
$this->updateAliasTable($aliasTable, $selectedGift['id']);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -855,7 +874,7 @@ class BlindBoxTurntableGiftDrawWorld extends Model
|
|||||||
$totalQuantity = $roomPanInfo['total_quantity'] ?: 0;
|
$totalQuantity = $roomPanInfo['total_quantity'] ?: 0;
|
||||||
$totalRemaining = $roomPanInfo['total_remaining'] ?: 0;
|
$totalRemaining = $roomPanInfo['total_remaining'] ?: 0;
|
||||||
$periods = $periods ?: 0;
|
$periods = $periods ?: 0;
|
||||||
$totalDrawTimes = max(0, $totalQuantity - $totalRemaining);
|
$totalDrawTimes = max(0, $totalQuantity - $totalRemaining); //总抽奖次数
|
||||||
return [
|
return [
|
||||||
'code' => 1,
|
'code' => 1,
|
||||||
'msg' => '计算成功',
|
'msg' => '计算成功',
|
||||||
|
|||||||
Reference in New Issue
Block a user