implement demotion logic in VocabularyRepository and refactor VocabularyExerciseViewModel answer checking
This commit is contained in:
@@ -480,16 +480,32 @@ class VocabularyRepository private constructor(context: Context) {
|
||||
correctCount: Int, incorrectCount: Int,
|
||||
criteriaCorrect: Int, criteriaWrong: Int
|
||||
): VocabularyStage {
|
||||
val readyToAdvance = if (isCorrect) correctCount >= criteriaCorrect else incorrectCount >= criteriaWrong
|
||||
if (!readyToAdvance) return currentStage
|
||||
return when (currentStage) {
|
||||
VocabularyStage.NEW -> VocabularyStage.STAGE_1
|
||||
VocabularyStage.STAGE_1 -> VocabularyStage.STAGE_2
|
||||
VocabularyStage.STAGE_2 -> VocabularyStage.STAGE_3
|
||||
VocabularyStage.STAGE_3 -> VocabularyStage.STAGE_4
|
||||
VocabularyStage.STAGE_4 -> VocabularyStage.STAGE_5
|
||||
VocabularyStage.STAGE_5 -> VocabularyStage.LEARNED
|
||||
VocabularyStage.LEARNED -> VocabularyStage.LEARNED
|
||||
if (isCorrect) {
|
||||
// Correct answer: advance to next stage if criteria met
|
||||
val readyToAdvance = correctCount >= criteriaCorrect
|
||||
if (!readyToAdvance) return currentStage
|
||||
return when (currentStage) {
|
||||
VocabularyStage.NEW -> VocabularyStage.STAGE_1
|
||||
VocabularyStage.STAGE_1 -> VocabularyStage.STAGE_2
|
||||
VocabularyStage.STAGE_2 -> VocabularyStage.STAGE_3
|
||||
VocabularyStage.STAGE_3 -> VocabularyStage.STAGE_4
|
||||
VocabularyStage.STAGE_4 -> VocabularyStage.STAGE_5
|
||||
VocabularyStage.STAGE_5 -> VocabularyStage.LEARNED
|
||||
VocabularyStage.LEARNED -> VocabularyStage.LEARNED
|
||||
}
|
||||
} else {
|
||||
// Incorrect answer: demote to previous stage if criteria met
|
||||
val readyToDemote = incorrectCount >= criteriaWrong
|
||||
if (!readyToDemote) return currentStage
|
||||
return when (currentStage) {
|
||||
VocabularyStage.LEARNED -> VocabularyStage.STAGE_5
|
||||
VocabularyStage.STAGE_5 -> VocabularyStage.STAGE_4
|
||||
VocabularyStage.STAGE_4 -> VocabularyStage.STAGE_3
|
||||
VocabularyStage.STAGE_3 -> VocabularyStage.STAGE_2
|
||||
VocabularyStage.STAGE_2 -> VocabularyStage.STAGE_1
|
||||
VocabularyStage.STAGE_1 -> VocabularyStage.STAGE_1
|
||||
VocabularyStage.NEW -> VocabularyStage.NEW
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,8 @@ fun VocabularyExerciseHostScreen(
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
|
||||
// Reset exercise state when starting fresh
|
||||
exerciseViewModel.resetExercise()
|
||||
|
||||
vocabularyViewModel.prepareExercise(
|
||||
categoryIdsAsJson,
|
||||
@@ -249,7 +250,15 @@ private fun ExerciseScreen(
|
||||
}
|
||||
|
||||
LaunchedEffect(currentExerciseState, score, wrongAnswers) {
|
||||
if (currentExerciseState == null && (score + wrongAnswers) >= totalItems && totalItems > 0) {
|
||||
// Only trigger completion when:
|
||||
// 1. Current exercise state is null (no more items to show)
|
||||
// 2. We have answered all items (score + wrong = total)
|
||||
// 3. We have at least one item to process
|
||||
// 4. We're not already in a completed state (prevent duplicate triggers)
|
||||
if (currentExerciseState == null &&
|
||||
(score + wrongAnswers) >= totalItems &&
|
||||
totalItems > 0 &&
|
||||
(score + wrongAnswers) > 0) {
|
||||
onFinish(score, wrongAnswers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,38 +240,12 @@ class VocabularyExerciseViewModel @Inject constructor(
|
||||
else -> if (shuffleLanguages) Random.nextBoolean() else false
|
||||
}
|
||||
|
||||
_exerciseState.value = when (randomType) {
|
||||
VocabularyExerciseType.GUESSING -> VocabularyExerciseState.Guessing(
|
||||
item = itemToUse,
|
||||
isSwitched = isSwitched
|
||||
)
|
||||
VocabularyExerciseType.SPELLING -> VocabularyExerciseState.Spelling(
|
||||
item = itemToUse,
|
||||
isSwitched = isSwitched
|
||||
)
|
||||
VocabularyExerciseType.MULTIPLE_CHOICE -> {
|
||||
val correctAnswer = if (isSwitched) itemToUse.wordFirst else itemToUse.wordSecond
|
||||
val options = generateMultipleChoiceOptions(correctAnswer, isSwitched)
|
||||
VocabularyExerciseState.MultipleChoice(
|
||||
item = itemToUse,
|
||||
isSwitched = isSwitched,
|
||||
options = options
|
||||
)
|
||||
}
|
||||
VocabularyExerciseType.WORD_JUMBLE -> {
|
||||
val wordToJumble = if (isSwitched) itemToUse.wordFirst else itemToUse.wordSecond
|
||||
VocabularyExerciseState.WordJumble(
|
||||
item = itemToUse,
|
||||
isSwitched = isSwitched,
|
||||
jumbledLetters = wordToJumble.toList().mapIndexed { index, char -> Pair(char, index) }.shuffled()
|
||||
)
|
||||
}
|
||||
}
|
||||
@Suppress("HardCodedStringLiteral")
|
||||
Log.d("ExerciseDebug", "Item: ${itemToUse.wordFirst} (${itemToUse.languageFirstId}) / ${itemToUse.wordSecond} (${itemToUse.languageSecondId}), Switched: $isSwitched")
|
||||
@Suppress("HardCodedStringLiteral")
|
||||
Log.d("ExerciseDebug", "Origin Lang: ${config.originLanguageId}, Target Lang: ${config.targetLanguageId}")
|
||||
|
||||
// Set the exercise state based on the random type
|
||||
_exerciseState.value = when (randomType) {
|
||||
VocabularyExerciseType.GUESSING -> VocabularyExerciseState.Guessing(
|
||||
item = itemToUse,
|
||||
@@ -344,18 +318,16 @@ class VocabularyExerciseViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAnswer(answer: Any) {
|
||||
viewModelScope.launch {
|
||||
val state = _exerciseState.value ?: return@launch
|
||||
private suspend fun checkAnswer(answer: Any) {
|
||||
val state = _exerciseState.value ?: return
|
||||
val correctAnswer = if (state.isSwitched) state.item.wordFirst else state.item.wordSecond
|
||||
|
||||
// Check if the state is a Spelling type before proceeding with specific logic
|
||||
val isCorrect = when (state) {
|
||||
is VocabularyExerciseState.Spelling -> {
|
||||
val userAnswer = (answer as String).trim()
|
||||
val languageId = if (state.isSwitched) state.item.languageFirstId else state.item.languageSecondId
|
||||
val language = languageRepository.getLanguageById(languageId ?: 0)
|
||||
?: return@launch
|
||||
?: return
|
||||
|
||||
// Get articles for the language
|
||||
val articles = languageConfigRepository.getArticlesForLanguage(language.code)
|
||||
@@ -405,7 +377,6 @@ class VocabularyExerciseViewModel @Inject constructor(
|
||||
is VocabularyExerciseState.WordJumble -> state.copy(isCorrect = isCorrect, isRevealed = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateJumbledWord(assembledWord: List<Pair<Char, Int>>) {
|
||||
_exerciseState.value = when (val state = _exerciseState.value) {
|
||||
|
||||
Reference in New Issue
Block a user