update quiz type 2
This commit is contained in:
parent
133fa954fd
commit
522e568a9e
|
@ -31,20 +31,21 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
import com.example.lexilearn.data.model.MaterialDataModel
|
import com.example.lexilearn.data.model.MaterialDataModel
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
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.offset
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.VolumeUp
|
import androidx.compose.material.icons.filled.VolumeUp
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
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.material3.Surface
|
||||||
import androidx.compose.runtime.livedata.observeAsState
|
import androidx.compose.runtime.livedata.observeAsState
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
|
||||||
import androidx.compose.runtime.mutableStateMapOf
|
import androidx.compose.runtime.mutableStateMapOf
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
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
|
||||||
|
@ -52,8 +53,6 @@ import androidx.compose.ui.unit.IntOffset
|
||||||
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
|
||||||
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.CardQuiz
|
||||||
import com.example.lexilearn.ui.components.DraggableAnswerCard
|
import com.example.lexilearn.ui.components.DraggableAnswerCard
|
||||||
import com.example.lexilearn.ui.components.FirebaseImage
|
import com.example.lexilearn.ui.components.FirebaseImage
|
||||||
|
@ -65,7 +64,6 @@ import com.google.accompanist.flowlayout.FlowRow
|
||||||
import com.google.accompanist.flowlayout.MainAxisAlignment
|
import com.google.accompanist.flowlayout.MainAxisAlignment
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun QuizScreen(
|
fun QuizScreen(
|
||||||
navController: NavController,
|
navController: NavController,
|
||||||
|
@ -73,12 +71,22 @@ fun QuizScreen(
|
||||||
quizViewModel: QuizViewModel = viewModel()
|
quizViewModel: QuizViewModel = viewModel()
|
||||||
) {
|
) {
|
||||||
val question by quizViewModel.currentQuestion.collectAsState()
|
val question by quizViewModel.currentQuestion.collectAsState()
|
||||||
|
val isButtonVisible by quizViewModel.isButtonVisible
|
||||||
val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState()
|
val isAnswerCorrect by quizViewModel.isAnswerCorrect.collectAsState()
|
||||||
val isTTSInitialized = quizViewModel.isTTSInitialized.observeAsState(false)
|
val isTTSInitialized = quizViewModel.isTTSInitialized.observeAsState(false)
|
||||||
|
val snackbarMessage by quizViewModel.snackbarMessage.collectAsState()
|
||||||
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
quizViewModel.loadRandomQuestion(material)
|
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) }
|
||||||
|
|
||||||
|
@ -92,25 +100,6 @@ fun QuizScreen(
|
||||||
val dataQuiz by quizViewModel.questionShuffled.collectAsState()
|
val dataQuiz by quizViewModel.questionShuffled.collectAsState()
|
||||||
val listAnswer by quizViewModel.shuffledAnswerLetters.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 {
|
val quizXOffset = remember {
|
||||||
mutableStateMapOf<Int, Float>()
|
mutableStateMapOf<Int, Float>()
|
||||||
}
|
}
|
||||||
|
@ -139,7 +128,10 @@ fun QuizScreen(
|
||||||
mutableStateMapOf<Int, Rect>()
|
mutableStateMapOf<Int, Rect>()
|
||||||
}
|
}
|
||||||
|
|
||||||
Surface(modifier = Modifier.fillMaxSize()) {
|
Scaffold(
|
||||||
|
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
|
||||||
|
){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),
|
||||||
|
@ -156,7 +148,7 @@ fun QuizScreen(
|
||||||
horizontalArrangement = Arrangement.End,
|
horizontalArrangement = Arrangement.End,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
"Level: 3",
|
"",
|
||||||
modifier = Modifier.padding(22.dp),
|
modifier = Modifier.padding(22.dp),
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
fontSize = 18.sp,
|
fontSize = 18.sp,
|
||||||
|
@ -173,25 +165,13 @@ fun QuizScreen(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
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 != null) {
|
||||||
if (question?.questionType == QuestionType.IMAGE) {
|
if (question?.questionType == QuestionType.IMAGE) {
|
||||||
FirebaseImage(
|
FirebaseImage(
|
||||||
path = question!!.question,
|
path = question!!.question,
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
modifier = Modifier.size(200.dp)
|
modifier = Modifier.size(160.dp)
|
||||||
)
|
)
|
||||||
|
|
||||||
} else if (question?.questionType == QuestionType.TEXT) {
|
} else if (question?.questionType == QuestionType.TEXT) {
|
||||||
Text(
|
Text(
|
||||||
text = question!!.question,
|
text = question!!.question,
|
||||||
|
@ -204,164 +184,25 @@ fun QuizScreen(
|
||||||
onClick = {
|
onClick = {
|
||||||
quizViewModel.speakLetter(question!!.question)
|
quizViewModel.speakLetter(question!!.question)
|
||||||
},
|
},
|
||||||
modifier = Modifier
|
|
||||||
.size(160.dp)
|
|
||||||
|
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.VolumeUp, // 🔥 Ikon Speaker dari Material Icons
|
imageVector = Icons.Filled.VolumeUp,
|
||||||
contentDescription = "Speaker Icon",
|
contentDescription = "Speaker Icon",
|
||||||
tint = Color.Black // 🔥 Warna ikon
|
tint = Color.Black,
|
||||||
|
modifier = Modifier.size(200.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(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(
|
FlowRow(
|
||||||
modifier = Modifier.fillMaxWidth().padding(12.dp),
|
mainAxisSpacing = 8.dp,
|
||||||
mainAxisSpacing = 8.dp, // Jarak horizontal antar item
|
crossAxisSpacing = 8.dp,
|
||||||
crossAxisSpacing = 8.dp, // Jarak vertikal antar item
|
mainAxisAlignment = MainAxisAlignment.Center,
|
||||||
mainAxisAlignment = MainAxisAlignment.Center
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(12.dp)
|
||||||
|
|
||||||
) {
|
) {
|
||||||
dataQuiz.forEach { dt ->
|
dataQuiz.forEach { dt ->
|
||||||
val id = dt.id
|
val id = dt.id
|
||||||
|
@ -404,7 +245,8 @@ fun QuizScreen(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
boxRectDragable[id] = it.boundsInWindow()
|
boxRectDragable[id] =
|
||||||
|
it.boundsInWindow()
|
||||||
}
|
}
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
.pointerInput(Unit) {
|
.pointerInput(Unit) {
|
||||||
|
@ -426,8 +268,14 @@ fun QuizScreen(
|
||||||
if (dataQuiz[ind].hasContent)
|
if (dataQuiz[ind].hasContent)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if (boxRectDragable[id]!!.overlaps(rect)) {
|
if (boxRectDragable[id]!!.overlaps(
|
||||||
quizViewModel.updateQuestionShuffled(ind, dt)
|
rect
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
quizViewModel.updateQuestionShuffled(
|
||||||
|
ind,
|
||||||
|
dt
|
||||||
|
)
|
||||||
dt.apply {
|
dt.apply {
|
||||||
hasContent = false
|
hasContent = false
|
||||||
showCard = false
|
showCard = false
|
||||||
|
@ -439,7 +287,10 @@ fun QuizScreen(
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (boxRectDragable[id]!!.overlaps(rectColumnAnswer)) {
|
if (boxRectDragable[id]!!.overlaps(
|
||||||
|
rectColumnAnswer
|
||||||
|
)
|
||||||
|
) {
|
||||||
val emDt = dt.emp
|
val emDt = dt.emp
|
||||||
if (emDt != null) {
|
if (emDt != null) {
|
||||||
dt.apply {
|
dt.apply {
|
||||||
|
@ -491,11 +342,12 @@ fun QuizScreen(
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
|
.heightIn(min = 300.dp)
|
||||||
.onGloballyPositioned {
|
.onGloballyPositioned {
|
||||||
rectColumnAnswer = it.boundsInWindow()
|
rectColumnAnswer = it.boundsInWindow()
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
listAnswer.chunked(2).forEach { rowItems ->
|
listAnswer.chunked(3).forEach { rowItems ->
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.Center
|
horizontalArrangement = Arrangement.Center
|
||||||
|
@ -513,7 +365,7 @@ fun QuizScreen(
|
||||||
DraggableAnswerCard(
|
DraggableAnswerCard(
|
||||||
item = item.data,
|
item = item.data,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(10.dp)
|
.padding(4.dp)
|
||||||
.size(cardSize[id]!!)
|
.size(cardSize[id]!!)
|
||||||
.offset {
|
.offset {
|
||||||
IntOffset(
|
IntOffset(
|
||||||
|
@ -548,18 +400,13 @@ fun QuizScreen(
|
||||||
cardSize[id] = minSize
|
cardSize[id] = minSize
|
||||||
quizViewModel.updateQuestionShuffled(
|
quizViewModel.updateQuestionShuffled(
|
||||||
ind,
|
ind,
|
||||||
dataQuiz[ind].copy(data = item.data, showCard = true, emp = id, hasContent = true)
|
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
|
checkNull = true
|
||||||
cardSize[id] = 0.dp
|
cardSize[id] = 0.dp
|
||||||
answerXOffset[id] = 0f
|
answerXOffset[id] = 0f
|
||||||
|
@ -583,86 +430,9 @@ fun QuizScreen(
|
||||||
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)
|
|
||||||
// }
|
|
||||||
//}
|
|
|
@ -2,16 +2,22 @@ package com.example.lexilearn.ui.views.pQuiz
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.speech.tts.TextToSpeech
|
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.AndroidViewModel
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.example.lexilearn.data.model.MaterialDataModel
|
import com.example.lexilearn.data.model.MaterialDataModel
|
||||||
import com.example.lexilearn.data.model.QuizQuestion
|
import com.example.lexilearn.data.model.QuizQuestion
|
||||||
import com.example.lexilearn.data.repository.QuizRepository
|
import com.example.lexilearn.data.repository.QuizRepository
|
||||||
import com.example.lexilearn.domain.models.ModelAnswerRead
|
import com.example.lexilearn.domain.models.ModelAnswerRead
|
||||||
import com.example.lexilearn.domain.models.ModelSpell
|
import com.example.lexilearn.domain.models.ModelSpell
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class QuizViewModel(application: Application) : AndroidViewModel(application),
|
class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
|
@ -33,25 +39,14 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
|
|
||||||
private val _shuffledAnswerLetters = MutableStateFlow<List<ModelAnswerRead>>(emptyList())
|
private val _shuffledAnswerLetters = MutableStateFlow<List<ModelAnswerRead>>(emptyList())
|
||||||
val shuffledAnswerLetters: StateFlow<List<ModelAnswerRead>> = _shuffledAnswerLetters
|
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())
|
private val _questionShuffled = MutableStateFlow<List<ModelSpell>>(emptyList())
|
||||||
val questionShuffled: StateFlow<List<ModelSpell>> = _questionShuffled
|
val questionShuffled: StateFlow<List<ModelSpell>> = _questionShuffled
|
||||||
|
|
||||||
|
private val _isButtonVisible = mutableStateOf(false)
|
||||||
|
val isButtonVisible: State<Boolean> get() = _isButtonVisible
|
||||||
|
|
||||||
fun updateQuestionShuffled(index: Int, newData: ModelSpell) {
|
fun updateQuestionShuffled(index: Int, newData: ModelSpell) {
|
||||||
_questionShuffled.value = _questionShuffled.value.mapIndexed { i, item ->
|
_questionShuffled.value = _questionShuffled.value.mapIndexed { i, item ->
|
||||||
if (i == index) {
|
if (i == index) {
|
||||||
|
@ -69,20 +64,29 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
|
|
||||||
|
|
||||||
fun loadRandomQuestion(material: MaterialDataModel) {
|
fun loadRandomQuestion(material: MaterialDataModel) {
|
||||||
// _currentQuestion.value = quizRepository.generateRandomQuestion(material)
|
_currentQuestion.value = quizRepository.generateQuestion(material, 2, 2)
|
||||||
_currentQuestion.value = quizRepository.generateQuestion(material, 1, 2)
|
|
||||||
val dataQuest = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
val dataQuest =
|
||||||
|
_currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
||||||
ModelSpell(index + 1, true, "?", showCard = false)
|
ModelSpell(index + 1, true, "?", showCard = false)
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
_questionShuffled.value = dataQuest
|
_questionShuffled.value = dataQuest
|
||||||
val listAnswer = _currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
|
||||||
|
val listAnswer =
|
||||||
|
_currentQuestion.value?.correctAnswer?.correctWord?.mapIndexed { index, char ->
|
||||||
ModelAnswerRead(index + 1, char.toString())
|
ModelAnswerRead(index + 1, char.toString())
|
||||||
} ?: emptyList()
|
} ?: emptyList()
|
||||||
_shuffledAnswerLetters.value = listAnswer
|
val shuflledAnswer = listAnswer.shuffled()
|
||||||
println("testing_question ${_currentQuestion.value}")
|
_shuffledAnswerLetters.value = shuflledAnswer
|
||||||
println("testing_question ${material}")
|
|
||||||
|
// Menambahkan delay 1 detik sebelum memanggil observeData()
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// delay(1000L) // delay 1 detik
|
||||||
|
//
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun submitAnswer(answer: String) {
|
fun submitAnswer(answer: String) {
|
||||||
_userAnswer.value = answer
|
_userAnswer.value = answer
|
||||||
_isAnswerCorrect.value =
|
_isAnswerCorrect.value =
|
||||||
|
@ -95,6 +99,7 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
|
|
||||||
init {
|
init {
|
||||||
tts = TextToSpeech(application, this)
|
tts = TextToSpeech(application, this)
|
||||||
|
observeData()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onInit(status: Int) {
|
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() {
|
override fun onCleared() {
|
||||||
tts?.stop()
|
tts?.stop()
|
||||||
tts?.shutdown()
|
tts?.shutdown()
|
||||||
|
|
Loading…
Reference in New Issue