86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
|
#!/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
|
||
|
SCHEDULE_URL = 'https://cfp.fairydust.reisen/iger-2022/schedule/export/schedule.json'
|
||
|
TIMEZONE = 'Europe/Berlin'
|
||
|
|
||
|
def parse_duration(s, num_parts):
|
||
|
duration = 0
|
||
|
for t in s.split(':', maxsplit=num_parts-1):
|
||
|
duration *= 60
|
||
|
duration += int(t)
|
||
|
|
||
|
return duration
|
||
|
|
||
|
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'], 2)*60)
|
||
|
if end_date is None or date > end_date:
|
||
|
end_date = date
|
||
|
|
||
|
event['end_date'] = date
|
||
|
|
||
|
timeline = []
|
||
|
timeslot = parse_duration(conference['timeslot_duration'], 2)
|
||
|
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()},
|
||
|
'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()
|