feat: types de questions et générateur (tables 1..maxTable)
This commit is contained in:
4 files changed
+119
No files matched your search
@@ -0,0 +1,10 @@
|
|||||||
|
package com.livrets.game
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class GameConfig(
|
||||||
|
val questionCount: Int, // 5..50
|
||||||
|
val secondsPerQuestion: Int, // 3..30
|
||||||
|
val maxTable: Int, // 1..12 : les deux facteurs sont tirés dans 1..maxTable
|
||||||
|
)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.livrets.game
|
||||||
|
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
sealed interface Question {
|
||||||
|
val table: Int
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("direct")
|
||||||
|
data class Direct(val a: Int, val b: Int) : Question {
|
||||||
|
override val table: Int get() = maxOf(a, b)
|
||||||
|
override fun toString(): String = "$a × $b = ?"
|
||||||
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
@SerialName("missing_factor")
|
||||||
|
data class MissingFactor(val a: Int, val b: Int) : Question {
|
||||||
|
override val table: Int get() = maxOf(a, b)
|
||||||
|
override fun toString(): String = "$a × ? = ${a * b}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val Question.correctAnswer: Int
|
||||||
|
get() = when (this) {
|
||||||
|
is Question.Direct -> a * b
|
||||||
|
is Question.MissingFactor -> b
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.livrets.game
|
||||||
|
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
fun interface QuestionSource {
|
||||||
|
fun next(previous: Question?, maxTable: Int): Question
|
||||||
|
}
|
||||||
|
|
||||||
|
class QuestionGenerator(private val random: Random = Random.Default) : QuestionSource {
|
||||||
|
override fun next(previous: Question?, maxTable: Int): Question {
|
||||||
|
while (true) {
|
||||||
|
val a = random.nextInt(1, maxTable + 1)
|
||||||
|
val b = random.nextInt(1, maxTable + 1)
|
||||||
|
val question =
|
||||||
|
if (random.nextBoolean()) Question.Direct(a, b) else Question.MissingFactor(a, b)
|
||||||
|
if (question != previous) return question
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.livrets.game
|
||||||
|
|
||||||
|
import kotlin.random.Random
|
||||||
|
import kotlin.test.Test
|
||||||
|
import kotlin.test.assertEquals
|
||||||
|
import kotlin.test.assertNotEquals
|
||||||
|
import kotlin.test.assertTrue
|
||||||
|
|
||||||
|
class QuestionGeneratorTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `tous les facteurs restent dans 1 a maxTable`() {
|
||||||
|
val generator = QuestionGenerator(Random(42))
|
||||||
|
repeat(500) {
|
||||||
|
val q = generator.next(previous = null, maxTable = 6)
|
||||||
|
val (a, b) = when (q) {
|
||||||
|
is Question.Direct -> q.a to q.b
|
||||||
|
is Question.MissingFactor -> q.a to q.b
|
||||||
|
}
|
||||||
|
assertTrue(a in 1..6, "a=$a hors bornes")
|
||||||
|
assertTrue(b in 1..6, "b=$b hors bornes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `les deux formes de question sont produites`() {
|
||||||
|
val generator = QuestionGenerator(Random(7))
|
||||||
|
val questions = List(200) { generator.next(previous = null, maxTable = 12) }
|
||||||
|
assertTrue(questions.any { it is Question.Direct })
|
||||||
|
assertTrue(questions.any { it is Question.MissingFactor })
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `pas de doublon consecutif`() {
|
||||||
|
val generator = QuestionGenerator(Random(123))
|
||||||
|
var previous: Question? = null
|
||||||
|
repeat(300) {
|
||||||
|
val q = generator.next(previous, 12)
|
||||||
|
assertNotEquals(previous, q)
|
||||||
|
previous = q
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `table vaut le plus grand facteur`() {
|
||||||
|
assertEquals(8, Question.Direct(3, 8).table)
|
||||||
|
assertEquals(9, Question.MissingFactor(9, 4).table)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `bonne reponse selon la forme`() {
|
||||||
|
assertEquals(56, Question.Direct(7, 8).correctAnswer)
|
||||||
|
assertEquals(8, Question.MissingFactor(7, 8).correctAnswer)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `affichage des deux formes`() {
|
||||||
|
assertEquals("7 × 8 = ?", Question.Direct(7, 8).toString())
|
||||||
|
assertEquals("7 × ? = 56", Question.MissingFactor(7, 8).toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user