1 /**
<lambda>null2  * 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.testapps.toolbox.seed
17 
18 import android.content.Context
19 import android.health.connect.HealthConnectManager
20 import android.health.connect.datatypes.BasalMetabolicRateRecord
21 import android.health.connect.datatypes.BodyFatRecord
22 import android.health.connect.datatypes.BodyWaterMassRecord
23 import android.health.connect.datatypes.BoneMassRecord
24 import android.health.connect.datatypes.DataOrigin
25 import android.health.connect.datatypes.Device
26 import android.health.connect.datatypes.HeightRecord
27 import android.health.connect.datatypes.LeanBodyMassRecord
28 import android.health.connect.datatypes.Metadata
29 import android.health.connect.datatypes.WeightRecord
30 import android.health.connect.datatypes.units.Length
31 import android.health.connect.datatypes.units.Mass
32 import android.health.connect.datatypes.units.Percentage
33 import android.health.connect.datatypes.units.Power
34 import android.os.Build.MANUFACTURER
35 import android.os.Build.MODEL
36 import com.android.healthconnect.testapps.toolbox.utils.GeneralUtils.Companion.getMetaData
37 import com.android.healthconnect.testapps.toolbox.utils.GeneralUtils.Companion.insertRecords
38 import kotlinx.coroutines.runBlocking
39 import java.time.Duration.ofDays
40 import java.time.Duration.ofMinutes
41 import java.time.Instant
42 import java.time.temporal.ChronoUnit
43 import kotlin.random.Random
44 
45 class SeedBodyMeasurementsData(private val context: Context, private val manager: HealthConnectManager)  {
46 
47     private val start = Instant.now().truncatedTo(ChronoUnit.DAYS)
48     private val yesterday = start.minus(ofDays(1))
49     private val lastWeek = start.minus(ofDays(7))
50     private val lastMonth = start.minus(ofDays(31))
51 
52     fun seedBodyMeasurementsData(){
53         runBlocking {
54             try {
55                 seedBodyFatRecord()
56                 seedBodyWaterMassRecord()
57                 seedHeightRecord()
58                 seedBoneMassRecord()
59                 seedLeanBodyMassRecord()
60                 seedBasalMetabolicRate()
61                 seedWeightRecord()
62 
63             } catch (ex: Exception) {
64                 throw ex
65             }
66         }
67     }
68 
69     private suspend fun seedBodyFatRecord(){
70         val records = (1L..3).map { timeOffSet ->
71             getBodyFatRecord(getValidBodyFatPercentage(), start.plus(ofMinutes(timeOffSet)))
72         }
73         val yesterdayRecords = (1L..3).map { timeOffSet ->
74             getBodyFatRecord(getValidBodyFatPercentage(), yesterday.plus(ofMinutes(timeOffSet)))
75         }
76         val lastWeekRecords = (1L..3).map { timeOffSet ->
77             getBodyFatRecord(getValidBodyFatPercentage(), lastWeek.plus(ofMinutes(timeOffSet)))
78         }
79         val lastMonthRecords = (1L..3).map { timeOffSet ->
80             getBodyFatRecord(getValidBodyFatPercentage(), lastMonth.plus(ofMinutes(timeOffSet)))
81         }
82 
83         insertRecords(records, manager)
84         insertRecords(yesterdayRecords, manager)
85         insertRecords(lastWeekRecords, manager)
86         insertRecords(lastMonthRecords, manager)
87     }
88 
89     private suspend fun seedBodyWaterMassRecord(){
90         val records = (1L..3).map { timeOffSet ->
91             getBodyWaterMassRecord(getValidMassData(20000, 45000), start.plus(ofMinutes(timeOffSet)))
92         }
93         val yesterdayRecords = (1L..3).map { timeOffSet ->
94             getBodyWaterMassRecord(getValidMassData(20000, 45000), yesterday.plus(ofMinutes(timeOffSet)))
95         }
96         val lastWeekRecords = (1L..3).map { timeOffSet ->
97             getBodyWaterMassRecord(getValidMassData(20000, 45000), lastWeek.plus(ofMinutes(timeOffSet)))
98         }
99         val lastMonthRecords = (1L..3).map { timeOffSet ->
100             getBodyWaterMassRecord(getValidMassData(20000, 45000), lastMonth.plus(ofMinutes(timeOffSet)))
101         }
102 
103         insertRecords(records, manager)
104         insertRecords(yesterdayRecords, manager)
105         insertRecords(lastWeekRecords, manager)
106         insertRecords(lastMonthRecords, manager)
107     }
108 
109     private suspend fun seedBoneMassRecord(){
110         val records = (1L..3).map { timeOffSet ->
111             getBoneMassRecord(getValidMassData(5000, 11000), start.plus(ofMinutes(timeOffSet)))
112         }
113         val yesterdayRecords = (1L..3).map { timeOffSet ->
114             getBoneMassRecord(getValidMassData(5000, 11000), yesterday.plus(ofMinutes(timeOffSet)))
115         }
116         val lastWeekRecords = (1L..3).map { timeOffSet ->
117             getBoneMassRecord(getValidMassData(5000, 11000), lastWeek.plus(ofMinutes(timeOffSet)))
118         }
119         val lastMonthRecords = (1L..3).map { timeOffSet ->
120             getBoneMassRecord(getValidMassData(5000, 11000), lastMonth.plus(ofMinutes(timeOffSet)))
121         }
122 
123         insertRecords(records, manager)
124         insertRecords(yesterdayRecords, manager)
125         insertRecords(lastWeekRecords, manager)
126         insertRecords(lastMonthRecords, manager)
127     }
128 
129     private suspend fun seedHeightRecord(){
130         val records = (1L..3).map { timeOffSet ->
131             getHeightRecord(getValidHeightData(), start.plus(ofMinutes(timeOffSet)))
132         }
133         val yesterdayRecords = (1L..3).map { timeOffSet ->
134             getHeightRecord(getValidHeightData(), yesterday.plus(ofMinutes(timeOffSet)))
135         }
136         val lastWeekRecords = (1L..3).map { timeOffSet ->
137             getHeightRecord(getValidHeightData(), lastWeek.plus(ofMinutes(timeOffSet)))
138         }
139         val lastMonthRecords = (1L..3).map { timeOffSet ->
140             getHeightRecord(getValidHeightData(), lastMonth.plus(ofMinutes(timeOffSet)))
141         }
142 
143         insertRecords(records, manager)
144         insertRecords(yesterdayRecords, manager)
145         insertRecords(lastWeekRecords, manager)
146         insertRecords(lastMonthRecords, manager)
147     }
148 
149     private suspend fun seedBasalMetabolicRate(){
150         val records = (1L..3).map { timeOffSet ->
151             getBasalMetabolicRateRecord(getValidBasalMetabolicRateData(), start.plus(ofMinutes(timeOffSet)))
152         }
153         val yesterdayRecords = (1L..3).map { timeOffSet ->
154             getBasalMetabolicRateRecord(getValidBasalMetabolicRateData(), yesterday.plus(ofMinutes(timeOffSet)))
155         }
156         val lastWeekRecords = (1L..3).map { timeOffSet ->
157             getBasalMetabolicRateRecord(getValidBasalMetabolicRateData(), lastWeek.plus(ofMinutes(timeOffSet)))
158         }
159         val lastMonthRecords = (1L..3).map { timeOffSet ->
160             getBasalMetabolicRateRecord(getValidBasalMetabolicRateData(), lastMonth.plus(ofMinutes(timeOffSet)))
161         }
162 
163         insertRecords(records, manager)
164         insertRecords(yesterdayRecords, manager)
165         insertRecords(lastWeekRecords, manager)
166         insertRecords(lastMonthRecords, manager)
167     }
168 
169     private suspend fun seedLeanBodyMassRecord(){
170         val records = (1L..3).map { timeOffSet ->
171             getLeanBodyMassRecord(getValidMassData(45000, 90000), start.plus(ofMinutes(timeOffSet)))
172         }
173         val yesterdayRecords = (1L..3).map { timeOffSet ->
174             getLeanBodyMassRecord(getValidMassData(45000, 90000), yesterday.plus(ofMinutes(timeOffSet)))
175         }
176         val lastWeekRecords = (1L..3).map { timeOffSet ->
177             getLeanBodyMassRecord(getValidMassData(45000, 90000), lastWeek.plus(ofMinutes(timeOffSet)))
178         }
179         val lastMonthRecords = (1L..3).map { timeOffSet ->
180             getLeanBodyMassRecord(getValidMassData(45000, 90000), lastMonth.plus(ofMinutes(timeOffSet)))
181         }
182 
183         insertRecords(records, manager)
184         insertRecords(yesterdayRecords, manager)
185         insertRecords(lastWeekRecords, manager)
186         insertRecords(lastMonthRecords, manager)
187     }
188 
189     private suspend fun seedWeightRecord(){
190         val records = (1L..3).map { timeOffSet ->
191             getWeightRecord(getValidMassData(45000, 90000), start.plus(ofMinutes(timeOffSet)))
192         }
193         val yesterdayRecords = (1L..3).map { timeOffSet ->
194             getWeightRecord(getValidMassData(45000, 90000), yesterday.plus(ofMinutes(timeOffSet)))
195         }
196         val lastWeekRecords = (1L..3).map { timeOffSet ->
197             getWeightRecord(getValidMassData(45000, 90000), lastWeek.plus(ofMinutes(timeOffSet)))
198         }
199         val lastMonthRecords = (1L..3).map { timeOffSet ->
200             getWeightRecord(getValidMassData(45000, 90000), lastMonth.plus(ofMinutes(timeOffSet)))
201         }
202 
203         insertRecords(records, manager)
204         insertRecords(yesterdayRecords, manager)
205         insertRecords(lastWeekRecords, manager)
206         insertRecords(lastMonthRecords, manager)
207     }
208 
209     private fun getBodyFatRecord(percentage: Percentage, time: Instant): BodyFatRecord {
210         return BodyFatRecord.Builder(getMetaData(context), time, percentage).build()
211     }
212 
213     private fun getValidBodyFatPercentage(): Percentage {
214         return Percentage.fromValue(Random.nextInt(10, 25).toDouble())
215     }
216 
217     private fun getBodyWaterMassRecord(bodyWaterMass: Mass, time: Instant): BodyWaterMassRecord {
218         return BodyWaterMassRecord.Builder(getMetaData(context), time, bodyWaterMass).build()
219     }
220 
221     private fun getValidMassData(min: Int, max: Int): Mass {
222         return Mass.fromGrams(Random.nextInt(min, max).toDouble())
223     }
224 
225     private fun getBoneMassRecord(mass: Mass, time: Instant): BoneMassRecord {
226         return BoneMassRecord.Builder(getMetaData(context), time, mass).build()
227     }
228 
229     private fun getHeightRecord(height: Length, time: Instant): HeightRecord {
230         return HeightRecord.Builder(getMetaData(context), time, height).build()
231     }
232 
233     private fun getValidHeightData(): Length {
234         return Length.fromMeters(Random.nextDouble(1.6, 1.8))
235     }
236 
237     private fun getLeanBodyMassRecord(mass: Mass, time: Instant): LeanBodyMassRecord {
238         return LeanBodyMassRecord.Builder(getMetaData(context), time, mass).build()
239     }
240 
241     private fun getWeightRecord(weight: Mass, time: Instant): WeightRecord {
242         return WeightRecord.Builder(getMetaData(context), time, weight).build()
243     }
244 
245     private fun getBasalMetabolicRateRecord(basalMetabolicRate: Power, time: Instant): BasalMetabolicRateRecord {
246         return BasalMetabolicRateRecord.Builder(getMetaData(context), time, basalMetabolicRate).build()
247     }
248 
249     private fun getValidBasalMetabolicRateData() : Power {
250         return Power.fromWatts(Random.nextInt(65, 80).toDouble())
251     }
252 }