import { assertExists } from '@ulangi/assert' ; import { DefinitionExtraFieldParser , VocabularyExtraFieldParser , } from '@ulangi/ulangi-common/core' ; import { Definition , Vocabulary } from '@ulangi/ulangi-common/interfaces' ; import { ObservableReflexQuestion } from '@ulangi/ulangi-observable' ; import * as _ from 'lodash' ; import { DefinitionPool } from '../pools/DefinitionPool' ; import { RandomVocabularyIterator } from './RandomVocabularyIterator' ; export class ReflexQuestionIterator { private vocabularyExtraFieldParser = new VocabularyExtraFieldParser ( ) ; private definitionExtraFieldParser = new DefinitionExtraFieldParser ( ) ; private definitionPool = new DefinitionPool ( ) ; private randomVocabularyIterator : RandomVocabularyIterator ; private currentQuestion ? : ObservableReflexQuestion ; public constructor ( vocabularyList ? ) { this . randomVocabularyIterator = new RandomVocabularyIterator ( vocabularyList ) ; this . definitionPool = new DefinitionPool ( new Map ( typeof vocabularyList !== 'undefined' ? _ . flatMap ( Array . from ( vocabularyList . values ( ) ) , ( vocabulary ) : [ string , Definition ] [ ] => { return vocabulary . definitions . map ( ( definition ) : [ string , Definition ] => { return [ definition . definitionId , definition ] ; } ) ; } ) : [ ] ) ) ; } public next ( ) { const nextVocabulary = this . randomVocabularyIterator . next ( ) ; this . currentQuestion = this . makeQuestion ( nextVocabulary ) ; return this . currentQuestion ; } public current ( ) { return assertExists ( this . currentQuestion ) ; } public merge ( vocabularyList ) { this . randomVocabularyIterator . merge ( vocabularyList ) ; this . definitionPool . merge ( new Map ( typeof vocabularyList !== 'undefined' ? _ . flatMap ( Array . from ( vocabularyList . values ( ) ) , ( vocabulary ) : [ string , Definition ] [ ] => { return vocabulary . definitions . map ( ( definition ) : [ string , Definition ] => { return [ definition . definitionId , definition ] ; } ) ; } ) : [ ] ) ) ; } public isDone ( ) { return this . randomVocabularyIterator . isDone ( ) ; } public getNumberOfQuestionLeft ( ) { return this . randomVocabularyIterator . getQueueSize ( ) ; } public shuffleQueue ( ) { this . randomVocabularyIterator . shuffleQueue ( ) ; } public reset ( ) { this . randomVocabularyIterator = new RandomVocabularyIterator ( ) ; this . currentQuestion = undefined ; } private makeQuestion ( vocabulary ) { const correctDefinition = assertExists ( _ . sample ( vocabulary . definitions . slice ( ) ) , 'definition should not be null or undefined' ) ; const correctMeaning = this . definitionExtraFieldParser . parse ( correctDefinition . meaning ) . plainMeaning ; const exceptIds = vocabulary . definitions . map ( ( definition ) : string => definition . definitionId ) ; const randomDefinition = assertExists ( _ . first ( this . definitionPool . getRandomDefinitionsFromPool ( 1 , false , exceptIds ) ) , 'definition should not be null or undefined' ) ; const randomMeaning = this . definitionExtraFieldParser . parse ( randomDefinition . meaning ) . plainMeaning ; return new ObservableReflexQuestion ( this . vocabularyExtraFieldParser . parse ( vocabulary . vocabularyText ) . vocabularyTerm , _ . random ( 0 , 1 ) === 1 ? correctMeaning : randomMeaning , correctMeaning ) ; } }