diff --git a/.idea/compiler.xml b/.idea/compiler.xml
new file mode 100644
index 0000000..b589d56
--- /dev/null
+++ b/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
new file mode 100644
index 0000000..7ce6325
--- /dev/null
+++ b/.idea/deploymentTargetDropDown.xml
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index 89935b5..0897082 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -1,10 +1,17 @@
+
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
new file mode 100644
index 0000000..fdf8d99
--- /dev/null
+++ b/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index c2b3ddc..8978d23 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,7 +1,6 @@
-
-
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 03b0703..882371f 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -3,7 +3,6 @@ plugins {
alias(libs.plugins.jetbrainsKotlinAndroid)
id("com.google.gms.google-services")
}
-
android {
namespace = "com.example.chiecnonkydieu"
compileSdk = 34
@@ -34,6 +33,10 @@ android {
kotlinOptions {
jvmTarget = "1.8"
}
+
+ buildFeatures {
+ viewBinding = true
+ }
}
dependencies {
@@ -47,4 +50,11 @@ dependencies {
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
+
+ //coroutine
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0")
+
+ //wheel
+ implementation("androidx.navigation:navigation-dynamic-features-fragment:2.7.7")
+ implementation ("com.github.thanhniencung:LuckyWheel:a6110f5128")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 53c2086..270e0e3 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,6 +12,22 @@
android:supportsRtl="true"
android:theme="@style/Theme.ChiecNonKyDieu"
tools:targetApi="31">
+
+
+
+
+
@@ -21,6 +37,10 @@
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/MainActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/MainActivity.kt
index 7488fa7..3dabaea 100644
--- a/app/src/main/java/com/example/chiecnonkydieu/MainActivity.kt
+++ b/app/src/main/java/com/example/chiecnonkydieu/MainActivity.kt
@@ -1,29 +1,60 @@
package com.example.chiecnonkydieu
+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.google.firebase.Firebase
-import com.google.firebase.database.database
+import com.example.chiecnonkydieu.databinding.ActivityMainBinding
+import com.example.chiecnonkydieu.ui.CreateRoomActivity
+import com.example.chiecnonkydieu.ui.PlayingRoomActivity
+import com.example.chiecnonkydieu.ui.SearchRoomActivity
+import com.example.chiecnonkydieu.ui.wheel.WheelActivity
class MainActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
- setContentView(R.layout.activity_main)
+ binding = ActivityMainBinding.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
}
- // Write a message to the database
- val database = Firebase.database
- val myRef = database.getReference("message")
+// // Write a message to the database
+// val database = Firebase.database
+// val myRef = database.getReference("message")
+//
+// myRef.setValue("Hello, World!")
+//
+// val intent = Intent(this, WaitingRoomActivity::class.java)
+// startActivity(intent)
+ binding.btnBatDau.setOnClickListener {
+// goToPlayingRoom()
+ val intent = Intent(this, WheelActivity::class.java)
+ startActivity(intent)
+ }
- myRef.setValue("Hello, World!")
+ binding.btnTaoPhong.setOnClickListener {
+ val intent = Intent(this, CreateRoomActivity::class.java)
+ startActivity(intent)
+ }
+ binding.btnTimPhong.setOnClickListener {
+ val intent = Intent(this, SearchRoomActivity::class.java)
+ startActivity(intent)
+ }
+
+ }
+ private fun goToPlayingRoom() {
+ // TODO Set cung
+ val intent = Intent(this, PlayingRoomActivity::class.java)
+ intent.putExtra("room_id", "7232")
+ startActivity(intent)
}
}
\ 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
new file mode 100644
index 0000000..59545de
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/data/DataSource.kt
@@ -0,0 +1,5 @@
+package com.example.chiecnonkydieu.data
+
+import rubikstudio.library.model.LuckyItem
+
+
diff --git a/app/src/main/java/com/example/chiecnonkydieu/data/GameData.kt b/app/src/main/java/com/example/chiecnonkydieu/data/GameData.kt
new file mode 100644
index 0000000..4374aa6
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/data/GameData.kt
@@ -0,0 +1,93 @@
+package com.example.chiecnonkydieu.data
+
+import android.content.Context
+import android.util.Log
+import android.widget.Toast
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.google.firebase.Firebase
+import com.google.firebase.database.DataSnapshot
+import com.google.firebase.database.DatabaseError
+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()
+ val gameModel: LiveData = _gameModel
+
+ const val REFERENCE_ROOM = "rooms"
+ private lateinit var appContext: Context
+
+
+ val database: DatabaseReference = Firebase.database.reference
+
+ fun initialize(context: Context) {
+
+ appContext = context.applicationContext
+ }
+ fun saveGameModel(model: GameModel) {
+ _gameModel.postValue(model)
+ database.child(REFERENCE_ROOM).child(model.gameId.toString()).setValue(model)
+ }
+
+ suspend fun joinOnlineGame(player: Player, gameId: Int): Boolean {
+ val deferred = CompletableDeferred()
+
+ database.child(REFERENCE_ROOM).child(gameId.toString())
+ .get()
+ .addOnSuccessListener { snapshot ->
+ val gameModel: GameModel? = snapshot.getValue(GameModel::class.java)
+ if (gameModel != null) {
+ when (gameModel.playersList.size) {
+ 1 -> {
+ gameModel.playersList.add(player)
+ gameModel.gameStatus = GameStatus.JOINED1
+ saveGameModel(gameModel)
+ Toast.makeText(appContext, "Successfully joined1 game", Toast.LENGTH_LONG).show()
+ deferred.complete(true)
+ }
+ 2 -> {
+ gameModel.playersList.add(player)
+ gameModel.gameStatus = GameStatus.JOINED2
+ saveGameModel(gameModel)
+ Toast.makeText(appContext, "Successfully joined2 game", Toast.LENGTH_LONG).show()
+ deferred.complete(true)
+ }
+ else -> {
+ Toast.makeText(appContext, "Game is full (3 players)", Toast.LENGTH_LONG).show()
+ deferred.complete(false)
+ }
+ }
+ } else {
+ Toast.makeText(appContext, "Cannot find room with id $gameId", Toast.LENGTH_LONG).show()
+ deferred.complete(false)
+ }
+ }
+ .addOnFailureListener { exception ->
+ Toast.makeText(appContext, "Error: $exception", Toast.LENGTH_LONG).show()
+ deferred.complete(false)
+ }
+
+ return deferred.await()
+ }
+
+ suspend fun fetchGameModel(gameId: Int) {
+ database.child(REFERENCE_ROOM).child(gameId.toString())
+ .addValueEventListener(object : ValueEventListener {
+ override fun onDataChange(snapshot: DataSnapshot) {
+ val gameModel: GameModel? = snapshot.getValue(GameModel::class.java)
+ if (gameModel != null) {
+ saveGameModel(gameModel)
+ }
+ }
+
+ override fun onCancelled(error: DatabaseError) {
+ // Handle error
+ Log.e("fetchGameModel", "Error fetching game model: ${error.message}")
+ }
+ })
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/data/GameModel.kt b/app/src/main/java/com/example/chiecnonkydieu/data/GameModel.kt
new file mode 100644
index 0000000..52200b7
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/data/GameModel.kt
@@ -0,0 +1,23 @@
+package com.example.chiecnonkydieu.data
+
+import android.health.connect.datatypes.units.Length
+
+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 "
+
+)
+
+enum class GameStatus {
+ CREATED,
+ JOINED1,
+ JOINED2,
+ INPROGRESS,
+ FINISHED
+}
diff --git a/app/src/main/java/com/example/chiecnonkydieu/data/Player.kt b/app/src/main/java/com/example/chiecnonkydieu/data/Player.kt
new file mode 100644
index 0000000..0565137
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/data/Player.kt
@@ -0,0 +1,7 @@
+package com.example.chiecnonkydieu.data
+
+data class Player(
+ val name: String = "Player",
+ val gender: Boolean = true,
+ val score: Int = 0
+)
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/CreateRoomActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/CreateRoomActivity.kt
new file mode 100644
index 0000000..d914deb
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/CreateRoomActivity.kt
@@ -0,0 +1,70 @@
+package com.example.chiecnonkydieu.ui
+
+import android.content.Intent
+import android.os.Bundle
+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.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.databinding.ActivityCreateRoomBinding
+import kotlinx.coroutines.launch
+import kotlin.random.Random
+
+class CreateRoomActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityCreateRoomBinding
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivityCreateRoomBinding.inflate(layoutInflater)
+ val view = binding.root
+ setContentView(view)
+
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.create_room_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)
+
+
+ binding.tvMaPhong.text = (1000 .. 9999).random().toString()
+ binding.btnCreateRoom.setOnClickListener {
+ lifecycleScope.launch {
+ GameData.initialize(applicationContext)
+ val gameModel: GameModel = GameModel(
+ gameStatus = GameStatus.CREATED,
+ gameId = binding.tvMaPhong.text.toString().toInt(),
+ currentQuestion = "Thủ đô của Việt Nam nằm ở đâu?"
+ )
+ gameModel.playersList.add(Player(binding.edtName.text.toString()))
+ GameData.saveGameModel(
+ gameModel
+ )
+ }
+ goToWaitingRooom()
+ }
+ }
+
+ override fun onSupportNavigateUp(): Boolean {
+ onBackPressed()
+ return true
+ }
+
+ fun goToWaitingRooom() {
+ val intent = Intent(this, WaitingRoomActivity::class.java)
+ intent.putExtra("room_id", binding.tvMaPhong.text.toString())
+ startActivity(intent)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/PlayingRoomActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/PlayingRoomActivity.kt
new file mode 100644
index 0000000..876f2fc
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/PlayingRoomActivity.kt
@@ -0,0 +1,186 @@
+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
new file mode 100644
index 0000000..023a84a
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/SearchRoomActivity.kt
@@ -0,0 +1,76 @@
+package com.example.chiecnonkydieu.ui
+
+import android.content.Intent
+import android.os.Bundle
+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.lifecycle.lifecycleScope
+import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.data.GameData
+import com.example.chiecnonkydieu.data.Player
+import com.example.chiecnonkydieu.databinding.ActivitySearchRoomBinding
+import kotlinx.coroutines.async
+import kotlinx.coroutines.coroutineScope
+import kotlinx.coroutines.launch
+
+class SearchRoomActivity : AppCompatActivity() {
+ private lateinit var binding: ActivitySearchRoomBinding
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivitySearchRoomBinding.inflate(layoutInflater)
+ val view = binding.root
+ setContentView(view)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.search_room_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)
+
+ binding.btnSearchRoom.setOnClickListener {
+ lifecycleScope.launch {
+ val isJoined = lifecycleScope.async {
+ GameData.initialize(applicationContext)
+ GameData.joinOnlineGame(
+ player = Player(name = binding.edtName.text.toString()),
+ gameId = binding.edtMaPhong.text.toString().toInt()
+ )
+ }.await()
+
+ if (isJoined) {
+ goToWaitingRooom()
+ } else {
+ Toast.makeText(applicationContext, "Error when connect game", Toast.LENGTH_LONG).show()
+ }
+ }
+
+ }
+ }
+
+ fun goToWaitingRooom() {
+ try {
+ val intent = Intent(this, WaitingRoomActivity::class.java)
+ intent.putExtra("room_id", binding.edtMaPhong.text.toString())
+ startActivity(intent)
+ }
+ catch (exception: Exception) {
+ Toast.makeText(this, binding.edtMaPhong.text, Toast.LENGTH_LONG).show()
+ }
+ }
+
+ override fun onSupportNavigateUp(): Boolean {
+ onBackPressed()
+ return true
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/WaitingRoomActivity.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/WaitingRoomActivity.kt
new file mode 100644
index 0000000..b79b049
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/WaitingRoomActivity.kt
@@ -0,0 +1,158 @@
+package com.example.chiecnonkydieu.ui
+
+import android.content.Intent
+import android.graphics.Color
+import android.os.Bundle
+import androidx.activity.enableEdgeToEdge
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.Toolbar
+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.GameData.gameModel
+import com.example.chiecnonkydieu.data.GameModel
+import com.example.chiecnonkydieu.data.GameStatus
+import com.example.chiecnonkydieu.data.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 kotlinx.coroutines.launch
+
+class WaitingRoomActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityWaitingRoomBinding
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivityWaitingRoomBinding.inflate(layoutInflater)
+ val view = binding.root
+ setContentView(view)
+ ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.waiting_room_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)
+
+
+ binding.tvMaPhong.text = intent.getStringExtra("room_id")
+// fetch data from firebase
+ 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) {
+ goToPlayingRoom()
+ finish()
+ }
+ })
+
+ binding.btnStartGame.setOnClickListener {
+ val gameModel: GameModel? = GameData.gameModel.value
+ if (gameModel != null) {
+ gameModel.gameStatus = GameStatus.INPROGRESS
+ GameData.saveGameModel(
+ gameModel
+ )
+ }
+ goToPlayingRoom()
+ }
+
+
+
+
+ }
+
+ // Tu dong lang nghe su thay doi tu database trong vong doi cua activity
+// override fun onStart() {
+// super.onStart()
+//
+// GameData.database.addValueEventListener(object :
+// ValueEventListener {
+// override fun onDataChange(snapshot: DataSnapshot) {
+// val gameModel: GameModel? = snapshot.getValue(GameModel::class.java)
+// if (gameModel != null) {
+// GameData.saveGameModel(gameModel)
+// }
+// }
+//
+// override fun onCancelled(error: DatabaseError) {
+// //
+// }
+// })
+// }
+
+ private fun updateUi(gameModel: GameModel?) {
+ if (gameModel != null) {
+ 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
+ }
+ 2 -> {
+ // player1 and player 2
+ val colorResId = R.color.orange
+ val backgroundColor = ContextCompat.getColor(this, colorResId)
+ binding.cvPlayer1.setCardBackgroundColor(backgroundColor)
+ binding.cvPlayer2.setCardBackgroundColor(backgroundColor)
+ 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
+
+ }
+
+ 3 -> {
+ // 3 player
+ val colorResId = R.color.orange
+ val backgroundColor = ContextCompat.getColor(this, colorResId)
+ binding.cvPlayer1.setCardBackgroundColor(backgroundColor)
+ binding.cvPlayer2.setCardBackgroundColor(backgroundColor)
+ binding.cvPlayer3.setCardBackgroundColor(backgroundColor)
+ 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
+ }
+ }
+
+ }
+
+ }
+
+ override fun onSupportNavigateUp(): Boolean {
+ onBackPressed()
+ return true
+ }
+
+ private fun goToPlayingRoom() {
+ val intent = Intent(this, PlayingRoomActivity::class.java).apply {
+ putExtra("room_id", binding.tvMaPhong.text.toString())
+ flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
+ }
+ startActivity(intent)
+ }
+}
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
new file mode 100644
index 0000000..25df369
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelActivity.kt
@@ -0,0 +1,93 @@
+package com.example.chiecnonkydieu.ui.wheel
+
+import android.content.Intent
+import android.os.Build
+import android.os.Bundle
+import android.os.CountDownTimer
+import android.widget.Toast
+import androidx.activity.enableEdgeToEdge
+import androidx.activity.viewModels
+import androidx.annotation.RequiresApi
+import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.widget.Toolbar
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.get
+import com.example.chiecnonkydieu.R
+import com.example.chiecnonkydieu.databinding.ActivityWheelBinding
+import rubikstudio.library.LuckyWheelView
+import rubikstudio.library.model.LuckyItem
+
+class WheelActivity : AppCompatActivity() {
+ private lateinit var binding: ActivityWheelBinding
+ private lateinit var countDownTimer: CountDownTimer
+
+ @RequiresApi(Build.VERSION_CODES.O)
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableEdgeToEdge()
+ binding = ActivityWheelBinding.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)
+
+ val wheelViewModel: WheelViewModel by viewModels()
+ val luckyWheelView: LuckyWheelView = binding.luckyWheel
+
+ wheelViewModel.initLuckyItemList(this)
+ luckyWheelView.setData(wheelViewModel.luckyItemsList)
+
+ luckyWheelView.isTouchEnabled = false
+ luckyWheelView.setOnTouchListener { v, event ->
+ val indexAns = wheelViewModel.getIndexAfterRotate()
+ luckyWheelView.setRound(3)
+ luckyWheelView.startLuckyWheelWithTargetIndex(indexAns)
+ Toast.makeText(this, wheelViewModel.getStringItemAtIndex(indexAns), Toast.LENGTH_LONG).show()
+ return@setOnTouchListener true
+ }
+
+
+ binding.btnQuay.setOnClickListener {
+ 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()
+ }
+
+ // count down timer
+ countDownTimer = object : CountDownTimer(7000, 1000) {
+ override fun onTick(millisUntilFinished: Long) {
+ val secondsLeft = millisUntilFinished / 1000
+ binding.tvConLaiXGiay.text = String.format(getString(R.string.con_lai_x_giay), secondsLeft.toString())
+ }
+
+ override fun onFinish() {
+ binding.tvConLaiXGiay.text = String.format(getString(R.string.con_lai_x_giay), 0)
+ binding.btnQuay.performClick()
+
+ }
+ }
+
+ countDownTimer.start()
+
+ }
+ override fun onSupportNavigateUp(): Boolean {
+ onBackPressed()
+ return true
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ countDownTimer.cancel()
+ }
+}
\ No newline at end of file
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
new file mode 100644
index 0000000..3153000
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/wheel/WheelViewModel.kt
@@ -0,0 +1,87 @@
+package com.example.chiecnonkydieu.ui.wheel
+
+import android.content.Context
+import android.graphics.Color
+import androidx.core.content.ContextCompat
+import androidx.lifecycle.ViewModel
+import com.example.chiecnonkydieu.R
+import rubikstudio.library.model.LuckyItem
+class WheelViewModel: ViewModel() {
+ private val _luckyItemsList: MutableList = mutableListOf()
+ val luckyItemsList:List = _luckyItemsList
+
+ fun initLuckyItemList(context: Context) {
+ val luckyItem: LuckyItem = LuckyItem()
+ luckyItem.secondaryText = "100"
+ luckyItem.color = ContextCompat.getColor(context, R.color.purple_300)
+ _luckyItemsList.add(luckyItem)
+
+ val luckyItem2: LuckyItem = LuckyItem()
+ luckyItem2.secondaryText = "400"
+ luckyItem2.color = ContextCompat.getColor(context, R.color.green)
+ _luckyItemsList.add(luckyItem2)
+
+ val luckyItem3: LuckyItem = LuckyItem()
+ luckyItem3.secondaryText = "800"
+ luckyItem3.color = ContextCompat.getColor(context, R.color.blue_200)
+ _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)
+ _luckyItemsList.add(luckyItem4)
+
+ val luckyItem5: LuckyItem = LuckyItem()
+ luckyItem5.secondaryText = "1200"
+ luckyItem5.color = ContextCompat.getColor(context, R.color.gray)
+ _luckyItemsList.add(luckyItem5)
+
+ val luckyItem6: LuckyItem = LuckyItem()
+ luckyItem6.secondaryText = "600"
+ luckyItem6.color = ContextCompat.getColor(context, R.color.blue_200)
+
+ _luckyItemsList.add(luckyItem6)
+
+ val luckyItem7: LuckyItem = LuckyItem()
+ luckyItem7.topText = "MISS TURN"
+ luckyItem7.icon = R.drawable.ic_man
+ luckyItem7.color = ContextCompat.getColor(context, R.color.purple_500)
+ _luckyItemsList.add(luckyItem7)
+
+ val luckyItem8: LuckyItem = LuckyItem()
+ luckyItem8.secondaryText = "800"
+ luckyItem8.color = ContextCompat.getColor(context, R.color.green)
+ _luckyItemsList.add(luckyItem8)
+
+ val luckyItem9: LuckyItem = LuckyItem()
+ luckyItem9.secondaryText = "1500"
+ luckyItem9.color = ContextCompat.getColor(context, R.color.purple_300)
+ _luckyItemsList.add(luckyItem9)
+
+ val luckyItem10: LuckyItem = LuckyItem()
+ luckyItem10.secondaryText = "400"
+ luckyItem10.color = ContextCompat.getColor(context, R.color.green)
+ _luckyItemsList.add(luckyItem10)
+
+ val luckyItem11: LuckyItem = LuckyItem()
+ luckyItem11.topText = "ITEM"
+ luckyItem11.icon = R.drawable.ic_wheel
+ luckyItem11.color = ContextCompat.getColor(context, R.color.orange)
+ _luckyItemsList.add(luckyItem11)
+ }
+
+ fun getIndexAfterRotate(): Int {
+ // TODO
+ val size = _luckyItemsList.size - 1
+ return (0 .. size).random()
+ }
+ fun getStringItemAtIndex(index: Int): String {
+ return if (!_luckyItemsList[index].secondaryText.isNullOrEmpty()) {
+ _luckyItemsList[index].secondaryText
+ }
+ else {
+ _luckyItemsList[index].topText
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/chiecnonkydieu/ui/wheelSpinnerViewModel/WheelSpinnerViewModel.kt b/app/src/main/java/com/example/chiecnonkydieu/ui/wheelSpinnerViewModel/WheelSpinnerViewModel.kt
new file mode 100644
index 0000000..d584f86
--- /dev/null
+++ b/app/src/main/java/com/example/chiecnonkydieu/ui/wheelSpinnerViewModel/WheelSpinnerViewModel.kt
@@ -0,0 +1,46 @@
+package com.example.chiecnonkydieu.ui.wheelSpinnerViewModel
+
+import com.example.chiecnonkydieu.R
+
+import android.content.Context
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import rubikstudio.library.LuckyWheelView
+import rubikstudio.library.model.LuckyItem
+import java.util.*
+
+class WheelSpinnerViewModel ( itemList: List, context: Context ): ViewModel() {
+ private val luckyItemList = MutableLiveData>()
+ val liveLuckyItemList: LiveData>
+ get() = luckyItemList
+ private val spinIndex = MutableLiveData()
+ val liveSpinIndex : LiveData
+ get() = spinIndex
+ private val colors = arrayOf(R.color.orange, R.color.black)
+
+ init {
+ val listItems = mutableListOf()
+
+ for (i in itemList.indices) run {
+ val luckyItem = LuckyItem()
+ luckyItem.secondaryText = itemList[i]
+ luckyItem.topText = ( i + 1 ).toString()
+ luckyItem.color = context.getColor( this.colors[if (i % 2 == 0) 0 else 1] )
+ listItems.add(luckyItem)
+ }
+
+ this.luckyItemList.value = listItems
+ }
+
+ fun spinWheel() {
+ val rand = Random()
+ spinIndex.value = rand.nextInt(this.luckyItemList.value!!.size - 1) + 0
+ }
+
+ fun doneSpinning(){
+ spinIndex.value = -1
+ }
+
+}
+
diff --git a/app/src/main/res/drawable/ic_arrow_back.xml b/app/src/main/res/drawable/ic_arrow_back.xml
new file mode 100644
index 0000000..99f85de
--- /dev/null
+++ b/app/src/main/res/drawable/ic_arrow_back.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_center_wheel.png b/app/src/main/res/drawable/ic_center_wheel.png
new file mode 100644
index 0000000..5063bfc
Binary files /dev/null and b/app/src/main/res/drawable/ic_center_wheel.png differ
diff --git a/app/src/main/res/drawable/ic_cursor.png b/app/src/main/res/drawable/ic_cursor.png
new file mode 100644
index 0000000..c275eb4
Binary files /dev/null and b/app/src/main/res/drawable/ic_cursor.png differ
diff --git a/app/src/main/res/drawable/ic_hint.png b/app/src/main/res/drawable/ic_hint.png
new file mode 100644
index 0000000..f04f2e6
Binary files /dev/null and b/app/src/main/res/drawable/ic_hint.png differ
diff --git a/app/src/main/res/drawable/ic_loading.png b/app/src/main/res/drawable/ic_loading.png
new file mode 100644
index 0000000..a230e78
Binary files /dev/null and b/app/src/main/res/drawable/ic_loading.png differ
diff --git a/app/src/main/res/drawable/ic_man.png b/app/src/main/res/drawable/ic_man.png
new file mode 100644
index 0000000..1c927a4
Binary files /dev/null and b/app/src/main/res/drawable/ic_man.png differ
diff --git a/app/src/main/res/drawable/ic_roulette.png b/app/src/main/res/drawable/ic_roulette.png
new file mode 100644
index 0000000..a249e61
Binary files /dev/null and b/app/src/main/res/drawable/ic_roulette.png differ
diff --git a/app/src/main/res/drawable/ic_wheel.png b/app/src/main/res/drawable/ic_wheel.png
new file mode 100644
index 0000000..d61a8dc
Binary files /dev/null and b/app/src/main/res/drawable/ic_wheel.png differ
diff --git a/app/src/main/res/drawable/ic_woman.png b/app/src/main/res/drawable/ic_woman.png
new file mode 100644
index 0000000..23fcf9e
Binary files /dev/null and b/app/src/main/res/drawable/ic_woman.png differ
diff --git a/app/src/main/res/drawable/orange_card.xml b/app/src/main/res/drawable/orange_card.xml
new file mode 100644
index 0000000..f326b9e
--- /dev/null
+++ b/app/src/main/res/drawable/orange_card.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/purple_gradient.xml b/app/src/main/res/drawable/purple_gradient.xml
new file mode 100644
index 0000000..01c0d84
--- /dev/null
+++ b/app/src/main/res/drawable/purple_gradient.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rounded_button.xml b/app/src/main/res/drawable/rounded_button.xml
new file mode 100644
index 0000000..9dfe968
--- /dev/null
+++ b/app/src/main/res/drawable/rounded_button.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rounded_button_secondary.xml b/app/src/main/res/drawable/rounded_button_secondary.xml
new file mode 100644
index 0000000..f326b9e
--- /dev/null
+++ b/app/src/main/res/drawable/rounded_button_secondary.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rounded_green.xml b/app/src/main/res/drawable/rounded_green.xml
new file mode 100644
index 0000000..fa65d73
--- /dev/null
+++ b/app/src/main/res/drawable/rounded_green.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/font/open_sans.xml b/app/src/main/res/font/open_sans.xml
new file mode 100644
index 0000000..f9284b2
--- /dev/null
+++ b/app/src/main/res/font/open_sans.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/app/src/main/res/font/open_sans_bold.xml b/app/src/main/res/font/open_sans_bold.xml
new file mode 100644
index 0000000..eba352b
--- /dev/null
+++ b/app/src/main/res/font/open_sans_bold.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/app/src/main/res/font/open_sans_semibold.xml b/app/src/main/res/font/open_sans_semibold.xml
new file mode 100644
index 0000000..13a062d
--- /dev/null
+++ b/app/src/main/res/font/open_sans_semibold.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/app/src/main/res/layout/activity_create_room.xml b/app/src/main/res/layout/activity_create_room.xml
new file mode 100644
index 0000000..50a71bf
--- /dev/null
+++ b/app/src/main/res/layout/activity_create_room.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 86a5d97..85e4b3b 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -5,15 +5,91 @@
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:background="@drawable/purple_gradient"
tools:context=".MainActivity">
+
+
+
+ app:layout_constraintTop_toBottomOf="@+id/tv_title" />
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_playing_room.xml b/app/src/main/res/layout/activity_playing_room.xml
new file mode 100644
index 0000000..9976548
--- /dev/null
+++ b/app/src/main/res/layout/activity_playing_room.xml
@@ -0,0 +1,333 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_search_room.xml b/app/src/main/res/layout/activity_search_room.xml
new file mode 100644
index 0000000..079482e
--- /dev/null
+++ b/app/src/main/res/layout/activity_search_room.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_waiting_room.xml b/app/src/main/res/layout/activity_waiting_room.xml
new file mode 100644
index 0000000..af56bfe
--- /dev/null
+++ b/app/src/main/res/layout/activity_waiting_room.xml
@@ -0,0 +1,172 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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
new file mode 100644
index 0000000..77346c7
--- /dev/null
+++ b/app/src/main/res/layout/activity_wheel.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dialog_edittext.xml b/app/src/main/res/layout/dialog_edittext.xml
new file mode 100644
index 0000000..15f8e9f
--- /dev/null
+++ b/app/src/main/res/layout/dialog_edittext.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
\ 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 c8524cd..6ce16a8 100644
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -2,4 +2,15 @@
#FF000000
#FFFFFFFF
+
+ #95E1D3
+ #FEC14E
+ #EAFFD0
+
+ #A35DFE
+ #D28FFF
+ #D9D9D9
+
+ #11E132
+
\ No newline at end of file
diff --git a/app/src/main/res/values/font_certs.xml b/app/src/main/res/values/font_certs.xml
new file mode 100644
index 0000000..d2226ac
--- /dev/null
+++ b/app/src/main/res/values/font_certs.xml
@@ -0,0 +1,17 @@
+
+
+
+ - @array/com_google_android_gms_fonts_certs_dev
+ - @array/com_google_android_gms_fonts_certs_prod
+
+
+ -
+ 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
+
+
+
diff --git a/app/src/main/res/values/preloaded_fonts.xml b/app/src/main/res/values/preloaded_fonts.xml
new file mode 100644
index 0000000..71de273
--- /dev/null
+++ b/app/src/main/res/values/preloaded_fonts.xml
@@ -0,0 +1,8 @@
+
+
+
+ - @font/open_sans
+ - @font/open_sans_bold
+ - @font/open_sans_semibold
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dcd5f47..0b807f7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,3 +1,28 @@
ChiecNonKyDieu
+ CHIẾC NÓN KỲ DIỆU
+
+ BẮT ĐẦU
+ TẠO PHÒNG
+ TÌM PHÒNG
+ wheel logo
+
+ Tạo phòng
+ Tìm phòng
+ Tên Người chơi
+ Mã phòng
+
+ Đợi người chơi
+ Đang đợi người chơi
+ Vòng 1
+ Thủ đô của Việt Nam ở đâu?
+ Nhập 1 ký tự
+ Đoán
+ Giải
+ Quay
+ Hint
+
+ Đến lượt của bạn
+ Còn lại %s s
+ Nhập lời giải
\ No newline at end of file
diff --git a/build.gradle.kts b/build.gradle.kts
index 2107749..7548677 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -2,6 +2,10 @@ buildscript {
dependencies {
classpath(libs.google.services)
}
+ repositories {
+ maven { url = uri("https://www.jitpack.io") }
+ }
+
}
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index c31862a..741499a 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -16,6 +16,9 @@ dependencyResolutionManagement {
repositories {
google()
mavenCentral()
+ maven {
+ setUrl("https://jitpack.io")
+ }
}
}