From c4c3ba8ac11d049aefe1d8ee9afef716a81d30b2 Mon Sep 17 00:00:00 2001 From: zhl Date: Fri, 8 Jan 2021 11:34:44 +0800 Subject: [PATCH] finish unlock hero --- docs/api.md | 23 ++++- src/controllers/AccountController.ts | 71 +------------ src/controllers/HeroController.ts | 70 +++++++++++++ src/models/Account.ts | 91 ----------------- src/models/User.ts | 146 +++++++++++++++++++++++++++ src/plugins/apiauth.ts | 4 +- 6 files changed, 241 insertions(+), 164 deletions(-) create mode 100644 src/controllers/HeroController.ts delete mode 100644 src/models/Account.ts create mode 100644 src/models/User.ts diff --git a/docs/api.md b/docs/api.md index de69f12..adfd86a 100644 --- a/docs/api.md +++ b/docs/api.md @@ -244,8 +244,7 @@ | 字段 | 说明 | | -------- | -------------------------------------- | -| moneyid |代币的item id | -| count |试用数量 | +| count |使用数量 | 3. Response: JSON @@ -258,7 +257,25 @@ ``` ### 11. 将专属英雄碎片转化成经验 +1. Method: POST +2. URI: /api/:accountid/hero/toexp/:heroid +| 字段 | 说明 | +| -------- | -------------------------------------- | +| accountid | 帐号id | +| heroid | 英雄id | + + + +3. Response: JSON + +```json +{ + exp: 1022, // 当前经验值 + exp_POST: 100, // 本次获得的经验 + level: 1 // 当前等级 +} +``` ## 三. 服务端接口列表 @@ -277,3 +294,5 @@ ``` + +``` \ No newline at end of file diff --git a/src/controllers/AccountController.ts b/src/controllers/AccountController.ts index 7be4d06..a3da3d1 100644 --- a/src/controllers/AccountController.ts +++ b/src/controllers/AccountController.ts @@ -1,18 +1,15 @@ import BaseController from "../common/base.controller"; import {role, router} from "../decorators/router"; -import {Account} from "../models/Account"; +import {User} from "../models/User"; import {ZError} from "../common/ZError"; -import {Hero} from "../models/subdoc/Hero"; import {Card} from "../models/subdoc/Card"; -import {CardGroup} from "../models/CardGroup"; -import {MoneyTypeConst} from "../constants/MoneyTypeConst"; export default class AccountController extends BaseController { @role('anon') @router('post /api/:accountid/uinfo') async info(req: any) { let {accountid} = req.params; - let account = (await Account.findOrCreate({_id: accountid})).doc; + let account = (await User.findOrCreate({_id: accountid})).doc; let result: any = {accountid: account.id}; if (account.locked) { throw new ZError(4, 'account locked'); @@ -63,69 +60,5 @@ export default class AccountController extends BaseController { return result; } - @router('post /api/:accountid/heros') - async herolist(req: any) { - let account = req.user; - let heros: any[] = []; - for(let [key, hero] of account.heros) { - heros.push({ - heroid: hero.heroid, - owned: true, - usetype: 0, - level: hero.level, - exp: hero.exp, - free: hero.free, - free_expire: 0 - }); - } - //TODO:: 添加限免英雄和免费英雄 - return heros; - } - - @router('post /api/:accountid/hero/unlock/:heroid') - async unlockHero(req: any) { - let account = req.user; - let {heroid, type} = req.params; - if (!heroid) { - throw new ZError(101, '未指定heroid'); - } - if (account.heros.has(heroid + '')) { - if (!account.heros.get(heroid + '').free) { - throw new ZError(102, '你已经解锁了该英雄'); - } - } - let money0 = MoneyTypeConst.getHeroShard(heroid); - let money1 = MoneyTypeConst.HERO_SHARD; - let count0 = account.moneys.has(money0) ? account.moneys.get(money0) : 0; - let count1 = account.moneys.has(money1) ? account.moneys.get(money1) : 0; - // TODO:: 根据配置获取解锁英雄需要的碎片数量 - let needCount = 30; - if (count0 + count1 < needCount) { - throw new ZError(102, '碎片数量不足'); - } - if (count0 > 0) { - let rest = needCount - count0; - if (rest >= 0) { - needCount = rest; - account.moneys.set(money0, 0); - } else { - needCount = 0; - account.moneys.set(money0, Math.abs(rest)); - } - } - // 上面已经过滤了 count0 + count1 > needcount, 所以这里不需要判断碎片是否足够 - if (needCount > 0) { - count1 = count1 - needCount; - account.moneys.set(money1, count1); - } - let hero = new Hero(); - hero.heroid = heroid; - hero.free = false; - hero.level = 1; - hero.exp = 0; - account.heros.set(heroid + '', hero); - return {}; - } - } diff --git a/src/controllers/HeroController.ts b/src/controllers/HeroController.ts new file mode 100644 index 0000000..98fe13c --- /dev/null +++ b/src/controllers/HeroController.ts @@ -0,0 +1,70 @@ +import BaseController from "../common/base.controller"; +import {router} from "../decorators/router"; +import {ZError} from "../common/ZError"; +import {MoneyTypeConst} from "../constants/MoneyTypeConst"; +import {Hero} from "../models/subdoc/Hero"; +import {User} from "../models/User"; + +export default class HeroController extends BaseController { + @router('post /api/:accountid/heros') + async herolist(req: any) { + let account = req.user; + let heros: any[] = []; + for(let [key, hero] of account.heros) { + heros.push({ + heroid: hero.heroid, + owned: true, + usetype: 0, + level: hero.level, + exp: hero.exp, + free: hero.free, + free_expire: 0 + }); + } + //TODO:: 添加限免英雄和免费英雄 + return heros; + } + + @router('post /api/:accountid/hero/unlock/:heroid') + async unlockHero(req: any) { + let account = req.user; + let {heroid, type} = req.params; + if (!heroid) { + throw new ZError(101, '未指定heroid'); + } + try { + if (!type) { + let hero = await account.unlockHero(heroid); + await account.save(); + return hero; + } else { + let hero = await account.tryHero(heroid); + await account.save(); + return hero; + } + } catch (err) { + throw err; + } + + + } + + @router('post /api/:accountid/hero/update/:heroid') + async updateHero(req: any) { + let account = req.user; + let {heroid, count} = req.params; + if (!heroid) { + throw new ZError(101, '未指定heroid'); + } + if (!account.heros.has(heroid + '')) { + throw new ZError(102, '你未解锁该英雄'); + } + } + + @router('post /api/:accountid/hero/toexp/:heroid') + async shardToExp(req: any) { + let account = req.user; + let {heroid} = req.params; + + } +} diff --git a/src/models/Account.ts b/src/models/Account.ts deleted file mode 100644 index 35e2a46..0000000 --- a/src/models/Account.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { - prop, - getModelForClass, - modelOptions, - index, - plugin, - mongoose -} from '@typegoose/typegoose'; -import {dbconn} from '../decorators/dbconn'; -// @ts-ignore -import findOrCreate from 'mongoose-findorcreate'; -import { - Base, - FindOrCreate, - TimeStamps -} from "@typegoose/typegoose/lib/defaultClasses"; -import {Card} from "./subdoc/Card"; -import {Hero} from "./subdoc/Hero"; - -interface AccountClass extends Base, TimeStamps {} -@dbconn() -// @index({ _id: 1}, { unique: true }) -@plugin(findOrCreate) -@modelOptions({schemaOptions: - {collection: "account", timestamps: true} -}) -class AccountClass extends FindOrCreate{ - @prop() - public _id: string; - - @prop({default: false}) - public locked: boolean; - @prop() - public lockedtime?: number; - - @prop() - public comment?: string; - @prop() - public lastLogin?: Date; - /** - * 已获得卡牌信息 - */ - @prop({ type: () => [Number] }) - public cards: number[]; - /** - * 已解锁英雄信息 - */ - @prop({ type: Hero, default: new Map() }) - public heros: Map; - /** - * 货币信息 - * coin: 金币 - * diamond: 钻石 - * hero_shard: 通用英雄碎片 - * hero_exp: 通用英雄经验 - * hero_shard_heroid: 英雄专用碎片 - * hero_exp_heroid: 英雄专用经验 - * card_scroll: 抽卡卷轴 - */ - @prop({ type: Number, default: new Map() }) - public moneys: Map; - - - /** - * 匹配: 胜利场数, 失败场数, 平局场数, 掉线场数 - */ - @prop({type: Number, default: [0,0,0,0]}) - public normal_stat: number[]; - /** - * 当前赛季: 胜利场数, 失败场数, 平局场数, 掉线场数 - */ - @prop({type: Number, default: [0,0,0,0]}) - public season_stat: number[]; - - /** - * 所有未定义的信息, 供扩展 - */ - @prop({type: mongoose.Schema.Types.Mixed}) - public extinfo: any; - - public toJson() { - return { - accountid: this._id, - } - } -} - - -export const Account = getModelForClass(AccountClass, -// @ts-ignore - {existingConnection: AccountClass['db']}); diff --git a/src/models/User.ts b/src/models/User.ts new file mode 100644 index 0000000..8fbdf9e --- /dev/null +++ b/src/models/User.ts @@ -0,0 +1,146 @@ +import { + prop, + getModelForClass, + modelOptions, + index, + plugin, + mongoose +} from '@typegoose/typegoose'; +import {dbconn} from '../decorators/dbconn'; +// @ts-ignore +import findOrCreate from 'mongoose-findorcreate'; +import { + Base, + FindOrCreate, + TimeStamps +} from "@typegoose/typegoose/lib/defaultClasses"; +import {Card} from "./subdoc/Card"; +import {Hero} from "./subdoc/Hero"; +import {ZError} from "../common/ZError"; +import {MoneyTypeConst} from "../constants/MoneyTypeConst"; + +interface AccountClass extends Base, TimeStamps {} +@dbconn() +// @index({ _id: 1}, { unique: true }) +@plugin(findOrCreate) +@modelOptions({schemaOptions: + {collection: "account", timestamps: true} +}) +class UserClass extends FindOrCreate{ + @prop() + public _id: string; + + @prop({default: false}) + public locked: boolean; + @prop() + public lockedtime?: number; + + @prop() + public comment?: string; + @prop() + public lastLogin?: Date; + /** + * 已获得卡牌信息 + */ + @prop({ type: () => [Number] }) + public cards: number[]; + /** + * 已解锁英雄信息 + */ + @prop({ type: Hero, default: new Map() }) + public heros: Map; + /** + * 货币信息 + * coin: 金币 + * diamond: 钻石 + * hero_shard: 通用英雄碎片 + * hero_exp: 通用英雄经验 + * hero_shard_heroid: 英雄专用碎片 + * hero_exp_heroid: 英雄专用经验 + * card_scroll: 抽卡卷轴 + */ + @prop({ type: Number, default: new Map() }) + public moneys: Map; + + + /** + * 匹配: 胜利场数, 失败场数, 平局场数, 掉线场数 + */ + @prop({type: Number, default: [0,0,0,0]}) + public normal_stat: number[]; + /** + * 当前赛季: 胜利场数, 失败场数, 平局场数, 掉线场数 + */ + @prop({type: Number, default: [0,0,0,0]}) + public season_stat: number[]; + + /** + * 所有未定义的信息, 供扩展 + */ + @prop({type: mongoose.Schema.Types.Mixed}) + public extinfo: any; + + public toJson() { + return { + accountid: this._id, + } + } + + public async unlockHero(heroid: number) { + if (this.heros.has(heroid + '')) { + if (!this.heros.get(heroid + '').free) { + throw new ZError(102, '你已经解锁了该英雄'); + } + } + let money0 = MoneyTypeConst.getHeroShard(heroid); + let money1 = MoneyTypeConst.HERO_SHARD; + let count0 = this.moneys.has(money0) ? this.moneys.get(money0) : 0; + let count1 = this.moneys.has(money1) ? this.moneys.get(money1) : 0; + // TODO:: 根据配置获取解锁英雄需要的碎片数量 + let needCount = 30; + if (count0 + count1 < needCount) { + throw new ZError(102, '碎片数量不足'); + } + if (count0 > 0) { + let rest = needCount - count0; + if (rest >= 0) { + needCount = rest; + this.moneys.set(money0, 0); + } else { + needCount = 0; + this.moneys.set(money0, Math.abs(rest)); + } + } + // 上面已经过滤了 count0 + count1 > needcount, 所以这里不需要判断碎片是否足够 + if (needCount > 0) { + count1 = count1 - needCount; + this.moneys.set(money1, count1); + } + let hero = new Hero(); + hero.heroid = heroid; + hero.free = false; + hero.level = 1; + hero.exp = 0; + this.heros.set(heroid + '', hero); + return hero; + } + + public async tryHero(heroid: number) { + if (this.heros.has(heroid + '')) { + throw new ZError(102, '你已经解锁了该英雄'); + } + //TODO:: 根据配置查看该英雄是否可使用 + let hero = new Hero(); + hero.heroid = heroid; + hero.free = true; + hero.level = 1; + hero.exp = 0; + this.heros.set(heroid+'', hero); + return hero; + } +} + + +export const User = getModelForClass(UserClass, +// @ts-ignore + {existingConnection: UserClass['db']}); diff --git a/src/plugins/apiauth.ts b/src/plugins/apiauth.ts index 515f57e..79fc9fc 100644 --- a/src/plugins/apiauth.ts +++ b/src/plugins/apiauth.ts @@ -4,7 +4,7 @@ import { FastifyRequest, } from 'fastify'; import fastifyPlugin from 'fastify-plugin'; -import {Account} from '../models/Account'; +import {User} from '../models/User'; import {ZError} from "../common/ZError"; declare module 'fastify' { @@ -41,7 +41,7 @@ const apiAuthPlugin: FastifyPluginAsync = async function( // if (!data || !data.id) { // return reply.send({code: 10, msg: 'need login'}); // } - let account = await Account.findById(accountid); + let account = await User.findById(accountid); if (!account) { return reply.send({code: 5, msg: 'account not found'}); }