diff --git a/web-app/js/projects.js b/web-app/js/projects.js
index 65e8486c..539371d1 100644
--- a/web-app/js/projects.js
+++ b/web-app/js/projects.js
@@ -2,74 +2,105 @@
// Each project's HTML and logic lives in its own file under js/projects/
const projectInstructions = {
- // Project instructions moved to modular files under js/projects/
+ // Project instructions moved to modular files under js/projects/
};
-
function toPascalCase(slug) {
- return slug.split(/[^a-zA-Z0-9]+/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join('');
+ return slug
+ .split(/[^a-zA-Z0-9]+/)
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
+ .join("");
}
function getProjectHTML(projectName) {
- const fnName = 'get' + toPascalCase(projectName) + 'HTML';
- if (typeof window[fnName] === 'function') return window[fnName]();
- return `
Project '${projectName}' content not available.
`;
+ const fnName = "get" + toPascalCase(projectName) + "HTML";
+
+ try {
+ // 1. Check if the project module actually loaded
+ if (typeof window[fnName] === "function") {
+ return window[fnName]();
+ } else {
+ // Throw an error so the catch block handles the missing module
+ throw new Error(`Module ${fnName} is missing or failed to initialize.`);
+ }
+ } catch (error) {
+ // 2. Log it for the developers
+ console.warn(`[Project Loader] Failed to load ${projectName}:`, error);
+
+ // 3. Return a user-friendly UI error state for the user
+ return `
+
+
⚠️
+
+ SYSTEM ERROR: PROJECT OFFLINE
+
+
+ We couldn't initialize the interactive environment for ${projectName}. The underlying module may be missing or corrupted.
+
+
+
+ `;
+ }
}
function getProjectInstructions(projectName) {
- // Modules may provide richer instructions; fall back to a simple hint.
- const fnName = 'get' + toPascalCase(projectName) + 'Instructions';
- if (typeof window[fnName] === 'function') return window[fnName]();
- return { title: projectName, steps: ['Open the project and follow on-screen instructions.'] };
+ // Modules may provide richer instructions; fall back to a simple hint.
+ const fnName = "get" + toPascalCase(projectName) + "Instructions";
+ if (typeof window[fnName] === "function") return window[fnName]();
+ return {
+ title: projectName,
+ steps: ["Open the project and follow on-screen instructions."],
+ };
}
-
function initializeProject(projectName) {
+ const initializers = {
+ "tic-tac-toe": "initTicTacToe",
+ "rock-paper-scissor": "initRockPaperScissor",
+ "dice-rolling": "initDiceRolling",
+ "coin-flip": "initCoinFlip",
+ "blackjack-21": "initBlackjack",
+ "number-guessing": "initNumberGuessing",
+ hangman: "initHangman",
+ "word-scramble": "initWordScramble",
+ flames: "initFlames",
+ "dots-boxes": "initDotsBoxes",
+ "emoji-memory": "initEmojiMemoryGame",
+ fibonacci: "initFibonacci",
+ "binary-search": "initBinarySearch",
+ "bubble-sort": "initBubbleSort",
+ "progression-recognizer": "initProgressionRecognizer",
+ "pascal-triangle": "initPascalTriangle",
+ armstrong: "initArmstrong",
+ calculator: "initCalculator",
+ collatz: "initCollatz",
+ "prime-analyzer": "initPrimeAnalyzer",
+ "projectile-motion": "initProjectileMotion",
+ "coordinate-polar-transform": "initCoordinatePolarTransform",
+ "derivative-calculator": "initDerivativeCalculator",
+ "morse-code": "initMorseCode",
+ "tower-of-hanoi": "initTowerOfHanoi",
+ "number-converter": "initNumberConverter",
+ "typing-speed-tester": "initTypingSpeedTester",
+ "snake-game": "initSnakeGame",
+ "password-forge": "initPasswordForge",
+ "spot-the-difference": "initSpotTheDifference",
+ "whack-a-mole": "initWhackaMole",
+ "flappy-game": "initFlappyGame",
+ "productive-pet": "initProductivePet",
+ "simon-says": "initSimonSays",
+ "2048-game": "init2048Game",
+ "color-palette": "initColorPalette",
+ "math-quiz": "initMathQuiz",
+ "resume-analyzer": "initAIResumeAnalyzer",
+ "caesar-cipher": "initCaesarCipher",
+ };
- const initializers = {
- 'tic-tac-toe': 'initTicTacToe',
- 'rock-paper-scissor': 'initRockPaperScissor',
- 'dice-rolling': 'initDiceRolling',
- 'coin-flip': 'initCoinFlip',
- 'blackjack-21': 'initBlackjack',
- 'number-guessing': 'initNumberGuessing',
- 'hangman': 'initHangman',
- 'word-scramble': 'initWordScramble',
- 'flames': 'initFlames',
- 'dots-boxes': 'initDotsBoxes',
- 'emoji-memory': 'initEmojiMemoryGame',
- 'fibonacci': 'initFibonacci',
- 'binary-search': 'initBinarySearch',
- 'bubble-sort': 'initBubbleSort',
- 'progression-recognizer': 'initProgressionRecognizer',
- 'pascal-triangle': 'initPascalTriangle',
- 'armstrong': 'initArmstrong',
- 'calculator': 'initCalculator',
- 'collatz': 'initCollatz',
- 'prime-analyzer': 'initPrimeAnalyzer',
- 'projectile-motion': 'initProjectileMotion',
- 'coordinate-polar-transform': 'initCoordinatePolarTransform',
- 'derivative-calculator': 'initDerivativeCalculator',
- 'morse-code': 'initMorseCode',
- 'tower-of-hanoi': 'initTowerOfHanoi',
- 'number-converter': 'initNumberConverter',
- 'typing-speed-tester': 'initTypingSpeedTester',
- 'snake-game': 'initSnakeGame',
- 'password-forge': 'initPasswordForge',
- 'spot-the-difference': 'initSpotTheDifference',
- 'whack-a-mole': 'initWhackaMole',
- 'flappy-game': 'initFlappyGame',
- 'productive-pet': 'initProductivePet',
- 'simon-says': 'initSimonSays',
- '2048-game': 'init2048Game',
- 'color-palette': 'initColorPalette',
- 'math-quiz': 'initMathQuiz',
- 'resume-analyzer': 'initAIResumeAnalyzer',
- 'caesar-cipher': 'initCaesarCipher'
- };
-
- const initializerName = initializers[projectName];
- if (initializerName && typeof window[initializerName] === 'function') {
- window[initializerName]();
- }
+ const initializerName = initializers[projectName];
+ if (initializerName && typeof window[initializerName] === "function") {
+ window[initializerName]();
+ }
}