Files
DexcomBluetoothUploader/lib/nightscout/com/eveningoutpost/dexdrip/Models/Reminder.java
2020-07-18 21:44:27 -04:00

400 lines
14 KiB
Java

package com.eveningoutpost.dexdrip.Models;
import android.content.Context;
import android.provider.BaseColumns;
import com.activeandroid.Model;
import com.activeandroid.annotation.Column;
import com.activeandroid.annotation.Table;
import com.activeandroid.query.Select;
import com.activeandroid.util.SQLiteUtils;
import com.eveningoutpost.dexdrip.Home;
import com.eveningoutpost.dexdrip.Reminders;
import com.eveningoutpost.dexdrip.UtilityModels.Constants;
import com.eveningoutpost.dexdrip.UtilityModels.Pref;
import com.eveningoutpost.dexdrip.utils.HomeWifi;
import com.google.gson.annotations.Expose;
import java.util.Calendar;
import java.util.List;
/**
* Created by jamorham on 01/02/2017.
*/
@Table(name = "Reminder", id = BaseColumns._ID)
public class Reminder extends Model {
private static final String TAG = "Reminder";
private static boolean patched = false;
public static final String REMINDERS_ALL_DISABLED = "reminders-all-disabled";
public static final String REMINDERS_NIGHT_DISABLED = "reminders-at-night-disabled";
public static final String REMINDERS_RESTART_TOMORROW = "reminders-restart-tomorrow";
public static final String REMINDERS_ADVANCED_MODE = "reminders-advanced-mode";
private static final String[] schema = {
"CREATE TABLE Reminder (_id INTEGER PRIMARY KEY AUTOINCREMENT)",
"ALTER TABLE Reminder ADD COLUMN next_due INTEGER",
"ALTER TABLE Reminder ADD COLUMN period INTEGER",
"ALTER TABLE Reminder ADD COLUMN snoozed_till INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN last_snoozed_for INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN last_fired INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN fired_times INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN alerted_times INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN title TEXT",
"ALTER TABLE Reminder ADD COLUMN alt_title TEXT",
"ALTER TABLE Reminder ADD COLUMN sound_uri TEXT",
"ALTER TABLE Reminder ADD COLUMN ideal_time TEXT",
"ALTER TABLE Reminder ADD COLUMN priority INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN enabled INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN weekdays INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN weekends INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN repeating INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN alternating INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN alternate INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN chime INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN homeonly INTEGER DEFAULT 0",
"ALTER TABLE Reminder ADD COLUMN speak INTEGER DEFAULT 0",
"CREATE INDEX index_Reminder_next_due on Reminder(next_due)",
"CREATE INDEX index_Reminder_enabled on Reminder(enabled)",
"CREATE INDEX index_Reminder_weekdays on Reminder(weekdays)",
"CREATE INDEX index_Reminder_homeonly on Reminder(homeonly)",
"CREATE INDEX index_Reminder_weekends on Reminder(weekends)",
"CREATE INDEX index_Reminder_priority on Reminder(priority)",
"CREATE INDEX index_Reminder_timestamp on Reminder(timestamp)",
"CREATE INDEX index_Reminder_snoozed_till on Reminder(snoozed_till)"
};
@Expose
@Column(name = "title")
public String title;
@Expose
@Column(name = "alt_title")
public String alternate_title;
@Expose
@Column(name = "next_due", index = true)
public long next_due;
@Expose
@Column(name = "period")
public long period;
@Expose
@Column(name = "sound_uri")
public String sound_uri;
@Expose
@Column(name = "enabled", index = true)
public boolean enabled;
@Expose
@Column(name = "weekdays", index = true)
public boolean weekdays;
@Expose
@Column(name = "weekends", index = true)
public boolean weekends;
@Expose
@Column(name = "homeonly", index = true)
public boolean homeonly;
@Expose
@Column(name = "speak")
public boolean speak;
@Expose
@Column(name = "repeating")
public boolean repeating;
@Expose
@Column(name = "chime")
public boolean chime_only;
@Expose
@Column(name = "alternating")
public boolean alternating;
@Expose
@Column(name = "alternate")
public boolean alternate;
@Expose
@Column(name = "snoozed_till", index = true)
public long snoozed_till;
@Expose
@Column(name = "last_fired", index = true)
public long last_fired;
@Expose
@Column(name = "last_snoozed_for")
public long last_snoozed_for;
@Expose
@Column(name = "fired_times")
public long fired_times;
@Expose
@Column(name = "alerted_times")
public long alerted_times;
@Expose
@Column(name = "priority")
public long priority;
@Expose
@Column(name = "ideal_time")
public String ideal_time;
public boolean isAlternate() {
if (alternating && (alternate_title != null)) {
return alternate;
} else {
return false;
}
}
public String getTitle() {
return isAlternate() ? alternate_title : title;
}
public String getAlternateTitle() {
return alternate_title != null ? alternate_title : title + " alternate";
}
public void updateTitle(String new_title) {
if (isAlternate()) {
alternate_title = new_title;
} else {
title = new_title;
}
save();
}
public boolean isHoursPeriod() {
return (period >= Constants.HOUR_IN_MS) && (period < Constants.DAY_IN_MS);
}
public boolean isDaysPeriod() {
return (period >= Constants.DAY_IN_MS) && (period < (Constants.WEEK_IN_MS * 2));
}
public boolean isWeeksPeriod() {
return (period >= (2 * Constants.WEEK_IN_MS));
}
public long periodInUnits() {
if (isDaysPeriod()) return period / Constants.DAY_IN_MS;
if (isHoursPeriod()) return period / Constants.HOUR_IN_MS;
if (isWeeksPeriod()) return period / Constants.WEEK_IN_MS;
return -1; // ERROR
}
public boolean isDue() {
if ((enabled) && (next_due <= JoH.tsl())) {
return true;
} else {
return false;
}
}
public boolean isSnoozed() {
if (snoozed_till > JoH.tsl()) {
return true;
} else {
return false;
}
}
public boolean shouldNotify() {
return enabled && isDue() && !isSnoozed();
}
public synchronized void notified() {
if (last_fired < next_due) fired_times++;
alerted_times++;
last_fired = JoH.tsl();
if (chime_only) {
if (repeating) {
UserError.Log.d(TAG, "Rescheduling next");
schedule_next();
} else {
enabled = false;
}
}
save();
}
public synchronized void reminder_alert() {
Reminders.doAlert(this);
}
public synchronized void schedule_next() {
this.next_due = this.next_due + this.period;
// check it is actually in the future
while (this.next_due < JoH.tsl()) {
this.next_due = this.next_due + this.period;
}
if (alternating) alternate = !alternate;
alerted_times = 0; // reset counter
save();
}
protected synchronized static void fixUpTable(String[] schema) {
if (patched) return;
for (String patch : schema) {
try {
SQLiteUtils.execSql(patch);
} catch (Exception e) {
//
}
}
patched = true;
}
public static Reminder create(String title, long period) {
fixUpTable(schema);
Reminder reminder = new Reminder();
reminder.title = title;
reminder.alternate_title = title + " alternate";
reminder.period = period;
reminder.next_due = JoH.tsl() + period;
reminder.enabled = true;
reminder.snoozed_till = 0;
reminder.last_snoozed_for = 0;
reminder.last_fired = 0;
reminder.fired_times = 0;
reminder.repeating = true;
reminder.alternating = false;
reminder.alternate = false;
reminder.chime_only = false;
reminder.homeonly = false;
reminder.ideal_time = JoH.hourMinuteString();
reminder.priority = 5; // default
reminder.save();
return reminder;
}
public static List<Reminder> getActiveReminders() {
fixUpTable(schema);
final long now = JoH.tsl();
final List<Reminder> reminders = new Select()
.from(Reminder.class)
.where("enabled = ?", true)
.where("next_due < ?", now)
.where("snoozed_till < ?", now)
.orderBy("enabled desc, next_due asc")
.execute();
return reminders;
}
private static boolean isNight() {
final int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
return hour < 9; // midnight to 9am we say is night
}
public static synchronized void processAnyDueReminders() {
if (JoH.quietratelimit("reminder_due_check", 10)) {
if (!Pref.getBooleanDefaultFalse(REMINDERS_ALL_DISABLED)
&& (!Pref.getBooleanDefaultFalse(REMINDERS_NIGHT_DISABLED) || !isNight())) {
final Reminder due_reminder = getNextActiveReminder();
if (due_reminder != null) {
UserError.Log.d(TAG, "Found due reminder! " + due_reminder.title);
due_reminder.reminder_alert();
}
} else {
// reminders are disabled - should we re-enable them?
if (Pref.getBooleanDefaultFalse(REMINDERS_RESTART_TOMORROW)) {
// temporary testing logic
final int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
if (hour == 10) {
if (JoH.pratelimit("restart-reminders", 7200)) {
UserError.Log.d(TAG, "Re-enabling reminders as its morning time");
Pref.setBoolean(REMINDERS_ALL_DISABLED, false);
}
}
}
}
}
}
public static Reminder getNextActiveReminder() {
fixUpTable(schema);
final boolean onHomeWifi = !HomeWifi.isSet() || HomeWifi.isConnected();
final long now = JoH.tsl();
final Reminder reminder = new Select()
.from(Reminder.class)
.where("enabled = ?", true)
.where("next_due < ?", now)
.where("snoozed_till < ?", now)
.where("last_fired < (? - (600000 * alerted_times))", now)
// if on home wifi or not set then anything otherwise only home only = false
.where(onHomeWifi ? "homeonly > -1 " : "homeonly = 0")
.orderBy("enabled desc, priority desc, next_due asc")
.executeSingle();
return reminder;
}
public static List<Reminder> getAllReminders() {
fixUpTable(schema);
final List<Reminder> reminders = new Select()
.from(Reminder.class)
.orderBy("enabled desc, priority desc, next_due asc")
.execute();
return reminders;
}
public synchronized static void firstInit(Context context) {
fixUpTable(schema);
/* Inevitable.task("reminders-first-init", 2000, new Runnable() {
@Override
public void run() {
try {
final Reminder reminder = new Select()
.from(Reminder.class)
.where("enabled = ?", true)
.executeSingle();
if (reminder != null) {
// PendingIntent serviceIntent = PendingIntent.getService(xdrip.getAppContext(), 0, new Intent(xdrip.getAppContext(), MissedReadingService.class), PendingIntent.FLAG_UPDATE_CURRENT);
// PendingIntent serviceIntent = WakeLockTrampoline.getPendingIntent(MissedReadingService.class);
// JoH.wakeUpIntent(xdrip.getAppContext(), Constants.MINUTE_IN_MS, serviceIntent);
// UserError.Log.ueh(TAG, "Starting missed readings service");
}
} catch (NullPointerException e) {
UserError.Log.wtf(TAG, "Got nasty initial concurrency exception: " + e);
}
}
});
*/
}
public static Reminder byid(long id) {
return new Select()
.from(Reminder.class)
.where("_ID = ?", id)
.executeSingle();
}
/*static Reminder getForPreciseTimestamp(double timestamp, double precision, String plugin) {
fixUpTable(schema);
final Reminder Reminder = new Select()
.from(Reminder.class)
.where("timestamp <= ?", (timestamp + precision))
.where("timestamp >= ?", (timestamp - precision))
.where("plugin = ?", plugin)
.orderBy("abs(timestamp - " + timestamp + ") asc")
.executeSingle();
if (Reminder != null && Math.abs(Reminder.timestamp - timestamp) < precision) {
return Reminder;
}
return null;
}
*/
}