Skip to content

Commit

Permalink
Merge pull request #412 from fmasa/fix-encumbrance
Browse files Browse the repository at this point in the history
Make encumbrance text input parsing more robust
  • Loading branch information
fmasa authored Feb 11, 2025
2 parents 604c35e + 88b8617 commit f89ef35
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ fun NonCompendiumTrappingForm(
maxLength = 8,
validate = validate,
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number),
filters = listOf(Filter.DigitsAndDotSymbolsOnly),
filters = listOf(Filter.DecimalNumber),
)

TextInput(
Expand Down Expand Up @@ -348,7 +348,11 @@ private class InventoryItemFormData(
) = InventoryItemFormData(
id = remember(item) { item?.id ?: uuid4() },
name = inputValue(item?.name ?: "", Rules.NotBlank()),
encumbrance = inputValue(item?.encumbrance?.toString() ?: "0"),
encumbrance =
inputValue(
item?.encumbrance?.toInputString() ?: "0",
Rules.NonNegativeDecimal(),
),
quantity = inputValue(item?.quantity?.toString() ?: "1", Rules.PositiveInteger()),
itemQualities =
rememberSaveable(item?.id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ fun TrappingDialog(
maxLength = 8,
validate = validate,
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number),
filters = listOf(Filter.DigitsAndDotSymbolsOnly),
filters = listOf(Filter.DecimalNumber),
)

TextInput(
Expand Down Expand Up @@ -490,7 +490,11 @@ private class TrappingFormData(
TrappingFormData(
id = remember(item) { item?.id ?: uuid4() },
name = inputValue(item?.name ?: "", Rules.NotBlank()),
encumbrance = inputValue(item?.encumbrance?.toString() ?: "0"),
encumbrance =
inputValue(
item?.encumbrance?.toInputString() ?: "0",
Rules.NonNegativeDecimal(),
),
description = inputValue(item?.description ?: ""),
type = TrappingTypeFormData.fromTrappingType(item?.trappingType),
isVisibleToPlayers = item?.isVisibleToPlayers ?: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import dev.icerock.moko.parcelize.Parcelable
import dev.icerock.moko.parcelize.Parcelize
import kotlinx.serialization.Serializable
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import java.util.Locale
import kotlin.jvm.JvmInline

@Parcelize
Expand All @@ -17,6 +19,7 @@ value class Encumbrance(private val value: Double) : Parcelable {
val One: Encumbrance = Encumbrance(1.0)
val Zero: Encumbrance = Encumbrance(0.0)
private val formatter = DecimalFormat("#,##0.###")
private val inputFormatter = DecimalFormat("##0.###", DecimalFormatSymbols(Locale.ENGLISH))

fun maximumForCharacter(characteristics: Stats): Encumbrance =
Encumbrance(
Expand All @@ -37,6 +40,10 @@ value class Encumbrance(private val value: Double) : Parcelable {
operator fun minus(other: Encumbrance) = Encumbrance((value - other.value).coerceAtLeast(0.0))

override fun toString(): String = formatter.format(value)

fun toInputString(): String = inputFormatter.format(value)

fun toDouble(): Double = value
}

fun Iterable<Encumbrance>.sum(): Encumbrance = fold(Encumbrance.Zero) { a, b -> a + b }
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ class Rules(private vararg val rules: Rule) : Rule {
it.toIntOrNull() != null && it.toInt() >= 0
}

@Composable
fun NonNegativeDecimal() =
rule(stringResource(Str.validation_non_negative)) {
it.toDoubleOrNull() != null && it.toDouble() >= 0
}

/**
* This is useful usually for inputs that:
* - Have small width that doesn't allow us to show full error message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,17 @@ import cz.frantisekmasa.wfrp_master.common.core.domain.Expression
import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.Spacing

interface Filter {
companion object {
val DigitsAndDotSymbolsOnly: Filter = AllowedCharacters(('0'..'9').toList() + '.')
}

fun process(value: String): String

private class AllowedCharacters(private val characters: List<Char>) : Filter {
override fun process(value: String) = value.filter { it in characters }
object DecimalNumber : Filter {
private val ALLOWED_CHARACTERS = ('0'..'9').toSet() + '.'

override fun process(value: String) =
value
.asSequence()
.map { if (it == ',') '.' else it }
.filter { it in ALLOWED_CHARACTERS }
.joinToString("")
}

class MaxLength(private val maxLength: Int) : Filter {
Expand Down

0 comments on commit f89ef35

Please sign in to comment.