Refactor the character sheet.
This commit is contained in:
parent
52f7f8333b
commit
51021d41d5
37 changed files with 1996 additions and 529 deletions
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
@ -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"
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue