Add values/strings file

This commit is contained in:
Thomas Andres Gomez 2024-11-07 18:42:57 +01:00
parent 5bc8706972
commit 7af0c15a62
14 changed files with 615 additions and 362 deletions

View file

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="UTF-8"?>
<resources>
<string name="main_page__create_action">Créer une feuille de personnage</string>
<string name="roll_page__critical_success">Réussite critique</string>
<string name="roll_page__special_success">Réussite spéciale</string>
<string name="roll_page__success">Réussite</string>
<string name="roll_page__failure">Échec</string>
<string name="roll_page__critical_failure">Échec critique</string>
<string name="character_sheet_edit__title">Création de personnage</string>
<string name="character_sheet_edit__name_placeholder">Nom</string>
<string name="character_sheet_edit__add_roll_action">Ajouter un lancé</string>
<string name="character_sheet_edit__save_action">Sauvegarder</string>
<string name="character_sheet_edit__characteristics__title">Charactéristiques</string>
<string name="character_sheet_edit__characteristics__str">Force</string>
<string name="character_sheet_edit__characteristics__dex">Dextérité</string>
<string name="character_sheet_edit__characteristics__con">Constitution</string>
<string name="character_sheet_edit__characteristics__hei">Taille</string>
<string name="character_sheet_edit__characteristics__int">Intelligence</string>
<string name="character_sheet_edit__characteristics__pow">Pouvoir</string>
<string name="character_sheet_edit__characteristics__cha">Charisme</string>
<string name="character_sheet_edit__sub_characteristics__title">Charactéristiques dérivées</string>
<string name="character_sheet_edit__sub_characteristics__movement">Déplacement</string>
<string name="character_sheet_edit__sub_characteristics__hit_point">Points de vie</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__armor">Armure</string>
<string name="character_sheet_edit__skills__title">Compétances</string>
<string name="character_sheet_edit__skills__add_action">Ajouter une compétance</string>
<string name="character_sheet_edit__skills__combat">Bagarre</string>
<string name="character_sheet_edit__skills__dodge">Esquive</string>
<string name="character_sheet_edit__skills__grab">Saisie</string>
<string name="character_sheet_edit__skills__throw">Lancer</string>
<string name="character_sheet_edit__skills__athletics">Athlétisme</string>
<string name="character_sheet_edit__skills__acrobatics">Acrobatie</string>
<string name="character_sheet_edit__skills__perception">Perception</string>
<string name="character_sheet_edit__skills__search">Recherche</string>
<string name="character_sheet_edit__skills__empathy">Empathie</string>
<string name="character_sheet_edit__skills__persuasion">Persuasion</string>
<string name="character_sheet_edit__skills__intimidation">Intimidation</string>
<string name="character_sheet_edit__skills__spiel">Baratin</string>
<string name="character_sheet_edit__skills__bargain">Marchandage</string>
<string name="character_sheet_edit__skills__discretion">Discrétion</string>
<string name="character_sheet_edit__skills__sleight_of_hand">Escamotage</string>
<string name="character_sheet_edit__skills__aid">Premiers soins</string>
<string name="character_sheet_edit__occupation__title">Occupations</string>
<string name="character_sheet_edit__occupation__add_action">Ajouter une occupation</string>
<string name="character_sheet_edit__magic__title">Compétences magiques</string>
<string name="character_sheet_edit__magic__add_action">Ajouter une compétence magique</string>
<string name="character_sheet__characteristics__str">Force</string>
<string name="character_sheet__characteristics__dex">Dextérité</string>
<string name="character_sheet__characteristics__con">Constitution</string>
<string name="character_sheet__characteristics__hei">Taille</string>
<string name="character_sheet__characteristics__int">Intelligence</string>
<string name="character_sheet__characteristics__pow">Pouvoir</string>
<string name="character_sheet__characteristics__cha">Charisme</string>
<string name="character_sheet__sub_characteristics__title">Charactéristiques dérivées</string>
<string name="character_sheet__sub_characteristics__movement">Déplacement</string>
<string name="character_sheet__sub_characteristics__hit_point">Points de vie</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__armor">Armure</string>
<string name="character_sheet__skills__title">Compétences</string>
<string name="character_sheet__occupations_title">Occupations</string>
<string name="character_sheet__magics__title">Compétences magiques</string>
</resources>

View file

@ -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"
}
}
}

View file

