@cariva-dev/exercise-sdk 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/CarivaExerciseSdk.podspec +20 -0
  2. package/README.md +374 -0
  3. package/android/build.gradle +66 -0
  4. package/android/src/main/AndroidManifest.xml +40 -0
  5. package/android/src/main/java/com/carivaexercisesdk/CarivaExerciseSdkPackage.kt +30 -0
  6. package/android/src/main/java/com/carivaexercisesdk/HealthConnectModule.kt +222 -0
  7. package/android/src/main/java/com/carivaexercisesdk/HealthConnectPermissionUsageActivity.kt +11 -0
  8. package/android/src/main/java/com/carivaexercisesdk/HealthConnectPermissionsRationaleActivity.kt +11 -0
  9. package/android/src/main/java/com/carivaexercisesdk/Pagination.kt +23 -0
  10. package/android/src/main/java/com/carivaexercisesdk/application/connection/command/ConnectCommand.kt +12 -0
  11. package/android/src/main/java/com/carivaexercisesdk/application/connection/dto/ConnectResultDto.kt +13 -0
  12. package/android/src/main/java/com/carivaexercisesdk/application/connection/handler/ConnectHandler.kt +79 -0
  13. package/android/src/main/java/com/carivaexercisesdk/application/connection/port/HealthConnectConnectionPort.kt +16 -0
  14. package/android/src/main/java/com/carivaexercisesdk/application/connection/port/PermissionRequestPort.kt +5 -0
  15. package/android/src/main/java/com/carivaexercisesdk/application/datasource/command/SetDatasourcePolicyCommand.kt +6 -0
  16. package/android/src/main/java/com/carivaexercisesdk/application/datasource/handler/GetDatasourcePolicyHandler.kt +10 -0
  17. package/android/src/main/java/com/carivaexercisesdk/application/datasource/handler/SetDatasourcePolicyHandler.kt +22 -0
  18. package/android/src/main/java/com/carivaexercisesdk/application/datasource/port/DatasourcePolicyRepository.kt +9 -0
  19. package/android/src/main/java/com/carivaexercisesdk/application/exercise/dto/BasalReadResultDto.kt +11 -0
  20. package/android/src/main/java/com/carivaexercisesdk/application/exercise/dto/ExerciseDataDto.kt +41 -0
  21. package/android/src/main/java/com/carivaexercisesdk/application/exercise/handler/GetExerciseDataHandler.kt +346 -0
  22. package/android/src/main/java/com/carivaexercisesdk/application/exercise/port/ExerciseRecordPort.kt +45 -0
  23. package/android/src/main/java/com/carivaexercisesdk/application/exercise/query/GetExerciseDataQuery.kt +9 -0
  24. package/android/src/main/java/com/carivaexercisesdk/domain/connection/entity/ConnectionAggregate.kt +13 -0
  25. package/android/src/main/java/com/carivaexercisesdk/domain/connection/service/ConnectionDecisionService.kt +37 -0
  26. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/ConnectionNextAction.kt +8 -0
  27. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/HealthConnectStatus.kt +8 -0
  28. package/android/src/main/java/com/carivaexercisesdk/domain/connection/valueobject/PermissionScope.kt +36 -0
  29. package/android/src/main/java/com/carivaexercisesdk/domain/datasource/entity/DatasourcePolicy.kt +8 -0
  30. package/android/src/main/java/com/carivaexercisesdk/domain/datasource/valueobject/DatasourceType.kt +14 -0
  31. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/ExerciseDomainService.kt +89 -0
  32. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectCaloriesFallbackMerger.kt +351 -0
  33. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectInternalsConstants.kt +55 -0
  34. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectModuleInternals.kt +316 -0
  35. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectOverlapNormalizer.kt +400 -0
  36. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectSourceTrust.kt +249 -0
  37. package/android/src/main/java/com/carivaexercisesdk/domain/exercise/services/HealthConnectUnifiedRecordBuilder.kt +316 -0
  38. package/android/src/main/java/com/carivaexercisesdk/infrastructure/healthconnect/HealthConnectConnectionAdapter.kt +156 -0
  39. package/android/src/main/java/com/carivaexercisesdk/infrastructure/healthconnect/HealthConnectExerciseRecordAdapter.kt +464 -0
  40. package/android/src/main/java/com/carivaexercisesdk/infrastructure/persistence/InMemoryDatasourcePolicyRepository.kt +21 -0
  41. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/ConnectResultMapper.kt +23 -0
  42. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyJsonParser.kt +51 -0
  43. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyMapper.kt +46 -0
  44. package/android/src/main/java/com/carivaexercisesdk/infrastructure/reactnative/ExerciseDataMapper.kt +99 -0
  45. package/android/src/test/java/com/carivaexercisesdk/ArchitectureDependencyRuleTest.kt +60 -0
  46. package/android/src/test/java/com/carivaexercisesdk/HealthConnectModuleDatasourceParserTest.kt +69 -0
  47. package/android/src/test/java/com/carivaexercisesdk/HealthConnectModuleInternalsTest.kt +406 -0
  48. package/android/src/test/java/com/carivaexercisesdk/application/connection/handler/ConnectHandlerTest.kt +153 -0
  49. package/android/src/test/java/com/carivaexercisesdk/application/datasource/handler/DatasourcePolicyRoundTripTest.kt +63 -0
  50. package/android/src/test/java/com/carivaexercisesdk/application/datasource/handler/SetDatasourcePolicyHandlerTest.kt +42 -0
  51. package/android/src/test/java/com/carivaexercisesdk/domain/connection/service/ConnectionDecisionServiceTest.kt +68 -0
  52. package/android/src/test/java/com/carivaexercisesdk/infrastructure/reactnative/DatasourcePolicyMapperTest.kt +22 -0
  53. package/ios/CarivaExerciseSdk.h +5 -0
  54. package/ios/CarivaExerciseSdk.mm +7 -0
  55. package/lib/module/connect/index.js +7 -0
  56. package/lib/module/connect/index.js.map +1 -0
  57. package/lib/module/datasource/index.js +10 -0
  58. package/lib/module/datasource/index.js.map +1 -0
  59. package/lib/module/exercise/index.js +7 -0
  60. package/lib/module/exercise/index.js.map +1 -0
  61. package/lib/module/index.js +6 -0
  62. package/lib/module/index.js.map +1 -0
  63. package/lib/module/native/module.js +13 -0
  64. package/lib/module/native/module.js.map +1 -0
  65. package/lib/module/package.json +1 -0
  66. package/lib/typescript/package.json +1 -0
  67. package/lib/typescript/src/connect/index.d.ts +16 -0
  68. package/lib/typescript/src/connect/index.d.ts.map +1 -0
  69. package/lib/typescript/src/datasource/index.d.ts +12 -0
  70. package/lib/typescript/src/datasource/index.d.ts.map +1 -0
  71. package/lib/typescript/src/exercise/index.d.ts +64 -0
  72. package/lib/typescript/src/exercise/index.d.ts.map +1 -0
  73. package/lib/typescript/src/index.d.ts +4 -0
  74. package/lib/typescript/src/index.d.ts.map +1 -0
  75. package/lib/typescript/src/native/module.d.ts +14 -0
  76. package/lib/typescript/src/native/module.d.ts.map +1 -0
  77. package/package.json +127 -0
  78. package/src/connect/index.ts +34 -0
  79. package/src/datasource/index.ts +20 -0
  80. package/src/exercise/index.ts +75 -0
  81. package/src/index.tsx +22 -0
  82. package/src/native/module.ts +23 -0
