diff --git a/app/src/main/java/com/todoroo/astrid/alarms/AlarmCalculator.kt b/app/src/main/java/com/todoroo/astrid/alarms/AlarmCalculator.kt index 57c0eb8f0..4ca140784 100644 --- a/app/src/main/java/com/todoroo/astrid/alarms/AlarmCalculator.kt +++ b/app/src/main/java/com/todoroo/astrid/alarms/AlarmCalculator.kt @@ -75,10 +75,16 @@ class AlarmCalculator( */ private fun calculateNextRandomReminder(random: Random, task: Task, reminderPeriod: Long) = if (reminderPeriod > 0) { + val baseline = when { + task.reminderLast > 0 -> task.reminderLast + task.isRecurring -> task.modificationDate + else -> task.creationDate + } + + val multiplier = 0.85f + 0.3f * random.nextFloat(task.id + baseline) + maxOf( - task.reminderLast - .coerceAtLeast(task.creationDate) - .plus((reminderPeriod * (0.85f + 0.3f * random.nextFloat())).toLong()), + baseline.plus((reminderPeriod * multiplier).toLong()), task.hideUntil ) } else { diff --git a/app/src/main/java/org/tasks/reminders/Random.java b/app/src/main/java/org/tasks/reminders/Random.java deleted file mode 100644 index 5dc51a282..000000000 --- a/app/src/main/java/org/tasks/reminders/Random.java +++ /dev/null @@ -1,10 +0,0 @@ -package org.tasks.reminders; - -public class Random { - - private static final java.util.Random random = new java.util.Random(); - - public float nextFloat() { - return random.nextFloat(); - } -} diff --git a/app/src/main/java/org/tasks/reminders/Random.kt b/app/src/main/java/org/tasks/reminders/Random.kt new file mode 100644 index 000000000..7885026d0 --- /dev/null +++ b/app/src/main/java/org/tasks/reminders/Random.kt @@ -0,0 +1,14 @@ +package org.tasks.reminders + +import java.util.Random + +open class Random { + open fun nextFloat(seed: Long): Float { + random.setSeed(seed) + return random.nextFloat() + } + + companion object { + private val random = Random() + } +} diff --git a/app/src/test/java/com/todoroo/astrid/alarms/AlarmCalculatorTest.kt b/app/src/test/java/com/todoroo/astrid/alarms/AlarmCalculatorTest.kt index 12c7bba54..84199dc6c 100644 --- a/app/src/test/java/com/todoroo/astrid/alarms/AlarmCalculatorTest.kt +++ b/app/src/test/java/com/todoroo/astrid/alarms/AlarmCalculatorTest.kt @@ -295,7 +295,7 @@ class AlarmCalculatorTest { @Test fun scheduleOverdueRandomReminder() { - random.seed = 0.3865f + random.stub = 0.3865f freezeAt(now) { val alarm = alarmCalculator.toAlarmEntry( newTask( @@ -316,7 +316,7 @@ class AlarmCalculatorTest { @Test fun scheduleOverdueRandomReminderForHiddenTask() { - random.seed = 0.3865f + random.stub = 0.3865f freezeAt(now) { val task = newTask( with(REMINDER_LAST, now.minusDays(14)), @@ -335,7 +335,7 @@ class AlarmCalculatorTest { @Test fun scheduleInitialRandomReminder() { - random.seed = 0.3865f + random.stub = 0.3865f freezeAt(now) { val alarm = alarmCalculator.toAlarmEntry( @@ -358,7 +358,7 @@ class AlarmCalculatorTest { @Test fun scheduleNextRandomReminder() { - random.seed = 0.3865f + random.stub = 0.3865f freezeAt(now) { val alarm = alarmCalculator.toAlarmEntry( @@ -379,9 +379,28 @@ class AlarmCalculatorTest { } } + @Test + fun randomReminderIsDeterministic() { + val calculator = AlarmCalculator( + isDefaultDueTimeEnabled = true, + random = Random(), + defaultDueTime = TimeUnit.HOURS.toMillis(13).toInt(), + ) + + freezeAt(now) { + val task = newTask(with(CREATION_TIME, now.minusDays(1))) + val alarm = Alarm(time = ONE_WEEK, type = TYPE_RANDOM) + + val first = calculator.toAlarmEntry(task, alarm) + val second = calculator.toAlarmEntry(task, alarm) + + assertEquals(first, second) + } + } + internal class RandomStub : Random() { - var seed = 1.0f + var stub = 1.0f - override fun nextFloat() = seed + override fun nextFloat(seed: Long) = this.stub } } \ No newline at end of file