diff --git a/hwe/sammo/Betting.php b/hwe/sammo/Betting.php index c1272b07..10623121 100644 --- a/hwe/sammo/Betting.php +++ b/hwe/sammo/Betting.php @@ -25,7 +25,8 @@ class Betting return Json::encode($bettingType); } - public function purifyBettingKey(array $bettingType): array{ + public function purifyBettingKey(array $bettingType): array + { $selectCnt = $this->info->selectCnt; sort($bettingType, SORT_NUMERIC); $bettingType = array_unique($bettingType, SORT_NUMERIC); //NOTE: key로 바로 사용하므로 중요함 @@ -34,11 +35,11 @@ class Betting } if ($bettingType[0] < 0) { - throw new \InvalidArgumentException('올바르지 않은 값이 있습니다.(0 미만)'); + throw new \InvalidArgumentException('올바르지 않은 값이 있습니다.(0 미만)' . print_r($bettingType, true)); } if (Util::array_last($bettingType) >= count($this->info->candidates)) { - throw new \InvalidArgumentException('올바르지 않은 값이 있습니다.(초과)'); + throw new \InvalidArgumentException('올바르지 않은 값이 있습니다.(초과)' . print_r($bettingType, true)); } return $bettingType; @@ -66,7 +67,7 @@ class Betting } $winnerList = $db->queryAllLists( - 'SELECT general_id, user_id, amount WHERE betting_id = %i AND betting_type = %s', + 'SELECT general_id, user_id, amount FROM ng_betting WHERE betting_id = %i AND betting_type = %s AND general_id > 0', $this->bettingID, $this->_convertBettingKey($bettingType) ); @@ -85,7 +86,7 @@ class Betting $result = []; foreach ($winnerList as [$generalID, $userID, $amount]) { - $result[$generalID] = [ + $result[] = [ 'generalID' => $generalID, 'userID' => $userID, 'amount' => $amount * $multiplier, @@ -136,7 +137,7 @@ class Betting $db = DB::db(); foreach ($db->queryAllLists( - 'SELECT general_id, user_id, amount, betting_type WHERE betting_id = %i', + 'SELECT general_id, user_id, amount, betting_type FROM ng_betting WHERE betting_id = %i', $this->bettingID ) as [$generalID, $userID, $amount, $bettingTypeKey]) { $bettingType = Json::decode($bettingTypeKey); @@ -169,7 +170,7 @@ class Betting $remainRewardAmount -= $givenRewardAmount; // /2가 아니라 다른 값이 될 경우를 대비.. } - foreach (Util::range(1, $selectCnt) as $matchPoint) { + foreach (Util::range(1, $selectCnt + 1) as $matchPoint) { if (!key_exists($matchPoint, $rewardAmount)) { continue; } @@ -190,7 +191,7 @@ class Betting $multiplier = $subReward / $subAmount[$matchPoint]; foreach ($subWinners[$matchPoint] as $subWinner) { $subWinner['amount'] *= $multiplier; - $result[$subWinner['generalID']] = $subWinner; + $result[] = $subWinner; } } @@ -200,43 +201,78 @@ class Betting public function giveReward(array $winnerType) { $rewardList = $this->calcReward($winnerType); + $selectCnt = $this->info->selectCnt; $db = DB::db(); if ($this->info->reqInheritancePoint) { + /** @var UserLogger[] */ + $loggers = []; foreach ($rewardList as $rewardItem) { if ($rewardItem['userID'] === null) { continue; } $userID = $rewardItem['userID']; - $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); - $previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0]; - - $userLogger = new UserLogger($userID); $amount = $rewardItem['amount']; + $inheritStor = KVStorage::getStorage($db, "inheritance_{$userID}"); + $previousPoint = ($inheritStor->getValue('previous') ?? [0, 0])[0]; $nextPoint = $previousPoint + $amount; $inheritStor->setValue('previous', [$nextPoint, 0]); + $inheritStor->invalidateCacheValue('previous');//XXX: 실제로는 previous 값을 사용할 수 없도록 락을 걸어야 한다. $amountText = number_format($amount); $previousPointText = number_format($previousPoint); $nextPointText = number_format($nextPoint); - $userLogger->push("{$this->info->name} 베팅 보상으로 {$amountText} 포인트 획득.", "inheritPoint"); + $matchPoint = $rewardItem['matchPoint']; + + if ($matchPoint == $selectCnt) { + $partialText = '베팅 당첨'; + } else { + $partialText = "베팅 부분 당첨({$matchPoint}/{$selectCnt})"; + } + + if (key_exists($userID, $loggers)) { + $userLogger = $loggers[$userID]; + } else { + $userLogger = new UserLogger($userID); + $loggers[$userID] = $userLogger; + } + + [$year, $month] = Util::parseYearMonth($this->info->openYearMonth); + + $userLogger->push("{$this->info->name} {$partialText} 보상으로 {$amountText} 포인트 획득.", "inheritPoint"); $userLogger->push("포인트 {$previousPointText} => {$nextPointText}", "inheritPoint"); + } + + foreach ($loggers as $userLogger) { $userLogger->flush(); } + } else { - foreach (General::createGeneralObjListFromDB(Util::squeezeFromArray($rewardList, 'generalID'), ['gold', 'npc'], 1) as $gambler) { - $reward = Util::round($rewardList[$gambler->getID()]['amount']); + $generalList = General::createGeneralObjListFromDB(array_unique(Util::squeezeFromArray($rewardList, 'generalID')), ['gold', 'npc'], 1); + foreach ($rewardList as $rewardItem) { + $gambler = $generalList[$rewardItem['generalID']]; + $reward = Util::round($rewardItem['amount']); + $matchPoint = $rewardItem['matchPoint']; $gambler->increaseVar('gold', $reward); if (($gambler->getNPCType() == 0) || ($gambler->getNPCType() == 1 && $gambler->getRankVar('betgold', 0) > 0)) { $gambler->increaseRankVar('betwingold', $reward); $gambler->increaseRankVar('betwin', 1); } + + if ($matchPoint == $selectCnt) { + $partialText = '베팅 당첨'; + } else { + $partialText = "베팅 부분 당첨({$matchPoint}/{$selectCnt})"; + } $rewardText = number_format($reward); - $gambler->getLogger()->pushGeneralActionLog("{$this->info->name}의 베팅 보상으로 {$rewardText}의 금 획득!", ActionLogger::EVENT_PLAIN); - $gambler->applyDB($db); + $gambler->getLogger()->pushGeneralActionLog("{$this->info->name}의 {$partialText} 보상으로 {$rewardText}의 금 획득!", ActionLogger::EVENT_PLAIN); + } + + foreach ($generalList as $general) { + $general->applyDB($db); } } diff --git a/hwe/sammo/Event/Action/FinishNationBetting.php b/hwe/sammo/Event/Action/FinishNationBetting.php index 7e824494..6cecba38 100644 --- a/hwe/sammo/Event/Action/FinishNationBetting.php +++ b/hwe/sammo/Event/Action/FinishNationBetting.php @@ -2,6 +2,7 @@ namespace sammo\Event\Action; +use sammo\ActionLogger; use sammo\Betting; use \sammo\GameConst; use \sammo\Util; @@ -20,30 +21,43 @@ class FinishNationBetting extends \sammo\Event\Action { $db = DB::db(); - $bettingStor = KVStorage::getStorage($db, 'betting'); - $bettingInfoRaw = $bettingStor->getValue("id_{$this->bettingID}"); - if($bettingInfoRaw === null){ - return [__CLASS__, true]; - } - - try{ + try { $bettingHelper = new Betting($this->bettingID); - } - catch (\Exception $e){ + } catch (\Exception $e) { return [__CLASS__, false, $e->getMessage()]; } $bettingInfo = $bettingHelper->getInfo(); - if($bettingInfo->type != 'nationBetting'){ + if ($bettingInfo->type != 'bettingNation') { return [__CLASS__, false, 'invalid type', $bettingInfo->type]; } - $winnerNations = $bettingHelper->purifyBettingKey($db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0')); - if(count($winnerNations) != $bettingInfo->selectCnt){ + $winnerNations = $db->queryFirstColumn('SELECT nation FROM nation WHERE level > 0'); + if (count($winnerNations) != $bettingInfo->selectCnt) { return [__CLASS__, false, 'invalid winner cnt', $bettingInfo->selectCnt]; } - $bettingHelper->giveReward($winnerNations); + //nation_id와 betting_type이 일치하지 않으므로 정렬 + $nationIDMap = []; + foreach ($bettingInfo->candidates as $idx => $candidate) { + $aux = $candidate->aux; + if (!$aux) { + return [__CLASS__, false, "invalid aux {$idx}:{$candidate->title}"]; + } + $nationID = $aux['nation']; + $nationIDMap[$nationID] = $idx; + } + + $winnerTypes = []; + foreach ($winnerNations as $winnerNationID) { + $winnerTypes[] = $nationIDMap[$winnerNationID]; + } + $winnerTypes = $bettingHelper->purifyBettingKey($winnerTypes); + + $bettingHelper->giveReward($winnerTypes); + $logger = new ActionLogger(0, 0, $env['year'], $env['month']); + [$year, $month] = Util::parseYearMonth($bettingInfo->openYearMonth); + $logger->pushGlobalHistoryLog("【내기】 {$year}년 {$month}월에 열렸던 {$bettingInfo->name} 내기의 결과가 나왔습니다!"); return [__CLASS__, true]; } diff --git a/hwe/sammo/Event/Action/OpenNationBetting.php b/hwe/sammo/Event/Action/OpenNationBetting.php index 6f097e77..8384d25c 100644 --- a/hwe/sammo/Event/Action/OpenNationBetting.php +++ b/hwe/sammo/Event/Action/OpenNationBetting.php @@ -81,7 +81,7 @@ class OpenNationBetting extends \sammo\Event\Action $bettingInfo = new BettingInfo( id: $bettingID, type: 'bettingNation', - name: "[{$year}년 {$month}월] {$name} 예상 베팅", + name: "{$name} 예상", finished: false, selectCnt: $this->nationCnt, reqInheritancePoint: true, diff --git a/hwe/ts/PageNationBetting.vue b/hwe/ts/PageNationBetting.vue index c3f0e479..51d03996 100644 --- a/hwe/ts/PageNationBetting.vue +++ b/hwe/ts/PageNationBetting.vue @@ -95,7 +95,7 @@ :key="info.id" @click="loadBetting(info.id)" > - {{ info.name }} + [{{ parseYearMonth(info.openYearMonth)[0] }}년 {{ parseYearMonth(info.openYearMonth)[1] }}월] {{ info.name }} (종료)