Merge pull request 'RepositoryAndroid' (#25) from RepositoryAndroid into Android

Reviewed-on: tom.biard/ScienceQuest#25
je me fais confiance
Android
Renaud BEURET 1 year ago
commit 08cd13867d

@ -3,20 +3,7 @@
<component name="deploymentTargetDropDown"> <component name="deploymentTargetDropDown">
<value> <value>
<entry key="app"> <entry key="app">
<State> <State />
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="/local/avd/Pixel_7_Pro_API_34.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-03-21T10:47:15.864183783Z" />
</State>
</entry> </entry>
</value> </value>
</component> </component>

@ -1,18 +1,13 @@
package fr.iut.sciencequest package fr.iut.sciencequest
import android.os.Bundle import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import fr.iut.sciencequest.ViewModels.ScientifiquesDecouvertsVM
import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.navigation.NavHost import fr.iut.sciencequest.navigation.NavHost
import fr.iut.sciencequest.stub.StubScientifique1
import fr.iut.sciencequest.ui.theme.ScienceQuestTheme import fr.iut.sciencequest.ui.theme.ScienceQuestTheme
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {

@ -1,52 +0,0 @@
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}")
}
}

@ -1,38 +0,0 @@
package fr.iut.sciencequest.ViewModels
import android.util.Log
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.toMutableStateList
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import fr.iut.sciencequest.ViewModels.UiStates.ScientifiqueDecouvertsUIState
import fr.iut.sciencequest.model.buisness.Scientifique.fetchScientifiqueById
import fr.iut.sciencequest.model.buisness.Scientifique.fetchScientifiques
import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.model.metier.Scientifique
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
class ScientifiquesDecouvertsVM : ViewModel() {
var listeScientifique: MutableStateFlow<ScientifiqueDecouvertsUIState> = MutableStateFlow(ScientifiqueDecouvertsUIState())
// fun getScientifiqueById(id: Int) {
// Log.d("ViewModelScientifique", "Recup un scientifique d'id: $id")
// var scientifique: Scientifique
// viewModelScope.launch {
//
// }
// }
fun getScientifiques(page: Int) {
Log.d("ViewModelScientifique","Recup la liste de scientifiques")
viewModelScope.launch {
fetchScientifiques(page).collect {
listeScientifique.value = ScientifiqueDecouvertsUIState(it.scientifiques.ToModel().toMutableList())
}
}
}
}

@ -1,13 +0,0 @@
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
)

@ -1,22 +0,0 @@
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
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,30 @@
package fr.iut.sciencequest.model.dto.extensions
import fr.iut.sciencequest.model.dto.question.QuestionDTO
import fr.iut.sciencequest.model.dto.question.QuestionWithSimpleResponseDTO
import fr.iut.sciencequest.model.metier.question.Question
import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse
fun QuestionDTO.ToModel(): Question {
return Question(
this.id,
this.question,
this.reponses.ToModel()
)
}
fun List<QuestionDTO>.ToModel(): List<Question> {
val liste = mutableListOf<Question>()
for (question in this) {
liste.add(question.ToModel())
}
return liste
}
fun Question.ToQuestionWithSimpleReponse(): QuestionWithSimpleReponse {
return QuestionWithSimpleReponse(
this.id,
this.question,
this.reponses.ToSimpleReponses()
)
}

@ -0,0 +1,20 @@
package fr.iut.sciencequest.model.dto.extensions
import fr.iut.sciencequest.model.dto.question.QuestionWithSimpleResponseDTO
import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse
fun QuestionWithSimpleResponseDTO.ToModel(): QuestionWithSimpleReponse {
return QuestionWithSimpleReponse(
this.id,
this.question,
this.reponses.ToModel()
)
}
fun List<QuestionWithSimpleResponseDTO>.ToModel(): List<QuestionWithSimpleReponse> {
val liste = ArrayList<QuestionWithSimpleReponse>()
for (question in this) {
liste.add(question.ToModel())
}
return liste
}

