• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * 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.ExercisePerformanceGoal
20 import android.health.connect.datatypes.ExerciseSegmentType
21 import android.icu.text.MessageFormat
22 import android.util.Log
23 import com.android.healthconnect.controller.R
24 import com.android.healthconnect.controller.data.entries.FormattedEntry
25 import com.android.healthconnect.controller.data.entries.FormattedEntry.ExercisePerformanceGoalEntry
26 import com.android.healthconnect.controller.dataentries.formatters.SpeedFormatter.Companion.ACTIVITY_TYPES_WITH_PACE_VELOCITY
27 import com.android.healthconnect.controller.dataentries.formatters.SpeedFormatter.Companion.SWIMMING_ACTIVITY_TYPES
28 import com.android.healthconnect.controller.dataentries.units.UnitPreferences
29 import dagger.hilt.android.qualifiers.ApplicationContext
30 import javax.inject.Inject
31 
32 /** Formatter for printing ExercisePerformanceGoal data. */
33 class ExercisePerformanceGoalFormatter
34 @Inject
35 constructor(
36     @ApplicationContext private val context: Context,
37     private val speedFormatter: SpeedFormatter
38 ) {
39     private val ACTIVITY_TYPES_WITH_CADENCE_MOTION =
40         listOf(
41             ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BIKING,
42             ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_BIKING_STATIONARY,
43             ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_ROWING_MACHINE,
44             ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_WHEELCHAIR)
45 
formatGoalnull46     fun formatGoal(
47         goal: ExercisePerformanceGoal,
48         unitPreferences: UnitPreferences,
49         exerciseSegmentType: Int
50     ): FormattedEntry {
51         return ExercisePerformanceGoalEntry(
52             goal = goal,
53             title = formatPerformanceGoal(goal, unitPreferences, exerciseSegmentType),
54             titleA11y = formatPerformanceGoalA11y(goal, unitPreferences, exerciseSegmentType))
55     }
56 
formatPerformanceGoalnull57     private fun formatPerformanceGoal(
58         performanceGoal: ExercisePerformanceGoal,
59         unitPreferences: UnitPreferences,
60         exerciseSegmentType: Int
61     ): String {
62         return when (performanceGoal) {
63             is ExercisePerformanceGoal.PowerGoal ->
64                 context.getString(
65                     R.string.performance_goals_range,
66                     MessageFormat.format(
67                         context.getString(R.string.watt_format),
68                         mapOf("value" to performanceGoal.minPower.inWatts)),
69                     MessageFormat.format(
70                         context.getString(R.string.watt_format),
71                         mapOf("value" to performanceGoal.maxPower.inWatts)))
72             is ExercisePerformanceGoal.AmrapGoal ->
73                 context.getString(R.string.amrap_performance_goal)
74             is ExercisePerformanceGoal.CadenceGoal -> {
75                 if (ACTIVITY_TYPES_WITH_CADENCE_MOTION.contains(exerciseSegmentType)) {
76                     return context.getString(
77                         R.string.performance_goals_range,
78                         MessageFormat.format(
79                             context.getString(R.string.cycling_rpm),
80                             mapOf("count" to performanceGoal.minRpm)),
81                         MessageFormat.format(
82                             context.getString(R.string.cycling_rpm),
83                             mapOf("count" to performanceGoal.maxRpm)))
84                 }
85                 return context.getString(
86                     R.string.performance_goals_range,
87                     MessageFormat.format(
88                         context.getString(R.string.steps_per_minute),
89                         mapOf("value" to performanceGoal.minRpm)),
90                     MessageFormat.format(
91                         context.getString(R.string.steps_per_minute),
92                         mapOf("value" to performanceGoal.maxRpm)))
93             }
94             is ExercisePerformanceGoal.SpeedGoal ->
95                 if (ACTIVITY_TYPES_WITH_PACE_VELOCITY.contains(exerciseSegmentType) ||
96                     SWIMMING_ACTIVITY_TYPES.contains(exerciseSegmentType))
97                     context.getString(
98                         R.string.performance_goals_range,
99                         speedFormatter.formatSpeedValue(
100                             performanceGoal.maxSpeed, unitPreferences, exerciseSegmentType),
101                         speedFormatter.formatSpeedValue(
102                             performanceGoal.minSpeed, unitPreferences, exerciseSegmentType))
103                 else
104                     context.getString(
105                         R.string.performance_goals_range,
106                         speedFormatter.formatSpeedValue(
107                             performanceGoal.minSpeed, unitPreferences, exerciseSegmentType),
108                         speedFormatter.formatSpeedValue(
109                             performanceGoal.maxSpeed, unitPreferences, exerciseSegmentType))
110             is ExercisePerformanceGoal.HeartRateGoal ->
111                 context.getString(
112                     R.string.performance_goals_range,
113                     MessageFormat.format(
114                         context.getString(R.string.heart_rate_value),
115                         mapOf("count" to performanceGoal.minBpm)),
116                     MessageFormat.format(
117                         context.getString(R.string.heart_rate_value),
118                         mapOf("count" to performanceGoal.maxBpm)))
119             is ExercisePerformanceGoal.WeightGoal ->
120                 MassFormatter.formatValue(
121                     context, performanceGoal.mass, unitPreferences.getWeightUnit())
122             is ExercisePerformanceGoal.RateOfPerceivedExertionGoal ->
123                 context.getString(R.string.rate_of_perceived_exertion_goal, performanceGoal.rpe)
124             else -> {
125                 Log.e("Error", "Unknown performance goal $performanceGoal")
126                 return ""
127             }
128         }
129     }
130 
formatPerformanceGoalA11ynull131     private fun formatPerformanceGoalA11y(
132         performanceGoal: ExercisePerformanceGoal,
133         unitPreferences: UnitPreferences,
134         exerciseSegmentType: Int
135     ): String {
136         return when (performanceGoal) {
137             is ExercisePerformanceGoal.PowerGoal ->
138                 context.getString(
139                     R.string.performance_goals_range,
140                     MessageFormat.format(
141                         context.getString(R.string.watt_format_long),
142                         mapOf("value" to performanceGoal.minPower.inWatts)),
143                     MessageFormat.format(
144                         context.getString(R.string.watt_format_long),
145                         mapOf("value" to performanceGoal.maxPower.inWatts)))
146             is ExercisePerformanceGoal.AmrapGoal ->
147                 context.getString(R.string.amrap_performance_goal)
148             is ExercisePerformanceGoal.CadenceGoal -> {
149                 if (ACTIVITY_TYPES_WITH_CADENCE_MOTION.contains(exerciseSegmentType)) {
150                     return context.getString(
151                         R.string.performance_goals_range,
152                         MessageFormat.format(
153                             context.getString(R.string.cycling_rpm_long),
154                             mapOf("count" to performanceGoal.minRpm)),
155                         MessageFormat.format(
156                             context.getString(R.string.cycling_rpm_long),
157                             mapOf("count" to performanceGoal.maxRpm)))
158                 }
159                 return context.getString(
160                     R.string.performance_goals_range,
161                     MessageFormat.format(
162                         context.getString(R.string.steps_per_minute_long),
163                         mapOf("value" to performanceGoal.minRpm)),
164                     MessageFormat.format(
165                         context.getString(R.string.steps_per_minute_long),
166                         mapOf("value" to performanceGoal.maxRpm)))
167             }
168             is ExercisePerformanceGoal.SpeedGoal ->
169                 if (ACTIVITY_TYPES_WITH_PACE_VELOCITY.contains(exerciseSegmentType) ||
170                     SWIMMING_ACTIVITY_TYPES.contains(exerciseSegmentType))
171                     context.getString(
172                         R.string.performance_goals_range,
173                         speedFormatter.formatA11ySpeedValue(
174                             performanceGoal.maxSpeed, unitPreferences, exerciseSegmentType),
175                         speedFormatter.formatA11ySpeedValue(
176                             performanceGoal.minSpeed, unitPreferences, exerciseSegmentType))
177                 else
178                     context.getString(
179                         R.string.performance_goals_range,
180                         speedFormatter.formatA11ySpeedValue(
181                             performanceGoal.minSpeed, unitPreferences, exerciseSegmentType),
182                         speedFormatter.formatA11ySpeedValue(
183                             performanceGoal.maxSpeed, unitPreferences, exerciseSegmentType))
184             is ExercisePerformanceGoal.HeartRateGoal ->
185                 context.getString(
186                     R.string.performance_goals_range,
187                     MessageFormat.format(
188                         context.getString(R.string.heart_rate_long_value),
189                         mapOf("count" to performanceGoal.minBpm)),
190                     MessageFormat.format(
191                         context.getString(R.string.heart_rate_long_value),
192                         mapOf("count" to performanceGoal.maxBpm)))
193             is ExercisePerformanceGoal.WeightGoal ->
194                 MassFormatter.formatA11yValue(
195                     context, performanceGoal.mass, unitPreferences.getWeightUnit())
196             is ExercisePerformanceGoal.RateOfPerceivedExertionGoal ->
197                 context.getString(R.string.rate_of_perceived_exertion_goal, performanceGoal.rpe)
198             else -> {
199                 Log.e("Error", "Unknown performance goal $performanceGoal")
200                 return ""
201             }
202         }
203     }
204 }
205