playerId = $playerId; } public static function getRedisKey(int $playerId): string { return self::REDIS_KEY_PREFIX . $playerId; } public static function getStartIndexKey(int $playerId): string { return self::REDIS_KEY_START_INDEX . $playerId; } /** 从 Redis 加载或根据玩家与 DiceLotteryConfig 创建并保存 */ public static function getOrCreate(int $playerId): self { $key = self::getRedisKey($playerId); $cached = Cache::get($key); if ($cached && is_string($cached)) { $data = json_decode($cached, true); if (is_array($data)) { $s = new self($playerId); $s->configType0Id = (int) ($data['config_type_0_id'] ?? 0); $s->configType1Id = (int) ($data['config_type_1_id'] ?? 0); $s->playerWeights = $data['player_weights'] ?? []; return $s; } } $player = DicePlayer::find($playerId); if (!$player) { throw new \RuntimeException('玩家不存在'); } $config0 = DiceLotteryConfig::where('type', 0)->find(); $config1 = DiceLotteryConfig::where('type', 1)->find(); $s = new self($playerId); $s->configType0Id = $config0 ? (int) $config0->id : null; $s->configType1Id = $config1 ? (int) $config1->id : null; $s->playerWeights = [ 't1_wight' => (int) ($player->t1_wight ?? 0), 't2_wight' => (int) ($player->t2_wight ?? 0), 't3_wight' => (int) ($player->t3_wight ?? 0), 't4_wight' => (int) ($player->t4_wight ?? 0), 't5_wight' => (int) ($player->t5_wight ?? 0), ]; $s->save(); return $s; } public function save(): void { $key = self::getRedisKey($this->playerId); $data = [ 'config_type_0_id' => $this->configType0Id, 'config_type_1_id' => $this->configType1Id, 'player_weights' => $this->playerWeights, ]; Cache::set($key, json_encode($data), self::EXPIRE); } /** 根据奖池配置的 t1_wight..t5_wight 权重随机抽取档位 T1-T5 */ public static function drawTierByWeights(DiceLotteryConfig $config): string { $tiers = ['T1', 'T2', 'T3', 'T4', 'T5']; $weights = [ (int) ($config->t1_wight ?? 0), (int) ($config->t2_wight ?? 0), (int) ($config->t3_wight ?? 0), (int) ($config->t4_wight ?? 0), (int) ($config->t5_wight ?? 0), ]; $total = array_sum($weights); if ($total <= 0) { return $tiers[array_rand($tiers)]; } $r = mt_rand(1, $total); $acc = 0; foreach ($weights as $i => $w) { $acc += $w; if ($r <= $acc) { return $tiers[$i]; } } return $tiers[4]; } /** 按 paid_ticket_count 与 free_ticket_count 权重随机抽取 0=付费 1=免费 */ public static function drawTicketType(int $paid, int $free): int { if ($paid <= 0 && $free <= 0) { throw new \RuntimeException('抽奖券不足'); } if ($paid <= 0) { return 1; } if ($free <= 0) { return 0; } $total = $paid + $free; $r = mt_rand(1, $total); return $r <= $paid ? 0 : 1; } public function getConfigType0Id(): ?int { return $this->configType0Id; } public function getConfigType1Id(): ?int { return $this->configType1Id; } }