Coverage Summary for Class: HapticRequestValidator (cloud.mindbox.mobile_sdk.inapp.data.validators)
| Class |
Method, %
|
Branch, %
|
Line, %
|
Instruction, %
|
| HapticRequestValidator |
100%
(7/7)
|
100%
(42/42)
|
100%
(31/31)
|
100%
(214/214)
|
| HapticRequestValidator$Companion |
|
| HapticRequestValidator$isValidPattern$$inlined$sortedBy$1 |
0%
(0/1)
|
|
| Total |
87.5%
(7/8)
|
100%
(42/42)
|
100%
(31/31)
|
100%
(214/214)
|
package cloud.mindbox.mobile_sdk.inapp.data.validators
import cloud.mindbox.mobile_sdk.inapp.presentation.view.HapticConstants
import cloud.mindbox.mobile_sdk.inapp.presentation.view.HapticPatternEvent
import cloud.mindbox.mobile_sdk.inapp.presentation.view.HapticRequest
import cloud.mindbox.mobile_sdk.logger.mindboxLogW
internal class HapticRequestValidator : Validator<HapticRequest> {
override fun isValid(item: HapticRequest): Boolean = when (item) {
is HapticRequest.Selection -> true
is HapticRequest.Impact -> true
is HapticRequest.Pattern -> isValidPattern(item.events)
}
private fun isValidPattern(events: List<HapticPatternEvent>): Boolean {
if (events.isEmpty()) return logAndFail("pattern is empty")
if (events.size > MAX_EVENTS) return logAndFail("too many events: ${events.size}")
if (!events.all { isValidEvent(it) }) return false
return isValidPatternOrder(events.sortedBy { it.time })
}
private fun isValidEvent(event: HapticPatternEvent): Boolean {
if (event.time !in 0L..MAX_TOTAL_DURATION_MS) {
return logAndFail("event time out of range: ${event.time}")
}
if (event.duration !in 0L..MAX_SINGLE_EVENT_DURATION_MS) {
return logAndFail("event duration out of range: ${event.duration}")
}
if (event.intensity !in 0f..1f) {
return logAndFail("event intensity out of range: ${event.intensity}")
}
if (event.sharpness !in 0f..1f) {
return logAndFail("event sharpness out of range: ${event.sharpness}")
}
val effectiveDuration: Long = effectiveDurationOf(event)
if (event.time + effectiveDuration > MAX_TOTAL_DURATION_MS) {
return logAndFail("event time + effectiveDuration exceeds max: ${event.time + effectiveDuration}")
}
return true
}
private fun isValidPatternOrder(sortedEvents: List<HapticPatternEvent>): Boolean {
for (i in 1 until sortedEvents.size) {
val previous: HapticPatternEvent = sortedEvents[i - 1]
val next: HapticPatternEvent = sortedEvents[i]
val previousEnd: Long = previous.time + effectiveDurationOf(previous)
if (next.time < previousEnd) {
return logAndFail("event at time=${next.time} overlaps previous event ending at $previousEnd")
}
}
return true
}
private fun effectiveDurationOf(event: HapticPatternEvent): Long =
if (event.duration > 0) event.duration else HapticConstants.TRANSIENT_DURATION_MS
private fun logAndFail(reason: String): Boolean {
mindboxLogW("[Haptic] invalid pattern: $reason")
return false
}
private companion object {
const val MAX_EVENTS = 128
const val MAX_TOTAL_DURATION_MS = 30_000L
const val MAX_SINGLE_EVENT_DURATION_MS = 5_000L
}
}