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.PowerRecord 20 import android.health.connect.datatypes.PowerRecord.PowerRecordSample 21 import android.icu.text.MessageFormat 22 import androidx.annotation.StringRes 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.FormattedSessionDetail 26 import com.android.healthconnect.controller.dataentries.formatters.shared.EntryFormatter 27 import com.android.healthconnect.controller.dataentries.formatters.shared.RecordDetailsFormatter 28 import com.android.healthconnect.controller.dataentries.units.UnitPreferences 29 import com.android.healthconnect.controller.utils.LocalDateTimeFormatter 30 import dagger.hilt.android.qualifiers.ApplicationContext 31 import javax.inject.Inject 32 import javax.inject.Singleton 33 34 /** Formatter for printing Power series data. */ 35 @Singleton 36 class PowerFormatter @Inject constructor(@ApplicationContext private val context: Context) : 37 EntryFormatter<PowerRecord>(context), RecordDetailsFormatter<PowerRecord> { 38 39 private val timeFormatter = LocalDateTimeFormatter(context) 40 41 override suspend fun formatRecord( 42 record: PowerRecord, 43 header: String, 44 headerA11y: String, 45 unitPreferences: UnitPreferences 46 ): FormattedEntry { 47 return FormattedEntry.SeriesDataEntry( 48 uuid = record.metadata.id, 49 header = header, 50 headerA11y = headerA11y, 51 title = formatValue(record, unitPreferences), 52 titleA11y = formatA11yValue(record, unitPreferences), 53 dataType = getDataType(record)) 54 } 55 56 override suspend fun formatValue( 57 record: PowerRecord, 58 unitPreferences: UnitPreferences 59 ): String { 60 return format(R.string.watt_format, record.samples) 61 } 62 63 override suspend fun formatA11yValue( 64 record: PowerRecord, 65 unitPreferences: UnitPreferences 66 ): String { 67 return format(R.string.watt_format_long, record.samples) 68 } 69 70 override suspend fun formatRecordDetails(record: PowerRecord): List<FormattedEntry> { 71 return record.samples 72 .sortedBy { it.time } 73 .map { sample -> formatSample(record.metadata.id, sample) } 74 } 75 76 private fun format(@StringRes res: Int, samples: List<PowerRecordSample>): String { 77 if (samples.isEmpty()) { 78 return context.getString(R.string.no_data) 79 } 80 val avrPower = samples.sumOf { it.power.inWatts } / samples.size 81 return MessageFormat.format(context.getString(res), mapOf("value" to avrPower)) 82 } 83 84 private fun formatSample(id: String, sample: PowerRecordSample): FormattedSessionDetail { 85 return FormattedSessionDetail( 86 uuid = id, 87 header = timeFormatter.formatTime(sample.time), 88 headerA11y = timeFormatter.formatTime(sample.time), 89 title = 90 MessageFormat.format( 91 context.getString(R.string.watt_format), 92 mapOf("value" to sample.power.inWatts)), 93 titleA11y = 94 MessageFormat.format( 95 context.getString(R.string.watt_format_long), 96 mapOf("value" to sample.power.inWatts)), 97 ) 98 } 99 } 100