From f821406578ff94189588c7bd2b11b91949533cf1 Mon Sep 17 00:00:00 2001 From: Faraphel Date: Thu, 30 May 2024 21:09:57 +0200 Subject: [PATCH] rewrote the database, added the entire session system, updated the api with it, continued the UI --- app/build.gradle.kts | 1 + .../faraphel/tasks_valider/MainActivity.kt | 28 ++- .../connectivity/task/TaskClient.kt | 1 + .../connectivity/task/TaskServer.kt | 12 +- .../tasks_valider/database/TaskDatabase.kt | 2 + .../database/api/TaskDatabaseApi.kt | 20 +- .../database/api/entities/ClassApi.kt | 8 +- .../database/api/entities/PersonApi.kt | 8 +- .../api/entities/RelationClassPersonApi.kt | 9 +- .../RelationPersonSessionSubjectApi.kt | 10 + .../database/api/entities/SessionApi.kt | 7 +- .../database/api/entities/SubjectApi.kt | 9 +- .../database/api/entities/TaskApi.kt | 9 +- .../database/api/entities/ValidationApi.kt | 9 +- .../database/api/entities/base/BaseApi.kt | 10 +- .../database/api/entities/base/BaseJsonApi.kt | 18 +- .../database/api/entities/base/BaseTaskApi.kt | 49 +++++ .../tasks_valider/database/dao/ClassDao.kt | 16 +- .../tasks_valider/database/dao/PersonDao.kt | 19 +- .../database/dao/RelationClassPersonDao.kt | 23 ++- .../dao/RelationPersonSessionSubjectDao.kt | 32 ++++ .../tasks_valider/database/dao/SessionDao.kt | 10 +- .../tasks_valider/database/dao/SubjectDao.kt | 17 +- .../tasks_valider/database/dao/TaskDao.kt | 16 +- .../database/dao/ValidationDao.kt | 19 +- .../dao/base/{BaseDao.kt => BaseCronDao.kt} | 8 +- .../database/dao/base/BaseSessionDao.kt | 11 ++ .../database/dao/base/BaseTaskDao.kt | 6 + .../RelationPersonSessionSubjectEntity.kt | 48 +++++ .../faraphel/tasks_valider/database/test.kt | 16 ++ .../communication/internet/selection.kt | 8 +- .../screen/communication/internet/server.kt | 176 +++++++++++------- .../ui/screen/communication/selection.kt | 10 +- .../tasks_valider/ui/screen/task/session.kt | 8 +- .../tasks_valider/ui/screen/task/student.kt | 81 +++++++- 35 files changed, 583 insertions(+), 151 deletions(-) create mode 100644 app/src/main/java/com/faraphel/tasks_valider/database/api/entities/RelationPersonSessionSubjectApi.kt create mode 100644 app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseTaskApi.kt create mode 100644 app/src/main/java/com/faraphel/tasks_valider/database/dao/RelationPersonSessionSubjectDao.kt rename app/src/main/java/com/faraphel/tasks_valider/database/dao/base/{BaseDao.kt => BaseCronDao.kt} (82%) create mode 100644 app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseSessionDao.kt create mode 100644 app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseTaskDao.kt create mode 100644 app/src/main/java/com/faraphel/tasks_valider/database/entities/RelationPersonSessionSubjectEntity.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index c904fdf..ee6f05e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -76,4 +76,5 @@ dependencies { debugImplementation("androidx.compose.ui:ui-tooling") debugImplementation("androidx.compose.ui:ui-test-manifest") ksp("androidx.room:room-compiler:2.6.1") + implementation(kotlin("reflect")) } diff --git a/app/src/main/java/com/faraphel/tasks_valider/MainActivity.kt b/app/src/main/java/com/faraphel/tasks_valider/MainActivity.kt index 9d897df..5c9b6fc 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/MainActivity.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/MainActivity.kt @@ -6,24 +6,42 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.annotation.RequiresApi +import androidx.room.Room import com.faraphel.tasks_valider.connectivity.bwf.BwfManager import com.faraphel.tasks_valider.database.TaskDatabase +import com.faraphel.tasks_valider.database.populateTaskDatabaseTest import com.faraphel.tasks_valider.ui.screen.communication.CommunicationModeSelectionScreen class MainActivity : ComponentActivity() { private var bwfManager: BwfManager? = null ///< the WiFi-Direct helper - - companion object { - private lateinit var database: TaskDatabase ///< the database manager - } + private lateinit var database: TaskDatabase ///< the database manager @RequiresApi(Build.VERSION_CODES.O) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + // Reset the database | TODO(Faraphel): only for testing purpose + this.deleteDatabase("local") + + // Create the database + this.database = Room.databaseBuilder( + this, + TaskDatabase::class.java, + "local" + ).build() + + // Populate the database with test data + // TODO(Faraphel): remove test data + Thread { + populateTaskDatabaseTest(database) + }.let { thread -> + thread.start() + thread.join() + } + this.setContent { - CommunicationModeSelectionScreen(this) + CommunicationModeSelectionScreen(this, database) } } diff --git a/app/src/main/java/com/faraphel/tasks_valider/connectivity/task/TaskClient.kt b/app/src/main/java/com/faraphel/tasks_valider/connectivity/task/TaskClient.kt index b1917e1..2ca14f3 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/connectivity/task/TaskClient.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/connectivity/task/TaskClient.kt @@ -3,6 +3,7 @@ package com.faraphel.tasks_valider.connectivity.task import okhttp3.HttpUrl import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient +import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody diff --git a/app/src/main/java/com/faraphel/tasks_valider/connectivity/task/TaskServer.kt b/app/src/main/java/com/faraphel/tasks_valider/connectivity/task/TaskServer.kt index 2eb7b6b..0654c30 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/connectivity/task/TaskServer.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/connectivity/task/TaskServer.kt @@ -5,21 +5,25 @@ import com.faraphel.tasks_valider.connectivity.task.session.TaskSessionManager import com.faraphel.tasks_valider.database.TaskDatabase import com.faraphel.tasks_valider.database.api.TaskDatabaseApi import com.faraphel.tasks_valider.database.entities.PersonEntity +import com.faraphel.tasks_valider.database.entities.SessionEntity import fi.iki.elonen.NanoHTTPD /** * A server to handle the task API to allow clients to interact with the database. - * @param port the port of the server - * @param database the database to interact with + * @param port the port of the server. + * @param database the database to interact with. + * @param session the current session. + * @param adminPersonEntity the person that represent the host of the session. */ class TaskServer( private val port: Int, private val database: TaskDatabase, - adminPersonEntity: PersonEntity, + private val session: SessionEntity, + private val adminPersonEntity: PersonEntity, ) : NanoHTTPD(port) { private val sessionManager = TaskSessionManager(adminPersonEntity) ///< the session manager - private val databaseApi = TaskDatabaseApi(this.database) ///< the api of the database + private val databaseApi = TaskDatabaseApi(this.database, session) ///< the api of the database private val sessionManagerApi = TaskSessionManagerApi(this.sessionManager, this.database) ///< the api of the session manager /** diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/TaskDatabase.kt b/app/src/main/java/com/faraphel/tasks_valider/database/TaskDatabase.kt index f2ff03e..80754d6 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/TaskDatabase.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/TaskDatabase.kt @@ -22,6 +22,7 @@ import com.faraphel.tasks_valider.database.entities.* ValidationEntity::class, RelationClassPersonEntity::class, + RelationPersonSessionSubjectEntity::class, ], version = 1 ) @@ -37,4 +38,5 @@ abstract class TaskDatabase: RoomDatabase() { abstract fun validationDao(): ValidationDao abstract fun relationClassPersonDao(): RelationClassPersonDao + abstract fun relationPersonSessionSubjectDao(): RelationPersonSessionSubjectDao } diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/TaskDatabaseApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/TaskDatabaseApi.kt index 90312e4..943c880 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/TaskDatabaseApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/TaskDatabaseApi.kt @@ -8,16 +8,20 @@ import com.faraphel.tasks_valider.database.api.entities.base.BaseApi import com.faraphel.tasks_valider.database.entities.* import fi.iki.elonen.NanoHTTPD -class TaskDatabaseApi(private val database: TaskDatabase) { +class TaskDatabaseApi( + private val database: TaskDatabase, + private val session: SessionEntity, +) { private val api: Map = mapOf( - ClassEntity.TABLE_NAME to ClassApi(this.database.classDao()), - PersonEntity.TABLE_NAME to PersonApi(this.database.personDao()), - SessionEntity.TABLE_NAME to SessionApi(this.database.sessionDao()), - SubjectEntity.TABLE_NAME to SubjectApi(this.database.subjectDao()), - TaskEntity.TABLE_NAME to TaskApi(this.database.taskDao()), - ValidationEntity.TABLE_NAME to ValidationApi(this.database.validationDao()), + ClassEntity.TABLE_NAME to ClassApi(this.database.classDao(), session), + PersonEntity.TABLE_NAME to PersonApi(this.database.personDao(), session), + SessionEntity.TABLE_NAME to SessionApi(this.database.sessionDao(), session), + SubjectEntity.TABLE_NAME to SubjectApi(this.database.subjectDao(), session), + TaskEntity.TABLE_NAME to TaskApi(this.database.taskDao(), session), + ValidationEntity.TABLE_NAME to ValidationApi(this.database.validationDao(), session), - RelationClassPersonEntity.TABLE_NAME to RelationClassPersonApi(this.database.relationClassPersonDao()), + RelationClassPersonEntity.TABLE_NAME to RelationClassPersonApi(this.database.relationClassPersonDao(), session), + RelationPersonSessionSubjectEntity.TABLE_NAME to RelationPersonSessionSubjectApi(this.database.relationPersonSessionSubjectDao(), session), ) /** diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/ClassApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/ClassApi.kt index a012aa2..bbfe608 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/ClassApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/ClassApi.kt @@ -1,7 +1,9 @@ package com.faraphel.tasks_valider.database.api.entities -import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao import com.faraphel.tasks_valider.database.entities.ClassEntity +import com.faraphel.tasks_valider.database.entities.SessionEntity -class ClassApi(dao: BaseDao) : BaseJsonApi(dao) +class ClassApi(dao: BaseTaskDao, session: SessionEntity) : + BaseTaskApi(dao, session) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/PersonApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/PersonApi.kt index d9edf18..eb8a8b8 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/PersonApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/PersonApi.kt @@ -1,7 +1,9 @@ package com.faraphel.tasks_valider.database.api.entities -import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao import com.faraphel.tasks_valider.database.entities.PersonEntity +import com.faraphel.tasks_valider.database.entities.SessionEntity -class PersonApi(dao: BaseDao) : BaseJsonApi(dao) +class PersonApi(dao: BaseTaskDao, session: SessionEntity) : + BaseTaskApi(dao, session) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/RelationClassPersonApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/RelationClassPersonApi.kt index 3f437b5..e2395e9 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/RelationClassPersonApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/RelationClassPersonApi.kt @@ -1,7 +1,10 @@ package com.faraphel.tasks_valider.database.api.entities -import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity +import com.faraphel.tasks_valider.database.entities.SessionEntity -class RelationClassPersonApi(dao: BaseDao) : BaseJsonApi(dao) + +class RelationClassPersonApi(dao: BaseTaskDao, session: SessionEntity) : + BaseTaskApi(dao, session) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/RelationPersonSessionSubjectApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/RelationPersonSessionSubjectApi.kt new file mode 100644 index 0000000..5b2983b --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/RelationPersonSessionSubjectApi.kt @@ -0,0 +1,10 @@ +package com.faraphel.tasks_valider.database.api.entities + +import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity +import com.faraphel.tasks_valider.database.entities.SessionEntity + + +class RelationPersonSessionSubjectApi(dao: BaseTaskDao, session: SessionEntity) : + BaseTaskApi(dao, session) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/SessionApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/SessionApi.kt index 2eb7dc2..cfad134 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/SessionApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/SessionApi.kt @@ -1,7 +1,8 @@ package com.faraphel.tasks_valider.database.api.entities -import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao import com.faraphel.tasks_valider.database.entities.SessionEntity -class SessionApi(dao: BaseDao) : BaseJsonApi(dao) +class SessionApi(dao: BaseTaskDao, session: SessionEntity) : + BaseTaskApi(dao, session) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/SubjectApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/SubjectApi.kt index caca63a..383e3ed 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/SubjectApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/SubjectApi.kt @@ -1,7 +1,10 @@ package com.faraphel.tasks_valider.database.api.entities -import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.SessionEntity import com.faraphel.tasks_valider.database.entities.SubjectEntity -class SubjectApi(dao: BaseDao) : BaseJsonApi(dao) + +class SubjectApi(dao: BaseTaskDao, session: SessionEntity) : + BaseTaskApi(dao, session) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/TaskApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/TaskApi.kt index c331a98..f56a317 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/TaskApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/TaskApi.kt @@ -1,7 +1,10 @@ package com.faraphel.tasks_valider.database.api.entities -import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.SessionEntity import com.faraphel.tasks_valider.database.entities.TaskEntity -class TaskApi(dao: BaseDao) : BaseJsonApi(dao) + +class TaskApi(dao: BaseTaskDao, session: SessionEntity) : + BaseTaskApi(dao, session) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/ValidationApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/ValidationApi.kt index 60e3010..4326afc 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/ValidationApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/ValidationApi.kt @@ -1,7 +1,10 @@ package com.faraphel.tasks_valider.database.api.entities -import com.faraphel.tasks_valider.database.api.entities.base.BaseJsonApi -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.api.entities.base.BaseTaskApi +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.SessionEntity import com.faraphel.tasks_valider.database.entities.ValidationEntity -class ValidationApi(dao: BaseDao) : BaseJsonApi(dao) + +class ValidationApi(dao: BaseTaskDao, session: SessionEntity) : + BaseTaskApi(dao, session) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseApi.kt index d40665e..535861f 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseApi.kt @@ -10,23 +10,23 @@ interface BaseApi { * Handle the HEAD request * This is used to check if a data exists in the database */ - fun head(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response + fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response /** * Handle the GET request - * This is used to get data from the database + * This is used to get all the data of a table from the database */ - fun get(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response + fun get(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response /** * Handle the POST request * This is used to insert data into the database */ - fun post(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response + fun post(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response /** * Handle the PUT request * This is used to delete data from the database */ - fun delete(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response + fun delete(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response } \ No newline at end of file diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseJsonApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseJsonApi.kt index 4668feb..70bfa15 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseJsonApi.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseJsonApi.kt @@ -1,6 +1,6 @@ package com.faraphel.tasks_valider.database.api.entities.base -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao import com.faraphel.tasks_valider.database.entities.base.BaseEntity import com.google.gson.Gson import com.google.gson.reflect.TypeToken @@ -11,7 +11,7 @@ import fi.iki.elonen.NanoHTTPD * This is preconfigured to handle JSON data. * @param Entity the entity type to handle */ -abstract class BaseJsonApi(private val dao: BaseDao) : BaseApi { +abstract class BaseJsonApi(private val dao: BaseCronDao) : BaseApi { companion object { private val parser = Gson() ///< The JSON parser } @@ -20,9 +20,9 @@ abstract class BaseJsonApi(private val dao: BaseDao) // Requests - override fun head(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { + override fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { val obj = parser.fromJson( - session.inputStream.bufferedReader().readText(), + httpSession.inputStream.bufferedReader().readText(), this.entityTypeToken.type ) val exists = this.dao.exists(obj) @@ -34,7 +34,7 @@ abstract class BaseJsonApi(private val dao: BaseDao) ) } - override fun get(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { + override fun get(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { return NanoHTTPD.newFixedLengthResponse( NanoHTTPD.Response.Status.OK, "application/json", @@ -42,9 +42,9 @@ abstract class BaseJsonApi(private val dao: BaseDao) ) } - override fun post(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { + override fun post(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { val obj = parser.fromJson( - session.inputStream.bufferedReader().readText(), + httpSession.inputStream.bufferedReader().readText(), this.entityTypeToken.type ) val id = this.dao.insert(obj) @@ -56,9 +56,9 @@ abstract class BaseJsonApi(private val dao: BaseDao) ) } - override fun delete(session: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { + override fun delete(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { val obj = parser.fromJson( - session.inputStream.bufferedReader().readText(), + httpSession.inputStream.bufferedReader().readText(), this.entityTypeToken.type ) val count = this.dao.delete(obj) diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseTaskApi.kt b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseTaskApi.kt new file mode 100644 index 0000000..5e29abb --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/database/api/entities/base/BaseTaskApi.kt @@ -0,0 +1,49 @@ +package com.faraphel.tasks_valider.database.api.entities.base + +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.SessionEntity +import com.faraphel.tasks_valider.database.entities.base.BaseEntity +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken +import fi.iki.elonen.NanoHTTPD + +/** + * A base for the API to handle the database operations. + * This is preconfigured to handle data for Task objects. + * @param Entity the entity type to handle + */ +abstract class BaseTaskApi( + private val dao: BaseTaskDao, + private val session: SessionEntity, +) : BaseJsonApi(dao) { + companion object { + private val parser = Gson() ///< The JSON parser + } + + private val entityTypeToken: TypeToken = object: TypeToken() {} ///< the type of the managed entity + + // Requests + + override fun head(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { + val obj = parser.fromJson( + httpSession.inputStream.bufferedReader().readText(), + this.entityTypeToken.type + ) + // check if the object is in the object accessible from the session + val exists = this.dao.getAllBySession(session.id).contains(obj) + + return NanoHTTPD.newFixedLengthResponse( + if (exists) NanoHTTPD.Response.Status.OK else NanoHTTPD.Response.Status.NOT_FOUND, + "text/plain", + if (exists) "Exists" else "Not found" + ) + } + + override fun get(httpSession: NanoHTTPD.IHTTPSession): NanoHTTPD.Response { + return NanoHTTPD.newFixedLengthResponse( + NanoHTTPD.Response.Status.OK, + "application/json", + parser.toJson(this.dao.getAllBySession(session.id)) + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/ClassDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/ClassDao.kt index 879e624..e7f2dab 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/dao/ClassDao.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/ClassDao.kt @@ -2,17 +2,27 @@ package com.faraphel.tasks_valider.database.dao import androidx.room.Dao import androidx.room.Query -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao +import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao import com.faraphel.tasks_valider.database.entities.ClassEntity import com.faraphel.tasks_valider.database.entities.PersonEntity import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity import com.faraphel.tasks_valider.database.entities.SessionEntity @Dao -interface ClassDao : BaseDao { +interface ClassDao : BaseTaskDao { @Query("SELECT * FROM ${ClassEntity.TABLE_NAME}") override fun getAll(): List + @Query( + "SELECT * FROM ${ClassEntity.TABLE_NAME} " + + "JOIN ${SessionEntity.TABLE_NAME} " + + "ON ${SessionEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " + + "WHERE ${SessionEntity.TABLE_NAME}.id = :sessionId" + ) + override fun getAllBySession(sessionId: Long): List + /** * Get the object from its identifier */ @@ -31,7 +41,7 @@ interface ClassDao : BaseDao { * @param id the id of the class */ @Query( - "SELECT * FROM ${PersonEntity.TABLE_NAME} " + + "SELECT ${PersonEntity.TABLE_NAME}.* FROM ${PersonEntity.TABLE_NAME} " + "JOIN ${RelationClassPersonEntity.TABLE_NAME} " + "ON ${PersonEntity.TABLE_NAME}.id = ${RelationClassPersonEntity.TABLE_NAME}.student_id " + "WHERE ${RelationClassPersonEntity.TABLE_NAME}.class_id = :id" diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/PersonDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/PersonDao.kt index 10ef3e9..7b481e8 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/dao/PersonDao.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/PersonDao.kt @@ -2,11 +2,13 @@ package com.faraphel.tasks_valider.database.dao import androidx.room.Dao import androidx.room.Query -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao +import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao import com.faraphel.tasks_valider.database.entities.* @Dao -interface PersonDao : BaseDao { +interface PersonDao : BaseTaskDao { @Query("SELECT * FROM ${PersonEntity.TABLE_NAME}") override fun getAll(): List @@ -16,6 +18,19 @@ interface PersonDao : BaseDao { @Query("SELECT * FROM ${PersonEntity.TABLE_NAME} WHERE id = :id") fun getById(id: Long): PersonEntity? + @Query( + "SELECT * FROM ${PersonEntity.TABLE_NAME} " + + "WHERE id IN (" + + "SELECT student_id FROM ${RelationClassPersonEntity.TABLE_NAME} " + + "JOIN ${ClassEntity.TABLE_NAME} " + + "ON ${RelationClassPersonEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " + + "JOIN ${SessionEntity.TABLE_NAME} " + + "ON ${SessionEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " + + "WHERE ${SessionEntity.TABLE_NAME}.id = :sessionId" + + ")" + ) + override fun getAllBySession(sessionId: Long): List + /** * Allow to get all the classes the person is attending as a student */ diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/RelationClassPersonDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/RelationClassPersonDao.kt index 30bea9b..3f77a53 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/dao/RelationClassPersonDao.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/RelationClassPersonDao.kt @@ -2,22 +2,35 @@ package com.faraphel.tasks_valider.database.dao import androidx.room.Dao import androidx.room.Query -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao +import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.ClassEntity import com.faraphel.tasks_valider.database.entities.RelationClassPersonEntity +import com.faraphel.tasks_valider.database.entities.SessionEntity @Dao -interface RelationClassPersonDao : BaseDao { +interface RelationClassPersonDao : BaseTaskDao { @Query("SELECT * FROM ${RelationClassPersonEntity.TABLE_NAME}") override fun getAll(): List + @Query( + "SELECT ${RelationClassPersonEntity.TABLE_NAME}.* FROM ${RelationClassPersonEntity.TABLE_NAME} " + + "JOIN ${ClassEntity.TABLE_NAME} " + + "ON ${RelationClassPersonEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " + + "JOIN ${SessionEntity.TABLE_NAME} " + + "ON ${SessionEntity.TABLE_NAME}.class_id = ${ClassEntity.TABLE_NAME}.id " + + "WHERE ${SessionEntity.TABLE_NAME}.id = :sessionId" + ) + override fun getAllBySession(sessionId: Long): List + /** * Get the object from its identifiers */ @Query( "SELECT * FROM ${RelationClassPersonEntity.TABLE_NAME} " + - "WHERE " + - "class_id = :classId AND " + - "student_id = :studentId" + "WHERE class_id = :classId " + + "AND student_id = :studentId" ) fun getById(classId: Long, studentId: Long): RelationClassPersonEntity? } diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/RelationPersonSessionSubjectDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/RelationPersonSessionSubjectDao.kt new file mode 100644 index 0000000..45eede5 --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/RelationPersonSessionSubjectDao.kt @@ -0,0 +1,32 @@ +package com.faraphel.tasks_valider.database.dao + +import androidx.room.Dao +import androidx.room.Query +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao +import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity + + +@Dao +interface RelationPersonSessionSubjectDao : BaseTaskDao { + @Query("SELECT * FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME}") + override fun getAll(): List + + @Query( + "SELECT * FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " + + "WHERE session_id = :sessionId" + ) + override fun getAllBySession(sessionId: Long): List + + /** + * Get the object from its identifiers + */ + @Query( + "SELECT * FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " + + "WHERE student_id = :studentId " + + "AND session_id = :sessionId " + + "AND subject_id = :subjectId" + ) + fun getById(studentId: Long, sessionId: Long, subjectId: Long): RelationPersonSessionSubjectEntity? +} \ No newline at end of file diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/SessionDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/SessionDao.kt index e6c9c2a..29cc8df 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/dao/SessionDao.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/SessionDao.kt @@ -2,14 +2,20 @@ package com.faraphel.tasks_valider.database.dao import androidx.room.Dao import androidx.room.Query -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao +import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.ClassEntity import com.faraphel.tasks_valider.database.entities.SessionEntity @Dao -interface SessionDao : BaseDao { +interface SessionDao : BaseTaskDao { @Query("SELECT * FROM ${SessionEntity.TABLE_NAME}") override fun getAll(): List + @Query("SELECT * FROM ${SessionEntity.TABLE_NAME} WHERE id = :sessionId") + override fun getAllBySession(sessionId: Long): List + /** * Get the object from its identifier */ diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/SubjectDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/SubjectDao.kt index eba5345..fbe8900 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/dao/SubjectDao.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/SubjectDao.kt @@ -2,15 +2,28 @@ package com.faraphel.tasks_valider.database.dao import androidx.room.Dao import androidx.room.Query -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao +import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.ClassEntity +import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity import com.faraphel.tasks_valider.database.entities.SubjectEntity import com.faraphel.tasks_valider.database.entities.TaskEntity @Dao -interface SubjectDao : BaseDao { +interface SubjectDao : BaseTaskDao { @Query("SELECT * FROM ${SubjectEntity.TABLE_NAME}") override fun getAll(): List + @Query( + "SELECT * FROM ${SubjectEntity.TABLE_NAME} " + + "WHERE id IN (" + + "SELECT subject_id FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " + + "WHERE session_id = :sessionId" + + ")" + ) + override fun getAllBySession(sessionId: Long): List + /** * Get the object from its identifier */ diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/TaskDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/TaskDao.kt index ff8e4e1..6d68256 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/dao/TaskDao.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/TaskDao.kt @@ -2,15 +2,27 @@ package com.faraphel.tasks_valider.database.dao import androidx.room.Dao import androidx.room.Query -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao +import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity import com.faraphel.tasks_valider.database.entities.TaskEntity import com.faraphel.tasks_valider.database.entities.ValidationEntity @Dao -interface TaskDao : BaseDao { +interface TaskDao : BaseTaskDao { @Query("SELECT * FROM ${TaskEntity.TABLE_NAME}") override fun getAll(): List + @Query( + "SELECT * FROM ${TaskEntity.TABLE_NAME} " + + "WHERE subject_id IN (" + + "SELECT subject_id FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " + + "WHERE session_id = :sessionId" + + ")" + ) + override fun getAllBySession(sessionId: Long): List + /** * Get the object from its identifier */ diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/ValidationDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/ValidationDao.kt index 3d32dab..81262cc 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/dao/ValidationDao.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/ValidationDao.kt @@ -2,14 +2,29 @@ package com.faraphel.tasks_valider.database.dao import androidx.room.Dao import androidx.room.Query -import com.faraphel.tasks_valider.database.dao.base.BaseDao +import com.faraphel.tasks_valider.database.dao.base.BaseCronDao +import com.faraphel.tasks_valider.database.dao.base.BaseSessionDao +import com.faraphel.tasks_valider.database.dao.base.BaseTaskDao +import com.faraphel.tasks_valider.database.entities.RelationPersonSessionSubjectEntity +import com.faraphel.tasks_valider.database.entities.TaskEntity import com.faraphel.tasks_valider.database.entities.ValidationEntity @Dao -interface ValidationDao : BaseDao { +interface ValidationDao : BaseTaskDao { @Query("SELECT * FROM ${ValidationEntity.TABLE_NAME}") override fun getAll(): List + @Query( + "SELECT * FROM ${ValidationEntity.TABLE_NAME} " + + "JOIN ${TaskEntity.TABLE_NAME} " + + "ON ${ValidationEntity.TABLE_NAME}.task_id = ${TaskEntity.TABLE_NAME}.id " + + "WHERE ${TaskEntity.TABLE_NAME}.subject_id IN (" + + "SELECT subject_id FROM ${RelationPersonSessionSubjectEntity.TABLE_NAME} " + + "WHERE session_id = :sessionId" + + ")" + ) + override fun getAllBySession(sessionId: Long): List + /** * Get the object from its identifiers */ diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseCronDao.kt similarity index 82% rename from app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseDao.kt rename to app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseCronDao.kt index b06e62f..dfd824d 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseDao.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseCronDao.kt @@ -3,17 +3,13 @@ package com.faraphel.tasks_valider.database.dao.base import androidx.room.Delete import androidx.room.Insert import androidx.room.OnConflictStrategy -import androidx.room.Update -import com.google.gson.Gson -import com.google.gson.reflect.TypeToken - /** - * A base DAO to handle the database operations. + * A base DAO to handle the database operations (CRON). * @param Entity the entity to handle */ -interface BaseDao { +interface BaseCronDao { /** * Check if the entities exists in the database. */ diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseSessionDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseSessionDao.kt new file mode 100644 index 0000000..1e457c4 --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseSessionDao.kt @@ -0,0 +1,11 @@ +package com.faraphel.tasks_valider.database.dao.base + +/** + * The base for a DAO that is inside a session scope. + */ +interface BaseSessionDao { + /** + * Return all the objects concerned by a session. + */ + fun getAllBySession(sessionId: Long): List +} diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseTaskDao.kt b/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseTaskDao.kt new file mode 100644 index 0000000..c55a6cd --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/database/dao/base/BaseTaskDao.kt @@ -0,0 +1,6 @@ +package com.faraphel.tasks_valider.database.dao.base + +/** + * The base for a DAO for the task project. + */ +interface BaseTaskDao: BaseCronDao, BaseSessionDao diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/entities/RelationPersonSessionSubjectEntity.kt b/app/src/main/java/com/faraphel/tasks_valider/database/entities/RelationPersonSessionSubjectEntity.kt new file mode 100644 index 0000000..d39a8e9 --- /dev/null +++ b/app/src/main/java/com/faraphel/tasks_valider/database/entities/RelationPersonSessionSubjectEntity.kt @@ -0,0 +1,48 @@ +package com.faraphel.tasks_valider.database.entities + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.ForeignKey +import com.faraphel.tasks_valider.database.entities.base.BaseEntity + + +/** + * Represent the relation that associate a subject to a person for a specific session. + */ +@Entity( + tableName = RelationPersonSessionSubjectEntity.TABLE_NAME, + primaryKeys = [ + "student_id", + "session_id", + "subject_id" + ], + foreignKeys = [ + ForeignKey( + entity = PersonEntity::class, + parentColumns = ["id"], + childColumns = ["student_id"], + onDelete = ForeignKey.CASCADE + ), + ForeignKey( + entity = SessionEntity::class, + parentColumns = ["id"], + childColumns = ["session_id"], + onDelete = ForeignKey.CASCADE + ), + ForeignKey( + entity = SubjectEntity::class, + parentColumns = ["id"], + childColumns = ["subject_id"], + onDelete = ForeignKey.CASCADE + ), + ] +) +data class RelationPersonSessionSubjectEntity ( + @ColumnInfo("student_id", index = true) val studentId: Long, + @ColumnInfo("session_id", index = true) val sessionId: Long, + @ColumnInfo("subject_id", index = true) val subjectId: Long, +) : BaseEntity() { + companion object { + const val TABLE_NAME = "relation_person_session_subject" + } +} \ No newline at end of file diff --git a/app/src/main/java/com/faraphel/tasks_valider/database/test.kt b/app/src/main/java/com/faraphel/tasks_valider/database/test.kt index 22b5f02..a27785b 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/database/test.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/database/test.kt @@ -114,4 +114,20 @@ fun populateTaskDatabaseTest(database: TaskDatabase) { val taskA3 = database.taskDao().getById(taskA3Id)!! val taskB1 = database.taskDao().getById(taskB1Id)!! val taskB2 = database.taskDao().getById(taskB2Id)!! +} + + +fun populateSubjectSessionPersonTest(database: TaskDatabase, session: SessionEntity) { + // get the list of available subjects + val subjects = database.subjectDao().getAll() + + // give a random subject to everyone in the session + database.personDao().getAllBySession(session.id).forEach { person -> + // get a random subject + val subject = subjects.random() + // insert a new subject for a person for a specific session + database.relationPersonSessionSubjectDao().insert( + RelationPersonSessionSubjectEntity(person.id, session.id, subject.id) + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/selection.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/selection.kt index 085df9f..0f9424c 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/selection.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/selection.kt @@ -1,6 +1,8 @@ package com.faraphel.tasks_valider.ui.screen.communication.internet import android.app.Activity +import android.os.Build +import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.Column import androidx.compose.material3.Button import androidx.compose.material3.Text @@ -9,16 +11,18 @@ import androidx.navigation.NavController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import com.faraphel.tasks_valider.database.TaskDatabase +@RequiresApi(Build.VERSION_CODES.O) @Composable -fun CommunicationInternetSelectScreen(activity: Activity) { +fun CommunicationInternetSelectScreen(activity: Activity, database: TaskDatabase) { val controller = rememberNavController() NavHost(navController = controller, startDestination = "mode") { composable("mode") { CommunicationInternetSelectContent(controller) } composable("client") { CommunicationInternetClientScreen(activity) } - composable("server") { CommunicationInternetServerScreen(activity) } + composable("server") { CommunicationInternetServerScreen(activity, database) } } } diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server.kt index dc6c275..fdf598e 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/internet/server.kt @@ -1,88 +1,114 @@ package com.faraphel.tasks_valider.ui.screen.communication.internet import android.app.Activity +import android.os.Build import android.util.Log +import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material3.Button import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.Text import androidx.compose.material3.TextField -import androidx.compose.runtime.Composable -import androidx.compose.runtime.MutableState -import androidx.compose.runtime.mutableIntStateOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember +import androidx.compose.runtime.* import androidx.compose.ui.text.input.KeyboardType -import androidx.room.Room +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController import com.faraphel.tasks_valider.connectivity.task.TaskClient import com.faraphel.tasks_valider.connectivity.task.TaskServer import com.faraphel.tasks_valider.database.TaskDatabase import com.faraphel.tasks_valider.database.entities.ClassEntity import com.faraphel.tasks_valider.database.entities.PersonEntity -import com.faraphel.tasks_valider.database.populateTaskDatabaseTest +import com.faraphel.tasks_valider.database.entities.SessionEntity +import com.faraphel.tasks_valider.database.populateSubjectSessionPersonTest import com.faraphel.tasks_valider.ui.screen.authentification.AuthentificationServerScreen import com.faraphel.tasks_valider.ui.screen.communication.DEFAULT_SERVER_PORT import com.faraphel.tasks_valider.ui.screen.communication.RANGE_SERVER_PORT import com.faraphel.tasks_valider.ui.screen.task.TaskSessionScreen +import java.time.Instant /** * Screen for the host to configure the server */ +@RequiresApi(Build.VERSION_CODES.O) @Composable -fun CommunicationInternetServerScreen(activity: Activity) { +fun CommunicationInternetServerScreen( + activity: Activity, + database: TaskDatabase, +) { + val controller = rememberNavController() + val adminPersonEntity = remember { mutableStateOf(null) } - - // if the admin person is not created, prompt the user for the admin information - if (adminPersonEntity.value == null) { - return AuthentificationServerScreen(adminPersonEntity) - } - val client = remember { mutableStateOf(null) } - // if the client to the server is not created, prompt the user for the server configuration - if (client.value == null) { - return CommunicationInternetServerContent( - activity, - adminPersonEntity.value!!, - client - ) + NavHost(navController = controller, startDestination = "authentication") { + composable("authentication") { + // if the admin person is not created, prompt the user for the admin information + if (adminPersonEntity.value == null) AuthentificationServerScreen(adminPersonEntity) + else controller.navigate("configuration") + } + composable("configuration") { + if (client.value == null) + CommunicationInternetServerContent( + database, + adminPersonEntity.value!!, + client + ) + else controller.navigate("session") + } + composable("session") { + TaskSessionScreen(activity, client.value!!) + } } - - // otherwise, go to the base tasks screen - return TaskSessionScreen(activity, client.value!!) } +@RequiresApi(Build.VERSION_CODES.O) @Composable fun CommunicationInternetServerContent( - activity: Activity, + database: TaskDatabase, adminPersonEntity: PersonEntity, client: MutableState ) { - val expandedStudentList = remember { mutableStateOf(false) } + val classes = remember { mutableStateOf?>(null) } + val selectedClass = remember { mutableStateOf(null) } + val areClassesExpanded = remember { mutableStateOf(false) } + val serverPort = remember { mutableIntStateOf(DEFAULT_SERVER_PORT) } + LaunchedEffect(true) { + // refresh the list of classes + Thread { refreshClasses(database, classes) }.start() + } + Column { - // student list - Button(onClick = { expandedStudentList.value = !expandedStudentList.value }) { - Text(text = "Select Students List") + // classes + Button(onClick = { areClassesExpanded.value = !areClassesExpanded.value }) { + Row { + Text(text = "Class") + // display the selected class, if selected + if (selectedClass.value != null) + Text(text = selectedClass.value!!.name) + } } DropdownMenu( - expanded = expandedStudentList.value, - onDismissRequest = { expandedStudentList.value = false } + expanded = areClassesExpanded.value, + onDismissRequest = { areClassesExpanded.value = false } ) { // TODO(Faraphel): student lists should be loaded from the database or a file - DropdownMenuItem( - text = { Text("ISRI") }, - onClick = {} - ) - DropdownMenuItem( - text = { Text("MIAGE") }, - onClick = {} - ) + classes.value?.forEach { class_ -> + DropdownMenuItem( + text = { Text(class_.name) }, + onClick = { + selectedClass.value = class_ + areClassesExpanded.value = false + } + ) + } } // server port @@ -97,35 +123,57 @@ fun CommunicationInternetServerContent( } ) - Button(onClick = { - Thread { // a thread is used for networking - // Reset the database | TODO(Faraphel): only for testing purpose - activity.deleteDatabase("local") + // check if a class is selected + if (selectedClass.value != null) + // button to create the server + Button(onClick = { + Thread { // a thread is used for networking - // Create the database - val database = Room.databaseBuilder( - activity, - TaskDatabase::class.java, - "local" - ).build() + // Insert the admin in the database + database.personDao().insert(adminPersonEntity) - // Populate the database with test data - // TODO(Faraphel): remove test data - populateTaskDatabaseTest(database) + // Create a new session + // TODO(Faraphel): name + val (sessionId) = database.sessionDao().insert( + SessionEntity( + name="NOM", + start=Instant.now(), + classId=selectedClass.value!!.id, + ) + ) + val session = database.sessionDao().getById(sessionId)!! - // Insert the admin in the database - database.personDao().insert(adminPersonEntity) + // TODO(Faraphel): remove, this is a test function + Thread { + populateSubjectSessionPersonTest(database, session) + }.let { thread -> + thread.start() + thread.join() + } - // Create the server - Log.i("room-server", "creating the server") - val server = TaskServer(serverPort.intValue, database, adminPersonEntity) - server.start() + // Create the server + Log.i("room-server", "creating the server") + val server = TaskServer( + serverPort.intValue, + database, + session, + adminPersonEntity, + ) + server.start() - // Get the client from the server - client.value = server.getAdminClient() - }.start() - }) { - Text("Create") - } + // Get the client from the server + client.value = server.getAdminClient() + }.start() + }) { + Text("Create") + } } } + + +/** + * Refresh the list of classes + */ +fun refreshClasses(database: TaskDatabase, classes: MutableState?>) { + classes.value = database.classDao().getAll() +} diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/selection.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/selection.kt index fac1c7b..d95ea0b 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/selection.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/communication/selection.kt @@ -1,7 +1,9 @@ package com.faraphel.tasks_valider.ui.screen.communication import android.app.Activity +import android.os.Build import android.widget.Toast +import androidx.annotation.RequiresApi import androidx.compose.foundation.layout.Column import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults @@ -13,6 +15,7 @@ import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import com.faraphel.tasks_valider.connectivity.bwf.BwfManager +import com.faraphel.tasks_valider.database.TaskDatabase import com.faraphel.tasks_valider.ui.screen.communication.internet.CommunicationInternetSelectScreen import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.CommunicationWifiP2pScreen @@ -21,10 +24,13 @@ import com.faraphel.tasks_valider.ui.screen.communication.wifiP2p.CommunicationW * CommunicationController is the main controller for the communication screen. * It is responsible for handling the navigation between the different communication methods. * It is also responsible for initializing the communication methods. + * * @param activity: The activity that hosts the communication screen. + * @param database: the database. */ +@RequiresApi(Build.VERSION_CODES.O) @Composable -fun CommunicationModeSelectionScreen(activity: Activity) { +fun CommunicationModeSelectionScreen(activity: Activity, database: TaskDatabase) { val controller = rememberNavController() NavHost( @@ -35,7 +41,7 @@ fun CommunicationModeSelectionScreen(activity: Activity) { CommunicationSelectContent(controller, activity) } composable("internet") { - CommunicationInternetSelectScreen(activity) + CommunicationInternetSelectScreen(activity, database) } composable("wifi-p2p") { val bwfManager = BwfManager.fromActivity(activity) diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/session.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/session.kt index c77eefc..2d1335a 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/session.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/session.kt @@ -23,19 +23,19 @@ import com.google.gson.reflect.TypeToken @Composable fun TaskSessionScreen(activity: Activity, client: TaskClient) { val students = remember { mutableStateOf?>(null) } - val selected_student = remember { mutableStateOf(null) } + val selectedStudent = remember { mutableStateOf(null) } // if the groups are not yet defined, refresh the list if (students.value == null) return Thread { refreshStudents(activity, client, students) }.start() - if (selected_student.value != null) - return TaskStudentScreen(selected_student.value!!) + if (selectedStudent.value != null) + return TaskStudentScreen(activity, client, selectedStudent.value!!) Column { // if the groups have already been defined, display them for (student in students.value!!) { - Button(onClick = { selected_student.value = student }) { + Button(onClick = { selectedStudent.value = student }) { Text(text = student.fullName()) } } diff --git a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/student.kt b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/student.kt index 1fffe77..20acbb8 100644 --- a/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/student.kt +++ b/app/src/main/java/com/faraphel/tasks_valider/ui/screen/task/student.kt @@ -1,14 +1,89 @@ package com.faraphel.tasks_valider.ui.screen.task +import android.app.Activity +import android.widget.Toast +import androidx.compose.foundation.layout.Column +import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import com.faraphel.tasks_valider.database.entities.PersonEntity +import androidx.compose.runtime.MutableState +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import com.faraphel.tasks_valider.connectivity.task.TaskClient +import com.faraphel.tasks_valider.database.entities.* +import com.google.gson.Gson +import com.google.gson.reflect.TypeToken /** * This screen represent a student * @param student the student object */ @Composable -fun TaskStudentScreen(student: PersonEntity) { - Text(text = student.fullName()) +fun TaskStudentScreen(activity: Activity, client: TaskClient, student: PersonEntity) { + val tasks = remember { mutableStateOf?>(null) } + + if (tasks.value == null) + Thread { refreshTasks(activity, client, student, tasks) }.start() + + Column { + Text(text = student.fullName()) + + tasks.value?.forEach { task -> + Button(onClick = {}) { + Column { + Text(task.title) + task.description?.let { description -> Text(description) } + } + } + } + } +} + +fun refreshTasks( + activity: Activity, + client: TaskClient, + student: PersonEntity, + tasks: MutableState?> +) { + val jsonParser = Gson() + + // try to obtain the list of subject + val responseSubjects = client.get("entities/" + RelationPersonSessionSubjectEntity.TABLE_NAME) + + // in case of error, notify it + if (!responseSubjects.isSuccessful) + return activity.runOnUiThread { Toast.makeText(activity, responseSubjects.message, Toast.LENGTH_LONG).show() } + + // parse the list of subjects + val allPersonSessionSubjects = jsonParser.fromJson>( + responseSubjects.body.string(), + object : TypeToken>(){}.type + ) + + // get the subject that the student is using + val relationPersonSessionSubjects = allPersonSessionSubjects.firstOrNull { relation -> relation.studentId == student.id } + + if (relationPersonSessionSubjects == null) + // TODO(Faraphel): should be able to assign a subject ? + return activity.runOnUiThread { Toast.makeText(activity, "No subject assigned", Toast.LENGTH_LONG).show() } + + // try to obtain the list of tasks + val responseTasks = client.get("entities/" + TaskEntity.TABLE_NAME) + + // in case of error, notify it + if (!responseTasks.isSuccessful) + return activity.runOnUiThread { Toast.makeText(activity, responseTasks.message, Toast.LENGTH_LONG).show() } + + // parse the list of subjects + val allTasks = jsonParser.fromJson>( + responseTasks.body.string(), + object : TypeToken>(){}.type + ) + + // get the tasks that are linked to this subject + tasks.value = allTasks.filter { task -> + task.subjectId == relationPersonSessionSubjects.subjectId + }.sortedBy { task -> + task.order + } }