update quiz type 2

This commit is contained in:
DimazzP 2025-02-16 14:01:59 +07:00
parent 133fa954fd
commit 522e568a9e
2 changed files with 362 additions and 545 deletions

View File

@ -31,20 +31,21 @@ import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import com.example.lexilearn.data.model.MaterialDataModel
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.VolumeUp
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Surface
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateMapOf
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.Dp
@ -52,8 +53,6 @@ import androidx.compose.ui.unit.IntOffset
import androidx.constraintlayout.compose.ConstraintLayout
import com.example.lexilearn.R
import com.example.lexilearn.data.model.QuestionType
import com.example.lexilearn.domain.models.ModelAnswerRead
import com.example.lexilearn.ui.components.ButtonNext
import com.example.lexilearn.ui.components.CardQuiz
import com.example.lexilearn.ui.components.DraggableAnswerCard
import com.example.lexilearn.ui.components.FirebaseImage
@ -65,7 +64,6 @@ import com.google.accompanist.flowlayout.FlowRow
import com.google.accompanist.flowlayout.MainAxisAlignment
import kotlin.math.roundToInt
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun QuizScreen(
navController: NavController,
@ -73,12 +71,22 @@ fun QuizScreen(
quizViewModel: QuizViewModel = viewModel()
) {
val question by quizViewModel.currentQuestion.collectAsState()
val isButtonVisible by quizViewModel.isButtonVisible
val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState()
val isTTSInitialized = quizViewModel.isTTSInitialized.observeAsState(false)
val snackbarMessage by quizViewModel.snackbarMessage.collectAsState()
val snackbarHostState = remember { SnackbarHostState() }
LaunchedEffect(Unit) {
quizViewModel.loadRandomQuestion(material)
}
LaunchedEffect(snackbarMessage) {
snackbarMessage?.let { message ->
snackbarHostState.showSnackbar(message)
quizViewModel.onSnackbarShown()
}
}
var rectColumnAnswer by remember { mutableStateOf(Rect.Zero) }
@ -92,25 +100,6 @@ fun QuizScreen(
val dataQuiz by quizViewModel.questionShuffled.collectAsState()
val listAnswer by quizViewModel.shuffledAnswerLetters.collectAsState()
// var dataQuiz = remember {
// mutableStateListOf(
// ModelSpell(1, true, "? ", showCard = false),
// ModelSpell(2, true, "?", showCard = false),
// ModelSpell(3, true, "?", showCard = false),
// ModelSpell(4, true, "?", showCard = false),
// )
// }
// val listAnswer =
// remember {
// mutableStateListOf(
// ModelAnswerRead(1, "a"),
// ModelAnswerRead(2, "c"),
// ModelAnswerRead(3, "d"),
// ModelAnswerRead(4, "k")
// )
// }
val quizXOffset = remember {
mutableStateMapOf<Int, Float>()
}
@ -139,530 +128,311 @@ fun QuizScreen(
mutableStateMapOf<Int, Rect>()
}
Surface(modifier = Modifier.fillMaxSize()) {
GradientQuiz(
navController = navController,
headerText = stringResource(id = R.string.spelltitle),
modifier = Modifier.fillMaxSize()
) {
ConstraintLayout {
val buttonRef = createRef()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.End,
Scaffold(
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
){innerPadding->
Surface(modifier = Modifier.fillMaxSize().padding(innerPadding)) {
GradientQuiz(
navController = navController,
headerText = stringResource(id = R.string.spelltitle),
modifier = Modifier.fillMaxSize()
) {
ConstraintLayout {
val buttonRef = createRef()
Column(
modifier = Modifier.fillMaxSize(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
"Level: 3",
modifier = Modifier.padding(22.dp),
fontWeight = FontWeight.SemiBold,
fontSize = 18.sp,
color = ctextWhite
)
}
MyShadowCard(
modifier = Modifier
.padding(12.dp)
.fillMaxWidth()
) {
Column(
Row(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
horizontalArrangement = Arrangement.End,
) {
Spacer(modifier = Modifier.height(12.dp))
// Text(
// text = "Susun Kata",
// fontSize = 20.sp,
// fontWeight = FontWeight.Bold
// )
// Spacer(modifier = Modifier.height(12.dp))
// Image(
// painter = painterResource(id = R.drawable.ic_news),
// contentDescription = "image",
// modifier = Modifier.size(120.dp)
// )
if (question != null) {
if (question?.questionType == QuestionType.IMAGE) {
FirebaseImage(
path = question!!.question,
contentScale = ContentScale.Crop,
modifier = Modifier.size(200.dp)
)
} else if (question?.questionType == QuestionType.TEXT) {
Text(
text = question!!.question,
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(12.dp)
)
} else if (question?.questionType == QuestionType.AUDIO) {
IconButton(
onClick = {
quizViewModel.speakLetter(question!!.question)
},
modifier = Modifier
.size(160.dp)
) {
Icon(
imageVector = Icons.Filled.VolumeUp, // 🔥 Ikon Speaker dari Material Icons
contentDescription = "Speaker Icon",
tint = Color.Black // 🔥 Warna ikon
Text(
"",
modifier = Modifier.padding(22.dp),
fontWeight = FontWeight.SemiBold,
fontSize = 18.sp,
color = ctextWhite
)
}
MyShadowCard(
modifier = Modifier
.padding(12.dp)
.fillMaxWidth()
) {
Column(
modifier = Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally
) {
Spacer(modifier = Modifier.height(12.dp))
if (question != null) {
if (question?.questionType == QuestionType.IMAGE) {
FirebaseImage(
path = question!!.question,
contentScale = ContentScale.Crop,
modifier = Modifier.size(160.dp)
)
} else if (question?.questionType == QuestionType.TEXT) {
Text(
text = question!!.question,
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(12.dp)
)
} else if (question?.questionType == QuestionType.AUDIO) {
IconButton(
onClick = {
quizViewModel.speakLetter(question!!.question)
},
) {
Icon(
imageVector = Icons.Filled.VolumeUp,
contentDescription = "Speaker Icon",
tint = Color.Black,
modifier = Modifier.size(200.dp)
)
}
}
}
}
Spacer(modifier = Modifier.height(12.dp))
FlowRow(
mainAxisSpacing = 8.dp,
crossAxisSpacing = 8.dp,
mainAxisAlignment = MainAxisAlignment.Center,
modifier = Modifier
.fillMaxWidth()
.padding(12.dp)
Spacer(modifier = Modifier.height(12.dp))
// Row(
// modifier = Modifier.fillMaxWidth(),
// horizontalArrangement = Arrangement.SpaceAround
// ) {
// dataQuiz.forEach { dt ->
// val id = dt.id
// if (!boxRectDragable.containsKey(id))
// boxRectDragable[id] = Rect.Zero
// if (!boxRectQuiz.containsKey(id))
// boxRectQuiz[id] = Rect.Zero
// if (!quizXOffset.containsKey(id))
// quizXOffset[id] = 0f
// if (!quizYOffset.containsKey(id))
// quizYOffset[id] = 0f
// CardQuiz(
// modifier = Modifier
// .padding(vertical = 10.dp)
// .size(minSize)
// .onGloballyPositioned { coordinates ->
// if (dt.type)
// boxRectQuiz[id] = coordinates.boundsInWindow()
// }
// ) {
// if (dt.type) {
// Text(
// text = dt.data, // Use the state to display text
// color = ctextWhite,
// fontWeight = FontWeight.Bold,
// textAlign = TextAlign.Center,
// modifier = Modifier.fillMaxWidth()
// )
// if (dt.showCard) {
// DraggableAnswerCard(
// item = dt.data,
// modifier = Modifier
// .offset {
// val xOffset = quizXOffset[id] ?: 0f
// val yOffset = quizYOffset[id] ?: 0f
// IntOffset(
// xOffset.roundToInt(),
// yOffset.roundToInt()
// )
// }
// .onGloballyPositioned {
// boxRectDragable[id] =
// it.boundsInWindow()
// }
// .fillMaxSize()
// .pointerInput(Unit) {
// detectDragGestures(
// onDrag = { change, dragAmount ->
// change.consume()
// quizXOffset[id] =
// quizXOffset[id]!! + dragAmount.x
// quizYOffset[id] =
// quizYOffset[id]!! + dragAmount.y
// },
// onDragEnd = {
// var checkNull = false
// for ((ind, entry) in boxRectQuiz.entries.withIndex()) {
// val (key, rect) = entry
// if (key == id)
// continue
//
// if (dataQuiz[ind].hasContent)
// continue
//
// if (boxRectDragable[id]!!.overlaps(
// rect
// )
// ) {
// quizViewModel.updateQuestionShuffled(
// ind,
// dt
// )
//// dataQuiz =
//// dataQuiz.apply {
//// this[ind] =
//// this[ind].copy(
//// data = dt.data,
//// showCard = true,
//// emp = dt.emp,
//// hasContent = true
//// )
//// }
// dt.apply {
// hasContent = false
// showCard = false
// data = "?"
// }
// checkNull = true
// quizXOffset[id] = 0f
// quizYOffset[id] = 0f
// break
// }
//
// }
// if (boxRectDragable[id]!!.overlaps(
// rectColumnAnswer
// )
// ) {
// val emDt = dt.emp
// if (emDt != null) {
// dt.apply {
// hasContent = false
// showCard = false
// data = "?"
// }
// checkNull = true
// cardSize[emDt] = maxSize
// quizXOffset[id] = 0f
// quizYOffset[id] = 0f
// dt.data = "?"
// }
// }
// if (!checkNull) {
// quizXOffset[id] = 0f
// quizYOffset[id] = 0f
// }
// }
// )
// }
// )
// }
// } else {
// Box(modifier = Modifier.align(Alignment.CenterVertically)) {
// Text(
// text = dt.data,
// color = ctextWhite,
// fontSize = 20.sp,
// fontWeight = FontWeight.Bold,
// textAlign = TextAlign.Center,
// )
// }
//
// }
// }
// }
// }
FlowRow(
modifier = Modifier.fillMaxWidth().padding(12.dp),
mainAxisSpacing = 8.dp, // Jarak horizontal antar item
crossAxisSpacing = 8.dp, // Jarak vertikal antar item
mainAxisAlignment = MainAxisAlignment.Center
) {
dataQuiz.forEach { dt ->
val id = dt.id
if (!boxRectDragable.containsKey(id))
boxRectDragable[id] = Rect.Zero
if (!boxRectQuiz.containsKey(id))
boxRectQuiz[id] = Rect.Zero
if (!quizXOffset.containsKey(id))
quizXOffset[id] = 0f
if (!quizYOffset.containsKey(id))
quizYOffset[id] = 0f
) {
dataQuiz.forEach { dt ->
val id = dt.id
if (!boxRectDragable.containsKey(id))
boxRectDragable[id] = Rect.Zero
if (!boxRectQuiz.containsKey(id))
boxRectQuiz[id] = Rect.Zero
if (!quizXOffset.containsKey(id))
quizXOffset[id] = 0f
if (!quizYOffset.containsKey(id))
quizYOffset[id] = 0f
CardQuiz(
modifier = Modifier
.padding(vertical = 10.dp)
.size(minSize)
.onGloballyPositioned { coordinates ->
if (dt.type)
boxRectQuiz[id] = coordinates.boundsInWindow()
}
) {
if (dt.type) {
Text(
text = dt.data,
color = ctextWhite,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
if (dt.showCard) {
DraggableAnswerCard(
item = dt.data,
modifier = Modifier
.offset {
val xOffset = quizXOffset[id] ?: 0f
val yOffset = quizYOffset[id] ?: 0f
IntOffset(
xOffset.roundToInt(),
yOffset.roundToInt()
)
}
.onGloballyPositioned {
boxRectDragable[id] = it.boundsInWindow()
}
.fillMaxSize()
.pointerInput(Unit) {
detectDragGestures(
onDrag = { change, dragAmount ->
change.consume()
quizXOffset[id] =
quizXOffset[id]!! + dragAmount.x
quizYOffset[id] =
quizYOffset[id]!! + dragAmount.y
},
onDragEnd = {
var checkNull = false
for ((ind, entry) in boxRectQuiz.entries.withIndex()) {
val (key, rect) = entry
if (key == id)
continue
if (dataQuiz[ind].hasContent)
continue
if (boxRectDragable[id]!!.overlaps(rect)) {
quizViewModel.updateQuestionShuffled(ind, dt)
dt.apply {
hasContent = false
showCard = false
data = "?"
}
checkNull = true
quizXOffset[id] = 0f
quizYOffset[id] = 0f
break
}
}
if (boxRectDragable[id]!!.overlaps(rectColumnAnswer)) {
val emDt = dt.emp
if (emDt != null) {
dt.apply {
hasContent = false
showCard = false
data = "?"
}
checkNull = true
cardSize[emDt] = maxSize
quizXOffset[id] = 0f
quizYOffset[id] = 0f
dt.data = "?"
}
}
if (!checkNull) {
quizXOffset[id] = 0f
quizYOffset[id] = 0f
}
}
)
}
)
}
} else {
Box(modifier = Modifier) {
CardQuiz(
modifier = Modifier
.padding(vertical = 10.dp)
.size(minSize)
.onGloballyPositioned { coordinates ->
if (dt.type)
boxRectQuiz[id] = coordinates.boundsInWindow()
}
) {
if (dt.type) {
Text(
text = dt.data,
color = ctextWhite,
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
if (dt.showCard) {
DraggableAnswerCard(
item = dt.data,
modifier = Modifier
.offset {
val xOffset = quizXOffset[id] ?: 0f
val yOffset = quizYOffset[id] ?: 0f
IntOffset(
xOffset.roundToInt(),
yOffset.roundToInt()
)
}
.onGloballyPositioned {
boxRectDragable[id] =
it.boundsInWindow()
}
.fillMaxSize()
.pointerInput(Unit) {
detectDragGestures(
onDrag = { change, dragAmount ->
change.consume()
quizXOffset[id] =
quizXOffset[id]!! + dragAmount.x
quizYOffset[id] =
quizYOffset[id]!! + dragAmount.y
},
onDragEnd = {
var checkNull = false
for ((ind, entry) in boxRectQuiz.entries.withIndex()) {
val (key, rect) = entry
if (key == id)
continue
if (dataQuiz[ind].hasContent)
continue
if (boxRectDragable[id]!!.overlaps(
rect
)
) {
quizViewModel.updateQuestionShuffled(
ind,
dt
)
dt.apply {
hasContent = false
showCard = false
data = "?"
}
checkNull = true
quizXOffset[id] = 0f
quizYOffset[id] = 0f
break
}
}
if (boxRectDragable[id]!!.overlaps(
rectColumnAnswer
)
) {
val emDt = dt.emp
if (emDt != null) {
dt.apply {
hasContent = false
showCard = false
data = "?"
}
checkNull = true
cardSize[emDt] = maxSize
quizXOffset[id] = 0f
quizYOffset[id] = 0f
dt.data = "?"
}
}
if (!checkNull) {
quizXOffset[id] = 0f
quizYOffset[id] = 0f
}
}
)
}
)
}
} else {
Box(modifier = Modifier) {
Text(
text = dt.data,
color = ctextWhite,
fontSize = 20.sp,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center,
)
}
}
}
}
}
Spacer(modifier = Modifier.height(12.dp))
}
Spacer(modifier = Modifier.height(12.dp))
}
}
Spacer(modifier = Modifier.height(12.dp))
Spacer(
modifier = Modifier
.fillMaxWidth()
.height(1.dp)
.background(ctextGray)
)
Spacer(modifier = Modifier.height(12.dp))
Column(
modifier = Modifier
.fillMaxWidth()
.onGloballyPositioned {
rectColumnAnswer = it.boundsInWindow()
},
) {
listAnswer.chunked(2).forEach { rowItems ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
rowItems.forEach { item ->
val id = item.id
if (!cardSize.containsKey(id))
cardSize[id] = maxSize
if (!boxRectAnswer.containsKey(id))
boxRectAnswer[id] = Rect.Zero
if (!answerXOffset.containsKey(id))
answerXOffset[id] = 0f
if (!answerYOffset.containsKey(id))
answerYOffset[id] = 0f
DraggableAnswerCard(
item = item.data,
modifier = Modifier
.padding(10.dp)
.size(cardSize[id]!!)
.offset {
IntOffset(
answerXOffset[id]!!.roundToInt(),
answerYOffset[id]!!.roundToInt()
)
}
.onGloballyPositioned { coordinates ->
boxRectAnswer[id] = coordinates.boundsInWindow()
}
.pointerInput(Unit) {
detectDragGestures(
onDrag = { change, dragAmount ->
change.consume()
answerXOffset[id] =
answerXOffset[id]!! + dragAmount.x
answerYOffset[id] =
answerYOffset[id]!! + dragAmount.y
cardSize[id] = minSize
},
onDragEnd = {
var checkNull = false
for ((ind, entry) in boxRectQuiz.entries.withIndex()) {
val (_, rect) = entry
if (dataQuiz[ind].hasContent)
continue
Spacer(modifier = Modifier.height(12.dp))
Spacer(
modifier = Modifier
.fillMaxWidth()
.height(1.dp)
.background(ctextGray)
)
Spacer(modifier = Modifier.height(12.dp))
Column(
modifier = Modifier
.fillMaxWidth()
.heightIn(min = 300.dp)
.onGloballyPositioned {
rectColumnAnswer = it.boundsInWindow()
},
) {
listAnswer.chunked(3).forEach { rowItems ->
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Center
) {
rowItems.forEach { item ->
val id = item.id
if (!cardSize.containsKey(id))
cardSize[id] = maxSize
if (!boxRectAnswer.containsKey(id))
boxRectAnswer[id] = Rect.Zero
if (!answerXOffset.containsKey(id))
answerXOffset[id] = 0f
if (!answerYOffset.containsKey(id))
answerYOffset[id] = 0f
DraggableAnswerCard(
item = item.data,
modifier = Modifier
.padding(4.dp)
.size(cardSize[id]!!)
.offset {
IntOffset(
answerXOffset[id]!!.roundToInt(),
answerYOffset[id]!!.roundToInt()
)
}
.onGloballyPositioned { coordinates ->
boxRectAnswer[id] = coordinates.boundsInWindow()
}
.pointerInput(Unit) {
detectDragGestures(
onDrag = { change, dragAmount ->
change.consume()
answerXOffset[id] =
answerXOffset[id]!! + dragAmount.x
answerYOffset[id] =
answerYOffset[id]!! + dragAmount.y
cardSize[id] = minSize
},
onDragEnd = {
var checkNull = false
for ((ind, entry) in boxRectQuiz.entries.withIndex()) {
val (_, rect) = entry
if (dataQuiz[ind].hasContent)
continue
if (boxRectAnswer[id]!!.overlaps(
rect
)
) {
cardSize[id] = minSize
quizViewModel.updateQuestionShuffled(
ind,
dataQuiz[ind].copy(data = item.data, showCard = true, emp = id, hasContent = true)
)
// dataQuiz = dataQuiz
// .apply {
// this[ind] =
// this[ind].copy(
// data = item.data,
// showCard = true,
// emp = id,
// hasContent = true
// )
// }
checkNull = true
cardSize[id] = 0.dp
if (boxRectAnswer[id]!!.overlaps(
rect
)
) {
cardSize[id] = minSize
quizViewModel.updateQuestionShuffled(
ind,
dataQuiz[ind].copy(
data = item.data,
showCard = true,
emp = id,
hasContent = true
)
)
checkNull = true
cardSize[id] = 0.dp
answerXOffset[id] = 0f
answerYOffset[id] = 0f
break
}
}
if (!checkNull) {
cardSize[id] = maxSize
answerXOffset[id] = 0f
answerYOffset[id] = 0f
break
}
}
if (!checkNull) {
cardSize[id] = maxSize
answerXOffset[id] = 0f
answerYOffset[id] = 0f
}
}
)
}
)
)
}
)
}
}
}
}
Spacer(modifier = Modifier.height(12.dp))
}
Spacer(modifier = Modifier.height(12.dp))
}
ButtonNext(
onclick = {
navController.navigate("write")
},
text = stringResource(id = R.string.next),
painter = painterResource(id = R.drawable.ic_next),
modifier = Modifier
.padding(vertical = 30.dp, horizontal = 50.dp)
.fillMaxWidth()
.constrainAs(buttonRef) {
bottom.linkTo(parent.bottom)
}
)
}
}
}
}
//
//@Composable
//fun DragAndDropAnswer(correctAnswer: String, onAnswerSubmitted: (String) -> Unit) {
// val shuffledLetters = correctAnswer.toList().shuffled()
//
// var selectedLetters by remember { mutableStateOf("") }
// val answerBoxRect = remember { mutableStateOf(Rect.Zero) }
//
// Column(
// modifier = Modifier.fillMaxWidth(),
// horizontalAlignment = Alignment.CenterHorizontally
// ) {
// Box(
// modifier = Modifier
// .size(150.dp, 50.dp)
// .background(Color.LightGray)
// .onGloballyPositioned { answerBoxRect.value = it.boundsInWindow() },
// contentAlignment = Alignment.Center
// ) {
// Text(text = selectedLetters, fontSize = 20.sp)
// }
//
// Spacer(modifier = Modifier.height(20.dp))
//
// Row {
// shuffledLetters.forEach { letter ->
// DraggableLetter(
// letter = letter.toString(),
// onDrop = {
// selectedLetters += letter
// if (selectedLetters.length == correctAnswer.length) {
// onAnswerSubmitted(selectedLetters)
// }
// }
// )
// }
// }
// }
//}
//
//@Composable
//fun DraggableLetter(letter: String, onDrop: () -> Unit) {
// var offsetX by remember { mutableStateOf(0f) }
// var offsetY by remember { mutableStateOf(0f) }
//
// Box(
// modifier = Modifier
// .size(50.dp)
// .background(Color.Blue)
// .pointerInput(Unit) {
// detectDragGestures(
// onDrag = { change, dragAmount ->
// change.consume()
// offsetX += dragAmount.x
// offsetY += dragAmount.y
// },
// onDragEnd = { onDrop() }
// )
// },
// contentAlignment = Alignment.Center
// ) {
// Text(text = letter, fontSize = 20.sp, color = Color.White)
// }
//}
}
}

View File

@ -2,20 +2,26 @@ package com.example.lexilearn.ui.views.pQuiz
import android.app.Application
import android.speech.tts.TextToSpeech
import android.util.Log
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.example.lexilearn.data.model.MaterialDataModel
import com.example.lexilearn.data.model.QuizQuestion
import com.example.lexilearn.data.repository.QuizRepository
import com.example.lexilearn.domain.models.ModelAnswerRead
import com.example.lexilearn.domain.models.ModelSpell
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch
import java.util.Locale
class QuizViewModel(application: Application) : AndroidViewModel(application),
TextToSpeech.OnInitListener {
TextToSpeech.OnInitListener {
private val quizRepository = QuizRepository()
private val _currentQuestion = MutableStateFlow<QuizQuestion?>(null)
@ -33,25 +39,14 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
private val _shuffledAnswerLetters = MutableStateFlow<List<ModelAnswerRead>>(emptyList())
val shuffledAnswerLetters: StateFlow<List<ModelAnswerRead>> = _shuffledAnswerLetters
// fun updateShuffledLetter(index: Int, newData: ModelAnswerRead) {
// _shuffledAnswerLetters.value = _shuffledAnswerLetters.value.mapIndexed { i, item ->
// if (i == index) {
// item.copy(
// data = newData.data,
// showCard = true,
// emp = newData.emp,
// hasContent = true
// )
// } else {
// item
// }
// }
// }
private val _questionShuffled = MutableStateFlow<List<ModelSpell>>(emptyList())
val questionShuffled: StateFlow<List<ModelSpell>> = _questionShuffled
private val _isButtonVisible = mutableStateOf(false)
val isButtonVisible: State<Boolean> get() = _isButtonVisible
fun updateQuestionShuffled(index: Int, newData: ModelSpell) {
_questionShuffled.value = _questionShuffled.value.mapIndexed { i, item ->
if (i == index) {
@ -69,20 +64,29 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
fun loadRandomQuestion(material: MaterialDataModel) {
// _currentQuestion.value = quizRepository.generateRandomQuestion(material)
_currentQuestion.value = quizRepository.generateQuestion(material, 1, 2)
val dataQuest = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
ModelSpell(index + 1, true, "?", showCard = false)
} ?: emptyList()
_currentQuestion.value = quizRepository.generateQuestion(material, 2, 2)
val dataQuest =
_currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
ModelSpell(index + 1, true, "?", showCard = false)
} ?: emptyList()
_questionShuffled.value = dataQuest
val listAnswer = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
ModelAnswerRead(index + 1, char.toString())
} ?: emptyList()
_shuffledAnswerLetters.value = listAnswer
println("testing_question ${_currentQuestion.value}")
println("testing_question ${material}")
val listAnswer =
_currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
ModelAnswerRead(index + 1, char.toString())
} ?: emptyList()
val shuflledAnswer = listAnswer.shuffled()
_shuffledAnswerLetters.value = shuflledAnswer
// Menambahkan delay 1 detik sebelum memanggil observeData()
// viewModelScope.launch {
// delay(1000L) // delay 1 detik
//
// }
}
fun submitAnswer(answer: String) {
_userAnswer.value = answer
_isAnswerCorrect.value =
@ -95,6 +99,7 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
init {
tts = TextToSpeech(application, this)
observeData()
}
override fun onInit(status: Int) {
@ -112,6 +117,48 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
}
}
fun checkAnswer(answerString: String): Boolean {
if (answerString == currentQuestion.value?.correctAnswer?.correctWord) {
return true
}
return false
}
fun observeData() {
viewModelScope.launch {
_questionShuffled.collect { newList ->
// Lakukan aksi setiap kali data berubah
var answerString = ""
newList.forEach { text ->
answerString = answerString + text.data
}
if (answerString.contains("?") || answerString.isEmpty() || answerString.contains("null")) {
_isButtonVisible.value = false
} else {
Log.d("cobaaja", answerString)
val checkData = checkAnswer(answerString);
if (checkData) {
triggerSnackbar("Jawaban Benar")
} else {
triggerSnackbar("Jawaban Salah")
}
_isButtonVisible.value = true
}
}
}
}
private val _snackbarMessage = MutableStateFlow<String?>(null)
val snackbarMessage: StateFlow<String?> = _snackbarMessage
fun triggerSnackbar(message: String) {
_snackbarMessage.value = message
}
fun onSnackbarShown() {
_snackbarMessage.value = null
}
override fun onCleared() {
tts?.stop()
tts?.shutdown()