Skip to content

Instantly share code, notes, and snippets.

@dstanek
Last active April 18, 2016 14:35
Show Gist options
  • Save dstanek/b0c1e839b2dd937faff1f81728e51e27 to your computer and use it in GitHub Desktop.
Save dstanek/b0c1e839b2dd937faff1f81728e51e27 to your computer and use it in GitHub Desktop.
Code to take the OpenStack schedule that was downloaded from https://www.openstack.org/api/v1/summits/6/schedule and turn it into something almost usable.
#!/usr/bin/env python3
import collections
import datetime
import json
MIN_INC = 5
EVENT_CONTINUED = object()
EMPTY = object()
EMPTY_CONTINUED = object()
class Event:
def __init__(self, start, end, title, location):
format = '%Y-%m-%d %H:%M'
self.start = datetime.datetime.strptime(start.rsplit(':', 1)[0], format)
self.end = datetime.datetime.strptime(end.rsplit(':', 1)[0], format)
self.title = title
self.location = location
def __str__(self):
return '<div class="title">{}</div><div class="dates">{}-{}</div> in {}'.format(
self.title,
self.start.strftime('%H:%M'),
self.end.strftime('%H:%M'), self.location)
class Location:
def __init__(self, location_id):
self.location_id = location_id
self.events = {}
def add_event(self, e):
self.events[e.start] = e
def get_event_at(self, dt):
return self.events.get(dt)
class Table:
def __init__(self):
self.day_start = datetime.datetime.max
self.day_end = datetime.datetime.min
self.locations = {}
self.datetimes = set([])
def add_event(self, e):
location = self.locations.get(e.location)
if not location:
location = self.locations[e.location] = Location(e.location)
self.locations[e.location].add_event(e)
self.datetimes.add(e.start)
self.datetimes.add(e.end)
if e.start < self.day_start:
self.day_start = e.start
if e.end > self.day_end:
self.day_end = e.end
def draw(self):
times_map = {dt: n for n, dt in enumerate(sorted(self.datetimes))}
all_times = list(sorted(self.datetimes))
sorted_locations = [self.locations[_id] for _id in sorted(self.locations)]
col_cnt = len(sorted_locations) + 1
row_cnt = len(all_times)
num_cols = range(len(sorted_locations)+1)
num_rows = range(len(all_times))
table = [[None for _ in num_cols] for _ in num_rows]
for n, dt in enumerate(all_times):
table[n][0] = (dt.strftime('%H:%M'), 1)
cur_time_loc = times_map[dt]
for n_loc, location in enumerate(sorted_locations, start=1):
event = location.get_event_at(dt)
if event:
end_time_loc = times_map[event.end]
num_slots = end_time_loc - cur_time_loc
table[n][n_loc] = (event, num_slots)
if num_slots > 1:
for inc in range(1, num_slots):
table[n+inc][n_loc] = EVENT_CONTINUED
for n_row, row in enumerate(table):
for n_col, col in enumerate(row):
if col is None:
extra = 1
for x in range(n_row+1, row_cnt):
if table[x][n_col] is None:
table[x][n_col] = EMPTY_CONTINUED
extra +=1
else:
break
table[n_row][n_col] = (EMPTY, extra)
print('<table border="1" id="{}">'.format(self.date.strftime('%m-%d-%Y')))
print('<caption>Schedule for {}</caption'.format(self.date.strftime('%m-%d-%Y')))
print('<tr>')
print('<td>&nbsp;</td>')
for location in sorted_locations:
print('<td>{:d}</td>'.format(location.location_id))
print('</tr>')
for row in table:
print('<tr>')
for col in row:
if col in (EVENT_CONTINUED, EMPTY_CONTINUED):
continue
elif col[0] is EMPTY:
print('<td class="empty" rowspan="{:d}">&nbsp;</td>'.format(col[1]))
elif col:
event, slots = col
print('<td rowspan="{:d}">{}</td>'.format(slots, event))
else:
raise Exception # something broke
print('</tr>')
print('</table>')
@property
def date(self):
x = list(list(self.locations.values())[-1].events.values())[-1]
return x.start
class Page:
def __init__(self, tables):
self.tables = tables
def draw_nav(self):
print('<ul class="nav">')
for date in sorted(self.tables):
print('<li><a href="#{0}">{0}</a></li>'.format(date.strftime('%m-%d-%Y')))
print('</ul>')
def draw(self):
for date in sorted(self.tables):
self.tables[date].draw()
tables = collections.defaultdict(Table)
data = json.load(open('sched.json'))
for event in data['events']:
e = Event(event['start_datetime'],
event['end_datetime'],
event['title'],
event['location_id'])
tables[e.start.date()].add_event(e)
page = Page(tables)
print("""\
<html>
<head>
<style type="text/css">
table {
border-collapse: collapse;
margin: 2em 0;
overflow: scroll;
overflow-y: hidden;
width: 100%;
}
caption {
font-size: 1.25em;
text-align: left;
}
table tr td {
padding: .5em;
}
.empty {
background-color: lightgray;
}
ul.nav {
list-style-type: none;
margin: 0;
padding: 0;
}
ul.nav li {
display: inline;
padding-right: 1em;
}
</style>
</head>
<body>
""")
page.draw_nav()
page.draw()
print("""
</body>
</html>
""")
#!/usr/bin/env python3
import json
import requests
headers = {
'Cookie': '-*- Get this from your own browser session -*-',
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'en-US,en;q=0.8',
'If-None-Match': '-*- Get this from your own browser session -*-',
'Referer': 'https://www.openstack.org/summit/austin-2016/summit-schedule',
'X-Requested-With': 'XMLHttpRequest',
}
resp = requests.get('https://www.openstack.org/api/v1/summits/6/schedule', headers=headers)
print(json.dumps(resp.json()))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment