Skip to content

Instantly share code, notes, and snippets.

@victory316
Created December 8, 2023 00:26
Show Gist options
  • Save victory316/0d349d278ca0c0bd9f39d42b31d03b90 to your computer and use it in GitHub Desktop.
Save victory316/0d349d278ca0c0bd9f39d42b31d03b90 to your computer and use it in GitHub Desktop.
Conditional event checker
private const val KEY_LAST_ACCESS = "KEY_LAST_ACCESS"
private const val KEY_SENT_EVENT = "KEY_SENT_EVENT"
private const val KEY_RETENTION_DAY_COUNT = "KEY_RETENTION_DAY_COUNT"
class SingularConditionEventChecker @Inject constructor(
private val logger: AnalyticsLogger,
private val preferenceRepository: PreferencesRepository,
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher
) {
private var lastAccessDate: LocalDate? = null
private var retentionDayCount: Int? = null
private var sentEvents: Set<String> = setOf()
private var dataLoaded = false
private var actionQueued = false
private val targetEvents = listOf(
DayTwoRetentionEvent(
condition = { retentionDayCount == 2 },
eventToSend = Event.DayTwoRetention
),
DayFiveRetentionEvent(
condition = { retentionDayCount == 5 },
eventToSend = Event.DayFiveRetention
)
)
init {
CoroutineScope(ioDispatcher).launch {
combine(
preferenceRepository.getInteger(KEY_RETENTION_DAY_COUNT),
preferenceRepository.getLong(KEY_LAST_ACCESS),
preferenceRepository.getStringSet(KEY_SENT_EVENT)
) { dayCount, lastAccess, sentEvent ->
retentionDayCount = dayCount
lastAccessDate = lastAccess?.let { LocalDate.ofEpochDay(it) }
if (sentEvent != null) {
sentEvents = sentEvent
}
}.collect {
dataLoaded = true
if (actionQueued) {
updateConditionData()
checkEventsCondition()
actionQueued = false
}
}
}
}
fun doOnForeground() {
if (dataLoaded) {
updateConditionData()
checkEventsCondition()
} else {
actionQueued = true
}
}
private fun checkEventsCondition() {
targetEvents.forEach { event ->
if (event.isSatisfied() && !isEventLogged(event.getEventHash())) {
logger.logEvent(event.eventToSend)
saveSentEvent(event.getEventHash())
}
}
}
private fun updateConditionData() {
CoroutineScope(ioDispatcher).launch {
try {
val betweenDaysInLastAccess = ChronoUnit.DAYS.between(
lastAccessDate,
LocalDate.now()
)
if (betweenDaysInLastAccess == 1L) {
updatePreferences((retentionDayCount ?: 0).plus(1))
} else if (betweenDaysInLastAccess >= 2L) {
updatePreferences(0)
}
} catch (ignored: NullPointerException) {
updatePreferences(0)
}
}
}
private suspend fun updatePreferences(retentionDayCount: Int) {
preferenceRepository.saveLong(
key = KEY_LAST_ACCESS,
data = LocalDate.now().toEpochDay()
)
preferenceRepository.saveInteger(
key = KEY_RETENTION_DAY_COUNT,
data = retentionDayCount
)
}
private fun isEventLogged(eventHash: String) = sentEvents.contains(eventHash)
private fun saveSentEvent(eventHash: String) {
CoroutineScope(ioDispatcher).launch {
preferenceRepository.saveStringSet(
key = KEY_SENT_EVENT,
data = sentEvents.toMutableSet().apply {
add(eventHash)
}.toSet()
)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment