diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml new file mode 100644 index 0000000..0d81a5f --- /dev/null +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -0,0 +1,68 @@ + + + Créer une feuille de personnage + + Réussite critique + Réussite spéciale + Réussite + Échec + Échec critique + + Création de personnage + Nom + Ajouter un lancé + Sauvegarder + Charactéristiques + Force + Dextérité + Constitution + Taille + Intelligence + Pouvoir + Charisme + Charactéristiques dérivées + Déplacement + Points de vie + Points de pouvoir + Bonus aux dégats + Armure + Compétances + Ajouter une compétance + Bagarre + Esquive + Saisie + Lancer + Athlétisme + Acrobatie + Perception + Recherche + Empathie + Persuasion + Intimidation + Baratin + Marchandage + Discrétion + Escamotage + Premiers soins + Occupations + Ajouter une occupation + Compétences magiques + Ajouter une compétence magique + + Force + Dextérité + Constitution + Taille + Intelligence + Pouvoir + Charisme + Charactéristiques dérivées + Déplacement + Points de vie + Points de pouvoir + Bonus aux dégats + Armure + Compétences + Occupations + Compétences magiques + \ No newline at end of file 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 new file mode 100644 index 0000000..553aa76 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCase.kt @@ -0,0 +1,19 @@ +package com.pixelized.desktop.lwa.business + +object 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 20ecb1b..a0a67ec 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 @@ -3,27 +3,33 @@ package com.pixelized.desktop.lwa.business import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet object RollUseCase { - private val d100 = (1..100) private val diceParser = Regex( - """(?[+-])?\h*(?[ade])?(?\d+)d(?\d+)""" + """(?[+-])?\s*(?[ade])?(?\d+)[dD](?\d+)""" ) private val flatParser = Regex( - """(?[+-])?\h(?\d+)\b""" + """(?[+-])?\s*[^a-zA-Z](?\d+)\b""" ) private val paramParser = Regex( - """(?[+-])?\h(?BDGT)\b""" + """(?[+-])?\s*(?BDGT)\b""" ) fun rollD100(): Int { - return d100.random() + return roll(quantity = 1, faces = 100) + } + + fun roll(quantity: Int, faces: Int): Int { + return sum(count = quantity) { (Math.random() * faces.toDouble() + 1).toInt() } } fun roll(characterSheet: CharacterSheet, roll: String): Int { println(roll) return diceParser.findAll(roll).sumOf { val (sign, modifier, quantity, faces) = it.destructured - ((if (sign == "-") -1 else 1) * quantity.toInt() * (Math.random() * faces.toDouble() + 1).toInt()).also { + ((if (sign == "-") -1 else 1) * roll( + quantity = quantity.toInt(), + faces = faces.toInt() + )).also { println("roll ${sign}${quantity}d${faces} -> $it") } } + flatParser.findAll(roll).sumOf { @@ -36,7 +42,10 @@ object RollUseCase { (if (sign == "-") -1 else 1) * when (param) { "BDGT" -> diceParser.findAll(characterSheet.damageBonus).sumOf { val (sign, modifier, quantity, faces) = it.destructured - ((if (sign == "-") -1 else 1) * quantity.toInt() * (Math.random() * faces.toDouble() + 1).toInt()).also { + ((if (sign == "-") -1 else 1) * roll( + quantity = quantity.toInt(), + faces = faces.toInt() + )).also { println("param: ${sign}${param} -> $it") } } @@ -45,4 +54,12 @@ object RollUseCase { } } } + + private fun sum(count: Int, block: () -> Int): Int { + return if (count > 1) { + block() + sum(count - 1, block) + } else { + block() + } + } } \ No newline at end of file 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 2566a44..7733d68 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 @@ -3,34 +3,68 @@ package com.pixelized.desktop.lwa.screen.characterSheet.detail import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Node +import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.* +import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__str +import org.jetbrains.compose.resources.getString class CharacterSheetFactory { - fun convertToUio(model: CharacterSheet): CharacterSheetPageUio { + suspend fun convertToUio(model: CharacterSheet): CharacterSheetPageUio { return CharacterSheetPageUio( id = model.id, name = model.name, characteristics = listOf( - Characteristic(label = "Force", value = "${model.strength}"), - Characteristic(label = "Dextérité", value = "${model.dexterity}"), - Characteristic(label = "Constitution", value = "${model.constitution}"), - Characteristic(label = "Taille", value = "${model.height}"), - Characteristic(label = "Intelligence", value = "${model.intelligence}"), - Characteristic(label = "Pouvoir", value = "${model.power}"), - Characteristic(label = "Charisme", value = "${model.charisma}"), + Characteristic( + label = getString(Res.string.character_sheet__characteristics__str), + value = "${model.strength}", + ), + Characteristic( + label = getString(Res.string.character_sheet__characteristics__dex), + value = "${model.dexterity}", + ), + Characteristic( + label = getString(Res.string.character_sheet__characteristics__con), + value = "${model.constitution}", + ), + Characteristic( + label = getString(Res.string.character_sheet__characteristics__hei), + value = "${model.height}", + ), + Characteristic( + label = getString(Res.string.character_sheet__characteristics__int), + value = "${model.intelligence}", + ), + Characteristic( + label = getString(Res.string.character_sheet__characteristics__pow), + value = "${model.power}", + ), + Characteristic( + label = getString(Res.string.character_sheet__characteristics__cha), + value = "${model.charisma}", + ), ), subCharacteristics = listOf( - Characteristic(label = "Déplacement ", value = "${model.movement}"), Characteristic( - label = "Points de vie", - value = "${model.currentHp}/${model.maxHp}" + label = getString(Res.string.character_sheet__sub_characteristics__movement), + value = "${model.movement}", ), Characteristic( - label = "Points de pouvoir", - value = "${model.currentPP}/${model.maxPP}" + label = getString(Res.string.character_sheet__sub_characteristics__hit_point), + value = "${model.currentHp}/${model.maxHp}", + ), + Characteristic( + label = getString(Res.string.character_sheet__sub_characteristics__power_point), + value = "${model.currentPP}/${model.maxPP}", + ), + Characteristic( + label = getString(Res.string.character_sheet__sub_characteristics__damage_bonus), + value = model.damageBonus, + ), + Characteristic( + label = getString(Res.string.character_sheet__sub_characteristics__armor), + value = "${model.armor}", ), - Characteristic(label = "Bonus aux dégâts", value = model.damageBonus), - Characteristic(label = "Armure", value = "${model.armor}"), ), skills = model.skills.mapNotNull { if (it.value > 0) { diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt index 227f2b5..cb3f03d 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt @@ -49,8 +49,13 @@ import com.pixelized.desktop.lwa.screen.roll.RollPage import com.pixelized.desktop.lwa.screen.roll.RollViewModel import kotlinx.coroutines.launch import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.character_sheet__magics__title +import lwacharactersheet.composeapp.generated.resources.character_sheet__occupations_title +import lwacharactersheet.composeapp.generated.resources.character_sheet__skills__title +import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__title import lwacharactersheet.composeapp.generated.resources.ic_d20_32dp import org.jetbrains.compose.resources.painterResource +import org.jetbrains.compose.resources.stringResource @Stable data class CharacterSheetPageUio( @@ -122,7 +127,10 @@ fun CharacterSheetPage( } }, onCharacteristic = { characteristic -> - rollViewModel.prepareRoll(sheet = sheet, characteristic = characteristic) + rollViewModel.prepareRoll( + sheet = sheet, + characteristic = characteristic + ) overlayViewModel.show() }, onSkill = { node -> @@ -228,7 +236,7 @@ fun CharacterSheetPageContent( modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), style = MaterialTheme.typography.caption, textAlign = TextAlign.Center, - text = "Charactéristiques dérivées" + text = stringResource(Res.string.character_sheet__sub_characteristics__title), ) characterSheet.subCharacteristics.forEach { Characteristics( @@ -246,7 +254,7 @@ fun CharacterSheetPageContent( modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), style = MaterialTheme.typography.caption, textAlign = TextAlign.Center, - text = "Compétences", + text = stringResource(Res.string.character_sheet__skills__title), ) characterSheet.skills.forEach { Skill( @@ -266,7 +274,7 @@ fun CharacterSheetPageContent( modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), style = MaterialTheme.typography.caption, textAlign = TextAlign.Center, - text = "Occupations" + text = stringResource(Res.string.character_sheet__occupations_title), ) characterSheet.occupations.forEach { Skill( @@ -286,7 +294,7 @@ fun CharacterSheetPageContent( modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), style = MaterialTheme.typography.caption, textAlign = TextAlign.Center, - text = "Compétences magiques" + text = stringResource(Res.string.character_sheet__magics__title), ) characterSheet.magics.forEach { Skill( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt index 11ec376..6f4a380 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt @@ -8,6 +8,7 @@ import androidx.lifecycle.ViewModel import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetDestination import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.utils.extention.collectAsState +import kotlinx.coroutines.runBlocking class CharacterSheetViewModel( savedStateHandle: SavedStateHandle, @@ -23,7 +24,9 @@ class CharacterSheetViewModel( get() = repository .characterSheetFlow(id = argument.id) .collectAsState { sheet -> - sheet?.let { model -> factory.convertToUio(model = model) } + sheet?.let { model -> + runBlocking { factory.convertToUio(model = model) } + } } suspend fun deleteCharacter(id: String) { 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 new file mode 100644 index 0000000..3514e80 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditFactory.kt @@ -0,0 +1,309 @@ +package com.pixelized.desktop.lwa.screen.characterSheet.edit + +import com.pixelized.desktop.lwa.business.DamageBonusUseCase.bonusDamage +import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase.normalize +import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet +import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditPageUio.SkillGroup +import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio +import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__characteristics__cha +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__characteristics__con +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__characteristics__dex +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__characteristics__hei +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__characteristics__int +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__characteristics__pow +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__characteristics__str +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__characteristics__title +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__magic__add_action +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__magic__title +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__name_placeholder +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__occupation__add_action +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__occupation__title +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__acrobatics +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__add_action +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__aid +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__athletics +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__bargain +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__combat +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__discretion +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__dodge +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__empathy +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__grab +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__intimidation +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__perception +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__persuasion +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__search +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__sleight_of_hand +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__spiel +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__throw +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__skills__title +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__movement +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__power_point +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__title +import org.jetbrains.compose.resources.getString +import java.util.UUID +import kotlin.math.ceil +import kotlin.math.max + +class CharacterSheetEditFactory { + + fun convertToModel(sheet: CharacterSheetEditPageUio): CharacterSheet { + return CharacterSheet( + id = sheet.id, + name = sheet.name.value.value, + strength = sheet.skills[0].fields[0].unpack(), + dexterity = sheet.skills[0].fields[1].unpack(), + constitution = sheet.skills[0].fields[2].unpack(), + height = sheet.skills[0].fields[3].unpack(), + intelligence = sheet.skills[0].fields[4].unpack(), + power = sheet.skills[0].fields[5].unpack(), + charisma = sheet.skills[0].fields[6].unpack(), + movement = sheet.skills[1].fields[0].unpack(), + currentHp = sheet.skills[1].fields[1].unpack(), + maxHp = sheet.skills[1].fields[1].unpack(), + currentPP = sheet.skills[1].fields[2].unpack(), + maxPP = sheet.skills[1].fields[2].unpack(), + damageBonus = sheet.skills[1].fields[3].unpack(), + armor = sheet.skills[1].fields[4].unpack(), + skills = sheet.skills[2].fields.map { + CharacterSheet.Skill( + label = it.label.value, + value = it.unpack(), + used = false, + ) + }, + occupations = sheet.skills[3].fields.map { + CharacterSheet.Skill( + label = it.label.value, + value = it.unpack(), + used = false, + ) + }, + magics = sheet.skills[4].fields.map { + CharacterSheet.Skill( + label = it.label.value, + value = it.unpack(), + used = false, + ) + }, + rolls = sheet.rolls.map { + CharacterSheet.Roll( + label = it.label.value, + roll = it.unpack(), + ) + }, + ) + } + + suspend fun convertToUio( + sheet: CharacterSheet?, + ): CharacterSheetEditPageUio { + val str = FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__characteristics__str), + initialValue = sheet?.strength?.toString() ?: "", + valuePlaceHolder = { "0" }, + ) + val dex = FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__characteristics__dex), + initialValue = sheet?.dexterity?.toString() ?: "", + valuePlaceHolder = { "0" } + ) + val con = FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__characteristics__con), + initialValue = sheet?.constitution?.toString() ?: "", + valuePlaceHolder = { "0" } + ) + val hei = FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__characteristics__hei), + initialValue = sheet?.height?.toString() ?: "", + valuePlaceHolder = { "0" } + ) + val int = FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__characteristics__int), + initialValue = sheet?.intelligence?.toString() ?: "", + valuePlaceHolder = { "0" } + ) + val pow = FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__characteristics__pow), + initialValue = sheet?.power?.toString() ?: "", + valuePlaceHolder = { "0" } + ) + val cha = FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__characteristics__cha), + initialValue = sheet?.charisma?.toString() ?: "", + valuePlaceHolder = { "0" } + ) + + fun str(): Int = str.unpack() ?: 0 + fun dex(): Int = dex.unpack() ?: 0 + fun con(): Int = con.unpack() ?: 0 + fun hei(): Int = hei.unpack() ?: 0 + fun int(): Int = int.unpack() ?: 0 + fun pow(): Int = pow.unpack() ?: 0 + fun cha(): Int = cha.unpack() ?: 0 + + return CharacterSheetEditPageUio( + id = sheet?.id ?: UUID.randomUUID().toString(), + name = FieldUio.create( + isLabelDisplayed = false, + initialLabel = getString(Res.string.character_sheet_edit__name_placeholder), + initialValue = sheet?.name ?: "" + ), + skills = listOf( + SkillGroup( + type = SkillGroup.Type.CHARACTERISTICS, + title = getString(Res.string.character_sheet_edit__characteristics__title), + fields = listOf(str, dex, con, hei, int, pow, cha), + ), + SkillGroup( + type = SkillGroup.Type.SUB_CHARACTERISTICS, + title = getString(Res.string.character_sheet_edit__sub_characteristics__title), + fields = listOf( + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__movement), + initialValue = sheet?.movement?.toString() ?: "", + valuePlaceHolder = { "10" } + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__hit_point), + initialValue = sheet?.maxHp?.toString() ?: "", + valuePlaceHolder = { "${ceil((con() + hei()) / 2f).toInt()}" } + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__power_point), + initialValue = sheet?.maxPP?.toString() ?: "", + valuePlaceHolder = { "${pow()}" } + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__damage_bonus), + initialValue = sheet?.damageBonus ?: "", + valuePlaceHolder = { bonusDamage(strength = str(), height = hei()) } + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__sub_characteristics__armor), + initialValue = sheet?.armor?.toString() ?: "", + valuePlaceHolder = { "0" } + ), + ), + ), + SkillGroup( + type = SkillGroup.Type.SKILLS, + title = getString(Res.string.character_sheet_edit__skills__title), + action = getString(Res.string.character_sheet_edit__skills__add_action), + fields = sheet?.skills?.map { + FieldUio.create( + initialLabel = it.label, + initialValue = it.value.toString(), + ) + } ?: listOf( + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__combat), + valuePlaceHolder = { "${normalize(dex() * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__dodge), + valuePlaceHolder = { "${normalize(dex() * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__grab), + valuePlaceHolder = { "${normalize(str() + hei())}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__throw), + valuePlaceHolder = { "${normalize(str() + dex())}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__athletics), + valuePlaceHolder = { "${normalize(str() + con() * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__acrobatics), + valuePlaceHolder = { "${normalize(dex() + con() * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__perception), + valuePlaceHolder = { "${normalize(10 + int() * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__search), + valuePlaceHolder = { "${normalize(10 + int() * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__empathy), + valuePlaceHolder = { "${normalize(cha() + int())}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__persuasion), + valuePlaceHolder = { "${normalize(cha() * 3)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__intimidation), + valuePlaceHolder = { "${normalize(cha() + max(pow(), hei()) * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__spiel), + valuePlaceHolder = { "${normalize(cha() * 2 + int())}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__bargain), + valuePlaceHolder = { "${normalize(cha() * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__discretion), + valuePlaceHolder = { "${normalize(cha() + dex() * 2 - hei())}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__sleight_of_hand), + valuePlaceHolder = { "${normalize(dex() * 2)}" }, + ), + FieldUio.create( + initialLabel = getString(Res.string.character_sheet_edit__skills__aid), + valuePlaceHolder = { "${normalize(int() + dex())}" }, + ), + ), + ), + SkillGroup( + type = SkillGroup.Type.OCCUPATIONS, + title = getString(Res.string.character_sheet_edit__occupation__title), + action = getString(Res.string.character_sheet_edit__occupation__add_action), + fields = sheet?.occupations?.map { + FieldUio.create( + initialLabel = it.label, + initialValue = it.value.toString(), + valuePlaceHolder = { "40" } + ) + } ?: emptyList(), + ), + SkillGroup( + type = SkillGroup.Type.MAGICS, + title = getString(Res.string.character_sheet_edit__magic__title), + action = getString(Res.string.character_sheet_edit__magic__add_action), + fields = sheet?.magics?.map { + FieldUio.create( + initialLabel = it.label, + initialValue = it.value.toString() + ) + } ?: emptyList(), + ), + ), + rolls = sheet?.rolls?.map { + FieldUio.create( + isLabelEditable = true, + initialLabel = it.label, + initialValue = it.roll, + ) + } ?: emptyList() + ) + } + + private inline fun FieldUio.unpack(): T { + val tmp = value.value.ifBlank { valuePlaceHolder.value } + return when (T::class) { + Int::class -> (tmp.toIntOrNull() ?: 0) as T + else -> tmp as T + } + } +} \ No newline at end of file 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 330cf15..fdf9161 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 @@ -34,6 +34,11 @@ import com.pixelized.desktop.lwa.navigation.LocalScreen import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.Form import kotlinx.coroutines.launch +import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__add_roll_action +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__save_action +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__title +import org.jetbrains.compose.resources.stringResource @Stable data class CharacterSheetEditPageUio( @@ -46,7 +51,7 @@ data class CharacterSheetEditPageUio( data class SkillGroup( val title: String, val type: Type, - val editable: Boolean = false, + val action: String? = null, val fields: List, ) { @Stable @@ -106,7 +111,7 @@ fun CharacterSheetEdit( Text( overflow = TextOverflow.Ellipsis, maxLines = 1, - text = "Création de personnage", + text = stringResource(Res.string.character_sheet_edit__title), ) }, navigationIcon = { @@ -152,7 +157,7 @@ fun CharacterSheetEdit( field = it, ) } - if (it.editable) { + it.action?.let { label -> Row( modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, @@ -169,7 +174,7 @@ fun CharacterSheetEdit( horizontalArrangement = Arrangement.spacedBy(space = 4.dp), ) { Text( - text = "Ajouter une ligne", + text = label, ) Icon( imageVector = Icons.Default.Add, @@ -186,6 +191,7 @@ fun CharacterSheetEdit( form.rolls.forEach { Form( modifier = Modifier.fillMaxWidth(), + valueWidth = 120.dp, field = it, ) } @@ -197,7 +203,7 @@ fun CharacterSheetEdit( TextButton( onClick = onNewCategory, ) { - Text(text = "Ajouter un lancé") + Text(text = stringResource(Res.string.character_sheet_edit__add_roll_action)) } } @@ -208,7 +214,7 @@ fun CharacterSheetEdit( TextButton( onClick = onSave, ) { - Text(text = "Sauvegarder") + Text(text = stringResource(Res.string.character_sheet_edit__save_action)) } } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditViewModel.kt index 55711e5..823f529 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetEditViewModel.kt @@ -8,6 +8,7 @@ import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetEditDestin import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditPageUio.SkillGroup import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio +import kotlinx.coroutines.runBlocking class CharacterSheetEditViewModel( savedStateHandle: SavedStateHandle, @@ -15,11 +16,13 @@ class CharacterSheetEditViewModel( private val argument = CharacterSheetEditDestination.Argument(savedStateHandle) private val repository = CharacterSheetRepository - private val factory = CharacterSheetFactory() + private val factory = CharacterSheetEditFactory() - private val _characterSheet = repository - .characterSheetFlow(id = argument.id).value - .let { sheet -> mutableStateOf(factory.convertToUio(sheet = sheet)) } + private val _characterSheet = mutableStateOf( + repository.characterSheetFlow(id = argument.id).value.let { + runBlocking { factory.convertToUio(it) } + } + ) val characterSheet: State get() = _characterSheet fun onSkill(skill: SkillGroup) { @@ -32,8 +35,8 @@ class CharacterSheetEditViewModel( addAll(group.fields) add( FieldUio.create( - label = "", isLabelEditable = true, + initialLabel = "", valuePlaceHolder = { when (group.type) { SkillGroup.Type.CHARACTERISTICS -> "" @@ -61,7 +64,7 @@ class CharacterSheetEditViewModel( rolls = sheet.rolls.toMutableList().apply { add( FieldUio.create( - label = "", + initialLabel = "", isLabelEditable = true, valuePlaceHolder = { "" }, ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetFactory.kt deleted file mode 100644 index 471392e..0000000 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/CharacterSheetFactory.kt +++ /dev/null @@ -1,279 +0,0 @@ -package com.pixelized.desktop.lwa.screen.characterSheet.edit - -import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase.normalize -import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet -import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditPageUio.SkillGroup -import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio -import java.util.UUID -import kotlin.math.ceil -import kotlin.math.max - -class CharacterSheetFactory { - - fun convertToModel(sheet: CharacterSheetEditPageUio): CharacterSheet { - return CharacterSheet( - id = sheet.id, - name = sheet.name.value.value, - strength = sheet.skills[0].fields[0].unpack(), - dexterity = sheet.skills[0].fields[1].unpack(), - constitution = sheet.skills[0].fields[2].unpack(), - height = sheet.skills[0].fields[3].unpack(), - intelligence = sheet.skills[0].fields[4].unpack(), - power = sheet.skills[0].fields[5].unpack(), - charisma = sheet.skills[0].fields[6].unpack(), - movement = sheet.skills[1].fields[0].unpack(), - currentHp = sheet.skills[1].fields[1].unpack(), - maxHp = sheet.skills[1].fields[1].unpack(), - currentPP = sheet.skills[1].fields[2].unpack(), - maxPP = sheet.skills[1].fields[2].unpack(), - damageBonus = sheet.skills[1].fields[3].unpack(), - armor = sheet.skills[1].fields[4].unpack(), - skills = sheet.skills[2].fields.map { - CharacterSheet.Skill( - label = it.label.value, - value = it.unpack(), - used = false, - ) - }, - occupations = sheet.skills[3].fields.map { - CharacterSheet.Skill( - label = it.label.value, - value = it.unpack(), - used = false, - ) - }, - magics = sheet.skills[4].fields.map { - CharacterSheet.Skill( - label = it.label.value, - value = it.unpack(), - used = false, - ) - }, - rolls = sheet.rolls.map { - CharacterSheet.Roll( - label = it.label.value, - roll = it.unpack(), - ) - }, - ) - } - - fun convertToUio( - sheet: CharacterSheet?, - ): CharacterSheetEditPageUio { - val str = FieldUio.create( - label = "Force", - valuePlaceHolder = { "0" }, - initialValue = sheet?.strength?.toString() ?: "" - ) - val dex = FieldUio.create( - label = "Dextérité", - valuePlaceHolder = { "0" }, - initialValue = sheet?.dexterity?.toString() ?: "" - ) - val con = FieldUio.create( - label = "Constitution", - valuePlaceHolder = { "0" }, - initialValue = sheet?.constitution?.toString() ?: "" - ) - val hei = FieldUio.create( - label = "Taille", - valuePlaceHolder = { "0" }, - initialValue = sheet?.height?.toString() ?: "" - ) - val int = FieldUio.create( - label = "Intelligence", - valuePlaceHolder = { "0" }, - initialValue = sheet?.intelligence?.toString() ?: "" - ) - val pow = FieldUio.create( - label = "Pouvoir", - valuePlaceHolder = { "0" }, - initialValue = sheet?.power?.toString() ?: "" - ) - val cha = FieldUio.create( - label = "Charisme", - valuePlaceHolder = { "0" }, - initialValue = sheet?.charisma?.toString() ?: "" - ) - - fun str(): Int = str.unpack() ?: 0 - fun dex(): Int = dex.unpack() ?: 0 - fun con(): Int = con.unpack() ?: 0 - fun hei(): Int = hei.unpack() ?: 0 - fun int(): Int = int.unpack() ?: 0 - fun pow(): Int = pow.unpack() ?: 0 - fun cha(): Int = cha.unpack() ?: 0 - - return CharacterSheetEditPageUio( - id = sheet?.id ?: UUID.randomUUID().toString(), - name = FieldUio.create( - useLabelAsPlaceholder = true, - label = "Name", - initialValue = sheet?.name ?: "" - ), - skills = listOf( - SkillGroup( - title = "Charactéristiques", - type = SkillGroup.Type.CHARACTERISTICS, - fields = listOf(str, dex, con, hei, int, pow, cha), - ), - SkillGroup( - title = "Charactéristiques dérivées", - type = SkillGroup.Type.SUB_CHARACTERISTICS, - fields = listOf( - FieldUio.create( - label = "Déplacement", - valuePlaceHolder = { "10" }, - initialValue = sheet?.movement?.toString() ?: "" - ), - FieldUio.create( - label = "Points de vie", - valuePlaceHolder = { "${ceil((con() + hei()) / 2f).toInt()}" }, - initialValue = sheet?.maxHp?.toString() ?: "" - ), - FieldUio.create( - label = "Points de pouvoir", - valuePlaceHolder = { "${pow()}" }, - initialValue = sheet?.maxPP?.toString() ?: "" - ), - FieldUio.create( - label = "Bonus aux dégats", - valuePlaceHolder = { - val bonus = str() + hei() - when { - bonus < 12 -> "-1d6" - bonus in 12..17 -> "-1d4" - bonus in 18..22 -> "-0" - bonus in 23..29 -> "1d4" - bonus in 30..39 -> "1d6" - else -> "2d6" - } - }, - initialValue = sheet?.damageBonus ?: "" - ), - FieldUio.create( - label = "Armure", - valuePlaceHolder = { "0" }, - initialValue = sheet?.armor?.toString() ?: "" - ), - ), - ), - SkillGroup( - title = "Compétances", - type = SkillGroup.Type.SKILLS, - editable = true, - fields = sheet?.skills?.map { - FieldUio.create( - label = it.label, - initialValue = it.value.toString(), - ) - } ?: listOf( - FieldUio.create( - label = "Bagarre", - valuePlaceHolder = { "${normalize(dex() * 2)}" }, - ), - FieldUio.create( - label = "Esquive", - valuePlaceHolder = { "${normalize(dex() * 2)}" }, - ), - FieldUio.create( - label = "Saisie", - valuePlaceHolder = { "${normalize(str() + hei())}" }, - ), - FieldUio.create( - label = "Lancer", - valuePlaceHolder = { "${normalize(str() + dex())}" }, - ), - FieldUio.create( - label = "Athlétisme", - valuePlaceHolder = { "${normalize(str() + con() * 2)}" }, - ), - FieldUio.create( - label = "Acrobatie", - valuePlaceHolder = { "${normalize(dex() + con() * 2)}" }, - ), - FieldUio.create( - label = "Perception", - valuePlaceHolder = { "${normalize(10 + int() * 2)}" }, - ), - FieldUio.create( - label = "Recherche", - valuePlaceHolder = { "${normalize(10 + int() * 2)}" }, - ), - FieldUio.create( - label = "Empathie", - valuePlaceHolder = { "${normalize(cha() + int())}" }, - ), - FieldUio.create( - label = "Persuasion", - valuePlaceHolder = { "${normalize(cha() * 3)}" }, - ), - FieldUio.create( - label = "Intimidation", - valuePlaceHolder = { "${normalize(cha() + max(pow(), hei()) * 2)}" }, - ), - FieldUio.create( - label = "Baratin", - valuePlaceHolder = { "${normalize(cha() * 2 + int())}" }, - ), - FieldUio.create( - label = "Marchandage", - valuePlaceHolder = { "${normalize(cha() * 2)}" }, - ), - FieldUio.create( - label = "Discrétion", - valuePlaceHolder = { "${normalize(cha() + dex() * 2 - hei())}" }, - ), - FieldUio.create( - label = "Escamotage", - valuePlaceHolder = { "${normalize(dex() * 2)}" }, - ), - FieldUio.create( - label = "Premiers soins", - valuePlaceHolder = { "${normalize(int() + dex())}" }, - ), - ), - ), - SkillGroup( - title = "Occupations", - type = SkillGroup.Type.OCCUPATIONS, - editable = true, - fields = sheet?.occupations?.map { - FieldUio.create( - label = it.label, - valuePlaceHolder = { "40" }, - initialValue = it.value.toString() - ) - } ?: emptyList(), - ), - SkillGroup( - title = "Compétences magiques", - type = SkillGroup.Type.MAGICS, - editable = true, - fields = sheet?.magics?.map { - FieldUio.create( - label = it.label, - initialValue = it.value.toString() - ) - } ?: emptyList(), - ), - ), - rolls = sheet?.rolls?.map { - FieldUio.create( - label = it.label, - isLabelEditable = true, - initialValue = it.roll, - ) - } ?: emptyList() - ) - } - - private inline fun FieldUio.unpack(): T { - val tmp = value.value.ifBlank { valuePlaceHolder.value } - return when (T::class) { - Int::class -> (tmp.toIntOrNull() ?: 0) as T - else -> tmp as T - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/composable/FieldUio.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/composable/FieldUio.kt index e03e31b..cfe360c 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/composable/FieldUio.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/edit/composable/FieldUio.kt @@ -22,37 +22,41 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @Stable open class FieldUio( - val useLabelAsPlaceholder: Boolean, + val isLabelDisplayed: Boolean, val isLabelEditable: Boolean, val label: State, + val labelPlaceHolder: State, val onLabelChange: (String) -> Unit, - val valuePlaceHolder: State, val value: State, + val valuePlaceHolder: State, val onValueChange: (String) -> Unit, ) { companion object { @Stable fun create( - useLabelAsPlaceholder: Boolean = false, + isLabelDisplayed: Boolean = true, isLabelEditable: Boolean = false, - label: String = "", + initialLabel: String = "", + labelPlaceHolder: () -> String = { "" }, initialValue: String = "", valuePlaceHolder: () -> String = { "" }, ): FieldUio { - val labelState = mutableStateOf(label) - val valueState = mutableStateOf(initialValue) + val label = mutableStateOf(initialLabel) + val value = mutableStateOf(initialValue) return FieldUio( - useLabelAsPlaceholder = useLabelAsPlaceholder, - isLabelEditable = useLabelAsPlaceholder.not() && isLabelEditable, - label = labelState, - onLabelChange = { labelState.value = it }, + isLabelDisplayed = isLabelDisplayed, + isLabelEditable = isLabelEditable, + label = label, + labelPlaceHolder = derivedStateOf(labelPlaceHolder), + onLabelChange = { label.value = it }, + value = value, valuePlaceHolder = derivedStateOf(valuePlaceHolder), - value = valueState, - onValueChange = { valueState.value = it }, + onValueChange = { value.value = it }, ) } } @@ -61,27 +65,17 @@ open class FieldUio( @Composable fun Form( modifier: Modifier = Modifier, + valueWidth: Dp = 80.dp, field: FieldUio, ) { val focus = LocalFocusManager.current AnimatedContent( - targetState = field.useLabelAsPlaceholder, + targetState = field.isLabelDisplayed, transitionSpec = { fadeIn() togetherWith fadeOut() } ) { when (it) { true -> { - TextField( - modifier = modifier, - value = field.value.value, - label = { Text(text = field.label.value) }, - singleLine = true, - keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) }, - onValueChange = field.onValueChange, - ) - } - - else -> { Row( modifier = modifier, horizontalArrangement = Arrangement.spacedBy(space = 8.dp), @@ -94,32 +88,43 @@ fun Form( ) { editable -> when (editable) { true -> TextField( - value = field.label.value, - placeholder = { Text(text = "Nom") }, - singleLine = true, keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) }, + singleLine = true, + placeholder = { Text(text = field.labelPlaceHolder.value) }, onValueChange = field.onLabelChange, + value = field.label.value, ) else -> Text( modifier = Modifier.padding(horizontal = 16.dp), - maxLines = 1, - overflow = TextOverflow.Ellipsis, style = MaterialTheme.typography.body1, + overflow = TextOverflow.Ellipsis, + maxLines = 1, text = field.label.value ) } } TextField( - modifier = Modifier.width(width = 80.dp), - value = field.value.value, - placeholder = { Text(text = field.valuePlaceHolder.value) }, - singleLine = true, + modifier = Modifier.width(width = valueWidth), keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) }, + singleLine = true, + placeholder = { Text(text = field.valuePlaceHolder.value) }, onValueChange = field.onValueChange, + value = field.value.value, ) } } + + else -> { + TextField( + modifier = modifier, + keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) }, + singleLine = true, + label = { Text(text = field.label.value) }, + onValueChange = field.onValueChange, + value = field.value.value, + ) + } } } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPage.kt index 6030c66..a8bcbaa 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/main/MainPage.kt @@ -12,7 +12,6 @@ import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.State -import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign @@ -22,6 +21,9 @@ import androidx.lifecycle.viewmodel.compose.viewModel import com.pixelized.desktop.lwa.navigation.LocalScreen import com.pixelized.desktop.lwa.navigation.destination.navigateToCharacterSheet import com.pixelized.desktop.lwa.navigation.destination.navigateToCharacterSheetEdit +import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.main_page__create_action +import org.jetbrains.compose.resources.stringResource @Stable data class CharacterUio( @@ -67,13 +69,13 @@ fun MainPageContent( Column { characters.value.forEach { sheet -> TextButton( - onClick = { onCharacter(sheet) } + onClick = { onCharacter(sheet) }, ) { Text( modifier = Modifier.fillMaxWidth(), - maxLines = 1, overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Start, + maxLines = 1, text = sheet.name, ) } @@ -88,7 +90,7 @@ fun MainPageContent( maxLines = 1, overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Start, - text = "Créer une feuille de personnage", + text = stringResource(Res.string.main_page__create_action), ) } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt index 3365441..60bcf17 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt @@ -16,6 +16,13 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.roll_page__critical_failure +import lwacharactersheet.composeapp.generated.resources.roll_page__critical_success +import lwacharactersheet.composeapp.generated.resources.roll_page__failure +import lwacharactersheet.composeapp.generated.resources.roll_page__special_success +import lwacharactersheet.composeapp.generated.resources.roll_page__success +import org.jetbrains.compose.resources.getString class RollViewModel : ViewModel() { private val _roll = mutableStateOf(RollUio(label = "", value = 0)) @@ -117,12 +124,11 @@ class RollViewModel : ViewModel() { _result.value = RollResultUio( label = rollStep?.let { rollStep -> when (roll) { - // TODO wording - in rollStep.criticalSuccessRange -> "Réussite critique" - in rollStep.specialSuccessRange -> "Réussite spéciale" - in rollStep.successRange -> "Réussite" - in rollStep.failureRange -> "Échec" - in rollStep.criticalFailureRange -> "Échec critique" + in rollStep.criticalSuccessRange -> getString(resource = Res.string.roll_page__critical_success) + in rollStep.specialSuccessRange -> getString(resource = Res.string.roll_page__special_success) + in rollStep.successRange -> getString(resource = Res.string.roll_page__success) + in rollStep.failureRange -> getString(resource = Res.string.roll_page__failure) + in rollStep.criticalFailureRange -> getString(resource = Res.string.roll_page__critical_failure) else -> "" } } ?: "", 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 new file mode 100644 index 0000000..28d8bfe --- /dev/null +++ b/composeApp/src/commonTest/kotlin/com/pixelized/desktop/lwa/business/DamageBonusUseCaseTest.kt @@ -0,0 +1,52 @@ +package com.pixelized.desktop.lwa.business + +import org.junit.Test + +class DamageBonusUseCaseTest { + + @Test + fun testBonusDamage() { + (0 until 12).forEach { + val result = DamageBonusUseCase.bonusDamage(stat = 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 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 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 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 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 expected = "+2d6" + assert(result == expected) { + "Expected:'$expected' bonus damage for stat:'$it' but was:'$result'" + } + } + } +}