@GoldRt

Непонятная ошибка в поиске команды из базы игроков по параметрам?

Всем привет, только начал изучать JS и придумал задачу для закрепления знаний. Суть задачи - сделать алгоритм создания команды из базы игроков которые находятся в очереди. Взял пример из лиги легенд. Человек может выбрать предпочтительную линию на которую хочет пойти (мид, бот, адк, джангл, топ) и второстопенную (тоже самое). Также может выбрать Fill, то есть любая линия. И также есть статус Autofill, когда игрока принудительно заставляют идти на любую свободную линию. Написал скрипт, работает, но проблема в том, что если вызвать функцию сбора команды не один раз, а много, иногда он закидывает не 5 игроков в команду как должен, а 2-4. Не могу найти ошибку. Расписал комментарии чтобы было понятно где что происходит.

let PlayersInQueue = [[5,2,1,19866],[5,4,0,96863],[6,2,0,369606],[5,2,0,257717],[4,0,0,167220],[4,2,1,116557],[3,1,1,20507],[5,3,1,328891],[3,6,1,188176],[6,4,1,239416],[4,4,0,448144],[0,4,1,79320],[3,3,0,122325],[6,4,0,403696],[1,6,0,200534],[4,0,0,397010],[4,2,0,484358],[2,6,0,392902],[5,5,0,107724],[3,2,0,115068],[3,2,1,472744],[3,0,1,486824],[3,1,0,447424],[4,0,0,471797],[5,4,0,112687],[2,6,1,441996],[5,6,0,488176],[3,3,0,485133],[2,3,0,425290],[2,6,1,376416],[5,5,1,362535],[1,1,1,283178],[1,3,0,472208],[6,1,0,389172],[6,3,1,145920],[1,2,1,439644],[3,1,1,454456],[5,4,0,298799],[1,2,0,71282],[5,0,1,325957],[5,2,0,245366],[1,1,0,301032],[2,5,0,116755],[2,6,0,411710],[4,2,1,130909],[2,2,1,80643],[4,1,0,320999],[6,5,1,307824],[1,5,1,156860],[2,2,0,303156],[1,0,1,286035],[1,2,1,286574],[3,1,1,477263],[3,6,0,191744],[4,5,0,409834],[6,1,1,432410],[2,4,0,353708],[0,2,0,357880],[3,0,1,232074],[2,0,0,35853],[3,5,1,1898],[2,5,1,1092],[4,4,0,197439],[4,6,1,418696],[6,6,0,227399],[5,1,0,325799],[1,5,0,266574],[2,1,1,48207],[4,1,0,336102],[0,1,0,292027],[3,1,1,54589],[1,3,0,398170],[2,5,0,262130],[2,1,1,42245],[5,4,1,98316],[1,3,1,136631],[4,3,0,84651],[3,5,0,237278],[3,1,1,481633],[0,4,0,457959],[3,3,0,110649],[1,2,0,447934],[3,5,0,275029],[1,3,0,276505],[4,4,0,495423],[4,2,0,764],[1,2,1,34876],[4,2,1,357991],[4,5,0,490470],[4,1,0,51576],[4,5,1,378812],[2,1,1,17033],[4,6,0,272902],[1,0,0,435363],[2,1,1,117937],[4,1,1,463268],[5,4,1,78812],[6,6,0,310355],[3,5,1,441936],[1,2,0,312407],[3,5,1,142204],[3,0,1,382111],[3,5,0,249228],[4,6,1,259402],[6,3,1,473603],[1,4,0,324597],[2,6,1,52063],[5,4,1,74549],[3,6,0,472682],[0,2,0,216251],[3,1,1,320834],[2,3,1,259764],[4,5,1,338431],[6,4,0,247280],[2,5,1,480016],[1,5,0,180823],[4,1,0,235568],[3,5,0,137102],[3,5,1,122769],[4,1,0,471551],[5,3,0,272901],[4,3,0,362943],[5,6,0,219152],[4,1,1,421342],[3,5,0,177055],[3,3,1,334851],[2,4,0,364679],[1,4,0,258311],[5,1,1,490405],[4,1,1,155153],[4,4,1,87663],[1,5,1,48662],[3,2,0,97880],[1,4,1,419599],[3,1,1,94493],[3,5,0,53874],[4,4,1,489566],[3,4,1,41385],[4,2,1,220867],[4,3,1,357528],[2,5,0,93395],[2,3,0,170699],[5,0,0,429635],[2,4,0,42663],[3,1,1,339519],[5,1,0,376898],[4,4,0,15278],[4,1,0,289187],[2,1,1,408840],[5,2,0,428279],[3,2,0,405445],[3,2,0,5492],[1,5,0,410673],[2,4,1,333911],[2,5,1,220864],[3,3,0,211934],[0,4,1,454354],[5,5,1,195817],[3,0,1,313403],[6,5,0,53958],[5,5,1,49760],[3,2,0,312295],[3,5,1,18772],[6,3,1,338578],[3,1,0,338944],[2,0,1,15768],[4,1,1,184150],[4,4,1,3631],[3,0,1,54957],[0,3,0,333627],[2,1,0,11550],[4,4,0,492899],[4,3,0,476959],[5,4,0,12888],[4,4,0,105282],[5,3,1,157154],[4,5,0,352759],[0,6,1,201474],[1,4,0,353258],[0,1,1,188205],[6,1,0,45250],[2,4,1,395303],[1,4,1,103275],[5,5,1,260323],[2,1,0,457027],[6,2,0,210633],[1,4,0,492148],[2,1,1,346636],[1,6,0,93532],[3,3,1,411956],[3,4,1,427870],[5,1,1,133809],[6,5,0,179041],[4,5,1,319695],[5,4,0,211685],[5,3,0,41020],[2,2,0,220649],[3,6,0,266863],[0,0,1,175948],[1,5,1,234803]];

