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