Make unit converter parsing more lenient and add units of volume
Close #1323
This commit is contained in:
@@ -13,13 +13,13 @@ import de.mm20.launcher2.unitconverter.converters.MassConverter
|
||||
import de.mm20.launcher2.unitconverter.converters.TemperatureConverter
|
||||
import de.mm20.launcher2.unitconverter.converters.TimeConverter
|
||||
import de.mm20.launcher2.unitconverter.converters.VelocityConverter
|
||||
import de.mm20.launcher2.unitconverter.converters.VolumeConverter
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -27,7 +27,7 @@ import org.koin.core.component.KoinComponent
|
||||
|
||||
interface UnitConverterRepository {
|
||||
fun search(query: String): Flow<UnitConverter?>
|
||||
suspend fun getAvailableConverters(includeCurrencies: Boolean) : List<Converter>
|
||||
suspend fun getAvailableConverters(includeCurrencies: Boolean): List<Converter>
|
||||
}
|
||||
|
||||
internal class UnitConverterRepositoryImpl(
|
||||
@@ -56,7 +56,7 @@ internal class UnitConverterRepositoryImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getAvailableConverters(includeCurrencies: Boolean) : List<Converter> {
|
||||
override suspend fun getAvailableConverters(includeCurrencies: Boolean): List<Converter> {
|
||||
val converters = mutableListOf(
|
||||
MassConverter(context),
|
||||
LengthConverter(context),
|
||||
@@ -64,7 +64,8 @@ internal class UnitConverterRepositoryImpl(
|
||||
TimeConverter(context),
|
||||
VelocityConverter(context),
|
||||
AreaConverter(context),
|
||||
TemperatureConverter(context)
|
||||
TemperatureConverter(context),
|
||||
VolumeConverter(context),
|
||||
)
|
||||
if (includeCurrencies) converters.add(CurrencyConverter(currencyRepository))
|
||||
|
||||
@@ -75,28 +76,51 @@ internal class UnitConverterRepositoryImpl(
|
||||
query: String,
|
||||
includeCurrencies: Boolean
|
||||
): UnitConverter? {
|
||||
if (!query.matches(Regex("[0-9,.:]+ [^\\s]+")) &&
|
||||
!query.matches(Regex("[0-9,.:]+ [^\\s]+ >> [^\\s]+")) &&
|
||||
!query.matches(Regex("[0-9,.:]+ [^\\s]+ > [^\\s]+")) &&
|
||||
!query.matches(Regex("[0-9,.:]+ [^\\s]+ - [^\\s]+"))) return null
|
||||
val valueStr: String
|
||||
val unitStr: String
|
||||
val targetUnitStr: String?
|
||||
val regex = Regex("""([+\-]?[\d+\-e,.]+|[^\d>\-]+)""")
|
||||
|
||||
query.split(" ").also {
|
||||
valueStr = it.get(0)
|
||||
unitStr = it.get(1)
|
||||
targetUnitStr = it.getOrNull(3)
|
||||
val matches = regex.findAll(query)
|
||||
|
||||
var inputStr: String? = null
|
||||
var inputValue: Double? = null
|
||||
var inputUnit: String? = null
|
||||
var outputUnit: String? = null
|
||||
|
||||
for ((i, match) in matches.withIndex()) {
|
||||
when (i) {
|
||||
0 -> {
|
||||
inputStr = match.value.trim()
|
||||
inputValue = inputStr.toDoubleOrNull()
|
||||
?: inputStr.replace(',', '.').toDoubleOrNull()
|
||||
?: return null
|
||||
}
|
||||
1 -> inputUnit = match.value.trim()
|
||||
2 -> {
|
||||
if (!match.value.contains("-") && !match.value.contains(">")) {
|
||||
outputUnit = match.value.trim()
|
||||
}
|
||||
}
|
||||
3 -> {
|
||||
if (outputUnit == null) {
|
||||
outputUnit = match.value.trim()
|
||||
break
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
}
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
|
||||
if (inputValue == null || inputUnit == null) {
|
||||
return null
|
||||
}
|
||||
val value = valueStr.toDoubleOrNull() ?: valueStr.replace(',', '.').toDoubleOrNull()
|
||||
?: return null
|
||||
|
||||
val converters = getAvailableConverters(includeCurrencies)
|
||||
|
||||
for (converter in converters) {
|
||||
if (!converter.isValidUnit(unitStr)) continue
|
||||
if (targetUnitStr != null && !converter.isValidUnit(targetUnitStr)) continue
|
||||
return converter.convert(context, unitStr, value, targetUnitStr)
|
||||
if (!converter.isValidUnit(inputUnit)) continue
|
||||
if (outputUnit != null && !converter.isValidUnit(outputUnit)) continue
|
||||
return converter.convert(context, inputUnit, inputValue, outputUnit)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
package de.mm20.launcher2.unitconverter.converters
|
||||
|
||||
import android.content.Context
|
||||
import de.mm20.launcher2.unitconverter.Dimension
|
||||
import de.mm20.launcher2.unitconverter.R
|
||||
|
||||
internal class VolumeConverter(context: Context) : SimpleFactorConverter() {
|
||||
override val dimension: Dimension = Dimension.Volume
|
||||
|
||||
override val standardUnits = listOf(
|
||||
// SI units
|
||||
MeasureUnitWithFactor(
|
||||
factor = 1.0,
|
||||
symbol = context.getString(R.string.unit_cubic_meter_symbol),
|
||||
nameResource = R.plurals.unit_cubic_meter
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 1_000_000.0,
|
||||
symbol = context.getString(R.string.unit_cubic_centimeter_symbol),
|
||||
nameResource = R.plurals.unit_cubic_centimeter
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 1_000_000_000.0,
|
||||
symbol = context.getString(R.string.unit_cubic_millimeter_symbol),
|
||||
nameResource = R.plurals.unit_cubic_millimeter
|
||||
),
|
||||
// Other metric units
|
||||
MeasureUnitWithFactor(
|
||||
factor = 1000.0,
|
||||
symbol = context.getString(R.string.unit_liter_symbol),
|
||||
nameResource = R.plurals.unit_liter
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 1_000_000.0,
|
||||
symbol = context.getString(R.string.unit_milliliter_symbol),
|
||||
nameResource = R.plurals.unit_milliliter
|
||||
),
|
||||
|
||||
// Imperial geometric units
|
||||
MeasureUnitWithFactor(
|
||||
factor = 61023.74409473228,
|
||||
symbol = context.getString(R.string.unit_cubic_inch_symbol),
|
||||
nameResource = R.plurals.unit_cubic_inch
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 61023.74409473228 / 1728.0,
|
||||
symbol = context.getString(R.string.unit_cubic_foot_symbol),
|
||||
nameResource = R.plurals.unit_cubic_foot
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 61023.74409473228 / (1728.0 * 27.0),
|
||||
symbol = context.getString(R.string.unit_cubic_yard_symbol),
|
||||
nameResource = R.plurals.unit_cubic_yard
|
||||
),
|
||||
|
||||
// US fluid units
|
||||
MeasureUnitWithFactor(
|
||||
factor = 264.1720523581484,
|
||||
symbol = context.getString(R.string.unit_gallon_us_symbol),
|
||||
nameResource = R.plurals.unit_gallon_us
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 264.1720523581484 * 8,
|
||||
symbol = context.getString(R.string.unit_pint_us_symbol),
|
||||
nameResource = R.plurals.unit_pint_us
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 264.1720523581484 * 16,
|
||||
symbol = context.getString(R.string.unit_cup_symbol),
|
||||
nameResource = R.plurals.unit_cup
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 264.1720523581484 * 128,
|
||||
symbol = context.getString(R.string.unit_fluid_ounce_us_symbol),
|
||||
nameResource = R.plurals.unit_fluid_ounce_us
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 264.1720523581484 * 256,
|
||||
symbol = context.getString(R.string.unit_tablespoon_symbol),
|
||||
nameResource = R.plurals.unit_tablespoon
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 264.1720523581484 * 768,
|
||||
symbol = context.getString(R.string.unit_teaspoon_symbol),
|
||||
nameResource = R.plurals.unit_teaspoon
|
||||
),
|
||||
|
||||
// Imperial fluid units
|
||||
MeasureUnitWithFactor(
|
||||
factor = 219.9692482990878,
|
||||
symbol = context.getString(R.string.unit_gallon_imp_symbol),
|
||||
nameResource = R.plurals.unit_gallon_imp
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 219.969248299087 * 8,
|
||||
symbol = context.getString(R.string.unit_pint_imp_symbol),
|
||||
nameResource = R.plurals.unit_pint_imp
|
||||
),
|
||||
MeasureUnitWithFactor(
|
||||
factor = 219.969248299087 * 128,
|
||||
symbol = context.getString(R.string.unit_fluid_ounce_imp_symbol),
|
||||
nameResource = R.plurals.unit_fluid_ounce_imp
|
||||
),
|
||||
|
||||
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user