diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/intents/IntentSchedulerTest.kt b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/intents/IntentSchedulerTest.kt index 7b260278c..b2ad2ed2b 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/intents/IntentSchedulerTest.kt +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/intents/IntentSchedulerTest.kt @@ -80,7 +80,7 @@ class IntentSchedulerTest : BaseAndroidTest() { @Test @MediumTest fun testScheduleShowReminder() { - for (h in habitList) h.setReminder(null) + for (h in habitList) h.reminder = null ReminderReceiver.clearLastReceivedIntent() setSystemTime("America/Chicago", 2020, JUNE, 1, 12, 30) diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.java index e869b9095..92ca230e6 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/performance/PerformanceTest.java @@ -60,7 +60,7 @@ public class PerformanceTest extends BaseAndroidTest @Test(timeout = 5000) public void benchmarkCreateHabitCommand() { - Database db = ((SQLModelFactory) modelFactory).db; + Database db = ((SQLModelFactory) modelFactory).getDatabase(); db.beginTransaction(); for (int i = 0; i < 1_000; i++) { @@ -75,7 +75,7 @@ public class PerformanceTest extends BaseAndroidTest @Test(timeout = 5000) public void benchmarkCreateRepetitionCommand() { - Database db = ((SQLModelFactory) modelFactory).db; + Database db = ((SQLModelFactory) modelFactory).getDatabase(); db.beginTransaction(); Habit habit = fixtures.createEmptyHabit(); for (int i = 0; i < 5_000; i++) diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/TargetWidgetTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/TargetWidgetTest.java index 8a9338ace..feac2e4e5 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/TargetWidgetTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/widgets/TargetWidgetTest.java @@ -48,6 +48,8 @@ public class TargetWidgetTest extends BaseViewTest habit = fixtures.createLongNumericalHabit(); habit.setColor(new PaletteColor(11)); + habit.setFrequency(Frequency.WEEKLY); + habit.invalidateNewerThan(Timestamp.ZERO); TargetWidget widget = new TargetWidget(targetContext, 0, habit); view = convertToView(widget, 400, 400); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt index bb8dce596..7259014c1 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/edit/EditHabitActivity.kt @@ -73,10 +73,10 @@ class EditHabitActivity : AppCompatActivity() { color = habit.color freqNum = habit.frequency.numerator freqDen = habit.frequency.denominator - if (habit.hasReminder()) { - reminderHour = habit.reminder.hour - reminderMin = habit.reminder.minute - reminderDays = habit.reminder.days + habit.reminder?.let { + reminderHour = it.hour + reminderMin = it.minute + reminderDays = it.days } binding.nameInput.setText(habit.name) binding.questionInput.setText(habit.question) @@ -210,9 +210,9 @@ class EditHabitActivity : AppCompatActivity() { habit.description = notesInput.text.trim().toString() habit.color = color if (reminderHour >= 0) { - habit.setReminder(Reminder(reminderHour, reminderMin, reminderDays)) + habit.reminder = Reminder(reminderHour, reminderMin, reminderDays) } else { - habit.setReminder(null) + habit.reminder = null } habit.frequency = Frequency(freqNum, freqDen) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt index 47802ca04..3ca85ee04 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCard.kt @@ -82,7 +82,7 @@ class SubtitleCardPresenter( fun present(): SubtitleCardViewModel { val reminderText = if (habit.hasReminder()) { - formatTime(context, habit.reminder.hour, habit.reminder.minute)!! + formatTime(context, habit.reminder!!.hour, habit.reminder!!.minute)!! } else { resources.getString(R.string.reminder_off) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt index 1b40927cd..363fd6aca 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/TargetCard.kt @@ -69,7 +69,7 @@ class TargetCardPresenter( val daysInQuarter = 91 val daysInYear = cal.getActualMaximum(Calendar.DAY_OF_YEAR) - val targetToday = habit.getTargetValue() / habit.frequency.denominator + val targetToday = habit.targetValue / habit.frequency.denominator val targetThisWeek = targetToday * 7 val targetThisMonth = targetToday * daysInMonth val targetThisQuarter = targetToday * daysInQuarter diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingController.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingController.kt index 9f234dc9c..f0dc659cc 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingController.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/automation/EditSettingController.kt @@ -28,13 +28,13 @@ import org.isoron.uhabits.core.models.* class EditSettingController(private val activity: Activity) { fun onSave(habit: Habit, action: Int) { - if (habit.getId() == null) return + if (habit.id == null) return val actionName = getActionName(action) val blurb = String.format("%s: %s", actionName, habit.name) val bundle = Bundle() bundle.putInt("action", action) - bundle.putLong("habit", habit.getId()!!) + bundle.putLong("habit", habit.id!!) activity.setResult(Activity.RESULT_OK, Intent().apply { putExtra(EXTRA_STRING_BLURB, blurb) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt index 21f5563ac..6d6222c25 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt @@ -76,7 +76,7 @@ class PendingIntentFactory timestamp: Long): PendingIntent = PendingIntent.getBroadcast( context, - (habit.getId()!! % Integer.MAX_VALUE).toInt() + 1, + (habit.id!! % Integer.MAX_VALUE).toInt() + 1, Intent(context, ReminderReceiver::class.java).apply { action = ReminderReceiver.ACTION_SHOW_REMINDER data = Uri.parse(habit.uriString) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java index 3e18c6191..d756b956d 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/ReminderReceiver.java @@ -81,7 +81,7 @@ public class ReminderReceiver extends BroadcastReceiver if (habit == null) return; Log.d("ReminderReceiver", String.format( "onShowReminder habit=%d timestamp=%d reminderTime=%d", - habit.id, + habit.getId(), timestamp, reminderTime)); reminderController.onShowReminder(habit, @@ -90,13 +90,13 @@ public class ReminderReceiver extends BroadcastReceiver case ACTION_DISMISS_REMINDER: if (habit == null) return; - Log.d("ReminderReceiver", String.format("onDismiss habit=%d", habit.id)); + Log.d("ReminderReceiver", String.format("onDismiss habit=%d", habit.getId())); reminderController.onDismiss(habit); break; case ACTION_SNOOZE_REMINDER: if (habit == null) return; - Log.d("ReminderReceiver", String.format("onSnoozePressed habit=%d", habit.id)); + Log.d("ReminderReceiver", String.format("onSnoozePressed habit=%d", habit.getId())); reminderController.onSnoozePressed(habit, context); break; diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/tasks/ImportDataTask.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/tasks/ImportDataTask.java index db56a3857..b210ed70a 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/tasks/ImportDataTask.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/tasks/ImportDataTask.java @@ -67,7 +67,7 @@ public class ImportDataTask implements Task @Override public void doInBackground() { - modelFactory.db.beginTransaction(); + modelFactory.getDatabase().beginTransaction(); try { @@ -75,7 +75,7 @@ public class ImportDataTask implements Task { importer.importHabitsFromFile(file); result = SUCCESS; - modelFactory.db.setTransactionSuccessful(); + modelFactory.getDatabase().setTransactionSuccessful(); } else { @@ -88,7 +88,7 @@ public class ImportDataTask implements Task Log.e("ImportDataTask", "Import failed", e); } - modelFactory.db.endTransaction(); + modelFactory.getDatabase().endTransaction(); } @Override diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt index 4e8e6592d..88662a013 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/CheckmarkWidget.kt @@ -66,7 +66,7 @@ open class CheckmarkWidget( override fun getDefaultWidth() = 125 private fun getNumericalEntryState(): Int { - return if (habit.isCompletedToday) { + return if (habit.isCompletedToday()) { Entry.YES_MANUAL } else { Entry.NO diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/LoopDBImporter.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/LoopDBImporter.java index 4e5a120dc..a178ceeca 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/LoopDBImporter.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/LoopDBImporter.java @@ -119,10 +119,9 @@ public class LoopDBImporter extends AbstractImporter else { Habit modified = modelFactory.buildHabit(); - habitRecord.id = habit.id; + habitRecord.id = habit.getId(); habitRecord.copyTo(modified); - if (!modified.getData().equals(habit.getData())) - new EditHabitCommand(modelFactory, habitList, habit, modified).execute(); + new EditHabitCommand(modelFactory, habitList, habit, modified).execute(); } // Reload saved version of the habit diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/EntryList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/EntryList.java index 464d48341..d50109a3e 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/EntryList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/EntryList.java @@ -31,6 +31,7 @@ import java.util.*; import javax.annotation.concurrent.*; import static org.isoron.uhabits.core.models.Entry.*; +import static org.isoron.uhabits.core.models.Habit.*; import static org.isoron.uhabits.core.utils.StringUtils.*; /** @@ -39,16 +40,20 @@ import static org.isoron.uhabits.core.utils.StringUtils.*; @ThreadSafe public class EntryList { - protected final Habit habit; + protected Habit habit = null; protected ArrayList list; - public EntryList(Habit habit) + public EntryList() { - this.habit = habit; this.list = new ArrayList<>(); } + public void setHabit(Habit habit) + { + this.habit = habit; + } + @NonNull static List buildEntriesFromInterval(Entry[] original, ArrayList intervals) @@ -425,6 +430,22 @@ public class EntryList return getByInterval(oldest.getTimestamp(), DateUtils.getTodayWithOffset()); } + public boolean isCompletedToday() + { + int todayCheckmark = getTodayValue(); + if (habit.isNumerical()) + { + if (habit.getTargetType() == AT_LEAST) + return todayCheckmark / 1000.0 >= habit.getTargetValue(); + else + return todayCheckmark / 1000.0 <= habit.getTargetValue(); + } + else + { + return (todayCheckmark != NO && todayCheckmark != UNKNOWN); + } + } + static final class Interval { final Timestamp begin; diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.java deleted file mode 100644 index ec5765f60..000000000 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.java +++ /dev/null @@ -1,510 +0,0 @@ -/* - * Copyright (C) 2016 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -package org.isoron.uhabits.core.models; - -import androidx.annotation.*; - -import org.apache.commons.lang3.builder.*; - -import java.util.*; - -import javax.annotation.concurrent.*; -import javax.inject.*; - -import static org.isoron.uhabits.core.models.Entry.*; -import static org.isoron.uhabits.core.utils.StringUtils.defaultToStringStyle; - -/** - * The thing that the user wants to track. - */ -@ThreadSafe -public class Habit -{ - public static final int AT_LEAST = 0; - - public static final int AT_MOST = 1; - - public static final String HABIT_URI_FORMAT = - "content://org.isoron.uhabits/habit/%d"; - - public static final int NUMBER_HABIT = 1; - - public static final int YES_NO_HABIT = 0; - - @Nullable - public Long id; - - @NonNull - private HabitData data; - - @NonNull - private StreakList streaks; - - @NonNull - private ScoreList scores; - - @NonNull - private RepetitionList repetitions; - - @NonNull - private EntryList computedEntries; - - private ModelObservable observable = new ModelObservable(); - - /** - * Constructs a habit with default data. - *

- * The habit is not archived, not highlighted, has no reminders and is - * placed in the last position of the list of habits. - */ - @Inject - Habit(@NonNull ModelFactory factory) - { - this.data = new HabitData(); - computedEntries = factory.buildEntryList(this); - streaks = factory.buildStreakList(this); - scores = factory.buildScoreList(this); - repetitions = factory.buildRepetitionList(this); - } - - Habit(@NonNull ModelFactory factory, @NonNull HabitData data) - { - this.data = new HabitData(data); - computedEntries = factory.buildEntryList(this); - streaks = factory.buildStreakList(this); - scores = factory.buildScoreList(this); - repetitions = factory.buildRepetitionList(this); - observable = new ModelObservable(); - } - - /** - * Clears the reminder for a habit. - */ - public synchronized void clearReminder() - { - data.reminder = null; - observable.notifyListeners(); - } - - /** - * Copies all the attributes of the specified habit into this habit - * - * @param model the model whose attributes should be copied from - */ - public synchronized void copyFrom(@NonNull Habit model) - { - this.data = new HabitData(model.data); - observable.notifyListeners(); - } - - @NonNull - public synchronized EntryList getComputedEntries() - { - return computedEntries; - } - - @NonNull - public synchronized PaletteColor getColor() - { - return data.color; - } - - public synchronized void setColor(@NonNull PaletteColor color) - { - data.color = color; - } - - @NonNull - public synchronized String getDescription() - { - return data.description; - } - - public synchronized void setDescription(@NonNull String description) - { - data.description = description; - } - - @NonNull - public synchronized Frequency getFrequency() - { - return data.frequency; - } - - public synchronized void setFrequency(@NonNull Frequency frequency) - { - data.frequency = frequency; - invalidateNewerThan(Timestamp.ZERO); - } - - @Nullable - public synchronized Long getId() - { - return id; - } - - public synchronized void setId(@Nullable Long id) - { - this.id = id; - } - - @NonNull - public synchronized String getName() - { - return data.name; - } - - public synchronized void setName(@NonNull String name) - { - data.name = name; - } - - public ModelObservable getObservable() - { - return observable; - } - - /** - * Returns the reminder for this habit. - *

- * Before calling this method, you should call {@link #hasReminder()} to - * verify that a reminder does exist, otherwise an exception will be - * thrown. - * - * @return the reminder for this habit - * @throws IllegalStateException if habit has no reminder - */ - @NonNull - public synchronized Reminder getReminder() - { - if (data.reminder == null) throw new IllegalStateException(); - return data.reminder; - } - - public synchronized void setReminder(@Nullable Reminder reminder) - { - data.reminder = reminder; - } - - public RepetitionList getOriginalEntries() - { - return repetitions; - } - - @NonNull - public ScoreList getScores() - { - return scores; - } - - @NonNull - public StreakList getStreaks() - { - return streaks; - } - - public synchronized int getTargetType() - { - return data.targetType; - } - - public synchronized void setTargetType(int targetType) - { - if (targetType != AT_LEAST && targetType != AT_MOST) - throw new IllegalArgumentException( - String.format("invalid targetType: %d", targetType)); - data.targetType = targetType; - } - - public synchronized double getTargetValue() - { - return data.targetValue; - } - - public synchronized void setTargetValue(double targetValue) - { - if (targetValue < 0) throw new IllegalArgumentException(); - data.targetValue = targetValue; - } - - public synchronized int getType() - { - return data.type; - } - - public synchronized void setType(int type) - { - if (type != YES_NO_HABIT && type != NUMBER_HABIT) - throw new IllegalArgumentException(); - - data.type = type; - } - - @NonNull - public synchronized String getUnit() - { - return data.unit; - } - - public synchronized void setUnit(@NonNull String unit) - { - data.unit = unit; - } - - /** - * Returns the public URI that identifies this habit - * - * @return the URI - */ - public String getUriString() - { - return String.format(Locale.US, HABIT_URI_FORMAT, getId()); - } - - public synchronized boolean hasId() - { - return getId() != null; - } - - /** - * Returns whether the habit has a reminder. - * - * @return true if habit has reminder, false otherwise - */ - public synchronized boolean hasReminder() - { - return data.reminder != null; - } - - public void invalidateNewerThan(Timestamp timestamp) - { - getScores().invalidateNewerThan(timestamp); - getComputedEntries().invalidateNewerThan(timestamp); - getStreaks().invalidateNewerThan(timestamp); - } - - public synchronized boolean isArchived() - { - return data.archived; - } - - public synchronized void setArchived(boolean archived) - { - data.archived = archived; - } - - public synchronized boolean isCompletedToday() - { - int todayCheckmark = getComputedEntries().getTodayValue(); - if (isNumerical()) - { - if(getTargetType() == AT_LEAST) - return todayCheckmark / 1000.0 >= data.targetValue; - else - return todayCheckmark / 1000.0 <= data.targetValue; - } - else return (todayCheckmark != NO && todayCheckmark != UNKNOWN); - } - - public synchronized boolean isNumerical() - { - return data.type == NUMBER_HABIT; - } - - public HabitData getData() - { - return new HabitData(data); - } - - public Integer getPosition() - { - return data.position; - } - - public void setPosition(int newPosition) - { - data.position = newPosition; - } - - @NonNull - public String getQuestion() - { - return data.question; - } - - public void setQuestion(@NonNull String question) - { - data.question = question; - } - - @NonNull - public String getUUID() - { - return data.uuid; - } - - public void setUUID(@NonNull String uuid) - { - data.uuid = uuid; - } - - public static final class HabitData - { - @NonNull - public String name; - - @NonNull - public String description; - - @NonNull - public String question; - - @NonNull - public Frequency frequency; - - public PaletteColor color; - - public boolean archived; - - public int targetType; - - public double targetValue; - - public int type; - - public String uuid; - - @NonNull - public String unit; - - @Nullable - public Reminder reminder; - - public int position; - - public HabitData() - { - this.color = new PaletteColor(8); - this.archived = false; - this.frequency = new Frequency(3, 7); - this.type = YES_NO_HABIT; - this.name = ""; - this.description = ""; - this.question = ""; - this.targetType = AT_LEAST; - this.targetValue = 100; - this.unit = ""; - this.position = 0; - this.uuid = UUID.randomUUID().toString().replace("-", ""); - } - - public HabitData(@NonNull HabitData model) - { - this.name = model.name; - this.description = model.description; - this.question = model.question; - this.frequency = model.frequency; - this.color = model.color; - this.archived = model.archived; - this.targetType = model.targetType; - this.targetValue = model.targetValue; - this.type = model.type; - this.unit = model.unit; - this.reminder = model.reminder; - this.position = model.position; - this.uuid = model.uuid; - } - - @Override - public String toString() - { - return new ToStringBuilder(this, defaultToStringStyle()) - .append("name", name) - .append("description", description) - .append("frequency", frequency) - .append("color", color) - .append("archived", archived) - .append("targetType", targetType) - .append("targetValue", targetValue) - .append("type", type) - .append("unit", unit) - .append("reminder", reminder) - .append("position", position) - .append("question", question) - .append("uuid", uuid) - .toString(); - } - - @Override - public boolean equals(Object o) - { - if (this == o) return true; - - if (o == null || getClass() != o.getClass()) return false; - - HabitData habitData = (HabitData) o; - - return new EqualsBuilder() - .append(color, habitData.color) - .append(archived, habitData.archived) - .append(targetType, habitData.targetType) - .append(targetValue, habitData.targetValue) - .append(type, habitData.type) - .append(name, habitData.name) - .append(description, habitData.description) - .append(frequency, habitData.frequency) - .append(unit, habitData.unit) - .append(reminder, habitData.reminder) - .append(position, habitData.position) - .append(question, habitData.question) - .append(uuid, habitData.uuid) - .isEquals(); - } - - @Override - public int hashCode() - { - return new HashCodeBuilder(17, 37) - .append(name) - .append(description) - .append(frequency) - .append(color) - .append(archived) - .append(targetType) - .append(targetValue) - .append(type) - .append(unit) - .append(reminder) - .append(position) - .append(question) - .append(uuid) - .toHashCode(); - } - } - - @Override - public String toString() - { - return new ToStringBuilder(this, defaultToStringStyle()) - .append("id", id) - .append("data", data) - .toString(); - } -} diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.kt b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.kt new file mode 100644 index 000000000..f869cabf8 --- /dev/null +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Habit.kt @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.uhabits.core.models + +data class Habit( + var color: PaletteColor = PaletteColor(8), + var description: String = "", + var frequency: Frequency = Frequency.DAILY, + var id: Long? = null, + var isArchived: Boolean = false, + var name: String = "", + var position: Int = 0, + var question: String = "", + var reminder: Reminder? = null, + var targetType: Int = AT_LEAST, + var targetValue: Double = 0.0, + var type: Int = YES_NO_HABIT, + var unit: String = "", + var uuid: String? = null, + val computedEntries: EntryList, + val originalEntries: RepetitionList, + val scores: ScoreList, + val streaks: StreakList, +) { + var observable = ModelObservable() + + val isNumerical: Boolean + get() = type == NUMBER_HABIT + + val uriString: String + get() = "content://org.isoron.uhabits/habit/$id" + + fun hasReminder(): Boolean = reminder != null + + fun isCompletedToday(): Boolean = computedEntries.isCompletedToday + + fun invalidateNewerThan(timestamp: Timestamp?) { + scores.invalidateNewerThan(timestamp) + computedEntries.invalidateNewerThan(timestamp) + streaks.invalidateNewerThan(timestamp) + } + + fun copyFrom(other: Habit) { + this.color = other.color + this.description = other.description + this.frequency = other.frequency + // this.id should not be copied + this.isArchived = other.isArchived + this.name = other.name + this.position = other.position + this.question = other.question + this.reminder = other.reminder + this.targetType = other.targetType + this.targetValue = other.targetValue + this.type = other.type + this.unit = other.unit + this.uuid = other.uuid + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Habit) return false + + if (color != other.color) return false + if (description != other.description) return false + if (frequency != other.frequency) return false + if (id != other.id) return false + if (isArchived != other.isArchived) return false + if (name != other.name) return false + if (position != other.position) return false + if (question != other.question) return false + if (reminder != other.reminder) return false + if (targetType != other.targetType) return false + if (targetValue != other.targetValue) return false + if (type != other.type) return false + if (unit != other.unit) return false + if (uuid != other.uuid) return false + + return true + } + + override fun hashCode(): Int { + var result = color.hashCode() + result = 31 * result + description.hashCode() + result = 31 * result + frequency.hashCode() + result = 31 * result + (id?.hashCode() ?: 0) + result = 31 * result + isArchived.hashCode() + result = 31 * result + name.hashCode() + result = 31 * result + position + result = 31 * result + question.hashCode() + result = 31 * result + (reminder?.hashCode() ?: 0) + result = 31 * result + targetType + result = 31 * result + targetValue.hashCode() + result = 31 * result + type + result = 31 * result + unit.hashCode() + result = 31 * result + (uuid?.hashCode() ?: 0) + return result + } + + companion object { + const val AT_LEAST = 0 + const val AT_MOST = 1 + const val NUMBER_HABIT = 1 + const val YES_NO_HABIT = 0 + } +} \ No newline at end of file diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ModelFactory.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ModelFactory.java deleted file mode 100644 index 60290a183..000000000 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ModelFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2016 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -package org.isoron.uhabits.core.models; - -import org.isoron.uhabits.core.database.*; -import org.isoron.uhabits.core.models.sqlite.records.*; - -/** - * Interface implemented by factories that provide concrete implementations of - * the core model classes. - */ -public interface ModelFactory -{ - EntryList buildEntryList(Habit habit); - - default Habit buildHabit() - { - return new Habit(this); - } - - default Habit buildHabit(Habit.HabitData data) - { - return new Habit(this, data); - } - - HabitList buildHabitList(); - - RepetitionList buildRepetitionList(Habit habit); - - ScoreList buildScoreList(Habit habit); - - StreakList buildStreakList(Habit habit); - - Repository buildHabitListRepository(); - - Repository buildRepetitionListRepository(); -} diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ModelFactory.kt b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ModelFactory.kt new file mode 100644 index 000000000..3f7579e49 --- /dev/null +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ModelFactory.kt @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.uhabits.core.models + +import org.isoron.uhabits.core.database.* +import org.isoron.uhabits.core.models.sqlite.records.* + +/** + * Interface implemented by factories that provide concrete implementations of + * the core model classes. + */ +interface ModelFactory { + + fun buildHabit(): Habit { + val computedEntries = buildEntryList() + val originalEntries = buildRepetitionList() + val scores = buildScoreList() + val streaks = buildStreakList() + val habit = Habit( + computedEntries = computedEntries, + originalEntries = originalEntries, + scores = scores, + streaks = streaks, + ) + computedEntries.setHabit(habit) + originalEntries.setHabit(habit) + scores.setHabit(habit) + streaks.setHabit(habit) + return habit + } + + fun buildEntryList(): EntryList + fun buildHabitList(): HabitList + fun buildRepetitionList(): RepetitionList + fun buildScoreList(): ScoreList + fun buildStreakList(): StreakList + fun buildHabitListRepository(): Repository + fun buildRepetitionListRepository(): Repository +} \ No newline at end of file diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/RepetitionList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/RepetitionList.java index 994f4c848..16ed0bfa9 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/RepetitionList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/RepetitionList.java @@ -27,12 +27,11 @@ import java.util.*; public class RepetitionList { - @NonNull - protected final Habit habit; + protected Habit habit; private final ArrayList list = new ArrayList<>(); - public RepetitionList(@NonNull Habit habit) + public void setHabit(Habit habit) { this.habit = habit; } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java index a8e4a8ded..8b55f868e 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/ScoreList.java @@ -31,22 +31,13 @@ import static org.isoron.uhabits.core.models.Entry.*; public abstract class ScoreList implements Iterable { - protected final Habit habit; + protected Habit habit; - protected ModelObservable observable; + protected ModelObservable observable = new ModelObservable(); - /** - * Creates a new ScoreList for the given habit. - *

- * The list is populated automatically according to the repetitions that the - * habit has. - * - * @param habit the habit to which the scores belong. - */ - public ScoreList(Habit habit) + public void setHabit(Habit habit) { this.habit = habit; - observable = new ModelObservable(); } /** diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/StreakList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/StreakList.java index 0339a864d..b6a0a9464 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/StreakList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/StreakList.java @@ -32,14 +32,13 @@ import java.util.*; */ public abstract class StreakList { - protected final Habit habit; + protected Habit habit; - protected ModelObservable observable; + protected ModelObservable observable = new ModelObservable(); - protected StreakList(Habit habit) + public void setHabit(Habit habit) { this.habit = habit; - observable = new ModelObservable(); } public abstract List getAll(); diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java index a242b5c0d..65ec9f448 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryHabitList.java @@ -95,7 +95,7 @@ public class MemoryHabitList extends HabitList @Override public synchronized Habit getByUUID(String uuid) { - for (Habit h : list) if (h.getUUID().equals(uuid)) return h; + for (Habit h : list) if (h.getUuid().equals(uuid)) return h; return null; } @@ -174,7 +174,7 @@ public class MemoryHabitList extends HabitList scoreComparatorDesc.compare(h2, h1); Comparator positionComparator = (h1, h2) -> - h1.getPosition().compareTo(h2.getPosition()); + Integer.compare(h1.getPosition(), h2.getPosition()); Comparator statusComparatorDesc = (h1, h2) -> { diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryModelFactory.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryModelFactory.java deleted file mode 100644 index da7161b69..000000000 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryModelFactory.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2016 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - */ - -package org.isoron.uhabits.core.models.memory; - -import org.isoron.uhabits.core.database.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.models.sqlite.records.*; - -public class MemoryModelFactory implements ModelFactory -{ - @Override - public EntryList buildEntryList(Habit habit) - { - return new EntryList(habit); - } - - @Override - public HabitList buildHabitList() - { - return new MemoryHabitList(); - } - - @Override - public RepetitionList buildRepetitionList(Habit habit) - { - return new RepetitionList(habit); - } - - @Override - public ScoreList buildScoreList(Habit habit) - { - return new MemoryScoreList(habit); - } - - @Override - public StreakList buildStreakList(Habit habit) - { - return new MemoryStreakList(habit); - } - - @Override - public Repository buildHabitListRepository() - { - throw new IllegalStateException(); - } - - @Override - public Repository buildRepetitionListRepository() - { - throw new IllegalStateException(); - } -} diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryModelFactory.kt b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryModelFactory.kt new file mode 100644 index 000000000..53f30d66d --- /dev/null +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryModelFactory.kt @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ +package org.isoron.uhabits.core.models.memory + +import org.isoron.uhabits.core.models.* + +class MemoryModelFactory : ModelFactory { + override fun buildEntryList() = EntryList() + override fun buildHabitList() = MemoryHabitList() + override fun buildRepetitionList() = RepetitionList() + override fun buildScoreList() = MemoryScoreList() + override fun buildStreakList() = MemoryStreakList() + override fun buildHabitListRepository() = throw NotImplementedError() + override fun buildRepetitionListRepository() = throw NotImplementedError() +} \ No newline at end of file diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryScoreList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryScoreList.java index 23d378e4a..d15c5792c 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryScoreList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryScoreList.java @@ -27,13 +27,7 @@ import java.util.*; public class MemoryScoreList extends ScoreList { - ArrayList list; - - public MemoryScoreList(Habit habit) - { - super(habit); - list = new ArrayList<>(); - } + ArrayList list = new ArrayList<>(); @Override public void add(List scores) diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryStreakList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryStreakList.java index 160c0743d..e3a1fbe41 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryStreakList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/memory/MemoryStreakList.java @@ -27,13 +27,7 @@ import java.util.*; public class MemoryStreakList extends StreakList { - ArrayList list; - - public MemoryStreakList(Habit habit) - { - super(habit); - list = new ArrayList<>(); - } + ArrayList list = new ArrayList<>(); @Override public Streak getNewestComputed() diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLModelFactory.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLModelFactory.java deleted file mode 100644 index 082169443..000000000 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLModelFactory.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2017 Álinson Santos Xavier - * - * This file is part of Loop Habit Tracker. - * - * Loop Habit Tracker is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation, either version 3 of the License, or (at your - * option) any later version. - * - * Loop Habit Tracker is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * - */ - -package org.isoron.uhabits.core.models.sqlite; - -import org.isoron.uhabits.core.database.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.models.memory.*; -import org.isoron.uhabits.core.models.sqlite.records.*; - -import javax.inject.*; - -/** - * Factory that provides models backed by an SQLite database. - */ -public class SQLModelFactory implements ModelFactory -{ - public final Database db; - - @Inject - public SQLModelFactory(Database db) - { - this.db = db; - } - - @Override - public EntryList buildEntryList(Habit habit) - { - return new EntryList(habit); - } - - @Override - public HabitList buildHabitList() - { - return new SQLiteHabitList(this); - } - - @Override - public RepetitionList buildRepetitionList(Habit habit) - { - return new SQLiteRepetitionList(habit, this); - } - - @Override - public ScoreList buildScoreList(Habit habit) - { - return new MemoryScoreList(habit); - } - - @Override - public StreakList buildStreakList(Habit habit) - { - return new MemoryStreakList(habit); - } - - @Override - public Repository buildHabitListRepository() - { - return new Repository<>(HabitRecord.class, db); - } - - @Override - public Repository buildRepetitionListRepository() - { - return new Repository<>(RepetitionRecord.class, db); - } -} diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLModelFactory.kt b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLModelFactory.kt new file mode 100644 index 000000000..af32668e3 --- /dev/null +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLModelFactory.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2017 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * + */ +package org.isoron.uhabits.core.models.sqlite + +import org.isoron.uhabits.core.database.* +import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.models.memory.* +import org.isoron.uhabits.core.models.sqlite.records.* +import javax.inject.* + +/** + * Factory that provides models backed by an SQLite database. + */ +class SQLModelFactory +@Inject constructor( + val database: Database, +) : ModelFactory { + + override fun buildEntryList() = EntryList() + override fun buildHabitList() = SQLiteHabitList(this) + override fun buildRepetitionList() = SQLiteRepetitionList(this) + override fun buildScoreList() = MemoryScoreList() + override fun buildStreakList() = MemoryStreakList() + + override fun buildHabitListRepository() = + Repository(HabitRecord::class.java, database) + + override fun buildRepetitionListRepository() = + Repository(RepetitionRecord::class.java, database) +} \ No newline at end of file diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java index 11054a69b..fc06e1a56 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteHabitList.java @@ -91,7 +91,7 @@ public class SQLiteHabitList extends HabitList HabitRecord record = new HabitRecord(); record.copyFrom(habit); repository.save(record); - habit.id = record.id; + habit.setId(record.id); list.add(habit); getObservable().notifyListeners(); diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteRepetitionList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteRepetitionList.java index 11f9d2af6..783cb14ae 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteRepetitionList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteRepetitionList.java @@ -40,10 +40,8 @@ public class SQLiteRepetitionList extends RepetitionList private boolean loaded = false; - public SQLiteRepetitionList(@NonNull Habit habit, - @NonNull ModelFactory modelFactory) + public SQLiteRepetitionList(@NonNull ModelFactory modelFactory) { - super(habit); repository = modelFactory.buildRepetitionListRepository(); } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.java index 93c67ce8e..bf1a15007 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.java @@ -98,7 +98,7 @@ public class HabitRecord this.unit = model.getUnit(); this.position = model.getPosition(); this.question = model.getQuestion(); - this.uuid = model.getUUID(); + this.uuid = model.getUuid(); Frequency freq = model.getFrequency(); this.freqNum = freq.getNumerator(); @@ -130,7 +130,7 @@ public class HabitRecord habit.setTargetValue(this.targetValue); habit.setUnit(this.unit); habit.setPosition(this.position); - habit.setUUID(this.uuid); + habit.setUuid(this.uuid); if (reminderHour != null && reminderMin != null) { diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java index 89f2b7154..da35d71da 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java @@ -74,7 +74,7 @@ public class ReminderScheduler implements CommandRunner.Listener if (!habit.hasReminder()) { - sys.log("ReminderScheduler", "habit=" + habit.id + " has no reminder. Skipping."); + sys.log("ReminderScheduler", "habit=" + habit.getId() + " has no reminder. Skipping."); return; } @@ -107,17 +107,17 @@ public class ReminderScheduler implements CommandRunner.Listener public synchronized void scheduleAtTime(@NonNull Habit habit, long reminderTime) { - sys.log("ReminderScheduler", "Scheduling alarm for habit=" + habit.id); + sys.log("ReminderScheduler", "Scheduling alarm for habit=" + habit.getId()); if (!habit.hasReminder()) { - sys.log("ReminderScheduler", "habit=" + habit.id + " has no reminder. Skipping."); + sys.log("ReminderScheduler", "habit=" + habit.getId() + " has no reminder. Skipping."); return; } if (habit.isArchived()) { - sys.log("ReminderScheduler", "habit=" + habit.id + " is archived. Skipping."); + sys.log("ReminderScheduler", "habit=" + habit.getId() + " is archived. Skipping."); return; } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/NotificationTray.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/NotificationTray.java index d7c40cded..3ab1ac437 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/NotificationTray.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/NotificationTray.java @@ -184,13 +184,13 @@ public class NotificationTray @Override public void onPostExecute() { - systemTray.log("Showing notification for habit=" + habit.id); + systemTray.log("Showing notification for habit=" + habit.getId()); if (todayValue != Entry.UNKNOWN) { systemTray.log(String.format( Locale.US, "Habit %d already checked. Skipping.", - habit.id)); + habit.getId())); return; } @@ -198,7 +198,7 @@ public class NotificationTray systemTray.log(String.format( Locale.US, "Habit %d does not have a reminder. Skipping.", - habit.id)); + habit.getId())); return; } @@ -207,7 +207,7 @@ public class NotificationTray systemTray.log(String.format( Locale.US, "Habit %d is archived. Skipping.", - habit.id)); + habit.getId())); return; } @@ -215,7 +215,7 @@ public class NotificationTray systemTray.log(String.format( Locale.US, "Habit %d not supposed to run today. Skipping.", - habit.id)); + habit.getId())); return; } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitBehavior.kt b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitBehavior.kt index 609f300e0..f8fbdc674 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitBehavior.kt +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitBehavior.kt @@ -67,7 +67,7 @@ class ShowHabitBehavior( timestamp, thousands, ), - habit.getId(), + habit.id, ) } } else { diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/commands/EditHabitCommandTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/commands/EditHabitCommandTest.java index 045107d6e..f05cbd71d 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/commands/EditHabitCommandTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/commands/EditHabitCommandTest.java @@ -52,10 +52,9 @@ public class EditHabitCommandTest extends BaseUnitTest } @Test - public void testExecuteUndoRedo() + public void testExecute() { - command = - new EditHabitCommand(modelFactory, habitList, habit, modified); + command = new EditHabitCommand(modelFactory, habitList, habit, modified); double originalScore = habit.getScores().getTodayValue(); assertThat(habit.getName(), equalTo("original")); @@ -66,7 +65,7 @@ public class EditHabitCommandTest extends BaseUnitTest } @Test - public void testExecuteUndoRedo_withModifiedInterval() + public void testExecute_withModifiedInterval() { modified.setFrequency(Frequency.TWO_TIMES_PER_WEEK); command = diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitTest.java index ac51c5a06..99ea9e75a 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/HabitTest.java @@ -72,16 +72,13 @@ public class HabitTest extends BaseUnitTest @Test - public void test_hasReminder_clearReminder() + public void test_hasReminder() { Habit h = modelFactory.buildHabit(); assertThat(h.hasReminder(), is(false)); h.setReminder(new Reminder(8, 30, WeekdayList.EVERY_DAY)); assertThat(h.hasReminder(), is(true)); - - h.clearReminder(); - assertThat(h.hasReminder(), is(false)); } @Test @@ -132,31 +129,9 @@ public class HabitTest extends BaseUnitTest @Test public void testEquals() throws Exception { - EqualsVerifier - .forClass(Habit.HabitData.class) - .suppress(Warning.NONFINAL_FIELDS) - .verify(); - EqualsVerifier.forClass(Score.class).verify(); EqualsVerifier.forClass(Streak.class).verify(); EqualsVerifier.forClass(Reminder.class).verify(); EqualsVerifier.forClass(WeekdayList.class).verify(); } - - @Test - public void testToString() throws Exception - { - Habit h = modelFactory.buildHabit(); - h.setUUID("nnnn"); - h.setReminder(new Reminder(22, 30, WeekdayList.EVERY_DAY)); - String expected = "{id: , data: {name: , description: ," + - " frequency: {numerator: 3, denominator: 7}," + - " color: PaletteColor(paletteIndex=8), archived: false, targetType: 0," + - " targetValue: 100.0, type: 0, unit: ," + - " reminder: {hour: 22, minute: 30," + - " days: {weekdays: [true,true,true,true,true,true,true]}}," + - " position: 0, question: , uuid: nnnn}}"; - - assertThat(h.toString(), equalTo(expected)); - } } \ No newline at end of file diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/ScoreListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/ScoreListTest.java index 8e9a15196..7d1043299 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/ScoreListTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/ScoreListTest.java @@ -219,6 +219,7 @@ public class ScoreListTest extends BaseUnitTest // Missing 2 repetitions out of 4 per week, the score should converge to 50% habit.setFrequency(new Frequency(4, 7)); + habit.invalidateNewerThan(Timestamp.ZERO); assertThat(habit.getScores().getTodayValue(), closeTo(0.5, E)); } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecordTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecordTest.java index 94a2e2f2f..0c245763f 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecordTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecordTest.java @@ -50,7 +50,7 @@ public class HabitRecordTest extends BaseUnitTest Habit duplicate = modelFactory.buildHabit(); record.copyTo(duplicate); - assertThat(original.getData(), equalTo(duplicate.getData())); + assertThat(original, equalTo(duplicate)); } @Test @@ -76,6 +76,6 @@ public class HabitRecordTest extends BaseUnitTest Habit duplicate = modelFactory.buildHabit(); record.copyTo(duplicate); - assertThat(original.getData(), equalTo(duplicate.getData())); + assertThat(original, equalTo(duplicate)); } } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.java index 4f8790c73..33b952215 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/reminders/ReminderSchedulerTest.java @@ -56,7 +56,7 @@ public class ReminderSchedulerTest extends BaseUnitTest { super.setUp(); habit = fixtures.createEmptyHabit(); - habit.id = habitId; + habit.setId(habitId); reminderScheduler = new ReminderScheduler(commandRunner, habitList, sys, widgetPreferences); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/widgets/WidgetBehaviorTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/widgets/WidgetBehaviorTest.java index 931065813..86e23b727 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/widgets/WidgetBehaviorTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/ui/widgets/WidgetBehaviorTest.java @@ -63,7 +63,7 @@ public class WidgetBehaviorTest extends BaseUnitTest behavior.onAddRepetition(habit, timestamp); verify(commandRunner).execute( new CreateRepetitionCommand(habitList, habit, timestamp, YES_MANUAL), - habit.id); + habit.getId()); verify(notificationTray).cancel(habit); verifyZeroInteractions(preferences); } @@ -74,7 +74,7 @@ public class WidgetBehaviorTest extends BaseUnitTest behavior.onRemoveRepetition(habit, timestamp); verify(commandRunner).execute( new CreateRepetitionCommand(habitList, habit, timestamp, NO), - habit.id); + habit.getId()); verify(notificationTray).cancel(habit); verifyZeroInteractions(preferences); } @@ -96,7 +96,7 @@ public class WidgetBehaviorTest extends BaseUnitTest verify(preferences).isSkipEnabled(); verify(commandRunner).execute( new CreateRepetitionCommand(habitList, habit, timestamp, nextValue), - habit.id); + habit.getId()); verify(notificationTray).cancel(habit); reset(preferences, commandRunner, notificationTray); } @@ -111,7 +111,7 @@ public class WidgetBehaviorTest extends BaseUnitTest behavior.onIncrement(habit, timestamp, 100); verify(commandRunner).execute( new CreateRepetitionCommand(habitList, habit, timestamp, 600), - habit.id); + habit.getId()); verify(notificationTray).cancel(habit); verifyZeroInteractions(preferences); } @@ -125,7 +125,7 @@ public class WidgetBehaviorTest extends BaseUnitTest behavior.onDecrement(habit, timestamp, 100); verify(commandRunner).execute( new CreateRepetitionCommand(habitList, habit, timestamp, 400), - habit.id); + habit.getId()); verify(notificationTray).cancel(habit); verifyZeroInteractions(preferences); }