mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Replace RepetitionList by Entries
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Entry> 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;
|
||||
}
|
||||
|
||||
@@ -101,10 +101,10 @@ public class LoopDBImporter extends AbstractImporter
|
||||
habitsRepository = new Repository<>(HabitRecord.class, db);
|
||||
entryRepository = new Repository<>(EntryRecord.class, db);
|
||||
|
||||
List<HabitRecord> records = habitsRepository.findAll("order by position");
|
||||
for (HabitRecord habitRecord : records)
|
||||
List<HabitRecord> habitRecords = habitsRepository.findAll("order by position");
|
||||
for (HabitRecord habitRecord : habitRecords)
|
||||
{
|
||||
List<EntryRecord> reps =
|
||||
List<EntryRecord> 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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
* <p>
|
||||
* 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<Timestamp, Array<Int>> {
|
||||
val entries = getKnown()
|
||||
val map = hashMapOf<Timestamp, Array<Int>>()
|
||||
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;
|
||||
|
||||
@@ -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<Entry> 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<Entry> 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<Entry> 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<Entry> getAll()
|
||||
{
|
||||
Entry oldest = habit.getOriginalEntries().getOldest();
|
||||
if (oldest == null) return new ArrayList<>();
|
||||
List<Entry> 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;
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
|
||||
@@ -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<HabitRecord>
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Entry> list = new ArrayList<>();
|
||||
|
||||
public void setHabit(Habit habit)
|
||||
{
|
||||
this.habit = habit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a checkmark to the list.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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<Entry> getByInterval(Timestamp fromTimestamp, Timestamp toTimestamp)
|
||||
{
|
||||
ArrayList<Entry> 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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<Timestamp, Integer[]> getWeekdayFrequency()
|
||||
{
|
||||
List<Entry> entries =
|
||||
getByInterval(Timestamp.ZERO, DateUtils.getTodayWithOffset());
|
||||
HashMap<Timestamp, Integer[]> 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.
|
||||
* <p>
|
||||
* If the list does not contain the checkmark, it is unchanged.
|
||||
* <p>
|
||||
* 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();
|
||||
}
|
||||
}
|
||||
@@ -192,9 +192,11 @@ public abstract class ScoreList implements Iterable<Score>
|
||||
|
||||
if (newestComputed == null)
|
||||
{
|
||||
Entry oldest = habit.getOriginalEntries().getOldest();
|
||||
if (oldest != null) from =
|
||||
Timestamp.oldest(from, oldest.getTimestamp());
|
||||
List<Entry> 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<Score>
|
||||
*/
|
||||
protected void computeAll()
|
||||
{
|
||||
Entry oldest = habit.getOriginalEntries().getOldest();
|
||||
if (oldest == null) return;
|
||||
List<Entry> entries = habit.getOriginalEntries().getKnown();
|
||||
if(entries.isEmpty()) return;
|
||||
Entry oldest = entries.get(entries.size() - 1);
|
||||
|
||||
Timestamp today = DateUtils.getTodayWithOffset();
|
||||
compute(oldest.getTimestamp(), today);
|
||||
|
||||
@@ -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<Entry> entries = habit.getOriginalEntries().getKnown();
|
||||
if(entries.isEmpty()) return null;
|
||||
return entries.get(entries.size() - 1).getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ import javax.inject.*;
|
||||
*/
|
||||
public class SQLiteHabitList extends HabitList
|
||||
{
|
||||
private static SQLiteHabitList instance;
|
||||
|
||||
@NonNull
|
||||
private final Repository<HabitRecord> 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);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
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<EntryRecord> 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<EntryRecord> 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<Entry> 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");
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,468 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<EntryList.Interval> 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<Entry> 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<Entry> 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<EntryList.Interval> intervals = new ArrayList<>();
|
||||
intervals.add(new EntryList.Interval(day(0), day(0), day(-10)));
|
||||
|
||||
List<Entry> expected = new ArrayList<>();
|
||||
expected.add(new Entry(day(0), YES_MANUAL));
|
||||
|
||||
List<Entry> 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<EntryList.Interval> 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<EntryList.Interval> 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<EntryList.Interval> 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<EntryList.Interval> 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<EntryList.Interval> 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<EntryList.Interval> 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<EntryList.Interval> 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<EntryList.Interval> 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<Entry> 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<Entry> 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<EntryList.Interval> 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<EntryList.Interval> 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<EntryList.Interval> 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<EntryList.Interval> 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<Entry> 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<Entry> 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<Entry> 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));
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<Timestamp, Integer[]> 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));
|
||||
}
|
||||
}
|
||||
@@ -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<Integer> 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)
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Álinson Santos Xavier <isoron@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<EntryRecord> 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<Entry> 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);
|
||||
}
|
||||
}
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user