# Conflicts:
#	android/app/src/main/java/fr/iut/sciencequest/ViewModels/PenduViewModel.kt
#	android/app/src/main/java/fr/iut/sciencequest/view/games/Pendu.kt
RepositoryAndroid^2
Lilian BRETON 1 year ago
commit 3288aa1ee1

@ -25,7 +25,7 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
NavHost(this)
NavHost()
}
}
}

@ -0,0 +1,52 @@
package fr.iut.sciencequest.ViewModels
import android.os.Handler
import android.os.Looper
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import fr.iut.sciencequest.ViewModels.UiStates.KahootUIState
import fr.iut.sciencequest.model.buisness.Question.fetchQuestions
import fr.iut.sciencequest.stub.StubQuestionWithReponses2
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
class KahootViewModel: ViewModel() {
var uiState = MutableStateFlow(KahootUIState())
private val handler = Handler(Looper.getMainLooper())
fun lancerPartie() {
viewModelScope.launch {
fetchQuestions(2).collect() {
for (question in it.questions) {
handler.postDelayed(
{
Log.d("KahootViewModel","J'actualise les questions")
uiState.value = KahootUIState(question,
duréePartie = uiState.value.duréePartie,
nbPoints = uiState.value.nbPoints,
reponseChoisie = false)
},
uiState.value.duréePartie
)
}
}
}
}
// NOTE : tpsReponse en ms
fun ajouterPoints(tpsReponse: Long) {
Log.d("KahootViewModel","Je reçois une réponse")
if (uiState.value.reponseChoisie) {
Log.d("KahootViewModel","Le joueur a déjà répondu")
return
}
val nbPoints: Int = (10_000 - tpsReponse).toInt()
uiState.value = KahootUIState(uiState.value.question,
duréePartie = uiState.value.duréePartie,
nbPoints = uiState.value.nbPoints + nbPoints,
reponseChoisie = true)
Log.d("KahootViewModel","Le joueur à ${uiState.value.nbPoints}")
}
}

@ -0,0 +1,17 @@
package fr.iut.sciencequest.ViewModels
import androidx.lifecycle.ViewModel
import fr.iut.sciencequest.ViewModels.UiStates.LoginUIState
import kotlinx.coroutines.flow.MutableStateFlow
class LoginViewModel: ViewModel() {
var uiState = MutableStateFlow(LoginUIState())
fun setPseudo(pseudo: String) {
uiState.value = LoginUIState(pseudo, uiState.value.mdp)
}
fun setMdp(mdp: String) {
uiState.value = LoginUIState(uiState.value.pseudo, mdp)
}
}

