diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index 2d1506b..f3edc75 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -42,6 +42,8 @@
Points de pouvoir
Bonus aux dégats
Armure
+ Bonus d'apprentissage
+ Bonus de PV
Compétences communes
Compétences spéciales
Ajouter une compétence spéciale
@@ -94,6 +96,8 @@
Points de pouvoir
Bonus aux dégats
Armure
+ Bonus d'apprentissage
+ Bonus de PV
Compétences communes
Compétences spéciales
Compétences magiques
@@ -113,7 +117,8 @@
les points de pouvoir sont égaux au POU et sont dépensés pour utiliser la magie ou d’autres pouvoirs. Tous les points de pouvoir régénèrent naturellement après une nuit de repos.
Les personnages plus massifs ou plus forts infligent plus de dégâts quand ils frappent leurs ennemis en combat au corps à corps. Le modificateur s’applique aux dégâts infligés par toute attaque portée par les personnages avec des armes de mêlée (BDC). La moitié de ce bonus s'applique aux attaques de lancer (BDD).
Une armure protège son porteur des blessures. Lorsqu’un personnage est touché en combat par une attaque non magique, soustrayez les points d’armure aux points de dégâts infligés. Les dommages au-delà de la protection de l’armure surpassent celle-ci et sont infligés au personnage, réduisant ses points de vie actuels.
-
+ Plus un personnage est intelligent, plus il assimile rapidement les connaissances et plus il digère son expérience efficacement. Ce modificateur s'applique au score des compétences nouvellement acquises et aux jets d'expériences. Il est égal à (INT - 10) x 2 avec une valeur minimale de zéro.
+ Plus un personnage est de bonne constitution, plus son corps se renforce rapidement. Ce modificateur indique le nombre de "PV" maximum que le personnage gagne à chaque progression. Il est égal à CON / 3, arrondi à l'inférieur.
Attaque en combat à mains nues. Une attaque réussie inflige 1D3 + BDGT.
Éviter une attaque, un projectile, etc.
Maitriser/immobiliser un adversaire.
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt
index 274acf8..2cb200d 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt
@@ -1,8 +1,7 @@
package com.pixelized.desktop.lwa
-import com.pixelized.desktop.lwa.business.DamageBonusUseCase
+import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
import com.pixelized.desktop.lwa.business.RollUseCase
-import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
import com.pixelized.desktop.lwa.business.SkillStepUseCase
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
@@ -71,9 +70,8 @@ val parserDependencies
val useCaseDependencies
get() = module {
- factoryOf(::DamageBonusUseCase)
factoryOf(::SkillStepUseCase)
- factoryOf(::SkillNormalizerUseCase)
factoryOf(::RollUseCase)
factoryOf(::SkillValueComputationUseCase)
+ factoryOf(::CharacterSheetUseCase)
}
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/CharacterSheetUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/CharacterSheetUseCase.kt
new file mode 100644
index 0000000..f948904
--- /dev/null
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/CharacterSheetUseCase.kt
@@ -0,0 +1,56 @@
+package com.pixelized.desktop.lwa.business
+
+import kotlin.math.ceil
+import kotlin.math.max
+
+class CharacterSheetUseCase {
+
+ fun normalize(value: Int): Int {
+ return value - value % 5 // (truncate(value.toFloat() / 5f) * 5f).toInt()
+ }
+
+ fun defaultMovement(): Int = 10
+
+ fun defaultMaxHp(
+ constitution: Int,
+ height: Int,
+ ): Int {
+ return (ceil((constitution + height) / 2f).toInt())
+ }
+
+ fun defaultMaxPower(
+ power: Int,
+ ): Int {
+ return power
+ }
+
+ fun defaultDamageBonus(
+ strength: Int,
+ height: Int,
+ ): String {
+ return defaultDamageBonus(sum = strength + height)
+ }
+
+ fun defaultDamageBonus(
+ sum: Int,
+ ): String {
+ return when {
+ sum < 12 -> "-1d6"
+ sum in 12..17 -> "-1d4"
+ sum in 18..22 -> "+0"
+ sum in 23..29 -> "+1d4"
+ sum in 30..39 -> "+1d6"
+ else -> "+2d6"
+ }
+ }
+
+ fun defaultArmor(): Int = 0
+
+ fun defaultLearning(intelligence: Int): Int {
+ return max(0, (intelligence - 10) * 2)
+ }
+
+ fun defaultHpGrow(constitution: Int): Int {
+ return (constitution / 3)
+ }
+}
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCase.kt
deleted file mode 100644
index 5aeef35..0000000
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCase.kt
+++ /dev/null
@@ -1,19 +0,0 @@
-package com.pixelized.desktop.lwa.business
-
-class DamageBonusUseCase {
-
- fun bonusDamage(strength: Int, height: Int): String {
- return bonusDamage(stat = strength + height)
- }
-
- fun bonusDamage(stat: Int): String {
- return when {
- stat < 12 -> "-1d6"
- stat in 12..17 -> "-1d4"
- stat in 18..22 -> "+0"
- stat in 23..29 -> "+1d4"
- stat in 30..39 -> "+1d6"
- else -> "+2d6"
- }
- }
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/RollUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/RollUseCase.kt
index 64811ec..007e2d2 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/RollUseCase.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/RollUseCase.kt
@@ -7,10 +7,6 @@ import kotlin.math.min
class RollUseCase {
- fun rollD100(): Int {
- return roll(modifier = null, quantity = 1, faces = 100)
- }
-
fun roll(dice: Instruction.Dice): Int {
return roll(
modifier = dice.modifier,
@@ -19,9 +15,13 @@ class RollUseCase {
)
}
- fun roll(modifier: Instruction.Dice.Modifier?, quantity: Int, faces: Int): Int {
+ fun roll(
+ modifier: Instruction.Dice.Modifier? = null,
+ quantity: Int = 1,
+ faces: Int,
+ ): Int {
print("{")
- return sum(count = quantity) {
+ return sum(count = quantity) { left ->
when (modifier) {
Instruction.Dice.Modifier.ADVANTAGE -> {
val roll1 = roll(faces = faces)
@@ -54,6 +54,8 @@ class RollUseCase {
null -> {
roll(faces = faces).also { print("$it") }
}
+ }.also {
+ if (quantity > 1 && left != 1) print(",")
}
}.also {
print("}:")
@@ -61,14 +63,14 @@ class RollUseCase {
}
private fun roll(faces: Int): Int {
- return (Math.random() * faces.toDouble() + 1).toInt()
+ return (Math.random() * faces.toDouble() + 1.0).toInt()
}
- private fun sum(count: Int, block: () -> Int): Int {
+ private fun sum(count: Int, block: (Int) -> Int): Int {
return if (count > 1) {
- block() + sum(count - 1, block)
+ block(count) + sum(count - 1, block)
} else {
- block()
+ block(count)
}
}
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/SkillNormalizerUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/SkillNormalizerUseCase.kt
deleted file mode 100644
index a77ec8f..0000000
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/SkillNormalizerUseCase.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.pixelized.desktop.lwa.business
-
-import kotlin.math.truncate
-
-class SkillNormalizerUseCase {
- fun normalize(value: Int): Int {
- return (truncate(value.toFloat() / 5f) * 5f).toInt()
- }
-}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/parser/arithmetic/Instruction.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/parser/arithmetic/Instruction.kt
index 1763599..daba7ab 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/parser/arithmetic/Instruction.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/parser/arithmetic/Instruction.kt
@@ -1,16 +1,15 @@
package com.pixelized.desktop.lwa.parser.arithmetic
-sealed class Instruction(
- val sign: Int,
-) {
- class Dice(
- sign: Int,
+sealed class Instruction {
+ abstract val sign: Int
+
+ data class Dice(
+ override val sign: Int,
val modifier: Modifier?,
val quantity: Int,
val faces: Int,
- ) : Instruction(
- sign = sign,
- ) {
+ ) : Instruction() {
+
enum class Modifier {
ADVANTAGE,
DISADVANTAGE,
@@ -29,23 +28,20 @@ sealed class Instruction(
}
}
- class Flat(
- sign: Int,
+ data class Flat(
+ override val sign: Int,
val value: Int,
- ) : Instruction(
- sign = sign,
- ) {
+ ) : Instruction() {
override fun toString(): String {
return "${sign.sign}${value}"
}
}
- class Word(
- sign: Int,
+ data class Word(
+ override val sign: Int,
val type: Type,
- ) : Instruction(
- sign = sign
- ) {
+ ) : Instruction() {
+
enum class Type {
BDC, // Damages bonus for melee
BDD, // Damages bonus for range
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetJsonFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetJsonFactory.kt
index f6bde59..40a7576 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetJsonFactory.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetJsonFactory.kt
@@ -1,34 +1,13 @@
package com.pixelized.desktop.lwa.repository.characterSheet
-import com.pixelized.desktop.lwa.business.DamageBonusUseCase
-import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
+import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJson
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJsonV1
-import kotlinx.coroutines.runBlocking
-import lwacharactersheet.composeapp.generated.resources.Res
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__acrobatics
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__aid
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__athletics
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__bargain
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__combat
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__discretion
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__dodge
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__empathy
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__grab
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__intimidation
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__perception
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__persuasion
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__search
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__sleight_of_hand
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__spiel
-import lwacharactersheet.composeapp.generated.resources.tooltip__skills__throw
-import org.jetbrains.compose.resources.getString
-import kotlin.math.ceil
class CharacterSheetJsonFactory(
- private val bonusDamageUseCase: DamageBonusUseCase,
private val skillDescriptionFactory: SkillDescriptionFactory,
+ private val characterSheetUseCase: CharacterSheetUseCase,
) {
fun convertToJson(
@@ -51,6 +30,8 @@ class CharacterSheetJsonFactory(
maxPP = if (sheet.overrideMaxPP) sheet.maxPp else null,
damageBonus = if (sheet.overrideDamageBonus) sheet.damageBonus else null,
armor = if (sheet.overrideArmor) sheet.armor else null,
+ learning = if (sheet.overrideLearning) sheet.learning else null,
+ hpGrowf = if (sheet.overrideHpGrow) sheet.hpGrow else null,
skills = sheet.commonSkills.map {
CharacterSheetJsonV1.Skill(
id = it.id,
@@ -108,8 +89,8 @@ class CharacterSheetJsonFactory(
private suspend fun convertFromV1(
json: CharacterSheetJsonV1,
- ): CharacterSheet {
- val sheet = CharacterSheet(
+ ): CharacterSheet = characterSheetUseCase.run {
+ CharacterSheet(
id = json.id,
name = json.name,
strength = json.strength,
@@ -120,21 +101,27 @@ class CharacterSheetJsonFactory(
power = json.power,
charisma = json.charisma,
overrideMovement = json.movement != null,
- movement = json.movement ?: 10,
+ movement = json.movement ?: defaultMovement(),
currentHp = json.currentHp,
overrideMaxHp = json.maxHp != null,
- maxHp = json.maxHp ?: (ceil((json.constitution + json.height) / 2f).toInt()),
+ maxHp = json.maxHp ?: defaultMaxHp(
+ constitution = json.constitution,
+ height = json.height,
+ ),
currentPp = json.currentPP,
overrideMaxPP = json.maxPP != null,
- maxPp = json.maxPP ?: json.power,
+ maxPp = json.maxPP ?: defaultMaxPower(power = json.power),
overrideDamageBonus = json.damageBonus != null,
- damageBonus = json.damageBonus
- ?: bonusDamageUseCase.bonusDamage(
- strength = json.strength,
- height = json.height
- ),
+ damageBonus = json.damageBonus ?: defaultDamageBonus(
+ strength = json.strength,
+ height = json.height,
+ ),
overrideArmor = json.armor != null,
- armor = json.armor ?: 0,
+ armor = json.armor ?: defaultArmor(),
+ overrideLearning = json.learning != null,
+ learning = json.learning ?: defaultLearning(intelligence = json.intelligence),
+ overrideHpGrow = json.hpGrowf != null,
+ hpGrow = json.hpGrowf ?: defaultHpGrow(constitution = json.constitution),
commonSkills = json.skills.map {
CharacterSheet.Skill(
id = it.id,
@@ -179,6 +166,5 @@ class CharacterSheetJsonFactory(
)
},
)
- return sheet
}
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/model/CharacterSheet.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/model/CharacterSheet.kt
index 2ce9e5b..254c58c 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/model/CharacterSheet.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/model/CharacterSheet.kt
@@ -24,6 +24,10 @@ data class CharacterSheet(
val damageBonus: String,
val overrideArmor: Boolean,
val armor: Int,
+ val overrideLearning: Boolean,
+ val learning: Int,
+ val overrideHpGrow: Boolean,
+ val hpGrow: Int,
// skills
val commonSkills: List,
val specialSkills: List,
@@ -80,5 +84,7 @@ data class CharacterSheet(
const val PP = "PP"
const val DMG = "DMG"
const val ARMOR = "ARMOR"
+ const val LB = "LEARNING"
+ const val GHP = "HP_GROW"
}
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/model/CharacterSheetJsonV1.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/model/CharacterSheetJsonV1.kt
index 5668a85..d2e4550 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/model/CharacterSheetJsonV1.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/model/CharacterSheetJsonV1.kt
@@ -22,6 +22,8 @@ data class CharacterSheetJsonV1(
val maxPP: Int?,
val damageBonus: String?,
val armor: Int?,
+ val learning: Int?,
+ val hpGrowf: Int?,
// skills
val skills: List,
// occupations
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetFactory.kt
index 49df2d3..ef9142d 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetFactory.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetFactory.kt
@@ -18,6 +18,8 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet__charact
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__armor
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__damage_bonus
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__hit_point
+import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__hp_grow
+import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__learning
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__movement
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__power_point
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__charisma
@@ -30,6 +32,8 @@ import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__armor
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__bonus_damage
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__hit_point
+import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__hp_grow
+import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__learning
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__movement
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__power_point
import org.jetbrains.compose.resources.getString
@@ -171,6 +175,26 @@ class CharacterSheetFactory(
),
editable = false,
),
+ Characteristic(
+ id = CharacteristicId.LB,
+ label = getString(Res.string.character_sheet__sub_characteristics__learning),
+ value = "${sheet.learning}",
+ tooltips = TooltipUio(
+ title = getString(Res.string.character_sheet__sub_characteristics__learning),
+ description = getString(Res.string.tooltip__sub_characteristics__learning),
+ ),
+ editable = false,
+ ),
+ Characteristic(
+ id = CharacteristicId.GHP,
+ label = getString(Res.string.character_sheet__sub_characteristics__hp_grow),
+ value = "${sheet.hpGrow}",
+ tooltips = TooltipUio(
+ title = getString(Res.string.character_sheet__sub_characteristics__hp_grow),
+ description = getString(Res.string.tooltip__sub_characteristics__hp_grow),
+ ),
+ editable = false,
+ ),
),
commonSkills = sheet.commonSkills.map { skill ->
Node(
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditFactory.kt
index f061317..eb94cc0 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditFactory.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditFactory.kt
@@ -3,8 +3,7 @@ package com.pixelized.desktop.lwa.screen.characterSheet.edit
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
-import com.pixelized.desktop.lwa.business.DamageBonusUseCase
-import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
+import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
import com.pixelized.desktop.lwa.repository.characterSheet.SkillDescriptionFactory
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.SkillFieldFactory
@@ -45,27 +44,26 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sk
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__throw
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__armor
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__damage_bonus
-import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__hit_point
+import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__hp_grow
+import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__learning
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__max_hit_point
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__max_power_point
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__movement
-import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__power_point
import org.jetbrains.compose.resources.getString
import java.util.UUID
-import kotlin.math.ceil
import kotlin.math.max
-import kotlin.math.min
class CharacterSheetEditFactory(
- private val bonusDamageUseCase: DamageBonusUseCase,
+ private val characterSheetUseCase: CharacterSheetUseCase,
private val skillFieldFactory: SkillFieldFactory,
private val skillDescriptionFactory: SkillDescriptionFactory,
- private val normalizer: SkillNormalizerUseCase,
) {
suspend fun updateCharacterSheet(
currentSheet: CharacterSheet?,
editedSheet: CharacterSheetEditPageUio,
): CharacterSheet {
+ val editedMaxHp = editedSheet.maxHp.unpack()?.toIntOrNull() ?: currentSheet?.maxHp ?: 0
+ val editedMaxPp = editedSheet.maxPp.unpack()?.toIntOrNull() ?: currentSheet?.maxPp ?: 0
return CharacterSheet(
id = editedSheet.id,
name = editedSheet.name.value.value,
@@ -95,19 +93,11 @@ class CharacterSheetEditFactory(
?: currentSheet?.movement
?: 10,
overrideMaxHp = editedSheet.maxHp.value.value.value.isNotBlank(),
- maxHp = editedSheet.maxHp.unpack()?.toIntOrNull()
- ?: currentSheet?.maxHp
- ?: 0,
- currentHp = editedSheet.currentHp.unpack()?.toIntOrNull()
- ?: currentSheet?.currentHp
- ?: 0,
+ maxHp = editedMaxHp,
+ currentHp = currentSheet?.currentHp?.coerceAtMost(editedMaxHp) ?: editedMaxHp,
overrideMaxPP = editedSheet.maxPp.value.value.value.isNotBlank(),
- maxPp = editedSheet.maxPp.unpack()?.toIntOrNull()
- ?: currentSheet?.maxPp
- ?: 0,
- currentPp = editedSheet.currentPp.unpack()?.toIntOrNull()
- ?: currentSheet?.currentPp
- ?: 0,
+ maxPp = editedMaxPp,
+ currentPp = currentSheet?.currentPp?.coerceAtMost(editedMaxPp) ?: editedMaxPp,
overrideDamageBonus = editedSheet.damageBonus.value.value.value.isNotBlank(),
damageBonus = editedSheet.damageBonus.unpack()
?: currentSheet?.damageBonus
@@ -116,6 +106,10 @@ class CharacterSheetEditFactory(
armor = editedSheet.armor.unpack()?.toIntOrNull()
?: currentSheet?.armor
?: 0,
+ overrideLearning = editedSheet.learning.value.value.value.isNotBlank(),
+ learning = editedSheet.learning.unpack()?.toIntOrNull() ?: 0,
+ overrideHpGrow = editedSheet.hpGrow.value.value.value.isNotBlank(),
+ hpGrow = editedSheet.hpGrow.unpack()?.toIntOrNull() ?: 0,
commonSkills = editedSheet.commonSkills.map { editedSkill ->
val currentSkill = currentSheet?.commonSkills?.firstOrNull {
it.id == editedSkill.id
@@ -236,239 +230,243 @@ class CharacterSheetEditFactory(
val specialSkillsLabel = getString(Res.string.character_sheet_edit__skills__special_title)
val magicSkillsLabel = getString(Res.string.character_sheet_edit__skills__magic_title)
- val maxHitPoint = SimpleFieldUio(
- label = getString(Res.string.character_sheet_edit__sub_characteristics__max_hit_point),
- value = skillFieldFactory.createWrapper(
- value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
- placeholder = derivedStateOf { "${ceil((con() + hei()) / 2f).toInt()}" },
- )
- )
- val maxPowerPoint = SimpleFieldUio(
- label = getString(Res.string.character_sheet_edit__sub_characteristics__max_power_point),
- value = skillFieldFactory.createWrapper(
- value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
- placeholder = derivedStateOf { "${pow()}" },
- )
- )
-
- return CharacterSheetEditPageUio(
- id = sheet?.id ?: UUID.randomUUID().toString(),
- name = skillFieldFactory.createWrapper(
- label = mutableStateOf(getString(Res.string.character_sheet_edit__name_label)),
- value = sheet?.name ?: ""
- ),
- strength = str,
- dexterity = dex,
- constitution = con,
- height = hei,
- intelligence = int,
- power = pow,
- charisma = cha,
- movement = SimpleFieldUio(
- label = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
- value = skillFieldFactory.createWrapper(
- value = if (sheet?.overrideMovement == true) "${sheet.movement}" else "",
- placeholder = mutableStateOf("10"),
- )
- ),
- maxHp = maxHitPoint,
- currentHp = SimpleFieldUio(
- label = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point),
- value = skillFieldFactory.createWrapper(
- enable = false,
- placeholder = derivedStateOf {
- val min = min(
- sheet?.currentHp ?: Int.MAX_VALUE,
- maxHitPoint.unpack()?.toIntOrNull() ?: Int.MAX_VALUE,
- )
- if (min != Int.MAX_VALUE) "$min" else ""
- },
- )
- ),
- maxPp = maxPowerPoint,
- currentPp = SimpleFieldUio(
- label = getString(Res.string.character_sheet_edit__sub_characteristics__power_point),
- value = skillFieldFactory.createWrapper(
- enable = false,
- placeholder = derivedStateOf {
- val min = min(
- sheet?.currentPp ?: Int.MAX_VALUE,
- maxPowerPoint.unpack()?.toIntOrNull() ?: Int.MAX_VALUE,
- )
- if (min != Int.MAX_VALUE) "$min" else ""
- },
- )
- ),
- damageBonus = SimpleFieldUio(
- label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
- value = skillFieldFactory.createWrapper(
- value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
- placeholder = derivedStateOf {
- bonusDamageUseCase.bonusDamage(
- strength = str(),
- height = hei()
- )
- },
- )
- ),
- armor = SimpleFieldUio(
- label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
- value = skillFieldFactory.createWrapper(
- value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
- placeholder = mutableStateOf("0"),
- )
- ),
- commonSkills = listOf(
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.COMBAT_ID,
- label = getString(Res.string.character_sheet_edit__skills__combat),
- base = derivedStateOf { normalizer.normalize(dex() * 2) },
+ return with(characterSheetUseCase) {
+ CharacterSheetEditPageUio(
+ id = sheet?.id ?: UUID.randomUUID().toString(),
+ name = skillFieldFactory.createWrapper(
+ label = mutableStateOf(getString(Res.string.character_sheet_edit__name_label)),
+ value = sheet?.name ?: ""
),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.DODGE_ID,
- label = getString(Res.string.character_sheet_edit__skills__dodge),
- base = derivedStateOf { normalizer.normalize(dex() * 2) },
+ strength = str,
+ dexterity = dex,
+ constitution = con,
+ height = hei,
+ intelligence = int,
+ power = pow,
+ charisma = cha,
+ movement = SimpleFieldUio(
+ label = getString(Res.string.character_sheet_edit__sub_characteristics__movement),
+ value = skillFieldFactory.createWrapper(
+ value = if (sheet?.overrideMovement == true) "${sheet.movement}" else "",
+ placeholder = derivedStateOf {
+ "${characterSheetUseCase.defaultMovement()}"
+ },
+ )
),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.GRAB_ID,
- label = getString(Res.string.character_sheet_edit__skills__grab),
- base = derivedStateOf { normalizer.normalize(str() + hei()) },
+ maxHp = SimpleFieldUio(
+ label = getString(Res.string.character_sheet_edit__sub_characteristics__max_hit_point),
+ value = skillFieldFactory.createWrapper(
+ value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
+ placeholder = derivedStateOf {
+ "${
+ characterSheetUseCase.defaultMaxHp(
+ constitution = con(),
+ height = hei()
+ )
+ }"
+ },
+ )
),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.THROW_ID,
- label = getString(Res.string.character_sheet_edit__skills__throw),
- base = derivedStateOf { normalizer.normalize(str() + dex()) },
+ maxPp = SimpleFieldUio(
+ label = getString(Res.string.character_sheet_edit__sub_characteristics__max_power_point),
+ value = skillFieldFactory.createWrapper(
+ value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
+ placeholder = derivedStateOf {
+ "${characterSheetUseCase.defaultMaxPower(power = pow())}"
+ },
+ )
),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.ATHLETICS_ID,
- label = getString(Res.string.character_sheet_edit__skills__athletics),
- base = derivedStateOf { normalizer.normalize(str() + con() * 2) },
+ damageBonus = SimpleFieldUio(
+ label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
+ value = skillFieldFactory.createWrapper(
+ value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
+ placeholder = derivedStateOf {
+ characterSheetUseCase.defaultDamageBonus(
+ strength = str(),
+ height = hei()
+ )
+ },
+ )
),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.ACROBATICS_ID,
- label = getString(Res.string.character_sheet_edit__skills__acrobatics),
- base = derivedStateOf { normalizer.normalize(dex() + con() * 2) },
+ armor = SimpleFieldUio(
+ label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
+ value = skillFieldFactory.createWrapper(
+ value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
+ placeholder = derivedStateOf {
+ "${characterSheetUseCase.defaultArmor()}"
+ },
+ )
),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.PERCEPTION_ID,
- label = getString(Res.string.character_sheet_edit__skills__perception),
- base = derivedStateOf { normalizer.normalize(10 + int() * 2) },
+ learning = SimpleFieldUio(
+ label = getString(Res.string.character_sheet_edit__sub_characteristics__learning),
+ value = skillFieldFactory.createWrapper(
+ value = if (sheet?.overrideLearning == true) "${sheet.learning}" else "",
+ placeholder = derivedStateOf {
+ "${characterSheetUseCase.defaultLearning(intelligence = int())}"
+ },
+ )
),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.SEARCH_ID,
- label = getString(Res.string.character_sheet_edit__skills__search),
- base = derivedStateOf { normalizer.normalize(10 + int() * 2) },
+ hpGrow = SimpleFieldUio(
+ label = getString(Res.string.character_sheet_edit__sub_characteristics__hp_grow),
+ value = skillFieldFactory.createWrapper(
+ value = if (sheet?.overrideHpGrow == true) "${sheet.hpGrow}" else "",
+ placeholder = derivedStateOf {
+ "${characterSheetUseCase.defaultHpGrow(constitution = con())}"
+ },
+ )
),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.EMPATHY_ID,
- label = getString(Res.string.character_sheet_edit__skills__empathy),
- base = derivedStateOf { normalizer.normalize(cha() + int()) },
- ),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.PERSUASION_ID,
- label = getString(Res.string.character_sheet_edit__skills__persuasion),
- base = derivedStateOf { normalizer.normalize(cha() * 3) },
- ),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.INTIMIDATION_ID,
- label = getString(Res.string.character_sheet_edit__skills__intimidation),
- base = derivedStateOf { normalizer.normalize(cha() + max(pow(), hei()) * 2) },
- ),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.SPIEL_ID,
- label = getString(Res.string.character_sheet_edit__skills__spiel),
- base = derivedStateOf { normalizer.normalize(cha() * 2 + int()) },
- ),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.BARGAIN_ID,
- label = getString(Res.string.character_sheet_edit__skills__bargain),
- base = derivedStateOf { normalizer.normalize(cha() * 2) },
- ),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.DISCRETION_ID,
- label = getString(Res.string.character_sheet_edit__skills__discretion),
- base = derivedStateOf { normalizer.normalize(cha() + dex() * 2 - hei()) },
- ),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID,
- label = getString(Res.string.character_sheet_edit__skills__sleight_of_hand),
- base = derivedStateOf { normalizer.normalize(dex() * 2) },
- ),
- createBaseSkill(
- sheet = sheet,
- id = CharacterSheet.CommonSkillId.AID_ID,
- label = getString(Res.string.character_sheet_edit__skills__aid),
- base = derivedStateOf { normalizer.normalize(int() + dex()) },
- ),
- ),
- specialSkills = sheet?.specialSkills?.map { skill ->
- skillFieldFactory.createSkill(
- id = skill.id,
- label = specialSkillsLabel,
- descriptionValue = skill.description ?: "",
- labelValue = skill.label,
- baseValue = skill.base,
- bonusValue = skill.bonus ?: "",
- levelValue = skill.level ?: "",
- options = run {
- val current = sheet.specialSkills.firstOrNull { it.id == skill.id }
- listOf(
- skillFieldFactory.occupationOption(checked = current?.occupation ?: false),
- skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
- )
- },
- )
- } ?: emptyList(),
- magicSkills = sheet?.magicSkills?.map { skill ->
- skillFieldFactory.createSkill(
- id = skill.id,
- label = magicSkillsLabel,
- descriptionValue = skill.description ?: "",
- labelValue = skill.label,
- baseValue = skill.base,
- bonusValue = skill.bonus ?: "",
- levelValue = skill.level ?: "",
- options = run {
- val current = sheet.magicSkills.firstOrNull { it.id == skill.id }
- listOf(
- skillFieldFactory.occupationOption(
- checked = current?.occupation ?: false
- ),
- skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
- )
- },
- )
- } ?: emptyList(),
- actions = sheet?.actions?.map { action ->
- ActionFieldUio(
- id = action.id,
- label = skillFieldFactory.createWrapper(
- label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__name_label)),
- value = action.label,
+ commonSkills = listOf(
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.COMBAT_ID,
+ label = getString(Res.string.character_sheet_edit__skills__combat),
+ base = derivedStateOf { normalize(dex() * 2) },
),
- action = skillFieldFactory.createWrapper(
- label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__action_label)),
- value = action.roll,
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.DODGE_ID,
+ label = getString(Res.string.character_sheet_edit__skills__dodge),
+ base = derivedStateOf { normalize(dex() * 2) },
),
- option = skillFieldFactory.deleteOption { onDeleteSkill(action.id) },
- )
- } ?: emptyList(),
- )
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.GRAB_ID,
+ label = getString(Res.string.character_sheet_edit__skills__grab),
+ base = derivedStateOf { normalize(str() + hei()) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.THROW_ID,
+ label = getString(Res.string.character_sheet_edit__skills__throw),
+ base = derivedStateOf { normalize(str() + dex()) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.ATHLETICS_ID,
+ label = getString(Res.string.character_sheet_edit__skills__athletics),
+ base = derivedStateOf { normalize(str() + con() * 2) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.ACROBATICS_ID,
+ label = getString(Res.string.character_sheet_edit__skills__acrobatics),
+ base = derivedStateOf { normalize(dex() + con() * 2) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.PERCEPTION_ID,
+ label = getString(Res.string.character_sheet_edit__skills__perception),
+ base = derivedStateOf { normalize(10 + int() * 2) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.SEARCH_ID,
+ label = getString(Res.string.character_sheet_edit__skills__search),
+ base = derivedStateOf { normalize(10 + int() * 2) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.EMPATHY_ID,
+ label = getString(Res.string.character_sheet_edit__skills__empathy),
+ base = derivedStateOf { normalize(cha() + int()) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.PERSUASION_ID,
+ label = getString(Res.string.character_sheet_edit__skills__persuasion),
+ base = derivedStateOf { normalize(cha() * 3) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.INTIMIDATION_ID,
+ label = getString(Res.string.character_sheet_edit__skills__intimidation),
+ base = derivedStateOf { normalize(cha() + max(pow(), hei()) * 2) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.SPIEL_ID,
+ label = getString(Res.string.character_sheet_edit__skills__spiel),
+ base = derivedStateOf { normalize(cha() * 2 + int()) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.BARGAIN_ID,
+ label = getString(Res.string.character_sheet_edit__skills__bargain),
+ base = derivedStateOf { normalize(cha() * 2) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.DISCRETION_ID,
+ label = getString(Res.string.character_sheet_edit__skills__discretion),
+ base = derivedStateOf { normalize(cha() + dex() * 2 - hei()) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.SLEIGHT_OF_HAND_ID,
+ label = getString(Res.string.character_sheet_edit__skills__sleight_of_hand),
+ base = derivedStateOf { normalize(dex() * 2) },
+ ),
+ createBaseSkill(
+ sheet = sheet,
+ id = CharacterSheet.CommonSkillId.AID_ID,
+ label = getString(Res.string.character_sheet_edit__skills__aid),
+ base = derivedStateOf { normalize(int() + dex()) },
+ ),
+ ),
+ specialSkills = sheet?.specialSkills?.map { skill ->
+ skillFieldFactory.createSkill(
+ id = skill.id,
+ label = specialSkillsLabel,
+ descriptionValue = skill.description ?: "",
+ labelValue = skill.label,
+ baseValue = skill.base,
+ bonusValue = skill.bonus ?: "",
+ levelValue = skill.level ?: "",
+ options = run {
+ val current = sheet.specialSkills.firstOrNull { it.id == skill.id }
+ listOf(
+ skillFieldFactory.occupationOption(current?.occupation ?: false),
+ skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
+ )
+ },
+ )
+ } ?: emptyList(),
+ magicSkills = sheet?.magicSkills?.map { skill ->
+ skillFieldFactory.createSkill(
+ id = skill.id,
+ label = magicSkillsLabel,
+ descriptionValue = skill.description ?: "",
+ labelValue = skill.label,
+ baseValue = skill.base,
+ bonusValue = skill.bonus ?: "",
+ levelValue = skill.level ?: "",
+ options = run {
+ val current = sheet.magicSkills.firstOrNull { it.id == skill.id }
+ listOf(
+ skillFieldFactory.occupationOption(
+ checked = current?.occupation ?: false
+ ),
+ skillFieldFactory.deleteOption { onDeleteSkill(skill.id) },
+ )
+ },
+ )
+ } ?: emptyList(),
+ actions = sheet?.actions?.map { action ->
+ ActionFieldUio(
+ id = action.id,
+ label = skillFieldFactory.createWrapper(
+ label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__name_label)),
+ value = action.label,
+ ),
+ action = skillFieldFactory.createWrapper(
+ label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__action_label)),
+ value = action.roll,
+ ),
+ option = skillFieldFactory.deleteOption { onDeleteSkill(action.id) },
+ )
+ } ?: emptyList(),
+ )
+ }
}
private suspend fun createBaseSkill(
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt
index 98c50f6..7aa4b8b 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditPage.kt
@@ -70,10 +70,10 @@ data class CharacterSheetEditPageUio(
val movement: SimpleFieldUio,
val maxHp: SimpleFieldUio,
val maxPp: SimpleFieldUio,
- val currentHp: SimpleFieldUio,
- val currentPp: SimpleFieldUio,
val damageBonus: SimpleFieldUio,
val armor: SimpleFieldUio,
+ val learning: SimpleFieldUio,
+ val hpGrow: SimpleFieldUio,
val commonSkills: List,
val specialSkills: List,
val magicSkills: List,
@@ -94,11 +94,11 @@ data class CharacterSheetEditPageUio(
get() = listOf(
movement,
maxHp,
- currentHp,
maxPp,
- currentPp,
damageBonus,
armor,
+ learning,
+ hpGrow,
)
}
diff --git a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCaseTest.kt b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCaseTest.kt
index 28d8bfe..f6fcc7b 100644
--- a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCaseTest.kt
+++ b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCaseTest.kt
@@ -6,43 +6,45 @@ class DamageBonusUseCaseTest {
@Test
fun testBonusDamage() {
+ val userCase = CharacterSheetUseCase()
+
(0 until 12).forEach {
- val result = DamageBonusUseCase.bonusDamage(stat = it)
+ val result = userCase.defaultDamageBonus(sum = it)
val expected = "-1d6"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(12 until 18).forEach {
- val result = DamageBonusUseCase.bonusDamage(stat = it)
+ val result = userCase.defaultDamageBonus(sum = it)
val expected = "-1d4"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(18 until 23).forEach {
- val result = DamageBonusUseCase.bonusDamage(stat = it)
+ val result = userCase.defaultDamageBonus(sum = it)
val expected = "+0"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(23 until 30).forEach {
- val result = DamageBonusUseCase.bonusDamage(stat = it)
+ val result = userCase.defaultDamageBonus(sum = it)
val expected = "+1d4"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(30 until 40).forEach {
- val result = DamageBonusUseCase.bonusDamage(stat = it)
+ val result = userCase.defaultDamageBonus(sum = it)
val expected = "+1d6"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
}
}
(40 until 100).forEach {
- val result = DamageBonusUseCase.bonusDamage(stat = it)
+ val result = userCase.defaultDamageBonus(sum = it)
val expected = "+2d6"
assert(result == expected) {
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
diff --git a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/RollUseCaseTest.kt b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/RollUseCaseTest.kt
index 356de21..9a0aac1 100644
--- a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/RollUseCaseTest.kt
+++ b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/RollUseCaseTest.kt
@@ -5,7 +5,7 @@ import org.junit.Test
class RollUseCaseTest {
companion object {
- private const val ROLL_COUNT = 1000000000
+ private const val ROLL_COUNT = 100000000 // 100*10^6
}
@Test
@@ -20,16 +20,18 @@ class RollUseCaseTest {
@Test
fun testRoll1D100_() {
- val result = build1D100ResultSet()
+ val results = build1D100ResultSet()
- val delta = 0.001f
+ val delta = 0.005f
val median = (ROLL_COUNT / 100).let {
(it * (1f - delta)).toInt()..(it * (1f + delta)).toInt()
}
println("Testing if with $ROLL_COUNT rolls we have at least all results in $median.")
- assert(result.all { it in median }) {
- "Maybe a false negative, we expected that all values should be in $median a result.\nroll amount: $ROLL_COUNT - result:$result"
+ results.map { it in median }.forEachIndexed { index, result ->
+ assert(result) {
+ "Maybe a false negative, we expected that all values should be in $median a result.\nroll amount: $ROLL_COUNT - index:$index result:${results[index]}"
+ }
}
}
@@ -37,7 +39,7 @@ class RollUseCaseTest {
val useCase = RollUseCase()
val result = MutableList(100) { 0 }
repeat(count) {
- val roll = useCase.rollD100()
+ val roll = useCase.roll(faces = 100)
result[roll - 1] += 1
}
return result
diff --git a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/SkillNormalizerUseCaseText.kt b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/SkillNormalizerUseCaseText.kt
index d2c3273..f5b67da 100644
--- a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/SkillNormalizerUseCaseText.kt
+++ b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/SkillNormalizerUseCaseText.kt
@@ -6,7 +6,8 @@ class SkillNormalizerUseCaseText {
@Test
fun testNormalization() {
- val useCase = SkillNormalizerUseCase()
+ val useCase = CharacterSheetUseCase()
+
val samples = listOf(
0 to 0,
1 to 0,
@@ -19,6 +20,96 @@ class SkillNormalizerUseCaseText {
8 to 5,
9 to 5,
10 to 10,
+ 11 to 10,
+ 12 to 10,
+ 13 to 10,
+ 14 to 10,
+ 15 to 15,
+ 16 to 15,
+ 17 to 15,
+ 18 to 15,
+ 19 to 15,
+ 20 to 20,
+ 21 to 20,
+ 22 to 20,
+ 23 to 20,
+ 24 to 20,
+ 25 to 25,
+ 26 to 25,
+ 27 to 25,
+ 28 to 25,
+ 29 to 25,
+ 30 to 30,
+ 31 to 30,
+ 32 to 30,
+ 33 to 30,
+ 34 to 30,
+ 35 to 35,
+ 36 to 35,
+ 37 to 35,
+ 38 to 35,
+ 39 to 35,
+ 40 to 40,
+ 41 to 40,
+ 42 to 40,
+ 43 to 40,
+ 44 to 40,
+ 45 to 45,
+ 46 to 45,
+ 47 to 45,
+ 48 to 45,
+ 49 to 45,
+ 50 to 50,
+ 51 to 50,
+ 52 to 50,
+ 53 to 50,
+ 54 to 50,
+ 55 to 55,
+ 56 to 55,
+ 57 to 55,
+ 58 to 55,
+ 59 to 55,
+ 60 to 60,
+ 61 to 60,
+ 62 to 60,
+ 63 to 60,
+ 64 to 60,
+ 65 to 65,
+ 66 to 65,
+ 67 to 65,
+ 68 to 65,
+ 69 to 65,
+ 70 to 70,
+ 71 to 70,
+ 72 to 70,
+ 73 to 70,
+ 74 to 70,
+ 75 to 75,
+ 76 to 75,
+ 77 to 75,
+ 78 to 75,
+ 79 to 75,
+ 80 to 80,
+ 81 to 80,
+ 82 to 80,
+ 83 to 80,
+ 84 to 80,
+ 85 to 85,
+ 86 to 85,
+ 87 to 85,
+ 88 to 85,
+ 89 to 85,
+ 90 to 90,
+ 91 to 90,
+ 92 to 90,
+ 93 to 90,
+ 94 to 90,
+ 95 to 95,
+ 96 to 95,
+ 97 to 95,
+ 98 to 95,
+ 99 to 95,
+ 100 to 100,
)
samples.forEach { (value, expected) ->
assert(useCase.normalize(value) == expected) {
diff --git a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/SkillStepUseCaseTest.kt b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/SkillStepUseCaseTest.kt
index 6e90b07..6cdbaef 100644
--- a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/SkillStepUseCaseTest.kt
+++ b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/SkillStepUseCaseTest.kt
@@ -7,8 +7,9 @@ class SkillStepUseCaseTest {
@Test
fun testStepForSkill() {
+ val useCase = SkillStepUseCase()
(1..500).forEach { skill ->
- val step = SkillStepUseCase.computeSkillStep(
+ val step = useCase.computeSkillStep(
skill = skill,
)
val expected = expected[skill] ?: error(
diff --git a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/parser/InstructionParserTest.kt b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/parser/InstructionParserTest.kt
index 9629dcc..54aa7ae 100644
--- a/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/parser/InstructionParserTest.kt
+++ b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/parser/InstructionParserTest.kt
@@ -13,16 +13,16 @@ class InstructionParserTest {
fun test(
instruction: String,
- expectedModifier: Instruction.Dice.Modifier.Dice.Modifier?,
+ expectedModifier: Instruction.Dice.Modifier?,
expectedQuantity: Int,
expectedFaces: Int,
) {
- val dice = parser.parseInstruction(instruction = instruction)
+ val dice = parser.parse(value = instruction).first()
- assert(dice is Instruction.Dice.Dice) {
+ assert(dice is Instruction.Dice) {
"Instruction should be ArithmeticInstruction.Dice but was: ${dice::class.java.simpleName}"
}
- (dice as? Instruction.Dice.Dice)?.let {
+ (dice as? Instruction.Dice)?.let {
assert(dice.modifier == expectedModifier) {
"$instruction modifier should be:\"$expectedModifier\", but was: ${dice.modifier}"
}
@@ -66,14 +66,14 @@ class InstructionParserTest {
val parser = ArithmeticParser()
ArithmeticParser.words.map { instruction ->
- val word = parser.parseInstruction(instruction = instruction)
+ val word = parser.parse(value = instruction).first()
- assert(word is Instruction.Word.Word) {
+ assert(word is Instruction.Word) {
"Instruction should be ArithmeticInstruction.Word but was: ${word::class.java.simpleName}"
}
- (word as? Instruction.Word.Word)?.let {
- assert(it.name == instruction) {
- "Instruction should be $instruction, but was ${it.name}"
+ (word as? Instruction.Word)?.let {
+ assert(it.type.name == instruction) {
+ "Instruction should be $instruction, but was ${it.type.name}"
}
}
}
@@ -84,12 +84,12 @@ class InstructionParserTest {
val parser = ArithmeticParser()
"100".let { instruction ->
- val flat = parser.parseInstruction(instruction = instruction)
+ val flat = parser.parse(value = instruction).first()
- assert(flat is Instruction.Flat.Flat) {
+ assert(flat is Instruction.Flat) {
"Instruction should be ArithmeticInstruction.Flat but was: ${flat::class.java.simpleName}"
}
- (flat as? Instruction.Flat.Flat)?.let {
+ (flat as? Instruction.Flat)?.let {
assert("${it.value}" == instruction) {
"Instruction should be $instruction, but was ${it.value}"
}
@@ -97,59 +97,42 @@ class InstructionParserTest {
}
}
- @Test
- fun testFailedInstructionParse() {
- val parser = ArithmeticParser()
- assertFails(
- message = "Instruction parse should failed with UnknownInstruction",
- ) {
- parser.parseInstruction(instruction = "a110")
- }
- }
-
@Test
fun testRollParse() {
val parser = ArithmeticParser()
fun test(
- arithmetics: Instruction,
- expectedSign: Int,
+ instruction: Instruction,
expectedInstruction: Instruction,
) {
- assert(arithmetics.sign == expectedSign) {
- "Arithmetic sign should be $expectedSign but was: ${arithmetics.sign}"
- }
- assert(arithmetics.instruction == expectedInstruction) {
- "Arithmetic instruction should be $expectedInstruction but was: ${arithmetics.instruction}"
+ assert(instruction == expectedInstruction) {
+ "Arithmetic instruction should be $expectedInstruction but was: $instruction"
}
}
- val instructions = parser.parse(value = "1+1d6+2-BDC+BDD")
+ val instructions = parser.parse(
+ value = "1+1d6+2-BDC+BDD",
+ )
test(
- arithmetics = instructions[0],
- expectedSign = 1,
- expectedInstruction = Instruction.Flat(value = 1),
+ instruction = instructions[0],
+ expectedInstruction = Instruction.Flat(sign = 1, value = 1),
)
test(
- arithmetics = instructions[1],
- expectedSign = 1,
- expectedInstruction = Instruction.Dice(quantity = 1, faces = 6, modifier = null),
+ instruction = instructions[1],
+ expectedInstruction = Instruction.Dice(sign = 1, modifier = null, quantity = 1, faces = 6),
)
test(
- arithmetics = instructions[2],
- expectedSign = 1,
- expectedInstruction = Instruction.Flat(value = 2),
+ instruction = instructions[2],
+ expectedInstruction = Instruction.Flat(sign = 1, value = 2),
)
test(
- arithmetics = instructions[3],
- expectedSign = -1,
- expectedInstruction = Instruction.Word.BDC,
+ instruction = instructions[3],
+ expectedInstruction = Instruction.Word(sign = -1, type = Instruction.Word.Type.BDC),
)
test(
- arithmetics = instructions[4],
- expectedSign = 1,
- expectedInstruction = Instruction.Word.BDD,
+ instruction = instructions[4],
+ expectedInstruction = Instruction.Word(sign = 1, type = Instruction.Word.Type.BDD),
)
}
}
\ No newline at end of file