'use strict'; const { CrudService } = require('naf-framework-mongoose-free/lib/service'); const { isNullOrUndefined, trimData } = require('naf-core').Util; const { BusinessError, ErrorCode } = require('naf-core').Error; const _ = require('lodash'); const assert = require('assert'); const { ObjectId } = require('mongoose').Types; // 赛程信息 class ScheduleService extends CrudService { constructor(ctx) { super(ctx, 'schedule'); this.model = this.ctx.model.Schedule; } /** * 通过团队创建人id查询赛程信息 * @param {String} user_id 团队创建人id * @param {Object} options 查询附加参数 */ async getByTeamCreater({ user_id, ...query }, { skip = 0, limit = 0 } = {}) { // 用 id 查团队表 create_id:id; 获取团队id去查红方和蓝方的赛程信息 const team = await this.ctx.model.Team.findOne({ create_id: user_id }, { _id: 1 }); if (!team) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到该用户的团队信息'); const condition = { $or: [{ red_id: team._id }, { blue_id: team._id }], ...query }; const data = await this.model.find(condition).skip(parseInt(skip)).limit(parseInt(limit)); const total = await this.model.count(condition); return { data, total }; } async checkNeedNext(id) { const sch = await this.model.findById(id); const { red_branch, blue_branch, match_id, match_name, status } = sch; // 手动确定比赛结束,如果比赛不结束,那就不需要下面 if (status !== '2') return; if (!red_branch || !blue_branch) return; // 有比分,有位置, 再看看同一轮其他比赛是不是有轮空的.有轮空的就不安排,没有轮空的就直接安排晋级比赛 // 将胜利的队伍的属性取出来,以便下面生成新数据 const winProp = []; const propList = [ 'id', 'name', 'logo', 'members' ]; const winTeam = this.getWinTeam(sch); for (const p of propList) { winProp.push({ key: p, value: sch[`${winTeam}_${p}`] }); } // 随便拿一个位置,主要是下面要用轮数去做查询 const match_position = _.get(sch, 'red_position', _.get(sch, 'blue_position')); const mpl = match_position.split('-'); const head = _.head(mpl); const mpReg = new RegExp(`${head}-`); const condition = { match_id, match_name, match_position: mpReg, is_bye: true }; const has_bye = await this.model.count(condition); // 说明有轮空,让管理员去创建下一轮的所有比赛赛程 if (has_bye > 1) return; /** * 没有轮空,直接创建比赛 * 流程位置计算公式: * a:赛程轮数: _.head() * n:该轮队伍编号: _.last() * a - n/n+1 => a+1 - (n+1) / 2 ; * 条件: a>=1, n>=1 ,且n为奇数 */ const turn = parseInt(head) + 1; const last = _.last(mpl); let times; if (last % 2 > 0) { // 奇数,+1再/2 能算出下一轮的场次 times = (parseInt(last) + 1) / 2; } else { times = parseInt(last) / 2; } const next_match_position = `${turn}-${times}`; // 先查询有没有 match_name: '晋级赛', let nextMatchCreateData = { match_id, match_name, match_position: next_match_position, }; let nextMatch = await this.model.findOne(nextMatchCreateData); // 设置队伍数据的函数 const setTeamData = (team, source) => { for (const obj of winProp) { const { key, value } = obj; source[`${team}_${key}`] = value; } return source; }; if (nextMatch) { // 已经有了下场比赛的数据,做修改,将新数据放蓝队里 // 修改,一定是将数据放入蓝队中,所以需要判断下蓝队和红队是不是一个队伍,看下id就行 const nmRed_id = _.get(nextMatch, 'red_id'); const winTeamId = _.get( winProp.find(f => f.key === 'id'), 'value' ); if (nmRed_id === winTeamId) return; nextMatch = setTeamData('blue', nextMatch); await nextMatch.save(); } else { // 没有,将数据放红队里 nextMatchCreateData = setTeamData('red', nextMatchCreateData); await this.model.create(nextMatchCreateData); } } // 根据比分Object获取胜利的队伍 getWinTeam(data) { const { red_branch = 0, blue_branch = 0 } = data; if (red_branch > blue_branch) return 'red'; return 'blue'; } } module.exports = ScheduleService;