将机器人的信息存入account表, 增加服务端获取机器人信息的接口
This commit is contained in:
parent
8dcac22067
commit
483af1973c
13
docs/api.md
13
docs/api.md
@ -666,15 +666,24 @@
|
||||
{
|
||||
nickname: '阿三', // 英雄id
|
||||
avatar: true, // 头像
|
||||
accountid: ''
|
||||
score: 1000
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 随机获取一个机器人信息
|
||||
1. Method: GET
|
||||
1. Method: POST
|
||||
2. URI: /svr/randomrobot
|
||||
|
||||
> POST参数
|
||||
|
||||
|
||||
| 字段 | 说明 |
|
||||
| -------- | -------------------------------------- |
|
||||
| min |最小天梯分 |
|
||||
| max |最高天梯分 |
|
||||
| accounts |需要过滤的accountid数组 |
|
||||
|
||||
|
||||
3. Response: JSON
|
||||
|
||||
@ -683,6 +692,8 @@
|
||||
{
|
||||
nickname: '阿三', // 英雄id
|
||||
avatar: true, // 头像
|
||||
accountid: ''
|
||||
score: 1000
|
||||
}
|
||||
```
|
||||
|
||||
|
5
package-lock.json
generated
5
package-lock.json
generated
@ -909,6 +909,11 @@
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.1.20",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.20.tgz",
|
||||
"integrity": "sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw=="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
|
@ -28,6 +28,7 @@
|
||||
"mime-types": "^2.1.28",
|
||||
"mongoose": "5.10.3",
|
||||
"mongoose-findorcreate": "^3.0.0",
|
||||
"nanoid": "^3.1.20",
|
||||
"redis": "^2.8.0",
|
||||
"tracer": "^1.1.4",
|
||||
"urlencode": "^1.1.0"
|
||||
|
@ -81,4 +81,20 @@ export class BaseConst {
|
||||
*/
|
||||
public static readonly ROBOT_INFO_SEP = '|||'
|
||||
|
||||
|
||||
public static readonly RANK_SCORE = 'rank_score'
|
||||
/**
|
||||
* 机器人帐号id前缀
|
||||
*/
|
||||
public static readonly ROBOT_PREFIX = '1000_3200_'
|
||||
/**
|
||||
* 机器人默认名
|
||||
*/
|
||||
public static readonly DEFAULT_ROBOT_NAME = '匿名玩家'
|
||||
/**
|
||||
* 机器人默认头像
|
||||
*/
|
||||
public static readonly DEFAULT_ROBOT_AVATAR = 'https://resource.kingsome.cn/matchvs_cdn/1.0.0.1/avatar/21_1.jpg'
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,64 +1,23 @@
|
||||
import BaseController from '../common/base.controller'
|
||||
import { role, router } from '../decorators/router'
|
||||
import { User } from '../models/User'
|
||||
import { ZError } from '../common/ZError'
|
||||
import { Card } from '../models/subdoc/Card'
|
||||
import { BaseConst } from '../constants/BaseConst'
|
||||
import { Hero } from '../models/subdoc/Hero'
|
||||
import { BagItem, ItemType } from '../models/BagItem'
|
||||
import { addHeroDefaultCardGroup } from '../dao/CardGroupDao'
|
||||
import { RedisClient } from '../redis/RedisClient'
|
||||
import { checkGameing, setGameing, usersByScore } from '../service/rank'
|
||||
import { fetchAccount } from '../dao/AccountDao'
|
||||
import { generateId } from '../utils/security.util'
|
||||
import { getRandom } from '../utils/number.util'
|
||||
|
||||
export default class AccountController extends BaseController {
|
||||
@role('anon')
|
||||
@router('post /api/:accountid/uinfo')
|
||||
async info(req: any) {
|
||||
let { accountid, nickname, avatar } = req.params
|
||||
let account = (await User.findOrCreate({ _id: accountid })).doc
|
||||
const account = await fetchAccount({accountid, nickname, avatar})
|
||||
account.isnew = 0
|
||||
await account.save()
|
||||
let result: any = { accountid: account.id }
|
||||
if (account.locked) {
|
||||
throw new ZError(4, 'account locked')
|
||||
}
|
||||
const formulaCfg = global.$cfg.get(BaseConst.FORMULA)
|
||||
if (account.season_score == -1) {
|
||||
account.season_score = formulaCfg.get(70003).number
|
||||
}
|
||||
if (nickname) {
|
||||
account.nickname = nickname
|
||||
}
|
||||
if (avatar) {
|
||||
account.avatar = avatar
|
||||
}
|
||||
let cardMap = account.cardMap
|
||||
for (let [, cfg] of global.$cfg.get(BaseConst.EFFECTCARD)) {
|
||||
if (cfg.org_gift == 1 && cfg.type_id == 1 && !cardMap.has(cfg.id + '')) {
|
||||
const card = new Card()
|
||||
card.cardid = cfg.id
|
||||
card.owned = true
|
||||
card.ban = false
|
||||
card.usetype = 0
|
||||
card.free = true
|
||||
card.free_expire = 0
|
||||
card.time = Date.now()
|
||||
cardMap.set(card.cardid + '', card)
|
||||
}
|
||||
}
|
||||
for (let [, cfg] of global.$cfg.get(BaseConst.HERO)) {
|
||||
if (cfg.org_gift == 1) {
|
||||
let hero = new Hero()
|
||||
hero.heroid = cfg.id
|
||||
hero.free = true
|
||||
hero.trial = false
|
||||
hero.level = 1
|
||||
hero.slot = 1
|
||||
hero.time = Date.now()
|
||||
hero.exp = 0
|
||||
if (!account.heros.has(cfg.id + '')) {
|
||||
account.heros.set(cfg.id + '', hero)
|
||||
await addHeroDefaultCardGroup(accountid, hero.heroid, cardMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
result.cards = [...account.cardMap.values()].map(o => o.toJson())
|
||||
let heros: any[] = []
|
||||
for (let [key, hero] of account.heros) {
|
||||
@ -66,7 +25,6 @@ export default class AccountController extends BaseController {
|
||||
}
|
||||
|
||||
result.heros = heros
|
||||
await account.save()
|
||||
const moneyList = await BagItem.find({accountid, itemtype: ItemType.MONEY})
|
||||
result.moneys = moneyList.map(o => o.toJson())
|
||||
result.normal_stat = account.normal_stat
|
||||
@ -80,6 +38,7 @@ export default class AccountController extends BaseController {
|
||||
async simpleInfo(req: any) {
|
||||
let account = req.user
|
||||
return {
|
||||
accountid: account._id,
|
||||
nickname: account.nickname,
|
||||
avatar: account.avatar,
|
||||
score: account.season_score
|
||||
@ -88,15 +47,46 @@ export default class AccountController extends BaseController {
|
||||
|
||||
@router('post /svr/randomrobot')
|
||||
async randomRobot(req: any) {
|
||||
let { min, max } = req.params
|
||||
// @ts-ignore
|
||||
let str: string = await new RedisClient().srandmember(BaseConst.ROBOT_INFO)
|
||||
let arr = ['default', 'https://resource.kingsome.cn/matchvs_cdn/1.0.0.1/avatar/21_1.jpg']
|
||||
if (str)
|
||||
arr = str.split(BaseConst.ROBOT_INFO_SEP)
|
||||
let { min, max, accounts } = req.params
|
||||
let accountSet = new Set(accounts)
|
||||
let datas: any = await usersByScore(min, max)
|
||||
let accountid, targetScore
|
||||
if (datas.length > 0) {
|
||||
for (let i = 0; i < datas.length; i += 2) {
|
||||
let gameing = await checkGameing(datas[i])
|
||||
if (gameing) {
|
||||
continue
|
||||
}
|
||||
if (!accountSet.has(datas[i]) ) {
|
||||
accountid = datas[i]
|
||||
targetScore = datas[i + 1] | 0
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!accountid) {
|
||||
accountid = BaseConst.ROBOT_PREFIX + generateId()
|
||||
targetScore = getRandom(min, max) | 0
|
||||
}
|
||||
let account = await fetchAccount({accountid, robot: true})
|
||||
if (account.isnew) {
|
||||
// @ts-ignore
|
||||
let str: string = await new RedisClient().srandmember(BaseConst.ROBOT_INFO)
|
||||
let arr = [BaseConst.DEFAULT_ROBOT_NAME, BaseConst.DEFAULT_ROBOT_AVATAR]
|
||||
if (str)
|
||||
arr = str.split(BaseConst.ROBOT_INFO_SEP)
|
||||
account.nickname = arr[0]
|
||||
account.avatar = arr[1]
|
||||
account.season_score = targetScore
|
||||
account.isnew = 0
|
||||
await account.save()
|
||||
}
|
||||
await setGameing(accountid)
|
||||
return {
|
||||
nickname: arr[0],
|
||||
avatar: arr[1]
|
||||
accounid: account._id,
|
||||
nickname: account.nickname,
|
||||
avatar: account.avatar,
|
||||
score: account.season_score
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import { MatchCfg } from '../cfg/parsers/MatchCfg'
|
||||
import ItemCtrl from '../logic/ItemCtrl'
|
||||
import { ItemInfo } from '../logic/ItemDef'
|
||||
import { BagItem } from '../models/BagItem'
|
||||
import { updateRank } from '../service/rank'
|
||||
|
||||
export default class RecordController extends BaseController {
|
||||
@role('anon')
|
||||
@ -56,7 +57,8 @@ export default class RecordController extends BaseController {
|
||||
continue
|
||||
}
|
||||
|
||||
user.season_score = Math.max(user.season_score + player.scoreChange, fc.get(70002).number)
|
||||
user.season_score = Math.max((user.season_score + player.scoreChange) | 0, fc.get(70002).number)
|
||||
await updateRank(user._id, user.season_score)
|
||||
if (!user.season_data) {
|
||||
user.season_data = new Map()
|
||||
}
|
||||
|
62
src/dao/AccountDao.ts
Normal file
62
src/dao/AccountDao.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { User } from '../models/User'
|
||||
import { ZError } from '../common/ZError'
|
||||
import { BaseConst } from '../constants/BaseConst'
|
||||
import { updateRank } from '../service/rank'
|
||||
import { Card } from '../models/subdoc/Card'
|
||||
import { Hero } from '../models/subdoc/Hero'
|
||||
import { addHeroDefaultCardGroup } from './CardGroupDao'
|
||||
|
||||
export async function fetchAccount({ accountid, nickname, avatar, robot = false }
|
||||
: { accountid: string, nickname?: string, avatar?: string, robot?: boolean }) {
|
||||
let account = (await User.findOrCreate({ _id: accountid })).doc
|
||||
if (account.locked) {
|
||||
throw new ZError(4, 'account locked')
|
||||
}
|
||||
const formulaCfg = global.$cfg.get(BaseConst.FORMULA)
|
||||
if (account.season_score == -1) {
|
||||
account.season_score = formulaCfg.get(70003).number
|
||||
await updateRank(accountid, account.season_score)
|
||||
}
|
||||
if (robot) {
|
||||
account.robot = 1
|
||||
}
|
||||
if (nickname) {
|
||||
account.nickname = nickname
|
||||
}
|
||||
if (avatar) {
|
||||
account.avatar = avatar
|
||||
}
|
||||
let cardMap = account.cardMap
|
||||
for (let [, cfg] of global.$cfg.get(BaseConst.EFFECTCARD)) {
|
||||
if (cfg.org_gift == 1 && cfg.type_id == 1 && !cardMap.has(cfg.id + '')) {
|
||||
const card = new Card()
|
||||
card.cardid = cfg.id
|
||||
card.owned = true
|
||||
card.ban = false
|
||||
card.usetype = 0
|
||||
card.free = true
|
||||
card.free_expire = 0
|
||||
card.time = Date.now()
|
||||
cardMap.set(card.cardid + '', card)
|
||||
}
|
||||
}
|
||||
for (let [, cfg] of global.$cfg.get(BaseConst.HERO)) {
|
||||
if (cfg.org_gift == 1) {
|
||||
let hero = new Hero()
|
||||
hero.heroid = cfg.id
|
||||
hero.free = true
|
||||
hero.trial = false
|
||||
hero.level = 1
|
||||
hero.slot = 1
|
||||
hero.time = Date.now()
|
||||
hero.exp = 0
|
||||
if (!account.heros.has(cfg.id + '')) {
|
||||
account.heros.set(cfg.id + '', hero)
|
||||
await addHeroDefaultCardGroup(accountid, hero.heroid, cardMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await account.save()
|
||||
return account
|
||||
}
|
@ -63,6 +63,9 @@ class UserClass extends FindOrCreate {
|
||||
|
||||
@prop({default: 0})
|
||||
public robot: number
|
||||
|
||||
@prop({default: 1})
|
||||
public isnew: number
|
||||
/**
|
||||
* 已获得卡牌信息
|
||||
*/
|
||||
|
@ -156,6 +156,20 @@ export class RedisClient {
|
||||
});
|
||||
}
|
||||
|
||||
public async zadd(key: string, value: any, member: string) {
|
||||
return new Promise((resolve) => {
|
||||
this.pub.zadd(key, value, member, resolve);
|
||||
});
|
||||
}
|
||||
public async zrangebyscore(key: string, min: number, max: number) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.pub.zrangebyscore(key, min, max, 'withscores', (err, data) => {
|
||||
if (err) { return reject(err); }
|
||||
resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public async hset(key: string, field: string, value: string) {
|
||||
return new Promise((resolve) => {
|
||||
this.pub.hset(key, field, value, resolve);
|
||||
|
@ -1,4 +1,22 @@
|
||||
import { RedisClient } from '../redis/RedisClient'
|
||||
import { BaseConst } from '../constants/BaseConst'
|
||||
|
||||
export function updateRank(accountid: string, score: number) {
|
||||
const MAX_TIME = 5000000000000
|
||||
|
||||
export async function updateRank(accountid: string, score: number) {
|
||||
let scoreL = parseFloat(`${score | 0}.${MAX_TIME - Date.now()}`)
|
||||
await new RedisClient().zadd(BaseConst.RANK_SCORE, scoreL, accountid)
|
||||
}
|
||||
|
||||
export async function usersByScore(min: number, max: number) {
|
||||
return await new RedisClient().zrangebyscore(BaseConst.RANK_SCORE, min, max)
|
||||
}
|
||||
|
||||
export async function setGameing(accountid: string) {
|
||||
await new RedisClient().setex('gameing_' + accountid, (Date.now() / 1000 | 0) + '', 30)
|
||||
}
|
||||
|
||||
export async function checkGameing(accountid: string) {
|
||||
return await new RedisClient().get('gameing_' + accountid)
|
||||
}
|
||||
|
||||
|
10
src/utils/number.util.ts
Normal file
10
src/utils/number.util.ts
Normal file
@ -0,0 +1,10 @@
|
||||
/**
|
||||
* 随机数
|
||||
* @param {number} max
|
||||
* @param {number} min
|
||||
* @return {number}
|
||||
*/
|
||||
export function getRandom(max: number, min: number): number {
|
||||
min = min || 0;
|
||||
return Math.floor(Math.random()*(max-min)+min);
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
|
||||
import crypto from 'crypto'
|
||||
import { nanoid } from 'nanoid'
|
||||
|
||||
// 生成签名字段
|
||||
// paramStr 为key1=val1&key2=val2, key1, key2按字母升序
|
||||
@ -8,3 +8,7 @@ export function createSign(secretKey: string, paramStr: string, timestamp: numbe
|
||||
paramStr = `${paramStr}:${timestamp}${secretKey}`;
|
||||
return crypto.createHash('md5').update(paramStr, 'utf8').digest('hex');
|
||||
}
|
||||
|
||||
export function generateId(length: number = 21) {
|
||||
return nanoid(length);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user