@ -3,27 +3,33 @@ package com.pixelized.desktop.lwa.business
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet
object RollUseCase { object RollUseCase {
private val d100 = (1..100)
private val diceParser = Regex( private val diceParser = Regex(
"""(?<sign>[+-])?\h*(?<modifier>[ade])?(?<quantity>\d+)d(?<face>\d+)""" """(?<sign>[+-])?\s*(?<modifier>[ade])?(?<quantity>\d+)[dD](?<face>\d+)"""
) )
private val flatParser = Regex( private val flatParser = Regex(
"""(?<sign>[+-])?\h(?<value>\d+)\b""" """(?<sign>[+-])?\s*[^a-zA-Z](?<value>\d+)\b"""
) )
private val paramParser = Regex( private val paramParser = Regex(
"""(?<sign>[+-])?\h(?<param>BDGT)\b""" """(?<sign>[+-])?\s*(?<param>BDGT)\b"""
) )
fun rollD100(): Int { 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 { fun roll(characterSheet: CharacterSheet, roll: String): Int {
println(roll) println(roll)
return diceParser.findAll(roll).sumOf { return diceParser.findAll(roll).sumOf {
val (sign, modifier, quantity, faces) = it.destructured 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") println("roll ${sign}${quantity}d${faces} -> $it")
} }
} + flatParser.findAll(roll).sumOf { } + flatParser.findAll(roll).sumOf {
@ -36,7 +42,10 @@ object RollUseCase {
(if (sign == "-") -1 else 1) * when (param) { (if (sign == "-") -1 else 1) * when (param) {
"BDGT" -> diceParser.findAll(characterSheet.damageBonus).sumOf { "BDGT" -> diceParser.findAll(characterSheet.damageBonus).sumOf {
val (sign, modifier, quantity, faces) = it.destructured 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") 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()
}
}
} }

View file

@ -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.repository.characterSheet.CharacterSheet
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Node 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 { class CharacterSheetFactory {
fun convertToUio(model: CharacterSheet): CharacterSheetPageUio { suspend fun convertToUio(model: CharacterSheet): CharacterSheetPageUio {
return CharacterSheetPageUio( return CharacterSheetPageUio(
id = model.id, id = model.id,
name = model.name, name = model.name,
characteristics = listOf( characteristics = listOf(
Characteristic(label = "Force", value = "${model.strength}"), Characteristic(
Characteristic(label = "Dextérité", value = "${model.dexterity}"), label = getString(Res.string.character_sheet__characteristics__str),
Characteristic(label = "Constitution", value = "${model.constitution}"), value = "${model.strength}",
Characteristic(label = "Taille", value = "${model.height}"), ),
Characteristic(label = "Intelligence", value = "${model.intelligence}"), Characteristic(
Characteristic(label = "Pouvoir", value = "${model.power}"), label = getString(Res.string.character_sheet__characteristics__dex),
Characteristic(label = "Charisme", value = "${model.charisma}"), 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( subCharacteristics = listOf(
Characteristic(label = "Déplacement ", value = "${model.movement}"),
Characteristic( Characteristic(
label = "Points de vie", label = getString(Res.string.character_sheet__sub_characteristics__movement),
value = "${model.currentHp}/${model.maxHp}" value = "${model.movement}",
), ),
Characteristic( Characteristic(
label = "Points de pouvoir", label = getString(Res.string.character_sheet__sub_characteristics__hit_point),
value = "${model.currentPP}/${model.maxPP}" 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 { skills = model.skills.mapNotNull {
if (it.value > 0) { if (it.value > 0) {

View file

@ -49,8 +49,13 @@ import com.pixelized.desktop.lwa.screen.roll.RollPage
import com.pixelized.desktop.lwa.screen.roll.RollViewModel import com.pixelized.desktop.lwa.screen.roll.RollViewModel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res 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 lwacharactersheet.composeapp.generated.resources.ic_d20_32dp
import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
@Stable @Stable
data class CharacterSheetPageUio( data class CharacterSheetPageUio(
@ -122,7 +127,10 @@ fun CharacterSheetPage(
} }
}, },
onCharacteristic = { characteristic -> onCharacteristic = { characteristic ->
rollViewModel.prepareRoll(sheet = sheet, characteristic = characteristic) rollViewModel.prepareRoll(
sheet = sheet,
characteristic = characteristic
)
overlayViewModel.show() overlayViewModel.show()
}, },
onSkill = { node -> onSkill = { node ->
@ -228,7 +236,7 @@ fun CharacterSheetPageContent(
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
style = MaterialTheme.typography.caption, style = MaterialTheme.typography.caption,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
text = "Charactéristiques dérivées" text = stringResource(Res.string.character_sheet__sub_characteristics__title),
) )
characterSheet.subCharacteristics.forEach { characterSheet.subCharacteristics.forEach {
Characteristics( Characteristics(
@ -246,7 +254,7 @@ fun CharacterSheetPageContent(
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
style = MaterialTheme.typography.caption, style = MaterialTheme.typography.caption,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
text = "Compétences", text = stringResource(Res.string.character_sheet__skills__title),
) )
characterSheet.skills.forEach { characterSheet.skills.forEach {
Skill( Skill(
@ -266,7 +274,7 @@ fun CharacterSheetPageContent(
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
style = MaterialTheme.typography.caption, style = MaterialTheme.typography.caption,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
text = "Occupations" text = stringResource(Res.string.character_sheet__occupations_title),
) )
characterSheet.occupations.forEach { characterSheet.occupations.forEach {
Skill( Skill(
@ -286,7 +294,7 @@ fun CharacterSheetPageContent(
modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp), modifier = Modifier.fillMaxWidth().padding(bottom = 8.dp),
style = MaterialTheme.typography.caption, style = MaterialTheme.typography.caption,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
text = "Compétences magiques" text = stringResource(Res.string.character_sheet__magics__title),
) )
characterSheet.magics.forEach { characterSheet.magics.forEach {
Skill( Skill(

View file

@ -8,6 +8,7 @@ import androidx.lifecycle.ViewModel
import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetDestination import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetDestination
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.utils.extention.collectAsState import com.pixelized.desktop.lwa.utils.extention.collectAsState
import kotlinx.coroutines.runBlocking
class CharacterSheetViewModel( class CharacterSheetViewModel(
savedStateHandle: SavedStateHandle, savedStateHandle: SavedStateHandle,
@ -23,7 +24,9 @@ class CharacterSheetViewModel(
get() = repository get() = repository
.characterSheetFlow(id = argument.id) .characterSheetFlow(id = argument.id)
.collectAsState { sheet -> .collectAsState { sheet ->
sheet?.let { model -> factory.convertToUio(model = model) } sheet?.let { model ->
runBlocking { factory.convertToUio(model = model) }
}
} }
suspend fun deleteCharacter(id: String) { suspend fun deleteCharacter(id: String) {

View file

@ -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 <reified T> 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
}
}
}

View file

@ -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.FieldUio
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.Form import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.Form
import kotlinx.coroutines.launch 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 @Stable
data class CharacterSheetEditPageUio( data class CharacterSheetEditPageUio(
@ -46,7 +51,7 @@ data class CharacterSheetEditPageUio(
data class SkillGroup( data class SkillGroup(
val title: String, val title: String,
val type: Type, val type: Type,
val editable: Boolean = false, val action: String? = null,
val fields: List<FieldUio>, val fields: List<FieldUio>,
) { ) {
@Stable @Stable
@ -106,7 +111,7 @@ fun CharacterSheetEdit(
Text( Text(
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
maxLines = 1, maxLines = 1,
text = "Création de personnage", text = stringResource(Res.string.character_sheet_edit__title),
) )
}, },
navigationIcon = { navigationIcon = {
@ -152,7 +157,7 @@ fun CharacterSheetEdit(
field = it, field = it,
) )
} }
if (it.editable) { it.action?.let { label ->
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
@ -169,7 +174,7 @@ fun CharacterSheetEdit(
horizontalArrangement = Arrangement.spacedBy(space = 4.dp), horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) { ) {
Text( Text(
text = "Ajouter une ligne", text = label,
) )
Icon( Icon(
imageVector = Icons.Default.Add, imageVector = Icons.Default.Add,
@ -186,6 +191,7 @@ fun CharacterSheetEdit(
form.rolls.forEach { form.rolls.forEach {
Form( Form(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
valueWidth = 120.dp,
field = it, field = it,
) )
} }
@ -197,7 +203,7 @@ fun CharacterSheetEdit(
TextButton( TextButton(
onClick = onNewCategory, 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( TextButton(
onClick = onSave, onClick = onSave,
) { ) {
Text(text = "Sauvegarder") Text(text = stringResource(Res.string.character_sheet_edit__save_action))
} }
} }
} }

View file

@ -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.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditPageUio.SkillGroup import com.pixelized.desktop.lwa.screen.characterSheet.edit.CharacterSheetEditPageUio.SkillGroup
import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio import com.pixelized.desktop.lwa.screen.characterSheet.edit.composable.FieldUio
import kotlinx.coroutines.runBlocking
class CharacterSheetEditViewModel( class CharacterSheetEditViewModel(
savedStateHandle: SavedStateHandle, savedStateHandle: SavedStateHandle,
@ -15,11 +16,13 @@ class CharacterSheetEditViewModel(
private val argument = CharacterSheetEditDestination.Argument(savedStateHandle) private val argument = CharacterSheetEditDestination.Argument(savedStateHandle)
private val repository = CharacterSheetRepository private val repository = CharacterSheetRepository
private val factory = CharacterSheetFactory() private val factory = CharacterSheetEditFactory()
private val _characterSheet = repository private val _characterSheet = mutableStateOf(
.characterSheetFlow(id = argument.id).value repository.characterSheetFlow(id = argument.id).value.let {
.let { sheet -> mutableStateOf(factory.convertToUio(sheet = sheet)) } runBlocking { factory.convertToUio(it) }
}
)
val characterSheet: State<CharacterSheetEditPageUio> get() = _characterSheet val characterSheet: State<CharacterSheetEditPageUio> get() = _characterSheet
fun onSkill(skill: SkillGroup) { fun onSkill(skill: SkillGroup) {
@ -32,8 +35,8 @@ class CharacterSheetEditViewModel(
addAll(group.fields) addAll(group.fields)
add( add(
FieldUio.create( FieldUio.create(
label = "",
isLabelEditable = true, isLabelEditable = true,
initialLabel = "",
valuePlaceHolder = { valuePlaceHolder = {
when (group.type) { when (group.type) {
SkillGroup.Type.CHARACTERISTICS -> "" SkillGroup.Type.CHARACTERISTICS -> ""
@ -61,7 +64,7 @@ class CharacterSheetEditViewModel(
rolls = sheet.rolls.toMutableList().apply { rolls = sheet.rolls.toMutableList().apply {
add( add(
FieldUio.create( FieldUio.create(
label = "", initialLabel = "",
isLabelEditable = true, isLabelEditable = true,
valuePlaceHolder = { "" }, valuePlaceHolder = { "" },
) )

View file

@ -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 <reified T> 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
}
}
}

View file

@ -22,37 +22,41 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.focus.FocusDirection
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@Stable @Stable
open class FieldUio( open class FieldUio(
val useLabelAsPlaceholder: Boolean, val isLabelDisplayed: Boolean,
val isLabelEditable: Boolean, val isLabelEditable: Boolean,
val label: State<String>, val label: State<String>,
val labelPlaceHolder: State<String>,
val onLabelChange: (String) -> Unit, val onLabelChange: (String) -> Unit,
val valuePlaceHolder: State<String>,
val value: State<String>, val value: State<String>,
val valuePlaceHolder: State<String>,
val onValueChange: (String) -> Unit, val onValueChange: (String) -> Unit,
) { ) {
companion object { companion object {
@Stable @Stable
fun create( fun create(
useLabelAsPlaceholder: Boolean = false, isLabelDisplayed: Boolean = true,
isLabelEditable: Boolean = false, isLabelEditable: Boolean = false,
label: String = "", initialLabel: String = "",
labelPlaceHolder: () -> String = { "" },
initialValue: String = "", initialValue: String = "",
valuePlaceHolder: () -> String = { "" }, valuePlaceHolder: () -> String = { "" },
): FieldUio { ): FieldUio {
val labelState = mutableStateOf(label) val label = mutableStateOf(initialLabel)
val valueState = mutableStateOf(initialValue) val value = mutableStateOf(initialValue)
return FieldUio( return FieldUio(
useLabelAsPlaceholder = useLabelAsPlaceholder, isLabelDisplayed = isLabelDisplayed,
isLabelEditable = useLabelAsPlaceholder.not() && isLabelEditable, isLabelEditable = isLabelEditable,
label = labelState, label = label,
onLabelChange = { labelState.value = it }, labelPlaceHolder = derivedStateOf(labelPlaceHolder),
onLabelChange = { label.value = it },
value = value,
valuePlaceHolder = derivedStateOf(valuePlaceHolder), valuePlaceHolder = derivedStateOf(valuePlaceHolder),
value = valueState, onValueChange = { value.value = it },
onValueChange = { valueState.value = it },
) )
} }
} }
@ -61,27 +65,17 @@ open class FieldUio(
@Composable @Composable
fun Form( fun Form(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
valueWidth: Dp = 80.dp,
field: FieldUio, field: FieldUio,
) { ) {
val focus = LocalFocusManager.current val focus = LocalFocusManager.current
AnimatedContent( AnimatedContent(
targetState = field.useLabelAsPlaceholder, targetState = field.isLabelDisplayed,
transitionSpec = { fadeIn() togetherWith fadeOut() } transitionSpec = { fadeIn() togetherWith fadeOut() }
) { ) {
when (it) { when (it) {
true -> { 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( Row(
modifier = modifier, modifier = modifier,
horizontalArrangement = Arrangement.spacedBy(space = 8.dp), horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
@ -94,32 +88,43 @@ fun Form(
) { editable -> ) { editable ->
when (editable) { when (editable) {
true -> TextField( true -> TextField(
value = field.label.value,
placeholder = { Text(text = "Nom") },
singleLine = true,
keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) }, keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) },
singleLine = true,
placeholder = { Text(text = field.labelPlaceHolder.value) },
onValueChange = field.onLabelChange, onValueChange = field.onLabelChange,
value = field.label.value,
) )
else -> Text( else -> Text(
modifier = Modifier.padding(horizontal = 16.dp), modifier = Modifier.padding(horizontal = 16.dp),
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.body1, style = MaterialTheme.typography.body1,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = field.label.value text = field.label.value
) )
} }
} }
TextField( TextField(
modifier = Modifier.width(width = 80.dp), modifier = Modifier.width(width = valueWidth),
value = field.value.value,
placeholder = { Text(text = field.valuePlaceHolder.value) },
singleLine = true,
keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) }, keyboardActions = KeyboardActions { focus.moveFocus(FocusDirection.Next) },
singleLine = true,
placeholder = { Text(text = field.valuePlaceHolder.value) },
onValueChange = field.onValueChange, 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,
)
}
} }
} }
} }

View file

@ -12,7 +12,6 @@ import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign 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.LocalScreen
import com.pixelized.desktop.lwa.navigation.destination.navigateToCharacterSheet import com.pixelized.desktop.lwa.navigation.destination.navigateToCharacterSheet
import com.pixelized.desktop.lwa.navigation.destination.navigateToCharacterSheetEdit 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 @Stable
data class CharacterUio( data class CharacterUio(
@ -67,13 +69,13 @@ fun MainPageContent(
Column { Column {
characters.value.forEach { sheet -> characters.value.forEach { sheet ->
TextButton( TextButton(
onClick = { onCharacter(sheet) } onClick = { onCharacter(sheet) },
) { ) {
Text( Text(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
maxLines = 1,
text = sheet.name, text = sheet.name,
) )
} }
@ -88,7 +90,7 @@ fun MainPageContent(
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
textAlign = TextAlign.Start, textAlign = TextAlign.Start,
text = "Créer une feuille de personnage", text = stringResource(Res.string.main_page__create_action),
) )
} }
} }

View file

@ -16,6 +16,13 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking 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() { class RollViewModel : ViewModel() {
private val _roll = mutableStateOf(RollUio(label = "", value = 0)) private val _roll = mutableStateOf(RollUio(label = "", value = 0))
@ -117,12 +124,11 @@ class RollViewModel : ViewModel() {
_result.value = RollResultUio( _result.value = RollResultUio(
label = rollStep?.let { rollStep -> label = rollStep?.let { rollStep ->
when (roll) { when (roll) {
// TODO wording in rollStep.criticalSuccessRange -> getString(resource = Res.string.roll_page__critical_success)
in rollStep.criticalSuccessRange -> "Réussite critique" in rollStep.specialSuccessRange -> getString(resource = Res.string.roll_page__special_success)
in rollStep.specialSuccessRange -> "Réussite spéciale" in rollStep.successRange -> getString(resource = Res.string.roll_page__success)
in rollStep.successRange -> "Réussite" in rollStep.failureRange -> getString(resource = Res.string.roll_page__failure)
in rollStep.failureRange -> "Échec" in rollStep.criticalFailureRange -> getString(resource = Res.string.roll_page__critical_failure)
in rollStep.criticalFailureRange -> "Échec critique"
else -> "" else -> ""
} }
} ?: "", } ?: "",

View file

@ -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'"
}
}
}
}