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,
|
correctCount: Int, incorrectCount: Int,
|
||||||
criteriaCorrect: Int, criteriaWrong: Int
|
criteriaCorrect: Int, criteriaWrong: Int
|
||||||
): VocabularyStage {
|
): VocabularyStage {
|
||||||
val readyToAdvance = if (isCorrect) correctCount >= criteriaCorrect else incorrectCount >= criteriaWrong
|
if (isCorrect) {
|
||||||
if (!readyToAdvance) return currentStage
|
// Correct answer: advance to next stage if criteria met
|
||||||
return when (currentStage) {
|
val readyToAdvance = correctCount >= criteriaCorrect
|
||||||
VocabularyStage.NEW -> VocabularyStage.STAGE_1
|
if (!readyToAdvance) return currentStage
|
||||||
VocabularyStage.STAGE_1 -> VocabularyStage.STAGE_2
|
return when (currentStage) {
|
||||||
VocabularyStage.STAGE_2 -> VocabularyStage.STAGE_3
|
VocabularyStage.NEW -> VocabularyStage.STAGE_1
|
||||||
VocabularyStage.STAGE_3 -> VocabularyStage.STAGE_4
|
VocabularyStage.STAGE_1 -> VocabularyStage.STAGE_2
|
||||||
VocabularyStage.STAGE_4 -> VocabularyStage.STAGE_5
|
VocabularyStage.STAGE_2 -> VocabularyStage.STAGE_3
|
||||||
VocabularyStage.STAGE_5 -> VocabularyStage.LEARNED
|
VocabularyStage.STAGE_3 -> VocabularyStage.STAGE_4
|
||||||
VocabularyStage.LEARNED -> VocabularyStage.LEARNED
|
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,8 +77,9 @@ fun VocabularyExerciseHostScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
// Reset exercise state when starting fresh
|
||||||
|
exerciseViewModel.resetExercise()
|
||||||
|
|
||||||
vocabularyViewModel.prepareExercise(
|
vocabularyViewModel.prepareExercise(
|
||||||
categoryIdsAsJson,
|
categoryIdsAsJson,
|
||||||
stageNamesAsJson,
|
stageNamesAsJson,
|
||||||
@@ -249,7 +250,15 @@ private fun ExerciseScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(currentExerciseState, score, wrongAnswers) {
|
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)
|
onFinish(score, wrongAnswers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,38 +240,12 @@ class VocabularyExerciseViewModel @Inject constructor(
|
|||||||
else -> if (shuffleLanguages) Random.nextBoolean() else false
|
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")
|
@Suppress("HardCodedStringLiteral")
|
||||||
Log.d("ExerciseDebug", "Item: ${itemToUse.wordFirst} (${itemToUse.languageFirstId}) / ${itemToUse.wordSecond} (${itemToUse.languageSecondId}), Switched: $isSwitched")
|
Log.d("ExerciseDebug", "Item: ${itemToUse.wordFirst} (${itemToUse.languageFirstId}) / ${itemToUse.wordSecond} (${itemToUse.languageSecondId}), Switched: $isSwitched")
|
||||||
@Suppress("HardCodedStringLiteral")
|
@Suppress("HardCodedStringLiteral")
|
||||||
Log.d("ExerciseDebug", "Origin Lang: ${config.originLanguageId}, Target Lang: ${config.targetLanguageId}")
|
Log.d("ExerciseDebug", "Origin Lang: ${config.originLanguageId}, Target Lang: ${config.targetLanguageId}")
|
||||||
|
|
||||||
|
// Set the exercise state based on the random type
|
||||||
_exerciseState.value = when (randomType) {
|
_exerciseState.value = when (randomType) {
|
||||||
VocabularyExerciseType.GUESSING -> VocabularyExerciseState.Guessing(
|
VocabularyExerciseType.GUESSING -> VocabularyExerciseState.Guessing(
|
||||||
item = itemToUse,
|
item = itemToUse,
|
||||||
@@ -344,18 +318,16 @@ class VocabularyExerciseViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkAnswer(answer: Any) {
|
private suspend fun checkAnswer(answer: Any) {
|
||||||
viewModelScope.launch {
|
val state = _exerciseState.value ?: return
|
||||||
val state = _exerciseState.value ?: return@launch
|
|
||||||
val correctAnswer = if (state.isSwitched) state.item.wordFirst else state.item.wordSecond
|
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) {
|
val isCorrect = when (state) {
|
||||||
is VocabularyExerciseState.Spelling -> {
|
is VocabularyExerciseState.Spelling -> {
|
||||||
val userAnswer = (answer as String).trim()
|
val userAnswer = (answer as String).trim()
|
||||||
val languageId = if (state.isSwitched) state.item.languageFirstId else state.item.languageSecondId
|
val languageId = if (state.isSwitched) state.item.languageFirstId else state.item.languageSecondId
|
||||||
val language = languageRepository.getLanguageById(languageId ?: 0)
|
val language = languageRepository.getLanguageById(languageId ?: 0)
|
||||||
?: return@launch
|
?: return
|
||||||
|
|
||||||
// Get articles for the language
|
// Get articles for the language
|
||||||
val articles = languageConfigRepository.getArticlesForLanguage(language.code)
|
val articles = languageConfigRepository.getArticlesForLanguage(language.code)
|
||||||
@@ -405,7 +377,6 @@ class VocabularyExerciseViewModel @Inject constructor(
|
|||||||
is VocabularyExerciseState.WordJumble -> state.copy(isCorrect = isCorrect, isRevealed = true)
|
is VocabularyExerciseState.WordJumble -> state.copy(isCorrect = isCorrect, isRevealed = true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateJumbledWord(assembledWord: List<Pair<Char, Int>>) {
|
private fun updateJumbledWord(assembledWord: List<Pair<Char, Int>>) {
|
||||||
_exerciseState.value = when (val state = _exerciseState.value) {
|
_exerciseState.value = when (val state = _exerciseState.value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user