@ -0,0 +1,37 @@
package fr.iut.sciencequest.model.dto.extensions
import fr.iut.sciencequest.model.dto.reponse.ReponseDTO
import fr.iut.sciencequest.model.metier.reponse.Reponse
import fr.iut.sciencequest.model.metier.reponse.ReponseSimple
fun ReponseDTO.ToModel(): Reponse {
return Reponse(
this.id,
this.reponse,
this.question.ToModel(),
this.scientifique.ToModel()
)
}
fun List<ReponseDTO>.ToModel(): List<Reponse> {
val liste = ArrayList<Reponse>()
for (reponse in this) {
liste.add(reponse.ToModel())
}
return liste
}
fun Reponse.ToSimpleReponse(): ReponseSimple {
return ReponseSimple(
this.id,
this.reponse
)
}
fun List<Reponse>.ToSimpleReponses(): List<ReponseSimple> {
val liste = ArrayList<ReponseSimple>()
for (reponse in this) {
liste.add(reponse.ToSimpleReponse())
}
return liste
}

@ -0,0 +1,19 @@
package fr.iut.sciencequest.model.dto.extensions
import fr.iut.sciencequest.model.dto.reponse.ReponseSimpleDTO
import fr.iut.sciencequest.model.metier.reponse.ReponseSimple
fun ReponseSimpleDTO.ToModel(): ReponseSimple {
return ReponseSimple(
this.id,
this.reponse
)
}
fun List<ReponseSimpleDTO>.ToModel(): List<ReponseSimple> {
val liste = ArrayList<ReponseSimple>()
for (reponse in this) {
liste.add(reponse.ToModel())
}
return liste
}

@ -1,7 +0,0 @@
package fr.iut.sciencequest.model.metier
class Question(
val id: Int,
val question: String,
val reponses: List<Reponse>
) {}

@ -1,9 +0,0 @@
package fr.iut.sciencequest.model.metier
class Reponse (
val id: Int,
val reponse: String,
val question: Question,
val scientifique: Scientifique
) {}

@ -0,0 +1,10 @@
package fr.iut.sciencequest.model.metier.question
import fr.iut.sciencequest.model.metier.reponse.Reponse
class Question(
val id: Int,
val question: String,
val reponses: List<Reponse>
) {}

@ -0,0 +1,10 @@
package fr.iut.sciencequest.model.metier.question
import fr.iut.sciencequest.model.metier.reponse.Reponse
import fr.iut.sciencequest.model.metier.reponse.ReponseSimple
class QuestionWithSimpleReponse (
val id: Int,
val question: String,
val reponses: List<ReponseSimple>
)

@ -0,0 +1,12 @@
package fr.iut.sciencequest.model.metier.reponse
import fr.iut.sciencequest.model.metier.question.Question
import fr.iut.sciencequest.model.metier.Scientifique
class Reponse (
val id: Int,
val reponse: String,
val question: Question,
val scientifique: Scientifique
) {}

@ -0,0 +1,11 @@
package fr.iut.sciencequest.model.metier.reponse
class ReponseSimple {
val id: Int
val reponse: String
constructor(id: Int, reponse: String) {
this.id = id
this.reponse = reponse
}
}

@ -0,0 +1,11 @@
package fr.iut.sciencequest.model.repositories.question
import fr.iut.sciencequest.model.metier.question.Question
import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
interface IQuestionRepository {
val questions: StateFlow<List<QuestionWithSimpleReponse>>
suspend fun fetchQuestions(index: Int)
}

@ -0,0 +1,31 @@
package fr.iut.sciencequest.model.repositories.question
import android.util.Log
import fr.iut.sciencequest.model.buisness.Question.QuestionRequestService
import fr.iut.sciencequest.model.buisness.createRequestService
import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.model.metier.question.Question
import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.update
import retrofit2.create
class QuestionAPIRepository : IQuestionRepository {
private val _questions = MutableStateFlow<List<QuestionWithSimpleReponse>>(emptyList())
override val questions: StateFlow<List<QuestionWithSimpleReponse>>
get() = _questions.asStateFlow()
override suspend fun fetchQuestions(index: Int) {
val serviceClient = createRequestService().create<QuestionRequestService>()
try {
_questions.value = serviceClient.getQuestions(index).questions.ToModel()
} catch (e: Exception) {
Log.e("Requete API Question", e.message.toString())
}
}
}