@ -39,24 +39,25 @@ class PenduViewModel : ViewModel() {
// mot : mot à trouver
// motAct : état actuel du mot trouvé par l'utilisateur
fun PlayAction(lettre: Char) {
val lowerCaseLetter = lettre.lowercaseChar()
Log.d("PenduViewModel","Un utilisateur joue une action")
if (lettre == ' ' || uiState.value.motATrou.contains(lettre)) {
if (lettre == ' ' || uiState.value.lettresUtilises.contains(lowerCaseLetter)) {
Log.d("PenduViewModel","L'utilisateur a fait une action invalide")
uiState.value = PenduUIState(false,
false,
uiState.value.nbViesRestantes,
uiState.value.motATrouver,
uiState.value.motATrou
uiState.value.motATrou,
uiState.value.lettresUtilises
)
}
if (uiState.value.motATrouver.lowercase().contains(lettre.lowercase())) {
return
} else if (uiState.value.motATrouver.lowercase().contains(lowerCaseLetter)) {
Log.d("PenduViewModel","L'utilisateur a trouvé une lettre")
var nvMotATrou = uiState.value.motATrou
for (index in uiState.value.motATrouver.indices) {
if (uiState.value.motATrouver[index].lowercase() == lettre.lowercase()) {
nvMotATrou = nvMotATrou.replaceRange(index,index + 1,
uiState.value.motATrouver[index].toString()
)
val letterToCheck = uiState.value.motATrouver[index]
if (letterToCheck.lowercaseChar() == lowerCaseLetter) {
nvMotATrou = nvMotATrou.replaceRange(index,index + 1, letterToCheck.toString())
}
}
var isWon = false
@ -67,7 +68,8 @@ class PenduViewModel : ViewModel() {
true,
uiState.value.nbViesRestantes,
uiState.value.motATrouver,
nvMotATrou
nvMotATrou,
uiState.value.lettresUtilises.plus(lowerCaseLetter)
)
} else {
Log.d("PenduViewModel","L'utilisateur s'est trompé de lettre")
@ -75,7 +77,8 @@ class PenduViewModel : ViewModel() {
true,
uiState.value.nbViesRestantes - 1,
uiState.value.motATrouver,
uiState.value.motATrou
uiState.value.motATrou,
uiState.value.lettresUtilises.plus(lowerCaseLetter)
)
}
}

@ -0,0 +1,13 @@
package fr.iut.sciencequest.ViewModels.UiStates
import fr.iut.sciencequest.model.dto.question.QuestionWithSimpleResponseDTO
import fr.iut.sciencequest.model.dto.reponse.ReponseSimpleDTO
import fr.iut.sciencequest.stub.StubQuestionWithReponses
data class KahootUIState (
val question: QuestionWithSimpleResponseDTO = StubQuestionWithReponses,
val reponseChoisie: Boolean = false,
// NOTE : Supposé en millisecondes
val duréePartie: Long = 10_000,
val nbPoints: Int = 0
)

@ -0,0 +1,6 @@
package fr.iut.sciencequest.ViewModels.UiStates
data class LoginUIState (
val pseudo: String = "Pseudo",
val mdp: String = "Mot de passe"
)

@ -5,5 +5,6 @@ data class PenduUIState(
val isActionGood: Boolean = false,
val nbViesRestantes: Int = 10,
val motATrouver: String = "Mot",
val motATrou: String = "___"
val motATrou: String = "___",
val lettresUtilises: String = ""
)

@ -7,5 +7,5 @@ import retrofit2.http.Query
interface QuestionRequestService {
@GET("questions?page")
fun getQuestions(@Query("page") index: Int): Call<QuestionListDTO>
suspend fun getQuestions(@Query("page") index: Int): QuestionListDTO
}

@ -1,45 +1,22 @@
package fr.iut.sciencequest.model.buisness.Question
import android.util.Log
import fr.iut.sciencequest.model.buisness.Scientifique.ScientifiqueRequestService
import fr.iut.sciencequest.model.buisness.createRequestService
import fr.iut.sciencequest.model.dto.question.QuestionListDTO
import kotlinx.coroutines.flow.flow
import retrofit2.Call
import retrofit2.Callback
import retrofit2.Response
import retrofit2.create
import java.lang.IllegalArgumentException
fun fetchQuestions(index: Int) {
//val serviceClient = createRequestService().create<QuestionRequestService>()
//Log.d("Requete API","Fetch un scientifique")
//serviceClient.getQuestion(index).enqueue(
// object: Callback<QuestionListDTO> {
// override fun onResponse(
// call: Call<QuestionListDTO>,
// response: Response<QuestionListDTO>
// ) {
// // NOTE : il faudrait probablement utiliser une autre exception
// // exception personnalisée ?
// val data = response.body() ?:
// throw IllegalArgumentException("ERREUR : l'api a donné une réponse vide")
// // Devrait appeler le ModelView, la méthode onResponse ne renvoit rien
// // Pour le moment des print pour vérifier que la requêtre fonctionne
// // sans avoir besoin des vues.
// for (question in data.questions) {
// Log.d("Requete Question", "id question: " + question.id.toString())
// Log.d("Requete Question","Libelle: " + question.question)
// Log.d("Requete Question","Reponses: ")
// for (reponse in question.reponses) {
// Log.d("Requete Question","id: " + reponse.id)
// Log.d("Requete Question","Libelle: " + reponse.reponse)
// }
// }
// }
//
// override fun onFailure(call: Call<QuestionListDTO>, t: Throwable) {
// Log.e("Requete API","Erreur lors d'une requete api")
// throw t
// }
// }
//)
suspend fun fetchQuestions(index: Int) = flow {
val serviceClient = createRequestService().create<QuestionRequestService>()
try {
val response = serviceClient.getQuestions(index)
emit(response)
} catch (e: Exception) {
Log.e("Requete API Question",e.message.toString())
}
}

@ -0,0 +1,7 @@
package fr.iut.sciencequest.model.dto
class JeuDTO (
val id: Int,
val nom: String,
val nbrParties: UInt
)

@ -0,0 +1,11 @@
package fr.iut.sciencequest.model.dto
import fr.iut.sciencequest.model.dto.joueur.JoueurSimpleDTO
class PartieDTO (
val id: Int,
val codeInvitation: String,
val joueurs: List<JoueurSimpleDTO>,
val jeu: JeuDTO,
val thematiques: List<ThematiqueDTO>
)

@ -1,6 +1,6 @@
package fr.iut.sciencequest.model.dto.ScientifiqueDTOs
import fr.iut.sciencequest.model.dto.DifficulteDTO
import fr.iut.sciencequest.model.dto.difficulte.DifficulteDTO
import fr.iut.sciencequest.model.dto.ThematiqueDTO
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@ -3,7 +3,7 @@ package fr.iut.sciencequest.model.dto
import kotlinx.serialization.Serializable
@Serializable
class ThematiqueDTO (
data class ThematiqueDTO (
val id: Int,
val libelle: String
)

@ -1,4 +1,4 @@
package fr.iut.sciencequest.model.dto
package fr.iut.sciencequest.model.dto.difficulte
import kotlinx.serialization.Serializable

@ -0,0 +1,6 @@
package fr.iut.sciencequest.model.dto.difficulte
class DifficulteSimpleDTO (
val id: Int,
val libelle: String
)

@ -1,6 +1,6 @@
package fr.iut.sciencequest.model.dto.extensions
import fr.iut.sciencequest.model.dto.DifficulteDTO
import fr.iut.sciencequest.model.dto.difficulte.DifficulteDTO
import fr.iut.sciencequest.model.metier.Difficulte
fun DifficulteDTO.ToModel(): Difficulte {

@ -0,0 +1,9 @@
package fr.iut.sciencequest.model.dto.joueur
import fr.iut.sciencequest.model.dto.PartieDTO
class JoueurDTO (
val id: Int,
val pseudo: String,
val partie: PartieDTO
)

@ -0,0 +1,6 @@
package fr.iut.sciencequest.model.dto.joueur
class JoueurSimpleDTO (
val id: Int,
val pseudo: String,
)

@ -1,7 +1,5 @@
package fr.iut.sciencequest.model.metier
import fr.iut.sciencequest.model.dto.DifficulteDTO
class Scientifique {
val id: Int
val nom: String

@ -4,9 +4,11 @@ import android.content.Context
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import fr.iut.sciencequest.ViewModels.KahootViewModel
import fr.iut.sciencequest.ViewModels.PenduViewModel
import fr.iut.sciencequest.ViewModels.ScientifiquesDecouvertsVM
import fr.iut.sciencequest.stub.StubQuestionWithReponses
@ -19,12 +21,12 @@ import fr.iut.sciencequest.view.scientifiques.scientifiqueListeScreen
@Composable
fun NavHost(context: Context) {
fun NavHost(kahotVM: KahootViewModel = viewModel()) {
val navController = rememberNavController()
NavHost(
modifier = Modifier.fillMaxSize(),
navController = navController,
startDestination = "pendu"
startDestination = "home"
) {
composable(route = "home") {
HomeScreen(
@ -38,6 +40,7 @@ fun NavHost(context: Context) {
navController.navigate("pendu")
},
goToKahoot = {
kahotVM.lancerPartie()
navController.navigate("kahoot")
}
)
@ -72,8 +75,7 @@ fun NavHost(context: Context) {
},
goToHome = {
navController.navigate("home")
},
context = context
}
)
}
@ -84,7 +86,7 @@ fun NavHost(context: Context) {
goToHome = {
navController.navigate("home")
},
StubQuestionWithReponses)
viewModel = kahotVM)
}
composable(route = "listeScientifiques") {

@ -9,8 +9,19 @@ object StubQuestionWithReponses: QuestionWithSimpleResponseDTO(
reponses = listOf<ReponseSimpleDTO>(
ReponseSimpleDTO(id=0, "Reponse 1"),
ReponseSimpleDTO(id=1, "Reponse 2"),
ReponseSimpleDTO(id=1, "Reponse 3"),
ReponseSimpleDTO(id=1, "Reponse 4"),
ReponseSimpleDTO(id=2, "Reponse 3"),
ReponseSimpleDTO(id=3, "Reponse 4"),
)
)
{}
object StubQuestionWithReponses2: QuestionWithSimpleResponseDTO(
id = 1,
question = "Ceci est une autre question ?",
reponses = listOf(
ReponseSimpleDTO(id = 4, "Moi une reponse?"),
ReponseSimpleDTO(id = 5, "La réponse A"),
ReponseSimpleDTO(id = 6, "Je suis faux"),
ReponseSimpleDTO(id = 5, "Toutes les réponses")
)
)

@ -1,6 +1,6 @@
package fr.iut.sciencequest.stub
import fr.iut.sciencequest.model.dto.DifficulteDTO
import fr.iut.sciencequest.model.dto.difficulte.DifficulteDTO
import fr.iut.sciencequest.model.dto.ScientifiqueDTOs.ScientifiqueDTO
import fr.iut.sciencequest.model.dto.ThematiqueDTO

@ -14,9 +14,14 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.ViewModels.KahootViewModel
@Composable
fun HomeScreen(goToHome: () -> Unit, goToAccount: () -> Unit, goToPendu: () -> Unit, goToKahoot: () -> Unit) {
fun HomeScreen(goToHome: () -> Unit,
goToAccount: () -> Unit,
goToPendu: () -> Unit,
goToKahoot: () -> Unit) {
Column (modifier = Modifier.fillMaxWidth()){
TopBar(goToAccount, goToHome)
MainContent(goToPendu, goToKahoot)

@ -13,10 +13,7 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@ -27,44 +24,41 @@ import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.R
import fr.iut.sciencequest.ViewModels.LoginViewModel
@Composable
fun LoginScreen(goToAccount: () -> Unit, goToHome: () -> Unit) {
fun LoginScreen(viewModel: LoginViewModel = viewModel(),
goToAccount: () -> Unit,
goToHome: () -> Unit) {
Scaffold(
topBar = {
TopBar(goToAccount, goToHome, stringResource(id = R.string.connection))
},
) { innerPadding ->
LoginContainer(Modifier.padding(innerPadding))
LoginContainer(viewModel, Modifier.padding(innerPadding))
}
}
@Composable
fun LoginContainer(modifier: Modifier) {
fun LoginContainer(viewModel: LoginViewModel,
modifier: Modifier) {
val state = viewModel.uiState.collectAsState()
Column(
modifier = modifier.fillMaxHeight(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
val defaultPseudo = stringResource(id = R.string.Pseudo)
var pseudo by remember {
mutableStateOf(defaultPseudo)
}
val defaultMdp = stringResource(id = R.string.mdp)
var mdp by remember {
mutableStateOf(defaultMdp)
}
//Text(text = stringResource(id = R.string.connection))
TextField(value = pseudo ,
onValueChange = { pseudo = it },
TextField(value = state.value.pseudo,
onValueChange = { viewModel.setPseudo(it) },
modifier = Modifier
.padding(20.dp)
.fillMaxWidth()
.fillMaxWidth(),
)
TextField(value = mdp,
onValueChange = { mdp = it },
TextField(value = state.value.mdp,
onValueChange = { viewModel.setMdp(it) },
modifier = Modifier
.padding(20.dp)
.fillMaxWidth()
@ -82,7 +76,7 @@ fun LoginContainer(modifier: Modifier) {
textDecoration = TextDecoration.Underline,
color = colorResource(id = R.color.purple_200)
),
onClick = registerPopup()
onClick = { }/*TODO*/ //registerPopup()
)
}

@ -10,6 +10,7 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
@ -17,40 +18,54 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.R
import fr.iut.sciencequest.ViewModels.KahootViewModel
import fr.iut.sciencequest.model.dto.question.QuestionWithSimpleResponseDTO
import fr.iut.sciencequest.model.dto.reponse.ReponseSimpleDTO
import fr.iut.sciencequest.stub.StubQuestionWithReponses
import fr.iut.sciencequest.view.TopBar
import java.util.Timer
@Composable
fun KahootScreen(goToAccount: () -> Unit, goToHome: () -> Unit, question: QuestionWithSimpleResponseDTO) {
fun KahootScreen(viewModel: KahootViewModel = viewModel(),
goToAccount: () -> Unit,
goToHome: () -> Unit) {
val state = viewModel.uiState.collectAsState()
Column(modifier = Modifier.fillMaxWidth()) {
TopBar(goToAccount, goToHome, stringResource(id = R.string.kahoot))
KahootPlayer(question)
KahootPlayer(state.value.question) {
viewModel.ajouterPoints(it)
}
}
}
@Preview
@Composable
fun KahootScreenPreview(){
KahootScreen(goToAccount = {}, goToHome = {}, StubQuestionWithReponses)
KahootScreen(goToAccount = {}, goToHome = {})
}
@Preview
@Composable
fun KahootPlayerPreview(){
KahootPlayer(question = StubQuestionWithReponses)
val i = 0
KahootPlayer(question = StubQuestionWithReponses) {}
}
@Composable
fun KahootPlayer(question: QuestionWithSimpleResponseDTO){
fun KahootPlayer(question: QuestionWithSimpleResponseDTO,
sendReponse: (Long) -> Unit){
val context = LocalContext.current;
val currTime = System.currentTimeMillis()
Column (horizontalAlignment = Alignment.CenterHorizontally){
KahootQuestion(question = question.question)
KahootReponses(reponses = question.reponses) {Toast.makeText(context, it.reponse, Toast.LENGTH_SHORT).show()}
KahootReponses(reponses = question.reponses) {
sendReponse(currTime - System.currentTimeMillis())
Toast.makeText(context, it.reponse, Toast.LENGTH_SHORT).show()
}
}
}

@ -2,7 +2,6 @@ package fr.iut.sciencequest.view.games
import android.content.Context
import android.widget.Toast
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
@ -14,10 +13,10 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.R
import fr.iut.sciencequest.ViewModels.PenduViewModel
@ -25,36 +24,50 @@ import fr.iut.sciencequest.view.TopBar
@Composable
fun PenduScreen(viewModel: PenduViewModel = viewModel(),
context: Context,
goToAccount: () -> Unit,
goToHome: () -> Unit) {
val state = viewModel.uiState.collectAsState()
val context = LocalContext.current;
Column(modifier = Modifier.fillMaxWidth()) {
TopBar(goToAccount, goToHome, stringResource(id = R.string.pendu))
//Text(text = stringResource(id = R.string.pendu), modifier = Modifier.padding(top=10.dp))
Column(modifier = Modifier
.align(Alignment.CenterHorizontally)
.fillMaxWidth())
Column(modifier = Modifier.align(Alignment.CenterHorizontally))
{
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
Text(text = state.value.motATrou, fontSize = 30.sp)
}
Text(text = state.value.motATrou)
TextField(value = "",
onValueChange = {
if (it.isNotEmpty()) {
viewModel.PlayAction(it[0])
onValueChange = { onLetterEntered(it, viewModel, context, goToHome) },
modifier = Modifier.padding(20.dp))
afficherVies(state.value.nbViesRestantes)
Button(onClick = { viewModel.InitPartie() }) {
Text(text = stringResource(id = R.string.reset_game))
}
Text("Lettres utilisées: " + state.value.lettresUtilises)
}
}
}
fun onLetterEntered(entered: String,
vm: PenduViewModel,
context: Context,
goToHome: () -> Unit) {
val state = vm.uiState
if (entered.isNotEmpty()) {
vm.PlayAction(entered[0])
if ((!state.value.isWon) && (state.value.nbViesRestantes == 0)) {
goToHome()
} else if (state.value.isWon) {
Toast.makeText(context,"Vous avez gagné !",Toast.LENGTH_LONG).show()
goToHome()
}
}},
modifier = Modifier.padding(20.dp))
Button(onClick = { viewModel.InitPartie() }) {
Text(text = stringResource(id = R.string.reset_game))
}
}
@Preview
@Composable
fun afficherVies(nbVies : Int = 10) {
Row {
for (i in 1..nbVies) {
Text("\u2665 ")
}
}
}

Loading…
Cancel
Save