Spaces:
Sleeping
Sleeping
Fix level progression and word validation issues
Browse files- Add validation to prevent selecting all-caps words that appear in passages
- Implement proper 2-round requirement before level advancement
- Update UI to show progress feedback (e.g., "1/2 rounds completed")
- Fix bug where words like "VOLUME" were selected when visible in text
- src/aiService.js +9 -3
- src/app.js +11 -3
- src/clozeGameEngine.js +16 -3
src/aiService.js
CHANGED
@@ -428,7 +428,7 @@ Return as JSON: {"passage1": {...}, "passage2": {...}}`
|
|
428 |
parsed.passage2.words = parsed.passage2.words.filter(word => word && word.trim() !== '');
|
429 |
|
430 |
// Filter problematic words and validate word lengths based on level
|
431 |
-
const validateWords = (words) => {
|
432 |
const problematicWords = ['negro', 'retard', 'retarded', 'nigger', 'chinaman', 'jap', 'gypsy', 'savage', 'primitive', 'heathen'];
|
433 |
return words.filter(word => {
|
434 |
const cleanWord = word.replace(/[^a-zA-Z]/g, '');
|
@@ -437,6 +437,12 @@ Return as JSON: {"passage1": {...}, "passage2": {...}}`
|
|
437 |
// Skip problematic words
|
438 |
if (problematicWords.includes(lowerWord)) return false;
|
439 |
|
|
|
|
|
|
|
|
|
|
|
|
|
440 |
// Check length constraints
|
441 |
if (level <= 2) {
|
442 |
return cleanWord.length >= 4 && cleanWord.length <= 7;
|
@@ -451,8 +457,8 @@ Return as JSON: {"passage1": {...}, "passage2": {...}}`
|
|
451 |
const originalP1Count = parsed.passage1.words.length;
|
452 |
const originalP2Count = parsed.passage2.words.length;
|
453 |
|
454 |
-
parsed.passage1.words = validateWords(parsed.passage1.words);
|
455 |
-
parsed.passage2.words = validateWords(parsed.passage2.words);
|
456 |
|
457 |
console.log(`β
Level ${level} batch validation: P1 ${parsed.passage1.words.length}/${originalP1Count}, P2 ${parsed.passage2.words.length}/${originalP2Count} words passed`);
|
458 |
|
|
|
428 |
parsed.passage2.words = parsed.passage2.words.filter(word => word && word.trim() !== '');
|
429 |
|
430 |
// Filter problematic words and validate word lengths based on level
|
431 |
+
const validateWords = (words, passageText) => {
|
432 |
const problematicWords = ['negro', 'retard', 'retarded', 'nigger', 'chinaman', 'jap', 'gypsy', 'savage', 'primitive', 'heathen'];
|
433 |
return words.filter(word => {
|
434 |
const cleanWord = word.replace(/[^a-zA-Z]/g, '');
|
|
|
437 |
// Skip problematic words
|
438 |
if (problematicWords.includes(lowerWord)) return false;
|
439 |
|
440 |
+
// Check if word appears in all caps in the passage (like "VOLUME")
|
441 |
+
if (passageText.includes(word.toUpperCase()) && word === word.toUpperCase()) {
|
442 |
+
console.log(`Skipping all-caps word: ${word}`);
|
443 |
+
return false;
|
444 |
+
}
|
445 |
+
|
446 |
// Check length constraints
|
447 |
if (level <= 2) {
|
448 |
return cleanWord.length >= 4 && cleanWord.length <= 7;
|
|
|
457 |
const originalP1Count = parsed.passage1.words.length;
|
458 |
const originalP2Count = parsed.passage2.words.length;
|
459 |
|
460 |
+
parsed.passage1.words = validateWords(parsed.passage1.words, passage1);
|
461 |
+
parsed.passage2.words = validateWords(parsed.passage2.words, passage2);
|
462 |
|
463 |
console.log(`β
Level ${level} batch validation: P1 ${parsed.passage1.words.length}/${originalP1Count}, P2 ${parsed.passage2.words.length}/${originalP2Count} words passed`);
|
464 |
|
src/app.js
CHANGED
@@ -69,9 +69,11 @@ class App {
|
|
69 |
<strong>${roundData.title}</strong> by ${roundData.author}
|
70 |
`;
|
71 |
|
72 |
-
// Show level information
|
73 |
const blanksCount = roundData.blanks.length;
|
74 |
-
|
|
|
|
|
75 |
|
76 |
// Show contextualization from AI agent
|
77 |
this.elements.contextualization.innerHTML = `
|
@@ -160,7 +162,13 @@ class App {
|
|
160 |
}
|
161 |
|
162 |
if (results.passed) {
|
163 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
164 |
this.elements.result.className = 'mt-4 text-center font-semibold text-green-600';
|
165 |
} else {
|
166 |
if (this.game.currentLevel >= 3) {
|
|
|
69 |
<strong>${roundData.title}</strong> by ${roundData.author}
|
70 |
`;
|
71 |
|
72 |
+
// Show level information
|
73 |
const blanksCount = roundData.blanks.length;
|
74 |
+
const levelInfo = `Level ${this.game.currentLevel} β’ ${blanksCount} blank${blanksCount > 1 ? 's' : ''}`;
|
75 |
+
|
76 |
+
this.elements.roundInfo.innerHTML = levelInfo;
|
77 |
|
78 |
// Show contextualization from AI agent
|
79 |
this.elements.contextualization.innerHTML = `
|
|
|
162 |
}
|
163 |
|
164 |
if (results.passed) {
|
165 |
+
// Check if this completes the requirements for level advancement
|
166 |
+
const roundsCompleted = this.game.roundsPassedAtCurrentLevel + 1; // +1 for this round
|
167 |
+
if (roundsCompleted >= 2) {
|
168 |
+
message += ` - Excellent! Advancing to Level ${this.game.currentLevel + 1}! π`;
|
169 |
+
} else {
|
170 |
+
message += ` - Great job! ${roundsCompleted}/2 rounds completed for Level ${this.game.currentLevel + 1}`;
|
171 |
+
}
|
172 |
this.elements.result.className = 'mt-4 text-center font-semibold text-green-600';
|
173 |
} else {
|
174 |
if (this.game.currentLevel >= 3) {
|
src/clozeGameEngine.js
CHANGED
@@ -25,6 +25,9 @@ class ClozeGame {
|
|
25 |
this.currentBooks = []; // Array of two books per round
|
26 |
this.passages = []; // Array of two passages per round
|
27 |
this.currentPassageIndex = 0; // 0 for first passage, 1 for second
|
|
|
|
|
|
|
28 |
}
|
29 |
|
30 |
async initialize() {
|
@@ -749,11 +752,21 @@ class ClozeGame {
|
|
749 |
// Always increment round counter
|
750 |
this.currentRound++;
|
751 |
|
752 |
-
//
|
753 |
if (roundPassed) {
|
754 |
-
this.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
755 |
}
|
756 |
-
// If failed, stay at same level
|
757 |
|
758 |
// Clear chat conversations for new round
|
759 |
this.chatService.clearConversations();
|
|
|
25 |
this.currentBooks = []; // Array of two books per round
|
26 |
this.passages = []; // Array of two passages per round
|
27 |
this.currentPassageIndex = 0; // 0 for first passage, 1 for second
|
28 |
+
|
29 |
+
// Level progression tracking
|
30 |
+
this.roundsPassedAtCurrentLevel = 0; // Track successful rounds at current level
|
31 |
}
|
32 |
|
33 |
async initialize() {
|
|
|
752 |
// Always increment round counter
|
753 |
this.currentRound++;
|
754 |
|
755 |
+
// Track successful rounds and advance level after 2 successful rounds
|
756 |
if (roundPassed) {
|
757 |
+
this.roundsPassedAtCurrentLevel++;
|
758 |
+
console.log(`Round passed! Total rounds passed at level ${this.currentLevel}: ${this.roundsPassedAtCurrentLevel}`);
|
759 |
+
|
760 |
+
// Advance level after 2 successful rounds
|
761 |
+
if (this.roundsPassedAtCurrentLevel >= 2) {
|
762 |
+
this.currentLevel++;
|
763 |
+
this.roundsPassedAtCurrentLevel = 0; // Reset counter for new level
|
764 |
+
console.log(`Advancing to level ${this.currentLevel} after 2 successful rounds`);
|
765 |
+
}
|
766 |
+
} else {
|
767 |
+
// Failed round - do not reset the counter, user must accumulate 2 passes
|
768 |
+
console.log(`Round failed. Still need ${2 - this.roundsPassedAtCurrentLevel} more passed round(s) to advance from level ${this.currentLevel}`);
|
769 |
}
|
|
|
770 |
|
771 |
// Clear chat conversations for new round
|
772 |
this.chatService.clearConversations();
|