where('enable', BoolEnum::YES)->first(); return $dlt; } public function saleLotteries(Customer $customer, $lotteryTypeId) { $lotteryType = LotteryType::where('type', LottType::DLT) ->where('status', BoolEnum::YES) ->find($lotteryTypeId); ThrowException::isTrue(!$lotteryType, '不支持此彩种'); /** @var Lottery $lott */ $lott = Lottery::active()->shopAndType($customer->shop_id, $lotteryTypeId)->first(); ThrowException::isTrue(!$lott, '暂不支持该彩种'); /** @var Dlt $dlt */ $dlt = $this->getSellingDlt(); ThrowException::isTrue(!$dlt, '暂未开售'); $playTypes = PlayType::asDltSelectArray(); $gets = Dlt::where('state', BoolEnum::YES) ->where('close_time', '>', date('Y-m-d H:i:s', time() + $lott->earlySecond())) ->orderBy('issue_num', 'desc') ->limit(10) ->get(); $result = []; foreach ($gets as $item) { $result[] = [ 'issue_num' => $item->issue_num, 'result_qian' => $item->qian, 'result_hou' => $item->hou, ]; } return [ 'play_type' => $playTypes, 'result' => $result, 'current' => [ 'issue_num' => $dlt->issue_num, 'close_time_str' => $dlt->getCloseTime($lott->earlySecond()) ], ]; } public function refreshOddsForCreateOrder($data, $enableAdd = 0) { $odds = $this->refreshOdds($data); $result = []; foreach ($odds as $item) { $item['enable_add'] = $enableAdd; $result[] = $item; } return $result; } public function refreshOdds($data) { $result = []; foreach ($data as $k => $item) { // 单式变复式 if ($item['play_type'] == PlayType::DLT_DANSHI) { if (count($item['play_odd']['qian']) > 5 || count($item['play_odd']['hou']) > 2) { $item['play_type'] = PlayType::DLT_FUSHI; } } if (Arr::get($item, 'play_odd.qian')) { $item['play_odd']['qian'] = $this->sortArray(Arr::get($item, 'play_odd.qian')); } if (Arr::get($item, 'play_odd.hou')) { $item['play_odd']['hou'] = $this->sortArray(Arr::get($item, 'play_odd.hou')); } if (Arr::get($item, 'play_odd.qian_dan')) { $item['play_odd']['qian_dan'] = $this->sortArray(Arr::get($item, 'play_odd.qian_dan')); } if (Arr::get($item, 'play_odd.qian_tuo')) { $item['play_odd']['qian_tuo'] = $this->sortArray(Arr::get($item, 'play_odd.qian_tuo')); } if (Arr::get($item, 'play_odd.hou_dan')) { $item['play_odd']['hou_dan'] = $this->sortArray(Arr::get($item, 'play_odd.hou_dan')); } if (Arr::get($item, 'play_odd.hou_tuo')) { $item['play_odd']['hou_tuo'] = $this->sortArray(Arr::get($item, 'play_odd.hou_tuo')); } $result[$k] = $item; } return $result; } private function sortArray($array) { if ($array) { sort($array); } return $array; } public function computePrizeInfo($data, $betsNum = 1, $passModeKeys = []) { $dlt = $this->getSellingDlt(); ThrowException::isTrue(!$dlt, '暂未开售'); $zhuTotal = 0; $money = 0; foreach ($data as $item) { if ($item['play_type'] == PlayType::DLT_DANSHI) { $res = $this->computeDanshi($item); $money += $res['money']; $zhuTotal += $res['zhu_num']; continue; } if ($item['play_type'] == PlayType::DLT_FUSHI) { $res = $this->computeFushi($item); $money += $res['money']; $zhuTotal += $res['zhu_num']; continue; } if ($item['play_type'] == PlayType::DLT_DANTUO) { $res = $this->computeDantuo($item); $money += $res['money']; $zhuTotal += $res['zhu_num']; } } return [ 'zhu_num' => $zhuTotal, 'bets_num' => 0, 'expect_bets' => 0, 'money' => $money, 'prize_min' => 0, 'prize_max' => 0 ]; } // 追加后的金额 protected function computeAddMoney($money, $enableAdd) { if ($enableAdd) { return $money + $money / 2; } return $money; } protected function computeDanshi($data) { $betsNum = $data['bets_num']; $money = Config::lotteryUnitPrice() * $betsNum; $money = $this->computeAddMoney($money, Arr::get($data, 'enable_add')); return [ 'zhu_num' => 1, 'bets_num' => $betsNum, 'expect_bets' => 0, 'money' => $money, 'prize_min' => 0, 'prize_max' => 0, ]; } protected function computeFushi($data) { $danshis = $this->fushiToDanshi($data); $allZhuShu = count($danshis); $betsNum = $data['bets_num']; $money = Config::lotteryUnitPrice() * $allZhuShu * $betsNum; $money = $this->computeAddMoney($money, Arr::get($data, 'enable_add')); return [ 'zhu_num' => 1, 'bets_num' => $betsNum, 'expect_bets' => 0, 'money' => $money, 'prize_min' => 0, 'prize_max' => 0, ]; } protected function computeDantuo($data) { $danshis = $this->dantuoToDanshi($data); $allZhuShu = count($danshis); $betsNum = $data['bets_num']; $money = Config::lotteryUnitPrice() * $allZhuShu * $betsNum; $money = $this->computeAddMoney($money, Arr::get($data, 'enable_add')); return [ 'zhu_num' => $allZhuShu, 'bets_num' => $betsNum, 'expect_bets' => 0, 'money' => $money, 'prize_min' => 0, 'prize_max' => 0, ]; } public function fushiToDanshi($data) { $qian = Arr::get($data, 'play_odd.qian', []); $hou = Arr::get($data, 'play_odd.hou', []); $qianNum = 5; $qianAll = Helps::combination($qian, $qianNum); $houNum = 2; $houAll = Helps::combination($hou, $houNum); $result = []; foreach ($qianAll as $qian) { foreach ($houAll as $hou) { $result[] = [ 'qian' => $qian, 'hou' => $hou ]; } } return $result; } public function dantuoToDanshi($data) { $qianDan = Arr::get($data, 'play_odd.qian_dan', []); $qianTuo = Arr::get($data, 'play_odd.qian_tuo', []); $houDan = Arr::get($data, 'play_odd.hou_dan', []); $houTuo = Arr::get($data, 'play_odd.hou_tuo', []); $qianNum = 5; if ($qianDan) { $qianNum -= count($qianDan); } $qianZuhe = Helps::combination($qianTuo, $qianNum); $qianAll = []; foreach ($qianZuhe as $item) { $qianAll[] = array_merge($qianDan, $item); } $houNum = 2; if ($houDan) { $houNum -= count($houDan); } $houZuhe = Helps::combination($houTuo, $houNum); $houAll = []; foreach ($houZuhe as $item) { $houAll[] = array_merge($houDan, $item); } $result = []; foreach ($qianAll as $qian) { foreach ($houAll as $hou) { $result[] = [ 'qian' => $qian, 'hou' => $hou ]; } } return $result; } public function valid(Lottery $lottery, $data) { foreach ($data as $item) { ThrowException::isTrue(!isset($item['bets_num']), '请选择投注倍数'); if (!isset($item['play_type']) || !isset($item['play_odd'])) { ThrowException::run('play数据错误'); } if (!in_array($item['play_type'], [PlayType::DLT_DANSHI, PlayType::DLT_DANTUO, PlayType::DLT_FUSHI])) { ThrowException::run('不支持该dlt_play_type'); } if ($item['play_type'] == PlayType::DLT_DANSHI) { $this->validDanshi($item['play_odd']); continue; } if ($item['play_type'] == PlayType::DLT_FUSHI) { $this->validFushi($item['play_odd']); continue; } if ($item['play_type'] == PlayType::DLT_DANTUO) { $this->validDantuo($item['play_odd']); continue; } } } public function validFushi($data) { if (!isset($data['qian']) || !isset($data['hou'])) { ThrowException::run('单式数据格式错误'); } $qian = $data['qian']; $hou = $data['hou']; if (count($qian) <= 5 && count($hou) <= 2) { ThrowException::run('复式数据格式c错误'); } ThrowException::isTrue(!DltService::inQianQuhao($qian), '单式前区号不存在'); ThrowException::isTrue(!DltService::inHouQuHao($hou), '单式后区号不存在'); } public function validDanshi($data) { if (!isset($data['qian']) || !isset($data['hou'])) { ThrowException::run('单式数据格式错误'); } $qian = $data['qian']; $hou = $data['hou']; if (count($qian) != 5 || count($hou) != 2) { ThrowException::run('单式数据格式c错误'); } ThrowException::isTrue(!DltService::inQianQuhao($qian), '单式前区号不存在'); ThrowException::isTrue(!DltService::inHouQuHao($hou), '单式后区号不存在'); } public function validDantuo($data) { $qianDan = Arr::get($data, 'qian_dan', []); $qianTuo = Arr::get($data, 'qian_tuo', []); $houDan = Arr::get($data, 'hou_dan', []); $houTuo = Arr::get($data, 'hou_tuo', []); if (!$qianDan && !$houDan) { ThrowException::run('前区胆码或后区胆码必须选一个'); } ThrowException::isTrue(count($qianTuo) < 2, '前区拖码至少选两个'); ThrowException::isTrue(count($houTuo) < 2, '后区拖码至少选两个'); $qianCount = count($qianDan) + count($qianTuo); ThrowException::isTrue($qianCount < 6, '胆拖投注至少选择6个红球'); if ($houDan && count($houDan) != 1) { ThrowException::run('后区胆码最多可选1个'); } if ($qianDan) { ThrowException::isTrue(!DltService::inQianQuhao($qianDan), '前区胆码号错误'); } ThrowException::isTrue(!DltService::inQianQuhao($qianTuo), '前区拖码号错误'); if ($houDan) { ThrowException::isTrue(!DltService::inHouQuHao($houDan), '后区胆码号错误'); } ThrowException::isTrue(!DltService::inHouQuHao($houTuo), '后区拖码号错误'); } public function createPiaos($data) { $danshiData = []; $dantuoData = []; foreach ($data as $item) { if ($item['play_type'] == PlayType::DLT_DANSHI) { // 考虑有重复的单式数据 $danshiString = $this->makeDanshiString($item); if (Arr::get($danshiData, $danshiString)) { $danshiData[$danshiString]['bets_num'] += $item['bets_num']; } else { $danshiData[$danshiString] = [ 'qian' => $item['play_odd']['qian'], 'hou' => $item['play_odd']['hou'], PlayType::DLT_DANSHI => $danshiString, 'bets_num' => $item['bets_num'], 'zhu_num' => $item['bets_num'], ]; } } else if ($item['play_type'] == PlayType::DLT_DANTUO) { $danshiList = $this->dantuoToDanshi($item); $item['zhu_num'] = count($danshiList); $dantuoData[] = $item; } else if ($item['play_type'] == PlayType::DLT_FUSHI) { $danshiList = $this->fushiToDanshi($item); $item[PlayType::DLT_FUSHI] = $this->makeDanshiString($item); $item['zhu_num'] = count($danshiList); $dantuoData[] = $item; } } $danshiPiaos = []; $danshiData = array_values($danshiData); if ($danshiData) { $danshiChucks = array_chunk($danshiData, 5); foreach ($danshiChucks as $chuck) { $danshiPiaos[] = [ 'play_type' => PlayType::DLT_DANSHI, 'bets_num' => array_sum(array_column($chuck, 'bets_num')), 'zhu_num' => $item['bets_num'], 'play_odd' => $chuck ]; } } return array_merge($danshiPiaos, $dantuoData); } private function makeDanshiString($data) { $qian = Arr::get($data, 'play_odd.qian'); $hou = Arr::get($data, 'play_odd.hou'); return implode(',', $qian) . '|' . implode(',', $hou); } public function createOrder(Customer $customer, $data) { $lotteryTypeId = Arr::get($data, 'lottery_type_id'); $playType = Arr::get($data, 'play_type'); $type = Arr::get($data, 'type', OrderType::NORMAL); $fadanSecret = Arr::get($data, 'type_mode', 1); $fadanDesc = Arr::get($data, 'type_desc', ''); $betsNum = Arr::get($data, 'bets_num'); $passModeKeys = Arr::get($data, 'pass_mode_keys'); $odds = Arr::get($data, 'odds'); // 购买的场次或投注信息 $union_piece_total = intval(Arr::get($data, 'union_piece_total', 0)); $union_piece_buy = intval(Arr::get($data, 'union_piece_buy', 0)); $union_piece_keep = intval(Arr::get($data, 'union_piece_keep', 0)); $union_keep = Arr::get($data, 'union_keep', BoolEnum::NO); $union_brokerage = intval(Arr::get($data, 'union_brokerage', 0)); $fadan_order_no = Arr::get($data, 'fadan_order_no', ''); $enableAdd = Arr::get($data, 'enable_add') ? 1 : 0; /** @var Dlt $dlt */ $dlt = $this->getSellingDlt(); ThrowException::isTrue(!$dlt, '暂未开售'); ThrowException::isTrue($type == OrderType::FADAN, '不支持发单'); ThrowException::isTrue($type == OrderType::GENDAN, '不支持跟单'); /** @var Lottery $lott */ $lott = LotteryService::getLottery($customer->shop->id, $lotteryTypeId); throw_if(!$lott, JingCaiException::create('店铺未开通该彩种!')); ThrowException::isTrue(date('Y-m-d H:i:s') > $dlt->getCloseTime($lott->earlySecond()), '投注已截止'); $this->valid($lott, $odds); $odds = $this->refreshOddsForCreateOrder($odds, $enableAdd); $computeInfo = $this->computePrizeInfo($odds, $betsNum, $passModeKeys); $oddsRaw = [ 'enable_add' => $enableAdd ]; $lott->validMixMoney($computeInfo['money']); if ($type == OrderType::UNION) { $lott->validEnableHemai(); throw_if(!$fadanDesc, JingCaiException::create('请填写合买宣言!')); ThrowException::isTrue($union_piece_total <= 0, '总份数不能小于0'); $piecePrice = $computeInfo['money'] / $union_piece_total; ThrowException::isTrue($piecePrice <= 1, '每份金额必须大于1'); ThrowException::isTrue($union_piece_buy > $union_piece_total, '超过方案总金额'); if ($union_keep == BoolEnum::YES) { $union_piece_keep = $union_piece_total - $union_piece_buy; } $this->canCreateUnionOrder($customer->id); } $pid = 0; DB::beginTransaction(); try { $earlyTime = $dlt->getCloseTime($lott->earlySecond()); $lateTime = $earlyTime; $piaos = $this->createPiaos($odds); $order = new Order(); $order->pid = $pid; $order->issue_num = $dlt->issue_num; $order->customer_id = $customer->id; $order->lottery_id = $lott->id; $order->shop_id = $customer->shop_id; $order->lottery_type_id = $lott->lottery_type_id; $order->order_sn = Order::makeOrderSn(); $order->play_type = ''; $order->bets_num = $computeInfo['bets_num']; $order->bets_expect_num = $computeInfo['expect_bets']; $order->zhu_num = $computeInfo['zhu_num']; $order->piao_num = count($piaos); $order->money = $computeInfo['money']; $order->prize_min = $computeInfo['prize_min']; $order->prize_max = $computeInfo['prize_max']; $order->pay_state = PayState::UNPAID; $order->pass_mode = $passModeKeys; $order->odds_close_time = $dlt->getCloseTime(0); $order->odds_early_close_time = $earlyTime; $order->odds_late_close_time = $lateTime; $order->type = $type; $order->type_mode = $fadanSecret; $order->type_desc = $fadanDesc; $order->odds = $odds; $order->odds_raw = $oddsRaw; if ($type == OrderType::UNION) { $pieceMoney = $order->money / $union_piece_total; $order->union_piece_total = $union_piece_total; $order->union_piece_buy = $union_piece_buy; $order->union_piece_self = $union_piece_buy; $order->union_piece_keep = $union_piece_keep; $order->union_keep = $union_keep; $order->union_brokerage = $union_brokerage; $order->union_piece_money = $pieceMoney; $order->union_money = $pieceMoney * ($union_piece_buy + $union_piece_keep); } $order->created_date = date('Ymd'); // 设置合作相关的数据 $order->setCooperateInfo($lott); $order->save(); // 如果是合买,更新自己的pid if ($order->type == OrderType::UNION) { $order->pid = $order->id; $order->save(); } DB::commit(); return $order; } catch (JingCaiException $e) { DB::rollBack(); Log::error('dlt::order::create ValidateException: ' . $e); throw $e; } catch (\Exception $e) { DB::rollBack(); Log::error('dlt::order::create Exception: ' . $e); throw $e; } } public function canCreateUnionOrder($customerId) { } /** * 跟单 * @param $data * @param Customer $customer * @return Order * @throws \Throwable */ public function copyOrder(Customer $customer, Order $od, $data) { ThrowException::run('不支持跟单'); } public function showOrder(Customer $customer, Order $order) { $order->sellings = []; // 自购的 if ($order->customerCanSeeSellings($customer)) { $order->sellings = $this->getOrderOdds($order); } $order->play_name = $order->lottery->name; unset($order->lottery); return $order; } public function getOrderOdds($order) { $odds = $order->odds; foreach ($odds as &$item) { $computeInfo = null; if ($item['play_type'] == PlayType::DLT_DANSHI) { $computeInfo = $this->computeDanshi($item); } else if ($item['play_type'] == PlayType::DLT_DANTUO) { $computeInfo = $this->computeDantuo($item); } else if ($item['play_type'] == PlayType::DLT_FUSHI) { $computeInfo = $this->computeFushi($item); } if ($computeInfo) { $item['money'] = $computeInfo['money']; $item['bets_num'] = $computeInfo['bets_num']; $item['zhu_num'] = $computeInfo['zhu_num']; } } return $odds; } public function sellerShowOrder(Seller $seller, Order $order) { $order->sellings = []; if ($order->sellerCanSeeSellings($seller)) { $order->sellings = $this->getOrderOdds($order); } $order->play_name = $order->lottery->name; unset($order->lottery); return $order; } public function chaiPiao(Order $order) { $piaos = $this->createPiaos($order->odds); foreach ($piaos as &$item) { $item['money'] = $item['bets_num'] * $item['zhu_num'] * Config::lotteryUnitPrice(); if ($item['play_type'] == PlayType::DLT_DANTUO) { $item['play_type_name'] = '胆拖'; continue; } if ($item['play_type'] == PlayType::DLT_DANSHI) { $item['play_type_name'] = '单式'; continue; } if ($item['play_type'] == PlayType::DLT_FUSHI) { $item['play_type_name'] = '复式'; continue; } } return $piaos; } public function danshiWinPrize(Dlt $dlt, $oddData, $enableAdd = 0) { $resultQian = $dlt->qian; $resultHou = $dlt->hou; $qian = $oddData['qian']; $hou = $oddData['hou']; $qianInters = array_intersect($resultQian, $qian); $houInters = array_intersect($resultHou, $hou); $qianIntersCount = count($qianInters); $houIntersCount = count($houInters); if ($qianIntersCount == 5 && $houIntersCount == 2) { $endPrize = $dlt->base1_prize; if ($enableAdd) { $endPrize += $dlt->add1_prize; } return [ 'rank' => 1, 'prize' => $endPrize, 'prize_after_tax' => Config::getAfterTaxPrize($endPrize), ]; } if ($qianIntersCount == 5 && $houIntersCount == 1) { $endPrize = $dlt->base2_prize; if ($enableAdd) { $endPrize += $dlt->add2_prize; } return [ 'rank' => 2, 'prize' => $endPrize, 'prize_after_tax' => Config::getAfterTaxPrize($endPrize), ]; } if ($qianIntersCount == 5 && $houIntersCount == 0) { return [ 'rank' => 3, 'prize' => 10000, 'prize_after_tax' => Config::getAfterTaxPrize(10000), ]; } if ($qianIntersCount == 4 && $houIntersCount == 2) { return [ 'rank' => 4, 'prize' => 3000, 'prize_after_tax' => Config::getAfterTaxPrize(3000), ]; } if ($qianIntersCount == 4 && $houIntersCount == 1) { return [ 'rank' => 5, 'prize' => 300, 'prize_after_tax' => Config::getAfterTaxPrize(300), ]; } if ($qianIntersCount == 3 && $houIntersCount == 2) { return [ 'rank' => 6, 'prize' => 200, 'prize_after_tax' => Config::getAfterTaxPrize(200), ]; } if ($qianIntersCount == 4 && $houIntersCount == 0) { return [ 'rank' => 7, 'prize' => 100, 'prize_after_tax' => Config::getAfterTaxPrize(100), ]; } if (($qianIntersCount == 3 && $houIntersCount == 1) || ($qianIntersCount == 2 && $houIntersCount == 2)) { return [ 'rank' => 8, 'prize' => 15, 'prize_after_tax' => Config::getAfterTaxPrize(15), ]; } if (($qianIntersCount == 3 && $houIntersCount == 0) || ($qianIntersCount == 1 && $houIntersCount == 2) || ($qianIntersCount == 2 && $houIntersCount == 1) || ($qianIntersCount == 0 && $houIntersCount == 2)) { return [ 'rank' => 9, 'prize' => 5, 'prize_after_tax' => Config::getAfterTaxPrize(5), ]; } return null; } }