diff --git a/config/logdb.mysql.cluster.php b/config/logdb.mysql.cluster.php new file mode 100644 index 00000000..622e73a3 --- /dev/null +++ b/config/logdb.mysql.cluster.php @@ -0,0 +1,10 @@ + 1, + 'host' => 'mysql-host', + 'port' => 3306, + 'user' => 'root', + 'passwd' => 'keji178', + 'dbname' => 'logdb_dev_1' + ); diff --git a/doc/HashRateShop.py b/doc/HashRateShop.py new file mode 100644 index 00000000..87e02a74 --- /dev/null +++ b/doc/HashRateShop.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +import _common + +class HashRateShop(object): + + def __init__(self): + self.apis = [ + { + 'name': 'getGoodsList', + 'desc': '获取商品列表', + 'group': 'HashRateShop', + 'url': 'webapp/index.php?c=HashRateShop&a=getGoodsList', + 'params': [ + _common.ReqHead(), + ], + 'response': [ + _common.RspHead(), + ['!goods_list', [_common.HashRateGoods()], '商品列表'], + ] + }, + { + 'name': 'buyGoodsS', + 'desc': '购买商品', + 'group': 'HashRateShop', + 'surl': 'webapp/index.php?c=HashRateShop&a=buyGoodsS', + 'params': [ + _common.ReqHead(), + ['goods_id', '', '商品唯一id'], + ['goods_num', '', '商品数量'], + ], + 'response': [ + _common.RspHead(), + ['goods_info', _common.HashRateGoods(), '商品信息(客户端刷新用)'], + ['award', _common.Award(), '奖励信息'], + ['property_chg', _common.PropertyChg(), '属性变更'], + ] + } + ] diff --git a/doc/_common.py b/doc/_common.py index e65e11f3..c65f6a64 100644 --- a/doc/_common.py +++ b/doc/_common.py @@ -1934,3 +1934,15 @@ class VipLevelInfo(object): ['curpoint', 0, '当前点数'], ['target', 0, '升级所需点数,如为-1则已是最高等级'], ] + +class HashRateGoods(object): + + def __init__(self): + self.fields = [ + ['goods_id', 0, '商品id'], + ['item_id', 0, '道具id'], + ['item_num', 0, '道具数量'], + ['purchased_num', 0, '已购买数量'], + ['max_num', 0, '最大数量(-1不限购)'], + ['count_down', 0, '倒计时(单位秒,只有已售罄才有效)'], + ] diff --git a/sql/gamedb.sql b/sql/gamedb.sql index 236bfc85..9abb7230 100644 --- a/sql/gamedb.sql +++ b/sql/gamedb.sql @@ -2194,3 +2194,28 @@ CREATE TABLE `t_rookie_task_value` ( ) ENGINE=InnoDB AUTO_INCREMENT=10000 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; /*!40101 SET character_set_client = @saved_cs_client */; + +-- Table structure for table `t_hashrate_shop_buy_record` +-- + +DROP TABLE IF EXISTS `t_hashrate_shop_buy_record`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `t_hashrate_shop_buy_record` ( + `idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', + `account_id` varchar(60) NOT NULL DEFAULT '' COMMENT '账号id', + `goods_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品id', + `item_id` int(11) NOT NULL DEFAULT '0' COMMENT '道具id', + `this_day_buy_times` int(11) NOT NULL DEFAULT '0' COMMENT '今日购买次数', + `this_week_buy_times` int(11) NOT NULL DEFAULT '0' COMMENT '本周购买次数', + `this_month_buy_times` int(11) NOT NULL DEFAULT '0' COMMENT '本月购买次数', + `total_buy_times` int(11) NOT NULL DEFAULT '0' COMMENT '总购买次数', + `last_buy_time` int(11) NOT NULL DEFAULT '0' COMMENT '最后一次购买时间', + `createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', + `modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间', + PRIMARY KEY (`idx`), + KEY `account_id` (`account_id`), + UNIQUE KEY `account_id_goods_id` (`account_id`, `goods_id`) +) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +/*!40101 SET character_set_client = @saved_cs_client */; + diff --git a/sql/gamedb2006_migrate_241001_01.sql b/sql/gamedb2006_migrate_241001_01.sql index 79b8a2b9..4b687bed 100644 --- a/sql/gamedb2006_migrate_241001_01.sql +++ b/sql/gamedb2006_migrate_241001_01.sql @@ -14,6 +14,7 @@ CREATE TABLE `t_user_bind_gold_record` ( PRIMARY KEY (`idx`) ) ENGINE=InnoDB AUTO_INCREMENT=10000 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + CREATE TABLE `t_user_rookie_task_bind` ( `idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', `account_id` varchar(60) NOT NULL DEFAULT '' COMMENT '账号id(channel + "_" + gameid + "_" + openid)', @@ -44,6 +45,24 @@ CREATE TABLE `t_rookie_task_value` ( UNIQUE KEY `account_id_task` (`account_id`, `task_type`) ) ENGINE=InnoDB AUTO_INCREMENT=10000 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; +CREATE TABLE `t_hashrate_shop_buy_record` ( + `idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', + `account_id` varchar(60) NOT NULL DEFAULT '' COMMENT '账号id', + `goods_id` int(11) NOT NULL DEFAULT '0' COMMENT '商品id', + `item_id` int(11) NOT NULL DEFAULT '0' COMMENT '道具id', + `this_day_buy_times` int(11) NOT NULL DEFAULT '0' COMMENT '今日购买次数', + `this_week_buy_times` int(11) NOT NULL DEFAULT '0' COMMENT '本周购买次数', + `this_month_buy_times` int(11) NOT NULL DEFAULT '0' COMMENT '本月购买次数', + `total_buy_times` int(11) NOT NULL DEFAULT '0' COMMENT '总购买次数', + `last_buy_time` int(11) NOT NULL DEFAULT '0' COMMENT '最后一次购买时间', + `createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', + `modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间', + PRIMARY KEY (`idx`), + KEY `account_id` (`account_id`), + UNIQUE KEY `account_id_goods_id` (`account_id`, `goods_id`) +) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + + insert into version (version) values(2024092401); commit; diff --git a/webapp/controller/BaseController.class.php b/webapp/controller/BaseController.class.php index 387e07fd..1df3c724 100644 --- a/webapp/controller/BaseController.class.php +++ b/webapp/controller/BaseController.class.php @@ -88,6 +88,26 @@ class BaseController { return phpcommon\getMondaySeconds($time, $this->timeZone); } + public function _getMonthFirstDaySeconds() + { + return phpcommon\getThisMonthFirstDaySeconds($this->_getNowTime(), $this->timeZone); + } + + public function _getMonthFirstDaySecondsByTime($time) + { + return phpcommon\getThisMonthFirstDaySeconds($time, $this->timeZone); + } + + public function _getNextMonthFirstDaySeconds() + { + return phpcommon\getNextMonthFirstDaySeconds($this->_getNowTime(), $this->timeZone); + } + + public function _getNextMonthFirstDaySecondsByTime($time) + { + return phpcommon\getNextMonthFirstDaySeconds($time, $this->timeZone); + } + public function _inTimeRangeStr($beginTimeStr, $endTimeStr) { $beginTimeOffset = myself()->_getDaySecondsOffset(strtotime("2024-6-22 ". $beginTimeStr)); diff --git a/webapp/controller/HashRateShopController.class.php b/webapp/controller/HashRateShopController.class.php new file mode 100644 index 00000000..6376fd1c --- /dev/null +++ b/webapp/controller/HashRateShopController.class.php @@ -0,0 +1,121 @@ + _rspData( + array( + 'goods_list' => $goodsList, + ) + ); + } + + public function testBuyGoods() + { + if (SERVER_ENV != _ONLINE) { + $this->internalBuyGoods(); + } + } + + public function buyGoodsS() + { + $this->internalBuyGoods(); + } + + public function internalBuyGoods() + { + if (SERVER_ENV == _ONLINE) { + myself()->_verifySwitch('hashrate.shop.buy'); + } + $goodsId = getReqVal('goods_id', 0); + $goodsNum = intval(getReqVal('goods_num', 0)); + + if ($goodsNum < 1) { + myself()->_rspErr(1, "goods_num parameter error, goods_num: {$goodsNum}"); + return; + } + + $goodsMeta = mt\HashRateShop::find($goodsId); + if (!$goodsMeta) { + myself()->_rspErr(1, 'goods not found'); + return; + } + if ($goodsMeta['is_close']) { + myself()->_rspErr(1, 'no right to purchase'); + return; + } + $itemMeta = mt\Item::get($goodsMeta['type']); + if (!$itemMeta) { + myself()->_rspErr(1, 'goods not found, goods_id: ' . $goodsMeta['goods_id']); + return; + } + $errCode = 0; + $errMsg = ''; + if (!HashRateShopService::buyLimitCheck($goodsMeta, $goodsNum, $errCode, $errMsg)) { + myself()->_rspErr($errCode, $errMsg); + return; + } + $propertyChgService = new services\PropertyChgService(); + $awardService = new services\AwardService(); + $price = $goodsMeta['pile_price']; + if ($price < 1) { + myself()->_rspErr(1, "config error"); + return; + } + if ($price * $goodsNum > models\HashRate::getMyCurrentHashRate()) { + myself()->_rspErr(2, "hashrate not enough"); + return; + } + models\HashRate::decMyCurrentHashRate($price * $goodsNum); + error_log(models\HashRate::getMyCurrentHashRate()); + models\HashRateShopBuyRecord::add($goodsMeta['id'], $goodsNum, $goodsMeta['type']); + for ($i = 0; $i < $goodsNum; $i++) { + $this->internalAddItem($awardService, + $propertyChgService, + $itemMeta, + $goodsMeta['item_num'] + ); + } + $propertyChgService->addUserChg(); + $this->_rspData( + array( + 'award' => $awardService->toDto(), + 'property_chg' => $propertyChgService->toDto(), + ) + ); + } + + private function internalAddItem($awardService, + $propertyChgService, + $itemMeta, + $count + ) + { + myself()->_addItems( + array( + array( + 'item_id' => $itemMeta['id'], + 'item_num' => $count + ) + ), + $awardService, + $propertyChgService); + } + +} diff --git a/webapp/models/HashRate.php b/webapp/models/HashRate.php index 77255af3..1e22f6a0 100644 --- a/webapp/models/HashRate.php +++ b/webapp/models/HashRate.php @@ -109,6 +109,46 @@ class HashRate extends BaseModel return $myHashRate; } + public static function getMyCurrentHashRate(){ + $currentPeriod = myself()->_callMtStatic('AchievementsCycle', 'getCurrentPeriod'); + if (empty($currentPeriod)) { + return 0; + } + $row = SqlHelper::ormSelectOne( + myself()->_getSelfMysql(), + 't_hash_rate_reward', + array( + 'account_id' => myself()->_getAccountId(), + 'period' => $currentPeriod['id'], + ) + ); + $myHashRate = 0; + if ($row){ + $myHashRate = $row['reward']; + } + return $myHashRate; + } + + public static function decMyCurrentHashRate($val){ + $val = intval($val); + $currentPeriod = myself()->_callMtStatic('AchievementsCycle', 'getCurrentPeriod'); + if ($currentPeriod) { + SqlHelper::update( + myself()->_getSelfMysql(), + 't_hash_rate_reward', + array( + 'account_id' => myself()->_getAccountId(), + 'period' => $currentPeriod['id'], + ), + array( + 'reward' => function () use($val) { + return "GREATEST(0, reward - ${val})"; + }, + ) + ); + } + } + public static function getTotalByAccount($accountId,$period){ $row = SqlHelper::ormSelectOne( myself()->_getSelfMysql(), @@ -126,4 +166,4 @@ class HashRate extends BaseModel } -} \ No newline at end of file +} diff --git a/webapp/models/HashRateShopBuyRecord.php b/webapp/models/HashRateShopBuyRecord.php new file mode 100644 index 00000000..8acd33c0 --- /dev/null +++ b/webapp/models/HashRateShopBuyRecord.php @@ -0,0 +1,111 @@ +_getSelfMysql(), + 't_hashrate_shop_buy_record', + array( + 'account_id' => myself()->_getAccountId(), + 'goods_id' => $goodsId, + ) + ); + return $row; + } + + public static function all() + { + $rows = SqlHelper::ormSelect( + myself()->_getSelfMysql(), + 't_hashrate_shop_buy_record', + array( + 'account_id' => myself()->_getAccountId(), + ) + ); + return array_map(function ($row) { + $nowDaySeconds = myself()->_getNowDaySeconds(); + if (!($row['last_buy_time'] >= $nowDaySeconds && + $row['last_buy_time'] <= $nowDaySeconds + 3600 * 24)) { + $row['this_day_buy_times'] = 0; + } + $mondaySeconds = myself()->_getMondaySeconds(); + if (!($row['last_buy_time'] >= $mondaySeconds && + $row['last_buy_time'] <= $mondaySeconds + 3600 * 24 * 7)) { + $row['this_week_buy_times'] = 0; + } + $monthFirstDaySeconds = myself()->_getMonthFirstDaySeconds(); + $nextMonthFirstDaySeconds = myself()->_getNextMonthFirstDaySeconds(); + if (!($row['last_buy_time'] >= $monthFirstDaySeconds && + $row['last_buy_time'] <= $nextMonthFirstDaySeconds)) { + $row['this_month_buy_times'] = 0; + } + return $row; + }, $rows); + } + + public static function allToHash() + { + $rows = self::all(); + $buyRecordHash = array(); + array_walk($rows, function ($row) use (&$buyRecordHash) { + $buyRecordHash[$row['goods_id']] = $row; + }); + return $buyRecordHash; + } + + public static function add($goodsId, $goodsNum, $itemId) + { + $goodsNum = intval($goodsNum); + SqlHelper::upsert( + myself()->_getSelfMysql(), + 't_hashrate_shop_buy_record', + array( + 'account_id' => myself()->_getAccountId(), + 'goods_id' => $goodsId, + ), + array( + 'this_day_buy_times' => function () use($goodsNum) { + $nowDaySeconds = myself()->_getNowDaySeconds(); + $cond = " last_buy_time>=${nowDaySeconds} AND last_buy_time<=${nowDaySeconds} + 3600 * 24 "; + return "CASE WHEN (${cond}) THEN this_day_buy_times + ${goodsNum} ELSE 0 END"; + }, + 'this_week_buy_times' => function () use($goodsNum) { + $mondaySeconds = myself()->_getMondaySeconds(); + $cond = " last_buy_time>=${mondaySeconds} AND last_buy_time<=${mondaySeconds} + 3600 * 24 * 7 "; + return "CASE WHEN (${cond}) THEN this_week_buy_times + ${goodsNum} ELSE 0 END"; + }, + 'this_month_buy_times' => function () use($goodsNum) { + $monthFirstDaySeconds = myself()->_getMonthFirstDaySeconds(); + $cond = " last_buy_time>=${monthFirstDaySeconds} "; + return "CASE WHEN (${cond}) THEN this_month_buy_times + ${goodsNum} ELSE 0 END"; + }, + 'total_buy_times' => function () use($goodsNum) { + return "total_buy_times + ${goodsNum}"; + }, + 'last_buy_time' => myself()->_getNowTime(), + 'modifytime' => myself()->_getNowTime(), + ), + array( + 'account_id' => myself()->_getAccountId(), + 'goods_id' => $goodsId, + 'item_id' => $itemId, + 'this_day_buy_times' => $goodsNum, + 'this_week_buy_times' => $goodsNum, + 'this_month_buy_times' => $goodsNum, + 'total_buy_times' => $goodsNum, + 'last_buy_time' => myself()->_getNowTime(), + 'createtime' => myself()->_getNowTime(), + 'modifytime' => myself()->_getNowTime(), + ) + ); + } + +} diff --git a/webapp/mt/HashRateShop.php b/webapp/mt/HashRateShop.php new file mode 100644 index 00000000..6a58edba --- /dev/null +++ b/webapp/mt/HashRateShop.php @@ -0,0 +1,33 @@ + myself()->_getNowTime()) { + continue; + } + $goodsDto = array( + 'goods_id' => $goodsMeta['id'], + 'price' => $goodsMeta['pile_price'], + 'item_id' => $goodsMeta['type'], + 'item_num' => $goodsMeta['item_num'], + 'purchased_num' => 0, + 'max_num' => $goodsMeta['limit_num'], + 'count_down' => 0, + ); + switch ($goodsMeta['limit_type']) { + case mt\HashRateShop::DAILY_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $goodsMeta['id']); + $goodsDto['purchased_num'] = $buyRecord ? $buyRecord['this_day_buy_times'] : 0; + if ($buyRecord && $goodsDto['purchased_num'] > 0 && + $goodsDto['purchased_num'] >= $goodsDto['max_num']) { + $goodsDto['count_down'] = myself()->_getNowDaySeconds() + 3600 * 24 - myself()->_getNowTime(); + } + } + break; + case mt\HashRateShop::WEEKLY_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $goodsMeta['id']); + $goodsDto['purchased_num'] = $buyRecord ? $buyRecord['this_week_buy_times'] : 0; + if ($buyRecord && $goodsDto['purchased_num'] > 0 && + $goodsDto['purchased_num'] >= $goodsDto['max_num']) { + $goodsDto['count_down'] = myself()->_getMondaySeconds() + 3600 * 24 * 7 - myself()->_getNowTime(); + } + } + break; + case mt\HashRateShop::MONTH_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $goodsMeta['id']); + $goodsDto['purchased_num'] = $buyRecord ? $buyRecord['this_week_buy_times'] : 0; + } + break; + case mt\HashRateShop::TOTAL_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $goodsMeta['id']); + $goodsDto['purchased_num'] = $buyRecord ? $buyRecord['total_buy_times'] : 0; + } + break; + default: { + } + break; + } + array_push($goodsList, $goodsDto); + } + return $goodsList; + } + + public static function buyLimitCheck($goodsMeta, $goodsNum, &$errCode, &$errMsg) + { + if ($goodsMeta['is_close']) { + $errCode = 1; + $errMsg = 'cant buy'; + return; + } + if ($goodsMeta['first_time'] > myself()->_getNowTime()) { + $errCode = 1; + $errMsg = 'cant buy'; + return; + } + $errCode = 0; + $errMsg = ''; + $buyRecordHash = HashRateShopBuyRecord::allToHash(); + $boughtTimes = 1; + $goodsId = $goodsMeta['id']; + { + switch ($goodsMeta['limit_type']) { + case mt\HashRateShop::DAILY_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $goodsId); + $boughtTimes = $buyRecord ? $buyRecord['this_day_buy_times'] + $goodsNum : 1; + if ($buyRecord && getXVal($buyRecord, 'this_day_buy_times', 0) >= $goodsMeta['limit_num']) { + $errCode = 2; + $errMsg = 'Daily purchase limit'; + return false; + } + } + break; + case mt\HashRateShop::WEEKLY_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $goodsId); + $boughtTimes = $buyRecord ? $buyRecord['this_week_buy_times'] + $goodsNum : 1; + if ($buyRecord && getXVal($buyRecord, 'this_week_buy_times', 0) >= $goodsMeta['limit_num']) { + $errCode = 2; + $errMsg = 'Weekly purchase limit reached'; + return false; + } + } + break; + case mt\HashRateShop::MONTH_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $goodsId); + $boughtTimes = $buyRecord ? $buyRecord['this_month_buy_times'] + $goodsNum : 1; + if ($buyRecord && getXVal($buyRecord, 'this_month_buy_times', 0) >= $goodsMeta['limit_num']) { + $errCode = 2; + $errMsg = 'Month purchase limit reached'; + return false; + } + } + break; + case mt\HashRateShop::TOTAL_BUY_LIMIT: { + $buyRecord = getXVal($buyRecordHash, $goodsId); + $boughtTimes = $buyRecord ? $buyRecord['total_buy_times'] + $goodsNum : 1; + if ($buyRecord && getXVal($buyRecord, 'total_buy_times', 0) >= $goodsMeta['limit_num']) { + $errCode = 2; + $errMsg = 'Purchase limit reached'; + return false; + } + } + break; + default: { + } + break; + } + } + return true; + } + +}