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, PUSH_ROUTE } from '../consts'; import { EVENT_REFRESH_NUM } from '../consts'; import { STATUS } from '../consts/statusCode'; import { gameData } from '../pubUtils/data'; import { DicQuestion } from '../pubUtils/dictionary/DicQuestion'; import { sendMessageToUserWithSuc } from './pushService'; import { WarStar } from '../domain/dbGeneral'; /** * 从检查接口调用,检查是否有这么个战斗,顺便保存一下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) { const eventStatus = session.get('eventStatus'); // console.log('*******startEvent ', eventStatus) if(eventStatus == EVENT_STATUS.WAITING) { let roleId = session.get('roleId'); let roleName = session.get('roleName'); let sid = session.get('sid'); let event = await refreshEvent(1, roleId, roleName, 0, []); // 刷新初始的一件 if(event.length > 0) { await RoleModel.setEventStatus(roleId, EVENT_STATUS.STARTING); session.set('eventStatus', EVENT_STATUS.STARTING); session.push('eventStatus', () => {}); pushEventMsg(sid, roleId, { event }); // 推送 } return event; } else { return [] } } /** * 获取当前的奇遇事件 * * @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); } else { let curEvent = event[index]; if(curEvent.status == EVENT_RECORD_STATUS.FAIL_RECEIVED || curEvent.status == EVENT_RECORD_STATUS.SUCCESS_RECEIVED) { // 当前的几个已领取,pre的补位 event[index] = 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.filter(cur => cur.movePointArray && cur.movePointArray.length > 0); let role = await RoleModel.findByRoleId(roleId); dicEvent = dicEvent.filter(cur => { // 筛选适合等级 let { suitLevel, previousGk } = cur; return suitLevel.min <= role.lv && suitLevel.max >= role.lv && checkPreviousGk(previousGk, role.warStar) }); 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); if(!point) break; 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; if(randomList.length == 0) return [] 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(x < 500) { // 基本不希望本轮和上轮出现过的关卡再次出现 if(!hasEvent && !hasPreEvent) break; } else { // 但是实在找不到,只要本轮没出现过就好 if(!hasEvent) break; } dic = getRandEelmWithWeight(randomList).dic; } if(!dic) break; let point = randomPosition(dic.movePointArray, prePoint, curPoint); if(!point) break; 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; } export function checkPreviousGk(previousGk: number, warStar: WarStar[]) { if(!previousGk) return true; let preBattle = warStar.findIndex(cur => cur.id == previousGk); return preBattle != -1; } /** * 随机出当前事件的位置 * * @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) { // 还是不够,那是配表的问题,直接报错 return false; } 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 ) { sendMessageToUserWithSuc(roleId, PUSH_ROUTE.SEND_EVENT, msg, 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 } = dicQuestion; if(rid.includes(id)) continue; rid.push(id); result.push({id, question, answer}); 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 } }