from django.db.models import Max import random class Algorithm(object): shows = None ranks = None origranks = None double = None def __init__(self, shows, members, choices): """Initialisation : - on aggrège toutes les demandes pour chaque spectacle dans show.requests - on crée des tables de demandes pour chaque personne, afin de pouvoir modifier les rankings""" self.max_group = 2*max(choice.priority for choice in choices) self.shows = [] showdict = {} for show in shows: show.nrequests = 0 showdict[show] = show show.requests = [] self.shows.append(show) self.ranks = {} self.origranks = {} self.choices = {} next_rank = {} member_shows = {} for member in members: self.ranks[member] = {} self.choices[member] = {} next_rank[member] = 1 member_shows[member] = {} for choice in choices: member = choice.participant if choice.spectacle in member_shows[member]: continue else: member_shows[member][choice.spectacle] = True showdict[choice.spectacle].requests.append(member) showdict[choice.spectacle].nrequests += 2 if choice.double else 1 self.ranks[member][choice.spectacle] = next_rank[member] next_rank[member] += 2 if choice.double else 1 self.choices[member][choice.spectacle] = choice for member in members: self.origranks[member] = dict(self.ranks[member]) def IncrementRanks(self, member, currank, increment=1): for show in self.ranks[member]: if self.ranks[member][show] > currank: self.ranks[member][show] -= increment def appendResult(self, l, member, show): l.append((member, self.ranks[member][show], self.origranks[member][show], self.choices[member][show].double)) def __call__(self, seed): random.seed(seed) results = [] shows = sorted(self.shows, key=lambda x: x.nrequests / x.slots, reverse=True) for show in shows: # On regroupe tous les gens ayant le même rang groups = dict([(i, []) for i in range(1, self.max_group + 1)]) for member in show.requests: if self.ranks[member][show] == 0: raise RuntimeError(member, show.title) groups[self.ranks[member][show]].append(member) # On passe à l'attribution winners = [] losers = [] for i in range(1, self.max_group + 1): group = list(groups[i]) random.shuffle(group) for member in group: if self.choices[member][show].double: # double if len(winners) + 1 < show.slots: self.appendResult(winners, member, show) self.appendResult(winners, member, show) elif not self.choices[member][show].autoquit \ and len(winners) < show.slots: self.appendResult(winners, member, show) self.appendResult(losers, member, show) else: self.appendResult(losers, member, show) self.appendResult(losers, member, show) self.IncrementRanks(member, i, 2) else: # simple if len(winners) < show.slots: self.appendResult(winners, member, show) else: self.appendResult(losers, member, show) self.IncrementRanks(member, i) results.append((show, winners, losers)) return results