From 0e59a42078c4070ee16c89b960b3161a67be7b84 Mon Sep 17 00:00:00 2001 From: hujiabin <519660157@qq.com> Date: Fri, 13 Oct 2023 14:57:28 +0800 Subject: [PATCH] 1 --- server/game2006service/tasks/season.js | 410 +++++++++--------- sql/archived/gamedb2006_migrate_230920_01.sql | 38 +- webapp/controller/RestApiController.class.php | 219 +++++----- 3 files changed, 340 insertions(+), 327 deletions(-) diff --git a/server/game2006service/tasks/season.js b/server/game2006service/tasks/season.js index fd3592c9..e122c0d4 100644 --- a/server/game2006service/tasks/season.js +++ b/server/game2006service/tasks/season.js @@ -1,205 +1,205 @@ -const app = require('j7/app'); -const utils = require('j7/utils'); -const metaFactory = require('../metadata/factory'); -const FormulaService = require('../services/factory').create('FormulaService', null); -const constant = require('../constant'); - - -class Season { - seasonList = []; - async start() { - - while (true) { - await this.doRoutine(utils.getUtcTime()); - const nowTime = utils.getUtcTime(); - const daySeconds = utils.getDaySeconds(nowTime, constant.TIME_ZONE); - // const sleepTime = daySeconds + 3600 * 24 - nowTime; - let sleepTime = 120; - if (utils.isOnlineEnv()) { - sleepTime = daySeconds + 3600 * 25 - nowTime; - } - console.log('Season.sleepTime:' + sleepTime, new Date(), sleepTime / 60); - await utils.sleep(sleepTime*1000); - } - } - - async doRoutine(nowTime) { - try { - // console.time("season ranking"); - this.seasonList = []; - metaFactory.traverseMetaList("RankSeason", (config, idx) => { - this.seasonList.push({ - start_time: new Date(config.start_time+" GMT+0000").getTime()/1000, - end_time: new Date(config.end_time+" GMT+0000").getTime()/1000, - id: config.id - }); - return true; - }); - - // console.log("season ranking",this.seasonList); - if (this.checkSeasonEnd(nowTime)) { - // console.log("赛季空档期"); - await this.calcRanking(nowTime); - } - - // console.timeLog("season ranking"); - // console.timeEnd("season ranking"); - - console.log("season ranking end"); - } - catch(err) { - console.log(err); - } - } - - checkSeasonEnd(nowTime) { - let c = this.getCurSeasonId(nowTime); - if (!!c) { - return (nowTime>c.end_time); - } - return false; - } - - getCurSeasonId(nowTime) { - let s = this.seasonList[0]; - for( let c of this.seasonList) { - if (nowTime >= c.start_time) { - s = c; - } - } - return s; - } - - async calcRanking(nowTime) { - console.log("calc ranking..."); - - const {err, conn} = await app.getDbConn("GameDb20060"); - if (err) { - throw err; - } - if (!err && conn) { - // 检查是否本赛季已完成排名 - const seasonId = this.getCurSeasonId(nowTime).id; - if (!await this.alreadySorted(conn,seasonId)) { - // 从user表中遍历所有用户,每次取1000个用户,逐步加入到排序表中 - let sorted = []; - let lastIdx = 0; - while(lastIdx>=0) { - const result = await this.getRecords(conn, lastIdx, 1000); - lastIdx = result.lastIdx; - if (lastIdx != -1) { - this.insertNewRecords(sorted, result.records) - } - } - await this.pushRankingResult(conn, sorted, seasonId); - } - else { - console.log("already calc ranking, no need to calc"); - } - } - - console.log("calc ranking...done"); - } - - async alreadySorted(conn, seasonId) { - const {err, rows} = await conn.execQuery( - 'SELECT idx from t_season_ranking where season=? LIMIT 1', - [ - seasonId - ] - ); - if (err) { - throw err; - } - return rows.length>0; - } - - async getRecords(conn, lastIdx, limit) { - const {err, rows} = await conn.execQuery( - 'select idx,account_id,`address`,channel,`rank`,`score`,createtime, score_modifytime from t_user where idx > ? order by idx LIMIT ?', - [ - lastIdx, - limit - ] - ); - if (err) { - throw err; - } - if (rows.length==0) { - return { - lastIdx: -1, - records: [] - }; - } - - return { - lastIdx: rows[rows.length-1].idx, - records: rows - }; - } - - insertNewRecords(sorted, records) { - // 根据分数加入到排序表中,始终保留钱10000名 - - // console.time("inserNewRecords"); - for (let element of records) { - // if (element.score>=2800) { - sorted.push(element); - sorted.sort(function(a,b) { - let r = b.score - a.score; - if (r==0) { - r = a.score_modifytime - b.score_modifytime; - } - if (r==0) { - r = a.idx - b.idx; - } - return r; - }); - // } - } - // if (sorted.length>10000) { - // sorted.length = 10000; - // } - // console.timeLog("inserNewRecords"); - // console.timeEnd("inserNewRecords"); - } - - async pushRankingResult(conn, sorted, seasonId) { - // 计算排名并存入数据库 - // console.log(sorted); - const nowTime = utils.getUtcTime(); - - await utils.serial( - sorted, - async (element, index) => { - let ranking = index+1; - let TopX = FormulaService.celTopX(ranking); - let ponit = 0; - if (element['score'] >= 2800){ - ponit = FormulaService.celUserRankingPoint(ranking,TopX).toFixed(0); - } - await conn.insert( - 't_season_ranking', - [ - ['account_id', element['account_id']], - ['address', element['address']], - ['channel', element['channel']], - ['rank', element['rank']], - ['score', element['score']], - ['ranking', ranking], - ['season', seasonId], - ['ranking_point', ponit], - ['createtime', element.createtime], - ['modifytime', element.score_modifytime], - ] - ) - } - ); - } -} - -function init() { - (new Season()).start(); -} - -exports.init = init; +const app = require('j7/app'); +const utils = require('j7/utils'); +const metaFactory = require('../metadata/factory'); +const FormulaService = require('../services/factory').create('FormulaService', null); +const constant = require('../constant'); + + +class Season { + seasonList = []; + async start() { + + while (true) { + await this.doRoutine(utils.getUtcTime()); + const nowTime = utils.getUtcTime(); + const daySeconds = utils.getDaySeconds(nowTime, constant.TIME_ZONE); + // const sleepTime = daySeconds + 3600 * 24 - nowTime; + let sleepTime = 120; + if (utils.isOnlineEnv()) { + sleepTime = daySeconds + 3600 * 25 - nowTime; + } + console.log('Season.sleepTime:' + sleepTime, new Date(), sleepTime / 60); + await utils.sleep(sleepTime*1000); + } + } + + async doRoutine(nowTime) { + try { + // console.time("season ranking"); + this.seasonList = []; + metaFactory.traverseMetaList("RankSeason", (config, idx) => { + this.seasonList.push({ + start_time: new Date(config.start_time+" GMT+0000").getTime()/1000, + end_time: new Date(config.end_time+" GMT+0000").getTime()/1000, + id: config.id + }); + return true; + }); + + // console.log("season ranking",this.seasonList); + if (this.checkSeasonEnd(nowTime)) { + // console.log("赛季空档期"); + await this.calcRanking(nowTime); + } + + // console.timeLog("season ranking"); + // console.timeEnd("season ranking"); + + console.log("season ranking end"); + } + catch(err) { + console.log(err); + } + } + + checkSeasonEnd(nowTime) { + let c = this.getCurSeasonId(nowTime); + if (!!c) { + return (nowTime>c.end_time); + } + return false; + } + + getCurSeasonId(nowTime) { + let s = this.seasonList[0]; + for( let c of this.seasonList) { + if (nowTime >= c.start_time) { + s = c; + } + } + return s; + } + + async calcRanking(nowTime) { + console.log("calc ranking..."); + + const {err, conn} = await app.getDbConn("GameDb20060"); + if (err) { + throw err; + } + if (!err && conn) { + // 检查是否本赛季已完成排名 + const seasonId = this.getCurSeasonId(nowTime).id; + if (!await this.alreadySorted(conn,seasonId)) { + // 从user表中遍历所有用户,每次取1000个用户,逐步加入到排序表中 + let sorted = []; + let lastIdx = 0; + while(lastIdx>=0) { + const result = await this.getRecords(conn, lastIdx, 1000); + lastIdx = result.lastIdx; + if (lastIdx != -1) { + this.insertNewRecords(sorted, result.records) + } + } + await this.pushRankingResult(conn, sorted, seasonId); + } + else { + console.log("already calc ranking, no need to calc"); + } + } + + console.log("calc ranking...done"); + } + + async alreadySorted(conn, seasonId) { + const {err, rows} = await conn.execQuery( + 'SELECT idx from t_season_ranking where season=? LIMIT 1', + [ + seasonId + ] + ); + if (err) { + throw err; + } + return rows.length>0; + } + + async getRecords(conn, lastIdx, limit) { + const {err, rows} = await conn.execQuery( + 'select idx,account_id,`address`,channel,`rank`,`score`,createtime, score_modifytime from t_user where idx > ? order by idx LIMIT ?', + [ + lastIdx, + limit + ] + ); + if (err) { + throw err; + } + if (rows.length==0) { + return { + lastIdx: -1, + records: [] + }; + } + + return { + lastIdx: rows[rows.length-1].idx, + records: rows + }; + } + + insertNewRecords(sorted, records) { + // 根据分数加入到排序表中,始终保留钱10000名 + + // console.time("inserNewRecords"); + for (let element of records) { + // if (element.score>=2800) { + sorted.push(element); + sorted.sort(function(a,b) { + let r = b.score - a.score; + if (r==0) { + r = a.score_modifytime - b.score_modifytime; + } + if (r==0) { + r = a.idx - b.idx; + } + return r; + }); + // } + } + // if (sorted.length>10000) { + // sorted.length = 10000; + // } + // console.timeLog("inserNewRecords"); + // console.timeEnd("inserNewRecords"); + } + + async pushRankingResult(conn, sorted, seasonId) { + // 计算排名并存入数据库 + // console.log(sorted); + const nowTime = utils.getUtcTime(); + + await utils.serial( + sorted, + async (element, index) => { + let ranking = index+1; + let TopX = FormulaService.celTopX(ranking); + let ponit = 0; + if (element['score'] >= 2800){ + ponit = FormulaService.celUserRankingPoint(ranking,TopX).toFixed(0); + } + await conn.insert( + 't_season_ranking', + [ + ['account_id', element['account_id']], + ['address', element['address']], + ['channel', element['channel']], + ['rank', element['rank']], + ['score', element['score']], + ['ranking', ranking], + ['season', seasonId], + ['ranking_point', ponit], + ['createtime', nowTime], + ['modifytime', nowTime], + ] + ) + } + ); + } +} + +function init() { + (new Season()).start(); +} + +exports.init = init; diff --git a/sql/archived/gamedb2006_migrate_230920_01.sql b/sql/archived/gamedb2006_migrate_230920_01.sql index bbd3f238..40eb437b 100644 --- a/sql/archived/gamedb2006_migrate_230920_01.sql +++ b/sql/archived/gamedb2006_migrate_230920_01.sql @@ -1,19 +1,19 @@ -begin; - -CREATE TABLE `t_avatar` ( - `idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', - `account_id` varchar(60) NOT NULL DEFAULT '' COMMENT '账号id(channel + "_" + gameid + "_" + openid)', - `token_id` varchar(60) COMMENT 'token_id', - `item_id` int(11) NOT NULL COMMENT 'item_id', - `item_type` int(11) NOT NULL COMMENT 'item类型', - `status` int(11) NOT NULL DEFAULT '0' COMMENT '装备状态', - `hero_idx` bigint DEFAULT NULL COMMENT '英雄外键id', - `createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', - `modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间', - PRIMARY KEY (`idx`), - UNIQUE KEY `hero_idx_type` (`hero_idx`, `item_type`) -) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; - -insert into version (version) values(2023092001); - -commit; +begin; + +CREATE TABLE `t_avatar` ( + `idx` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id', + `account_id` varchar(60) NOT NULL DEFAULT '' COMMENT '账号id(channel + "_" + gameid + "_" + openid)', + `token_id` varchar(60) COMMENT 'token_id', + `item_id` int(11) NOT NULL COMMENT 'item_id', + `item_type` int(11) NOT NULL COMMENT 'item类型', + `status` int(11) NOT NULL DEFAULT '0' COMMENT '装备状态', + `hero_idx` bigint DEFAULT NULL COMMENT '英雄外键id', + `createtime` int(11) NOT NULL DEFAULT '0' COMMENT '创建时间', + `modifytime` int(11) NOT NULL DEFAULT '0' COMMENT '修改时间', + PRIMARY KEY (`idx`), + UNIQUE KEY `hero_idx_type` (`hero_idx`, `item_type`) +) ENGINE=InnoDB AUTO_INCREMENT=10001 DEFAULT CHARSET=utf8 COLLATE=utf8_bin; + +insert into version (version) values(2023092001); + +commit; diff --git a/webapp/controller/RestApiController.class.php b/webapp/controller/RestApiController.class.php index 94c948d8..12e35c67 100644 --- a/webapp/controller/RestApiController.class.php +++ b/webapp/controller/RestApiController.class.php @@ -1,103 +1,116 @@ - 0 ? $tmpStrs[0] : ''; - $this->nftInfo(explode('/', $requestUri)); - } - } - } - - /* - https://game2006api.cebggame.com/api/nft/$netId/$nftType/$tokenId - $netId: 链id(网络id) - $nftType: 目前就hero - $tokenId:tokenid - */ - private function nftInfo($path) - { - if (count($path) < 5) { - return; - } - $netId = $path[3]; - $nftType = $path[4]; - $tokenId = $path[5]; - $heroDb = Hero::findByTokenId2($tokenId); - - if (!$heroDb){ - echo json_encode(array( - "name" => "", - "description" => "", - "image" => "", - "attributes" => array(), - )); - die; - } - $heroMeta = \mt\Hero::get($heroDb['hero_id']); - $NftMeta = \mt\NftDesc::getByItemId($heroDb['hero_id']); -//https://www.cebg.games/res/nfts/30100.png - $info = array( - "name" => $heroMeta['name'], - "description" => $NftMeta['desc'], - "image" => "https://www.cebg.games/res/nfts/".$heroDb['hero_id'].".png", - "attributes" => array(), - ); - array_push($info['attributes'],array( - "trait_type" => "level", - "value" => intval($heroDb['hero_lv']), - "max_value" => 15, - )); - $randAttr = emptyReplace(json_decode($heroDb['rand_attr'], true), array()); - foreach ($randAttr as $attr){ - switch ($attr['quality']){ - case 1 : $quality = "D";break; - case 2 : $quality = "C";break; - case 3 : $quality = "B";break; - case 4 : $quality = "A";break; - case 5 : $quality = "S";break; - default : $quality = ""; - } - switch ($attr['attr_id']){ - case kHAT_Hp : { - array_push($info['attributes'],array( - "trait_type" => "Hp", -// "value" => intval($attr['val']), - "value" => $quality, - )); - } - break; - case kHAT_Atk : { - array_push($info['attributes'],array( - "trait_type" => "Atk", -// "value" => intval($attr['val']), - "value" => $quality, - )); - } - break; - case kHAT_Def : { - array_push($info['attributes'],array( - "trait_type" => "Def", -// "value" => intval($attr['val']), - "value" => $quality, - )); - } - } - } - echo json_encode($info); - } - -} + 0 ? $tmpStrs[0] : ''; + $this->nftInfo(explode('/', $requestUri)); + } + } + } + + /* + https://game2006api.cebggame.com/api/nft/$netId/$nftType/$tokenId + $netId: 链id(网络id) + $nftType: 目前就hero,planet + $tokenId:tokenid + */ + private function nftInfo($path) + { + if (count($path) < 5) { + return; + } + $netId = $path[3]; + $nftType = $path[4]; + $tokenId = $path[5]; + $info = array( + "name" => "", + "description" => "", + "image" => "", + "attributes" => array(), + ); + switch ($nftType){ + case "hero" :{ + $heroDb = Hero::findByTokenId2($tokenId); + if (!$heroDb){ + echo json_encode($info); + die; + } + $heroMeta = \mt\Hero::get($heroDb['hero_id']); + $NftMeta = \mt\NftDesc::getByItemId($heroDb['hero_id']); +//https://www.cebg.games/res/nfts/30100.png + $info['name'] = $heroMeta['name']; + $info['description'] = $NftMeta['desc']; + $info['image'] = "https://www.cebg.games/res/nfts/".$heroDb['hero_id'].".png"; + array_push($info['attributes'],array( + "trait_type" => "level", + "value" => intval($heroDb['hero_lv']), + "max_value" => 15, + )); + $randAttr = emptyReplace(json_decode($heroDb['rand_attr'], true), array()); + foreach ($randAttr as $attr){ + switch ($attr['quality']){ + case 1 : $quality = "D";break; + case 2 : $quality = "C";break; + case 3 : $quality = "B";break; + case 4 : $quality = "A";break; + case 5 : $quality = "S";break; + default : $quality = ""; + } + switch ($attr['attr_id']){ + case kHAT_Hp : { + array_push($info['attributes'],array( + "trait_type" => "Hp", + "value" => $quality, + )); + } + break; + case kHAT_Atk : { + array_push($info['attributes'],array( + "trait_type" => "Atk", + "value" => $quality, + )); + } + break; + case kHAT_Def : { + array_push($info['attributes'],array( + "trait_type" => "Def", + "value" => $quality, + )); + } + } + } + } + break; + case "planet" : { + $planetDb = Nft::getNft($tokenId); + if (!$planetDb){ + echo json_encode($info); + die; + } + $NftMeta = \mt\NftDesc::getByItemId($planetDb['item_id']); + $info['name'] = $NftMeta['name'] ? : "planet"; + $info['description'] = $NftMeta['desc'] ? : "planet"; + $info['image'] = "https://www.cebg.games/res/nfts/".$planetDb['item_id'].".png"; + } + } + + echo json_encode($info); + } + +}