update unlock material

This commit is contained in:
DimazzP 2025-02-21 09:32:07 +07:00
parent 522e568a9e
commit 98474010d0
9 changed files with 489 additions and 251 deletions

View File

@ -7,9 +7,11 @@ import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.navigation.NavType
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import androidx.navigation.navArgument
import com.example.lexilearn.data.model.MaterialDataModel import com.example.lexilearn.data.model.MaterialDataModel
import com.example.lexilearn.data.model.UserModel import com.example.lexilearn.data.model.UserModel
import com.example.lexilearn.data.repository.MaterialRepository import com.example.lexilearn.data.repository.MaterialRepository
@ -91,6 +93,15 @@ fun MyApp() {
composable("resultscreening") { ResultScreeningScreen(navController) } composable("resultscreening") { ResultScreeningScreen(navController) }
composable("learnAlphabet") { LearnAlphabetScreen(navController) } composable("learnAlphabet") { LearnAlphabetScreen(navController) }
composable("learnNumber") { LearnNumberScreen(navController) } composable("learnNumber") { LearnNumberScreen(navController) }
// composable(
// "navMaterial/{materialId}",
// arguments = listOf(
// navArgument("materialId") { type = NavType.StringType }
// )
// ) { backStackEntry ->
// val materialId = backStackEntry.arguments?.getString("materialId") ?: ""
// NavMaterialScreen(navController, materialId)
// }
composable("navMaterial/{materialId}") { backStackEntry -> composable("navMaterial/{materialId}") { backStackEntry ->
val materialId = backStackEntry.arguments?.getString("materialId") val materialId = backStackEntry.arguments?.getString("materialId")
NavMaterialScreen(navController, materialId ?: "") NavMaterialScreen(navController, materialId ?: "")
@ -99,9 +110,11 @@ fun MyApp() {
val materialList = navController.previousBackStackEntry val materialList = navController.previousBackStackEntry
?.savedStateHandle ?.savedStateHandle
?.get<List<MaterialDataModel>>("materialList") ?.get<List<MaterialDataModel>>("materialList")
val indexValue = navController.previousBackStackEntry
?.savedStateHandle
?.get<Int>("indexValue") ?: -1
if (materialList != null) { if (materialList != null) {
DetailMaterialScreen(navController, materialList) DetailMaterialScreen(navController, materialList, indexValue)
}else{ }else{
println("masuk kondisi else") println("masuk kondisi else")
} }
@ -111,14 +124,21 @@ fun MyApp() {
?.savedStateHandle ?.savedStateHandle
?.get<List<MaterialDataModel>>("selectedMaterialList") ?.get<List<MaterialDataModel>>("selectedMaterialList")
val selectedMaterial = selectedMaterialList?.firstOrNull() val typeQuiz = navController.previousBackStackEntry
?.savedStateHandle
?.get<String>("typeQuiz") ?: "default"
if (selectedMaterial != null) { val indexValue = navController.previousBackStackEntry
QuizScreen(navController, selectedMaterial) ?.savedStateHandle
?.get<Int>("indexValue") ?: 0
if (!selectedMaterialList.isNullOrEmpty()) {
QuizScreen(navController, selectedMaterialList, typeQuiz, indexValue)
} else { } else {
Text("Error: Data tidak tersedia") Text("Error: Data tidak tersedia")
} }
} }
// composable("detailMaterial/{materialJson}") { backStackEntry -> // composable("detailMaterial/{materialJson}") { backStackEntry ->
// val jsonMaterial = backStackEntry.arguments?.getString("materialJson") // val jsonMaterial = backStackEntry.arguments?.getString("materialJson")
// //

View File

@ -65,24 +65,27 @@ class MaterialRepository(private val context: Context) {
} }
fun updateUnlockData(idUnlock: String, value: Int, callback: (Boolean) -> Unit) { fun updateUnlockData(idUnlock: String, value: Int, callback: (Boolean) -> Unit) {
try {
val userId = sharedPrefHelper.getUserId() val userId = sharedPrefHelper.getUserId()
if (userId == null) { if (userId == null) {
println("printUpdateUnlock: userId is null")
callback(false) callback(false)
return return
} }
val userRef = FirebaseDatabase.getInstance().getReference("users/$userId/unlock_data/$idUnlock") val userRef = FirebaseDatabase.getInstance().getReference("users/$userId/unlock_data/$idUnlock")
// 🔥 Ambil data user dari Firebase // Ambil data user dari Firebase dengan try-catch di dalam callback
userRef.get().addOnSuccessListener { snapshot -> userRef.get().addOnSuccessListener { snapshot ->
try {
val currentValue = snapshot.getValue(Int::class.java) ?: 0 val currentValue = snapshot.getValue(Int::class.java) ?: 0
// 🔥 Hanya update jika nilai baru lebih besar // Hanya update jika nilai baru lebih besar
if (value > currentValue) { if (value > currentValue) {
userRef.setValue(value).addOnCompleteListener { task -> userRef.setValue(value).addOnCompleteListener { task ->
try {
if (task.isSuccessful) { if (task.isSuccessful) {
// 🔥 Update juga di SharedPreferences // Update juga di SharedPreferences
val updatedUser = sharedPrefHelper.getUserData() val updatedUser = sharedPrefHelper.getUserData()
updatedUser?.unlock_data?.let { unlockData -> updatedUser?.unlock_data?.let { unlockData ->
when (idUnlock) { when (idUnlock) {
@ -92,20 +95,110 @@ class MaterialRepository(private val context: Context) {
"limb" -> unlockData.limb = value "limb" -> unlockData.limb = value
} }
} }
sharedPrefHelper.saveUserData(updatedUser!!) // Pastikan updatedUser tidak null sebelum menyimpan
if (updatedUser != null) {
println("printUpdateUnlock: successfully updated Firebase and SharedPreferences")
sharedPrefHelper.saveUserData(updatedUser)
callback(true) callback(true)
} else { } else {
println("printUpdateUnlock: updatedUser is null after updating Firebase")
callback(false)
}
} else {
println("printUpdateUnlock: task is not successful")
callback(false)
}
} catch (e: Exception) {
e.printStackTrace()
println("printUpdateUnlock: exception in onCompleteListener: $e")
callback(false) callback(false)
} }
} }
} else { } else {
callback(false) // 🔥 Jika nilai baru <= nilai lama, tidak update println("printUpdateUnlock: new value $value is not greater than current value $currentValue")
callback(false) // Jika nilai baru <= nilai lama, tidak update
}
} catch (e: Exception) {
e.printStackTrace()
println("printUpdateUnlock: exception in onSuccessListener: $e")
callback(false)
} }
}.addOnFailureListener { }.addOnFailureListener {
it.printStackTrace()
println("printUpdateUnlock: failed to get data: ${it.message}")
callback(false)
}
} catch (e: Exception) {
println("printUpdateUnlock: error_update_unlock_data: $e")
e.printStackTrace()
callback(false) callback(false)
} }
} }
// fun updateUnlockData(idUnlock: String, value: Int, callback: (Boolean) -> Unit) {
// try {
// val userId = sharedPrefHelper.getUserId()
// if (userId == null) {
// callback(false)
// return
// }
//
// val userRef = FirebaseDatabase.getInstance().getReference("users/$userId/unlock_data/$idUnlock")
//
// // Ambil data user dari Firebase dengan try-catch di dalam callback
// userRef.get().addOnSuccessListener { snapshot ->
// try {
// val currentValue = snapshot.getValue(Int::class.java) ?: 0
//
// // Hanya update jika nilai baru lebih besar
// if (value > currentValue) {
// userRef.setValue(value).addOnCompleteListener { task ->
// try {
// if (task.isSuccessful) {
// // Update juga di SharedPreferences
// val updatedUser = sharedPrefHelper.getUserData()
// updatedUser?.unlock_data?.let { unlockData ->
// when (idUnlock) {
// "animal" -> unlockData.animal = value
// "family" -> unlockData.family = value
// "house" -> unlockData.house = value
// "limb" -> unlockData.limb = value
// }
// }
// // Pastikan updatedUser tidak null sebelum menyimpan
// if (updatedUser != null) {
// sharedPrefHelper.saveUserData(updatedUser)
// callback(true)
// } else {
// callback(false)
// }
// } else {
// callback(false)
// }
// } catch (e: Exception) {
// e.printStackTrace()
// callback(false)
// }
// }
// } else {
// callback(false) // Jika nilai baru <= nilai lama, tidak update
// }
// } catch (e: Exception) {
// e.printStackTrace()
// callback(false)
// }
// }.addOnFailureListener {
// it.printStackTrace()
// callback(false)
// }
// } catch (e: Exception) {
// println("error_update_unlock_data: $e")
// e.printStackTrace()
// callback(false)
// }
// }
fun getUnlockValue(idUnlock: String, callback: (Int?) -> Unit) { fun getUnlockValue(idUnlock: String, callback: (Int?) -> Unit) {
val userId = sharedPrefHelper.getUserId() val userId = sharedPrefHelper.getUserId()

View File

@ -41,7 +41,7 @@ import com.example.lexilearn.ui.theme.ctextBlack
import com.example.lexilearn.ui.theme.ctextGray import com.example.lexilearn.ui.theme.ctextGray
@Composable @Composable
fun DetailMaterialScreen(navController: NavController, materialListData: List<MaterialDataModel>) { fun DetailMaterialScreen(navController: NavController, materialListData: List<MaterialDataModel>, indexValue: Int) {
val viewModel: DetailMaterialViewModel = viewModel() val viewModel: DetailMaterialViewModel = viewModel()
LaunchedEffect(materialListData) { LaunchedEffect(materialListData) {
viewModel.fetchMaterial(materialListData) viewModel.fetchMaterial(materialListData)
@ -154,17 +154,19 @@ fun DetailMaterialScreen(navController: NavController, materialListData: List<Ma
} }
ButtonNext( ButtonNext(
onclick = { onclick = {
val selectedMaterial = materialListData.firstOrNull() if (materialListData.isNotEmpty()) {
if (selectedMaterial != null) {
// Simpan ke savedStateHandle sebagai List<MaterialDataModel> tapi hanya satu elemen
navController.currentBackStackEntry navController.currentBackStackEntry
?.savedStateHandle ?.savedStateHandle
?.set("selectedMaterialList", listOf(selectedMaterial)) ?.set("selectedMaterialList", viewModel.randomMaterialModel())
navController.currentBackStackEntry
// Navigasi ke QuizScreen ?.savedStateHandle
?.set("typeQuiz", materialListData[0].category)
navController.currentBackStackEntry
?.savedStateHandle
?.set("indexValue", indexValue)
navController.navigate("quizScreen") navController.navigate("quizScreen")
} }
// navController.navigate("spell")
}, },
text = "Kerjakan Kuis", text = "Kerjakan Kuis",
painter = painterResource(id = R.drawable.ic_next), painter = painterResource(id = R.drawable.ic_next),

View File

@ -7,6 +7,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import com.example.lexilearn.data.model.MaterialDataModel import com.example.lexilearn.data.model.MaterialDataModel
import com.example.lexilearn.data.repository.MaterialRepository import com.example.lexilearn.data.repository.MaterialRepository
import com.example.lexilearn.data.repository.QuizRepository
import com.example.lexilearn.domain.models.ModelSpell import com.example.lexilearn.domain.models.ModelSpell
import com.example.lexilearn.utils.generateNumberList import com.example.lexilearn.utils.generateNumberList
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -20,6 +21,7 @@ class DetailMaterialViewModel(application: Application) : AndroidViewModel(appli
private val _isTTSInitialized = MutableLiveData(false) private val _isTTSInitialized = MutableLiveData(false)
val isTTSInitialized: LiveData<Boolean> = _isTTSInitialized val isTTSInitialized: LiveData<Boolean> = _isTTSInitialized
val alphabetList = generateNumberList() val alphabetList = generateNumberList()
private val quizRepository = QuizRepository()
private val repository = MaterialRepository(application) private val repository = MaterialRepository(application)
@ -46,6 +48,10 @@ class DetailMaterialViewModel(application: Application) : AndroidViewModel(appli
} }
} }
fun randomMaterialModel(): List<MaterialDataModel> {
return _materialList.value.shuffled()
}
init { init {
tts = TextToSpeech(application, this) tts = TextToSpeech(application, this)
} }

View File

@ -249,7 +249,7 @@ fun HomeScreen(navController: NavController) {
) )
} }
} }
ButtonHome(onClick = { }, ButtonHome(onClick = { navController.navigate("navMaterial/house") },
color = Color(0xffea2b72), color = Color(0xffea2b72),
modifier = Modifier modifier = Modifier
@ -304,7 +304,7 @@ fun HomeScreen(navController: NavController) {
) )
} }
} }
ButtonHome(onClick = { navController.navigate("read") }, ButtonHome(onClick = { navController.navigate("navMaterial/family") },
color = Color(0xffedb92f), color = Color(0xffedb92f),
modifier = Modifier modifier = Modifier
.constrainAs(newsRef) { .constrainAs(newsRef) {

View File

@ -17,6 +17,9 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.blur
@ -44,6 +47,16 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
viewModel.fetchMaterial(materialId) viewModel.fetchMaterial(materialId)
} }
val numberUnlock by navController.currentBackStackEntry
?.savedStateHandle
?.getLiveData<Int>("numberUnlock")
?.observeAsState(initial = 0) ?: remember { mutableIntStateOf(0) }
LaunchedEffect(numberUnlock) {
println("printUpdateUnlock-nav $numberUnlock")
viewModel.updateUnlockValue(materialId, numberUnlock)
}
val materialList by viewModel.materialList.collectAsState() val materialList by viewModel.materialList.collectAsState()
val textTitle by viewModel.textTitle.observeAsState("") val textTitle by viewModel.textTitle.observeAsState("")
val sizeUnlock by viewModel.sizeUnlock.observeAsState() val sizeUnlock by viewModel.sizeUnlock.observeAsState()
@ -89,6 +102,9 @@ fun NavMaterialScreen(navController: NavController, materialId: String) {
"materialList", "materialList",
chunk chunk
) )
navController.currentBackStackEntry?.savedStateHandle?.set(
"indexValue", index
)
navController.navigate("detailMaterial") navController.navigate("detailMaterial")
} }
}, },

