'金库爆破王', 2 => '马桌双修财神', 3 => '金币收割机', ]; /** * 参与净盈利统计的游戏流水来源。 */ private const GAME_PROFIT_SOURCES = [ CurrencySource::BACCARAT_BET, CurrencySource::BACCARAT_WIN, CurrencySource::HORSE_BET, CurrencySource::HORSE_WIN, ]; /** * 获取指定日期的游戏净盈利前三榜。 * * @return Collection */ public function topThree(?string $date = null): Collection { $statsDate = CarbonImmutable::parse($date ?? today()->toDateString())->startOfDay(); $cacheKey = 'daily_game_profit_leaderboard:v2:'.$statsDate->toDateString(); return Cache::remember($cacheKey, 300, function () use ($statsDate) { $rangeStart = $statsDate; $rangeEnd = $statsDate->addDay(); return UserCurrencyLog::query() ->join('users', 'users.id', '=', 'user_currency_logs.user_id') ->where('user_currency_logs.currency', 'gold') ->whereIn('user_currency_logs.source', array_map( fn (CurrencySource $source): string => $source->value, self::GAME_PROFIT_SOURCES )) ->where('user_currency_logs.created_at', '>=', $rangeStart) ->where('user_currency_logs.created_at', '<', $rangeEnd) ->where('users.username', '!=', 'AI小班长') ->groupBy('user_currency_logs.user_id', 'users.username', 'users.usersf') ->havingRaw('SUM(user_currency_logs.amount) > 0') ->orderByRaw('SUM(user_currency_logs.amount) DESC') ->orderBy('user_currency_logs.user_id') ->limit(3) ->selectRaw('user_currency_logs.user_id, users.username, users.usersf, SUM(user_currency_logs.amount) as net_profit') ->get() ->values() ->map(function (object $row, int $index): object { $rank = $index + 1; return (object) [ 'rank' => $rank, 'title' => self::TITLES[$rank], 'user_id' => (int) $row->user_id, 'username' => (string) $row->username, 'headface_url' => $this->resolveHeadfaceUrl((string) ($row->usersf ?: '1.gif')), 'net_profit' => (int) $row->net_profit, ]; }); }); } /** * 解析榜单头像地址。 */ private function resolveHeadfaceUrl(string $headface): string { if (str_starts_with($headface, 'storage/')) { return '/'.$headface; } return '/images/headface/'.strtolower($headface); } }