1 /** <lambda>null2 * 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 * ``` 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * ``` 10 * 11 * Unless required by applicable law or agreed to in writing, software distributed under the License 12 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 13 * or implied. See the License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16 package com.android.healthconnect.controller.dataentries.formatters 17 18 import android.content.Context 19 import android.health.connect.datatypes.MealType 20 import android.health.connect.datatypes.NutritionRecord 21 import android.health.connect.datatypes.units.Energy 22 import android.health.connect.datatypes.units.Mass 23 import android.icu.text.MessageFormat.* 24 import androidx.annotation.StringRes 25 import com.android.healthconnect.controller.R 26 import com.android.healthconnect.controller.dataentries.formatters.EnergyFormatter.formatEnergyA11yValue 27 import com.android.healthconnect.controller.dataentries.formatters.EnergyFormatter.formatEnergyValue 28 import com.android.healthconnect.controller.dataentries.formatters.MealFormatter.formatMealType 29 import com.android.healthconnect.controller.dataentries.formatters.shared.EntryFormatter 30 import com.android.healthconnect.controller.dataentries.units.UnitPreferences 31 import dagger.hilt.android.qualifiers.ApplicationContext 32 import java.util.StringJoiner 33 import javax.inject.Inject 34 35 /** Formatter for printing NutritionRecord data. */ 36 class NutritionFormatter @Inject constructor(@ApplicationContext private val context: Context) : 37 EntryFormatter<NutritionRecord>(context) { 38 39 override suspend fun formatValue( 40 record: NutritionRecord, 41 unitPreferences: UnitPreferences 42 ): String { 43 val nutritionData = 44 getAggregations( 45 record, 46 { mass -> 47 val grams = mass.inGrams 48 format(context.getString(R.string.gram_short_format), mapOf("count" to grams)) 49 }, 50 { energy -> formatEnergyValue(context, energy, unitPreferences) }) 51 return nutritionData.ifEmpty { "-" } 52 } 53 54 override suspend fun formatA11yValue( 55 record: NutritionRecord, 56 unitPreferences: UnitPreferences 57 ): String { 58 val nutritionData = 59 getAggregations( 60 record, 61 { mass -> 62 val grams = mass.inGrams 63 format(context.getString(R.string.gram_long_format), mapOf("count" to grams)) 64 }, 65 { energy -> formatEnergyA11yValue(context, energy, unitPreferences) }) 66 return nutritionData.ifEmpty { "-" } 67 } 68 69 private fun getAggregations( 70 record: NutritionRecord, 71 formatMass: (mass: Mass) -> String, 72 formatEnergy: (energy: Energy) -> String, 73 ): String { 74 val stringJoiner = StringJoiner("\n") 75 record.mealName?.run { stringJoiner.addAggregation(R.string.meal_name, this) } 76 if (record.mealType != MealType.MEAL_TYPE_UNKNOWN) { 77 stringJoiner.addAggregation( 78 R.string.mealtype_label, formatMealType(context, record.mealType)) 79 } 80 record.biotin?.addAggregation(R.string.biotin, stringJoiner, formatMass) 81 record.caffeine?.addAggregation(R.string.caffeine, stringJoiner, formatMass) 82 record.calcium?.addAggregation(R.string.calcium, stringJoiner, formatMass) 83 record.chloride?.addAggregation(R.string.chloride, stringJoiner, formatMass) 84 record.cholesterol?.addAggregation(R.string.cholesterol, stringJoiner, formatMass) 85 record.chromium?.addAggregation(R.string.chromium, stringJoiner, formatMass) 86 record.copper?.addAggregation(R.string.copper, stringJoiner, formatMass) 87 record.dietaryFiber?.addAggregation(R.string.dietary_fiber, stringJoiner, formatMass) 88 record.energy?.addAggregation(R.string.energy_consumed_total, stringJoiner, formatEnergy) 89 record.energyFromFat?.addAggregation( 90 R.string.energy_consumed_from_fat, stringJoiner, formatEnergy) 91 record.folate?.addAggregation(R.string.folate, stringJoiner, formatMass) 92 record.folicAcid?.addAggregation(R.string.folic_acid, stringJoiner, formatMass) 93 record.iodine?.addAggregation(R.string.iodine, stringJoiner, formatMass) 94 record.iron?.addAggregation(R.string.iron, stringJoiner, formatMass) 95 record.magnesium?.addAggregation(R.string.magnesium, stringJoiner, formatMass) 96 record.manganese?.addAggregation(R.string.manganese, stringJoiner, formatMass) 97 record.molybdenum?.addAggregation(R.string.molybdenum, stringJoiner, formatMass) 98 record.monounsaturatedFat?.addAggregation( 99 R.string.monounsaturated_fat, stringJoiner, formatMass) 100 record.niacin?.addAggregation(R.string.niacin, stringJoiner, formatMass) 101 record.pantothenicAcid?.addAggregation(R.string.pantothenic_acid, stringJoiner, formatMass) 102 record.phosphorus?.addAggregation(R.string.phosphorus, stringJoiner, formatMass) 103 record.polyunsaturatedFat?.addAggregation( 104 R.string.polyunsaturated_fat, stringJoiner, formatMass) 105 record.potassium?.addAggregation(R.string.potassium, stringJoiner, formatMass) 106 record.riboflavin?.addAggregation(R.string.riboflavin, stringJoiner, formatMass) 107 record.saturatedFat?.addAggregation(R.string.saturated_fat, stringJoiner, formatMass) 108 record.selenium?.addAggregation(R.string.selenium, stringJoiner, formatMass) 109 record.sodium?.addAggregation(R.string.sodium, stringJoiner, formatMass) 110 record.sugar?.addAggregation(R.string.sugar, stringJoiner, formatMass) 111 record.thiamin?.addAggregation(R.string.thiamin, stringJoiner, formatMass) 112 record.totalCarbohydrate?.addAggregation( 113 R.string.total_carbohydrate, stringJoiner, formatMass) 114 record.totalFat?.addAggregation(R.string.total_fat, stringJoiner, formatMass) 115 record.transFat?.addAggregation(R.string.trans_fat, stringJoiner, formatMass) 116 record.unsaturatedFat?.addAggregation(R.string.unsaturated_fat, stringJoiner, formatMass) 117 record.vitaminA?.addAggregation(R.string.vitamin_a, stringJoiner, formatMass) 118 record.vitaminB12?.addAggregation(R.string.vitamin_b12, stringJoiner, formatMass) 119 record.vitaminB6?.addAggregation(R.string.vitamin_b6, stringJoiner, formatMass) 120 record.vitaminC?.addAggregation(R.string.vitamin_c, stringJoiner, formatMass) 121 record.vitaminD?.addAggregation(R.string.vitamin_d, stringJoiner, formatMass) 122 record.vitaminE?.addAggregation(R.string.vitamin_e, stringJoiner, formatMass) 123 record.vitaminK?.addAggregation(R.string.vitamin_k, stringJoiner, formatMass) 124 record.zinc?.addAggregation(R.string.zinc, stringJoiner, formatMass) 125 126 return stringJoiner.toString() 127 } 128 129 private fun StringJoiner.addAggregation(@StringRes labelRes: Int, value: String) { 130 val label = context.getString(labelRes) 131 add(context.getString(R.string.nutrient_with_value, label, value)) 132 } 133 134 private fun Mass.addAggregation( 135 @StringRes labelRes: Int, 136 stringJoiner: StringJoiner, 137 formatMass: (mass: Mass) -> String 138 ) { 139 stringJoiner.addAggregation(labelRes, formatMass(this)) 140 } 141 142 private fun Energy.addAggregation( 143 @StringRes labelRes: Int, 144 stringJoiner: StringJoiner, 145 formatEnergy: (energy: Energy) -> String 146 ) { 147 stringJoiner.addAggregation(labelRes, formatEnergy(this)) 148 } 149 } 150