feature: finished slide building process
This commit is contained in:
+59
-16
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
import shutil
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
@@ -9,19 +10,23 @@ from mistletoe import Document
|
||||
from tqdm import tqdm
|
||||
|
||||
from renderer.fifty_ohm_html_renderer import FiftyOhmHtmlRenderer
|
||||
from renderer.fifty_ohm_html_slide_renderer import FiftyOhmHtmlSlideRenderer
|
||||
|
||||
|
||||
class Build:
|
||||
def __init__(self):
|
||||
memory = Memory("./cache", verbose=0)
|
||||
self.env = Environment(loader=FileSystemLoader("templates/html"))
|
||||
self.env = Environment(loader=FileSystemLoader("templates/"))
|
||||
self.env.filters["shuffle_answers"] = self.__filter_shuffle_answers
|
||||
self.questions = self.__parse_katalog()
|
||||
|
||||
# Decorate the method with memory.cache
|
||||
self.__build_question = memory.cache(self.__build_question)
|
||||
self.__build_chapter = memory.cache(self.__build_chapter)
|
||||
self.__build_section = memory.cache(self.__build_section)
|
||||
self.__build_page = memory.cache(self.__build_page)
|
||||
self.__build_question = memory.cache(self.__build_question)
|
||||
self.__build_question_slide = memory.cache(self.__build_question_slide)
|
||||
self.__build_chapter = memory.cache(self.__build_chapter)
|
||||
self.__build_section = memory.cache(self.__build_section)
|
||||
self.__build_page = memory.cache(self.__build_page)
|
||||
self.__build_chapter_slidedeck = memory.cache(self.__build_chapter_slidedeck)
|
||||
|
||||
def __parse_katalog(self):
|
||||
with open("data/fragenkatalog3b.json") as fragenkatalog_file:
|
||||
@@ -42,10 +47,10 @@ class Build:
|
||||
return questions
|
||||
|
||||
# cached
|
||||
def __build_question(self, input):
|
||||
def __build_question(self, input, template_file="html/question.html"):
|
||||
"""Combines the original question dataset from BNetzA with our internal metadata"""
|
||||
|
||||
question_template = self.env.get_template("question.html")
|
||||
question_template = self.env.get_template(template_file)
|
||||
|
||||
with open("data/metadata.json") as metadata_file:
|
||||
metadata = json.load(metadata_file)
|
||||
@@ -89,9 +94,12 @@ class Build:
|
||||
answer_pictures=answer_pictures,
|
||||
)
|
||||
|
||||
def __build_question_slide(self, input):
|
||||
return self.__build_question(input, template_file="slide/question.html")
|
||||
|
||||
# cached
|
||||
def __build_page(self, content) :
|
||||
page_template = self.env.get_template("page.html")
|
||||
page_template = self.env.get_template("html/page.html")
|
||||
return page_template.render(content=content)
|
||||
|
||||
def __picture_handler(self, id):
|
||||
@@ -108,8 +116,8 @@ class Build:
|
||||
|
||||
# cached
|
||||
def __build_chapter(self, edition, edition_name, number, chapter, next_chapter=None):
|
||||
chapter_template = self.env.get_template("chapter.html")
|
||||
next_chapter_template = self.env.get_template("next_chapter.html")
|
||||
chapter_template = self.env.get_template("html/chapter.html")
|
||||
next_chapter_template = self.env.get_template("html/next_chapter.html")
|
||||
with open(f'build/{edition}_chapter_{chapter["ident"]}.html', 'w') as file:
|
||||
result = chapter_template.render(
|
||||
edition=edition,
|
||||
@@ -129,10 +137,10 @@ class Build:
|
||||
file.write(result)
|
||||
|
||||
# cached
|
||||
def __build_section(self, edition, edition_name, section, chapter, next_section=None, next_chapter=None):
|
||||
section_template = self.env.get_template("section.html")
|
||||
next_section_template = self.env.get_template("next_section.html")
|
||||
next_chapter_template = self.env.get_template("next_chapter.html")
|
||||
def __build_section(self, edition, edition_name, section, section_id, chapter, next_section=None, next_chapter=None):
|
||||
section_template = self.env.get_template("html/section.html")
|
||||
next_section_template = self.env.get_template("html/next_section.html")
|
||||
next_chapter_template = self.env.get_template("html/next_chapter.html")
|
||||
with open(f'build/{edition}_{section["ident"]}.html', 'w') as file:
|
||||
|
||||
with FiftyOhmHtmlRenderer(
|
||||
@@ -146,6 +154,7 @@ class Build:
|
||||
edition=edition,
|
||||
name=edition_name,
|
||||
section=section,
|
||||
section_id=section_id,
|
||||
chapter=chapter,
|
||||
)
|
||||
|
||||
@@ -164,8 +173,41 @@ class Build:
|
||||
result = BeautifulSoup(result, "html.parser").prettify()
|
||||
file.write(result)
|
||||
|
||||
def __build_chapter_slidedeck(self, edition, chapter, sections):
|
||||
with open(f'build/{edition}_slide_{chapter["ident"]}.html', 'w') as file:
|
||||
slide_template = self.env.get_template("slide/slide.html")
|
||||
help_template = self.env.get_template("slide/help.html")
|
||||
with FiftyOhmHtmlSlideRenderer(
|
||||
question_renderer=self.__build_question_slide,
|
||||
picture_handler=self.__picture_handler,
|
||||
photo_handler=self.__photo_handler
|
||||
) as renderer:
|
||||
result = "<section>\n"
|
||||
result += f'<section data-background="#DAEEFA">\n<h1>{chapter["title"]}</h1>\n</section>\n'
|
||||
result += help_template.render()
|
||||
result += "</section>\n"
|
||||
for section in sections:
|
||||
tmp = f'<section data-background="#DAEEFA">\n<h1>{section["title"]}</h1>\n</section>\n'
|
||||
tmp += renderer.render_wrapper(section["slide"])
|
||||
result += f"<section>{tmp}</section>\n"
|
||||
|
||||
result = slide_template.render(content=result)
|
||||
file.write(result)
|
||||
|
||||
def __filter_shuffle_answers(self, seq):
|
||||
answers = []
|
||||
firstrun = True
|
||||
for answer in seq:
|
||||
if firstrun:
|
||||
answers.append({"content": answer, "correct": True})
|
||||
firstrun = False
|
||||
else:
|
||||
answers.append({"content": answer, "correct": False})
|
||||
random.shuffle(answers)
|
||||
return answers
|
||||
|
||||
def __build_book_index(self, book):
|
||||
template = self.env.get_template("course_index.html")
|
||||
template = self.env.get_template("html/course_index.html")
|
||||
with open(f"build/{book['edition']}_course_index.html", "w") as file:
|
||||
result = template.render(
|
||||
book=book,
|
||||
@@ -185,10 +227,11 @@ class Build:
|
||||
for number, chapter in enumerate(tqdm(chapters, desc=f"Build Edition: {edition}"),1):
|
||||
next_chapter = chapters[number] if number < len(chapters) else None
|
||||
self.__build_chapter(edition, edition_name, number, chapter, next_chapter)
|
||||
self.__build_chapter_slidedeck(edition, chapter, chapter["sections"])
|
||||
|
||||
for i, section in enumerate(chapter["sections"],1) :
|
||||
next_section = chapter["sections"][i] if i < len(chapter["sections"]) else None
|
||||
self.__build_section(edition, edition_name, section, chapter, next_section, next_chapter)
|
||||
self.__build_section(edition, edition_name, section, i, chapter, next_section, next_chapter)
|
||||
|
||||
def build_assets(self):
|
||||
shutil.copytree("assets", "build/assets", dirs_exist_ok=True)
|
||||
@@ -0,0 +1,112 @@
|
||||
<section>
|
||||
<h3>Navigationshilfe</h3>
|
||||
<p>Diese Navigationshilfe zeigt die ersten Schritte zur Verwendung der Präsention. Sie kann mit ⟶ (Pfeiltaste
|
||||
rechts) übersprungen werden.</p>
|
||||
</section>
|
||||
<section style="font-size: smaller;">
|
||||
<h4>Navigation</h4>
|
||||
<div id="left">
|
||||
<p>Zwischen den Folien und Abschnitten kann man mittels der Pfeiltasten hin- und herspringen, dazu kann man auch
|
||||
die Pfeiltasten am Computer nutzen.</p>
|
||||
<img src="assets/images/slides/navigation.png" alt="Navigationspfeile für die Präsentation" />
|
||||
</div>
|
||||
<div id="right">
|
||||
<ul class="list">
|
||||
<li>Pfeil runter und hoch: Nächste / Vorherige Folie</li>
|
||||
<li>Pfeil rechts und links: Nächster / Vorheriger Abschnitt</li>
|
||||
<li>Leertaste oder „n“: Der Reihe nach alle Elemente in Folien aufdecken oder zur nächsten Folie blättern
|
||||
</li>
|
||||
<li>Shift-Leertaste oder „p“: Der Reihe nach Elemente rückwärts zudecken oder zur vorherigen Folie blättern
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<section style="font-size: smaller;">
|
||||
<h4>Weitere Funktionen</h4>
|
||||
<p>Mit ein paar Tastenkürzeln können weitere Funktionen aufgerufen werden. Die wichtigsten sind:</p>
|
||||
<dl>
|
||||
<dt>F1</dt>
|
||||
<dd>Help / Hilfe</dd>
|
||||
<dt>o</dt>
|
||||
<dd>Overview / Übersicht aller Folien</dd>
|
||||
<dt>s</dt>
|
||||
<dd>Speaker View / Referentenansicht</dd>
|
||||
<dt>f</dt>
|
||||
<dd>Full Screen / Vollbildmodus</dd>
|
||||
<dt>b</dt>
|
||||
<dd>Break, Black, Pause / Ausblenden der Präsentation</dd>
|
||||
<dt>Alt-Click</dt>
|
||||
<dd>In die Folie hin- oder herauszoomen</dd>
|
||||
</dl>
|
||||
</section>
|
||||
<section style="font-size: smaller;">
|
||||
<h4>Übersicht</h4>
|
||||
<div id="left">
|
||||
<p>Die Präsentation ist zweidimensional aufgebaut. Dadurch sind in Spalten die einzelnen Abschnitte eines
|
||||
Kapitels und in den Reihen die Folien zu den Abschnitten.</p>
|
||||
<p>Tippt man ein „o“ ein, bekommt man eine Übersicht über alle Folien des jeweiligen Kapitels. Das hilft
|
||||
sich zunächst einen Überblick zu verschaffen oder sich zu orientieren, wenn man das Gefühlt hat sich
|
||||
„verlaufen“ zu haben. Die Navigation erfolgt über die Pfeiltasten.</p>
|
||||
</div>
|
||||
<div id="right">
|
||||
<img src="assets/images/slides/overview.png" alt="Übersicht aller Folien" />
|
||||
<p>Durch Anklicken einer Folie wird diese präsentiert.</p>
|
||||
</div>
|
||||
</section>
|
||||
<section style="font-size: smaller;">
|
||||
<h4>Referentenansicht</h4>
|
||||
<div id="left">
|
||||
<img src="assets/images/slides/notes.png" alt="Referentenansicht" />
|
||||
<p>Tippt man ein „s“ ein, bekommt man ein neues Fenster, die Referentenansicht.</p>
|
||||
<p>Indem man „Layout“ auswählt, kann man zwischen verschieden Anordnungen der Elemente auswählen.</p>
|
||||
</div>
|
||||
<div id="right">
|
||||
<p>Die Referentenansicht bietet folgende Elemente:</p>
|
||||
<ul class="list">
|
||||
<li>Links sieht man die aktuelle Folie</li>
|
||||
<li>Rechts oben sieht man die nächste Folie</li>
|
||||
<li>Rechts in der Mitte Hilfsmittel zur Zeiteinteilung</li>
|
||||
<li>Rechts unten, die „Notizen für den Vortragenden“</li>
|
||||
<li>Unten die Pfeile zur Navigation</li>
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<section style="font-size: smaller;">
|
||||
<h3>Praxistipps zur Referentenansicht</h3>
|
||||
<ul class="list">
|
||||
<li>Wenn man mit einem Projektor arbeitet, stellt man im Betriebssystem die Nutzung von 2 Monitoren ein: Die
|
||||
Referentenansicht wird dann zum Beispiel auf dem Laptop angezeigt, während die Teilnehmer die
|
||||
Präsentation angezeigt bekommen.</li>
|
||||
<li>Bei einer Online-Präsentation, wie beispielsweise auf <a href="https://treff.darc.de/">TREFF.darc.de</a>
|
||||
präsentiert man den Browser-Tab und navigiert im „Speaker View“ Fenster.</li>
|
||||
<li>Die Referentenansicht bezieht sich immer auf ein Kapitel. Am Ende des Kapitels muss sie geschlossen
|
||||
werden, um im neuen Kapitel eine neue Referentenansicht zu öffnen.</li>
|
||||
<li>Um mit dem Mauszeiger etwas zu markieren oder den Zoom zu verwenden, muss mit der Maus auf den
|
||||
Bildschirm mit der Präsentation gewechselt werden.</li>
|
||||
</ul>
|
||||
</section>
|
||||
<section style="font-size: smaller;">
|
||||
<h4>Vollbild</h4>
|
||||
<p>Tippt man ein „f“ ein, wird die aktuelle Folie im Vollbild angezeigt. Mit „Esc“ kann man diesen wieder
|
||||
verlassen.</p>
|
||||
<p>Das ist insbesondere für den Bildschirm mit der Präsentation für das Publikum praktisch.</li>
|
||||
</section>
|
||||
<section style="font-size: smaller;">
|
||||
<h4>Ausblenden</h4>
|
||||
<p>Tippt man ein „b“ ein, wird die Präsentation ausgeblendet.</p>
|
||||
<p>Sie kann wie folgte wieder eingeblendet werden:</p>
|
||||
<ul class="list">
|
||||
<li>Durch klicken in das Fenster.</li>
|
||||
<li>Durch nochmaliges Drücken von „b“.</li>
|
||||
<li>Durch klicken der Schaltfläche „Resume presentation:</li>
|
||||
</ul>
|
||||
<img src="assets/images/slides/resume.png" alt="Schaltfläche für Resume Presentation" />
|
||||
</section>
|
||||
<section style="font-size: smaller;">
|
||||
<h4>Zoom</h4>
|
||||
<p>Bei gedrückter Alt-Taste und einem Mausklick in der Präsentation wird in diesen Teil hineingezoomt. Das ist
|
||||
praktisch, um Details von Schaltungen hervorzuheben. Durh einen nochmaligen Mausklick zusammen mit Alt wird
|
||||
wieder herausgezoomt.</p>
|
||||
<p>Das Zoomen funktioniert nur im ausgewählten Fenster. Die Referentenansicht ist hier nicht mit dem
|
||||
Präsenationsansicht gesynct.</p>
|
||||
</section>
|
||||
@@ -7,7 +7,7 @@
|
||||
{% endif -%}
|
||||
<div class="question-text">{{ number }}: {{ question }}</div>
|
||||
{% if picture_question -%}
|
||||
<div class="question-picture"><img class="r-stretch" src="picture/{{ picture_question }}.svg"></div>
|
||||
<div class="question-picture"><img class="r-stretch" src="pictures/{{ picture_question }}.svg"></div>
|
||||
{% endif -%}
|
||||
<div class="answers">
|
||||
{% if answers[0] -%}
|
||||
@@ -17,7 +17,7 @@
|
||||
{% endif -%}
|
||||
{% if answer_pictures[0] -%}
|
||||
{% for answer in answer_pictures|shuffle_answers -%}
|
||||
<div class="question-picture{% if not answer.correct %} fragment semi-fade-out{% endif -%}" {% if not answer.correct -%} data-fragment-index="1" {% endif -%}><b>{{ answer_label[loop.index - 1] }}:</b><img class="r-stretch" src="picture/{{ answer.content }}.svg"></div>
|
||||
<div class="question-picture{% if not answer.correct %} fragment semi-fade-out{% endif -%}" {% if not answer.correct -%} data-fragment-index="1" {% endif -%}><b>{{ answer_label[loop.index - 1] }}:</b><img class="r-stretch" src="pictures/{{ answer.content }}.svg"></div>
|
||||
{% endfor -%}
|
||||
{% endif -%}
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>DARC Ausbildungsplattform</title>
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link rel="stylesheet" href="assets/reveal.js/dist/reset.css">
|
||||
<link rel="stylesheet" href="assets/reveal.js/dist/reveal.css">
|
||||
<link rel="stylesheet" href="assets/style-slide.css">
|
||||
<!-- Theme used for syntax highlighting of code -->
|
||||
<link rel="stylesheet" href="assets/reveal.js/plugin/highlight/monokai.css">
|
||||
<!-- Chart plugin -->
|
||||
<script src="assets/reveal.js-plugins/chart/plugin.js"></script>
|
||||
<script src="assets/chartjs/4.4.1/chart.min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="reveal">
|
||||
<!-- Any section element inside of this container is displayed as a slide -->
|
||||
<div class="slides">
|
||||
{{ content }}
|
||||
</div>
|
||||
|
||||
<script src="assets/reveal.js/dist/reveal.js"></script>
|
||||
<script src="assets/reveal.js/plugin/zoom/zoom.js"></script>
|
||||
<script src="assets/reveal.js/plugin/notes/notes.js"></script>
|
||||
<script src="assets/reveal.js/plugin/search/search.js"></script>
|
||||
<script src="assets/reveal.js/plugin/markdown/markdown.js"></script>
|
||||
<script src="assets/reveal.js/plugin/highlight/highlight.js"></script>
|
||||
<script src="assets/reveal.js/plugin/math/math.js"></script>
|
||||
<script>
|
||||
|
||||
// Also available as an ES module, see:
|
||||
// https://revealjs.com/initialization/
|
||||
Reveal.initialize({
|
||||
controls: true,
|
||||
progress: true,
|
||||
slideNumber: 'c/t',
|
||||
showSlideNumber: 'speaker',
|
||||
center: true,
|
||||
hash: true,
|
||||
transition: 'slide',
|
||||
showNotes: false,
|
||||
pdfSeparateFragments: false,
|
||||
|
||||
// Learn about plugins: https://revealjs.com/plugins/
|
||||
plugins: [ RevealZoom, RevealNotes, RevealSearch, RevealMarkdown, RevealHighlight, RevealMath.KaTeX, RevealChart ]
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -39,13 +39,6 @@ def filter_shuffle_answers(seq):
|
||||
except Exception:
|
||||
return seq
|
||||
|
||||
|
||||
env = Environment(loader=FileSystemLoader("templates/"))
|
||||
env.filters["shuffle_answers"] = filter_shuffle_answers
|
||||
question_template = env.get_template("slide/question.html")
|
||||
questions = parse_katalog()
|
||||
|
||||
|
||||
def question_stub(input):
|
||||
"""Combines the original question dataset from BNetzA with our internal metadata"""
|
||||
with open("data/metadata.json") as metadata_file:
|
||||
@@ -84,77 +77,17 @@ def question_stub(input):
|
||||
answer_pictures=answer_pictures,
|
||||
)
|
||||
|
||||
def print_head():
|
||||
return """<! DOCTYPE html>
|
||||
<html lang="de"><head>
|
||||
<meta charset="utf-8">
|
||||
|
||||
<title>DARC Ausbildungsplattform</title>
|
||||
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<link rel="stylesheet" href="../assets/reveal.js/dist/reset.css">
|
||||
<link rel="stylesheet" href="../assets/reveal.js/dist/reveal.css">
|
||||
<link rel="stylesheet" href="../assets/style-slide.css">
|
||||
|
||||
<!-- Theme used for syntax highlighting of code -->
|
||||
<link rel="stylesheet" href="../assets/reveal.js/plugin/highlight/monokai.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="reveal">
|
||||
<div class="slides">
|
||||
"""
|
||||
|
||||
#<!-- Chart plugin -->
|
||||
#<script src="../assets/reveal.js-plugins/chart/plugin.js"></script>
|
||||
#<script src="../assets/chartjs/4.4.1/chart.min.js"></script>
|
||||
|
||||
def print_tail():
|
||||
return """</div>
|
||||
</div>
|
||||
<script src="../assets/reveal.js/dist/reveal.js"></script>
|
||||
<script src="../assets/reveal.js/plugin/zoom/zoom.js"></script>
|
||||
<script src="../assets/reveal.js/plugin/notes/notes.js"></script>
|
||||
<script src="../assets/reveal.js/plugin/search/search.js"></script>
|
||||
<script src="../assets/reveal.js/plugin/markdown/markdown.js"></script>
|
||||
<script src="../assets/reveal.js/plugin/highlight/highlight.js"></script>
|
||||
<script src="../assets/reveal.js/plugin/math/math.js"></script>
|
||||
<script>
|
||||
|
||||
// Also available as an ES module, see:
|
||||
// https://revealjs.com/initialization/
|
||||
Reveal.initialize({
|
||||
controls: true,
|
||||
progress: true,
|
||||
slideNumber: 'c/t',
|
||||
showSlideNumber: 'speaker',
|
||||
center: true,
|
||||
hash: true,
|
||||
transition: 'slide',
|
||||
showNotes: false,
|
||||
pdfSeparateFragments: false,
|
||||
|
||||
// Learn about plugins: https://revealjs.com/plugins/
|
||||
plugins: [ RevealZoom, RevealNotes, RevealSearch, RevealMarkdown, RevealHighlight, RevealMath.KaTeX] //, RevealChart ]
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>"""
|
||||
env = Environment(loader=FileSystemLoader("templates/"))
|
||||
env.filters["shuffle_answers"] = filter_shuffle_answers
|
||||
question_template = env.get_template("slide/question.html")
|
||||
slide_template = env.get_template("slide/slide.html")
|
||||
questions = parse_katalog()
|
||||
|
||||
def test_html_slides(capsys):
|
||||
with capsys.disabled():
|
||||
with open("test/acceptanceTestSlides.md") as file:
|
||||
content = file.read()
|
||||
with FiftyOhmHtmlSlideRenderer(question_stub) as renderer:
|
||||
output = ""
|
||||
output = print_head()
|
||||
output += renderer.render_wrapper(content)
|
||||
output += print_tail()
|
||||
with FiftyOhmHtmlSlideRenderer(question_renderer=question_stub) as renderer:
|
||||
output = renderer.render_wrapper(content)
|
||||
with open("test/acceptanceTestSlides.html", "w") as output_file:
|
||||
output_file.write(output)
|
||||
|
||||
Reference in New Issue
Block a user