Моделирование швейцарского турнира в Джанго - PullRequest
3 голосов
/ 11 мая 2009

Я пытаюсь создать модели, представляющие швейцарский турнир , с несколькими раундами. Каждый раунд каждый будет в паре с другим игроком, за исключением случая, когда выходит нечетный игрок, когда один игрок получит прощание.

Мне нужно отслеживать результат каждой пары; то есть, какой игрок выиграл. Кроме того, я хотел бы позже иметь возможность эффективно искать всех игроков, которые когда-либо играли против данного игрока.

Очевидные вещи:

class Tournament(models.Model):
    name = models.CharField(max_length=80)

class Player(models.Model):
    name = models.CharField(max_length=80)

Сначала я планировал иметь класс "TournamentPairing", который выглядел примерно так:

class TournamentPairing(models.Model):
    tournament = models.ForeignKey(Tournament)
    round = models.IntegerKey()
    player1 = models.ForeignKey(Player)
    player2 = models.ForeignKey(Player, null = True) # In case of a bye, this is None.
    outcome = models.CharField(max_length=1) # player1 wins, loses, bye, or tie

Но это кажется хакерским, особенно то, что player2 иногда None. Кроме того, я не думаю, что это облегчает поиск (так как искомый игрок может находиться в слоте player1 или player2).

Есть ли лучший способ? Я подозреваю, что мой django noob-ness препятствует мне найти правильное решение здесь.

Ответы [ 2 ]

5 голосов
/ 11 мая 2009

Вы можете реорганизовать свой класс TournamentPairing, чтобы сделать его более «круглым» центром, чтобы облегчить выполнение запросов.

ВЫБОРЫ = ( ('n', 'Normal'), («б», «пока»), )

class Round(models.Model):        
    number = models.IntegerField()
    round_type = models.CharField(max_length=1, default="n", choices=CHOICES)
    tournament = models.ForeignKey(Tournament)
    players = models.ManyToManyField(Player, related_name="rounds")
    winner = models.ForeignKey(Player, null=True, related_name="round_winner") 

В случае ничьей, укажите поле победителя для игрока с именем "Tie".

Затем, по вашим критериям поиска, вы увидите список игроков, против которых играл данный игрок:

# grab a player 
p = Player.objects.get(name='Tom')

# see what rounds this player played in
rounds_played = p.rounds.all()

# who did this player play against?
[r.players for r in rounds_played]

# to see all rounds this player won
p.round_winner.all()
1 голос
/ 11 мая 2009

Я думаю, что у вас должен быть только один список игроков, а не разделять его на player1 и player2, они могут быть созданы при настройке раунда.

Ваш класс игроков может включать в себя список игроков, которых они сыграли, и последним игроком в этом списке будет текущий игрок, с которым они сталкиваются. Когда вы выбираете следующего игрока, который должен сыграть кто-то, добавьте его в список.

class Player(Models.model):
  name = models.CharField(max_length=80)
  playersPlayed = []

В течение каждого раунда для одного игрока просто перебирайте глобальный список игроков и сравнивайте конкретного игрока с каждым элементом PlayersPlayed. Если элемент не существует, этого человека можно сыграть, и этот игрок должен быть добавлен в список. Если игрок не может быть найден в конкретном раунде, ему дается свидание.

Надеюсь, это хотя бы отправная точка.

...