In [1]:
from sessions import *
from venueordering import *
from pylatex_textboxes import *
from formatting_solver import *
In [2]:
import itertools as it
import pandas as pd
import datetime
In [3]:
df = pd.read_excel("con_data/items_03-28-2018.xlsx", )
df.loc[112,:]
Out[3]:
In [4]:
day2date = {
"Thursday":datetime.date(2018,3,29),
"Friday":datetime.date(2018,3,30),
"Saturday":datetime.date(2018,3,31),
"Sunday":datetime.date(2018,4,1),
"Monday":datetime.date(2018,4,2),
}
def load_grenadine_session(prog_item):
title = prog_item['Title']
print(title)
id = prog_item.name
date = day2date[prog_item['Day']]
start_time = datetime.datetime.strptime(prog_item["Time"], "%H:%M").time()
start = datetime.datetime.combine(date, start_time)
end = start + datetime.timedelta(minutes=int(prog_item["Duration"]))
people = prog_item["Participants"]
tags = prog_item["Tracks"].split(",")
tags.append(prog_item["Format"])
if title=="Lunch" or title=="Dinner":
tags.append("Break")
venues = [prog_item['Room']]
description = prog_item['Description']
return session(id, start, end, title, tags, people, venues, description)
def fetch_sessions(path):
df = pd.read_excel(path,keep_default_na=False) #keep_default_na stops emptystring being converted to nan
return [load_grenadine_session(df.loc[ii,:])
for ii in range(len(df))
if len(df.loc[ii,"Day"])>0 #must have Day set
]
In [5]:
def all_venues(sessions):
return set().union(*(ss.venues for ss in sessions))
def replace_room_with_rooms(sessions, old, *news):
for sess in sessions:
if old in sess.venues:
#print(sess.title)
sess.venues.remove(old)
sess.venues.update(news)
sessions
"Find multiple copies of events for different rooms at the same time, and convert them to single events in spanning rooms"
def bridge_rooms(sessions):
bridged_sessions = []
sessions.sort(key=lambda x: (x.start, x.end, x.title))
for _, matchs in it.groupby(sessions, lambda x: (x.start, x.end, x.title)):
matchs = list(matchs) #GoldPlate: this doesn't have to be done
head = matchs[0]
tail = matchs[1:]
for sess in tail:
head.venues.update(sess.venues)
bridged_sessions.append(head)
sessions[:]=bridged_sessions[:]
return sessions
def fill_empty_room_slots(sessions):
venues = all_venues(sessions)
for ss in sessions:
if len(ss.venues)==0:
print(ss.title)
ss.venues = venues
sessions
In [6]:
sessions = fetch_sessions("con_data/items_03-28-2018.xlsx")
In [7]:
# Remove sessions that are not really program items from the book's perspective
nonevent_rooms = set(["Meeting Room 1", 'Meetings on 5 foyer', 'Boardroom foyer'])
sessions = [sess for sess in sessions
if sess.venues==set() or sess.venues-nonevent_rooms != set()]
In [8]:
replace_room_with_rooms(sessions, 'Swan Rooms', 'Swan Room, Black', 'Swan Room, White')
bridge_rooms(sessions);
fill_empty_room_slots(sessions)
In [9]:
set(tuple(cc.venues) for cc in sessions)
Out[9]:
In [10]:
venue_order = ['West Grand River', 'East Grand River', 'Mount Newman','Pilbara', 'Boardroom (main floor)',
'Meeting Room 3', 'Meeting Room 5', 'Meeting Room 6', 'Meeting Room 7']
In [11]:
from pylatex.utils import escape_latex, NoEscape
from pylatex.utils import NoEscape
from pagelayout import Multicols
from itertools import groupby
from pylatex.base_classes import Environment
class Minipage(Environment):
def __init__(self, width):
Environment.__init__(self,arguments=[width])
def write_descriptions(sessions, doc):
for day_name, day_session in groupby(sessions, lambda ss: ss.day):
#with doc.create(Section(day_name,numbering=False)):
with doc.create(Multicols(2)):
doc.append(NoEscape("[\section*{%s}]" %day_name))
for session in day_session:
if len(session.description)==0:
continue
title = session.title
if "AdultsOnly" in session.tags:
title+=NoEscape(" [ADULT]")
with doc.create(Subsection(title,numbering=False)):
with doc.create(Description()) as desc:
doc.append(Command("setlength",[NoEscape("\itemsep"),"0pt"]))
doc.append(Command("setlength",[NoEscape("\parsep"),"0pt"]))
doc.append(Command("setlength",[NoEscape("\parskip"),"0pt"]))
desc.add_item("When:", session.day+", "+session.start_time+" – "+session.end_time)
if len(session.venues)>0:
desc.add_item("Where:", ", ".join(session.venues))
if len(session.people)>0:
desc.add_item("Who:", ", ".join(session.people))
#if len(session.tags)>0:
# desc.add_item("Tags:", ", ".join(session.tags))
doc.append(session.description)
doc.append(Command("newpage"))
In [12]:
import pylatex
from pylatex import Document, Section, Subsection, Subsubsection, Table, Package, lists
from pylatex.lists import Description
from pylatex.utils import escape_latex, NoEscape
from itertools import groupby
from pylatex.base_classes.command import Options
from pylatex.utils import escape_latex
def write_venues(doc, tt_solver):
doc.append(textpos_origin('0.9cm','1cm'))
doc.append(TextcolorboxStyle('sharp corners','center upper', valign='center',
colframe='blue!50!black',colback='blue!10!white',
boxsep='0pt',top='0mm',bottom='0mm',left='0mm',right='1mm'))
for venue in tt_solver.venues:
venue_words = venue.split()
if len(venue_words) == 2:
#Split the string onto two lines if it exactly 2 words
venue_text = venue_words[0] + '\n' + venue_words[1]
else:
venue_text = venue
doc.append(FixedTextbox(venue_text,
tt_solver.get_venue_x(venue),
'0cm',
'1.5cm',
tt_solver.get_venue_width())
)
def make_pretty_timetable(doc,sessions, tt_solver):
for date, day_sessions in groupby(sessions, lambda ss: ss.start.date()):
day_str = str(DAYS[date.weekday()])
with doc.create(Subsection(NoEscape(day_str+" \hfill "+day_str+" \hfill "+day_str), numbering=False)):
write_venues(doc,tt_solver)
doc.append(TextcolorboxStyle('rounded corners', 'center upper', valign='center',
colframe='blue!50!black',colback='white!10!white',
boxsep='1pt',top='0mm',bottom='0mm',left='0mm',right='0mm'))
day_sessions = sorted(day_sessions, key = lambda ss: -len(ss.venues) or -len(tt_solver.venues)-1)
for session in day_sessions:
#print("*", session.title)
colback = tt_solver.get_color(session)
tcb_options = Options(colback=colback) if colback else None
doc.append(FixedTextbox(NoEscape('%s \\\\ \\tcbfontsize{0.75} %s -- %s ' %
tuple(map(escape_latex, (session.title, session.start_time, session.end_time)))),
tt_solver.get_x(session),
tt_solver.get_y(session),
tt_solver.get_height(session),
tt_solver.get_width(session),
tcb_options=tcb_options))
doc.append(Command('newpage'))
In [13]:
doc = Document(documentclass="scrreprt")
margins=['tmargin=0.5cm','bmargin=1.5cm','lmargin=1.5cm','rmargin=1cm',]
doc.packages.append(Package('geometry', options=margins))
doc.packages.append(Package('xcolor', options=["svgnames","dvipsnames"]))
doc.packages.append(Package("microtype"))
#doc.packages.append(Package("draftwatermark"))
doc.append(Command("newgeometry",arguments=",".join(margins)))
#doc.append(Command("SetWatermarkText", "Draft v0.7.0"))
#doc.append(Command("SetWatermarkScale", "0.5"))
#doc.append(Command("SetWatermarkColor", "0.9,0.3,0.3", "rgb"))
#############
tt_solver = timetable_metric_solver(sessions,
hour_len=1.7,
venue_width=2.15,
units='cm',
overlap=0.05,
voffset=1.7,
venue_order = venue_order,
get_tag_colors = get_tag_colors_mono
)
make_pretty_timetable(doc,sessions, tt_solver)
write_descriptions(sessions,doc)
###############
with open("out/exported.tex", 'w') as fh:
doc.dump(fh)
#####
from IPython.display import FileLink, FileLinks
#!lualatex --output-directory=out --interaction=nonstopmode out/exported.tex
FileLinks("./out")
Out[13]:
In [ ]:
In [14]:
sessions[12].people
Out[14]:
In [15]:
#ROOMs/DAYS
import pylatex
from pylatex import Document, Section, Subsection, Subsubsection, Table, Package,lists
from pylatex.lists import Description
from pylatex.base_classes import Command
from itertools import groupby
from collections import defaultdict
vds = defaultdict(lambda : defaultdict(list))
for date, day_sessions in groupby(sessions, lambda ss: ss.start.date()):
for sess in day_sessions:
for venue in sess.venues:
vds[venue][date].append(sess)
#################################
doc = Document(documentclass="article")
doc.packages.append(Package('enumitem'))
doc.packages.append(Package('calc'))
doc.append(NoEscape(r"\setlist[description]{leftmargin=!,labelwidth=\widthof{\bfseries 13:00 – 14:00}}"))
for venue in vds.keys():
doc.append(Command("newpage"))
doc.append(Command("pagestyle","empty"))
doc.append(Command("LARGE"))
doc.append(NoEscape(r"\renewcommand{\familydefault}{\sfdefault}"))
for date in sorted(vds[venue]):
day = DAYS[date.weekday()]
with doc.create(Section(NoEscape("\Huge %s\\\\ %s" % (day,venue)), numbering=False)):
with doc.create(Description()) as sched:
sesses = sorted(vds[venue][date], key=lambda ss: ss.start)
for sess in sesses:
sched.add_item(NoEscape("%s – %s" % (sess.start_time, sess.end_time)), sess.title)
doc.append(Command("newpage"))
from IPython.display import FileLink, FileLinks
with open("out/exported_days.tex", 'w') as temp_out:
doc.dump(temp_out)
#!lualatex --output-directory=out --interaction=nonstopmode exported_days.tex
FileLinks("./out")
Out[15]:
In [ ]:
In [ ]: