milwright commited on
Commit
9ed86c2
Β·
1 Parent(s): dc9cc8c

Fix word matching logic to prevent fallback override

Browse files

- Only use manual fallback when AI provides zero words
- Add detailed logging to track word matching process
- Prevent valid AI selections from being replaced by fallback
- Fix issue where 'doubt' was replaced by 'thoughts' due to premature fallback

Files changed (1) hide show
  1. src/clozeGameEngine.js +31 -21
src/clozeGameEngine.js CHANGED
@@ -299,13 +299,13 @@ class ClozeGame {
299
  expectedBlanks = 3;
300
  }
301
 
302
- // If AI didn't provide enough words, fall back to manual selection
303
- if (selectedWords.length < expectedBlanks) {
304
- console.warn(`AI provided ${selectedWords.length} words but need ${expectedBlanks}, using fallback`);
305
  const words = this.originalText.split(/\s+/);
306
- const fallbackWords = this.selectWordsManually(words, expectedBlanks - selectedWords.length);
307
- selectedWords = [...selectedWords, ...fallbackWords].slice(0, expectedBlanks);
308
- console.log(`Combined AI + fallback words:`, selectedWords);
309
  }
310
 
311
  // Limit selected words to expected number
@@ -320,7 +320,9 @@ class ClozeGame {
320
 
321
  // Find indices of selected words using flexible matching
322
  const selectedIndices = [];
323
- selectedWords.forEach(word => {
 
 
324
  // First try exact match (cleaned)
325
  let index = wordsOnly.findIndex((w, idx) => {
326
  const cleanW = w.replace(/[^\w]/g, '').toLowerCase();
@@ -328,29 +330,37 @@ class ClozeGame {
328
  return cleanW === cleanWord && !selectedIndices.includes(idx);
329
  });
330
 
331
- // Fallback to includes match if exact fails
332
- if (index === -1) {
 
 
333
  index = wordsOnly.findIndex((w, idx) =>
334
  w.toLowerCase().includes(word.toLowerCase()) && !selectedIndices.includes(idx)
335
  );
336
- }
337
-
338
- // Enhanced fallback: try base word matching (remove common suffixes)
339
- if (index === -1) {
340
- const baseWord = word.replace(/[^\w]/g, '').toLowerCase().replace(/(ed|ing|s|es|er|est)$/, '');
341
- if (baseWord.length > 2) {
342
- index = wordsOnly.findIndex((w, idx) => {
343
- const cleanW = w.replace(/[^\w]/g, '').toLowerCase();
344
- const baseW = cleanW.replace(/(ed|ing|s|es|er|est)$/, '');
345
- return baseW === baseWord && !selectedIndices.includes(idx);
346
- });
 
 
 
 
 
 
347
  }
348
  }
349
 
350
  if (index !== -1) {
351
  selectedIndices.push(index);
352
  } else {
353
- console.warn(`Could not find word "${word}" in passage`);
354
  }
355
  });
356
 
 
299
  expectedBlanks = 3;
300
  }
301
 
302
+ // Only use fallback if AI provided no words at all
303
+ if (selectedWords.length === 0) {
304
+ console.warn(`AI provided no words, using manual fallback selection`);
305
  const words = this.originalText.split(/\s+/);
306
+ const fallbackWords = this.selectWordsManually(words, expectedBlanks);
307
+ selectedWords = fallbackWords;
308
+ console.log(`Fallback words:`, selectedWords);
309
  }
310
 
311
  // Limit selected words to expected number
 
320
 
321
  // Find indices of selected words using flexible matching
322
  const selectedIndices = [];
323
+ selectedWords.forEach((word, wordIdx) => {
324
+ console.log(`Searching for word ${wordIdx + 1}/${selectedWords.length}: "${word}"`);
325
+
326
  // First try exact match (cleaned)
327
  let index = wordsOnly.findIndex((w, idx) => {
328
  const cleanW = w.replace(/[^\w]/g, '').toLowerCase();
 
330
  return cleanW === cleanWord && !selectedIndices.includes(idx);
331
  });
332
 
333
+ if (index !== -1) {
334
+ console.log(`βœ“ Found exact match: "${wordsOnly[index]}" at position ${index}`);
335
+ } else {
336
+ // Fallback to includes match if exact fails
337
  index = wordsOnly.findIndex((w, idx) =>
338
  w.toLowerCase().includes(word.toLowerCase()) && !selectedIndices.includes(idx)
339
  );
340
+
341
+ if (index !== -1) {
342
+ console.log(`βœ“ Found includes match: "${wordsOnly[index]}" at position ${index}`);
343
+ } else {
344
+ // Enhanced fallback: try base word matching (remove common suffixes)
345
+ const baseWord = word.replace(/[^\w]/g, '').toLowerCase().replace(/(ed|ing|s|es|er|est)$/, '');
346
+ if (baseWord.length > 2) {
347
+ index = wordsOnly.findIndex((w, idx) => {
348
+ const cleanW = w.replace(/[^\w]/g, '').toLowerCase();
349
+ const baseW = cleanW.replace(/(ed|ing|s|es|er|est)$/, '');
350
+ return baseW === baseWord && !selectedIndices.includes(idx);
351
+ });
352
+
353
+ if (index !== -1) {
354
+ console.log(`βœ“ Found base word match: "${wordsOnly[index]}" at position ${index}`);
355
+ }
356
+ }
357
  }
358
  }
359
 
360
  if (index !== -1) {
361
  selectedIndices.push(index);
362
  } else {
363
+ console.warn(`βœ— Could not find word "${word}" in passage`);
364
  }
365
  });
366