diff --git a/data/common/src/main/java/com/sadellie/unitto/data/common/BigDecimalUtils.kt b/data/common/src/main/java/com/sadellie/unitto/data/common/BigDecimalUtils.kt index 94f12cfb..5d755aa0 100644 --- a/data/common/src/main/java/com/sadellie/unitto/data/common/BigDecimalUtils.kt +++ b/data/common/src/main/java/com/sadellie/unitto/data/common/BigDecimalUtils.kt @@ -24,7 +24,6 @@ import java.math.RoundingMode import kotlin.math.floor import kotlin.math.log10 -// TODO Use everywhere fun BigDecimal.format( scale: Int, outputFormat: Int @@ -35,25 +34,43 @@ fun BigDecimal.format( .toStringWith(outputFormat) } -// TODO Move tests and mark as internal /** - * Shorthand function to use correct `toString` method according to [outputFormat]. + * Removes all trailing zeroes. */ -fun BigDecimal.toStringWith(outputFormat: Int): String { - // Setting result value using a specified OutputFormat - return when (outputFormat) { - OutputFormat.ALLOW_ENGINEERING -> this.toString() - OutputFormat.FORCE_ENGINEERING -> this.toEngineeringString() - else -> this.toPlainString() - } +fun BigDecimal.trimZeros(): BigDecimal { + return if (this.isEqualTo(BigDecimal.ZERO)) BigDecimal.ZERO else this.stripTrailingZeros() } +/** + * Uses [compareTo], ignores scale differences. + * + * @param bd BigDecimal to which this BigDecimal is to be compared. + * @return `true` if [compareTo] returned 0 + */ +fun BigDecimal.isEqualTo(bd: BigDecimal): Boolean = compareTo(bd) == 0 + +/** + * Uses [compareTo], ignores scale differences. + * + * @param bd BigDecimal to which this BigDecimal is to be compared. + * @return `true` if [compareTo] returned 1 + */ +fun BigDecimal.isGreaterThan(bd: BigDecimal): Boolean = compareTo(bd) == 1 + +/** + * Uses [compareTo], ignores scale differences. + * + * @param bd BigDecimal to which this BigDecimal is to be compared. + * @return `true` if [compareTo] returned -1 + */ +fun BigDecimal.isLessThan(bd: BigDecimal): Boolean = compareTo(bd) == -1 + /** * Sets the minimum scale that is required to get first non zero value in fractional part * * @param[prefScale] Is the preferred scale, the one which will be compared against */ -fun BigDecimal.setMinimumRequiredScale(prefScale: Int): BigDecimal { +internal fun BigDecimal.setMinimumRequiredScale(prefScale: Int): BigDecimal { /** * Here we are getting the amount of zeros in fractional part before non zero value * For example, for 0.00000123456 we need the length of 00000 @@ -75,10 +92,13 @@ fun BigDecimal.setMinimumRequiredScale(prefScale: Int): BigDecimal { } /** - * Removes all trailing zeroes. + * Shorthand function to use correct `toString` method according to [outputFormat]. */ -fun BigDecimal.trimZeros(): BigDecimal { - return if (this.isEqualTo(BigDecimal.ZERO)) BigDecimal.ZERO else this.stripTrailingZeros() +private fun BigDecimal.toStringWith(outputFormat: Int): String { + // Setting result value using a specified OutputFormat + return when (outputFormat) { + OutputFormat.ALLOW_ENGINEERING -> this.toString() + OutputFormat.FORCE_ENGINEERING -> this.toEngineeringString() + else -> this.toPlainString() + } } - -fun BigDecimal.isEqualTo(bd: BigDecimal): Boolean = compareTo(bd) == 0 diff --git a/data/units/src/test/java/com/sadellie/unitto/data/units/MinimumRequiredScaleTest.kt b/data/common/src/test/java/com/sadellie/unitto/data/common/MinimumRequiredScaleTest.kt similarity index 94% rename from data/units/src/test/java/com/sadellie/unitto/data/units/MinimumRequiredScaleTest.kt rename to data/common/src/test/java/com/sadellie/unitto/data/common/MinimumRequiredScaleTest.kt index 1deaf6d3..bdd97838 100644 --- a/data/units/src/test/java/com/sadellie/unitto/data/units/MinimumRequiredScaleTest.kt +++ b/data/common/src/test/java/com/sadellie/unitto/data/common/MinimumRequiredScaleTest.kt @@ -16,9 +16,8 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.units +package com.sadellie.unitto.data.common -import com.sadellie.unitto.data.common.setMinimumRequiredScale import org.junit.Assert.assertEquals import org.junit.Test import java.math.BigDecimal diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/FuelBackward.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/FuelBackward.kt index 91c68396..e349de33 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/FuelBackward.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/FuelBackward.kt @@ -19,6 +19,7 @@ package com.sadellie.unitto.data.model.unit import com.sadellie.unitto.core.base.MAX_PRECISION +import com.sadellie.unitto.data.common.isEqualTo import com.sadellie.unitto.data.model.UnitGroup import java.math.BigDecimal import java.math.RoundingMode @@ -35,7 +36,7 @@ data class FuelBackward( ) : DefaultUnit { override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { // Avoid division by zero - if (unitTo.basicUnit.compareTo(BigDecimal.ZERO) == 0) return BigDecimal.ZERO + if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO return when (unitTo) { is FuelForward -> this diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/FuelForward.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/FuelForward.kt index 457ecaa9..19278567 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/FuelForward.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/FuelForward.kt @@ -19,6 +19,7 @@ package com.sadellie.unitto.data.model.unit import com.sadellie.unitto.core.base.MAX_PRECISION +import com.sadellie.unitto.data.common.isEqualTo import com.sadellie.unitto.data.model.UnitGroup import java.math.BigDecimal import java.math.RoundingMode @@ -35,7 +36,7 @@ data class FuelForward( ) : DefaultUnit { override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { // Avoid division by zero - if (unitTo.basicUnit.compareTo(BigDecimal.ZERO) == 0) return BigDecimal.ZERO + if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO return when (unitTo) { is FuelForward -> this diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt index 5c4fa0e0..4554b58d 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt @@ -19,6 +19,7 @@ package com.sadellie.unitto.data.model.unit import com.sadellie.unitto.core.base.MAX_PRECISION +import com.sadellie.unitto.data.common.isEqualTo import com.sadellie.unitto.data.model.UnitGroup import java.math.BigDecimal import java.math.RoundingMode @@ -35,7 +36,7 @@ data class NormalUnit( ) : DefaultUnit { override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { // Avoid division by zero - if (unitTo.basicUnit.compareTo(BigDecimal.ZERO) == 0) return BigDecimal.ZERO + if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO return this .basicUnit diff --git a/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsTest.kt b/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsTest.kt index 630f51f0..d16af0c8 100644 --- a/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsTest.kt +++ b/data/units/src/test/java/com/sadellie/unitto/data/units/AllUnitsTest.kt @@ -20,8 +20,8 @@ package com.sadellie.unitto.data.units import android.content.Context import androidx.room.Room -import com.sadellie.unitto.data.common.setMinimumRequiredScale -import com.sadellie.unitto.data.common.trimZeros +import com.sadellie.unitto.core.base.OutputFormat +import com.sadellie.unitto.data.common.format import com.sadellie.unitto.data.database.UnittoDatabase import com.sadellie.unitto.data.model.UnitGroup import com.sadellie.unitto.data.model.unit.DefaultUnit @@ -42,7 +42,7 @@ class AllUnitsTest { private var history: MutableMap> = mutableMapOf() private val mContext: Context = RuntimeEnvironment.getApplication().applicationContext private val database = Room.inMemoryDatabaseBuilder(mContext, UnittoDatabase::class.java).build() - private val allUnitsRepository = UnitsRepository( + private val allUnitsRepository = UnitsRepositoryImpl( unitsDao = database.unitsDao(), currencyRatesDao = database.currencyRatesDao(), mContext = mContext @@ -550,14 +550,10 @@ class AllUnitsTest { UnitGroup.NUMBER_BASE -> (unitFrom as NumberBaseUnit).convert((unitTo as NumberBaseUnit), value) UnitGroup.FLOW_RATE -> (unitFrom as ReverseUnit) .convert((unitTo as DefaultUnit), BigDecimal(value)) - .setMinimumRequiredScale(5) - .trimZeros() - .toPlainString() + .format(5, OutputFormat.PLAIN) else -> (unitFrom as DefaultUnit) .convert((unitTo as DefaultUnit), BigDecimal(value)) - .setMinimumRequiredScale(5) - .trimZeros() - .toPlainString() + .format(5, OutputFormat.PLAIN) } assertEquals("Failed at $this to $checkingId", expected, actual) println("PASSED: $this -> $expected == $actual") diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt index b4af4ef6..a8936a73 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorViewModel.kt @@ -29,11 +29,9 @@ import com.sadellie.unitto.core.ui.common.textfield.addBracket import com.sadellie.unitto.core.ui.common.textfield.addTokens import com.sadellie.unitto.core.ui.common.textfield.deleteTokens import com.sadellie.unitto.core.ui.common.textfield.getTextField +import com.sadellie.unitto.data.common.format import com.sadellie.unitto.data.common.isExpression -import com.sadellie.unitto.data.common.setMinimumRequiredScale import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.common.toStringWith -import com.sadellie.unitto.data.common.trimZeros import com.sadellie.unitto.data.model.repository.CalculatorHistoryRepository import com.sadellie.unitto.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel @@ -104,9 +102,7 @@ internal class CalculatorViewModel @Inject constructor( input = ui.input.text, radianMode = ui.radianMode, ) - .setMinimumRequiredScale(ui.precision) - .trimZeros() - .toStringWith(ui.outputFormat) + .format(ui.precision, ui.outputFormat) ) } catch (e: ExpressionException.DivideByZero) { CalculationResult.Empty @@ -198,10 +194,7 @@ internal class CalculatorViewModel @Inject constructor( _equalClicked.update { true } - val resultFormatted = result - .setMinimumRequiredScale(prefs.precision) - .trimZeros() - .toStringWith(prefs.outputFormat) + val resultFormatted = result.format(prefs.precision, prefs.outputFormat) withContext(Dispatchers.IO) { calculatorHistoryRepository.add( diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt index cd91c026..772900e3 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterUIState.kt @@ -24,6 +24,9 @@ import com.sadellie.unitto.core.base.R import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols import com.sadellie.unitto.core.ui.common.textfield.formatExpression +import com.sadellie.unitto.data.common.isEqualTo +import com.sadellie.unitto.data.common.isGreaterThan +import com.sadellie.unitto.data.common.isLessThan import com.sadellie.unitto.data.common.trimZeros import com.sadellie.unitto.data.model.unit.DefaultUnit import com.sadellie.unitto.data.model.unit.NumberBaseUnit @@ -62,7 +65,7 @@ internal sealed class ConverterResult { data class Default(val value: BigDecimal) : ConverterResult() { override fun equals(other: Any?): Boolean { if (other !is Default) return false - return this.value.compareTo(other.value) == 0 + return this.value.isEqualTo(other.value) } override fun hashCode(): Int = value.hashCode() @@ -90,35 +93,35 @@ internal sealed class ConverterResult { internal fun ConverterResult.Time.format(mContext: Context, formatterSymbols: FormatterSymbols): String { val result = mutableListOf() - if (day.compareTo(BigDecimal.ZERO) == 1) { + if (day.isGreaterThan(BigDecimal.ZERO)) { result += "${day.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_day_short)}" } - if (hour.compareTo(BigDecimal.ZERO) == 1) { + if (hour.isGreaterThan(BigDecimal.ZERO)) { result += "${hour.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_hour_short)}" } - if (minute.compareTo(BigDecimal.ZERO) == 1) { + if (minute.isGreaterThan(BigDecimal.ZERO)) { result += "${minute.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_minute_short)}" } - if (second.compareTo(BigDecimal.ZERO) == 1) { + if (second.isGreaterThan(BigDecimal.ZERO)) { result += "${second.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_second_short)}" } - if (millisecond.compareTo(BigDecimal.ZERO) == 1) { + if (millisecond.isGreaterThan(BigDecimal.ZERO)) { result += "${millisecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_millisecond_short)}" } - if (microsecond.compareTo(BigDecimal.ZERO) == 1) { + if (microsecond.isGreaterThan(BigDecimal.ZERO)) { result += "${microsecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_microsecond_short)}" } - if (nanosecond.compareTo(BigDecimal.ZERO) == 1) { + if (nanosecond.isGreaterThan(BigDecimal.ZERO)) { result += "${nanosecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_nanosecond_short)}" } - if (attosecond.compareTo(BigDecimal.ZERO) == 1) { + if (attosecond.isGreaterThan(BigDecimal.ZERO)) { result += "${attosecond.toPlainString().formatExpression(formatterSymbols)}${mContext.getString(R.string.unit_attosecond_short)}" } @@ -131,7 +134,7 @@ internal fun formatTime( val negative = input < BigDecimal.ZERO val inputAbs = input.abs() - if (inputAbs.compareTo(attosecondBasicUnit) == -1) return ConverterResult.Time( + if (inputAbs.isLessThan(attosecondBasicUnit)) return ConverterResult.Time( negative = negative, day = BigDecimal.ZERO, hour = BigDecimal.ZERO, @@ -143,7 +146,7 @@ internal fun formatTime( attosecond = inputAbs ) - if (inputAbs.compareTo(nanosecondBasicUnit) == -1) return ConverterResult.Time( + if (inputAbs.isLessThan(nanosecondBasicUnit)) return ConverterResult.Time( negative = negative, day = BigDecimal.ZERO, hour = BigDecimal.ZERO, diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt index f6d13b6a..7a66d743 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt @@ -24,10 +24,8 @@ import com.sadellie.unitto.core.base.MAX_PRECISION import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols import com.sadellie.unitto.core.ui.common.textfield.formatExpression -import com.sadellie.unitto.data.common.setMinimumRequiredScale +import com.sadellie.unitto.data.common.format import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.common.toStringWith -import com.sadellie.unitto.data.common.trimZeros import com.sadellie.unitto.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.MutableStateFlow @@ -78,9 +76,7 @@ class FormattingViewModel @Inject constructor( } return BigDecimal(bigD) - .setMinimumRequiredScale(precision) - .trimZeros() - .toStringWith(outputFormat) + .format(precision, outputFormat) .formatExpression(formatterSymbols) }