def test_iterator(self): start = datetime(2011, 1, 1, 0) end = datetime(2011, 1, 2, 0) for raster in VALID_RASTER_VALUES: results = list(iterate_span(start, end, raster)) self.assertEqual(len(results), 24 * 60 / raster)
def all_slots(self, start=None, end=None): """ Returns the slots which exist with this timespan. Reserved or free. """ start, end = self.align_dates(start, end) if self.partly_available: for start, end in iterate_span(start, end, self.raster): yield start, end else: yield self.start, self.end
def availability(self): """Returns the availability in percent.""" if self.partly_available: total = sum(1 for s in self.all_slots()) else: total = 1 count = len(self.reserved_slots) for blocked_period in self._query_blocked_periods(): count += len(list(iterate_span(blocked_period.start, blocked_period.end, self.raster))) if total == count: return 0.0 if count == 0: return 100.0 return 100.0 - (float(count) / float(total) * 100.0)
def availability_partitions(self, scheduler): """Partitions the space between start and end into blocks of either free, blocked or reserved time. Each block has a percentage representing the space the block occupies compared to the size of the whole allocation. The blocks are ordered from start to end. Each block is an item with two values. The first being the percentage, the second being the type. The type can be one of None, 'reserved' or 'blocked'. So given an allocation that goes from 8 to 9 and a reservation that goes from 8:15 until 8:30 and a block that goes from 8:30 to 9:00 we get the following blocks: [ (25%, None), (25%, 'reserved'), (50%, 'blocked') ] This is useful to divide an allocation block into different divs on the frontend, indicating to the user which parts of an allocation are available for reservation. Makes sure to only display slots that are within it's resources first_hour/last_hour timespan. """ resource = get_resource_by_uuid(scheduler.uuid).getObject() min_start_resource = datetime.combine(self.start, time(resource.first_hour)) max_end_resource = datetime.combine(self.end, time(resource.last_hour)) display_start = max(min_start_resource, self.start) display_end = min(max_end_resource, self.end) reserved = dict((r.start, r) for r in self.reserved_slots if r.start >= display_start and r.end <= display_end) blocked = set() for blocked_period in self._query_blocked_periods(): blocked.update(start for start, end in iterate_span(max(blocked_period.start, display_start), min(blocked_period.end, display_end), self.raster)) if not (reserved or blocked): return [(100.0, None)] # Get the percentage one slot represents slots = list(self.all_slots(display_start, display_end)) step = 100.0 / float(len(slots)) # Create an entry for each slot with either True or False pieces = [] for slot in slots: piece = None if slot[0] in reserved: reserved_slot = reserved[slot[0]] token = reserved_slot.reservation_token reservation = scheduler.reservation_by_token(token).one() piece = ('reserved', reservation.description, reservation.id) elif slot[0] in blocked: piece = ('blocked', None) pieces.append(piece) # Group by the None/'reserved'/'blocked' values in the pieces and sum # up the percentage partitions = [] for flag, group in groupby(pieces, key=lambda p: p): percentage = len(list(group)) * step partitions.append([percentage, flag]) # Make sure to get rid of floating point rounding errors total = sum([p[0] for p in partitions]) diff = 100.0 - total partitions[-1:][0][0] -= diff return partitions
def availability_partitions(self, scheduler): """Partitions the space between start and end into blocks of either free, blocked or reserved time. Each block has a percentage representing the space the block occupies compared to the size of the whole allocation. The blocks are ordered from start to end. Each block is an item with two values. The first being the percentage, the second being the type. The type can be one of None, 'reserved' or 'blocked'. So given an allocation that goes from 8 to 9 and a reservation that goes from 8:15 until 8:30 and a block that goes from 8:30 to 9:00 we get the following blocks: [ (25%, None), (25%, 'reserved'), (50%, 'blocked') ] This is useful to divide an allocation block into different divs on the frontend, indicating to the user which parts of an allocation are available for reservation. Makes sure to only display slots that are within it's resources first_hour/last_hour timespan. """ resource = get_resource_by_uuid(scheduler.uuid).getObject() min_start_resource = datetime.combine(self.start, time(resource.first_hour)) max_end_resource = datetime.combine(self.end, time(resource.last_hour)) display_start = max(min_start_resource, self.start) display_end = min(max_end_resource, self.end) reserved = dict((r.start, r) for r in self.reserved_slots if r.start >= display_start and r.end <= display_end) blocked = set() for blocked_period in self._query_blocked_periods(): blocked.update( start for start, end in iterate_span( max(blocked_period.start, display_start), min(blocked_period.end, display_end), self.raster ) ) if not (reserved or blocked): return [(100.0, None)] # Get the percentage one slot represents slots = list(self.all_slots(display_start, display_end)) step = 100.0 / float(len(slots)) # Create an entry for each slot with either True or False pieces = [] for slot in slots: piece = None if slot[0] in reserved: reserved_slot = reserved[slot[0]] token = reserved_slot.reservation_token reservation = scheduler.reservation_by_token(token).one() piece = ("reserved", reservation.description, reservation.id) elif slot[0] in blocked: piece = ("blocked", None) pieces.append(piece) # Group by the None/'reserved'/'blocked' values in the pieces and sum # up the percentage partitions = [] for flag, group in groupby(pieces, key=lambda p: p): percentage = len(list(group)) * step partitions.append([percentage, flag]) # Make sure to get rid of floating point rounding errors total = sum([p[0] for p in partitions]) diff = 100.0 - total partitions[-1:][0][0] -= diff return partitions