添加抽卡的方法
This commit is contained in:
parent
c6714648d4
commit
9394e0def8
@ -19,6 +19,7 @@ const fs = require('fs');
|
||||
const join = require('path').join;
|
||||
|
||||
let config: Config = require('../config/config.json');
|
||||
require('./common/Extend');
|
||||
|
||||
export class ApiServer {
|
||||
server: FastifyInstance<Server, IncomingMessage, ServerResponse>;
|
||||
|
863
src/common/Extend.ts
Normal file
863
src/common/Extend.ts
Normal file
@ -0,0 +1,863 @@
|
||||
|
||||
/**
|
||||
* 对数字进行补0操作
|
||||
* @param value 要补0的数值
|
||||
* @param length 要补的总长度
|
||||
* @return 补0之后的字符串
|
||||
*/
|
||||
function zeroize(value: number | string, length: number = 2): string {
|
||||
let str = "" + value;
|
||||
let zeros = "";
|
||||
for (let i = 0, len = length - str.length; i < len; i++) {
|
||||
zeros += "0";
|
||||
}
|
||||
return zeros + str;
|
||||
}
|
||||
|
||||
/****************************************扩展Object****************************************/
|
||||
interface Object {
|
||||
/**
|
||||
* 返回一个浅副本的对象
|
||||
* 此对象会拷贝key value
|
||||
*
|
||||
* @memberOf Object
|
||||
*/
|
||||
clone?(): Object;
|
||||
/**
|
||||
* 将数据拷贝到 to
|
||||
* @param to 目标
|
||||
*/
|
||||
copyto?(to: Object):void;
|
||||
/**
|
||||
* 获取指定属性的描述,会查找当前数据和原型数据
|
||||
* @param property 指定的属性名字
|
||||
*/
|
||||
getPropertyDescriptor?(property: string): PropertyDescriptor;
|
||||
|
||||
|
||||
zssign?(target: any): any;
|
||||
}
|
||||
|
||||
Object.defineProperties(Object.prototype, {
|
||||
clone: {
|
||||
value: function () {
|
||||
let o = {};
|
||||
for (let n in this) {
|
||||
// @ts-ignore
|
||||
o[n] = this[n];
|
||||
}
|
||||
return o;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
getPropertyDescriptor: {
|
||||
value: function (property: string): any {
|
||||
let data = Object.getOwnPropertyDescriptor(this, property);
|
||||
if (data) {
|
||||
return data;
|
||||
}
|
||||
let prototype = Object.getPrototypeOf(this);
|
||||
if (prototype) {
|
||||
return prototype.getPropertyDescriptor(property);
|
||||
}
|
||||
return;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
copyto: {
|
||||
value: function (to: Object) {
|
||||
for (let p in this) {
|
||||
if (!(p in to)) { // 本身没有这个属性
|
||||
// @ts-ignore
|
||||
to[p] = this[p];
|
||||
} else {
|
||||
let data: PropertyDescriptor = to.getPropertyDescriptor(p);
|
||||
if (data) {
|
||||
if (data.set || data.writable) {// 可进行赋值
|
||||
// @ts-ignore
|
||||
to[p] = this[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
zssign: {
|
||||
value: function (target: Object) {
|
||||
if (target === undefined || target === null) {
|
||||
throw new TypeError('Cannot convert undefined or null to object');
|
||||
}
|
||||
|
||||
let output = Object(target);
|
||||
for (let nextKey in this) {
|
||||
if (!(nextKey in output)) { // 本身没有这个属性
|
||||
output[nextKey] = this[nextKey];
|
||||
}
|
||||
// else {
|
||||
// let data: PropertyDescriptor = output.getPropertyDescriptor(nextKey);
|
||||
// if (data) {
|
||||
// if (data.set || data.writable) {// 可进行赋值
|
||||
// output[nextKey] = this[nextKey];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
return output;
|
||||
},
|
||||
writable: true
|
||||
}
|
||||
});
|
||||
|
||||
/****************************************扩展Math****************************************/
|
||||
interface Math {
|
||||
/**
|
||||
* 让数值处于指定的最大值和最小值之间,低于最小值取最小值,高于最大值取最大值
|
||||
* @param value 要处理的数值
|
||||
* @param min 最小值
|
||||
* @param max 最大值
|
||||
*/
|
||||
clamp?(value: number, min: number, max: number): number;
|
||||
|
||||
/**
|
||||
* 从最小值到最大值之间随机[min,max)
|
||||
*/
|
||||
random2?(min: number, max: number): number;
|
||||
/**
|
||||
* 角度转弧度的乘数
|
||||
* Math.PI / 180
|
||||
* @type {number}
|
||||
* @memberOf Math
|
||||
*/
|
||||
DEG_TO_RAD: number;
|
||||
/**
|
||||
* 弧度转角度的乘数
|
||||
* 180 / Math.PI
|
||||
*/
|
||||
RAD_TO_DEG: number;
|
||||
/**
|
||||
* 整圆的弧度
|
||||
*/
|
||||
PI2: number;
|
||||
/**
|
||||
* 90°的弧度
|
||||
*
|
||||
* @type {number}
|
||||
* @memberOf Math
|
||||
*/
|
||||
PI_1_2: number;
|
||||
}
|
||||
|
||||
Math.DEG_TO_RAD = Math.PI / 180;
|
||||
|
||||
Math.RAD_TO_DEG = 180 / Math.PI;
|
||||
|
||||
Math.PI2 = 2 * Math.PI;
|
||||
|
||||
Math.PI_1_2 = Math.PI * .5;
|
||||
|
||||
Math.clamp = (value, min, max) => {
|
||||
if (value < min) {
|
||||
value = min;
|
||||
}
|
||||
if (value > max) {
|
||||
value = max;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Math.random2 = (min, max) => {
|
||||
return min + Math.random() * (max - min);
|
||||
}
|
||||
|
||||
/****************************************扩展Number********************************************/
|
||||
interface Number {
|
||||
/**
|
||||
* 对数字进行补0操作
|
||||
* @param length 要补的总长度
|
||||
* @return 补0之后的字符串
|
||||
*/
|
||||
zeroize?(length: number): string;
|
||||
|
||||
/**
|
||||
* 数值介于,`min` `max`直接,包含min,max
|
||||
* 即:[min,max]
|
||||
*
|
||||
* @param {number} min
|
||||
* @param {number} max
|
||||
* @returns {boolean}
|
||||
* @memberof Number
|
||||
*/
|
||||
between?(min: number, max: number): boolean;
|
||||
}
|
||||
|
||||
Object.defineProperties(Number.prototype, {
|
||||
zeroize: {
|
||||
value: function (this: number, length: number) { return zeroize(this, length) },
|
||||
writable: true
|
||||
},
|
||||
between: {
|
||||
value: function (this: number, min: number, max: number) { return min <= this && max >= this },
|
||||
writable: true
|
||||
}
|
||||
});
|
||||
|
||||
/****************************************扩展String****************************************/
|
||||
interface String {
|
||||
/**
|
||||
* 替换字符串中{0}{1}{2}{a} {b}这样的数据,用obj对应key替换,或者是数组中对应key的数据替换
|
||||
*/
|
||||
substitute?(...args: any): string;
|
||||
substitute?(args: any[]): string;
|
||||
/**
|
||||
* 对数字进行补0操作
|
||||
* @param length 要补的总长度
|
||||
* @return 补0之后的字符串
|
||||
*/
|
||||
zeroize?(length: number): string;
|
||||
/**
|
||||
* 将一个字符串转换成一个很小几率重复的数值
|
||||
* <font color="#ff0000">此方法hash的字符串并不一定唯一,慎用</font>
|
||||
*/
|
||||
hash?(): number;
|
||||
|
||||
/**
|
||||
* 获取字符串长度,中文方块字符算两个长度
|
||||
*/
|
||||
trueLength?(): number;
|
||||
/**
|
||||
* 中文字符个数
|
||||
* */
|
||||
cnLength?(): number;
|
||||
/**
|
||||
* 比较版本号
|
||||
* */
|
||||
versionCompare?(target: string): number;
|
||||
}
|
||||
|
||||
|
||||
Object.defineProperties(String.prototype, {
|
||||
zeroize: {
|
||||
value: function (length: number) { return zeroize(this, length) },
|
||||
writable: true
|
||||
},
|
||||
substitute: {
|
||||
value: function (this: string) {
|
||||
let len = arguments.length;
|
||||
if (len > 0) {
|
||||
let obj: IArguments;
|
||||
if (len == 1) {
|
||||
obj = arguments[0];
|
||||
if (typeof obj !== "object") {
|
||||
obj = arguments;
|
||||
}
|
||||
} else {
|
||||
obj = arguments;
|
||||
}
|
||||
if ((obj instanceof Object) && !(obj instanceof RegExp)) {
|
||||
return this.replace(/\{(?:%([^{}]+)%)?([^{}]+)\}/g, function (match: string, handler: string, key: string) {
|
||||
//检查key中,是否为%开头,如果是,则尝试按方法处理
|
||||
// @ts-ignore
|
||||
let value = obj[key];
|
||||
if (handler) {//如果有处理器,拆分处理器
|
||||
let func = String.subHandler[handler];
|
||||
if (func) {
|
||||
value = func(value);
|
||||
}
|
||||
}
|
||||
return (value !== undefined) ? '' + value : match;
|
||||
});
|
||||
}
|
||||
}
|
||||
return this.toString();//防止生成String对象,ios反射String对象会当成一个NSDictionary处理
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
hash: {
|
||||
value: function () {
|
||||
let len = this.length;
|
||||
let hash = 5381;
|
||||
for (let i = 0; i < len; i++) {
|
||||
hash += (hash << 5) + this.charCodeAt(i);
|
||||
}
|
||||
return hash & 0x7fffffff;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
trueLength: {
|
||||
value: function () {
|
||||
let arr: string[] = this.match(/[\u2E80-\u9FBF]/ig);
|
||||
return this.length + (arr ? arr.length : 0);
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
cnLength: {
|
||||
value: function () {
|
||||
let arr: string[] = this.match(/[\u2E80-\u9FBF]/ig);
|
||||
return arr ? arr.length : 0;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
versionCompare: {
|
||||
value: function (target: string): number {
|
||||
const GTR = 1; //大于
|
||||
const LSS = -1; //小于
|
||||
const EQU = 0; //等于
|
||||
if (!target) {
|
||||
return GTR;
|
||||
}
|
||||
let v1arr = String(this).split(".").map(function (a) {
|
||||
return parseInt(a);
|
||||
});
|
||||
let v2arr = String(target).split(".").map(function (a) {
|
||||
return parseInt(a);
|
||||
});
|
||||
let arrLen = Math.max(v1arr.length, v2arr.length);
|
||||
let result;
|
||||
|
||||
//排除错误调用
|
||||
if (this == undefined || target == undefined) {
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
//检查空字符串,任何非空字符串都大于空字符串
|
||||
if (this.length == 0 && target.length == 0) {
|
||||
return EQU;
|
||||
} else if (this.length == 0) {
|
||||
return LSS;
|
||||
} else if (target.length == 0) {
|
||||
return GTR;
|
||||
}
|
||||
//循环比较版本号
|
||||
for (let i = 0; i < arrLen; i++) {
|
||||
result = versionComp(v1arr[i], v2arr[i]);
|
||||
if (result == EQU) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
function versionComp(n1: number, n2: number) {
|
||||
if (typeof n1 != "number") {
|
||||
n1 = 0;
|
||||
}
|
||||
if (typeof n2 != "number") {
|
||||
n2 = 0;
|
||||
}
|
||||
if (n1 > n2) {
|
||||
return GTR;
|
||||
} else if (n1 < n2) {
|
||||
return LSS;
|
||||
} else {
|
||||
return EQU;
|
||||
}
|
||||
}
|
||||
},
|
||||
writable: true
|
||||
}
|
||||
});
|
||||
interface StringConstructor {
|
||||
/**
|
||||
* 对数字进行补0操作
|
||||
* @param value 要补0的数值
|
||||
* @param length 要补的总长度
|
||||
* @return 补0之后的字符串
|
||||
*/
|
||||
zeroize?: (value: number, length: number) => string;
|
||||
|
||||
|
||||
/**
|
||||
* substitute的回调函数
|
||||
*
|
||||
* @type {Readonly<{ [index: string]: { (input: any): string } }>}
|
||||
* @memberOf StringConstructor
|
||||
*/
|
||||
subHandler?: Readonly<{ [index: string]: { (input: any): string } }>;
|
||||
}
|
||||
|
||||
String.zeroize = zeroize;
|
||||
|
||||
|
||||
|
||||
/****************************************扩展Date****************************************/
|
||||
|
||||
|
||||
interface Date {
|
||||
|
||||
/**
|
||||
* 格式化日期
|
||||
*
|
||||
* @param {string} mask 时间字符串
|
||||
* @param {boolean} [local] 是否基于本地时间显示,目前项目,除了报错信息,其他时间都用UTC时间显示
|
||||
* @returns {string} 格式化后的时间
|
||||
*/
|
||||
format(mask: string, local?: boolean): string;
|
||||
}
|
||||
|
||||
Object.defineProperties(Date.prototype, {
|
||||
format: {
|
||||
value: function (mask: string, local?: boolean) {
|
||||
let d: Date = this;
|
||||
// @ts-ignore
|
||||
return mask.replace(/"[^"]*"|'[^']*'|(?:d{1,2}|m{1,2}|yy(?:yy)?|([hHMs])\1?)/g, function ($0: string) {
|
||||
switch ($0) {
|
||||
case "d": return gd();
|
||||
case "dd": return zeroize(gd());
|
||||
case "M": return gM() + 1;
|
||||
case "MM": return zeroize(gM() + 1);
|
||||
case "yy": return (gy() + "").substr(2);
|
||||
case "yyyy": return gy();
|
||||
case "h": return gH() % 12 || 12;
|
||||
case "hh": return zeroize(gH() % 12 || 12);
|
||||
case "H": return gH();
|
||||
case "HH": return zeroize(gH());
|
||||
case "m": return gm();
|
||||
case "mm": return zeroize(gm());
|
||||
case "s": return gs();
|
||||
case "ss": return zeroize(gs());
|
||||
default: return $0.substr(1, $0.length - 2);
|
||||
}
|
||||
});
|
||||
function gd() { return local ? d.getDate() : d.getUTCDate() }
|
||||
function gM() { return local ? d.getMonth() : d.getUTCMonth() }
|
||||
function gy() { return local ? d.getFullYear() : d.getUTCFullYear() }
|
||||
function gH() { return local ? d.getHours() : d.getUTCHours() }
|
||||
function gm() { return local ? d.getMinutes() : d.getUTCMinutes() }
|
||||
function gs() { return local ? d.getSeconds() : d.getUTCSeconds() }
|
||||
},
|
||||
writable: true
|
||||
}
|
||||
});
|
||||
|
||||
/****************************************扩展Array****************************************/
|
||||
const enum ArraySort {
|
||||
/**
|
||||
* 升序
|
||||
*/
|
||||
ASC = 0,
|
||||
/**
|
||||
* 降序
|
||||
*/
|
||||
DESC = 1
|
||||
}
|
||||
|
||||
|
||||
|
||||
interface ArrayConstructor {
|
||||
// binaryInsert<T>(partArr: T[], item: T, filter: { (tester: T, ...args): boolean }, ...args);
|
||||
SORT_DEFAULT: { number: 0, string: "", boolean: false };
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于对Array排序时,处理undefined
|
||||
*/
|
||||
Array.SORT_DEFAULT = {
|
||||
number: 0,
|
||||
string: "",
|
||||
boolean: false
|
||||
}
|
||||
Object.freeze(Array.SORT_DEFAULT);
|
||||
|
||||
interface Array<T> {
|
||||
/**
|
||||
* 如果数组中没有要放入的对象,则将对象放入数组
|
||||
*
|
||||
* @param {T} t 要放入的对象
|
||||
* @returns {number} 放入的对象,在数组中的索引
|
||||
*
|
||||
* @member Array
|
||||
*/
|
||||
pushOnce?(t: T): number;
|
||||
|
||||
/**
|
||||
*
|
||||
* 删除某个数据
|
||||
* @param {T} t
|
||||
* @returns {boolean} true 有这个数据并且删除成功
|
||||
* false 没有这个数据
|
||||
*/
|
||||
remove?(t: T): boolean;
|
||||
|
||||
/**
|
||||
* 排序 支持多重排序
|
||||
* 降序, 升序
|
||||
* @param {(keyof T)[]} kArr 参数属性列表
|
||||
* @param {(boolean[] | ArraySort[])} [dArr] 是否降序,默认升序
|
||||
* @returns {this}
|
||||
*
|
||||
* @member Array
|
||||
*/
|
||||
multiSort?(kArr: (keyof T)[], dArr?: boolean[] | ArraySort[]): this;
|
||||
|
||||
/**
|
||||
* 默认排序
|
||||
*
|
||||
* @param {string} [key]
|
||||
* @param {boolean} [descend]
|
||||
*
|
||||
* @member Array
|
||||
*/
|
||||
doSort?(key?: keyof T, descend?: boolean | ArraySort): this;
|
||||
doSort?(descend?: boolean | ArraySort, key?: keyof T): this;
|
||||
|
||||
/**
|
||||
* 将数组克隆到to
|
||||
* to的数组长度会和当前数组一致
|
||||
*
|
||||
* @template T
|
||||
* @param {Array<T>} to
|
||||
*/
|
||||
cloneTo?<T>(to: Array<T>):void;
|
||||
|
||||
/**
|
||||
* 将数组附加到to中
|
||||
*
|
||||
* @template T
|
||||
* @param {Array<T>} to
|
||||
*
|
||||
* @member ArrayConstructor
|
||||
*/
|
||||
appendTo?<T>(to: Array<T>):void;
|
||||
|
||||
/**
|
||||
* 移除数组index位置的元素, 比slice效率高
|
||||
* @param index
|
||||
*/
|
||||
spliceOne?(index: number): boolean;
|
||||
|
||||
/**
|
||||
* 随机排序
|
||||
*/
|
||||
randomSort?():void;
|
||||
|
||||
/**
|
||||
* 检查数组中是否含有另外一个object
|
||||
* @param obj 与数组同类型的obj | 同类型的数组 | 指定child字段的值 | 指定child字段的数组
|
||||
* @param child 比较字段
|
||||
*/
|
||||
contains?<T>(obj: T | T[] | {} | {}[], child?: string): boolean;
|
||||
|
||||
/**
|
||||
* 将数组随机插入当前数组中
|
||||
* @param arr
|
||||
*/
|
||||
randomInsert?<T>(arr: Array<T>):void;
|
||||
/**
|
||||
* 随机获取n个元素
|
||||
* @param count
|
||||
*/
|
||||
randomGet?<T>(count?: number):T[];
|
||||
/**
|
||||
* 随机获取1个元素
|
||||
*/
|
||||
randomOne?<T>():T;
|
||||
/**
|
||||
* 随机移除n个元素
|
||||
* @param count
|
||||
*/
|
||||
randomRemove?<T>(count?: number):T[];
|
||||
/**
|
||||
* 数组移动n位
|
||||
* @param n n > 0 右移, n<0 左移
|
||||
*/
|
||||
moveElement?<T>(n: number): T[];
|
||||
|
||||
/**
|
||||
* 两个数组并集
|
||||
* @param arr
|
||||
*/
|
||||
union?<T>(arr: T[]): T[];
|
||||
|
||||
/**
|
||||
* 两个数组交集
|
||||
* @param arr
|
||||
*/
|
||||
intersect?<T>(arr: T[]): T[];
|
||||
/**
|
||||
* 相对于arr的差集
|
||||
* @param arr
|
||||
*/
|
||||
difference?<T>(arr: T[]): T[];
|
||||
}
|
||||
|
||||
Object.defineProperties(Array.prototype, {
|
||||
cloneTo: {
|
||||
value: function <T>(this: T[], b: any[]) {
|
||||
b.length = this.length;
|
||||
let len = this.length;
|
||||
b.length = len;
|
||||
for (let i = 0; i < len; i++) {
|
||||
b[i] = this[i];
|
||||
}
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
appendTo: {
|
||||
value: function <T>(this: T[], b: any[]) {
|
||||
let len = this.length;
|
||||
for (let i = 0; i < len; i++) {
|
||||
b.push(this[i]);
|
||||
}
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
pushOnce: {
|
||||
value: function <T>(this: T[], t: T) {
|
||||
let idx = this.indexOf(t);
|
||||
if (!~idx) {
|
||||
idx = this.length;
|
||||
this[idx] = t;
|
||||
}
|
||||
return idx;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
remove: {
|
||||
value: function <T>(this: T[], t: T) {
|
||||
let idx = this.indexOf(t);
|
||||
if (~idx) {
|
||||
this.splice(idx, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
doSort: {
|
||||
value: function () {
|
||||
let key: string, descend: boolean;
|
||||
let len = arguments.length;
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
let arg = arguments[i];
|
||||
let t = typeof arg;
|
||||
if (t === "string") {
|
||||
key = arg;
|
||||
} else {
|
||||
descend = !!arg;
|
||||
}
|
||||
}
|
||||
if (key) {
|
||||
return this.sort((a: any, b: any) => descend ? b[key] - a[key] : a[key] - b[key]);
|
||||
} else {
|
||||
return this.sort((a: any, b: any) => descend ? b - a : a - b);
|
||||
}
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
multiSort: {
|
||||
value: function (kArr: string[], dArr?: boolean[] | boolean) {
|
||||
let isArr = Array.isArray(dArr);
|
||||
return this.sort((a: any, b: any): number => {
|
||||
const def = Array.SORT_DEFAULT;
|
||||
for (let idx = 0, len = kArr.length; idx < len; idx++) {
|
||||
let key = kArr[idx];
|
||||
// @ts-ignore
|
||||
let mode = isArr ? !!dArr[idx] : !!dArr;
|
||||
let av = a[key];
|
||||
let bv = b[key];
|
||||
let typea = typeof av;
|
||||
let typeb = typeof bv;
|
||||
if (typea == "object" || typeb == "object") {
|
||||
return 0;
|
||||
}
|
||||
else if (typea != typeb) {
|
||||
if (typea == "undefined") {
|
||||
// @ts-ignore
|
||||
bv = def[typeb];
|
||||
} else if (typeb == "undefined") {
|
||||
// @ts-ignore
|
||||
av = def[typea];
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (av < bv) {
|
||||
return mode ? 1 : -1;
|
||||
} else if (av > bv) {
|
||||
return mode ? -1 : 1;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
spliceOne: {
|
||||
value: function (index: number): boolean {
|
||||
if (index === -1 || index >= this.length) {
|
||||
return false;
|
||||
}
|
||||
const len = this.length - 1;
|
||||
for (let i = index; i < len; i++) {
|
||||
this[i] = this[i + 1];
|
||||
}
|
||||
this.length = len;
|
||||
return true;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
|
||||
randomSort: {
|
||||
value: function<T> () {
|
||||
for (let j, x, i = this.length; i; j = (Math.random() * i) | 0, x = this[--i], this[i] = this[j], this[j] = x) {
|
||||
;
|
||||
}
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
contains: {
|
||||
value: function<T> (obj: T | T[] | {} | {}[], child?: string): boolean {
|
||||
let result = false;
|
||||
if (child) {
|
||||
const isArr = Array.isArray(obj);
|
||||
if (isArr) {
|
||||
// @ts-ignore
|
||||
if (obj[0].hasOwnProperty(child)) {
|
||||
let set0 = new Set();
|
||||
// @ts-ignore
|
||||
for (let s of obj) {
|
||||
// @ts-ignore
|
||||
set0.add(s[child]);
|
||||
}
|
||||
// @ts-ignore
|
||||
let set1 = new Set(this.filter (x => set0.has(x)));
|
||||
return set0.size === set1.size;
|
||||
} else {
|
||||
// @ts-ignore
|
||||
let set0 = new Set(obj);
|
||||
let set1 = new Set(this.filter ((x: {}) => set0.has(x)));
|
||||
return set1.size === set0.size;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (obj.hasOwnProperty(child)) {
|
||||
for (let sub of this) {
|
||||
if (sub.hasOwnProperty(child)) {
|
||||
// @ts-ignore
|
||||
if (sub[child] === obj[child]) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let sub of this) {
|
||||
if (sub.hasOwnProperty(child)) {
|
||||
// @ts-ignore
|
||||
if (sub[child] === obj) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
// 不指定 比较字段 的话, 只处理2种情况
|
||||
// 1: obj 为数组
|
||||
// 2: obj 不是数组
|
||||
if (Array.isArray(obj)) {
|
||||
let set0 = new Set(obj);
|
||||
// @ts-ignore
|
||||
let set1 = new Set(this.filter (x => set0.has(x)));
|
||||
return set1.size === set0.size;
|
||||
} else {
|
||||
let idx = this.indexOf(obj);
|
||||
return !!(~idx);
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
randomInsert: {
|
||||
value: function<T>(arr: Array<T>) {
|
||||
const length = this.length;
|
||||
arr.forEach(value => {
|
||||
this.splice(Math.random() * length, 0 , value);
|
||||
})
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
randomGet: {
|
||||
value: function<T>(count: number = 1):T[] {
|
||||
let shuffled: T[] = this.slice(0), i = this.length, min = i - count, temp, index;
|
||||
if (min < 0) {
|
||||
return shuffled;
|
||||
}
|
||||
while (i-- > min) {
|
||||
index = Math.floor((i + 1) * Math.random());
|
||||
temp = shuffled[index];
|
||||
shuffled[index] = shuffled[i];
|
||||
shuffled[i] = temp;
|
||||
}
|
||||
return shuffled.slice(min);
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
randomOne: {
|
||||
value: function<T>(): T {
|
||||
let results = this.randomGet(1);
|
||||
if (results.length > 0) {
|
||||
return results[0];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
randomRemove: {
|
||||
value: function<T>(count: number = 1):T[] {
|
||||
let result = [];
|
||||
while (count -- > 0 && this.length > 0) {
|
||||
let index = Math.random() * this.length | 0;
|
||||
result.push(...this.splice(index, 1));
|
||||
}
|
||||
return result;
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
|
||||
moveElement: {
|
||||
value: function<T> (n: number): T[] {
|
||||
if (Math.abs(n) > this.length) n = n % this.length;
|
||||
return this.slice(-n).concat(this.slice(0, -n));
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
|
||||
union: {
|
||||
value: function<T> (this: T[], b: any[]): T[] {
|
||||
let a = this.concat(b);
|
||||
return [...new Set(a)];
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
|
||||
intersect: {
|
||||
value: function<T> (this: T[], b: any[]): T[] {
|
||||
let set0 = new Set(b);
|
||||
let set1 = new Set(this.filter (x => set0.has(x)));
|
||||
return [...set1];
|
||||
},
|
||||
writable: true
|
||||
},
|
||||
|
||||
difference: {
|
||||
value: function<T> (this: T[], b: any[]): T[] {
|
||||
let set0 = new Set(b);
|
||||
let set1 = new Set(this.filter(x => !set0.has(x)));
|
||||
return [...set1];
|
||||
},
|
||||
writable: true
|
||||
}
|
||||
|
||||
});
|
@ -4,6 +4,7 @@ import {CardGroup} from "../models/CardGroup";
|
||||
import {ZError} from "../common/ZError";
|
||||
import {Card} from "../models/subdoc/Card";
|
||||
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
|
||||
import {BaseConst} from "../constants/BaseConst";
|
||||
|
||||
export default class CardController extends BaseController {
|
||||
@router('post /api/:accountid/card_group/:heroid')
|
||||
@ -102,8 +103,37 @@ export default class CardController extends BaseController {
|
||||
}
|
||||
account.moneys.set(MoneyTypeConst.CARD_SCROLL, money - count);
|
||||
|
||||
// TODO: 随机取count张卡牌, 并与当前已有的卡比较, 将新卡添加进用户卡组
|
||||
// TODO: 根据配置的概率获取卡
|
||||
let cardMap = global.$cfg.get(BaseConst.UNIT);
|
||||
let cards: any[] = [];
|
||||
for (let [id, card] of cardMap) {
|
||||
if (card.unittypei_id == 2) {
|
||||
cards.push(card);
|
||||
}
|
||||
}
|
||||
let cardsgetd: number[] = cards.randomGet(count).map((o: any) => o.id);
|
||||
let totalCards = account.cards.union(cardsgetd);
|
||||
let dulpSet = new Set(account.cards.intersect(cardsgetd));
|
||||
let results: any = [];
|
||||
let expHero = account.moneys.get(MoneyTypeConst.HERO_EXP) || 0;
|
||||
//TODO: 根据配置设置每张卡分解后得到的经验
|
||||
const expPreCard = 10;
|
||||
for (let id of cardsgetd) {
|
||||
let data: any = {id};
|
||||
if (dulpSet.has(id)) {
|
||||
data.isnew = false;
|
||||
data.expdust = MoneyTypeConst.HERO_EXP;
|
||||
data.dustcount = expPreCard;
|
||||
expHero += expPreCard;
|
||||
} else {
|
||||
data.isnew = true;
|
||||
}
|
||||
results.push(data);
|
||||
}
|
||||
|
||||
account.moneys.set(MoneyTypeConst.HERO_EXP, expHero);
|
||||
account.cards = totalCards;
|
||||
await account.save();
|
||||
return {};
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user