Merge remote-tracking branch 'origin/develop' into develop
This commit is contained in:
@@ -47,7 +47,6 @@ class Lottery extends Model
|
||||
//送礼 开启事务
|
||||
Db::startTrans();
|
||||
//扣除用户金币并记录日志
|
||||
// $wallet_update = model('api/GiveGift')->change_user_cion_or_earnings_log($send_uid,$all_gift_price,$room_id,1,10,'用户金币购买幸运币礼物');
|
||||
$wallet_update = model('api/UserWallet')->change_user_cion_log($send_uid, $all_gift_price, $room_id, 10, '用户金币购买幸运币礼物');
|
||||
if(!$wallet_update){
|
||||
Db::rollback();
|
||||
@@ -62,7 +61,10 @@ class Lottery extends Model
|
||||
|
||||
//送给一人礼物的总价格(扣除用户的数额)
|
||||
$gift_price = $gift_info['gift_price'] * $num;
|
||||
|
||||
//幸运币收益率
|
||||
$lucky_rate = db::name('bb_lottery_config')->where(['key' => 'lucky_rate'])->value('value');
|
||||
$recv_coin = round($gift_price * $lucky_rate / 100, 2);
|
||||
$small_pool = $gift_price - $recv_coin;
|
||||
foreach ($toarray as $k => $to_id){
|
||||
// 1. 记录礼物赠送
|
||||
$giftRecord = [
|
||||
@@ -70,30 +72,24 @@ class Lottery extends Model
|
||||
'recv_uid' => $to_id,
|
||||
'gift_id' => $gift_id,
|
||||
'gift_gold' => $gift_price,
|
||||
'recv_gold' => $gift_price /2 ,
|
||||
'small_pool_add' => $gift_price /2 ,
|
||||
'create_time' => time()
|
||||
'recv_gold' => $recv_coin,
|
||||
'small_pool_add' => $small_pool,
|
||||
'create_time' => time(),
|
||||
'remark' => '幸运币收益率'.$lucky_rate.'%'
|
||||
];
|
||||
$giftId = Db::name('bb_lottery_gift_record')->insertGetId($giftRecord);
|
||||
|
||||
//收礼记录行为日志
|
||||
$give_gift = model('api/SendGift')->change_user_give_gift_log($send_uid,$gift_id,$gift_price,$num,$to_id,2,1,0,'送幸运币');
|
||||
$give_gift = model('api/SendGift')->change_user_give_gift_logs($send_uid,$gift_id,$gift_price,$num,$to_id,2,1,0,'送幸运币');
|
||||
if(!$give_gift){
|
||||
Db::rollback();
|
||||
return ['code' => 0, 'msg' => '送礼失败', 'data' => null];
|
||||
}
|
||||
//计算收礼人得益
|
||||
$receiver_earnings = $gift_price /2/get_system_config_value('rmb_coin_ratio');
|
||||
$receiver_earnings = $recv_coin/get_system_config_value('rmb_coin_ratio');
|
||||
//增加收益并记录日志
|
||||
// $receiver = model('api/GiveGift') -> change_user_cion_or_earnings_log($to_id,$receiver_earnings,$room_id,2,11,'收幸运币礼增加收益');
|
||||
$receiver = model('api/UserWallet')->change_user_earnings_log($to_id,$receiver_earnings,$room_id,11,'收幸运币礼增加收益');
|
||||
$receiver = model('api/UserWallet')->change_user_earnings_log($to_id,$receiver_earnings,$room_id,11,'收幸运币礼物增加收益');
|
||||
|
||||
// //用户魅力等级更新
|
||||
// $user_level = model('api/Level')->user_level_data_update($to_id,$gift_price,2,$room_id);
|
||||
// if(!$user_level){
|
||||
// Db::rollback();
|
||||
// return ['code' => 0, 'msg' => '用户等级更新失败', 'data' => null];
|
||||
// }
|
||||
//增加房间幸运值
|
||||
db::name('vs_room')->where(['id' => $room_id])->setInc('luck_value',$gift_price);
|
||||
db::name('vs_room_luck_value')->insert( [
|
||||
@@ -134,8 +130,63 @@ class Lottery extends Model
|
||||
}
|
||||
|
||||
|
||||
//抽奖
|
||||
//抽奖(不带大奖池)
|
||||
public function lottery($send_uid,$gift_price,$num,$room_id,$giftId,$fromUserInfo=null,$gift_info=null)
|
||||
{
|
||||
$small_prize_play_image = db::name('bb_lottery_config')->where(['key' => 'small_prize_play_image'])->value('value');
|
||||
try {
|
||||
$gift_gold = $gift_price;
|
||||
$service = new LotteryService();
|
||||
for($i=0;$i<$num;$i++){
|
||||
$reslut = $service->handleGift($send_uid, $gift_gold, $giftId);
|
||||
if ($reslut['code'] == 1) {
|
||||
$result = $reslut['data'];
|
||||
//(未开奖时)
|
||||
if ($result['is_small_prize'] == 0) {
|
||||
//不做处理
|
||||
} else {//开奖
|
||||
$beilv = floor($result['small_prize_amount'] / $gift_price);
|
||||
$wallet_update = model('api/UserWallet')->change_user_cion_log($send_uid,$result['small_prize_amount'],$room_id,58,'参与幸运币活动获得'.$beilv.'倍');
|
||||
if(!$wallet_update){
|
||||
return ['code' => 0, 'msg' => '流水记录失败', 'data' => null];
|
||||
}
|
||||
|
||||
$tet['text'] = '恭喜用户'.$fromUserInfo['nickname'].'在幸运币活动中获得幸运币'.$beilv.'倍';
|
||||
$tet['type'] = 2;
|
||||
$tet['beilv'] = $beilv;
|
||||
$tet['play_image'] = $small_prize_play_image;
|
||||
$tet['FromUserInfo'] = $fromUserInfo;
|
||||
$tet['user_id'] = $send_uid;
|
||||
model('api/Chat')->sendMsg(1100,$room_id,$tet);
|
||||
|
||||
$push = new Push($send_uid, $room_id);
|
||||
$room_name = Db::name('vs_room')->where(['id' => $room_id, 'apply_status' => 2])->value('room_name');
|
||||
$text = '恭喜'.$fromUserInfo['nickname'] . '在' . $room_name . '房间获得幸运币'. $beilv . '倍';
|
||||
$text_list_new[] = [
|
||||
'text' => $text,
|
||||
'gift_picture' => $gift_info['base_image'],
|
||||
'room_id' => $room_id,
|
||||
'fromUserName' => $fromUserInfo['nickname'],
|
||||
'toUserName' => '',
|
||||
'giftName' => '',
|
||||
'roomId' => $room_id,
|
||||
'number' => 1,
|
||||
];
|
||||
$push->giftBanner($text_list_new);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ['code' => 1, 'msg' => '送礼成功', 'data' => null];
|
||||
} catch (Exception $e) {
|
||||
Log::error('抽奖处理失败:' . $e->getMessage());
|
||||
return ['code' => 0, 'msg' => $e->getMessage(), 'data' => null];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//抽奖(带大奖池)
|
||||
public function lotterys($send_uid,$gift_price,$num,$room_id,$giftId,$fromUserInfo=null,$gift_info=null)
|
||||
{
|
||||
$big_prize_play_image = db::name('bb_lottery_config')->where(['key' => 'big_prize_play_image'])->value('value');
|
||||
$small_prize_play_image = db::name('bb_lottery_config')->where(['key' => 'small_prize_play_image'])->value('value');
|
||||
@@ -143,7 +194,7 @@ class Lottery extends Model
|
||||
for($i=0;$i<$num;$i++){
|
||||
$gift_gold = $gift_price;
|
||||
$service = new LotteryService();
|
||||
$reslut = $service->handleGift($send_uid, $gift_gold, $giftId);
|
||||
$reslut = $service->handleGifts($send_uid, $gift_gold, $giftId);
|
||||
if ($reslut['code'] == 1) {
|
||||
$result = $reslut['data'];
|
||||
//(未开奖时)
|
||||
|
||||
@@ -8,39 +8,26 @@ class LotteryGiftLua
|
||||
public static function getLotteryLuaScript()
|
||||
{
|
||||
return <<<LUA
|
||||
-- 接收参数:send_uid, recv_uid, gift_gold, small_trigger_times, big_threshold, small_round, big_round, big_total_gold
|
||||
-- 接收参数:send_uid, gift_gold, small_trigger_times, big_threshold, small_round, big_round, big_total_gold
|
||||
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]) -- 大奖池当前轮次金额
|
||||
|
||||
-- 核心约束:强制小轮次 ≥ 大轮次
|
||||
if small_round < big_round then
|
||||
small_round = big_round
|
||||
end
|
||||
local gift_gold = tonumber(ARGV[2])
|
||||
local small_trigger_times = ARGV[3] -- 小奖池触发次数
|
||||
local small_round = tonumber(ARGV[4]) -- 小奖池当前轮次
|
||||
local lucky_rate = tonumber(ARGV[5]) -- 收益率
|
||||
local lottery_rate = tonumber(ARGV[6]) -- 爆币率
|
||||
|
||||
-- 1. 基础金额拆分
|
||||
local recv_gold = gift_gold * 0.5
|
||||
local small_pool_add = gift_gold * 0.5
|
||||
local recv_gold = gift_gold * lucky_rate
|
||||
local small_pool_add = gift_gold * (1-lucky_rate)
|
||||
|
||||
-- 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与入参一致)
|
||||
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))
|
||||
@@ -51,7 +38,6 @@ 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,
|
||||
@@ -60,70 +46,23 @@ local result = {
|
||||
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
|
||||
}
|
||||
|
||||
-- 5. 小奖池开奖判断(小轮次+1)
|
||||
if small_total_times >= small_trigger_times then
|
||||
result.is_small_prize = 1
|
||||
-- 小奖随机比例
|
||||
local small_ratio = math.random(2, 99)
|
||||
local small_ratio = math.random(2, lottery_rate)
|
||||
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. 大奖池开奖判断(大轮次+1)
|
||||
if big_total_gold >= big_threshold then
|
||||
result.is_big_prize = 1
|
||||
-- 大奖比例权重
|
||||
local weight_sum = 20 + 50 + 30
|
||||
local random_weight = math.random(1, weight_sum)
|
||||
local big_ratio = random_weight <= 20 and 60 or (random_weight <= 70 and 70 or 80)
|
||||
-- 大奖金额
|
||||
result.big_prize_amount = math.floor(big_total_gold * big_ratio / 100 * 100) / 100
|
||||
result.big_release_amount = math.floor((big_total_gold - 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
|
||||
|
||||
-- ===================== 新增核心逻辑 =====================
|
||||
-- 小奖开奖金额累加到大奖池下一轮次(新的big_round)
|
||||
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
|
||||
|
||||
-- 返回结果
|
||||
@@ -132,6 +71,8 @@ LUA;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 获取Lua脚本
|
||||
public static function getLotteryLuaScripts()
|
||||
{
|
||||
|
||||
@@ -104,6 +104,99 @@ class LotteryService
|
||||
throw new Exception('参数错误');
|
||||
}
|
||||
|
||||
// 读取配置+独立轮次
|
||||
$small_trigger_times = intval($this->config['small_pool_trigger_times'] ?? 200);//触发抽奖次数
|
||||
$small_round = intval($this->redis->get('lottery:small_pool:round') ?: 1);//小奖轮次
|
||||
$lucky_rate = db::name('bb_lottery_config')->where(['key' => 'lucky_rate'])->value('value');//收益率
|
||||
$lottery_rate = db::name('bb_lottery_config')->where(['key' => 'lottery_rate'])->value('value');//爆币率
|
||||
|
||||
|
||||
// 加载Lua脚本
|
||||
$luaSha = LotteryGiftLua::getLotteryLuaScript();
|
||||
|
||||
// 执行Lua脚本(入参:small_round + big_round)
|
||||
$result = $this->redis->eval($luaSha, [
|
||||
$send_uid,
|
||||
$gift_gold,
|
||||
$small_trigger_times,
|
||||
$small_round,
|
||||
$lucky_rate,
|
||||
$lottery_rate
|
||||
], 0);
|
||||
|
||||
$result = json_decode($result, true);
|
||||
if (json_last_error() !== JSON_ERROR_NONE) {
|
||||
throw new Exception('Lua脚本执行失败');
|
||||
}
|
||||
|
||||
// 开启数据库事务
|
||||
Db::startTrans();
|
||||
try {
|
||||
// . 1记录小奖池累计流水(未开奖时)
|
||||
if ($result['is_small_prize'] == 0) {
|
||||
$this->addPoolFlow(
|
||||
1, // 小奖池
|
||||
1, // 累计
|
||||
$result['small_pool_add'],
|
||||
$result['small_total_gold'] - $result['small_pool_add'],
|
||||
$result['small_total_gold'],
|
||||
$giftId,
|
||||
$result['small_round'], // 新增:传入轮次
|
||||
"小奖池累计:用户{$send_uid}送礼,轮次{$result['small_round']}"
|
||||
);
|
||||
} else {
|
||||
$winnerUid = $send_uid; // 奖默认给当前送礼用户
|
||||
//2.开小奖剩余划入大奖后 大奖够开奖
|
||||
// 小奖中奖记录
|
||||
$this->addWinnerRecord(
|
||||
$winnerUid,
|
||||
1, // 小奖
|
||||
$result['small_prize_amount'],//中奖金额
|
||||
$result['small_total_gold'],//奖池总金额
|
||||
$this->getSmallRatio($result['small_prize_amount'], $result['small_total_gold']),//中奖比例
|
||||
0 //释放金额
|
||||
);
|
||||
// 3. 小奖池开奖流水
|
||||
$this->addPoolFlow(
|
||||
1, // 小奖池
|
||||
2, // 开奖扣除
|
||||
$result['small_prize_amount'],
|
||||
$result['small_total_gold'],
|
||||
$result['small_total_gold'] - $result['small_prize_amount'],
|
||||
$giftId,
|
||||
$result['small_round'] - 1, // 开奖轮次为当前轮次-1(已结束的轮次)
|
||||
"小奖池开奖:轮次" . ($result['small_round'] - 1).",中奖金额:{$result['small_prize_amount']}金币"
|
||||
);
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
return [
|
||||
'code' => 1,
|
||||
'msg' => '处理成功',
|
||||
'data' => $result
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
Db::rollback();
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 处理送礼抽奖逻辑 (带大奖池)
|
||||
* @param int $send_uid 送礼用户ID
|
||||
* @param float $gift_gold 礼物金币数
|
||||
* @param int $giftId 礼物ID
|
||||
* @return array 处理结果
|
||||
* @throws Exception
|
||||
*/
|
||||
public function handleGifts($send_uid, $gift_gold, $giftId)
|
||||
{
|
||||
// 参数校验
|
||||
if ($gift_gold <= 0 || !$send_uid) {
|
||||
throw new Exception('参数错误');
|
||||
}
|
||||
|
||||
// 读取配置+独立轮次+大奖池金额
|
||||
$small_trigger_times = intval($this->config['small_pool_trigger_times'] ?? 200);
|
||||
$big_threshold = floatval($this->config['big_pool_threshold'] ?? 1000);
|
||||
|
||||
Reference in New Issue
Block a user