${optionsHTML}
`;
quizForm.appendChild(questionEl);
});
trainingData.quizTotal = trainingData.config.quiz.length;
}
function submitQuiz() {
if (!quizForm || !quizScore) return;
let score = 0;
trainingData.config.quiz.forEach((q, index) => {
const selected = quizForm.querySelector(
`input[name="q${index}"]:checked`
);
if (
selected &&
parseInt(selected.value, 10) === q.correct
) {
score++;
}
});
trainingData.quizScore = score;
quizScore.textContent = `Your score: ${score} / ${trainingData.quizTotal}`;
}
// Tab 5: Systems Check
function verifyCode() {
if (
!activationCodeInput ||
!systemsResult ||
!dashboardIntro
)
return;
const inputCode = activationCodeInput.value.trim();
if (inputCode === trainingData.config.activationCode) {
trainingData.systemsGo = true;
systemsResult.textContent =
"Systems GO. Training Complete. View Dashboard for report.";
systemsResult.style.color = "var(--success-color)";
// All modules done, populate dashboard
updateDashboard();
// II.B.4: Direct user to final relevant tab (Dashboard)
showTab(0);
dashboardIntro.style.display = "none";
dashboardContent.style.display = "block";
} else {
trainingData.systemsGo = false;
systemsResult.textContent =
"Activation Failed. Check code and try again.";
systemsResult.style.color = "var(--accent-color)";
}
}
// Tab 1: Dashboard
function updateDashboard() {
if (!dashboardTableBody) return;
const results = [
{
Assessment: "Trainee Name",
Result: trainingData.astronautName,
},
{
Assessment: "Reaction Time",
Result: trainingData.reactionTime
? `${trainingData.reactionTime} ms`
: "Not completed",
},
{
Assessment: "Knowledge Quiz",
Result:
trainingData.quizScore !== null
? `${trainingData.quizScore} / ${trainingData.quizTotal}`
: "Not completed",
},
{
Assessment: "Systems Check",
Result:
trainingData.systemsGo === true
? "GO"
: trainingData.systemsGo === false
? "NO GO"
: "Not completed",
},
];
dashboardTableBody.innerHTML = ""; // Clear old results
results.forEach((item) => {
dashboardTableBody.innerHTML += `
| ${item.Assessment} |
${item.Result} |
`;
});
}
// Tab 6: Configuration (V.A, V.B, V.C)
function buildConfigEditor() {
if (!configCodeInput || !configQuizEditor) return;
// Populate activation code
configCodeInput.value =
trainingData.config.activationCode;
// Populate quiz editor
configQuizEditor.innerHTML = "";
trainingData.config.quiz.forEach((q, index) => {
const editorEl = document.createElement("div");
editorEl.className = "atg-form-group";
editorEl.innerHTML = `
Question ${index + 1}
`;
configQuizEditor.appendChild(editorEl);
});
}
function saveConfig() {
if (
!configCodeInput ||
!configQuizEditor ||
!configSaveStatus
)
return;
// Save activation code
trainingData.config.activationCode =
configCodeInput.value.trim();
// Save quiz questions
const newQuizData = [];
trainingData.config.quiz.forEach((q, index) => {
const newQ = {
q: container.querySelector(`#atg-config-q${index}`)
.value,
options: [
container.querySelector(`#atg-config-q${index}-opt0`)
.value,
container.querySelector(`#atg-config-q${index}-opt1`)
.value,
container.querySelector(`#atg-config-q${index}-opt2`)
.value,
],
correct: parseInt(
container.querySelector(
`#atg-config-q${index}-correct`
).value,
10
),
};
newQuizData.push(newQ);
});
trainingData.config.quiz = newQuizData;
// Re-build the quiz with new data
buildQuiz();
// Show feedback
configSaveStatus.textContent = "Configuration saved successfully!";
setTimeout(
() => (configSaveStatus.textContent = ""),
3000
);
}
// --- PDF Download Logic (II.C) ---
function downloadPDF() {
// V.A: Rigorous testing of PDF feature
try {
// Check if jsPDF and autoTable are loaded
if (
typeof window.jspdf === "undefined" ||
typeof window.jspdf.jsPDF === "undefined"
) {
console.error("jsPDF is not loaded.");
alert("Error: PDF library not loaded.");
return;
}
if (
typeof window.jspdf.jsPDF.autoTable === "undefined"
) {
console.error("jsPDF-AutoTable is not loaded.");
alert("Error: PDF AutoTable library not loaded.");
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
// II.C.2: Professional formatting
doc.setFontSize(20);
doc.setTextColor("#005f9e"); // II.C.3: Visual consistency
doc.text("Astronaut Training: Mission Report", 14, 22);
doc.setFontSize(12);
doc.setTextColor("#212121");
doc.text(
`Trainee: ${trainingData.astronautName}`,
14,
35
);
// II.C.2: Tabular presentation
const tableHead = [["Assessment", "Result"]];
const tableBody = [
[
"Reaction Time",
trainingData.reactionTime
? `${trainingData.reactionTime} ms`
: "Not completed",
],
[
"Knowledge Quiz",
trainingData.quizScore !== null
? `${trainingData.quizScore} / ${trainingData.quizTotal}`
: "Not completed",
],
[
"Systems Check",
trainingData.systemsGo ? "GO" : "NO GO",
],
];
doc.autoTable({
startY: 45,
head: tableHead,
body: tableBody,
theme: "grid",
headStyles: {
fillColor: "#005f9e", // II.C.3: Visual consistency
textColor: "#ffffff",
},
styles: {
cellPadding: 3,
fontSize: 11,
},
});
// II.C.2: Excludes extraneous elements (by default)
doc.save("Astronaut_Training_Report.pdf");
} catch (e) {
console.error("PDF Generation Failed:", e);
alert(
"An error occurred while generating the PDF. Please check the console."
);
}
}
// --- IV.C: Event Listeners ---
// Tab click navigation
tabs.forEach((tab, index) => {
tab.addEventListener("click", () => showTab(index));
});
// Next/Prev buttons
prevBtn.addEventListener("click", ()_ =>
showTab(currentTabIndex + 1)
);
nextBtn.addEventListener("click", ()_ =>
showTab(currentTabIndex - 1)
);
// Module buttons
if (saveProfileBtn)
saveProfileBtn.addEventListener("click", saveProfile);
if (startReactionBtn)
startReactionBtn.addEventListener(
"click",
startReactionTest
);
if (stopReactionBtn)
stopReactionBtn.addEventListener("click", stopReactionTest);
if (submitQuizBtn)
submitQuizBtn.addEventListener("click", submitQuiz);
if (verifyCodeBtn)
verifyCodeBtn.addEventListener("click", verifyCode);
if (saveConfigBtn)
saveConfigBtn.addEventListener("click", saveConfig);
if (downloadPdfBtn)
downloadPdfBtn.addEventListener("click", downloadPDF);
// --- Initial Setup ---
buildQuiz();
buildConfigEditor();
showTab(0); // Start on the first tab
}
})();