Files
SuperminarenandClaude Sonnet 5.5 874838f525 Swedish adaptation: Instegscertifikat and HAREC
- Editions replaced by INSTEG, HAREC and UPPGRADERING (Instegscertifikat -> HAREC)
- Question pool optional; simulator, homework tool and solutions switch off without one
- All UI strings, templates, renderers and project JS localised to sv-SE
  (decimal comma, Swedish non-breaking-space rules, Å/Ä/Ö in Morse table)
- DARC branding, membership CTA and German links removed; attribution footer added
- Page names centralised in src/pages.py
- README and docs rewritten in Swedish

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
2026-10-10 15:03:02 +02:00

244 lines
8.7 KiB
JavaScript

(function () {
"use strict";
var COURSE_CHOICES = [
{ edition: "INSTEG", label: "Instegscertifikat", detail: "Instegskurs", color: "#47ABE8" },
{ edition: "HAREC", label: "HAREC", detail: "HAREC-kurs", color: "#FE756C" },
{ edition: "UPPGRADERING", label: "Uppgradering", detail: "Instegscertifikat → HAREC", 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("Det gick inte att kopiera"));
}
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: "Avsnitt" },
{ number: 4, label: "Frågor" },
{ 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("Innehållsförteckningen hittades inte (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 || "Okänt fel vid laddning";
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 = "Övningslänken kopierades."; })
.catch(function () { copyMessage.value = "Länken kunde inte kopieras automatiskt. Kopiera den från fältet."; });
}
Promise.all([
fetch("assets/question_pool.json"),
fetch("assets/metadata.json"),
fetch("assets/question_index.json")
])
.then(function (responses) {
var names = ["Frågebanken", "Metadata", "Frågeindex"];
responses.forEach(function (response, index) {
if (!response.ok) throw new Error(names[index] + " hittades inte (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 || "Okänt fel vid laddning";
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");
})();