Spaces:
Sleeping
Sleeping
milwright
commited on
Commit
Β·
04bba1d
1
Parent(s):
4ea90f7
add streak indicator and prevent concatenated word selection
Browse files- index.html +5 -2
- src/aiService.js +8 -2
- src/app.js +19 -0
index.html
CHANGED
|
@@ -28,7 +28,10 @@
|
|
| 28 |
<div class="paper-content">
|
| 29 |
<div class="flex justify-between items-center mb-4">
|
| 30 |
<div id="book-info" class="biblio-info"></div>
|
| 31 |
-
<div
|
|
|
|
|
|
|
|
|
|
| 32 |
</div>
|
| 33 |
<div id="contextualization" class="context-box mb-4 p-3 rounded-lg"></div>
|
| 34 |
<div id="passage-content" class="prose max-w-none mb-6"></div>
|
|
@@ -59,7 +62,7 @@
|
|
| 59 |
Show Hints
|
| 60 |
</button>
|
| 61 |
<div class="controls-divider"></div>
|
| 62 |
-
<button id="leaderboard-btn" class="leaderboard-footer-btn" title="View leaderboard">
|
| 63 |
π
|
| 64 |
</button>
|
| 65 |
</div>
|
|
|
|
| 28 |
<div class="paper-content">
|
| 29 |
<div class="flex justify-between items-center mb-4">
|
| 30 |
<div id="book-info" class="biblio-info"></div>
|
| 31 |
+
<div class="flex gap-2 items-center">
|
| 32 |
+
<div id="streak-info" class="round-badge px-3 py-1 rounded-full text-sm hidden"></div>
|
| 33 |
+
<div id="round-info" class="round-badge px-3 py-1 rounded-full text-sm"></div>
|
| 34 |
+
</div>
|
| 35 |
</div>
|
| 36 |
<div id="contextualization" class="context-box mb-4 p-3 rounded-lg"></div>
|
| 37 |
<div id="passage-content" class="prose max-w-none mb-6"></div>
|
|
|
|
| 62 |
Show Hints
|
| 63 |
</button>
|
| 64 |
<div class="controls-divider"></div>
|
| 65 |
+
<button type="button" id="leaderboard-btn" class="leaderboard-footer-btn" title="View leaderboard">
|
| 66 |
π
|
| 67 |
</button>
|
| 68 |
</div>
|
src/aiService.js
CHANGED
|
@@ -242,7 +242,7 @@ class OpenRouterService {
|
|
| 242 |
content: 'Select words for a cloze exercise. Return ONLY a JSON array of words, nothing else.'
|
| 243 |
}, {
|
| 244 |
role: 'user',
|
| 245 |
-
content: `Select ${count} ${level <= 2 ? 'easy' : level <= 4 ? 'medium' : 'challenging'} words (${wordLengthConstraint}) from this passage. Choose meaningful nouns, verbs, or adjectives. Avoid capitalized words and proper nouns.
|
| 246 |
|
| 247 |
Passage: "${passage}"`
|
| 248 |
}],
|
|
@@ -382,6 +382,12 @@ Passage: "${passage}"`
|
|
| 382 |
return false;
|
| 383 |
}
|
| 384 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 385 |
// Check if word exists as non-capitalized word after position 10 (matches game engine)
|
| 386 |
if (!passageWordMap.has(cleanWord.toLowerCase())) {
|
| 387 |
return false;
|
|
@@ -524,7 +530,7 @@ Passage: "${passage}"`
|
|
| 524 |
content: 'Process passages for cloze exercises. Return ONLY a JSON object.'
|
| 525 |
}, {
|
| 526 |
role: 'user',
|
| 527 |
-
content: `Select ${blanksPerPassage} ${level <= 2 ? 'easy' : level <= 4 ? 'medium' : 'challenging'} words (${wordLengthConstraint}) from each passage.
|
| 528 |
|
| 529 |
Passage 1 ("${book1.title}" by ${book1.author}):
|
| 530 |
${passage1}
|
|
|
|
| 242 |
content: 'Select words for a cloze exercise. Return ONLY a JSON array of words, nothing else.'
|
| 243 |
}, {
|
| 244 |
role: 'user',
|
| 245 |
+
content: `Select ${count} ${level <= 2 ? 'easy' : level <= 4 ? 'medium' : 'challenging'} words (${wordLengthConstraint}) from this passage. Choose meaningful nouns, verbs, or adjectives. Avoid capitalized words and proper nouns. NEVER select concatenated words like "fromthe", "tothe", "andthe", "hewas", "shewas" - these should be two separate words.
|
| 246 |
|
| 247 |
Passage: "${passage}"`
|
| 248 |
}],
|
|
|
|
| 382 |
return false;
|
| 383 |
}
|
| 384 |
|
| 385 |
+
// Reject obvious concatenated words like "fromthe", "tothe", etc.
|
| 386 |
+
if (/^(from|to|and)(the|a)$/i.test(cleanWord)) {
|
| 387 |
+
console.log(`π« Rejected concatenated word: "${word}"`);
|
| 388 |
+
return false;
|
| 389 |
+
}
|
| 390 |
+
|
| 391 |
// Check if word exists as non-capitalized word after position 10 (matches game engine)
|
| 392 |
if (!passageWordMap.has(cleanWord.toLowerCase())) {
|
| 393 |
return false;
|
|
|
|
| 530 |
content: 'Process passages for cloze exercises. Return ONLY a JSON object.'
|
| 531 |
}, {
|
| 532 |
role: 'user',
|
| 533 |
+
content: `Select ${blanksPerPassage} ${level <= 2 ? 'easy' : level <= 4 ? 'medium' : 'challenging'} words (${wordLengthConstraint}) from each passage. NEVER select concatenated words like "fromthe", "tothe", "andthe", "hewas", "shewas" - these should be two separate words.
|
| 534 |
|
| 535 |
Passage 1 ("${book1.title}" by ${book1.author}):
|
| 536 |
${passage1}
|
src/app.js
CHANGED
|
@@ -16,6 +16,7 @@ class App {
|
|
| 16 |
stickyControls: document.getElementById('sticky-controls'),
|
| 17 |
bookInfo: document.getElementById('book-info'),
|
| 18 |
roundInfo: document.getElementById('round-info'),
|
|
|
|
| 19 |
contextualization: document.getElementById('contextualization'),
|
| 20 |
passageContent: document.getElementById('passage-content'),
|
| 21 |
hintsSection: document.getElementById('hints-section'),
|
|
@@ -82,6 +83,9 @@ class App {
|
|
| 82 |
|
| 83 |
this.elements.roundInfo.innerHTML = levelInfo;
|
| 84 |
|
|
|
|
|
|
|
|
|
|
| 85 |
// Show contextualization from AI agent
|
| 86 |
this.elements.contextualization.innerHTML = `
|
| 87 |
<div class="flex items-start gap-2">
|
|
@@ -192,6 +196,21 @@ class App {
|
|
| 192 |
// Show next button and hide submit button
|
| 193 |
this.elements.submitBtn.style.display = 'none';
|
| 194 |
this.elements.nextBtn.classList.remove('hidden');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 195 |
}
|
| 196 |
|
| 197 |
highlightAnswers(results) {
|
|
|
|
| 16 |
stickyControls: document.getElementById('sticky-controls'),
|
| 17 |
bookInfo: document.getElementById('book-info'),
|
| 18 |
roundInfo: document.getElementById('round-info'),
|
| 19 |
+
streakInfo: document.getElementById('streak-info'),
|
| 20 |
contextualization: document.getElementById('contextualization'),
|
| 21 |
passageContent: document.getElementById('passage-content'),
|
| 22 |
hintsSection: document.getElementById('hints-section'),
|
|
|
|
| 83 |
|
| 84 |
this.elements.roundInfo.innerHTML = levelInfo;
|
| 85 |
|
| 86 |
+
// Update streak display
|
| 87 |
+
this.updateStreakDisplay();
|
| 88 |
+
|
| 89 |
// Show contextualization from AI agent
|
| 90 |
this.elements.contextualization.innerHTML = `
|
| 91 |
<div class="flex items-start gap-2">
|
|
|
|
| 196 |
// Show next button and hide submit button
|
| 197 |
this.elements.submitBtn.style.display = 'none';
|
| 198 |
this.elements.nextBtn.classList.remove('hidden');
|
| 199 |
+
|
| 200 |
+
// Update streak display after processing results
|
| 201 |
+
this.updateStreakDisplay();
|
| 202 |
+
}
|
| 203 |
+
|
| 204 |
+
updateStreakDisplay() {
|
| 205 |
+
const stats = this.game.leaderboardService.getPlayerStats();
|
| 206 |
+
const currentStreak = stats.currentStreak;
|
| 207 |
+
|
| 208 |
+
if (currentStreak > 0) {
|
| 209 |
+
this.elements.streakInfo.innerHTML = `π₯ ${currentStreak} streak`;
|
| 210 |
+
this.elements.streakInfo.classList.remove('hidden');
|
| 211 |
+
} else {
|
| 212 |
+
this.elements.streakInfo.classList.add('hidden');
|
| 213 |
+
}
|
| 214 |
}
|
| 215 |
|
| 216 |
highlightAnswers(results) {
|