@ -0,0 +1,14 @@
package fr.iut.sciencequest.model.repositories.scientifique
import fr.iut.sciencequest.model.metier.Scientifique
import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.StateFlow
interface IScientifiqueRepository {
val scientifique: StateFlow<Scientifique>
val scientifiques: StateFlow<List<Scientifique>>
suspend fun fetchScientifiques(index: Int)
suspend fun fetchScientifiqueById(id: Int)
}

@ -0,0 +1,44 @@
package fr.iut.sciencequest.model.repositories.scientifique
import android.util.Log
import fr.iut.sciencequest.model.buisness.Question.QuestionRequestService
import fr.iut.sciencequest.model.buisness.Scientifique.ScientifiqueRequestService
import fr.iut.sciencequest.model.buisness.createRequestService
import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.model.metier.Scientifique
import fr.iut.sciencequest.stub.StubScientifique1
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flow
import retrofit2.create
class ScientifiqueAPIRepository: IScientifiqueRepository {
private val _scientifique = MutableStateFlow(StubScientifique1.ToModel())
override val scientifique: StateFlow<Scientifique>
get() = _scientifique.asStateFlow()
private val _scientifiques = MutableStateFlow<List<Scientifique>>(emptyList())
override val scientifiques: StateFlow<List<Scientifique>>
get() = _scientifiques.asStateFlow()
override suspend fun fetchScientifiqueById(id: Int) {
val serviceClient = createRequestService().create<ScientifiqueRequestService>()
try {
_scientifique.value = serviceClient.getScientifique(id).ToModel()
} catch (e: Exception) {
Log.e("Requete API Scientifiqu", e.message.toString())
}
}
override suspend fun fetchScientifiques(index: Int) {
val serviceClient = createRequestService().create<ScientifiqueRequestService>()
try {
_scientifiques.value = serviceClient.getScientifiques(index).scientifiques.ToModel()
} catch (e: Exception) {
Log.e("Requete API Scientifiqu", e.message.toString())
}
}
}

@ -0,0 +1,39 @@
package fr.iut.sciencequest.model.repositories.scientifique
import android.content.res.Resources.NotFoundException
import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.model.metier.Scientifique
import fr.iut.sciencequest.stub.StubScientifique1
import fr.iut.sciencequest.stub.StubScientifique2
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class ScientifiqueStubRepostory : IScientifiqueRepository {
private var listeStub : MutableList<Scientifique> = mutableListOf(
StubScientifique1.ToModel(),
StubScientifique2.ToModel()
)
private val _scientifique = MutableStateFlow(StubScientifique1.ToModel())
override val scientifique: StateFlow<Scientifique>
get() = _scientifique.asStateFlow()
private val _scientifiques = MutableStateFlow<List<Scientifique>>(emptyList())
override val scientifiques: StateFlow<List<Scientifique>>
get() = _scientifiques.asStateFlow()
override suspend fun fetchScientifiques(index: Int) {
_scientifiques.value = listeStub
}
override suspend fun fetchScientifiqueById(id: Int) {
val retrieved = listeStub.find {
it.id == id
} ?: throw NotFoundException("Scientifique introuvable dans le stub")
_scientifique.value = retrieved
}
fun setScientifiqueStubList(scientifiques: MutableList<Scientifique>) {
listeStub = scientifiques
}
}

