Refactor the roll mechanism to allow broader instructions set.
This commit is contained in:
parent
d2ae180cf7
commit
8d93d46cce
10 changed files with 207 additions and 146 deletions
|
|
@ -1,19 +1,7 @@
|
|||
package com.pixelized.desktop.lwa.business
|
||||
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
|
||||
object RollUseCase {
|
||||
|
||||
private val diceParser = Regex(
|
||||
"""(?<sign>[+-])?\s*(?<modifier>[ade])?(?<quantity>\d+)[dD](?<face>\d+)"""
|
||||
)
|
||||
private val flatParser = Regex(
|
||||
"""(?<sign>[+-])?\s*[^a-zA-Z](?<value>\d+)\b"""
|
||||
)
|
||||
private val paramParser = Regex(
|
||||
"""(?<sign>[+-])?\s*(?<param>BDGT)\b"""
|
||||
)
|
||||
|
||||
fun rollD100(): Int {
|
||||
return roll(quantity = 1, faces = 100)
|
||||
}
|
||||
|
|
@ -22,39 +10,6 @@ object RollUseCase {
|
|||
return sum(count = quantity) { (Math.random() * faces.toDouble() + 1).toInt() }
|
||||
}
|
||||
|
||||
fun roll(characterSheet: CharacterSheet, roll: String): Int {
|
||||
println(roll)
|
||||
return diceParser.findAll(roll).sumOf { match ->
|
||||
val (sign, modifier, quantity, faces) = match.destructured
|
||||
((if (sign == "-") -1 else 1) * roll(
|
||||
quantity = quantity.toInt(),
|
||||
faces = faces.toInt()
|
||||
)).also {
|
||||
println("roll ${sign}${quantity}d${faces} -> $it")
|
||||
}
|
||||
} + flatParser.findAll(roll).sumOf { match ->
|
||||
val (sign, value) = match.destructured
|
||||
((if (sign == "-") -1 else 1) * value.toInt()).also {
|
||||
println("flat: ${sign}${value} -> $it")
|
||||
}
|
||||
} + paramParser.findAll(roll).sumOf { match ->
|
||||
val (sign, param) = match.destructured
|
||||
(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) * roll(
|
||||
quantity = quantity.toInt(),
|
||||
faces = faces.toInt()
|
||||
)).also {
|
||||
println("param: ${sign}${param} -> $it")
|
||||
}
|
||||
}
|
||||
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun sum(count: Int, block: () -> Int): Int {
|
||||
return if (count > 1) {
|
||||
block() + sum(count - 1, block)
|
||||
|
|
|
|||
|
|
@ -1,39 +1,110 @@
|
|||
package com.pixelized.desktop.lwa.business
|
||||
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.Instruction
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import kotlin.math.max
|
||||
|
||||
class SkillValueComputationUseCase {
|
||||
|
||||
class SkillValueComputationUseCase(
|
||||
private val arithmeticParser: ArithmeticParser,
|
||||
) {
|
||||
fun computeSkillValue(
|
||||
sheet: CharacterSheet,
|
||||
skill: CharacterSheet.Skill,
|
||||
diminished: Int,
|
||||
): Int {
|
||||
val baseSum = skill.base.sumOf {
|
||||
when (val instruction = it.instruction) {
|
||||
val baseSum = arithmeticParser.parse(skill.base).sumOf { instruction ->
|
||||
when (instruction) {
|
||||
is Instruction.Dice -> 0
|
||||
is Instruction.Flat -> instruction.value
|
||||
Instruction.Word.BDC -> 0
|
||||
Instruction.Word.BDD -> 0
|
||||
Instruction.Word.STR -> sheet.strength
|
||||
Instruction.Word.DEX -> sheet.dexterity
|
||||
Instruction.Word.CON -> sheet.constitution
|
||||
Instruction.Word.HEI -> sheet.height
|
||||
Instruction.Word.INT -> sheet.intelligence
|
||||
Instruction.Word.POW -> sheet.power
|
||||
Instruction.Word.CHA -> sheet.charisma
|
||||
} * it.sign
|
||||
|
||||
is Instruction.Flat -> {
|
||||
instruction.value
|
||||
}
|
||||
|
||||
is Instruction.Word -> {
|
||||
when (instruction.type) {
|
||||
Instruction.Word.Type.BDC -> 0
|
||||
Instruction.Word.Type.BDD -> 0
|
||||
Instruction.Word.Type.STR -> sheet.strength
|
||||
Instruction.Word.Type.DEX -> sheet.dexterity
|
||||
Instruction.Word.Type.CON -> sheet.constitution
|
||||
Instruction.Word.Type.HEI -> sheet.height
|
||||
Instruction.Word.Type.INT -> sheet.intelligence
|
||||
Instruction.Word.Type.POW -> sheet.power
|
||||
Instruction.Word.Type.CHA -> sheet.charisma
|
||||
}
|
||||
}
|
||||
} * instruction.sign
|
||||
}
|
||||
|
||||
val base = if (skill.occupation) {
|
||||
max(MIN_OCCUPATION_VALUE, baseSum)
|
||||
} else {
|
||||
baseSum
|
||||
}
|
||||
|
||||
return max(base + skill.bonus + skill.level - diminished, 0)
|
||||
}
|
||||
|
||||
fun computeRoll(
|
||||
sheet: CharacterSheet,
|
||||
roll: String,
|
||||
): Int { // TODO Roll detail instead of an simple Int.
|
||||
print("Roll ->")
|
||||
return arithmeticParser.parse(roll).sumOf { instruction ->
|
||||
val value = when (instruction) {
|
||||
is Instruction.Dice -> RollUseCase.roll(
|
||||
quantity = instruction.quantity,
|
||||
faces = instruction.faces
|
||||
)
|
||||
|
||||
is Instruction.Flat -> instruction.value
|
||||
|
||||
is Instruction.Word -> {
|
||||
when (instruction.type) {
|
||||
Instruction.Word.Type.BDC -> {
|
||||
val damageBonusInstructions = arithmeticParser
|
||||
.parse(sheet.damageBonus)
|
||||
.firstOrNull()
|
||||
if (damageBonusInstructions is Instruction.Dice) {
|
||||
RollUseCase.roll(
|
||||
quantity = damageBonusInstructions.quantity,
|
||||
faces = damageBonusInstructions.faces
|
||||
)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
Instruction.Word.Type.BDD -> {
|
||||
val damageBonusInstructions = arithmeticParser
|
||||
.parse(sheet.damageBonus)
|
||||
.firstOrNull()
|
||||
if (damageBonusInstructions is Instruction.Dice) {
|
||||
RollUseCase.roll(
|
||||
quantity = damageBonusInstructions.quantity,
|
||||
faces = damageBonusInstructions.faces
|
||||
) / 2
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
Instruction.Word.Type.STR -> sheet.strength
|
||||
Instruction.Word.Type.DEX -> sheet.dexterity
|
||||
Instruction.Word.Type.CON -> sheet.constitution
|
||||
Instruction.Word.Type.HEI -> sheet.height
|
||||
Instruction.Word.Type.INT -> sheet.intelligence
|
||||
Instruction.Word.Type.POW -> sheet.power
|
||||
Instruction.Word.Type.CHA -> sheet.charisma
|
||||
}
|
||||
}
|
||||
} * instruction.sign
|
||||
|
||||
value.also { print(" ($instruction):$it") }
|
||||
}.also { println() }
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MIN_OCCUPATION_VALUE = 40
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,13 +21,13 @@ class ArithmeticParser {
|
|||
)
|
||||
|
||||
@Throws(Instruction.UnknownInstruction::class)
|
||||
fun parse(value: String): List<Arithmetic> {
|
||||
fun parse(value: String): List<Instruction> {
|
||||
return operatorParser.findAll(value).mapNotNull {
|
||||
val (operator, instruction) = it.destructured
|
||||
if (instruction.isNotBlank()) {
|
||||
Arithmetic(
|
||||
parseInstruction(
|
||||
sign = parseOperator(operator),
|
||||
instruction = parseInstruction(instruction),
|
||||
instruction = instruction,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
|
@ -36,10 +36,14 @@ class ArithmeticParser {
|
|||
}
|
||||
|
||||
@Throws(Instruction.UnknownInstruction::class)
|
||||
fun parseInstruction(instruction: String): Instruction {
|
||||
fun parseInstruction(
|
||||
sign: Int,
|
||||
instruction: String
|
||||
): Instruction {
|
||||
diceParser.find(instruction)?.let {
|
||||
val (modifier, quantity, faces) = it.destructured
|
||||
Instruction.Dice(
|
||||
sign = sign,
|
||||
modifier = parseModifier(value = modifier),
|
||||
quantity = quantity.toInt(),
|
||||
faces = faces.toInt(),
|
||||
|
|
@ -47,11 +51,17 @@ class ArithmeticParser {
|
|||
}?.let { return it }
|
||||
|
||||
wordParser.find(instruction)?.let {
|
||||
parseWord(value = it.value)
|
||||
parseWord(
|
||||
sign = sign,
|
||||
value = it.value
|
||||
)
|
||||
}?.let { return it }
|
||||
|
||||
flatParser.find(instruction)?.let {
|
||||
Instruction.Flat(value = it.value.toInt())
|
||||
Instruction.Flat(
|
||||
sign = sign,
|
||||
value = it.value.toInt(),
|
||||
)
|
||||
}?.let { return it }
|
||||
|
||||
throw Instruction.UnknownInstruction(payload = instruction)
|
||||
|
|
@ -74,31 +84,39 @@ class ArithmeticParser {
|
|||
}
|
||||
}
|
||||
|
||||
private fun parseWord(value: String): Word? {
|
||||
private fun parseWord(
|
||||
sign: Int,
|
||||
value: String,
|
||||
): Word? {
|
||||
return try {
|
||||
Word.valueOf(value)
|
||||
Word(
|
||||
sign = sign,
|
||||
type = Word.Type.valueOf(value),
|
||||
)
|
||||
} catch (_: Exception) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
fun convertInstructionToString(
|
||||
instructions: List<Arithmetic>,
|
||||
instructions: List<Instruction>,
|
||||
): String {
|
||||
return instructions.map {
|
||||
val sign = if (it.sign > 0) "+" else "-"
|
||||
val value = when (val instruction = it.instruction) {
|
||||
is Instruction.Dice -> "${instruction.modifier ?: ""}${instruction.quantity}d${instruction.faces}"
|
||||
is Instruction.Flat -> "${instruction.value}"
|
||||
Word.BDC -> Word.BDC.name
|
||||
Word.BDD -> Word.BDD.name
|
||||
Word.STR -> Word.STR.name
|
||||
Word.DEX -> Word.DEX.name
|
||||
Word.CON -> Word.CON.name
|
||||
Word.HEI -> Word.HEI.name
|
||||
Word.INT -> Word.INT.name
|
||||
Word.POW -> Word.POW.name
|
||||
Word.CHA -> Word.CHA.name
|
||||
val value = when (it) {
|
||||
is Instruction.Dice -> "${it.modifier ?: ""}${it.quantity}d${it.faces}"
|
||||
is Instruction.Flat -> "${it.value}"
|
||||
is Word -> when (it.type) {
|
||||
Word.Type.BDC -> Word.Type.BDC.name
|
||||
Word.Type.BDD -> Word.Type.BDD.name
|
||||
Word.Type.STR -> Word.Type.STR.name
|
||||
Word.Type.DEX -> Word.Type.DEX.name
|
||||
Word.Type.CON -> Word.Type.CON.name
|
||||
Word.Type.HEI -> Word.Type.HEI.name
|
||||
Word.Type.INT -> Word.Type.INT.name
|
||||
Word.Type.POW -> Word.Type.POW.name
|
||||
Word.Type.CHA -> Word.Type.CHA.name
|
||||
}
|
||||
}
|
||||
"$sign$value"
|
||||
}.joinToString(separator = " ") {
|
||||
|
|
@ -107,6 +125,6 @@ class ArithmeticParser {
|
|||
}
|
||||
|
||||
companion object {
|
||||
val words: List<String> = Word.entries.map { it.name }
|
||||
val words: List<String> = Word.Type.entries.map { it.name }
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +1,64 @@
|
|||
package com.pixelized.desktop.lwa.parser.arithmetic
|
||||
|
||||
class Arithmetic(
|
||||
sealed class Instruction(
|
||||
val sign: Int,
|
||||
val instruction: Instruction,
|
||||
)
|
||||
|
||||
sealed interface Instruction {
|
||||
data class Dice(
|
||||
) {
|
||||
class Dice(
|
||||
sign: Int,
|
||||
val modifier: Modifier?,
|
||||
val quantity: Int,
|
||||
val faces: Int,
|
||||
) : Instruction {
|
||||
) : Instruction(
|
||||
sign = sign,
|
||||
) {
|
||||
enum class Modifier {
|
||||
ADVANTAGE,
|
||||
DISADVANTAGE,
|
||||
EMPHASIS,
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "${sign.sign}${quantity}d${faces}"
|
||||
}
|
||||
}
|
||||
|
||||
data class Flat(
|
||||
class Flat(
|
||||
sign: Int,
|
||||
val value: Int,
|
||||
) : Instruction
|
||||
) : Instruction(
|
||||
sign = sign,
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "${sign.sign}${value}"
|
||||
}
|
||||
}
|
||||
|
||||
enum class Word : Instruction {
|
||||
BDC, // Damages bonus for melee
|
||||
BDD, // Damages bonus for range
|
||||
STR, // Strength
|
||||
DEX, // Dexterity
|
||||
CON, // Constitution
|
||||
HEI, // Height
|
||||
INT, // Intelligence
|
||||
POW, // Power
|
||||
CHA, // Charisma
|
||||
class Word(
|
||||
sign: Int,
|
||||
val type: Type,
|
||||
) : Instruction(
|
||||
sign = sign
|
||||
) {
|
||||
enum class Type {
|
||||
BDC, // Damages bonus for melee
|
||||
BDD, // Damages bonus for range
|
||||
STR, // Strength
|
||||
DEX, // Dexterity
|
||||
CON, // Constitution
|
||||
HEI, // Height
|
||||
INT, // Intelligence
|
||||
POW, // Power
|
||||
CHA, // Charisma
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "${sign.sign}${type}"
|
||||
}
|
||||
}
|
||||
|
||||
class UnknownInstruction(payload: String) : RuntimeException(
|
||||
"Unknown instruction exception. Unable to parse the following payload:\"$payload\" into an instruction"
|
||||
)
|
||||
|
||||
val Int.sign: String get() = if (this > 0) "+" else "-"
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ class CharacterSheetJsonFactory(
|
|||
CharacterSheetJsonV1.Skill(
|
||||
id = it.id,
|
||||
label = it.label,
|
||||
base = arithmeticParser.convertInstructionToString(it.base),
|
||||
base = it.base,
|
||||
bonus = it.bonus,
|
||||
level = it.level,
|
||||
occupation = it.occupation,
|
||||
|
|
@ -47,7 +47,7 @@ class CharacterSheetJsonFactory(
|
|||
CharacterSheetJsonV1.Skill(
|
||||
id = it.id,
|
||||
label = it.label,
|
||||
base = arithmeticParser.convertInstructionToString(it.base),
|
||||
base = it.base,
|
||||
bonus = it.bonus,
|
||||
level = it.level,
|
||||
occupation = it.occupation,
|
||||
|
|
@ -58,7 +58,7 @@ class CharacterSheetJsonFactory(
|
|||
CharacterSheetJsonV1.Skill(
|
||||
id = it.id,
|
||||
label = it.label,
|
||||
base = arithmeticParser.convertInstructionToString(it.base),
|
||||
base = it.base,
|
||||
bonus = it.bonus,
|
||||
level = it.level,
|
||||
occupation = it.occupation,
|
||||
|
|
@ -69,7 +69,7 @@ class CharacterSheetJsonFactory(
|
|||
CharacterSheetJsonV1.Roll(
|
||||
id = it.id,
|
||||
label = it.label,
|
||||
roll = arithmeticParser.convertInstructionToString(it.roll),
|
||||
roll = it.roll,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -117,7 +117,7 @@ class CharacterSheetJsonFactory(
|
|||
CharacterSheet.Skill(
|
||||
id = it.id,
|
||||
label = it.label,
|
||||
base = arithmeticParser.parse(it.base),
|
||||
base = it.base,
|
||||
bonus = it.bonus,
|
||||
level = it.level,
|
||||
occupation = it.occupation,
|
||||
|
|
@ -128,7 +128,7 @@ class CharacterSheetJsonFactory(
|
|||
CharacterSheet.Skill(
|
||||
id = it.id,
|
||||
label = it.label,
|
||||
base = arithmeticParser.parse(it.base),
|
||||
base = it.base,
|
||||
bonus = it.bonus,
|
||||
level = it.level,
|
||||
occupation = it.occupation,
|
||||
|
|
@ -139,7 +139,7 @@ class CharacterSheetJsonFactory(
|
|||
CharacterSheet.Skill(
|
||||
id = it.id,
|
||||
label = it.label,
|
||||
base = arithmeticParser.parse(it.base),
|
||||
base = it.base,
|
||||
bonus = it.bonus,
|
||||
level = it.level,
|
||||
occupation = it.occupation,
|
||||
|
|
@ -150,7 +150,7 @@ class CharacterSheetJsonFactory(
|
|||
CharacterSheet.Roll(
|
||||
id = it.id,
|
||||
label = it.label,
|
||||
roll = arithmeticParser.parse(it.roll),
|
||||
roll = it.roll,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
package com.pixelized.desktop.lwa.repository.characterSheet.model
|
||||
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.Arithmetic
|
||||
|
||||
data class CharacterSheet(
|
||||
val id: String,
|
||||
val name: String,
|
||||
|
|
@ -36,7 +34,7 @@ data class CharacterSheet(
|
|||
data class Skill(
|
||||
val id: String,
|
||||
val label: String,
|
||||
val base: List<Arithmetic>,
|
||||
val base: String,
|
||||
val bonus: Int,
|
||||
val level: Int,
|
||||
val occupation: Boolean,
|
||||
|
|
@ -46,7 +44,7 @@ data class CharacterSheet(
|
|||
data class Roll(
|
||||
val id: String,
|
||||
val label: String,
|
||||
val roll: List<Arithmetic>,
|
||||
val roll: String,
|
||||
)
|
||||
|
||||
object CommonSkillId {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.pixelized.desktop.lwa.screen.characterSheet.detail
|
|||
|
||||
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
|
||||
import com.pixelized.desktop.lwa.composable.tooltip.TooltipUio
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet.CommonSkillId
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
|
||||
|
|
@ -51,6 +52,7 @@ import org.jetbrains.compose.resources.getString
|
|||
|
||||
class CharacterSheetFactory(
|
||||
private val skillUseCase: SkillValueComputationUseCase,
|
||||
private val arithmeticParser: ArithmeticParser,
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
|
@ -251,7 +253,7 @@ class CharacterSheetFactory(
|
|||
if (it.roll.isNotEmpty()) {
|
||||
CharacterSheetPageUio.Roll(
|
||||
label = it.label,
|
||||
value = "TODO",//it.roll,
|
||||
value = it.roll,
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
|
|
|||
|
|
@ -4,9 +4,7 @@ import androidx.compose.runtime.State
|
|||
import androidx.compose.runtime.derivedStateOf
|
||||
import com.pixelized.desktop.lwa.business.DamageBonusUseCase
|
||||
import com.pixelized.desktop.lwa.business.SkillNormalizerUseCase.normalize
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.Arithmetic
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.Instruction
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.common.SkillFieldFactory
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.common.occupation
|
||||
|
|
@ -94,12 +92,7 @@ class CharacterSheetEditFactory(
|
|||
CharacterSheet.Skill(
|
||||
id = editedSkill.id,
|
||||
label = editedSkill.label,
|
||||
base = listOf(
|
||||
Arithmetic(
|
||||
sign = 1,
|
||||
instruction = Instruction.Flat(editedSkill.base.value)
|
||||
)
|
||||
),
|
||||
base = "${editedSkill.base}",
|
||||
bonus = editedSkill.bonus.value.value.toIntOrNull() ?: 0,
|
||||
level = editedSkill.level.value.value.toIntOrNull() ?: 0,
|
||||
occupation = editedSkill.option.checked.value,
|
||||
|
|
@ -113,7 +106,7 @@ class CharacterSheetEditFactory(
|
|||
CharacterSheet.Skill(
|
||||
id = editedSkill.id,
|
||||
label = editedSkill.label.value.value,
|
||||
base = parser.parse(editedSkill.base.value.value),
|
||||
base = editedSkill.base.value.value,
|
||||
bonus = editedSkill.bonus.value.value.toIntOrNull() ?: 0,
|
||||
level = editedSkill.level.value.value.toIntOrNull() ?: 0,
|
||||
occupation = editedSkill.options.occupation,
|
||||
|
|
@ -127,7 +120,7 @@ class CharacterSheetEditFactory(
|
|||
CharacterSheet.Skill(
|
||||
id = editedSkill.id,
|
||||
label = editedSkill.label.value.value,
|
||||
base = parser.parse(editedSkill.base.value.value),
|
||||
base = editedSkill.base.value.value,
|
||||
bonus = editedSkill.bonus.value.value.toIntOrNull() ?: 0,
|
||||
level = editedSkill.level.value.value.toIntOrNull() ?: 0,
|
||||
occupation = editedSkill.options.occupation,
|
||||
|
|
@ -138,7 +131,7 @@ class CharacterSheetEditFactory(
|
|||
CharacterSheet.Roll(
|
||||
id = "", // TODO
|
||||
label = it.label.value,
|
||||
roll = parser.parse(value = it.unpack()),
|
||||
roll = it.unpack(),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -345,7 +338,7 @@ class CharacterSheetEditFactory(
|
|||
id = skill.id,
|
||||
label = specialSkillsLabel,
|
||||
labelValue = skill.label,
|
||||
baseValue = parser.convertInstructionToString(instructions = skill.base),
|
||||
baseValue = skill.base,
|
||||
bonusValue = skill.bonus.takeIf { it > 0 }?.toString() ?: "",
|
||||
levelValue = skill.level.takeIf { it > 0 }?.toString() ?: "",
|
||||
options = run {
|
||||
|
|
@ -362,7 +355,7 @@ class CharacterSheetEditFactory(
|
|||
id = skill.id,
|
||||
label = magicSkillsLabel,
|
||||
labelValue = skill.label,
|
||||
baseValue = parser.convertInstructionToString(instructions = skill.base),
|
||||
baseValue = skill.base,
|
||||
bonusValue = skill.bonus.takeIf { it > 0 }?.toString() ?: "",
|
||||
levelValue = skill.level.takeIf { it > 0 }?.toString() ?: "",
|
||||
options = run {
|
||||
|
|
|
|||
|
|
@ -3,14 +3,13 @@ package com.pixelized.desktop.lwa.screen.roll
|
|||
import androidx.compose.animation.core.Animatable
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.pixelized.desktop.lwa.business.RollUseCase
|
||||
import com.pixelized.desktop.lwa.business.SkillStepUseCase
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.business.SkillValueComputationUseCase
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||
import com.pixelized.desktop.lwa.repository.roll.RollHistoryRepository
|
||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio
|
||||
import com.pixelized.desktop.lwa.screen.roll.DifficultyUio.Difficulty
|
||||
|
|
@ -34,6 +33,7 @@ import org.jetbrains.compose.resources.getString
|
|||
class RollViewModel(
|
||||
private val characterSheetRepository: CharacterSheetRepository,
|
||||
private val rollHistoryRepository: RollHistoryRepository,
|
||||
private val skillComputation: SkillValueComputationUseCase,
|
||||
) : ViewModel() {
|
||||
|
||||
private lateinit var sheet: CharacterSheet
|
||||
|
|
@ -168,11 +168,12 @@ class RollViewModel(
|
|||
}
|
||||
)
|
||||
}
|
||||
val roll = if (rollAction == "1d100") {
|
||||
RollUseCase.rollD100()
|
||||
} else {
|
||||
RollUseCase.roll(characterSheet = sheet, roll = rollAction)
|
||||
}
|
||||
|
||||
val roll = skillComputation.computeRoll(
|
||||
sheet = sheet,
|
||||
roll = rollAction,
|
||||
)
|
||||
|
||||
val success = rollStep?.let {
|
||||
when (roll) {
|
||||
in it.criticalSuccess -> getString(resource = Res.string.roll_page__critical_success)
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
package com.pixelized.desktop.lwa.parser
|
||||
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.Arithmetic
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.Instruction
|
||||
import com.pixelized.desktop.lwa.parser.arithmetic.ArithmeticParser
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertFails
|
||||
|
||||
class ArithmeticParserTest {
|
||||
class InstructionParserTest {
|
||||
|
||||
@Test
|
||||
fun testDiceInstructionParse() {
|
||||
|
|
@ -14,16 +13,16 @@ class ArithmeticParserTest {
|
|||
|
||||
fun test(
|
||||
instruction: String,
|
||||
expectedModifier: Instruction.Dice.Modifier?,
|
||||
expectedModifier: Instruction.Dice.Modifier.Dice.Modifier?,
|
||||
expectedQuantity: Int,
|
||||
expectedFaces: Int,
|
||||
) {
|
||||
val dice = parser.parseInstruction(instruction = instruction)
|
||||
|
||||
assert(dice is Instruction.Dice) {
|
||||
assert(dice is Instruction.Dice.Dice) {
|
||||
"Instruction should be ArithmeticInstruction.Dice but was: ${dice::class.java.simpleName}"
|
||||
}
|
||||
(dice as? Instruction.Dice)?.let {
|
||||
(dice as? Instruction.Dice.Dice)?.let {
|
||||
assert(dice.modifier == expectedModifier) {
|
||||
"$instruction modifier should be:\"$expectedModifier\", but was: ${dice.modifier}"
|
||||
}
|
||||
|
|
@ -69,10 +68,10 @@ class ArithmeticParserTest {
|
|||
ArithmeticParser.words.map { instruction ->
|
||||
val word = parser.parseInstruction(instruction = instruction)
|
||||
|
||||
assert(word is Instruction.Word) {
|
||||
assert(word is Instruction.Word.Word) {
|
||||
"Instruction should be ArithmeticInstruction.Word but was: ${word::class.java.simpleName}"
|
||||
}
|
||||
(word as? Instruction.Word)?.let {
|
||||
(word as? Instruction.Word.Word)?.let {
|
||||
assert(it.name == instruction) {
|
||||
"Instruction should be $instruction, but was ${it.name}"
|
||||
}
|
||||
|
|
@ -87,10 +86,10 @@ class ArithmeticParserTest {
|
|||
"100".let { instruction ->
|
||||
val flat = parser.parseInstruction(instruction = instruction)
|
||||
|
||||
assert(flat is Instruction.Flat) {
|
||||
assert(flat is Instruction.Flat.Flat) {
|
||||
"Instruction should be ArithmeticInstruction.Flat but was: ${flat::class.java.simpleName}"
|
||||
}
|
||||
(flat as? Instruction.Flat)?.let {
|
||||
(flat as? Instruction.Flat.Flat)?.let {
|
||||
assert("${it.value}" == instruction) {
|
||||
"Instruction should be $instruction, but was ${it.value}"
|
||||
}
|
||||
|
|
@ -113,7 +112,7 @@ class ArithmeticParserTest {
|
|||
val parser = ArithmeticParser()
|
||||
|
||||
fun test(
|
||||
arithmetics: Arithmetic,
|
||||
arithmetics: Instruction,
|
||||
expectedSign: Int,
|
||||
expectedInstruction: Instruction,
|
||||
) {
|
||||
Loading…
Add table
Add a link
Reference in a new issue