From eb96868afcbd77df18ea5c821bfc3f1ed7eee453 Mon Sep 17 00:00:00 2001 From: Sad Ellie Date: Wed, 28 Feb 2024 22:07:16 +0300 Subject: [PATCH] Refactor Converter - no longer abusing mapLatest and StateFlow - id-based system in UI and business layers --- .../sadellie/unitto/data/common/FlowUtils.kt | 71 --- data/converter/build.gradle.kts | 2 + .../data/converter/BatchConvertResult.kt} | 18 +- .../unitto/data/converter/ConverterResult.kt | 82 +++ .../unitto/data/converter/DataStoreModule.kt | 46 -- .../data/converter/UnitSearchResultItem.kt} | 45 +- .../data/converter/UnitsRepositoryImpl.kt | 570 +++++++++++++----- .../converter/collections/Acceleration.kt | 8 +- .../data/converter/collections/Angle.kt | 8 +- .../unitto/data/converter/collections/Area.kt | 8 +- .../data/converter/collections/Currency.kt | 424 ++++++------- .../unitto/data/converter/collections/Data.kt | 8 +- .../converter/collections/DataTransfer.kt | 8 +- .../collections/ElectrostaticCapacitance.kt | 8 +- .../data/converter/collections/Energy.kt | 8 +- .../data/converter/collections/FlowRate.kt | 50 +- .../unitto/data/converter/collections/Flux.kt | 8 +- .../data/converter/collections/Force.kt | 8 +- .../converter/collections/FuelConsumption.kt | 21 +- .../data/converter/collections/Length.kt | 9 +- .../data/converter/collections/Luminance.kt | 8 +- .../unitto/data/converter/collections/Mass.kt | 8 +- .../data/converter/collections/NumberBase.kt | 8 +- .../data/converter/collections/Power.kt | 8 +- .../data/converter/collections/Prefix.kt | 8 +- .../data/converter/collections/Pressure.kt | 8 +- .../data/converter/collections/Speed.kt | 17 +- .../data/converter/collections/Temperature.kt | 155 ++--- .../unitto/data/converter/collections/Time.kt | 8 +- .../data/converter/collections/Torque.kt | 8 +- .../data/converter/collections/Volume.kt | 8 +- .../unitto/data/converter/AllUnitsTest.kt | 15 +- .../data/converter/ConverterUIStateKtTest.kt | 247 ++++++++ .../unitto/data/database/CurrencyRatesDao.kt | 6 + .../unitto/data/database/UnitsEntity.kt | 2 +- .../data/model/{ => converter}/UnitGroup.kt | 2 +- .../model/{ => converter}/UnitsListSorting.kt | 2 +- .../data/model/converter/unit/BasicUnit.kt | 47 ++ .../unit/NormalUnit.kt} | 80 ++- .../model/converter/unit/NumberBaseUnit.kt | 34 ++ .../data/model/repository/UnitsRepository.kt | 50 -- .../repository/UserPreferencesRepository.kt | 7 +- .../unitto/data/model/unit/NormalUnit.kt | 79 --- .../unitto/data/model/unit/NumberBaseUnit.kt | 57 -- .../unitto/data/model/unit/ReverseUnit.kt | 63 -- .../unitto/data/model/unit/TemperatureUnit.kt | 56 -- .../model/userprefs/ConverterPreferences.kt | 4 +- .../model/userprefs/UnitGroupsPreferences.kt | 2 +- .../unitto/data/userprefs/PreferenceExt.kt | 4 +- .../unitto/data/userprefs/PreferenceModels.kt | 4 +- .../UserPreferencesRepositoryImpl.kt | 11 +- .../feature/converter/ConverterScreen.kt | 265 +++++--- .../feature/converter/ConverterUIState.kt | 158 +---- .../feature/converter/ConverterViewModel.kt | 467 +++++--------- .../converter/UnitFromSelectorScreen.kt | 46 +- .../converter/UnitFromSelectorViewModel.kt | 124 ++++ .../feature/converter/UnitSelectorUIState.kt | 27 +- .../feature/converter/UnitToSelectorScreen.kt | 97 +-- ...iewModel.kt => UnitToSelectorViewModel.kt} | 116 ++-- .../feature/converter/components/ChipsRow.kt | 2 +- .../converter/components/UnitGroupHeader.kt | 2 +- .../feature/converter/components/UnitsList.kt | 54 +- .../navigation/ConverterNavigation.kt | 64 +- .../converter/ConverterUIStateKtTest.kt | 134 ---- .../converter/ConverterSettingsScreen.kt | 4 +- .../converter/ConverterSettingsViewModel.kt | 2 +- .../settings/unitgroups/UnitGroupsScreen.kt | 2 +- .../settings/unitgroups/UnitGroupsUIState.kt | 2 +- .../unitgroups/UnitGroupsViewModel.kt | 2 +- 69 files changed, 1934 insertions(+), 2060 deletions(-) rename data/{model/src/main/java/com/sadellie/unitto/data/model/unit/DefaultUnit.kt => converter/src/main/java/com/sadellie/unitto/data/converter/BatchConvertResult.kt} (70%) create mode 100644 data/converter/src/main/java/com/sadellie/unitto/data/converter/ConverterResult.kt delete mode 100644 data/converter/src/main/java/com/sadellie/unitto/data/converter/DataStoreModule.kt rename data/{model/src/main/java/com/sadellie/unitto/data/model/unit/AbstractUnit.kt => converter/src/main/java/com/sadellie/unitto/data/converter/UnitSearchResultItem.kt} (77%) create mode 100644 data/converter/src/test/java/com/sadellie/unitto/data/converter/ConverterUIStateKtTest.kt rename data/model/src/main/java/com/sadellie/unitto/data/model/{ => converter}/UnitGroup.kt (97%) rename data/model/src/main/java/com/sadellie/unitto/data/model/{ => converter}/UnitsListSorting.kt (94%) create mode 100644 data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/BasicUnit.kt rename data/model/src/main/java/com/sadellie/unitto/data/model/{unit/BackwardUnit.kt => converter/unit/NormalUnit.kt} (50%) create mode 100644 data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/NumberBaseUnit.kt delete mode 100644 data/model/src/main/java/com/sadellie/unitto/data/model/repository/UnitsRepository.kt delete mode 100644 data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt delete mode 100644 data/model/src/main/java/com/sadellie/unitto/data/model/unit/NumberBaseUnit.kt delete mode 100644 data/model/src/main/java/com/sadellie/unitto/data/model/unit/ReverseUnit.kt delete mode 100644 data/model/src/main/java/com/sadellie/unitto/data/model/unit/TemperatureUnit.kt create mode 100644 feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitFromSelectorViewModel.kt rename feature/converter/src/main/java/com/sadellie/unitto/feature/converter/{UnitSelectorViewModel.kt => UnitToSelectorViewModel.kt} (51%) delete mode 100644 feature/converter/src/test/java/com/sadellie/unitto/feature/converter/ConverterUIStateKtTest.kt diff --git a/data/common/src/main/java/com/sadellie/unitto/data/common/FlowUtils.kt b/data/common/src/main/java/com/sadellie/unitto/data/common/FlowUtils.kt index f0702c5d..70383493 100644 --- a/data/common/src/main/java/com/sadellie/unitto/data/common/FlowUtils.kt +++ b/data/common/src/main/java/com/sadellie/unitto/data/common/FlowUtils.kt @@ -83,76 +83,5 @@ fun combine( ) } -@Suppress("UNCHECKED_CAST", "UNUSED") -fun combine( - flow: Flow, - flow2: Flow, - flow3: Flow, - flow4: Flow, - flow5: Flow, - flow6: Flow, - flow7: Flow, - flow8: Flow, - transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R, -): Flow = - kotlinx.coroutines.flow.combine( - flow, - flow2, - flow3, - flow4, - flow5, - flow6, - flow7, - flow8, - ) { args: Array<*> -> - transform( - args[0] as T1, - args[1] as T2, - args[2] as T3, - args[3] as T4, - args[4] as T5, - args[5] as T6, - args[6] as T7, - args[7] as T8, - ) - } - -@Suppress("UNCHECKED_CAST", "UNUSED") -fun combine( - flow: Flow, - flow2: Flow, - flow3: Flow, - flow4: Flow, - flow5: Flow, - flow6: Flow, - flow7: Flow, - flow8: Flow, - flow9: Flow, - transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R, -): Flow = - kotlinx.coroutines.flow.combine( - flow, - flow2, - flow3, - flow4, - flow5, - flow6, - flow7, - flow8, - flow9, - ) { args: Array<*> -> - transform( - args[0] as T1, - args[1] as T2, - args[2] as T3, - args[3] as T4, - args[4] as T5, - args[5] as T6, - args[6] as T7, - args[7] as T8, - args[8] as T9, - ) - } - fun Flow.stateIn(scope: CoroutineScope, initialValue: T): StateFlow = stateIn(scope, SharingStarted.WhileSubscribed(5000L), initialValue) diff --git a/data/converter/build.gradle.kts b/data/converter/build.gradle.kts index 43f19b5a..ce1ec0b4 100644 --- a/data/converter/build.gradle.kts +++ b/data/converter/build.gradle.kts @@ -35,11 +35,13 @@ android { } dependencies { + testImplementation(libs.org.robolectric.robolectric) implementation(libs.com.squareup.moshi.moshi.kotlin) implementation(libs.com.squareup.retrofit2.converter.moshi) implementation(project(":core:base")) implementation(project(":data:common")) implementation(project(":data:database")) + implementation(project(":data:evaluatto")) implementation(project(":data:model")) } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/DefaultUnit.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/BatchConvertResult.kt similarity index 70% rename from data/model/src/main/java/com/sadellie/unitto/data/model/unit/DefaultUnit.kt rename to data/converter/src/main/java/com/sadellie/unitto/data/converter/BatchConvertResult.kt index 9a8b0c48..2f37e38b 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/DefaultUnit.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/BatchConvertResult.kt @@ -1,6 +1,6 @@ /* * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev + * Copyright (c) 2024 Elshan Agaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,10 +16,18 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.unit +package com.sadellie.unitto.data.converter import java.math.BigDecimal -interface DefaultUnit : AbstractUnit { - fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal -} +interface BatchConvertResult + +@JvmInline +value class DefaultBatchConvertResult( + val value: BigDecimal, +) : BatchConvertResult + +@JvmInline +value class NumberBaseBatchConvertResult( + val value: String, +) : BatchConvertResult diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/ConverterResult.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/ConverterResult.kt new file mode 100644 index 00000000..578007e4 --- /dev/null +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/ConverterResult.kt @@ -0,0 +1,82 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.data.converter + +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import java.math.BigDecimal + +sealed class ConverterResult { + + sealed class Error : ConverterResult() { + data object Currency : Error() + + data object BadInput : Error() + + data object ConversionError : Error() + + data object DivideByZero : Error() + } + + data class Default( + val value: BigDecimal, + val calculation: BigDecimal, + ) : ConverterResult() + + data class NumberBase(val value: String) : ConverterResult() + + data class Time( + val negative: Boolean = false, + val day: BigDecimal = BigDecimal.ZERO, + val hour: BigDecimal = BigDecimal.ZERO, + val minute: BigDecimal = BigDecimal.ZERO, + val second: BigDecimal = BigDecimal.ZERO, + val millisecond: BigDecimal = BigDecimal.ZERO, + val microsecond: BigDecimal = BigDecimal.ZERO, + val nanosecond: BigDecimal = BigDecimal.ZERO, + val attosecond: BigDecimal = BigDecimal.ZERO, + ) : ConverterResult() + + data class FootInch( + val foot: BigDecimal, + val inch: BigDecimal, + ) : ConverterResult() { + companion object { + /** + * Creates an object for displaying formatted foot and inch output. Units are passed as objects so + * that changes in basic units don't require modifying the method. Also this method can't access + * units repository directly. + * + * @param input Input in feet. + * @param footUnit Foot unit [BasicUnit.Default]. + * @param inchUnit Inch unit [BasicUnit.Default]. + * @return Result where decimal places are converter into inches. + */ + fun fromBigDecimal( + input: BigDecimal, + footUnit: BasicUnit.Default, + inchUnit: BasicUnit.Default, + ): FootInch { + val (integral, fractional) = input.divideAndRemainder(BigDecimal.ONE) + return FootInch(integral, footUnit.convert(inchUnit, fractional)) + } + } + } + + data object Loading : ConverterResult() +} diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/DataStoreModule.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/DataStoreModule.kt deleted file mode 100644 index 2bd8d9cc..00000000 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/DataStoreModule.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.converter - -import android.content.Context -import com.sadellie.unitto.data.database.CurrencyRatesDao -import com.sadellie.unitto.data.database.UnitsDao -import com.sadellie.unitto.data.model.repository.UnitsRepository -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent - -@Module -@InstallIn(SingletonComponent::class) -class DataStoreModule { - @Provides - fun provideUnitsRepository( - unitsDao: UnitsDao, - currencyRatesDao: CurrencyRatesDao, - @ApplicationContext appContext: Context, - ): UnitsRepository { - return UnitsRepositoryImpl( - unitsDao = unitsDao, - currencyRatesDao = currencyRatesDao, - mContext = appContext, - ) - } -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/AbstractUnit.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitSearchResultItem.kt similarity index 77% rename from data/model/src/main/java/com/sadellie/unitto/data/model/unit/AbstractUnit.kt rename to data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitSearchResultItem.kt index a752aaa8..1b85aab1 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/AbstractUnit.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitSearchResultItem.kt @@ -1,6 +1,6 @@ /* * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev + * Copyright (c) 2024 Elshan Agaev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,45 +16,32 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.unit +package com.sadellie.unitto.data.converter import android.content.Context import com.sadellie.unitto.data.common.lev import com.sadellie.unitto.data.common.normalizeSuperscript -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal +import com.sadellie.unitto.data.database.UnitsEntity +import com.sadellie.unitto.data.model.converter.unit.BasicUnit -interface AbstractUnit { - val id: String - val basicUnit: BigDecimal - val group: UnitGroup - val displayName: Int - val shortName: Int - val isFavorite: Boolean - val pairId: String? - val counter: Int +data class UnitSearchResultItem( + val basicUnit: BasicUnit, + val stats: UnitsEntity, + val conversion: BatchConvertResult?, +) - fun clone( - id: String = this.id, - basicUnit: BigDecimal = this.basicUnit, - group: UnitGroup = this.group, - displayName: Int = this.displayName, - shortName: Int = this.shortName, - isFavorite: Boolean = this.isFavorite, - pairId: String? = this.pairId, - counter: Int = this.counter, - ): AbstractUnit -} - -fun Sequence.filterByLev(stringA: String, context: Context): Sequence { +fun Sequence.filterByLev( + stringA: String, + context: Context, +): Sequence { val stringToCompare = stringA.trim().lowercase() // We don't need units where name is too different, half of the symbols is wrong in this situation val threshold: Int = stringToCompare.length / 2 // List of pair: Unit and it's levDist - val unitsWithDist = mutableListOf>() + val unitsWithDist = mutableListOf>() this.forEach { unit -> val unitShortName: String = context - .getString(unit.shortName) + .getString(unit.basicUnit.shortName) .lowercase() .normalizeSuperscript() /** @@ -67,7 +54,7 @@ fun Sequence.filterByLev(stringA: String, context: Context): Seque } val unitFullName: String = context - .getString(unit.displayName) + .getString(unit.basicUnit.displayName) .lowercase() .normalizeSuperscript() diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitsRepositoryImpl.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitsRepositoryImpl.kt index 9b2a6930..3f28b144 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitsRepositoryImpl.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/UnitsRepositoryImpl.kt @@ -20,6 +20,10 @@ package com.sadellie.unitto.data.converter import android.content.Context import android.util.Log +import com.sadellie.unitto.core.base.Token +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.converter.collections.accelerationCollection import com.sadellie.unitto.data.converter.collections.angleCollection import com.sadellie.unitto.data.converter.collections.areaCollection @@ -49,22 +53,16 @@ import com.sadellie.unitto.data.database.CurrencyRatesDao import com.sadellie.unitto.data.database.CurrencyRatesEntity import com.sadellie.unitto.data.database.UnitsDao import com.sadellie.unitto.data.database.UnitsEntity -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.repository.UnitsRepository -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.ReverseUnit -import com.sadellie.unitto.data.model.unit.filterByLev +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting +import com.sadellie.unitto.data.model.converter.unit.BasicUnit import dagger.hilt.android.qualifiers.ApplicationContext +import io.github.sadellie.evaluatto.Expression +import io.github.sadellie.evaluatto.ExpressionException import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.flowOn -import kotlinx.coroutines.flow.update import kotlinx.coroutines.withContext import java.math.BigDecimal +import java.math.RoundingMode import java.time.LocalDate import javax.inject.Inject @@ -72,87 +70,58 @@ class UnitsRepositoryImpl @Inject constructor( private val unitsDao: UnitsDao, private val currencyRatesDao: CurrencyRatesDao, @ApplicationContext private val mContext: Context, -) : UnitsRepository { - private val inMemoryUnits = MutableStateFlow( - lengthCollection + - currencyCollection + - massCollection + - speedCollection + - temperatureCollection + - areaCollection + - timeCollection + - volumeCollection + - dataCollection + - pressureCollection + - accelerationCollection + - energyCollection + - powerCollection + - angleCollection + - dataTransferCollection + - fluxCollection + - numberBaseCollection + - electrostaticCapacitance + - prefixCollection + - forceCollection + - torqueCollection + - flowRateCollection + - luminanceCollection + - fuelConsumptionCollection, - ) +) { + private val inMemory = lengthCollection + + currencyCollection + + massCollection + + speedCollection + + temperatureCollection + + areaCollection + + timeCollection + + volumeCollection + + dataCollection + + pressureCollection + + accelerationCollection + + energyCollection + + powerCollection + + angleCollection + + dataTransferCollection + + fluxCollection + + numberBaseCollection + + electrostaticCapacitance + + prefixCollection + + forceCollection + + torqueCollection + + flowRateCollection + + luminanceCollection + + fuelConsumptionCollection - override val units: Flow> = combine( - unitsDao.getAllFlow(), - inMemoryUnits, - ) { basedList, inMemoryList -> - return@combine inMemoryList.map { inMemoryUnit -> - val inBaseUnit = basedList.find { it.unitId == inMemoryUnit.id } - ?: return@map inMemoryUnit - inMemoryUnit.clone( - isFavorite = inBaseUnit.isFavorite, - counter = inBaseUnit.frequency, - pairId = inBaseUnit.pairedUnitId, - ) - } - } - .flowOn(Dispatchers.IO) - - override suspend fun getById(id: String): AbstractUnit { - return units.first().first { it.id == id } + suspend fun getById(id: String): BasicUnit = withContext(Dispatchers.Default) { + return@withContext inMemory.first { it.id == id } } - override suspend fun getCollection(group: UnitGroup): List { - return units.first().filter { it.group == group } + suspend fun getPairId(id: String): String = withContext(Dispatchers.IO) { + val basedUnitPair = getUnitStats(id).pairedUnitId + if (basedUnitPair != null) return@withContext basedUnitPair + + val inMemoryUnit = inMemory.first { it.id == id } + val collection = inMemory.filter { it.group == inMemoryUnit.group } + + val pair = collection + .map { getById(it.id) to getUnitStats(it.id) } + .sortedByDescending { it.second.frequency } + .firstOrNull { it.second.isFavorite }?.first ?: collection.first() + + return@withContext pair.id } - override suspend fun favorite(unit: AbstractUnit) = withContext(Dispatchers.IO) { - val basedUnit = unitsDao.getById(unit.id) + suspend fun incrementCounter(id: String) = withContext(Dispatchers.IO) { + val basedUnit = unitsDao.getById(id) if (basedUnit == null) { unitsDao.insertUnit( UnitsEntity( - unitId = unit.id, - isFavorite = true, - ), - ) - } else { - unitsDao.insertUnit( - UnitsEntity( - unitId = basedUnit.unitId, - isFavorite = !basedUnit.isFavorite, - pairedUnitId = basedUnit.pairedUnitId, - frequency = basedUnit.frequency, - ), - ) - } - } - - override suspend fun incrementCounter(unit: AbstractUnit) = withContext(Dispatchers.IO) { - val basedUnit = unitsDao.getById(unit.id) - - if (basedUnit == null) { - unitsDao.insertUnit( - UnitsEntity( - unitId = unit.id, + unitId = id, frequency = 1, ), ) @@ -168,14 +137,17 @@ class UnitsRepositoryImpl @Inject constructor( } } - override suspend fun setPair(unit: AbstractUnit, pair: AbstractUnit) = withContext(Dispatchers.IO) { - val basedUnit = unitsDao.getById(unit.id) + suspend fun setPair( + id: String, + pairId: String, + ) = withContext(Dispatchers.IO) { + val basedUnit = unitsDao.getById(id) if (basedUnit == null) { unitsDao.insertUnit( UnitsEntity( - unitId = unit.id, - pairedUnitId = pair.id, + unitId = id, + pairedUnitId = pairId, ), ) } else { @@ -183,95 +155,375 @@ class UnitsRepositoryImpl @Inject constructor( UnitsEntity( unitId = basedUnit.unitId, isFavorite = basedUnit.isFavorite, - pairedUnitId = pair.id, + pairedUnitId = pairId, frequency = basedUnit.frequency, ), ) } } - override suspend fun updateRates(unit: AbstractUnit): LocalDate? = withContext(Dispatchers.IO) { - var basedConversions = currencyRatesDao.getLatestRates(baseId = unit.id) - val epochDay = LocalDate.now().toEpochDay() + suspend fun favorite(id: String) = withContext(Dispatchers.IO) { + val basedUnit = unitsDao.getById(id) - if (basedConversions.firstOrNull()?.date != epochDay) { + if (basedUnit == null) { + unitsDao.insertUnit( + UnitsEntity( + unitId = id, + isFavorite = true, + ), + ) + } else { + unitsDao.insertUnit( + UnitsEntity( + unitId = basedUnit.unitId, + isFavorite = !basedUnit.isFavorite, + pairedUnitId = basedUnit.pairedUnitId, + frequency = basedUnit.frequency, + ), + ) + } + } + + suspend fun filterUnits( + query: String, + unitGroups: List, + favoritesOnly: Boolean, + sorting: UnitsListSorting, + ): Map> = withContext(Dispatchers.IO) { + return@withContext filterUnitCollections( + query = query, + unitGroups = unitGroups, + favoritesOnly = favoritesOnly, + sorting = sorting, + ) + .groupBy { it.basicUnit.group } + } + + suspend fun filterUnitsAndBatchConvert( + query: String, + unitGroup: UnitGroup, + favoritesOnly: Boolean, + sorting: UnitsListSorting, + unitFromId: String, + input: String?, + ): Map> = withContext(Dispatchers.IO) { + val units = filterUnitCollections( + query = query, + unitGroups = listOf(unitGroup), + favoritesOnly = favoritesOnly, + sorting = sorting, + ) + + if (input == null) { + return@withContext units.groupBy { it.basicUnit.group } + } + + val unitWithConversions = try { + when (unitGroup) { + UnitGroup.CURRENCY -> { + val inputBD = BigDecimal(input) + + val validCurrencyPairs = withContext(Dispatchers.IO) { + currencyRatesDao.getLatestRates(unitFromId) + } + .filter { it.pairUnitValue?.isGreaterThan(BigDecimal.ZERO) ?: false } + + val validIds = validCurrencyPairs.map { it.pairUnitId } + + units + .filter { it.basicUnit.id in validIds } + .map { unitTo -> + unitTo.basicUnit as BasicUnit.Default + val factor = validCurrencyPairs + .first { it.pairUnitId == unitTo.basicUnit.id } + .pairUnitValue + val conversion = inputBD.multiply(factor) + + unitTo.copy( + conversion = DefaultBatchConvertResult(conversion), + ) + } + } + + UnitGroup.NUMBER_BASE -> { + val unitFrom = getById(unitFromId) as BasicUnit.NumberBase + + units.map { unitTo -> + unitTo.basicUnit as BasicUnit.NumberBase + val conversion = unitFrom.convert(unitTo.basicUnit, input) + + unitTo.copy( + conversion = NumberBaseBatchConvertResult(conversion), + ) + } + } + + else -> { + val unitFrom = getById(unitFromId) as BasicUnit.Default + val inputBD = BigDecimal(input) + + units.map { unitTo -> + unitTo.basicUnit as BasicUnit.Default + val conversion = unitFrom.convert(unitTo.basicUnit, inputBD) + + unitTo.copy( + conversion = DefaultBatchConvertResult(conversion), + ) + } + } + } + } catch (e: Exception) { + Log.e("UnitsRepositoryImpl", "Failed to batch convert: $e") + units + } + + return@withContext unitWithConversions.groupBy { it.basicUnit.group } + } + + suspend fun convertDefault( + unitFromId: String, + unitToId: String, + value1: String, + value2: String, + formatTime: Boolean, + ): ConverterResult = withContext(Dispatchers.Default) { + val calculated: BigDecimal = try { + // Calculate expression in first text field + var calculated1 = Expression(value1.ifEmpty { Token.Digit._0 }).calculate() + + // Calculate expression in second text field + if (unitFromId == UnitID.foot) { + val calculatedInches = Expression(value2.ifEmpty { Token.Digit._0 }).calculate() + // turn inches into feet so that it all comes down to converting from feet only + val inches = getById(UnitID.inch) as BasicUnit.Default + val feet = getById(UnitID.foot) as BasicUnit.Default + val inchesConvertedToFeet = inches.convert(feet, calculatedInches) + + calculated1 += inchesConvertedToFeet + } + + calculated1 + } catch (e: ExpressionException.DivideByZero) { + return@withContext ConverterResult.Error.DivideByZero + } catch (e: Exception) { + return@withContext ConverterResult.Error.BadInput + } + + return@withContext try { + val unitFrom = getById(unitFromId) as BasicUnit.Default + val unitTo = getById(unitToId) as BasicUnit.Default + + when { + (unitFrom.group == UnitGroup.TIME) and (formatTime) -> + convertTime(unitFrom, calculated) + + unitTo.id == UnitID.foot -> + convertToFoot(unitFrom, unitTo, calculated) + + unitFrom.group == UnitGroup.CURRENCY -> + convertCurrencies(unitFromId, unitToId, calculated) + + else -> + convertDefault(unitFrom, unitTo, calculated) + } + } catch (e: Exception) { + ConverterResult.Error.ConversionError + } + } + + suspend fun convertNumberBase( + unitFromId: String, + unitToId: String, + value: String, + ): ConverterResult = withContext(Dispatchers.Default) { + return@withContext try { + val unitFrom = getById(unitFromId) as BasicUnit.NumberBase + val unitTo = getById(unitToId) as BasicUnit.NumberBase + val conversion = unitFrom.convert(unitTo, value) + + ConverterResult.NumberBase(conversion) + } catch (e: Exception) { + ConverterResult.Error.ConversionError + } + } + + private suspend fun getUnitStats(id: String): UnitsEntity = withContext(Dispatchers.IO) { + unitsDao.getById(id) ?: UnitsEntity(unitId = id) + } + + private fun convertDefault( + unitFrom: BasicUnit.Default, + unitTo: BasicUnit.Default, + value: BigDecimal, + ): ConverterResult.Default = ConverterResult.Default(unitFrom.convert(unitTo, value), value) + + internal fun convertTime( + unitFrom: BasicUnit.Default, + value: BigDecimal, + ): ConverterResult.Time { + val input = value.multiply(unitFrom.factor) + + val negative = input < BigDecimal.ZERO + val inputAbs = input.abs() + + if (inputAbs.isLessThan(attosecondBasicUnit)) { + return ConverterResult.Time( + negative = negative, + day = BigDecimal.ZERO, + hour = BigDecimal.ZERO, + minute = BigDecimal.ZERO, + second = BigDecimal.ZERO, + millisecond = BigDecimal.ZERO, + microsecond = BigDecimal.ZERO, + nanosecond = BigDecimal.ZERO, + attosecond = inputAbs, + ) + } + + if (inputAbs.isLessThan(nanosecondBasicUnit)) { + return ConverterResult.Time( + negative = negative, + day = BigDecimal.ZERO, + hour = BigDecimal.ZERO, + minute = BigDecimal.ZERO, + second = BigDecimal.ZERO, + millisecond = BigDecimal.ZERO, + microsecond = BigDecimal.ZERO, + nanosecond = BigDecimal.ZERO, + attosecond = inputAbs.trimZeros(), + ) + } + + // DAY + var division = inputAbs.divideAndRemainder(dayBasicUnit) + val day = division.component1().setScale(0, RoundingMode.HALF_EVEN) + var remainingSeconds = division.component2().setScale(0, RoundingMode.HALF_EVEN) + + division = remainingSeconds.divideAndRemainder(hourBasicUnit) + val hour = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(minuteBasicUnit) + val minute = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(secondBasicUnit) + val second = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(millisecondBasicUnit) + val millisecond = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(microsecondBasicUnit) + val microsecond = division.component1() + remainingSeconds = division.component2() + + division = remainingSeconds.divideAndRemainder(nanosecondBasicUnit) + val nanosecond = division.component1() + remainingSeconds = division.component2() + + val attosecond = remainingSeconds + + return ConverterResult.Time( + negative = negative, + day = day, + hour = hour, + minute = minute, + second = second, + millisecond = millisecond, + microsecond = microsecond, + nanosecond = nanosecond, + attosecond = attosecond, + ) + } + + private suspend fun convertToFoot( + unitFrom: BasicUnit.Default, + unitTo: BasicUnit.Default, + value: BigDecimal, + ): ConverterResult.FootInch = ConverterResult.FootInch.fromBigDecimal( + input = unitFrom.convert(unitTo, value), + footUnit = unitTo, + inchUnit = getById(UnitID.inch) as BasicUnit.Default, + ) + + private suspend fun convertCurrencies( + unitFromId: String, + unitToId: String, + value: BigDecimal, + ): ConverterResult = withContext(Dispatchers.IO) { + refreshCurrencyRates(unitFromId) + + val latestRate = currencyRatesDao.getLatestRate(unitFromId, unitToId) + if (latestRate?.pairUnitValue == null) return@withContext ConverterResult.Error.Currency + + val conversion = value.multiply(latestRate.pairUnitValue) + + return@withContext ConverterResult.Default(conversion, value) + } + + private suspend fun filterUnitCollections( + query: String, + unitGroups: List, + favoritesOnly: Boolean, + sorting: UnitsListSorting, + ): Sequence = withContext(Dispatchers.IO) { + var units = inMemory + .filter { it.group in unitGroups } + .map { UnitSearchResultItem(it, getUnitStats(it.id), null) } + .asSequence() + + if (favoritesOnly) { + units = units.filter { it.stats.isFavorite } + } + + units = when (sorting) { + UnitsListSorting.USAGE -> units.sortedByDescending { it.stats.frequency } + UnitsListSorting.ALPHABETICAL -> units.sortedBy { mContext.getString(it.basicUnit.displayName) } + UnitsListSorting.SCALE_ASC -> units.sortedBy { it.basicUnit.factor } + UnitsListSorting.SCALE_DESC -> units.sortedByDescending { it.basicUnit.factor } + else -> units + } + + units = if (query.isEmpty()) { + units.sortedByDescending { it.stats.isFavorite } + } else { + units.filterByLev(query, mContext) + } + return@withContext units + } + + private suspend fun refreshCurrencyRates(unitFromId: String) = withContext(Dispatchers.IO) { + val latestUpdateDate = currencyRatesDao.getLatestRateTimeStamp(unitFromId) + val currentDate = LocalDate.now().toEpochDay() + + if (latestUpdateDate != currentDate) { + // Need to update cache needed try { - val conversions = CurrencyApi.service.getCurrencyPairs(unit.id) + val conversions = CurrencyApi.service.getCurrencyPairs(unitFromId) val rates = conversions.currency .map { (pairId, pairValue) -> CurrencyRatesEntity( - baseUnitId = unit.id, - date = epochDay, + baseUnitId = unitFromId, + date = currentDate, pairUnitId = pairId, pairUnitValue = BigDecimal.valueOf(pairValue), ) } currencyRatesDao.insertRates(rates) - - basedConversions = currencyRatesDao.getLatestRates(baseId = unit.id) } catch (e: Exception) { - Log.d("UnitsRepository", "Skipped update: $e") + Log.d("UnitsRepositoryImpl", "Skipped update: $e") } } - inMemoryUnits.update { units -> - units.map { localUnit -> - if (localUnit.group != UnitGroup.CURRENCY) return@map localUnit - if (localUnit !is ReverseUnit) return@map localUnit - - val rate = basedConversions - .firstOrNull { localUnit.id == it.pairUnitId } - ?.pairUnitValue ?: BigDecimal.ZERO - - return@map if (rate > BigDecimal.ZERO) { - localUnit.copy(basicUnit = rate) - } else { - localUnit.copy(basicUnit = BigDecimal.ZERO) - } - } - } - - return@withContext basedConversions - .firstOrNull() - ?.date - ?.let { LocalDate.ofEpochDay(it) } - } - - override suspend fun filterUnits( - query: String, - unitGroup: UnitGroup?, - favoritesOnly: Boolean, - hideBrokenUnits: Boolean, - sorting: UnitsListSorting, - shownUnitGroups: List, - ): Map> { - // Leave only shown unit groups - var units: Sequence = if (unitGroup == null) { - units.first().filter { it.group in shownUnitGroups } - } else { - getCollection(unitGroup) - }.asSequence() - - if (favoritesOnly) { - units = units.filter { it.isFavorite } - } - if (hideBrokenUnits) { - units = units.filter { it.basicUnit > BigDecimal.ZERO } - } - - units = when (sorting) { - UnitsListSorting.USAGE -> units.sortedByDescending { it.counter } - UnitsListSorting.ALPHABETICAL -> units.sortedBy { mContext.getString(it.displayName) } - UnitsListSorting.SCALE_ASC -> units.sortedBy { it.basicUnit } - UnitsListSorting.SCALE_DESC -> units.sortedByDescending { it.basicUnit } - else -> units - } - - units = if (query.isEmpty()) { - units.sortedByDescending { it.isFavorite } - } else { - // For search we sort by popularity and Levenshtein distance (short and long name). - units.filterByLev(query, mContext) - } - return units.groupBy { it.group } } } + +private val dayBasicUnit by lazy { BigDecimal("86400000000000000000000") } +private val hourBasicUnit by lazy { BigDecimal("3600000000000000000000") } +private val minuteBasicUnit by lazy { BigDecimal("60000000000000000000") } +private val secondBasicUnit by lazy { BigDecimal("1000000000000000000") } +private val millisecondBasicUnit by lazy { BigDecimal("1000000000000000") } +private val microsecondBasicUnit by lazy { BigDecimal("1000000000000") } +private val nanosecondBasicUnit by lazy { BigDecimal("1000000000") } +private val attosecondBasicUnit by lazy { BigDecimal("1") } diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Acceleration.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Acceleration.kt index 0b79419a..c98da758 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Acceleration.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Acceleration.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val accelerationCollection: List by lazy { +internal val accelerationCollection: List by lazy { listOf( NormalUnit(UnitID.attometer_per_square_second, BigDecimal("1"), UnitGroup.ACCELERATION, R.string.unit_attometer_per_square_second, R.string.unit_attometer_per_square_second_short), NormalUnit(UnitID.femtometer_per_square_second, BigDecimal("1000"), UnitGroup.ACCELERATION, R.string.unit_femtometer_per_square_second, R.string.unit_femtometer_per_square_second_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Angle.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Angle.kt index caa436ea..11cdf82e 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Angle.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Angle.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val angleCollection: List by lazy { +internal val angleCollection: List by lazy { listOf( NormalUnit(UnitID.angle_second, BigDecimal("1"), UnitGroup.ANGLE, R.string.unit_angle_second, R.string.unit_angle_second_short), NormalUnit(UnitID.angle_minute, BigDecimal("60"), UnitGroup.ANGLE, R.string.unit_angle_minute, R.string.unit_angle_minute_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Area.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Area.kt index 19aee8df..cdc9470e 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Area.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Area.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val areaCollection: List by lazy { +internal val areaCollection: List by lazy { listOf( NormalUnit(UnitID.cent, BigDecimal("6083246572000000000000000000000000"), UnitGroup.AREA, R.string.unit_cent, R.string.unit_cent_short), NormalUnit(UnitID.acre, BigDecimal("60832465720000000000000000000000"), UnitGroup.AREA, R.string.unit_acre, R.string.unit_acre_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Currency.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Currency.kt index d49bb180..90665b80 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Currency.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Currency.kt @@ -19,221 +19,221 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.ReverseUnit import com.sadellie.unitto.data.converter.UnitID +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val currencyCollection: List by lazy { +internal val currencyCollection: List by lazy { listOf( - ReverseUnit(UnitID.currency_1inch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_1inch, R.string.unit_currency_1inch_short), - ReverseUnit(UnitID.currency_ada, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ada, R.string.unit_currency_ada_short), - ReverseUnit(UnitID.currency_aed, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aed, R.string.unit_currency_aed_short), - ReverseUnit(UnitID.currency_afn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_afn, R.string.unit_currency_afn_short), - ReverseUnit(UnitID.currency_algo, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_algo, R.string.unit_currency_algo_short), - ReverseUnit(UnitID.currency_all, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_all, R.string.unit_currency_all_short), - ReverseUnit(UnitID.currency_amd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_amd, R.string.unit_currency_amd_short), - ReverseUnit(UnitID.currency_ang, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ang, R.string.unit_currency_ang_short), - ReverseUnit(UnitID.currency_aoa, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aoa, R.string.unit_currency_aoa_short), - ReverseUnit(UnitID.currency_ars, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ars, R.string.unit_currency_ars_short), - ReverseUnit(UnitID.currency_atom, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_atom, R.string.unit_currency_atom_short), - ReverseUnit(UnitID.currency_aud, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aud, R.string.unit_currency_aud_short), - ReverseUnit(UnitID.currency_avax, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_avax, R.string.unit_currency_avax_short), - ReverseUnit(UnitID.currency_awg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_awg, R.string.unit_currency_awg_short), - ReverseUnit(UnitID.currency_azn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_azn, R.string.unit_currency_azn_short), - ReverseUnit(UnitID.currency_bam, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bam, R.string.unit_currency_bam_short), - ReverseUnit(UnitID.currency_bbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bbd, R.string.unit_currency_bbd_short), - ReverseUnit(UnitID.currency_bch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bch, R.string.unit_currency_bch_short), - ReverseUnit(UnitID.currency_bdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bdt, R.string.unit_currency_bdt_short), - ReverseUnit(UnitID.currency_bgn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bgn, R.string.unit_currency_bgn_short), - ReverseUnit(UnitID.currency_bhd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bhd, R.string.unit_currency_bhd_short), - ReverseUnit(UnitID.currency_bif, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bif, R.string.unit_currency_bif_short), - ReverseUnit(UnitID.currency_bmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bmd, R.string.unit_currency_bmd_short), - ReverseUnit(UnitID.currency_bnb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnb, R.string.unit_currency_bnb_short), - ReverseUnit(UnitID.currency_bnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnd, R.string.unit_currency_bnd_short), - ReverseUnit(UnitID.currency_bob, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bob, R.string.unit_currency_bob_short), - ReverseUnit(UnitID.currency_brl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_brl, R.string.unit_currency_brl_short), - ReverseUnit(UnitID.currency_bsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bsd, R.string.unit_currency_bsd_short), - ReverseUnit(UnitID.currency_btc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btc, R.string.unit_currency_btc_short), - ReverseUnit(UnitID.currency_btn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btn, R.string.unit_currency_btn_short), - ReverseUnit(UnitID.currency_busd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_busd, R.string.unit_currency_busd_short), - ReverseUnit(UnitID.currency_bwp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bwp, R.string.unit_currency_bwp_short), - ReverseUnit(UnitID.currency_byn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byn, R.string.unit_currency_byn_short), - ReverseUnit(UnitID.currency_byr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byr, R.string.unit_currency_byr_short), - ReverseUnit(UnitID.currency_bzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bzd, R.string.unit_currency_bzd_short), - ReverseUnit(UnitID.currency_cad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cad, R.string.unit_currency_cad_short), - ReverseUnit(UnitID.currency_cdf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cdf, R.string.unit_currency_cdf_short), - ReverseUnit(UnitID.currency_chf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chf, R.string.unit_currency_chf_short), - ReverseUnit(UnitID.currency_chz, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chz, R.string.unit_currency_chz_short), - ReverseUnit(UnitID.currency_clf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clf, R.string.unit_currency_clf_short), - ReverseUnit(UnitID.currency_clp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clp, R.string.unit_currency_clp_short), - ReverseUnit(UnitID.currency_cny, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cny, R.string.unit_currency_cny_short), - ReverseUnit(UnitID.currency_cop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cop, R.string.unit_currency_cop_short), - ReverseUnit(UnitID.currency_crc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_crc, R.string.unit_currency_crc_short), - ReverseUnit(UnitID.currency_cro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cro, R.string.unit_currency_cro_short), - ReverseUnit(UnitID.currency_cuc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cuc, R.string.unit_currency_cuc_short), - ReverseUnit(UnitID.currency_cup, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cup, R.string.unit_currency_cup_short), - ReverseUnit(UnitID.currency_cve, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cve, R.string.unit_currency_cve_short), - ReverseUnit(UnitID.currency_czk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_czk, R.string.unit_currency_czk_short), - ReverseUnit(UnitID.currency_dai, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dai, R.string.unit_currency_dai_short), - ReverseUnit(UnitID.currency_djf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_djf, R.string.unit_currency_djf_short), - ReverseUnit(UnitID.currency_dkk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dkk, R.string.unit_currency_dkk_short), - ReverseUnit(UnitID.currency_doge, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_doge, R.string.unit_currency_doge_short), - ReverseUnit(UnitID.currency_dop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dop, R.string.unit_currency_dop_short), - ReverseUnit(UnitID.currency_dot, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dot, R.string.unit_currency_dot_short), - ReverseUnit(UnitID.currency_dzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dzd, R.string.unit_currency_dzd_short), - ReverseUnit(UnitID.currency_egld, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egld, R.string.unit_currency_egld_short), - ReverseUnit(UnitID.currency_egp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egp, R.string.unit_currency_egp_short), - ReverseUnit(UnitID.currency_enj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_enj, R.string.unit_currency_enj_short), - ReverseUnit(UnitID.currency_ern, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ern, R.string.unit_currency_ern_short), - ReverseUnit(UnitID.currency_etb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etb, R.string.unit_currency_etb_short), - ReverseUnit(UnitID.currency_etc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etc, R.string.unit_currency_etc_short), - ReverseUnit(UnitID.currency_eth, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eth, R.string.unit_currency_eth_short), - ReverseUnit(UnitID.currency_eur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eur, R.string.unit_currency_eur_short), - ReverseUnit(UnitID.currency_fil, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fil, R.string.unit_currency_fil_short), - ReverseUnit(UnitID.currency_fjd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fjd, R.string.unit_currency_fjd_short), - ReverseUnit(UnitID.currency_fkp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fkp, R.string.unit_currency_fkp_short), - ReverseUnit(UnitID.currency_ftt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ftt, R.string.unit_currency_ftt_short), - ReverseUnit(UnitID.currency_gbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gbp, R.string.unit_currency_gbp_short), - ReverseUnit(UnitID.currency_gel, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gel, R.string.unit_currency_gel_short), - ReverseUnit(UnitID.currency_ggp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ggp, R.string.unit_currency_ggp_short), - ReverseUnit(UnitID.currency_ghs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ghs, R.string.unit_currency_ghs_short), - ReverseUnit(UnitID.currency_gip, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gip, R.string.unit_currency_gip_short), - ReverseUnit(UnitID.currency_gmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gmd, R.string.unit_currency_gmd_short), - ReverseUnit(UnitID.currency_gnf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gnf, R.string.unit_currency_gnf_short), - ReverseUnit(UnitID.currency_grt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_grt, R.string.unit_currency_grt_short), - ReverseUnit(UnitID.currency_gtq, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gtq, R.string.unit_currency_gtq_short), - ReverseUnit(UnitID.currency_gyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gyd, R.string.unit_currency_gyd_short), - ReverseUnit(UnitID.currency_hkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hkd, R.string.unit_currency_hkd_short), - ReverseUnit(UnitID.currency_hnl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hnl, R.string.unit_currency_hnl_short), - ReverseUnit(UnitID.currency_hrk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hrk, R.string.unit_currency_hrk_short), - ReverseUnit(UnitID.currency_htg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_htg, R.string.unit_currency_htg_short), - ReverseUnit(UnitID.currency_huf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_huf, R.string.unit_currency_huf_short), - ReverseUnit(UnitID.currency_icp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_icp, R.string.unit_currency_icp_short), - ReverseUnit(UnitID.currency_idr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_idr, R.string.unit_currency_idr_short), - ReverseUnit(UnitID.currency_ils, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ils, R.string.unit_currency_ils_short), - ReverseUnit(UnitID.currency_imp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_imp, R.string.unit_currency_imp_short), - ReverseUnit(UnitID.currency_inj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inj, R.string.unit_currency_inj_short), - ReverseUnit(UnitID.currency_inr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inr, R.string.unit_currency_inr_short), - ReverseUnit(UnitID.currency_iqd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_iqd, R.string.unit_currency_iqd_short), - ReverseUnit(UnitID.currency_irr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_irr, R.string.unit_currency_irr_short), - ReverseUnit(UnitID.currency_isk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_isk, R.string.unit_currency_isk_short), - ReverseUnit(UnitID.currency_jep, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jep, R.string.unit_currency_jep_short), - ReverseUnit(UnitID.currency_jmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jmd, R.string.unit_currency_jmd_short), - ReverseUnit(UnitID.currency_jod, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jod, R.string.unit_currency_jod_short), - ReverseUnit(UnitID.currency_jpy, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jpy, R.string.unit_currency_jpy_short), - ReverseUnit(UnitID.currency_kes, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kes, R.string.unit_currency_kes_short), - ReverseUnit(UnitID.currency_kgs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kgs, R.string.unit_currency_kgs_short), - ReverseUnit(UnitID.currency_khr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_khr, R.string.unit_currency_khr_short), - ReverseUnit(UnitID.currency_kmf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kmf, R.string.unit_currency_kmf_short), - ReverseUnit(UnitID.currency_kpw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kpw, R.string.unit_currency_kpw_short), - ReverseUnit(UnitID.currency_krw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_krw, R.string.unit_currency_krw_short), - ReverseUnit(UnitID.currency_ksm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ksm, R.string.unit_currency_ksm_short), - ReverseUnit(UnitID.currency_kwd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kwd, R.string.unit_currency_kwd_short), - ReverseUnit(UnitID.currency_kyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kyd, R.string.unit_currency_kyd_short), - ReverseUnit(UnitID.currency_kzt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kzt, R.string.unit_currency_kzt_short), - ReverseUnit(UnitID.currency_lak, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lak, R.string.unit_currency_lak_short), - ReverseUnit(UnitID.currency_lbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lbp, R.string.unit_currency_lbp_short), - ReverseUnit(UnitID.currency_link, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_link, R.string.unit_currency_link_short), - ReverseUnit(UnitID.currency_lkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lkr, R.string.unit_currency_lkr_short), - ReverseUnit(UnitID.currency_lrd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lrd, R.string.unit_currency_lrd_short), - ReverseUnit(UnitID.currency_lsl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lsl, R.string.unit_currency_lsl_short), - ReverseUnit(UnitID.currency_ltc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltc, R.string.unit_currency_ltc_short), - ReverseUnit(UnitID.currency_ltl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltl, R.string.unit_currency_ltl_short), - ReverseUnit(UnitID.currency_luna, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_luna, R.string.unit_currency_luna_short), - ReverseUnit(UnitID.currency_lvl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lvl, R.string.unit_currency_lvl_short), - ReverseUnit(UnitID.currency_lyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lyd, R.string.unit_currency_lyd_short), - ReverseUnit(UnitID.currency_mad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mad, R.string.unit_currency_mad_short), - ReverseUnit(UnitID.currency_matic, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_matic, R.string.unit_currency_matic_short), - ReverseUnit(UnitID.currency_mdl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mdl, R.string.unit_currency_mdl_short), - ReverseUnit(UnitID.currency_mga, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mga, R.string.unit_currency_mga_short), - ReverseUnit(UnitID.currency_mkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mkd, R.string.unit_currency_mkd_short), - ReverseUnit(UnitID.currency_mmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mmk, R.string.unit_currency_mmk_short), - ReverseUnit(UnitID.currency_mnt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mnt, R.string.unit_currency_mnt_short), - ReverseUnit(UnitID.currency_mop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mop, R.string.unit_currency_mop_short), - ReverseUnit(UnitID.currency_mro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mro, R.string.unit_currency_mro_short), - ReverseUnit(UnitID.currency_mur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mur, R.string.unit_currency_mur_short), - ReverseUnit(UnitID.currency_mvr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mvr, R.string.unit_currency_mvr_short), - ReverseUnit(UnitID.currency_mwk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mwk, R.string.unit_currency_mwk_short), - ReverseUnit(UnitID.currency_mxn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mxn, R.string.unit_currency_mxn_short), - ReverseUnit(UnitID.currency_myr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_myr, R.string.unit_currency_myr_short), - ReverseUnit(UnitID.currency_mzn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mzn, R.string.unit_currency_mzn_short), - ReverseUnit(UnitID.currency_nad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nad, R.string.unit_currency_nad_short), - ReverseUnit(UnitID.currency_ngn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ngn, R.string.unit_currency_ngn_short), - ReverseUnit(UnitID.currency_nio, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nio, R.string.unit_currency_nio_short), - ReverseUnit(UnitID.currency_nok, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nok, R.string.unit_currency_nok_short), - ReverseUnit(UnitID.currency_npr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_npr, R.string.unit_currency_npr_short), - ReverseUnit(UnitID.currency_nzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nzd, R.string.unit_currency_nzd_short), - ReverseUnit(UnitID.currency_omr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_omr, R.string.unit_currency_omr_short), - ReverseUnit(UnitID.currency_one, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_one, R.string.unit_currency_one_short), - ReverseUnit(UnitID.currency_pab, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pab, R.string.unit_currency_pab_short), - ReverseUnit(UnitID.currency_pen, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pen, R.string.unit_currency_pen_short), - ReverseUnit(UnitID.currency_pgk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pgk, R.string.unit_currency_pgk_short), - ReverseUnit(UnitID.currency_php, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_php, R.string.unit_currency_php_short), - ReverseUnit(UnitID.currency_pkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pkr, R.string.unit_currency_pkr_short), - ReverseUnit(UnitID.currency_pln, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pln, R.string.unit_currency_pln_short), - ReverseUnit(UnitID.currency_pyg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pyg, R.string.unit_currency_pyg_short), - ReverseUnit(UnitID.currency_qar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_qar, R.string.unit_currency_qar_short), - ReverseUnit(UnitID.currency_ron, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ron, R.string.unit_currency_ron_short), - ReverseUnit(UnitID.currency_rsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rsd, R.string.unit_currency_rsd_short), - ReverseUnit(UnitID.currency_rub, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rub, R.string.unit_currency_rub_short), - ReverseUnit(UnitID.currency_rwf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rwf, R.string.unit_currency_rwf_short), - ReverseUnit(UnitID.currency_sar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sar, R.string.unit_currency_sar_short), - ReverseUnit(UnitID.currency_sbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sbd, R.string.unit_currency_sbd_short), - ReverseUnit(UnitID.currency_scr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_scr, R.string.unit_currency_scr_short), - ReverseUnit(UnitID.currency_sdg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sdg, R.string.unit_currency_sdg_short), - ReverseUnit(UnitID.currency_sek, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sek, R.string.unit_currency_sek_short), - ReverseUnit(UnitID.currency_sgd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sgd, R.string.unit_currency_sgd_short), - ReverseUnit(UnitID.currency_shib, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shib, R.string.unit_currency_shib_short), - ReverseUnit(UnitID.currency_shp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shp, R.string.unit_currency_shp_short), - ReverseUnit(UnitID.currency_sll, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sll, R.string.unit_currency_sll_short), - ReverseUnit(UnitID.currency_sol, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sol, R.string.unit_currency_sol_short), - ReverseUnit(UnitID.currency_sos, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sos, R.string.unit_currency_sos_short), - ReverseUnit(UnitID.currency_srd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_srd, R.string.unit_currency_srd_short), - ReverseUnit(UnitID.currency_std, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_std, R.string.unit_currency_std_short), - ReverseUnit(UnitID.currency_svc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_svc, R.string.unit_currency_svc_short), - ReverseUnit(UnitID.currency_syp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_syp, R.string.unit_currency_syp_short), - ReverseUnit(UnitID.currency_szl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_szl, R.string.unit_currency_szl_short), - ReverseUnit(UnitID.currency_thb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_thb, R.string.unit_currency_thb_short), - ReverseUnit(UnitID.currency_theta, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_theta, R.string.unit_currency_theta_short), - ReverseUnit(UnitID.currency_tjs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tjs, R.string.unit_currency_tjs_short), - ReverseUnit(UnitID.currency_tmt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tmt, R.string.unit_currency_tmt_short), - ReverseUnit(UnitID.currency_tnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tnd, R.string.unit_currency_tnd_short), - ReverseUnit(UnitID.currency_top, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_top, R.string.unit_currency_top_short), - ReverseUnit(UnitID.currency_trx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_trx, R.string.unit_currency_trx_short), - ReverseUnit(UnitID.currency_try, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_try, R.string.unit_currency_try_short), - ReverseUnit(UnitID.currency_ttd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ttd, R.string.unit_currency_ttd_short), - ReverseUnit(UnitID.currency_twd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_twd, R.string.unit_currency_twd_short), - ReverseUnit(UnitID.currency_tzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tzs, R.string.unit_currency_tzs_short), - ReverseUnit(UnitID.currency_uah, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uah, R.string.unit_currency_uah_short), - ReverseUnit(UnitID.currency_ugx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ugx, R.string.unit_currency_ugx_short), - ReverseUnit(UnitID.currency_uni, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uni, R.string.unit_currency_uni_short), - ReverseUnit(UnitID.currency_usd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usd, R.string.unit_currency_usd_short), - ReverseUnit(UnitID.currency_usdc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdc, R.string.unit_currency_usdc_short), - ReverseUnit(UnitID.currency_usdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdt, R.string.unit_currency_usdt_short), - ReverseUnit(UnitID.currency_uyu, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uyu, R.string.unit_currency_uyu_short), - ReverseUnit(UnitID.currency_uzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uzs, R.string.unit_currency_uzs_short), - ReverseUnit(UnitID.currency_vef, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vef, R.string.unit_currency_vef_short), - ReverseUnit(UnitID.currency_vet, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vet, R.string.unit_currency_vet_short), - ReverseUnit(UnitID.currency_vnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vnd, R.string.unit_currency_vnd_short), - ReverseUnit(UnitID.currency_vuv, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vuv, R.string.unit_currency_vuv_short), - ReverseUnit(UnitID.currency_wbtc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wbtc, R.string.unit_currency_wbtc_short), - ReverseUnit(UnitID.currency_wst, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wst, R.string.unit_currency_wst_short), - ReverseUnit(UnitID.currency_xaf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xaf, R.string.unit_currency_xaf_short), - ReverseUnit(UnitID.currency_xag, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xag, R.string.unit_currency_xag_short), - ReverseUnit(UnitID.currency_xau, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xau, R.string.unit_currency_xau_short), - ReverseUnit(UnitID.currency_xcd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xcd, R.string.unit_currency_xcd_short), - ReverseUnit(UnitID.currency_xdr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xdr, R.string.unit_currency_xdr_short), - ReverseUnit(UnitID.currency_xlm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xlm, R.string.unit_currency_xlm_short), - ReverseUnit(UnitID.currency_xmr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xmr, R.string.unit_currency_xmr_short), - ReverseUnit(UnitID.currency_xof, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xof, R.string.unit_currency_xof_short), - ReverseUnit(UnitID.currency_xpf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xpf, R.string.unit_currency_xpf_short), - ReverseUnit(UnitID.currency_xrp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xrp, R.string.unit_currency_xrp_short), - ReverseUnit(UnitID.currency_yer, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_yer, R.string.unit_currency_yer_short), - ReverseUnit(UnitID.currency_zar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zar, R.string.unit_currency_zar_short), - ReverseUnit(UnitID.currency_zmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmk, R.string.unit_currency_zmk_short), - ReverseUnit(UnitID.currency_zmw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmw, R.string.unit_currency_zmw_short), - ReverseUnit(UnitID.currency_zwl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zwl, R.string.unit_currency_zwl_short), + NormalUnit(UnitID.currency_1inch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_1inch, R.string.unit_currency_1inch_short, backward = true), + NormalUnit(UnitID.currency_ada, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ada, R.string.unit_currency_ada_short, backward = true), + NormalUnit(UnitID.currency_aed, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aed, R.string.unit_currency_aed_short, backward = true), + NormalUnit(UnitID.currency_afn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_afn, R.string.unit_currency_afn_short, backward = true), + NormalUnit(UnitID.currency_algo, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_algo, R.string.unit_currency_algo_short, backward = true), + NormalUnit(UnitID.currency_all, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_all, R.string.unit_currency_all_short, backward = true), + NormalUnit(UnitID.currency_amd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_amd, R.string.unit_currency_amd_short, backward = true), + NormalUnit(UnitID.currency_ang, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ang, R.string.unit_currency_ang_short, backward = true), + NormalUnit(UnitID.currency_aoa, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aoa, R.string.unit_currency_aoa_short, backward = true), + NormalUnit(UnitID.currency_ars, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ars, R.string.unit_currency_ars_short, backward = true), + NormalUnit(UnitID.currency_atom, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_atom, R.string.unit_currency_atom_short, backward = true), + NormalUnit(UnitID.currency_aud, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aud, R.string.unit_currency_aud_short, backward = true), + NormalUnit(UnitID.currency_avax, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_avax, R.string.unit_currency_avax_short, backward = true), + NormalUnit(UnitID.currency_awg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_awg, R.string.unit_currency_awg_short, backward = true), + NormalUnit(UnitID.currency_azn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_azn, R.string.unit_currency_azn_short, backward = true), + NormalUnit(UnitID.currency_bam, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bam, R.string.unit_currency_bam_short, backward = true), + NormalUnit(UnitID.currency_bbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bbd, R.string.unit_currency_bbd_short, backward = true), + NormalUnit(UnitID.currency_bch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bch, R.string.unit_currency_bch_short, backward = true), + NormalUnit(UnitID.currency_bdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bdt, R.string.unit_currency_bdt_short, backward = true), + NormalUnit(UnitID.currency_bgn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bgn, R.string.unit_currency_bgn_short, backward = true), + NormalUnit(UnitID.currency_bhd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bhd, R.string.unit_currency_bhd_short, backward = true), + NormalUnit(UnitID.currency_bif, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bif, R.string.unit_currency_bif_short, backward = true), + NormalUnit(UnitID.currency_bmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bmd, R.string.unit_currency_bmd_short, backward = true), + NormalUnit(UnitID.currency_bnb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnb, R.string.unit_currency_bnb_short, backward = true), + NormalUnit(UnitID.currency_bnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnd, R.string.unit_currency_bnd_short, backward = true), + NormalUnit(UnitID.currency_bob, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bob, R.string.unit_currency_bob_short, backward = true), + NormalUnit(UnitID.currency_brl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_brl, R.string.unit_currency_brl_short, backward = true), + NormalUnit(UnitID.currency_bsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bsd, R.string.unit_currency_bsd_short, backward = true), + NormalUnit(UnitID.currency_btc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btc, R.string.unit_currency_btc_short, backward = true), + NormalUnit(UnitID.currency_btn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btn, R.string.unit_currency_btn_short, backward = true), + NormalUnit(UnitID.currency_busd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_busd, R.string.unit_currency_busd_short, backward = true), + NormalUnit(UnitID.currency_bwp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bwp, R.string.unit_currency_bwp_short, backward = true), + NormalUnit(UnitID.currency_byn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byn, R.string.unit_currency_byn_short, backward = true), + NormalUnit(UnitID.currency_byr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byr, R.string.unit_currency_byr_short, backward = true), + NormalUnit(UnitID.currency_bzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bzd, R.string.unit_currency_bzd_short, backward = true), + NormalUnit(UnitID.currency_cad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cad, R.string.unit_currency_cad_short, backward = true), + NormalUnit(UnitID.currency_cdf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cdf, R.string.unit_currency_cdf_short, backward = true), + NormalUnit(UnitID.currency_chf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chf, R.string.unit_currency_chf_short, backward = true), + NormalUnit(UnitID.currency_chz, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chz, R.string.unit_currency_chz_short, backward = true), + NormalUnit(UnitID.currency_clf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clf, R.string.unit_currency_clf_short, backward = true), + NormalUnit(UnitID.currency_clp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clp, R.string.unit_currency_clp_short, backward = true), + NormalUnit(UnitID.currency_cny, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cny, R.string.unit_currency_cny_short, backward = true), + NormalUnit(UnitID.currency_cop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cop, R.string.unit_currency_cop_short, backward = true), + NormalUnit(UnitID.currency_crc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_crc, R.string.unit_currency_crc_short, backward = true), + NormalUnit(UnitID.currency_cro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cro, R.string.unit_currency_cro_short, backward = true), + NormalUnit(UnitID.currency_cuc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cuc, R.string.unit_currency_cuc_short, backward = true), + NormalUnit(UnitID.currency_cup, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cup, R.string.unit_currency_cup_short, backward = true), + NormalUnit(UnitID.currency_cve, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cve, R.string.unit_currency_cve_short, backward = true), + NormalUnit(UnitID.currency_czk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_czk, R.string.unit_currency_czk_short, backward = true), + NormalUnit(UnitID.currency_dai, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dai, R.string.unit_currency_dai_short, backward = true), + NormalUnit(UnitID.currency_djf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_djf, R.string.unit_currency_djf_short, backward = true), + NormalUnit(UnitID.currency_dkk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dkk, R.string.unit_currency_dkk_short, backward = true), + NormalUnit(UnitID.currency_doge, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_doge, R.string.unit_currency_doge_short, backward = true), + NormalUnit(UnitID.currency_dop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dop, R.string.unit_currency_dop_short, backward = true), + NormalUnit(UnitID.currency_dot, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dot, R.string.unit_currency_dot_short, backward = true), + NormalUnit(UnitID.currency_dzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dzd, R.string.unit_currency_dzd_short, backward = true), + NormalUnit(UnitID.currency_egld, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egld, R.string.unit_currency_egld_short, backward = true), + NormalUnit(UnitID.currency_egp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egp, R.string.unit_currency_egp_short, backward = true), + NormalUnit(UnitID.currency_enj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_enj, R.string.unit_currency_enj_short, backward = true), + NormalUnit(UnitID.currency_ern, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ern, R.string.unit_currency_ern_short, backward = true), + NormalUnit(UnitID.currency_etb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etb, R.string.unit_currency_etb_short, backward = true), + NormalUnit(UnitID.currency_etc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etc, R.string.unit_currency_etc_short, backward = true), + NormalUnit(UnitID.currency_eth, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eth, R.string.unit_currency_eth_short, backward = true), + NormalUnit(UnitID.currency_eur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eur, R.string.unit_currency_eur_short, backward = true), + NormalUnit(UnitID.currency_fil, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fil, R.string.unit_currency_fil_short, backward = true), + NormalUnit(UnitID.currency_fjd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fjd, R.string.unit_currency_fjd_short, backward = true), + NormalUnit(UnitID.currency_fkp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fkp, R.string.unit_currency_fkp_short, backward = true), + NormalUnit(UnitID.currency_ftt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ftt, R.string.unit_currency_ftt_short, backward = true), + NormalUnit(UnitID.currency_gbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gbp, R.string.unit_currency_gbp_short, backward = true), + NormalUnit(UnitID.currency_gel, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gel, R.string.unit_currency_gel_short, backward = true), + NormalUnit(UnitID.currency_ggp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ggp, R.string.unit_currency_ggp_short, backward = true), + NormalUnit(UnitID.currency_ghs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ghs, R.string.unit_currency_ghs_short, backward = true), + NormalUnit(UnitID.currency_gip, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gip, R.string.unit_currency_gip_short, backward = true), + NormalUnit(UnitID.currency_gmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gmd, R.string.unit_currency_gmd_short, backward = true), + NormalUnit(UnitID.currency_gnf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gnf, R.string.unit_currency_gnf_short, backward = true), + NormalUnit(UnitID.currency_grt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_grt, R.string.unit_currency_grt_short, backward = true), + NormalUnit(UnitID.currency_gtq, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gtq, R.string.unit_currency_gtq_short, backward = true), + NormalUnit(UnitID.currency_gyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gyd, R.string.unit_currency_gyd_short, backward = true), + NormalUnit(UnitID.currency_hkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hkd, R.string.unit_currency_hkd_short, backward = true), + NormalUnit(UnitID.currency_hnl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hnl, R.string.unit_currency_hnl_short, backward = true), + NormalUnit(UnitID.currency_hrk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hrk, R.string.unit_currency_hrk_short, backward = true), + NormalUnit(UnitID.currency_htg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_htg, R.string.unit_currency_htg_short, backward = true), + NormalUnit(UnitID.currency_huf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_huf, R.string.unit_currency_huf_short, backward = true), + NormalUnit(UnitID.currency_icp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_icp, R.string.unit_currency_icp_short, backward = true), + NormalUnit(UnitID.currency_idr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_idr, R.string.unit_currency_idr_short, backward = true), + NormalUnit(UnitID.currency_ils, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ils, R.string.unit_currency_ils_short, backward = true), + NormalUnit(UnitID.currency_imp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_imp, R.string.unit_currency_imp_short, backward = true), + NormalUnit(UnitID.currency_inj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inj, R.string.unit_currency_inj_short, backward = true), + NormalUnit(UnitID.currency_inr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inr, R.string.unit_currency_inr_short, backward = true), + NormalUnit(UnitID.currency_iqd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_iqd, R.string.unit_currency_iqd_short, backward = true), + NormalUnit(UnitID.currency_irr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_irr, R.string.unit_currency_irr_short, backward = true), + NormalUnit(UnitID.currency_isk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_isk, R.string.unit_currency_isk_short, backward = true), + NormalUnit(UnitID.currency_jep, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jep, R.string.unit_currency_jep_short, backward = true), + NormalUnit(UnitID.currency_jmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jmd, R.string.unit_currency_jmd_short, backward = true), + NormalUnit(UnitID.currency_jod, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jod, R.string.unit_currency_jod_short, backward = true), + NormalUnit(UnitID.currency_jpy, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jpy, R.string.unit_currency_jpy_short, backward = true), + NormalUnit(UnitID.currency_kes, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kes, R.string.unit_currency_kes_short, backward = true), + NormalUnit(UnitID.currency_kgs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kgs, R.string.unit_currency_kgs_short, backward = true), + NormalUnit(UnitID.currency_khr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_khr, R.string.unit_currency_khr_short, backward = true), + NormalUnit(UnitID.currency_kmf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kmf, R.string.unit_currency_kmf_short, backward = true), + NormalUnit(UnitID.currency_kpw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kpw, R.string.unit_currency_kpw_short, backward = true), + NormalUnit(UnitID.currency_krw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_krw, R.string.unit_currency_krw_short, backward = true), + NormalUnit(UnitID.currency_ksm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ksm, R.string.unit_currency_ksm_short, backward = true), + NormalUnit(UnitID.currency_kwd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kwd, R.string.unit_currency_kwd_short, backward = true), + NormalUnit(UnitID.currency_kyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kyd, R.string.unit_currency_kyd_short, backward = true), + NormalUnit(UnitID.currency_kzt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kzt, R.string.unit_currency_kzt_short, backward = true), + NormalUnit(UnitID.currency_lak, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lak, R.string.unit_currency_lak_short, backward = true), + NormalUnit(UnitID.currency_lbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lbp, R.string.unit_currency_lbp_short, backward = true), + NormalUnit(UnitID.currency_link, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_link, R.string.unit_currency_link_short, backward = true), + NormalUnit(UnitID.currency_lkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lkr, R.string.unit_currency_lkr_short, backward = true), + NormalUnit(UnitID.currency_lrd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lrd, R.string.unit_currency_lrd_short, backward = true), + NormalUnit(UnitID.currency_lsl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lsl, R.string.unit_currency_lsl_short, backward = true), + NormalUnit(UnitID.currency_ltc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltc, R.string.unit_currency_ltc_short, backward = true), + NormalUnit(UnitID.currency_ltl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltl, R.string.unit_currency_ltl_short, backward = true), + NormalUnit(UnitID.currency_luna, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_luna, R.string.unit_currency_luna_short, backward = true), + NormalUnit(UnitID.currency_lvl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lvl, R.string.unit_currency_lvl_short, backward = true), + NormalUnit(UnitID.currency_lyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lyd, R.string.unit_currency_lyd_short, backward = true), + NormalUnit(UnitID.currency_mad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mad, R.string.unit_currency_mad_short, backward = true), + NormalUnit(UnitID.currency_matic, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_matic, R.string.unit_currency_matic_short, backward = true), + NormalUnit(UnitID.currency_mdl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mdl, R.string.unit_currency_mdl_short, backward = true), + NormalUnit(UnitID.currency_mga, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mga, R.string.unit_currency_mga_short, backward = true), + NormalUnit(UnitID.currency_mkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mkd, R.string.unit_currency_mkd_short, backward = true), + NormalUnit(UnitID.currency_mmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mmk, R.string.unit_currency_mmk_short, backward = true), + NormalUnit(UnitID.currency_mnt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mnt, R.string.unit_currency_mnt_short, backward = true), + NormalUnit(UnitID.currency_mop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mop, R.string.unit_currency_mop_short, backward = true), + NormalUnit(UnitID.currency_mro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mro, R.string.unit_currency_mro_short, backward = true), + NormalUnit(UnitID.currency_mur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mur, R.string.unit_currency_mur_short, backward = true), + NormalUnit(UnitID.currency_mvr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mvr, R.string.unit_currency_mvr_short, backward = true), + NormalUnit(UnitID.currency_mwk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mwk, R.string.unit_currency_mwk_short, backward = true), + NormalUnit(UnitID.currency_mxn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mxn, R.string.unit_currency_mxn_short, backward = true), + NormalUnit(UnitID.currency_myr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_myr, R.string.unit_currency_myr_short, backward = true), + NormalUnit(UnitID.currency_mzn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mzn, R.string.unit_currency_mzn_short, backward = true), + NormalUnit(UnitID.currency_nad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nad, R.string.unit_currency_nad_short, backward = true), + NormalUnit(UnitID.currency_ngn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ngn, R.string.unit_currency_ngn_short, backward = true), + NormalUnit(UnitID.currency_nio, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nio, R.string.unit_currency_nio_short, backward = true), + NormalUnit(UnitID.currency_nok, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nok, R.string.unit_currency_nok_short, backward = true), + NormalUnit(UnitID.currency_npr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_npr, R.string.unit_currency_npr_short, backward = true), + NormalUnit(UnitID.currency_nzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nzd, R.string.unit_currency_nzd_short, backward = true), + NormalUnit(UnitID.currency_omr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_omr, R.string.unit_currency_omr_short, backward = true), + NormalUnit(UnitID.currency_one, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_one, R.string.unit_currency_one_short, backward = true), + NormalUnit(UnitID.currency_pab, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pab, R.string.unit_currency_pab_short, backward = true), + NormalUnit(UnitID.currency_pen, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pen, R.string.unit_currency_pen_short, backward = true), + NormalUnit(UnitID.currency_pgk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pgk, R.string.unit_currency_pgk_short, backward = true), + NormalUnit(UnitID.currency_php, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_php, R.string.unit_currency_php_short, backward = true), + NormalUnit(UnitID.currency_pkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pkr, R.string.unit_currency_pkr_short, backward = true), + NormalUnit(UnitID.currency_pln, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pln, R.string.unit_currency_pln_short, backward = true), + NormalUnit(UnitID.currency_pyg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pyg, R.string.unit_currency_pyg_short, backward = true), + NormalUnit(UnitID.currency_qar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_qar, R.string.unit_currency_qar_short, backward = true), + NormalUnit(UnitID.currency_ron, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ron, R.string.unit_currency_ron_short, backward = true), + NormalUnit(UnitID.currency_rsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rsd, R.string.unit_currency_rsd_short, backward = true), + NormalUnit(UnitID.currency_rub, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rub, R.string.unit_currency_rub_short, backward = true), + NormalUnit(UnitID.currency_rwf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rwf, R.string.unit_currency_rwf_short, backward = true), + NormalUnit(UnitID.currency_sar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sar, R.string.unit_currency_sar_short, backward = true), + NormalUnit(UnitID.currency_sbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sbd, R.string.unit_currency_sbd_short, backward = true), + NormalUnit(UnitID.currency_scr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_scr, R.string.unit_currency_scr_short, backward = true), + NormalUnit(UnitID.currency_sdg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sdg, R.string.unit_currency_sdg_short, backward = true), + NormalUnit(UnitID.currency_sek, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sek, R.string.unit_currency_sek_short, backward = true), + NormalUnit(UnitID.currency_sgd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sgd, R.string.unit_currency_sgd_short, backward = true), + NormalUnit(UnitID.currency_shib, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shib, R.string.unit_currency_shib_short, backward = true), + NormalUnit(UnitID.currency_shp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shp, R.string.unit_currency_shp_short, backward = true), + NormalUnit(UnitID.currency_sll, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sll, R.string.unit_currency_sll_short, backward = true), + NormalUnit(UnitID.currency_sol, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sol, R.string.unit_currency_sol_short, backward = true), + NormalUnit(UnitID.currency_sos, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sos, R.string.unit_currency_sos_short, backward = true), + NormalUnit(UnitID.currency_srd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_srd, R.string.unit_currency_srd_short, backward = true), + NormalUnit(UnitID.currency_std, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_std, R.string.unit_currency_std_short, backward = true), + NormalUnit(UnitID.currency_svc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_svc, R.string.unit_currency_svc_short, backward = true), + NormalUnit(UnitID.currency_syp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_syp, R.string.unit_currency_syp_short, backward = true), + NormalUnit(UnitID.currency_szl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_szl, R.string.unit_currency_szl_short, backward = true), + NormalUnit(UnitID.currency_thb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_thb, R.string.unit_currency_thb_short, backward = true), + NormalUnit(UnitID.currency_theta, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_theta, R.string.unit_currency_theta_short, backward = true), + NormalUnit(UnitID.currency_tjs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tjs, R.string.unit_currency_tjs_short, backward = true), + NormalUnit(UnitID.currency_tmt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tmt, R.string.unit_currency_tmt_short, backward = true), + NormalUnit(UnitID.currency_tnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tnd, R.string.unit_currency_tnd_short, backward = true), + NormalUnit(UnitID.currency_top, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_top, R.string.unit_currency_top_short, backward = true), + NormalUnit(UnitID.currency_trx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_trx, R.string.unit_currency_trx_short, backward = true), + NormalUnit(UnitID.currency_try, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_try, R.string.unit_currency_try_short, backward = true), + NormalUnit(UnitID.currency_ttd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ttd, R.string.unit_currency_ttd_short, backward = true), + NormalUnit(UnitID.currency_twd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_twd, R.string.unit_currency_twd_short, backward = true), + NormalUnit(UnitID.currency_tzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tzs, R.string.unit_currency_tzs_short, backward = true), + NormalUnit(UnitID.currency_uah, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uah, R.string.unit_currency_uah_short, backward = true), + NormalUnit(UnitID.currency_ugx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ugx, R.string.unit_currency_ugx_short, backward = true), + NormalUnit(UnitID.currency_uni, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uni, R.string.unit_currency_uni_short, backward = true), + NormalUnit(UnitID.currency_usd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usd, R.string.unit_currency_usd_short, backward = true), + NormalUnit(UnitID.currency_usdc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdc, R.string.unit_currency_usdc_short, backward = true), + NormalUnit(UnitID.currency_usdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdt, R.string.unit_currency_usdt_short, backward = true), + NormalUnit(UnitID.currency_uyu, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uyu, R.string.unit_currency_uyu_short, backward = true), + NormalUnit(UnitID.currency_uzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uzs, R.string.unit_currency_uzs_short, backward = true), + NormalUnit(UnitID.currency_vef, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vef, R.string.unit_currency_vef_short, backward = true), + NormalUnit(UnitID.currency_vet, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vet, R.string.unit_currency_vet_short, backward = true), + NormalUnit(UnitID.currency_vnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vnd, R.string.unit_currency_vnd_short, backward = true), + NormalUnit(UnitID.currency_vuv, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vuv, R.string.unit_currency_vuv_short, backward = true), + NormalUnit(UnitID.currency_wbtc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wbtc, R.string.unit_currency_wbtc_short, backward = true), + NormalUnit(UnitID.currency_wst, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wst, R.string.unit_currency_wst_short, backward = true), + NormalUnit(UnitID.currency_xaf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xaf, R.string.unit_currency_xaf_short, backward = true), + NormalUnit(UnitID.currency_xag, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xag, R.string.unit_currency_xag_short, backward = true), + NormalUnit(UnitID.currency_xau, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xau, R.string.unit_currency_xau_short, backward = true), + NormalUnit(UnitID.currency_xcd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xcd, R.string.unit_currency_xcd_short, backward = true), + NormalUnit(UnitID.currency_xdr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xdr, R.string.unit_currency_xdr_short, backward = true), + NormalUnit(UnitID.currency_xlm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xlm, R.string.unit_currency_xlm_short, backward = true), + NormalUnit(UnitID.currency_xmr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xmr, R.string.unit_currency_xmr_short, backward = true), + NormalUnit(UnitID.currency_xof, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xof, R.string.unit_currency_xof_short, backward = true), + NormalUnit(UnitID.currency_xpf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xpf, R.string.unit_currency_xpf_short, backward = true), + NormalUnit(UnitID.currency_xrp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xrp, R.string.unit_currency_xrp_short, backward = true), + NormalUnit(UnitID.currency_yer, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_yer, R.string.unit_currency_yer_short, backward = true), + NormalUnit(UnitID.currency_zar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zar, R.string.unit_currency_zar_short, backward = true), + NormalUnit(UnitID.currency_zmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmk, R.string.unit_currency_zmk_short, backward = true), + NormalUnit(UnitID.currency_zmw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmw, R.string.unit_currency_zmw_short, backward = true), + NormalUnit(UnitID.currency_zwl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zwl, R.string.unit_currency_zwl_short, backward = true), ) } diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Data.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Data.kt index 109901b9..60aff586 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Data.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Data.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val dataCollection: List by lazy { +internal val dataCollection: List by lazy { listOf( NormalUnit(UnitID.bit, BigDecimal("1"), UnitGroup.DATA, R.string.unit_bit, R.string.unit_bit_short), NormalUnit(UnitID.kibibit, BigDecimal("1024"), UnitGroup.DATA, R.string.unit_kibibit, R.string.unit_kibibit_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/DataTransfer.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/DataTransfer.kt index 8b2cb3ff..9ef41644 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/DataTransfer.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/DataTransfer.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val dataTransferCollection: List by lazy { +internal val dataTransferCollection: List by lazy { listOf( NormalUnit(UnitID.bit_per_second, BigDecimal("1"), UnitGroup.DATA_TRANSFER, R.string.unit_bit_per_second, R.string.unit_bit_per_second_short), NormalUnit(UnitID.kibibit_per_second, BigDecimal("1024"), UnitGroup.DATA_TRANSFER, R.string.unit_kibibit_per_second, R.string.unit_kibibit_per_second_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/ElectrostaticCapacitance.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/ElectrostaticCapacitance.kt index b977c1f5..0282f351 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/ElectrostaticCapacitance.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/ElectrostaticCapacitance.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val electrostaticCapacitance: List by lazy { +internal val electrostaticCapacitance: List by lazy { listOf( NormalUnit(UnitID.attofarad, BigDecimal("1"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_attofarad, R.string.unit_attofarad_short), NormalUnit(UnitID.picofarad, BigDecimal("1000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_picofarad, R.string.unit_picofarad_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Energy.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Energy.kt index cc928cd5..a2427b46 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Energy.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Energy.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val energyCollection: List by lazy { +internal val energyCollection: List by lazy { listOf( NormalUnit(UnitID.electron_volt, BigDecimal("0.160217733"), UnitGroup.ENERGY, R.string.unit_electron_volt, R.string.unit_electron_volt_short), NormalUnit(UnitID.attojoule, BigDecimal("1.00"), UnitGroup.ENERGY, R.string.unit_attojoule, R.string.unit_attojoule_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FlowRate.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FlowRate.kt index 0126ef92..66baf4da 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FlowRate.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FlowRate.kt @@ -20,33 +20,33 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.ReverseUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -val flowRateCollection: List by lazy { +val flowRateCollection: List by lazy { listOf( - ReverseUnit(UnitID.liter_per_hour, BigDecimal("3600000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_hour, R.string.unit_liter_per_hour_short), - ReverseUnit(UnitID.liter_per_minute, BigDecimal("60000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_minute, R.string.unit_liter_per_minute_short), - ReverseUnit(UnitID.liter_per_second, BigDecimal("1000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_second, R.string.unit_liter_per_second_short), - ReverseUnit(UnitID.milliliter_per_hour, BigDecimal("3600000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_hour, R.string.unit_milliliter_per_hour_short), - ReverseUnit(UnitID.milliliter_per_minute, BigDecimal("60000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_minute, R.string.unit_milliliter_per_minute_short), - ReverseUnit(UnitID.milliliter_per_second, BigDecimal("1000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_second, R.string.unit_milliliter_per_second_short), - ReverseUnit(UnitID.cubic_meter_per_hour, BigDecimal("3600"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_hour, R.string.unit_cubic_meter_per_hour_short), - ReverseUnit(UnitID.cubic_meter_per_minute, BigDecimal("60"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_minute, R.string.unit_cubic_meter_per_minute_short), - ReverseUnit(UnitID.cubic_meter_per_second, BigDecimal("1"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_second, R.string.unit_cubic_meter_per_second_short), - ReverseUnit(UnitID.cubic_millimeter_per_hour, BigDecimal("3600000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_hour, R.string.unit_cubic_millimeter_per_hour_short), - ReverseUnit(UnitID.cubic_millimeter_per_minute, BigDecimal("60000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_minute, R.string.unit_cubic_millimeter_per_minute_short), - ReverseUnit(UnitID.cubic_millimeter_per_second, BigDecimal("1000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_second, R.string.unit_cubic_millimeter_per_second_short), - ReverseUnit(UnitID.cubic_foot_per_hour, BigDecimal("127132.80019736"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_hour, R.string.unit_cubic_foot_per_hour_short), - ReverseUnit(UnitID.cubic_foot_per_minute, BigDecimal("2118.8800032893"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_minute, R.string.unit_cubic_foot_per_minute_short), - ReverseUnit(UnitID.cubic_foot_per_second, BigDecimal("35.314666721489"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_second, R.string.unit_cubic_foot_per_second_short), - ReverseUnit(UnitID.gallons_per_hour_us, BigDecimal("951019.38848933"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_us, R.string.unit_gallon_per_hour_us_short), - ReverseUnit(UnitID.gallons_per_minute_us, BigDecimal("15850.323141489"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_us, R.string.unit_gallon_per_minute_us_short), - ReverseUnit(UnitID.gallons_per_second_us, BigDecimal("264.17205235815"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_us, R.string.unit_gallon_per_second_us_short), - ReverseUnit(UnitID.gallons_per_hour_imperial, BigDecimal("791889.29387672"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_imperial, R.string.unit_gallon_per_hour_imperial_short), - ReverseUnit(UnitID.gallons_per_minute_imperial, BigDecimal("13198.154897945"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_imperial, R.string.unit_gallon_per_minute_imperial_short), - ReverseUnit(UnitID.gallons_per_second_imperial, BigDecimal("219.96924829909"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_imperial, R.string.unit_gallon_per_second_imperial_short), + NormalUnit(UnitID.liter_per_hour, BigDecimal("3600000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_hour, R.string.unit_liter_per_hour_short, true), + NormalUnit(UnitID.liter_per_minute, BigDecimal("60000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_minute, R.string.unit_liter_per_minute_short, true), + NormalUnit(UnitID.liter_per_second, BigDecimal("1000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_second, R.string.unit_liter_per_second_short, true), + NormalUnit(UnitID.milliliter_per_hour, BigDecimal("3600000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_hour, R.string.unit_milliliter_per_hour_short, true), + NormalUnit(UnitID.milliliter_per_minute, BigDecimal("60000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_minute, R.string.unit_milliliter_per_minute_short, true), + NormalUnit(UnitID.milliliter_per_second, BigDecimal("1000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_second, R.string.unit_milliliter_per_second_short, true), + NormalUnit(UnitID.cubic_meter_per_hour, BigDecimal("3600"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_hour, R.string.unit_cubic_meter_per_hour_short, true), + NormalUnit(UnitID.cubic_meter_per_minute, BigDecimal("60"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_minute, R.string.unit_cubic_meter_per_minute_short, true), + NormalUnit(UnitID.cubic_meter_per_second, BigDecimal("1"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_second, R.string.unit_cubic_meter_per_second_short, true), + NormalUnit(UnitID.cubic_millimeter_per_hour, BigDecimal("3600000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_hour, R.string.unit_cubic_millimeter_per_hour_short, true), + NormalUnit(UnitID.cubic_millimeter_per_minute, BigDecimal("60000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_minute, R.string.unit_cubic_millimeter_per_minute_short, true), + NormalUnit(UnitID.cubic_millimeter_per_second, BigDecimal("1000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_second, R.string.unit_cubic_millimeter_per_second_short, true), + NormalUnit(UnitID.cubic_foot_per_hour, BigDecimal("127132.80019736"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_hour, R.string.unit_cubic_foot_per_hour_short, true), + NormalUnit(UnitID.cubic_foot_per_minute, BigDecimal("2118.8800032893"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_minute, R.string.unit_cubic_foot_per_minute_short, true), + NormalUnit(UnitID.cubic_foot_per_second, BigDecimal("35.314666721489"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_second, R.string.unit_cubic_foot_per_second_short, true), + NormalUnit(UnitID.gallons_per_hour_us, BigDecimal("951019.38848933"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_us, R.string.unit_gallon_per_hour_us_short, true), + NormalUnit(UnitID.gallons_per_minute_us, BigDecimal("15850.323141489"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_us, R.string.unit_gallon_per_minute_us_short, true), + NormalUnit(UnitID.gallons_per_second_us, BigDecimal("264.17205235815"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_us, R.string.unit_gallon_per_second_us_short, true), + NormalUnit(UnitID.gallons_per_hour_imperial, BigDecimal("791889.29387672"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_imperial, R.string.unit_gallon_per_hour_imperial_short, true), + NormalUnit(UnitID.gallons_per_minute_imperial, BigDecimal("13198.154897945"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_imperial, R.string.unit_gallon_per_minute_imperial_short, true), + NormalUnit(UnitID.gallons_per_second_imperial, BigDecimal("219.96924829909"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_imperial, R.string.unit_gallon_per_second_imperial_short, true), ) } diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Flux.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Flux.kt index b39c16a1..99320131 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Flux.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Flux.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val fluxCollection: List by lazy { +internal val fluxCollection: List by lazy { listOf( NormalUnit(UnitID.maxwell, BigDecimal("1"), UnitGroup.FLUX, R.string.unit_maxwell, R.string.unit_maxwell_short), NormalUnit(UnitID.microweber, BigDecimal("100"), UnitGroup.FLUX, R.string.unit_microweber, R.string.unit_microweber_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Force.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Force.kt index 1a750c27..de5e5aa7 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Force.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Force.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -val forceCollection: List by lazy { +val forceCollection: List by lazy { listOf( NormalUnit(UnitID.attonewton, BigDecimal("1"), UnitGroup.FORCE, R.string.unit_attonewton, R.string.unit_attonewton_short), NormalUnit(UnitID.dyne, BigDecimal("10000000000000"), UnitGroup.FORCE, R.string.unit_dyne, R.string.unit_dyne_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FuelConsumption.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FuelConsumption.kt index bf5ec752..0e10fe10 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FuelConsumption.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/FuelConsumption.kt @@ -20,23 +20,22 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.BackwardUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -val fuelConsumptionCollection: List by lazy { +val fuelConsumptionCollection: List by lazy { listOf( NormalUnit( UnitID.kilometer_per_liter, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_km_per_l, R.string.unit_km_per_l_short), - BackwardUnit(UnitID.liter_per_kilometer, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_km, R.string.unit_l_per_km_short), - BackwardUnit(UnitID.liter_per_100_kilometer, BigDecimal("100"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_100_km, R.string.unit_l_per_100_km_short), + NormalUnit(UnitID.liter_per_kilometer, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_km, R.string.unit_l_per_km_short, true), + NormalUnit(UnitID.liter_per_100_kilometer, BigDecimal("100"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_100_km, R.string.unit_l_per_100_km_short, true), NormalUnit( UnitID.mile_per_gallon_uk, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_uk, R.string.unit_mi_per_gallon_uk_short), NormalUnit( UnitID.mile_per_gallon_us, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_us, R.string.unit_mi_per_gallon_us_short), NormalUnit( UnitID.mile_us_per_liter, BigDecimal("1.609344"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_us_per_l, R.string.unit_mi_us_per_l_short), - BackwardUnit(UnitID.gallon_us_per_mile, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_mile, R.string.unit_gallon_us_per_mile_short), - BackwardUnit(UnitID.gallon_uk_per_mile, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_mile, R.string.unit_gallon_uk_per_mile_short), - BackwardUnit(UnitID.gallon_us_per_100_mile, BigDecimal("42.51437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_100_mile, R.string.unit_gallon_us_per_100_mile_short), - BackwardUnit(UnitID.gallon_uk_per_100_mile, BigDecimal("35.400618996"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_100_mile, R.string.unit_gallon_uk_per_100_mile_short), + NormalUnit(UnitID.gallon_us_per_mile, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_mile, R.string.unit_gallon_us_per_mile_short, true), + NormalUnit(UnitID.gallon_uk_per_mile, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_mile, R.string.unit_gallon_uk_per_mile_short, true), + NormalUnit(UnitID.gallon_us_per_100_mile, BigDecimal("42.51437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_100_mile, R.string.unit_gallon_us_per_100_mile_short, true), + NormalUnit(UnitID.gallon_uk_per_100_mile, BigDecimal("35.400618996"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_100_mile, R.string.unit_gallon_uk_per_100_mile_short, true), ) } diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Length.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Length.kt index 4bb1f83c..96ffd4da 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Length.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Length.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val lengthCollection: List by lazy { +internal val lengthCollection: List by lazy { listOf( NormalUnit(UnitID.attometer, BigDecimal("1"), UnitGroup.LENGTH, R.string.unit_attometer, R.string.unit_attometer_short), NormalUnit(UnitID.nanometer, BigDecimal("1000000000"), UnitGroup.LENGTH, R.string.unit_nanometer, R.string.unit_nanometer_short), @@ -55,3 +55,4 @@ internal val lengthCollection: List by lazy { NormalUnit(UnitID.sun_equatorial_radius, BigDecimal("695508000000000000000000000"), UnitGroup.LENGTH, R.string.unit_sun_equatorial_radius, R.string.unit_sun_equatorial_radius_short), ) } + diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Luminance.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Luminance.kt index 65fd29d2..0625c466 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Luminance.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Luminance.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -val luminanceCollection: List by lazy { +val luminanceCollection: List by lazy { listOf( NormalUnit(UnitID.candela_per_square_meter, BigDecimal("31415926.5359"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_meter, R.string.unit_candela_per_square_meter_short), NormalUnit(UnitID.candela_per_square_centimeter, BigDecimal("314159265359"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_centimeter, R.string.unit_candela_per_square_centimeter_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Mass.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Mass.kt index 5e3aa85e..9f5f29c1 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Mass.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Mass.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val massCollection: List by lazy { +internal val massCollection: List by lazy { listOf( NormalUnit(UnitID.electron_mass_rest, BigDecimal("0.00000000000000000000000000091093897"), UnitGroup.MASS, R.string.unit_electron_mass_rest, R.string.unit_electron_mass_rest_short), NormalUnit(UnitID.atomic_mass_unit, BigDecimal("0.0000000000000000000000016605402"), UnitGroup.MASS, R.string.unit_atomic_mass_unit, R.string.unit_atomic_mass_unit_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/NumberBase.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/NumberBase.kt index 09a5854a..a9b56b95 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/NumberBase.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/NumberBase.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NumberBaseUnit import java.math.BigDecimal -internal val numberBaseCollection: List by lazy { +internal val numberBaseCollection: List by lazy { listOf( NumberBaseUnit(UnitID.binary, BigDecimal("2.0"), UnitGroup.NUMBER_BASE, R.string.unit_binary, R.string.unit_binary_short), NumberBaseUnit(UnitID.ternary, BigDecimal("3.0"), UnitGroup.NUMBER_BASE, R.string.unit_ternary, R.string.unit_ternary_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Power.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Power.kt index 381ed636..c60393d5 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Power.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Power.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val powerCollection: List by lazy { +internal val powerCollection: List by lazy { listOf( NormalUnit(UnitID.attowatt, BigDecimal("1"), UnitGroup.POWER, R.string.unit_attowatt, R.string.unit_attowatt_short), NormalUnit(UnitID.watt, BigDecimal("1000000000000000000"), UnitGroup.POWER, R.string.unit_watt, R.string.unit_watt_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Prefix.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Prefix.kt index 8a850c5d..9971d8da 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Prefix.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Prefix.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -val prefixCollection: List by lazy { +val prefixCollection: List by lazy { listOf( NormalUnit(UnitID.prefix_quetta, BigDecimal("1000000000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_quetta, R.string.unit_prefix_quetta_short), NormalUnit(UnitID.prefix_ronna, BigDecimal("1000000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_ronna, R.string.unit_prefix_ronna_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Pressure.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Pressure.kt index 79379f53..d1802c4a 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Pressure.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Pressure.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val pressureCollection: List by lazy { +internal val pressureCollection: List by lazy { listOf( NormalUnit(UnitID.attopascal, BigDecimal("1"), UnitGroup.PRESSURE, R.string.unit_attopascal, R.string.unit_attopascal_short), NormalUnit(UnitID.femtopascal, BigDecimal("1000"), UnitGroup.PRESSURE, R.string.unit_femtopascal, R.string.unit_femtopascal_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Speed.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Speed.kt index 6712989c..c7ea7fb1 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Speed.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Speed.kt @@ -20,13 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.BackwardUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val speedCollection: List by lazy { +internal val speedCollection: List by lazy { listOf( NormalUnit( UnitID.millimeter_per_hour, BigDecimal("1"), UnitGroup.SPEED, R.string.unit_millimeter_per_hour, R.string.unit_millimeter_per_hour_short), NormalUnit( UnitID.millimeter_per_minute, BigDecimal("60"), UnitGroup.SPEED, R.string.unit_millimeter_per_minute, R.string.unit_millimeter_per_minute_short), @@ -49,10 +48,10 @@ internal val speedCollection: List by lazy { NormalUnit( UnitID.mile_per_hour, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_mile_per_hour, R.string.unit_mile_per_hour_short), NormalUnit( UnitID.mile_per_minute, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_mile_per_minute, R.string.unit_mile_per_minute_short), NormalUnit( UnitID.mile_per_second, BigDecimal("5793638400"), UnitGroup.SPEED, R.string.unit_mile_per_second, R.string.unit_mile_per_second_short), - BackwardUnit(UnitID.minute_per_kilometer, BigDecimal("60000000"), UnitGroup.SPEED, R.string.unit_minute_per_kilometer, R.string.unit_minute_per_kilometer_short), - BackwardUnit(UnitID.minute_per_mile, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_minute_per_mile, R.string.unit_minute_per_mile_short), - BackwardUnit(UnitID.hour_per_kilometer, BigDecimal("1000000"), UnitGroup.SPEED, R.string.unit_hour_per_kilometer, R.string.unit_hour_per_kilometer_short), - BackwardUnit(UnitID.hour_per_mile, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_hour_per_mile, R.string.unit_hour_per_mile_short), + NormalUnit(UnitID.minute_per_kilometer, BigDecimal("60000000"), UnitGroup.SPEED, R.string.unit_minute_per_kilometer, R.string.unit_minute_per_kilometer_short, true), + NormalUnit(UnitID.minute_per_mile, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_minute_per_mile, R.string.unit_minute_per_mile_short, true), + NormalUnit(UnitID.hour_per_kilometer, BigDecimal("1000000"), UnitGroup.SPEED, R.string.unit_hour_per_kilometer, R.string.unit_hour_per_kilometer_short, true), + NormalUnit(UnitID.hour_per_mile, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_hour_per_mile, R.string.unit_hour_per_mile_short, true), NormalUnit( UnitID.knot, BigDecimal("1852000"), UnitGroup.SPEED, R.string.unit_knot, R.string.unit_knot_short), NormalUnit( UnitID.velocity_of_light_in_vacuum, BigDecimal("1079252848799998"), UnitGroup.SPEED, R.string.unit_velocity_of_light_in_vacuum, R.string.unit_velocity_of_light_in_vacuum_short), NormalUnit( UnitID.cosmic_velocity_first, BigDecimal("28440000000"), UnitGroup.SPEED, R.string.unit_cosmic_velocity_first, R.string.unit_cosmic_velocity_first_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Temperature.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Temperature.kt index 5ede22af..ca1ef537 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Temperature.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Temperature.kt @@ -21,89 +21,90 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.MAX_PRECISION import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.TemperatureUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit import java.math.BigDecimal import java.math.RoundingMode -internal val temperatureCollection: List by lazy { - listOf( - TemperatureUnit( - id = UnitID.celsius, - basicUnit = BigDecimal.ONE, - group = UnitGroup.TEMPERATURE, - displayName = R.string.unit_celsius, - shortName = R.string.unit_celsius_short, - customConvert = { unitTo, value -> - when (unitTo.id) { - UnitID.fahrenheit -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .times(BigDecimal("1.8")) - .plus(BigDecimal("32")) - } +internal val temperatureCollection: List by lazy { + val celsius = object : BasicUnit.Default { + override val id: String = UnitID.celsius + override val group: UnitGroup = UnitGroup.TEMPERATURE + override val displayName: Int = R.string.unit_celsius + override val shortName: Int = R.string.unit_celsius_short + override val factor: BigDecimal = BigDecimal.ONE + override val backward: Boolean = false - UnitID.kelvin -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .plus(BigDecimal("273.15")) - } + override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) { + UnitID.fahrenheit -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .times(BigDecimal("1.8")) + .plus(BigDecimal("32")) + } - else -> value - } + UnitID.kelvin -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .plus(BigDecimal("273.15")) } - ), - TemperatureUnit( - id = UnitID.fahrenheit, - basicUnit = BigDecimal.ONE, - group = UnitGroup.TEMPERATURE, - displayName = R.string.unit_fahrenheit, - shortName = R.string.unit_fahrenheit_short, - customConvert = { unitTo, value -> - when (unitTo.id) { - UnitID.celsius -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .minus(BigDecimal("32")) - .times(BigDecimal("5")) - .div(BigDecimal("9")) - } - UnitID.kelvin -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .minus(BigDecimal("32")) - .times(BigDecimal("5")) - .div(BigDecimal("9")) - .add(BigDecimal("273.15")) - } - else -> value - } + + else -> value + } + } + + val fahrenheit = object : BasicUnit.Default { + override val id: String = UnitID.fahrenheit + override val group: UnitGroup = UnitGroup.TEMPERATURE + override val displayName: Int = R.string.unit_fahrenheit + override val shortName: Int = R.string.unit_fahrenheit_short + override val factor: BigDecimal = BigDecimal.ONE + override val backward: Boolean = false + + override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) { + UnitID.celsius -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .minus(BigDecimal("32")) + .times(BigDecimal("5")) + .div(BigDecimal("9")) } - ), - TemperatureUnit( - id = UnitID.kelvin, - basicUnit = BigDecimal.ONE, - group = UnitGroup.TEMPERATURE, - displayName = R.string.unit_kelvin, - shortName = R.string.unit_kelvin_short, - customConvert = { unitTo, value -> - when (unitTo.id) { - UnitID.celsius -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .minus(BigDecimal("273.15")) - } - UnitID.fahrenheit -> { - value - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .minus(BigDecimal("273.15")) - .times(BigDecimal("1.8")) - .plus(BigDecimal("32")) - } - else -> value - } + UnitID.kelvin -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .minus(BigDecimal("32")) + .times(BigDecimal("5")) + .div(BigDecimal("9")) + .add(BigDecimal("273.15")) } - ), - ) + else -> value + } + } + + val kelvin = object : BasicUnit.Default { + override val id: String = UnitID.kelvin + override val group: UnitGroup = UnitGroup.TEMPERATURE + override val displayName: Int = R.string.unit_kelvin + override val shortName: Int = R.string.unit_kelvin_short + override val factor: BigDecimal = BigDecimal.ONE + override val backward: Boolean = false + + override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) { + UnitID.celsius -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .minus(BigDecimal("273.15")) + } + UnitID.fahrenheit -> { + value + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .minus(BigDecimal("273.15")) + .times(BigDecimal("1.8")) + .plus(BigDecimal("32")) + } + else -> value + } + } + + listOf(celsius, fahrenheit, kelvin) } diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Time.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Time.kt index b6da3f8c..6945d594 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Time.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Time.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val timeCollection: List by lazy { +internal val timeCollection: List by lazy { listOf( NormalUnit(UnitID.attosecond, BigDecimal("1"), UnitGroup.TIME, R.string.unit_attosecond, R.string.unit_attosecond_short), NormalUnit(UnitID.nanosecond, BigDecimal("1000000000"), UnitGroup.TIME, R.string.unit_nanosecond, R.string.unit_nanosecond_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Torque.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Torque.kt index 9eb39b50..640cea4b 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Torque.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Torque.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -val torqueCollection: List by lazy { +val torqueCollection: List by lazy { listOf( NormalUnit(UnitID.dyne_millimeter, BigDecimal("1"), UnitGroup.TORQUE, R.string.unit_dyne_millimeter, R.string.unit_dyne_millimeter_short), NormalUnit(UnitID.dyne_centimeter, BigDecimal("10"), UnitGroup.TORQUE, R.string.unit_dyne_centimeter, R.string.unit_dyne_centimeter_short), diff --git a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Volume.kt b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Volume.kt index c32b456b..1bd2f21d 100644 --- a/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Volume.kt +++ b/data/converter/src/main/java/com/sadellie/unitto/data/converter/collections/Volume.kt @@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections import com.sadellie.unitto.core.base.R import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal -internal val volumeCollection: List by lazy { +internal val volumeCollection: List by lazy { listOf( NormalUnit(UnitID.attoliter, BigDecimal("1"), UnitGroup.VOLUME, R.string.unit_attoliter, R.string.unit_attoliter_short), NormalUnit(UnitID.milliliter, BigDecimal("1000000000000000"), UnitGroup.VOLUME, R.string.unit_milliliter, R.string.unit_milliliter_short), diff --git a/data/converter/src/test/java/com/sadellie/unitto/data/converter/AllUnitsTest.kt b/data/converter/src/test/java/com/sadellie/unitto/data/converter/AllUnitsTest.kt index 1f571d0c..ff0956ad 100644 --- a/data/converter/src/test/java/com/sadellie/unitto/data/converter/AllUnitsTest.kt +++ b/data/converter/src/test/java/com/sadellie/unitto/data/converter/AllUnitsTest.kt @@ -44,10 +44,9 @@ import com.sadellie.unitto.data.converter.collections.temperatureCollection import com.sadellie.unitto.data.converter.collections.timeCollection import com.sadellie.unitto.data.converter.collections.torqueCollection import com.sadellie.unitto.data.converter.collections.volumeCollection -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.DefaultUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit -import com.sadellie.unitto.data.model.unit.ReverseUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.BasicUnit +import com.sadellie.unitto.data.model.converter.unit.NumberBaseUnit import kotlinx.coroutines.runBlocking import org.junit.After import org.junit.Assert.assertEquals @@ -595,13 +594,11 @@ class AllUnitsTest { val actual = when (unitFrom.group) { UnitGroup.NUMBER_BASE -> (unitFrom as NumberBaseUnit).convert((unitTo as NumberBaseUnit), value) - UnitGroup.FLOW_RATE -> (unitFrom as ReverseUnit) - .convert((unitTo as DefaultUnit), BigDecimal(value)) - .format(5, OutputFormat.PLAIN) - else -> (unitFrom as DefaultUnit) - .convert((unitTo as DefaultUnit), BigDecimal(value)) + else -> (unitFrom as BasicUnit.Default) + .convert((unitTo as BasicUnit.Default), BigDecimal(value)) .format(5, OutputFormat.PLAIN) } + assertEquals("Failed at $this to $checkingId", expected, actual) println("PASSED: $this -> $expected == $actual") val content: Set = history.getOrDefault(unitFrom.group, setOf()) diff --git a/data/converter/src/test/java/com/sadellie/unitto/data/converter/ConverterUIStateKtTest.kt b/data/converter/src/test/java/com/sadellie/unitto/data/converter/ConverterUIStateKtTest.kt new file mode 100644 index 00000000..75387f0f --- /dev/null +++ b/data/converter/src/test/java/com/sadellie/unitto/data/converter/ConverterUIStateKtTest.kt @@ -0,0 +1,247 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.data.converter + +import android.content.Context +import com.sadellie.unitto.data.database.CurrencyRatesDao +import com.sadellie.unitto.data.database.CurrencyRatesEntity +import com.sadellie.unitto.data.database.UnitsDao +import com.sadellie.unitto.data.database.UnitsEntity +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.NormalUnit +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment +import java.math.BigDecimal + +@RunWith(RobolectricTestRunner::class) +class ConverterUIStateKtTest { + + @Test + fun convertTime() { + var basicValue = BigDecimal("1") + val mContext: Context = RuntimeEnvironment.getApplication().applicationContext + val repo = UnitsRepositoryImpl( + unitsDao = object : UnitsDao { + override fun getAllFlow(): Flow> = emptyFlow() + override suspend fun insertUnit(unit: UnitsEntity) {} + override suspend fun getById(unitId: String): UnitsEntity? = null + override suspend fun clear() {} + }, + currencyRatesDao = object : CurrencyRatesDao { + override suspend fun insertRates(currencyRates: List) {} + override suspend fun getLatestRateTimeStamp(baseId: String): Long? = null + override suspend fun getLatestRates(baseId: String): List = emptyList() + override suspend fun getLatestRate(baseId: String, pairId: String): CurrencyRatesEntity? = null + override fun size(): Flow = emptyFlow() + override suspend fun clear() {} + }, + mContext = mContext, + ) + + fun String.formatTime(): ConverterResult.Time { + val unitFrom = NormalUnit( + id = "", + factor = basicValue, + group = UnitGroup.TIME, + displayName = 0, + shortName = 0, + backward = false, + ) + + return repo.convertTime(unitFrom, BigDecimal(this)) + } + + // Edgy things (minus, decimals and zeros) + assertEquals( + ConverterResult.Time( + negative = true, + attosecond = BigDecimal("28"), + ), + "-28".formatTime(), + ) + + assertEquals( + ConverterResult.Time( + negative = true, + attosecond = BigDecimal("0.05"), + ), + "-0.05".formatTime(), + ) + + assertEquals( + ConverterResult.Time(), + "0".formatTime(), + ) + + basicValue = BigDecimal("86400000000000000000000") + assertEquals( + ConverterResult.Time( + negative = true, + day = BigDecimal("28"), + ), + "-28".formatTime(), + ) + assertEquals( + ConverterResult.Time( + negative = true, + hour = BigDecimal("1"), + minute = BigDecimal("12"), + ), + "-0.05".formatTime(), + ) + assertEquals( + ConverterResult.Time(), + "0".formatTime(), + ) + assertEquals( + ConverterResult.Time(), + "-0".formatTime(), + ) + + // DAYS + basicValue = BigDecimal("86400000000000000000000") + assertEquals( + ConverterResult.Time( + hour = BigDecimal("12"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + day = BigDecimal("90"), + minute = BigDecimal("7"), + second = BigDecimal("12"), + ), + "90.005".formatTime(), + ) + + // HOURS + basicValue = BigDecimal("3600000000000000000000") + assertEquals( + ConverterResult.Time( + minute = BigDecimal("30"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + day = BigDecimal("3"), + hour = BigDecimal("18"), + second = BigDecimal("18"), + ), + "90.005".formatTime(), + ) + + // MINUTES + basicValue = BigDecimal("60000000000000000000") + assertEquals( + ConverterResult.Time( + second = BigDecimal("30"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + hour = BigDecimal("1"), + minute = BigDecimal("30"), + millisecond = BigDecimal("300"), + ), + "90.005".formatTime(), + ) + + // SECONDS + basicValue = BigDecimal("1000000000000000000") + assertEquals( + ConverterResult.Time( + millisecond = BigDecimal("500"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + minute = BigDecimal("1"), + second = BigDecimal("30"), + millisecond = BigDecimal("5"), + ), + "90.005".formatTime(), + ) + + // MILLISECONDS + basicValue = BigDecimal("1000000000000000") + assertEquals( + ConverterResult.Time( + microsecond = BigDecimal("500"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + millisecond = BigDecimal("90"), + microsecond = BigDecimal("5"), + ), + "90.005".formatTime(), + ) + + // MICROSECONDS + basicValue = BigDecimal("1000000000000") + assertEquals( + ConverterResult.Time( + nanosecond = BigDecimal("500"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + microsecond = BigDecimal("90"), + nanosecond = BigDecimal("5"), + ), + "90.005".formatTime(), + ) + + // NANOSECONDS + basicValue = BigDecimal("1000000000") + assertEquals( + ConverterResult.Time( + nanosecond = BigDecimal("90"), + attosecond = BigDecimal("5000000"), + ), + "90.005".formatTime(), + ) + + // ATTOSECONDS + basicValue = BigDecimal("1") + assertEquals( + ConverterResult.Time( + attosecond = BigDecimal("0.5"), + ), + "0.5".formatTime(), + ) + assertEquals( + ConverterResult.Time( + attosecond = BigDecimal("90.005"), + ), + "90.005".formatTime(), + ) + } +} diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesDao.kt b/data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesDao.kt index 58ea3c4b..b89aa92a 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesDao.kt +++ b/data/database/src/main/java/com/sadellie/unitto/data/database/CurrencyRatesDao.kt @@ -30,9 +30,15 @@ interface CurrencyRatesDao { @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertRates(currencyRates: List) + @Query("SELECT DISTINCT timestamp FROM currency_rates WHERE base_unit_id = :baseId") + suspend fun getLatestRateTimeStamp(baseId: String): Long? + @Query("SELECT DISTINCT * FROM currency_rates WHERE timestamp = (SELECT MAX(timestamp) FROM currency_rates) AND base_unit_id = :baseId") suspend fun getLatestRates(baseId: String): List + @Query("SELECT DISTINCT * FROM currency_rates WHERE timestamp = (SELECT MAX(timestamp) FROM currency_rates) AND base_unit_id = :baseId AND pair_unit_id = :pairId") + suspend fun getLatestRate(baseId: String, pairId: String): CurrencyRatesEntity? + @Query("SELECT COUNT(*) from currency_rates") fun size(): Flow diff --git a/data/database/src/main/java/com/sadellie/unitto/data/database/UnitsEntity.kt b/data/database/src/main/java/com/sadellie/unitto/data/database/UnitsEntity.kt index 22b9c5cb..de0ed8e1 100644 --- a/data/database/src/main/java/com/sadellie/unitto/data/database/UnitsEntity.kt +++ b/data/database/src/main/java/com/sadellie/unitto/data/database/UnitsEntity.kt @@ -30,7 +30,7 @@ import androidx.room.PrimaryKey * @param frequency Show the amount of time this unit was used */ @Entity(tableName = "units") -class UnitsEntity( +data class UnitsEntity( @PrimaryKey val unitId: String, @ColumnInfo(name = "is_favorite") val isFavorite: Boolean = false, @ColumnInfo(name = "paired_unit_id") val pairedUnitId: String? = null, diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/UnitGroup.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/UnitGroup.kt similarity index 97% rename from data/model/src/main/java/com/sadellie/unitto/data/model/UnitGroup.kt rename to data/model/src/main/java/com/sadellie/unitto/data/model/converter/UnitGroup.kt index e279bc29..7931e258 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/UnitGroup.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/UnitGroup.kt @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model +package com.sadellie.unitto.data.model.converter import androidx.annotation.StringRes import com.sadellie.unitto.core.base.R diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/UnitsListSorting.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/UnitsListSorting.kt similarity index 94% rename from data/model/src/main/java/com/sadellie/unitto/data/model/UnitsListSorting.kt rename to data/model/src/main/java/com/sadellie/unitto/data/model/converter/UnitsListSorting.kt index b688182f..3f90abd4 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/UnitsListSorting.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/UnitsListSorting.kt @@ -16,6 +16,6 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model +package com.sadellie.unitto.data.model.converter enum class UnitsListSorting { USAGE, ALPHABETICAL, SCALE_DESC, SCALE_ASC } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/BasicUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/BasicUnit.kt new file mode 100644 index 00000000..2dec14bc --- /dev/null +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/BasicUnit.kt @@ -0,0 +1,47 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2023-2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.data.model.converter.unit + +import androidx.annotation.StringRes +import com.sadellie.unitto.data.model.converter.UnitGroup +import java.math.BigDecimal + +sealed interface BasicUnit { + + val id: String + + val group: UnitGroup + + @get:StringRes + val displayName: Int + + @get:StringRes val shortName: Int + + val factor: BigDecimal + + interface NumberBase : BasicUnit { + fun convert(unitTo: NumberBase, value: String): String + } + + interface Default : BasicUnit { + val backward: Boolean + + fun convert(unitTo: Default, value: BigDecimal): BigDecimal + } +} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/BackwardUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/NormalUnit.kt similarity index 50% rename from data/model/src/main/java/com/sadellie/unitto/data/model/unit/BackwardUnit.kt rename to data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/NormalUnit.kt index 85e89e36..fb3d96dc 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/BackwardUnit.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/NormalUnit.kt @@ -16,64 +16,56 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.data.model.unit +package com.sadellie.unitto.data.model.converter.unit import com.sadellie.unitto.core.base.MAX_PRECISION import com.sadellie.unitto.data.common.isEqualTo -import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitGroup import java.math.BigDecimal import java.math.RoundingMode -data class BackwardUnit( +data class NormalUnit( override val id: String, - override val basicUnit: BigDecimal, + override val factor: BigDecimal, override val group: UnitGroup, override val displayName: Int, override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, -) : DefaultUnit { - override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { - // Avoid division by zero - if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO - - return when (unitTo) { - is NormalUnit -> - this - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .div(unitTo.basicUnit) - .div(value) - - is BackwardUnit -> + override val backward: Boolean = false, +) : BasicUnit.Default { + override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal { + if (value.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO + return when { + // BACKWARD -> BACKWARD + backward and unitTo.backward -> unitTo - .basicUnit + .factor .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) .multiply(value) - .div(this.basicUnit) + .div(this.factor) - else -> BigDecimal.ZERO + // BACKWARD -> FORWARD + backward and !unitTo.backward -> + this + .factor + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .div(unitTo.factor) + .div(value) + + // FORWARD -> BACKWARD + !backward and unitTo.backward -> + unitTo + .factor + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .div(this.factor) + .div(value) + + // FORWARD -> FORWARD + else -> + this + .factor + .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) + .multiply(value) + .div(unitTo.factor) } } - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): BackwardUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) } diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/NumberBaseUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/NumberBaseUnit.kt new file mode 100644 index 00000000..65cc22c3 --- /dev/null +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/converter/unit/NumberBaseUnit.kt @@ -0,0 +1,34 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.data.model.converter.unit + +import com.sadellie.unitto.data.model.converter.UnitGroup +import java.math.BigDecimal + +data class NumberBaseUnit( + override val id: String, + override val factor: BigDecimal, + override val group: UnitGroup, + override val displayName: Int, + override val shortName: Int, +) : BasicUnit.NumberBase { + override fun convert(unitTo: BasicUnit.NumberBase, value: String): String = value + .toBigInteger(factor.intValueExact()) + .toString(unitTo.factor.intValueExact()) +} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UnitsRepository.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UnitsRepository.kt deleted file mode 100644 index 3dd07e63..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UnitsRepository.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.repository - -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit -import kotlinx.coroutines.flow.Flow -import java.time.LocalDate - -interface UnitsRepository { - val units: Flow> - - suspend fun getById(id: String): AbstractUnit - - suspend fun getCollection(group: UnitGroup): List - - suspend fun favorite(unit: AbstractUnit) - - suspend fun incrementCounter(unit: AbstractUnit) - - suspend fun setPair(unit: AbstractUnit, pair: AbstractUnit) - - suspend fun updateRates(unit: AbstractUnit): LocalDate? - - suspend fun filterUnits( - query: String, - unitGroup: UnitGroup?, - favoritesOnly: Boolean, - hideBrokenUnits: Boolean, - sorting: UnitsListSorting, - shownUnitGroups: List = emptyList(), - ): Map> -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt index c66c76eb..36ca775d 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/repository/UserPreferencesRepository.kt @@ -18,9 +18,8 @@ package com.sadellie.unitto.data.model.repository -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting import com.sadellie.unitto.data.model.userprefs.AboutPreferences import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences import com.sadellie.unitto.data.model.userprefs.AppPreferences @@ -55,7 +54,7 @@ interface UserPreferencesRepository { suspend fun updateOutputFormat(outputFormat: Int) - suspend fun updateLatestPairOfUnits(unitFrom: AbstractUnit, unitTo: AbstractUnit) + suspend fun updateLatestPairOfUnits(unitFrom: String, unitTo: String) suspend fun updateThemingMode(themingMode: ThemingMode) 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 deleted file mode 100644 index a37ed501..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NormalUnit.kt +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -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 - -data class NormalUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, -) : DefaultUnit { - override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { - // Avoid division by zero - if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO - - return when (unitTo) { - is NormalUnit -> - this - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .multiply(value) - .div(unitTo.basicUnit) - - is BackwardUnit -> - unitTo - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .div(this.basicUnit) - .div(value) - - else -> BigDecimal.ZERO - } - } - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): NormalUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NumberBaseUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NumberBaseUnit.kt deleted file mode 100644 index f34dc90a..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/NumberBaseUnit.kt +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.unit - -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal - -data class NumberBaseUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, -) : AbstractUnit { - fun convert(toBase: NumberBaseUnit, input: String): String { - return input.toBigInteger(basicUnit.intValueExact()).toString(toBase.basicUnit.intValueExact()) - } - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): NumberBaseUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/ReverseUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/ReverseUnit.kt deleted file mode 100644 index c9511f45..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/ReverseUnit.kt +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.unit - -import com.sadellie.unitto.core.base.MAX_PRECISION -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal -import java.math.RoundingMode - -data class ReverseUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, -) : DefaultUnit { - override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal { - return unitTo - .basicUnit - .setScale(MAX_PRECISION, RoundingMode.HALF_EVEN) - .div(this.basicUnit) - .multiply(value) - } - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): ReverseUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/TemperatureUnit.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/unit/TemperatureUnit.kt deleted file mode 100644 index f00d9e4f..00000000 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/unit/TemperatureUnit.kt +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.data.model.unit - -import com.sadellie.unitto.data.model.UnitGroup -import java.math.BigDecimal - -data class TemperatureUnit( - override val id: String, - override val basicUnit: BigDecimal, - override val group: UnitGroup, - override val displayName: Int, - override val shortName: Int, - override val isFavorite: Boolean = false, - override val pairId: String? = null, - override val counter: Int = 0, - val customConvert: (unitTo: DefaultUnit, value: BigDecimal) -> BigDecimal, -) : DefaultUnit { - override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal = customConvert(unitTo, value) - - override fun clone( - id: String, - basicUnit: BigDecimal, - group: UnitGroup, - displayName: Int, - shortName: Int, - isFavorite: Boolean, - pairId: String?, - counter: Int, - ): TemperatureUnit = copy( - id = id, - basicUnit = basicUnit, - group = group, - displayName = displayName, - shortName = shortName, - isFavorite = isFavorite, - pairId = pairId, - counter = counter, - ) -} diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/ConverterPreferences.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/ConverterPreferences.kt index bde5dbd1..d802fa0e 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/ConverterPreferences.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/ConverterPreferences.kt @@ -19,8 +19,8 @@ package com.sadellie.unitto.data.model.userprefs import com.sadellie.unitto.core.base.FormatterSymbols -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting interface ConverterPreferences { val formatterSymbols: FormatterSymbols diff --git a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/UnitGroupsPreferences.kt b/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/UnitGroupsPreferences.kt index ba0c3555..9ddcc22d 100644 --- a/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/UnitGroupsPreferences.kt +++ b/data/model/src/main/java/com/sadellie/unitto/data/model/userprefs/UnitGroupsPreferences.kt @@ -18,7 +18,7 @@ package com.sadellie.unitto.data.model.userprefs -import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitGroup interface UnitGroupsPreferences { val shownUnitGroups: List diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt index 3620950b..fedb2d4c 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt +++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceExt.kt @@ -24,8 +24,8 @@ import com.sadellie.unitto.core.base.OutputFormat import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.base.TopLevelDestinations import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting import io.github.sadellie.themmo.core.MonetMode import io.github.sadellie.themmo.core.ThemingMode diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt index 98913d3f..a162cbe1 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt +++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/PreferenceModels.kt @@ -19,8 +19,8 @@ package com.sadellie.unitto.data.userprefs import com.sadellie.unitto.core.base.FormatterSymbols -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting import com.sadellie.unitto.data.model.userprefs.AboutPreferences import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences import com.sadellie.unitto.data.model.userprefs.AppPreferences diff --git a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferencesRepositoryImpl.kt b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferencesRepositoryImpl.kt index faa5d123..6bf07706 100644 --- a/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferencesRepositoryImpl.kt +++ b/data/userprefs/src/main/java/com/sadellie/unitto/data/userprefs/UserPreferencesRepositoryImpl.kt @@ -22,10 +22,9 @@ import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.emptyPreferences -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import com.sadellie.unitto.data.model.unit.AbstractUnit import com.sadellie.unitto.data.model.userprefs.AboutPreferences import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences import com.sadellie.unitto.data.model.userprefs.AppPreferences @@ -182,10 +181,10 @@ class UserPreferencesRepositoryImpl @Inject constructor( } } - override suspend fun updateLatestPairOfUnits(unitFrom: AbstractUnit, unitTo: AbstractUnit) { + override suspend fun updateLatestPairOfUnits(unitFrom: String, unitTo: String) { dataStore.edit { preferences -> - preferences[PrefsKeys.LATEST_LEFT_SIDE] = unitFrom.id - preferences[PrefsKeys.LATEST_RIGHT_SIDE] = unitTo.id + preferences[PrefsKeys.LATEST_LEFT_SIDE] = unitFrom + preferences[PrefsKeys.LATEST_RIGHT_SIDE] = unitTo } } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt index f18f63c6..cbe70452 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterScreen.kt @@ -55,6 +55,7 @@ import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -83,24 +84,30 @@ import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField import com.sadellie.unitto.core.ui.common.textfield.NumberBaseTextField import com.sadellie.unitto.core.ui.common.textfield.SimpleTextField +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.datetime.formatDateWeekDayMonthYear import com.sadellie.unitto.data.common.format +import com.sadellie.unitto.data.common.isEqualTo +import com.sadellie.unitto.data.common.isExpression +import com.sadellie.unitto.data.converter.ConverterResult import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit +import com.sadellie.unitto.data.model.converter.UnitGroup import com.sadellie.unitto.feature.converter.components.DefaultKeyboard import com.sadellie.unitto.feature.converter.components.NumberBaseKeyboard import com.sadellie.unitto.feature.converter.components.UnitSelectionButton +import java.math.BigDecimal import java.util.Locale @Composable internal fun ConverterRoute( viewModel: ConverterViewModel = hiltViewModel(), - navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit, - navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit, + navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit, + navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit, openDrawer: () -> Unit, ) { - val uiState = viewModel.converterUiState.collectAsStateWithLifecycle() + val uiState = viewModel.converterUIState.collectAsStateWithLifecycle() ConverterScreen( uiState = uiState.value, @@ -108,30 +115,24 @@ internal fun ConverterRoute( navigateToRightScreen = navigateToRightScreen, openDrawer = openDrawer, swapUnits = viewModel::swapUnits, - processInput = viewModel::addTokens, - deleteDigit = viewModel::deleteTokens, - clearInput = viewModel::clearInput, - onValueChange = viewModel::updateInput, - onFocusOnInput2 = viewModel::updateFocused, - onErrorClick = viewModel::updateCurrencyRates, - addBracket = viewModel::addBracket, + updateInput1 = viewModel::updateInput1, + updateInput2 = viewModel::updateInput2, + convertDefault = viewModel::convertDefault, + convertNumberBase = viewModel::convertNumberBase, ) } @Composable private fun ConverterScreen( uiState: UnitConverterUIState, - navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit, - navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit, + navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit, + navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit, openDrawer: () -> Unit, - swapUnits: () -> Unit, - processInput: (String) -> Unit, - deleteDigit: () -> Unit, - clearInput: () -> Unit, - onValueChange: (TextFieldValue) -> Unit, - onFocusOnInput2: (Boolean) -> Unit, - onErrorClick: (AbstractUnit) -> Unit, - addBracket: () -> Unit, + swapUnits: (String, String) -> Unit, + updateInput1: (TextFieldValue) -> Unit, + updateInput2: (TextFieldValue) -> Unit, + convertDefault: () -> Unit, + convertNumberBase: () -> Unit, ) { when (uiState) { UnitConverterUIState.Loading -> EmptyScreen() @@ -143,13 +144,11 @@ private fun ConverterScreen( NumberBase( modifier = Modifier.padding(it), uiState = uiState, - onValueChange = onValueChange, - processInput = processInput, - deleteDigit = deleteDigit, + updateInput1 = updateInput1, navigateToLeftScreen = navigateToLeftScreen, swapUnits = swapUnits, navigateToRightScreen = navigateToRightScreen, - clearInput = clearInput, + convert = convertNumberBase, ) } } @@ -161,16 +160,12 @@ private fun ConverterScreen( Default( modifier = Modifier.padding(it), uiState = uiState, - onValueChange = onValueChange, - onFocusOnInput2 = onFocusOnInput2, - processInput = processInput, - deleteDigit = deleteDigit, + updateInput1 = updateInput1, + updateInput2 = updateInput2, navigateToLeftScreen = navigateToLeftScreen, swapUnits = swapUnits, navigateToRightScreen = navigateToRightScreen, - clearInput = clearInput, - refreshCurrencyRates = onErrorClick, - addBracket = addBracket, + convert = convertDefault, ) } } @@ -194,14 +189,20 @@ private fun UnitConverterTopBar( private fun NumberBase( modifier: Modifier, uiState: UnitConverterUIState.NumberBase, - onValueChange: (TextFieldValue) -> Unit, - processInput: (String) -> Unit, - deleteDigit: () -> Unit, - navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit, - swapUnits: () -> Unit, - navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit, - clearInput: () -> Unit, + updateInput1: (TextFieldValue) -> Unit, + navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit, + swapUnits: (String, String) -> Unit, + navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit, + convert: () -> Unit, ) { + LaunchedEffect( + uiState.input.text, + uiState.unitFrom.id, + uiState.unitTo.id, + ) { + convert() + } + PortraitLandscape( modifier = modifier.fillMaxSize(), content1 = { contentModifier -> @@ -213,7 +214,7 @@ private fun NumberBase( minRatio = 0.7f, placeholder = Token.Digit._0, value = uiState.input, - onValueChange = onValueChange, + onValueChange = updateInput1, ) AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName)) @@ -228,18 +229,27 @@ private fun NumberBase( UnitSelectionButtons( unitFromLabel = stringResource(uiState.unitFrom.displayName), unitToLabel = stringResource(uiState.unitTo.displayName), - swapUnits = swapUnits, - navigateToLeftScreen = { navigateToLeftScreen(uiState) }, - navigateToRightScreen = { navigateToRightScreen(uiState) }, + swapUnits = { swapUnits(uiState.unitTo.id, uiState.unitFrom.id) }, + navigateToLeftScreen = { + navigateToLeftScreen(uiState.unitFrom.id, uiState.unitFrom.group) + }, + navigateToRightScreen = { + navigateToRightScreen( + uiState.unitFrom.id, + uiState.unitTo.id, + uiState.unitFrom.group, + uiState.input.text, + ) + }, ) } }, - content2 = { + content2 = { modifier2 -> NumberBaseKeyboard( - modifier = it, - addDigit = processInput, - deleteDigit = deleteDigit, - clearInput = clearInput, + modifier = modifier2, + addDigit = { updateInput1(uiState.input.addTokens(it)) }, + deleteDigit = { updateInput1(uiState.input.deleteTokens()) }, + clearInput = { updateInput1(TextFieldValue()) }, ) }, ) @@ -249,22 +259,21 @@ private fun NumberBase( private fun Default( modifier: Modifier, uiState: UnitConverterUIState.Default, - onValueChange: (TextFieldValue) -> Unit, - onFocusOnInput2: (Boolean) -> Unit, - processInput: (String) -> Unit, - deleteDigit: () -> Unit, - navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit, - swapUnits: () -> Unit, - navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit, - clearInput: () -> Unit, - refreshCurrencyRates: (AbstractUnit) -> Unit, - addBracket: () -> Unit, + updateInput1: (TextFieldValue) -> Unit, + updateInput2: (TextFieldValue) -> Unit, + navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit, + swapUnits: (String, String) -> Unit, + navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit, + convert: () -> Unit, ) { val locale: Locale = LocalLocale.current - var calculation by remember(uiState.calculation) { - mutableStateOf( - TextFieldValue(uiState.calculation?.format(uiState.scale, uiState.outputFormat) ?: ""), - ) + val showCalculation = remember(uiState.input1.text, uiState.result) { + if (uiState.input1.text.isExpression()) { + if (uiState.result is ConverterResult.Default) { + return@remember !uiState.result.calculation.isEqualTo(BigDecimal.ZERO) + } + } + false } val connection by connectivityState() val lastUpdate by remember(uiState.currencyRateUpdateState) { @@ -273,14 +282,25 @@ private fun Default( uiState.currencyRateUpdateState.date.formatDateWeekDayMonthYear(locale) } } + var focusedOnInput1 by rememberSaveable { mutableStateOf(true) } LaunchedEffect(connection) { - if ((connection == ConnectionState.Available) and (uiState.result == ConverterResult.Error)) { + if ((connection == ConnectionState.Available) and (uiState.result is ConverterResult.Error)) { val unitFrom = uiState.unitFrom - if (unitFrom.group == UnitGroup.CURRENCY) refreshCurrencyRates(unitFrom) + if (unitFrom.group == UnitGroup.CURRENCY) convert() } } + LaunchedEffect( + uiState.input1.text, + uiState.input2.text, + uiState.unitFrom.id, + uiState.unitTo.id, + uiState.formatTime, + ) { + convert() + } + PortraitLandscape( modifier = modifier.fillMaxSize(), content1 = { contentModifier -> @@ -322,7 +342,7 @@ private fun Default( .weight(1f), value = uiState.input1, minRatio = 0.7f, - onValueChange = onValueChange, + onValueChange = updateInput1, formatterSymbols = uiState.formatterSymbols, placeholder = Token.Digit._0, ) @@ -340,10 +360,10 @@ private fun Default( modifier = Modifier .fillMaxWidth() .weight(1f) - .onFocusEvent { state -> onFocusOnInput2(state.hasFocus) }, + .onFocusEvent { state -> focusedOnInput1 = !state.hasFocus }, value = uiState.input2, minRatio = 0.7f, - onValueChange = onValueChange, + onValueChange = updateInput2, formatterSymbols = uiState.formatterSymbols, placeholder = Token.Digit._0, ) @@ -355,21 +375,30 @@ private fun Default( modifier = textFieldModifier, value = uiState.input1, minRatio = 0.7f, - onValueChange = onValueChange, + onValueChange = updateInput1, formatterSymbols = uiState.formatterSymbols, placeholder = Token.Digit._0, ) AnimatedVisibility( - visible = calculation.text.isNotEmpty(), + visible = showCalculation, modifier = Modifier.weight(1f), enter = expandVertically(clip = false), exit = shrinkVertically(clip = false), ) { + var calculationTextField by remember(uiState.result) { + val text = if (uiState.result is ConverterResult.Default) { + uiState.result.calculation + .format(uiState.scale, uiState.outputFormat) + } else { + "" + } + mutableStateOf(TextFieldValue(text)) + } ExpressionTextField( modifier = Modifier, - value = calculation, + value = calculationTextField, minRatio = 0.7f, - onValueChange = { calculation = it }, + onValueChange = { calculationTextField = it }, textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f), formatterSymbols = uiState.formatterSymbols, readOnly = true, @@ -384,14 +413,14 @@ private fun Default( scale = uiState.scale, outputFormat = uiState.outputFormat, formatterSymbols = uiState.formatterSymbols, - onErrorClick = { refreshCurrencyRates(uiState.unitFrom) }, + onErrorClick = convert, ) AnimatedUnitShortName( stringResource( - if (uiState.result is ConverterResult.Error) { - R.string.click_to_try_again_label - } else { - uiState.unitTo.shortName + when (uiState.result) { + // Currency conversion can be retried + is ConverterResult.Error.Currency -> R.string.click_to_try_again_label + else -> uiState.unitTo.shortName }, ), ) @@ -401,22 +430,58 @@ private fun Default( UnitSelectionButtons( unitFromLabel = stringResource(uiState.unitFrom.displayName), unitToLabel = stringResource(uiState.unitTo.displayName), - swapUnits = swapUnits, - navigateToLeftScreen = { navigateToLeftScreen(uiState) }, - navigateToRightScreen = { navigateToRightScreen(uiState) }, + swapUnits = { swapUnits(uiState.unitTo.id, uiState.unitFrom.id) }, + navigateToLeftScreen = { + navigateToLeftScreen(uiState.unitFrom.id, uiState.unitFrom.group) + }, + navigateToRightScreen = { + val input = if (uiState.result is ConverterResult.Default) { + uiState.result.calculation.toPlainString() + } else { + uiState.input1.text + } + + navigateToRightScreen( + uiState.unitFrom.id, + uiState.unitTo.id, + uiState.unitFrom.group, + input, + ) + }, ) } }, - content2 = { + content2 = { modifier2 -> DefaultKeyboard( - modifier = it, - addDigit = processInput, - deleteDigit = deleteDigit, - clearInput = clearInput, + modifier = modifier2, + addDigit = { + if (focusedOnInput1) { + updateInput1(uiState.input1.addTokens(it)) + } else { + updateInput2(uiState.input2.addTokens(it)) + } + }, + deleteDigit = { + if (focusedOnInput1) { + updateInput1(uiState.input1.deleteTokens()) + } else { + updateInput2(uiState.input2.deleteTokens()) + } + }, + clearInput = { + updateInput1(TextFieldValue()) + updateInput2(TextFieldValue()) + }, fractional = uiState.formatterSymbols.fractional, middleZero = uiState.middleZero, acButton = uiState.acButton, - addBracket = addBracket, + addBracket = { + if (focusedOnInput1) { + updateInput1(uiState.input1.addBracket()) + } else { + updateInput2(uiState.input2.addBracket()) + } + }, ) }, ) @@ -454,6 +519,17 @@ private fun ConverterResultTextField( ) } + is ConverterResult.Error.DivideByZero -> { + SimpleTextField( + modifier = modifier, + value = TextFieldValue(stringResource(R.string.calculator_divide_by_zero_error)), + onValueChange = { onErrorClick() }, + minRatio = 0.7f, + readOnly = true, + textColor = MaterialTheme.colorScheme.error, + ) + } + is ConverterResult.Error -> { SimpleTextField( modifier = modifier, @@ -578,16 +654,13 @@ private fun UnitSelectionButtons( private fun PreviewConverterScreen() { ConverterScreen( uiState = UnitConverterUIState.Loading, - navigateToLeftScreen = {}, - navigateToRightScreen = {}, + navigateToLeftScreen = { _, _ -> }, + navigateToRightScreen = { _, _, _, _ -> }, openDrawer = {}, - swapUnits = {}, - processInput = {}, - deleteDigit = {}, - clearInput = {}, - onValueChange = {}, - onFocusOnInput2 = {}, - onErrorClick = {}, - addBracket = {}, + swapUnits = { _, _ -> }, + updateInput1 = {}, + updateInput2 = {}, + convertDefault = {}, + convertNumberBase = {}, ) } 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 4d18b048..598a3b06 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 @@ -25,14 +25,10 @@ import com.sadellie.unitto.core.base.R import com.sadellie.unitto.core.base.Token import com.sadellie.unitto.core.ui.common.textfield.formatExpression import com.sadellie.unitto.data.common.format -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 +import com.sadellie.unitto.data.converter.ConverterResult +import com.sadellie.unitto.data.model.converter.unit.BasicUnit import java.math.BigDecimal -import java.math.RoundingMode internal sealed class UnitConverterUIState { data object Loading : UnitConverterUIState() @@ -40,10 +36,9 @@ internal sealed class UnitConverterUIState { data class Default( val input1: TextFieldValue, val input2: TextFieldValue, - val calculation: BigDecimal?, val result: ConverterResult, - val unitFrom: DefaultUnit, - val unitTo: DefaultUnit, + val unitFrom: BasicUnit.Default, + val unitTo: BasicUnit.Default, val middleZero: Boolean, val formatterSymbols: FormatterSymbols, val scale: Int, @@ -56,45 +51,11 @@ internal sealed class UnitConverterUIState { data class NumberBase( val input: TextFieldValue, val result: ConverterResult, - val unitFrom: NumberBaseUnit, - val unitTo: NumberBaseUnit, + val unitFrom: BasicUnit.NumberBase, + val unitTo: BasicUnit.NumberBase, ) : UnitConverterUIState() } -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.isEqualTo(other.value) - } - - override fun hashCode(): Int = value.hashCode() - } - - data class NumberBase(val value: String) : ConverterResult() - - data class Time( - val negative: Boolean, - val day: BigDecimal, - val hour: BigDecimal, - val minute: BigDecimal, - val second: BigDecimal, - val millisecond: BigDecimal, - val microsecond: BigDecimal, - val nanosecond: BigDecimal, - val attosecond: BigDecimal, - ) : ConverterResult() - - data class FootInch( - val foot: BigDecimal, - val inch: BigDecimal, - ) : ConverterResult() - - data object Loading : ConverterResult() - - data object Error : ConverterResult() -} - internal fun ConverterResult.Time.format( mContext: Context, formatterSymbols: FormatterSymbols, @@ -154,110 +115,3 @@ internal fun ConverterResult.FootInch.format( return result } - -internal fun formatTime( - input: BigDecimal, -): ConverterResult.Time { - val negative = input < BigDecimal.ZERO - val inputAbs = input.abs() - - if (inputAbs.isLessThan(attosecondBasicUnit)) { - return ConverterResult.Time( - negative = negative, - day = BigDecimal.ZERO, - hour = BigDecimal.ZERO, - minute = BigDecimal.ZERO, - second = BigDecimal.ZERO, - millisecond = BigDecimal.ZERO, - microsecond = BigDecimal.ZERO, - nanosecond = BigDecimal.ZERO, - attosecond = inputAbs, - ) - } - - if (inputAbs.isLessThan(nanosecondBasicUnit)) { - return ConverterResult.Time( - negative = negative, - day = BigDecimal.ZERO, - hour = BigDecimal.ZERO, - minute = BigDecimal.ZERO, - second = BigDecimal.ZERO, - millisecond = BigDecimal.ZERO, - microsecond = BigDecimal.ZERO, - nanosecond = BigDecimal.ZERO, - attosecond = inputAbs.trimZeros(), - ) - } - - // DAY - var division = inputAbs.divideAndRemainder(dayBasicUnit) - val day = division.component1().setScale(0, RoundingMode.HALF_EVEN) - var remainingSeconds = division.component2().setScale(0, RoundingMode.HALF_EVEN) - - division = remainingSeconds.divideAndRemainder(hourBasicUnit) - val hour = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(minuteBasicUnit) - val minute = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(secondBasicUnit) - val second = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(millisecondBasicUnit) - val millisecond = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(microsecondBasicUnit) - val microsecond = division.component1() - remainingSeconds = division.component2() - - division = remainingSeconds.divideAndRemainder(nanosecondBasicUnit) - val nanosecond = division.component1() - remainingSeconds = division.component2() - - val attosecond = remainingSeconds - - return ConverterResult.Time( - negative = negative, - day = day, - hour = hour, - minute = minute, - second = second, - millisecond = millisecond, - microsecond = microsecond, - nanosecond = nanosecond, - attosecond = attosecond, - ) -} - -/** - * Creates an object for displaying formatted foot and inch output. Units are passed as objects so - * that changes in basic units don't require modifying the method. Also this method can't access - * units repository directly. - * - * @param input Input in feet. - * @param footUnit Foot unit [DefaultUnit]. - * @param inchUnit Inch unit [DefaultUnit]. - * @return Result where decimal places are converter into inches. - */ -internal fun formatFootInch( - input: BigDecimal, - footUnit: DefaultUnit, - inchUnit: DefaultUnit, -): ConverterResult.FootInch { - val (integral, fractional) = input.divideAndRemainder(BigDecimal.ONE) - - return ConverterResult.FootInch(integral, footUnit.convert(inchUnit, fractional)) -} - -private val dayBasicUnit by lazy { BigDecimal("86400000000000000000000") } -private val hourBasicUnit by lazy { BigDecimal("3600000000000000000000") } -private val minuteBasicUnit by lazy { BigDecimal("60000000000000000000") } -private val secondBasicUnit by lazy { BigDecimal("1000000000000000000") } -private val millisecondBasicUnit by lazy { BigDecimal("1000000000000000") } -private val microsecondBasicUnit by lazy { BigDecimal("1000000000000") } -private val nanosecondBasicUnit by lazy { BigDecimal("1000000000") } -private val attosecondBasicUnit by lazy { BigDecimal("1") } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt index 1bbb7cf3..d5bc5078 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/ConverterViewModel.kt @@ -22,365 +22,210 @@ import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.sadellie.unitto.core.base.Token -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.base.OutputFormat import com.sadellie.unitto.core.ui.common.textfield.getTextField import com.sadellie.unitto.data.common.combine -import com.sadellie.unitto.data.common.isExpression import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.repository.UnitsRepository +import com.sadellie.unitto.data.converter.ConverterResult +import com.sadellie.unitto.data.converter.UnitsRepositoryImpl +import com.sadellie.unitto.data.model.converter.unit.BasicUnit import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.DefaultUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit import dagger.hilt.android.lifecycle.HiltViewModel -import io.github.sadellie.evaluatto.Expression -import io.github.sadellie.evaluatto.ExpressionException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.first -import kotlinx.coroutines.flow.getAndUpdate +import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.mapLatest import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import java.math.BigDecimal import javax.inject.Inject @HiltViewModel internal class ConverterViewModel @Inject constructor( private val userPrefsRepository: UserPreferencesRepository, - private val unitsRepo: UnitsRepository, + private val unitsRepo: UnitsRepositoryImpl, private val savedStateHandle: SavedStateHandle, ) : ViewModel() { + private var conversionJob: Job? = null private val converterInputKey1 = "CONVERTER_INPUT_1" private val converterInputKey2 = "CONVERTER_INPUT_2" private val input1 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey1)) private val input2 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey2)) - private val focusedOnInput2 = MutableStateFlow(false) - private val calculation = MutableStateFlow(null) - private val result = MutableStateFlow(ConverterResult.Loading) - private val unitFrom = MutableStateFlow(null) - private val unitTo = MutableStateFlow(null) + private val output = MutableStateFlow(ConverterResult.Loading) - private val currenciesState = MutableStateFlow(CurrencyRateUpdateState.Nothing) - private var loadCurrenciesJob: Job? = null + private val unitFromId = MutableStateFlow(null) + private val unitToId = MutableStateFlow(null) - val converterUiState: StateFlow = combine( + private val unitFrom = unitFromId + .mapLatest { it?.let { unitsRepo.getById(it) } } + .flowOn(Dispatchers.Default) + .stateIn(viewModelScope, null) + + private val unitTo = unitToId + .mapLatest { it?.let { unitsRepo.getById(it) } } + .flowOn(Dispatchers.Default) + .stateIn(viewModelScope, null) + + val converterUIState: StateFlow = combine( input1, input2, - calculation, - result, + output, unitFrom, unitTo, userPrefsRepository.converterPrefs, - currenciesState, - ) { input1, input2, calculation, result, unitFrom, unitTo, prefs, currenciesState -> - return@combine when { - (unitFrom is DefaultUnit) and (unitTo is DefaultUnit) -> { - UnitConverterUIState.Default( - input1 = input1, - input2 = input2, - calculation = calculation, - result = result, - unitFrom = unitFrom as DefaultUnit, - unitTo = unitTo as DefaultUnit, - middleZero = prefs.middleZero, - formatterSymbols = prefs.formatterSymbols, - scale = prefs.precision, - outputFormat = prefs.outputFormat, - formatTime = prefs.unitConverterFormatTime, - currencyRateUpdateState = currenciesState, - acButton = prefs.acButton, - ) - } - (unitFrom is NumberBaseUnit) and (unitTo is NumberBaseUnit) -> { - UnitConverterUIState.NumberBase( - input = input1, - result = result, - unitFrom = unitFrom as NumberBaseUnit, - unitTo = unitTo as NumberBaseUnit, - ) - } - else -> UnitConverterUIState.Loading + ) { input1Value, input2Value, outputValue, unitFromValue, unitToValue, prefs -> + if (unitFromValue == null) return@combine UnitConverterUIState.Loading + if (unitToValue == null) return@combine UnitConverterUIState.Loading + + whenBothAre( + value1 = unitFromValue, + value2 = unitToValue, + ) { unitFrom, unitTo -> + return@combine UnitConverterUIState.Default( + input1 = input1Value, + input2 = input2Value, + result = outputValue, + unitFrom = unitFrom, + unitTo = unitTo, + middleZero = prefs.middleZero, + formatterSymbols = prefs.formatterSymbols, + scale = prefs.precision, + outputFormat = OutputFormat.PLAIN, + formatTime = prefs.unitConverterFormatTime, + currencyRateUpdateState = CurrencyRateUpdateState.Nothing, + acButton = prefs.acButton, + ) } + + whenBothAre( + value1 = unitFromValue, + value2 = unitToValue, + ) { unitFrom, unitTo -> + return@combine UnitConverterUIState.NumberBase( + input = input1Value, + result = outputValue, + unitFrom = unitFrom, + unitTo = unitTo, + ) + } + + return@combine UnitConverterUIState.Loading } - .mapLatest { ui -> - when (currenciesState.value) { - is CurrencyRateUpdateState.Loading -> { - result.update { ConverterResult.Loading } - return@mapLatest ui - } - is CurrencyRateUpdateState.Error -> { - result.update { ConverterResult.Error } - return@mapLatest ui - } - is CurrencyRateUpdateState.Ready, is CurrencyRateUpdateState.Nothing -> {} - } - - when (ui) { - is UnitConverterUIState.Default -> { - convertDefault( - unitFrom = ui.unitFrom, - unitTo = ui.unitTo, - input1 = ui.input1, - input2 = ui.input2, - formatTime = ui.formatTime, - ) - } - is UnitConverterUIState.NumberBase -> { - convertNumberBase( - unitFrom = ui.unitFrom, - unitTo = ui.unitTo, - input = ui.input, - ) - } - is UnitConverterUIState.Loading -> {} - } - - ui - } .stateIn(viewModelScope, UnitConverterUIState.Loading) - fun swapUnits() { - unitFrom - .getAndUpdate { unitTo.value } - .also { oldUnitFrom -> unitTo.update { oldUnitFrom } } + fun updateInput1(value: TextFieldValue) { + input1.update { value } + savedStateHandle[converterInputKey1] = value.text + } - loadCurrenciesJob?.cancel() - currenciesState.update { CurrencyRateUpdateState.Nothing } - unitFrom.value?.let { - if (it.group == UnitGroup.CURRENCY) updateCurrencyRates(it) + fun updateInput2(value: TextFieldValue) { + input2.update { value } + savedStateHandle[converterInputKey2] = value.text + } + + fun updateUnitFromId(id: String) = viewModelScope.launch { + val pairId = unitsRepo.getPairId(id) + + unitFromId.update { id } + unitToId.update { pairId } + + unitsRepo.incrementCounter(id) + updateLatestPairOfUnits() + } + + fun updateUnitToId(id: String) = viewModelScope.launch { + unitToId.update { id } + unitsRepo.incrementCounter(id) + setPair() + updateLatestPairOfUnits() + } + + fun swapUnits( + newUnitFromId: String, + newInputToId: String, + ) = viewModelScope.launch { + unitFromId.update { newUnitFromId } + unitToId.update { newInputToId } + setPair() + updateLatestPairOfUnits() + } + + fun convertDefault() { + conversionJob?.cancel() + conversionJob = viewModelScope.launch { + val result = unitsRepo.convertDefault( + unitFromId = unitFromId.value ?: return@launch, + unitToId = unitToId.value ?: return@launch, + value1 = input1.value.text, + value2 = input2.value.text, + formatTime = userPrefsRepository.converterPrefs.first().unitConverterFormatTime, + ) + + when (result) { + is ConverterResult.Error.BadInput -> Unit + else -> output.update { result } + } } + } - viewModelScope.launch { - val unitTo = unitTo.value ?: return@launch - val unitFrom = unitFrom.value ?: return@launch - - userPrefsRepository.updateLatestPairOfUnits(unitFrom = unitFrom, unitTo = unitTo) + fun convertNumberBase() { + conversionJob?.cancel() + conversionJob = viewModelScope.launch { + unitsRepo.convertNumberBase( + unitFromId = unitFromId.value ?: return@launch, + unitToId = unitToId.value ?: return@launch, + value = input1.value.text, + ) } } + private fun loadInitialUnits() = viewModelScope.launch { + val prefs = userPrefsRepository.converterPrefs.first() + unitFromId.update { prefs.latestLeftSideUnit } + unitToId.update { prefs.latestRightSideUnit } + } + + private fun setPair() = viewModelScope.launch { + unitsRepo.setPair( + id = unitFromId.value ?: return@launch, + pairId = unitToId.value ?: return@launch, + ) + } + + private fun updateLatestPairOfUnits() = viewModelScope.launch { + userPrefsRepository + .updateLatestPairOfUnits( + unitFrom = unitFromId.value ?: return@launch, + unitTo = unitToId.value ?: return@launch, + ) + } + /** - * Change currently focused text field. For feet and inches input + * Will call [block] if both [value1] and [value2] are [T]. * - * @param focusOnInput2 `true` if focus is on inches input. `false`if focus on feet input. + * @param T What to check against. + * @param value1 Value to check. + * @param value2 Value to check. + * @param block Block that will be called if the has passed. */ - fun updateFocused(focusOnInput2: Boolean) = focusedOnInput2.update { focusOnInput2 } - - fun addTokens(tokens: String) { - if (focusedOnInput2.value) { - input2.update { - val newValue = it.addTokens(tokens) - savedStateHandle[converterInputKey2] = newValue.text - newValue - } - } else { - input1.update { - val newValue = it.addTokens(tokens) - savedStateHandle[converterInputKey1] = newValue.text - newValue - } - } - } - - fun addBracket() { - if (focusedOnInput2.value) { - input2.update { - val newValue = it.addBracket() - savedStateHandle[converterInputKey2] = newValue.text - newValue - } - } else { - input1.update { - val newValue = it.addBracket() - savedStateHandle[converterInputKey1] = newValue.text - newValue - } - } - } - - fun deleteTokens() { - if (focusedOnInput2.value) { - input2.update { - val newValue = it.deleteTokens() - savedStateHandle[converterInputKey2] = newValue.text - newValue - } - } else { - input1.update { - val newValue = it.deleteTokens() - savedStateHandle[converterInputKey1] = newValue.text - newValue - } - } - } - - fun clearInput() { - input1.update { - savedStateHandle[converterInputKey1] = "" - TextFieldValue() - } - input2.update { - savedStateHandle[converterInputKey2] = "" - TextFieldValue() - } - } - - fun updateInput(value: TextFieldValue) = input1.update { value } - - fun updateCurrencyRates(unit: AbstractUnit) { - loadCurrenciesJob = viewModelScope.launch(Dispatchers.IO) { - try { - currenciesState.update { CurrencyRateUpdateState.Loading } - val updateDate = unitsRepo.updateRates(unit) ?: throw Exception("Empty cache") - - // Set to fresh objects with updated basic unit values - unitFrom.update { unitFrom -> unitFrom?.id?.let { unitsRepo.getById(it) } } - unitTo.update { unitTo -> unitTo?.id?.let { unitsRepo.getById(it) } } - currenciesState.update { CurrencyRateUpdateState.Ready(updateDate) } - } catch (e: Exception) { - currenciesState.update { CurrencyRateUpdateState.Error } - } - } - } - - fun updateUnitFrom(unit: AbstractUnit) = viewModelScope.launch { - val pairId = unit.pairId - val pair: AbstractUnit = if (pairId == null) { - val collection = unitsRepo.getCollection(unit.group).sortedByDescending { it.counter } - collection.firstOrNull { it.isFavorite } ?: collection.first() - } else { - unitsRepo.getById(pairId) - } - - withContext(Dispatchers.Default) { - unitsRepo.incrementCounter(unit) - userPrefsRepository.updateLatestPairOfUnits(unitFrom = unit, unitTo = pair) - } - - loadCurrenciesJob?.cancel() - currenciesState.update { CurrencyRateUpdateState.Nothing } - if (unit.group == UnitGroup.CURRENCY) updateCurrencyRates(unit) - - unitFrom.update { - // We change from something to base converter or the other way around - if ((it?.group == UnitGroup.NUMBER_BASE) xor (unit.group == UnitGroup.NUMBER_BASE)) { - clearInput() - } - - unit - } - unitTo.update { pair } - } - - fun updateUnitTo(unit: AbstractUnit) { - unitTo.update { unit } - - viewModelScope.launch { - val unitTo = unitTo.value ?: return@launch - val unitFrom = unitFrom.value ?: return@launch - - unitsRepo.incrementCounter(unitTo) - - unitsRepo.setPair(unitFrom, unitTo) - userPrefsRepository.updateLatestPairOfUnits(unitFrom = unitFrom, unitTo = unitTo) - } - } - - private fun convertDefault( - unitFrom: DefaultUnit, - unitTo: DefaultUnit, - input1: TextFieldValue, - input2: TextFieldValue, - formatTime: Boolean, - ) = viewModelScope.launch(Dispatchers.Default) { - val footInchInput = unitFrom.id == UnitID.foot - - if (footInchInput) { - calculation.update { null } - } - - // Calculate - val calculated1 = try { - Expression(input1.text.ifEmpty { Token.Digit._0 }).calculate() - } catch (e: ExpressionException.DivideByZero) { - calculation.update { null } - return@launch - } catch (e: Exception) { - return@launch - } - - // Update calculation - calculation.update { if (input1.text.isExpression()) calculated1 else null } - - // Convert - val result: ConverterResult = try { - var conversion = unitFrom.convert(unitTo, calculated1) - if (footInchInput) { - // Converted from second text field too - val inches = unitsRepo.getById(UnitID.inch) as DefaultUnit - val calculated2 = try { - Expression(input2.text.ifEmpty { Token.Digit._0 }).calculate() - } catch (e: ExpressionException.DivideByZero) { - calculation.update { null } - return@launch - } catch (e: Exception) { - return@launch - } - conversion += inches.convert(unitTo, calculated2) - } - when { - (unitFrom.group == UnitGroup.TIME) and (formatTime) -> formatTime(calculated1.multiply(unitFrom.basicUnit)) - unitTo.id == UnitID.foot -> formatFootInch(conversion, unitTo, unitsRepo.getById(UnitID.inch) as DefaultUnit) - else -> ConverterResult.Default(conversion) - } - } catch (e: Exception) { - ConverterResult.Default(BigDecimal.ZERO) - } - - // Update result - this@ConverterViewModel.result.update { result } - } - - private fun convertNumberBase( - unitFrom: NumberBaseUnit, - unitTo: NumberBaseUnit, - input: TextFieldValue, - ) = viewModelScope.launch(Dispatchers.Default) { - val conversion = try { - unitFrom.convert(unitTo, input.text.ifEmpty { Token.Digit._0 }) - } catch (e: Exception) { - "" - } - - result.update { ConverterResult.NumberBase(conversion) } + private inline fun whenBothAre( + value1: Any?, + value2: Any?, + block: (v1: T, v2: T) -> Unit, + ) { + if ((value1 is T) and (value2 is T)) block(value1 as T, value2 as T) } init { - viewModelScope.launch(Dispatchers.Default) { - try { - val userPrefs = userPrefsRepository.converterPrefs.first() - val unitFrom = unitsRepo.getById(userPrefs.latestLeftSideUnit) - val unitTo = unitsRepo.getById(userPrefs.latestRightSideUnit) + loadInitialUnits() + } - this@ConverterViewModel.unitFrom.update { unitFrom } - this@ConverterViewModel.unitTo.update { unitTo } - if (unitFrom.group == UnitGroup.CURRENCY) updateCurrencyRates(unitFrom) - } catch (e: NoSuchElementException) { - val unitFrom = unitsRepo.getById(UnitID.kilometer) - val unitTo = unitsRepo.getById(UnitID.mile) - - this@ConverterViewModel.unitFrom.update { unitFrom } - this@ConverterViewModel.unitTo.update { unitTo } - } - } + override fun onCleared() { + super.onCleared() + viewModelScope.cancel() } } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitFromSelectorScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitFromSelectorScreen.kt index 899ca49a..423c67aa 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitFromSelectorScreen.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitFromSelectorScreen.kt @@ -22,12 +22,10 @@ import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext @@ -39,10 +37,11 @@ import com.sadellie.unitto.core.base.R import com.sadellie.unitto.core.ui.common.EmptyScreen import com.sadellie.unitto.core.ui.common.SearchBar import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit +import com.sadellie.unitto.data.converter.UnitSearchResultItem +import com.sadellie.unitto.data.database.UnitsEntity +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import com.sadellie.unitto.feature.converter.components.ChipsRow import com.sadellie.unitto.feature.converter.components.FavoritesButton import com.sadellie.unitto.feature.converter.components.UnitsList @@ -50,7 +49,7 @@ import java.math.BigDecimal @Composable internal fun UnitFromSelectorRoute( - unitSelectorViewModel: UnitSelectorViewModel, + unitSelectorViewModel: UnitFromSelectorViewModel, converterViewModel: ConverterViewModel, navigateUp: () -> Unit, navigateToUnitGroups: () -> Unit, @@ -62,7 +61,7 @@ internal fun UnitFromSelectorRoute( uiState = uiState, onQueryChange = unitSelectorViewModel::updateSelectorQuery, toggleFavoritesOnly = unitSelectorViewModel::updateShowFavoritesOnly, - updateUnitFrom = converterViewModel::updateUnitFrom, + updateUnitFrom = converterViewModel::updateUnitFromId, updateUnitGroup = unitSelectorViewModel::updateSelectedUnitGroup, favoriteUnit = unitSelectorViewModel::favoriteUnit, navigateUp = navigateUp, @@ -77,25 +76,14 @@ private fun UnitFromSelectorScreen( uiState: UnitSelectorUIState.UnitFrom, onQueryChange: (TextFieldValue) -> Unit, toggleFavoritesOnly: (Boolean) -> Unit, - updateUnitFrom: (AbstractUnit) -> Unit, + updateUnitFrom: (String) -> Unit, updateUnitGroup: (UnitGroup?) -> Unit, - favoriteUnit: (AbstractUnit) -> Unit, + favoriteUnit: (UnitSearchResultItem) -> Unit, navigateUp: () -> Unit, navigateToUnitGroups: () -> Unit, ) { val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior() - val chipsRowLazyListState = rememberLazyListState() - - LaunchedEffect(uiState.unitFrom, uiState.shownUnitGroups) { - kotlin.runCatching { - val groupToSelect = uiState.shownUnitGroups.indexOf(uiState.unitFrom.group) - if (groupToSelect > -1) { - chipsRowLazyListState.scrollToItem(groupToSelect) - } - } - } - Scaffold( modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), topBar = { @@ -127,15 +115,16 @@ private fun UnitFromSelectorScreen( }, ) { paddingValues -> val resources = LocalContext.current.resources + UnitsList( modifier = Modifier.padding(paddingValues), searchResult = uiState.units, navigateToUnitGroups = navigateToUnitGroups, - currentUnitId = uiState.unitFrom.id, - supportLabel = { resources.getString(it.shortName) }, + currentUnitId = uiState.unitFromId, + supportLabel = { resources.getString(it.basicUnit.shortName) }, onClick = { onQueryChange(TextFieldValue()) - updateUnitFrom(it) + updateUnitFrom(it.basicUnit.id) navigateUp() }, favoriteUnit = { favoriteUnit(it) }, @@ -146,7 +135,7 @@ private fun UnitFromSelectorScreen( @Preview @Composable private fun UnitFromSelectorScreenPreview() { - val units: Map> = mapOf( + val units: Map> = mapOf( UnitGroup.LENGTH to listOf( NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), @@ -155,14 +144,15 @@ private fun UnitFromSelectorScreenPreview() { NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), - ), + ) + .map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) }, ) UnitFromSelectorScreen( uiState = UnitSelectorUIState.UnitFrom( - unitFrom = units.values.first().first(), + unitFromId = UnitID.kilometer, query = TextFieldValue("test"), - units = UnitSearchResult.Success(units), + units = units, selectedUnitGroup = UnitGroup.SPEED, shownUnitGroups = UnitGroup.entries, showFavoritesOnly = false, diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitFromSelectorViewModel.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitFromSelectorViewModel.kt new file mode 100644 index 00000000..fcd5ca30 --- /dev/null +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitFromSelectorViewModel.kt @@ -0,0 +1,124 @@ +/* + * Unitto is a calculator for Android + * Copyright (c) 2024 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.feature.converter + +import androidx.compose.ui.text.input.TextFieldValue +import androidx.lifecycle.SavedStateHandle +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.sadellie.unitto.data.common.stateIn +import com.sadellie.unitto.data.converter.UnitSearchResultItem +import com.sadellie.unitto.data.converter.UnitsRepositoryImpl +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.repository.UserPreferencesRepository +import com.sadellie.unitto.feature.converter.navigation.UNIT_FROM_ID_ARG +import com.sadellie.unitto.feature.converter.navigation.UNIT_GROUP_ARG +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +internal class UnitFromSelectorViewModel @Inject constructor( + private val userPrefsRepository: UserPreferencesRepository, + private val unitsRepo: UnitsRepositoryImpl, + savedStateHandle: SavedStateHandle, +) : ViewModel() { + private var searchJob: Job? = null + + private val query = MutableStateFlow(TextFieldValue()) + private val searchResults = MutableStateFlow>?>(null) + private val selectedUnitGroup = MutableStateFlow(savedStateHandle.get(UNIT_GROUP_ARG)) + private val unitFromId = savedStateHandle.get(UNIT_FROM_ID_ARG) + + val unitFromUIState: StateFlow = combine( + query, + searchResults, + selectedUnitGroup, + userPrefsRepository.converterPrefs, + ) { query, searchResults, selectedUnitGroup, prefs -> + if (searchResults == null) return@combine UnitSelectorUIState.Loading + + return@combine UnitSelectorUIState.UnitFrom( + query = query, + unitFromId = unitFromId ?: "", + shownUnitGroups = prefs.shownUnitGroups, + showFavoritesOnly = prefs.unitConverterFavoritesOnly, + units = searchResults, + selectedUnitGroup = selectedUnitGroup, + sorting = prefs.unitConverterSorting, + ) + } + .stateIn(viewModelScope, UnitSelectorUIState.Loading) + + fun updateSelectorQuery(value: TextFieldValue) { + query.update { value } + onSearch() + } + + fun updateShowFavoritesOnly(value: Boolean) = viewModelScope.launch { + userPrefsRepository.updateUnitConverterFavoritesOnly(value) + onSearch() + } + + fun updateSelectedUnitGroup(value: UnitGroup?) { + selectedUnitGroup.update { value } + onSearch() + } + + fun favoriteUnit(unit: UnitSearchResultItem) = viewModelScope.launch { + unitsRepo.favorite(unit.basicUnit.id) + onSearch() + } + + private fun onSearch() { + searchJob?.cancel() + searchJob = viewModelScope.launch { + val prefs = userPrefsRepository.converterPrefs.first() + val selectedGroupValue = selectedUnitGroup.value + val result = unitsRepo.filterUnits( + query = query.value.text, + favoritesOnly = prefs.unitConverterFavoritesOnly, + sorting = prefs.unitConverterSorting, + unitGroups = if (selectedGroupValue == null) { + prefs.shownUnitGroups + } else { + listOf(selectedGroupValue) + }, + ) + + searchResults.update { result } + } + } + + init { + onSearch() + } + + override fun onCleared() { + super.onCleared() + viewModelScope.cancel() + } +} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitSelectorUIState.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitSelectorUIState.kt index f1884d10..b25575cc 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitSelectorUIState.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitSelectorUIState.kt @@ -20,29 +20,30 @@ package com.sadellie.unitto.feature.converter import androidx.compose.ui.text.input.TextFieldValue import com.sadellie.unitto.core.base.FormatterSymbols -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit +import com.sadellie.unitto.data.converter.UnitSearchResultItem +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting +import com.sadellie.unitto.data.model.converter.unit.BasicUnit internal sealed class UnitSelectorUIState { data object Loading : UnitSelectorUIState() data class UnitFrom( val query: TextFieldValue, - val unitFrom: AbstractUnit, + val unitFromId: String, val shownUnitGroups: List, val showFavoritesOnly: Boolean, - val units: UnitSearchResult, + val units: Map>, val selectedUnitGroup: UnitGroup?, val sorting: UnitsListSorting, ) : UnitSelectorUIState() data class UnitTo( val query: TextFieldValue, - val unitFrom: AbstractUnit, - val unitTo: AbstractUnit, + val unitFrom: BasicUnit, + val unitTo: BasicUnit, val showFavoritesOnly: Boolean, - val units: UnitSearchResult, + val units: Map>, val input: String?, val sorting: UnitsListSorting, val scale: Int, @@ -50,13 +51,3 @@ internal sealed class UnitSelectorUIState { val formatterSymbols: FormatterSymbols, ) : UnitSelectorUIState() } - -internal sealed class UnitSearchResult { - data object Empty : UnitSearchResult() - - data object Loading : UnitSearchResult() - - data class Success( - val units: Map>, - ) : UnitSearchResult() -} diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitToSelectorScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitToSelectorScreen.kt index 17f6fbcc..73fd8f50 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitToSelectorScreen.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitToSelectorScreen.kt @@ -36,20 +36,21 @@ import com.sadellie.unitto.core.ui.common.EmptyScreen import com.sadellie.unitto.core.ui.common.SearchBar import com.sadellie.unitto.core.ui.common.textfield.formatExpression import com.sadellie.unitto.data.common.format +import com.sadellie.unitto.data.converter.DefaultBatchConvertResult +import com.sadellie.unitto.data.converter.NumberBaseBatchConvertResult import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.DefaultUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.data.model.unit.NumberBaseUnit +import com.sadellie.unitto.data.converter.UnitSearchResultItem +import com.sadellie.unitto.data.database.UnitsEntity +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import com.sadellie.unitto.feature.converter.components.FavoritesButton import com.sadellie.unitto.feature.converter.components.UnitsList import java.math.BigDecimal @Composable internal fun UnitToSelectorRoute( - unitSelectorViewModel: UnitSelectorViewModel, + unitSelectorViewModel: UnitToSelectorViewModel, converterViewModel: ConverterViewModel, navigateUp: () -> Unit, navigateToUnitGroups: () -> Unit, @@ -61,7 +62,7 @@ internal fun UnitToSelectorRoute( uiState = uiState, onQueryChange = unitSelectorViewModel::updateSelectorQuery, toggleFavoritesOnly = unitSelectorViewModel::updateShowFavoritesOnly, - updateUnitTo = converterViewModel::updateUnitTo, + updateUnitTo = converterViewModel::updateUnitToId, favoriteUnit = unitSelectorViewModel::favoriteUnit, navigateUp = navigateUp, navigateToUnitGroups = navigateToUnitGroups, @@ -75,8 +76,8 @@ private fun UnitToSelectorScreen( uiState: UnitSelectorUIState.UnitTo, onQueryChange: (TextFieldValue) -> Unit, toggleFavoritesOnly: (Boolean) -> Unit, - updateUnitTo: (AbstractUnit) -> Unit, - favoriteUnit: (AbstractUnit) -> Unit, + updateUnitTo: (String) -> Unit, + favoriteUnit: (UnitSearchResultItem) -> Unit, navigateUp: () -> Unit, navigateToUnitGroups: () -> Unit, ) { @@ -105,19 +106,25 @@ private fun UnitToSelectorScreen( navigateToUnitGroups = navigateToUnitGroups, currentUnitId = uiState.unitTo.id, supportLabel = { - formatUnitToSupportLabel( - unitFrom = uiState.unitFrom, - unitTo = it, - input = uiState.input, - shortName = resources.getString(it.shortName), - scale = uiState.scale, - outputFormat = uiState.outputFormat, - formatterSymbols = uiState.formatterSymbols, - ) + val label = resources.getString(it.basicUnit.shortName) + + when (val conversion = it.conversion) { + is DefaultBatchConvertResult -> { + val formattedConversion = conversion.value + .format(uiState.scale, uiState.outputFormat) + .formatExpression(uiState.formatterSymbols) + + "$formattedConversion $label" + } + is NumberBaseBatchConvertResult -> { + "${conversion.value} $label" + } + else -> label + } }, onClick = { onQueryChange(TextFieldValue()) - updateUnitTo(it) + updateUnitTo(it.basicUnit.id) navigateUp() }, favoriteUnit = { favoriteUnit(it) }, @@ -125,49 +132,10 @@ private fun UnitToSelectorScreen( } } -private fun formatUnitToSupportLabel( - unitFrom: AbstractUnit?, - unitTo: AbstractUnit?, - input: String?, - shortName: String, - scale: Int, - outputFormat: Int, - formatterSymbols: FormatterSymbols, -): String { - if (input.isNullOrEmpty()) return shortName - - try { - if ((unitFrom is DefaultUnit) and (unitTo is DefaultUnit)) { - unitFrom as DefaultUnit - unitTo as DefaultUnit - - val conversion = unitFrom - .convert(unitTo, BigDecimal(input)) - .format(scale, outputFormat) - .formatExpression(formatterSymbols) - - return "$conversion $shortName" - } - - if ((unitFrom is NumberBaseUnit) and (unitTo is NumberBaseUnit)) { - unitFrom as NumberBaseUnit - unitTo as NumberBaseUnit - - val conversion = unitFrom.convert(unitTo, input).uppercase() - - return "$conversion $shortName" - } - } catch (e: Exception) { - return shortName - } - - return shortName -} - @Preview @Composable private fun UnitToSelectorPreview() { - val units: Map> = mapOf( + val units: Map> = mapOf( UnitGroup.LENGTH to listOf( NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), @@ -176,15 +144,16 @@ private fun UnitToSelectorPreview() { NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), - ), + ) + .map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) }, ) UnitToSelectorScreen( uiState = UnitSelectorUIState.UnitTo( - unitFrom = units.values.first().first(), - unitTo = units.values.first().first(), + unitFrom = units.values.first().first().basicUnit, + unitTo = units.values.first().first().basicUnit, query = TextFieldValue("test"), - units = UnitSearchResult.Success(units), + units = units, showFavoritesOnly = false, sorting = UnitsListSorting.USAGE, input = "100", diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitSelectorViewModel.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitToSelectorViewModel.kt similarity index 51% rename from feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitSelectorViewModel.kt rename to feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitToSelectorViewModel.kt index 331c2a3d..16fc8a76 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitSelectorViewModel.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/UnitToSelectorViewModel.kt @@ -23,83 +23,48 @@ import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.repository.UnitsRepository +import com.sadellie.unitto.data.converter.UnitSearchResultItem +import com.sadellie.unitto.data.converter.UnitsRepositoryImpl +import com.sadellie.unitto.data.model.converter.UnitGroup import com.sadellie.unitto.data.model.repository.UserPreferencesRepository -import com.sadellie.unitto.data.model.unit.AbstractUnit import com.sadellie.unitto.feature.converter.navigation.INPUT_ARG import com.sadellie.unitto.feature.converter.navigation.UNIT_FROM_ID_ARG import com.sadellie.unitto.feature.converter.navigation.UNIT_GROUP_ARG import com.sadellie.unitto.feature.converter.navigation.UNIT_TO_ID_ARG import dagger.hilt.android.lifecycle.HiltViewModel -import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine -import kotlinx.coroutines.flow.mapLatest +import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -internal class UnitSelectorViewModel @Inject constructor( +internal class UnitToSelectorViewModel @Inject constructor( private val userPrefsRepository: UserPreferencesRepository, - private val unitsRepo: UnitsRepository, + private val unitsRepo: UnitsRepositoryImpl, savedStateHandle: SavedStateHandle, ) : ViewModel() { + private var searchJob: Job? = null + private val query = MutableStateFlow(TextFieldValue()) - private val searchResults = MutableStateFlow(UnitSearchResult.Loading) + private val searchResults = MutableStateFlow>?>(null) private val selectedUnitGroup = MutableStateFlow(savedStateHandle.get(UNIT_GROUP_ARG)) private val unitFromId = savedStateHandle.get(UNIT_FROM_ID_ARG) private val unitToId = savedStateHandle.get(UNIT_TO_ID_ARG) private val input = savedStateHandle.get(INPUT_ARG) - val unitFromUIState: StateFlow = combine( - query, - searchResults, - selectedUnitGroup, - userPrefsRepository.converterPrefs, - ) { query, searchResults, selectedUnitGroup, prefs -> - if (unitFromId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading - - return@combine UnitSelectorUIState.UnitFrom( - query = query, - unitFrom = unitsRepo.getById(unitFromId), - shownUnitGroups = prefs.shownUnitGroups, - showFavoritesOnly = prefs.unitConverterFavoritesOnly, - units = searchResults, - selectedUnitGroup = selectedUnitGroup, - sorting = prefs.unitConverterSorting, - ) - } - .mapLatest { ui -> - if (ui is UnitSelectorUIState.UnitFrom) { - searchResults.update { - val result = unitsRepo.filterUnits( - query = ui.query.text, - unitGroup = ui.selectedUnitGroup, - favoritesOnly = ui.showFavoritesOnly, - hideBrokenUnits = false, - sorting = ui.sorting, - shownUnitGroups = ui.shownUnitGroups, - ) - - if (result.isEmpty()) UnitSearchResult.Empty else UnitSearchResult.Success(result) - } - } - - ui - } - .stateIn(viewModelScope, UnitSelectorUIState.Loading) - val unitToUIState: StateFlow = combine( query, searchResults, userPrefsRepository.converterPrefs, - unitsRepo.units, - ) { query, searchResults, prefs, _ -> + ) { query, searchResults, prefs -> if (unitFromId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading if (unitToId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading + if (searchResults == null) return@combine UnitSelectorUIState.Loading UnitSelectorUIState.UnitTo( query = query, @@ -114,35 +79,46 @@ internal class UnitSelectorViewModel @Inject constructor( formatterSymbols = prefs.formatterSymbols, ) } - .mapLatest { ui -> - if (ui is UnitSelectorUIState.UnitTo) { - searchResults.update { - if (ui.unitFrom.group == UnitGroup.CURRENCY) unitsRepo.updateRates(ui.unitFrom) - - val result = unitsRepo.filterUnits( - query = ui.query.text, - unitGroup = ui.unitFrom.group, - favoritesOnly = ui.showFavoritesOnly, - hideBrokenUnits = true, - sorting = ui.sorting, - ) - - if (result.isEmpty()) UnitSearchResult.Empty else UnitSearchResult.Success(result) - } - } - ui - } .stateIn(viewModelScope, UnitSelectorUIState.Loading) - fun updateSelectorQuery(value: TextFieldValue) = query.update { value } + fun updateSelectorQuery(value: TextFieldValue) { + query.update { value } + onSearch() + } fun updateShowFavoritesOnly(value: Boolean) = viewModelScope.launch { userPrefsRepository.updateUnitConverterFavoritesOnly(value) + onSearch() } - fun updateSelectedUnitGroup(value: UnitGroup?) = selectedUnitGroup.update { value } + fun favoriteUnit(unit: UnitSearchResultItem) = viewModelScope.launch { + unitsRepo.favorite(unit.basicUnit.id) + onSearch() + } - fun favoriteUnit(unit: AbstractUnit) = viewModelScope.launch(Dispatchers.IO) { - unitsRepo.favorite(unit) + private fun onSearch() { + searchJob?.cancel() + searchJob = viewModelScope.launch { + val prefs = userPrefsRepository.converterPrefs.first() + val result = unitsRepo.filterUnitsAndBatchConvert( + query = query.value.text, + unitGroup = selectedUnitGroup.value ?: return@launch, + favoritesOnly = prefs.unitConverterFavoritesOnly, + sorting = prefs.unitConverterSorting, + unitFromId = unitFromId ?: return@launch, + input = input, + ) + + searchResults.update { result } + } + } + + init { + onSearch() + } + + override fun onCleared() { + super.onCleared() + viewModelScope.cancel() } } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ChipsRow.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ChipsRow.kt index a1773459..266f1101 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ChipsRow.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/ChipsRow.kt @@ -48,7 +48,7 @@ import androidx.compose.ui.unit.dp import com.sadellie.unitto.core.base.R import com.sadellie.unitto.core.ui.common.AssistChip import com.sadellie.unitto.core.ui.common.FilterChip -import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitGroup /** * Row of chips with [UnitGroup]s. Temporary solution diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitGroupHeader.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitGroupHeader.kt index 9b260aa0..9bf1f0c6 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitGroupHeader.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitGroupHeader.kt @@ -24,7 +24,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.sadellie.unitto.core.ui.common.Header -import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitGroup @Composable internal fun UnitGroupHeader(modifier: Modifier, unitGroup: UnitGroup) { diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitsList.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitsList.kt index 3dcf5993..b978cce6 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitsList.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitsList.kt @@ -19,6 +19,7 @@ package com.sadellie.unitto.feature.converter.components import androidx.compose.animation.Crossfade +import androidx.compose.animation.core.tween import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -30,57 +31,55 @@ import androidx.compose.ui.tooling.preview.Preview import com.sadellie.unitto.core.base.R import com.sadellie.unitto.core.ui.common.SearchPlaceholder import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.unit.AbstractUnit -import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.feature.converter.UnitSearchResult +import com.sadellie.unitto.data.converter.UnitSearchResultItem +import com.sadellie.unitto.data.database.UnitsEntity +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.unit.NormalUnit import java.math.BigDecimal @Composable internal fun UnitsList( modifier: Modifier, - searchResult: UnitSearchResult, + searchResult: Map>, navigateToUnitGroups: () -> Unit, currentUnitId: String, - supportLabel: (AbstractUnit) -> String, - onClick: (AbstractUnit) -> Unit, - favoriteUnit: (AbstractUnit) -> Unit, + supportLabel: (UnitSearchResultItem) -> String, + onClick: (UnitSearchResultItem) -> Unit, + favoriteUnit: (UnitSearchResultItem) -> Unit, ) { Crossfade( modifier = modifier, targetState = searchResult, label = "Units list", + animationSpec = tween(200), ) { result -> - when (result) { - is UnitSearchResult.Success -> LazyColumn( + when { + result.isEmpty() -> SearchPlaceholder( + onButtonClick = navigateToUnitGroups, + supportText = stringResource(R.string.converter_no_results_support), + buttonLabel = stringResource(R.string.open_settings_label), + ) + else -> LazyColumn( modifier = Modifier.fillMaxSize(), ) { - result.units.forEach { (group, units) -> + result.forEach { (group, units) -> item(group.name) { UnitGroupHeader(Modifier.animateItemPlacement(), group) } - items(units, { it.id }) { + items(units, { it.basicUnit.id }) { BasicUnitListItem( modifier = Modifier.animateItemPlacement(), - name = stringResource(it.displayName), + name = stringResource(it.basicUnit.displayName), supportLabel = supportLabel(it), - isFavorite = it.isFavorite, - isSelected = it.id == currentUnitId, + isFavorite = it.stats.isFavorite, + isSelected = it.basicUnit.id == currentUnitId, onClick = { onClick(it) }, favoriteUnit = { favoriteUnit(it) }, ) } } } - - UnitSearchResult.Empty -> SearchPlaceholder( - onButtonClick = navigateToUnitGroups, - supportText = stringResource(R.string.converter_no_results_support), - buttonLabel = stringResource(R.string.open_settings_label), - ) - - UnitSearchResult.Loading -> Unit } } } @@ -89,7 +88,7 @@ internal fun UnitsList( @Composable private fun PreviewUnitsList() { val resources = LocalContext.current.resources - val groupedUnits: Map> = mapOf( + val units: Map> = mapOf( UnitGroup.LENGTH to listOf( NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), @@ -98,15 +97,16 @@ private fun PreviewUnitsList() { NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), - ), + ) + .map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) }, ) UnitsList( modifier = Modifier.fillMaxSize(), - searchResult = UnitSearchResult.Success(units = groupedUnits), + searchResult = units, navigateToUnitGroups = {}, currentUnitId = UnitID.mile, - supportLabel = { resources.getString(it.shortName) }, + supportLabel = { resources.getString(it.basicUnit.shortName) }, onClick = {}, favoriteUnit = {}, ) diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt index 507f40d7..b536bb42 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/navigation/ConverterNavigation.kt @@ -28,11 +28,9 @@ import androidx.navigation.navDeepLink import com.sadellie.unitto.core.ui.model.DrawerItem import com.sadellie.unitto.core.ui.unittoComposable import com.sadellie.unitto.core.ui.unittoNavigation -import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitGroup import com.sadellie.unitto.feature.converter.ConverterRoute import com.sadellie.unitto.feature.converter.ConverterViewModel -import com.sadellie.unitto.feature.converter.CurrencyRateUpdateState -import com.sadellie.unitto.feature.converter.UnitConverterUIState import com.sadellie.unitto.feature.converter.UnitFromSelectorRoute import com.sadellie.unitto.feature.converter.UnitToSelectorRoute @@ -47,7 +45,7 @@ internal const val UNIT_TO_ID_ARG = "unitToIdArg" internal const val INPUT_ARG = "inputArg" private const val UNIT_FROM_ROUTE = "$UNIT_FROM/{$UNIT_FROM_ID_ARG}/{$UNIT_GROUP_ARG}" -private const val UNIT_TO_ROUTE = "$UNIT_TO/{$UNIT_FROM_ID_ARG}/{$UNIT_TO_ID_ARG}/{$INPUT_ARG}" +private const val UNIT_TO_ROUTE = "$UNIT_TO/{$UNIT_FROM_ID_ARG}/{$UNIT_TO_ID_ARG}/{$UNIT_GROUP_ARG}/{$INPUT_ARG}" private fun NavHostController.navigateLeft( unitFromId: String, unitGroup: UnitGroup, @@ -56,8 +54,9 @@ private fun NavHostController.navigateLeft( private fun NavHostController.navigateRight( unitFromId: String, unitToId: String, - input: String?, -) = navigate("$UNIT_TO/$unitFromId/$unitToId/$input") + unitGroup: UnitGroup, + input: String, +) = navigate("$UNIT_TO/$unitFromId/$unitToId/$unitGroup/${input.ifEmpty { null }}") fun NavGraphBuilder.converterGraph( openDrawer: () -> Unit, @@ -80,54 +79,8 @@ fun NavGraphBuilder.converterGraph( ConverterRoute( viewModel = parentViewModel, - // Navigation logic is here, but should actually be in ConverterScreen - navigateToLeftScreen = { uiState: UnitConverterUIState -> - when (uiState) { - is UnitConverterUIState.Default -> - navController - .navigateLeft(uiState.unitFrom.id, uiState.unitFrom.group) - - is UnitConverterUIState.NumberBase -> - navController - .navigateLeft(uiState.unitFrom.id, uiState.unitFrom.group) - - else -> Unit - } - }, - navigateToRightScreen = { uiState: UnitConverterUIState -> - when (uiState) { - is UnitConverterUIState.Default -> { - // Don't allow converting if still loading currencies - val convertingCurrencies = uiState.unitFrom.group == UnitGroup.CURRENCY - val currenciesReady = - uiState.currencyRateUpdateState is CurrencyRateUpdateState.Ready - - val input: String? = if (convertingCurrencies and !currenciesReady) { - null - } else { - (uiState.calculation?.toPlainString() ?: uiState.input1.text) - .ifEmpty { null } - } - - navController.navigateRight( - uiState.unitFrom.id, - uiState.unitTo.id, - input, - ) - } - - is UnitConverterUIState.NumberBase -> { - val input = uiState.input.text.ifEmpty { null } - navController.navigateRight( - uiState.unitFrom.id, - uiState.unitTo.id, - input, - ) - } - - UnitConverterUIState.Loading -> Unit - } - }, + navigateToLeftScreen = navController::navigateLeft, + navigateToRightScreen = navController::navigateRight, openDrawer = openDrawer, ) } @@ -166,6 +119,9 @@ fun NavGraphBuilder.converterGraph( navArgument(UNIT_TO_ID_ARG) { type = NavType.StringType }, + navArgument(UNIT_GROUP_ARG) { + type = NavType.EnumType(UnitGroup::class.java) + }, navArgument(INPUT_ARG) { type = NavType.StringType nullable = true diff --git a/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/ConverterUIStateKtTest.kt b/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/ConverterUIStateKtTest.kt deleted file mode 100644 index d87d15ef..00000000 --- a/feature/converter/src/test/java/com/sadellie/unitto/feature/converter/ConverterUIStateKtTest.kt +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Unitto is a calculator for Android - * Copyright (c) 2023-2024 Elshan Agaev - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.sadellie.unitto.feature.converter - -import android.content.Context -import com.sadellie.unitto.core.base.FormatterSymbols -import com.sadellie.unitto.core.base.Token -import org.junit.Assert -import org.junit.Test -import org.junit.runner.RunWith -import org.robolectric.RobolectricTestRunner -import org.robolectric.RuntimeEnvironment -import java.math.BigDecimal - -@RunWith(RobolectricTestRunner::class) -class ConverterUIStateKtTest { - - @Test - fun format() { - val formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD) - var basicValue = BigDecimal("1") - val mContext: Context = RuntimeEnvironment.getApplication().applicationContext - - fun String.formatTime() = formatTime(basicValue.multiply(BigDecimal(this))) - .format(mContext, formatterSymbols) - - // Edgy things (minus, decimals and zeros) - Assert.assertEquals("−28as", "-28".formatTime()) - Assert.assertEquals("−0.05as", "-0.05".formatTime()) - Assert.assertEquals("0", "0".formatTime()) - - basicValue = BigDecimal("86400000000000000000000") - Assert.assertEquals("−28d", "-28".formatTime()) - Assert.assertEquals("−1h 12m", "-0.05".formatTime()) - Assert.assertEquals("0", "0".formatTime()) - Assert.assertEquals("0", "-0".formatTime()) - - // DAYS - basicValue = BigDecimal("86400000000000000000000") - Assert.assertEquals("12h", "0.5".formatTime()) - Assert.assertEquals("1h 12m", "0.05".formatTime()) - Assert.assertEquals("7m 12s", "0.005".formatTime()) - Assert.assertEquals("28d", "28".formatTime()) - Assert.assertEquals("90d", "90".formatTime()) - Assert.assertEquals("90d 12h", "90.5".formatTime()) - Assert.assertEquals("90d 7m 12s", "90.005".formatTime()) - - // HOURS - basicValue = BigDecimal("3600000000000000000000") - Assert.assertEquals("30m", "0.5".formatTime()) - Assert.assertEquals("3m", "0.05".formatTime()) - Assert.assertEquals("18s", "0.005".formatTime()) - Assert.assertEquals("1d 4h", "28".formatTime()) - Assert.assertEquals("3d 18h", "90".formatTime()) - Assert.assertEquals("3d 18h 30m", "90.5".formatTime()) - Assert.assertEquals("3d 18h 18s", "90.005".formatTime()) - - // MINUTES - basicValue = BigDecimal("60000000000000000000") - Assert.assertEquals("30s", "0.5".formatTime()) - Assert.assertEquals("3s", "0.05".formatTime()) - Assert.assertEquals("300ms", "0.005".formatTime()) - Assert.assertEquals("28m", "28".formatTime()) - Assert.assertEquals("1h 30m", "90".formatTime()) - Assert.assertEquals("1h 30m 30s", "90.5".formatTime()) - Assert.assertEquals("1h 30m 300ms", "90.005".formatTime()) - - // SECONDS - basicValue = BigDecimal("1000000000000000000") - Assert.assertEquals("500ms", "0.5".formatTime()) - Assert.assertEquals("50ms", "0.05".formatTime()) - Assert.assertEquals("5ms", "0.005".formatTime()) - Assert.assertEquals("28s", "28".formatTime()) - Assert.assertEquals("1m 30s", "90".formatTime()) - Assert.assertEquals("1m 30s 500ms", "90.5".formatTime()) - Assert.assertEquals("1m 30s 5ms", "90.005".formatTime()) - - // MILLISECONDS - basicValue = BigDecimal("1000000000000000") - Assert.assertEquals("500µs", "0.5".formatTime()) - Assert.assertEquals("50µs", "0.05".formatTime()) - Assert.assertEquals("5µs", "0.005".formatTime()) - Assert.assertEquals("28ms", "28".formatTime()) - Assert.assertEquals("90ms", "90".formatTime()) - Assert.assertEquals("90ms 500µs", "90.5".formatTime()) - Assert.assertEquals("90ms 5µs", "90.005".formatTime()) - - // MICROSECONDS - basicValue = BigDecimal("1000000000000") - Assert.assertEquals("500ns", "0.5".formatTime()) - Assert.assertEquals("50ns", "0.05".formatTime()) - Assert.assertEquals("5ns", "0.005".formatTime()) - Assert.assertEquals("28µs", "28".formatTime()) - Assert.assertEquals("90µs", "90".formatTime()) - Assert.assertEquals("90µs 500ns", "90.5".formatTime()) - Assert.assertEquals("90µs 5ns", "90.005".formatTime()) - - // NANOSECONDS - basicValue = BigDecimal("1000000000") - Assert.assertEquals("500 000 000as", "0.5".formatTime()) - Assert.assertEquals("50 000 000as", "0.05".formatTime()) - Assert.assertEquals("5 000 000as", "0.005".formatTime()) - Assert.assertEquals("28ns", "28".formatTime()) - Assert.assertEquals("90ns", "90".formatTime()) - Assert.assertEquals("90ns 500 000 000as", "90.5".formatTime()) - Assert.assertEquals("90ns 5 000 000as", "90.005".formatTime()) - - // ATTOSECONDS - basicValue = BigDecimal("1") - Assert.assertEquals("0.5as", "0.5".formatTime()) - Assert.assertEquals("0.05as", "0.05".formatTime()) - Assert.assertEquals("0.005as", "0.005".formatTime()) - Assert.assertEquals("28as", "28".formatTime()) - Assert.assertEquals("90as", "90".formatTime()) - Assert.assertEquals("90.5as", "90.5".formatTime()) - Assert.assertEquals("90.005as", "90.005".formatTime()) - } -} diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt index 0fbb92cb..09711df3 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsScreen.kt @@ -42,8 +42,8 @@ import com.sadellie.unitto.core.ui.common.EmptyScreen import com.sadellie.unitto.core.ui.common.ListItem import com.sadellie.unitto.core.ui.common.NavigateUpButton import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.data.model.UnitGroup -import com.sadellie.unitto.data.model.UnitsListSorting +import com.sadellie.unitto.data.model.converter.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitsListSorting import com.sadellie.unitto.data.model.userprefs.ConverterPreferences import com.sadellie.unitto.data.userprefs.ConverterPreferencesImpl import com.sadellie.unitto.feature.settings.components.AlertDialogWithList diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsViewModel.kt index f6c2bf36..d1f1d3a7 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsViewModel.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/converter/ConverterSettingsViewModel.kt @@ -21,7 +21,7 @@ package com.sadellie.unitto.feature.settings.converter import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.UnitsListSorting +import com.sadellie.unitto.data.model.converter.UnitsListSorting import com.sadellie.unitto.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsScreen.kt index d87d00d2..d57fc9ff 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsScreen.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsScreen.kt @@ -56,7 +56,7 @@ import com.sadellie.unitto.core.ui.common.EmptyScreen import com.sadellie.unitto.core.ui.common.Header import com.sadellie.unitto.core.ui.common.NavigateUpButton import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar -import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitGroup import org.burnoutcrew.reorderable.ReorderableItem import org.burnoutcrew.reorderable.detectReorder import org.burnoutcrew.reorderable.detectReorderAfterLongPress diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsUIState.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsUIState.kt index 7a12173a..261dbc1f 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsUIState.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsUIState.kt @@ -18,7 +18,7 @@ package com.sadellie.unitto.feature.settings.unitgroups -import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitGroup internal sealed class UnitGroupsUIState { data object Loading : UnitGroupsUIState() diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsViewModel.kt index 2b94f734..d1ddd84a 100644 --- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsViewModel.kt +++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/unitgroups/UnitGroupsViewModel.kt @@ -21,7 +21,7 @@ package com.sadellie.unitto.feature.settings.unitgroups import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.sadellie.unitto.data.common.stateIn -import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.converter.UnitGroup import com.sadellie.unitto.data.model.repository.UserPreferencesRepository import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.flow.map