function GetPlayers (a = 5) { // Берем 'a' кол-во игроков из общей базы и удаляем их от туда, возвращаем в качестве результата функции
  let PlayersStorage = [];
  for (let i = 0; i < a; i++){
    PlayersStorage.push(PlayersInQueue[0]); // Добавление игроков из общей базы во временную базу
    PlayersInQueue.shift(); // Удаления игроков из общей базы
    }
  return PlayersStorage;}

function GetTeam(FindPlayersToTeamCount = 20) { //Находим команду
  let FindTeam = [1,2,3,4,5]; // Доступные линии куда игрок может пойти
  let FullTeam = []; // Готовая команда
  let PlayersToRemoveFromStorage = []; // Игроки которые попали в команду и будут удалены из временной базы поиска игроков
  let TeamStorage = GetPlayers(FindPlayersToTeamCount); // Получаем временную базу игроков
    for (let i = 0; i < TeamStorage.length; i++){
      if (TeamStorage[i][0] === 6 && FindTeam.length !== 0 && FullTeam.length !== 5){ // Число 6 значит, что игрок выбрал Fill (любая линия) и находится в приоритете очереди. Добавляем ему в первый свободный слот команды
        TeamStorage[i][0] = FindTeam[0]; // Во временной базе меняем линию у игрока с Fill на первую свободную
        PlayersToRemoveFromStorage.push(i); // Добавляем индекс игрока для последующего удаления из баз поиска команды
        FullTeam.push(TeamStorage[i]); // Добавляем игрока в команду
        FindTeam.shift(); // Удаляем первую линию из доступных линий занятую этим игроком
        } else if (TeamStorage[i][2] === 1 && FindTeam.length !== 0 && FullTeam.length !== 5) { // Число 1 во втором аргументе значит, что игрок попал под Autofill (любая линия принудительно) и находится в приоритете очереди. Добавляем ему в первый свободный слот команды
        TeamStorage[i][0] = FindTeam[0]; // Во временной базе меняем линию у игрока с Autofill на первую свободную
        PlayersToRemoveFromStorage.push(i); // Добавляем индекс игрока для последующего удаления из баз поиска команды
        FullTeam.push(TeamStorage[i]); // Добавляем игрока в команду
        FindTeam.shift(); // Удаляем первую линию из доступных линий занятую этим игроком
        } else
      if (TeamStorage[i][0] > 0 && TeamStorage[i][0] <= 5 && FindTeam.length != 0  && FullTeam.length != 5){ // Числа 1-5 значат, что игрок выбрал одну из приоритетных линий. Ищем свободную линию в списке и добавляем есть есть.
        if (FindTeam.indexOf(TeamStorage[i][0]) > -1){
          FindTeam.splice(FindTeam.indexOf(TeamStorage[i][0])); // Удаляем линию из доступных линий занятую этим игроком
          FullTeam.push(TeamStorage[i]); // Добавляем игрока в команду
          PlayersToRemoveFromStorage.push(i); // Добавляем индекс игрока для последующего удаления из баз поиска команды
          }
      } else if (TeamStorage[i][1] > 0 && TeamStorage[i][1] <= 5 && FindTeam.length != 0  && FullTeam.length != 5){ // Числа 1-5 значат, что игрок выбрал одну из второстепенных линий. Ищем свободную линию в списке и добавляем есть есть.
        if (FindTeam.indexOf(TeamStorage[i][0]) > -1){
          FindTeam.splice(FindTeam.indexOf(TeamStorage[i][0])); // Удаляем линию из доступных линий занятую этим игроком
          FullTeam.push(TeamStorage[i]); // Добавляем игрока в команду
          PlayersToRemoveFromStorage.push(i); // Добавляем индекс игрока для последующего удаления из баз поиска команды
          }
  }}
  if (FindTeam.length != 0) {GetTeam(100)} else { // Удаляем готовую команду из временной базы. Добавляем временную базу обратно в общую базу (в начало) для повторного поиска. Возвращаем результат в виде готовой команды.
    let PlayersRemoveList = PlayersToRemoveFromStorage.reverse();
    for (let k = 0; k < PlayersToRemoveFromStorage.length; k++){
    TeamStorage.splice(PlayersRemoveList[k],1);} // Удаляем игрока 'k' из временной базы
    PlayersInQueue = TeamStorage.concat(PlayersInQueue); // Конкатенируем временную и постоянную базы
    return FullTeam;};
}
function GetTeamStats(a = 1){ // Простой вывод готовой команды (Для понимания как работает код)
let Result = [];
 for (let k = 0; k < a; k++){
let Team = GetTeam();
for (let i = 0; i < Team.length; i++){
console.log('User ID: ' + Team[i][3]);
if (Team[i][0] == 6){console.log('Main role: Fill')} else
if (Team[i][0] == 1){console.log('Main role: ADC')} else
if (Team[i][0] == 2){console.log('Main role: Support')} else
if (Team[i][0] == 3){console.log('Main role: Jungle')} else
if (Team[i][0] == 4){console.log('Main role: Mid')} else
if (Team[i][0] == 5){console.log('Main role: Top')}
if (Team[i][1] == 1){console.log('Second role: ADC')} else
if (Team[i][1] == 2){console.log('Second role: Support')} else
if (Team[i][1] == 3){console.log('Second role: Jungle')} else
if (Team[i][1] == 4){console.log('Second role: Mid')} else
if (Team[i][1] == 5){console.log('Second role: Top')}
if (Team[i][2] == 1){console.log('Autofill: Yes')} else
if (Team[i][2] == 0){console.log('Autofill: No')}
if (Team[i][0] > 0){console.log('')}
}}
return Result;}

