Add values/strings file
This commit is contained in:
parent
5bc8706972
commit
7af0c15a62
14 changed files with 615 additions and 362 deletions
|
|
@ -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>
|
||||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
"""(?<sign>[+-])?\h*(?<modifier>[ade])?(?<quantity>\d+)d(?<face>\d+)"""
|
||||
"""(?<sign>[+-])?\s*(?<modifier>[ade])?(?<quantity>\d+)[dD](?<face>\d+)"""
|
||||
)
|
||||
private val flatParser = Regex(
|
||||
"""(?<sign>[+-])?\h(?<value>\d+)\b"""
|
||||
"""(?<sign>[+-])?\s*[^a-zA-Z](?<value>\d+)\b"""
|
||||
)
|
||||
private val paramParser = Regex(
|
||||
"""(?<sign>[+-])?\h(?<param>BDGT)\b"""
|
||||
"""(?<sign>[+-])?\s*(?<param>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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<FieldUio>,
|
||||
) {
|
||||
@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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<CharacterSheetEditPageUio> 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 = { "" },
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String>,
|
||||
val labelPlaceHolder: State<String>,
|
||||
val onLabelChange: (String) -> Unit,
|
||||
val valuePlaceHolder: State<String>,
|
||||
val value: State<String>,
|
||||
val valuePlaceHolder: State<String>,
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 -> ""
|
||||
}
|
||||
} ?: "",
|
||||
|
|
|
|||
|
|
@ -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'"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue