1 /** 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 5 * in compliance with the License. You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software distributed under the License 10 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 11 * or implied. See the License for the specific language governing permissions and limitations under 12 * the License. 13 */ 14 package com.android.healthconnect.controller.dataentries.units 15 16 import kotlin.math.roundToInt 17 18 object WeightConverter { 19 private const val POUNDS_PER_STONE = 14 20 21 private const val KG_PER_POUND = 0.453592 22 private const val KG_PER_STONE = 6.35029 23 private const val POUND_PER_KG = 2.20462 24 private const val STONE_PER_KG = 0.157473 25 26 private const val MAX_STONE_TO_KG_INPUT = Double.MAX_VALUE / KG_PER_STONE 27 private const val MAX_KG_TO_POUND_INPUT = Double.MAX_VALUE / POUND_PER_KG 28 29 /** 30 * Converts from kilograms to the provided units 31 * 32 * @param toUnit the units type to convert the passed in sourceKilograms (kg) to 33 * @param sourceKilograms the kg weight to convert to toUnit weight 34 * @return the sourceKilograms in toUnit weight units 35 */ convertFromKilogramsnull36 fun convertFromKilograms(toUnit: WeightUnit, sourceKilograms: Double): Double { 37 return when (toUnit) { 38 WeightUnit.KILOGRAM -> keepOneDecimal(sourceKilograms) 39 WeightUnit.POUND -> { 40 require( 41 !(sourceKilograms > MAX_KG_TO_POUND_INPUT || 42 sourceKilograms < -MAX_KG_TO_POUND_INPUT)) { 43 "Kilogram input out of range: $sourceKilograms" 44 } 45 keepOneDecimal(sourceKilograms * POUND_PER_KG) 46 } 47 WeightUnit.STONE -> keepOneDecimal(sourceKilograms * STONE_PER_KG) 48 } 49 } 50 51 /** 52 * Converts from grams to the provided units 53 * 54 * @param toUnit the units type to convert the passed in sourceGrams (g) to 55 * @param sourceGrams the gram weight to convert to toUnit weight 56 * @return the sourceGrams in toUnit weight units 57 */ convertFromGramsnull58 fun convertFromGrams(toUnit: WeightUnit, sourceGrams: Double): Double { 59 return convertFromKilograms(toUnit, sourceGrams / 1000) 60 } 61 62 /** 63 * Converts from pounds to stones and pounds. 64 * 65 * @param weight the weight in pounds to convert 66 * @param significantDigits the number of significant digits to round the pounds to 67 */ stonePoundsFromPoundsnull68 fun stonePoundsFromPounds(weight: Double, significantDigits: Int): StonePounds { 69 var stone = (weight / POUNDS_PER_STONE).toInt() 70 val pow = Math.pow(10.0, significantDigits.toDouble()) 71 var pound = keepOneDecimal((weight % POUNDS_PER_STONE * pow).roundToInt() / pow) 72 if (pound == POUNDS_PER_STONE.toDouble()) { 73 pound = 0.0 74 stone++ 75 } 76 return StonePounds(stone, pound) 77 } 78 keepOneDecimalnull79 private fun keepOneDecimal(weight: Double): Double { 80 return (weight * 10).roundToInt() / 10.0 81 } 82 } 83 84 /** 85 * Encapsulates the result of a conversion to UK imperial units; whole stones and fractional pounds. 86 * 87 * @param stone Stone value (14 pounds). 88 * @param pounds Pounds (between zero and 14). 89 */ 90 data class StonePounds(val stone: Int, val pounds: Double) 91