app/soc/logic/allocations.py
changeset 2130 83f4fab7c556
parent 2073 6eb9b4652c80
child 2137 3d5692ae414c
equal deleted inserted replaced
2129:f6ca1647bff7 2130:83f4fab7c556
    44   # I tried to write explicit code that does not require any
    44   # I tried to write explicit code that does not require any
    45   # additional comments (with the exception of the set notation for
    45   # additional comments (with the exception of the set notation for
    46   # the convenience of any mathematicians that happen to read this
    46   # the convenience of any mathematicians that happen to read this
    47   # piece of code ;).
    47   # piece of code ;).
    48 
    48 
    49   def __init__(self, orgs, popularity, mentors, slots,
    49   def __init__(self, orgs, popularity, max, slots,
    50                max_slots_per_org, min_slots_per_org, iterative):
    50                max_slots_per_org, min_slots_per_org, iterative):
    51     """Initializes the allocator.
    51     """Initializes the allocator.
    52 
    52 
    53     Args:
    53     Args:
    54       orgs: a list of all the orgs that need to be allocated
    54       orgs: a list of all the orgs that need to be allocated
    70     self.min_slots_per_org = min_slots_per_org
    70     self.min_slots_per_org = min_slots_per_org
    71     self.orgs = set(orgs)
    71     self.orgs = set(orgs)
    72     self.popularity = None
    72     self.popularity = None
    73     self.total_popularity = None
    73     self.total_popularity = None
    74     self.initial_popularity = popularity
    74     self.initial_popularity = popularity
    75     self.mentors = mentors
    75     self.max = max
    76     self.iterative = iterative
    76     self.iterative = iterative
    77 
    77 
    78   def allocate(self, locked_slots, adjusted_slots):
    78   def allocate(self, locked_slots):
    79     """Allocates the slots and returns the result.
    79     """Allocates the slots and returns the result.
    80 
    80 
    81     Args:
    81     Args:
    82       locked_slots: a dict with orgs and the number of slots they get
    82       locked_slots: a dict with orgs and the number of slots they get
    83       adjusted_slots: a dict with orgs and the number of extra slots they get
    83       adjusted_slots: a dict with orgs and the number of extra slots they get
    84     """
    84     """
    85 
    85 
    86     self.locked_slots = locked_slots
    86     self.locked_slots = locked_slots
    87     self.adjusted_slots = adjusted_slots
       
    88 
    87 
    89     self.buildSets()
    88     self.buildSets()
    90 
    89 
    91     if not sum(self.popularity.values()) or not sum(self.mentors.values()):
    90     if not sum(self.popularity.values()) or not sum(self.max.values()):
    92       return self.popularity
    91       return self.popularity
    93 
    92 
    94     if self.iterative:
    93     if self.iterative:
    95       return self.iterativeAllocation()
    94       return self.iterativeAllocation()
    96     else:
    95     else:
   102 
   101 
   103     popularity = self.initial_popularity.copy()
   102     popularity = self.initial_popularity.copy()
   104 
   103 
   105     # set s
   104     # set s
   106     locked_slots = self.locked_slots
   105     locked_slots = self.locked_slots
   107     adjusted_slots = self.adjusted_slots
       
   108 
   106 
   109     # set a and b
   107     # set a and b
   110     locked_orgs = set(locked_slots.keys())
   108     locked_orgs = set(locked_slots.keys())
   111     adjusted_orgs = set(adjusted_slots.keys())
       
   112 
   109 
   113     # set a' and b'
   110     # set a' and b'
   114     unlocked_orgs = self.orgs.difference(locked_orgs)
   111     unlocked_orgs = self.orgs.difference(locked_orgs)
   115 
   112 
   116     # set a*b and a'*b'
       
   117     locked_and_adjusted_orgs = locked_orgs.intersection(adjusted_orgs)
       
   118 
       
   119     # a+o and b+o should be o
   113     # a+o and b+o should be o
   120     locked_orgs_or_orgs = self.orgs.union(locked_orgs)
   114     locked_orgs_or_orgs = self.orgs.union(locked_orgs)
   121     adjusted_orgs_or_orgs = self.orgs.union(adjusted_orgs)
       
   122 
   115 
   123     total_popularity = sum(popularity.values())
   116     total_popularity = sum(popularity.values())
   124 
       
   125     # an item can be only a or b, so a*b should be empty
       
   126     if locked_and_adjusted_orgs:
       
   127       raise Error("Cannot have an org locked and adjusted")
       
   128 
   117 
   129     # a+o should be o, testing length is enough though
   118     # a+o should be o, testing length is enough though
   130     if len(locked_orgs_or_orgs) != len(self.orgs):
   119     if len(locked_orgs_or_orgs) != len(self.orgs):
   131       raise Error("Unknown org as locked slot")
   120       raise Error("Unknown org as locked slot")
   132 
   121 
   133     # same for b+o
       
   134     if len(adjusted_orgs_or_orgs) != len(self.orgs):
       
   135       raise Error("Unknown org as adjusted slot")
       
   136 
       
   137     self.adjusted_orgs = adjusted_orgs
       
   138     self.unlocked_orgs = unlocked_orgs
   122     self.unlocked_orgs = unlocked_orgs
   139     self.locked_orgs = locked_orgs
   123     self.locked_orgs = locked_orgs
   140     self.popularity = popularity
   124     self.popularity = popularity
   141     self.total_popularity = total_popularity
   125     self.total_popularity = total_popularity
   142 
   126 
   145     """
   129     """
   146 
   130 
   147     slots = int(math.floor(float(slots)))
   131     slots = int(math.floor(float(slots)))
   148     slots = min(slots, self.max_slots_per_org)
   132     slots = min(slots, self.max_slots_per_org)
   149     slots = max(slots, self.min_slots_per_org)
   133     slots = max(slots, self.min_slots_per_org)
   150     slots = min(slots, self.mentors[org])
   134     slots = min(slots, self.max[org])
   151 
   135 
   152     return slots
   136     return slots
   153 
   137 
   154   def iterativeAllocation(self):
   138   def iterativeAllocation(self):
   155     """A simple iterative algorithm.
   139     """A simple iterative algorithm.