123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- 'use strict';
- const { CrudService } = require('naf-framework-mongoose-free/lib/service');
- const { BusinessError, ErrorCode } = require('naf-core').Error;
- const _ = require('lodash');
- const assert = require('assert');
- const { ObjectId } = require('mongoose').Types;
- //
- class MatchSmallGroupScheduleService extends CrudService {
- constructor(ctx) {
- super(ctx, 'matchsmallgroupschedule');
- this.model = this.ctx.model.Race.MatchSmallGroupSchedule;
- this.baseUserModel = this.ctx.model.Base.User;
- this.userModel = this.ctx.model.Race.User;
- this.teamApplyModel = this.ctx.model.Race.TeamApply;
- // 加入框架
- this.defaultModule = this.app.config.defaultModel || 'Race';
- }
- async result({ match_id, group_id, project_id }) {
- const { refMods, populate } = this.getRefMods();
- let list = await this.model.find({ match_id, group_id, project_id }).populate({
- path: 'team_id',
- model: this.ctx.model.Race.MatchTeamGroup,
- select: 'name',
- });
- if (list.length <= 0) return;
- list = JSON.parse(JSON.stringify(list));
- list = list.map(i => {
- const { winner, player_one, player_one_score, player_two, player_two_score } = i;
- if (winner) return i;
- if (player_one_score > player_two_score) i.winner = player_one;
- else i.winner = player_two;
- i.team_name = _.get(i, 'team_id.name');
- i.team_id = _.get(i, 'team_id._id');
- return i;
- });
- const newArr = [];
- for (const i of list) {
- const d = await this.getPlayerName(i);
- newArr.push(d);
- }
- list = _.groupBy(newArr, 'team_id');
- const arr = [];
- for (const team_id in list) {
- const groups = list[team_id];
- const team_name = _.get(_.head(groups), 'team_name');
- const obj = { team_name, team_id };
- let players = [];
- const p1s = groups.map(i => ({ player: i.player_one, player_name: i.player_one_name }));
- const p2s = groups.map(i => ({ player: i.player_two, player_name: i.player_two_name }));
- players.push(...p1s, ...p2s);
- players = _.uniqBy(players, 'player');
- // 转换成object[], player:选手; win: 胜场; score:净胜球
- players = players.map(i => ({ player: i.player, player_name: i.player_name, win: 0, score: 0 }));
- for (const g of groups) {
- const { winner, player_one, player_one_score, player_two, player_two_score } = g;
- const p1RoundScore = this.getScore(player_one_score, player_two_score);
- const p2RoundScore = this.getScore(player_two_score, player_one_score);
- const p1 = players.find(f => f.player === player_one);
- const p2 = players.find(f => f.player === player_two);
- // p1,p2谁没有就不行
- if (!p1 || !p2) continue;
- p1.score = p1.score + p1RoundScore || 0;
- p2.score = p2.score + p2RoundScore || 0;
- if (winner === player_one) p1.win += 1;
- else p2.win += 1;
- }
- players = _.orderBy(players, [ 'win', 'score' ], [ 'desc', 'desc' ]);
- obj.score = players;
- const playerArr = players.map(i => i.player_name);
- const scoreList = [];
- for (const p1 of players) {
- // 每列的第一个位置是选手
- const marr = [ p1.player_name ];
- for (const p2 of players) {
- // 循环表头的选手, 自己和自己没分
- if (p1.player === p2.player) {
- marr.push(null);
- continue;
- }
- const r = groups.find(f => (f.player_one === p1.player && f.player_two === p2.player) || (f.player_one === p2.player && f.player_two === p1.player));
- if (!r) marr.push(null);
- else {
- const { player_one_score, player_two_score } = r;
- marr.push(`${player_one_score || 0}:${player_two_score || 0}`);
- }
- }
- scoreList.push(marr);
- }
- obj.table = [ playerArr, ...scoreList ];
- arr.push(obj);
- }
- return arr;
- }
- /**
- * 计算净胜分
- * @param {String|Number} s1 分数1
- * @param {String|Number} s2 分数2
- * @return {Number} 净胜分
- */
- getScore(s1, s2) {
- return (parseInt(s1) || 0) - (parseInt(s2) || 0);
- }
- // 换选手名称
- async getPlayerName(data) {
- if (!data) return data;
- data = JSON.parse(JSON.stringify(data));
- const { player_type, player_one, player_two } = data;
- if (!player_type) return data;
- // 人处理
- if (player_type === 'Race.User') {
- if (player_one) {
- const p1 = await this.userModel.findById(player_one, { user_id: 1 }).populate({ path: 'user_id', model: this.baseUserModel, select: 'name' });
- data.player_one_name = _.get(p1, 'user_id.name');
- }
- if (player_two) {
- const p2 = await this.userModel.findById(player_two, { user_id: 1 }).populate({ path: 'user_id', model: this.baseUserModel, select: 'name' });
- data.player_two_name = _.get(p2, 'user_id.name');
- }
- } else if (player_type === 'Race.TeamApply') {
- if (player_one) {
- const p1 = await this.teamApplyModel.findById(player_one, { one_member_name: 1, two_member_name: 1 });
- data.player_one_name = `${_.get(p1, 'one_member_name')}-${_.get(p1, 'two_member_name')}`;
- }
- if (player_two) {
- const p2 = await this.teamApplyModel.findById(player_two, { one_member_name: 1, two_member_name: 1 });
- data.player_two_name = `${_.get(p2, 'one_member_name')}-${_.get(p2, 'two_member_name')}`;
- }
- }
- return data;
- }
- async saveAll(data) {
- for (const i of data) {
- const { _id } = i;
- if (!_id) {
- // TODO: 创建前:需要检查这些人员是否出现在这个项目中的别的组中
- await this.model.create(i);
- } else {
- await this.model.updateOne({ _id }, i);
- }
- }
- }
- async beforeCreate(body) {
- // 检查数据是否有重复,如果符合检查重复条件,就把之前的删了,用新来的
- const { match_id, group_id, project_id, team_id, player_one, player_two } = body;
- const query = {
- match_id,
- group_id,
- project_id,
- team_id,
- $or: [
- { player_one, player_two },
- { player_one: player_two, player_two: player_one },
- ],
- };
- const d = await this.model.findOne(query);
- if (d) await this.model.deleteOne(query);
- return body;
- }
- async beforeQuery(filter) {
- // 可查询自己的赛程-user_id / 某人的赛程
- // const { user_id, user_name } = filter;
- const user_name = _.get(filter, 'user_name');
- let user_id = _.get(filter, 'user_id');
- // 没有user_id就不需要处理查询条件
- if (!user_id && !user_name) return filter;
- const usualCondition = _.pick(filter, [ 'match_id', 'group_id', 'project_id' ]);
- if (user_name) {
- // 要先找比赛用户模块的数据id
- const baseUser = await this.baseUserModel.findOne({ name: new RegExp(user_name) }, { _id: 1 });
- if (!baseUser) delete filter.user_name;
- delete filter.user_name;
- const baseUserId = baseUser._id;
- const raceUser = await this.userModel.findOne({ user_id: baseUserId, type: '0' });
- if (raceUser) user_id = raceUser._id;
- }
- if (user_id) {
- // 需要查:该用户是 单打 和 双打 的情况
- // 单打,直接user_id 为player_one/two 就可以,双打需要查teamApply
- // 所以先把user_id添加进查询范围里
- let probablyList = [ user_id ];
- // 尽可能的缩小查询范围
- // 接着找组队申请中和该用户有关的人
- const teamApplyList = await this.teamApplyModel.find({ ...usualCondition, status: '1', $or: [{ one_member_id: user_id }, { two_member_id: user_id }] }, { _id: 1 });
- const teamApplyIds = teamApplyList.map(i => i._id);
- probablyList.push(...teamApplyIds);
- // 删除user_id.会造成错误
- delete filter.user_id;
- // 添加该用户正确的范围条件
- probablyList = probablyList.map(i => ObjectId(i).toString());
- filter.$or = [{ player_one: { $in: probablyList } }, { player_two: { $in: probablyList } }];
- }
- return filter;
- }
- async afterQuery(filter, data) {
- data = JSON.parse(JSON.stringify(data));
- for (const d of data) {
- const { player_type, player_one, player_two, referee_id } = d;
- if (player_type === 'Race.User') {
- const p1 = await this.userModel.findById(player_one, { user_id: 1 }).populate({ path: 'user_id', model: this.baseUserModel, select: 'name' });
- const p2 = await this.userModel.findById(player_two, { user_id: 1 }).populate({ path: 'user_id', model: this.baseUserModel, select: 'name' });
- d.player_one_name = _.get(p1, 'user_id.name');
- d.player_two_name = _.get(p2, 'user_id.name');
- } else if (player_type === 'Race.TeamApply') {
- const p1 = await this.teamApplyModel.findById(player_one, { one_member_name: 1, two_member_name: 1 });
- const p2 = await this.teamApplyModel.findById(player_two, { one_member_name: 1, two_member_name: 1 });
- d.player_one_name = `${_.get(p1, 'one_member_name')}-${_.get(p1, 'two_member_name')}`;
- d.player_two_name = `${_.get(p2, 'one_member_name')}-${_.get(p2, 'two_member_name')}`;
- }
- const referee = await this.userModel.findById(referee_id).populate({
- path: 'user_id',
- model: this.baseUserModel,
- });
- d.referee_id_name = _.get(referee, 'user_id.name');
- }
- return data;
- }
- async fetch(filter, { sort, desc, projection } = {}) {
- assert(filter);
- filter = await this.beforeFetch(filter);
- const { _id, id } = filter;
- if (_id || id) filter = { _id: ObjectId(_id || id) };
- // 处理排序
- if (sort && _.isString(sort)) {
- sort = { [sort]: desc ? -1 : 1 };
- } else if (sort && _.isArray(sort)) {
- sort = sort.map(f => ({ [f]: desc ? -1 : 1 })).reduce((p, c) => ({ ...p, ...c }), {});
- }
- const { refMods, populate } = this.getRefMods();
- let res = await this.model.findOne(filter, projection).populate(populate).exec();
- res = JSON.parse(JSON.stringify(res));
- for (const obj of refMods) {
- const { col, prop, type } = obj;
- if (!prop) continue;
- if (_.isArray(prop)) {
- for (const p of prop) {
- if (type === 'String') res[`${col}_${p}`] = _.get(res, `${col}.${p}`);
- if (type === 'Array') {
- const list = [];
- const oList = _.get(res, `${col}`);
- for (const d of oList) {
- const obj = { _id: d._id };
- obj[p] = _.get(d, p);
- list.push(obj);
- }
- res[`${col}_${p}`] = list;
- }
- }
- res[col] = _.get(res, `${col}._id`);
- }
- }
- res = await this.afterFetch(filter, res);
- return res;
- }
- async afterFetch(filter, d) {
- const { player_type, player_one, player_two, referee_id } = d;
- if (player_type === 'Race.User') {
- const p1 = await this.userModel.findById(player_one, { user_id: 1 }).populate({ path: 'user_id', model: this.baseUserModel, select: 'name' });
- const p2 = await this.userModel.findById(player_two, { user_id: 1 }).populate({ path: 'user_id', model: this.baseUserModel, select: 'name' });
- d.player_one_name = _.get(p1, 'user_id.name');
- d.player_two_name = _.get(p2, 'user_id.name');
- } else if (player_type === 'Race.TeamApply') {
- const p1 = await this.teamApplyModel.findById(player_one, { one_member_name: 1, two_member_name: 1 });
- const p2 = await this.teamApplyModel.findById(player_two, { one_member_name: 1, two_member_name: 1 });
- d.player_one_name = `${_.get(p1, 'one_member_name')}-${_.get(p1, 'two_member_name')}`;
- d.player_two_name = `${_.get(p2, 'one_member_name')}-${_.get(p2, 'two_member_name')}`;
- }
- const referee = await this.userModel.findById(referee_id).populate({
- path: 'user_id',
- model: this.baseUserModel,
- });
- d.referee_id_name = _.get(referee, 'user_id.name');
- return d;
- }
- }
- module.exports = MatchSmallGroupScheduleService;
|