1 /** <lambda>null2 * Copyright (C) 2024 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.ExerciseCompletionGoal 20 import android.health.connect.datatypes.PlannedExerciseStep 21 import com.android.healthconnect.controller.R 22 import com.android.healthconnect.controller.data.entries.FormattedEntry 23 import com.android.healthconnect.controller.data.entries.FormattedEntry.FormattedSectionContent 24 import com.android.healthconnect.controller.data.entries.FormattedEntry.PlannedExerciseStepEntry 25 import com.android.healthconnect.controller.dataentries.formatters.shared.LengthFormatter 26 import com.android.healthconnect.controller.dataentries.units.UnitPreferences 27 import dagger.hilt.android.qualifiers.ApplicationContext 28 import javax.inject.Inject 29 30 /** Formatter for printing PlannedExerciseStep data. */ 31 class PlannedExerciseStepFormatter 32 @Inject 33 constructor( 34 @ApplicationContext private val context: Context, 35 private val exercisePerformanceGoalFormatter: ExercisePerformanceGoalFormatter, 36 private val exerciseSegmentTypeFormatter: ExerciseSegmentTypeFormatter 37 ) { 38 39 fun formatStep(step: PlannedExerciseStep, unitPreferences: UnitPreferences): FormattedEntry { 40 return PlannedExerciseStepEntry( 41 step = step, 42 title = formatStepTitle(step, unitPreferences), 43 titleA11y = formatStepTitleA11y(step, unitPreferences)) 44 } 45 46 fun formatStepDetails( 47 step: PlannedExerciseStep, 48 unitPreferences: UnitPreferences 49 ): List<FormattedEntry> { 50 val performanceGoals = step.performanceGoals 51 return buildList { 52 if (!step.description.isNullOrBlank()) { 53 add(FormattedSectionContent(title = step.description.toString(), bulleted = true)) 54 } 55 56 if (performanceGoals.isNotEmpty()) { 57 performanceGoals.forEach { performanceGoal -> 58 add( 59 exercisePerformanceGoalFormatter.formatGoal( 60 performanceGoal, unitPreferences, step.exerciseType)) 61 } 62 } 63 } 64 } 65 66 private fun formatStepTitle( 67 step: PlannedExerciseStep, 68 unitPreferences: UnitPreferences 69 ): String { 70 val completionGoal = step.completionGoal 71 val exerciseSegmentType = step.exerciseType 72 return context.getString( 73 R.string.planned_exercise_step_title, 74 formatCompletionGoal(completionGoal, unitPreferences), 75 exerciseSegmentTypeFormatter.getSegmentType(exerciseSegmentType)) 76 } 77 78 private fun formatStepTitleA11y( 79 step: PlannedExerciseStep, 80 unitPreferences: UnitPreferences 81 ): String { 82 val completionGoal = step.completionGoal 83 val exerciseSegmentType = step.exerciseType 84 return context.getString( 85 R.string.planned_exercise_step_title, 86 formatCompletionGoalA11y(completionGoal, unitPreferences), 87 exerciseSegmentTypeFormatter.getSegmentType(exerciseSegmentType)) 88 } 89 90 private fun formatCompletionGoal( 91 completionGoal: ExerciseCompletionGoal, 92 unitPreferences: UnitPreferences 93 ): String { 94 return when (completionGoal) { 95 is ExerciseCompletionGoal.DistanceGoal -> 96 LengthFormatter.formatValue(context, completionGoal.distance, unitPreferences) 97 is ExerciseCompletionGoal.DurationGoal -> 98 DurationFormatter.formatDurationShort(context, completionGoal.duration) 99 is ExerciseCompletionGoal.StepsGoal -> 100 StepsFormatter(context).formatUnit(completionGoal.steps.toLong()) 101 is ExerciseCompletionGoal.RepetitionsGoal -> completionGoal.repetitions.toString() 102 is ExerciseCompletionGoal.ActiveCaloriesBurnedGoal -> 103 context.getString( 104 R.string.active_calories_burned, 105 EnergyFormatter.formatEnergyValue( 106 context, completionGoal.activeCalories, unitPreferences)) 107 is ExerciseCompletionGoal.DistanceWithVariableRestGoal -> 108 context.getString( 109 R.string.distance_with_variable_rest_goal_formatted, 110 LengthFormatter.formatValue(context, completionGoal.distance, unitPreferences), 111 DurationFormatter.formatDurationShort(context, completionGoal.duration)) 112 is ExerciseCompletionGoal.TotalCaloriesBurnedGoal -> 113 context.getString( 114 R.string.total_calories_burned, 115 EnergyFormatter.formatEnergyValue( 116 context, completionGoal.totalCalories, unitPreferences)) 117 else -> throw IllegalArgumentException("Unknown completion goal $completionGoal") 118 } 119 } 120 121 private fun formatCompletionGoalA11y( 122 completionGoal: ExerciseCompletionGoal, 123 unitPreferences: UnitPreferences 124 ): String { 125 return when (completionGoal) { 126 is ExerciseCompletionGoal.DistanceGoal -> 127 LengthFormatter.formatA11yValue(context, completionGoal.distance, unitPreferences) 128 is ExerciseCompletionGoal.DurationGoal -> 129 DurationFormatter.formatDurationLong(context, completionGoal.duration) 130 is ExerciseCompletionGoal.StepsGoal -> 131 StepsFormatter(context).formatA11yUnit(completionGoal.steps.toLong()) 132 is ExerciseCompletionGoal.RepetitionsGoal -> completionGoal.repetitions.toString() 133 is ExerciseCompletionGoal.ActiveCaloriesBurnedGoal -> 134 context.getString( 135 R.string.active_calories_burned, 136 EnergyFormatter.formatEnergyA11yValue( 137 context, completionGoal.activeCalories, unitPreferences)) 138 is ExerciseCompletionGoal.DistanceWithVariableRestGoal -> 139 context.getString( 140 R.string.distance_with_variable_rest_goal_formatted, 141 LengthFormatter.formatA11yValue( 142 context, completionGoal.distance, unitPreferences), 143 DurationFormatter.formatDurationLong(context, completionGoal.duration)) 144 is ExerciseCompletionGoal.TotalCaloriesBurnedGoal -> 145 context.getString( 146 R.string.total_calories_burned, 147 EnergyFormatter.formatEnergyA11yValue( 148 context, completionGoal.totalCalories, unitPreferences)) 149 else -> throw IllegalArgumentException("Unknown completion goal $completionGoal") 150 } 151 } 152 } 153