2009-05-11 7 views
2

J'essaye de créer des modèles qui représentent un swiss tournament, avec plusieurs tours. A chaque tour, tout le monde sera jumelé avec un autre joueur, sauf dans le cas où il y a un joueur impair, quand un joueur aura un bye.Modélisation d'un tournoi swiss à Django

J'ai besoin de garder une trace du résultat de chaque appariement; c'est-à-dire, quel joueur a gagné. En outre, j'aimerais être capable de rechercher plus efficacement tous les joueurs qui ont déjà joué contre un joueur donné.

Les choses évidentes:

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

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

Au début, je comptais avoir une classe « TournamentPairing » qui avait l'air quelque chose comme ceci:

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 

Mais que ça fait genre de aki, en particulier la partie à propos de player2 étant Aucun parfois. En outre, je ne pense pas que cela facilite la recherche très bien (puisque le joueur que nous recherchons pourrait être dans la fente player1 ou player2).

Y a-t-il un meilleur moyen? Je soupçonne que mon django noob-ness me retient de trouver la bonne solution ici.

+0

Voulez-vous mettre en œuvre l'algorithme d'appariement ainsi? – Svante

+0

Nous pouvons avoir une meilleure idée si vous répertoriez les recherches/opérations sur les appariements. – muhuk

Répondre

5

Vous pouvez refactoriser votre classe TournamentPairing pour qu'elle soit plus "ronde" centrée pour faciliter les requêtes.

CHOICES = ( ('n', 'Normal'), ('b', 'Bye'), )

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") 

Dans le cas d'égalité, ont point de champ gagnant joueur appelé "Cravate".

Ensuite, selon vos critères de recherche, pour voir une liste des joueurs qu'un joueur donné a joué contre:

# 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() 
+0

Cela semble vraiment être la bonne façon de le faire. Merci! – csbrooks

1

Je pense que vous devriez avoir une seule liste de joueurs et ne pas la diviser en joueurs1 et joueurs2, ceux-ci peuvent être construits quand un tour est configuré.

Votre classe de joueur pourrait inclure une liste des joueurs qu'elle a joués, et le dernier joueur sur cette liste serait le joueur actuel auquel elle est confrontée. Quand vous choisissez le prochain joueur que quelqu'un doit jouer, ajoutez ce joueur à la liste.

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

Au cours de chaque tour, pour un seul joueur, il suffit de parcourir la liste globale des joueurs et de comparer un joueur en particulier à chaque élément playersPlayed. Si l'élément n'existe pas, cette personne peut être jouée et ce joueur devrait alors être ajouté à la liste. Si un joueur ne peut pas être trouvé pour un tour particulier, alors ce joueur reçoit un bye. J'espère que c'est au moins un point de départ.