From 8bc76097659b15e1f156b819b148ed0276f952a0 Mon Sep 17 00:00:00 2001 From: Renaud BEURET Date: Sun, 7 Apr 2024 19:05:10 +0200 Subject: [PATCH] [ADD] Kahoot fonctionne avec partie (push tres atomique) --- android/app/build.gradle.kts | 1 + .../java/fr/iut/sciencequest/MainActivity.kt | 5 +- .../buisness/KahootPartieRequestService.kt | 27 ++++++ .../model/buisness/ServiceUtils.kt | 2 +- .../model/dto/extensions/JeuExtension.kt | 12 +++ .../dto/extensions/JoueurSimpleExtension.kt | 19 ++++ .../model/dto/extensions/PartieExtension.kt | 14 +++ .../dto/extensions/PartieKahootExtension.kt | 14 +++ .../dto/extensions/QuestionPartieExtension.kt | 21 +++++ .../dto/extensions/ThematiqueExtensions.kt | 8 ++ .../model/dto/joueur/JoueurDTO.kt | 2 +- .../model/dto/joueur/JoueurScoreDTO.kt | 10 +++ .../model/dto/joueur/JoueurSimpleDTO.kt | 3 + .../model/dto/partie/LaunchedPartieDTO.kt | 10 +++ .../model/dto/partie/NouvellePartieDTO.kt | 10 +++ .../model/dto/{ => partie}/PartieDTO.kt | 4 +- .../model/dto/partie/PartieKahootDTO.kt | 17 ++++ .../model/dto/question/QuestionPartieDTO.kt | 12 +++ .../model/dto/reponse/ReponseInfoDTO.kt | 9 ++ .../model/dto/reponseValidityDTO.kt | 10 +++ .../fr/iut/sciencequest/model/metier/Jeu.kt | 7 ++ .../model/metier/joueur/JoueurSimple.kt | 6 ++ .../model/metier/partie/Partie.kt | 13 +++ .../model/metier/partie/PartieKahoot.kt | 13 +++ .../model/metier/question/QuestionPartie.kt | 9 ++ .../kahootPartie/IKahootPartieRepository.kt | 18 ++++ .../kahootPartie/KahootAPIRepository.kt | 81 +++++++++++++++++ .../fr/iut/sciencequest/navigation/NavHost.kt | 63 ++++++++++++-- .../fr/iut/sciencequest/view/games/Qui.kt | 16 ++-- .../view/games/{ => kahoot}/Kahoot.kt | 55 +++++++----- .../view/games/kahoot/RejoindreKahoot.kt | 29 +++++++ .../games/kahoot/RejoindreKahootAvecCode.kt | 45 ++++++++++ .../view/games/kahoot/Resultat.kt | 33 +++++++ .../view/games/kahoot/WaitingScreen.kt | 51 +++++++++++ .../viewModels/KahootJoinViewModel.kt | 18 ++++ .../viewModels/KahootViewModel.kt | 87 ++++++++++++++----- .../viewModels/uiStates/KahootJoinUIState.kt | 5 ++ .../viewModels/uiStates/KahootUIState.kt | 11 ++- android/app/src/main/res/values/strings.xml | 4 + 39 files changed, 712 insertions(+), 62 deletions(-) create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/buisness/KahootPartieRequestService.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/JeuExtension.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/JoueurSimpleExtension.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/PartieExtension.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/PartieKahootExtension.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/QuestionPartieExtension.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurScoreDTO.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/LaunchedPartieDTO.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/NouvellePartieDTO.kt rename android/app/src/main/java/fr/iut/sciencequest/model/dto/{ => partie}/PartieDTO.kt (62%) create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/PartieKahootDTO.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/question/QuestionPartieDTO.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/reponse/ReponseInfoDTO.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/dto/reponseValidityDTO.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/metier/Jeu.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/metier/joueur/JoueurSimple.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/metier/partie/Partie.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/metier/partie/PartieKahoot.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/metier/question/QuestionPartie.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/repositories/kahootPartie/IKahootPartieRepository.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/model/repositories/kahootPartie/KahootAPIRepository.kt rename android/app/src/main/java/fr/iut/sciencequest/view/games/{ => kahoot}/Kahoot.kt (68%) create mode 100644 android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/RejoindreKahoot.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/RejoindreKahootAvecCode.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/Resultat.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/WaitingScreen.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/viewModels/KahootJoinViewModel.kt create mode 100644 android/app/src/main/java/fr/iut/sciencequest/viewModels/uiStates/KahootJoinUIState.kt diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 238ab8d..84d9ca6 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -51,6 +51,7 @@ android { } dependencies { + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.6.0-RC.2") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.2") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-javafx:1.7.3") diff --git a/android/app/src/main/java/fr/iut/sciencequest/MainActivity.kt b/android/app/src/main/java/fr/iut/sciencequest/MainActivity.kt index bd86650..6a516b7 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/MainActivity.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/MainActivity.kt @@ -3,16 +3,19 @@ package fr.iut.sciencequest import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import androidx.activity.viewModels import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.ui.Modifier import fr.iut.sciencequest.navigation.NavHost import fr.iut.sciencequest.ui.theme.ScienceQuestTheme +import fr.iut.sciencequest.viewModels.KahootViewModel class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + val vm = viewModels { KahootViewModel.ApiFactory } setContent { ScienceQuestTheme { // A surface container using the 'background' color from the theme @@ -20,7 +23,7 @@ class MainActivity : ComponentActivity() { modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { - NavHost() + NavHost(vm.value) } } } diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/buisness/KahootPartieRequestService.kt b/android/app/src/main/java/fr/iut/sciencequest/model/buisness/KahootPartieRequestService.kt new file mode 100644 index 0000000..244ed98 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/buisness/KahootPartieRequestService.kt @@ -0,0 +1,27 @@ +package fr.iut.sciencequest.model.buisness + +import fr.iut.sciencequest.model.dto.partie.LaunchedPartieDTO +import fr.iut.sciencequest.model.dto.partie.PartieKahootDTO +import fr.iut.sciencequest.model.dto.partie.NouvellePartieDTO +import fr.iut.sciencequest.model.dto.question.QuestionPartieDTO +import fr.iut.sciencequest.model.dto.reponse.ReponseInfoDTO +import fr.iut.sciencequest.model.dto.reponseValidityDTO +import retrofit2.http.Body +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.Path +import retrofit2.http.Query + +interface KahootPartieRequestService { + @POST("partie/kahoot") + suspend fun createPartie(@Body gameInfo: NouvellePartieDTO): PartieKahootDTO + + @POST("partie/kahoot/{codePartie}/demarrer") + suspend fun launchPartie(@Path("codePartie") code: String): LaunchedPartieDTO + + @GET("partie/kahoot/{codePartie}/question") + suspend fun getQuestionFromPartie(@Path("codePartie") code: String): QuestionPartieDTO + + @POST("partie/kahoot/{codeInvitation}/reponse") + suspend fun postResponse(@Path("codeInvitation") code:String, @Body reponseInfo: ReponseInfoDTO): reponseValidityDTO +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/buisness/ServiceUtils.kt b/android/app/src/main/java/fr/iut/sciencequest/model/buisness/ServiceUtils.kt index 3742b19..5fe180d 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/model/buisness/ServiceUtils.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/model/buisness/ServiceUtils.kt @@ -13,6 +13,6 @@ val httpClient = OkHttpClient() fun createRequestService(): Retrofit = Retrofit.Builder() .baseUrl(API_BASE_URL) - .addConverterFactory(Json { ignoreUnknownKeys = true }.asConverterFactory(MediaType.get("application/json"))) + .addConverterFactory(Json { ignoreUnknownKeys = true; coerceInputValues = true }.asConverterFactory(MediaType.get("application/json"))) .client(httpClient) .build() \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/JeuExtension.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/JeuExtension.kt new file mode 100644 index 0000000..a19e9d3 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/JeuExtension.kt @@ -0,0 +1,12 @@ +package fr.iut.sciencequest.model.dto.extensions + +import fr.iut.sciencequest.model.dto.JeuDTO +import fr.iut.sciencequest.model.metier.Jeu + +fun JeuDTO.toModel(): Jeu { + return Jeu( + this.id, + this.nom, + this.nbrParties + ) +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/JoueurSimpleExtension.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/JoueurSimpleExtension.kt new file mode 100644 index 0000000..f474953 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/JoueurSimpleExtension.kt @@ -0,0 +1,19 @@ +package fr.iut.sciencequest.model.dto.extensions + +import fr.iut.sciencequest.model.dto.joueur.JoueurSimpleDTO +import fr.iut.sciencequest.model.metier.joueur.JoueurSimple + +fun JoueurSimpleDTO.toModel(): JoueurSimple { + return JoueurSimple( + this.id, + this.pseudo + ) +} + +fun List.toModel(): List { + val liste = mutableListOf() + for (joueur in this) { + liste.add(joueur.toModel()) + } + return liste +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/PartieExtension.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/PartieExtension.kt new file mode 100644 index 0000000..9424efd --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/PartieExtension.kt @@ -0,0 +1,14 @@ +package fr.iut.sciencequest.model.dto.extensions + +import fr.iut.sciencequest.model.dto.partie.PartieDTO +import fr.iut.sciencequest.model.metier.partie.Partie + +fun PartieDTO.toModel(): Partie { + return Partie( + this.id, + this.codeInvitation, + this.joueurs.toModel(), + this.jeu.toModel(), + this.thematiques.toModel() + ) +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/PartieKahootExtension.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/PartieKahootExtension.kt new file mode 100644 index 0000000..ca7246e --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/PartieKahootExtension.kt @@ -0,0 +1,14 @@ +package fr.iut.sciencequest.model.dto.extensions + +import fr.iut.sciencequest.model.dto.partie.PartieKahootDTO +import fr.iut.sciencequest.model.metier.partie.PartieKahoot + +fun PartieKahootDTO.toModel(): PartieKahoot { + return PartieKahoot( + this.id, + this.code, + this.thematiques.toModel(), + this.joueurs.toModel(), + this.difficulte.ToModel() + ) +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/QuestionPartieExtension.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/QuestionPartieExtension.kt new file mode 100644 index 0000000..4107a6d --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/QuestionPartieExtension.kt @@ -0,0 +1,21 @@ +package fr.iut.sciencequest.model.dto.extensions + +import fr.iut.sciencequest.model.dto.question.QuestionPartieDTO +import fr.iut.sciencequest.model.metier.question.QuestionPartie +import kotlinx.datetime.Instant +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toInstant + +fun QuestionPartieDTO.toModel(): QuestionPartie { + var limite: Instant + if (this.limitTime == null) { + limite = LocalDateTime(1,1,1,1,1,1,1).toInstant(TimeZone.UTC) + } else { + limite = Instant.parse(this.limitTime) + } + return QuestionPartie( + this.question?.ToModel(), + limite + ) +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/ThematiqueExtensions.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/ThematiqueExtensions.kt index b828f57..3237ab8 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/ThematiqueExtensions.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/extensions/ThematiqueExtensions.kt @@ -9,4 +9,12 @@ fun ThematiqueDTO.ToModel(): Thematique { libelle = this.libelle ) return model +} + +fun List.toModel(): List { + val liste = mutableListOf() + for (thematique in this) { + liste.add(thematique.ToModel()) + } + return liste } \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurDTO.kt index 65c1d24..b441911 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurDTO.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurDTO.kt @@ -1,6 +1,6 @@ package fr.iut.sciencequest.model.dto.joueur -import fr.iut.sciencequest.model.dto.PartieDTO +import fr.iut.sciencequest.model.dto.partie.PartieDTO class JoueurDTO ( val id: Int, diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurScoreDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurScoreDTO.kt new file mode 100644 index 0000000..3cb1e25 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurScoreDTO.kt @@ -0,0 +1,10 @@ +package fr.iut.sciencequest.model.dto.joueur + +import fr.iut.sciencequest.model.metier.joueur.JoueurSimple +import kotlinx.serialization.Serializable + +@Serializable +class JoueurScoreDTO ( + val joueur: JoueurSimpleDTO, + val score: Int +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurSimpleDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurSimpleDTO.kt index 6fb3857..15ee7c9 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurSimpleDTO.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/joueur/JoueurSimpleDTO.kt @@ -1,5 +1,8 @@ package fr.iut.sciencequest.model.dto.joueur +import kotlinx.serialization.Serializable + +@Serializable class JoueurSimpleDTO ( val id: Int, val pseudo: String, diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/LaunchedPartieDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/LaunchedPartieDTO.kt new file mode 100644 index 0000000..2ae4ab9 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/LaunchedPartieDTO.kt @@ -0,0 +1,10 @@ +package fr.iut.sciencequest.model.dto.partie + +import fr.iut.sciencequest.model.dto.joueur.JoueurScoreDTO +import kotlinx.serialization.Serializable + +@Serializable +class LaunchedPartieDTO ( + val status: String, + val scores: List +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/NouvellePartieDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/NouvellePartieDTO.kt new file mode 100644 index 0000000..dd9b987 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/NouvellePartieDTO.kt @@ -0,0 +1,10 @@ +package fr.iut.sciencequest.model.dto.partie + +import kotlinx.serialization.Serializable + +@Serializable +data class NouvellePartieDTO ( + val idJoueur: Int, + val thematiques: List, + val idDifficulte: Int +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/PartieDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/PartieDTO.kt similarity index 62% rename from android/app/src/main/java/fr/iut/sciencequest/model/dto/PartieDTO.kt rename to android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/PartieDTO.kt index 64df64c..c812d07 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/model/dto/PartieDTO.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/PartieDTO.kt @@ -1,5 +1,7 @@ -package fr.iut.sciencequest.model.dto +package fr.iut.sciencequest.model.dto.partie +import fr.iut.sciencequest.model.dto.JeuDTO +import fr.iut.sciencequest.model.dto.ThematiqueDTO import fr.iut.sciencequest.model.dto.joueur.JoueurSimpleDTO class PartieDTO ( diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/PartieKahootDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/PartieKahootDTO.kt new file mode 100644 index 0000000..39376c8 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/partie/PartieKahootDTO.kt @@ -0,0 +1,17 @@ +package fr.iut.sciencequest.model.dto.partie + +import fr.iut.sciencequest.model.dto.ThematiqueDTO +import fr.iut.sciencequest.model.dto.difficulte.DifficulteDTO +import fr.iut.sciencequest.model.dto.joueur.JoueurSimpleDTO +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +class PartieKahootDTO ( + val id: Int, + @SerialName("codeInvitation") + val code: String, + val thematiques: List, + val joueurs: List, + val difficulte: DifficulteDTO +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/question/QuestionPartieDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/question/QuestionPartieDTO.kt new file mode 100644 index 0000000..63d4cbe --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/question/QuestionPartieDTO.kt @@ -0,0 +1,12 @@ +package fr.iut.sciencequest.model.dto.question + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +class QuestionPartieDTO ( + @SerialName("questionActuel") + val question: QuestionWithSimpleResponseDTO?, + @SerialName("tempsLimiteReponse") + val limitTime: String? +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/reponse/ReponseInfoDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/reponse/ReponseInfoDTO.kt new file mode 100644 index 0000000..10c2d2a --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/reponse/ReponseInfoDTO.kt @@ -0,0 +1,9 @@ +package fr.iut.sciencequest.model.dto.reponse + +import kotlinx.serialization.Serializable + +@Serializable +data class ReponseInfoDTO ( + val idJoueur: Int, + val idReponse: Int +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/dto/reponseValidityDTO.kt b/android/app/src/main/java/fr/iut/sciencequest/model/dto/reponseValidityDTO.kt new file mode 100644 index 0000000..5c000c2 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/dto/reponseValidityDTO.kt @@ -0,0 +1,10 @@ +package fr.iut.sciencequest.model.dto + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +class reponseValidityDTO ( + @SerialName("estValide") + val isValid: Boolean +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/metier/Jeu.kt b/android/app/src/main/java/fr/iut/sciencequest/model/metier/Jeu.kt new file mode 100644 index 0000000..6b6ec6f --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/metier/Jeu.kt @@ -0,0 +1,7 @@ +package fr.iut.sciencequest.model.metier + +class Jeu ( + val id: Int, + val nom: String, + val nbrParties: UInt +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/metier/joueur/JoueurSimple.kt b/android/app/src/main/java/fr/iut/sciencequest/model/metier/joueur/JoueurSimple.kt new file mode 100644 index 0000000..c7cca54 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/metier/joueur/JoueurSimple.kt @@ -0,0 +1,6 @@ +package fr.iut.sciencequest.model.metier.joueur + +class JoueurSimple ( + val id: Int, + val pseudo: String +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/metier/partie/Partie.kt b/android/app/src/main/java/fr/iut/sciencequest/model/metier/partie/Partie.kt new file mode 100644 index 0000000..a6d7927 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/metier/partie/Partie.kt @@ -0,0 +1,13 @@ +package fr.iut.sciencequest.model.metier.partie + +import fr.iut.sciencequest.model.metier.Jeu +import fr.iut.sciencequest.model.metier.Thematique +import fr.iut.sciencequest.model.metier.joueur.JoueurSimple + +class Partie ( + val id: Int, + val codeInvitation: String, + val joueurs: List, + val jeu: Jeu, + val thematiques: List +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/metier/partie/PartieKahoot.kt b/android/app/src/main/java/fr/iut/sciencequest/model/metier/partie/PartieKahoot.kt new file mode 100644 index 0000000..a281ef0 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/metier/partie/PartieKahoot.kt @@ -0,0 +1,13 @@ +package fr.iut.sciencequest.model.metier.partie + +import fr.iut.sciencequest.model.metier.Difficulte +import fr.iut.sciencequest.model.metier.Thematique +import fr.iut.sciencequest.model.metier.joueur.JoueurSimple + +class PartieKahoot ( + val id: Int, + val code: String, + val thematiques: List, + val joueurs: List, + val difficulte: Difficulte +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/metier/question/QuestionPartie.kt b/android/app/src/main/java/fr/iut/sciencequest/model/metier/question/QuestionPartie.kt new file mode 100644 index 0000000..87d3a8d --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/metier/question/QuestionPartie.kt @@ -0,0 +1,9 @@ +package fr.iut.sciencequest.model.metier.question + +import kotlinx.datetime.Instant +import kotlinx.datetime.LocalDateTime + +class QuestionPartie ( + val question: QuestionWithSimpleReponse?, + val date: Instant +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/repositories/kahootPartie/IKahootPartieRepository.kt b/android/app/src/main/java/fr/iut/sciencequest/model/repositories/kahootPartie/IKahootPartieRepository.kt new file mode 100644 index 0000000..6efbd89 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/repositories/kahootPartie/IKahootPartieRepository.kt @@ -0,0 +1,18 @@ +package fr.iut.sciencequest.model.repositories.kahootPartie + +import fr.iut.sciencequest.model.dto.partie.NouvellePartieDTO +import fr.iut.sciencequest.model.metier.partie.PartieKahoot +import fr.iut.sciencequest.model.metier.question.QuestionPartie +import kotlinx.coroutines.flow.StateFlow + +interface IKahootPartieRepository { + val partie: StateFlow + val question: StateFlow + val isStarted: StateFlow + val isReponseValid: StateFlow + + suspend fun createPartie(nvPartie: NouvellePartieDTO) + suspend fun startPartie(code: String) + suspend fun getQuestion(code: String) + suspend fun postReponse(code: String, idJoueur: Int, idReponse: Int) +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/model/repositories/kahootPartie/KahootAPIRepository.kt b/android/app/src/main/java/fr/iut/sciencequest/model/repositories/kahootPartie/KahootAPIRepository.kt new file mode 100644 index 0000000..dae6f13 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/model/repositories/kahootPartie/KahootAPIRepository.kt @@ -0,0 +1,81 @@ +package fr.iut.sciencequest.model.repositories.kahootPartie + +import android.util.Log +import fr.iut.sciencequest.model.buisness.KahootPartieRequestService +import fr.iut.sciencequest.model.buisness.createRequestService +import fr.iut.sciencequest.model.dto.extensions.toModel +import fr.iut.sciencequest.model.dto.partie.NouvellePartieDTO +import fr.iut.sciencequest.model.dto.reponse.ReponseInfoDTO +import fr.iut.sciencequest.model.metier.Difficulte +import fr.iut.sciencequest.model.metier.partie.PartieKahoot +import fr.iut.sciencequest.model.metier.question.QuestionPartie +import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toInstant +import retrofit2.create + +class KahootAPIRepository: IKahootPartieRepository { + + private val _partie = MutableStateFlow(PartieKahoot(0,"", emptyList(),emptyList(), Difficulte(0,""))) + override val partie: StateFlow + get() = _partie.asStateFlow() + + private val _question = MutableStateFlow(QuestionPartie(QuestionWithSimpleReponse(0,"", emptyList()), LocalDateTime(1,1,1,1,1 ).toInstant( + TimeZone.UTC))) + override val question: StateFlow + get() = _question.asStateFlow() + + private val _isStarted = MutableStateFlow(false) + override val isStarted: StateFlow + get() = _isStarted.asStateFlow() + + private val _isValidResponse = MutableStateFlow(false) + override val isReponseValid: StateFlow + get() = _isValidResponse.asStateFlow() + + override suspend fun createPartie(nvPartie: NouvellePartieDTO) { + val serviceClient = createRequestService().create() + try { + _partie.value = serviceClient.createPartie(nvPartie).toModel() + Log.d("Req partie crea",_partie.value.code) + } catch (e: Exception) { + Log.e("Requete API Partie crea", e.message.toString()) + } + } + + override suspend fun startPartie(code: String) { + val serviceClient = createRequestService().create() + try { + val partieStatus = serviceClient.launchPartie(code) + _isStarted.value = partieStatus.status == "Started" + } catch (e: Exception) { + Log.e("Requete API Partie star", e.message.toString()) + } + } + + override suspend fun getQuestion(code: String) { + val serviceClient = createRequestService().create() + try { + _question.value = serviceClient.getQuestionFromPartie(code).toModel() + } catch (e: Exception) { + Log.e("Requete API Partie getq", e.message.toString()) + _question.value = QuestionPartie( + question = _question.value.question, + date = LocalDateTime(1,1,1,1,1,1,1).toInstant(TimeZone.UTC) + ) + } + } + + override suspend fun postReponse(code: String, idJoueur: Int, idReponse: Int) { + val serviceClient = createRequestService().create() + try { + _isValidResponse.value = serviceClient.postResponse(code, ReponseInfoDTO(idJoueur, idReponse)).isValid + } catch (e: Exception) { + Log.e("Requete API Partie post", e.message.toString()) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/navigation/NavHost.kt b/android/app/src/main/java/fr/iut/sciencequest/navigation/NavHost.kt index cd50bd8..bb011e5 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/navigation/NavHost.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/navigation/NavHost.kt @@ -2,21 +2,27 @@ package fr.iut.sciencequest.navigation import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState 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.view.AccountScreen import fr.iut.sciencequest.view.HomeScreen import fr.iut.sciencequest.view.LoginScreen -import fr.iut.sciencequest.view.games.KahootScreen +import fr.iut.sciencequest.view.games.kahoot.KahootScreen import fr.iut.sciencequest.view.games.PenduScreen import fr.iut.sciencequest.view.games.QuiScreen +import fr.iut.sciencequest.view.games.kahoot.MenuKahoot +import fr.iut.sciencequest.view.games.kahoot.ResultatKahoot +import fr.iut.sciencequest.view.games.kahoot.WaitingScreen import fr.iut.sciencequest.view.scientifiques.scientifiqueListeScreen +import fr.iut.sciencequest.viewModels.KahootViewModel @Composable -fun NavHost() { +fun NavHost(kahootVM: KahootViewModel) { val navController = rememberNavController() NavHost( modifier = Modifier.fillMaxSize(), @@ -35,7 +41,7 @@ fun NavHost() { navController.navigate("pendu") }, goToKahoot = { - navController.navigate("kahoot") + navController.navigate("kahootMenu") }, goToQui = { navController.navigate("qui") @@ -76,17 +82,64 @@ fun NavHost() { ) } - composable(route= "kahoot"){ + composable(route= "kahootGame"){ KahootScreen( goToAccount = { navController.navigate("account") }, goToHome = { navController.navigate("home") - } + }, + goToResult = { + navController.navigate("kahootResult") + }, + viewModel = kahootVM + ) + } + + composable(route = "kahootResult") { + ResultatKahoot( + goToAccount = { + navController.navigate("account") + }, + goToHome = { + navController.navigate("home") + }, + kahootViewModel = kahootVM + ) + } + + composable(route= "kahootMenu"){ + MenuKahoot( + goToAccount = { + navController.navigate("account") + }, + goToHome = { + navController.navigate("home") + }, + goToWaiting = { + kahootVM.createPartie(1,1, listOf(1)) + navController.navigate("kahootWaiting") + }, + kahootViewModel = kahootVM ) } + composable(route = "kahootWaiting") { + WaitingScreen( + goToAccount = { + navController.navigate("account") + }, + goToHome = { + navController.navigate("home") + }, + goToGame = { + navController.navigate("kahootGame") + }, + kahootViewModel = kahootVM + ) + } + composable(route= "qui"){ QuiScreen(goToAccount = { navController.navigate("account") diff --git a/android/app/src/main/java/fr/iut/sciencequest/view/games/Qui.kt b/android/app/src/main/java/fr/iut/sciencequest/view/games/Qui.kt index 3ce5cb6..007f8cd 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/view/games/Qui.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/view/games/Qui.kt @@ -37,8 +37,8 @@ fun QuiScreen(viewModel: KahootViewModel = viewModel(), val state = viewModel.uiState.collectAsState() Column(modifier = Modifier.fillMaxWidth()) { TopBar(goToAccount, goToHome, stringResource(id = R.string.kahoot)) - QuiPlayer(state.value.question) { - viewModel.ajouterPoints(it) + QuiPlayer(state.value.questionPartie.question) { + // viewModel.ajouterPoints(it) } } } @@ -59,16 +59,16 @@ fun QuiPlayerPreview(){ @Composable -fun QuiPlayer(question: QuestionWithSimpleReponse, +fun QuiPlayer(question: QuestionWithSimpleReponse?, sendReponse: (Long) -> Unit){ val context = LocalContext.current; val currTime = System.currentTimeMillis() Column (horizontalAlignment = Alignment.CenterHorizontally){ - QuiQuestion(question = question.question) - QuiReponses(reponses = question.reponses) { - sendReponse(currTime - System.currentTimeMillis()) - Toast.makeText(context, it.reponse, Toast.LENGTH_SHORT).show() - } + //QuiQuestion(question = question.question) + //QuiReponses(reponses = question.reponses) { + // sendReponse(currTime - System.currentTimeMillis()) + // Toast.makeText(context, it.reponse, Toast.LENGTH_SHORT).show() + //} } } diff --git a/android/app/src/main/java/fr/iut/sciencequest/view/games/Kahoot.kt b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/Kahoot.kt similarity index 68% rename from android/app/src/main/java/fr/iut/sciencequest/view/games/Kahoot.kt rename to android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/Kahoot.kt index 1658ec0..460fe86 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/view/games/Kahoot.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/Kahoot.kt @@ -1,5 +1,6 @@ -package fr.iut.sciencequest.view.games +package fr.iut.sciencequest.view.games.kahoot +import android.util.Log import android.widget.Toast import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -31,40 +32,44 @@ import fr.iut.sciencequest.stub.StubQuestionWithReponses import fr.iut.sciencequest.view.TopBar @Composable -fun KahootScreen(viewModel: KahootViewModel = viewModel(factory = KahootViewModel.ApiFactory), +fun KahootScreen(viewModel: KahootViewModel, goToAccount: () -> Unit, - goToHome: () -> Unit) { - val state = viewModel.uiState.collectAsState() + goToHome: () -> Unit, + goToResult: () -> Unit) { LaunchedEffect(key1 = Unit) { + Log.d("Kahoot","Je lance la partie") viewModel.lancerPartie() + Log.d("Kahoot","Je vais chercher la question") + viewModel.updateQuestion(goToResult) } + val state = viewModel.uiState.collectAsState() Column(modifier = Modifier.fillMaxWidth()) { TopBar(goToAccount, goToHome, stringResource(id = R.string.kahoot)) - - KahootPlayer(state.value.question) { - viewModel.ajouterPoints(it) + Log.d("Kahoot",state.value.questionPartie.question!!.question) + KahootPlayer(state.value.questionPartie.question) { pts, rep -> + viewModel.ajouterPoints(pts, rep) } } } -@Preview -@Composable -fun KahootScreenPreview(){ - KahootScreen(goToAccount = {}, goToHome = {}) -} +// @Preview +// @Composable +// fun KahootScreenPreview(){ +// KahootScreen(goToAccount = {}, goToHome = {}, goToResult = {}) +// } -@Preview -@Composable -fun KahootPlayerPreview(){ - val i = 0 - KahootPlayer(question = StubQuestionWithReponses.ToModel()) {} -} +// @Preview +// @Composable +// fun KahootPlayerPreview(){ +// val i = 0 +// KahootPlayer(question = StubQuestionWithReponses.ToModel()) {} +// } @Composable -fun KahootPlayer(question: QuestionWithSimpleReponse, - sendReponse: (Long) -> Unit){ +fun KahootPlayer(question: QuestionWithSimpleReponse?, + sendReponse: (Long, Int) -> Unit){ val context = LocalContext.current; val currTime = System.currentTimeMillis() @@ -73,10 +78,12 @@ fun KahootPlayer(question: QuestionWithSimpleReponse, verticalArrangement = Arrangement.SpaceEvenly, modifier = Modifier.fillMaxHeight() ) { - KahootQuestion(question = question.question) - KahootReponses(reponses = question.reponses) { - sendReponse(System.currentTimeMillis() - currTime) - Toast.makeText(context, it.reponse, Toast.LENGTH_SHORT).show() + if (question != null) { + KahootQuestion(question = question.question) + KahootReponses(reponses = question.reponses) { + sendReponse(System.currentTimeMillis() - currTime, it.id) + Toast.makeText(context, it.reponse, Toast.LENGTH_SHORT).show() + } } } } diff --git a/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/RejoindreKahoot.kt b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/RejoindreKahoot.kt new file mode 100644 index 0000000..f53409e --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/RejoindreKahoot.kt @@ -0,0 +1,29 @@ +package fr.iut.sciencequest.view.games.kahoot + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.lifecycle.viewmodel.compose.viewModel +import fr.iut.sciencequest.R +import fr.iut.sciencequest.view.TopBar +import fr.iut.sciencequest.viewModels.KahootJoinViewModel +import fr.iut.sciencequest.viewModels.KahootViewModel + +@Composable +fun MenuKahoot(kahootViewModel: KahootViewModel = viewModel(factory = KahootViewModel.ApiFactory), + kahootJoinVM: KahootJoinViewModel = viewModel(), + goToAccount: () -> Unit, + goToHome: () -> Unit, + goToWaiting: (KahootViewModel) -> Unit) { + Column(modifier = Modifier.fillMaxWidth()) { + TopBar(goToAccount, goToHome, stringResource(id = R.string.kahoot)) + RejoindreKahootAvecCodeContainer() + Button(onClick = { goToWaiting(kahootViewModel) }) { + Text("Creer une partie") + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/RejoindreKahootAvecCode.kt b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/RejoindreKahootAvecCode.kt new file mode 100644 index 0000000..2167ee8 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/RejoindreKahootAvecCode.kt @@ -0,0 +1,45 @@ +package fr.iut.sciencequest.view.games.kahoot + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.lifecycle.viewmodel.compose.viewModel +import fr.iut.sciencequest.R +import fr.iut.sciencequest.viewModels.KahootJoinViewModel + +@Preview +@Composable +fun RejoindreKahootAvecCodeContainer(kahootJoinVM: KahootJoinViewModel = viewModel()) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + + ) { + Text(stringResource(id = R.string.join_game)) + KahootCodeInputContainer(kahootJoinVM) + } +} + +@Preview +@Composable +fun KahootCodeInputContainer(kahootJoinVM: KahootJoinViewModel = viewModel()) { + val state = kahootJoinVM.uiState.collectAsState() + Column ( + horizontalAlignment = Alignment.CenterHorizontally + ){ + TextField(value = state.value.code, + onValueChange = {kahootJoinVM.setCode(it)}) + Button(onClick = { /*TODO*/ }) { + Text(text = stringResource(id = R.string.join)) + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/Resultat.kt b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/Resultat.kt new file mode 100644 index 0000000..b3d807b --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/Resultat.kt @@ -0,0 +1,33 @@ +package fr.iut.sciencequest.view.games.kahoot + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.lifecycle.viewmodel.compose.viewModel +import fr.iut.sciencequest.R +import fr.iut.sciencequest.view.TopBar +import fr.iut.sciencequest.viewModels.KahootJoinViewModel +import fr.iut.sciencequest.viewModels.KahootViewModel + +@Composable +fun ResultatKahoot(goToAccount: () -> Unit, + goToHome: () -> Unit, + kahootViewModel: KahootViewModel) { + val state = kahootViewModel.uiState.collectAsState() + Column(modifier = Modifier.fillMaxWidth()) { + TopBar(goToAccount, goToHome, stringResource(id = R.string.kahoot)) + Column(modifier = Modifier.fillMaxHeight(), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally) { + Text("Vous avez " + state.value.nbPoints + "points") + } + } +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/WaitingScreen.kt b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/WaitingScreen.kt new file mode 100644 index 0000000..8fef115 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/view/games/kahoot/WaitingScreen.kt @@ -0,0 +1,51 @@ +package fr.iut.sciencequest.view.games.kahoot + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +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.res.stringResource +import androidx.lifecycle.viewmodel.compose.viewModel +import fr.iut.sciencequest.R +import fr.iut.sciencequest.model.metier.joueur.JoueurSimple +import fr.iut.sciencequest.view.TopBar +import fr.iut.sciencequest.viewModels.KahootJoinViewModel +import fr.iut.sciencequest.viewModels.KahootViewModel + +@Composable +fun WaitingScreen(kahootViewModel: KahootViewModel = viewModel(factory = KahootViewModel.ApiFactory), + goToAccount: () -> Unit, + goToHome: () -> Unit, + goToGame: () -> Unit) { + val state = kahootViewModel.uiState.collectAsState() + Column(modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally) { + TopBar(goToAccount, goToHome, stringResource(id = R.string.kahoot)) + Column { + Text(text = stringResource(id = R.string.user_in_game)) + ListeJoueurs(state.value.partie.joueurs) + Button(onClick = { goToGame() }) { + Text(stringResource(id = R.string.start_game)) + } + } + } +} + +@Composable +fun ListeJoueurs(joueurs: List) { + for (joueur in joueurs) { + JoueurContainer(joueur) + } +} + +@Composable +fun JoueurContainer(joueur: JoueurSimple) { + Row { + Text("Pseudo: " + joueur.pseudo) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/viewModels/KahootJoinViewModel.kt b/android/app/src/main/java/fr/iut/sciencequest/viewModels/KahootJoinViewModel.kt new file mode 100644 index 0000000..5bd7559 --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/viewModels/KahootJoinViewModel.kt @@ -0,0 +1,18 @@ +package fr.iut.sciencequest.viewModels + +import androidx.lifecycle.ViewModel +import fr.iut.sciencequest.viewModels.uiStates.KahootJoinUIState +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class KahootJoinViewModel : ViewModel() { + private val _uiState = MutableStateFlow(KahootJoinUIState()) + val uiState = _uiState.asStateFlow() + + fun setCode(code: String) { + if (code.length >= 6) { + return + } + _uiState.value = KahootJoinUIState(code) + } +} \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/viewModels/KahootViewModel.kt b/android/app/src/main/java/fr/iut/sciencequest/viewModels/KahootViewModel.kt index 48cafca..57016c6 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/viewModels/KahootViewModel.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/viewModels/KahootViewModel.kt @@ -6,49 +6,90 @@ import android.util.Log import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope -import fr.iut.sciencequest.model.repositories.question.IQuestionRepository -import fr.iut.sciencequest.model.repositories.question.QuestionAPIRepository +import fr.iut.sciencequest.model.dto.partie.NouvellePartieDTO +import fr.iut.sciencequest.model.repositories.kahootPartie.IKahootPartieRepository +import fr.iut.sciencequest.model.repositories.kahootPartie.KahootAPIRepository import fr.iut.sciencequest.viewModels.uixStates.KahootUIState import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch +import kotlinx.datetime.Clock +import kotlinx.datetime.Instant +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toInstant +import kotlinx.datetime.toLocalDateTime class KahootViewModel( - val questionRepo: IQuestionRepository + val kahootRepo: IKahootPartieRepository ): ViewModel() { private val _uiState = MutableStateFlow(KahootUIState()) val uiState = _uiState.asStateFlow() private val handler = Handler(Looper.getMainLooper()) + fun createPartie(idJoueur: Int, idDifficulte: Int, thematiques: List) { + viewModelScope.launch { + val infosToCreate = NouvellePartieDTO(idJoueur, thematiques, idDifficulte) + kahootRepo.createPartie(infosToCreate) + + _uiState.value = KahootUIState( + dureePartie = _uiState.value.dureePartie, + nbPoints = _uiState.value.nbPoints, + reponseChoisie = false, + partie = kahootRepo.partie.value + ) + } + } + fun lancerPartie() { viewModelScope.launch { - questionRepo.fetchQuestions(2) + kahootRepo.startPartie(_uiState.value.partie.code) _uiState.value = KahootUIState( - questionRepo.questions.value.get(0), - dureePartie = uiState.value.dureePartie, - nbPoints = uiState.value.nbPoints, - reponseChoisie = false + partie = kahootRepo.partie.value, + nbPoints = _uiState.value.nbPoints, + reponseChoisie = false, + dureePartie = uiState.value.dureePartie ) - for (index: Int in 1..questionRepo.questions.value.size) { + } + } + + fun updateQuestion(goToResult: () -> Unit) { + viewModelScope.launch { + Log.d("Hop j'attends","a") + kahootRepo.getQuestion(_uiState.value.partie.code) + if (kahootRepo.question.value.date == LocalDateTime(1,1,1,1,1,1,1).toInstant(TimeZone.UTC)) { + Log.d("Je passe là","j'ai fini le kahoot") + goToResult() + } else { + _uiState.value = KahootUIState( + questionPartie = kahootRepo.question.value, + nbPoints = _uiState.value.nbPoints, + reponseChoisie = false, + partie = _uiState.value.partie + ) + val now: Instant = Clock.System.now() + val today: LocalDateTime = now.toLocalDateTime(TimeZone.currentSystemDefault()) + handler.postDelayed( { - _uiState.value = KahootUIState( - questionRepo.questions.value.get(index), - dureePartie = uiState.value.dureePartie, - nbPoints = uiState.value.nbPoints, - reponseChoisie = false - ) + Log.d("PostDelayed","je vais chercher la prochaine question") + updateQuestion(goToResult) }, - uiState.value.dureePartie * index + uiState.value.dureePartie ) } } } // NOTE : tpsReponse en ms - fun ajouterPoints(tpsReponse: Long) { + fun ajouterPoints(tpsReponse: Long, reponseId: Int) { + var isResponseValid = false + viewModelScope.launch { + kahootRepo.postReponse(_uiState.value.partie.code,1,reponseId) + isResponseValid = kahootRepo.isReponseValid.value + } if (tpsReponse < 0) { throw IllegalArgumentException("ERREUR: Temps négatif donné à l'ajout de points") } else if (tpsReponse > uiState.value.dureePartie) { @@ -57,12 +98,18 @@ class KahootViewModel( if (uiState.value.reponseChoisie) { return } - val nbPoints: Int = (uiState.value.dureePartie - tpsReponse).toInt() - _uiState.value = KahootUIState(uiState.value.question, + val nbPoints: Int = if (isResponseValid) { + (uiState.value.dureePartie - tpsReponse).toInt() + } else { + 0 + } + _uiState.value = KahootUIState( + questionPartie = uiState.value.questionPartie, dureePartie = uiState.value.dureePartie, nbPoints = uiState.value.nbPoints + nbPoints, reponseChoisie = true) } + companion object { val ApiFactory: ViewModelProvider.Factory = object : ViewModelProvider.Factory { @@ -71,7 +118,7 @@ class KahootViewModel( modelClass: Class ): T { return KahootViewModel( - QuestionAPIRepository() + KahootAPIRepository() ) as T } } diff --git a/android/app/src/main/java/fr/iut/sciencequest/viewModels/uiStates/KahootJoinUIState.kt b/android/app/src/main/java/fr/iut/sciencequest/viewModels/uiStates/KahootJoinUIState.kt new file mode 100644 index 0000000..20c93ce --- /dev/null +++ b/android/app/src/main/java/fr/iut/sciencequest/viewModels/uiStates/KahootJoinUIState.kt @@ -0,0 +1,5 @@ +package fr.iut.sciencequest.viewModels.uiStates + +data class KahootJoinUIState ( + val code: String = "" +) \ No newline at end of file diff --git a/android/app/src/main/java/fr/iut/sciencequest/viewModels/uiStates/KahootUIState.kt b/android/app/src/main/java/fr/iut/sciencequest/viewModels/uiStates/KahootUIState.kt index 1ee7ae9..6eceb70 100644 --- a/android/app/src/main/java/fr/iut/sciencequest/viewModels/uiStates/KahootUIState.kt +++ b/android/app/src/main/java/fr/iut/sciencequest/viewModels/uiStates/KahootUIState.kt @@ -1,11 +1,20 @@ package fr.iut.sciencequest.viewModels.uixStates import fr.iut.sciencequest.model.dto.extensions.ToModel +import fr.iut.sciencequest.model.metier.Difficulte +import fr.iut.sciencequest.model.metier.partie.Partie +import fr.iut.sciencequest.model.metier.partie.PartieKahoot +import fr.iut.sciencequest.model.metier.question.QuestionPartie import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse import fr.iut.sciencequest.stub.StubQuestionWithReponses +import kotlinx.datetime.LocalDateTime +import kotlinx.datetime.TimeZone +import kotlinx.datetime.toInstant data class KahootUIState ( - val question: QuestionWithSimpleReponse = StubQuestionWithReponses.ToModel(), + val partie: PartieKahoot = PartieKahoot(0,"", emptyList(), emptyList(), Difficulte(0,"")), + val questionPartie: QuestionPartie = QuestionPartie(QuestionWithSimpleReponse(0,"", emptyList()), LocalDateTime(1,1,1,1,1).toInstant( + TimeZone.UTC)), val reponseChoisie: Boolean = false, // NOTE : Supposé en millisecondes val dureePartie: Long = 10_000, diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 7c35053..e7fc56c 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -14,4 +14,8 @@ Si vous n\'avez pas encore de compte, vous avez deux possibilitées, soit vous continuez sans compte, soit vous vous inscrivez Coming soon... Nouvelle Partie + Rejoindre une Partie + Rejoindre + Joueurs dans la partie: + Lancer la partie \ No newline at end of file