View File

@ -73,6 +73,19 @@ class NavMaterialViewModel(application: Application) : AndroidViewModel(applicat
} }
} }
fun updateUnlockValue(materialId: String, value: Int) {
if(value >= (_sizeUnlock.value ?: 0) && _materialList.value.size > value){
viewModelScope.launch {
repository.updateUnlockData(materialId, value){
println("numberUnlock update unlock value success $it")
fetchMaterial(materialId)
}
}
}else{
println("numberUnlock-else $value, ${_sizeUnlock.value}, ${_materialList.value.size}")
}
}
override fun onCleared() { override fun onCleared() {
tts?.stop() tts?.stop()
tts?.shutdown() tts?.shutdown()

View File

@ -42,6 +42,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.key
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateMapOf import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -50,6 +51,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.zIndex
import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.ConstraintLayout
import com.example.lexilearn.R import com.example.lexilearn.R
import com.example.lexilearn.data.model.QuestionType import com.example.lexilearn.data.model.QuestionType
@ -67,9 +69,12 @@ import kotlin.math.roundToInt
@Composable @Composable
fun QuizScreen( fun QuizScreen(
navController: NavController, navController: NavController,
material: MaterialDataModel, materials: List<MaterialDataModel>,
typeQuiz: String,
indexValue: Int,
quizViewModel: QuizViewModel = viewModel() quizViewModel: QuizViewModel = viewModel()
) { ) {
println("testco tipe: ${typeQuiz}, index = ${indexValue}")
val question by quizViewModel.currentQuestion.collectAsState() val question by quizViewModel.currentQuestion.collectAsState()
val isButtonVisible by quizViewModel.isButtonVisible val isButtonVisible by quizViewModel.isButtonVisible
val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState() val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState()
@ -77,16 +82,8 @@ fun QuizScreen(
val snackbarMessage by quizViewModel.snackbarMessage.collectAsState() val snackbarMessage by quizViewModel.snackbarMessage.collectAsState()
val snackbarHostState = remember { SnackbarHostState() } val snackbarHostState = remember { SnackbarHostState() }
val indexQuiz by quizViewModel.indexQuiz.collectAsState()
LaunchedEffect(Unit) {
quizViewModel.loadRandomQuestion(material)
}
LaunchedEffect(snackbarMessage) {
snackbarMessage?.let { message ->
snackbarHostState.showSnackbar(message)
quizViewModel.onSnackbarShown()
}
}
var rectColumnAnswer by remember { mutableStateOf(Rect.Zero) } var rectColumnAnswer by remember { mutableStateOf(Rect.Zero) }
@ -128,10 +125,50 @@ fun QuizScreen(
mutableStateMapOf<Int, Rect>() mutableStateMapOf<Int, Rect>()
} }
fun clearOffsets() {
boxRectAnswer.clear()
boxRectDragable.clear()
cardSize.clear()
quizXOffset.clear()
quizYOffset.clear()
boxRectQuiz.clear()
answerXOffset.clear()
answerYOffset.clear()
}
LaunchedEffect(Unit) {
quizViewModel.initMaterialData(materials)
}
LaunchedEffect(indexQuiz) {
println("indexQuizValue = $indexQuiz")
if (indexQuiz < materials.size) {
clearOffsets()
quizViewModel.randomQuestion()
} else {
navController.getBackStackEntry("navMaterial/$typeQuiz")
.savedStateHandle
.set("numberUnlock", indexValue + 1)
println("printUpdateUnlock-quiz $indexValue")
// Kemudian kembali ke halaman sebelumnya
navController.popBackStack()
navController.popBackStack()
}
}
LaunchedEffect(snackbarMessage) {
snackbarMessage?.let { message ->
snackbarHostState.showSnackbar(message)
quizViewModel.onSnackbarShown()
}
}
Scaffold( Scaffold(
snackbarHost = { SnackbarHost(hostState = snackbarHostState) } snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
){innerPadding-> ) { innerPadding ->
Surface(modifier = Modifier.fillMaxSize().padding(innerPadding)) { Surface(
modifier = Modifier
.fillMaxSize()
.padding(innerPadding)
) {
GradientQuiz( GradientQuiz(
navController = navController, navController = navController,
headerText = stringResource(id = R.string.spelltitle), headerText = stringResource(id = R.string.spelltitle),
@ -205,6 +242,7 @@ fun QuizScreen(
) { ) {
dataQuiz.forEach { dt -> dataQuiz.forEach { dt ->
key(dt.id) {
val id = dt.id val id = dt.id
if (!boxRectDragable.containsKey(id)) if (!boxRectDragable.containsKey(id))
boxRectDragable[id] = Rect.Zero boxRectDragable[id] = Rect.Zero
@ -217,11 +255,13 @@ fun QuizScreen(
CardQuiz( CardQuiz(
modifier = Modifier modifier = Modifier
.zIndex(zIndex = 1f)
.padding(vertical = 10.dp) .padding(vertical = 10.dp)
.size(minSize) .size(minSize)
.onGloballyPositioned { coordinates -> .onGloballyPositioned { coordinates ->
if (dt.type) if (dt.type)
boxRectQuiz[id] = coordinates.boundsInWindow() boxRectQuiz[id] =
coordinates.boundsInWindow()
} }
) { ) {
if (dt.type) { if (dt.type) {
@ -237,8 +277,10 @@ fun QuizScreen(
item = dt.data, item = dt.data,
modifier = Modifier modifier = Modifier
.offset { .offset {
val xOffset = quizXOffset[id] ?: 0f val xOffset =
val yOffset = quizYOffset[id] ?: 0f quizXOffset[id] ?: 0f
val yOffset =
quizYOffset[id] ?: 0f
IntOffset( IntOffset(
xOffset.roundToInt(), xOffset.roundToInt(),
yOffset.roundToInt() yOffset.roundToInt()
@ -277,13 +319,17 @@ fun QuizScreen(
dt dt
) )
dt.apply { dt.apply {
hasContent = false hasContent =
showCard = false false
showCard =
false
data = "?" data = "?"
} }
checkNull = true checkNull = true
quizXOffset[id] = 0f quizXOffset[id] =
quizYOffset[id] = 0f 0f
quizYOffset[id] =
0f
break break
} }
} }
@ -294,14 +340,19 @@ fun QuizScreen(
val emDt = dt.emp val emDt = dt.emp
if (emDt != null) { if (emDt != null) {
dt.apply { dt.apply {
hasContent = false hasContent =
showCard = false false
showCard =
false
data = "?" data = "?"
} }
checkNull = true checkNull = true
cardSize[emDt] = maxSize cardSize[emDt] =
quizXOffset[id] = 0f maxSize
quizYOffset[id] = 0f quizXOffset[id] =
0f
quizYOffset[id] =
0f
dt.data = "?" dt.data = "?"
} }
} }
@ -328,6 +379,7 @@ fun QuizScreen(
} }
} }
} }
}
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
} }
} }
@ -353,6 +405,7 @@ fun QuizScreen(
horizontalArrangement = Arrangement.Center horizontalArrangement = Arrangement.Center
) { ) {
rowItems.forEach { item -> rowItems.forEach { item ->
key(item.id) {
val id = item.id val id = item.id
if (!cardSize.containsKey(id)) if (!cardSize.containsKey(id))
cardSize[id] = maxSize cardSize[id] = maxSize
@ -374,7 +427,8 @@ fun QuizScreen(
) )
} }
.onGloballyPositioned { coordinates -> .onGloballyPositioned { coordinates ->
boxRectAnswer[id] = coordinates.boundsInWindow() boxRectAnswer[id] =
coordinates.boundsInWindow()
} }
.pointerInput(Unit) { .pointerInput(Unit) {
detectDragGestures( detectDragGestures(
@ -427,6 +481,7 @@ fun QuizScreen(
} }
} }
} }
}
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
} }

View File

@ -24,6 +24,9 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
TextToSpeech.OnInitListener { TextToSpeech.OnInitListener {
private val quizRepository = QuizRepository() private val quizRepository = QuizRepository()
private var materialList: List<MaterialDataModel> = emptyList()
private val _currentQuestion = MutableStateFlow<QuizQuestion?>(null) private val _currentQuestion = MutableStateFlow<QuizQuestion?>(null)
val currentQuestion: StateFlow<QuizQuestion?> = _currentQuestion val currentQuestion: StateFlow<QuizQuestion?> = _currentQuestion
@ -33,6 +36,14 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
private val _isAnswerCorrect = MutableStateFlow<Boolean?>(null) private val _isAnswerCorrect = MutableStateFlow<Boolean?>(null)
val isAnswerCorrect: StateFlow<Boolean?> = _isAnswerCorrect val isAnswerCorrect: StateFlow<Boolean?> = _isAnswerCorrect
private val _indexQuiz = MutableStateFlow(0)
val indexQuiz: StateFlow<Int> = _indexQuiz
// Update indexQuiz saat jawaban benar
fun incrementIndexQuiz() {
_indexQuiz.value += 1
}
fun loadNewQuestion(material: MaterialDataModel, questionMode: Int, answerMode: Int) { fun loadNewQuestion(material: MaterialDataModel, questionMode: Int, answerMode: Int) {
_currentQuestion.value = quizRepository.generateQuestion(material, questionMode, answerMode) _currentQuestion.value = quizRepository.generateQuestion(material, questionMode, answerMode)
} }
@ -63,28 +74,49 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
} }
fun loadRandomQuestion(material: MaterialDataModel) { fun initMaterialData(material: List<MaterialDataModel>) {
_currentQuestion.value = quizRepository.generateQuestion(material, 2, 2) materialList = material;
}
val dataQuest = // fun randomQuestion() {
_currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char -> // _currentQuestion.value = quizRepository.generateQuestion(materialList[_indexQuiz.value], 2, 2)
ModelSpell(index + 1, true, "?", showCard = false) // val dataQuest =
// _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
// ModelSpell(index + 1, true, data = "coba $char", showCard = false)
// } ?: emptyList()
// _questionShuffled.value = dataQuest
//
// val listAnswer =
// _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
// ModelAnswerRead(index + 1, char.toString())
// } ?: emptyList()
// val shuflledAnswer = listAnswer.shuffled()
// _shuffledAnswerLetters.value = shuflledAnswer
// println("testlistanswer ${_shuffledAnswerLetters.value}")
// }
// Di dalam fungsi randomQuestion() pada QuizViewModel
fun randomQuestion() {
_currentQuestion.value = quizRepository.generateQuestion(materialList[_indexQuiz.value], 2, 2)
// Generate unique IDs berdasarkan indexQuiz dan indeks karakter
val dataQuest = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
ModelSpell(
id = (_indexQuiz.value * 100) + index + 1, // ID unik per pertanyaan
type = true,
data = "?",
showCard = false
)
} ?: emptyList() } ?: emptyList()
_questionShuffled.value = dataQuest _questionShuffled.value = dataQuest
val listAnswer = val listAnswer = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
_currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char -> ModelAnswerRead(
ModelAnswerRead(index + 1, char.toString()) id = (_indexQuiz.value * 100) + index + 1, // ID unik per pertanyaan
data = char.toString()
)
} ?: emptyList() } ?: emptyList()
val shuflledAnswer = listAnswer.shuffled() _shuffledAnswerLetters.value = listAnswer.shuffled()
_shuffledAnswerLetters.value = shuflledAnswer }
// Menambahkan delay 1 detik sebelum memanggil observeData()
// viewModelScope.launch {
// delay(1000L) // delay 1 detik
//
// }
}
fun submitAnswer(answer: String) { fun submitAnswer(answer: String) {
@ -139,6 +171,7 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
val checkData = checkAnswer(answerString); val checkData = checkAnswer(answerString);
if (checkData) { if (checkData) {
triggerSnackbar("Jawaban Benar") triggerSnackbar("Jawaban Benar")
incrementIndexQuiz()
} else { } else {
triggerSnackbar("Jawaban Salah") triggerSnackbar("Jawaban Salah")
} }