statistics.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. 'use strict';
  2. const { CrudService } = require('naf-framework-mongoose-free/lib/service');
  3. const { BusinessError, ErrorCode } = require('naf-core').Error;
  4. const _ = require('lodash');
  5. const assert = require('assert');
  6. const { ObjectId } = require('mongoose').Types;
  7. // 统计
  8. class StatisticsService extends CrudService {
  9. constructor(ctx) {
  10. super(ctx, 'statistics');
  11. }
  12. async match({ match_id }) {
  13. const teamList = await this.ctx.model.Matchteam.find({ match_id }, { logo: 1, team_name: 1, team_id: 1 });
  14. const resList = [];
  15. for (const team of teamList) {
  16. const { team_id } = team;
  17. const matchList = await this.ctx.model.Schedule.find({ match_id, $or: [{ red_id: team_id }, { blue_id: team_id }], is_bye: false });
  18. const res = this.computedTeam(matchList, team_id);
  19. const info = this.getOtherInfoFromList(matchList, team_id);
  20. resList.push({ ...res, ...info });
  21. }
  22. return _.orderBy(resList, [ 'win', 'score' ], [ 'desc', 'desc' ]);
  23. }
  24. async ranking() {
  25. const projecList = [ 'id', 'name', 'branch', 'integral', 'logo' ];
  26. const groups = [ 'red', 'blue' ];
  27. const projection = {};
  28. for (const g of groups) {
  29. for (const prop of projecList) {
  30. projection[`${g}_${prop}`] = 1;
  31. }
  32. }
  33. // 查出所有的比赛
  34. const list = await this.ctx.model.Schedule.find({}, projection);
  35. // console.log(list);
  36. // 统计出所有队伍(去重)
  37. const rts = list.map(f => f.red_id);
  38. const bts = list.map(f => f.blue_id);
  39. const teamList = _.uniq(_.compact([ ...rts, ...bts ]));
  40. const rList = [];
  41. for (const team_id of teamList) {
  42. // 获得这支队伍在所有比赛中的胜负情况及积分
  43. const res = this.computedTeam(list, team_id);
  44. const info = this.getOtherInfoFromList(list, team_id);
  45. rList.push({ ...info, ...res });
  46. }
  47. const winList = _.orderBy(rList, 'win', [ 'desc' ]);
  48. const scoreList = _.orderBy(rList, 'score', [ 'desc' ]);
  49. return { winList, scoreList };
  50. }
  51. /**
  52. * 根据队伍id,算出在范围内队伍的 胜负次数 及 积分
  53. * @param {Array} list 比赛列表
  54. * @param {String} team_id 队伍id
  55. */
  56. computedTeam(list, team_id) {
  57. let winTimes = 0; // 胜利次数
  58. let loseTimes = 0; // 失败次数
  59. let score = 0; // 积分
  60. for (const match of list) {
  61. const { red_id, blue_id, red_branch, blue_branch } = match;
  62. if (!red_branch && !blue_branch) continue;
  63. let teamInMatch = 'blue';
  64. if (red_id === team_id) teamInMatch = 'red';
  65. else if (blue_id === team_id) teamInMatch = 'blue';
  66. else {
  67. // 该队伍不是红蓝任意一方,说明不是这的,下一场
  68. continue;
  69. }
  70. // 加积分
  71. score += parseInt(match[`${teamInMatch}_integral`]) || 0;
  72. // 算胜负: winTeam => true : 红队胜;反之蓝队胜
  73. const winTeam = parseInt(red_branch) > parseInt(blue_branch);
  74. if (winTeam && teamInMatch === 'red') winTimes++;
  75. else if (!winTeam && teamInMatch !== 'red') winTimes++;
  76. else loseTimes++;
  77. }
  78. return { win: winTimes, lose: loseTimes, score };
  79. }
  80. /**
  81. * 根据比赛列表获取队伍信息
  82. * @param {Array} list 比赛列表
  83. * @param {String} team_id 队伍id
  84. */
  85. getOtherInfoFromList(list, team_id) {
  86. const match = list.find(f => f.red_id === team_id || f.blue_id === team_id);
  87. let logo = {};
  88. let name = '';
  89. if (match) {
  90. const { red_id } = match;
  91. if (red_id === team_id) {
  92. logo = match.red_logo;
  93. name = match.red_name;
  94. } else {
  95. logo = match.blue_logo;
  96. name = match.blue_name;
  97. }
  98. }
  99. return { logo, name };
  100. }
  101. }
  102. module.exports = StatisticsService;