update competition
This commit is contained in:
parent
217f587965
commit
940378ce37
|
@ -58,10 +58,17 @@ class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
repository.createUser(newUser) { success, newUserId ->
|
repository.createUser(newUser) { success, newUserId ->
|
||||||
if (success) {
|
if (success) {
|
||||||
Toast.makeText(this, "User Baru Dibuat! Login Sekarang...", Toast.LENGTH_SHORT).show()
|
Toast.makeText(
|
||||||
|
this,
|
||||||
|
"User Baru Dibuat! Login Sekarang...",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
repository.loginUser(email, password) { loginSuccess, loggedInUserId ->
|
repository.loginUser(email, password) { loginSuccess, loggedInUserId ->
|
||||||
if (loginSuccess) {
|
if (loginSuccess) {
|
||||||
Log.d("MainActivity", "Login Berhasil setelah buat akun! User ID: $loggedInUserId")
|
Log.d(
|
||||||
|
"MainActivity",
|
||||||
|
"Login Berhasil setelah buat akun! User ID: $loggedInUserId"
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
Log.e("MainActivity", "Login Gagal setelah membuat akun!")
|
Log.e("MainActivity", "Login Gagal setelah membuat akun!")
|
||||||
}
|
}
|
||||||
|
@ -91,6 +98,13 @@ fun MyApp() {
|
||||||
composable("write") { WriteScreen(navController) }
|
composable("write") { WriteScreen(navController) }
|
||||||
composable("screening") { ScreeningScreen(navController) }
|
composable("screening") { ScreeningScreen(navController) }
|
||||||
// composable("resultscreening") { ResultScreeningScreen(navController) }
|
// composable("resultscreening") { ResultScreeningScreen(navController) }
|
||||||
|
composable(
|
||||||
|
route = "resultscreening/{totalScore}",
|
||||||
|
arguments = listOf(navArgument("totalScore") { type = NavType.IntType })
|
||||||
|
) { backStackEntry ->
|
||||||
|
val totalScore = backStackEntry.arguments?.getInt("totalScore") ?: 0
|
||||||
|
ResultScreeningScreen(navController, totalScore)
|
||||||
|
}
|
||||||
composable("learnAlphabet") { LearnAlphabetScreen(navController) }
|
composable("learnAlphabet") { LearnAlphabetScreen(navController) }
|
||||||
composable("learnNumber") { LearnNumberScreen(navController) }
|
composable("learnNumber") { LearnNumberScreen(navController) }
|
||||||
// composable(
|
// composable(
|
||||||
|
@ -115,7 +129,7 @@ fun MyApp() {
|
||||||
?.get<Int>("indexValue") ?: -1
|
?.get<Int>("indexValue") ?: -1
|
||||||
if (materialList != null) {
|
if (materialList != null) {
|
||||||
DetailMaterialScreen(navController, materialList, indexValue)
|
DetailMaterialScreen(navController, materialList, indexValue)
|
||||||
}else{
|
} else {
|
||||||
println("masuk kondisi else")
|
println("masuk kondisi else")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.example.lexilearn.data.model
|
||||||
|
|
||||||
|
data class CompetitionScore(
|
||||||
|
val userId: String = "",
|
||||||
|
val name: String = "",
|
||||||
|
val score: Int = 0
|
||||||
|
)
|
|
@ -9,6 +9,9 @@ import com.example.lexilearn.data.model.UserModel
|
||||||
import com.google.firebase.database.*
|
import com.google.firebase.database.*
|
||||||
import com.google.firebase.database.DatabaseReference
|
import com.google.firebase.database.DatabaseReference
|
||||||
import com.google.firebase.database.FirebaseDatabase
|
import com.google.firebase.database.FirebaseDatabase
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class FirebaseHelper(private val context: Context) {
|
class FirebaseHelper(private val context: Context) {
|
||||||
private val sharedPrefHelper = SharedPrefHelper(context)
|
private val sharedPrefHelper = SharedPrefHelper(context)
|
||||||
|
@ -122,4 +125,35 @@ class FirebaseHelper(private val context: Context) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
fun fetchTop10Scores(callback: (List<Pair<String, Int>>) -> Unit) {
|
||||||
|
val todayDate = getTodayDate()
|
||||||
|
val databaseReference: DatabaseReference =
|
||||||
|
FirebaseDatabase.getInstance().getReference("competitions/$todayDate")
|
||||||
|
|
||||||
|
databaseReference.addListenerForSingleValueEvent(object : ValueEventListener {
|
||||||
|
override fun onDataChange(snapshot: DataSnapshot) {
|
||||||
|
val scoreList = mutableListOf<Pair<String, Int>>()
|
||||||
|
|
||||||
|
for (scoreSnapshot in snapshot.children) {
|
||||||
|
val name = scoreSnapshot.child("name").getValue(String::class.java) ?: "Unknown"
|
||||||
|
val score = scoreSnapshot.child("score").getValue(Int::class.java) ?: 0
|
||||||
|
scoreList.add(Pair(name, score))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Urutkan berdasarkan skor tertinggi dan ambil 10 data
|
||||||
|
val top10Scores = scoreList.sortedByDescending { it.second }.take(10)
|
||||||
|
callback(top10Scores)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCancelled(error: DatabaseError) {
|
||||||
|
Log.e("FirebaseHelper", "Error fetching scores: ${error.message}")
|
||||||
|
callback(emptyList()) // Jika error, kembalikan list kosong
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTodayDate(): String {
|
||||||
|
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault())
|
||||||
|
return dateFormat.format(Date()) // Mendapatkan tanggal hari ini (misalnya "25-02-2025")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
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.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
@ -52,10 +53,9 @@ import com.example.lexilearn.ui.theme.cwhite
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun HomeScreen(navController: NavController) {
|
fun HomeScreen(navController: NavController, viewModel: HomeViewModel = viewModel()) {
|
||||||
val viewModel: HomeViewModel = viewModel()
|
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
val leaderBoard = listOf("Tono (987)", "Budi (965)")
|
val competitionScore = viewModel.topScores.collectAsState()
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
@ -139,9 +139,9 @@ fun HomeScreen(navController: NavController) {
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(10.dp))
|
Spacer(modifier = Modifier.height(10.dp))
|
||||||
LazyColumn {
|
LazyColumn {
|
||||||
itemsIndexed(leaderBoard) { index, player ->
|
itemsIndexed(competitionScore.value) { index, player ->
|
||||||
Text(
|
Text(
|
||||||
text = "${index + 1}. $player",
|
text = "${index + 1}. ${player.name} (${player.score})",
|
||||||
color = cAccent,
|
color = cAccent,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = 14.sp
|
fontSize = 14.sp
|
||||||
|
@ -157,7 +157,7 @@ fun HomeScreen(navController: NavController) {
|
||||||
)
|
)
|
||||||
.width(160.dp)
|
.width(160.dp)
|
||||||
.clickable {
|
.clickable {
|
||||||
viewModel.prepareCompetitionQuiz {dataMaterial->
|
viewModel.prepareCompetitionQuiz { dataMaterial ->
|
||||||
navController.currentBackStackEntry
|
navController.currentBackStackEntry
|
||||||
?.savedStateHandle
|
?.savedStateHandle
|
||||||
?.set("selectedMaterialList", dataMaterial)
|
?.set("selectedMaterialList", dataMaterial)
|
||||||
|
|
|
@ -1,22 +1,78 @@
|
||||||
package com.example.lexilearn.ui.views.pHome
|
package com.example.lexilearn.ui.views.pHome
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.util.Log
|
||||||
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.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import com.example.lexilearn.data.model.CompetitionScore
|
||||||
import com.example.lexilearn.data.model.MaterialDataModel
|
import com.example.lexilearn.data.model.MaterialDataModel
|
||||||
import com.example.lexilearn.data.model.QuizState
|
import com.example.lexilearn.data.model.QuizState
|
||||||
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.data.repository.QuizRepository
|
||||||
|
import com.google.firebase.database.DataSnapshot
|
||||||
|
import com.google.firebase.database.DatabaseError
|
||||||
|
import com.google.firebase.database.DatabaseReference
|
||||||
|
import com.google.firebase.database.FirebaseDatabase
|
||||||
|
import com.google.firebase.database.ValueEventListener
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
class HomeViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
|
||||||
|
private val totalDataCompetition = 3
|
||||||
|
|
||||||
private val _materialRepository = MaterialRepository(application)
|
private val _materialRepository = MaterialRepository(application)
|
||||||
private val _quizRepository = QuizRepository()
|
private val _quizRepository = QuizRepository()
|
||||||
|
|
||||||
|
private val database: DatabaseReference = FirebaseDatabase.getInstance().getReference("competitions")
|
||||||
|
|
||||||
|
private val _topScores = MutableStateFlow<List<CompetitionScore>>(emptyList())
|
||||||
|
val topScores: StateFlow<List<CompetitionScore>> get() = _topScores.asStateFlow()
|
||||||
|
|
||||||
|
// 🔥 Mendapatkan tanggal hari ini dalam format "dd-MM-yyyy"
|
||||||
|
private fun getTodayDate(): String {
|
||||||
|
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault())
|
||||||
|
return dateFormat.format(Date())
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
fetchTop10Scores()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 🔥 Fungsi untuk mengambil 10 skor tertinggi secara real-time dari Firebase
|
||||||
|
fun fetchTop10Scores() {
|
||||||
|
val todayDate = getTodayDate()
|
||||||
|
val dateRef = database.child(todayDate)
|
||||||
|
|
||||||
|
dateRef.orderByChild("score").limitToLast(10) // Ambil 10 skor tertinggi
|
||||||
|
.addValueEventListener(object : ValueEventListener {
|
||||||
|
override fun onDataChange(snapshot: DataSnapshot) {
|
||||||
|
val scoreList = mutableListOf<CompetitionScore>()
|
||||||
|
|
||||||
|
for (scoreSnapshot in snapshot.children) {
|
||||||
|
val scoreData = scoreSnapshot.getValue(CompetitionScore::class.java)
|
||||||
|
scoreData?.let { scoreList.add(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Urutkan dari yang tertinggi ke terendah
|
||||||
|
_topScores.value = scoreList.sortedByDescending { it.score }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCancelled(error: DatabaseError) {
|
||||||
|
Log.e("CompetitionViewModel", "Error fetching scores: ${error.message}")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
fun prepareCompetitionQuiz(callback: (List<MaterialDataModel>) -> Unit) {
|
fun prepareCompetitionQuiz(callback: (List<MaterialDataModel>) -> Unit) {
|
||||||
_materialRepository.getAllMaterialData("all") { materials ->
|
_materialRepository.getAllMaterialData("all") { materials ->
|
||||||
_quizRepository.getRandomMaterials(3, materials) { randomData ->
|
_quizRepository.getRandomMaterials(totalDataCompetition, materials) { randomData ->
|
||||||
randomData.forEach { println(it) }
|
randomData.forEach { println(it) }
|
||||||
callback(randomData)
|
callback(randomData)
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,6 +169,14 @@ fun QuizScreen(
|
||||||
quizViewModel.onSnackbarShown()
|
quizViewModel.onSnackbarShown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
val finalScore by quizViewModel.finalScore.collectAsState()
|
||||||
|
LaunchedEffect(finalScore) {
|
||||||
|
finalScore?.let { scoreFin ->
|
||||||
|
navController.navigate("resultscreening/$scoreFin") {
|
||||||
|
popUpTo("quizscreen") { inclusive = true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Scaffold(
|
Scaffold(
|
||||||
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
|
snackbarHost = { SnackbarHost(hostState = snackbarHostState) }
|
||||||
) { innerPadding ->
|
) { innerPadding ->
|
||||||
|
|
|
@ -284,6 +284,8 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
val liveCurrentScore: StateFlow<Int> get() = _liveCurrentScore.asStateFlow()
|
val liveCurrentScore: StateFlow<Int> get() = _liveCurrentScore.asStateFlow()
|
||||||
private val _formattedResponseTime = MutableStateFlow("0.0")
|
private val _formattedResponseTime = MutableStateFlow("0.0")
|
||||||
val formattedResponseTime: StateFlow<String> get() = _formattedResponseTime.asStateFlow()
|
val formattedResponseTime: StateFlow<String> get() = _formattedResponseTime.asStateFlow()
|
||||||
|
private val _finalScore = MutableStateFlow<Int?>(null) // Menyimpan skor akhir untuk navigasi
|
||||||
|
val finalScore: StateFlow<Int?> get() = _finalScore.asStateFlow()
|
||||||
|
|
||||||
private var questionList = listOf<MaterialDataModel>()
|
private var questionList = listOf<MaterialDataModel>()
|
||||||
private var currentQuestionIndex = 0
|
private var currentQuestionIndex = 0
|
||||||
|
@ -361,7 +363,7 @@ class QuizViewModel(application: Application) : AndroidViewModel(application),
|
||||||
_liveCurrentScore.value = baseScore
|
_liveCurrentScore.value = baseScore
|
||||||
startStopwatch() // Restart stopwatch
|
startStopwatch() // Restart stopwatch
|
||||||
}else{
|
}else{
|
||||||
|
_finalScore.value = _totalScore.value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,13 +12,10 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
import androidx.compose.ui.graphics.Outline
|
|
||||||
import androidx.compose.ui.graphics.Shape
|
|
||||||
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.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.constraintlayout.compose.ConstraintLayout
|
import androidx.constraintlayout.compose.ConstraintLayout
|
||||||
|
@ -30,21 +27,30 @@ import androidx.compose.foundation.layout.offset
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.geometry.RoundRect
|
|
||||||
import androidx.compose.ui.graphics.Path
|
|
||||||
import androidx.constraintlayout.compose.Dimension
|
import androidx.constraintlayout.compose.Dimension
|
||||||
import com.example.lexilearn.ui.components.CustomButton
|
import com.example.lexilearn.ui.components.CustomButton
|
||||||
import com.example.lexilearn.ui.theme.cprimary
|
import com.example.lexilearn.ui.theme.cprimary
|
||||||
import com.example.lexilearn.ui.theme.ctextBlack
|
import com.example.lexilearn.ui.theme.ctextBlack
|
||||||
import com.example.lexilearn.ui.theme.cwhite
|
import com.example.lexilearn.ui.theme.cwhite
|
||||||
import com.example.lexilearn.ui.views.pScreening.ScreeningViewModel
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ResultScreeningScreen(navController: NavController, totalScore: Int, viewModel: ScreeningViewModel) {
|
fun ResultScreeningScreen(
|
||||||
|
navController: NavController,
|
||||||
|
totalScore: Int,
|
||||||
|
viewModel: ResultScreeningViewModel = viewModel()
|
||||||
|
) {
|
||||||
|
|
||||||
|
val scorePosition = viewModel.positionScore.collectAsState()
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
viewModel.submitScore(totalScore)
|
||||||
|
}
|
||||||
GradientScreening(
|
GradientScreening(
|
||||||
backButton = { navController.popBackStack() },
|
backButton = { navController.popBackStack() },
|
||||||
headerText = stringResource(id = R.string.rescreentitle),
|
headerText = "Skor Kompetisi",
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
ConstraintLayout(
|
ConstraintLayout(
|
||||||
|
@ -86,13 +92,13 @@ fun ResultScreeningScreen(navController: NavController, totalScore: Int, viewMod
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(30.dp))
|
Spacer(modifier = Modifier.height(30.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Dyslexia",
|
text = "Skor",
|
||||||
fontSize = 20.sp,
|
fontSize = 20.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = ctextBlack
|
color = ctextBlack
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = "66%",
|
text = "$totalScore",
|
||||||
fontSize = 50.sp,
|
fontSize = 50.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = cprimary,
|
color = cprimary,
|
||||||
|
@ -112,33 +118,37 @@ fun ResultScreeningScreen(navController: NavController, totalScore: Int, viewMod
|
||||||
end.linkTo(parent.end)
|
end.linkTo(parent.end)
|
||||||
}) {
|
}) {
|
||||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||||
Text(
|
Text(
|
||||||
text = "Anda menjawab \"ya\" pada 2 dari 3 pertanyaan yang menunjukkan 66% kemungkinan Anda menderita disleksia.",
|
text = "Wow, hebat sekali! 🎉 Kamu menduduki peringkat ${scorePosition.value} hari ini! 🚀",
|
||||||
fontSize = 16.sp,
|
fontSize = 16.sp,
|
||||||
color = ctextBlack,
|
color = ctextBlack,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.padding(top = 24.dp)
|
modifier = Modifier.padding(top = 24.dp)
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = R.string.rescreendesc),
|
text = "Petualanganmu belum berakhir! 🔥 Coba lagi dan naikkan peringkatmu! 🏆",
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
color = ctextGray,
|
color = ctextGray,
|
||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
modifier = Modifier.padding(top = 16.dp, bottom = 20.dp)
|
modifier = Modifier.padding(top = 16.dp, bottom = 20.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CustomButton(
|
CustomButton(
|
||||||
text = stringResource(id = R.string.close),
|
text = stringResource(id = R.string.close),
|
||||||
onClick = { },
|
onClick = {
|
||||||
modifier = Modifier.padding(horizontal = 24.dp, vertical = 12.dp).constrainAs(buttonRef) {
|
navController.popBackStack()
|
||||||
bottom.linkTo(parent.bottom, margin = 12.dp)
|
},
|
||||||
end.linkTo(parent.end, margin = 12.dp)
|
modifier = Modifier
|
||||||
start.linkTo(parent.start, margin = 12.dp)
|
.padding(horizontal = 24.dp, vertical = 12.dp)
|
||||||
width = Dimension.fillToConstraints
|
.constrainAs(buttonRef) {
|
||||||
})
|
bottom.linkTo(parent.bottom, margin = 12.dp)
|
||||||
|
end.linkTo(parent.end, margin = 12.dp)
|
||||||
|
start.linkTo(parent.start, margin = 12.dp)
|
||||||
|
width = Dimension.fillToConstraints
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,89 @@
|
||||||
package com.example.lexilearn.ui.views.pResultScreening
|
package com.example.lexilearn.ui.views.pResultScreening
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.util.Log
|
||||||
import androidx.lifecycle.AndroidViewModel
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import com.example.lexilearn.data.model.CompetitionScore
|
||||||
|
import com.example.lexilearn.data.repository.MaterialRepository
|
||||||
|
import com.example.lexilearn.data.repository.QuizRepository
|
||||||
|
import com.google.firebase.database.DataSnapshot
|
||||||
|
import com.google.firebase.database.DatabaseError
|
||||||
|
import com.google.firebase.database.DatabaseReference
|
||||||
|
import com.google.firebase.database.FirebaseDatabase
|
||||||
|
import com.google.firebase.database.ValueEventListener
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.UUID
|
||||||
|
|
||||||
class ResultScreeningViewModel(application: Application) : AndroidViewModel(application) {
|
class ResultScreeningViewModel(application: Application) : AndroidViewModel(application) {
|
||||||
|
private val database: DatabaseReference = FirebaseDatabase.getInstance().getReference("competitions")
|
||||||
|
private val materialRepo = MaterialRepository(application)
|
||||||
|
|
||||||
|
private val _positionScore = MutableStateFlow(0)
|
||||||
|
val positionScore: StateFlow<Int> = _positionScore
|
||||||
|
|
||||||
|
private fun getTodayDate(): String {
|
||||||
|
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault())
|
||||||
|
return dateFormat.format(Date())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun submitScore(score: Int) {
|
||||||
|
|
||||||
|
materialRepo.getUserData {dataUser->
|
||||||
|
val todayDate = getTodayDate()
|
||||||
|
val dateRef = database.child(todayDate)
|
||||||
|
|
||||||
|
// Buat ID unik untuk skor
|
||||||
|
val scoreId = dateRef.push().key ?: UUID.randomUUID().toString()
|
||||||
|
val scoreData = mapOf("score" to score, "name" to "${dataUser?.name}")
|
||||||
|
|
||||||
|
dateRef.child(scoreId).setValue(scoreData)
|
||||||
|
.addOnSuccessListener {
|
||||||
|
Log.d("CompetitionViewModel", "Score added successfully!")
|
||||||
|
checkUserRanking(todayDate, scoreId, score)
|
||||||
|
}
|
||||||
|
.addOnFailureListener {
|
||||||
|
Log.e("CompetitionViewModel", "Error saving score: ${it.message}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkUserRanking(todayDate: String, scoreId: String, userScore: Int) {
|
||||||
|
val dateRef = database.child(todayDate)
|
||||||
|
|
||||||
|
dateRef.orderByChild("score").addListenerForSingleValueEvent(object : ValueEventListener {
|
||||||
|
override fun onDataChange(snapshot: DataSnapshot) {
|
||||||
|
val scoreList = mutableListOf<Pair<String, Int>>() // (scoreId, score)
|
||||||
|
|
||||||
|
for (scoreSnapshot in snapshot.children) {
|
||||||
|
val id = scoreSnapshot.key ?: continue
|
||||||
|
val score = scoreSnapshot.child("score").getValue(Int::class.java) ?: 0
|
||||||
|
scoreList.add(id to score)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Urutkan skor dari tertinggi ke terendah
|
||||||
|
val sortedScores = scoreList.sortedByDescending { it.second }
|
||||||
|
|
||||||
|
// Cari posisi user
|
||||||
|
// val userRank = sortedScores.indexOfFirst { it.first == scoreId } + 1
|
||||||
|
val userRank = maxOf(1, sortedScores.indexOfFirst { it.first == scoreId } + 1)
|
||||||
|
|
||||||
|
_positionScore.value = userRank
|
||||||
|
|
||||||
|
if (userRank > 0) {
|
||||||
|
Log.d("ResultScreeningVM", "User is ranked: #$userRank out of ${sortedScores.size}")
|
||||||
|
} else {
|
||||||
|
Log.d("ResultScreeningVM", "User rank not found.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCancelled(error: DatabaseError) {
|
||||||
|
Log.e("ResultScreeningVM", "Error fetching scores: ${error.message}")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue