import { string } from 'mathjs'; import { ApiCall } from 'tsrpc'; import { prizeType } from '../protocols/type'; import { player } from '../protocols/user/type'; export class PublicShared { /**合并奖励 */ static mergePrize(prize: prizeType[]): prizeType[] { let typeObj: k_v> = {}; let mergeArr: prizeType[] = []; prize.forEach(atn => { if (!typeObj[atn.a]) typeObj[atn.a] = {}; if (!typeObj[atn.a][atn.t]) typeObj[atn.a][atn.t] = { n: 0, colour: atn.colour || 0 }; typeObj[atn.a][atn.t].n += atn.n; }); for (let type in typeObj) { for (let id in typeObj[type]) { mergeArr.push({ a: type, t: id, n: typeObj[type][id].n, colour: typeObj[type][id].colour }); } } return mergeArr; } static exprStr2Compile = {}; /**eval预编译 */ static eval(expr:any, scope?:object){ if(Array.isArray(expr)) { let res = [] expr.forEach( item => { if(! this.exprStr2Compile[item] ){ this.exprStr2Compile[item] = mathJs.compile(item); } res.push(this.exprStr2Compile[item].evaluate(scope)) }) return res } else { if(! this.exprStr2Compile[expr] ){ this.exprStr2Compile[expr] = mathJs.compile(expr); } return this.exprStr2Compile[expr].evaluate(scope); } } /**合并属性 */ static mergeProperty(obj1: any = {}, obj2: any = {}) { for (let k in obj2) { if (obj2[k] instanceof Array) { if (obj1[k]) obj1[k] = obj1[k].concat(obj2[k]); else obj1[k] = obj2[k]; } else if (obj2[k] instanceof Object) { if (obj1[k]) PublicShared.mergeProperty(obj1[k], obj2[k]); else { obj1[k] = {}; PublicShared.mergeProperty(obj1[k], obj2[k]); } } else { if (obj1[k]) obj1[k] += obj2[k]; else obj1[k] = obj2[k]; } } } /** * 随机掉落组 * @param id 掉落组id * @param num 随机次数 * @param conf */ static randomDropGroup(id: string | number, num = 1, conf = G.gc.diaoluo): prizeType[] { let prize = []; let weight = []; let dlz = JSON.parse(JSON.stringify(conf[id])); dlz.forEach((d, index) => { if (weight[index - 1]) { weight.push(weight[index - 1] + d.p); } else { weight.push(d.p); } }); for (let n = 0; n < num; n++) { let prizeIndex = 0; // debug 举例:diaoluo.json 250001参数的[p:1, p:140], 随机数范围是 1-141,小于等于1的概率较小,所以大部分取后面的值,后面的值给的物品数量是0 let randomNum = this.randomNum(1, weight[weight.length - 1]); for (let index = 0; index < weight.length; index++) { if (randomNum <= weight[index]) { prizeIndex = index; break; } } prize.push(dlz[prizeIndex]); } return prize; } /** * 随机概率组 */ static randomDropAny(dropArr: T[]): T { let dropGrop = { 0: dropArr }; return this.randomDropGroup(0, 1, dropGrop as any)[0] as any; } /** * 随机生成区间范围整数 */ static randomNum(min: number, max: number) { return Math.floor(Math.random() * (max - min + 1) + min); } /**获取道具配置 */ static getAtnConf(atn: prizeType) { if (atn.a == 'attr') return G.gc.attr[atn.t]; else if (atn.a == 'item') return G.gc.item[atn.t]; else if (atn.a == 'hero') return G.gc.hero[atn.t]; else if (atn.a == 'equip') return G.gc.equip[atn.t]; return null; } /**获取当天0点时间戳 */ static getToDayZeroTime(time: string): number; static getToDayZeroTime(time?: number): number; static getToDayZeroTime(time: string | number) { let t = typeof time == 'string' ? new Date(time) : new Date((time || G.time) * 1000); return Math.round(t.setHours(0, 0, 0, 0) / 1000); } /**获取本周周一0点时间戳 */ static getToWeekMondayZeroTime(time = G.time) { let toDay = new Date(time * 1000); let day = toDay.getDay() || 7; let z = new Date(toDay.getFullYear(), toDay.getMonth(), toDay.getDate() + 1 - day); return Math.round(z.getTime() / 1000); } /**获取当前第几周 避免跨年导致key不一样,以周一时间戳去计算*/ static getToWeek(time = this.getToWeekMondayZeroTime()) { let toDay = new Date(time * 1000); let day = toDay.getDay() || 7; let z = new Date(toDay.getFullYear(), toDay.getMonth(), toDay.getDate() + 1 - day); let z2 = new Date(toDay.getFullYear(), 0, 1); let rq = (z.getTime() - z2.getTime()) / 1000; let s1 = Math.ceil(rq / (24 * 60 * 60)); let s2 = Math.ceil(s1 / 7); return `${toDay.getFullYear()}_${s2}`; } /**周几 */ static getWeek(timestamp: number) { let toDay = new Date(timestamp * 1000); const day = toDay.getDay(); return day } /**是否同一天 */ static chkSameDate(time: string | number, chktime: string | number) { if (this.getToDayZeroTime(time as string) === this.getToDayZeroTime(chktime as string)) return true; return false; } /**获取今天是开服第几天 */ static getOpenServerDay(openTime: any = G.openTime, time = G.time) { let oDay = this.getToDayZeroTime(openTime); return Math.ceil((time - oDay) / 86400); } /**获取相差天数 */ static getDiff(oldTime: number, time = G.time) { let oDay = this.getToDayZeroTime(oldTime); return Math.ceil((time - oDay) / 86400); } /**数组buff转对象buff */ static arrBuffToObjectBuff(arrBuff: (string | number)[]) { let buff = {}; for (let i = 0; i < arrBuff.length; i++) { if (i % 2 != 0) continue; buff[arrBuff[i]] = arrBuff[i + 1]; } return buff; } static str(str: string, ...args: Array) { if (arguments.length < 2) return str; if (arguments.length == 2 && Object.prototype.toString.call(arguments[1]) == '[object Array]') { let args = arguments[1]; for (let i = 0; i < args.length; i++) { str = str.replace(new RegExp('\\{' + (i + 1) + '\\}', 'g'), args[i]); } } else { for (let i = 1; i < arguments.length; i++) { str = str.replace(new RegExp('\\{' + i + '\\}', 'g'), arguments[i]); } } return str; } static getEventIsOpen(cond: k_v, player: Partial) { let arr = Object.entries(cond); for (let [k, v] of arr) { if (k == 'day' && this.getOpenServerDay() < v) return false; if (player[k] < v) return false; } return true; } /**转化时间戳显示日期 */ static fmtTime(timestamp: number) { const date = new Date(timestamp * 1000); const year = date.getFullYear(); const month = date.getMonth() + 1; // 获取月份,需要加1 const day = date.getDate(); // 获取日期 const hour = date.getHours(); // 获取小时 const minute = date.getMinutes(); // 获取分钟 const second = date.getSeconds(); // 获取秒数 // const formattedDate = `${year}-${month}-${day} ${hour}:${minute}:${second}`; // 拼接成格式化后的日期字符串 const formattedDate = `${month}月${day}日${hour}:${minute}`; // 拼接成格式化后的日期字符串 return formattedDate; } /**功能开启 */ static getOpenCond(call: ApiCall, gongneng: string): [boolean, string] { let _con = G.gc.openCond[gongneng] if (!_con) return [false, "功能不存在"] let _res = false let _and = Object.keys(_con.and) for (let index = 0; index < _and.length; index++) { _res = true const element = _and[index]; if (element == "lv" && call.conn.gud.lv < _con.and[element]) { _res = false } else if (element == "openTime" && this.getOpenServerDay() < _con.and[element]) { _res = false } else if (element == "vip" && call.conn.gud.vip < _con.and[element]) { _res = false } else if (element == "mapId" && call.conn.gud.mapId < _con.and[element]) { _res = false } if (!_res) return [false, _con.tips] } let _or = Object.keys(_con.or) for (let index = 0; index < _or.length; index++) { _res = false const element = _or[index]; if (element == "lv" && call.conn.gud.lv >= _con.or[element]) { _res = true break } else if (element == "openTime" && this.getOpenServerDay() >= _con.or[element]) { _res = true break } else if (element == "vip" && call.conn.gud.vip >= _con.or[element]) { _res = true break } else if (element == "mapId" && call.conn.gud.mapId >= _con.or[element]) { _res = true break } } return [_res, _con.tips]; } }