Files
webman-buildadmin/app/common/service/GameRecordStatService.php
zhenhui 1eed3cf0f7 1.增加互斥锁:保证缓存和数据库数据一致性
2.增加消费队列,保证mysql数据的正常保存
2026-04-20 14:13:48 +08:00

108 lines
3.4 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace app\common\service;
use app\common\library\game\StreakWinReward;
use support\think\Db;
/**
* 对局维度统计:平台盈亏、中奖人数(与 GameLiveService 单号派彩口径一致)。
*/
final class GameRecordStatService
{
/**
* 根据注单与开奖号码回写 game_record 统计字段(已结束对局)。
*/
public static function refreshForRecordId(int $recordId): void
{
if ($recordId <= 0) {
return;
}
$record = Db::name('game_record')->where('id', $recordId)->find();
if (!$record) {
return;
}
$status = (int) ($record['status'] ?? 0);
$now = time();
if ($status !== 4) {
Db::name('game_record')->where('id', $recordId)->update([
'platform_profit_amount' => '0.0000',
'winner_user_count' => 0,
'update_time' => $now,
]);
GameHotDataCoordinator::afterGameRecordCommitted($recordId);
return;
}
$resultRaw = $record['result_number'] ?? null;
if ($resultRaw === null || $resultRaw === '') {
return;
}
$resultNum = (int) $resultRaw;
$bets = Db::name('bet_order')->where('period_id', $recordId)->select()->toArray();
$totalBet = '0.0000';
$totalPayout = '0.0000';
$winnerUserIds = [];
foreach ($bets as $bet) {
$st = (int) ($bet['status'] ?? 0);
if ($st === 3) {
continue;
}
$tb = (string) ($bet['total_amount'] ?? '0');
$totalBet = bcadd($totalBet, $tb, 4);
if ($st === 2) {
$payout = bcadd((string) ($bet['win_amount'] ?? '0'), (string) ($bet['jackpot_extra_amount'] ?? '0'), 4);
} else {
$payout = self::estimatePayoutForBet($bet, $resultNum);
}
$totalPayout = bcadd($totalPayout, $payout, 4);
if (bccomp($payout, '0', 4) > 0) {
$uid = (int) ($bet['user_id'] ?? 0);
if ($uid > 0) {
$winnerUserIds[$uid] = true;
}
}
}
$profit = bcsub($totalBet, $totalPayout, 4);
Db::name('game_record')->where('id', $recordId)->update([
'platform_profit_amount' => $profit,
'winner_user_count' => count($winnerUserIds),
'update_time' => $now,
]);
GameHotDataCoordinator::afterGameRecordCommitted($recordId);
}
/**
* 与 GameLiveService::estimateLossForNumber 一致:命中号码时 total_amount × odds_factor。
*/
private static function estimatePayoutForBet(array $bet, int $resultNumber): string
{
$pickNumbers = $bet['pick_numbers'] ?? null;
if (is_string($pickNumbers)) {
$decoded = json_decode($pickNumbers, true);
$pickNumbers = is_array($decoded) ? $decoded : [];
}
if (!is_array($pickNumbers)) {
$pickNumbers = [];
}
if (!in_array($resultNumber, array_map('intval', $pickNumbers), true)) {
return '0.0000';
}
$total = (string) ($bet['total_amount'] ?? '0');
$streak = (int) ($bet['streak_at_bet'] ?? 0);
$odds = StreakWinReward::totalOddsMultiplierForStreakAtBet($streak);
return bcmul($total, $odds, 4);
}
}