import { FrontendOrBackendSession, pinus } from 'pinus'; import EventRecord, { EventRecordModel } from '../db/EventRecord'; import { RoleModel } from '../db/Role'; import { genCode, getRandEelmWithWeight, resResult, getRandSingleEelm } from '../pubUtils/util'; import { EVENT_STATUS, EVENT_RECORD_STATUS, EVENT_TYPE, EVENT_RANDOM_TYPE_ONE_OPEN, EVENT_QUIZ_NUM, EVENT_ANSWER_STATUS, FUNCS_ID } from '../consts'; import { EVENT_REFRESH_NUM } from '../consts'; import { STATUS } from '../consts/statusCode'; import { gameData } from '../pubUtils/data'; import { DicQuestion } from '../pubUtils/dictionary/DicQuestion'; /** * 从检查接口调用,检查是否有这么个战斗,顺便保存一下battleCode * * @param roleId * @param eventStatus * @param battleId * @param battleCode */ export async function checkEventBattle(roleId: string, eventStatus: number, battleId: number, battleCode: string) { let now = new Date(); let refTime = eventStatus == EVENT_STATUS.OPEN? getEventTime(now): 0; let result = await EventRecordModel.setBattleCode(roleId, battleId, refTime, battleCode); if (!result) { if(refTime) { let preTime = getEventTime(new Date(refTime - 1)); // console.log('preTime:', preTime); result = await EventRecordModel.setBattleCode(roleId, battleId, preTime, battleCode); } } if (!result) { return { status: -1, resResult: resResult(STATUS.EVENT_INFO_NOT_FOUND) }; } else { return { status: 0, data: result }; } } /** * 从关卡结算接口调用,保存战斗情况 * * @param session * @param roleId * @param battleId * @param isSuccess * @param battleCode */ export async function setBattleStatus(session: FrontendOrBackendSession, roleId: string, battleId: number , isSuccess: boolean, battleCode: string) { let { BATTLE_SUCCESS, BATTLE_FAIL } = EVENT_RECORD_STATUS; let result = await EventRecordModel.setBattleStatus(roleId, battleId, battleCode, isSuccess?BATTLE_SUCCESS:BATTLE_FAIL); if (!result) { return { status: -1, resResult: resResult(STATUS.EVENT_INFO_NOT_FOUND) }; } await checkEvent(session, true); return { status: 0, data: result }; } /** * 获取刷新时间,12点时间或18点时间 * * @param now */ export function getEventTime(now: Date) { let curTime = Number(now); let todayA = now.setHours(12, 0, 0, 0); // 每天12点 let todayB = now.setHours(18, 0, 0, 0); // 每天18点 let yesterdayB = todayB - 86400000; // 前一天12点 let t = 0; if(curTime < todayA) { t = yesterdayB; } else if (curTime >= todayA && curTime < todayB) { t = todayA; } else if (curTime >= todayB) { t = todayB; } return t } /** * 从挑战结算接口调用,挑战完主线某一关,开始刷奇遇关卡 * * @param session */ export async function startEvent(session: FrontendOrBackendSession) { // console.log('*******setEventStatus') let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); let event = await refreshEvent(1, roleId, roleName, 0, []); // 刷新初始的一件 await RoleModel.setEventStatus(roleId, EVENT_STATUS.STARTING); session.set('eventStatus', EVENT_STATUS.STARTING); session.push('eventStatus', () => {}); pushEventMsg(sid, roleId, { event }); // 推送 } /** * 从filter调用,用于每次检查时间,获取事件并推送 * * @param session * @param isForce 即使不是12点和18点也强制刷新 */ export async function checkEvent(session: FrontendOrBackendSession, isForce:boolean = false) { try { let roleId = session.get('roleId'); let serverId = session.get('serverId'); let funcs = session.get('funcs'); let sid = session.get('sid'); if(roleId) { let roleName = session.get('roleName'); let eventStatus = session.get('eventStatus')||EVENT_STATUS.WAITING; if(funcs && funcs.includes(FUNCS_ID.EVENT) && eventStatus == EVENT_STATUS.WAITING) { await startEvent(session); } else { let eventTime = session.get('getEventTime')||0; let now = new Date(); let t = getEventTime(now); if(eventTime < t || isForce) { // 第一次登陆后可以刷新了 let event = await getEvent(eventStatus, roleId, roleName); if (eventStatus == EVENT_STATUS.STARTING || eventStatus == EVENT_STATUS.OPEN) { pushEventMsg(sid, roleId, { event }); // 推送 session.set('getEventTime', t); session.push('getEventTime', () => {}); } } } } return; }catch(err) { console.log(err.stack); throw err } } /** * 获取当前的奇遇事件 * * @param eventStatus * @param roleId * @param roleName */ export async function getEvent(eventStatus: number, roleId: string, roleName: string) { let now = new Date(); let curTime = getEventTime(now); // 这次的时间节点 0-12:前一天的18 12-18:12 18-24: 18 let preTime = getEventTime(new Date(curTime - 1)); // 上一次的时间节点 let event: Array = []; if (eventStatus == EVENT_STATUS.STARTING) { let result = await EventRecordModel.getEventRecordByTime(roleId, 0); for(let e of result) event.push(e); } else if( eventStatus == EVENT_STATUS.OPEN ) { let preEvents = await EventRecordModel.getEventRecordByTime(roleId, preTime); // 上次3个 if(!preEvents.length) preEvents = await EventRecordModel.getEventRecordByTime(roleId, 0); let curEvents = await EventRecordModel.getEventRecordByTime(roleId, curTime); // 这次3个 if(curEvents.length == 0) { // 这次3个没刷过,那就刷一下 let result = await refreshEvent(EVENT_REFRESH_NUM, roleId, roleName, curTime, preEvents); for(let e of result) event.push(e); } else { for(let e of curEvents) event.push(e); } for(let e of preEvents) { let index = event.findIndex(cur => cur.point == e.point); if(index == -1) event.push(e); } } return event; } /** * 刷新事件 * * @param num 刷多少事件 * @param roleId * @param roleName * @param t 时间刷新时间,每天的12点或18点 */ export async function refreshEvent(num: number, roleId: string, roleName: string, t: number, preEvents: Array) { let {WAITING, BATTLE_SUCCESS, BATTLE_FAIL} = EVENT_RECORD_STATUS; let prePoint = preEvents.filter(cur => { return [WAITING, BATTLE_SUCCESS, BATTLE_FAIL].includes(cur.status); }).map(cur => cur.point); let event = new Array(); let dicEvent = gameData.eventList; let role = await RoleModel.findByRoleId(roleId); dicEvent = dicEvent.filter(cur => { // 筛选适合等级 let { suitLevel } = cur; return suitLevel.min <= role.lv && suitLevel.max >= role.lv }); if(EVENT_RANDOM_TYPE_ONE_OPEN) { let historyRecord = await EventRecordModel.getHostoryEventRecord(roleId); let {history, turn} = historyRecord; let randomList = dicEvent.filter(cur => { return history.find(ccur => { return ccur.eventId != cur.eventID; }); }); let curPoint = new Array(); for(let i = 0; i < num; i++) { if(randomList.length == 0) { // 一轮刷新过,开始新的一轮,保证所有事件都能刷新一遍 turn ++; randomList = [...dicEvent]; } if(randomList.length == 0) break; // 如果还是为0,pass let index = Math.floor(Math.random() * randomList.length); let dic = randomList[index]; let point = randomPosition(dic.movePointArray, prePoint, curPoint); let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): undefined; let eventCode = genCode(8); let data = await EventRecordModel.saveEventRecord(eventCode, { roleId, refTime: t, eventId: dic.eventID, roleName, turn, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality, status: EVENT_RECORD_STATUS.WAITING, point, question }); event.push(data); randomList.splice(index, 1); } } else { let randomList = dicEvent; let curPoint = new Array(); for(let i = 0; i < num; i++) { let {dic} = getRandEelmWithWeight(randomList); // 临时处理,不出现相同的关卡id for(let x = 0; x < 1000; x++) { let hasEvent = event.find(cur => { return cur.type == EVENT_TYPE.BATTLE && cur.battleId == dic.warId}); let hasPreEvent = preEvents.find(cur => { return cur.type == EVENT_TYPE.BATTLE && cur.battleId == dic.warId}); if(!hasEvent && !hasPreEvent) break; dic = getRandEelmWithWeight(randomList).dic; } // if(!dic) break; let point = randomPosition(dic.movePointArray, prePoint, curPoint); let eventCode = genCode(8); let question = dic.eventType == EVENT_TYPE.QUIZ?randomQuestion(EVENT_QUIZ_NUM): []; let data = await EventRecordModel.saveEventRecord(eventCode, { roleId, refTime: t, eventId: dic.eventID, roleName, type: dic.eventType, battleId: dic.warId||0, quality: dic.quality, status: EVENT_RECORD_STATUS.WAITING, point, question }); event.push(data) } } return event; } /** * 随机出当前事件的位置 * * @param positionStr */ function randomPosition(positionArr: number[], prePoint: Array, curPoint: Array) { let range = positionArr.filter(point => {return !prePoint.includes(point) && !curPoint.includes(point)}); if(range.length == 0) { // 如果位置总数不够,就不管prePoint里的 range = positionArr.filter(point => {return !curPoint.includes(point)}); } if(range.length == 0) { // 还是不够,那是配表的问题,直接报错 throw new Error('event position not enough'); } let index = Math.floor(Math.random() * range.length); let point = range[index]; curPoint.push(point); return point } /** * 推送 * * @param roleId * @param msg */ function pushEventMsg(sid: string, roleId: string, msg: any ) { let channelService = pinus.app.get('channelService'); channelService.pushMessageByUids('onSpecialEvent', resResult(STATUS.SUCCESS, msg), [{ uid: roleId, sid: sid }]); } /** * 领取奖励时检查状态是否正确 * * @param type 事件类型 * @param status 状态id */ export function checkEventStatus(type: number, status: number) { console.log('type = '+ type + ' status = '+status); let flag: boolean; // 检查状态是否正确 if(type == EVENT_TYPE.BATTLE||type ==EVENT_TYPE.QUIZ) { if(status == EVENT_RECORD_STATUS.BATTLE_SUCCESS) { flag = true; } else if (status == EVENT_RECORD_STATUS.BATTLE_FAIL) { flag = true; } else { flag = true; } } else { if(status == EVENT_RECORD_STATUS.WAITING) { flag = true; } else { flag = false; } } return flag } /** * 领取奖励时调用,领取的是胜利奖励还是失败奖励 * * @param type * @param status * @param question */ export function getEventSuccessStatus(type: number, status: number, question: Array<{id: number, status: number}>) { let isSuccess: boolean, returnResult = 1; // 检查状态是否正确 if(type == EVENT_TYPE.BATTLE) { if(status == EVENT_RECORD_STATUS.BATTLE_SUCCESS) { isSuccess = true; } else { isSuccess = false; } } else if(type == EVENT_TYPE.BOX) { isSuccess = true; } else if (type == EVENT_TYPE.QUIZ) { isSuccess = true; for(let { status = EVENT_ANSWER_STATUS.WAITING } of question) { // console.log(status); if(status == EVENT_ANSWER_STATUS.WRONG) { isSuccess = false; } else if(status == EVENT_ANSWER_STATUS.WAITING) { isSuccess = false; returnResult = -1; } } } return { isSuccess, status: returnResult } } export function checkQuizParam(param: Array, database?: Array<{id: number}>) { if(database) { let flag = true; for(let {id} of database) { let index = param.indexOf(id); if(index == -1) flag = false; break; } return flag } else { return true } } /** * 从题库中随机题目 * * @param num 题目数量 */ function randomQuestion(num: number) { let questions = new Array(); gameData.question.forEach(cur => { questions.push(cur); }); let rid:Array = [], result = []; while(num > 0) { let dicQuestion = getRandSingleEelm(questions); let {id, question, answer, correct} = dicQuestion; if(rid.includes(id)) continue; rid.push(id); result.push({id, question, answer, correct}); num--; } return result; } /** * 对答案 * * @param id * @param answer */ export function checkQuiz(id: number, answer: number) { let result = gameData.question.get(id); return { isCorrect: !!result && result.correct == answer, answerNo: result?result.correct: 0 } }