Add support for Hp grow bonus and Leaning bonus.
This commit is contained in:
parent
3419afbe59
commit
ca20078ffa
18 changed files with 526 additions and 402 deletions
|
|
@ -42,6 +42,8 @@
|
||||||
<string name="character_sheet_edit__sub_characteristics__power_point">Points de pouvoir</string>
|
<string name="character_sheet_edit__sub_characteristics__power_point">Points de pouvoir</string>
|
||||||
<string name="character_sheet_edit__sub_characteristics__damage_bonus">Bonus aux dégats</string>
|
<string name="character_sheet_edit__sub_characteristics__damage_bonus">Bonus aux dégats</string>
|
||||||
<string name="character_sheet_edit__sub_characteristics__armor">Armure</string>
|
<string name="character_sheet_edit__sub_characteristics__armor">Armure</string>
|
||||||
|
<string name="character_sheet_edit__sub_characteristics__learning">Bonus d'apprentissage</string>
|
||||||
|
<string name="character_sheet_edit__sub_characteristics__hp_grow">Bonus de PV</string>
|
||||||
<string name="character_sheet_edit__skills__common_title">Compétences communes</string>
|
<string name="character_sheet_edit__skills__common_title">Compétences communes</string>
|
||||||
<string name="character_sheet_edit__skills__special_title">Compétences spéciales</string>
|
<string name="character_sheet_edit__skills__special_title">Compétences spéciales</string>
|
||||||
<string name="character_sheet_edit__skills__special_action">Ajouter une compétence spéciale</string>
|
<string name="character_sheet_edit__skills__special_action">Ajouter une compétence spéciale</string>
|
||||||
|
|
@ -94,6 +96,8 @@
|
||||||
<string name="character_sheet__sub_characteristics__power_point">Points de pouvoir</string>
|
<string name="character_sheet__sub_characteristics__power_point">Points de pouvoir</string>
|
||||||
<string name="character_sheet__sub_characteristics__damage_bonus">Bonus aux dégats</string>
|
<string name="character_sheet__sub_characteristics__damage_bonus">Bonus aux dégats</string>
|
||||||
<string name="character_sheet__sub_characteristics__armor">Armure</string>
|
<string name="character_sheet__sub_characteristics__armor">Armure</string>
|
||||||
|
<string name="character_sheet__sub_characteristics__learning">Bonus d'apprentissage</string>
|
||||||
|
<string name="character_sheet__sub_characteristics__hp_grow">Bonus de PV</string>
|
||||||
<string name="character_sheet__skills__common_title">Compétences communes</string>
|
<string name="character_sheet__skills__common_title">Compétences communes</string>
|
||||||
<string name="character_sheet__skills__special_title">Compétences spéciales</string>
|
<string name="character_sheet__skills__special_title">Compétences spéciales</string>
|
||||||
<string name="character_sheet__skills__magic_title">Compétences magiques</string>
|
<string name="character_sheet__skills__magic_title">Compétences magiques</string>
|
||||||
|
|
@ -113,7 +117,8 @@
|
||||||
<string name="tooltip__sub_characteristics__power_point">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.</string>
|
<string name="tooltip__sub_characteristics__power_point">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.</string>
|
||||||
<string name="tooltip__sub_characteristics__bonus_damage">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).</string>
|
<string name="tooltip__sub_characteristics__bonus_damage">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).</string>
|
||||||
<string name="tooltip__sub_characteristics__armor">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.</string>
|
<string name="tooltip__sub_characteristics__armor">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.</string>
|
||||||
|
<string name="tooltip__sub_characteristics__learning">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.</string>
|
||||||
|
<string name="tooltip__sub_characteristics__hp_grow">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.</string>
|
||||||
<string name="tooltip__skills__combat">Attaque en combat à mains nues. Une attaque réussie inflige 1D3 + BDGT.</string>
|
<string name="tooltip__skills__combat">Attaque en combat à mains nues. Une attaque réussie inflige 1D3 + BDGT.</string>
|
||||||
<string name="tooltip__skills__dodge">Éviter une attaque, un projectile, etc.</string>
|
<string name="tooltip__skills__dodge">Éviter une attaque, un projectile, etc.</string>
|
||||||
<string name="tooltip__skills__grab">Maitriser/immobiliser un adversaire.</string>
|
<string name="tooltip__skills__grab">Maitriser/immobiliser un adversaire.</string>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
package com.pixelized.desktop.lwa
|
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.RollUseCase
|
||||||
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
|
|
||||||
import com.pixelized.desktop.lwa.business.SkillStepUseCase
|
import com.pixelized.desktop.lwa.business.SkillStepUseCase
|
||||||
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
|
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
|
||||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
||||||
|
|
@ -71,9 +70,8 @@ val parserDependencies
|
||||||
|
|
||||||
val useCaseDependencies
|
val useCaseDependencies
|
||||||
get() = module {
|
get() = module {
|
||||||
factoryOf(::DamageBonusUseCase)
|
|
||||||
factoryOf(::SkillStepUseCase)
|
factoryOf(::SkillStepUseCase)
|
||||||
factoryOf(::SkillNormalizerUseCase)
|
|
||||||
factoryOf(::RollUseCase)
|
factoryOf(::RollUseCase)
|
||||||
factoryOf(::SkillValueComputationUseCase)
|
factoryOf(::SkillValueComputationUseCase)
|
||||||
|
factoryOf(::CharacterSheetUseCase)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -7,10 +7,6 @@ import kotlin.math.min
|
||||||
|
|
||||||
class RollUseCase {
|
class RollUseCase {
|
||||||
|
|
||||||
fun rollD100(): Int {
|
|
||||||
return roll(modifier = null, quantity = 1, faces = 100)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun roll(dice: Instruction.Dice): Int {
|
fun roll(dice: Instruction.Dice): Int {
|
||||||
return roll(
|
return roll(
|
||||||
modifier = dice.modifier,
|
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("{")
|
print("{")
|
||||||
return sum(count = quantity) {
|
return sum(count = quantity) { left ->
|
||||||
when (modifier) {
|
when (modifier) {
|
||||||
Instruction.Dice.Modifier.ADVANTAGE -> {
|
Instruction.Dice.Modifier.ADVANTAGE -> {
|
||||||
val roll1 = roll(faces = faces)
|
val roll1 = roll(faces = faces)
|
||||||
|
|
@ -54,6 +54,8 @@ class RollUseCase {
|
||||||
null -> {
|
null -> {
|
||||||
roll(faces = faces).also { print("$it") }
|
roll(faces = faces).also { print("$it") }
|
||||||
}
|
}
|
||||||
|
}.also {
|
||||||
|
if (quantity > 1 && left != 1) print(",")
|
||||||
}
|
}
|
||||||
}.also {
|
}.also {
|
||||||
print("}:")
|
print("}:")
|
||||||
|
|
@ -61,14 +63,14 @@ class RollUseCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun roll(faces: Int): Int {
|
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) {
|
return if (count > 1) {
|
||||||
block() + sum(count - 1, block)
|
block(count) + sum(count - 1, block)
|
||||||
} else {
|
} else {
|
||||||
block()
|
block(count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +1,15 @@
|
||||||
package com.pixelized.desktop.lwa.parser.arithmetic
|
package com.pixelized.desktop.lwa.parser.arithmetic
|
||||||
|
|
||||||
sealed class Instruction(
|
sealed class Instruction {
|
||||||
val sign: Int,
|
abstract val sign: Int
|
||||||
) {
|
|
||||||
class Dice(
|
data class Dice(
|
||||||
sign: Int,
|
override val sign: Int,
|
||||||
val modifier: Modifier?,
|
val modifier: Modifier?,
|
||||||
val quantity: Int,
|
val quantity: Int,
|
||||||
val faces: Int,
|
val faces: Int,
|
||||||
) : Instruction(
|
) : Instruction() {
|
||||||
sign = sign,
|
|
||||||
) {
|
|
||||||
enum class Modifier {
|
enum class Modifier {
|
||||||
ADVANTAGE,
|
ADVANTAGE,
|
||||||
DISADVANTAGE,
|
DISADVANTAGE,
|
||||||
|
|
@ -29,23 +28,20 @@ sealed class Instruction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Flat(
|
data class Flat(
|
||||||
sign: Int,
|
override val sign: Int,
|
||||||
val value: Int,
|
val value: Int,
|
||||||
) : Instruction(
|
) : Instruction() {
|
||||||
sign = sign,
|
|
||||||
) {
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "${sign.sign}${value}"
|
return "${sign.sign}${value}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Word(
|
data class Word(
|
||||||
sign: Int,
|
override val sign: Int,
|
||||||
val type: Type,
|
val type: Type,
|
||||||
) : Instruction(
|
) : Instruction() {
|
||||||
sign = sign
|
|
||||||
) {
|
|
||||||
enum class Type {
|
enum class Type {
|
||||||
BDC, // Damages bonus for melee
|
BDC, // Damages bonus for melee
|
||||||
BDD, // Damages bonus for range
|
BDD, // Damages bonus for range
|
||||||
|
|
|
||||||
|
|
@ -1,34 +1,13 @@
|
||||||
package com.pixelized.desktop.lwa.repository.characterSheet
|
package com.pixelized.desktop.lwa.repository.characterSheet
|
||||||
|
|
||||||
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
|
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
|
||||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
|
||||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
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.CharacterSheetJson
|
||||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheetJsonV1
|
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(
|
class CharacterSheetJsonFactory(
|
||||||
private val bonusDamageUseCase: DamageBonusUseCase,
|
|
||||||
private val skillDescriptionFactory: SkillDescriptionFactory,
|
private val skillDescriptionFactory: SkillDescriptionFactory,
|
||||||
|
private val characterSheetUseCase: CharacterSheetUseCase,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
fun convertToJson(
|
fun convertToJson(
|
||||||
|
|
@ -51,6 +30,8 @@ class CharacterSheetJsonFactory(
|
||||||
maxPP = if (sheet.overrideMaxPP) sheet.maxPp else null,
|
maxPP = if (sheet.overrideMaxPP) sheet.maxPp else null,
|
||||||
damageBonus = if (sheet.overrideDamageBonus) sheet.damageBonus else null,
|
damageBonus = if (sheet.overrideDamageBonus) sheet.damageBonus else null,
|
||||||
armor = if (sheet.overrideArmor) sheet.armor 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 {
|
skills = sheet.commonSkills.map {
|
||||||
CharacterSheetJsonV1.Skill(
|
CharacterSheetJsonV1.Skill(
|
||||||
id = it.id,
|
id = it.id,
|
||||||
|
|
@ -108,8 +89,8 @@ class CharacterSheetJsonFactory(
|
||||||
|
|
||||||
private suspend fun convertFromV1(
|
private suspend fun convertFromV1(
|
||||||
json: CharacterSheetJsonV1,
|
json: CharacterSheetJsonV1,
|
||||||
): CharacterSheet {
|
): CharacterSheet = characterSheetUseCase.run {
|
||||||
val sheet = CharacterSheet(
|
CharacterSheet(
|
||||||
id = json.id,
|
id = json.id,
|
||||||
name = json.name,
|
name = json.name,
|
||||||
strength = json.strength,
|
strength = json.strength,
|
||||||
|
|
@ -120,21 +101,27 @@ class CharacterSheetJsonFactory(
|
||||||
power = json.power,
|
power = json.power,
|
||||||
charisma = json.charisma,
|
charisma = json.charisma,
|
||||||
overrideMovement = json.movement != null,
|
overrideMovement = json.movement != null,
|
||||||
movement = json.movement ?: 10,
|
movement = json.movement ?: defaultMovement(),
|
||||||
currentHp = json.currentHp,
|
currentHp = json.currentHp,
|
||||||
overrideMaxHp = json.maxHp != null,
|
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,
|
currentPp = json.currentPP,
|
||||||
overrideMaxPP = json.maxPP != null,
|
overrideMaxPP = json.maxPP != null,
|
||||||
maxPp = json.maxPP ?: json.power,
|
maxPp = json.maxPP ?: defaultMaxPower(power = json.power),
|
||||||
overrideDamageBonus = json.damageBonus != null,
|
overrideDamageBonus = json.damageBonus != null,
|
||||||
damageBonus = json.damageBonus
|
damageBonus = json.damageBonus ?: defaultDamageBonus(
|
||||||
?: bonusDamageUseCase.bonusDamage(
|
strength = json.strength,
|
||||||
strength = json.strength,
|
height = json.height,
|
||||||
height = json.height
|
),
|
||||||
),
|
|
||||||
overrideArmor = json.armor != null,
|
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 {
|
commonSkills = json.skills.map {
|
||||||
CharacterSheet.Skill(
|
CharacterSheet.Skill(
|
||||||
id = it.id,
|
id = it.id,
|
||||||
|
|
@ -179,6 +166,5 @@ class CharacterSheetJsonFactory(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
return sheet
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -24,6 +24,10 @@ data class CharacterSheet(
|
||||||
val damageBonus: String,
|
val damageBonus: String,
|
||||||
val overrideArmor: Boolean,
|
val overrideArmor: Boolean,
|
||||||
val armor: Int,
|
val armor: Int,
|
||||||
|
val overrideLearning: Boolean,
|
||||||
|
val learning: Int,
|
||||||
|
val overrideHpGrow: Boolean,
|
||||||
|
val hpGrow: Int,
|
||||||
// skills
|
// skills
|
||||||
val commonSkills: List<Skill>,
|
val commonSkills: List<Skill>,
|
||||||
val specialSkills: List<Skill>,
|
val specialSkills: List<Skill>,
|
||||||
|
|
@ -80,5 +84,7 @@ data class CharacterSheet(
|
||||||
const val PP = "PP"
|
const val PP = "PP"
|
||||||
const val DMG = "DMG"
|
const val DMG = "DMG"
|
||||||
const val ARMOR = "ARMOR"
|
const val ARMOR = "ARMOR"
|
||||||
|
const val LB = "LEARNING"
|
||||||
|
const val GHP = "HP_GROW"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -22,6 +22,8 @@ data class CharacterSheetJsonV1(
|
||||||
val maxPP: Int?,
|
val maxPP: Int?,
|
||||||
val damageBonus: String?,
|
val damageBonus: String?,
|
||||||
val armor: Int?,
|
val armor: Int?,
|
||||||
|
val learning: Int?,
|
||||||
|
val hpGrowf: Int?,
|
||||||
// skills
|
// skills
|
||||||
val skills: List<Skill>,
|
val skills: List<Skill>,
|
||||||
// occupations
|
// occupations
|
||||||
|
|
|
||||||
|
|
@ -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__armor
|
||||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__damage_bonus
|
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__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__movement
|
||||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__power_point
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__power_point
|
||||||
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__charisma
|
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__armor
|
||||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__bonus_damage
|
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__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__movement
|
||||||
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__power_point
|
import lwacharactersheet.composeapp.generated.resources.tooltip__sub_characteristics__power_point
|
||||||
import org.jetbrains.compose.resources.getString
|
import org.jetbrains.compose.resources.getString
|
||||||
|
|
@ -171,6 +175,26 @@ class CharacterSheetFactory(
|
||||||
),
|
),
|
||||||
editable = false,
|
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 ->
|
commonSkills = sheet.commonSkills.map { skill ->
|
||||||
Node(
|
Node(
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@ package com.pixelized.desktop.lwa.screen.characterSheet.edit
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
|
import com.pixelized.desktop.lwa.business.CharacterSheetUseCase
|
||||||
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase
|
|
||||||
import com.pixelized.desktop.lwa.repository.characterSheet.SkillDescriptionFactory
|
import com.pixelized.desktop.lwa.repository.characterSheet.SkillDescriptionFactory
|
||||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||||
import com.pixelized.desktop.lwa.screen.characterSheet.edit.common.SkillFieldFactory
|
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__skills__throw
|
||||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__armor
|
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__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_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__max_power_point
|
||||||
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__movement
|
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 org.jetbrains.compose.resources.getString
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import kotlin.math.ceil
|
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
class CharacterSheetEditFactory(
|
class CharacterSheetEditFactory(
|
||||||
private val bonusDamageUseCase: DamageBonusUseCase,
|
private val characterSheetUseCase: CharacterSheetUseCase,
|
||||||
private val skillFieldFactory: SkillFieldFactory,
|
private val skillFieldFactory: SkillFieldFactory,
|
||||||
private val skillDescriptionFactory: SkillDescriptionFactory,
|
private val skillDescriptionFactory: SkillDescriptionFactory,
|
||||||
private val normalizer: SkillNormalizerUseCase,
|
|
||||||
) {
|
) {
|
||||||
suspend fun updateCharacterSheet(
|
suspend fun updateCharacterSheet(
|
||||||
currentSheet: CharacterSheet?,
|
currentSheet: CharacterSheet?,
|
||||||
editedSheet: CharacterSheetEditPageUio,
|
editedSheet: CharacterSheetEditPageUio,
|
||||||
): CharacterSheet {
|
): CharacterSheet {
|
||||||
|
val editedMaxHp = editedSheet.maxHp.unpack()?.toIntOrNull() ?: currentSheet?.maxHp ?: 0
|
||||||
|
val editedMaxPp = editedSheet.maxPp.unpack()?.toIntOrNull() ?: currentSheet?.maxPp ?: 0
|
||||||
return CharacterSheet(
|
return CharacterSheet(
|
||||||
id = editedSheet.id,
|
id = editedSheet.id,
|
||||||
name = editedSheet.name.value.value,
|
name = editedSheet.name.value.value,
|
||||||
|
|
@ -95,19 +93,11 @@ class CharacterSheetEditFactory(
|
||||||
?: currentSheet?.movement
|
?: currentSheet?.movement
|
||||||
?: 10,
|
?: 10,
|
||||||
overrideMaxHp = editedSheet.maxHp.value.value.value.isNotBlank(),
|
overrideMaxHp = editedSheet.maxHp.value.value.value.isNotBlank(),
|
||||||
maxHp = editedSheet.maxHp.unpack()?.toIntOrNull()
|
maxHp = editedMaxHp,
|
||||||
?: currentSheet?.maxHp
|
currentHp = currentSheet?.currentHp?.coerceAtMost(editedMaxHp) ?: editedMaxHp,
|
||||||
?: 0,
|
|
||||||
currentHp = editedSheet.currentHp.unpack()?.toIntOrNull()
|
|
||||||
?: currentSheet?.currentHp
|
|
||||||
?: 0,
|
|
||||||
overrideMaxPP = editedSheet.maxPp.value.value.value.isNotBlank(),
|
overrideMaxPP = editedSheet.maxPp.value.value.value.isNotBlank(),
|
||||||
maxPp = editedSheet.maxPp.unpack()?.toIntOrNull()
|
maxPp = editedMaxPp,
|
||||||
?: currentSheet?.maxPp
|
currentPp = currentSheet?.currentPp?.coerceAtMost(editedMaxPp) ?: editedMaxPp,
|
||||||
?: 0,
|
|
||||||
currentPp = editedSheet.currentPp.unpack()?.toIntOrNull()
|
|
||||||
?: currentSheet?.currentPp
|
|
||||||
?: 0,
|
|
||||||
overrideDamageBonus = editedSheet.damageBonus.value.value.value.isNotBlank(),
|
overrideDamageBonus = editedSheet.damageBonus.value.value.value.isNotBlank(),
|
||||||
damageBonus = editedSheet.damageBonus.unpack()
|
damageBonus = editedSheet.damageBonus.unpack()
|
||||||
?: currentSheet?.damageBonus
|
?: currentSheet?.damageBonus
|
||||||
|
|
@ -116,6 +106,10 @@ class CharacterSheetEditFactory(
|
||||||
armor = editedSheet.armor.unpack()?.toIntOrNull()
|
armor = editedSheet.armor.unpack()?.toIntOrNull()
|
||||||
?: currentSheet?.armor
|
?: currentSheet?.armor
|
||||||
?: 0,
|
?: 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 ->
|
commonSkills = editedSheet.commonSkills.map { editedSkill ->
|
||||||
val currentSkill = currentSheet?.commonSkills?.firstOrNull {
|
val currentSkill = currentSheet?.commonSkills?.firstOrNull {
|
||||||
it.id == editedSkill.id
|
it.id == editedSkill.id
|
||||||
|
|
@ -236,239 +230,243 @@ class CharacterSheetEditFactory(
|
||||||
val specialSkillsLabel = getString(Res.string.character_sheet_edit__skills__special_title)
|
val specialSkillsLabel = getString(Res.string.character_sheet_edit__skills__special_title)
|
||||||
val magicSkillsLabel = getString(Res.string.character_sheet_edit__skills__magic_title)
|
val magicSkillsLabel = getString(Res.string.character_sheet_edit__skills__magic_title)
|
||||||
|
|
||||||
val maxHitPoint = SimpleFieldUio(
|
return with(characterSheetUseCase) {
|
||||||
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_hit_point),
|
CharacterSheetEditPageUio(
|
||||||
value = skillFieldFactory.createWrapper(
|
id = sheet?.id ?: UUID.randomUUID().toString(),
|
||||||
value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
|
name = skillFieldFactory.createWrapper(
|
||||||
placeholder = derivedStateOf { "${ceil((con() + hei()) / 2f).toInt()}" },
|
label = mutableStateOf(getString(Res.string.character_sheet_edit__name_label)),
|
||||||
)
|
value = sheet?.name ?: ""
|
||||||
)
|
|
||||||
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) },
|
|
||||||
),
|
),
|
||||||
createBaseSkill(
|
strength = str,
|
||||||
sheet = sheet,
|
dexterity = dex,
|
||||||
id = CharacterSheet.CommonSkillId.DODGE_ID,
|
constitution = con,
|
||||||
label = getString(Res.string.character_sheet_edit__skills__dodge),
|
height = hei,
|
||||||
base = derivedStateOf { normalizer.normalize(dex() * 2) },
|
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(
|
maxHp = SimpleFieldUio(
|
||||||
sheet = sheet,
|
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_hit_point),
|
||||||
id = CharacterSheet.CommonSkillId.GRAB_ID,
|
value = skillFieldFactory.createWrapper(
|
||||||
label = getString(Res.string.character_sheet_edit__skills__grab),
|
value = if (sheet?.overrideMaxHp == true) "${sheet.maxHp}" else "",
|
||||||
base = derivedStateOf { normalizer.normalize(str() + hei()) },
|
placeholder = derivedStateOf {
|
||||||
|
"${
|
||||||
|
characterSheetUseCase.defaultMaxHp(
|
||||||
|
constitution = con(),
|
||||||
|
height = hei()
|
||||||
|
)
|
||||||
|
}"
|
||||||
|
},
|
||||||
|
)
|
||||||
),
|
),
|
||||||
createBaseSkill(
|
maxPp = SimpleFieldUio(
|
||||||
sheet = sheet,
|
label = getString(Res.string.character_sheet_edit__sub_characteristics__max_power_point),
|
||||||
id = CharacterSheet.CommonSkillId.THROW_ID,
|
value = skillFieldFactory.createWrapper(
|
||||||
label = getString(Res.string.character_sheet_edit__skills__throw),
|
value = if (sheet?.overrideMaxPP == true) "${sheet.maxPp}" else "",
|
||||||
base = derivedStateOf { normalizer.normalize(str() + dex()) },
|
placeholder = derivedStateOf {
|
||||||
|
"${characterSheetUseCase.defaultMaxPower(power = pow())}"
|
||||||
|
},
|
||||||
|
)
|
||||||
),
|
),
|
||||||
createBaseSkill(
|
damageBonus = SimpleFieldUio(
|
||||||
sheet = sheet,
|
label = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus),
|
||||||
id = CharacterSheet.CommonSkillId.ATHLETICS_ID,
|
value = skillFieldFactory.createWrapper(
|
||||||
label = getString(Res.string.character_sheet_edit__skills__athletics),
|
value = if (sheet?.overrideDamageBonus == true) sheet.damageBonus else "",
|
||||||
base = derivedStateOf { normalizer.normalize(str() + con() * 2) },
|
placeholder = derivedStateOf {
|
||||||
|
characterSheetUseCase.defaultDamageBonus(
|
||||||
|
strength = str(),
|
||||||
|
height = hei()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
),
|
),
|
||||||
createBaseSkill(
|
armor = SimpleFieldUio(
|
||||||
sheet = sheet,
|
label = getString(Res.string.character_sheet_edit__sub_characteristics__armor),
|
||||||
id = CharacterSheet.CommonSkillId.ACROBATICS_ID,
|
value = skillFieldFactory.createWrapper(
|
||||||
label = getString(Res.string.character_sheet_edit__skills__acrobatics),
|
value = if (sheet?.overrideArmor == true) "${sheet.armor}" else "",
|
||||||
base = derivedStateOf { normalizer.normalize(dex() + con() * 2) },
|
placeholder = derivedStateOf {
|
||||||
|
"${characterSheetUseCase.defaultArmor()}"
|
||||||
|
},
|
||||||
|
)
|
||||||
),
|
),
|
||||||
createBaseSkill(
|
learning = SimpleFieldUio(
|
||||||
sheet = sheet,
|
label = getString(Res.string.character_sheet_edit__sub_characteristics__learning),
|
||||||
id = CharacterSheet.CommonSkillId.PERCEPTION_ID,
|
value = skillFieldFactory.createWrapper(
|
||||||
label = getString(Res.string.character_sheet_edit__skills__perception),
|
value = if (sheet?.overrideLearning == true) "${sheet.learning}" else "",
|
||||||
base = derivedStateOf { normalizer.normalize(10 + int() * 2) },
|
placeholder = derivedStateOf {
|
||||||
|
"${characterSheetUseCase.defaultLearning(intelligence = int())}"
|
||||||
|
},
|
||||||
|
)
|
||||||
),
|
),
|
||||||
createBaseSkill(
|
hpGrow = SimpleFieldUio(
|
||||||
sheet = sheet,
|
label = getString(Res.string.character_sheet_edit__sub_characteristics__hp_grow),
|
||||||
id = CharacterSheet.CommonSkillId.SEARCH_ID,
|
value = skillFieldFactory.createWrapper(
|
||||||
label = getString(Res.string.character_sheet_edit__skills__search),
|
value = if (sheet?.overrideHpGrow == true) "${sheet.hpGrow}" else "",
|
||||||
base = derivedStateOf { normalizer.normalize(10 + int() * 2) },
|
placeholder = derivedStateOf {
|
||||||
|
"${characterSheetUseCase.defaultHpGrow(constitution = con())}"
|
||||||
|
},
|
||||||
|
)
|
||||||
),
|
),
|
||||||
createBaseSkill(
|
commonSkills = listOf(
|
||||||
sheet = sheet,
|
createBaseSkill(
|
||||||
id = CharacterSheet.CommonSkillId.EMPATHY_ID,
|
sheet = sheet,
|
||||||
label = getString(Res.string.character_sheet_edit__skills__empathy),
|
id = CharacterSheet.CommonSkillId.COMBAT_ID,
|
||||||
base = derivedStateOf { normalizer.normalize(cha() + int()) },
|
label = getString(Res.string.character_sheet_edit__skills__combat),
|
||||||
),
|
base = derivedStateOf { normalize(dex() * 2) },
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
action = skillFieldFactory.createWrapper(
|
createBaseSkill(
|
||||||
label = mutableStateOf(getString(Res.string.character_sheet_edit__actions__action_label)),
|
sheet = sheet,
|
||||||
value = action.roll,
|
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) },
|
createBaseSkill(
|
||||||
)
|
sheet = sheet,
|
||||||
} ?: emptyList(),
|
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(
|
private suspend fun createBaseSkill(
|
||||||
|
|
|
||||||
|
|
@ -70,10 +70,10 @@ data class CharacterSheetEditPageUio(
|
||||||
val movement: SimpleFieldUio,
|
val movement: SimpleFieldUio,
|
||||||
val maxHp: SimpleFieldUio,
|
val maxHp: SimpleFieldUio,
|
||||||
val maxPp: SimpleFieldUio,
|
val maxPp: SimpleFieldUio,
|
||||||
val currentHp: SimpleFieldUio,
|
|
||||||
val currentPp: SimpleFieldUio,
|
|
||||||
val damageBonus: SimpleFieldUio,
|
val damageBonus: SimpleFieldUio,
|
||||||
val armor: SimpleFieldUio,
|
val armor: SimpleFieldUio,
|
||||||
|
val learning: SimpleFieldUio,
|
||||||
|
val hpGrow: SimpleFieldUio,
|
||||||
val commonSkills: List<BaseSkillFieldUio>,
|
val commonSkills: List<BaseSkillFieldUio>,
|
||||||
val specialSkills: List<SkillFieldUio>,
|
val specialSkills: List<SkillFieldUio>,
|
||||||
val magicSkills: List<SkillFieldUio>,
|
val magicSkills: List<SkillFieldUio>,
|
||||||
|
|
@ -94,11 +94,11 @@ data class CharacterSheetEditPageUio(
|
||||||
get() = listOf(
|
get() = listOf(
|
||||||
movement,
|
movement,
|
||||||
maxHp,
|
maxHp,
|
||||||
currentHp,
|
|
||||||
maxPp,
|
maxPp,
|
||||||
currentPp,
|
|
||||||
damageBonus,
|
damageBonus,
|
||||||
armor,
|
armor,
|
||||||
|
learning,
|
||||||
|
hpGrow,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,43 +6,45 @@ class DamageBonusUseCaseTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testBonusDamage() {
|
fun testBonusDamage() {
|
||||||
|
val userCase = CharacterSheetUseCase()
|
||||||
|
|
||||||
(0 until 12).forEach {
|
(0 until 12).forEach {
|
||||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
val result = userCase.defaultDamageBonus(sum = it)
|
||||||
val expected = "-1d6"
|
val expected = "-1d6"
|
||||||
assert(result == expected) {
|
assert(result == expected) {
|
||||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(12 until 18).forEach {
|
(12 until 18).forEach {
|
||||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
val result = userCase.defaultDamageBonus(sum = it)
|
||||||
val expected = "-1d4"
|
val expected = "-1d4"
|
||||||
assert(result == expected) {
|
assert(result == expected) {
|
||||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(18 until 23).forEach {
|
(18 until 23).forEach {
|
||||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
val result = userCase.defaultDamageBonus(sum = it)
|
||||||
val expected = "+0"
|
val expected = "+0"
|
||||||
assert(result == expected) {
|
assert(result == expected) {
|
||||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(23 until 30).forEach {
|
(23 until 30).forEach {
|
||||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
val result = userCase.defaultDamageBonus(sum = it)
|
||||||
val expected = "+1d4"
|
val expected = "+1d4"
|
||||||
assert(result == expected) {
|
assert(result == expected) {
|
||||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(30 until 40).forEach {
|
(30 until 40).forEach {
|
||||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
val result = userCase.defaultDamageBonus(sum = it)
|
||||||
val expected = "+1d6"
|
val expected = "+1d6"
|
||||||
assert(result == expected) {
|
assert(result == expected) {
|
||||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(40 until 100).forEach {
|
(40 until 100).forEach {
|
||||||
val result = DamageBonusUseCase.bonusDamage(stat = it)
|
val result = userCase.defaultDamageBonus(sum = it)
|
||||||
val expected = "+2d6"
|
val expected = "+2d6"
|
||||||
assert(result == expected) {
|
assert(result == expected) {
|
||||||
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
"Expected:'$expected' bonus damage for stat:'$it' but was:'$result'"
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import org.junit.Test
|
||||||
class RollUseCaseTest {
|
class RollUseCaseTest {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val ROLL_COUNT = 1000000000
|
private const val ROLL_COUNT = 100000000 // 100*10^6
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -20,16 +20,18 @@ class RollUseCaseTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRoll1D100_() {
|
fun testRoll1D100_() {
|
||||||
val result = build1D100ResultSet()
|
val results = build1D100ResultSet()
|
||||||
|
|
||||||
val delta = 0.001f
|
val delta = 0.005f
|
||||||
val median = (ROLL_COUNT / 100).let {
|
val median = (ROLL_COUNT / 100).let {
|
||||||
(it * (1f - delta)).toInt()..(it * (1f + delta)).toInt()
|
(it * (1f - delta)).toInt()..(it * (1f + delta)).toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
println("Testing if with $ROLL_COUNT rolls we have at least all results in $median.")
|
println("Testing if with $ROLL_COUNT rolls we have at least all results in $median.")
|
||||||
assert(result.all { it in median }) {
|
results.map { it in median }.forEachIndexed { index, result ->
|
||||||
"Maybe a false negative, we expected that all values should be in $median a result.\nroll amount: $ROLL_COUNT - result:$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 useCase = RollUseCase()
|
||||||
val result = MutableList(100) { 0 }
|
val result = MutableList(100) { 0 }
|
||||||
repeat(count) {
|
repeat(count) {
|
||||||
val roll = useCase.rollD100()
|
val roll = useCase.roll(faces = 100)
|
||||||
result[roll - 1] += 1
|
result[roll - 1] += 1
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,8 @@ class SkillNormalizerUseCaseText {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testNormalization() {
|
fun testNormalization() {
|
||||||
val useCase = SkillNormalizerUseCase()
|
val useCase = CharacterSheetUseCase()
|
||||||
|
|
||||||
val samples = listOf(
|
val samples = listOf(
|
||||||
0 to 0,
|
0 to 0,
|
||||||
1 to 0,
|
1 to 0,
|
||||||
|
|
@ -19,6 +20,96 @@ class SkillNormalizerUseCaseText {
|
||||||
8 to 5,
|
8 to 5,
|
||||||
9 to 5,
|
9 to 5,
|
||||||
10 to 10,
|
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) ->
|
samples.forEach { (value, expected) ->
|
||||||
assert(useCase.normalize(value) == expected) {
|
assert(useCase.normalize(value) == expected) {
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ class SkillStepUseCaseTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testStepForSkill() {
|
fun testStepForSkill() {
|
||||||
|
val useCase = SkillStepUseCase()
|
||||||
(1..500).forEach { skill ->
|
(1..500).forEach { skill ->
|
||||||
val step = SkillStepUseCase.computeSkillStep(
|
val step = useCase.computeSkillStep(
|
||||||
skill = skill,
|
skill = skill,
|
||||||
)
|
)
|
||||||
val expected = expected[skill] ?: error(
|
val expected = expected[skill] ?: error(
|
||||||
|
|
|
||||||
|
|
@ -13,16 +13,16 @@ class InstructionParserTest {
|
||||||
|
|
||||||
fun test(
|
fun test(
|
||||||
instruction: String,
|
instruction: String,
|
||||||
expectedModifier: Instruction.Dice.Modifier.Dice.Modifier?,
|
expectedModifier: Instruction.Dice.Modifier?,
|
||||||
expectedQuantity: Int,
|
expectedQuantity: Int,
|
||||||
expectedFaces: 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}"
|
"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) {
|
assert(dice.modifier == expectedModifier) {
|
||||||
"$instruction modifier should be:\"$expectedModifier\", but was: ${dice.modifier}"
|
"$instruction modifier should be:\"$expectedModifier\", but was: ${dice.modifier}"
|
||||||
}
|
}
|
||||||
|
|
@ -66,14 +66,14 @@ class InstructionParserTest {
|
||||||
val parser = ArithmeticParser()
|
val parser = ArithmeticParser()
|
||||||
|
|
||||||
ArithmeticParser.words.map { instruction ->
|
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}"
|
"Instruction should be ArithmeticInstruction.Word but was: ${word::class.java.simpleName}"
|
||||||
}
|
}
|
||||||
(word as? Instruction.Word.Word)?.let {
|
(word as? Instruction.Word)?.let {
|
||||||
assert(it.name == instruction) {
|
assert(it.type.name == instruction) {
|
||||||
"Instruction should be $instruction, but was ${it.name}"
|
"Instruction should be $instruction, but was ${it.type.name}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -84,12 +84,12 @@ class InstructionParserTest {
|
||||||
val parser = ArithmeticParser()
|
val parser = ArithmeticParser()
|
||||||
|
|
||||||
"100".let { instruction ->
|
"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}"
|
"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) {
|
assert("${it.value}" == instruction) {
|
||||||
"Instruction should be $instruction, but was ${it.value}"
|
"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
|
@Test
|
||||||
fun testRollParse() {
|
fun testRollParse() {
|
||||||
val parser = ArithmeticParser()
|
val parser = ArithmeticParser()
|
||||||
|
|
||||||
fun test(
|
fun test(
|
||||||
arithmetics: Instruction,
|
instruction: Instruction,
|
||||||
expectedSign: Int,
|
|
||||||
expectedInstruction: Instruction,
|
expectedInstruction: Instruction,
|
||||||
) {
|
) {
|
||||||
assert(arithmetics.sign == expectedSign) {
|
assert(instruction == expectedInstruction) {
|
||||||
"Arithmetic sign should be $expectedSign but was: ${arithmetics.sign}"
|
"Arithmetic instruction should be $expectedInstruction but was: $instruction"
|
||||||
}
|
|
||||||
assert(arithmetics.instruction == expectedInstruction) {
|
|
||||||
"Arithmetic instruction should be $expectedInstruction but was: ${arithmetics.instruction}"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val instructions = parser.parse(value = "1+1d6+2-BDC+BDD")
|
val instructions = parser.parse(
|
||||||
|
value = "1+1d6+2-BDC+BDD",
|
||||||
|
)
|
||||||
|
|
||||||
test(
|
test(
|
||||||
arithmetics = instructions[0],
|
instruction = instructions[0],
|
||||||
expectedSign = 1,
|
expectedInstruction = Instruction.Flat(sign = 1, value = 1),
|
||||||
expectedInstruction = Instruction.Flat(value = 1),
|
|
||||||
)
|
)
|
||||||
test(
|
test(
|
||||||
arithmetics = instructions[1],
|
instruction = instructions[1],
|
||||||
expectedSign = 1,
|
expectedInstruction = Instruction.Dice(sign = 1, modifier = null, quantity = 1, faces = 6),
|
||||||
expectedInstruction = Instruction.Dice(quantity = 1, faces = 6, modifier = null),
|
|
||||||
)
|
)
|
||||||
test(
|
test(
|
||||||
arithmetics = instructions[2],
|
instruction = instructions[2],
|
||||||
expectedSign = 1,
|
expectedInstruction = Instruction.Flat(sign = 1, value = 2),
|
||||||
expectedInstruction = Instruction.Flat(value = 2),
|
|
||||||
)
|
)
|
||||||
test(
|
test(
|
||||||
arithmetics = instructions[3],
|
instruction = instructions[3],
|
||||||
expectedSign = -1,
|
expectedInstruction = Instruction.Word(sign = -1, type = Instruction.Word.Type.BDC),
|
||||||
expectedInstruction = Instruction.Word.BDC,
|
|
||||||
)
|
)
|
||||||
test(
|
test(
|
||||||
arithmetics = instructions[4],
|
instruction = instructions[4],
|
||||||
expectedSign = 1,
|
expectedInstruction = Instruction.Word(sign = 1, type = Instruction.Word.Type.BDD),
|
||||||
expectedInstruction = Instruction.Word.BDD,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue