diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
index 7ce6325..e12ae29 100644
--- a/.idea/deploymentTargetDropDown.xml
+++ b/.idea/deploymentTargetDropDown.xml
@@ -15,7 +15,7 @@
-
+
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 882371f..2bca692 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -57,4 +57,11 @@ dependencies {
//wheel
implementation("androidx.navigation:navigation-dynamic-features-fragment:2.7.7")
implementation ("com.github.thanhniencung:LuckyWheel:a6110f5128")
+
+ // DataStore
+ implementation("androidx.datastore:datastore-preferences:1.0.0")
+
+ // gemini
+ implementation("com.google.android.material:material:1.11.0")
+ implementation("com.google.ai.client.generativeai:generativeai:0.4.0")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 270e0e3..dee542d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -13,12 +13,27 @@
android:theme="@style/Theme.ChiecNonKyDieu"
tools:targetApi="31">
+
+
+
+
+
+
+
+
+
@@ -27,16 +42,11 @@
android:exported="false" />
+ android:exported="false"
+ android:launchMode="singleTop" />
-
-
-
-
-
-
+ android:exported="false"/>
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
@@ -50,6 +59,8 @@ class MainActivity : AppCompatActivity() {
startActivity(intent)
}
+
+
}
private fun goToPlayingRoom() {
// TODO Set cung
@@ -57,4 +68,22 @@ class MainActivity : AppCompatActivity() {
intent.putExtra("room_id", "7232")
startActivity(intent)
}
+
+ private fun isNetworkAvailable(): Boolean {
+ val connectivityManager =
+ getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
+ val networkInfo = connectivityManager.activeNetworkInfo
+ return networkInfo != null && networkInfo.isConnected
+ }
+
+ private fun showNoInternetMessage() {
+ val rootView: View = findViewById(android.R.id.content)
+ val snackbar = Snackbar.make(
+ rootView,
+ "Không có kết nối internet",
+ Snackbar.LENGTH_INDEFINITE
+ )
+ snackbar.view.setBackgroundColor(ContextCompat.getColor(this, R.color.orange))
+ snackbar.show()
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/data/DataSource.kt b/app/src/main/java/com/example/chiecnonkydieu/data/DataSource.kt
index 59545de..7892eb8 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/data/DataSource.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/data/DataSource.kt
@@ -1,5 +1,31 @@
package com.example.chiecnonkydieu.data
-import rubikstudio.library.model.LuckyItem
+import com.example.chiecnonkydieu.model.QuestionAnswer
+import com.google.firebase.database.DatabaseReference
+import com.google.firebase.database.ktx.database
+import com.google.firebase.ktx.Firebase
+val database: DatabaseReference = Firebase.database.reference
+const val REFERENCE_CAUHOI = "CAU HOI"
+val questionAnswerList: MutableList = mutableListOf(
+ QuestionAnswer(
+ "Hà Nội",
+ "HA NOI",
+ "Thủ đô của Việt Nam nằm ở đâu?",
+ "Hint1",
+ "Hint2",
+ "Hint3",
+ "Thong tin"
+ ),
+ QuestionAnswer(
+ "Hà Nội",
+ "HA NOI",
+ "Thủ đô của Việt Nam nằm ở đâu?",
+ "Hint1",
+ "Hint2",
+ "Hint3",
+ "Thong tin"
+ ),
+
+ )
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/data/GameData.kt b/app/src/main/java/com/example/chiecnonkydieu/data/GameData.kt
index 4374aa6..3e2b65f 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/data/GameData.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/data/GameData.kt
@@ -5,6 +5,7 @@ import android.util.Log
import android.widget.Toast
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
+import com.example.chiecnonkydieu.model.Player
import com.google.firebase.Firebase
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
@@ -12,7 +13,6 @@ import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.ValueEventListener
import com.google.firebase.database.database
import kotlinx.coroutines.CompletableDeferred
-import kotlin.coroutines.coroutineContext
object GameData {
private var _gameModel: MutableLiveData = MutableLiveData()
diff --git a/app/src/main/java/com/example/chiecnonkydieu/data/GameModel.kt b/app/src/main/java/com/example/chiecnonkydieu/data/GameModel.kt
index 52200b7..ad21f65 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/data/GameModel.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/data/GameModel.kt
@@ -1,17 +1,20 @@
package com.example.chiecnonkydieu.data
-import android.health.connect.datatypes.units.Length
+import com.example.chiecnonkydieu.model.LetterCard
+import com.example.chiecnonkydieu.model.Player
+import com.example.chiecnonkydieu.model.QuestionAnswer
data class GameModel(
val gameId: Int = -1,
val winner: String = "",
var gameStatus: GameStatus = GameStatus.CREATED,
val playersList: MutableList = mutableListOf(),
- val currentPlayer: Player = Player(),
- val currentQuestion: String = "",
- val currentAnswer: String = "HA NOI",
- val currentGuess: String = " A N "
-
+ var currentPlayer: Player = Player(),
+ var currentQuestionAnswer: QuestionAnswer = questionAnswerList[0],
+ val guessesCharacters: MutableList = mutableListOf(),
+ var letterCardList: MutableList = mutableListOf(),
+ val previousQuestionAnswers: MutableList = mutableListOf(),
+ var currentSpinValue: String = ""
)
enum class GameStatus {
@@ -19,5 +22,8 @@ enum class GameStatus {
JOINED1,
JOINED2,
INPROGRESS,
+ GUESS,
+ ENDROUND,
+ WAITING_TO_CONTINUE,
FINISHED
}
diff --git a/app/src/main/java/com/example/chiecnonkydieu/model/Hint.kt b/app/src/main/java/com/example/chiecnonkydieu/model/Hint.kt
new file mode 100644
index 0000000..df70231
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/model/Hint.kt
@@ -0,0 +1,6 @@
+package com.example.chiecnonkydieu.model
+
+data class Hint(
+ val title: String = "Đây là hint",
+ val isOpen: Boolean = false
+)
diff --git a/app/src/main/java/com/example/chiecnonkydieu/model/LetterCard.kt b/app/src/main/java/com/example/chiecnonkydieu/model/LetterCard.kt
new file mode 100644
index 0000000..85271e5
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/model/LetterCard.kt
@@ -0,0 +1,6 @@
+package com.example.chiecnonkydieu.model
+
+data class LetterCard(
+ val letter: String = "A",
+ var isHidden: Boolean = letter != " "
+)
diff --git a/app/src/main/java/com/example/chiecnonkydieu/data/Player.kt b/app/src/main/java/com/example/chiecnonkydieu/model/Player.kt
similarity index 57%
rename from app/src/main/java/com/example/chiecnonkydieu/data/Player.kt
rename to app/src/main/java/com/example/chiecnonkydieu/model/Player.kt
index 0565137..a99bb25 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/data/Player.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/model/Player.kt
@@ -1,7 +1,7 @@
-package com.example.chiecnonkydieu.data
+package com.example.chiecnonkydieu.model
data class Player(
val name: String = "Player",
val gender: Boolean = true,
- val score: Int = 0
+ var score: Int = 0
)
diff --git a/app/src/main/java/com/example/chiecnonkydieu/model/QuestionAnswer.kt b/app/src/main/java/com/example/chiecnonkydieu/model/QuestionAnswer.kt
new file mode 100644
index 0000000..dcbd60e
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/model/QuestionAnswer.kt
@@ -0,0 +1,12 @@
+package com.example.chiecnonkydieu.model
+
+
+data class QuestionAnswer(
+ var DoiTuong : String = "",
+ var DoiTuongInHoa : String = "",
+ var CauHoi : String = "",
+ var Hint1 : String = "",
+ var Hint2 : String = "",
+ var Hint3 : String = "",
+ var ThongTin : String = ""
+)
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/CreateRoomActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/CreateRoomActivity.kt
index d914deb..be1fc8d 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/ui/CreateRoomActivity.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/CreateRoomActivity.kt
@@ -1,24 +1,42 @@
package com.example.chiecnonkydieu.ui
+import android.content.Context
import android.content.Intent
import android.os.Bundle
+import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.stringPreferencesKey
+import androidx.datastore.preferences.preferencesDataStore
import androidx.lifecycle.lifecycleScope
import com.example.chiecnonkydieu.R
import com.example.chiecnonkydieu.data.GameData
import com.example.chiecnonkydieu.data.GameModel
import com.example.chiecnonkydieu.data.GameStatus
-import com.example.chiecnonkydieu.data.Player
+import com.example.chiecnonkydieu.model.LetterCard
+import com.example.chiecnonkydieu.model.Player
+import com.example.chiecnonkydieu.data.questionAnswerList
import com.example.chiecnonkydieu.databinding.ActivityCreateRoomBinding
+import com.example.chiecnonkydieu.model.QuestionAnswer
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
-import kotlin.random.Random
+
+val Context.dataStore: DataStore by preferencesDataStore(name = "player_data")
+val CURRENT_PLAYER = stringPreferencesKey("current_player")
class CreateRoomActivity : AppCompatActivity() {
+
private lateinit var binding: ActivityCreateRoomBinding
+
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
@@ -46,12 +64,20 @@ class CreateRoomActivity : AppCompatActivity() {
val gameModel: GameModel = GameModel(
gameStatus = GameStatus.CREATED,
gameId = binding.tvMaPhong.text.toString().toInt(),
- currentQuestion = "Thủ đô của Việt Nam nằm ở đâu?"
+ currentQuestionAnswer = questionAnswerList[1],
+ guessesCharacters = mutableListOf(),
+ currentPlayer = Player(name = binding.edtName.text.toString()),
+ letterCardList = getLetterCardListFromAnswer(questionAnswerList[0].DoiTuongInHoa),
+ previousQuestionAnswers = mutableListOf().apply {
+ add(questionAnswerList[1])
+ }
)
gameModel.playersList.add(Player(binding.edtName.text.toString()))
GameData.saveGameModel(
gameModel
)
+ saveCurrentPlayerToPreferencesDataStore(binding.edtName.text.toString())
+
}
goToWaitingRooom()
}
@@ -62,7 +88,26 @@ class CreateRoomActivity : AppCompatActivity() {
return true
}
- fun goToWaitingRooom() {
+
+ private fun saveCurrentPlayerToPreferencesDataStore(currentPlayer: String) {
+ lifecycleScope.launch {
+ dataStore.edit { settings ->
+ settings[CURRENT_PLAYER] = currentPlayer
+ }
+ val savedPlayer = dataStore.data.first()[CURRENT_PLAYER]
+ Log.d("DataStore", "Saved player from create: $savedPlayer")
+ }
+ }
+
+
+ private fun getLetterCardListFromAnswer(answer: String): MutableList{
+ val list = mutableListOf()
+ for (i in answer.indices) {
+ list.add(LetterCard(answer[i].toString()))
+ }
+ return list
+ }
+ private fun goToWaitingRooom() {
val intent = Intent(this, WaitingRoomActivity::class.java)
intent.putExtra("room_id", binding.tvMaPhong.text.toString())
startActivity(intent)
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/PlayingRoomActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/PlayingRoomActivity.kt
deleted file mode 100644
index 876f2fc..0000000
--- a/app/src/main/java/com/example/chiecnonkydieu/ui/PlayingRoomActivity.kt
+++ /dev/null
@@ -1,186 +0,0 @@
-package com.example.chiecnonkydieu.ui
-
-import android.content.DialogInterface
-import android.content.Intent
-import android.os.Bundle
-import android.text.InputType
-import android.view.LayoutInflater
-import android.view.ViewGroup
-import android.widget.EditText
-import android.widget.Toast
-import androidx.activity.enableEdgeToEdge
-import androidx.activity.viewModels
-import androidx.appcompat.app.AlertDialog
-import androidx.appcompat.app.AppCompatActivity
-import androidx.appcompat.widget.Toolbar
-import androidx.core.content.ContentProviderCompat.requireContext
-import androidx.core.content.ContextCompat
-import androidx.core.view.ViewCompat
-import androidx.core.view.WindowInsetsCompat
-import androidx.lifecycle.Observer
-import androidx.lifecycle.lifecycleScope
-import com.example.chiecnonkydieu.R
-import com.example.chiecnonkydieu.data.GameData
-import com.example.chiecnonkydieu.data.GameModel
-import com.example.chiecnonkydieu.data.GameStatus
-import com.example.chiecnonkydieu.databinding.ActivityPlayingRoomBinding
-import com.example.chiecnonkydieu.ui.wheel.WheelActivity
-import com.example.chiecnonkydieu.ui.wheel.WheelViewModel
-import kotlinx.coroutines.launch
-import rubikstudio.library.LuckyWheelView
-
-
-class PlayingRoomActivity : AppCompatActivity() {
- private lateinit var binding: ActivityPlayingRoomBinding
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- enableEdgeToEdge()
-
- binding = ActivityPlayingRoomBinding.inflate(layoutInflater)
- val view = binding.root
- setContentView(view)
- ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
- val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
- v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
- insets
- }
-
-
- val toolbar: Toolbar = binding.toolbar
- setSupportActionBar(toolbar)
-
- supportActionBar?.setDisplayHomeAsUpEnabled(true)
- supportActionBar?.setDisplayShowHomeEnabled(true)
-
-
- lifecycleScope.launch {
- GameData.fetchGameModel(intent.getStringExtra("room_id").toString().toInt())
-
- }
-
- GameData.gameModel.observe(this, Observer { gameModel ->
- updateUi(gameModel)
- })
-
- binding.btnDoan.setOnClickListener {
- Toast.makeText(this, "Doan click", Toast.LENGTH_LONG).show()
- if (binding.edtDoan.text.toString() == "A") {
- // TODO
- }
- }
-
- binding.btnGiai.setOnClickListener {
- Toast.makeText(this, "Giai click", Toast.LENGTH_LONG).show()
- showDialog()
- }
-
- binding.iconButton.setOnClickListener {
- Toast.makeText(this, "Hint click", Toast.LENGTH_LONG).show()
- }
-
- // Wheel
- val wheelViewModel: WheelViewModel by viewModels()
- val luckyWheelView: LuckyWheelView = binding.luckyWheel
-
- wheelViewModel.initLuckyItemList(this)
- luckyWheelView.setData(wheelViewModel.luckyItemsList)
- luckyWheelView.setLuckyRoundItemSelectedListener {
- Toast.makeText(this, "on click", Toast.LENGTH_LONG).show()
- goToWheelActivity()
- }
- luckyWheelView.isTouchEnabled = false
- binding.llWheel.setOnClickListener {
- goToWheelActivity()
- }
-
-
- }
- override fun onSupportNavigateUp(): Boolean {
- onBackPressed()
- return true
- }
- private fun goToWheelActivity() {
- val intent = Intent(this, WheelActivity::class.java)
- startActivity(intent)
- }
-
- private fun updateUi(gameModel: GameModel?) {
- if (gameModel != null) {
- gameModel.gameStatus = GameStatus.INPROGRESS
-
- updatePlayerList(gameModel)
- updateCurrentQuestion(gameModel)
- }
-
- }
-
- private fun showDialog() {
- var m_Text: String = ""
- val builder = AlertDialog.Builder(this)
- builder.setTitle("Nhập lời giải cho câu hỏi")
- val viewInflated = LayoutInflater.from(this).inflate(R.layout.dialog_edittext, null, false)
- val input = viewInflated.findViewById(R.id.input)
- builder.setView(viewInflated)
-
- builder.setPositiveButton(android.R.string.ok) { dialog, which ->
- dialog.dismiss()
- m_Text = input.text.toString()
- }
-
- builder.setNegativeButton(android.R.string.cancel) { dialog, which ->
- dialog.cancel()
- }
-
- builder.show()
-
-
- }
-
- private fun updateCurrentQuestion(gameModel: GameModel) {
- binding.tvQuestion.text = gameModel.currentQuestion
- }
-
- private fun updatePlayerList(gameModel: GameModel) {
- when (gameModel.playersList.size) {
- 1 -> {
- // player1
- val colorResId = R.color.orange
- val backgroundColor = ContextCompat.getColor(this, colorResId)
- binding.cvPlayer1.setCardBackgroundColor(backgroundColor)
- binding.imgLogo1.setImageResource(R.drawable.ic_man)
- binding.tvPlayerName1.text = gameModel.playersList[0].name
- binding.tvScore1.text = gameModel.playersList[0].score.toString()
- }
- 2 -> {
- // player1 and player 2
- val colorResId = R.color.orange
- val backgroundColor = ContextCompat.getColor(this, colorResId)
- binding.imgLogo1.setImageResource(R.drawable.ic_man)
- binding.imgLogo2.setImageResource(R.drawable.ic_man)
- binding.tvPlayerName1.text = gameModel.playersList[0].name
- binding.tvPlayerName2.text = gameModel.playersList[1].name
-
- binding.tvScore1.text = gameModel.playersList[0].score.toString()
- binding.tvScore2.text = gameModel.playersList[1].score.toString()
-
-
- }
-
- 3 -> {
- // 3 player
- val colorResId = R.color.orange
- val backgroundColor = ContextCompat.getColor(this, colorResId)
- binding.imgLogo1.setImageResource(R.drawable.ic_man)
- binding.imgLogo2.setImageResource(R.drawable.ic_man)
- binding.imgLogo3.setImageResource(R.drawable.ic_man)
- binding.tvPlayerName1.text = gameModel.playersList[0].name
- binding.tvPlayerName2.text = gameModel.playersList[1].name
- binding.tvPlayerName3.text = gameModel.playersList[2].name
-
- binding.tvScore1.text = gameModel.playersList[0].score.toString()
- binding.tvScore2.text = gameModel.playersList[1].score.toString()
- binding.tvScore3.text = gameModel.playersList[2].score.toString()
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/SearchRoomActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/SearchRoomActivity.kt
index 023a84a..24e5f88 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/ui/SearchRoomActivity.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/SearchRoomActivity.kt
@@ -1,24 +1,32 @@
package com.example.chiecnonkydieu.ui
+import android.content.Context
import android.content.Intent
import android.os.Bundle
+import android.util.Log
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.stringPreferencesKey
+import androidx.datastore.preferences.preferencesDataStore
import androidx.lifecycle.lifecycleScope
import com.example.chiecnonkydieu.R
import com.example.chiecnonkydieu.data.GameData
-import com.example.chiecnonkydieu.data.Player
+import com.example.chiecnonkydieu.model.Player
import com.example.chiecnonkydieu.databinding.ActivitySearchRoomBinding
import kotlinx.coroutines.async
-import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class SearchRoomActivity : AppCompatActivity() {
private lateinit var binding: ActivitySearchRoomBinding
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
@@ -48,6 +56,7 @@ class SearchRoomActivity : AppCompatActivity() {
}.await()
if (isJoined) {
+ saveCurrentPlayerToPreferencesDataStore(binding.edtName.text.toString())
goToWaitingRooom()
} else {
Toast.makeText(applicationContext, "Error when connect game", Toast.LENGTH_LONG).show()
@@ -57,6 +66,16 @@ class SearchRoomActivity : AppCompatActivity() {
}
}
+ private fun saveCurrentPlayerToPreferencesDataStore(currentPlayer: String) {
+ lifecycleScope.launch {
+ dataStore.edit { settings ->
+ settings[CURRENT_PLAYER] = currentPlayer
+ }
+ val savedPlayer = dataStore.data.first()[CURRENT_PLAYER]
+ Log.d("DataStore", "Saved player from search: $savedPlayer")
+ }
+ }
+
fun goToWaitingRooom() {
try {
val intent = Intent(this, WaitingRoomActivity::class.java)
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/WaitingRoomActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/WaitingRoomActivity.kt
index b79b049..8f9736d 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/ui/WaitingRoomActivity.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/WaitingRoomActivity.kt
@@ -1,7 +1,7 @@
package com.example.chiecnonkydieu.ui
+import android.content.Context
import android.content.Intent
-import android.graphics.Color
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
@@ -9,22 +9,26 @@ import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.edit
+import androidx.datastore.preferences.core.stringPreferencesKey
+import androidx.datastore.preferences.preferencesDataStore
import androidx.lifecycle.Observer
import androidx.lifecycle.lifecycleScope
import com.example.chiecnonkydieu.R
import com.example.chiecnonkydieu.data.GameData
-import com.example.chiecnonkydieu.data.GameData.gameModel
import com.example.chiecnonkydieu.data.GameModel
import com.example.chiecnonkydieu.data.GameStatus
-import com.example.chiecnonkydieu.data.Player
+import com.example.chiecnonkydieu.model.Player
import com.example.chiecnonkydieu.databinding.ActivityWaitingRoomBinding
-import com.google.firebase.database.DataSnapshot
-import com.google.firebase.database.DatabaseError
-import com.google.firebase.database.ValueEventListener
+import com.example.chiecnonkydieu.ui.playingRoom.PlayingRoomActivity
+import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch
class WaitingRoomActivity : AppCompatActivity() {
private lateinit var binding: ActivityWaitingRoomBinding
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
@@ -49,16 +53,13 @@ class WaitingRoomActivity : AppCompatActivity() {
lifecycleScope.launch {
GameData.fetchGameModel(intent.getStringExtra("room_id").toString().toInt())
- if (GameData.gameModel.value?.gameStatus == GameStatus.INPROGRESS) {
- goToPlayingRoom()
- }
}
// update ui with the new model
GameData.gameModel.observe(this, Observer { gameModel ->
updateUi(gameModel)
- if (gameModel.gameStatus == GameStatus.INPROGRESS) {
+ if (gameModel.gameStatus == GameStatus.INPROGRESS && !checkCurrentPlayer()) {
goToPlayingRoom()
finish()
}
@@ -73,6 +74,7 @@ class WaitingRoomActivity : AppCompatActivity() {
)
}
goToPlayingRoom()
+ finish()
}
@@ -99,6 +101,14 @@ class WaitingRoomActivity : AppCompatActivity() {
// })
// }
+ fun checkCurrentPlayer(): Boolean {
+ var savedPlayer: String? = ""
+ lifecycleScope.launchWhenCreated {
+ savedPlayer = dataStore.data.first()[com.example.chiecnonkydieu.ui.playingRoom.CURRENT_PLAYER]
+ }
+ return savedPlayer == GameData.gameModel.value?.currentPlayer?.name
+
+ }
private fun updateUi(gameModel: GameModel?) {
if (gameModel != null) {
when (gameModel.playersList.size) {
@@ -143,6 +153,7 @@ class WaitingRoomActivity : AppCompatActivity() {
}
+
override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return true
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/adapters/LetterCardAdapter.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/adapters/LetterCardAdapter.kt
new file mode 100644
index 0000000..6619f16
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/adapters/LetterCardAdapter.kt
@@ -0,0 +1,53 @@
+package com.example.chiecnonkydieu.ui.adapters
+
+import android.graphics.Color
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.RecyclerView
+import android.widget.TextView
+import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.model.LetterCard
+import com.google.android.material.card.MaterialCardView
+
+class LetterCardAdapter(val letterCardList: List): RecyclerView.Adapter() {
+
+ class LetterCardViewHolder(viewLetterCard: View) : RecyclerView.ViewHolder(viewLetterCard) {
+ private val tvLetter: TextView = viewLetterCard.findViewById(R.id.text_card_letter)
+ private val cardView: MaterialCardView = viewLetterCard.findViewById(R.id.card_view_letter_cards)
+
+ fun bind(letterCard: LetterCard) {
+ if (letterCard.letter == " ") {
+ cardView.visibility = View.INVISIBLE
+ } else if (!letterCard.isHidden) {
+ tvLetter.text = letterCard.letter
+ tvLetter.visibility = View.VISIBLE
+ cardView.setCardBackgroundColor(Color.YELLOW)
+ cardView.visibility = View.VISIBLE
+ }
+// else if (letterCard.isHidden) {
+// tvLetter.text = letterCard.letter
+// tvLetter.visibility = View.INVISIBLE
+// }
+ }
+
+ }
+
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int)
+ : LetterCardViewHolder {
+ val viewLetterCard = LayoutInflater.from(parent.context)
+ .inflate(R.layout.view_letter_card, parent, false)
+ return LetterCardViewHolder(viewLetterCard)
+ }
+
+ override fun onBindViewHolder(holder: LetterCardViewHolder, position: Int) {
+ holder.bind(letterCardList[position])
+ }
+
+ override fun getItemCount(): Int {
+ return if (letterCardList.isEmpty()) 0
+ else letterCardList.size
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/admin/AddQuestionActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/admin/AddQuestionActivity.kt
new file mode 100644
index 0000000..de41e8b
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/admin/AddQuestionActivity.kt
@@ -0,0 +1,237 @@
+package com.example.chiecnonkydieu.ui.admin
+
+import android.app.ProgressDialog
+import android.os.Bundle
+import android.widget.Button
+import android.widget.EditText
+import android.widget.ImageButton
+import android.widget.Toast
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.lifecycle.lifecycleScope
+import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.data.GameData
+import com.example.chiecnonkydieu.model.QuestionAnswer
+import com.google.ai.client.generativeai.GenerativeModel
+import com.google.firebase.database.DatabaseReference
+import com.google.firebase.database.ktx.database
+import com.google.firebase.ktx.Firebase
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+
+class AddQuestionActivity : AppCompatActivity() {
+
+ private val database: DatabaseReference by lazy {
+ Firebase.database.reference
+ }
+ final val REFERENCE_CAUHOI: String = "CAU HOI"
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_add_question)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.add_questions)) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
+ }
+
+ val edtDoiTuong : EditText = findViewById(R.id.edt_DapAnCuaTroChoi)
+ val btnHintDapAn : ImageButton = findViewById(R.id.btnHintDapAn)
+
+ val edtCauHoi : EditText = findViewById(R.id.edt_CauHoiVeDoiTuong)
+ val btnCauHoi : ImageButton = findViewById(R.id.btnHintCauHoi)
+
+ val edtDoiTuongInHoa : EditText = findViewById(R.id.edt_DapAnInHoa)
+ val btnDapAnInHoa : ImageButton = findViewById(R.id.btnHintInHoa)
+
+ val edtHint1 : EditText = findViewById(R.id.edt_Hint1)
+ val btnHint1 : ImageButton = findViewById(R.id.btnHint1)
+
+ val edtHint2 : EditText = findViewById(R.id.edt_Hint2)
+ val btnHint2 : ImageButton = findViewById(R.id.btnHint2)
+
+ val edtHint3 : EditText = findViewById(R.id.edt_Hint3)
+ val btnHint3 : ImageButton = findViewById(R.id.btnHint3)
+
+ val edtThongTinKienThuc : EditText = findViewById(R.id.edtThongTin)
+ val btnThongTin : ImageButton = findViewById(R.id.btnThongTin)
+
+ val btnTaoToanBo : Button = findViewById(R.id.btnTaoToanBo)
+ val btnThem : Button = findViewById(R.id.btnThem)
+
+
+ val generativeModel = GenerativeModel(
+ // For text-only input, use the gemini-pro model
+ modelName = "gemini-pro",
+ // Access your API key as a Build Configuration variable (see "Set up your API key" above)
+ apiKey = "AIzaSyBnrK2OivzemEL84fWtE7OGLGtzMm4B2Dc"
+ )
+
+ val imageButton: ImageButton = findViewById(R.id.btn_back)
+ imageButton.setOnClickListener {
+ onBackPressed()
+ }
+ btnHintDapAn.setOnClickListener{
+ runBlocking {
+ val prompt = "Cho tôi một từ tiếng việt bất kì có tối đa 12 kí tự.Khuyến khích bạn sử dụng các từ gần gũi với văn học, lịch sử, địa danh, văn hóa, con người, âm nhạc Việt Nam. Không cần giải thích chỉ cần ghi từ đó ra. Các từ không viết liền nhau ví dụ Khỏe Khoắn"
+ val response = generativeModel.generateContent(prompt)
+ edtDoiTuong.setText(response.text)
+ }
+ }
+ btnDapAnInHoa.setOnClickListener {
+ edtDoiTuongInHoa.setText(chuyenChuoiThanhChuoiInHoaKhongDau(edtDoiTuong.text.toString()))
+ }
+ btnCauHoi.setOnClickListener {
+ if(edtDoiTuong.text.length.equals(0)) {
+ Toast.makeText(applicationContext, "Vui lòng điền đối tượng", Toast.LENGTH_SHORT)
+ .show()
+ return@setOnClickListener
+ }
+ runBlocking {
+ val prompt = "Tôi đang làm trò chơi đoán từ, cho tôi một câu hỏi về từ để mọi người có thể đoán " + edtDoiTuong.text + ",chỉ cần ghi câu hỏi"
+ val response = generativeModel.generateContent(prompt)
+ edtCauHoi.setText(response.text)
+ }
+ }
+ btnHint1.setOnClickListener {
+ if(edtDoiTuong.text.length.equals(0)) {
+ Toast.makeText(applicationContext, "Vui lòng điền đối tượng", Toast.LENGTH_SHORT)
+ .show()
+ return@setOnClickListener
+ }
+ runBlocking {
+ val prompt = "Hãy cho tôi biết từ " + edtDoiTuong.text + " thuộc loại từ gì. Chỉ cần ghi loại từ"
+ val response = generativeModel.generateContent(prompt)
+ edtHint1.setText(response.text)
+ }
+ }
+ btnHint2.setOnClickListener {
+ if(edtDoiTuong.text.length.equals(0)) {
+ Toast.makeText(applicationContext, "Vui lòng điền đối tượng", Toast.LENGTH_SHORT)
+ .show()
+ return@setOnClickListener
+ }
+ runBlocking {
+ val prompt = "Tôi đang làm trò chơi đoán từ, cho tôi một gợi ý ngắn về từ để mọi người có thể đoán " + edtDoiTuong.text
+ val response = generativeModel.generateContent(prompt)
+ edtHint2.setText(response.text)
+ }
+ }
+ btnHint3.setOnClickListener {
+ if(edtDoiTuong.text.length.equals(0)) {
+ Toast.makeText(applicationContext, "Vui lòng điền đối tượng", Toast.LENGTH_SHORT)
+ .show()
+ return@setOnClickListener
+ }
+ runBlocking {
+ val prompt = "Tôi đang làm trò chơi đoán từ, cho tôi một gợi ý ngắn về từ để mọi người có thể đoán " + edtDoiTuong.text + " khác với gợi ý này: " + edtHint2.text
+ val response = generativeModel.generateContent(prompt)
+ edtHint3.setText(response.text)
+ }
+ }
+ btnThongTin.setOnClickListener {
+ if(edtDoiTuong.text.length.equals(0)) {
+ Toast.makeText(applicationContext, "Vui lòng điền đối tượng", Toast.LENGTH_SHORT)
+ .show()
+ return@setOnClickListener
+ }
+ runBlocking {
+ val prompt = "Cho tôi một số thông tin kiến thức về từ " + edtDoiTuong.text + ", chỉ cần ghi ngắn gọn không cần dài dòng, không cần format in đậm in nghiêng, chỉ cần font bình thường"
+ val response = generativeModel.generateContent(prompt)
+ edtThongTinKienThuc.setText(response.text)
+ }
+ }
+ btnTaoToanBo.setOnClickListener{
+ try{
+ val progressDialog = ProgressDialog.show(this, "Vui lòng chờ", "Đang tạo...");
+ lifecycleScope.launch {
+ val prompt = "Cho tôi một từ tiếng việt bất kì có tối đa 12 kí tự.Khuyến khích bạn sử dụng các từ gần gũi với văn học, lịch sử, địa danh Việt Nam. Không cần giải thích chỉ cần ghi từ đó ra"
+ val response = generativeModel.generateContent(prompt)
+ edtDoiTuong.setText(response.text)
+
+ val word = edtDoiTuong.text.toString()
+
+ // Convert word to uppercase without diacritics
+ edtDoiTuongInHoa.setText(chuyenChuoiThanhChuoiInHoaKhongDau(word))
+
+ // Generate question about the word
+ val questionPrompt = "Tôi đang làm trò chơi đoán từ, cho tôi một câu hỏi về từ để mọi người có thể đoán \"$word\"... Giới hạn dưới 30 chữ "
+ val questionResponse = generativeModel.generateContent(questionPrompt)
+ edtCauHoi.setText(questionResponse.text)
+
+ // Generate hint 1
+ val hint1Prompt = "Hãy cho tôi biết từ \"$word\" thuộc loại từ gì..."
+ val hint1Response = generativeModel.generateContent(hint1Prompt)
+ edtHint1.setText(hint1Response.text)
+
+ // Generate hint 2
+ val hint2Prompt = "Tôi đang làm trò chơi đoán từ, cho tôi một gợi ý ngắn về từ để mọi người có thể đoán \"$word\"..."
+ val hint2Response = generativeModel.generateContent(hint2Prompt)
+ edtHint2.setText(hint2Response.text)
+
+ // Generate hint 3
+ val hint3Prompt = "Tôi đang làm trò chơi đoán từ, cho tôi một gợi ý ngắn về từ để mọi người có thể đoán \"$word\" khác với gợi ý này: ${edtHint2.text}"
+ val hint3Response = generativeModel.generateContent(hint3Prompt)
+ edtHint3.setText(hint3Response.text)
+
+ // Generate knowledge about the word
+ val knowledgePrompt = "Cho tôi một số thông tin kiến thức về từ \"$word\", chỉ cần ghi ngắn gọn không cần dài dòng, không cần format in đậm in nghiêng, không cần dấu * để chỉ heading, chỉ cần font bình thường"
+ val knowledgeResponse = generativeModel.generateContent(knowledgePrompt)
+ edtThongTinKienThuc.setText(knowledgeResponse.text)
+ }
+ progressDialog.dismiss()
+ }
+ catch (ex : Exception){
+ Toast.makeText(applicationContext, "Thao tác quá nhanh vui lòng thử lại ", Toast.LENGTH_LONG).show()
+ }
+ }
+
+
+ btnThem.setOnClickListener{
+ try {
+ val BoCauHoi = QuestionAnswer()
+ BoCauHoi.DoiTuong = edtDoiTuong.text.toString()
+ BoCauHoi.CauHoi = edtCauHoi.text.toString()
+ BoCauHoi.DoiTuongInHoa = edtDoiTuongInHoa.text.toString()
+ BoCauHoi.Hint1 = edtHint1.text.toString()
+ BoCauHoi.Hint2 = edtHint2.text.toString()
+ BoCauHoi.Hint3 = edtHint3.text.toString()
+ BoCauHoi.ThongTin = edtThongTinKienThuc.text.toString()
+
+ database.child(REFERENCE_CAUHOI).push().setValue(BoCauHoi).addOnSuccessListener {
+ Toast.makeText(this, "Thêm câu hỏi thành công", Toast.LENGTH_LONG).show()
+ edtDoiTuong.text.clear()
+ edtCauHoi.text.clear()
+ edtDoiTuongInHoa.text.clear()
+ edtHint1.text.clear()
+ edtHint2.text.clear()
+ edtHint3.text.clear()
+ edtThongTinKienThuc.text.clear()
+ }
+
+ }
+ catch(e : Exception) {
+ Toast.makeText(applicationContext, "Vui lòng thử lại", Toast.LENGTH_LONG).show()
+ }
+
+ }
+
+ }
+ fun chuyenChuoiThanhChuoiInHoaKhongDau(chuoi: String): String {
+ val vietnameseCharactersWithAccents = "àáảãạâầấẩẫậăằắẳẵặèéẻẽẹêềếểễệìíỉĩịòóỏõọôồốổỗộơờớởỡợùúủũụưừứửữựỳýỷỹỵđÀÁẢÃẠÂẦẤẨẪẬĂẰẮẲẴẶÈÉẺẼẸÊỀẾỂỄỆÌÍỈĨỊÒÓỎÕỌÔỒỐỔỖỘƠỜỚỞỠỢÙÚỦŨỤƯỪỨỬỮỰỲÝỶỸỴĐ"
+ val vietnameseCharactersWithoutAccents = "aaaaaaaaaaaaaaaaaeeeeeeeeeeeiiiiiooooooooooooooooouuuuuuuuuuuyyyyydAAAAAAAAAAAAAAAAAEEEEEEEEEEEIIIIIOOOOOOOOOOOOOOOOOUUUUUUUUUUUYYYYYD"
+
+ val stringBuilder = StringBuilder()
+ for (char in chuoi) {
+ val index = vietnameseCharactersWithAccents.indexOf(char)
+ if (index != -1) {
+ stringBuilder.append(vietnameseCharactersWithoutAccents[index])
+ } else {
+ stringBuilder.append(char)
+ }
+ }
+ return stringBuilder.toString().toUpperCase()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/admin/HomeAdminActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/admin/HomeAdminActivity.kt
new file mode 100644
index 0000000..3014c02
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/admin/HomeAdminActivity.kt
@@ -0,0 +1,31 @@
+package com.example.chiecnonkydieu.ui.admin
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.databinding.ActivityHomeAdminBinding
+
+class HomeAdminActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityHomeAdminBinding
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivityHomeAdminBinding.inflate(layoutInflater)
+ val view = binding.root
+ setContentView(view)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.admin_main)) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
+ }
+ binding.btnThemCauHoi.setOnClickListener {
+ val intent = Intent(this, AddQuestionActivity::class.java)
+ startActivity(intent)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/admin/LoginActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/admin/LoginActivity.kt
new file mode 100644
index 0000000..f8d7924
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/admin/LoginActivity.kt
@@ -0,0 +1,41 @@
+package com.example.chiecnonkydieu.ui.admin
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import com.example.chiecnonkydieu.MainActivity
+import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.databinding.ActivityLoginBinding
+import com.example.chiecnonkydieu.databinding.ActivityPlayingRoomBinding
+import com.example.chiecnonkydieu.ui.wheel.WheelActivity
+
+class LoginActivity : AppCompatActivity() {
+
+ private lateinit var binding: ActivityLoginBinding
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivityLoginBinding.inflate(layoutInflater)
+ val view = binding.root
+ setContentView(view)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
+ }
+
+ binding.btnDangNhap.setOnClickListener {
+ if (binding.edtTaikhoan.text.toString() == "admin") {
+ val intent: Intent = Intent(this, HomeAdminActivity::class.java)
+ startActivity(intent)
+ }
+ else {
+ val intent: Intent = Intent(this, MainActivity::class.java)
+ startActivity(intent)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/playingRoom/PlayingRoomActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/playingRoom/PlayingRoomActivity.kt
new file mode 100644
index 0000000..b1ce07a
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/playingRoom/PlayingRoomActivity.kt
@@ -0,0 +1,381 @@
+package com.example.chiecnonkydieu.ui.playingRoom
+
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.widget.EditText
+import android.widget.ImageView
+import android.widget.LinearLayout
+import android.widget.TextView
+import android.widget.Toast
+import androidx.activity.enableEdgeToEdge
+import androidx.activity.viewModels
+import androidx.appcompat.app.AlertDialog
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.Toolbar
+import androidx.constraintlayout.widget.ConstraintLayout
+import androidx.core.content.ContextCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.datastore.core.DataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.core.stringPreferencesKey
+import androidx.datastore.preferences.preferencesDataStore
+import androidx.lifecycle.Observer
+import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.LinearLayoutManager
+import androidx.recyclerview.widget.RecyclerView
+import com.example.chiecnonkydieu.MainActivity
+import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.data.GameData
+import com.example.chiecnonkydieu.data.GameData.gameModel
+import com.example.chiecnonkydieu.data.GameModel
+import com.example.chiecnonkydieu.data.GameStatus
+import com.example.chiecnonkydieu.data.questionAnswerList
+import com.example.chiecnonkydieu.databinding.ActivityPlayingRoomBinding
+import com.example.chiecnonkydieu.ui.adapters.LetterCardAdapter
+import com.example.chiecnonkydieu.ui.dataStore
+import com.example.chiecnonkydieu.ui.wheel.WheelActivity
+import com.example.chiecnonkydieu.ui.wheel.WheelViewModel
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.launch
+import rubikstudio.library.LuckyWheelView
+
+
+private val Context.dataStore: DataStore by preferencesDataStore(name = "player_data")
+val CURRENT_PLAYER = stringPreferencesKey("current_player")
+class PlayingRoomActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityPlayingRoomBinding
+ val playingRoomViewModel: PlayingRoomViewModel by viewModels()
+
+ var indexWheel: Int = -1
+ var currentValueWheel: String = ""
+ private var isDialogShowing = false
+
+ lateinit var adapter: LetterCardAdapter
+ lateinit var recyclerView: RecyclerView
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+
+ binding = ActivityPlayingRoomBinding.inflate(layoutInflater)
+ val view = binding.root
+ setContentView(view)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
+ val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
+ v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
+ insets
+ }
+
+
+ val toolbar: Toolbar = binding.toolbar
+ setSupportActionBar(toolbar)
+
+ supportActionBar?.setDisplayHomeAsUpEnabled(true)
+ supportActionBar?.setDisplayShowHomeEnabled(true)
+
+
+ lifecycleScope.launch {
+ GameData.fetchGameModel(intent.getStringExtra("room_id").toString().toInt())
+ }
+
+ GameData.gameModel.observe(this, Observer { gameModel ->
+ updateUi(gameModel)
+ })
+
+ //Setup recyclerview
+ recyclerView = binding.recyclerviewLetterCards
+ val layoutManager = LinearLayoutManager(this)
+
+ layoutManager.orientation = LinearLayoutManager.HORIZONTAL // Set the orientation to horizontal if needed
+ recyclerView.layoutManager = layoutManager
+ adapter = LetterCardAdapter(gameModel.value!!.letterCardList)
+ recyclerView.adapter = adapter
+
+
+
+
+
+ binding.btnDoan.setOnClickListener {
+ if (playingRoomViewModel.isUserInputMatch(binding.edtDoan.text.toString()[0])) {
+ updateAdapterAndRecyclerView()
+ Toast.makeText(this, "Bạn đoán đúng rồi", Toast.LENGTH_SHORT).show()
+
+ }
+ else {
+ Toast.makeText(this, "Bạn đoán sai rồi", Toast.LENGTH_LONG).show()
+ }
+
+// if (playingRoomViewModel.checkRoundWin()) {
+// playingRoomViewModel.updateGameEndRound()
+// showWinnerDialog(playingRoomViewModel)
+// Toast.makeText(this, "Da doan xong", Toast.LENGTH_LONG).show()
+// }
+ binding.edtDoan.text?.clear()
+
+ }
+
+ binding.btnGiai.setOnClickListener {
+ showDialog(playingRoomViewModel)
+ }
+
+ binding.iconButton.setOnClickListener {
+ showHintDialog()
+ }
+
+ // Wheel
+ val wheelViewModel: WheelViewModel by viewModels()
+ val luckyWheelView: LuckyWheelView = binding.luckyWheel
+
+ wheelViewModel.initLuckyItemList(this)
+ luckyWheelView.setData(wheelViewModel.luckyItemsList)
+ luckyWheelView.isTouchEnabled = false
+ binding.llWheel.setOnClickListener {
+ if (checkCurrentPlayer()) {
+ goToWheelActivity()
+ }
+ else {
+ Toast.makeText(applicationContext, "Không phải lượt của bạn!", Toast.LENGTH_LONG).show()
+ }
+ }
+
+
+ }
+
+
+ override fun onSupportNavigateUp(): Boolean {
+ onBackPressed()
+ return true
+ }
+ private fun goToWheelActivity() {
+ val intent = Intent(this, WheelActivity::class.java)
+ startActivity(intent)
+ }
+
+
+ fun checkCurrentPlayer(): Boolean {
+ var savedPlayer: String? = ""
+ lifecycleScope.launchWhenCreated {
+ savedPlayer = dataStore.data.first()[CURRENT_PLAYER]
+ }
+ return savedPlayer == GameData.gameModel.value?.currentPlayer?.name
+ }
+ private fun updateUi(gameModel: GameModel?) {
+ if (gameModel != null) {
+ updatePlayerList(gameModel)
+ updateWheel(gameModel)
+ updateVisibility(gameModel)
+ updateCurrentQuestionAndAnswer(gameModel)
+ updateAdapterAndRecyclerView()
+ if (gameModel.gameStatus == GameStatus.ENDROUND && !isDialogShowing) {
+ showWinnerDialog(playingRoomViewModel)
+ playingRoomViewModel.updateStatusGameModel(GameStatus.WAITING_TO_CONTINUE)
+ }
+ }
+ }
+
+ fun updateWheel(gameModel: GameModel) {
+ if (!gameModel.currentSpinValue.isNullOrEmpty() && gameModel.currentSpinValue != currentValueWheel ) {
+ val wheelViewModel: WheelViewModel by viewModels()
+ for (i in wheelViewModel.luckyItemsList.indices) {
+ if (wheelViewModel.luckyItemsList[i].secondaryText == gameModel.currentSpinValue) {
+ indexWheel = i
+ currentValueWheel = gameModel.currentSpinValue
+ break
+ }
+ if (wheelViewModel.luckyItemsList[i].topText == gameModel.currentSpinValue) {
+ indexWheel = i
+ currentValueWheel = gameModel.currentSpinValue
+ break
+ }
+ }
+ // Kiem tra xem neu la nguoi choi hien tai thi chi cho round la 0, neu khong thi cho 3
+ if (checkCurrentPlayer()) {
+ // TODO
+ binding.luckyWheel.setRound(0)
+ binding.luckyWheel.startLuckyWheelWithTargetIndex(indexWheel)
+ }
+ else {
+ binding.luckyWheel.setRound(3)
+ binding.luckyWheel.startLuckyWheelWithTargetIndex(indexWheel)
+ }
+ }
+ }
+ fun updateVisibility(gameModel: GameModel) {
+
+ if (gameModel.gameStatus == GameStatus.INPROGRESS) {
+ binding.llHint.visibility = View.GONE
+ binding.tilDoan.visibility = View.GONE
+ binding.btnDoan.visibility = View.GONE
+ binding.btnGiai.visibility = View.GONE
+ }
+ else if (checkCurrentPlayer()){
+ binding.llHint.visibility = View.VISIBLE
+ binding.tilDoan.visibility = View.VISIBLE
+ binding.btnDoan.visibility = View.VISIBLE
+ binding.btnGiai.visibility = View.VISIBLE
+ }
+ }
+
+ private fun showDialog(viewModel: PlayingRoomViewModel) {
+
+ val builder = AlertDialog.Builder(this)
+ builder.setTitle("Nhập lời giải cho câu hỏi")
+ val viewInflated = LayoutInflater.from(this).inflate(R.layout.dialog_edittext, null, false)
+ val input = viewInflated.findViewById(R.id.input)
+ builder.setView(viewInflated)
+
+ builder.setPositiveButton(android.R.string.ok) { dialog, which ->
+
+ if (input.text.toString() == GameData.gameModel.value!!.currentQuestionAnswer.DoiTuongInHoa) {
+ Toast.makeText(this, "giai thanh cong", Toast.LENGTH_LONG).show()
+ viewModel.makeAllLetterCardReveal()
+ viewModel.updateGameEndRound()
+ }
+ dialog.dismiss()
+ }
+ builder.setNegativeButton(android.R.string.cancel) { dialog, which ->
+ dialog.cancel()
+ }
+
+ builder.show()
+ }
+
+ private fun showWinnerDialog(viewModel: PlayingRoomViewModel) {
+
+ isDialogShowing = true
+// viewModel.updateGameEndRound()
+ val builder = AlertDialog.Builder(this)
+ builder.setTitle("Xin chức mừng")
+ builder.setMessage("Đáp án chính xác là: ${GameData.gameModel.value!!.currentQuestionAnswer.DoiTuong}")
+
+ builder.setPositiveButton(R.string.btn_next) { dialog, which ->
+ var questionAnswerToBeGuess = questionAnswerList.random()
+ while (GameData.gameModel.value!!.previousQuestionAnswers.contains(questionAnswerToBeGuess)) {
+ questionAnswerToBeGuess = questionAnswerList.random()
+ }
+ playingRoomViewModel.setQuestionAndCurrentWordToBeGuessed(questionAnswerToBeGuess)
+ updateCurrentQuestionAndAnswer(GameData.gameModel.value!!)
+ Toast.makeText(applicationContext, "choi tiep click", Toast.LENGTH_LONG).show()
+ isDialogShowing = false
+ dialog.dismiss()
+ }
+
+ builder.setNegativeButton(R.string.btn_thoat) { dialog, which ->
+ dialog.cancel()
+ val intent = Intent(this, MainActivity::class.java)
+ intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
+ startActivity(intent)
+ finish()
+ }
+ builder.show()
+ }
+
+ private fun showHintDialog() {
+ val viewInflated = LayoutInflater.from(this).inflate(R.layout.list_hint, null, false)
+ val listHint = viewInflated.findViewById(R.id.cl_listHint)
+ val alertDialog = AlertDialog.Builder(this)
+ .setTitle("Choose Hint")
+ .setView(listHint)
+ .setNegativeButton("Cancel", null)
+ .show()
+
+ listHint.findViewById(R.id.ll_hint1).setOnClickListener {
+ Toast.makeText(applicationContext, "hint1 click", Toast.LENGTH_LONG).show()
+ listHint.findViewById(R.id.img_add1).visibility = View.GONE
+ listHint.findViewById(R.id.tv_hint1).text = GameData.gameModel.value!!.currentQuestionAnswer.Hint1
+ }
+ listHint.findViewById(R.id.ll_hint2).setOnClickListener {
+ Toast.makeText(applicationContext, "hint2 click", Toast.LENGTH_LONG).show()
+ listHint.findViewById(R.id.img_add2).visibility = View.GONE
+ listHint.findViewById(R.id.tv_hint2).text = GameData.gameModel.value!!.currentQuestionAnswer.Hint2
+ }
+ listHint.findViewById(R.id.ll_hint3).setOnClickListener {
+ Toast.makeText(applicationContext, "hint3 click", Toast.LENGTH_LONG).show()
+ listHint.findViewById(R.id.img_add3).visibility = View.GONE
+ listHint.findViewById(R.id.tv_hint3).text = GameData.gameModel.value!!.currentQuestionAnswer.Hint3
+ }
+
+
+ }
+
+ private fun updateCurrentQuestionAndAnswer(gameModel: GameModel) {
+ binding.tvQuestion.text = gameModel.currentQuestionAnswer.CauHoi
+ updateAdapterAndRecyclerView()
+ }
+
+ private fun updatePlayerList(gameModel: GameModel) {
+ when (gameModel.playersList.size) {
+ 1 -> {
+ // player1
+ val colorResId = R.color.orange
+ val backgroundColor = ContextCompat.getColor(this, colorResId)
+ binding.cvPlayer1.setCardBackgroundColor(backgroundColor)
+ binding.imgLogo1.setImageResource(R.drawable.ic_man)
+ binding.tvPlayerName1.text = gameModel.playersList[0].name
+ binding.tvScore1.text = gameModel.playersList[0].score.toString()
+ binding.cvPlayer2.visibility = View.INVISIBLE
+ binding.cvPlayer3.visibility = View.INVISIBLE
+ }
+ 2 -> {
+ // player1 and player 2
+ val colorResId = R.color.orange
+ val backgroundColor = ContextCompat.getColor(this, colorResId)
+ binding.imgLogo1.setImageResource(R.drawable.ic_man)
+ binding.imgLogo2.setImageResource(R.drawable.ic_man)
+ binding.tvPlayerName1.text = gameModel.playersList[0].name
+ binding.tvPlayerName2.text = gameModel.playersList[1].name
+
+ binding.tvScore1.text = gameModel.playersList[0].score.toString()
+ binding.tvScore2.text = gameModel.playersList[1].score.toString()
+ binding.cvPlayer3.visibility = View.INVISIBLE
+
+ }
+
+ 3 -> {
+ // 3 player
+ val colorResId = R.color.orange
+ val backgroundColor = ContextCompat.getColor(this, colorResId)
+ binding.imgLogo1.setImageResource(R.drawable.ic_man)
+ binding.imgLogo2.setImageResource(R.drawable.ic_man)
+ binding.imgLogo3.setImageResource(R.drawable.ic_man)
+ binding.tvPlayerName1.text = gameModel.playersList[0].name
+ binding.tvPlayerName2.text = gameModel.playersList[1].name
+ binding.tvPlayerName3.text = gameModel.playersList[2].name
+
+ binding.tvScore1.text = gameModel.playersList[0].score.toString()
+ binding.tvScore2.text = gameModel.playersList[1].score.toString()
+ binding.tvScore3.text = gameModel.playersList[2].score.toString()
+ }
+ }
+
+ val colorResId = R.color.orange
+ val currentPlayerColor = ContextCompat.getColor(this, colorResId)
+
+ val colorResBackgroundId = R.color.background
+ val backgroundColor = ContextCompat.getColor(this, colorResBackgroundId)
+ if (gameModel.currentPlayer.name == binding.tvPlayerName1.text.toString()) {
+ binding.cvPlayer1.setCardBackgroundColor(currentPlayerColor)
+ binding.cvPlayer2.setCardBackgroundColor(backgroundColor)
+ binding.cvPlayer3.setCardBackgroundColor(backgroundColor)
+ }
+ else if (gameModel.currentPlayer.name == binding.tvPlayerName2.text.toString()){
+ binding.cvPlayer2.setCardBackgroundColor(currentPlayerColor)
+ binding.cvPlayer1.setCardBackgroundColor(backgroundColor)
+ binding.cvPlayer3.setCardBackgroundColor(backgroundColor)
+ }
+ else {
+ binding.cvPlayer3.setCardBackgroundColor(currentPlayerColor)
+ binding.cvPlayer2.setCardBackgroundColor(backgroundColor)
+ binding.cvPlayer1.setCardBackgroundColor(backgroundColor)
+ }
+ }
+
+ private fun updateAdapterAndRecyclerView() {
+ adapter = LetterCardAdapter(gameModel.value!!.letterCardList)
+ recyclerView.adapter = adapter
+ adapter.notifyDataSetChanged()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/playingRoom/PlayingRoomViewModel.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/playingRoom/PlayingRoomViewModel.kt
new file mode 100644
index 0000000..ea1d0fb
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/playingRoom/PlayingRoomViewModel.kt
@@ -0,0 +1,222 @@
+package com.example.chiecnonkydieu.ui.playingRoom
+
+import android.content.Context
+import androidx.core.text.isDigitsOnly
+import androidx.datastore.core.DataStore
+import androidx.datastore.dataStore
+import androidx.datastore.preferences.core.Preferences
+import androidx.datastore.preferences.preferencesDataStore
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.example.chiecnonkydieu.data.GameData
+import com.example.chiecnonkydieu.data.GameData.gameModel
+import com.example.chiecnonkydieu.data.GameData.saveGameModel
+import com.example.chiecnonkydieu.data.GameModel
+import com.example.chiecnonkydieu.data.GameStatus
+import com.example.chiecnonkydieu.data.REFERENCE_CAUHOI
+import com.example.chiecnonkydieu.data.database
+import com.example.chiecnonkydieu.data.questionAnswerList
+import com.example.chiecnonkydieu.model.LetterCard
+import com.example.chiecnonkydieu.model.Player
+import com.example.chiecnonkydieu.model.QuestionAnswer
+import com.google.firebase.database.DataSnapshot
+import com.google.firebase.database.DatabaseError
+import com.google.firebase.database.ValueEventListener
+import kotlinx.coroutines.currentCoroutineContext
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.catch
+import kotlinx.coroutines.flow.firstOrNull
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.launch
+
+
+
+class PlayingRoomViewModel: ViewModel() {
+
+ private lateinit var gameModel: GameModel
+
+
+ init {
+ if (GameData.gameModel.value != null) {
+ gameModel = GameData.gameModel.value!!
+ }
+ getQuestionFromFirebase()
+ }
+
+ private fun getQuestionFromFirebase() {
+ val questionAnswerListFromFirebase: MutableList = mutableListOf()
+
+ // Lắng nghe sự kiện khi dữ liệu thay đổi trên Firebase
+ database.child(REFERENCE_CAUHOI).addListenerForSingleValueEvent(object :
+ ValueEventListener {
+ override fun onDataChange(dataSnapshot: DataSnapshot) {
+ // Xóa danh sách hiện tại để cập nhật với dữ liệu mới
+ questionAnswerListFromFirebase.clear()
+
+ // Lặp qua các nút con của nút "QUESTION_ANSWER" trên Firebase
+ for (snapshot in dataSnapshot.children) {
+ // Lấy dữ liệu từ DataSnapshot và chuyển đổi thành đối tượng QuestionAnswer
+ val questionAnswer = snapshot.getValue(QuestionAnswer::class.java)
+ if (questionAnswer != null) {
+ questionAnswerListFromFirebase.add(questionAnswer)
+ }
+ }
+
+ // Gán danh sách câu hỏi và câu trả lời từ Firebase vào questionAnswerList
+ questionAnswerList.clear()
+ questionAnswerList.addAll(questionAnswerListFromFirebase)
+ }
+
+ override fun onCancelled(databaseError: DatabaseError) {
+ // Xử lý khi có lỗi xảy ra
+ }
+ })
+ }
+
+
+ fun isUserInputMatch(playerInputChar: Char): Boolean {
+ val gameModel: GameModel? = GameData.gameModel.value
+ val playerInputStringLC = playerInputChar.lowercaseChar().toString()
+ val playerInputCharLC = playerInputChar.lowercaseChar()
+ gameModel?.let {
+ if (gameModel.currentQuestionAnswer.DoiTuongInHoa.contains(
+ playerInputStringLC,
+ ignoreCase = true
+ ) &&
+ ! gameModel.guessesCharacters.contains(playerInputStringLC)) {
+ saveGuessedChar(playerInputCharLC)
+ gameModel.letterCardList.filter {
+ it.letter.toLowerCase() == playerInputStringLC
+ }
+ .forEach{
+ it.isHidden = false
+ }
+ updateStatusGameModel(GameStatus.INPROGRESS)
+ updateScore(gameModel)
+ if (checkRoundWin()) {
+ updateStatusGameModel(GameStatus.ENDROUND)
+ }
+ changeTurn()
+ GameData.saveGameModel(gameModel)
+ return true
+ }
+ else {
+ updateStatusGameModel(GameStatus.INPROGRESS)
+ changeTurn()
+ GameData.saveGameModel(gameModel)
+ return false;
+ }
+ }
+ return false
+ }
+
+ fun setQuestionAndCurrentWordToBeGuessed(questionAnswer: QuestionAnswer): Boolean {
+ val gameModel: GameModel? = GameData.gameModel.value
+ gameModel?.let {
+ if (!gameModel.previousQuestionAnswers.contains(questionAnswer)) {
+ gameModel.previousQuestionAnswers.add(questionAnswer)
+ gameModel.currentQuestionAnswer = questionAnswer
+ val tempLetterCardList = mutableListOf()
+ for (i in questionAnswer.DoiTuongInHoa.indices) {
+ tempLetterCardList.add(LetterCard(questionAnswer.DoiTuongInHoa[i].toString()))
+ }
+ gameModel.letterCardList = tempLetterCardList
+ gameModel.gameStatus = GameStatus.INPROGRESS
+ gameModel.guessesCharacters.clear()
+ GameData.saveGameModel(gameModel)
+ return true
+ }
+ return false
+ }
+ return false
+ }
+
+ private fun saveGuessedChar(playerInputChar: Char) {
+ val gameModel: GameModel? = GameData.gameModel.value
+ gameModel?.let {
+ gameModel.guessesCharacters.add(playerInputChar.toString())
+ }
+ }
+
+ fun updateStatusGameModel(gameStatus: GameStatus) {
+ val gameModel: GameModel? = GameData.gameModel.value
+ gameModel?.let {
+ gameModel.gameStatus = gameStatus
+ }
+ }
+
+ fun updateScore(gameModel: GameModel) {
+ // TODO xu ly item, extra turn, miss turn
+ gameModel.let {
+ val currentPlayer = gameModel.currentPlayer
+ val currentSpinValue = gameModel.currentSpinValue
+ val index = gameModel.playersList.indexOfFirst { it.name == currentPlayer.name }
+ if (currentSpinValue.isDigitsOnly()) {
+ gameModel.playersList[index].score += currentSpinValue.toInt()
+ } else if (currentSpinValue == "ITEM"){
+ // TODO
+ } else if (currentSpinValue == "MISS TURN") {
+ changeTurn()
+ updateStatusGameModel(GameStatus.INPROGRESS)
+ }
+ }
+ }
+
+
+
+ private fun changeTurn() {
+ val gameModel: GameModel? = GameData.gameModel.value
+ var indexNewPlayer = -1
+ gameModel?.let {
+ for (i in gameModel.playersList.indices) {
+ if (gameModel.playersList[i].name == gameModel.currentPlayer.name) {
+ indexNewPlayer = (i + 1) % gameModel.playersList.size
+ }
+ }
+ gameModel.currentPlayer = gameModel.playersList[indexNewPlayer]
+ }
+ }
+
+ private fun nextRound() {
+ // TODO
+ }
+
+
+ fun checkRoundWin(): Boolean {
+ val gameModel: GameModel? = GameData.gameModel.value
+ var count = 0
+ gameModel?.let {
+
+ for (i in gameModel.letterCardList.indices) {
+ if (gameModel.letterCardList[i].isHidden) {
+ count++
+ }
+ }
+
+ }
+ return count == 0
+ }
+
+ fun makeAllLetterCardReveal() {
+ for (i in gameModel.letterCardList.indices) {
+ if (gameModel.letterCardList[i].isHidden) {
+ gameModel.letterCardList[i].isHidden = false
+ }
+ }
+// GameData.saveGameModel(gameModel)
+ }
+ fun resetGuessedCharacter() {
+ val gameModel: GameModel? = GameData.gameModel.value
+ gameModel?.let {
+ gameModel.guessesCharacters.clear()
+ }
+ }
+ fun updateGameEndRound() {
+ val gameModel: GameModel? = GameData.gameModel.value
+ gameModel?.let {
+ gameModel.gameStatus = GameStatus.ENDROUND
+ GameData.saveGameModel(gameModel)
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelActivity.kt
index 25df369..f30a72d 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelActivity.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelActivity.kt
@@ -14,9 +14,12 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.get
import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.data.GameData
+import com.example.chiecnonkydieu.data.GameStatus
import com.example.chiecnonkydieu.databinding.ActivityWheelBinding
import rubikstudio.library.LuckyWheelView
import rubikstudio.library.model.LuckyItem
+import java.util.concurrent.locks.ReentrantLock
class WheelActivity : AppCompatActivity() {
private lateinit var binding: ActivityWheelBinding
@@ -45,23 +48,43 @@ class WheelActivity : AppCompatActivity() {
wheelViewModel.initLuckyItemList(this)
luckyWheelView.setData(wheelViewModel.luckyItemsList)
-
luckyWheelView.isTouchEnabled = false
luckyWheelView.setOnTouchListener { v, event ->
+ countDownTimer.cancel()
val indexAns = wheelViewModel.getIndexAfterRotate()
luckyWheelView.setRound(3)
luckyWheelView.startLuckyWheelWithTargetIndex(indexAns)
Toast.makeText(this, wheelViewModel.getStringItemAtIndex(indexAns), Toast.LENGTH_LONG).show()
- return@setOnTouchListener true
+ wheelViewModel.updateCurrentSpinValue(wheelViewModel.getStringItemAtIndex(indexAns))
+ return@setOnTouchListener false
}
binding.btnQuay.setOnClickListener {
+ countDownTimer.cancel()
val indexAns = wheelViewModel.getIndexAfterRotate()
luckyWheelView.setRound(3)
luckyWheelView.startLuckyWheelWithTargetIndex(indexAns)
Toast.makeText(this, wheelViewModel.getStringItemAtIndex(indexAns), Toast.LENGTH_LONG).show()
-// Toast.makeText(this, wheelViewModel.luckyItemsList.get(3).secondaryText, Toast.LENGTH_LONG).show()
+ wheelViewModel.updateCurrentSpinValue(wheelViewModel.getStringItemAtIndex(indexAns))
+ }
+
+ binding.btnMissTurnDemo.setOnClickListener {
+ countDownTimer.cancel()
+ val indexAns = 6 // vi tri mac dinh cua miss turn item
+ luckyWheelView.setRound(3)
+ luckyWheelView.startLuckyWheelWithTargetIndex(indexAns)
+ Toast.makeText(this, wheelViewModel.getStringItemAtIndex(indexAns), Toast.LENGTH_LONG).show()
+ wheelViewModel.updateCurrentSpinValue(wheelViewModel.getStringItemAtIndex(indexAns))
+ }
+
+ binding.btnItemDemo.setOnClickListener {
+ countDownTimer.cancel()
+ val indexAns = 10 // vi tri mac dinh cua item demo
+ luckyWheelView.setRound(3)
+ luckyWheelView.startLuckyWheelWithTargetIndex(indexAns)
+ Toast.makeText(this, wheelViewModel.getStringItemAtIndex(indexAns), Toast.LENGTH_LONG).show()
+ wheelViewModel.updateCurrentSpinValue(wheelViewModel.getStringItemAtIndex(indexAns))
}
// count down timer
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelViewModel.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelViewModel.kt
index 3153000..3570c5d 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelViewModel.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelViewModel.kt
@@ -1,15 +1,23 @@
package com.example.chiecnonkydieu.ui.wheel
import android.content.Context
-import android.graphics.Color
import androidx.core.content.ContextCompat
+import androidx.core.text.isDigitsOnly
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.data.GameData
+import com.example.chiecnonkydieu.data.GameModel
+import com.example.chiecnonkydieu.data.GameStatus
+import com.example.chiecnonkydieu.model.LetterCard
import rubikstudio.library.model.LuckyItem
class WheelViewModel: ViewModel() {
private val _luckyItemsList: MutableList = mutableListOf()
val luckyItemsList:List = _luckyItemsList
+ private val _letterCardList = MutableLiveData>()
+ val letterCardList: LiveData> = _letterCardList
fun initLuckyItemList(context: Context) {
val luckyItem: LuckyItem = LuckyItem()
luckyItem.secondaryText = "100"
@@ -27,9 +35,8 @@ class WheelViewModel: ViewModel() {
_luckyItemsList.add(luckyItem3)
val luckyItem4: LuckyItem = LuckyItem()
- luckyItem4.topText = "EXTRA TURN"
- luckyItem4.icon = R.drawable.ic_man
- luckyItem4.color = ContextCompat.getColor(context, R.color.purple_500)
+ luckyItem4.secondaryText = "1000"
+ luckyItem4.color = ContextCompat.getColor(context, R.color.orange)
_luckyItemsList.add(luckyItem4)
val luckyItem5: LuckyItem = LuckyItem()
@@ -84,4 +91,40 @@ class WheelViewModel: ViewModel() {
_luckyItemsList[index].topText
}
}
+
+ fun updateStatusGameModel(gameStatus: GameStatus) {
+ val gameModel: GameModel? = GameData.gameModel.value
+ gameModel?.let {
+ gameModel.gameStatus = gameStatus
+ }
+ }
+
+ private fun changeTurn() {
+ val gameModel: GameModel? = GameData.gameModel.value
+ var indexNewPlayer = -1
+ gameModel?.let {
+ for (i in gameModel.playersList.indices) {
+ if (gameModel.playersList[i].name == gameModel.currentPlayer.name) {
+ indexNewPlayer = (i + 1) % gameModel.playersList.size
+ }
+ }
+ gameModel.currentPlayer = gameModel.playersList[indexNewPlayer]
+ }
+ }
+
+ fun updateCurrentSpinValue(spinValue: String) {
+ val gameModel: GameModel? = GameData.gameModel.value
+ gameModel?.let {
+ gameModel.currentSpinValue = spinValue
+ if (spinValue.isDigitsOnly() || spinValue == "ITEM") {
+ updateStatusGameModel(GameStatus.GUESS)
+ }
+ else if (spinValue == "MISS TURN"){
+ updateStatusGameModel(GameStatus.INPROGRESS)
+ changeTurn()
+ }
+ GameData.saveGameModel(gameModel)
+ }
+
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_add.png b/app/src/main/res/drawable/ic_add.png
new file mode 100644
index 0000000..472da26
Binary files /dev/null and b/app/src/main/res/drawable/ic_add.png differ
diff --git a/app/src/main/res/layout/activity_add_question.xml b/app/src/main/res/layout/activity_add_question.xml
new file mode 100644
index 0000000..39dfee9
--- /dev/null
+++ b/app/src/main/res/layout/activity_add_question.xml
@@ -0,0 +1,357 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_home_admin.xml b/app/src/main/res/layout/activity_home_admin.xml
new file mode 100644
index 0000000..ba50462
--- /dev/null
+++ b/app/src/main/res/layout/activity_home_admin.xml
@@ -0,0 +1,80 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml
new file mode 100644
index 0000000..216d91f
--- /dev/null
+++ b/app/src/main/res/layout/activity_login.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 85e4b3b..6913fe3 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -81,6 +81,7 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_taoPhong" />
+
+ tools:context=".ui.playingRoom.PlayingRoomActivity">
@@ -123,7 +123,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
- android:text="10" />
+ android:text="0" />
@@ -178,7 +178,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
- android:text="10" />
+ android:text="0" />
@@ -186,8 +186,10 @@
-
+
+ app:layout_constraintTop_toBottomOf="@+id/btn_giai">
+ app:lkwTopTextSize="12sp" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_wheel.xml b/app/src/main/res/layout/activity_wheel.xml
index 77346c7..b1fc980 100644
--- a/app/src/main/res/layout/activity_wheel.xml
+++ b/app/src/main/res/layout/activity_wheel.xml
@@ -4,8 +4,8 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
- android:background="@color/background"
android:layout_height="match_parent"
+ android:background="@color/background"
tools:context=".ui.wheel.WheelActivity">
+ app:layout_constraintTop_toBottomOf="@+id/tv_conLaiXGiay">
+ app:lkwTopTextSize="12sp" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/view_letter_card.xml b/app/src/main/res/layout/view_letter_card.xml
new file mode 100644
index 0000000..70515af
--- /dev/null
+++ b/app/src/main/res/layout/view_letter_card.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
index 6ce16a8..9f360c2 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -13,4 +13,6 @@
#11E132
+ #00AE1C
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0b807f7..d116ec1 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -5,6 +5,7 @@
BẮT ĐẦU
TẠO PHÒNG
TÌM PHÒNG
+ TẠO CÂU HỎI
wheel logo
Tạo phòng
@@ -25,4 +26,14 @@
Đến lượt của bạn
Còn lại %s s
Nhập lời giải
+
+ Thoát
+ Chơi tiếp
+ Đăng nhập
+
+ Tài khoản
+ Mật khẩu
+ TẠO NFT
+
+
\ No newline at end of file