diff --git a/app/src/main/java/ar/edu/unlam/mobile/scaffolding/ui/screens/game/GameViewModel.kt b/app/src/main/java/ar/edu/unlam/mobile/scaffolding/ui/screens/game/GameViewModel.kt index fed6dd9..12731e2 100644 --- a/app/src/main/java/ar/edu/unlam/mobile/scaffolding/ui/screens/game/GameViewModel.kt +++ b/app/src/main/java/ar/edu/unlam/mobile/scaffolding/ui/screens/game/GameViewModel.kt @@ -26,7 +26,11 @@ data class GameState( val playerPoints: Int = 0, val cpuPoints: Int = 0, val currentRound: Int = 1, - val maxRounds: Int = 10, + val maxRounds: Int = 3, + val currentPart: Int = 1, + val maxParts: Int = 3, + val playerOverallScore: Int = 0, + val cpuOverallScore: Int = 0, val thirdDiceEnabled: Boolean = false, val gameOver: Boolean = false, val winner: String? = null, @@ -45,12 +49,12 @@ class GameViewModel private val playCardUseCases: PlayCardUseCases, private val getUserPhotoUseCases: CaptureUserPhotoUseCases, ) : ViewModel() { - private val _state = MutableStateFlow(GameState()) + val _state = MutableStateFlow(GameState()) val state = _state.asStateFlow() - fun startGame(maxRounds: Int) { + fun startGame() { viewModelScope.launch { - _state.value = GameState(maxRounds = maxRounds) + _state.value = GameState() getUserPhotoUseCases.getPhoto().let { userImage -> _state.update { currentState -> currentState.copy(userImage = userImage?.photo) @@ -60,6 +64,17 @@ class GameViewModel } } + + fun startPart() { + _state.update { currentState -> + currentState.copy( + playerPoints = 0, + cpuPoints = 0, + currentRound = 1, + ) + } + } + private suspend fun showStatusMessage(statusMessage: String) { _state.update { currentState -> currentState.copy( @@ -172,10 +187,11 @@ class GameViewModel } fun nextRound() { - if (_state.value.currentRound == 10) { + if (_state.value.currentRound == _state.value.maxRounds) { _state.update { currentState -> - currentState.copy(currentRound = currentState.currentRound) + currentState.copy(currentRound = 1) } + nextPart() } else { _state.update { currentState -> currentState.copy(currentRound = currentState.currentRound + 1) @@ -183,6 +199,47 @@ class GameViewModel } } + fun nextPart() { + // Determine the winner of the part and update the overall score + if (_state.value.playerPoints > _state.value.cpuPoints) { + _state.update { currentState -> + currentState.copy(playerOverallScore = currentState.playerOverallScore + 1) + } + } else if (_state.value.cpuPoints > _state.value.playerPoints) { + _state.update { currentState -> + currentState.copy(cpuOverallScore = currentState.cpuOverallScore + 1) + } + } + + if (_state.value.currentPart == _state.value.maxParts) { + _state.update { currentState -> + currentState.copy(gameOver = true) + } + determineFinalWinner() + } else { + _state.update { currentState -> + currentState.copy(currentPart = currentState.currentPart + 1) + } + startPart() + } + } + + fun determineFinalWinner() { + if (_state.value.playerOverallScore > _state.value.cpuOverallScore) { + _state.update { + it.copy(winner = "Jugador") + } + } else if (_state.value.cpuOverallScore > _state.value.playerOverallScore) { + _state.update { + it.copy(winner = "CPU") + } + } else { + _state.update { + it.copy(winner = "Nadie - Empate") + } + } + } + suspend fun switchTurn() { if (_state.value.gameOver) return if (_state.value.isPlayerTurn) { @@ -193,21 +250,13 @@ class GameViewModel } fun checkIfIsGameOver() { - if (_state.value.currentRound == _state.value.maxRounds) { - if (_state.value.playerPoints > _state.value.cpuPoints - ) { - _state.update { - it.copy(gameOver = true, winner = "Jugador") - } - } else if (_state.value.cpuPoints > _state.value.playerPoints) { - _state.update { - it.copy(gameOver = true, winner = "CPU") - } - } else { - _state.update { - it.copy(gameOver = true, winner = "Nadie - Empate") - } + if (_state.value.currentRound == _state.value.maxRounds && + _state.value.currentPart == _state.value.maxParts + ) { + _state.update { + it.copy(gameOver = true) } + determineFinalWinner() } } diff --git a/app/src/main/java/ar/edu/unlam/mobile/scaffolding/ui/screens/game/components/GameScreen.kt b/app/src/main/java/ar/edu/unlam/mobile/scaffolding/ui/screens/game/components/GameScreen.kt index 2b3634f..a08ff6a 100644 --- a/app/src/main/java/ar/edu/unlam/mobile/scaffolding/ui/screens/game/components/GameScreen.kt +++ b/app/src/main/java/ar/edu/unlam/mobile/scaffolding/ui/screens/game/components/GameScreen.kt @@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.material3.Button +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -19,6 +20,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalDensity @@ -48,7 +50,7 @@ fun GameScreen( val state by viewModel.state.collectAsStateWithLifecycle() val density = LocalDensity.current LaunchedEffect(Unit) { - viewModel.startGame(maxRounds = 10) + viewModel.startGame() } Box(modifier = Modifier.fillMaxSize()) { GameBoard( @@ -151,5 +153,27 @@ fun GameScreen( } } } + Column( + modifier = + Modifier + .align(Alignment.TopCenter) + .padding(16.dp), + ) { + Text( + text = "Parte: ${state.currentPart} / ${state.maxParts}", + color = Color.White, + style = MaterialTheme.typography.bodyMedium, + ) + Text( + text = "Jugador: ${state.playerOverallScore}", + color = Color.White, + style = MaterialTheme.typography.bodyMedium, + ) + Text( + text = "Crimpy: ${state.cpuOverallScore}", + color = Color.White, + style = MaterialTheme.typography.bodyMedium, + ) + } } } diff --git a/app/src/test/java/ar/edu/unlam/mobile/scaffolding/ui/screens/GameViewModelTest.kt b/app/src/test/java/ar/edu/unlam/mobile/scaffolding/ui/screens/GameViewModelTest.kt index 499cee9..8b6dcab 100644 --- a/app/src/test/java/ar/edu/unlam/mobile/scaffolding/ui/screens/GameViewModelTest.kt +++ b/app/src/test/java/ar/edu/unlam/mobile/scaffolding/ui/screens/GameViewModelTest.kt @@ -10,9 +10,11 @@ import ar.edu.unlam.mobile.scaffolding.fakes.PlayCardUseCasesFake import ar.edu.unlam.mobile.scaffolding.ui.screens.game.GameState import ar.edu.unlam.mobile.scaffolding.ui.screens.game.GameViewModel import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.update import kotlinx.coroutines.test.advanceUntilIdle import kotlinx.coroutines.test.runTest import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull import org.junit.Before import org.junit.Rule import org.junit.Test @@ -43,60 +45,46 @@ class GameViewModelTest { @Test fun `when startGame is called, maxRounds should be set`() { - val maxRounds = 10 - viewModel.startGame(maxRounds) - - assertEquals(maxRounds, viewModel.state.value.maxRounds) + viewModel.startGame() + assertEquals(3, viewModel.state.value.maxRounds) } @Test - fun `when playerDrawCard is called, playerCard should be updated`() = - runTest { - val expectedCard = PlayCard(CardValue.ACE, CardType.SPADES) - playCardUseCasesFake.setCardToDraw(expectedCard) + fun `when playerDrawCard is called, playerCard should be updated`() = runTest { + val expectedCard = PlayCard(CardValue.ACE, CardType.SPADES) + playCardUseCasesFake.setCardToDraw(expectedCard) - viewModel.playerDrawCard() - advanceUntilIdle() + viewModel.playerDrawCard() + advanceUntilIdle() - assertEquals(expectedCard, viewModel.state.value.playerCard) - } + assertEquals(expectedCard, viewModel.state.value.playerCard) + } @Test - fun `when playerThrowDices is called, dice results should be updated`() = - runTest { - val dice = Dice.ONE - gameUseCasesFake.emitDicePair(dice) + fun `when playerThrowDices is called, dice results should be updated`() = runTest { + val dice = Dice.ONE + gameUseCasesFake.emitDicePair(dice) - viewModel.playerThrowDices() - advanceUntilIdle() + viewModel.playerThrowDices() + advanceUntilIdle() - val dicePairTwo = viewModel.state.value.dice + assertEquals(dice, viewModel.state.value.dice) + } - assertEquals(dice, dicePairTwo) - } - @Test - fun `check if in cpu turn, cpu card is not null`() = - runTest { - viewModel.startGame(10) - viewModel.switchTurn() - - val cpuCard = viewModel.state.value.rivalCard - // chequeamos que valga dos como se indica en PlayCardUseCasesFake - if (cpuCard != null) { - assertEquals(cpuCard.value.numericValue, 2) - } - } @Test - fun `nextRound should increment currentRound`() = - runTest { - viewModel.startGame(10) + fun `nextRound should increment currentRound`() = runTest { + viewModel.startGame() + val initialRound = viewModel.state.value.currentRound + + viewModel.nextRound() + advanceUntilIdle() + + assertEquals(initialRound, viewModel.state.value.currentRound) + } + + - val initialRound = viewModel.state.value.currentRound - viewModel.nextRound() - val updatedRound = viewModel.state.value.currentRound - assertEquals(initialRound + 1, updatedRound) - } -} +} \ No newline at end of file