@@ -0,0 +1,351 @@
1
+ package com.carivaexercisesdk.domain.exercise.services
2
+
3
+ internal object HealthConnectCaloriesFallbackMerger {
4
+ fun mergeCaloriesWithFallback(
5
+ primaryActiveCalories: HealthConnectModuleInternals.NormalizationResult,
6
+ totalCalories: HealthConnectModuleInternals.NormalizationResult,
7
+ basalCalories: HealthConnectModuleInternals.NormalizationResult,
8
+ stepsEvidenceSegments: List<HealthConnectModuleInternals.NormalizedSegment> = emptyList(),
9
+ activeTimeEvidenceSegments: List<HealthConnectModuleInternals.NormalizedSegment> =
10
+ emptyList(),
11
+ distanceEvidenceSegments: List<HealthConnectModuleInternals.NormalizedSegment> =
12
+ emptyList(),
13
+ basalSeedApplied: Boolean = false,
14
+ seededFromBeforeSince: Boolean = false,
15
+ basalSeedAgeHours: Double? = null
16
+ ): HealthConnectModuleInternals.NormalizationResult {
17
+ val directActiveCaloriesKcal = primaryActiveCalories.segments.sumOf { it.value }
18
+ val totalCaloriesKcal = totalCalories.segments.sumOf { it.value }
19
+ val basalCaloriesKcal = basalCalories.segments.sumOf { it.value }
20
+
21
+ val fallbackDerived =
22
+ deriveFallbackCaloriesSegments(
23
+ primaryActiveCalories = primaryActiveCalories.segments,
24
+ totalCalories = totalCalories.segments,
25
+ basalCalories = basalCalories.segments,
26
+ stepsEvidenceSegments = stepsEvidenceSegments,
27
+ activeTimeEvidenceSegments = activeTimeEvidenceSegments,
28
+ distanceEvidenceSegments = distanceEvidenceSegments
29
+ )
30
+ val fallbackFilled =
31
+ fillUncoveredIntervals(
32
+ primarySegments = primaryActiveCalories.segments,
33
+ fallbackSegments = fallbackDerived.segments
34
+ )
35
+ val warnings =
36
+ linkedSetOf<String>().apply {
37
+ addAll(primaryActiveCalories.warnings)
38
+ addAll(totalCalories.warnings)
39
+ addAll(basalCalories.warnings)
40
+ if (basalSeedApplied) {
41
+ add(HealthConnectInternalsConstants.WARNING_BMR_SEED_FROM_LATEST_BEFORE_SINCE_USED)
42
+ }
43
+ if (fallbackDerived.fallbackSuppressedSegments > 0) {
44
+ add(HealthConnectInternalsConstants.WARNING_BMR_MISSING_FOR_FALLBACK_WINDOW)
45
+ add(HealthConnectInternalsConstants.WARNING_FALLBACK_SUPPRESSED_DUE_TO_MISSING_BASAL)
46
+ }
47
+ if (fallbackDerived.idleGateSuppressedSegments > 0) {
48
+ add(HealthConnectInternalsConstants.WARNING_FALLBACK_SUPPRESSED_DUE_TO_IDLE_WINDOW)
49
+ }
50
+ if (fallbackFilled.fallbackUsedSegments > 0) {
51
+ add(HealthConnectInternalsConstants.WARNING_CALORIES_FALLBACK_USED)
52
+ if (primaryActiveCalories.segments.isEmpty()) {
53
+ add(HealthConnectInternalsConstants.WARNING_CALORIES_FALLBACK_ONLY_USED)
54
+ } else {
55
+ add(HealthConnectInternalsConstants.WARNING_CALORIES_FALLBACK_PARTIAL_USED)
56
+ }
57
+ }
58
+ }
59
+
60
+ val mergedActiveCaloriesKcal = fallbackFilled.segments.sumOf { it.value }
61
+ val fallbackContributionKcal = maxOf(mergedActiveCaloriesKcal - directActiveCaloriesKcal, 0.0)
62
+
63
+ return HealthConnectModuleInternals.NormalizationResult(
64
+ segments = fallbackFilled.segments,
65
+ stats = primaryActiveCalories.stats + totalCalories.stats + basalCalories.stats,
66
+ overlapStrategy = HealthConnectInternalsConstants.OVERLAP_STRATEGY_PROPORTIONAL,
67
+ warnings = warnings.toList(),
68
+ diagnostics =
69
+ HealthConnectModuleInternals.Diagnostics(
70
+ fallbackUsedSegments = fallbackFilled.fallbackUsedSegments,
71
+ fallbackSuppressedSegments = fallbackDerived.fallbackSuppressedSegments,
72
+ idleGateSuppressedSegments = fallbackDerived.idleGateSuppressedSegments,
73
+ basalSeedApplied = basalSeedApplied,
74
+ seededFromBeforeSince = seededFromBeforeSince,
75
+ basalSeedAgeHours = basalSeedAgeHours,
76
+ directActiveCaloriesKcal = directActiveCaloriesKcal,
77
+ totalCaloriesKcal = totalCaloriesKcal,
78
+ basalCaloriesKcal = basalCaloriesKcal,
79
+ mergedActiveCaloriesKcal = mergedActiveCaloriesKcal,
80
+ fallbackContributionKcal = fallbackContributionKcal
81
+ )
82
+ )
83
+ }
84
+
85
+ private data class FallbackDeriveResult(
86
+ val segments: List<HealthConnectModuleInternals.NormalizedSegment>,
87
+ val fallbackSuppressedSegments: Int,
88
+ val idleGateSuppressedSegments: Int
89
+ )
90
+
91
+ private fun deriveFallbackCaloriesSegments(
92
+ primaryActiveCalories: List<HealthConnectModuleInternals.NormalizedSegment>,
93
+ totalCalories: List<HealthConnectModuleInternals.NormalizedSegment>,
94
+ basalCalories: List<HealthConnectModuleInternals.NormalizedSegment>,
95
+ stepsEvidenceSegments: List<HealthConnectModuleInternals.NormalizedSegment>,
96
+ activeTimeEvidenceSegments: List<HealthConnectModuleInternals.NormalizedSegment>,
97
+ distanceEvidenceSegments: List<HealthConnectModuleInternals.NormalizedSegment>
98
+ ): FallbackDeriveResult {
99
+ if (totalCalories.isEmpty()) {
100
+ return FallbackDeriveResult(
101
+ segments = emptyList(),
102
+ fallbackSuppressedSegments = 0,
103
+ idleGateSuppressedSegments = 0
104
+ )
105
+ }
106
+
107
+ val breakpoints =
108
+ listOf(
109
+ primaryActiveCalories,
110
+ totalCalories,
111
+ basalCalories,
112
+ stepsEvidenceSegments,
113
+ activeTimeEvidenceSegments,
114
+ distanceEvidenceSegments
115
+ )
116
+ .flatMap { segments -> segments.flatMap { listOf(it.startMs, it.endMs) } }
117
+ .toSortedSet()
118
+ .toList()
119
+
120
+ if (breakpoints.size < 2) {
121
+ return FallbackDeriveResult(
122
+ segments = emptyList(),
123
+ fallbackSuppressedSegments = 0,
124
+ idleGateSuppressedSegments = 0
125
+ )
126
+ }
127
+
128
+ val derived = mutableListOf<HealthConnectModuleInternals.NormalizedSegment>()
129
+ var fallbackSuppressedSegments = 0
130
+ var idleGateSuppressedSegments = 0
131
+ for (index in 0 until breakpoints.lastIndex) {
132
+ val startMs = breakpoints[index]
133
+ val endMs = breakpoints[index + 1]
134
+ if (endMs <= startMs) {
135
+ continue
136
+ }
137
+
138
+ val totalValue = projectSegmentValue(totalCalories, startMs, endMs)
139
+ if (totalValue <= 0.0) {
140
+ continue
141
+ }
142
+ if (!hasCoverage(basalCalories, startMs, endMs)) {
143
+ fallbackSuppressedSegments += 1
144
+ continue
145
+ }
146
+ val basalValue = projectSegmentValue(basalCalories, startMs, endMs)
147
+ val activeValue = maxOf(totalValue - basalValue, 0.0)
148
+ if (activeValue <= 0.0) {
149
+ continue
150
+ }
151
+ val projectedDirectActive = projectSegmentValue(primaryActiveCalories, startMs, endMs)
152
+ val projectedSteps = projectSegmentValue(stepsEvidenceSegments, startMs, endMs)
153
+ val projectedDistance = projectSegmentValue(distanceEvidenceSegments, startMs, endMs)
154
+ val projectedActiveTime = projectSegmentValue(activeTimeEvidenceSegments, startMs, endMs)
155
+ if (projectedDirectActive == 0.0 &&
156
+ projectedSteps == 0.0 &&
157
+ projectedDistance == 0.0 &&
158
+ projectedActiveTime == 0.0
159
+ ) {
160
+ idleGateSuppressedSegments += 1
161
+ continue
162
+ }
163
+
164
+ derived.add(
165
+ HealthConnectModuleInternals.NormalizedSegment(
166
+ startMs = startMs,
167
+ endMs = endMs,
168
+ value = activeValue,
169
+ sourceType = HealthConnectInternalsConstants.SOURCE_FALLBACK,
170
+ packageName = HealthConnectInternalsConstants.PACKAGE_FALLBACK_TOTAL_MINUS_BASAL,
171
+ deviceModel = ""
172
+ )
173
+ )
174
+ }
175
+
176
+ return FallbackDeriveResult(
177
+ segments = derived,
178
+ fallbackSuppressedSegments = fallbackSuppressedSegments,
179
+ idleGateSuppressedSegments = idleGateSuppressedSegments
180
+ )
181
+ }
182
+
183
+ private data class FillFallbackResult(
184
+ val segments: List<HealthConnectModuleInternals.NormalizedSegment>,
185
+ val fallbackUsedSegments: Int
186
+ )
187
+
188
+ private data class ProjectedSegmentRepresentative(
189
+ val sourceType: String,
190
+ val packageName: String,
191
+ val deviceModel: String
192
+ )
193
+
194
+ private data class WeightedSegmentProjection(
195
+ val segment: HealthConnectModuleInternals.NormalizedSegment,
196
+ val projectedValue: Double
197
+ )
198
+
199
+ private fun fillUncoveredIntervals(
200
+ primarySegments: List<HealthConnectModuleInternals.NormalizedSegment>,
201
+ fallbackSegments: List<HealthConnectModuleInternals.NormalizedSegment>
202
+ ): FillFallbackResult {
203
+ if (primarySegments.isEmpty()) {
204
+ return FillFallbackResult(
205
+ segments = fallbackSegments,
206
+ fallbackUsedSegments = fallbackSegments.size
207
+ )
208
+ }
209
+ if (fallbackSegments.isEmpty()) {
210
+ return FillFallbackResult(segments = primarySegments, fallbackUsedSegments = 0)
211
+ }
212
+
213
+ val breakpoints =
214
+ listOf(primarySegments, fallbackSegments)
215
+ .flatMap { segments -> segments.flatMap { listOf(it.startMs, it.endMs) } }
216
+ .toSortedSet()
217
+ .toList()
218
+ if (breakpoints.size < 2) {
219
+ return FillFallbackResult(segments = primarySegments, fallbackUsedSegments = 0)
220
+ }
221
+
222
+ val merged = mutableListOf<HealthConnectModuleInternals.NormalizedSegment>()
223
+ var fallbackUsedSegments = 0
224
+ for (index in 0 until breakpoints.lastIndex) {
225
+ val startMs = breakpoints[index]
226
+ val endMs = breakpoints[index + 1]
227
+ if (endMs <= startMs) {
228
+ continue
229
+ }
230
+
231
+ val primaryValue = projectSegmentValue(primarySegments, startMs, endMs)
232
+ val fallbackValue = projectSegmentValue(fallbackSegments, startMs, endMs)
233
+ if (primaryValue <= 0.0 && fallbackValue <= 0.0) {
234
+ continue
235
+ }
236
+
237
+ if (primaryValue <= 0.0 && fallbackValue > 0.0) {
238
+ fallbackUsedSegments += 1
239
+ merged.add(
240
+ HealthConnectModuleInternals.NormalizedSegment(
241
+ startMs = startMs,
242
+ endMs = endMs,
243
+ value = fallbackValue,
244
+ sourceType = HealthConnectInternalsConstants.SOURCE_FALLBACK,
245
+ packageName = HealthConnectInternalsConstants.PACKAGE_FALLBACK_TOTAL_MINUS_BASAL,
246
+ deviceModel = ""
247
+ )
248
+ )
249
+ continue
250
+ }
251
+
252
+ if (primaryValue > 0.0) {
253
+ val representative = resolveProjectedSegmentRepresentative(primarySegments, startMs, endMs)
254
+ merged.add(
255
+ HealthConnectModuleInternals.NormalizedSegment(
256
+ startMs = startMs,
257
+ endMs = endMs,
258
+ value = primaryValue,
259
+ sourceType =
260
+ representative?.sourceType
261
+ ?: HealthConnectInternalsConstants.SOURCE_UNKNOWN,
262
+ packageName = representative?.packageName.orEmpty(),
263
+ deviceModel = representative?.deviceModel.orEmpty()
264
+ )
265
+ )
266
+ }
267
+ }
268
+
269
+ return FillFallbackResult(segments = merged, fallbackUsedSegments = fallbackUsedSegments)
270
+ }
271
+
272
+ private fun resolveProjectedSegmentRepresentative(
273
+ segments: List<HealthConnectModuleInternals.NormalizedSegment>,
274
+ startMs: Long,
275
+ endMs: Long
276
+ ): ProjectedSegmentRepresentative? {
277
+ return segments
278
+ .asSequence()
279
+ .mapNotNull { segment ->
280
+ val overlapStart = maxOf(startMs, segment.startMs)
281
+ val overlapEnd = minOf(endMs, segment.endMs)
282
+ if (overlapEnd <= overlapStart) {
283
+ return@mapNotNull null
284
+ }
285
+ val segmentDuration = (segment.endMs - segment.startMs).toDouble()
286
+ if (segmentDuration <= 0.0) {
287
+ return@mapNotNull null
288
+ }
289
+ val overlapDuration = (overlapEnd - overlapStart).toDouble()
290
+ val projectedValue = segment.value * (overlapDuration / segmentDuration)
291
+ if (projectedValue <= 0.0) {
292
+ return@mapNotNull null
293
+ }
294
+ WeightedSegmentProjection(segment, projectedValue)
295
+ }
296
+ .sortedWith(
297
+ compareByDescending<WeightedSegmentProjection> { it.projectedValue }
298
+ .thenByDescending {
299
+ HealthConnectSourceTrust.resolveSourcePriority(it.segment.sourceType)
300
+ }
301
+ .thenBy { it.segment.packageName }
302
+ .thenBy { it.segment.startMs }
303
+ .thenBy { it.segment.endMs }
304
+ )
305
+ .firstOrNull()
306
+ ?.let { projection ->
307
+ ProjectedSegmentRepresentative(
308
+ sourceType = projection.segment.sourceType,
309
+ packageName = projection.segment.packageName,
310
+ deviceModel = projection.segment.deviceModel
311
+ )
312
+ }
313
+ }
314
+
315
+ private fun projectSegmentValue(
316
+ segments: List<HealthConnectModuleInternals.NormalizedSegment>,
317
+ startMs: Long,
318
+ endMs: Long
319
+ ): Double {
320
+ if (segments.isEmpty() || endMs <= startMs) {
321
+ return 0.0
322
+ }
323
+
324
+ var total = 0.0
325
+ segments.forEach { segment ->
326
+ val overlapStart = maxOf(startMs, segment.startMs)
327
+ val overlapEnd = minOf(endMs, segment.endMs)
328
+ if (overlapEnd <= overlapStart) {
329
+ return@forEach
330
+ }
331
+
332
+ val segmentDuration = (segment.endMs - segment.startMs).toDouble()
333
+ if (segmentDuration <= 0.0) {
334
+ return@forEach
335
+ }
336
+
337
+ val overlapDuration = (overlapEnd - overlapStart).toDouble()
338
+ total += segment.value * (overlapDuration / segmentDuration)
339
+ }
340
+
341
+ return total
342
+ }
343
+
344
+ private fun hasCoverage(
345
+ segments: List<HealthConnectModuleInternals.NormalizedSegment>,
346
+ startMs: Long,
347
+ endMs: Long
348
+ ): Boolean {
349
+ return segments.any { segment -> minOf(endMs, segment.endMs) > maxOf(startMs, segment.startMs) }
350
+ }
351
+ }
@@ -0,0 +1,55 @@
1
+ package com.carivaexercisesdk.domain.exercise.services
2
+
3
+ internal object HealthConnectInternalsConstants {
4
+ const val SUPPORTED_HOURLY = "hourly"
5
+ const val SUPPORTED_DAILY = "daily"
6
+
7
+ const val SCOPE_STEPS = "steps"
8
+ const val SCOPE_ACTIVE_TIMES = "activetimes"
9
+ const val SCOPE_CALORIES = "calories"
10
+ const val SCOPE_DISTANCES = "distances"
11
+
12
+ const val SOURCE_MANUAL_INPUT = "manual_input"
13
+ const val SOURCE_DEVICE = "device"
14
+ const val SOURCE_APP = "app"
15
+ const val SOURCE_UNKNOWN = "unknown"
16
+ const val SOURCE_FALLBACK = "fallback"
17
+
18
+ const val PACKAGE_FALLBACK_TOTAL_MINUS_BASAL = "fallback_total_minus_basal"
19
+
20
+ const val OVERLAP_STRATEGY_SOURCE_PRIORITY = "source_priority"
21
+ const val OVERLAP_STRATEGY_PROPORTIONAL = "proportional"
22
+
23
+ const val WARNING_CALORIES_FALLBACK_USED = "calories_fallback_total_minus_basal_used"
24
+ const val WARNING_CALORIES_FALLBACK_ONLY_USED = "calories_fallback_only_used"
25
+ const val WARNING_CALORIES_FALLBACK_PARTIAL_USED = "calories_fallback_partial_used"
26
+ const val WARNING_BMR_SEED_FROM_LATEST_BEFORE_SINCE_USED =
27
+ "bmr_seed_from_latest_before_since_used"
28
+ const val WARNING_BMR_MISSING_FOR_FALLBACK_WINDOW = "bmr_missing_for_fallback_window"
29
+ const val WARNING_FALLBACK_SUPPRESSED_DUE_TO_MISSING_BASAL =
30
+ "fallback_suppressed_due_to_missing_basal"
31
+ const val WARNING_FALLBACK_SUPPRESSED_DUE_TO_IDLE_WINDOW =
32
+ "fallback_suppressed_due_to_idle_window"
33
+ const val WARNING_UNKNOWN_SOURCE_TYPE = "unknown_source_type_detected"
34
+
35
+ const val TRUST_REASON_ALLOWED = "allowed"
36
+ const val TRUST_REASON_MANUAL_WITH_DEVICE_LOW_CONFIDENCE =
37
+ "manual_with_device_low_confidence"
38
+ const val TRUST_REASON_UNKNOWN_WITH_DEVICE_LOW_CONFIDENCE =
39
+ "unknown_with_device_low_confidence"
40
+ const val TRUST_REASON_MANUAL_INPUT = "manual_input"
41
+ const val TRUST_REASON_UNKNOWN_WITHOUT_DEVICE = "unknown_without_device"
42
+ const val TRUST_REASON_MALFORMED_METADATA = "malformed_metadata"
43
+
44
+ const val TRUST_LEVEL_TRUSTED = "trusted"
45
+ const val TRUST_LEVEL_LOW_CONFIDENCE = "low_confidence"
46
+ const val TRUST_LEVEL_REJECTED = "rejected"
47
+
48
+ val SOURCE_PRIORITY =
49
+ mapOf(
50
+ SOURCE_DEVICE to 4,
51
+ SOURCE_APP to 3,
52
+ SOURCE_UNKNOWN to 2,
53
+ SOURCE_MANUAL_INPUT to 1
54
+ )
55
+ }