@ -1,17 +1,11 @@
package fr.iut.sciencequest.navigation package fr.iut.sciencequest.navigation
import android.content.Context
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController 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
import fr.iut.sciencequest.view.AccountScreen import fr.iut.sciencequest.view.AccountScreen
import fr.iut.sciencequest.view.HomeScreen import fr.iut.sciencequest.view.HomeScreen
import fr.iut.sciencequest.view.LoginScreen import fr.iut.sciencequest.view.LoginScreen
@ -22,7 +16,7 @@ import fr.iut.sciencequest.view.scientifiques.scientifiqueListeScreen
@Composable @Composable
fun NavHost(kahootVM: KahootViewModel = viewModel(), penduVM: PenduViewModel = viewModel()) { fun NavHost() {
val navController = rememberNavController() val navController = rememberNavController()
NavHost( NavHost(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
@ -38,11 +32,9 @@ fun NavHost(kahootVM: KahootViewModel = viewModel(), penduVM: PenduViewModel = v
navController.navigate("home") navController.navigate("home")
}, },
goToPendu = { goToPendu = {
penduVM.InitPartie()
navController.navigate("pendu") navController.navigate("pendu")
}, },
goToKahoot = { goToKahoot = {
kahootVM.lancerPartie()
navController.navigate("kahoot") navController.navigate("kahoot")
}, },
goToQui = { goToQui = {
@ -75,7 +67,6 @@ fun NavHost(kahootVM: KahootViewModel = viewModel(), penduVM: PenduViewModel = v
composable(route = "pendu") { composable(route = "pendu") {
PenduScreen( PenduScreen(
viewModel = penduVM,
goToAccount = { goToAccount = {
navController.navigate("account") navController.navigate("account")
}, },
@ -92,8 +83,7 @@ fun NavHost(kahootVM: KahootViewModel = viewModel(), penduVM: PenduViewModel = v
}, },
goToHome = { goToHome = {
navController.navigate("home") navController.navigate("home")
}, }
viewModel = kahootVM
) )
} }

@ -14,8 +14,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.ViewModels.KahootViewModel
@Composable @Composable
fun HomeScreen(goToHome: () -> Unit, fun HomeScreen(goToHome: () -> Unit,

@ -26,7 +26,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.R import fr.iut.sciencequest.R
import fr.iut.sciencequest.ViewModels.LoginViewModel import fr.iut.sciencequest.viewModels.LoginViewModel
@Composable @Composable
fun LoginScreen(viewModel: LoginViewModel = viewModel(), fun LoginScreen(viewModel: LoginViewModel = viewModel(),

@ -11,6 +11,7 @@ import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -22,17 +23,21 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.R import fr.iut.sciencequest.R
import fr.iut.sciencequest.ViewModels.KahootViewModel import fr.iut.sciencequest.viewModels.KahootViewModel
import fr.iut.sciencequest.model.dto.question.QuestionWithSimpleResponseDTO import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.model.dto.reponse.ReponseSimpleDTO import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse
import fr.iut.sciencequest.model.metier.reponse.ReponseSimple
import fr.iut.sciencequest.stub.StubQuestionWithReponses import fr.iut.sciencequest.stub.StubQuestionWithReponses
import fr.iut.sciencequest.view.TopBar import fr.iut.sciencequest.view.TopBar
@Composable @Composable
fun KahootScreen(viewModel: KahootViewModel = viewModel(), fun KahootScreen(viewModel: KahootViewModel = viewModel(factory = KahootViewModel.ApiFactory),
goToAccount: () -> Unit, goToAccount: () -> Unit,
goToHome: () -> Unit) { goToHome: () -> Unit) {
val state = viewModel.uiState.collectAsState() val state = viewModel.uiState.collectAsState()
LaunchedEffect(key1 = Unit) {
viewModel.lancerPartie()
}
Column(modifier = Modifier.fillMaxWidth()) { Column(modifier = Modifier.fillMaxWidth()) {
TopBar(goToAccount, goToHome, stringResource(id = R.string.kahoot)) TopBar(goToAccount, goToHome, stringResource(id = R.string.kahoot))
@ -53,13 +58,14 @@ fun KahootScreenPreview(){
@Composable @Composable
fun KahootPlayerPreview(){ fun KahootPlayerPreview(){
val i = 0 val i = 0
KahootPlayer(question = StubQuestionWithReponses) {} KahootPlayer(question = StubQuestionWithReponses.ToModel()) {}
} }
@Composable @Composable
fun KahootPlayer(question: QuestionWithSimpleResponseDTO, fun KahootPlayer(question: QuestionWithSimpleReponse,
sendResponse: (Long) -> Unit){ sendReponse: (Long) -> Unit){
val context = LocalContext.current; val context = LocalContext.current;
val currTime = System.currentTimeMillis() val currTime = System.currentTimeMillis()
Column ( Column (
@ -69,7 +75,7 @@ fun KahootPlayer(question: QuestionWithSimpleResponseDTO,
) { ) {
KahootQuestion(question = question.question) KahootQuestion(question = question.question)
KahootReponses(reponses = question.reponses) { KahootReponses(reponses = question.reponses) {
sendResponse(currTime - System.currentTimeMillis()) sendReponse(currTime - System.currentTimeMillis())
Toast.makeText(context, it.reponse, Toast.LENGTH_SHORT).show() Toast.makeText(context, it.reponse, Toast.LENGTH_SHORT).show()
} }
} }
@ -77,7 +83,7 @@ fun KahootPlayer(question: QuestionWithSimpleResponseDTO,
@Composable @Composable
fun KahootReponses(reponses : List<ReponseSimpleDTO>, action: (ReponseSimpleDTO)->Unit) { fun KahootReponses(reponses : List<ReponseSimple>, action: (ReponseSimple)->Unit) {
LazyVerticalGrid(columns = GridCells.Fixed(2), LazyVerticalGrid(columns = GridCells.Fixed(2),
contentPadding = PaddingValues(12.dp), contentPadding = PaddingValues(12.dp),
verticalArrangement = Arrangement.spacedBy(10.dp), verticalArrangement = Arrangement.spacedBy(10.dp),

@ -22,11 +22,11 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.R import fr.iut.sciencequest.R
import fr.iut.sciencequest.ViewModels.PenduViewModel import fr.iut.sciencequest.viewModels.PenduViewModel
import fr.iut.sciencequest.view.TopBar import fr.iut.sciencequest.view.TopBar
@Composable @Composable
fun PenduScreen(viewModel: PenduViewModel = viewModel(), fun PenduScreen(viewModel: PenduViewModel = viewModel(factory = PenduViewModel.ApiFactory),
goToAccount: () -> Unit, goToAccount: () -> Unit,
goToHome: () -> Unit goToHome: () -> Unit
) { ) {

@ -20,11 +20,14 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.R import fr.iut.sciencequest.R
import fr.iut.sciencequest.ViewModels.KahootViewModel import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.model.dto.question.QuestionWithSimpleResponseDTO import fr.iut.sciencequest.model.dto.question.QuestionWithSimpleResponseDTO
import fr.iut.sciencequest.model.dto.reponse.ReponseSimpleDTO import fr.iut.sciencequest.model.dto.reponse.ReponseSimpleDTO
import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse
import fr.iut.sciencequest.model.metier.reponse.ReponseSimple
import fr.iut.sciencequest.stub.StubQuestionWithReponses import fr.iut.sciencequest.stub.StubQuestionWithReponses
import fr.iut.sciencequest.view.TopBar import fr.iut.sciencequest.view.TopBar
import fr.iut.sciencequest.viewModels.KahootViewModel
import java.util.Timer import java.util.Timer
@Composable @Composable
@ -51,12 +54,12 @@ fun QuiScreenPreview(){
@Composable @Composable
fun QuiPlayerPreview(){ fun QuiPlayerPreview(){
val i = 0 val i = 0
QuiPlayer(question = StubQuestionWithReponses) {} QuiPlayer(question = StubQuestionWithReponses.ToModel()) {}
} }
@Composable @Composable
fun QuiPlayer(question: QuestionWithSimpleResponseDTO, fun QuiPlayer(question: QuestionWithSimpleReponse,
sendReponse: (Long) -> Unit){ sendReponse: (Long) -> Unit){
val context = LocalContext.current; val context = LocalContext.current;
val currTime = System.currentTimeMillis() val currTime = System.currentTimeMillis()
@ -71,7 +74,7 @@ fun QuiPlayer(question: QuestionWithSimpleResponseDTO,
@Composable @Composable
fun QuiReponses(reponses : List<ReponseSimpleDTO>, action: (ReponseSimpleDTO)->Unit) { fun QuiReponses(reponses : List<ReponseSimple>, action: (ReponseSimple)->Unit) {
LazyVerticalGrid(columns = GridCells.Fixed(2), LazyVerticalGrid(columns = GridCells.Fixed(2),
contentPadding = PaddingValues(12.dp), contentPadding = PaddingValues(12.dp),
verticalArrangement = Arrangement.spacedBy(10.dp), verticalArrangement = Arrangement.spacedBy(10.dp),

@ -1,22 +1,18 @@
package fr.iut.sciencequest.view.scientifiques package fr.iut.sciencequest.view.scientifiques
import android.util.Log
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import fr.iut.sciencequest.R import fr.iut.sciencequest.R
import fr.iut.sciencequest.ViewModels.ScientifiquesDecouvertsVM import fr.iut.sciencequest.viewModels.ScientifiquesDecouvertsVM
import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.model.metier.Scientifique
import fr.iut.sciencequest.stub.getScientifiqueListeStub
import fr.iut.sciencequest.view.TopBar import fr.iut.sciencequest.view.TopBar
@Composable @Composable
fun scientifiqueListeScreen(viewModel: ScientifiquesDecouvertsVM = viewModel(), fun scientifiqueListeScreen(viewModel: ScientifiquesDecouvertsVM = viewModel(factory = ScientifiquesDecouvertsVM.ApiFactory),
goToAccount: () -> Unit, goToAccount: () -> Unit,
goToHome: () -> Unit) { goToHome: () -> Unit) {
val liste by viewModel.listeScientifique.collectAsState() val liste by viewModel.listeScientifique.collectAsState()
@ -25,7 +21,9 @@ fun scientifiqueListeScreen(viewModel: ScientifiquesDecouvertsVM = viewModel(),
TopBar(goToAccount, goToHome, stringResource(id = R.string.sc_decouverts)) TopBar(goToAccount, goToHome, stringResource(id = R.string.sc_decouverts))
}, },
) { innerPadding -> ) { innerPadding ->
viewModel.getScientifiques(1) LaunchedEffect(key1 = Unit) {
viewModel.getScientifiques(1)
}
scientifiqueListeContainer(liste.scientifiques, innerPadding) scientifiqueListeContainer(liste.scientifiques, innerPadding)
} }
} }

@ -0,0 +1,72 @@
package fr.iut.sciencequest.viewModels
import android.os.Handler
import android.os.Looper
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.viewModels.uixStates.KahootUIState
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
class KahootViewModel(
val questionRepo: IQuestionRepository
): ViewModel() {
var uiState = MutableStateFlow(KahootUIState())
private val handler = Handler(Looper.getMainLooper())
fun lancerPartie() {
viewModelScope.launch {
questionRepo.fetchQuestions(2)
Log.d("KahootViewModel","J'ai trouvé ${questionRepo.questions.value.size} questions")
var count = 1
for (question in questionRepo.questions.value) {
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 * count
)
count++
}
}
}
// 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}")
}
companion object {
val ApiFactory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(
modelClass: Class<T>
): T {
return KahootViewModel(
QuestionAPIRepository()
) as T
}
}
}
}

@ -1,7 +1,7 @@
package fr.iut.sciencequest.ViewModels package fr.iut.sciencequest.viewModels
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import fr.iut.sciencequest.ViewModels.UiStates.LoginUIState import fr.iut.sciencequest.viewModels.uiStates.LoginUIState
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
class LoginViewModel: ViewModel() { class LoginViewModel: ViewModel() {

@ -1,32 +1,33 @@
package fr.iut.sciencequest.ViewModels package fr.iut.sciencequest.viewModels
import android.util.Log import android.util.Log
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import fr.iut.sciencequest.ViewModels.UiStates.PenduUIState import fr.iut.sciencequest.viewModels.uiStates.PenduUIState
import fr.iut.sciencequest.model.buisness.Scientifique.fetchScientifiqueById import fr.iut.sciencequest.model.repositories.scientifique.IScientifiqueRepository
import fr.iut.sciencequest.model.buisness.Scientifique.fetchScientifiquesInfos import fr.iut.sciencequest.model.repositories.scientifique.ScientifiqueAPIRepository
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class PenduViewModel : ViewModel() { class PenduViewModel(
val scientifiqueRepo: IScientifiqueRepository
) : ViewModel() {
var uiState = MutableStateFlow(PenduUIState()) var uiState = MutableStateFlow(PenduUIState())
fun InitPartie() { fun InitPartie() {
Log.d("PenduViewModel","Un utilisateur initialise une partie") Log.d("PenduViewModel","Un utilisateur initialise une partie")
viewModelScope.launch { viewModelScope.launch {
fetchScientifiquesInfos().collect { scientifiquesInfos -> scientifiqueRepo.fetchScientifiqueById(1)
Log.e("PenduViewModel",scientifiquesInfos.nbScientfiques.toString()) val scientifique = scientifiqueRepo.scientifique.value
fetchScientifiqueById((1..scientifiquesInfos.nbScientfiques).random()).collect { val nomComplet = scientifique.prenom + " " + scientifique.nom
val nomComplet = it.prenom + " " + it.nom Log.d("ViewModelPendu",nomComplet)
Log.d("ViewModelPendu",nomComplet) var motATrou = ""
var motATrou = "" for (chr in nomComplet) {
for (chr in nomComplet) { motATrou += if (chr == ' ') {
motATrou += if (chr == ' ') { ' '
' ' } else {
} else { '_'
'_'
}
} }
uiState.value = PenduUIState( uiState.value = PenduUIState(
isActionGood = true, isActionGood = true,
@ -37,7 +38,6 @@ class PenduViewModel : ViewModel() {
} }
} }
}
// mot : mot à trouver // mot : mot à trouver
// motAct : état actuel du mot trouvé par l'utilisateur // motAct : état actuel du mot trouvé par l'utilisateur
@ -84,4 +84,17 @@ class PenduViewModel : ViewModel() {
) )
} }
} }
companion object {
val ApiFactory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(
modelClass: Class<T>
): T {
return PenduViewModel(
ScientifiqueAPIRepository()
) as T
}
}
}
} }

@ -0,0 +1,40 @@
package fr.iut.sciencequest.viewModels
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope
import fr.iut.sciencequest.viewModels.uiStates.ScientifiqueDecouvertsUIState
import fr.iut.sciencequest.model.repositories.scientifique.IScientifiqueRepository
import fr.iut.sciencequest.model.repositories.scientifique.ScientifiqueAPIRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
class ScientifiquesDecouvertsVM(
val repository: IScientifiqueRepository
) : ViewModel() {
private val _listeScientifique: MutableStateFlow<ScientifiqueDecouvertsUIState> = MutableStateFlow(ScientifiqueDecouvertsUIState())
val listeScientifique = _listeScientifique.asStateFlow()
fun getScientifiques(page: Int) {
Log.d("ViewModelScientifique","Recup la liste de scientifiques")
viewModelScope.launch {
repository.fetchScientifiques(page)
_listeScientifique.value = ScientifiqueDecouvertsUIState(repository.scientifiques.value.toMutableList())
}
}
companion object {
val ApiFactory: ViewModelProvider.Factory = object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(
modelClass: Class<T>
): T {
return ScientifiquesDecouvertsVM(
ScientifiqueAPIRepository()
) as T
}
}
}
}

@ -0,0 +1,13 @@
package fr.iut.sciencequest.viewModels.uixStates
import fr.iut.sciencequest.model.dto.extensions.ToModel
import fr.iut.sciencequest.model.metier.question.QuestionWithSimpleReponse
import fr.iut.sciencequest.stub.StubQuestionWithReponses
data class KahootUIState (
val question: QuestionWithSimpleReponse = StubQuestionWithReponses.ToModel(),
val reponseChoisie: Boolean = false,
// NOTE : Supposé en millisecondes
val duréePartie: Long = 10_000,
val nbPoints: Int = 0
)

@ -1,4 +1,4 @@
package fr.iut.sciencequest.ViewModels.UiStates package fr.iut.sciencequest.viewModels.uiStates
data class LoginUIState ( data class LoginUIState (
val pseudo: String = "Pseudo", val pseudo: String = "Pseudo",

@ -1,4 +1,4 @@
package fr.iut.sciencequest.ViewModels.UiStates package fr.iut.sciencequest.viewModels.uiStates
data class PenduUIState( data class PenduUIState(
val isWon: Boolean = false, val isWon: Boolean = false,

@ -1,4 +1,4 @@
package fr.iut.sciencequest.ViewModels.UiStates package fr.iut.sciencequest.viewModels.uiStates
import fr.iut.sciencequest.model.metier.Scientifique import fr.iut.sciencequest.model.metier.Scientifique
Loading…
Cancel
Save