Skip to content
Snippets Groups Projects
Commit 060570db authored by tuhe's avatar tuhe
Browse files

Added sections

parent a3596fca
No related branches found
No related tags found
No related merge requests found
...@@ -15,7 +15,7 @@ with open("README.md", "r", encoding="utf-8") as fh: ...@@ -15,7 +15,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
# beamer-slider # beamer-slider
setuptools.setup( setuptools.setup(
name="coursebox", name="coursebox",
version="0.1.18.6", version="0.1.18.8",
author="Tue Herlau", author="Tue Herlau",
author_email="tuhe@dtu.dk", author_email="tuhe@dtu.dk",
description="A course management system currently used at DTU", description="A course management system currently used at DTU",
......
Metadata-Version: 2.1 Metadata-Version: 2.1
Name: coursebox Name: coursebox
Version: 0.1.18.6 Version: 0.1.18.8
Summary: A course management system currently used at DTU Summary: A course management system currently used at DTU
Home-page: https://lab.compute.dtu.dk/tuhe/coursebox Home-page: https://lab.compute.dtu.dk/tuhe/coursebox
Author: Tue Herlau Author: Tue Herlau
......
...@@ -286,6 +286,8 @@ def class_information(verbose=False, ...@@ -286,6 +286,8 @@ def class_information(verbose=False,
info = pickle.load(f) info = pickle.load(f)
info = _update_with_core_conf(info) info = _update_with_core_conf(info)
return info return info
elif verbose:
print("Coursebox> Loaded configurations from file", paths['information.xlsx'])
course_number = core_conf['course_number'] course_number = core_conf['course_number']
piazza = 'https://piazza.com/dtu.dk/%s%s/%s' % (semester().lower(), year(), course_number) piazza = 'https://piazza.com/dtu.dk/%s%s/%s' % (semester().lower(), year(), course_number)
...@@ -294,6 +296,10 @@ def class_information(verbose=False, ...@@ -294,6 +296,10 @@ def class_information(verbose=False,
continuing_education_mode = core_conf['continuing_education_mode'] continuing_education_mode = core_conf['continuing_education_mode']
faq = xlsx_to_dicts(paths['information.xlsx'], sheet='faq') faq = xlsx_to_dicts(paths['information.xlsx'], sheet='faq')
# sections = xlsx_to_dicts(paths['information.xlsx'], sheet='teachers')
if (sections := xlsx_to_dicts(paths['information.xlsx'], sheet='sections')) is not None:
sections = {v['id']: v for v in sections}
d = {'year': year(), d = {'year': year(),
'piazza': piazza, # deprecated. 'piazza': piazza, # deprecated.
'course_number': course_number, 'course_number': course_number,
...@@ -436,10 +442,21 @@ def class_information(verbose=False, ...@@ -436,10 +442,21 @@ def class_information(verbose=False,
dd = timedelta(days=l.get('show_solutions_after', 1)) dd = timedelta(days=l.get('show_solutions_after', 1))
d['release_rules'][str(n)] = dict(start=date+dd, end=date+timedelta(days=2000)) d['release_rules'][str(n)] = dict(start=date+dd, end=date+timedelta(days=2000))
# Update with section information.
if sections is not None:
for l in d['lectures']:
# print(l['number'])
l['date_sections'] = {s['id'] : {'date': l['date'] + timedelta(days=int(s['lecture_date_delta']) ) } for s in sections.values() }
l['date_sections'] = {k: {**v, **date2format(v['date']) } for k, v in l['date_sections'].items() }
l['teacher_initials_sections'] = {k: v.strip() for k, v in zip( list( sections.keys() ), l['teacher_initials'].split("/") ) }
if update_with_core_conf: if update_with_core_conf:
d = _update_with_core_conf(d) d = _update_with_core_conf(d)
d['sections'] = sections
return d return d
def _update_with_core_conf(d): def _update_with_core_conf(d):
......
# -*- coding: utf-8 -*-
import shutil, os, glob import shutil, os, glob
from datetime import datetime, timedelta from datetime import datetime, timedelta
import calendar import calendar
import pickle import pickle
import time import time
# from line_profiler_pycharm import profile
from coursebox.thtools_base import partition_list from coursebox.thtools_base import partition_list
import slider import slider
from jinjafy import jinjafy_comment from jinjafy import jinjafy_comment
from jinjafy import jinjafy_template from jinjafy import jinjafy_template
...@@ -19,9 +16,12 @@ from coursebox.core.info import class_information ...@@ -19,9 +16,12 @@ from coursebox.core.info import class_information
from coursebox.material.lecture_questions import lecture_question_compiler from coursebox.material.lecture_questions import lecture_question_compiler
from slider import latexmk from slider import latexmk
import coursebox import coursebox
# from line_profiler_pycharm import profile import asyncio
import time
from jinjafy.cache.simplecache import hash_file_
import tempfile
def get_feedback_groups(): def get_feedback_groups(): # This is really getting deprecated...
paths = get_paths() paths = get_paths()
feedback_file = paths['semester'] +"/feedback_groups.pkl" feedback_file = paths['semester'] +"/feedback_groups.pkl"
if os.path.exists(feedback_file): if os.path.exists(feedback_file):
...@@ -67,15 +67,12 @@ def get_feedback_groups(): ...@@ -67,15 +67,12 @@ def get_feedback_groups():
with open(feedback_file, 'wb') as f: with open(feedback_file, 'wb') as f:
pickle.dump(fbg, f) pickle.dump(fbg, f)
for k in fbg: for k in fbg:
g = fbg[k] g = fbg[k]
g2 = [] g2 = []
for s in g: for s in g:
if s in info['students']: if s in info['students']:
dl = info['students'][s]['firstname'] + " " + info['students'][s]['lastname'] dl = info['students'][s]['firstname'] + " " + info['students'][s]['lastname']
# dl = [ss['firstname']+" "+ss['lastname'] for ss in if ss['id'] == s]
if not dl: if not dl:
print("EMPTY LIST when making feedback groups. Probably an error in project correction sheets.") print("EMPTY LIST when making feedback groups. Probably an error in project correction sheets.")
continue continue
...@@ -86,7 +83,7 @@ def get_feedback_groups(): ...@@ -86,7 +83,7 @@ def get_feedback_groups():
PRESENTATION = 0 PRESENTATION = 0
NOTES = 1 NOTES = 1
HANDOUT = 2 HANDOUT = 2
def make_lectures(week=None, mode=0, gather_pdf_out=True, gather_sixup=True, make_quizzes=True, dosvg=False, Linux=False): def make_lectures(week=None, mode=0, gather_pdf_out=True, gather_sixup=True, make_quizzes=True, dosvg=False, async_pool=-1):
""" """
Mode determines what is compiled into the pdfs. It can be: Mode determines what is compiled into the pdfs. It can be:
...@@ -94,6 +91,8 @@ def make_lectures(week=None, mode=0, gather_pdf_out=True, gather_sixup=True, mak ...@@ -94,6 +91,8 @@ def make_lectures(week=None, mode=0, gather_pdf_out=True, gather_sixup=True, mak
mode = NOTES = 1: Version containing notes (used for self-study) mode = NOTES = 1: Version containing notes (used for self-study)
mode = HANDOUT = 2: version handed out to students. mode = HANDOUT = 2: version handed out to students.
""" """
assert mode in [PRESENTATION, NOTES, HANDOUT]
paths = get_paths() paths = get_paths()
if os.path.exists(paths['book']): if os.path.exists(paths['book']):
book_frontpage_png = paths['shared']+"/figures/book.png" #paths['lectures']+"/static/book.png" book_frontpage_png = paths['shared']+"/figures/book.png" #paths['lectures']+"/static/book.png"
...@@ -104,54 +103,88 @@ def make_lectures(week=None, mode=0, gather_pdf_out=True, gather_sixup=True, mak ...@@ -104,54 +103,88 @@ def make_lectures(week=None, mode=0, gather_pdf_out=True, gather_sixup=True, mak
# course_number = info['course_number'] # course_number = info['course_number']
if isinstance(week, int): if isinstance(week, int):
week = [week] week = [week]
lectures_to_compile = [lecture for lecture in info['lectures'] if week is None or lecture['number'] in week]
t = time.time()
if async_pool <= 1:
all_pdfs = [] all_pdfs = []
for lecture in info['lectures']: for lecture in lectures_to_compile: #info['lectures']:
w = lecture['number'] pdf_out = _compile_single_lecture(dosvg=dosvg, lecture=lecture, make_quizzes=make_quizzes, mode=mode)
if week is not None and w not in week: all_pdfs.append( (lecture['number'], pdf_out))
continue else:
# Do the async here.
cp_tasks = []
for lecture in lectures_to_compile: #info['lectures']:
tsk = _compile_single_lecture_async(dosvg=dosvg, lecture=lecture, make_quizzes=make_quizzes, mode=mode)
cp_tasks.append(tsk)
loop = asyncio.get_event_loop()
cm = asyncio.gather(*cp_tasks)
results = loop.run_until_complete(cm)
all_pdfs = [ (lecture['number'], pdf) for (lecture, pdf) in zip( lectures_to_compile, results ) ]
# raise Exception("no async here")
# pass
t2 = time.time() - t
print("main compile, t1, t2", t2)
ag = get_feedback_groups() if mode == PRESENTATION:
odex = "/presentation"
elif mode == HANDOUT:
odex = "/handout"
elif mode == NOTES:
odex = "/notes"
else:
odex = None
t = time.time()
if len(all_pdfs) and gather_pdf_out > 0:
if async_pool >= 2:
# if len(all_pdfs) > 0 and gather_pdf_out:
async_handle_pdf_collection(paths, all_pdfs, gather_sixup=gather_sixup, odir=odex)
else:
# if len(all_pdfs) > 0:
handle_pdf_collection(paths, all_pdfs, gather_pdf_out=gather_pdf_out, gather_sixup=gather_sixup, odir=odex)
t2 = time.time() - t
print("t1, t2", t2)
a = 234
def _setup_lecture_info(lecture, mode, dosvg, make_quizzes):
w = lecture['number']
info = class_information()
paths = get_paths()
# if week is not None and w not in week:
# continue
ag = get_feedback_groups()
lecture['feedback_groups'] = ag.get(w, []) lecture['feedback_groups'] = ag.get(w, [])
info.update({'week': w}) info.update({'week': w})
info['lecture'] = lecture info['lecture'] = lecture
info['lecture']['teacher'] = [t for t in info['teachers'] if t['initials'] == lecture['teacher_initials']].pop() info['lecture']['teacher'] = [t for t in info['teachers'] if t['initials'] == lecture['teacher_initials']].pop()
lecture_texdir = paths['lectures'] + '/Lecture_%s/Latex' % w lecture_texdir = paths['lectures'] + '/Lecture_%s/Latex' % w
lecture_texfile = lecture_texdir + "/Lecture_%i.tex" % w lecture_texfile = lecture_texdir + "/Lecture_%i.tex" % w
fix_shared(paths, output_dir=lecture_texdir, dosvg=dosvg) fix_shared(paths, output_dir=lecture_texdir, dosvg=dosvg)
# if os.path.exists(lecture_texdir):
if os.path.exists(lecture_texdir): # print("Latex directory found for lecture %i: %s" % (w, lecture_texdir))
print("Latex directory found for lecture %i: %s"%(w,lecture_texdir)) # # lecture_texdir_generated = lecture_texdir + "/templates"
lecture_texdir_generated = lecture_texdir +"/templates" # # if not os.path.exists(lecture_texdir_generated):
if not os.path.exists(lecture_texdir_generated): # # os.mkdir(lecture_texdir_generated)
# shutil.rmtree(lecture_texdir_generated)
# time.sleep(0.2)
os.mkdir(lecture_texdir_generated)
if mode == PRESENTATION: if mode == PRESENTATION:
info['slides_shownotes'] = False info['slides_shownotes'] = False
info['slides_handout'] = False info['slides_handout'] = False
odex = "/presentation" # odex = "/presentation"
elif mode == HANDOUT: elif mode == HANDOUT:
info['slides_shownotes'] = False info['slides_shownotes'] = False
info['slides_handout'] = True info['slides_handout'] = True
info['slides_showsolutions'] = False info['slides_showsolutions'] = False
odex = "/handout" # odex = "/handout"
elif mode == NOTES: elif mode == NOTES:
info['slides_shownotes'] = True info['slides_shownotes'] = True
info['slides_handout'] = True info['slides_handout'] = True
odex = "/notes" # odex = "/notes"
else:
raise Exception("Mode not recognized")
for f in glob.glob(paths['lectures'] + "/templates/*.tex"): for f in glob.glob(paths['lectures'] + "/templates/*.tex"):
ex = "_partial.tex" ex = "_partial.tex"
if f.endswith(ex): if f.endswith(ex):
# print(info) jinjafy_template(info, file_in=f,
print("Building file", f) file_out=lecture_texdir + "/templates/" + os.path.basename(f)[:-len(ex)] + ".tex")
jinjafy_template(info, file_in=f, file_out=lecture_texdir + "/templates/"+os.path.basename(f)[:-len(ex)] + ".tex")
# Fix questions. # Fix questions.
qtarg = lecture_texdir + "/questions" qtarg = lecture_texdir + "/questions"
...@@ -159,26 +192,86 @@ def make_lectures(week=None, mode=0, gather_pdf_out=True, gather_sixup=True, mak ...@@ -159,26 +192,86 @@ def make_lectures(week=None, mode=0, gather_pdf_out=True, gather_sixup=True, mak
os.mkdir(qtarg) os.mkdir(qtarg)
for f in glob.glob(paths['lectures'] + "/static/questions/*"): for f in glob.glob(paths['lectures'] + "/static/questions/*"):
shutil.copy(f, qtarg) shutil.copy(f, qtarg)
# Fix questions for this lecture
if make_quizzes: if make_quizzes:
lecture_question_compiler(paths, info, lecture_texfile) lecture_question_compiler(paths, info, lecture_texfile)
print("Making file", lecture_texfile, Linux) return lecture_texfile
# pdf_out = slider.latexmk(lecture_texfile, Linux=Linux) pass
def _compile_single_lecture(dosvg, lecture, make_quizzes, mode):
lecture_texfile = _setup_lecture_info(lecture, mode, dosvg, make_quizzes)
# Fix questions for this lecture
try: try:
pdf_out = slider.latexmk(lecture_texfile, Linux=Linux) pdf_out = slider.latexmk(lecture_texfile)
except Exception as e: except Exception as e:
log = lecture_texfile[:-4] + ".log" log = lecture_texfile[:-4] + ".log"
print("loading log", log) print("loading log", log)
with open(log, 'r') as f: with open(log, 'r') as f:
print(f.read()) print(f.read())
raise e raise e
all_pdfs.append( (w,pdf_out)) return pdf_out
async def _compile_single_lecture_async(dosvg, lecture, make_quizzes, mode):
lecture_texfile = _setup_lecture_info(lecture, mode, dosvg, make_quizzes)
# Fix questions for this lecture
try:
pdf_out = slider.latexmk_async(lecture_texfile)
except Exception as e:
log = lecture_texfile[:-4] + ".log"
print("loading log", log)
with open(log, 'r') as f:
print(f.read())
raise e
return pdf_out
if len(all_pdfs) > 0:
handle_pdf_collection(paths, all_pdfs, gather_pdf_out=gather_pdf_out, gather_sixup=gather_sixup, odir=odex)
# http://piazza.com/dtu.dk/spring2023/02465/home # http://piazza.com/dtu.dk/spring2023/02465/home
def async_handle_pdf_collection(paths, all_pdfs, gather_sixup, odir):
# tmp_dir = paths['lectures'] + '/Collected/tmp'
# if not os.path.isdir(tmp_dir):
# os.mkdir(tmp_dir)
import tempfile
tasks = []
for sixup in [False, True]:
if sixup and not gather_sixup: continue
for (week, _) in all_pdfs:
tasks.append(_compile_single(paths, sixup, week))
loop = asyncio.get_event_loop()
cm = asyncio.gather(*tasks)
pdf_compiled_all_6up = loop.run_until_complete(cm)
for f in pdf_compiled_all_6up:
assert os.path.isfile(f)
for dpdf in pdf_compiled_all_6up:
output_dir = paths['pdf_out'] + odir
if not os.path.exists(output_dir):
os.makedirs(output_dir)
shutil.copy(dpdf, output_dir + "/" + os.path.basename(dpdf))
# for f in glob.glob(tmp_dir + "/*"):
# os.remove(f)
async def _compile_single(paths, sixup, week):
# tmp_dir = tempfile.gettempdir()
tmp_dir = tempfile.mkdtemp()
if True:
# with tempfile.TemporaryDirectory() as tmp_dir:
# if not os.path.isdir(tmp_dir):
# os.mkdir(tmp_dir)
collect_template = paths['lectures'] + "/Collected/lecture_collector_partial.tex"
sixup_str = "-6up" if sixup else ""
tv = {'week': week,
'pdffiles': [paths['lectures'] + '/Lecture_%s/Latex/Lecture_%s.pdf' % (week, week)]}
if sixup:
tv['sixup'] = sixup
tex_out_sixup = tmp_dir + "/Lecture_%i%s.tex" % (week, sixup_str)
jinjafy_comment(data=tv, file_in=collect_template, file_out=tex_out_sixup, jinja_tag=None)
dpdf = await slider.latexmk_async(tex_out_sixup, cleanup=True)
else:
dpdf = tv['pdffiles'][0]
return dpdf
def handle_pdf_collection(paths, all_pdfs, gather_pdf_out, gather_sixup, odir): def handle_pdf_collection(paths, all_pdfs, gather_pdf_out, gather_sixup, odir):
tmp_dir = paths['lectures'] + '/Collected/tmp' tmp_dir = paths['lectures'] + '/Collected/tmp'
...@@ -229,15 +322,13 @@ def compile_simple_files(paths, info, template_file_list, verbose=False): ...@@ -229,15 +322,13 @@ def compile_simple_files(paths, info, template_file_list, verbose=False):
latexmk(tex_out, pdf_out= paths['pdf_out'] + "/" + os.path.basename(tex_out)[:-4]+".pdf") latexmk(tex_out, pdf_out= paths['pdf_out'] + "/" + os.path.basename(tex_out)[:-4]+".pdf")
# rec_fix_shared(shared_base=paths['shared'], output_dir=output_dir) # rec_fix_shared(shared_base=paths['shared'], output_dir=output_dir)
import time
# import dirsync # import dirsync
# dirsync.sync(paths['shared'], output_dir, 'diff') # dirsync.sync(paths['shared'], output_dir, 'diff')
# Do smarter fixin' # Do smarter fixin'
from pathlib import Path from pathlib import Path
from jinjafy.cache.simplecache import hash_file_
# @profile # @profile
def get_hash_from_base(base): def get_hash_from_base(base):
...@@ -514,7 +605,7 @@ def slide_converter(week=None, verbose=True, clean_temporary_files=False, copy_t ...@@ -514,7 +605,7 @@ def slide_converter(week=None, verbose=True, clean_temporary_files=False, copy_t
pdf_out = texdir +"/Lecture_%i.pdf"%n pdf_out = texdir +"/Lecture_%i.pdf"%n
shutil.copyfile(pdf_in, pdf_out) shutil.copyfile(pdf_in, pdf_out)
print("operating...") print("Importing slides OSVGS slides since they were deleted...")
lecture_tex_out = li_import(pdf_out, output_dir=texdir) lecture_tex_out = li_import(pdf_out, output_dir=texdir)
print("Wrote new main file: " + lecture_tex_out) print("Wrote new main file: " + lecture_tex_out)
else: else:
...@@ -528,5 +619,4 @@ def slide_converter(week=None, verbose=True, clean_temporary_files=False, copy_t ...@@ -528,5 +619,4 @@ def slide_converter(week=None, verbose=True, clean_temporary_files=False, copy_t
clean_temporary_files=clean_temporary_files, clean_temporary_files=clean_temporary_files,
copy_template_resource_files=copy_template_resource_files, copy_template_resource_files=copy_template_resource_files,
fix_broken_osvg_files=fix_broken_osvg_files, **kwargs) fix_broken_osvg_files=fix_broken_osvg_files, **kwargs)
print("Slides converted!") print("Slides converted!")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment