245 lines
8.7 KiB
JavaScript
245 lines
8.7 KiB
JavaScript
(function () {
|
|
"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" },
|
|
{ edition: "E", label: "Aufstockung N → E", detail: "E", color: "#FE756C" },
|
|
{ edition: "EA", label: "Aufstockung N → A", detail: "E + A", color: "#3BB583" },
|
|
{ edition: "A", label: "Aufstockung E → A", detail: "A", color: "#3BB583" }
|
|
];
|
|
|
|
function renderMathSoon() {
|
|
Vue.nextTick(function () {
|
|
if (typeof window.renderFiftyOhmMath !== "function") return;
|
|
window.renderFiftyOhmMath(document.getElementById("homework-generator"));
|
|
});
|
|
}
|
|
|
|
function copyText(text) {
|
|
if (navigator.clipboard && window.isSecureContext) return navigator.clipboard.writeText(text);
|
|
var input = document.createElement("textarea");
|
|
input.value = text;
|
|
input.setAttribute("readonly", "");
|
|
input.style.position = "fixed";
|
|
input.style.opacity = "0";
|
|
document.body.appendChild(input);
|
|
input.select();
|
|
var copied = document.execCommand("copy");
|
|
input.remove();
|
|
return copied ? Promise.resolve() : Promise.reject(new Error("Kopieren nicht möglich"));
|
|
}
|
|
|
|
var app = Vue.createApp({
|
|
setup: function () {
|
|
var ref = Vue.ref;
|
|
var computed = Vue.computed;
|
|
var reactive = Vue.reactive;
|
|
|
|
var loading = ref(true);
|
|
var loadError = ref("");
|
|
var step = ref(1);
|
|
var catalog = ref({});
|
|
var questionIndex = ref({});
|
|
var questionsBySection = ref({});
|
|
var selectedCourse = ref(null);
|
|
var toc = ref(null);
|
|
var selectedChapterIds = ref([]);
|
|
var selectedSectionIds = ref([]);
|
|
var questionSelection = reactive({});
|
|
var generatedUrl = ref("");
|
|
var copyMessage = ref("");
|
|
var tocCache = {};
|
|
|
|
var stepLabels = [
|
|
{ number: 1, label: "Kurs" },
|
|
{ number: 2, label: "Kapitel" },
|
|
{ number: 3, label: "Sektionen" },
|
|
{ number: 4, label: "Fragen" },
|
|
{ number: 5, label: "Link" }
|
|
];
|
|
|
|
function sectionQuestionIds(section) {
|
|
if (!selectedCourse.value) return [];
|
|
return questionsBySection.value[selectedCourse.value.edition + ":" + section.ident] || [];
|
|
}
|
|
|
|
function chapterQuestionCount(chapter) {
|
|
return chapter.sections.reduce(function (sum, section) {
|
|
return sum + sectionQuestionIds(section).length;
|
|
}, 0);
|
|
}
|
|
|
|
var selectedChapters = computed(function () {
|
|
if (!toc.value) return [];
|
|
return toc.value.chapters.filter(function (chapter) {
|
|
return selectedChapterIds.value.indexOf(chapter.ident) !== -1;
|
|
});
|
|
});
|
|
|
|
var selectedSectionGroups = computed(function () {
|
|
var groups = [];
|
|
selectedChapters.value.forEach(function (chapter) {
|
|
chapter.sections.forEach(function (section) {
|
|
if (selectedSectionIds.value.indexOf(section.ident) === -1) return;
|
|
groups.push({ chapter: chapter, section: section, questionIds: sectionQuestionIds(section) });
|
|
});
|
|
});
|
|
return groups;
|
|
});
|
|
|
|
var orderedQuestions = computed(function () {
|
|
return selectedSectionGroups.value.reduce(function (result, group) {
|
|
return result.concat(group.questionIds);
|
|
}, []);
|
|
});
|
|
|
|
var selectedQuestionIds = computed(function () {
|
|
return orderedQuestions.value.filter(function (questionId) { return questionSelection[questionId]; });
|
|
});
|
|
|
|
function buildSectionIndex() {
|
|
var result = {};
|
|
Object.keys(questionIndex.value).forEach(function (questionId) {
|
|
var entry = questionIndex.value[questionId];
|
|
(entry.editions || []).forEach(function (edition) {
|
|
var key = edition + ":" + entry.section;
|
|
if (!result[key]) result[key] = [];
|
|
result[key].push(questionId);
|
|
});
|
|
});
|
|
Object.keys(result).forEach(function (key) {
|
|
result[key].sort(function (left, right) {
|
|
return left.localeCompare(right, "de", { numeric: true });
|
|
});
|
|
});
|
|
questionsBySection.value = result;
|
|
}
|
|
|
|
function goToStep(number) {
|
|
step.value = number;
|
|
copyMessage.value = "";
|
|
if (number === 4) renderMathSoon();
|
|
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
}
|
|
|
|
function selectCourse(course) {
|
|
selectedCourse.value = course;
|
|
selectedChapterIds.value = [];
|
|
selectedSectionIds.value = [];
|
|
generatedUrl.value = "";
|
|
if (tocCache[course.edition]) {
|
|
toc.value = tocCache[course.edition];
|
|
goToStep(2);
|
|
return;
|
|
}
|
|
loading.value = true;
|
|
fetch("assets/toc/" + course.edition + ".json")
|
|
.then(function (response) {
|
|
if (!response.ok) throw new Error("Inhaltsverzeichnis nicht gefunden (HTTP " + response.status + ").");
|
|
return response.json();
|
|
})
|
|
.then(function (data) {
|
|
tocCache[course.edition] = data;
|
|
toc.value = data;
|
|
loading.value = false;
|
|
goToStep(2);
|
|
})
|
|
.catch(function (error) {
|
|
loadError.value = error.message || "Unbekannter Ladefehler";
|
|
loading.value = false;
|
|
});
|
|
}
|
|
|
|
function openSectionSelection() {
|
|
var preselectedSections = [];
|
|
selectedChapters.value.forEach(function (chapter) {
|
|
chapter.sections.forEach(function (section) {
|
|
if (sectionQuestionIds(section).length > 0) preselectedSections.push(section.ident);
|
|
});
|
|
});
|
|
selectedSectionIds.value = preselectedSections;
|
|
goToStep(3);
|
|
}
|
|
|
|
function openQuestionSelection() {
|
|
orderedQuestions.value.forEach(function (questionId) { questionSelection[questionId] = true; });
|
|
goToStep(4);
|
|
}
|
|
|
|
function setAllQuestions(selected) {
|
|
orderedQuestions.value.forEach(function (questionId) { questionSelection[questionId] = selected; });
|
|
}
|
|
|
|
function generateLink() {
|
|
var url = new URL("simulation.html", window.location.href);
|
|
url.search = "?homework=" + selectedQuestionIds.value.join("+");
|
|
generatedUrl.value = url.toString();
|
|
goToStep(5);
|
|
}
|
|
|
|
function copyLink() {
|
|
copyText(generatedUrl.value)
|
|
.then(function () { copyMessage.value = "Der Hausaufgabenlink wurde kopiert."; })
|
|
.catch(function () { copyMessage.value = "Der Link konnte nicht automatisch kopiert werden. Bitte kopiere ihn aus dem Feld."; });
|
|
}
|
|
|
|
Promise.all([
|
|
fetch("assets/fragenkatalog.json"),
|
|
fetch("assets/metadata.json"),
|
|
fetch("assets/question_index.json")
|
|
])
|
|
.then(function (responses) {
|
|
var names = ["Fragenkatalog", "Metadaten", "Fragenindex"];
|
|
responses.forEach(function (response, index) {
|
|
if (!response.ok) throw new Error(names[index] + " nicht gefunden (HTTP " + response.status + ").");
|
|
});
|
|
return Promise.all(responses.map(function (response) { return response.json(); }));
|
|
})
|
|
.then(function (data) {
|
|
questionIndex.value = data[2] || {};
|
|
catalog.value = window.FiftyOhmQuestions.normalizeCatalog(data[0], data[1] || {}, questionIndex.value);
|
|
buildSectionIndex();
|
|
loading.value = false;
|
|
})
|
|
.catch(function (error) {
|
|
loadError.value = error.message || "Unbekannter Ladefehler";
|
|
loading.value = false;
|
|
});
|
|
|
|
return {
|
|
loading: loading,
|
|
loadError: loadError,
|
|
step: step,
|
|
stepLabels: stepLabels,
|
|
courseChoices: COURSE_CHOICES,
|
|
catalog: catalog,
|
|
selectedCourse: selectedCourse,
|
|
toc: toc,
|
|
selectedChapterIds: selectedChapterIds,
|
|
selectedSectionIds: selectedSectionIds,
|
|
questionSelection: questionSelection,
|
|
selectedChapters: selectedChapters,
|
|
selectedSectionGroups: selectedSectionGroups,
|
|
orderedQuestions: orderedQuestions,
|
|
selectedQuestionIds: selectedQuestionIds,
|
|
generatedUrl: generatedUrl,
|
|
copyMessage: copyMessage,
|
|
sectionQuestionIds: sectionQuestionIds,
|
|
chapterQuestionCount: chapterQuestionCount,
|
|
goToStep: goToStep,
|
|
selectCourse: selectCourse,
|
|
openSectionSelection: openSectionSelection,
|
|
openQuestionSelection: openQuestionSelection,
|
|
setAllQuestions: setAllQuestions,
|
|
generateLink: generateLink,
|
|
copyLink: copyLink
|
|
};
|
|
}
|
|
});
|
|
|
|
app.mount("#homework-generator");
|
|
})();
|