import chineseWordsTxt from '../assets/words/chinese.txt?raw' ; import frenchWordsTxt from '../assets/words/french.txt?raw' ; import germanWordsTxt from '../assets/words/german.txt?raw' ; import hebrewWordsTxt from '../assets/words/hebrew.txt?raw' ; import italianWordsTxt from '../assets/words/italian.txt?raw' ; import japaneseWordsTxt from '../assets/words/japanese.txt?raw' ; import koreanWordsTxt from '../assets/words/korean.txt?raw' ; import portugueseWordsTxt from '../assets/words/portuguese.txt?raw' ; import russianWordsTxt from '../assets/words/russian.txt?raw' ; import spanishWordsTxt from '../assets/words/spanish.txt?raw' ; import { shuffle } from './utils' ; const languageWords = { chinese : chineseWordsTxt , french : frenchWordsTxt , german : germanWordsTxt , hebrew : hebrewWordsTxt , italian : italianWordsTxt , japanese : japaneseWordsTxt , korean : koreanWordsTxt , portuguese : portugueseWordsTxt , russian : russianWordsTxt , spanish : spanishWordsTxt , } ; export type LanguageType = keyof typeof languageWords ; export interface Word { id : string ; english : string ; kanji : string ; hiragana : string ; } export let globalWords = [ ] ; function init ( language ) { const wordsTxt = languageWords [ language ] ; globalWords = getWords ( wordsTxt ) ; } function getWords ( wordsTxt ) { const lines = wordsTxt . split ( '\n' ) ; const wordObjects = [ ] ; for ( const line of lines ) { const [ kanji , hiragana , english ] = line . split ( ':' ) ; wordObjects . push ( { id : `${ kanji }:${ hiragana }` , english , kanji , hiragana , } ) ; } return wordObjects ; } export const questionsAtOnce = 3 ; export const maxLevel = 48 ; export interface GuessResult { success : boolean ; gameOver : boolean ; } export class WordGame { level = 1 ; learningWords : Word [ ] = [ ] ; buttonWords : Word [ ] = [ ] ; nextQuestionIndex = 0 ; correctWordIndex = 0 ; corrects = 0 ; mistakes = 0 ; constructor ( language , level ) { this . level = level || 1 ; init ( language ) ; const wordCount = Math . floor ( globalWords . length / maxLevel ) ; const firstIndex = ( level - 1 ) * wordCount ; this . learningWords = globalWords . slice ( firstIndex , firstIndex + wordCount ) ; shuffle ( this . learningWords ) ; if ( this . learningWords . length <= questionsAtOnce ) { throw new Error ( "popNextWord will have an infinite loop" ) ; } this . fillButtonWords ( ) ; } popNextWord ( ) { let nextWord ; while ( true ) { nextWord = this . learningWords [ this . nextQuestionIndex ] ; this . nextQuestionIndex ++ ; if ( this . nextQuestionIndex >= this . learningWords . length ) { this . nextQuestionIndex = 0 ; } if ( this . buttonWords . indexOf ( nextWord ) >= 0 ) { continue ; } else { break ; } } this . correctWordIndex = Math . floor ( Math . random ( ) * this . buttonWords . length ) ; return nextWord ; } fillButtonWords ( ) { while ( this . buttonWords . length < questionsAtOnce ) { const nextWord = this . popNextWord ( ) ; this . buttonWords . push ( nextWord ) ; } } getAnswerWord ( ) { return this . buttonWords [ this . correctWordIndex ] ; } remainingWords ( ) { const levelLength = this . learningWords . length ; return levelLength - this . corrects ; } totalWords ( ) { return this . learningWords . length ; } tryAnswer ( index ) { if ( index === this . correctWordIndex ) { this . corrects ++ ; const nextWord = this . popNextWord ( ) ; this . buttonWords [ index ] = nextWord ; let gameOver = false ; if ( this . remainingWords ( ) <= 0 ) { gameOver = true ; } this . fillButtonWords ( ) ; return { success : true , gameOver , } ; } else { this . mistakes ++ ; return { success : false , gameOver : false , } ; } } score ( ) { return this . corrects - this . mistakes ; } }