from django.core.management.base import BaseCommand from symposion.conference.models import Section, current_conference from symposion.schedule.models import (Day, Presentation, Room, SlotKind, Schedule, Slot, SlotRoom) from symposion.proposals.models import ProposalBase from dateutil.parser import parse from collections import Counter from pathlib import Path import csv class Command(BaseCommand): known_headers = ["date", "start time", "end time", "kind", "rooms"] SLOTS = 'slots' TALKS = 'talks' help = "Updates the schedule based on two csv files, "\ "one that gives all the talk slots, the other the talks." def add_arguments(self, parser): parser.add_argument(self.SLOTS, type=Path) parser.add_argument(self.TALKS, type=Path) def handle(self, *args, **options): date_strs = set() slotkind_names = set() room_names = set() slot_details = {} slot_type_count = Counter() conf = current_conference() section = Section.objects.filter(conference=conf, slug="main").all().first() schedule, _created = Schedule.objects.get_or_create(section=section) with open(options[self.SLOTS]) as csv_file: csv_reader = csv.reader(csv_file) headers = next(csv_reader) assert headers == self.known_headers for row in csv_reader: assert len(row) == len(self.known_headers) rowdate, start_time, end_time, kind, rooms = row slotkind_names.add(kind) if rowdate: date = rowdate date_strs.add(date) assert kind, "kind cannot be blank" slot_type_count[(date, kind)] += 1 kindslot = f"{kind} {slot_type_count[(date, kind)]}" for room in rooms.split(';'): room = room.strip() room_names.add(room) slot_details[(date, kindslot, room)] = (start_time, end_time) with open(options[self.TALKS]) as csv_file: csv_reader = csv.reader(csv_file) used_rooms = next(csv_reader) talks = {} assert used_rooms[0] == '', "Cell (1, 1) must be empty" for room in used_rooms[1:]: assert room in room_names, f"Unknown room: {room}" for row in csv_reader: cell = row[0] if cell.rsplit(' ', 1)[0] in slotkind_names: kindslot = cell for i, room in enumerate(used_rooms[1:], 1): talk_id = row[i] if not talk_id: continue assert (date, kindslot, room) in slot_details, f"Slot ({date}, '{kindslot}', '{room}') not found" talks[(date, kindslot, room)] = int(talk_id) else: assert parse(row[0]), "Not a date: {row[0]}" date = row[0] for col in row[1:]: assert col == '', f"All other columns must be empty: {date}" days = {} for date in date_strs: day, _created = Day.objects.get_or_create( schedule=schedule, date=date) days[date] = day rooms = {} for room_name in room_names: room, _created = Room.objects.get_or_create( schedule=schedule, name=room_name, order=used_rooms.index(room_name)) rooms[room_name] = room slotkinds = {} for slotkind_name in slotkind_names: slotkind, _created = SlotKind.objects.get_or_create(schedule=schedule, label=slotkind_name) slotkinds[slotkind_name] = slotkind slots = {} for details in slot_details: date, kindslot, room = details start_time, end_time = slot_details[details] kind_name = kindslot.rsplit(' ', 1)[0] # TODO this should not be hard coded exclusive = kind_name in ["plenary", "morning tea", "afternoon tea"] slot, _created = Slot.objects.get_or_create( day=days[date], kind=slotkinds[kind_name], start=start_time, end=end_time, exclusive=exclusive) slots[(date, kind_name, start_time, end_time)] = slot for details, talk_id in talks.items(): date, kindslot, room = details kind_name = kindslot.rsplit(' ', 1)[0] (start_time, end_time) = slot_details[(date, kindslot, room)] slot = slots[(date, kind_name, start_time, end_time)] slotroom = SlotRoom.objects.get_or_create(slot=slot, room=rooms[room]) proposal = ProposalBase.objects.filter(pk=talk_id).first() assert proposal, f"Could not find proposal {talk_id}" preso = Presentation.objects.filter(proposal_base=proposal).first() print(f'would like to set {preso} to slot {slot}') #preso.slot = slot preso.save()