<commit_before>package com.pagecloud.slack.bot

import com.pagecloud.slack.logger
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service
import java.time.Duration
import java.time.LocalTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.concurrent.atomic.AtomicReference

/**
 * @author <NAME>
 */
@Service
class MovementSchedule {
    // Because... concurrency!
    private val nextSession: AtomicReference<LocalTime> = AtomicReference(LocalTime.of(11, 30))
    private val reminder: AtomicReference<Reminder> = AtomicReference(Reminder(LocalTime.of(11, 15), LocalTime.of(11, 30)))

    @Scheduled(cron = "0 1 1 * * MON-FRI", zone = "America/Toronto")
    fun resetReminders() {
        val newReminder = reminder.get().copy(firedToday = false)
        reminder.set(newReminder)
        log.info("Resetting reminder state; now $newReminder.")
    }

    fun scheduleNext(nextTime: LocalTime) {
        nextSession.set(nextTime)
        reminder.set(Reminder(nextTime.minus(SECOND_REMINDER), nextTime))
    }

    fun shouldSendReminders(): Boolean {
        val next = nextSession.get()
        val now = LocalTime.now(ZoneId.of("America/Toronto"))

        // We'll just have to wait until next time I guess...
        if (now.isAfter(next)) {
            return false
        }
        val reminder = this.reminder.get()
        if (now.hour == reminder.time.hour && now.minute == reminder.time.minute && !reminder.firedToday) {
            return true
        }
        return false
    }

    fun sendReminder(reminderFunction: (String) -> Unit) {
        val reminder = this.reminder.get()
        if (!reminder.firedToday) reminder.fire(reminderFunction)
    }

    companion object {
        val WINDOW: Duration = Duration.ofSeconds(60L)
        val FIRST_REMINDER = Duration.ofMinutes(60L)
        val SECOND_REMINDER = Duration.ofMinutes(15L)
        val LAST_REMINDER = Duration.ofMinutes(1L)

        val log = logger()
    }
}

data class Reminder(val time: LocalTime,
                    val moveTime: LocalTime,
                    var firedToday: Boolean = false) {
    fun fire(reminderFunction: (String) -> Unit) {
        val prettyTime = moveTime.format(PRETTY_FORMAT)
        val message = "Hey Healthy and Fit team! Just a reminder that the next stretch will be at $prettyTime!"
        reminderFunction(message)
        firedToday = true
    }
}


fun LocalTime.isAfter(otherTime: LocalTime, threshold: Duration): Boolean =
    this.isAfter(otherTime) && Duration.between(this, otherTime) <= threshold

val PRETTY_FORMAT: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm a")<commit_msg>Add multiple reminders later<commit_after>package com.pagecloud.slack.bot

import com.pagecloud.slack.logger
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service
import java.time.Duration
import java.time.LocalTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.util.concurrent.atomic.AtomicReference

/**
 * @author <NAME>
 */
@Service
class MovementSchedule {
    // Because... concurrency!
    private val nextSession: AtomicReference<LocalTime> = AtomicReference(LocalTime.of(11, 30))
    private val reminder: AtomicReference<Reminder> = AtomicReference(Reminder(LocalTime.of(11, 15), LocalTime.of(11, 30)))

    @Scheduled(cron = "0 1 1 * * MON-FRI", zone = "America/Toronto")
    fun resetReminders() {
        val newReminder = reminder.get().copy(firedToday = false)
        reminder.set(newReminder)
        log.info("Resetting reminder state; now $newReminder.")
    }

    fun scheduleNext(nextTime: LocalTime) {
        nextSession.set(nextTime)
        reminder.set(Reminder(nextTime.minus(SECOND_REMINDER), nextTime))
    }

    fun shouldSendReminders(): Boolean {
        val next = nextSession.get()
        val now = LocalTime.now(ZoneId.of("America/Toronto"))

        // We'll just have to wait until next time I guess...
        if (now.isAfter(next)) {
            return false
        }
        val reminder = this.reminder.get()
        if (now.hour == reminder.time.hour && now.minute == reminder.time.minute && !reminder.firedToday) {
            return true
        }
        return false
    }

    fun sendReminder(reminderFunction: (String) -> Unit) {
        val reminder = this.reminder.get()
        if (!reminder.firedToday) reminder.fire(reminderFunction)
    }

    // TODO add all reminders
    companion object {
        val FIRST_REMINDER = Duration.ofMinutes(60L)
        val SECOND_REMINDER = Duration.ofMinutes(15L)
        val LAST_REMINDER = Duration.ofMinutes(1L)

        val log = logger()
    }
}

data class Reminder(val time: LocalTime,
                    val moveTime: LocalTime,
                    var firedToday: Boolean = false) {
    fun fire(reminderFunction: (String) -> Unit) {
        val prettyTime = moveTime.format(PRETTY_FORMAT)
        val message = "Hey Healthy and Fit team! Just a reminder that the next stretch will be at $prettyTime!"
        reminderFunction(message)
        firedToday = true
    }
}

val PRETTY_FORMAT: DateTimeFormatter = DateTimeFormatter.ofPattern("hh:mm a")
{'fraction_non_alphanumeric': 0.10538373424971363, 'fraction_numerical': 0.008018327605956471, 'mean_word_length': 3.0022918258212377, 'pattern_counts': {'":': 0, '<': 10, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4738282', 'n_tokens_mistral': 1607, 'n_tokens_neox': 1534, 'n_words': 358}