#ruby #rake #datamapper #padrino
#ruby #грабли #datamapper #падрино
Вопрос:
Я пытаюсь назначить игроков в клуб. В клубе n игроков, и игрок принадлежит к клубу. В клубе может быть не более 23 игроков и не более 2 игроков, играющих на одной позиции.
clubs = Club.all #Club is a datamapper object. Returns 20 clubs
to_generate = 10000
while (to_generate > 0)
p = Player.new #Player is a datamapper object
p.position = position #position is a random integer defined elsewhere
clubs.each do |club|
count = 0
club.players.each do |club_player|
if (club_player.position == p.position)
count = 1
end
end
if (count < 2 amp;amp; club.players.length < 22)
club.players << p
p.club = club
end
end
p.save
to_generate -= 1
завершение
В конце сценария я ожидаю, что во всех клубах будет 22 игрока. Почему это не так?
РЕДАКТИРОВАТЬ: в конце сценария я получаю только 22 игрока, назначенных последнему клубу (20), и генерируется 10000 игроков
Комментарии:
1. Сколько игроков у каждого клуба в конце сценария?
2. Я отредактировал вопрос. В конце сценария я получаю только 22 игрока, назначенных последнему клубу (20), и генерируется 10000 игроков
3. Я думаю, у меня есть хороший ответ для вас.
Ответ №1:
Проблема 1. Вы можете превысить максимальное количество игроков в команде и на позиции
Эти строки
if (count < 3 amp;amp; club.players.length < 23)
club.players << p
p.club = club
end
можно резюмировать как «Вы можете добавить игрока в клуб, если в клубе менее 23 игроков и на этой позиции уже находится менее 3 игроков».
Это означает, что он позволяет вам добавить еще один… в общей сложности 3 для позиции и 23 для команды. Так что эта часть логики неверна. Вместо этого вы хотите
if (count < 2 amp;amp; club.players.length < 22)
Проблема 2. Случайное число может не гарантировать, что у вас есть правильные типы игроков
Если позиция генерируется случайным образом, вы не можете быть уверены, что у вас будет достаточно игроков нужного типа. Что, если, например, случайное число всегда совпадало с 2? У вас никогда не будет полной команды.
Проблема 3. как только игрок назначен, вы продолжаете пробовать другие клубы
Как только вы назначите игрока, вам не следует больше смотреть на клубы. Для этого вам нужно вырваться из each
блока.
if (count < 3 amp;amp; club.players.length < 23)
club.players << p
p.club = club
break
end
Даже если вы вызываете club.players << p
несколько раз для одного и того же игрока, DataMapper знает о вашей индивидуальной ассоциации, и последнее задание «выигрывает».
Комментарии:
1. Проблема 1: хорошо! Проблема 2: я генерирую 10000 игроков, нет простого способа, которым это могло бы произойти.
2. Что касается проблемы 2, это правда, что это маловероятно. Но лучше иметь детерминированное поведение. Таким образом, вместо того, чтобы просто использовать 10000 итераций для решения проблемы, вы могли бы сделать свой цикл while обусловленным проверкой того, есть ли в каждой команде требуемые 22 игрока.