@@ -38,7 +38,7 @@
|
|||||||
if (!value) return [];
|
if (!value) return [];
|
||||||
var seen = new Set();
|
var seen = new Set();
|
||||||
return value.toUpperCase().split(/[\s+,]+/).filter(function (questionId) {
|
return value.toUpperCase().split(/[\s+,]+/).filter(function (questionId) {
|
||||||
if (!/^[A-Z]{2}\d{3}$/.test(questionId) || seen.has(questionId)) return false;
|
if (!/^[A-Z]{2,3}\d{3}$/.test(questionId) || seen.has(questionId)) return false;
|
||||||
seen.add(questionId);
|
seen.add(questionId);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var COURSE_CHOICES = [
|
var COURSE_CHOICES = [
|
||||||
|
{ edition: "SWL", label: "SWL-Kurs", detail: "Kurzwellenhören", color: "#FFFFFF" },
|
||||||
{ edition: "N", label: "N-Kurs", detail: "N", color: "#47ABE8" },
|
{ edition: "N", label: "N-Kurs", detail: "N", color: "#47ABE8" },
|
||||||
{ edition: "NE", label: "E-Kurs", detail: "N + E", color: "#FE756C" },
|
{ edition: "NE", label: "E-Kurs", detail: "N + E", color: "#FE756C" },
|
||||||
{ edition: "NEA", label: "A-Kurs", detail: "N + E + A", color: "#3BB583" },
|
{ edition: "NEA", label: "A-Kurs", detail: "N + E + A", color: "#3BB583" },
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
|
|
||||||
function walk(section, sectionIndex, category) {
|
function walk(section, sectionIndex, category) {
|
||||||
(section.questions || []).forEach(function (question) {
|
(section.questions || []).forEach(function (question) {
|
||||||
var part = sectionIndex === 0
|
var part = String(question.class) === "SWL"
|
||||||
? partForClass[String(question.class)]
|
? "SWL"
|
||||||
: partForSection[sectionIndex];
|
: (sectionIndex === 0 ? partForClass[String(question.class)] : partForSection[sectionIndex]);
|
||||||
if (!part) return;
|
if (!part) return;
|
||||||
|
|
||||||
var questionMetadata = metadata[question.number] || {};
|
var questionMetadata = metadata[question.number] || {};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ conf = config.Config()
|
|||||||
# Build Everything:
|
# Build Everything:
|
||||||
bd = build.Build(conf)
|
bd = build.Build(conf)
|
||||||
bd.build_website()
|
bd.build_website()
|
||||||
|
bd.build_edition("SWL")
|
||||||
bd.build_edition("N")
|
bd.build_edition("N")
|
||||||
bd.build_edition("E")
|
bd.build_edition("E")
|
||||||
bd.build_edition("A")
|
bd.build_edition("A")
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ app = typer.Typer()
|
|||||||
@app.command()
|
@app.command()
|
||||||
def main(
|
def main(
|
||||||
edition: Annotated[list[Edition], typer.Option(help="Edition to build, can be specified multiple times.")] = [ # noqa: B006 -- default value is required for typer
|
edition: Annotated[list[Edition], typer.Option(help="Edition to build, can be specified multiple times.")] = [ # noqa: B006 -- default value is required for typer
|
||||||
|
Edition.swl,
|
||||||
Edition.n,
|
Edition.n,
|
||||||
Edition.e,
|
Edition.e,
|
||||||
Edition.a,
|
Edition.a,
|
||||||
|
|||||||
+40
-8
@@ -26,10 +26,32 @@ class Build:
|
|||||||
self.env.filters["shuffle_answers"] = self.__filter_shuffle_answers
|
self.env.filters["shuffle_answers"] = self.__filter_shuffle_answers
|
||||||
with self.config.p_data_fragenkatalog.open(encoding="utf-8") as file:
|
with self.config.p_data_fragenkatalog.open(encoding="utf-8") as file:
|
||||||
self.fragenkatalog = json.load(file)
|
self.fragenkatalog = json.load(file)
|
||||||
|
|
||||||
|
supplemental_questions = {}
|
||||||
|
if self.config.p_data_fragenkatalog_swl.exists():
|
||||||
|
with self.config.p_data_fragenkatalog_swl.open(encoding="utf-8") as file:
|
||||||
|
swl_fragenkatalog = json.load(file)
|
||||||
|
supplemental_questions = self.__parse_katalog(swl_fragenkatalog)
|
||||||
|
self.fragenkatalog["sections"].extend(swl_fragenkatalog.get("sections", []))
|
||||||
|
|
||||||
with self.config.p_data_metadata.open(encoding="utf-8") as file:
|
with self.config.p_data_metadata.open(encoding="utf-8") as file:
|
||||||
self.question_metadata = json.load(file)
|
self.question_metadata = json.load(file)
|
||||||
self.questions = self.__parse_katalog(self.fragenkatalog)
|
self.questions = self.__parse_katalog(self.fragenkatalog)
|
||||||
|
|
||||||
|
for number in supplemental_questions:
|
||||||
|
self.question_metadata.setdefault(
|
||||||
|
number,
|
||||||
|
{
|
||||||
|
"directus_id": "",
|
||||||
|
"picture_question": "",
|
||||||
|
"picture_a": "",
|
||||||
|
"picture_b": "",
|
||||||
|
"picture_c": "",
|
||||||
|
"picture_d": "",
|
||||||
|
"layout": "",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
self.question_index = {}
|
self.question_index = {}
|
||||||
self.question_token_pattern = re.compile(r"^\s*\[question:([\w\d]+)\]", re.MULTILINE)
|
self.question_token_pattern = re.compile(r"^\s*\[question:([\w\d]+)\]", re.MULTILINE)
|
||||||
|
|
||||||
@@ -143,8 +165,10 @@ class Build:
|
|||||||
|
|
||||||
def __build_exam_simulator(self):
|
def __build_exam_simulator(self):
|
||||||
self.config.p_build_assets.mkdir(parents=True, exist_ok=True)
|
self.config.p_build_assets.mkdir(parents=True, exist_ok=True)
|
||||||
shutil.copyfile(self.config.p_data_fragenkatalog, self.config.p_build_assets / "fragenkatalog.json")
|
with (self.config.p_build_assets / "fragenkatalog.json").open("w", encoding="utf-8") as file:
|
||||||
shutil.copyfile(self.config.p_data_metadata, self.config.p_build_assets / "metadata.json")
|
json.dump(self.fragenkatalog, file, ensure_ascii=False, indent=4)
|
||||||
|
with (self.config.p_build_assets / "metadata.json").open("w", encoding="utf-8") as file:
|
||||||
|
json.dump(self.question_metadata, file, ensure_ascii=False, indent=4)
|
||||||
(self.config.p_build_assets / "exam-questions.json").unlink(missing_ok=True)
|
(self.config.p_build_assets / "exam-questions.json").unlink(missing_ok=True)
|
||||||
|
|
||||||
picture_fields = ("picture_question", "picture_a", "picture_b", "picture_c", "picture_d")
|
picture_fields = ("picture_question", "picture_a", "picture_b", "picture_c", "picture_d")
|
||||||
@@ -191,8 +215,11 @@ class Build:
|
|||||||
def __build_homework_tool(self):
|
def __build_homework_tool(self):
|
||||||
toc_target = self.config.p_build_assets / "toc"
|
toc_target = self.config.p_build_assets / "toc"
|
||||||
toc_target.mkdir(parents=True, exist_ok=True)
|
toc_target.mkdir(parents=True, exist_ok=True)
|
||||||
for edition in ("N", "NE", "NEA", "E", "EA", "A"):
|
for edition in ("SWL", "N", "NE", "NEA", "E", "EA", "A"):
|
||||||
shutil.copyfile(self.config.p_data_toc / f"{edition}.json", toc_target / f"{edition}.json")
|
source = self.config.p_data_toc / f"{edition}.json"
|
||||||
|
if not source.exists():
|
||||||
|
source = self.config.p_data_toc / f"{edition.lower()}.json"
|
||||||
|
shutil.copyfile(source, toc_target / f"{edition}.json")
|
||||||
|
|
||||||
homework_template = self.env.get_template("html/homework.html")
|
homework_template = self.env.get_template("html/homework.html")
|
||||||
page = self.__build_page(
|
page = self.__build_page(
|
||||||
@@ -415,9 +442,12 @@ class Build:
|
|||||||
self.config.p_build.mkdir(exist_ok=True)
|
self.config.p_build.mkdir(exist_ok=True)
|
||||||
|
|
||||||
edition = edition.upper()
|
edition = edition.upper()
|
||||||
|
toc_file = self.config.p_data_toc / f"{edition}.json"
|
||||||
|
if not toc_file.exists():
|
||||||
|
toc_file = self.config.p_data_toc / f"{edition.lower()}.json"
|
||||||
|
|
||||||
with (
|
with (
|
||||||
(self.config.p_data_toc / f"{edition}.json").open(encoding="utf-8") as file,
|
toc_file.open(encoding="utf-8") as file,
|
||||||
Progress(
|
Progress(
|
||||||
TaskProgressColumn(),
|
TaskProgressColumn(),
|
||||||
BarColumn(),
|
BarColumn(),
|
||||||
@@ -456,9 +486,11 @@ class Build:
|
|||||||
with (self.config.p_data_sections / f"{ident}.md").open(encoding="utf-8") as sfile:
|
with (self.config.p_data_sections / f"{ident}.md").open(encoding="utf-8") as sfile:
|
||||||
section_content = sfile.read()
|
section_content = sfile.read()
|
||||||
section["content"] = section_content
|
section["content"] = section_content
|
||||||
with (self.config.p_data_slides / f"{ident}.md").open(encoding="utf-8") as sfile:
|
slide_file = self.config.p_data_slides / f"{ident}.md"
|
||||||
section_content = sfile.read()
|
if slide_file.exists():
|
||||||
section["slide"] = section_content
|
with slide_file.open(encoding="utf-8") as sfile:
|
||||||
|
section_content = sfile.read()
|
||||||
|
section["slide"] = section_content
|
||||||
|
|
||||||
if section["content"] is not None:
|
if section["content"] is not None:
|
||||||
self.__collect_question_occurrences(
|
self.__collect_question_occurrences(
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class Config:
|
|||||||
self.p_data_solutions = self.p_data_contents / "solutions"
|
self.p_data_solutions = self.p_data_contents / "solutions"
|
||||||
|
|
||||||
self.p_data_fragenkatalog = self.p_data_questions / "fragenkatalog3b.json"
|
self.p_data_fragenkatalog = self.p_data_questions / "fragenkatalog3b.json"
|
||||||
|
self.p_data_fragenkatalog_swl = self.p_data_questions / "fragenkatalog_swl.json"
|
||||||
self.p_data_metadata = self.p_data_questions / "metadata3b.json"
|
self.p_data_metadata = self.p_data_questions / "metadata3b.json"
|
||||||
|
|
||||||
self.p_build = Path(self.get_config_value("output", "./build") if build_path is None else build_path)
|
self.p_build = Path(self.get_config_value("output", "./build") if build_path is None else build_path)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from enum import StrEnum
|
|||||||
|
|
||||||
|
|
||||||
class Edition(StrEnum):
|
class Edition(StrEnum):
|
||||||
|
swl = "SWL"
|
||||||
n = "N"
|
n = "N"
|
||||||
e = "E"
|
e = "E"
|
||||||
a = "A"
|
a = "A"
|
||||||
|
|||||||
+28
-20
@@ -92,6 +92,12 @@
|
|||||||
<div class="col"><a href="A_course_index.html" class="btn w-100 text-white" style="background-color: #3BB583; border-color: #3BB583;">E -> A</a></div>
|
<div class="col"><a href="A_course_index.html" class="btn w-100 text-white" style="background-color: #3BB583; border-color: #3BB583;">E -> A</a></div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
|
<h5>Kurs für die DARC-SWL-Prüfung</h5>
|
||||||
|
<p>Du möchtest erst einmal im Amateurfunk zuhören? Als DARC-Mitglied kannst du nach der DE-Prüfung ein persönliches DE-Kennzeichen erhalten und SWL-QSL-Karten über die DARC-QSL-Vermittlung versenden.</p>
|
||||||
|
<div class="row row-cols-lg-1 g-2">
|
||||||
|
<div class="col"><a href="SWL_course_index.html" class="btn btn-outline-dark w-100">SWL<br><small>Kurzwellenhören</small></a></div>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
<h5>Fragestunden</h5>
|
<h5>Fragestunden</h5>
|
||||||
<p>Tauchen beim Selbststudium Fragen auf? Unsere ehrenamtlichen Helfer bieten für DARC-Mitglieder und Gäste eine Fragestunde Mittwochs um 19:00 Uhr und Sonntags um 18:00 Uhr auf dem DARC-Videokonferenzserver an.</p>
|
<p>Tauchen beim Selbststudium Fragen auf? Unsere ehrenamtlichen Helfer bieten für DARC-Mitglieder und Gäste eine Fragestunde Mittwochs um 19:00 Uhr und Sonntags um 18:00 Uhr auf dem DARC-Videokonferenzserver an.</p>
|
||||||
<div class="row row-cols-lg-2">
|
<div class="row row-cols-lg-2">
|
||||||
@@ -101,7 +107,7 @@
|
|||||||
<br>
|
<br>
|
||||||
<h5>DARC Chat</h5>
|
<h5>DARC Chat</h5>
|
||||||
<p>Der DARC e. V. betreibt eine eigene Matrix-Instanz. Dort gibt es einen Raum, in dem du deine Fragen stellen kannst:</p>
|
<p>Der DARC e. V. betreibt eine eigene Matrix-Instanz. Dort gibt es einen Raum, in dem du deine Fragen stellen kannst:</p>
|
||||||
<div class="row row-cols-lg-3">
|
<div class="row row-cols-lg-1">
|
||||||
<div class="col"><a href="https://matrix.to/#/#ausbildung:darc.de" class="btn btn-outline-dark w-100">💬 Ausbildung</a></div>
|
<div class="col"><a href="https://matrix.to/#/#ausbildung:darc.de" class="btn btn-outline-dark w-100">💬 Ausbildung</a></div>
|
||||||
</div>
|
</div>
|
||||||
<br>
|
<br>
|
||||||
@@ -113,17 +119,18 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col col-lg-8 row g-5 pb-5 m-0 row-cols-1 row-cols-lg-2">
|
<div class="col col-lg-8">
|
||||||
<div class="feature col">
|
<div class="row g-5 pb-5 row-cols-1 row-cols-lg-2">
|
||||||
|
<div class="feature col">
|
||||||
<div class="feature-icon bg-primary bg-gradient">
|
<div class="feature-icon bg-primary bg-gradient">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="#5f6368"><path d="m380-300 280-180-280-180v360ZM160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm0-80h640v-480H160v480Zm0 0v-480 480Z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" height="48" viewBox="0 -960 960 960" width="48" fill="#5f6368"><path d="m380-300 280-180-280-180v360ZM160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h640q33 0 56.5 23.5T880-720v480q0 33-23.5 56.5T800-160H160Zm0-80h640v-480H160v480Zm0 0v-480 480Z"/></svg>
|
||||||
</div>
|
</div>
|
||||||
<h2>Videokurse</h2>
|
<h2>Videokurse</h2>
|
||||||
<p>In Zusammenarbeit mit DL2YMR ist ein Videokurs für die Klasse N entstanden, der auf seinem YouTube-Kanal abrufbar ist. Weiterhin gibt es noch Vorlesungen für N+E sowie A. </p>
|
<p>In Zusammenarbeit mit DL2YMR ist ein Videokurs für die Klasse N entstanden, der auf seinem YouTube-Kanal abrufbar ist. Weiterhin gibt es noch Vorlesungen für N+E sowie A. </p>
|
||||||
<div class="d-grid gap-2 d-sm-flex flex-sm-wrap mb-5">
|
<div class="row row-cols-lg-3 g-2">
|
||||||
<a href="https://www.youtube.com/playlist?list=PLDpWnjHk5ERbcgpLPUaU0iTsD-wrmfENk" class="btn btn-outline-dark">Zum Videokurs Klasse N</a>
|
<div class="col"><a href="https://www.youtube.com/playlist?list=PLDpWnjHk5ERbcgpLPUaU0iTsD-wrmfENk" class="btn btn-outline-dark w-100">Videokurs<br><small>Klasse N</small></a></div>
|
||||||
<a href="https://www.youtube.com/playlist?list=PL_JZo16Mzs5XGeN5N81MwQ70dp7478VkM" class="btn btn-outline-dark">Vorlesung Klasse N+E</a>
|
<div class="col"><a href="https://www.youtube.com/playlist?list=PL_JZo16Mzs5XGeN5N81MwQ70dp7478VkM" class="btn btn-outline-dark w-100">Vorlesung<br><small>Klasse N+E</small></a></div>
|
||||||
<a href="https://www.youtube.com/playlist?list=PL_JZo16Mzs5XebdJhoIDLNp1MObBy7F5d" class="btn btn-outline-dark">Vorlesung Klasse A</a>
|
<div class="col"><a href="https://www.youtube.com/playlist?list=PL_JZo16Mzs5XebdJhoIDLNp1MObBy7F5d" class="btn btn-outline-dark w-100">Vorlesung<br><small>Klasse A</small></a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature col">
|
<div class="feature col">
|
||||||
@@ -133,9 +140,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<h2>Buch Klasse N</h2>
|
<h2>Buch Klasse N</h2>
|
||||||
<p>Die Lernhinhalte für die Klasse N gibt es auch als gedrucktes Buch. Es ist passend zum Online-Kurs ausgelegt.</p>
|
<p>Die Lernhinhalte für die Klasse N gibt es auch als gedrucktes Buch. Es ist passend zum Online-Kurs ausgelegt.</p>
|
||||||
<div class="d-grid gap-2 d-md-block mb-5">
|
<div class="row row-cols-lg-2 g-2 mb-5">
|
||||||
<a href="https://darcverlag.de/DARC-Amateurfunklehrgang-Klasse-N" class="btn btn-outline-dark">Beim DARC-Verlag kaufen</a>
|
<div class="col"><a href="https://darcverlag.de/DARC-Amateurfunklehrgang-Klasse-N" class="btn btn-outline-dark w-100">Beim DARC-Verlag kaufen</a></div>
|
||||||
<a href="https://www.amazon.de/dp/388692100X" class="btn btn-outline-dark">Amazon</a>
|
<div class="col"><a href="https://www.amazon.de/dp/388692100X" class="btn btn-outline-dark w-100">Bei Amazon Kaufen</a></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature col">
|
<div class="feature col">
|
||||||
@@ -144,9 +151,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<h2>Kurse</h2>
|
<h2>Kurse</h2>
|
||||||
<p>Einige unserer Ortsverbände bieten Präsenz- oder Onlinekurse mit erfahrenen Ausbildern an. Finde heraus, ob es einen für dich passenden Kurs bei dir in der Nähe gibt!</p>
|
<p>Einige unserer Ortsverbände bieten Präsenz- oder Onlinekurse mit erfahrenen Ausbildern an. Finde heraus, ob es einen für dich passenden Kurs bei dir in der Nähe gibt!</p>
|
||||||
<div class="d-grid gap-2 d-md-block mb-5">
|
<div class="d-flex gap-2 mb-5">
|
||||||
<a href="kurse_vor_ort_karte.html" class="btn btn-outline-dark">Präsenz</a>
|
<a href="kurse_vor_ort_karte.html" class="btn btn-outline-dark flex-fill">Präsenz</a>
|
||||||
<a href="kurse_vor_ort_liste.html" class="btn btn-outline-dark">Online</a>
|
<a href="kurse_vor_ort_liste.html" class="btn btn-outline-dark flex-fill">Online</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature col">
|
<div class="feature col">
|
||||||
@@ -155,8 +162,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<h2>Ausbildungs­paten</h2>
|
<h2>Ausbildungs­paten</h2>
|
||||||
<p>Unsere Ausbildungspaten sind erfahrene Funkamateure, die dich gerne unterstützen. Sie können mit dir auch praktisch üben und nützliche Tipps für die Praxis geben.</p>
|
<p>Unsere Ausbildungspaten sind erfahrene Funkamateure, die dich gerne unterstützen. Sie können mit dir auch praktisch üben und nützliche Tipps für die Praxis geben.</p>
|
||||||
<div class="d-grid gap-2 d-md-block mb-5">
|
<div class="d-grid gap-2 mb-5">
|
||||||
<a href="patenkarte.html" class="btn btn-outline-dark">Zur Patenkarte</a>
|
<a href="patenkarte.html" class="btn btn-outline-dark w-100">Zur Patenkarte</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature col">
|
<div class="feature col">
|
||||||
@@ -166,7 +173,7 @@
|
|||||||
<h2>Fragenkatalog</h2>
|
<h2>Fragenkatalog</h2>
|
||||||
<p>Den Fragenkatalog mit den amtlichen Prüfungsfragen gibt es digital bei der <a href="https://50ohm.de/fk">Bundesnetzagentur</a>. Beim DARC-Verlag kann man auch eine gedruckte Version bestellen.</p>
|
<p>Den Fragenkatalog mit den amtlichen Prüfungsfragen gibt es digital bei der <a href="https://50ohm.de/fk">Bundesnetzagentur</a>. Beim DARC-Verlag kann man auch eine gedruckte Version bestellen.</p>
|
||||||
<div class="d-grid gap-2 d-md-block mb-5">
|
<div class="d-grid gap-2 d-md-block mb-5">
|
||||||
<a href="https://darcverlag.de/Fragenkatalog-Klasse-N" class="btn btn-outline-dark">Beim DARC-Verlag kaufen</a>
|
<a href="https://darcverlag.de/Fragenkatalog-Klasse-N" class="btn btn-outline-dark w-100">Beim DARC-Verlag kaufen</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="feature col">
|
<div class="feature col">
|
||||||
@@ -175,11 +182,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<h2>Trainings App</h2>
|
<h2>Trainings App</h2>
|
||||||
<p>Zum Trainieren der Fragen gibt es die 50Ohm App. Sie ist passend zum Online-Kurs ausgelegt.</p>
|
<p>Zum Trainieren der Fragen gibt es die 50Ohm App. Sie ist passend zum Online-Kurs ausgelegt.</p>
|
||||||
<div class="d-grid gap-2 d-md-block mb-5">
|
<div class="d-flex gap-2 mb-5">
|
||||||
<a href="https://play.google.com/store/apps/details?id=de.darc.fuenfizigohm" class="btn btn-outline-dark">Android</a>
|
<a href="https://play.google.com/store/apps/details?id=de.darc.fuenfizigohm" class="btn btn-outline-dark flex-fill">Android</a>
|
||||||
<a href="https://apps.apple.com/de/app/50ohm/id6474642114" class="btn btn-outline-dark">iOS</a>
|
<a href="https://apps.apple.com/de/app/50ohm/id6474642114" class="btn btn-outline-dark flex-fill">iOS</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a rel="me" href="https://social.darc.de/@AJW"></a>
|
<a rel="me" href="https://social.darc.de/@AJW"></a>
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
from src.build import Build
|
||||||
|
from src.config import Config
|
||||||
|
|
||||||
|
|
||||||
|
def write_catalog(path, number):
|
||||||
|
path.write_text(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"sections": [
|
||||||
|
{
|
||||||
|
"title": f"Katalog {number}",
|
||||||
|
"questions": [
|
||||||
|
{
|
||||||
|
"number": number,
|
||||||
|
"class": "SWL" if number.startswith("SWL") else "1",
|
||||||
|
"question": f"Frage {number}",
|
||||||
|
"answer_a": "A",
|
||||||
|
"answer_b": "B",
|
||||||
|
"answer_c": "C",
|
||||||
|
"answer_d": "D",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def prepare_content(tmp_path, include_swl):
|
||||||
|
questions_path = tmp_path / "contents" / "questions"
|
||||||
|
questions_path.mkdir(parents=True)
|
||||||
|
write_catalog(questions_path / "fragenkatalog3b.json", "NA101")
|
||||||
|
(questions_path / "metadata3b.json").write_text(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"NA101": {
|
||||||
|
"directus_id": "1",
|
||||||
|
"picture_question": "",
|
||||||
|
"picture_a": "",
|
||||||
|
"picture_b": "",
|
||||||
|
"picture_c": "",
|
||||||
|
"picture_d": "",
|
||||||
|
"layout": "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
if include_swl:
|
||||||
|
write_catalog(questions_path / "fragenkatalog_swl.json", "SWL001")
|
||||||
|
|
||||||
|
|
||||||
|
def test_optional_swl_catalog_is_loaded_with_default_metadata(tmp_path):
|
||||||
|
prepare_content(tmp_path, include_swl=True)
|
||||||
|
|
||||||
|
build = Build(Config(content_path=tmp_path, build_path=tmp_path / "build"))
|
||||||
|
|
||||||
|
assert set(build.questions) == {"NA101", "SWL001"}
|
||||||
|
assert build.question_metadata["SWL001"]["layout"] == ""
|
||||||
|
assert len(build.fragenkatalog["sections"]) == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_missing_optional_swl_catalog_is_allowed(tmp_path):
|
||||||
|
prepare_content(tmp_path, include_swl=False)
|
||||||
|
|
||||||
|
build = Build(Config(content_path=tmp_path, build_path=tmp_path / "build"))
|
||||||
|
|
||||||
|
assert set(build.questions) == {"NA101"}
|
||||||
|
assert len(build.fragenkatalog["sections"]) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_lowercase_swl_toc_is_supported(tmp_path):
|
||||||
|
prepare_content(tmp_path, include_swl=True)
|
||||||
|
toc_path = tmp_path / "toc"
|
||||||
|
section_path = tmp_path / "contents" / "sections"
|
||||||
|
toc_path.mkdir()
|
||||||
|
section_path.mkdir()
|
||||||
|
(section_path / "swl_intro.md").write_text("Einführung", encoding="utf-8")
|
||||||
|
(toc_path / "swl.json").write_text(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"title": "SWL-Kurs",
|
||||||
|
"edition": "SWL",
|
||||||
|
"chapters": [
|
||||||
|
{
|
||||||
|
"title": "Einstieg",
|
||||||
|
"ident": "swl_einstieg",
|
||||||
|
"sections": [{"title": "Einführung", "ident": "swl_intro"}],
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
),
|
||||||
|
encoding="utf-8",
|
||||||
|
)
|
||||||
|
|
||||||
|
build = Build(Config(content_path=tmp_path, build_path=tmp_path / "build"))
|
||||||
|
|
||||||
|
build.build_edition("SWL")
|
||||||
|
assert (tmp_path / "build" / "SWL_course_index.html").exists()
|
||||||
|
assert (tmp_path / "build" / "SWL_swl_intro.html").exists()
|
||||||
Reference in New Issue
Block a user