www.iger.events/bin/fetch_schedule.py

104 lines
3.4 KiB
Python
Executable File

#!/usr/bin/env python3
from datetime import datetime, timedelta
from json import dumps, loads
from pathlib import Path
from urllib.request import urlopen
from zoneinfo import ZoneInfo
GRANULARITY = 30
ROOM_SEQUENCE = ('Sondermaschinenbau', 'Smart City Schmiede', 'Sofaecke', 'Außenbereich', 'Rennstrecke', 'Cyberspace')
SCHEDULE_URL = 'https://cfp.fairydust.reisen/iger-2022/schedule/export/schedule.json'
TIMEZONE = 'Europe/Berlin'
def parse_duration(s):
duration = 0
components = s.split(':')
if len(components) == 3:
duration += int(components[0])
duration *= 24
components = components[1:]
if len(components) == 2:
duration += int(components[0])
duration *= 60
duration += int(components[1])
else:
raise RuntimeError(f'invalid duration format: {s}')
return duration
def room_sequence_key(room):
try:
return ROOM_SEQUENCE.index(room)
except ValueError:
return len(ROOM_SEQUENCE)
def main():
with urlopen(SCHEDULE_URL) as f:
data = loads(f.read())
conference = data['schedule']['conference']
rooms = {}
for day in conference['days']:
for room in conference['rooms']:
name = room['name']
if name not in day['rooms']:
continue
if name not in rooms:
rooms[name] = []
rooms[name] += day['rooms'][name]
timezone = ZoneInfo(TIMEZONE)
start_date = None
end_date = None
for _, events in rooms.items():
for event in events:
date = datetime.fromisoformat(event['date']).astimezone(timezone)
if start_date is None or date < start_date:
start_date = date
event['start_date'] = date
date += timedelta(seconds=parse_duration(event['duration'])*60)
if end_date is None or date > end_date:
end_date = date
event['end_date'] = date
timeline = []
timeslot = parse_duration(conference['timeslot_duration'])
for offset in range(0, int((end_date-start_date).total_seconds()), GRANULARITY*60):
date = start_date + timedelta(seconds=offset)
timeline.append({'date': date.strftime('%Y-%m-%d'), 'start': offset//(timeslot*60)+1, 'time': date.strftime('%H:%M')})
out_data = {
'days': [day['date'] for day in conference['days']],
'end_date': end_date.isoformat(timespec='seconds'),
'rooms': {name: [{
'end': int((event['end_date']-start_date).total_seconds())//(timeslot*60)+1,
'end_time': event['end_date'].strftime('%H:%M'),
'speaker': ', '.join(person['public_name'] for person in event['persons']),
'start': int((event['start_date']-start_date).total_seconds())//(timeslot*60)+1,
'start_time': event['start_date'].strftime('%H:%M'),
'title': event['title'],
'url': event['url'],
} for event in events] for name, events in rooms.items()},
'room_sequence': sorted(rooms.keys(), key=room_sequence_key),
'span': GRANULARITY // timeslot,
'start_date': start_date.isoformat(timespec='seconds'),
'timeline': timeline,
'timezone': TIMEZONE,
'version': data['schedule']['version'],
}
with open(Path(__file__).resolve().parent.parent / 'data' / 'schedule.json', 'w') as f:
f.write(dumps(out_data))
if __name__ == '__main__':
main()