_getAccountId(); $costs = mt\Parameter::getByName('daily_selection_refresh_cost'); $arrCosts = explode('|', $costs['param_value']); $maxCount = count($arrCosts); $count = $this->countTodayRefreshTimes($address); if ($count >= $maxCount) { $this->_rspErr(2, 'The maximum number of refreshes has been reached'); return; } $cost = $arrCosts[$count]; $costItemId = $this->getCostItemIdByTokenType(ShopController::TOKEN_TYPE_GOLD); $costItems = $this->makeCostItems($costItemId, $cost); $lackItem = null; if (!$this->_hasEnoughItems($costItems, $lackItem)) { $this->_rspErr(2, $this->_getLackItemErrMsg($lackItem)); return; } $chk = $this->refreshDailySelectionWithMode($address, 1); if ($chk) { $this->_decItems($costItems); // error_log("refreshDailySelection-------" . $address . "---" . $cost); $this->_rspData( array( 'cost' => $cost, ) ); } else { $this->_rspErr(3, 'refresh failed'); } } public function getDailySelectionList() { $address = $this->_getAccountId(); // 不清除过期的每日精选可以避免跨日操作错误 // $chk = $this->clearBeforeTodayDailySelections(); $chk = $this->getTodayLastDailySelection($address); if (!$chk) { $chk = $this->refreshDailySelectionWithMode($address, 0); $chk = $this->getTodayLastDailySelection($address); } // 预检查是否有表格更新,未必能检测准确,但是可以避免大部分情况下的错误 $check = true; $selection = $chk[0]; $pre_goodsList = array(); for ($i = 1; $i <= 6; $i++) { $pre_goodsList[$i] = mt\Dailyselection::get($selection['grid_' . $i]); if (!$pre_goodsList[$i]) { $check = false; break; } } if (!$check) { $chk = $this->refreshDailySelectionWithMode($address, 0); $chk = $this->getTodayLastDailySelection($address); $selection = $chk[0]; } $selection = $chk[0]; $goodsList = array(); for ($i = 1; $i <= 6; $i++) { $goodsList[$i] = mt\Dailyselection::get($selection['grid_' . $i]); if ($goodsList[$i]) { $goodsList[$i]['count'] = $selection['count_' . $i]; // $goodsList[$i]['pending'] = $this->checkPendingBuyGoodsDS($address, $goodsList[$i]['goods_id'], $selection['idx'], $i); $goodsList[$i]['pending'] = 0; } } $count = $this->countTodayRefreshTimes($address); $costs = mt\Parameter::getByName('daily_selection_refresh_cost'); $arrCosts = explode('|', $costs['param_value']); $max_count = count($arrCosts); $cost = $count < $max_count ? $arrCosts[$count] : -1; $this->_rspData( array( 'idx' => $selection['idx'], 'refresh_info' => "{$count}/{$max_count}", 'cost' => $cost, 'goods_list' => $goodsList, ) ); } public function buyGoodsDS() { $idx = getReqVal('idx', 0); if ($idx <= 0) { $this->_rspErr(2, 'idx is invalid'); return; } $grid = getReqVal('grid', 0); if ($grid < 1 || $grid > 6) { $this->_rspErr(2, 'grid is invalid'); return; } $count = getReqVal('count', 0); if ($count<=0) { $this->_rspErr(2, 'count is invalid'); return; } $token_type = getReqVal('token_type', '4'); switch ($token_type) { case ShopController::TOKEN_TYPE_GOLD: case ShopController::TOKEN_TYPE_DIAMOND: break; default: $this->_rspErr(1, "token_type is unsupport, {$token_type}"); return; } $conn = $this->_getMysql(''); $row = SqlHelper::selectOne( $conn, 't_shop_dailyselection', array( 'idx', 'address', 'grid_' . $grid, 'count_' . $grid, ), array('idx' => $idx) ); if (!$row) { $this->_rspErr(2, 'idx is invalid'); return; } if ($row['grid_' . $grid] == 0) { $this->_rspErr(2, 'grid is invalid'); return; } if ($row['count_' . $grid] < $count) { $this->_rspErr(2, 'count is invalid'); return; } $sel_id = $row['grid_' . $grid]; $goods = mt\Dailyselection::get($sel_id); $desired_token_type = $goods['token_type']; $check_token_type = splitStr1($desired_token_type); if (!in_array($token_type, $check_token_type)) { $this->_rspErr(1, "token_type parameter error, desired_token_type: {$desired_token_type}"); return; } $token_pos = array_search($token_type, $check_token_type, true); $price_array = splitStr1($goods['price']); $discount_array = splitStr1($goods['discount']); $need_price = $price_array[$token_pos]; $discount = $discount_array[$token_pos]; $costItemId = $this->getCostItemIdByTokenType($token_type); $costItems = $this->makeCostItems($costItemId, $count * $need_price); error_log("buyGoodsDS costItems " . json_encode($costItems)); $lackItem = null; if (!$this->_hasEnoughItems($costItems, $lackItem)) { $this->_rspErr(2, $this->_getLackItemErrMsg($lackItem)); return; } $item_id = $goods['goods_id']; $item_num = $goods['goods_num']; $sql = "UPDATE t_shop_dailyselection SET count_$grid = count_$grid - $count WHERE idx = $idx"; $chk = $conn->execScript($sql); $itemMeta = mt\Item::get($item_id); $propertyChgService = new services\PropertyChgService(); for ($i = 0; $i < $count; $i++) { $this->internalAddItem($propertyChgService, $itemMeta, $item_num, 0); } $awardService = new services\AwardService(); $awardService->addItem($goods['goods_id'], $count * $item_num); $this->_decItems($costItems); $event = [ 'name' => LogService::SHOP_BUY_ITEM_DAILY, 'val' => $costItems[0]['item_num'] ]; switch ($token_type) { case ShopController::TOKEN_TYPE_GOLD: LogService::consumeGold($event); break; case ShopController::TOKEN_TYPE_DIAMOND: LogService::consumeDiamond($event); break; default: // 这里不应该出现,出现了说明配置表新增了一种货币,但是这里没有处理 error_log("buyGoodsDS token_type is invalid, token_type: {$token_type}"); return; } $goodsDto = array( 'goods_id' => $sel_id, 'item_id' => $goods['goods_id'], 'price_info' => array( 'item_id' => $goods['goods_id'], 'cost_list' => array(), ), 'bought_times' => 0, 'total_buy_times' => 0, ); { $priceInfo = mt\Item::getPriceInfo($itemMeta); if (!empty($priceInfo)) { $goodsDto['price_info'] = $priceInfo['price_info']; } } $propertyChgService->addUserChg(); $this->_rspData( array( 'idx' => $idx, 'grid' => $grid, 'count' => $count, 'award' => $awardService->toDto(), 'property_chg' => $propertyChgService->toDto(), ) ); } private function buyGoodsFree() { } private function decDailySelectionItem($idx, $grid, $count) { $self = myself(); if (!$self) return false; $conn = $self->_getMysql(''); $sql = "SELECT count_$grid FROM t_shop_dailyselection WHERE idx = $idx"; $chk = $conn->execQuery($sql); if (!$chk) return false; if ($chk[0]['count_' . $grid] < $count) return false; $sql = "UPDATE t_shop_dailyselection SET count_$grid = count_$grid - $count WHERE idx = $idx"; $chk = $conn->execScript($sql); return $chk; } private function clearBeforeTodayDailySelections() { $self = myself(); if (!$self) return; $conn = $self->_getMysql(''); $nowTime = $this->_getNowTime(); $dayTime = $this->_getDaySeconds($nowTime); $sql = "DELETE FROM t_shop_dailyselection WHERE refresh_time < $dayTime"; $chk = $conn->execScript($sql); return $chk; } private function countTodayRefreshTimes($address) { $self = myself(); if (!$self) return; $conn = $self->_getMysql(''); $nowTime = $this->_getNowTime(); $dayTime = $this->_getDaySeconds($nowTime); $sql = "SELECT COUNT(idx) AS cnt FROM t_shop_dailyselection WHERE address = '$address' AND refresh_mode = 1 AND refresh_time >= $dayTime"; $row = $conn->execQuery($sql); return $row[0]['cnt']; } private function getTodayLastDailySelection($address) { $self = myself(); if (!$self) return; $conn = $self->_getMysql(''); $nowTime = $this->_getNowTime(); $dayTime = $this->_getDaySeconds($nowTime); $sql = "SELECT * FROM t_shop_dailyselection WHERE address = '$address' AND refresh_time >= $dayTime ORDER BY idx DESC LIMIT 1"; $row = $conn->execQuery($sql); return $row; } private function refreshDailySelectionWithMode($address, $mode) { $selection = $this->randomNewDailySelection(); $self = myself(); if (!$self) return; $conn = $self->_getMysql(''); $nowTime = $this->_getNowTime(); $chk = SqlHelper::insert( $conn, 't_shop_dailyselection', array( 'address' => $address, 'refresh_mode' => $mode, 'refresh_time' => $nowTime, 'grid_1' => $selection[1]['id'], 'grid_2' => $selection[2]['id'], 'grid_3' => $selection[3]['id'], 'grid_4' => $selection[4]['id'], 'grid_5' => $selection[5]['id'], 'grid_6' => $selection[6]['id'], 'count_1' => 1, 'count_2' => 1, 'count_3' => 1, 'count_4' => 1, 'count_5' => 1, 'count_6' => 1, ) ); return $chk; } private function randomNewDailySelection() { $newDailySelection = array(); for ($i = 1; $i <= 6; $i++) { $store = mt\Dailyselection::getBySlot($i); $newDailySelection[$i] = $this->weighted_random($store); } return $newDailySelection; } private function weighted_random($array) { // 计算数组元素的总权重 $total_weight = array_sum(array_column($array, "weight")); // 生成一个随机数 $rand = mt_rand(1, $total_weight); // 遍历数组,找到随机数对应的元素 foreach ($array as $item) { // 如果随机数小于或等于当前元素的权重,返回该元素 if ($rand <= $item["weight"]) { return $item; } // 否则,减去当前元素的权重,继续循环 $rand -= $item["weight"]; } } }