diff --git a/docs/src/assets/images/diagramme_sql.png b/docs/src/assets/images/diagramme_sql.png new file mode 100644 index 0000000..afa2369 Binary files /dev/null and b/docs/src/assets/images/diagramme_sql.png differ diff --git a/docs/src/database/README.md b/docs/src/database/README.md index bd135cc..c31de80 100644 --- a/docs/src/database/README.md +++ b/docs/src/database/README.md @@ -16,13 +16,189 @@ It generates typesafe code for any labeled SQL statements. ::: warning -This section is under construction -> Stay tuned for an update. +Be carefull with SQL Delight , the project and his dependancies just move from `com.squareup.sqldelight.*` +to `app.cash.sqldelight.*` + +Pay attention also with beta, alpha version of Android studio that could produce bugs on gradle task management for code generation of SQL Delight databases. ::: + + ## ๐Ÿงช add and use your sqldelight database to your quizz to retrieve network only if you your quizz data are older than 5 minutes +> Refer to the multiplatform implementation of SQLDelight in official Github pages +> ๐Ÿ‘‰ https://cashapp.github.io/sqldelight/2.0.0/multiplatform_sqlite/ + + +#### Add the correct dependancies to the project +``` kotlin +plugins { +... + id("app.cash.sqldelight") version "2.0.0" +} +... + sourceSets { + val commonMain by getting { + dependencies { + ... + implementation("app.cash.sqldelight:runtime:2.0.0") + implementation("app.cash.sqldelight:coroutines-extensions:2.0.0") + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.1") + + } + } + val androidMain by getting { + dependencies { + ... + implementation("app.cash.sqldelight:android-driver:2.0.0") + + } + } + ... + val iosMain by creating { + ... + dependencies { + ... + implementation("app.cash.sqldelight:native-driver:2.0.0") + } + } + val desktopMain by getting { + dependencies { + ... + implementation("app.cash.sqldelight:sqlite-driver:2.0.0") + } + } + ... +``` +#### Create the native SQL driver factory and use it for creating the DB with `actual`/`expect` kotlin keywords + +#### Read carefully the modelisation UML below + +![diagram SQL ](../assets/images/diagramme_sql.png) + +#### Create you SQLDelight model 'QuizDatabase.sq' + +::: details QuizDatabase.sq (ressources of commonMain)* + +```sql +CREATE TABLE update_time ( + timestamprequest INTEGER +); + +INSERT INTO update_time(timestamprequest) VALUES (0); + +CREATE TABLE questions ( + id INTEGER PRIMARY KEY, + label TEXT NOT NULL, + correctAnswerId INTEGER NOT NULL + ); + + CREATE TABLE answers ( + id INTEGER NOT NULL, + label TEXT NOT NULL, + question_id INTEGER NOT NULL, + PRIMARY KEY (id, question_id), + FOREIGN KEY (question_id) + REFERENCES questions (id) + ON UPDATE CASCADE + ON DELETE CASCADE + ); + + selectUpdateTimestamp: + SELECT * + FROM update_time; + + insertTimeStamp: + INSERT INTO update_time(timestamprequest) + VALUES (:timestamp); + + deleteTimeStamp: + DELETE FROM update_time; + + deleteQuestions: + DELETE FROM questions; + + deleteAnswers: + DELETE FROM answers; + + selectAllQuestions: + SELECT * + FROM questions; + + selectAllAnswersFromQuestion: + SELECT * + FROM answers + WHERE question_id = :questionId; + + insertQuestion: + INSERT INTO questions(id, label,correctAnswerId) + VALUES (?, ?, ?); + + insertAnswer: + INSERT INTO answers(id, label,question_id) + VALUES (?, ?, ?); +``` +::: + +#### Create your Database datasource by generating insert and update suspending functions + +::: details network/QuizDB.kt (commonMain) +``` kotlin +package network + +import app.cash.sqldelight.db.SqlDriver +import com.myapplication.common.cache.Database +import com.myapplication.common.cache.QuizDatabaseQueries +import network.data.Answer +import network.data.Question + +class QuizDB(sqlDriver: SqlDriver) { + + private val database = Database(sqlDriver) + private val quizQueries: QuizDatabaseQueries = database.quizDatabaseQueries + + suspend fun getUpdateTimeStamp():Long = quizQueries.selectUpdateTimestamp().executeAsOneOrNull()?.timestamprequest ?: 0L + + suspend fun setUpdateTimeStamp(timeStamp:Long) { + quizQueries.deleteTimeStamp() + quizQueries.insertTimeStamp(timeStamp) + } + + suspend fun getAllQuestions() = quizQueries.selectAllQuestions( + mapper = { id, label, correctAnswer -> + Question(id,label,correctAnswer,getAnswersByQuestionId(id) + ) + }).executeAsList() + + private fun getAnswersByQuestionId(idQuestion:Long) = quizQueries.selectAllAnswersFromQuestion( + questionId = idQuestion, + mapper = { id, label, _ -> + Answer(id, label) + }).executeAsList() + + suspend fun insertQuestions(questions:List) { + quizQueries.deleteQuestions(); + quizQueries.deleteAnswers() + questions.forEach {question -> + quizQueries.insertQuestion(question.id, question.label, question.correctAnswerId) + question.answers.forEach {answer -> + quizQueries.insertAnswer(answer.id,answer.label,question.id) + } + } + } +} +``` +::: + +#### Update your repository by instanciating your database + +Your repository handle the following cases : +* If there is no network and it's the first time launch of the app : handle and error +* if there is no network and you have db datas : return on the flow the db data +* if there is network and db data are younger than 5 min : return on the flow the db data +* if there is network and db data are older than 5 min : retourn on the flow the network data and reset db data + ## ๐ŸŽฏ Solutions ::: tip diff --git a/others/KMP plan.md b/others/KMP plan.md new file mode 100644 index 0000000..536799c --- /dev/null +++ b/others/KMP plan.md @@ -0,0 +1,68 @@ +Prerequisites : POO, Developper tools knowledges (Git, Linux Shell, IDE) + +๐Ÿš€ Presentation of Kotlin +Some features +History +Some numbers and facts +Why switch from Java to Kotlin +Prerequisites + +Kotlin language features + +Basic features + Basic constructs (variables, control flow) + Functions + Null safety + Enumerations + +Intermediate features + Object oriented programming + Data class + Functional programming + Kotlin and Java interoperability + + Let's start kotlin multiplatform + Prerequisites + IDE support overview + KMP roadmap + Hands-on Lab objectives + Functionnally + Technically + Design screens + +Configure a KMP project + ๐Ÿงช Plugins installation + ๐Ÿงช Clone the KMP template provided by JetBrains + ๐Ÿ“š A Guided tour of the sample project + ๐Ÿงช Deploy your apps + +User interface + ๐Ÿ“š Reminder + Compose Multiplatform + How to create composables ? + Create composable for the Quiz + ๐Ÿงช WelcomeScreen + ๐Ÿงช ScoreScreen + ๐Ÿงช QuestionScreen + +Connectivity + ๐Ÿ“š Reminder + Data layer for KMP + Kotlin flow + Coroutine + Connect my Quizz to the internet + ๐Ÿงช Ktor as a multiplatform HTTP client + ๐Ÿ‘ทโ€โ™‚๏ธ Ktor as a rest API server + ๐Ÿงช Create a Ktor server module inside your actual + +Database & Datastore preferences + ๐Ÿงช add and use your sqldelight database to your quizz to retrieve network only if you your quizz data are older than 5 minutes + +Let's go further + ๐Ÿงช Create Navigation between composable screens + ๐ŸŽฏ Solutions + ๐Ÿ‘ทโ€โ™‚๏ธ Manage your ressources + ๐Ÿ‘ทโ€โ™‚๏ธ Integrate a JS Web target + + + diff --git a/others/Keys of quizzes with answers.docx b/others/Keys of quizzes with answers.docx new file mode 100644 index 0000000..8e06220 Binary files /dev/null and b/others/Keys of quizzes with answers.docx differ diff --git a/others/Quizz.md b/others/Quizz.md new file mode 100644 index 0000000..a4edcbb --- /dev/null +++ b/others/Quizz.md @@ -0,0 +1,90 @@ +Which components can be shared across platforms in Kotlin Multiplatform projects? +UI logic +Business logic +Data models +Networking code +Utility functions + + +Name some popular libraries/frameworks compatible with Kotlin Multiplatform. +Ktor +kotlinx.serialization +SQLDelight +kotlinx.coroutines + + +How does Kotlin Multiplatform handle platform-specific implementations? +Through expected and actual declarations +Expected declarations define an interface or contract +Actual declarations provide platform-specific implementations + + +What tools or IDE support is available for Kotlin Multiplatform development? +IntelliJ IDEA with Kotlin plugin +Android Studio +Visual Studio Code with Kotlin extension +jetbrain Fleet + + +What is the level of maturity or adoption of Kotlin Multiplatform in the development community? +Multiplatform is stable, ready for production +Multiplatform is not stable, not for production +Compose is not stable, not for production +Compose is stable, ready for production + + +1. **Which of the following best describes the primary advantage of using Ktor's HttpClient?** + + a) Synchronous processing of HTTP requests + b) Integration only with Android platforms + c) Asynchronous and non-blocking by default <-- + d) Exclusive support for RESTful APIs + + +**How do you typically perform a GET request using Ktor's HttpClient?** + + a) `get()` <-- + b) `sendRequest(HttpMethod.Get)` + c) `performGET()` + d) `executeRequest(Method.GET)` + + + **What is the purpose of `MutableState` in Jetpack Compose?** + + a) To manage global application state + b) To retain state within a composable and trigger recomposition + c) To handle lifecycle events in composables + d) To store read-only state + + + + **Which function is used to create and manage mutable state in Jetpack Compose?** + + a) `stateOf()` + b) `mutableStateOf()` <-- + c) `composeState()` + d) `createState()` + + + +5. **What is Kotlin Flows + a) Flows is a multithreading framework library for kotlin + b) Flows are built on Kotlin coroutines, supporting sequential asynchronous processing <-- + c) Flows are synchronous + d) Flows are limited to Android development only + + +6. **Which operator is commonly used to transform data emitted by a Kotlin Flow?** + + a) `map()` <-- + b) `switchMap()` + c) `flatMap()` + d) `transform()` + + +What role does `CoroutineScope` play in managing coroutines?** + + a) It determines the Thread used for asynchronous execusion thanks to Dispatcher <-- + c) It defines the lifecycle of the application + d) It specifies the UI thread for coroutine execution +