1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.car.carlauncher.calmmode;
18 
19 import android.icu.number.Notation;
20 import android.icu.number.NumberFormatter;
21 import android.icu.number.Precision;
22 import android.icu.util.MeasureUnit;
23 import android.os.Build;
24 import android.util.Log;
25 
26 import androidx.annotation.NonNull;
27 
28 import java.util.Locale;
29 
30 /**
31  * Class used to represent temperature
32  * <p>Contains a {@code float value}  and {@link MeasureUnit unit}
33  * <p>Use {@link Builder} to create an instance of {@link TemperatureData}
34  */
35 public class TemperatureData {
36 
37     private static final String TAG = TemperatureData.class.getSimpleName();
38     private static final boolean DEBUG = Build.isDebuggable();
39     private float mValue;
40     @NonNull
41     private MeasureUnit mUnit;
42 
TemperatureData(float value, @NonNull MeasureUnit unit)43     private TemperatureData(float value, @NonNull MeasureUnit unit) {
44         this.mValue = value;
45         this.mUnit = unit;
46     }
47 
48     /**
49      * @param temperatureData temperature data
50      * @param locale locale to use for creating string
51      * @return compact string representation of the value based on the locale
52      */
53     @NonNull
buildTemperatureString( @onNull TemperatureData temperatureData, @NonNull Locale locale, boolean showUnit)54     public static String buildTemperatureString(
55             @NonNull TemperatureData temperatureData, @NonNull Locale locale, boolean showUnit) {
56         return NumberFormatter.withLocale(locale)
57                 .notation(Notation.compactShort())
58                 .precision(Precision.integer())
59                 .unit(showUnit ? temperatureData.getUnit() : MeasureUnit.GENERIC_TEMPERATURE)
60                 .format(temperatureData.getValue())
61                 .toString();
62     }
63 
64     /**
65      * Converts temperature value from Celsius to Fahrenheit
66      *
67      * @param temperatureInCelsius temperature value in Celsius
68      * @return temperature value in Fahrenheit
69      */
convertCelsiusToFahrenheit(float temperatureInCelsius)70     public static float convertCelsiusToFahrenheit(float temperatureInCelsius) {
71         return (temperatureInCelsius * 9f / 5f) + 32;
72     }
73 
74     /**
75      * Converts temperature value from Fahrenheit to Celsius
76      *
77      * @param temperatureInFahrenheit temperature value in Fahrenheit
78      * @return temperature value in Celsius
79      */
convertFahrenheitToCelsius(float temperatureInFahrenheit)80     public static float convertFahrenheitToCelsius(float temperatureInFahrenheit) {
81         return (temperatureInFahrenheit - 32) * 5f / 9f;
82     }
83 
getValue()84     public float getValue() {
85         return mValue;
86     }
87 
88     @NonNull
getUnit()89     public MeasureUnit getUnit() {
90         return mUnit;
91     }
92 
93     @Override
toString()94     public String toString() {
95         return "TemperatureData{" + "value=" + mValue + ", unit=" + mUnit + '}';
96     }
97 
98 
99     /** Converts the value and changes unit from Fahrenheit to Celsius,
100      * does nothing if unit is already Celsius
101      */
convertToFahrenheit()102     public void convertToFahrenheit() {
103         if (mUnit == MeasureUnit.CELSIUS) {
104             mValue = convertCelsiusToFahrenheit(mValue);
105             mUnit = MeasureUnit.FAHRENHEIT;
106             return;
107         }
108         // no-op if unit is already FAHRENHEIT
109         if (DEBUG) {
110             Log.v(TAG, "Unit is already FAHRENHEIT. No conversion performed.");
111         }
112     }
113 
114     /** Converts the value and changes unit to Fahrenheit,
115      * does nothing if unit is already Fahrenheit
116      */
convertToCelsius()117     public void convertToCelsius() {
118         if (mUnit == MeasureUnit.FAHRENHEIT) {
119             mValue = convertFahrenheitToCelsius(mValue);
120             mUnit = MeasureUnit.CELSIUS;
121         }
122         // no-op if unit is already CELSIUS
123         if (DEBUG) {
124             Log.v(TAG, "Unit is already CELSIUS. No conversion performed.");
125         }
126     }
127 
128     public static final class Builder {
129 
130         private float mValue;
131         @NonNull private MeasureUnit mUnit = MeasureUnit.CELSIUS;
132 
Builder(float mValue, @NonNull MeasureUnit mUnit)133         private Builder(float mValue, @NonNull MeasureUnit mUnit) {
134             this.mValue = mValue;
135             this.mUnit = mUnit;
136         }
137 
Builder()138         public Builder() {}
139 
140         /**
141          * @param data TemperatureData object used to create Builder
142          * @return TemperatureData.Builder object
143          */
144         @NonNull
from(TemperatureData data)145         public static Builder from(TemperatureData data) {
146             return new Builder(data.getValue(), data.getUnit());
147         }
148 
149         /**
150          * @param temperatureCelsius temperature value in degrees Celsius
151          * @return {@link Builder builder}
152          */
setValueCelsius(float temperatureCelsius)153         Builder setValueCelsius(float temperatureCelsius) {
154             mValue = temperatureCelsius;
155             mUnit = MeasureUnit.CELSIUS;
156             return this;
157         }
158 
setValueFahrenheit(float temperatureFahrenheit)159         Builder setValueFahrenheit(float temperatureFahrenheit) {
160             mValue = temperatureFahrenheit;
161             mUnit = MeasureUnit.FAHRENHEIT;
162             return this;
163         }
164 
build()165         TemperatureData build() {
166             return new TemperatureData(mValue, mUnit);
167         }
168     }
169 }
170