爆币
This commit is contained in:
@@ -189,7 +189,8 @@ class Room extends BaseCom
|
||||
$pit_number = input('pit_number', 0);
|
||||
$heart_id = input('heart_id', 0);
|
||||
|
||||
if($gift_id == 88){
|
||||
$pool_gift_id = db::name('bb_lottery_config')->where(['key' => 'pool_gift_id'])->value('value');
|
||||
if($gift_id == $pool_gift_id){
|
||||
$reslut = model('Lottery')->gift($this->uid, $to_uid, $gift_id, $room_id,$gift_num);
|
||||
}else{
|
||||
$reslut = model('Room')->room_gift($this->uid, $to_uid, $gift_id, $gift_num, $type, $room_id, $pit_number,$heart_id);
|
||||
|
||||
@@ -23,8 +23,11 @@ class Lottery extends Model
|
||||
if(in_array($send_uid,$toarray)){
|
||||
return ['code' => 0, 'msg' => '收礼人不能包含自己', 'data' => null];
|
||||
}
|
||||
|
||||
//获取礼物信息
|
||||
$gift_info = Db::name('vs_gift')->where(['gid'=>$gift_id])
|
||||
->field('gid as gift_id,gift_name,gift_price,file_type,base_image,play_image,gift_type,label,is_public_server')->find();
|
||||
|
||||
//送给所有人的总价格
|
||||
$all_gift_price = $gift_info['gift_price'] * $num * count($toarray);
|
||||
//判断是否有足够的金币
|
||||
|
||||
@@ -126,6 +126,148 @@ if small_total_times >= small_trigger_times then
|
||||
end
|
||||
end
|
||||
|
||||
-- 返回结果
|
||||
return cjson.encode(result)
|
||||
LUA;
|
||||
|
||||
}
|
||||
|
||||
// 获取Lua脚本
|
||||
public static function getLotteryLuaScripts()
|
||||
{
|
||||
return <<<LUA
|
||||
-- 接收参数:
|
||||
-- send_uid, recv_uid, gift_gold, small_trigger_times, big_threshold,
|
||||
-- small_round, big_round, big_total_gold,
|
||||
-- big_weight_60, big_weight_70, big_weight_80, big_weight_total
|
||||
local send_uid = ARGV[1]
|
||||
local recv_uid = ARGV[2]
|
||||
local gift_gold = tonumber(ARGV[3])
|
||||
local small_trigger_times = tonumber(ARGV[4])
|
||||
local big_threshold = tonumber(ARGV[5])
|
||||
local small_round = tonumber(ARGV[6])
|
||||
local big_round = tonumber(ARGV[7])
|
||||
local big_total_gold = tonumber(ARGV[8])
|
||||
local big_weight_60 = tonumber(ARGV[9])
|
||||
local big_weight_70 = tonumber(ARGV[10])
|
||||
local big_weight_80 = tonumber(ARGV[11])
|
||||
local big_weight_total = tonumber(ARGV[12])
|
||||
|
||||
-- 核心约束:强制小轮次 ≥ 大轮次
|
||||
if small_round < big_round then
|
||||
small_round = big_round
|
||||
end
|
||||
|
||||
-- 1. 基础金额拆分
|
||||
local recv_gold = gift_gold * 0.5
|
||||
local small_pool_add = gift_gold * 0.5
|
||||
|
||||
-- 2. Redis键定义
|
||||
local small_round_key = "lottery:small_pool:round"
|
||||
local small_total_times_key = "lottery:small_pool:total_times"
|
||||
local small_total_gold_key = "lottery:small_pool:total_gold"
|
||||
local big_round_key = "lottery:big_pool:round"
|
||||
local big_total_gold_key = "lottery:big_pool:total_gold"
|
||||
|
||||
-- 初始化轮次
|
||||
redis.call('set', small_round_key, small_round)
|
||||
redis.call('set', big_round_key, big_round)
|
||||
if big_total_gold == 0 or big_total_gold == nil then
|
||||
big_total_gold = tonumber(redis.call('get', big_total_gold_key) or 0)
|
||||
end
|
||||
|
||||
-- 3. 小奖池累计更新
|
||||
local small_total_times = tonumber(redis.call('incr', small_total_times_key))
|
||||
local small_total_gold = tonumber(redis.call('get', small_total_gold_key) or 0)
|
||||
small_total_gold = math.floor((small_total_gold + small_pool_add) * 100) / 100
|
||||
redis.call('set', small_total_gold_key, small_total_gold)
|
||||
|
||||
-- 4. 返回结果初始化
|
||||
local result = {
|
||||
send_uid = send_uid,
|
||||
recv_uid = recv_uid,
|
||||
gift_gold = gift_gold,
|
||||
recv_gold = recv_gold,
|
||||
small_pool_add = small_pool_add,
|
||||
small_total_times = small_total_times,
|
||||
small_total_gold = small_total_gold,
|
||||
is_small_prize = 0,
|
||||
small_prize_amount = 0,
|
||||
small_remain_amount = 0,
|
||||
is_big_prize = 0,
|
||||
big_prize_amount = 0,
|
||||
big_release_amount = 0,
|
||||
small_round = small_round,
|
||||
big_round = big_round,
|
||||
big_total_gold = big_total_gold,
|
||||
small_prize_to_big_next_round = 0,
|
||||
big_ratio = 0,
|
||||
-- ===================== 新增核心字段 =====================
|
||||
big_pool_total_before_open = 0 -- 大奖开奖前的奖池总金额
|
||||
-- ======================================================
|
||||
}
|
||||
|
||||
-- 5. 小奖池开奖判断
|
||||
if small_total_times >= small_trigger_times then
|
||||
result.is_small_prize = 1
|
||||
-- 小奖随机比例
|
||||
local small_ratio = math.random(1, 99)
|
||||
result.small_prize_amount = math.floor(small_total_gold * small_ratio / 100 * 100) / 100
|
||||
result.small_remain_amount = math.floor((small_total_gold - result.small_prize_amount) * 100) / 100
|
||||
|
||||
-- 重置小奖池,小轮次+1
|
||||
redis.call('set', small_total_times_key, 0)
|
||||
redis.call('set', small_total_gold_key, 0)
|
||||
small_round = small_round + 1
|
||||
redis.call('set', small_round_key, small_round)
|
||||
result.small_round = small_round
|
||||
|
||||
-- 6. 小奖剩余划入大奖池当前轮次
|
||||
big_total_gold = math.floor((big_total_gold + result.small_remain_amount) * 100) / 100
|
||||
redis.call('set', big_total_gold_key, big_total_gold)
|
||||
result.big_total_gold = big_total_gold
|
||||
|
||||
-- 7. 大奖池开奖判断
|
||||
if big_total_gold >= big_threshold then
|
||||
-- ===================== 关键修改:记录开奖前总金额 =====================
|
||||
result.big_pool_total_before_open = big_total_gold -- 保存开奖前的总金额
|
||||
-- ======================================================
|
||||
|
||||
result.is_big_prize = 1
|
||||
-- 从配置读取权重计算出奖比例
|
||||
local random_weight = math.random(1, big_weight_total)
|
||||
local big_ratio = 60
|
||||
if random_weight > big_weight_60 and random_weight <= (big_weight_60 + big_weight_70) then
|
||||
big_ratio = 70
|
||||
elseif random_weight > (big_weight_60 + big_weight_70) then
|
||||
big_ratio = 80
|
||||
end
|
||||
result.big_ratio = big_ratio
|
||||
|
||||
-- 大奖金额计算(基于开奖前的总金额)
|
||||
result.big_prize_amount = math.floor(result.big_pool_total_before_open * big_ratio / 100 * 100) / 100
|
||||
result.big_release_amount = math.floor((result.big_pool_total_before_open - result.big_prize_amount) * 100) / 100
|
||||
|
||||
-- 重置大奖池,大轮次+1
|
||||
redis.call('set', big_total_gold_key, 0)
|
||||
big_round = big_round + 1
|
||||
redis.call('set', big_round_key, big_round)
|
||||
if small_round < big_round then
|
||||
small_round = big_round
|
||||
redis.call('set', small_round_key, small_round)
|
||||
result.small_round = small_round
|
||||
end
|
||||
result.big_round = big_round
|
||||
result.big_total_gold = 0
|
||||
|
||||
-- 小奖开奖金额划入大奖池下一轮
|
||||
result.small_prize_to_big_next_round = result.small_prize_amount
|
||||
local new_big_total_gold = math.floor(result.small_prize_amount * 100) / 100
|
||||
redis.call('set', big_total_gold_key, new_big_total_gold)
|
||||
result.big_total_gold = new_big_total_gold
|
||||
end
|
||||
end
|
||||
|
||||
-- 返回结果
|
||||
return cjson.encode(result)
|
||||
LUA;
|
||||
|
||||
@@ -12,6 +12,7 @@ class LotteryService
|
||||
private $redis;
|
||||
// 配置参数
|
||||
private $config;
|
||||
private $bigPrizeWeights;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@@ -19,10 +20,31 @@ class LotteryService
|
||||
// 加载配置
|
||||
$this->config = Db::name('bb_lottery_config')->column('value', 'key');
|
||||
// 初始化Redis缓存(若Redis数据丢失,从数据库恢复)
|
||||
$this->initBigPrizeWeights();
|
||||
$this->initRedisFromDb();
|
||||
$this->checkRoundConstraint();
|
||||
}
|
||||
|
||||
|
||||
private function initBigPrizeWeights()
|
||||
{
|
||||
$this->bigPrizeWeights = [
|
||||
'60' => intval($this->config['big_prize_ratio_60_weight'] ?? 20),
|
||||
'70' => intval($this->config['big_prize_ratio_70_weight'] ?? 50),
|
||||
'80' => intval($this->config['big_prize_ratio_80_weight'] ?? 30)
|
||||
];
|
||||
$this->bigPrizeWeights['total'] = array_sum($this->bigPrizeWeights);
|
||||
}
|
||||
|
||||
private function checkRoundConstraint()
|
||||
{
|
||||
$small_round = intval($this->redis->get('lottery:small_pool:round') ?: 1);
|
||||
$big_round = intval($this->redis->get('lottery:big_pool:round') ?: 1);
|
||||
if ($small_round < $big_round) {
|
||||
$this->redis->set('lottery:small_pool:round', $big_round);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 缓存恢复:独立恢复大小轮次+对应金额
|
||||
*/
|
||||
@@ -92,13 +114,17 @@ class LotteryService
|
||||
$big_total_gold = floatval($this->redis->get('lottery:big_pool:total_gold') ?: 0);
|
||||
|
||||
// 加载Lua脚本
|
||||
$luaSha = LotteryGiftLua::getLotteryLuaScript();
|
||||
$luaSha = LotteryGiftLua::getLotteryLuaScripts();
|
||||
|
||||
// 执行Lua脚本(入参:small_round + big_round)
|
||||
$result = $this->redis->eval($luaSha, [
|
||||
$send_uid, 0, $gift_gold,
|
||||
$small_trigger_times, $big_threshold,
|
||||
$small_round, $big_round, $big_total_gold
|
||||
$small_round, $big_round, $big_total_gold,
|
||||
$this->bigPrizeWeights['60'],
|
||||
$this->bigPrizeWeights['70'],
|
||||
$this->bigPrizeWeights['80'],
|
||||
$this->bigPrizeWeights['total']
|
||||
], 0);
|
||||
// var_dump($result);die;
|
||||
$result = json_decode($result, true);
|
||||
@@ -143,8 +169,8 @@ class LotteryService
|
||||
$winnerUid,
|
||||
2, // 大奖
|
||||
$result['big_prize_amount'],//中奖金额
|
||||
$result['big_total_gold'], // 开奖时大奖池金额
|
||||
$this->getBigRatio($result['big_prize_amount'], $result['big_total_gold']),
|
||||
$result['big_pool_total_before_open'], // 开奖时大奖池金额
|
||||
$result['big_ratio'],
|
||||
$result['big_release_amount']//释放金额
|
||||
);
|
||||
|
||||
@@ -153,7 +179,7 @@ class LotteryService
|
||||
2, // 大奖池
|
||||
4, // 释放
|
||||
-$result['big_release_amount'],//释放金额
|
||||
$result['big_total_gold'],// 开奖时大奖池金额
|
||||
$result['big_pool_total_before_open'],// 开奖时大奖池金额
|
||||
0,
|
||||
$giftId,
|
||||
$result['big_round'] - 1, // 关联已结束的小奖池轮次
|
||||
|
||||
Reference in New Issue
Block a user