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.ActiveCaloriesBurnedRecord 21 import android.health.connect.datatypes.ActivityIntensityRecord 22 import android.health.connect.datatypes.ActivityIntensityRecord.ACTIVITY_INTENSITY_TYPE_MODERATE 23 import android.health.connect.datatypes.ActivityIntensityRecord.ACTIVITY_INTENSITY_TYPE_VIGOROUS 24 import android.health.connect.datatypes.CyclingPedalingCadenceRecord 25 import android.health.connect.datatypes.CyclingPedalingCadenceRecord.CyclingPedalingCadenceRecordSample 26 import android.health.connect.datatypes.DistanceRecord 27 import android.health.connect.datatypes.ElevationGainedRecord 28 import android.health.connect.datatypes.ExerciseCompletionGoal 29 import android.health.connect.datatypes.ExerciseLap 30 import android.health.connect.datatypes.ExerciseSegment 31 import android.health.connect.datatypes.ExerciseSegmentType 32 import android.health.connect.datatypes.ExerciseSessionRecord 33 import android.health.connect.datatypes.ExerciseSessionType 34 import android.health.connect.datatypes.FloorsClimbedRecord 35 import android.health.connect.datatypes.PlannedExerciseBlock 36 import android.health.connect.datatypes.PlannedExerciseSessionRecord 37 import android.health.connect.datatypes.PlannedExerciseStep 38 import android.health.connect.datatypes.PlannedExerciseStep.EXERCISE_CATEGORY_ACTIVE 39 import android.health.connect.datatypes.PowerRecord 40 import android.health.connect.datatypes.PowerRecord.PowerRecordSample 41 import android.health.connect.datatypes.SpeedRecord 42 import android.health.connect.datatypes.SpeedRecord.SpeedRecordSample 43 import android.health.connect.datatypes.StepsCadenceRecord 44 import android.health.connect.datatypes.StepsCadenceRecord.StepsCadenceRecordSample 45 import android.health.connect.datatypes.StepsRecord 46 import android.health.connect.datatypes.TotalCaloriesBurnedRecord 47 import android.health.connect.datatypes.Vo2MaxRecord 48 import android.health.connect.datatypes.Vo2MaxRecord.Vo2MaxMeasurementMethod.MEASUREMENT_METHOD_COOPER_TEST 49 import android.health.connect.datatypes.Vo2MaxRecord.Vo2MaxMeasurementMethod.MEASUREMENT_METHOD_HEART_RATE_RATIO 50 import android.health.connect.datatypes.Vo2MaxRecord.Vo2MaxMeasurementMethod.MEASUREMENT_METHOD_METABOLIC_CART 51 import android.health.connect.datatypes.Vo2MaxRecord.Vo2MaxMeasurementMethod.MEASUREMENT_METHOD_MULTISTAGE_FITNESS_TEST 52 import android.health.connect.datatypes.Vo2MaxRecord.Vo2MaxMeasurementMethod.MEASUREMENT_METHOD_OTHER 53 import android.health.connect.datatypes.Vo2MaxRecord.Vo2MaxMeasurementMethod.MEASUREMENT_METHOD_ROCKPORT_FITNESS_TEST 54 import android.health.connect.datatypes.WheelchairPushesRecord 55 import android.health.connect.datatypes.units.Energy 56 import android.health.connect.datatypes.units.Length 57 import android.health.connect.datatypes.units.Power 58 import android.health.connect.datatypes.units.Velocity 59 import com.android.healthconnect.testapps.toolbox.data.ExerciseRoutesTestData 60 import com.android.healthconnect.testapps.toolbox.data.ExerciseRoutesTestData.Companion.generateExerciseRouteFromLocations 61 import com.android.healthconnect.testapps.toolbox.data.ExerciseRoutesTestData.Companion.routeDataMap 62 import com.android.healthconnect.testapps.toolbox.utils.GeneralUtils.Companion.getMetaData 63 import com.android.healthconnect.testapps.toolbox.utils.GeneralUtils.Companion.insertRecords 64 import java.time.Duration.ofDays 65 import java.time.Duration.ofMinutes 66 import java.time.Instant 67 import java.time.temporal.ChronoUnit 68 import kotlin.random.Random 69 import kotlinx.coroutines.runBlocking 70 71 class SeedActivityData(private val context: Context, private val manager: HealthConnectManager) { 72 73 companion object { 74 val VALID_VO2_MEASUREMENT_METHOD = 75 setOf( 76 MEASUREMENT_METHOD_OTHER, 77 MEASUREMENT_METHOD_METABOLIC_CART, 78 MEASUREMENT_METHOD_HEART_RATE_RATIO, 79 MEASUREMENT_METHOD_COOPER_TEST, 80 MEASUREMENT_METHOD_MULTISTAGE_FITNESS_TEST, 81 MEASUREMENT_METHOD_ROCKPORT_FITNESS_TEST, 82 ) 83 } 84 85 private val start = Instant.now().truncatedTo(ChronoUnit.DAYS) 86 private val yesterday = start.minus(ofDays(1)) 87 private val lastWeek = start.minus(ofDays(7)) 88 private val lastMonth = start.minus(ofDays(31)) 89 90 fun seedActivityData() { 91 runBlocking { 92 try { 93 seedActivityIntensityData() 94 seedStepsData() 95 seedDistanceData() 96 seedElevationGainedRecord() 97 seedActiveCaloriesBurnedData() 98 seedExerciseSessionData() 99 seedPlannedExerciseSessionRecord() 100 seedSpeedRecord() 101 seedPowerRecord() 102 seedCyclingPedalingCadenceRecord() 103 seedFloorsClimbedRecord() 104 seedTotalCaloriesBurnedRecord() 105 seedWheelchairPushesRecord() 106 seedVo2MaxRecord() 107 seedStepsCadenceRecord() 108 } catch (ex: Exception) { 109 throw ex 110 } 111 } 112 } 113 114 private suspend fun seedActivityIntensityData() { 115 val records = 116 listOf(start, yesterday, lastWeek, lastMonth).flatMap { baseTime -> 117 List(3) { 118 val startTime = baseTime.plus(ofMinutes(5 * it.toLong())) 119 120 ActivityIntensityRecord.Builder( 121 getMetaData(context), 122 startTime, 123 startTime.plus(ofMinutes(3)), 124 if (Random.nextBoolean()) ACTIVITY_INTENSITY_TYPE_MODERATE 125 else ACTIVITY_INTENSITY_TYPE_VIGOROUS, 126 ) 127 .build() 128 } 129 } 130 131 insertRecords(records, manager) 132 } 133 134 private suspend fun seedStepsData() { 135 val records = (1L..50).map { count -> getStepsRecord(count, start.plus(ofMinutes(count))) } 136 val yesterdayRecords = 137 (1L..3).map { count -> getStepsRecord(count, yesterday.plus(ofMinutes(count))) } 138 val lastWeekRecords = 139 (1L..3).map { count -> getStepsRecord(count, lastWeek.plus(ofMinutes(count))) } 140 val lastMonthRecords = 141 (1L..3).map { count -> getStepsRecord(count, lastMonth.plus(ofMinutes(count))) } 142 143 insertRecords(records, manager) 144 insertRecords(yesterdayRecords, manager) 145 insertRecords(lastWeekRecords, manager) 146 insertRecords(lastMonthRecords, manager) 147 } 148 149 private suspend fun seedDistanceData() { 150 val records = 151 (1L..50).map { timeOffSet -> 152 getDistanceData(getValidLengthData(500, 5000), start.plus(ofMinutes(timeOffSet))) 153 } 154 val yesterdayRecords = 155 (1L..3).map { timeOffSet -> 156 getDistanceData( 157 getValidLengthData(500, 5000), 158 yesterday.plus(ofMinutes(timeOffSet)), 159 ) 160 } 161 val lastWeekRecords = 162 (1L..3).map { timeOffSet -> 163 getDistanceData(getValidLengthData(500, 5000), lastWeek.plus(ofMinutes(timeOffSet))) 164 } 165 val lastMonthRecords = 166 (1L..3).map { timeOffSet -> 167 getDistanceData( 168 getValidLengthData(500, 5000), 169 lastMonth.plus(ofMinutes(timeOffSet)), 170 ) 171 } 172 173 insertRecords(records, manager) 174 insertRecords(yesterdayRecords, manager) 175 insertRecords(lastWeekRecords, manager) 176 insertRecords(lastMonthRecords, manager) 177 } 178 179 private suspend fun seedElevationGainedRecord() { 180 val records = 181 (1L..3).map { timeOffSet -> 182 getElevationGainedRecord( 183 getValidLengthData(500, 5000), 184 start.plus(ofMinutes(timeOffSet)), 185 ) 186 } 187 val yesterdayRecords = 188 (1L..3).map { timeOffSet -> 189 getElevationGainedRecord( 190 getValidLengthData(500, 5000), 191 yesterday.plus(ofMinutes(timeOffSet)), 192 ) 193 } 194 val lastWeekRecords = 195 (1L..3).map { timeOffSet -> 196 getElevationGainedRecord( 197 getValidLengthData(500, 5000), 198 lastWeek.plus(ofMinutes(timeOffSet)), 199 ) 200 } 201 val lastMonthRecords = 202 (1L..3).map { timeOffSet -> 203 getElevationGainedRecord( 204 getValidLengthData(500, 5000), 205 lastMonth.plus(ofMinutes(timeOffSet)), 206 ) 207 } 208 209 insertRecords(records, manager) 210 insertRecords(yesterdayRecords, manager) 211 insertRecords(lastWeekRecords, manager) 212 insertRecords(lastMonthRecords, manager) 213 } 214 215 private suspend fun seedActiveCaloriesBurnedData() { 216 val records = 217 (1L..15).map { timeOffSet -> 218 getActiveCaloriesBurnedRecord(getValidEnergy(), start.plus(ofMinutes(timeOffSet))) 219 } 220 val yesterdayRecords = 221 (1L..3).map { timeOffSet -> 222 getActiveCaloriesBurnedRecord( 223 getValidEnergy(), 224 yesterday.plus(ofMinutes(timeOffSet)), 225 ) 226 } 227 val lastWeekRecords = 228 (1L..3).map { timeOffSet -> 229 getActiveCaloriesBurnedRecord( 230 getValidEnergy(), 231 lastWeek.plus(ofMinutes(timeOffSet)), 232 ) 233 } 234 val lastMonthRecords = 235 (1L..3).map { timeOffSet -> 236 getActiveCaloriesBurnedRecord( 237 getValidEnergy(), 238 lastMonth.plus(ofMinutes(timeOffSet)), 239 ) 240 } 241 242 insertRecords(records, manager) 243 insertRecords(yesterdayRecords, manager) 244 insertRecords(lastWeekRecords, manager) 245 insertRecords(lastMonthRecords, manager) 246 } 247 248 private suspend fun seedExerciseSessionData() { 249 val records = 250 (1L..3).map { timeOffSet -> 251 val exerciseSegments = ArrayList<ExerciseSegment>() 252 repeat(5) { i -> 253 exerciseSegments.add( 254 ExerciseSegment.Builder( 255 start.plus(ofMinutes(timeOffSet + i)), 256 start.plus(ofMinutes(timeOffSet + i + 1)), 257 getValidSegmentType(), 258 ) 259 .build() 260 ) 261 } 262 val exerciseLaps = ArrayList<ExerciseLap>() 263 repeat(5) { i -> 264 exerciseLaps.add( 265 ExerciseLap.Builder( 266 start.plus(ofMinutes(timeOffSet + i)), 267 start.plus(ofMinutes(timeOffSet + i + 1)), 268 ) 269 .setLength(getValidLengthData(50, 1050)) 270 .build() 271 ) 272 } 273 274 getExerciseSessionRecord( 275 exerciseSegments, 276 exerciseLaps, 277 start.plus(ofMinutes(timeOffSet)), 278 ) 279 } 280 val yesterdayRecords = 281 (1L..3).map { timeOffSet -> 282 val exerciseSegments = ArrayList<ExerciseSegment>() 283 repeat(5) { i -> 284 exerciseSegments.add( 285 ExerciseSegment.Builder( 286 yesterday.plus(ofMinutes(timeOffSet + i)), 287 yesterday.plus(ofMinutes(timeOffSet + i + 1)), 288 getValidSegmentType(), 289 ) 290 .build() 291 ) 292 } 293 val exerciseLaps = ArrayList<ExerciseLap>() 294 repeat(5) { i -> 295 exerciseLaps.add( 296 ExerciseLap.Builder( 297 yesterday.plus(ofMinutes(timeOffSet + i)), 298 yesterday.plus(ofMinutes(timeOffSet + i + 1)), 299 ) 300 .setLength(getValidLengthData(50, 1050)) 301 .build() 302 ) 303 } 304 getExerciseSessionRecord( 305 exerciseSegments, 306 exerciseLaps, 307 yesterday.plus(ofMinutes(timeOffSet)), 308 ) 309 } 310 val lastWeekRecords = 311 (1L..3).map { timeOffSet -> 312 val exerciseSegments = ArrayList<ExerciseSegment>() 313 repeat(5) { i -> 314 exerciseSegments.add( 315 ExerciseSegment.Builder( 316 lastWeek.plus(ofMinutes(timeOffSet + i)), 317 lastWeek.plus(ofMinutes(timeOffSet + i + 1)), 318 getValidSegmentType(), 319 ) 320 .build() 321 ) 322 } 323 val exerciseLaps = ArrayList<ExerciseLap>() 324 repeat(5) { i -> 325 exerciseLaps.add( 326 ExerciseLap.Builder( 327 lastWeek.plus(ofMinutes(timeOffSet + i)), 328 lastWeek.plus(ofMinutes(timeOffSet + i + 1)), 329 ) 330 .setLength(getValidLengthData(50, 1050)) 331 .build() 332 ) 333 } 334 getExerciseSessionRecord( 335 exerciseSegments, 336 exerciseLaps, 337 lastWeek.plus(ofMinutes(timeOffSet)), 338 ) 339 } 340 val lastMonthRecords = 341 (1L..3).map { timeOffSet -> 342 val exerciseSegments = ArrayList<ExerciseSegment>() 343 repeat(5) { i -> 344 exerciseSegments.add( 345 ExerciseSegment.Builder( 346 lastMonth.plus(ofMinutes(timeOffSet + i)), 347 lastMonth.plus(ofMinutes(timeOffSet + i + 1)), 348 getValidSegmentType(), 349 ) 350 .build() 351 ) 352 } 353 val exerciseLaps = ArrayList<ExerciseLap>() 354 repeat(5) { i -> 355 exerciseLaps.add( 356 ExerciseLap.Builder( 357 lastMonth.plus(ofMinutes(timeOffSet + i)), 358 lastMonth.plus(ofMinutes(timeOffSet + i + 1)), 359 ) 360 .setLength(getValidLengthData(50, 1050)) 361 .build() 362 ) 363 } 364 getExerciseSessionRecord( 365 exerciseSegments, 366 exerciseLaps, 367 lastMonth.plus(ofMinutes(timeOffSet)), 368 ) 369 } 370 371 insertRecords(records, manager) 372 insertRecords(yesterdayRecords, manager) 373 insertRecords(lastWeekRecords, manager) 374 insertRecords(lastMonthRecords, manager) 375 } 376 377 private suspend fun seedPlannedExerciseSessionRecord() { 378 val tomorrow = start.plus(ofDays(1)) 379 val records = 380 (1L..3).map { timeOffSet -> 381 val plannedExerciseBlocks = ArrayList<PlannedExerciseBlock>() 382 repeat(10) { plannedExerciseBlocks.add(getValidPlannedExerciseBlockData()) } 383 getPlannedExerciseSessionRecord( 384 plannedExerciseBlocks, 385 start.plus(ofMinutes(timeOffSet)), 386 ) 387 } 388 val tomorrowRecords = 389 (1L..3).map { timeOffSet -> 390 val plannedExerciseBlocks = ArrayList<PlannedExerciseBlock>() 391 repeat(10) { plannedExerciseBlocks.add(getValidPlannedExerciseBlockData()) } 392 getPlannedExerciseSessionRecord( 393 plannedExerciseBlocks, 394 tomorrow.plus(ofMinutes(timeOffSet)), 395 ) 396 } 397 val yesterdayRecords = 398 (1L..3).map { timeOffSet -> 399 val plannedExerciseBlocks = ArrayList<PlannedExerciseBlock>() 400 repeat(10) { plannedExerciseBlocks.add(getValidPlannedExerciseBlockData()) } 401 getPlannedExerciseSessionRecord( 402 plannedExerciseBlocks, 403 yesterday.plus(ofMinutes(timeOffSet)), 404 ) 405 } 406 val lastWeekRecords = 407 (1L..3).map { timeOffSet -> 408 val plannedExerciseBlocks = ArrayList<PlannedExerciseBlock>() 409 repeat(10) { plannedExerciseBlocks.add(getValidPlannedExerciseBlockData()) } 410 getPlannedExerciseSessionRecord( 411 plannedExerciseBlocks, 412 lastWeek.plus(ofMinutes(timeOffSet)), 413 ) 414 } 415 val lastMonthRecords = 416 (1L..3).map { timeOffSet -> 417 val plannedExerciseBlocks = ArrayList<PlannedExerciseBlock>() 418 repeat(10) { plannedExerciseBlocks.add(getValidPlannedExerciseBlockData()) } 419 getPlannedExerciseSessionRecord( 420 plannedExerciseBlocks, 421 lastMonth.plus(ofMinutes(timeOffSet)), 422 ) 423 } 424 425 insertRecords(records, manager) 426 insertRecords(tomorrowRecords, manager) 427 insertRecords(yesterdayRecords, manager) 428 insertRecords(lastWeekRecords, manager) 429 insertRecords(lastMonthRecords, manager) 430 } 431 432 private suspend fun seedSpeedRecord() { 433 val records = 434 (1L..3).map { timeOffSet -> 435 val speedRecordSample = ArrayList<SpeedRecordSample>() 436 repeat(10) { i -> 437 speedRecordSample.add( 438 SpeedRecordSample( 439 getValidSpeedData(), 440 start.plus(ofMinutes(timeOffSet + i)), 441 ) 442 ) 443 } 444 getSpeedRecord(speedRecordSample, start.plus(ofMinutes(timeOffSet))) 445 } 446 val yesterdayRecords = 447 (1L..3).map { timeOffSet -> 448 val speedRecordSample = ArrayList<SpeedRecordSample>() 449 repeat(10) { i -> 450 speedRecordSample.add( 451 SpeedRecordSample( 452 getValidSpeedData(), 453 yesterday.plus(ofMinutes(timeOffSet + i)), 454 ) 455 ) 456 } 457 getSpeedRecord(speedRecordSample, yesterday.plus(ofMinutes(timeOffSet))) 458 } 459 val lastWeekRecords = 460 (1L..3).map { timeOffSet -> 461 val speedRecordSample = ArrayList<SpeedRecordSample>() 462 repeat(10) { i -> 463 speedRecordSample.add( 464 SpeedRecordSample( 465 getValidSpeedData(), 466 lastWeek.plus(ofMinutes(timeOffSet + i)), 467 ) 468 ) 469 } 470 getSpeedRecord(speedRecordSample, lastWeek.plus(ofMinutes(timeOffSet))) 471 } 472 val lastMonthRecords = 473 (1L..3).map { timeOffSet -> 474 val speedRecordSample = ArrayList<SpeedRecordSample>() 475 repeat(10) { i -> 476 speedRecordSample.add( 477 SpeedRecordSample( 478 getValidSpeedData(), 479 lastMonth.plus(ofMinutes(timeOffSet + i)), 480 ) 481 ) 482 } 483 getSpeedRecord(speedRecordSample, lastMonth.plus(ofMinutes(timeOffSet))) 484 } 485 486 insertRecords(records, manager) 487 insertRecords(yesterdayRecords, manager) 488 insertRecords(lastWeekRecords, manager) 489 insertRecords(lastMonthRecords, manager) 490 } 491 492 private suspend fun seedPowerRecord() { 493 val records = 494 (1L..3).map { timeOffSet -> 495 val powerRecordSample = ArrayList<PowerRecordSample>() 496 repeat(10) { i -> 497 powerRecordSample.add( 498 PowerRecordSample( 499 getValidPowerData(), 500 start.plus(ofMinutes(timeOffSet + i)), 501 ) 502 ) 503 } 504 505 getPowerRecord(powerRecordSample, start.plus(ofMinutes(timeOffSet))) 506 } 507 val yesterdayRecords = 508 (1L..3).map { timeOffSet -> 509 val powerRecordSample = ArrayList<PowerRecordSample>() 510 repeat(10) { i -> 511 powerRecordSample.add( 512 PowerRecordSample( 513 getValidPowerData(), 514 yesterday.plus(ofMinutes(timeOffSet + i)), 515 ) 516 ) 517 } 518 519 getPowerRecord(powerRecordSample, yesterday.plus(ofMinutes(timeOffSet))) 520 } 521 val lastWeekRecords = 522 (1L..3).map { timeOffSet -> 523 val powerRecordSample = ArrayList<PowerRecordSample>() 524 repeat(10) { i -> 525 powerRecordSample.add( 526 PowerRecordSample( 527 getValidPowerData(), 528 lastWeek.plus(ofMinutes(timeOffSet + i)), 529 ) 530 ) 531 } 532 533 getPowerRecord(powerRecordSample, lastWeek.plus(ofMinutes(timeOffSet))) 534 } 535 val lastMonthRecords = 536 (1L..3).map { timeOffSet -> 537 val powerRecordSample = ArrayList<PowerRecordSample>() 538 repeat(10) { i -> 539 powerRecordSample.add( 540 PowerRecordSample( 541 getValidPowerData(), 542 lastMonth.plus(ofMinutes(timeOffSet + i)), 543 ) 544 ) 545 } 546 547 getPowerRecord(powerRecordSample, lastMonth.plus(ofMinutes(timeOffSet))) 548 } 549 550 insertRecords(records, manager) 551 insertRecords(yesterdayRecords, manager) 552 insertRecords(lastWeekRecords, manager) 553 insertRecords(lastMonthRecords, manager) 554 } 555 556 private suspend fun seedCyclingPedalingCadenceRecord() { 557 val records = 558 (1L..3).map { timeOffSet -> 559 val cyclingCadenceSample = ArrayList<CyclingPedalingCadenceRecordSample>() 560 repeat(10) { i -> 561 cyclingCadenceSample.add( 562 CyclingPedalingCadenceRecordSample( 563 getValidDoubleData(60, 100), 564 start.plus(ofMinutes(timeOffSet + i)), 565 ) 566 ) 567 } 568 569 getCyclingPedalingCadenceRecord( 570 cyclingCadenceSample, 571 start.plus(ofMinutes(timeOffSet)), 572 ) 573 } 574 val yesterdayRecords = 575 (1L..3).map { timeOffSet -> 576 val cyclingCadenceSample = ArrayList<CyclingPedalingCadenceRecordSample>() 577 repeat(10) { i -> 578 cyclingCadenceSample.add( 579 CyclingPedalingCadenceRecordSample( 580 getValidDoubleData(60, 100), 581 yesterday.plus(ofMinutes(timeOffSet + i)), 582 ) 583 ) 584 } 585 586 getCyclingPedalingCadenceRecord( 587 cyclingCadenceSample, 588 yesterday.plus(ofMinutes(timeOffSet)), 589 ) 590 } 591 val lastWeekRecords = 592 (1L..3).map { timeOffSet -> 593 val cyclingCadenceSample = ArrayList<CyclingPedalingCadenceRecordSample>() 594 repeat(10) { i -> 595 cyclingCadenceSample.add( 596 CyclingPedalingCadenceRecordSample( 597 getValidDoubleData(60, 100), 598 lastWeek.plus(ofMinutes(timeOffSet + i)), 599 ) 600 ) 601 } 602 603 getCyclingPedalingCadenceRecord( 604 cyclingCadenceSample, 605 lastWeek.plus(ofMinutes(timeOffSet)), 606 ) 607 } 608 val lastMonthRecords = 609 (1L..3).map { timeOffSet -> 610 val cyclingCadenceSample = ArrayList<CyclingPedalingCadenceRecordSample>() 611 repeat(10) { i -> 612 cyclingCadenceSample.add( 613 CyclingPedalingCadenceRecordSample( 614 getValidDoubleData(60, 100), 615 lastMonth.plus(ofMinutes(timeOffSet + i)), 616 ) 617 ) 618 } 619 620 getCyclingPedalingCadenceRecord( 621 cyclingCadenceSample, 622 lastMonth.plus(ofMinutes(timeOffSet)), 623 ) 624 } 625 626 insertRecords(records, manager) 627 insertRecords(yesterdayRecords, manager) 628 insertRecords(lastWeekRecords, manager) 629 insertRecords(lastMonthRecords, manager) 630 } 631 632 private suspend fun seedFloorsClimbedRecord() { 633 val records = 634 (1L..3).map { timeOffSet -> 635 getFloorsClimbedRecord(getValidDoubleData(1, 10), start.plus(ofMinutes(timeOffSet))) 636 } 637 val yesterdayRecords = 638 (1L..3).map { timeOffSet -> 639 getFloorsClimbedRecord( 640 getValidDoubleData(1, 10), 641 yesterday.plus(ofMinutes(timeOffSet)), 642 ) 643 } 644 val lastWeekRecords = 645 (1L..3).map { timeOffSet -> 646 getFloorsClimbedRecord( 647 getValidDoubleData(1, 10), 648 lastWeek.plus(ofMinutes(timeOffSet)), 649 ) 650 } 651 val lastMonthRecords = 652 (1L..3).map { timeOffSet -> 653 getFloorsClimbedRecord( 654 getValidDoubleData(1, 10), 655 lastMonth.plus(ofMinutes(timeOffSet)), 656 ) 657 } 658 659 insertRecords(records, manager) 660 insertRecords(yesterdayRecords, manager) 661 insertRecords(lastWeekRecords, manager) 662 insertRecords(lastMonthRecords, manager) 663 } 664 665 private suspend fun seedTotalCaloriesBurnedRecord() { 666 val records = 667 (1L..3).map { timeOffSet -> 668 getTotalCaloriesBurnedRecord(getValidEnergy(), start.plus(ofMinutes(timeOffSet))) 669 } 670 val yesterdayRecords = 671 (1L..3).map { timeOffSet -> 672 getTotalCaloriesBurnedRecord( 673 getValidEnergy(), 674 yesterday.plus(ofMinutes(timeOffSet)), 675 ) 676 } 677 val lastWeekRecords = 678 (1L..3).map { timeOffSet -> 679 getTotalCaloriesBurnedRecord(getValidEnergy(), lastWeek.plus(ofMinutes(timeOffSet))) 680 } 681 val lastMonthRecords = 682 (1L..3).map { timeOffSet -> 683 getTotalCaloriesBurnedRecord( 684 getValidEnergy(), 685 lastMonth.plus(ofMinutes(timeOffSet)), 686 ) 687 } 688 689 insertRecords(records, manager) 690 insertRecords(yesterdayRecords, manager) 691 insertRecords(lastWeekRecords, manager) 692 insertRecords(lastMonthRecords, manager) 693 } 694 695 private suspend fun seedWheelchairPushesRecord() { 696 val records = 697 (1L..3).map { timeOffSet -> 698 getWheelchairPushesRecord(timeOffSet, start.plus(ofMinutes(timeOffSet))) 699 } 700 val yesterdayRecords = 701 (1L..3).map { timeOffSet -> 702 getWheelchairPushesRecord(timeOffSet, yesterday.plus(ofMinutes(timeOffSet))) 703 } 704 val lastWeekRecords = 705 (1L..3).map { timeOffSet -> 706 getWheelchairPushesRecord(timeOffSet, lastWeek.plus(ofMinutes(timeOffSet))) 707 } 708 val lastMonthRecords = 709 (1L..3).map { timeOffSet -> 710 getWheelchairPushesRecord(timeOffSet, lastMonth.plus(ofMinutes(timeOffSet))) 711 } 712 713 insertRecords(records, manager) 714 insertRecords(yesterdayRecords, manager) 715 insertRecords(lastWeekRecords, manager) 716 insertRecords(lastMonthRecords, manager) 717 } 718 719 private suspend fun seedVo2MaxRecord() { 720 val records = 721 (1L..3).map { timeOffSet -> 722 getVo2MaxRecord( 723 getValidVo2MeasurementMethod(), 724 getValidDoubleData(25, 40), 725 start.plus(ofMinutes(timeOffSet)), 726 ) 727 } 728 val yesterdayRecords = 729 (1L..3).map { timeOffSet -> 730 getVo2MaxRecord( 731 getValidVo2MeasurementMethod(), 732 getValidDoubleData(25, 40), 733 yesterday.plus(ofMinutes(timeOffSet)), 734 ) 735 } 736 val lastWeekRecords = 737 (1L..3).map { timeOffSet -> 738 getVo2MaxRecord( 739 getValidVo2MeasurementMethod(), 740 getValidDoubleData(25, 40), 741 lastWeek.plus(ofMinutes(timeOffSet)), 742 ) 743 } 744 val lastMonthRecords = 745 (1L..3).map { timeOffSet -> 746 getVo2MaxRecord( 747 getValidVo2MeasurementMethod(), 748 getValidDoubleData(25, 40), 749 lastMonth.plus(ofMinutes(timeOffSet)), 750 ) 751 } 752 753 insertRecords(records, manager) 754 insertRecords(yesterdayRecords, manager) 755 insertRecords(lastWeekRecords, manager) 756 insertRecords(lastMonthRecords, manager) 757 } 758 759 private suspend fun seedStepsCadenceRecord() { 760 val records = 761 (1L..3).map { timeOffSet -> 762 val stepsCadenceRecordSample = ArrayList<StepsCadenceRecordSample>() 763 repeat(10) { i -> 764 stepsCadenceRecordSample.add( 765 StepsCadenceRecordSample( 766 getValidDoubleData(160, 180), 767 start.plus(ofMinutes(timeOffSet + i)), 768 ) 769 ) 770 } 771 getStepsCadenceRecord(stepsCadenceRecordSample, start.plus(ofMinutes(timeOffSet))) 772 } 773 val yesterdayRecords = 774 (1L..3).map { timeOffSet -> 775 val stepsCadenceRecordSample = ArrayList<StepsCadenceRecordSample>() 776 repeat(10) { i -> 777 stepsCadenceRecordSample.add( 778 StepsCadenceRecordSample( 779 getValidDoubleData(160, 180), 780 yesterday.plus(ofMinutes(timeOffSet + i)), 781 ) 782 ) 783 } 784 getStepsCadenceRecord( 785 stepsCadenceRecordSample, 786 yesterday.plus(ofMinutes(timeOffSet)), 787 ) 788 } 789 val lastWeekRecords = 790 (1L..3).map { timeOffSet -> 791 val stepsCadenceRecordSample = ArrayList<StepsCadenceRecordSample>() 792 repeat(10) { i -> 793 stepsCadenceRecordSample.add( 794 StepsCadenceRecordSample( 795 getValidDoubleData(160, 180), 796 lastWeek.plus(ofMinutes(timeOffSet + i)), 797 ) 798 ) 799 } 800 getStepsCadenceRecord( 801 stepsCadenceRecordSample, 802 lastWeek.plus(ofMinutes(timeOffSet)), 803 ) 804 } 805 val lastMonthRecords = 806 (1L..3).map { timeOffSet -> 807 val stepsCadenceRecordSample = ArrayList<StepsCadenceRecordSample>() 808 repeat(10) { i -> 809 stepsCadenceRecordSample.add( 810 StepsCadenceRecordSample( 811 getValidDoubleData(160, 180), 812 lastMonth.plus(ofMinutes(timeOffSet + i)), 813 ) 814 ) 815 } 816 getStepsCadenceRecord( 817 stepsCadenceRecordSample, 818 lastMonth.plus(ofMinutes(timeOffSet)), 819 ) 820 } 821 822 insertRecords(records, manager) 823 insertRecords(yesterdayRecords, manager) 824 insertRecords(lastWeekRecords, manager) 825 insertRecords(lastMonthRecords, manager) 826 } 827 828 private fun getStepsRecord(count: Long, time: Instant): StepsRecord { 829 return StepsRecord.Builder(getMetaData(context), time, time.plusSeconds(30), count).build() 830 } 831 832 private fun getDistanceData(length: Length, time: Instant): DistanceRecord { 833 return DistanceRecord.Builder(getMetaData(context), time, time.plusSeconds(30), length) 834 .build() 835 } 836 837 private fun getValidLengthData(min: Int, max: Int): Length { 838 return Length.fromMeters((Random.nextInt(min, max)).toDouble()) 839 } 840 841 private fun getElevationGainedRecord(distance: Length, time: Instant): ElevationGainedRecord { 842 return ElevationGainedRecord.Builder( 843 getMetaData(context), 844 time, 845 time.plusSeconds(30), 846 distance, 847 ) 848 .build() 849 } 850 851 private fun getActiveCaloriesBurnedRecord( 852 energy: Energy, 853 time: Instant, 854 ): ActiveCaloriesBurnedRecord { 855 return ActiveCaloriesBurnedRecord.Builder( 856 getMetaData(context), 857 time, 858 time.plusSeconds(30), 859 energy, 860 ) 861 .build() 862 } 863 864 private fun getValidEnergy(): Energy { 865 return Energy.fromCalories((Random.nextInt(500, 5000)).toDouble()) 866 } 867 868 private fun getExerciseSessionRecord( 869 exerciseSegments: List<ExerciseSegment>, 870 laps: List<ExerciseLap>, 871 time: Instant, 872 ): ExerciseSessionRecord { 873 return ExerciseSessionRecord.Builder( 874 getMetaData(context), 875 time, 876 time.plusSeconds(1000), 877 ExerciseSessionType.EXERCISE_SESSION_TYPE_EXERCISE_CLASS, 878 ) 879 .setSegments(exerciseSegments) 880 .setLaps(laps) 881 .setRoute( 882 generateExerciseRouteFromLocations( 883 getValidExerciseRouteLocation(), 884 time.toEpochMilli(), 885 ) 886 ) 887 .build() 888 } 889 890 private fun getValidExerciseRouteLocation(): 891 List<ExerciseRoutesTestData.ExerciseRouteLocationData> { 892 return routeDataMap.values.random() 893 } 894 895 private fun getValidSegmentType(): Int { 896 return ExerciseSegmentType.EXERCISE_SEGMENT_TYPE_STRETCHING 897 } 898 899 private fun getPlannedExerciseSessionRecord( 900 plannedExerciseBlocks: List<PlannedExerciseBlock>, 901 time: Instant, 902 ): PlannedExerciseSessionRecord { 903 return PlannedExerciseSessionRecord.Builder( 904 getMetaData(context), 905 ExerciseSessionType.EXERCISE_SESSION_TYPE_EXERCISE_CLASS, 906 time, 907 time.plusSeconds(30), 908 ) 909 .setBlocks(plannedExerciseBlocks) 910 .build() 911 } 912 913 private fun getValidPlannedExerciseBlockData(): PlannedExerciseBlock { 914 return PlannedExerciseBlock.Builder(Random.nextInt(1, 5)) 915 .addStep(getValidPlannedExerciseStepData()) 916 .build() 917 } 918 919 private fun getValidPlannedExerciseStepData(): PlannedExerciseStep { 920 return PlannedExerciseStep.Builder( 921 ExerciseSessionType.EXERCISE_SESSION_TYPE_EXERCISE_CLASS, 922 EXERCISE_CATEGORY_ACTIVE, 923 getValidCompletionGoal(), 924 ) 925 .build() 926 } 927 928 private fun getValidCompletionGoal(): ExerciseCompletionGoal { 929 return ExerciseCompletionGoal.StepsGoal(Random.nextInt(100, 500)) 930 } 931 932 private fun getSpeedRecord(speed: List<SpeedRecordSample>, time: Instant): SpeedRecord { 933 return SpeedRecord.Builder(getMetaData(context), time, time.plusSeconds(1000), speed) 934 .build() 935 } 936 937 private fun getValidSpeedData(): Velocity { 938 return Velocity.fromMetersPerSecond(Random.nextInt(1, 10).toDouble()) 939 } 940 941 private fun getPowerRecord(power: List<PowerRecordSample>, time: Instant): PowerRecord { 942 return PowerRecord.Builder(getMetaData(context), time, time.plusSeconds(1000), power) 943 .build() 944 } 945 946 private fun getValidPowerData(): Power { 947 return Power.fromWatts(Random.nextInt(150, 400).toDouble()) 948 } 949 950 private fun getCyclingPedalingCadenceRecord( 951 cyclingCadenceSample: List<CyclingPedalingCadenceRecordSample>, 952 time: Instant, 953 ): CyclingPedalingCadenceRecord { 954 return CyclingPedalingCadenceRecord.Builder( 955 getMetaData(context), 956 time, 957 time.plusSeconds(1000), 958 cyclingCadenceSample, 959 ) 960 .build() 961 } 962 963 private fun getFloorsClimbedRecord(floors: Double, time: Instant): FloorsClimbedRecord { 964 return FloorsClimbedRecord.Builder(getMetaData(context), time, time.plusSeconds(30), floors) 965 .build() 966 } 967 968 private fun getTotalCaloriesBurnedRecord( 969 energy: Energy, 970 time: Instant, 971 ): TotalCaloriesBurnedRecord { 972 return TotalCaloriesBurnedRecord.Builder( 973 getMetaData(context), 974 time, 975 time.plusSeconds(30), 976 energy, 977 ) 978 .build() 979 } 980 981 private fun getWheelchairPushesRecord(count: Long, time: Instant): WheelchairPushesRecord { 982 return WheelchairPushesRecord.Builder( 983 getMetaData(context), 984 time, 985 time.plusSeconds(30), 986 count, 987 ) 988 .build() 989 } 990 991 private fun getVo2MaxRecord( 992 measurementMethod: Int, 993 vo2Max: Double, 994 time: Instant, 995 ): Vo2MaxRecord { 996 return Vo2MaxRecord.Builder(getMetaData(context), time, measurementMethod, vo2Max).build() 997 } 998 999 private fun getValidVo2MeasurementMethod(): Int { 1000 return VALID_VO2_MEASUREMENT_METHOD.random() 1001 } 1002 1003 private fun getStepsCadenceRecord( 1004 stepsCadenceRecordSample: List<StepsCadenceRecordSample>, 1005 time: Instant, 1006 ): StepsCadenceRecord { 1007 return StepsCadenceRecord.Builder( 1008 getMetaData(context), 1009 time, 1010 time.plusSeconds(1000), 1011 stepsCadenceRecordSample, 1012 ) 1013 .build() 1014 } 1015 1016 private fun getValidDoubleData(min: Int, max: Int): Double { 1017 return Random.nextInt(min, max).toDouble() 1018 } 1019 } 1020