diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java index acfbd7842..63647faa5 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/HabitFixtures.java @@ -75,7 +75,7 @@ public class HabitFixtures 81, 83, 89, 90, 91, 95, 102, 103, 108, 109, 120}; for (int mark : marks) - habit.getOriginalEntries().setValue(today.minus(mark), YES_MANUAL); + habit.getOriginalEntries().add(new Entry(today.minus(mark), YES_MANUAL)); return habit; } @@ -109,7 +109,7 @@ public class HabitFixtures 582, 583, 584, 586, 589}; for (int mark : marks) - habit.getOriginalEntries().setValue(today.minus(mark), YES_MANUAL); + habit.getOriginalEntries().add(new Entry(today.minus(mark), YES_MANUAL)); return habit; } @@ -128,7 +128,7 @@ public class HabitFixtures Timestamp timestamp = DateUtils.getToday(); for (int value : LONG_NUMERICAL_HABIT_ENTRIES) { - habit.getOriginalEntries().setValue(timestamp, value); + habit.getOriginalEntries().add(new Entry(timestamp, value)); timestamp = timestamp.minus(1); } @@ -146,7 +146,7 @@ public class HabitFixtures Timestamp timestamp = DateUtils.getToday(); for (boolean c : LONG_HABIT_ENTRIES) { - if (c) habit.getOriginalEntries().setValue(timestamp, YES_MANUAL); + if (c) habit.getOriginalEntries().add(new Entry(timestamp, YES_MANUAL)); timestamp = timestamp.minus(1); } diff --git a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/FrequencyChartTest.java b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/FrequencyChartTest.java index 94ff9fed9..be93e9806 100644 --- a/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/FrequencyChartTest.java +++ b/android/uhabits-android/src/androidTest/java/org/isoron/uhabits/activities/common/views/FrequencyChartTest.java @@ -46,7 +46,9 @@ public class FrequencyChartTest extends BaseViewTest Habit habit = fixtures.createLongHabit(); view = new FrequencyChart(targetContext); - view.setFrequency(habit.getOriginalEntries().getWeekdayFrequency()); + view.setFrequency(habit.getOriginalEntries().computeWeekdayFrequency( + habit.isNumerical() + )); view.setColor(PaletteUtilsKt.toFixedAndroidColor(habit.getColor())); measureView(view, dpToPixels(300), dpToPixels(100)); } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.kt index c9c53d6b4..c424adbaa 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/FrequencyCard.kt @@ -52,7 +52,9 @@ class FrequencyCardPresenter( ) { fun present() = FrequencyCardViewModel( color = habit.color, - frequency = habit.originalEntries.weekdayFrequency, + frequency = habit.originalEntries.computeWeekdayFrequency( + isNumerical = habit.isNumerical + ), firstWeekday = firstWeekday, ) } \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt index 9bcf9ee61..88776c3d6 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/OverviewCard.kt @@ -25,6 +25,7 @@ import android.widget.* import kotlinx.coroutines.* import org.isoron.uhabits.* import org.isoron.uhabits.core.models.* +import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL import org.isoron.uhabits.core.utils.* import org.isoron.uhabits.databinding.* import org.isoron.uhabits.utils.* @@ -74,12 +75,16 @@ class OverviewCardPresenter(val habit: Habit) { val scoreToday = scores.todayValue.toFloat() val scoreLastMonth = scores.getValue(lastMonth).toFloat() val scoreLastYear = scores.getValue(lastYear).toFloat() + val totalCount = habit.originalEntries.getKnown() + .filter { it.value == YES_MANUAL } + .count() + .toLong() return@IO OverviewCardViewModel( color = habit.color, scoreToday = scoreToday, scoreMonthDiff = scoreToday - scoreLastMonth, scoreYearDiff = scoreToday - scoreLastYear, - totalCount = habit.originalEntries.totalCount, + totalCount = totalCount, ) } } \ No newline at end of file diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt index 62b142526..fc871a9b4 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/FrequencyWidget.kt @@ -44,7 +44,7 @@ class FrequencyWidget( (widgetView.dataView as FrequencyChart).apply { setFirstWeekday(firstWeekday) setColor(habit.color.toThemedAndroidColor(context)) - setFrequency(habit.originalEntries.weekdayFrequency) + setFrequency(habit.originalEntries.computeWeekdayFrequency(habit.isNumerical)) } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/commands/CreateRepetitionCommand.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/commands/CreateRepetitionCommand.java index ceb372171..ae1a2d0d2 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/commands/CreateRepetitionCommand.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/commands/CreateRepetitionCommand.java @@ -52,8 +52,9 @@ public class CreateRepetitionCommand implements Command @Override public void execute() { - RepetitionList checks = habit.getOriginalEntries(); - checks.setValue(timestamp, value); + Entries checks = habit.getOriginalEntries(); + checks.add(new Entry(timestamp, value)); + habit.invalidateNewerThan(Timestamp.ZERO); habitList.resort(); } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.java index 3a2de5044..d5b2beac6 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitBullCSVImporter.java @@ -95,7 +95,7 @@ public class HabitBullCSVImporter extends AbstractImporter map.put(name, h); } - h.getOriginalEntries().setValue(timestamp, YES_MANUAL); + h.getOriginalEntries().add(new Entry(timestamp, YES_MANUAL)); } } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitsCSVExporter.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitsCSVExporter.java index 8b528557c..316359896 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitsCSVExporter.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/HabitsCSVExporter.java @@ -244,10 +244,10 @@ public class HabitsCSVExporter Timestamp newest = Timestamp.ZERO; for (Habit h : selectedHabits) { - if(h.getOriginalEntries().getOldest() == null || h.getOriginalEntries().getNewest() == null) - continue; - Timestamp currOld = h.getOriginalEntries().getOldest().getTimestamp(); - Timestamp currNew = h.getOriginalEntries().getNewest().getTimestamp(); + List entries = h.getOriginalEntries().getKnown(); + if (entries.isEmpty()) continue; + Timestamp currNew = entries.get(0).getTimestamp(); + Timestamp currOld = entries.get(entries.size() - 1).getTimestamp(); oldest = currOld.isOlderThan(oldest) ? currOld : oldest; newest = currNew.isNewerThan(newest) ? currNew : newest; } 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 2e6186b5d..2419f9cd7 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 @@ -101,10 +101,10 @@ public class LoopDBImporter extends AbstractImporter habitsRepository = new Repository<>(HabitRecord.class, db); entryRepository = new Repository<>(EntryRecord.class, db); - List records = habitsRepository.findAll("order by position"); - for (HabitRecord habitRecord : records) + List habitRecords = habitsRepository.findAll("order by position"); + for (HabitRecord habitRecord : habitRecords) { - List reps = + List entryRecords = entryRepository.findAll("where habit = ?", habitRecord.id.toString()); @@ -127,11 +127,11 @@ public class LoopDBImporter extends AbstractImporter // Reload saved version of the habit habit = habitList.getByUUID(habitRecord.uuid); - for (EntryRecord r : reps) + for (EntryRecord r : entryRecords) { Timestamp t = new Timestamp(r.timestamp); - Entry entry = habit.getOriginalEntries().getByTimestamp(t); - if (entry == null || entry.getValue() != r.value) + Entry existingEntry = habit.getOriginalEntries().get(t); + if (existingEntry.getValue() != r.value) new CreateRepetitionCommand(habitList, habit, t, r.value).execute(); } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/RewireDBImporter.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/RewireDBImporter.java index f249bea2b..22f8f3ac4 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/RewireDBImporter.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/RewireDBImporter.java @@ -167,7 +167,7 @@ public class RewireDBImporter extends AbstractImporter GregorianCalendar cal = DateUtils.getStartOfTodayCalendar(); cal.set(year, month - 1, day); - habit.getOriginalEntries().setValue(new Timestamp(cal), YES_MANUAL); + habit.getOriginalEntries().add(new Entry(new Timestamp(cal), YES_MANUAL)); } while (c.moveToNext()); } finally diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/TickmateDBImporter.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/TickmateDBImporter.java index 1066984ee..e198a0a9f 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/TickmateDBImporter.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/io/TickmateDBImporter.java @@ -102,7 +102,7 @@ public class TickmateDBImporter extends AbstractImporter GregorianCalendar cal = DateUtils.getStartOfTodayCalendar(); cal.set(year, month, day); - habit.getOriginalEntries().setValue(new Timestamp(cal), YES_MANUAL); + habit.getOriginalEntries().add(new Entry(new Timestamp(cal), YES_MANUAL)); } while (c.moveToNext()); } finally diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Entries.kt b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Entries.kt index e7140e59f..62eeb33b9 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Entries.kt +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Entries.kt @@ -23,6 +23,8 @@ import org.isoron.uhabits.core.models.Entry.Companion.UNKNOWN import org.isoron.uhabits.core.models.Entry.Companion.YES_AUTO import org.isoron.uhabits.core.models.Entry.Companion.YES_MANUAL import org.isoron.uhabits.core.utils.* +import java.util.* +import kotlin.collections.HashMap import kotlin.collections.set import kotlin.math.* @@ -136,6 +138,42 @@ open class Entries { entriesByTimestamp.clear() } + /** + * Returns the total number of successful entries for each month, grouped by day of week. + *

+ * The checkmarks are returned in a HashMap. The key is the timestamp for + * the first day of the month, at midnight (00:00). The value is an integer + * array with 7 entries. The first entry contains the total number of + * successful checkmarks during the specified month that occurred on a Saturday. The + * second entry corresponds to Sunday, and so on. If there are no + * successful checkmarks during a certain month, the value is null. + * + * @return total number of checkmarks by month versus day of week + */ + fun computeWeekdayFrequency(isNumerical: Boolean): HashMap> { + val entries = getKnown() + val map = hashMapOf>() + for ((originalTimestamp, value) in entries) { + val weekday = originalTimestamp.weekday + val truncatedTimestamp = Timestamp(originalTimestamp.toCalendar().apply { + set(Calendar.DAY_OF_MONTH, 1) + }.timeInMillis) + + var list = map[truncatedTimestamp] + if (list == null) { + list = arrayOf(0, 0, 0, 0, 0, 0, 0) + map[truncatedTimestamp] = list + } + + if (isNumerical) { + list[weekday] += value + } else if (value == YES_MANUAL) { + list[weekday] += 1 + } + } + return map + } + data class Interval(val begin: Timestamp, val center: Timestamp, val end: Timestamp) { val length: Int get() = begin.daysUntil(end) + 1; 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 d50109a3e..52b87bba6 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 @@ -182,8 +182,9 @@ public class EntryList @NonNull public synchronized final int[] getAllValues() { - Entry oldestOriginal = habit.getOriginalEntries().getOldest(); - if (oldestOriginal == null) return new int[0]; + List entries = habit.getOriginalEntries().getKnown(); + if(entries.isEmpty()) return new int[0]; + Entry oldestOriginal = entries.get(entries.size() - 1); Timestamp fromTimestamp = oldestOriginal.getTimestamp(); Timestamp toTimestamp = DateUtils.getTodayWithOffset(); @@ -365,16 +366,18 @@ public class EntryList if (newest != null && newest.getTimestamp().equals(today)) return; invalidateNewerThan(Timestamp.ZERO); - Entry oldestRep = habit.getOriginalEntries().getOldest(); - if (oldestRep == null) return; - final Timestamp from = oldestRep.getTimestamp(); + List entries = habit.getOriginalEntries().getKnown(); + if(entries.isEmpty()) return; + final Timestamp from = entries.get(entries.size() - 1).getTimestamp(); if (from.isNewerThan(today)) return; - Entry reps[] = habit - .getOriginalEntries() - .getByInterval(from, today) - .toArray(new Entry[0]); + Entry[] reps = entries.stream().filter(e -> + !e.getTimestamp().isOlderThan(from) && !e.getTimestamp().isNewerThan(today) + ).toArray(Entry[]::new); + List repsAsList = Arrays.asList(reps); + Collections.reverse(repsAsList); + reps = repsAsList.toArray(reps); if (habit.isNumerical()) computeNumerical(reps); else computeYesNo(reps); @@ -425,8 +428,9 @@ public class EntryList public List getAll() { - Entry oldest = habit.getOriginalEntries().getOldest(); - if (oldest == null) return new ArrayList<>(); + List entries = habit.getOriginalEntries().getKnown(); + if(entries.isEmpty()) return new ArrayList<>(); + Entry oldest = entries.get(entries.size() - 1); return getByInterval(oldest.getTimestamp(), DateUtils.getTodayWithOffset()); } @@ -456,6 +460,9 @@ public class EntryList Interval(Timestamp begin, Timestamp center, Timestamp end) { + if(begin.isNewerThan(center)) throw new IllegalArgumentException(); + if(center.isNewerThan(end)) throw new IllegalArgumentException(); + this.begin = begin; this.center = center; this.end = end; 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 index f869cabf8..6ed11ee93 100644 --- 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 @@ -34,7 +34,7 @@ data class Habit( var unit: String = "", var uuid: String? = null, val computedEntries: EntryList, - val originalEntries: RepetitionList, + val originalEntries: Entries, val scores: ScoreList, val streaks: StreakList, ) { 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 index 5a0e725e6..4c52dd8c6 100644 --- 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 @@ -29,25 +29,23 @@ 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, + originalEntries = buildOriginalEntries(), ) computedEntries.setHabit(habit) - originalEntries.setHabit(habit) scores.setHabit(habit) streaks.setHabit(habit) return habit } + fun buildOriginalEntries(): Entries fun buildEntryList(): EntryList fun buildHabitList(): HabitList - fun buildRepetitionList(): RepetitionList fun buildScoreList(): ScoreList fun buildStreakList(): StreakList fun buildHabitListRepository(): Repository 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 deleted file mode 100644 index 16ed0bfa9..000000000 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/RepetitionList.java +++ /dev/null @@ -1,243 +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.isoron.uhabits.core.utils.*; - -import java.util.*; - -public class RepetitionList -{ - protected Habit habit; - - private final ArrayList list = new ArrayList<>(); - - public void setHabit(Habit habit) - { - this.habit = habit; - } - - /** - * Adds a checkmark to the list. - *

- * Any implementation of this method must call observable.notifyListeners() - * after the checkmark has been added. - * - * @param entry the checkmark to be added. - */ - public void add(Entry entry) - { - list.add(entry); - } - - /** - * Returns the list of checkmarks that happened within the given time - * interval. - *

- * The list is sorted by timestamp in increasing order. That is, the first - * element corresponds to oldest timestamp, while the last element - * corresponds to the newest. The endpoints of the interval are included. - * - * @param fromTimestamp timestamp of the beginning of the interval - * @param toTimestamp timestamp of the end of the interval - * @return list of checkmarks within given time interval - */ - public List getByInterval(Timestamp fromTimestamp, Timestamp toTimestamp) - { - ArrayList filtered = new ArrayList<>(); - - for (Entry r : list) - { - Timestamp t = r.getTimestamp(); - if (t.isOlderThan(fromTimestamp) || t.isNewerThan(toTimestamp)) continue; - filtered.add(r); - } - - Collections.sort(filtered, - (r1, r2) -> r1.getTimestamp().compareTo(r2.getTimestamp())); - - return filtered; - } - - /** - * Returns the checkmark that has the given timestamp, or null if none - * exists. - * - * @param timestamp the checkmark timestamp. - * @return the checkmark that has the given timestamp. - */ - @Nullable - public Entry getByTimestamp(Timestamp timestamp) - { - for (Entry r : list) - if (r.getTimestamp().equals(timestamp)) return r; - - return null; - } - - /** - * If a checkmark with the given timestamp exists, return its value. Otherwise, returns - * Checkmark.NO for boolean habits and zero for numerical habits. - */ - @NonNull - public int getValue(Timestamp timestamp) - { - Entry check = getByTimestamp(timestamp); - if (check == null) return Entry.UNKNOWN; - return check.getValue(); - } - - /** - * Returns the oldest checkmark in the list. - *

- * If the list is empty, returns null. Repetitions in the future are - * discarded. - * - * @return oldest checkmark in the list, or null if list is empty. - */ - @Nullable - public Entry getOldest() - { - Timestamp oldestTimestamp = Timestamp.ZERO.plus(1000000); - Entry oldestRep = null; - - for (Entry rep : list) - { - if (rep.getTimestamp().isOlderThan(oldestTimestamp)) - { - oldestRep = rep; - oldestTimestamp = rep.getTimestamp(); - } - } - - return oldestRep; - } - - /** - * Returns the newest checkmark in the list. - *

- * If the list is empty, returns null. Repetitions in the past are - * discarded. - * - * @return newest checkmark in the list, or null if list is empty. - */ - @Nullable - public Entry getNewest() - { - Timestamp newestTimestamp = Timestamp.ZERO; - Entry newestRep = null; - - for (Entry rep : list) - { - if (rep.getTimestamp().isNewerThan(newestTimestamp)) - { - newestRep = rep; - newestTimestamp = rep.getTimestamp(); - } - } - - return newestRep; - } - - /** - * Returns the total number of successful checkmarks for each month, from the first - * checkmark until today, grouped by day of week. - *

- * The checkmarks are returned in a HashMap. The key is the timestamp for - * the first day of the month, at midnight (00:00). The value is an integer - * array with 7 entries. The first entry contains the total number of - * successful checkmarks during the specified month that occurred on a Saturday. The - * second entry corresponds to Sunday, and so on. If there are no - * successful checkmarks during a certain month, the value is null. - * - * @return total number of checkmarks by month versus day of week - */ - @NonNull - public HashMap getWeekdayFrequency() - { - List entries = - getByInterval(Timestamp.ZERO, DateUtils.getTodayWithOffset()); - HashMap map = new HashMap<>(); - - for (Entry e : entries) - { - if (!habit.isNumerical() && e.getValue() != Entry.YES_MANUAL) - continue; - - Calendar date = e.getTimestamp().toCalendar(); - int weekday = e.getTimestamp().getWeekday(); - date.set(Calendar.DAY_OF_MONTH, 1); - - Timestamp timestamp = new Timestamp(date.getTimeInMillis()); - Integer[] list = map.get(timestamp); - - if (list == null) - { - list = new Integer[7]; - Arrays.fill(list, 0); - map.put(timestamp, list); - } - - list[weekday]++; - } - - return map; - } - - /** - * Removes a given checkmark from the list. - *

- * If the list does not contain the checkmark, it is unchanged. - *

- * Any implementation of this method must call observable.notifyListeners() - * after the checkmark has been added. - * - * @param entry the checkmark to be removed - */ - public void remove(@NonNull Entry entry) - { - list.remove(entry); - } - - - public long getTotalCount() - { - int count = 0; - for (Entry rep : list) - if (rep.getValue() == Entry.YES_MANUAL) - count++; - return count; - } - - public void setValue(Timestamp timestamp, int value) - { - Entry check = getByTimestamp(timestamp); - if (check != null) remove(check); - add(new Entry(timestamp, value)); - habit.invalidateNewerThan(timestamp); - } - - public void removeAll() - { - list.clear(); - } -} 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 8b55f868e..c187a81e7 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 @@ -192,9 +192,11 @@ public abstract class ScoreList implements Iterable if (newestComputed == null) { - Entry oldest = habit.getOriginalEntries().getOldest(); - if (oldest != null) from = - Timestamp.oldest(from, oldest.getTimestamp()); + List entries = habit.getOriginalEntries().getKnown(); + if (!entries.isEmpty()) + from = Timestamp.oldest( + from, + entries.get(entries.size() - 1).getTimestamp()); forceRecompute(from, to, 0); } else @@ -212,8 +214,9 @@ public abstract class ScoreList implements Iterable */ protected void computeAll() { - Entry oldest = habit.getOriginalEntries().getOldest(); - if (oldest == null) return; + List entries = habit.getOriginalEntries().getKnown(); + if(entries.isEmpty()) return; + Entry oldest = entries.get(entries.size() - 1); Timestamp today = DateUtils.getTodayWithOffset(); compute(oldest.getTimestamp(), today); 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 b6a0a9464..c614148de 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 @@ -112,9 +112,9 @@ public abstract class StreakList Streak newestStreak = getNewestComputed(); if (newestStreak != null) return newestStreak.getStart(); - Entry oldestOriginal = habit.getOriginalEntries().getOldest(); - if (oldestOriginal != null) return oldestOriginal.getTimestamp(); - return null; + List entries = habit.getOriginalEntries().getKnown(); + if(entries.isEmpty()) return null; + return entries.get(entries.size() - 1).getTimestamp(); } /** 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 index 53f30d66d..9940bfc69 100644 --- 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 @@ -21,9 +21,9 @@ package org.isoron.uhabits.core.models.memory import org.isoron.uhabits.core.models.* class MemoryModelFactory : ModelFactory { + override fun buildOriginalEntries() = Entries() 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() 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 index 2eae29d70..bf6d817ce 100644 --- 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 @@ -33,10 +33,9 @@ class SQLModelFactory @Inject constructor( val database: Database, ) : ModelFactory { - + override fun buildOriginalEntries() = SQLiteEntries(database) override fun buildEntryList() = EntryList() override fun buildHabitList() = SQLiteHabitList(this) - override fun buildRepetitionList() = SQLiteRepetitionList(this) override fun buildScoreList() = MemoryScoreList() override fun buildStreakList() = MemoryStreakList() diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteEntries.kt b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteEntries.kt index d96e16a73..91d510798 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteEntries.kt +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteEntries.kt @@ -81,6 +81,8 @@ class SQLiteEntries(database: Database) : Entries() { } override fun clear() { - throw UnsupportedOperationException() + super.clear() + repository.execSQL("delete from repetitions where habit = ?", + habitId.toString()) } } 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 fc06e1a56..638993dc2 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 @@ -37,8 +37,6 @@ import javax.inject.*; */ public class SQLiteHabitList extends HabitList { - private static SQLiteHabitList instance; - @NonNull private final Repository repository; @@ -76,6 +74,7 @@ public class SQLiteHabitList extends HabitList Habit h = modelFactory.buildHabit(); rec.copyTo(h); + ((SQLiteEntries) h.getOriginalEntries()).setHabitId(h.getId()); list.add(h); } @@ -92,6 +91,7 @@ public class SQLiteHabitList extends HabitList record.copyFrom(habit); repository.save(record); habit.setId(record.id); + ((SQLiteEntries) habit.getOriginalEntries()).setHabitId(record.id); list.add(habit); getObservable().notifyListeners(); @@ -201,7 +201,7 @@ public class SQLiteHabitList extends HabitList if (record == null) throw new RuntimeException("habit not in database"); repository.executeAsTransaction(() -> { - habit.getOriginalEntries().removeAll(); + habit.getOriginalEntries().clear(); repository.remove(record); }); 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 deleted file mode 100644 index 075829404..000000000 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/sqlite/SQLiteRepetitionList.java +++ /dev/null @@ -1,135 +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 androidx.annotation.Nullable; -import androidx.annotation.*; - -import org.isoron.uhabits.core.database.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.models.sqlite.records.*; -import org.jetbrains.annotations.*; - -import java.util.*; - -/** - * Implementation of a {@link RepetitionList} that is backed by SQLite. - */ -public class SQLiteRepetitionList extends RepetitionList -{ - private final Repository repository; - - private boolean loaded = false; - - public SQLiteRepetitionList(@NonNull ModelFactory modelFactory) - { - repository = modelFactory.buildRepetitionListRepository(); - } - - private void loadRecords() - { - if (loaded) return; - loaded = true; - - check(habit.getId()); - List records = - repository.findAll("where habit = ? order by timestamp", - habit.getId().toString()); - - for (EntryRecord rec : records) - super.add(rec.toEntry()); - } - - @Override - public void add(Entry entry) - { - loadRecords(); - super.add(entry); - check(habit.getId()); - EntryRecord record = new EntryRecord(); - record.habitId = habit.getId(); - record.copyFrom(entry); - repository.save(record); - } - - @Override - public List getByInterval(Timestamp timeFrom, Timestamp timeTo) - { - loadRecords(); - return super.getByInterval(timeFrom, timeTo); - } - - @Override - @Nullable - public Entry getByTimestamp(Timestamp timestamp) - { - loadRecords(); - return super.getByTimestamp(timestamp); - } - - @Override - public Entry getOldest() - { - loadRecords(); - return super.getOldest(); - } - - @Override - public Entry getNewest() - { - loadRecords(); - return super.getNewest(); - } - - @Override - public void remove(@NonNull Entry entry) - { - loadRecords(); - super.remove(entry); - check(habit.getId()); - repository.execSQL( - "delete from repetitions where habit = ? and timestamp = ?", - habit.getId(), entry.getTimestamp().getUnixTime()); - } - - public void removeAll() - { - loadRecords(); - super.removeAll(); - check(habit.getId()); - repository.execSQL("delete from repetitions where habit = ?", - habit.getId()); - } - - @Override - public long getTotalCount() - { - loadRecords(); - return super.getTotalCount(); - } - - @Contract("null -> fail") - private void check(Long value) - { - if (value == null) throw new RuntimeException("null check failed"); - } -} diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/test/HabitFixtures.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/test/HabitFixtures.java index 83f53a7ab..bfb230bae 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/test/HabitFixtures.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/test/HabitFixtures.java @@ -65,7 +65,7 @@ public class HabitFixtures 81, 83, 89, 90, 91, 95, 102, 103, 108, 109, 120}; for (int mark : marks) - habit.getOriginalEntries().setValue(today.minus(mark), YES_MANUAL); + habit.getOriginalEntries().add(new Entry(today.minus(mark), YES_MANUAL)); return habit; } @@ -89,7 +89,7 @@ public class HabitFixtures for (int i = 0; i < times.length; i++) { Timestamp timestamp = today.minus(times[i]); - habit.getOriginalEntries().setValue(timestamp, values[i]); + habit.getOriginalEntries().add(new Entry(timestamp, values[i])); } return habit; @@ -125,7 +125,7 @@ public class HabitFixtures for (int i = 0; i < times.length; i++) { Timestamp timestamp = reference.minus(times[i]); - habit.getOriginalEntries().setValue(timestamp, values[i]); + habit.getOriginalEntries().add(new Entry(timestamp, values[i])); } return habit; @@ -144,7 +144,7 @@ public class HabitFixtures { int value = NO; if (c) value = YES_MANUAL; - habit.getOriginalEntries().setValue(timestamp, value); + habit.getOriginalEntries().add(new Entry(timestamp, value)); timestamp = timestamp.minus(1); } @@ -153,7 +153,7 @@ public class HabitFixtures private void saveIfSQLite(Habit habit) { - if (!(habit.getOriginalEntries() instanceof SQLiteRepetitionList)) return; + if (!(habit.getOriginalEntries() instanceof SQLiteEntries)) return; habitList.add(habit); } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitMenuBehavior.kt b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitMenuBehavior.kt index 946c697cd..61eb92997 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitMenuBehavior.kt +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/screens/habits/show/ShowHabitMenuBehavior.kt @@ -58,14 +58,14 @@ class ShowHabitMenuBehavior( fun onRandomize() { val random = Random() - habit.originalEntries.removeAll() + habit.originalEntries.clear() var strength = 50.0 for (i in 0 until 365 * 5) { if (i % 7 == 0) strength = Math.max(0.0, Math.min(100.0, strength + 10 * random.nextGaussian())) if (random.nextInt(100) > strength) continue var value = Entry.YES_MANUAL if (habit.isNumerical) value = (1000 + 250 * random.nextGaussian() * strength / 100).toInt() * 1000 - habit.originalEntries.setValue(DateUtils.getToday().minus(i), value) + habit.originalEntries.add(Entry(DateUtils.getToday().minus(i), value)) } habit.invalidateNewerThan(Timestamp.ZERO) screen.refresh() diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.java index 189a00ce8..e2b48756a 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/ui/widgets/WidgetBehavior.java @@ -70,7 +70,7 @@ public class WidgetBehavior public void onToggleRepetition(@NonNull Habit habit, Timestamp timestamp) { - int currentValue = habit.getOriginalEntries().getValue(timestamp); + int currentValue = habit.getOriginalEntries().get(timestamp).getValue(); int newValue; if(preferences.isSkipEnabled()) newValue = Entry.Companion.nextToggleValueWithSkip(currentValue); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/commands/CreateRepetitionCommandTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/commands/CreateRepetitionCommandTest.java index 5e00fbb28..0d1b81495 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/commands/CreateRepetitionCommandTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/commands/CreateRepetitionCommandTest.java @@ -51,13 +51,12 @@ public class CreateRepetitionCommandTest extends BaseUnitTest @Test public void testExecute() { - RepetitionList originalEntries = habit.getOriginalEntries(); - Entry entry = originalEntries.getByTimestamp(today); - assertNotNull(entry); + Entries originalEntries = habit.getOriginalEntries(); + Entry entry = originalEntries.get(today); assertEquals(YES_MANUAL, entry.getValue()); + command.execute(); - entry = originalEntries.getByTimestamp(today); - assertNotNull(entry); + entry = originalEntries.get(today); assertEquals(100, entry.getValue()); } } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/ImportTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/ImportTest.java index 0f1e1f5ea..58dc4b85b 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/ImportTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/io/ImportTest.java @@ -123,7 +123,7 @@ public class ImportTest extends BaseUnitTest GregorianCalendar date = DateUtils.getStartOfTodayCalendar(); date.set(year, month - 1, day); Timestamp timestamp = new Timestamp(date); - return h.getOriginalEntries().getValue(timestamp) == YES_MANUAL; + return h.getOriginalEntries().get(timestamp).getValue() == YES_MANUAL; } private void importFromFile(String assetFilename) throws IOException diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/EntriesTest.kt b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/EntriesTest.kt index f98474824..9c57a7d2d 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/EntriesTest.kt +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/EntriesTest.kt @@ -297,6 +297,45 @@ class EntriesTest { assertThat(actual, equalTo(expected)) } + @Test + fun testWeekdayFrequency() { + val entries = Entries() + val random = Random(123L) + val weekdayCount = Array(12) { Array(7) { 0 } } + val monthCount = Array(12) { 0 } + val day = DateUtils.getStartOfTodayCalendar() + + // Add repetitions randomly from January to December + day.set(2015, Calendar.JANUARY, 1, 0, 0, 0) + for (i in 0..364) { + if (random.nextBoolean()) { + val month = day[Calendar.MONTH] + val week = day[Calendar.DAY_OF_WEEK] % 7 + + // Leave the month of March empty, to check that it returns null + if (month == Calendar.MARCH) continue + + entries.add(Entry(Timestamp(day), YES_MANUAL)) + weekdayCount[month][week]++ + monthCount[month]++ + } + day.add(Calendar.DAY_OF_YEAR, 1) + } + + val freq = entries.computeWeekdayFrequency(isNumerical = false) + + // Repetitions should be counted correctly + for (month in 0..11) { + day.set(2015, month, 1, 0, 0, 0) + val actualCount = freq[Timestamp(day)] + if (monthCount[month] == 0) { + assertThat(actualCount, equalTo(null)) + } else { + assertThat(actualCount, equalTo(weekdayCount[month])) + } + } + } + fun day(offset: Int) = DateUtils.getToday().minus(offset) } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/EntryListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/EntryListTest.java deleted file mode 100644 index 2262f17e1..000000000 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/EntryListTest.java +++ /dev/null @@ -1,468 +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; - -import org.isoron.uhabits.core.*; -import org.isoron.uhabits.core.utils.*; -import org.junit.*; - -import java.io.*; -import java.util.*; - -import nl.jqno.equalsverifier.*; - -import static java.util.Calendar.*; -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.core.IsEqual.*; -import static org.isoron.uhabits.core.models.Entry.*; -import static org.isoron.uhabits.core.utils.DateUtils.TruncateField.MONTH; -import static org.isoron.uhabits.core.utils.DateUtils.TruncateField.QUARTER; -import static org.isoron.uhabits.core.utils.DateUtils.TruncateField.YEAR; - -public class EntryListTest extends BaseUnitTest -{ - private long dayLength; - - private Timestamp today; - - private Habit nonDailyHabit; - - private Habit emptyHabit; - - private Habit numericalHabit; - - @Override - public void setUp() throws Exception - { - super.setUp(); - - nonDailyHabit = fixtures.createShortHabit(); - habitList.add(nonDailyHabit); - - emptyHabit = fixtures.createEmptyHabit(); - habitList.add(emptyHabit); - - numericalHabit = fixtures.createNumericalHabit(); - habitList.add(numericalHabit); - today = DateUtils.getToday(); - } - - @Test - public void test_buildCheckmarksFromIntervals_1() throws Exception - { - Entry entries[] = new Entry[]{ - new Entry(day(10), YES_MANUAL), - new Entry(day(5), YES_MANUAL), - new Entry(day(2), YES_MANUAL), - new Entry(day(1), YES_MANUAL), - }; - - ArrayList intervals = new ArrayList<>(); - intervals.add(new EntryList.Interval(day(10), day(8), day(8))); - intervals.add(new EntryList.Interval(day(6), day(5), day(4))); - intervals.add(new EntryList.Interval(day(2), day(2), day(1))); - - List expected = new ArrayList<>(); - expected.add(new Entry(day(0), UNKNOWN)); - expected.add(new Entry(day(1), YES_MANUAL)); - expected.add(new Entry(day(2), YES_MANUAL)); - expected.add(new Entry(day(3), UNKNOWN)); - expected.add(new Entry(day(4), YES_AUTO)); - expected.add(new Entry(day(5), YES_MANUAL)); - expected.add(new Entry(day(6), YES_AUTO)); - expected.add(new Entry(day(7), UNKNOWN)); - expected.add(new Entry(day(8), YES_AUTO)); - expected.add(new Entry(day(9), YES_AUTO)); - expected.add(new Entry(day(10), YES_MANUAL)); - - List actual = - EntryList.buildEntriesFromInterval(entries, intervals); - assertThat(actual, equalTo(expected)); - } - - @Test - public void test_buildCheckmarksFromIntervals_2() throws Exception - { - Entry entries[] = new Entry[]{ - new Entry(day(0), YES_MANUAL), - }; - - ArrayList intervals = new ArrayList<>(); - intervals.add(new EntryList.Interval(day(0), day(0), day(-10))); - - List expected = new ArrayList<>(); - expected.add(new Entry(day(0), YES_MANUAL)); - - List actual = - EntryList.buildEntriesFromInterval(entries, intervals); - assertThat(actual, equalTo(expected)); - } - - @Test - public void test_buildIntervals_1() throws Exception - { - Entry entries[] = new Entry[]{ - new Entry(day(23), YES_MANUAL), - new Entry(day(18), YES_MANUAL), - new Entry(day(8), YES_MANUAL), - }; - - ArrayList expected = new ArrayList<>(); - expected.add(new EntryList.Interval(day(23), day(23), day(17))); - expected.add(new EntryList.Interval(day(18), day(18), day(12))); - expected.add(new EntryList.Interval(day(8), day(8), day(2))); - - ArrayList actual; - actual = EntryList.buildIntervals(Frequency.WEEKLY, entries); - assertThat(actual, equalTo(expected)); - } - - @Test - public void test_buildIntervals_2() throws Exception - { - Entry entries[] = new Entry[]{ - new Entry(day(23), YES_MANUAL), - new Entry(day(18), YES_MANUAL), - new Entry(day(8), YES_MANUAL), - }; - - ArrayList expected = new ArrayList<>(); - expected.add(new EntryList.Interval(day(23), day(23), day(23))); - expected.add(new EntryList.Interval(day(18), day(18), day(18))); - expected.add(new EntryList.Interval(day(8), day(8), day(8))); - - ArrayList actual; - actual = EntryList.buildIntervals(Frequency.DAILY, entries); - assertThat(actual, equalTo(expected)); - } - - @Test - public void test_buildIntervals_3() throws Exception - { - Entry entries[] = new Entry[]{ - new Entry(day(23), YES_MANUAL), - new Entry(day(22), YES_MANUAL), - new Entry(day(18), YES_MANUAL), - new Entry(day(15), YES_MANUAL), - new Entry(day(8), YES_MANUAL), - }; - - ArrayList expected = new ArrayList<>(); - expected.add(new EntryList.Interval(day(23), day(22), day(17))); - expected.add(new EntryList.Interval(day(22), day(18), day(16))); - expected.add(new EntryList.Interval(day(18), day(15), day(12))); - - ArrayList actual; - actual = - EntryList.buildIntervals(Frequency.TWO_TIMES_PER_WEEK, entries); - assertThat(actual, equalTo(expected)); - } - - - @Test - public void test_buildIntervals_4() throws Exception - { - Entry[] entries = new Entry[]{ - new Entry(day(30), YES_MANUAL), - new Entry(day(20), SKIP), - new Entry(day(10), YES_MANUAL), - }; - - ArrayList expected = new ArrayList<>(); - expected.add(new EntryList.Interval(day(30), day(30), day(28))); - expected.add(new EntryList.Interval(day(10), day(10), day(8))); - - ArrayList actual; - actual = EntryList.buildIntervals(new Frequency(1, 3), entries); - assertThat(actual, equalTo(expected)); - } - - @Test - public void test_getAllValues_moveBackwardsInTime() - { - travelInTime(-3); - - int[] expectedValues = { - YES_MANUAL, - YES_MANUAL, - YES_MANUAL, - YES_AUTO, - YES_AUTO, - YES_MANUAL, - YES_MANUAL - }; - - int[] actualValues = nonDailyHabit.getComputedEntries().getAllValues(); - - assertThat(actualValues, equalTo(expectedValues)); - } - - @Test - public void test_getAllValues_moveForwardInTime() - { - travelInTime(3); - - int[] expectedValues = { - UNKNOWN, - UNKNOWN, - UNKNOWN, - YES_MANUAL, - NO, - YES_AUTO, - YES_MANUAL, - YES_MANUAL, - YES_MANUAL, - YES_AUTO, - YES_AUTO, - YES_MANUAL, - YES_MANUAL - }; - - int[] actualValues = nonDailyHabit.getComputedEntries().getAllValues(); - - assertThat(actualValues, equalTo(expectedValues)); - } - - @Test - public void test_getAllValues_withEmptyHabit() - { - int[] expectedValues = new int[0]; - int[] actualValues = emptyHabit.getComputedEntries().getAllValues(); - - assertThat(actualValues, equalTo(expectedValues)); - } - - @Test - public void test_getAllValues_withNonDailyHabit() - { - int[] expectedValues = { - YES_MANUAL, - NO, - YES_AUTO, - YES_MANUAL, - YES_MANUAL, - YES_MANUAL, - YES_AUTO, - YES_AUTO, - YES_MANUAL, - YES_MANUAL - }; - - int[] actualValues = nonDailyHabit.getComputedEntries().getAllValues(); - - assertThat(actualValues, equalTo(expectedValues)); - } - - @Test - public void test_getByInterval_withNumericalHabits() throws Exception - { - EntryList entries = numericalHabit.getComputedEntries(); - - List expected = - Arrays.asList(new Entry(day(1), 200), new Entry(day(2), 0), - new Entry(day(3), 300), new Entry(day(4), 0), - new Entry(day(5), 400)); - - List actual = entries.getByInterval(day(5), day(1)); - assertThat(actual, equalTo(expected)); - } - - @Test - public void test_getTodayValue() - { - EntryList entries = nonDailyHabit.getComputedEntries(); - - travelInTime(-1); - assertThat(entries.getTodayValue(), equalTo(NO)); - - travelInTime(0); - assertThat(entries.getTodayValue(), equalTo(YES_MANUAL)); - - travelInTime(1); - assertThat(entries.getTodayValue(), equalTo(UNKNOWN)); - } - - @Test - public void test_getValues_withInvalidInterval() - { - int values[] = nonDailyHabit - .getComputedEntries() - .getValues(new Timestamp(0L).plus(100), new Timestamp(0L)); - assertThat(values, equalTo(new int[0])); - } - - @Test - public void test_getValues_withValidInterval() - { - Timestamp from = today.minus(15); - Timestamp to = today.minus(5); - - int[] expectedValues = { - YES_MANUAL, - YES_AUTO, - YES_AUTO, - YES_MANUAL, - YES_MANUAL, - UNKNOWN, - UNKNOWN, - UNKNOWN, - UNKNOWN, - UNKNOWN, - UNKNOWN - }; - - int[] actualValues = nonDailyHabit.getComputedEntries().getValues(from, to); - assertThat(actualValues, equalTo(expectedValues)); - } - - @Test - public void test_snapIntervalsTogether_1() throws Exception - { - ArrayList original = new ArrayList<>(); - original.add(new EntryList.Interval(day(27), day(27), day(21))); - original.add(new EntryList.Interval(day(20), day(20), day(14))); - original.add(new EntryList.Interval(day(12), day(12), day(6))); - original.add(new EntryList.Interval(day(8), day(8), day(2))); - - ArrayList expected = new ArrayList<>(); - expected.add(new EntryList.Interval(day(29), day(27), day(23))); - expected.add(new EntryList.Interval(day(22), day(20), day(16))); - expected.add(new EntryList.Interval(day(15), day(12), day(9))); - expected.add(new EntryList.Interval(day(8), day(8), day(2))); - - EntryList.snapIntervalsTogether(original); - assertThat(original, equalTo(expected)); - } - - @Test - public void test_snapIntervalsTogether_2() throws Exception - { - ArrayList original = new ArrayList<>(); - original.add(new EntryList.Interval(day(11), day(8), day(5))); - original.add(new EntryList.Interval(day(6), day(4), day(0))); - - ArrayList expected = new ArrayList<>(); - expected.add(new EntryList.Interval(day(13), day(8), day(7))); - expected.add(new EntryList.Interval(day(6), day(4), day(0))); - - EntryList.snapIntervalsTogether(original); - assertThat(original, equalTo(expected)); - } - - @Test - public void test_writeCSV() throws IOException - { - String expectedCSV = "2015-01-25,2\n2015-01-24,0\n2015-01-23,1\n" + - "2015-01-22,2\n2015-01-21,2\n2015-01-20,2\n" + - "2015-01-19,1\n2015-01-18,1\n2015-01-17,2\n" + - "2015-01-16,2\n"; - - - StringWriter writer = new StringWriter(); - nonDailyHabit.getComputedEntries().writeCSV(writer); - - assertThat(writer.toString(), equalTo(expectedCSV)); - } - - private Timestamp day(int offset) - { - return DateUtils.getToday().minus(offset); - } - - private void travelInTime(int days) - { - DateUtils.setFixedLocalTime( - FIXED_LOCAL_TIME + days * Timestamp.DAY_LENGTH); - } - - @Test - public void testEquals() throws Exception - { - EqualsVerifier.forClass(Entry.class).verify(); - EqualsVerifier.forClass(Timestamp.class).verify(); - EqualsVerifier.forClass(EntryList.Interval.class).verify(); - } - - @Test - public void testGroupBy() throws Exception - { - Habit habit = fixtures.createLongNumericalHabit(timestamp(2014, JUNE, 1)); - EntryList entries = habit.getComputedEntries(); - - List byMonth = entries.groupBy(MONTH, Calendar.SATURDAY); - assertThat(byMonth.size(), equalTo(25)); // from 2013-01-01 to 2015-01-01 - assertThat(byMonth.get(0), equalTo(new Entry(timestamp(2015, JANUARY, 1), 0))); - assertThat(byMonth.get(6), equalTo(new Entry(timestamp(2014, JULY, 1), 0))); - assertThat(byMonth.get(12), equalTo(new Entry(timestamp(2014, JANUARY, 1), 1706))); - assertThat(byMonth.get(18), equalTo(new Entry(timestamp(2013, JULY, 1), 1379))); - - List byQuarter = entries.groupBy(QUARTER, Calendar.SATURDAY); - assertThat(byQuarter.size(), equalTo(9)); // from 2013-Q1 to 2015-Q1 - assertThat(byQuarter.get(0), equalTo(new Entry(timestamp(2015, JANUARY, 1), 0))); - assertThat(byQuarter.get(4), equalTo(new Entry(timestamp(2014, JANUARY, 1), 4964))); - assertThat(byQuarter.get(8), equalTo(new Entry(timestamp(2013, JANUARY, 1), 4975))); - - List byYear = entries.groupBy(YEAR, Calendar.SATURDAY); - assertThat(byYear.size(), equalTo(3)); // from 2013 to 2015 - assertThat(byYear.get(0), equalTo(new Entry(timestamp(2015, JANUARY, 1), 0))); - assertThat(byYear.get(1), equalTo(new Entry(timestamp(2014, JANUARY, 1), 8227))); - assertThat(byYear.get(2), equalTo(new Entry(timestamp(2013, JANUARY, 1), 16172))); - } - - @Test - public void testGetTodayValue() throws Exception - { - Habit habit = fixtures.createLongNumericalHabit(timestamp(2014, JUNE, 1)); - EntryList checkmarks = habit.getComputedEntries(); - - DateUtils.setFixedLocalTime(unixTime(2050, MAY, 1)); - assertThat(checkmarks.getTodayValue(), equalTo(0)); - assertThat(checkmarks.getThisWeekValue(SATURDAY), equalTo(0)); - assertThat(checkmarks.getThisMonthValue(), equalTo(0)); - assertThat(checkmarks.getThisQuarterValue(), equalTo(0)); - assertThat(checkmarks.getThisYearValue(), equalTo(0)); - - DateUtils.setFixedLocalTime(unixTime(2014, JUNE, 6)); - assertThat(checkmarks.getTodayValue(), equalTo(0)); - assertThat(checkmarks.getThisWeekValue(SATURDAY), equalTo(230)); - assertThat(checkmarks.getThisWeekValue(SUNDAY), equalTo(230)); - assertThat(checkmarks.getThisWeekValue(MONDAY), equalTo(0)); - assertThat(checkmarks.getThisMonthValue(), equalTo(230)); - assertThat(checkmarks.getThisQuarterValue(), equalTo(3263)); - assertThat(checkmarks.getThisYearValue(), equalTo(8227)); - - DateUtils.setFixedLocalTime(unixTime(2014, JUNE, 1)); - assertThat(checkmarks.getTodayValue(), equalTo(230)); - assertThat(checkmarks.getThisWeekValue(SATURDAY), equalTo(230)); - assertThat(checkmarks.getThisWeekValue(SUNDAY), equalTo(230)); - assertThat(checkmarks.getThisMonthValue(), equalTo(230)); - - DateUtils.setFixedLocalTime(unixTime(2014, MAY, 16)); - assertThat(checkmarks.getTodayValue(), equalTo(0)); - assertThat(checkmarks.getThisWeekValue(SATURDAY), equalTo(419)); - assertThat(checkmarks.getThisWeekValue(THURSDAY), equalTo(134)); - assertThat(checkmarks.getThisMonthValue(), equalTo(1006)); - - DateUtils.setFixedLocalTime(unixTime(2000, MAY, 1)); - assertThat(checkmarks.getTodayValue(), equalTo(UNKNOWN)); - assertThat(checkmarks.getThisWeekValue(SATURDAY), equalTo(0)); - assertThat(checkmarks.getThisMonthValue(), equalTo(0)); - } -} 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 99ea9e75a..d23d3271e 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 @@ -40,19 +40,6 @@ public class HabitTest extends BaseUnitTest super.setUp(); } - @Test - public void testConstructor_default() - { - Habit habit = modelFactory.buildHabit(); - assertFalse(habit.isArchived()); - - assertThat(habit.hasReminder(), is(false)); - assertNotNull(habit.getStreaks()); - assertNotNull(habit.getScores()); - assertNotNull(habit.getOriginalEntries()); - assertNotNull(habit.getComputedEntries()); - } - @Test public void test_copyAttributes() { @@ -86,7 +73,7 @@ public class HabitTest extends BaseUnitTest { Habit h = modelFactory.buildHabit(); assertFalse(h.isCompletedToday()); - h.getOriginalEntries().setValue(getToday(), Entry.YES_MANUAL); + h.getOriginalEntries().add(new Entry(getToday(), Entry.YES_MANUAL)); assertTrue(h.isCompletedToday()); } @@ -99,19 +86,29 @@ public class HabitTest extends BaseUnitTest h.setTargetValue(100.0); assertFalse(h.isCompletedToday()); - h.getOriginalEntries().setValue(getToday(), 200_000); + h.getOriginalEntries().add(new Entry(getToday(), 200_000)); + h.invalidateNewerThan(Timestamp.ZERO); assertTrue(h.isCompletedToday()); - h.getOriginalEntries().setValue(getToday(), 100_000); + + h.getOriginalEntries().add(new Entry(getToday(), 100_000)); + h.invalidateNewerThan(Timestamp.ZERO); assertTrue(h.isCompletedToday()); - h.getOriginalEntries().setValue(getToday(), 50_000); + + h.getOriginalEntries().add(new Entry(getToday(), 50_000)); + h.invalidateNewerThan(Timestamp.ZERO); assertFalse(h.isCompletedToday()); h.setTargetType(Habit.AT_MOST); - h.getOriginalEntries().setValue(getToday(), 200_000); + h.getOriginalEntries().add(new Entry(getToday(), 200_000)); + h.invalidateNewerThan(Timestamp.ZERO); assertFalse(h.isCompletedToday()); - h.getOriginalEntries().setValue(getToday(), 100_000); + + h.getOriginalEntries().add(new Entry(getToday(), 100_000)); + h.invalidateNewerThan(Timestamp.ZERO); assertTrue(h.isCompletedToday()); - h.getOriginalEntries().setValue(getToday(), 50_000); + + h.getOriginalEntries().add(new Entry(getToday(), 50_000)); + h.invalidateNewerThan(Timestamp.ZERO); assertTrue(h.isCompletedToday()); } diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/RepetitionListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/RepetitionListTest.java deleted file mode 100644 index e33a07dc8..000000000 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/RepetitionListTest.java +++ /dev/null @@ -1,150 +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; - -import androidx.annotation.*; - -import org.isoron.uhabits.core.*; -import org.isoron.uhabits.core.utils.*; -import org.junit.*; - -import java.util.*; - -import static java.util.Calendar.*; -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.core.IsEqual.*; -import static org.isoron.uhabits.core.models.Entry.*; - -public class RepetitionListTest extends BaseUnitTest -{ - @NonNull - private RepetitionList reps; - - @NonNull - private Habit habit; - - private Timestamp today; - - private long day; - - @Override - @Before - public void setUp() throws Exception - { - super.setUp(); - habit = fixtures.createEmptyHabit(); - reps = habit.getOriginalEntries(); - - today = DateUtils.getToday(); - - reps.setValue(today.minus(3), YES_MANUAL); - reps.setValue(today.minus(2), YES_MANUAL); - reps.setValue(today, YES_MANUAL); - reps.setValue(today.minus(7), YES_MANUAL); - reps.setValue(today.minus(5), YES_MANUAL); - } - - @Override - @After - public void tearDown() throws Exception - { - super.tearDown(); - } - - @Test - public void test_getOldest() - { - Entry check = reps.getOldest(); - assertThat(check.getTimestamp(), equalTo(today.minus(7))); - } - - @Test - public void test_getWeekDayFrequency() - { - habit = fixtures.createEmptyHabit(); - reps = habit.getOriginalEntries(); - - Random random = new Random(123L); - Integer weekdayCount[][] = new Integer[12][7]; - Integer monthCount[] = new Integer[12]; - - Arrays.fill(monthCount, 0); - for (Integer row[] : weekdayCount) Arrays.fill(row, 0); - GregorianCalendar day = DateUtils.getStartOfTodayCalendar(); - - // Sets the current date to the end of November - day.set(2015, NOVEMBER, 30, 12, 0, 0); - DateUtils.setFixedLocalTime(day.getTimeInMillis()); - - // Add repetitions randomly from January to December - day.set(2015, JANUARY, 1, 0, 0, 0); - for (int i = 0; i < 365; i++) - { - if (random.nextBoolean()) - { - int month = day.get(Calendar.MONTH); - int week = day.get(Calendar.DAY_OF_WEEK) % 7; - - // Leave the month of March empty, to check that it returns null - if (month == MARCH) continue; - - reps.setValue(new Timestamp(day), YES_MANUAL); - - // Repetitions in December should not be counted - if (month == DECEMBER) continue; - - weekdayCount[month][week]++; - monthCount[month]++; - } - - day.add(Calendar.DAY_OF_YEAR, 1); - } - - HashMap freq = reps.getWeekdayFrequency(); - - // Repetitions until November should be counted correctly - for (int month = 0; month < 11; month++) - { - day.set(2015, month, 1, 0, 0, 0); - Integer actualCount[] = freq.get(new Timestamp(day)); - if (monthCount[month] == 0) assertThat(actualCount, equalTo(null)); - else assertThat(actualCount, equalTo(weekdayCount[month])); - } - - // Repetitions in December should be discarded - day.set(2015, DECEMBER, 1, 0, 0, 0); - assertThat(freq.get(new Timestamp(day)), equalTo(null)); - } - - @Test - public void test_setValue() - { - assertThat(reps.getValue(today), equalTo(YES_MANUAL)); - reps.setValue(today, NO); - assertThat(reps.getValue(today), equalTo(NO)); - - habit.setType(Habit.NUMBER_HABIT); - reps.setValue(today, 100); - assertThat(reps.getValue(today), equalTo(100)); - - reps.setValue(today, 500); - assertThat(reps.getValue(today), equalTo(500)); - } -} \ 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 7d1043299..95ea99fbe 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 @@ -327,34 +327,35 @@ public class ScoreListTest extends BaseUnitTest private void check(final int offset) { - RepetitionList entries = habit.getOriginalEntries(); + Entries entries = habit.getOriginalEntries(); Timestamp today = DateUtils.getToday(); - entries.setValue(today.minus(offset), YES_MANUAL); + entries.add(new Entry(today.minus(offset), YES_MANUAL)); } private void check(final int from, final int to) { - RepetitionList entries = habit.getOriginalEntries(); + Entries entries = habit.getOriginalEntries(); Timestamp today = DateUtils.getToday(); for (int i = from; i < to; i++) - entries.setValue(today.minus(i), YES_MANUAL); + entries.add(new Entry(today.minus(i), YES_MANUAL)); + habit.invalidateNewerThan(Timestamp.ZERO); } private void check(ArrayList values) { - RepetitionList entries = habit.getOriginalEntries(); + Entries entries = habit.getOriginalEntries(); Timestamp today = DateUtils.getToday(); for (int i = 0; i < values.size(); i++) if (values.get(i) == YES_MANUAL) - entries.setValue(today.minus(i), YES_MANUAL); + entries.add(new Entry(today.minus(i), YES_MANUAL)); } private void addSkip(final int day) { - RepetitionList entries = habit.getOriginalEntries(); + Entries entries = habit.getOriginalEntries(); Timestamp today = DateUtils.getToday(); - entries.setValue(today.minus(day), Entry.SKIP); + entries.add(new Entry(today.minus(day), Entry.SKIP)); } private void checkScoreValues(double[] expectedValues) diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/SQLiteRepetitionListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/SQLiteRepetitionListTest.java deleted file mode 100644 index c9d9385f4..000000000 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/sqlite/SQLiteRepetitionListTest.java +++ /dev/null @@ -1,143 +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 androidx.annotation.*; - -import org.isoron.uhabits.core.*; -import org.isoron.uhabits.core.database.*; -import org.isoron.uhabits.core.models.*; -import org.isoron.uhabits.core.models.sqlite.records.*; -import org.isoron.uhabits.core.test.*; -import org.isoron.uhabits.core.utils.*; -import org.junit.*; - -import java.util.*; - -import static junit.framework.TestCase.*; -import static org.hamcrest.MatcherAssert.*; -import static org.hamcrest.core.IsEqual.*; -import static org.isoron.uhabits.core.models.Entry.*; - -public class SQLiteRepetitionListTest extends BaseUnitTest -{ - private Habit habit; - - private Timestamp today; - - private RepetitionList originalCheckmarks; - - private long day; - - private Repository repository; - - @Override - public void setUp() throws Exception - { - super.setUp(); - - Database db = buildMemoryDatabase(); - modelFactory = new SQLModelFactory(db); - habitList = modelFactory.buildHabitList(); - fixtures = new HabitFixtures(modelFactory, habitList); - repository = new Repository<>(EntryRecord.class, db); - habit = fixtures.createLongHabit(); - - originalCheckmarks = habit.getOriginalEntries(); - today = DateUtils.getToday(); - } - - @Test - public void testAdd() - { - EntryRecord record = getByTimestamp(today.plus(1)); - assertNull(record); - - Entry rep = new Entry(today.plus(1), YES_MANUAL); - habit.getOriginalEntries().add(rep); - - record = getByTimestamp(today.plus(1)); - assertNotNull(record); - assertThat(record.value, equalTo(YES_MANUAL)); - } - - @Test - public void testGetByInterval() - { - List checks = - originalCheckmarks.getByInterval(today.minus(10), today); - - assertThat(checks.size(), equalTo(8)); - assertThat(checks.get(0).getTimestamp(), equalTo(today.minus(10))); - assertThat(checks.get(4).getTimestamp(), equalTo(today.minus(5))); - assertThat(checks.get(5).getTimestamp(), equalTo(today.minus(3))); - } - - @Test - public void testGetByTimestamp() - { - Entry rep = originalCheckmarks.getByTimestamp(today); - assertNotNull(rep); - assertThat(rep.getTimestamp(), equalTo(today)); - - rep = originalCheckmarks.getByTimestamp(today.minus(2)); - assertNull(rep); - } - - @Test - public void testGetOldest() - { - Entry rep = originalCheckmarks.getOldest(); - assertNotNull(rep); - assertThat(rep.getTimestamp(), equalTo(today.minus(120))); - } - - @Test - public void testGetOldest_withEmptyHabit() - { - Habit empty = fixtures.createEmptyHabit(); - Entry rep = empty.getOriginalEntries().getOldest(); - assertNull(rep); - } - - @Test - public void testRemove() - { - EntryRecord record = getByTimestamp(today); - assertNotNull(record); - - Entry rep = record.toEntry(); - originalCheckmarks.remove(rep); - - record = getByTimestamp(today); - assertNull(record); - } - - @Nullable - private EntryRecord getByTimestamp(Timestamp timestamp) - { - String query = "where habit = ? and timestamp = ?"; - String params[] = { - Long.toString(habit.getId()), Long.toString(timestamp.getUnixTime()) - }; - - return repository.findFirst(query, params); - } -} 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 86e23b727..9f0e8bb1a 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 @@ -91,7 +91,7 @@ public class WidgetBehaviorTest extends BaseUnitTest if(skipEnabled) nextValue = Entry.Companion.nextToggleValueWithSkip(currentValue); else nextValue = Entry.Companion.nextToggleValueWithoutSkip(currentValue); - habit.getOriginalEntries().setValue(timestamp, currentValue); + habit.getOriginalEntries().add(new Entry(timestamp, currentValue)); behavior.onToggleRepetition(habit, timestamp); verify(preferences).isSkipEnabled(); verify(commandRunner).execute( @@ -106,7 +106,7 @@ public class WidgetBehaviorTest extends BaseUnitTest public void testOnIncrement() { habit = fixtures.createNumericalHabit(); - habit.getOriginalEntries().setValue(timestamp, 500); + habit.getOriginalEntries().add(new Entry(timestamp, 500)); behavior.onIncrement(habit, timestamp, 100); verify(commandRunner).execute( @@ -120,7 +120,7 @@ public class WidgetBehaviorTest extends BaseUnitTest public void testOnDecrement() { habit = fixtures.createNumericalHabit(); - habit.getOriginalEntries().setValue(timestamp, 500); + habit.getOriginalEntries().add(new Entry(timestamp, 500)); behavior.onDecrement(habit, timestamp, 100); verify(commandRunner).execute(