|
@@ -0,0 +1,144 @@
|
|
|
|
|
+<?php
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+namespace App\Services;
|
|
|
|
|
+
|
|
|
|
|
+use App\Models\LhcLottery;
|
|
|
|
|
+use App\Models\LhcOrder;
|
|
|
|
|
+use Illuminate\Support\Facades\DB;
|
|
|
|
|
+
|
|
|
|
|
+//六合彩开奖结算相关
|
|
|
|
|
+class LhcSettlementService
|
|
|
|
|
+{
|
|
|
|
|
+
|
|
|
|
|
+ //根据期号结算订单
|
|
|
|
|
+ public static function settle($issue)
|
|
|
|
|
+ {
|
|
|
|
|
+ // 1. 获取开奖结果
|
|
|
|
|
+ $lottery = LhcLottery::where('issue', $issue)->first();
|
|
|
|
|
+ if (!$lottery) throw new \Exception("未找到期号 {$issue} 的开奖数据");
|
|
|
|
|
+
|
|
|
|
|
+ $numbers = is_array($lottery->numbers) ? $lottery->numbers : json_decode($lottery->numbers, true);
|
|
|
|
|
+ $specialNum = (int)end($numbers); // 最后一个是特码
|
|
|
|
|
+
|
|
|
|
|
+ // 预计算特码属性
|
|
|
|
|
+ $attr = [
|
|
|
|
|
+ 'num' => $specialNum,
|
|
|
|
|
+ 'zodiac' => self::getZodiac($specialNum, date('Y', strtotime($lottery->open_time))),
|
|
|
|
|
+ 'color' => self::getColor($specialNum),
|
|
|
|
|
+ 'ds' => $specialNum % 2 === 0 ? '双' : '单',
|
|
|
|
|
+ 'dx' => $specialNum >= 25 ? '大' : '小', // 49通常算和局或按规则定义
|
|
|
|
|
+ ];
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 批量获取待结算订单 (Chunk 处理防止内存溢出)
|
|
|
|
|
+ LhcOrder::where('issue', $issue)->where('lottery_status', 'pending')
|
|
|
|
|
+ ->chunk(100, function ($orders) use ($attr) {
|
|
|
|
|
+ foreach ($orders as $order) {
|
|
|
|
|
+ $this->processOrder($order, $attr);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function processOrder($order, $attr)
|
|
|
|
|
+ {
|
|
|
|
|
+ DB::transaction(function () use ($order, $attr) {
|
|
|
|
|
+ $isWin = false;
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 根据玩法判断中奖
|
|
|
|
|
+ switch ($order->play_type) {
|
|
|
|
|
+ case 'tm_number': // 特码直选
|
|
|
|
|
+ $isWin = (int)$order->bet_value === $attr['num'];
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'tm_sx': // 特码生肖
|
|
|
|
|
+ $isWin = $order->bet_value === $attr['zodiac'];
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'tm_bs': // 特码波色
|
|
|
|
|
+ $isWin = $order->bet_value === $attr['color'];
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'tm_ds': // 特码单双
|
|
|
|
|
+ $isWin = $order->bet_value === $attr['ds'];
|
|
|
|
|
+ break;
|
|
|
|
|
+ case 'tm_dx': // 特码大小
|
|
|
|
|
+ // 49 一般不计大小或算和,根据实际规则改写
|
|
|
|
|
+ if ($attr['num'] === 49) {
|
|
|
|
|
+ $this->refundOrder($order); // 49退本金
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ $isWin = $order->bet_value === $attr['dx'];
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 执行结算
|
|
|
|
|
+ if ($isWin) {
|
|
|
|
|
+ $bonus = $order->amount * $order->odds;
|
|
|
|
|
+ $order->update(['lottery_status' => '2', 'win_amount' => $bonus]);
|
|
|
|
|
+ $order->user->increment('balance', $bonus); // 派奖
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $order->update(['lottery_status' => '1']);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private function refundOrder($order) {
|
|
|
|
|
+ $order->update(['lottery_status' => '3', 'win_amount' => $order->amount]);
|
|
|
|
|
+ $order->user->increment('balance', $order->amount);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取特码对应的生肖
|
|
|
|
|
+ * 六合彩生肖逻辑:当年的生肖对应 01, 13, 25, 37, 49
|
|
|
|
|
+ * @param int $number 号码 (1-49)
|
|
|
|
|
+ * @param int $year 农历年份 (如 2024)
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function getZodiac($number, $year = null)
|
|
|
|
|
+ {
|
|
|
|
|
+ $year = $year ?: date('Y');
|
|
|
|
|
+
|
|
|
|
|
+ // 生肖对应索引 (固定顺序)
|
|
|
|
|
+ $zodiacList = ['鼠', '牛', '虎', '兔', '龙', '蛇', '马', '羊', '猴', '鸡', '狗', '猪'];
|
|
|
|
|
+
|
|
|
|
|
+ // 计算当年的本命生肖索引 (以 2024 龙年为例)
|
|
|
|
|
+ // 简易逻辑:(年份 - 4) % 12。2024 -> index 8 (龙)
|
|
|
|
|
+ $currentYearZodiacIndex = ($year - 4) % 12;
|
|
|
|
|
+
|
|
|
|
|
+ // 六合彩号码是从 1 开始逆推的
|
|
|
|
|
+ // 公式:(本命索引 - (号码 - 1) % 12 + 12) % 12
|
|
|
|
|
+ $targetIndex = ($currentYearZodiacIndex - ($number - 1) % 12 + 12) % 12;
|
|
|
|
|
+
|
|
|
|
|
+ return $zodiacList[$targetIndex];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取号码对应的波色
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function getColor($number)
|
|
|
|
|
+ {
|
|
|
|
|
+ $red = [1, 2, 7, 8, 12, 13, 18, 19, 23, 24, 29, 30, 34, 35, 40, 45, 46];
|
|
|
|
|
+ $blue = [3, 4, 9, 10, 14, 15, 20, 25, 26, 31, 36, 37, 41, 42, 47, 48];
|
|
|
|
|
+ $green = [5, 6, 11, 16, 17, 21, 22, 27, 28, 32, 33, 38, 39, 43, 44, 49];
|
|
|
|
|
+
|
|
|
|
|
+ if (in_array($number, $red)) return '红波';
|
|
|
|
|
+ if (in_array($number, $blue)) return '蓝波';
|
|
|
|
|
+ if (in_array($number, $green)) return '绿波';
|
|
|
|
|
+ return '未知';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 获取五行 (金木水火土)
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function getElement($number)
|
|
|
|
|
+ {
|
|
|
|
|
+ // 五行通常每年也会微调,此处为通用映射逻辑(示意)
|
|
|
|
|
+ $elements = [
|
|
|
|
|
+ '金' => [1, 2, 15, 16, 23, 24, 31, 32, 45, 46],
|
|
|
|
|
+ '木' => [5, 6, 13, 14, 27, 28, 35, 36, 43, 44],
|
|
|
|
|
+ '水' => [11, 12, 19, 20, 33, 34, 41, 42, 49],
|
|
|
|
|
+ '火' => [7, 8, 21, 22, 29, 30, 37, 38],
|
|
|
|
|
+ '土' => [3, 4, 9, 10, 17, 18, 25, 26, 39, 40, 47, 48],
|
|
|
|
|
+ ];
|
|
|
|
|
+ foreach ($elements as $name => $nums) {
|
|
|
|
|
+ if (in_array($number, $nums)) return $name;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+}
|