kpsul/bda/algorithm.py

107 lines
4.1 KiB
Python
Raw Normal View History

2016-07-15 00:02:56 +02:00
# -*- coding: utf-8 -*-
2012-07-11 17:39:20 +02:00
from __future__ import division
2016-07-15 00:02:56 +02:00
from __future__ import print_function
from __future__ import unicode_literals
from django.db.models import Max
2012-07-11 17:39:20 +02:00
import random
2012-07-11 17:39:20 +02:00
class Algorithm(object):
shows = None
ranks = None
origranks = None
double = None
def __init__(self, shows, members, choices):
2012-07-11 17:39:20 +02:00
"""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)
2012-07-11 17:39:20 +02:00
self.shows = []
showdict = {}
for show in shows:
show.nrequests = 0
2012-07-11 17:39:20 +02:00
showdict[show] = show
show.requests = []
self.shows.append(show)
self.ranks = {}
self.origranks = {}
self.choices = {}
next_rank = {}
member_shows = {}
2012-07-11 17:39:20 +02:00
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])
2012-07-11 17:39:20 +02:00
def IncrementRanks(self, member, currank, increment=1):
2012-07-11 17:39:20 +02:00
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))
2012-07-11 17:39:20 +02:00
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:
2012-07-11 17:39:20 +02:00
# On regroupe tous les gens ayant le même rang
groups = dict([(i, []) for i in range(1, self.max_group + 1)])
2012-07-11 17:39:20 +02:00
for member in show.requests:
if self.ranks[member][show] == 0:
raise RuntimeError(member, show.title)
2012-07-11 17:39:20 +02:00
groups[self.ranks[member][show]].append(member)
# On passe à l'attribution
winners = []
losers = []
for i in range(1, self.max_group + 1):
2012-07-11 17:39:20 +02:00
group = list(groups[i])
random.shuffle(group)
for member in group:
if self.choices[member][show].double: # double
2012-07-11 17:39:20 +02:00
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:
2012-07-11 17:39:20 +02:00
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
2012-07-11 17:39:20 +02:00
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))
2012-07-11 17:39:20 +02:00
return results