from django.db.models import Q from django.utils.safestring import mark_safe from django.utils.html import escape from django.utils.timezone import localtime from datetime import datetime, timedelta from copy import deepcopy from collections import OrderedDict, namedtuple from itertools import islice from .models import Room from proposals.models import Talk Event = namedtuple('Event', ['talk', 'row', 'rowcount']) class Program: def __init__(self, site, empty_rooms=False, talk_filter=None): self.talks = Talk.objects.\ filter(site=site, room__isnull=False, start_date__isnull=False).\ filter(Q(duration__gt=0) | Q(event__duration__gt=0)).\ exclude(accepted=False).\ order_by('start_date') if talk_filter: self.talks = self.talks.filter(talk_filter) if empty_rooms: self.rooms = Room.objects.filter(site=site) else: self.rooms = Room.objects.filter(talk__in=self.talks.all()).order_by('name').distinct() self.days = {} for talk in self.talks.all(): duration = talk.estimated_duration assert(duration) dt1 = talk.start_date d1 = localtime(dt1).date() if d1 not in self.days.keys(): self.days[d1] = {'timeslots': []} dt2 = dt1 + timedelta(minutes=duration) d2 = localtime(dt2).date() if d2 not in self.days.keys(): self.days[d2] = {'timeslots': []} if dt1 not in self.days[d1]['timeslots']: self.days[d1]['timeslots'].append(dt1) if dt2 not in self.days[d2]['timeslots']: self.days[d2]['timeslots'].append(dt2) self.cols = OrderedDict([(room, 1) for room in self.rooms]) for day in self.days.keys(): self.days[day]['timeslots'] = sorted(self.days[day]['timeslots']) self.days[day]['rows'] = OrderedDict([(timeslot, OrderedDict([(room, []) for room in self.rooms])) for timeslot in self.days[day]['timeslots'][:-1]]) for talk in self.talks.all(): self._add_talk(talk) def _add_talk(self, talk): room = talk.room dt1 = talk.start_date d1 = localtime(dt1).date() dt2 = talk.start_date + timedelta(minutes=talk.estimated_duration) d2 = localtime(dt2).date() assert(d1 == d2) # this is a current limitation dt1 = self.days[d1]['timeslots'].index(dt1) dt2 = self.days[d1]['timeslots'].index(dt2) col = None for row, timeslot in enumerate(islice(self.days[d1]['timeslots'], dt1, dt2)): if col is None: col = 0 while col < len(self.days[d1]['rows'][timeslot][room]) and self.days[d1]['rows'][timeslot][room][col]: col += 1 self.cols[room] = max(self.cols[room], col+1) event = Event(talk=talk, row=row, rowcount=dt2-dt1) while len(self.days[d1]['rows'][timeslot][room]) <= col: self.days[d1]['rows'][timeslot][room].append(None) self.days[d1]['rows'][timeslot][room][col] = event def _header(self): output = '