添加抽卡的方法
This commit is contained in:
parent
c6714648d4
commit
9394e0def8
@ -19,6 +19,7 @@ const fs = require('fs');
|
|||||||
const join = require('path').join;
|
const join = require('path').join;
|
||||||
|
|
||||||
let config: Config = require('../config/config.json');
|
let config: Config = require('../config/config.json');
|
||||||
|
require('./common/Extend');
|
||||||
|
|
||||||
export class ApiServer {
|
export class ApiServer {
|
||||||
server: FastifyInstance<Server, IncomingMessage, ServerResponse>;
|
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 {ZError} from "../common/ZError";
|
||||||
import {Card} from "../models/subdoc/Card";
|
import {Card} from "../models/subdoc/Card";
|
||||||
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
|
import {MoneyTypeConst} from "../constants/MoneyTypeConst";
|
||||||
|
import {BaseConst} from "../constants/BaseConst";
|
||||||
|
|
||||||
export default class CardController extends BaseController {
|
export default class CardController extends BaseController {
|
||||||
@router('post /api/:accountid/card_group/:heroid')
|
@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);
|
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();
|
await account.save();
|
||||||
return {};
|
return results;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user