console.log(GetTeam());
console.log(GetTeam());
console.log(GetTeam());
  • Вопрос задан
  • 73 просмотра
Пригласить эксперта
Ответы на вопрос 1
FFxSquall
@FFxSquall
Могу писать код, могу не писать
Что бы быстрее разобраться в коде позволил себе немного порефакторить. Надеюсь сможешь сам разобраться, одна из основных ошибок помечена комментарием. Так же стоит обратить внимание, что не все тупиковые ситуации обработаны.

function getPlayers(a = 5, skip = 0) {
  return PlayersInQueue.splice(skip, a);
}

function getTeam(FindPlayersToTeamCount = 20, skip = 0, team = [], availableLines = [1, 2, 3, 4, 5]) {
  let tempTeam = getPlayers(FindPlayersToTeamCount, skip);

  for (let i = 0; i < tempTeam.length; i++) {
    let player = tempTeam[i];
    let mainLine = player[0];
    let secondLine = player[1];
    let isAutoFill = player[2] === 1;

    if (team.length === 5) break;

    if (mainLine === 6 || isAutoFill) {
      // любая линия или сработал autofill
      player[0] = availableLines.shift();
      team.push(player);
    } else {
      // ищем основную или второстепенную свободную линию
      let mainLineId = availableLines.indexOf(mainLine);
      let secondLineId = availableLines.indexOf(secondLine);

      if (mainLineId < 0 && secondLineId < 0) continue;

      player[0] = availableLines.splice(mainLineId > -1 ? mainLineId : secondLineId, 1)[0];
      team.push(player);
    }
  }

  tempTeam = tempTeam.filter((p) => !team.some((p2) => p[3] == p2[3]));
  PlayersInQueue = tempTeam.concat(PlayersInQueue);

  if (team.length === 5) {
    return team;
  }

  // Если мы не смогли собрать команду нам нужно запустить поиск заново, но только для тех линий которые остались (в этом скорее всего и была ошибка по мимо остальных недочетов)
  getTeam(20, tempTeam.length, team, availableLines);
}


UPD: ещё одна из ошибок
FindTeam.splice(FindTeam.indexOf(TeamStorage[i][0]));
у вас тут удаляется не одна линия, а все после преданного индекса
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы