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.CyclingPedalingCadenceRecord
20 import android.icu.text.MessageFormat.*
21 import androidx.annotation.StringRes
22 import com.android.healthconnect.controller.R
23 import com.android.healthconnect.controller.data.entries.FormattedEntry
24 import com.android.healthconnect.controller.dataentries.formatters.shared.EntryFormatter
25 import com.android.healthconnect.controller.dataentries.formatters.shared.RecordDetailsFormatter
26 import com.android.healthconnect.controller.dataentries.units.UnitPreferences
27 import com.android.healthconnect.controller.utils.LocalDateTimeFormatter
28 import dagger.hilt.android.qualifiers.ApplicationContext
29 import javax.inject.Inject
30 
31 /** Formatter for printing CyclingCadenceRecord data. */
32 class CyclingPedalingCadenceFormatter
33 @Inject
34 constructor(@ApplicationContext private val context: Context) :
35     EntryFormatter<CyclingPedalingCadenceRecord>(context),
36     RecordDetailsFormatter<CyclingPedalingCadenceRecord> {
37 
38     private val timeFormatter = LocalDateTimeFormatter(context)
39 
40     override suspend fun formatRecord(
41         record: CyclingPedalingCadenceRecord,
42         header: String,
43         headerA11y: String,
44         unitPreferences: UnitPreferences
45     ): FormattedEntry {
46         return FormattedEntry.SeriesDataEntry(
47             uuid = record.metadata.id,
48             header = header,
49             headerA11y = headerA11y,
50             title = formatValue(record, unitPreferences),
51             titleA11y = formatA11yValue(record, unitPreferences),
52             dataType = getDataType(record))
53     }
54 
55     override suspend fun formatValue(
56         record: CyclingPedalingCadenceRecord,
57         unitPreferences: UnitPreferences
58     ): String {
59         return formatCadence(R.string.cycling_cadence_series_range, record) { rpm ->
60             format(context.getString(R.string.cycling_rpm), mapOf("count" to rpm))
61         }
62     }
63 
64     override suspend fun formatA11yValue(
65         record: CyclingPedalingCadenceRecord,
66         unitPreferences: UnitPreferences
67     ): String {
68         return formatCadence(R.string.cycling_cadence_series_range_long, record) { rpm ->
69             format(context.getString(R.string.cycling_rpm_long), mapOf("count" to rpm))
70         }
71     }
72 
73     override suspend fun formatRecordDetails(
74         record: CyclingPedalingCadenceRecord
75     ): List<FormattedEntry> {
76         return record.samples
77             .sortedBy { it.time }
78             .map { sample ->
79                 FormattedEntry.FormattedSessionDetail(
80                     uuid = record.metadata.id,
81                     header = timeFormatter.formatTime(sample.time),
82                     headerA11y = timeFormatter.formatTime(sample.time),
83                     title =
84                         format(
85                             context.getString(R.string.cycling_rpm),
86                             mapOf("count" to sample.revolutionsPerMinute)),
87                     titleA11y =
88                         format(
89                             context.getString(R.string.cycling_rpm_long),
90                             mapOf("count" to sample.revolutionsPerMinute)))
91             }
92     }
93 
94     private fun formatCadence(
95         @StringRes res: Int,
96         record: CyclingPedalingCadenceRecord,
97         getCadenceString: (rpm: Double) -> String
98     ): String {
99         if (record.samples.isEmpty()) {
100             return context.getString(R.string.no_data)
101         }
102 
103         val min = record.samples.minOf { it.revolutionsPerMinute }
104         val max = record.samples.maxOf { it.revolutionsPerMinute }
105 
106         if (min.equals(max)) {
107             return getCadenceString(min)
108         }
109 
110         return context.getString(res, getCadenceString(min), getCadenceString(max))
111     }
112 }
113