Refactor the character sheet.

This commit is contained in:
Thomas Andres Gomez 2024-11-26 11:50:53 +01:00
parent 52f7f8333b
commit 51021d41d5
37 changed files with 1996 additions and 529 deletions

View file

@ -0,0 +1,112 @@
package com.pixelized.desktop.lwa.parser.arithmetic
import com.pixelized.desktop.lwa.parser.arithmetic.Instruction.Dice.Modifier
import com.pixelized.desktop.lwa.parser.arithmetic.Instruction.Word
// https://medium.com/@gustavoinzunza/how-to-solve-balanced-parenthesis-problem-with-regex-in-ruby-113eff30a79a
// https://stackoverflow.com/questions/546433/regular-expression-to-match-balanced-parentheses
class ArithmeticParser {
private val operatorParser = Regex(
"""\s*(?<operator>[-+])?\s*(?<payload>[^-+]*)"""
)
private val diceParser = Regex(
"""^(?<modifier>[ade])?(?<quantity>\d+)[dD](?<faces>\d+)"""
)
private val wordParser = Regex(
"""^(?<word>${words.joinToString(separator = "|") { it }})"""
)
private val flatParser = Regex(
"""(?<flat>\d+)"""
)
@Throws(Instruction.UnknownInstruction::class)
fun parse(value: String): List<Arithmetic> {
return operatorParser.findAll(value).mapNotNull {
val (operator, instruction) = it.destructured
if (instruction.isNotBlank()) {
Arithmetic(
sign = parseOperator(operator),
instruction = parseInstruction(instruction),
)
} else {
null
}
}.toList()
}
@Throws(Instruction.UnknownInstruction::class)
fun parseInstruction(instruction: String): Instruction {
diceParser.find(instruction)?.let {
val (modifier, quantity, faces) = it.destructured
Instruction.Dice(
modifier = parseModifier(value = modifier),
quantity = quantity.toInt(),
faces = faces.toInt(),
)
}?.let { return it }
wordParser.find(instruction)?.let {
parseWord(value = it.value)
}?.let { return it }
flatParser.find(instruction)?.let {
Instruction.Flat(value = it.value.toInt())
}?.let { return it }
throw Instruction.UnknownInstruction(payload = instruction)
}
private fun parseOperator(operator: String): Int {
return when (operator) {
"-" -> -1
"+" -> 1
else -> 1
}
}
private fun parseModifier(value: String): Modifier? {
return when (value) {
"a" -> Modifier.ADVANTAGE
"d" -> Modifier.DISADVANTAGE
"e" -> Modifier.EMPHASIS
else -> null
}
}
private fun parseWord(value: String): Word? {
return try {
Word.valueOf(value)
} catch (_: Exception) {
return null
}
}
fun convertInstructionToString(
instructions: List<Arithmetic>,
): 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
}
"$sign$value"
}.joinToString(separator = " ") {
it
}
}
companion object {
val words: List<String> = Word.entries.map { it.name }
}
}

View file

@ -0,0 +1,40 @@
package com.pixelized.desktop.lwa.parser.arithmetic
class Arithmetic(
val sign: Int,
val instruction: Instruction,
)
sealed interface Instruction {
data class Dice(
val modifier: Modifier?,
val quantity: Int,
val faces: Int,
) : Instruction {
enum class Modifier {
ADVANTAGE,
DISADVANTAGE,
EMPHASIS,
}
}
data class Flat(
val value: Int,
) : Instruction
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 UnknownInstruction(payload: String) : RuntimeException(
"Unknown instruction exception. Unable to parse the following payload:\"$payload\" into an instruction"
)
}