Skip to content

Instantly share code, notes, and snippets.

@sharmaeklavya2
Last active July 23, 2017 11:11
Show Gist options
  • Save sharmaeklavya2/fa13d5955a2404942554 to your computer and use it in GitHub Desktop.
Save sharmaeklavya2/fa13d5955a2404942554 to your computer and use it in GitHub Desktop.
Script to make timetable in HTML using a list of sections
#/usr/bin/env python
'Generate Time Table'
from __future__ import print_function
import sys
import argparse
from collections import defaultdict
START_TIME = 8
# Time when classes start
DEFAULT_INDENT_STR = ' '
# Default indentation in HTML source
DEFAULT_TITLE = 'My timetable'
# Default text to show in <title> tag
DAY_INDEX = {
"M": 0,
"T": 1,
"W": 2,
"Th": 3,
"F": 4,
"S": 5,
}
DISP_DAYS = ["Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"]
# strings which will be shown in first column of the time table
STYLE_CLASS_MAP = {
"L": "lec",
"T": "tut",
"P": "prac",
"CH": "ch",
}
DEFAULT_STYLE = """
.lec
{color: black;}
.tut
{color: blue;}
.ch
{color: blue;}
.prac
{color: red;}
.clash
{background-color: #f2dede;}
.day, .timerow
{
color: grey;
font-size: 75%;
}
table
{
border: 1px solid black;
border-collapse: collapse;
}
td
{
border: 1px solid black;
padding: 2px 4px;
}
td.lunch
{border: none;}
"""
class CellPart:
subj = ''
sec = ''
room = ''
TEMPLATE = '{subj} {sec}\n{room}'
def __init__(self, subj, sec, room):
self.subj = subj
self.sec = sec
self.room = room
def get_styleclass(self):
return STYLE_CLASS_MAP.get(get_cls_type(self.sec), '')
def __str__(self):
return "CellPart({}, {}, {})".format(self.subj, self.sec, self.room)
def __repr__(self):
return str(self)
def render(self):
return CellPart.TEMPLATE.format(subj=self.subj, sec=self.sec, room=self.room)
class Cell:
"""
A Cell object corresponds to a cell in the timetable.
A Cell has multiple CellParts.
If the timetable is clash-free, there will be at most 1 CellPart in the Cell,
otherwise there can be multiple, each corresponding to a class scheduled at that time.
"""
parts = []
def __init__(self, parts=None):
self.parts = parts or []
def get_styleclass(self):
if len(self.parts) > 1:
return 'clash'
elif len(self.parts) == 0:
return None
else:
return self.parts[0].get_styleclass()
def __str__(self):
return 'Cell({})'.format(self.parts)
def __repr__(self):
return str(self)
def inner(self):
if len(self.parts) > 1:
res = '\n'.join(['<span class="{}">{}</span>'.format(
part.get_styleclass(), part.render()) for part in self.parts])
else:
res = '\n'.join([part.render() for part in self.parts])
return res.replace('\n', '<br />')
def outer(self):
styleclass = self.get_styleclass()
class_attr = '' if styleclass is None else ' class="{}"'.format(self.get_styleclass())
return '\t\t<td{}>{}</td>'.format(class_attr, self.inner())
def get_cls_type(mystr):
'Gets the longest prefix of mystr which does not contain any digit or special_char.'
for i, ch in enumerate(mystr):
if ch.isdigit() or ch in '?-':
return mystr[0:i]
return mystr
def read_sched(fname, min_hours=0):
"""
Reads a file fname and returns a matrix of Cell objects.
min_hours is the minimum number of hours to show in timetable.
"""
cell_parts = defaultdict(list)
myfile = open(fname)
for line in myfile:
line = line.split('#', 1)[0] # remove comments
parts = line.split()
if parts: # continue only if line was non-empty after removing comments
subj, sec, days_str, hours_str, room = parts[:5]
days = [DAY_INDEX[x] for x in days_str.split(',')]
hours = [int(x, 16) - 1 for x in hours_str.split(',')]
min_hours = max(min_hours, max(hours) + 1)
for day in days:
for hour in hours:
cell_parts[(day, hour)].append(CellPart(subj, sec, room))
tt = [[Cell(cell_parts[(day, hour)]) for hour in range(min_hours)] for day in range(len(DISP_DAYS))]
return tt
TIMECELL_TEMPLATE = '\t\t<td>{hour} ({beg}-{end})</td>'
HTML_TEMPLATE = """<!DOCTYPE html>
{comment}
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{title}</title>{styletag}
</head>
<body>
<table{tableattrs}>
<tr class="timerow">
<td></td>{timerow}
<td></td>
</tr>{tbody}
<tr class="timerow">
<td></td>{timerow}
<td></td>
</tr>
</table>
</body>
</html>"""
def tt_as_html(tt, style, indent=DEFAULT_INDENT_STR, title=None, comment=None):
""" Takes the 3D list created by read_sched and prints the timetable to stdout"""
title = title or DEFAULT_TITLE
comment = '<!-- {} -->'.format(comment) if comment else ''
if style:
styletag = '\n<style>{0}</style>'.format(style)
tableattrs = ''
else:
styletag = ''
tableattrs = ' border="1"'
min_hours = len(tt[0])
timerow = '\n' + '\n'.join([TIMECELL_TEMPLATE.format(
hour=i+1, beg=(i+START_TIME-1)%12+1, end=(i+8)%12+1) for i in range(min_hours)])
trs = []
for i, row in enumerate(tt):
daycell = '<td class="day">{day}</td>'.format(day=DISP_DAYS[i])
tds = '\n'.join([cell.outer() for cell in row])
tr = '\n\t<tr>\n\t\t{daycell}\n{tds}\n\t\t{daycell}\n\t</tr>'.format(
daycell=daycell, tds=tds)
trs.append(tr)
res = HTML_TEMPLATE.format(title=title, comment=comment, styletag=styletag,
tableattrs=tableattrs, timerow=timerow, tbody=''.join(trs))
return res.replace(' ', indent).replace('\t', indent)
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('file')
parser.add_argument('--title', default=DEFAULT_TITLE,
help='text to show in <title> tag')
parser.add_argument('--indent', default=DEFAULT_INDENT_STR,
help="""indent string to use in HTML source.
If this is an integer, use that many spaces.
Use '\\t' to specify tabs.""")
parser.add_argument('--min-hours', default=0, type=int,
help='minimum number of hours to show in timetable')
args = parser.parse_args()
fpath = args.file
try:
indent = ' ' * int(args.indent)
except ValueError:
indent = args.indent.replace('\\t', '\t')
style = DEFAULT_STYLE
print(tt_as_html(read_sched(fpath, args.min_hours), style, indent, args.title, comment=fpath))
if __name__=="__main__":
main()
#CS F213 Object Oriented Programming
OOP L2 T,Th,S 3 6109 Pankaj Vyas
OOP P3 Th 8,9 6018 Sunita Singhal
#CS F214 Logic in Computer Science
Logic L1 T,Th,S 5 5105 SHAN BALASUBRAMANIAM
Logic T2 T 2 6160 Vishal Gupta
#CS F215 Digital Design
DD L2 T,Th,S 4 5101 S MOHAN
DD P2 T 7,8,9 2241 Lucky Sharan, Priya Gupta
DD T1 M 1 2206 Sneh Lata Murotiya
#CS F222 Discrete Structures for Computer Science
Disco L1 M,W,F 7 6109 SK HAFIZUL ISLAM
Disco T3 W 1 6160 SK HAFIZUL ISLAM
#MATH F211 Mathematics III
Math3 L6 M,W,F 8 6153 Rakhee
Math3 CH6 S 1 6156 Rakhee
#GS F232 Introductory Psychology
Psycho L1 M,W,F 9 6105 TANU SHUKLA
#GS F321 Mass Media and Content Design
MMCD L1 M 3 6156 VIRENDRA SINGH NIRBAN
MMCD T1 W 2,3 6118 VIRENDRA SINGH NIRBAN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment