diff --git a/assets/exam-simulator.js b/assets/exam-simulator.js index 2efb9aa..977c06a 100644 --- a/assets/exam-simulator.js +++ b/assets/exam-simulator.js @@ -38,7 +38,7 @@ if (!value) return []; var seen = new Set(); 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); return true; }); diff --git a/assets/homework.js b/assets/homework.js index b500b8b..c0279f2 100644 --- a/assets/homework.js +++ b/assets/homework.js @@ -2,6 +2,7 @@ "use strict"; var COURSE_CHOICES = [ + { edition: "SWL", label: "SWL-Kurs", detail: "Kurzwellenhören", color: "#FFFFFF" }, { edition: "N", label: "N-Kurs", detail: "N", color: "#47ABE8" }, { edition: "NE", label: "E-Kurs", detail: "N + E", color: "#FE756C" }, { edition: "NEA", label: "A-Kurs", detail: "N + E + A", color: "#3BB583" }, diff --git a/assets/question-catalog.js b/assets/question-catalog.js index 4b682f5..357803f 100644 --- a/assets/question-catalog.js +++ b/assets/question-catalog.js @@ -12,9 +12,9 @@ function walk(section, sectionIndex, category) { (section.questions || []).forEach(function (question) { - var part = sectionIndex === 0 - ? partForClass[String(question.class)] - : partForSection[sectionIndex]; + var part = String(question.class) === "SWL" + ? "SWL" + : (sectionIndex === 0 ? partForClass[String(question.class)] : partForSection[sectionIndex]); if (!part) return; var questionMetadata = metadata[question.number] || {}; diff --git a/build.py b/build.py index a8f4c68..d23027e 100644 --- a/build.py +++ b/build.py @@ -6,6 +6,7 @@ conf = config.Config() # Build Everything: bd = build.Build(conf) bd.build_website() +bd.build_edition("SWL") bd.build_edition("N") bd.build_edition("E") bd.build_edition("A") diff --git a/main.py b/main.py index 51bf833..78cd7c9 100644 --- a/main.py +++ b/main.py @@ -12,6 +12,7 @@ app = typer.Typer() @app.command() 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.swl, Edition.n, Edition.e, Edition.a, diff --git a/src/build.py b/src/build.py index 41be79f..c9d9521 100644 --- a/src/build.py +++ b/src/build.py @@ -26,10 +26,32 @@ class Build: self.env.filters["shuffle_answers"] = self.__filter_shuffle_answers with self.config.p_data_fragenkatalog.open(encoding="utf-8") as 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: self.question_metadata = json.load(file) 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_token_pattern = re.compile(r"^\s*\[question:([\w\d]+)\]", re.MULTILINE) @@ -143,8 +165,10 @@ class Build: def __build_exam_simulator(self): 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") - shutil.copyfile(self.config.p_data_metadata, self.config.p_build_assets / "metadata.json") + with (self.config.p_build_assets / "fragenkatalog.json").open("w", encoding="utf-8") as file: + 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) picture_fields = ("picture_question", "picture_a", "picture_b", "picture_c", "picture_d") @@ -191,8 +215,11 @@ class Build: def __build_homework_tool(self): toc_target = self.config.p_build_assets / "toc" toc_target.mkdir(parents=True, exist_ok=True) - for edition in ("N", "NE", "NEA", "E", "EA", "A"): - shutil.copyfile(self.config.p_data_toc / f"{edition}.json", toc_target / f"{edition}.json") + for edition in ("SWL", "N", "NE", "NEA", "E", "EA", "A"): + 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") page = self.__build_page( @@ -415,9 +442,12 @@ class Build: self.config.p_build.mkdir(exist_ok=True) 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 ( - (self.config.p_data_toc / f"{edition}.json").open(encoding="utf-8") as file, + toc_file.open(encoding="utf-8") as file, Progress( TaskProgressColumn(), BarColumn(), @@ -456,9 +486,11 @@ class Build: with (self.config.p_data_sections / f"{ident}.md").open(encoding="utf-8") as sfile: section_content = sfile.read() section["content"] = section_content - with (self.config.p_data_slides / f"{ident}.md").open(encoding="utf-8") as sfile: - section_content = sfile.read() - section["slide"] = section_content + slide_file = self.config.p_data_slides / f"{ident}.md" + if slide_file.exists(): + with slide_file.open(encoding="utf-8") as sfile: + section_content = sfile.read() + section["slide"] = section_content if section["content"] is not None: self.__collect_question_occurrences( diff --git a/src/config.py b/src/config.py index 97d1dbb..e18e344 100644 --- a/src/config.py +++ b/src/config.py @@ -29,6 +29,7 @@ class Config: self.p_data_solutions = self.p_data_contents / "solutions" 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_build = Path(self.get_config_value("output", "./build") if build_path is None else build_path) diff --git a/src/edition.py b/src/edition.py index 2a250c5..fa079f2 100644 --- a/src/edition.py +++ b/src/edition.py @@ -2,6 +2,7 @@ from enum import StrEnum class Edition(StrEnum): + swl = "SWL" n = "N" e = "E" a = "A" diff --git a/templates/html/index.html b/templates/html/index.html index dee994b..669b1da 100644 --- a/templates/html/index.html +++ b/templates/html/index.html @@ -92,6 +92,12 @@
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.
+ +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.
Der DARC e. V. betreibt eine eigene Matrix-Instanz. Dort gibt es einen Raum, in dem du deine Fragen stellen kannst:
-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.
-Die Lernhinhalte für die Klasse N gibt es auch als gedrucktes Buch. Es ist passend zum Online-Kurs ausgelegt.
-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!
-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.
-Den Fragenkatalog mit den amtlichen Prüfungsfragen gibt es digital bei der Bundesnetzagentur. Beim DARC-Verlag kann man auch eine gedruckte Version bestellen.
Zum Trainieren der Fragen gibt es die 50Ohm App. Sie ist passend zum Online-Kurs ausgelegt.
- +