Files
ZYZ/game-server/app/services/eventSercive.ts
2020-10-28 14:38:48 +08:00

408 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { Application, FrontendOrBackendSession } from 'pinus';
import { getGamedata } from '../pubUtils/gamedata';
import EventRecord, { EventRecordModel } from '../db/EventRecord';
import { RoleModel } from '../db/Role';
import { genCode, decodeStrSingle, decodeStr, getRandomWithWeight, resResult } from '../pubUtils/util';
import { EVENT_STATUS, EVENT_RECORD_STATUS, EVENT_TYPE, EVENT_RANDOM_TYPE_ONE_OPEN, EVENT_QUIZ_NUM, EVENT_ANSWER_STATUS } from '../consts/consts';
import { EVENT_REFRESH_NUM } from '../consts/consts';
import { STATUS } from '../consts/statusCode';
/**
* 从检查接口调用检查是否有这么个战斗顺便保存一下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 app
* @param session
* @param roleId
* @param battleId
* @param isSuccess
* @param battleCode
*/
export async function setBattleStatus(app: Application, 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(app, 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) - 8*60*60*1000; // 每天12点修复时差
let todayB = now.setHours(18, 0, 0, 0) - 8*60*60*1000; // 每天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;
}
console.log('getEventTime', curTime, todayA, todayB, yesterdayB, t);
return t
}
/**
* 从挑战结算接口调用,挑战完主线某一关,开始刷奇遇关卡
*
* @param app
* @param session
*/
export async function startEvent(app: Application, session: FrontendOrBackendSession) {
// console.log('*******setEventStatus')
let roleId = session.get('roleId');
let roleName = session.get('roleName');
let channelName = roleId;
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(app, roleId, channelName, { event }); // 推送
}
/**
* 从filter调用用于每次检查时间获取事件并推送
*
* @param app
* @param session
* @param isForce 即使不是12点和18点也强制刷新
*/
export async function checkEvent(app: Application, session: FrontendOrBackendSession, isForce:boolean = false) {
try {
let roleId = session.get('roleId');
if(roleId) {
let roleName = session.get('roleName');
let channelName = roleId;
let eventStatus = session.get('eventStatus')||EVENT_STATUS.WAITING;
let eventTime = session.get('getEventTime')||0;
let now = new Date();
let t = getEventTime(now);
let channel = app.get('channelService').getChannel(channelName, false);
if(!!channel && (eventTime < t || isForce)) { // 第一次登陆后可以刷新了
let event = await getEvent(eventStatus, roleId, roleName);
if (eventStatus == EVENT_STATUS.STARTING || eventStatus == EVENT_STATUS.OPEN) {
pushEventMsg(app, roleId, channelName, { 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-1812 18-24 18
let preTime = getEventTime(new Date(curTime - 1)); // 上一次的时间节点
let event: Array<EventRecord> = [];
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个
let curEvents = await EventRecordModel.getEventRecordByTime(roleId, curTime); // 这次3个
if(curEvents.length == 0) { // 这次3个没刷过那就刷一下
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 result = await refreshEvent(EVENT_REFRESH_NUM, roleId, roleName, curTime, prePoint);
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, prePoint: Array<number>) {
let event = new Array();
let dicEvent = getGamedata('dic_zyz_event');
let role = await RoleModel.findByRoleId(roleId);
dicEvent = dicEvent.filter(cur => { // 筛选适合等级
let { suitLevel } = cur;
suitLevel = decodeStrSingle('eventSuitLevel', suitLevel);
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;
});
});
console.log(JSON.stringify(randomList));
let curPoint = new Array<number>();
for(let i = 0; i < num; i++) {
if(randomList.length == 0) { // 一轮刷新过,开始新的一轮,保证所有事件都能刷新一遍
turn ++;
randomList = [...dicEvent];
}
if(randomList.length == 0) break; // 如果还是为0pass
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<number>();
for(let i = 0; i < num; i++) {
let {dic} = getRandomWithWeight(randomList);
console.log(JSON.stringify(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(positionStr: string, prePoint: Array<number>, curPoint: Array<number>) {
let positionArr = decodeStr('point', positionStr, '&');
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 app
* @param roleId
* @param channelName
* @param msg
*/
function pushEventMsg(app: Application, roleId: string, channelName: string, msg: any ) {
console.log('***pushEventMsg', channelName)
let channelService = app.get('channelService');
let param = { msg };
let channel = channelService.getChannel(channelName, false);
if(!!channel) {
let tsid = channel.getMember(roleId)['sid'];
channelService.pushMessageByUids('onSpecialEvent', param, [{
uid: roleId,
sid: tsid
}]);
}
}
/**
* 领取奖励时检查状态是否正确
*
* @param type 事件类型
* @param status 状态id
*/
export function checkEventStatus(type: number, status: number) {
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 = false;
}
} 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 if (status == EVENT_RECORD_STATUS.BATTLE_FAIL) {
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<number>, 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 = getGamedata('Questions');
let rid:Array<number> = [], result = [];
while(num > 0) {
let index = Math.floor(Math.random() * questions.length);
let {id, question, a1, a2, a3, a4, correct} = questions[index];
if(rid.includes(id)) continue;
rid.push(id);
let answer = [a1, a2, a3, a4].filter(cur => cur);
result.push({id, question, answer, correct});
num--;
}
return result;
}
/**
* 对答案
*
* @param id
* @param answer
*/
export function checkQuiz(id: number, answer: number) {
let questions = getGamedata('Questions');
let result = questions[id - 1];
return {
isCorrect: !!result && result.correct == answer,
answerNo: result?result.correct: 0
}
}