mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 09:08:52 -06:00
Add instrumented unit tests for SQLite lists
This commit is contained in:
@@ -15,6 +15,7 @@ android {
|
|||||||
buildConfigField "String", "databaseFilename", "\"uhabits.db\""
|
buildConfigField "String", "databaseFilename", "\"uhabits.db\""
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
|
testInstrumentationRunnerArgument "size", "medium"
|
||||||
}
|
}
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
@@ -40,7 +41,7 @@ android {
|
|||||||
unitTests.all {
|
unitTests.all {
|
||||||
testLogging {
|
testLogging {
|
||||||
events "passed", "skipped", "failed", "standardOut", "standardError"
|
events "passed", "skipped", "failed", "standardOut", "standardError"
|
||||||
outputs.upToDateWhen {false}
|
outputs.upToDateWhen { false }
|
||||||
showStandardStreams = true
|
showStandardStreams = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public class BaseAndroidTest
|
|||||||
|
|
||||||
protected AndroidTestComponent androidTestComponent;
|
protected AndroidTestComponent androidTestComponent;
|
||||||
|
|
||||||
protected HabitFixtures habitFixtures;
|
protected HabitFixtures fixtures;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp()
|
public void setUp()
|
||||||
@@ -76,7 +76,7 @@ public class BaseAndroidTest
|
|||||||
HabitsApplication.setComponent(androidTestComponent);
|
HabitsApplication.setComponent(androidTestComponent);
|
||||||
androidTestComponent.inject(this);
|
androidTestComponent.inject(this);
|
||||||
|
|
||||||
habitFixtures = new HabitFixtures(habitList);
|
fixtures = new HabitFixtures(habitList);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void waitForAsyncTasks()
|
protected void waitForAsyncTasks()
|
||||||
|
|||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* 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.models.sqlite;
|
||||||
|
|
||||||
|
import android.support.test.runner.*;
|
||||||
|
import android.test.suitebuilder.annotation.*;
|
||||||
|
|
||||||
|
import com.activeandroid.query.*;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.models.*;
|
||||||
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.junit.runner.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@MediumTest
|
||||||
|
public class SQLiteCheckmarkListTest extends BaseAndroidTest
|
||||||
|
{
|
||||||
|
private Habit habit;
|
||||||
|
|
||||||
|
private CheckmarkList checkmarks;
|
||||||
|
|
||||||
|
private long today;
|
||||||
|
|
||||||
|
private long day;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
habit = fixtures.createLongHabit();
|
||||||
|
checkmarks = habit.getCheckmarks();
|
||||||
|
checkmarks.getToday(); // compute checkmarks
|
||||||
|
|
||||||
|
today = DateUtils.getStartOfToday();
|
||||||
|
day = DateUtils.millisecondsInOneDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdd()
|
||||||
|
{
|
||||||
|
checkmarks.invalidateNewerThan(0);
|
||||||
|
|
||||||
|
List<Checkmark> list = new LinkedList<>();
|
||||||
|
list.add(new Checkmark(habit, 0, 0));
|
||||||
|
list.add(new Checkmark(habit, 1, 1));
|
||||||
|
list.add(new Checkmark(habit, 2, 2));
|
||||||
|
|
||||||
|
checkmarks.add(list);
|
||||||
|
|
||||||
|
List<CheckmarkRecord> records = getAllRecords();
|
||||||
|
assertThat(records.size(), equalTo(3));
|
||||||
|
assertThat(records.get(0).timestamp, equalTo(2L));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetByInterval()
|
||||||
|
{
|
||||||
|
long from = today - 10 * day;
|
||||||
|
long to = today - 3 * day;
|
||||||
|
|
||||||
|
List<Checkmark> list = checkmarks.getByInterval(from, to);
|
||||||
|
assertThat(list.size(), equalTo(8));
|
||||||
|
|
||||||
|
assertThat(list.get(0).getTimestamp(), equalTo(today - 3 * day));
|
||||||
|
assertThat(list.get(3).getTimestamp(), equalTo(today - 6 * day));
|
||||||
|
assertThat(list.get(7).getTimestamp(), equalTo(today - 10 * day));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidateNewerThan()
|
||||||
|
{
|
||||||
|
List<CheckmarkRecord> records = getAllRecords();
|
||||||
|
assertThat(records.size(), equalTo(121));
|
||||||
|
|
||||||
|
checkmarks.invalidateNewerThan(today - 20 * day);
|
||||||
|
|
||||||
|
records = getAllRecords();
|
||||||
|
assertThat(records.size(), equalTo(100));
|
||||||
|
assertThat(records.get(0).timestamp, equalTo(today - 21 * day));
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<CheckmarkRecord> getAllRecords()
|
||||||
|
{
|
||||||
|
return new Select()
|
||||||
|
.from(CheckmarkRecord.class)
|
||||||
|
.where("habit = ?", habit.getId())
|
||||||
|
.orderBy("timestamp desc")
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,229 @@
|
|||||||
|
/*
|
||||||
|
* 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.models.sqlite;
|
||||||
|
|
||||||
|
import android.support.test.runner.*;
|
||||||
|
import android.test.suitebuilder.annotation.*;
|
||||||
|
|
||||||
|
import com.activeandroid.query.*;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.models.*;
|
||||||
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.junit.rules.*;
|
||||||
|
import org.junit.runner.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.*;
|
||||||
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
|
import static org.hamcrest.core.IsEqual.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("JavaDoc")
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@MediumTest
|
||||||
|
public class SQLiteHabitListTest extends BaseAndroidTest
|
||||||
|
{
|
||||||
|
@Rule
|
||||||
|
public ExpectedException exception = ExpectedException.none();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
fixtures.purgeHabits(habitList);
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
Habit h = new Habit();
|
||||||
|
h.setName("habit " + i);
|
||||||
|
h.setId((long) i);
|
||||||
|
if (i % 2 == 0) h.setArchived(1);
|
||||||
|
|
||||||
|
HabitRecord record = new HabitRecord();
|
||||||
|
record.copyFrom(h);
|
||||||
|
record.position = i;
|
||||||
|
record.save(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdd_withDuplicate()
|
||||||
|
{
|
||||||
|
Habit habit = new Habit();
|
||||||
|
habitList.add(habit);
|
||||||
|
exception.expect(IllegalArgumentException.class);
|
||||||
|
habitList.add(habit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdd_withId()
|
||||||
|
{
|
||||||
|
Habit habit = new Habit();
|
||||||
|
habit.setName("Hello world with id");
|
||||||
|
habit.setId(12300L);
|
||||||
|
|
||||||
|
habitList.add(habit);
|
||||||
|
assertThat(habit.getId(), equalTo(12300L));
|
||||||
|
|
||||||
|
HabitRecord record = getRecord(12300L);
|
||||||
|
assertNotNull(record);
|
||||||
|
assertThat(record.name, equalTo(habit.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdd_withoutId()
|
||||||
|
{
|
||||||
|
Habit habit = new Habit();
|
||||||
|
habit.setName("Hello world");
|
||||||
|
assertNull(habit.getId());
|
||||||
|
|
||||||
|
habitList.add(habit);
|
||||||
|
assertNotNull(habit.getId());
|
||||||
|
|
||||||
|
HabitRecord record = getRecord(habit.getId());
|
||||||
|
assertNotNull(record);
|
||||||
|
assertThat(record.name, equalTo(habit.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCountActive()
|
||||||
|
{
|
||||||
|
assertThat(habitList.countActive(), equalTo(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCountWithArchived()
|
||||||
|
{
|
||||||
|
assertThat(habitList.countWithArchived(), equalTo(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAll_withArchived()
|
||||||
|
{
|
||||||
|
List<Habit> habits = habitList.getAll(true);
|
||||||
|
assertThat(habits.size(), equalTo(10));
|
||||||
|
assertThat(habits.get(3).getName(), equalTo("habit 3"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAll_withoutArchived()
|
||||||
|
{
|
||||||
|
List<Habit> habits = habitList.getAll(false);
|
||||||
|
assertThat(habits.size(), equalTo(5));
|
||||||
|
assertThat(habits.get(3).getName(), equalTo("habit 7"));
|
||||||
|
|
||||||
|
List<Habit> another = habitList.getAll(false);
|
||||||
|
assertThat(habits, equalTo(another));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetById()
|
||||||
|
{
|
||||||
|
Habit h1 = habitList.getById(0);
|
||||||
|
assertNotNull(h1);
|
||||||
|
assertThat(h1.getName(), equalTo("habit 0"));
|
||||||
|
|
||||||
|
Habit h2 = habitList.getById(0);
|
||||||
|
assertNotNull(h2);
|
||||||
|
assertThat(h1, equalTo(h2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetById_withInvalid()
|
||||||
|
{
|
||||||
|
long invalidId = 9183792001L;
|
||||||
|
Habit h1 = habitList.getById(invalidId);
|
||||||
|
assertNull(h1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetByPosition()
|
||||||
|
{
|
||||||
|
Habit h = habitList.getByPosition(5);
|
||||||
|
assertNotNull(h);
|
||||||
|
assertThat(h.getName(), equalTo("habit 5"));
|
||||||
|
|
||||||
|
h = habitList.getByPosition(5000);
|
||||||
|
assertNull(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIndexOf()
|
||||||
|
{
|
||||||
|
Habit h1 = habitList.getByPosition(5);
|
||||||
|
assertNotNull(h1);
|
||||||
|
assertThat(habitList.indexOf(h1), equalTo(5));
|
||||||
|
|
||||||
|
Habit h2 = new Habit();
|
||||||
|
assertThat(habitList.indexOf(h2), equalTo(-1));
|
||||||
|
|
||||||
|
h2.setId(1000L);
|
||||||
|
assertThat(habitList.indexOf(h2), equalTo(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_reorder()
|
||||||
|
{
|
||||||
|
// Same as HabitListTest.java
|
||||||
|
// TODO: remove duplication
|
||||||
|
|
||||||
|
int operations[][] = {
|
||||||
|
{5, 2}, {3, 7}, {4, 4}, {3, 2}
|
||||||
|
};
|
||||||
|
|
||||||
|
int expectedPosition[][] = {
|
||||||
|
{0, 1, 3, 4, 5, 2, 6, 7, 8, 9},
|
||||||
|
{0, 1, 7, 3, 4, 2, 5, 6, 8, 9},
|
||||||
|
{0, 1, 7, 3, 4, 2, 5, 6, 8, 9},
|
||||||
|
{0, 1, 7, 2, 4, 3, 5, 6, 8, 9},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < operations.length; i++)
|
||||||
|
{
|
||||||
|
int from = operations[i][0];
|
||||||
|
int to = operations[i][1];
|
||||||
|
|
||||||
|
Habit fromHabit = habitList.getByPosition(from);
|
||||||
|
Habit toHabit = habitList.getByPosition(to);
|
||||||
|
habitList.reorder(fromHabit, toHabit);
|
||||||
|
|
||||||
|
int actualPositions[] = new int[10];
|
||||||
|
|
||||||
|
for (int j = 0; j < 10; j++)
|
||||||
|
{
|
||||||
|
Habit h = habitList.getById(j);
|
||||||
|
assertNotNull(h);
|
||||||
|
actualPositions[j] = habitList.indexOf(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
assertThat(actualPositions, equalTo(expectedPosition[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private HabitRecord getRecord(long id)
|
||||||
|
{
|
||||||
|
return new Select()
|
||||||
|
.from(HabitRecord.class)
|
||||||
|
.where("id = ?", id)
|
||||||
|
.executeSingle();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* 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.models.sqlite;
|
||||||
|
|
||||||
|
import android.support.annotation.*;
|
||||||
|
import android.support.test.runner.*;
|
||||||
|
import android.test.suitebuilder.annotation.*;
|
||||||
|
|
||||||
|
import com.activeandroid.query.*;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.models.*;
|
||||||
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.junit.runner.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
import static org.hamcrest.core.IsNot.not;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@MediumTest
|
||||||
|
public class SQLiteRepetitionListTest extends BaseAndroidTest
|
||||||
|
{
|
||||||
|
private Habit habit;
|
||||||
|
|
||||||
|
private long today;
|
||||||
|
|
||||||
|
private RepetitionList repetitions;
|
||||||
|
|
||||||
|
private long day;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
habit = fixtures.createLongHabit();
|
||||||
|
repetitions = habit.getRepetitions();
|
||||||
|
today = DateUtils.getStartOfToday();
|
||||||
|
day = DateUtils.millisecondsInOneDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdd()
|
||||||
|
{
|
||||||
|
RepetitionRecord record = getByTimestamp(today + day);
|
||||||
|
assertThat(record, is(nullValue()));
|
||||||
|
|
||||||
|
Repetition rep = new Repetition(habit, today + day);
|
||||||
|
habit.getRepetitions().add(rep);
|
||||||
|
|
||||||
|
record = getByTimestamp(today + day);
|
||||||
|
assertThat(record, is(not(nullValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetByInterval()
|
||||||
|
{
|
||||||
|
List<Repetition> reps =
|
||||||
|
repetitions.getByInterval(today - 10 * day, today);
|
||||||
|
|
||||||
|
assertThat(reps.size(), equalTo(8));
|
||||||
|
assertThat(reps.get(0).getTimestamp(), equalTo(today - 10 * day));
|
||||||
|
assertThat(reps.get(4).getTimestamp(), equalTo(today - 5 * day));
|
||||||
|
assertThat(reps.get(5).getTimestamp(), equalTo(today - 3 * day));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetByTimestamp()
|
||||||
|
{
|
||||||
|
Repetition rep = repetitions.getByTimestamp(today);
|
||||||
|
assertThat(rep, is(not(nullValue())));
|
||||||
|
assertThat(rep.getHabit(), equalTo(habit));
|
||||||
|
assertThat(rep.getTimestamp(), equalTo(today));
|
||||||
|
|
||||||
|
rep = repetitions.getByTimestamp(today - 2 * day);
|
||||||
|
assertThat(rep, is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetOldest()
|
||||||
|
{
|
||||||
|
Repetition rep = repetitions.getOldest();
|
||||||
|
assertThat(rep, is(not(nullValue())));
|
||||||
|
assertThat(rep.getHabit(), equalTo(habit));
|
||||||
|
assertThat(rep.getTimestamp(), equalTo(today - 120 * day));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetOldest_withEmptyHabit()
|
||||||
|
{
|
||||||
|
Habit empty = fixtures.createEmptyHabit();
|
||||||
|
Repetition rep = empty.getRepetitions().getOldest();
|
||||||
|
assertThat(rep, is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testRemove()
|
||||||
|
{
|
||||||
|
RepetitionRecord record = getByTimestamp(today);
|
||||||
|
assertThat(record, is(not(nullValue())));
|
||||||
|
|
||||||
|
Repetition rep = record.toRepetition();
|
||||||
|
repetitions.remove(rep);
|
||||||
|
|
||||||
|
record = getByTimestamp(today);
|
||||||
|
assertThat(record, is(nullValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private RepetitionRecord getByTimestamp(long timestamp)
|
||||||
|
{
|
||||||
|
return selectByTimestamp(timestamp).executeSingle();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private From selectByTimestamp(long timestamp)
|
||||||
|
{
|
||||||
|
return new Select()
|
||||||
|
.from(RepetitionRecord.class)
|
||||||
|
.where("habit = ?", habit.getId())
|
||||||
|
.and("timestamp = ?", timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* 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.models.sqlite;
|
||||||
|
|
||||||
|
import android.support.test.runner.*;
|
||||||
|
import android.test.suitebuilder.annotation.*;
|
||||||
|
|
||||||
|
import com.activeandroid.query.*;
|
||||||
|
|
||||||
|
import org.isoron.uhabits.*;
|
||||||
|
import org.isoron.uhabits.models.*;
|
||||||
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
|
import org.junit.*;
|
||||||
|
import org.junit.runner.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
import static junit.framework.Assert.assertNotNull;
|
||||||
|
import static junit.framework.Assert.assertNull;
|
||||||
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
|
@SuppressWarnings("JavaDoc")
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@MediumTest
|
||||||
|
public class SQLiteScoreListTest extends BaseAndroidTest
|
||||||
|
{
|
||||||
|
private Habit habit;
|
||||||
|
|
||||||
|
private ScoreList scores;
|
||||||
|
|
||||||
|
private long today;
|
||||||
|
|
||||||
|
private long day;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setUp()
|
||||||
|
{
|
||||||
|
super.setUp();
|
||||||
|
|
||||||
|
habit = fixtures.createLongHabit();
|
||||||
|
scores = habit.getScores();
|
||||||
|
|
||||||
|
today = DateUtils.getStartOfToday();
|
||||||
|
day = DateUtils.millisecondsInOneDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetAll()
|
||||||
|
{
|
||||||
|
List<Score> list = scores.getAll();
|
||||||
|
assertThat(list.size(), equalTo(121));
|
||||||
|
assertThat(list.get(0).getTimestamp(), equalTo(today));
|
||||||
|
assertThat(list.get(10).getTimestamp(), equalTo(today - 10 * day));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInvalidateNewerThan()
|
||||||
|
{
|
||||||
|
scores.getTodayValue(); // force recompute
|
||||||
|
List<ScoreRecord> records = getAllRecords();
|
||||||
|
assertThat(records.size(), equalTo(121));
|
||||||
|
|
||||||
|
scores.invalidateNewerThan(today - 10 * day);
|
||||||
|
|
||||||
|
records = getAllRecords();
|
||||||
|
assertThat(records.size(), equalTo(110));
|
||||||
|
assertThat(records.get(0).timestamp, equalTo(today - 11 * day));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAdd()
|
||||||
|
{
|
||||||
|
new Delete().from(ScoreRecord.class).execute();
|
||||||
|
|
||||||
|
List<Score> list = new LinkedList<>();
|
||||||
|
list.add(new Score(habit, today, 0));
|
||||||
|
list.add(new Score(habit, today - day, 0));
|
||||||
|
list.add(new Score(habit, today - 2 * day, 0));
|
||||||
|
|
||||||
|
scores.add(list);
|
||||||
|
|
||||||
|
List<ScoreRecord> records = getAllRecords();
|
||||||
|
assertThat(records.size(), equalTo(3));
|
||||||
|
assertThat(records.get(0).timestamp, equalTo(today));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetByTimestamp()
|
||||||
|
{
|
||||||
|
Score s = scores.getByTimestamp(today);
|
||||||
|
assertNotNull(s);
|
||||||
|
assertThat(s.getTimestamp(), equalTo(today));
|
||||||
|
|
||||||
|
s = scores.getByTimestamp(today - 200 * day);
|
||||||
|
assertNull(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<ScoreRecord> getAllRecords()
|
||||||
|
{
|
||||||
|
return new Select()
|
||||||
|
.from(ScoreRecord.class)
|
||||||
|
.where("habit = ?", habit.getId())
|
||||||
|
.orderBy("timestamp desc")
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ import android.support.test.espresso.NoMatchingViewException;
|
|||||||
import android.support.test.espresso.contrib.RecyclerViewActions;
|
import android.support.test.espresso.contrib.RecyclerViewActions;
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.sqlite.HabitRecord;
|
import org.isoron.uhabits.models.sqlite.records.HabitRecord;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import android.support.test.runner.AndroidJUnit4;
|
|||||||
import android.test.suitebuilder.annotation.LargeTest;
|
import android.test.suitebuilder.annotation.LargeTest;
|
||||||
|
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.R;
|
||||||
import org.isoron.uhabits.models.sqlite.HabitRecord;
|
import org.isoron.uhabits.models.sqlite.records.HabitRecord;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.DateUtils;
|
||||||
import org.isoron.uhabits.MainActivity;
|
import org.isoron.uhabits.MainActivity;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import android.test.suitebuilder.annotation.SmallTest;
|
|||||||
import org.isoron.uhabits.BaseAndroidTest;
|
import org.isoron.uhabits.BaseAndroidTest;
|
||||||
import org.isoron.uhabits.commands.ArchiveHabitsCommand;
|
import org.isoron.uhabits.commands.ArchiveHabitsCommand;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.unit.HabitFixtures;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -48,7 +47,7 @@ public class ArchiveHabitsCommandTest extends BaseAndroidTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habit = habitFixtures.createShortHabit();
|
habit = fixtures.createShortHabit();
|
||||||
command = new ArchiveHabitsCommand(Collections.singletonList(habit));
|
command = new ArchiveHabitsCommand(Collections.singletonList(habit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import android.test.suitebuilder.annotation.SmallTest;
|
|||||||
import org.isoron.uhabits.BaseAndroidTest;
|
import org.isoron.uhabits.BaseAndroidTest;
|
||||||
import org.isoron.uhabits.commands.ChangeHabitColorCommand;
|
import org.isoron.uhabits.commands.ChangeHabitColorCommand;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.unit.HabitFixtures;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
@@ -51,7 +50,7 @@ public class ChangeHabitColorCommandTest extends BaseAndroidTest
|
|||||||
|
|
||||||
for(int i = 0; i < 3; i ++)
|
for(int i = 0; i < 3; i ++)
|
||||||
{
|
{
|
||||||
Habit habit = habitFixtures.createShortHabit();
|
Habit habit = fixtures.createShortHabit();
|
||||||
habit.setColor(i + 1);
|
habit.setColor(i + 1);
|
||||||
habits.add(habit);
|
habits.add(habit);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import android.support.test.runner.AndroidJUnit4;
|
|||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
|
|
||||||
import org.isoron.uhabits.BaseAndroidTest;
|
import org.isoron.uhabits.BaseAndroidTest;
|
||||||
import org.isoron.uhabits.HabitsApplication;
|
|
||||||
import org.isoron.uhabits.commands.CreateHabitCommand;
|
import org.isoron.uhabits.commands.CreateHabitCommand;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -54,7 +53,7 @@ public class CreateHabitCommandTest extends BaseAndroidTest
|
|||||||
model.setName("New habit");
|
model.setName("New habit");
|
||||||
command = new CreateHabitCommand(model);
|
command = new CreateHabitCommand(model);
|
||||||
|
|
||||||
habitFixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -19,22 +19,20 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.unit.commands;
|
package org.isoron.uhabits.unit.commands;
|
||||||
|
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.*;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.BaseAndroidTest;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.commands.DeleteHabitsCommand;
|
import org.isoron.uhabits.commands.*;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.junit.Before;
|
import org.junit.*;
|
||||||
import org.junit.Rule;
|
import org.junit.rules.*;
|
||||||
import org.junit.Test;
|
import org.junit.runner.*;
|
||||||
import org.junit.rules.ExpectedException;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.*;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
@@ -53,18 +51,18 @@ public class DeleteHabitsCommandTest extends BaseAndroidTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habitFixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
habits = new LinkedList<>();
|
habits = new LinkedList<>();
|
||||||
|
|
||||||
// Habits that should be deleted
|
// Habits that should be deleted
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
Habit habit = habitFixtures.createShortHabit();
|
Habit habit = fixtures.createShortHabit();
|
||||||
habits.add(habit);
|
habits.add(habit);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extra habit that should not be deleted
|
// Extra habit that should not be deleted
|
||||||
Habit extraHabit = habitFixtures.createShortHabit();
|
Habit extraHabit = fixtures.createShortHabit();
|
||||||
extraHabit.setName("extra");
|
extraHabit.setName("extra");
|
||||||
|
|
||||||
command = new DeleteHabitsCommand(habits);
|
command = new DeleteHabitsCommand(habits);
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class EditHabitCommandTest extends BaseAndroidTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habit = habitFixtures.createShortHabit();
|
habit = fixtures.createShortHabit();
|
||||||
habit.setName("original");
|
habit.setName("original");
|
||||||
habit.setFreqDen(1);
|
habit.setFreqDen(1);
|
||||||
habit.setFreqNum(1);
|
habit.setFreqNum(1);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class ToggleRepetitionCommandTest extends BaseAndroidTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habit = habitFixtures.createShortHabit();
|
habit = fixtures.createShortHabit();
|
||||||
|
|
||||||
today = DateUtils.getStartOfToday();
|
today = DateUtils.getStartOfToday();
|
||||||
command = new ToggleRepetitionCommand(habit, today);
|
command = new ToggleRepetitionCommand(habit, today);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class UnarchiveHabitsCommandTest extends BaseAndroidTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habit = habitFixtures.createShortHabit();
|
habit = fixtures.createShortHabit();
|
||||||
habit.setArchived(1);
|
habit.setArchived(1);
|
||||||
habitList.update(habit);
|
habitList.update(habit);
|
||||||
|
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ public class HabitsCSVExporterTest extends BaseAndroidTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habitFixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
habitFixtures.createShortHabit();
|
fixtures.createShortHabit();
|
||||||
habitFixtures.createEmptyHabit();
|
fixtures.createEmptyHabit();
|
||||||
|
|
||||||
Context targetContext = InstrumentationRegistry.getTargetContext();
|
Context targetContext = InstrumentationRegistry.getTargetContext();
|
||||||
baseDir = targetContext.getCacheDir();
|
baseDir = targetContext.getCacheDir();
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public class ImportTest extends BaseAndroidTest
|
|||||||
super.setUp();
|
super.setUp();
|
||||||
DateUtils.setFixedLocalTime(null);
|
DateUtils.setFixedLocalTime(null);
|
||||||
|
|
||||||
habitFixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
context = InstrumentationRegistry.getInstrumentation().getContext();
|
context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||||
baseDir = FileUtils.getFilesDir("Backups");
|
baseDir = FileUtils.getFilesDir("Backups");
|
||||||
if(baseDir == null) fail("baseDir should not be null");
|
if(baseDir == null) fail("baseDir should not be null");
|
||||||
|
|||||||
@@ -1,33 +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.unit.models;
|
|
||||||
|
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.BaseAndroidTest;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
|
||||||
@SmallTest
|
|
||||||
public class ScoreListTest extends BaseAndroidTest
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -19,24 +19,21 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.unit.tasks;
|
package org.isoron.uhabits.unit.tasks;
|
||||||
|
|
||||||
import android.support.test.runner.AndroidJUnit4;
|
import android.support.test.runner.*;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.BaseAndroidTest;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.tasks.ExportCSVTask;
|
import org.isoron.uhabits.tasks.*;
|
||||||
import org.isoron.uhabits.unit.HabitFixtures;
|
import org.junit.*;
|
||||||
import org.junit.Before;
|
import org.junit.runner.*;
|
||||||
import org.junit.Test;
|
|
||||||
import org.junit.runner.RunWith;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertTrue;
|
import static junit.framework.Assert.*;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.hamcrest.Matchers.nullValue;
|
|
||||||
import static org.hamcrest.core.IsNot.not;
|
import static org.hamcrest.core.IsNot.not;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -52,7 +49,7 @@ public class ExportCSVTaskTest extends BaseAndroidTest
|
|||||||
@Test
|
@Test
|
||||||
public void testExportCSV() throws Throwable
|
public void testExportCSV() throws Throwable
|
||||||
{
|
{
|
||||||
habitFixtures.createShortHabit();
|
fixtures.createShortHabit();
|
||||||
List<Habit> habits = habitList.getAll(true);
|
List<Habit> habits = habitList.getAll(true);
|
||||||
|
|
||||||
ExportCSVTask task = new ExportCSVTask(habits, null);
|
ExportCSVTask task = new ExportCSVTask(habits, null);
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public class CheckmarkWidgetViewTest extends ViewTest
|
|||||||
super.setUp();
|
super.setUp();
|
||||||
InterfaceUtils.setFixedTheme(R.style.TransparentWidgetTheme);
|
InterfaceUtils.setFixedTheme(R.style.TransparentWidgetTheme);
|
||||||
|
|
||||||
habit = habitFixtures.createShortHabit();
|
habit = fixtures.createShortHabit();
|
||||||
view = new CheckmarkWidgetView(targetContext);
|
view = new CheckmarkWidgetView(targetContext);
|
||||||
view.setHabit(habit);
|
view.setHabit(habit);
|
||||||
refreshData(view);
|
refreshData(view);
|
||||||
|
|||||||
@@ -39,8 +39,8 @@ public class HabitFrequencyViewTest extends ViewTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habitFixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
Habit habit = habitFixtures.createLongHabit();
|
Habit habit = fixtures.createLongHabit();
|
||||||
|
|
||||||
view = new HabitFrequencyView(targetContext);
|
view = new HabitFrequencyView(targetContext);
|
||||||
view.setHabit(habit);
|
view.setHabit(habit);
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ public class HabitHistoryViewTest extends ViewTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habitFixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
habit = habitFixtures.createLongHabit();
|
habit = fixtures.createLongHabit();
|
||||||
|
|
||||||
view = new HabitHistoryView(targetContext);
|
view = new HabitHistoryView(targetContext);
|
||||||
view.setHabit(habit);
|
view.setHabit(habit);
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ public class HabitScoreViewTest extends ViewTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habitFixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
habit = habitFixtures.createLongHabit();
|
habit = fixtures.createLongHabit();
|
||||||
|
|
||||||
view = new HabitScoreView(targetContext);
|
view = new HabitScoreView(targetContext);
|
||||||
view.setHabit(habit);
|
view.setHabit(habit);
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ public class HabitStreakViewTest extends ViewTest
|
|||||||
{
|
{
|
||||||
super.setUp();
|
super.setUp();
|
||||||
|
|
||||||
habitFixtures.purgeHabits(habitList);
|
fixtures.purgeHabits(habitList);
|
||||||
Habit habit = habitFixtures.createLongHabit();
|
Habit habit = fixtures.createLongHabit();
|
||||||
|
|
||||||
view = new HabitStreakView(targetContext);
|
view = new HabitStreakView(targetContext);
|
||||||
measureView(dpToPixels(300), dpToPixels(100), view);
|
measureView(dpToPixels(300), dpToPixels(100), view);
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Checkmark represents the completion status of the habit for a given day.
|
* A Checkmark represents the completion status of the habit for a given day.
|
||||||
@@ -62,6 +62,11 @@ public class Checkmark
|
|||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int compareNewer(Checkmark other)
|
||||||
|
{
|
||||||
|
return Long.signum(this.getTimestamp() - other.getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
public Habit getHabit()
|
public Habit getHabit()
|
||||||
{
|
{
|
||||||
return habit;
|
return habit;
|
||||||
|
|||||||
@@ -19,16 +19,13 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.Writer;
|
import java.text.*;
|
||||||
import java.text.SimpleDateFormat;
|
import java.util.*;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The collection of {@link Checkmark}s belonging to a habit.
|
* The collection of {@link Checkmark}s belonging to a habit.
|
||||||
@@ -45,19 +42,29 @@ public abstract class CheckmarkList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the values for all the checkmarks, since the oldest repetition of
|
* Adds all the given checkmarks to the list.
|
||||||
* the habit until today. If there are no repetitions at all, returns an
|
|
||||||
* empty array.
|
|
||||||
* <p>
|
* <p>
|
||||||
* The values are returned in an array containing one integer value for each
|
* This should never be called by the application, since the checkmarks are
|
||||||
* day since the first repetition of the habit until today. The first entry
|
* computed automatically from the list of repetitions.
|
||||||
|
*
|
||||||
|
* @param checkmarks the checkmarks to be added.
|
||||||
|
*/
|
||||||
|
public abstract void add(List<Checkmark> checkmarks);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the values for all the checkmarks, since the oldest repetition of
|
||||||
|
* the habit until today.
|
||||||
|
* <p>
|
||||||
|
* If there are no repetitions at all, returns an empty array. The values
|
||||||
|
* are returned in an array containing one integer value for each day since
|
||||||
|
* the first repetition of the habit until today. The first entry
|
||||||
* corresponds to today, the second entry corresponds to yesterday, and so
|
* corresponds to today, the second entry corresponds to yesterday, and so
|
||||||
* on.
|
* on.
|
||||||
*
|
*
|
||||||
* @return values for the checkmarks in the interval
|
* @return values for the checkmarks in the interval
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public int[] getAllValues()
|
public final int[] getAllValues()
|
||||||
{
|
{
|
||||||
Repetition oldestRep = habit.getRepetitions().getOldest();
|
Repetition oldestRep = habit.getRepetitions().getOldest();
|
||||||
if (oldestRep == null) return new int[0];
|
if (oldestRep == null) return new int[0];
|
||||||
@@ -68,17 +75,32 @@ public abstract class CheckmarkList
|
|||||||
return getValues(fromTimestamp, toTimestamp);
|
return getValues(fromTimestamp, toTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the list of checkmarks that fall within the given interval.
|
||||||
|
* <p>
|
||||||
|
* There is exactly one checkmark per day in the interval. The endpoints of
|
||||||
|
* the interval are included. The list is ordered by timestamp (decreasing).
|
||||||
|
* That is, the first checkmark corresponds to the newest timestamp, and the
|
||||||
|
* last checkmark corresponds to the oldest timestamp.
|
||||||
|
*
|
||||||
|
* @param fromTimestamp timestamp of the beginning of the interval.
|
||||||
|
* @param toTimestamp timestamp of the end of the interval.
|
||||||
|
* @return the list of checkmarks within the interval.
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public abstract List<Checkmark> getByInterval(long fromTimestamp,
|
||||||
|
long toTimestamp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the checkmark for today.
|
* Returns the checkmark for today.
|
||||||
*
|
*
|
||||||
* @return checkmark for today
|
* @return checkmark for today
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public Checkmark getToday()
|
public final Checkmark getToday()
|
||||||
{
|
{
|
||||||
long today = DateUtils.getStartOfToday();
|
computeAll();
|
||||||
compute(today, today);
|
return getNewestComputed();
|
||||||
return getNewest();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -86,7 +108,7 @@ public abstract class CheckmarkList
|
|||||||
*
|
*
|
||||||
* @return value of today's checkmark
|
* @return value of today's checkmark
|
||||||
*/
|
*/
|
||||||
public int getTodayValue()
|
public final int getTodayValue()
|
||||||
{
|
{
|
||||||
Checkmark today = getToday();
|
Checkmark today = getToday();
|
||||||
if (today != null) return today.getValue();
|
if (today != null) return today.getValue();
|
||||||
@@ -106,7 +128,17 @@ public abstract class CheckmarkList
|
|||||||
* @param to timestamp for the newest checkmark
|
* @param to timestamp for the newest checkmark
|
||||||
* @return values for the checkmarks inside the given interval
|
* @return values for the checkmarks inside the given interval
|
||||||
*/
|
*/
|
||||||
public abstract int[] getValues(long from, long to);
|
public final int[] getValues(long from, long to)
|
||||||
|
{
|
||||||
|
List<Checkmark> checkmarks = getByInterval(from, to);
|
||||||
|
int values[] = new int[checkmarks.size()];
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (Checkmark c : checkmarks)
|
||||||
|
values[i++] = c.getValue();
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Marks as invalid every checkmark that has timestamp either equal or newer
|
* Marks as invalid every checkmark that has timestamp either equal or newer
|
||||||
@@ -119,13 +151,11 @@ public abstract class CheckmarkList
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes the entire list of checkmarks to the given writer, in CSV format.
|
* Writes the entire list of checkmarks to the given writer, in CSV format.
|
||||||
* There is one line for each checkmark. Each line contains two fields:
|
|
||||||
* timestamp and value.
|
|
||||||
*
|
*
|
||||||
* @param out the writer where the CSV will be output
|
* @param out the writer where the CSV will be output
|
||||||
* @throws IOException in case write operations fail
|
* @throws IOException in case write operations fail
|
||||||
*/
|
*/
|
||||||
public void writeCSV(Writer out) throws IOException
|
public final void writeCSV(Writer out) throws IOException
|
||||||
{
|
{
|
||||||
computeAll();
|
computeAll();
|
||||||
|
|
||||||
@@ -149,11 +179,11 @@ public abstract class CheckmarkList
|
|||||||
* @param from timestamp for the beginning of the interval
|
* @param from timestamp for the beginning of the interval
|
||||||
* @param to timestamp for the end of the interval
|
* @param to timestamp for the end of the interval
|
||||||
*/
|
*/
|
||||||
protected void compute(long from, final long to)
|
protected final void compute(long from, final long to)
|
||||||
{
|
{
|
||||||
final long day = DateUtils.millisecondsInOneDay;
|
final long day = DateUtils.millisecondsInOneDay;
|
||||||
|
|
||||||
Checkmark newestCheckmark = getNewest();
|
Checkmark newestCheckmark = getNewestComputed();
|
||||||
if (newestCheckmark != null)
|
if (newestCheckmark != null)
|
||||||
from = newestCheckmark.getTimestamp() + day;
|
from = newestCheckmark.getTimestamp() + day;
|
||||||
|
|
||||||
@@ -185,12 +215,16 @@ public abstract class CheckmarkList
|
|||||||
checks[i] = Checkmark.CHECKED_IMPLICITLY;
|
checks[i] = Checkmark.CHECKED_IMPLICITLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Checkmark> checkmarks = new LinkedList<>();
|
||||||
|
|
||||||
long timestamps[] = new long[nDays];
|
|
||||||
for (int i = 0; i < nDays; i++)
|
for (int i = 0; i < nDays; i++)
|
||||||
timestamps[i] = to - i * day;
|
{
|
||||||
|
int value = checks[i];
|
||||||
|
long timestamp = to - i * day;
|
||||||
|
checkmarks.add(new Checkmark(habit, timestamp, value));
|
||||||
|
}
|
||||||
|
|
||||||
insert(timestamps, checks);
|
add(checkmarks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -198,24 +232,21 @@ public abstract class CheckmarkList
|
|||||||
* repetition until today. Days that already have a corresponding checkmark
|
* repetition until today. Days that already have a corresponding checkmark
|
||||||
* are skipped.
|
* are skipped.
|
||||||
*/
|
*/
|
||||||
protected void computeAll()
|
protected final void computeAll()
|
||||||
{
|
{
|
||||||
Repetition oldest = habit.getRepetitions().getOldest();
|
Repetition oldest = habit.getRepetitions().getOldest();
|
||||||
if (oldest == null) return;
|
if (oldest == null) return;
|
||||||
|
|
||||||
Long today = DateUtils.getStartOfToday();
|
Long today = DateUtils.getStartOfToday();
|
||||||
|
|
||||||
compute(oldest.getTimestamp(), today);
|
compute(oldest.getTimestamp(), today);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns newest checkmark that has already been computed. Ignores any
|
* Returns newest checkmark that has already been computed.
|
||||||
* checkmark that has timestamp in the future. This does not update the
|
* <p>
|
||||||
* cache.
|
* Ignores any checkmark that has timestamp in the future.
|
||||||
*
|
*
|
||||||
* @return newest checkmark already computed
|
* @return newest checkmark already computed
|
||||||
*/
|
*/
|
||||||
protected abstract Checkmark getNewest();
|
protected abstract Checkmark getNewestComputed();
|
||||||
|
|
||||||
protected abstract void insert(long timestamps[], int values[]);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,17 +19,16 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import android.net.Uri;
|
import android.net.*;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.*;
|
||||||
import org.isoron.uhabits.HabitsApplication;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.*;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The thing that the user wants to track.
|
* The thing that the user wants to track.
|
||||||
@@ -105,7 +104,7 @@ public class Habit
|
|||||||
checkmarks = factory.buildCheckmarkList(this);
|
checkmarks = factory.buildCheckmarkList(this);
|
||||||
streaks = factory.buildStreakList(this);
|
streaks = factory.buildStreakList(this);
|
||||||
scores = factory.buildScoreList(this);
|
scores = factory.buildScoreList(this);
|
||||||
repetitions = factory.buidRepetitionList(this);
|
repetitions = factory.buildRepetitionList(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -128,7 +127,7 @@ public class Habit
|
|||||||
checkmarks = factory.buildCheckmarkList(this);
|
checkmarks = factory.buildCheckmarkList(this);
|
||||||
streaks = factory.buildStreakList(this);
|
streaks = factory.buildStreakList(this);
|
||||||
scores = factory.buildScoreList(this);
|
scores = factory.buildScoreList(this);
|
||||||
repetitions = factory.buidRepetitionList(this);
|
repetitions = factory.buildRepetitionList(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -235,7 +234,7 @@ public class Habit
|
|||||||
return freqNum;
|
return freqNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFreqNum(Integer freqNum)
|
public void setFreqNum(@NonNull Integer freqNum)
|
||||||
{
|
{
|
||||||
this.freqNum = freqNum;
|
this.freqNum = freqNum;
|
||||||
}
|
}
|
||||||
@@ -243,16 +242,18 @@ public class Habit
|
|||||||
/**
|
/**
|
||||||
* Not currently used.
|
* Not currently used.
|
||||||
*/
|
*/
|
||||||
|
@NonNull
|
||||||
public Integer getHighlight()
|
public Integer getHighlight()
|
||||||
{
|
{
|
||||||
return highlight;
|
return highlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHighlight(Integer highlight)
|
public void setHighlight(@NonNull Integer highlight)
|
||||||
{
|
{
|
||||||
this.highlight = highlight;
|
this.highlight = highlight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
public Long getId()
|
public Long getId()
|
||||||
{
|
{
|
||||||
return id;
|
return id;
|
||||||
@@ -387,7 +388,7 @@ public class Habit
|
|||||||
return archived != 0;
|
return archived != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setArchived(Integer archived)
|
public void setArchived(@NonNull Integer archived)
|
||||||
{
|
{
|
||||||
this.archived = archived;
|
this.archived = archived;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,18 +19,14 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.opencsv.CSVWriter;
|
import com.opencsv.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.utils.ColorUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.Writer;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An ordered collection of {@link Habit}s.
|
* An ordered collection of {@link Habit}s.
|
||||||
@@ -43,7 +39,8 @@ public abstract class HabitList
|
|||||||
* Creates a new HabitList.
|
* Creates a new HabitList.
|
||||||
* <p>
|
* <p>
|
||||||
* Depending on the implementation, this list can either be empty or be
|
* Depending on the implementation, this list can either be empty or be
|
||||||
* populated by some pre-existing habits.
|
* populated by some pre-existing habits, for example, from a certain
|
||||||
|
* database.
|
||||||
*/
|
*/
|
||||||
public HabitList()
|
public HabitList()
|
||||||
{
|
{
|
||||||
@@ -52,17 +49,24 @@ public abstract class HabitList
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a new habit in the list.
|
* Inserts a new habit in the list.
|
||||||
|
* <p>
|
||||||
|
* If the id of the habit is null, the list will assign it a new id, which
|
||||||
|
* is guaranteed to be unique in the scope of the list. If id is not null,
|
||||||
|
* the caller should make sure that the list does not already contain
|
||||||
|
* another habit with same id, otherwise a RuntimeException will be thrown.
|
||||||
*
|
*
|
||||||
* @param habit the habit to be inserted
|
* @param habit the habit to be inserted
|
||||||
|
* @throws IllegalArgumentException if the habit is already on the list.
|
||||||
*/
|
*/
|
||||||
public abstract void add(@NonNull Habit habit);
|
public abstract void add(@NonNull Habit habit)
|
||||||
|
throws IllegalArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total number of unarchived habits.
|
* Returns the total number of active habits.
|
||||||
*
|
*
|
||||||
* @return number of unarchived habits
|
* @return number of active habits
|
||||||
*/
|
*/
|
||||||
public abstract int count();
|
public abstract int countActive();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total number of habits, including archived habits.
|
* Returns the total number of habits, including archived habits.
|
||||||
|
|||||||
@@ -20,17 +20,17 @@
|
|||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface implemented by factories that provide concrete implementations
|
* Interface implemented by factories that provide concrete implementations of
|
||||||
* of the core model classes.
|
* the core model classes.
|
||||||
*/
|
*/
|
||||||
public interface ModelFactory
|
public interface ModelFactory
|
||||||
{
|
{
|
||||||
RepetitionList buidRepetitionList(Habit habit);
|
RepetitionList buildRepetitionList(Habit habit);
|
||||||
|
|
||||||
HabitList buildHabitList();
|
|
||||||
|
|
||||||
CheckmarkList buildCheckmarkList(Habit habit);
|
CheckmarkList buildCheckmarkList(Habit habit);
|
||||||
|
|
||||||
|
HabitList buildHabitList();
|
||||||
|
|
||||||
ScoreList buildScoreList(Habit habit);
|
ScoreList buildScoreList(Habit habit);
|
||||||
|
|
||||||
StreakList buildStreakList(Habit habit);
|
StreakList buildStreakList(Habit habit);
|
||||||
|
|||||||
@@ -19,8 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A ModelObservable allows objects to subscribe themselves to it and receive
|
* A ModelObservable allows objects to subscribe themselves to it and receive
|
||||||
|
|||||||
@@ -19,9 +19,9 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a record that the user has performed a certain habit at a certain
|
* Represents a record that the user has performed a certain habit at a certain
|
||||||
|
|||||||
@@ -19,15 +19,12 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.models.*;
|
||||||
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.Calendar;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The collection of {@link Repetition}s belonging to a habit.
|
* The collection of {@link Repetition}s belonging to a habit.
|
||||||
@@ -72,15 +69,16 @@ public abstract class RepetitionList
|
|||||||
/**
|
/**
|
||||||
* Returns the list of repetitions that happened within the given time
|
* Returns the list of repetitions that happened within the given time
|
||||||
* interval.
|
* interval.
|
||||||
*
|
* <p>
|
||||||
* The list is sorted by timestamp in decreasing order. That is, the first
|
* The list is sorted by timestamp in increasing order. That is, the first
|
||||||
* element corresponds to the most recent timestamp. The endpoints of the
|
* element corresponds to oldest timestamp, while the last element
|
||||||
* interval are included.
|
* corresponds to the newest. The endpoints of the interval are included.
|
||||||
*
|
*
|
||||||
* @param fromTimestamp timestamp of the beginning of the interval
|
* @param fromTimestamp timestamp of the beginning of the interval
|
||||||
* @param toTimestamp timestamp of the end of the interval
|
* @param toTimestamp timestamp of the end of the interval
|
||||||
* @return list of repetitions within given time interval
|
* @return list of repetitions within given time interval
|
||||||
*/
|
*/
|
||||||
|
// TODO: Change order timestamp desc
|
||||||
public abstract List<Repetition> getByInterval(long fromTimestamp,
|
public abstract List<Repetition> getByInterval(long fromTimestamp,
|
||||||
long toTimestamp);
|
long toTimestamp);
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,18 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents how strong a habit is at a certain date.
|
* Represents how strong a habit is at a certain date.
|
||||||
*/
|
*/
|
||||||
public class Score
|
public class Score
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Maximum score value attainable by any habit.
|
||||||
|
*/
|
||||||
|
public static final int MAX_VALUE = 19259478;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Habit to which this score belongs to.
|
* Habit to which this score belongs to.
|
||||||
*/
|
*/
|
||||||
@@ -42,11 +47,6 @@ public class Score
|
|||||||
*/
|
*/
|
||||||
private final Integer value;
|
private final Integer value;
|
||||||
|
|
||||||
/**
|
|
||||||
* Maximum score value attainable by any habit.
|
|
||||||
*/
|
|
||||||
public static final int MAX_VALUE = 19259478;
|
|
||||||
|
|
||||||
public Score(Habit habit, Long timestamp, Integer value)
|
public Score(Habit habit, Long timestamp, Integer value)
|
||||||
{
|
{
|
||||||
this.habit = habit;
|
this.habit = habit;
|
||||||
|
|||||||
@@ -19,21 +19,15 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.Writer;
|
import java.text.*;
|
||||||
import java.text.SimpleDateFormat;
|
import java.util.*;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public abstract class ScoreList
|
public abstract class ScoreList implements Iterable<Score>
|
||||||
{
|
{
|
||||||
protected final Habit habit;
|
protected final Habit habit;
|
||||||
|
|
||||||
@@ -53,8 +47,29 @@ public abstract class ScoreList
|
|||||||
observable = new ModelObservable();
|
observable = new ModelObservable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given scores to the list.
|
||||||
|
* <p>
|
||||||
|
* This method should not be called by the application, since the scores are
|
||||||
|
* computed automatically from the list of repetitions.
|
||||||
|
*
|
||||||
|
* @param scores the scores to add.
|
||||||
|
*/
|
||||||
|
public abstract void add(List<Score> scores);
|
||||||
|
|
||||||
public abstract List<Score> getAll();
|
public abstract List<Score> getAll();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the score that has the given timestamp.
|
||||||
|
* <p>
|
||||||
|
* If no such score exists, returns null.
|
||||||
|
*
|
||||||
|
* @param timestamp the timestamp to find.
|
||||||
|
* @return the score with given timestamp, or null if none exists.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public abstract Score getByTimestamp(long timestamp);
|
||||||
|
|
||||||
public ModelObservable getObservable()
|
public ModelObservable getObservable()
|
||||||
{
|
{
|
||||||
return observable;
|
return observable;
|
||||||
@@ -72,11 +87,20 @@ public abstract class ScoreList
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the score for a given day.
|
* Returns the value of the score for a given day.
|
||||||
|
* <p>
|
||||||
|
* If there is no score at the given timestamp (for example, if the
|
||||||
|
* timestamp given happens before the first repetition of the habit) then
|
||||||
|
* returns zero.
|
||||||
*
|
*
|
||||||
* @param timestamp the timestamp of a day
|
* @param timestamp the timestamp of a day
|
||||||
* @return score for that day
|
* @return score value for that day
|
||||||
*/
|
*/
|
||||||
public abstract int getValue(long timestamp);
|
public final int getValue(long timestamp)
|
||||||
|
{
|
||||||
|
Score s = getByTimestamp(timestamp);
|
||||||
|
if (s != null) return s.getValue();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public List<Score> groupBy(DateUtils.TruncateField field)
|
public List<Score> groupBy(DateUtils.TruncateField field)
|
||||||
{
|
{
|
||||||
@@ -95,12 +119,18 @@ public abstract class ScoreList
|
|||||||
*/
|
*/
|
||||||
public abstract void invalidateNewerThan(long timestamp);
|
public abstract void invalidateNewerThan(long timestamp);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterator<Score> iterator()
|
||||||
|
{
|
||||||
|
return getAll().iterator();
|
||||||
|
}
|
||||||
|
|
||||||
public void writeCSV(Writer out) throws IOException
|
public void writeCSV(Writer out) throws IOException
|
||||||
{
|
{
|
||||||
computeAll();
|
computeAll();
|
||||||
SimpleDateFormat dateFormat = DateUtils.getCSVDateFormat();
|
SimpleDateFormat dateFormat = DateUtils.getCSVDateFormat();
|
||||||
|
|
||||||
for (Score s : getAll())
|
for (Score s : this)
|
||||||
{
|
{
|
||||||
String timestamp = dateFormat.format(s.getTimestamp());
|
String timestamp = dateFormat.format(s.getTimestamp());
|
||||||
String score =
|
String score =
|
||||||
@@ -109,8 +139,6 @@ public abstract class ScoreList
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void add(List<Score> scores);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes and saves the scores that are missing inside a given time
|
* Computes and saves the scores that are missing inside a given time
|
||||||
* interval.
|
* interval.
|
||||||
@@ -173,20 +201,21 @@ public abstract class ScoreList
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the score for a certain day.
|
* Returns the most recent score that has already been computed.
|
||||||
|
* <p>
|
||||||
|
* If no score has been computed yet, returns null.
|
||||||
*
|
*
|
||||||
* @param timestamp the timestamp for the day
|
* @return the newest score computed, or null if none exist
|
||||||
* @return the score for the day
|
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
protected abstract Score get(long timestamp);
|
protected abstract Score getNewestComputed();
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private HashMap<Long, ArrayList<Long>> getGroupedValues(DateUtils.TruncateField field)
|
private HashMap<Long, ArrayList<Long>> getGroupedValues(DateUtils.TruncateField field)
|
||||||
{
|
{
|
||||||
HashMap<Long, ArrayList<Long>> groups = new HashMap<>();
|
HashMap<Long, ArrayList<Long>> groups = new HashMap<>();
|
||||||
|
|
||||||
for (Score s : getAll())
|
for (Score s : this)
|
||||||
{
|
{
|
||||||
long groupTimestamp = DateUtils.truncate(field, s.getTimestamp());
|
long groupTimestamp = DateUtils.truncate(field, s.getTimestamp());
|
||||||
|
|
||||||
@@ -199,17 +228,6 @@ public abstract class ScoreList
|
|||||||
return groups;
|
return groups;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the most recent score that has already been computed.
|
|
||||||
* <p>
|
|
||||||
* If no score has been computed yet, returns null.
|
|
||||||
*
|
|
||||||
* @return the newest score computed, or null if none exist
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
protected abstract Score getNewestComputed();
|
|
||||||
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private List<Score> groupsToAvgScores(HashMap<Long, ArrayList<Long>> groups)
|
private List<Score> groupsToAvgScores(HashMap<Long, ArrayList<Long>> groups)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
import org.apache.commons.lang3.builder.*;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
public class Streak
|
public class Streak
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,15 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The collection of {@link Streak}s that belong to a habit.
|
* The collection of {@link Streak}s that belong to a habit.
|
||||||
@@ -80,7 +76,7 @@ public abstract class StreakList
|
|||||||
List<Streak> streaks = checkmarksToStreaks(beginning, checks);
|
List<Streak> streaks = checkmarksToStreaks(beginning, checks);
|
||||||
|
|
||||||
removeNewestComputed();
|
removeNewestComputed();
|
||||||
insert(streaks);
|
add(streaks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -155,7 +151,7 @@ public abstract class StreakList
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void insert(@NonNull List<Streak> streaks);
|
protected abstract void add(@NonNull List<Streak> streaks);
|
||||||
|
|
||||||
protected abstract void removeNewestComputed();
|
protected abstract void removeNewestComputed();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.memory;
|
package org.isoron.uhabits.models.memory;
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Checkmark;
|
import android.support.annotation.*;
|
||||||
import org.isoron.uhabits.models.CheckmarkList;
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import org.isoron.uhabits.models.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In-memory implementation of {@link CheckmarkList}.
|
* In-memory implementation of {@link CheckmarkList}.
|
||||||
@@ -41,20 +39,25 @@ public class MemoryCheckmarkList extends CheckmarkList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[] getValues(long from, long to)
|
public void add(List<Checkmark> checkmarks)
|
||||||
{
|
{
|
||||||
compute(from, to);
|
list.addAll(checkmarks);
|
||||||
if (from > to) return new int[0];
|
Collections.sort(list, (c1, c2) -> c2.compareNewer(c1));
|
||||||
|
}
|
||||||
|
|
||||||
int length = (int) ((to - from) / DateUtils.millisecondsInOneDay + 1);
|
@NonNull
|
||||||
int values[] = new int[length];
|
@Override
|
||||||
|
public List<Checkmark> getByInterval(long fromTimestamp, long toTimestamp)
|
||||||
|
{
|
||||||
|
compute(fromTimestamp, toTimestamp);
|
||||||
|
|
||||||
|
List<Checkmark> filtered = new LinkedList<>();
|
||||||
|
|
||||||
int k = 0;
|
|
||||||
for (Checkmark c : list)
|
for (Checkmark c : list)
|
||||||
if(c.getTimestamp() >= from && c.getTimestamp() <= to)
|
if (c.getTimestamp() >= fromTimestamp &&
|
||||||
values[k++] = c.getValue();
|
c.getTimestamp() <= toTimestamp) filtered.add(c);
|
||||||
|
|
||||||
return values;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,7 +72,7 @@ public class MemoryCheckmarkList extends CheckmarkList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Checkmark getNewest()
|
protected Checkmark getNewestComputed()
|
||||||
{
|
{
|
||||||
long newestTimestamp = 0;
|
long newestTimestamp = 0;
|
||||||
Checkmark newestCheck = null;
|
Checkmark newestCheck = null;
|
||||||
@@ -86,17 +89,4 @@ public class MemoryCheckmarkList extends CheckmarkList
|
|||||||
return newestCheck;
|
return newestCheck;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void insert(long[] timestamps, int[] values)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < timestamps.length; i++)
|
|
||||||
{
|
|
||||||
long t = timestamps[i];
|
|
||||||
int v = values[i];
|
|
||||||
list.add(new Checkmark(habit, t, v));
|
|
||||||
}
|
|
||||||
|
|
||||||
Collections.sort(list,
|
|
||||||
(c1, c2) -> (int) (c2.getTimestamp() - c1.getTimestamp()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.memory;
|
package org.isoron.uhabits.models.memory;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.HabitList;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In-memory implementation of {@link HabitList}.
|
* In-memory implementation of {@link HabitList}.
|
||||||
@@ -42,13 +39,21 @@ public class MemoryHabitList extends HabitList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void add(Habit habit)
|
public void add(@NonNull Habit habit) throws IllegalArgumentException
|
||||||
{
|
{
|
||||||
|
if (list.contains(habit))
|
||||||
|
throw new IllegalArgumentException("habit already added");
|
||||||
|
|
||||||
|
Long id = habit.getId();
|
||||||
|
if (id != null && getById(id) != null)
|
||||||
|
throw new RuntimeException("duplicate id");
|
||||||
|
|
||||||
|
if (id == null) habit.setId((long) list.size());
|
||||||
list.addLast(habit);
|
list.addLast(habit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int count()
|
public int countActive()
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (Habit h : list) if (!h.isArchived()) count++;
|
for (Habit h : list) if (!h.isArchived()) count++;
|
||||||
@@ -61,13 +66,6 @@ public class MemoryHabitList extends HabitList
|
|||||||
return list.size();
|
return list.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Habit getById(long id)
|
|
||||||
{
|
|
||||||
for (Habit h : list) if (h.getId() == id) return h;
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public List<Habit> getAll(boolean includeArchive)
|
public List<Habit> getAll(boolean includeArchive)
|
||||||
@@ -76,6 +74,13 @@ public class MemoryHabitList extends HabitList
|
|||||||
return getFiltered(habit -> !habit.isArchived());
|
return getFiltered(habit -> !habit.isArchived());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Habit getById(long id)
|
||||||
|
{
|
||||||
|
for (Habit h : list) if (h.getId() == id) return h;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Habit getByPosition(int position)
|
public Habit getByPosition(int position)
|
||||||
@@ -84,7 +89,7 @@ public class MemoryHabitList extends HabitList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int indexOf(Habit h)
|
public int indexOf(@NonNull Habit h)
|
||||||
{
|
{
|
||||||
return list.indexOf(h);
|
return list.indexOf(h);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,18 +19,12 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.memory;
|
package org.isoron.uhabits.models.memory;
|
||||||
|
|
||||||
import org.isoron.uhabits.models.CheckmarkList;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Habit;
|
|
||||||
import org.isoron.uhabits.models.HabitList;
|
|
||||||
import org.isoron.uhabits.models.ModelFactory;
|
|
||||||
import org.isoron.uhabits.models.RepetitionList;
|
|
||||||
import org.isoron.uhabits.models.ScoreList;
|
|
||||||
import org.isoron.uhabits.models.StreakList;
|
|
||||||
|
|
||||||
public class MemoryModelFactory implements ModelFactory
|
public class MemoryModelFactory implements ModelFactory
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public RepetitionList buidRepetitionList(Habit habit)
|
public RepetitionList buildRepetitionList(Habit habit)
|
||||||
{
|
{
|
||||||
return new MemoryRepetitionList(habit);
|
return new MemoryRepetitionList(habit);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,16 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.memory;
|
package org.isoron.uhabits.models.memory;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Repetition;
|
|
||||||
import org.isoron.uhabits.models.RepetitionList;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In-memory implementation of {@link RepetitionList}.
|
* In-memory implementation of {@link RepetitionList}.
|
||||||
@@ -54,6 +49,7 @@ public class MemoryRepetitionList extends RepetitionList
|
|||||||
public List<Repetition> getByInterval(long fromTimestamp, long toTimestamp)
|
public List<Repetition> getByInterval(long fromTimestamp, long toTimestamp)
|
||||||
{
|
{
|
||||||
LinkedList<Repetition> filtered = new LinkedList<>();
|
LinkedList<Repetition> filtered = new LinkedList<>();
|
||||||
|
|
||||||
for (Repetition r : list)
|
for (Repetition r : list)
|
||||||
{
|
{
|
||||||
long t = r.getTimestamp();
|
long t = r.getTimestamp();
|
||||||
|
|||||||
@@ -19,16 +19,11 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.memory;
|
package org.isoron.uhabits.models.memory;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Score;
|
|
||||||
import org.isoron.uhabits.models.ScoreList;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MemoryScoreList extends ScoreList
|
public class MemoryScoreList extends ScoreList
|
||||||
{
|
{
|
||||||
@@ -40,14 +35,6 @@ public class MemoryScoreList extends ScoreList
|
|||||||
list = new LinkedList<>();
|
list = new LinkedList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getValue(long timestamp)
|
|
||||||
{
|
|
||||||
Score s = get(timestamp);
|
|
||||||
if (s != null) return s.getValue();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidateNewerThan(long timestamp)
|
public void invalidateNewerThan(long timestamp)
|
||||||
{
|
{
|
||||||
@@ -67,17 +54,9 @@ public class MemoryScoreList extends ScoreList
|
|||||||
return new LinkedList<>(list);
|
return new LinkedList<>(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void add(List<Score> scores)
|
|
||||||
{
|
|
||||||
list.addAll(scores);
|
|
||||||
Collections.sort(list,
|
|
||||||
(s1, s2) -> Long.signum(s2.getTimestamp() - s1.getTimestamp()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
@Nullable
|
||||||
protected Score get(long timestamp)
|
@Override
|
||||||
|
public Score getByTimestamp(long timestamp)
|
||||||
{
|
{
|
||||||
computeAll();
|
computeAll();
|
||||||
for (Score s : list)
|
for (Score s : list)
|
||||||
@@ -86,11 +65,19 @@ public class MemoryScoreList extends ScoreList
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(List<Score> scores)
|
||||||
|
{
|
||||||
|
list.addAll(scores);
|
||||||
|
Collections.sort(list,
|
||||||
|
(s1, s2) -> Long.signum(s2.getTimestamp() - s1.getTimestamp()));
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
protected Score getNewestComputed()
|
protected Score getNewestComputed()
|
||||||
{
|
{
|
||||||
if(list.isEmpty()) return null;
|
if (list.isEmpty()) return null;
|
||||||
return list.get(0);
|
return list.get(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,10 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.memory;
|
package org.isoron.uhabits.models.memory;
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Streak;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.isoron.uhabits.models.StreakList;
|
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class MemoryStreakList extends StreakList
|
public class MemoryStreakList extends StreakList
|
||||||
{
|
{
|
||||||
@@ -43,9 +39,8 @@ public class MemoryStreakList extends StreakList
|
|||||||
{
|
{
|
||||||
Streak newest = null;
|
Streak newest = null;
|
||||||
|
|
||||||
for(Streak s : list)
|
for (Streak s : list)
|
||||||
if(newest == null || s.getEnd() > newest.getEnd())
|
if (newest == null || s.getEnd() > newest.getEnd()) newest = s;
|
||||||
newest = s;
|
|
||||||
|
|
||||||
return newest;
|
return newest;
|
||||||
}
|
}
|
||||||
@@ -55,8 +50,8 @@ public class MemoryStreakList extends StreakList
|
|||||||
{
|
{
|
||||||
LinkedList<Streak> discard = new LinkedList<>();
|
LinkedList<Streak> discard = new LinkedList<>();
|
||||||
|
|
||||||
for(Streak s : list)
|
for (Streak s : list)
|
||||||
if(s.getEnd() >= timestamp - DateUtils.millisecondsInOneDay)
|
if (s.getEnd() >= timestamp - DateUtils.millisecondsInOneDay)
|
||||||
discard.add(s);
|
discard.add(s);
|
||||||
|
|
||||||
list.removeAll(discard);
|
list.removeAll(discard);
|
||||||
@@ -64,7 +59,7 @@ public class MemoryStreakList extends StreakList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void insert(List<Streak> streaks)
|
protected void add(List<Streak> streaks)
|
||||||
{
|
{
|
||||||
list.addAll(streaks);
|
list.addAll(streaks);
|
||||||
Collections.sort(list, (s1, s2) -> s2.compareNewer(s1));
|
Collections.sort(list, (s1, s2) -> s2.compareNewer(s1));
|
||||||
@@ -74,7 +69,7 @@ public class MemoryStreakList extends StreakList
|
|||||||
protected void removeNewestComputed()
|
protected void removeNewestComputed()
|
||||||
{
|
{
|
||||||
Streak newest = getNewestComputed();
|
Streak newest = getNewestComputed();
|
||||||
if(newest != null) list.remove(newest);
|
if (newest != null) list.remove(newest);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,13 +19,7 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite;
|
||||||
|
|
||||||
import org.isoron.uhabits.models.CheckmarkList;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Habit;
|
|
||||||
import org.isoron.uhabits.models.HabitList;
|
|
||||||
import org.isoron.uhabits.models.ModelFactory;
|
|
||||||
import org.isoron.uhabits.models.RepetitionList;
|
|
||||||
import org.isoron.uhabits.models.ScoreList;
|
|
||||||
import org.isoron.uhabits.models.StreakList;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory that provides models backed by an SQLite database.
|
* Factory that provides models backed by an SQLite database.
|
||||||
@@ -33,7 +27,7 @@ import org.isoron.uhabits.models.StreakList;
|
|||||||
public class SQLModelFactory implements ModelFactory
|
public class SQLModelFactory implements ModelFactory
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public RepetitionList buidRepetitionList(Habit habit)
|
public RepetitionList buildRepetitionList(Habit habit)
|
||||||
{
|
{
|
||||||
return new SQLiteRepetitionList(habit);
|
return new SQLiteRepetitionList(habit);
|
||||||
}
|
}
|
||||||
@@ -47,7 +41,7 @@ public class SQLModelFactory implements ModelFactory
|
|||||||
@Override
|
@Override
|
||||||
public HabitList buildHabitList()
|
public HabitList buildHabitList()
|
||||||
{
|
{
|
||||||
return new SQLiteHabitList();
|
return SQLiteHabitList.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,20 +19,17 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite;
|
||||||
|
|
||||||
import android.database.Cursor;
|
import android.database.sqlite.*;
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.support.annotation.*;
|
||||||
import android.database.sqlite.SQLiteStatement;
|
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.activeandroid.Cache;
|
import com.activeandroid.*;
|
||||||
import com.activeandroid.query.Delete;
|
import com.activeandroid.query.*;
|
||||||
import com.activeandroid.query.Select;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Checkmark;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.CheckmarkList;
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of a {@link CheckmarkList} that is backed by SQLite.
|
* Implementation of a {@link CheckmarkList} that is backed by SQLite.
|
||||||
@@ -44,6 +41,47 @@ public class SQLiteCheckmarkList extends CheckmarkList
|
|||||||
super(habit);
|
super(habit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(List<Checkmark> checkmarks)
|
||||||
|
{
|
||||||
|
String query =
|
||||||
|
"insert into Checkmarks(habit, timestamp, value) values (?,?,?)";
|
||||||
|
|
||||||
|
SQLiteDatabase db = Cache.openDatabase();
|
||||||
|
db.beginTransaction();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SQLiteStatement statement = db.compileStatement(query);
|
||||||
|
|
||||||
|
for (Checkmark c : checkmarks)
|
||||||
|
{
|
||||||
|
statement.bindLong(1, habit.getId());
|
||||||
|
statement.bindLong(2, c.getTimestamp());
|
||||||
|
statement.bindLong(3, c.getValue());
|
||||||
|
statement.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
db.setTransactionSuccessful();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
db.endTransaction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Checkmark> getByInterval(long fromTimestamp, long toTimestamp)
|
||||||
|
{
|
||||||
|
computeAll();
|
||||||
|
|
||||||
|
List<CheckmarkRecord> records = select()
|
||||||
|
.and("timestamp >= ?", fromTimestamp)
|
||||||
|
.and("timestamp <= ?", toTimestamp)
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
return toCheckmarks(records);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invalidateNewerThan(long timestamp)
|
public void invalidateNewerThan(long timestamp)
|
||||||
{
|
{
|
||||||
@@ -56,85 +94,30 @@ public class SQLiteCheckmarkList extends CheckmarkList
|
|||||||
observable.notifyListeners();
|
observable.notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@NonNull
|
|
||||||
public int[] getValues(long fromTimestamp, long toTimestamp)
|
|
||||||
{
|
|
||||||
compute(fromTimestamp, toTimestamp);
|
|
||||||
|
|
||||||
if (fromTimestamp > toTimestamp) return new int[0];
|
|
||||||
|
|
||||||
String query = "select value, timestamp from Checkmarks where " +
|
|
||||||
"habit = ? and timestamp >= ? and timestamp <= ?";
|
|
||||||
|
|
||||||
SQLiteDatabase db = Cache.openDatabase();
|
|
||||||
String args[] = {
|
|
||||||
habit.getId().toString(),
|
|
||||||
Long.toString(fromTimestamp),
|
|
||||||
Long.toString(toTimestamp)
|
|
||||||
};
|
|
||||||
Cursor cursor = db.rawQuery(query, args);
|
|
||||||
|
|
||||||
long day = DateUtils.millisecondsInOneDay;
|
|
||||||
int nDays = (int) ((toTimestamp - fromTimestamp) / day) + 1;
|
|
||||||
int[] checks = new int[nDays];
|
|
||||||
|
|
||||||
if (cursor.moveToFirst())
|
|
||||||
{
|
|
||||||
do
|
|
||||||
{
|
|
||||||
long timestamp = cursor.getLong(1);
|
|
||||||
int offset = (int) ((timestamp - fromTimestamp) / day);
|
|
||||||
checks[nDays - offset - 1] = cursor.getInt(0);
|
|
||||||
|
|
||||||
} while (cursor.moveToNext());
|
|
||||||
}
|
|
||||||
|
|
||||||
cursor.close();
|
|
||||||
return checks;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
protected Checkmark getNewest()
|
protected Checkmark getNewestComputed()
|
||||||
{
|
{
|
||||||
CheckmarkRecord record = new Select()
|
CheckmarkRecord record = select().limit(1).executeSingle();
|
||||||
.from(CheckmarkRecord.class)
|
if (record == null) return null;
|
||||||
.where("habit = ?", habit.getId())
|
|
||||||
.and("timestamp <= ?", DateUtils.getStartOfToday())
|
|
||||||
.orderBy("timestamp desc")
|
|
||||||
.limit(1)
|
|
||||||
.executeSingle();
|
|
||||||
|
|
||||||
if(record == null) return null;
|
|
||||||
return record.toCheckmark();
|
return record.toCheckmark();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@NonNull
|
||||||
protected void insert(long timestamps[], int values[])
|
private From select()
|
||||||
{
|
{
|
||||||
String query =
|
return new Select()
|
||||||
"insert into Checkmarks(habit, timestamp, value) values (?,?,?)";
|
.from(CheckmarkRecord.class)
|
||||||
|
.where("habit = ?", habit.getId())
|
||||||
SQLiteDatabase db = Cache.openDatabase();
|
.and("timestamp <= ?", DateUtils.getStartOfToday())
|
||||||
db.beginTransaction();
|
.orderBy("timestamp desc");
|
||||||
try
|
|
||||||
{
|
|
||||||
SQLiteStatement statement = db.compileStatement(query);
|
|
||||||
|
|
||||||
for (int i = 0; i < timestamps.length; i++)
|
|
||||||
{
|
|
||||||
statement.bindLong(1, habit.getId());
|
|
||||||
statement.bindLong(2, timestamps[i]);
|
|
||||||
statement.bindLong(3, values[i]);
|
|
||||||
statement.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
db.setTransactionSuccessful();
|
@NonNull
|
||||||
}
|
private List<Checkmark> toCheckmarks(@NonNull List<CheckmarkRecord> records)
|
||||||
finally
|
|
||||||
{
|
{
|
||||||
db.endTransaction();
|
List<Checkmark> checkmarks = new LinkedList<>();
|
||||||
}
|
for (CheckmarkRecord r : records) checkmarks.add(r.toCheckmark());
|
||||||
|
return checkmarks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,19 +19,14 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.activeandroid.query.From;
|
import com.activeandroid.query.*;
|
||||||
import com.activeandroid.query.Select;
|
|
||||||
import com.activeandroid.query.Update;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.HabitList;
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of a {@link HabitList} that is backed by SQLite.
|
* Implementation of a {@link HabitList} that is backed by SQLite.
|
||||||
@@ -42,11 +37,19 @@ public class SQLiteHabitList extends HabitList
|
|||||||
|
|
||||||
private HashMap<Long, Habit> cache;
|
private HashMap<Long, Habit> cache;
|
||||||
|
|
||||||
public SQLiteHabitList()
|
private SQLiteHabitList()
|
||||||
{
|
{
|
||||||
cache = new HashMap<>();
|
cache = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the global list of habits.
|
||||||
|
* <p>
|
||||||
|
* There is only one list of habit per application, corresponding to the
|
||||||
|
* habits table of the SQLite database.
|
||||||
|
*
|
||||||
|
* @return the global list of habits.
|
||||||
|
*/
|
||||||
public static SQLiteHabitList getInstance()
|
public static SQLiteHabitList getInstance()
|
||||||
{
|
{
|
||||||
if (instance == null) instance = new SQLiteHabitList();
|
if (instance == null) instance = new SQLiteHabitList();
|
||||||
@@ -56,15 +59,15 @@ public class SQLiteHabitList extends HabitList
|
|||||||
@Override
|
@Override
|
||||||
public void add(@NonNull Habit habit)
|
public void add(@NonNull Habit habit)
|
||||||
{
|
{
|
||||||
if(cache.containsValue(habit))
|
if (cache.containsValue(habit))
|
||||||
throw new RuntimeException("habit already in cache");
|
throw new IllegalArgumentException("habit already added");
|
||||||
|
|
||||||
HabitRecord record = new HabitRecord();
|
HabitRecord record = new HabitRecord();
|
||||||
record.copyFrom(habit);
|
record.copyFrom(habit);
|
||||||
record.position = countWithArchived();
|
record.position = countWithArchived();
|
||||||
|
|
||||||
Long id = habit.getId();
|
Long id = habit.getId();
|
||||||
if(id == null) id = record.save();
|
if (id == null) id = record.save();
|
||||||
else record.save(id);
|
else record.save(id);
|
||||||
|
|
||||||
habit.setId(id);
|
habit.setId(id);
|
||||||
@@ -72,7 +75,7 @@ public class SQLiteHabitList extends HabitList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int count()
|
public int countActive()
|
||||||
{
|
{
|
||||||
return select().count();
|
return select().count();
|
||||||
}
|
}
|
||||||
@@ -128,12 +131,14 @@ public class SQLiteHabitList extends HabitList
|
|||||||
.where("position = ?", position)
|
.where("position = ?", position)
|
||||||
.executeSingle();
|
.executeSingle();
|
||||||
|
|
||||||
return getById(record.getId());
|
if(record != null) return getById(record.getId());
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int indexOf(@NonNull Habit h)
|
public int indexOf(@NonNull Habit h)
|
||||||
{
|
{
|
||||||
|
if (h.getId() == null) return -1;
|
||||||
HabitRecord record = HabitRecord.get(h.getId());
|
HabitRecord record = HabitRecord.get(h.getId());
|
||||||
if (record == null) return -1;
|
if (record == null) return -1;
|
||||||
return record.position;
|
return record.position;
|
||||||
|
|||||||
@@ -19,64 +19,66 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.activeandroid.query.Delete;
|
import com.activeandroid.query.*;
|
||||||
import com.activeandroid.query.From;
|
|
||||||
import com.activeandroid.query.Select;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Repetition;
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
import org.isoron.uhabits.models.RepetitionList;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of a {@link RepetitionList} that is backed by SQLite.
|
* Implementation of a {@link RepetitionList} that is backed by SQLite.
|
||||||
*/
|
*/
|
||||||
public class SQLiteRepetitionList extends RepetitionList
|
public class SQLiteRepetitionList extends RepetitionList
|
||||||
{
|
{
|
||||||
HashMap<Long, Repetition> cache;
|
|
||||||
|
|
||||||
public SQLiteRepetitionList(@NonNull Habit habit)
|
public SQLiteRepetitionList(@NonNull Habit habit)
|
||||||
{
|
{
|
||||||
super(habit);
|
super(habit);
|
||||||
this.cache = new HashMap<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a repetition to the global SQLite database.
|
||||||
|
* <p>
|
||||||
|
* Given a repetition, this creates and saves the corresponding
|
||||||
|
* RepetitionRecord to the database.
|
||||||
|
*
|
||||||
|
* @param rep the repetition to be added
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void add(Repetition rep)
|
public void add(Repetition rep)
|
||||||
{
|
{
|
||||||
RepetitionRecord record = new RepetitionRecord();
|
RepetitionRecord record = new RepetitionRecord();
|
||||||
record.copyFrom(rep);
|
record.copyFrom(rep);
|
||||||
long id = record.save();
|
record.save();
|
||||||
cache.put(id, rep);
|
|
||||||
observable.notifyListeners();
|
observable.notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Repetition> getByInterval(long timeFrom, long timeTo)
|
public List<Repetition> getByInterval(long timeFrom, long timeTo)
|
||||||
{
|
{
|
||||||
return getFromRecord(selectFromTo(timeFrom, timeTo).execute());
|
return toRepetitions(selectFromTo(timeFrom, timeTo).execute());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@Nullable
|
||||||
public Repetition getByTimestamp(long timestamp)
|
public Repetition getByTimestamp(long timestamp)
|
||||||
{
|
{
|
||||||
RepetitionRecord record =
|
RepetitionRecord record =
|
||||||
select().where("timestamp = ?", timestamp).executeSingle();
|
select().where("timestamp = ?", timestamp).executeSingle();
|
||||||
return getFromRecord(record);
|
|
||||||
|
if (record == null) return null;
|
||||||
|
return record.toRepetition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Repetition getOldest()
|
public Repetition getOldest()
|
||||||
{
|
{
|
||||||
RepetitionRecord record = select().limit(1).executeSingle();
|
RepetitionRecord record = select().limit(1).executeSingle();
|
||||||
return getFromRecord(record);
|
if (record == null) return null;
|
||||||
|
return record.toRepetition();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -91,38 +93,6 @@ public class SQLiteRepetitionList extends RepetitionList
|
|||||||
observable.notifyListeners();
|
observable.notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
private List<Repetition> getFromRecord(
|
|
||||||
@Nullable List<RepetitionRecord> records)
|
|
||||||
{
|
|
||||||
List<Repetition> reps = new LinkedList<>();
|
|
||||||
if (records == null) return reps;
|
|
||||||
|
|
||||||
for (RepetitionRecord record : records)
|
|
||||||
{
|
|
||||||
Repetition rep = getFromRecord(record);
|
|
||||||
reps.add(rep);
|
|
||||||
}
|
|
||||||
|
|
||||||
return reps;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private Repetition getFromRecord(@Nullable RepetitionRecord record)
|
|
||||||
{
|
|
||||||
if (record == null) return null;
|
|
||||||
|
|
||||||
Long id = record.getId();
|
|
||||||
|
|
||||||
if (!cache.containsKey(id))
|
|
||||||
{
|
|
||||||
Repetition repetition = record.toRepetition();
|
|
||||||
cache.put(id, repetition);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cache.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private From select()
|
private From select()
|
||||||
{
|
{
|
||||||
@@ -140,4 +110,17 @@ public class SQLiteRepetitionList extends RepetitionList
|
|||||||
.and("timestamp >= ?", timeFrom)
|
.and("timestamp >= ?", timeFrom)
|
||||||
.and("timestamp <= ?", timeTo);
|
.and("timestamp <= ?", timeTo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private List<Repetition> toRepetitions(
|
||||||
|
@Nullable List<RepetitionRecord> records)
|
||||||
|
{
|
||||||
|
List<Repetition> reps = new LinkedList<>();
|
||||||
|
if (records == null) return reps;
|
||||||
|
|
||||||
|
for (RepetitionRecord record : records)
|
||||||
|
reps.add(record.toRepetition());
|
||||||
|
|
||||||
|
return reps;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,23 +19,16 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite;
|
||||||
|
|
||||||
import android.database.sqlite.SQLiteDatabase;
|
import android.database.sqlite.*;
|
||||||
import android.database.sqlite.SQLiteStatement;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.NonNull;
|
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.activeandroid.Cache;
|
import com.activeandroid.*;
|
||||||
import com.activeandroid.query.Delete;
|
import com.activeandroid.query.*;
|
||||||
import com.activeandroid.query.From;
|
|
||||||
import com.activeandroid.query.Select;
|
|
||||||
import com.activeandroid.util.SQLiteUtils;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Score;
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
import org.isoron.uhabits.models.ScoreList;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of a ScoreList that is backed by SQLite.
|
* Implementation of a ScoreList that is backed by SQLite.
|
||||||
@@ -53,12 +46,18 @@ public class SQLiteScoreList extends ScoreList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getValue(long timestamp)
|
@NonNull
|
||||||
|
public List<Score> getAll()
|
||||||
{
|
{
|
||||||
computeAll();
|
computeAll();
|
||||||
String[] args = {habit.getId().toString(), Long.toString(timestamp)};
|
|
||||||
return SQLiteUtils.intQuery(
|
List<ScoreRecord> records = select().execute();
|
||||||
"select score from Score where habit = ? and timestamp = ?", args);
|
List<Score> scores = new LinkedList<>();
|
||||||
|
|
||||||
|
for (ScoreRecord rec : records)
|
||||||
|
scores.add(rec.toScore());
|
||||||
|
|
||||||
|
return scores;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -72,42 +71,7 @@ public class SQLiteScoreList extends ScoreList
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@NonNull
|
public void add(List<Score> scores)
|
||||||
public List<Score> getAll()
|
|
||||||
{
|
|
||||||
List<ScoreRecord> records = select().execute();
|
|
||||||
List<Score> scores = new LinkedList<>();
|
|
||||||
|
|
||||||
for(ScoreRecord rec : records)
|
|
||||||
scores.add(rec.toScore());
|
|
||||||
|
|
||||||
return scores;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Nullable
|
|
||||||
@Override
|
|
||||||
protected Score getNewestComputed()
|
|
||||||
{
|
|
||||||
ScoreRecord record = select().limit(1).executeSingle();
|
|
||||||
if(record == null) return null;
|
|
||||||
return record.toScore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@Nullable
|
|
||||||
protected Score get(long timestamp)
|
|
||||||
{
|
|
||||||
computeAll();
|
|
||||||
|
|
||||||
ScoreRecord record =
|
|
||||||
select().where("timestamp = ?", timestamp).executeSingle();
|
|
||||||
|
|
||||||
if(record == null) return null;
|
|
||||||
return record.toScore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void add(List<Score> scores)
|
|
||||||
{
|
{
|
||||||
String query =
|
String query =
|
||||||
"insert into Score(habit, timestamp, score) values (?,?,?)";
|
"insert into Score(habit, timestamp, score) values (?,?,?)";
|
||||||
@@ -135,7 +99,29 @@ public class SQLiteScoreList extends ScoreList
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected From select()
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Score getByTimestamp(long timestamp)
|
||||||
|
{
|
||||||
|
computeAll();
|
||||||
|
|
||||||
|
ScoreRecord record =
|
||||||
|
select().where("timestamp = ?", timestamp).executeSingle();
|
||||||
|
|
||||||
|
if (record == null) return null;
|
||||||
|
return record.toScore();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
protected Score getNewestComputed()
|
||||||
|
{
|
||||||
|
ScoreRecord record = select().limit(1).executeSingle();
|
||||||
|
if (record == null) return null;
|
||||||
|
return record.toScore();
|
||||||
|
}
|
||||||
|
|
||||||
|
private From select()
|
||||||
{
|
{
|
||||||
return new Select()
|
return new Select()
|
||||||
.from(ScoreRecord.class)
|
.from(ScoreRecord.class)
|
||||||
|
|||||||
@@ -19,20 +19,15 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.activeandroid.query.Delete;
|
import com.activeandroid.query.*;
|
||||||
import com.activeandroid.query.Select;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Streak;
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
import org.isoron.uhabits.models.StreakList;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.isoron.uhabits.utils.DatabaseUtils;
|
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of a StreakList that is backed by SQLite.
|
* Implementation of a StreakList that is backed by SQLite.
|
||||||
@@ -61,7 +56,7 @@ public class SQLiteStreakList extends StreakList
|
|||||||
public Streak getNewestComputed()
|
public Streak getNewestComputed()
|
||||||
{
|
{
|
||||||
StreakRecord newestRecord = getNewestRecord();
|
StreakRecord newestRecord = getNewestRecord();
|
||||||
if(newestRecord == null) return null;
|
if (newestRecord == null) return null;
|
||||||
return newestRecord.toStreak();
|
return newestRecord.toStreak();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,19 +72,8 @@ public class SQLiteStreakList extends StreakList
|
|||||||
observable.notifyListeners();
|
observable.notifyListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
private StreakRecord getNewestRecord()
|
|
||||||
{
|
|
||||||
return new Select()
|
|
||||||
.from(StreakRecord.class)
|
|
||||||
.where("habit = ?", habit.getId())
|
|
||||||
.orderBy("end desc")
|
|
||||||
.limit(1)
|
|
||||||
.executeSingle();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void insert(@NonNull List<Streak> streaks)
|
protected void add(@NonNull List<Streak> streaks)
|
||||||
{
|
{
|
||||||
DatabaseUtils.executeAsTransaction(() -> {
|
DatabaseUtils.executeAsTransaction(() -> {
|
||||||
for (Streak streak : streaks)
|
for (Streak streak : streaks)
|
||||||
@@ -101,6 +85,24 @@ public class SQLiteStreakList extends StreakList
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void removeNewestComputed()
|
||||||
|
{
|
||||||
|
StreakRecord newestStreak = getNewestRecord();
|
||||||
|
if (newestStreak != null) newestStreak.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private StreakRecord getNewestRecord()
|
||||||
|
{
|
||||||
|
return new Select()
|
||||||
|
.from(StreakRecord.class)
|
||||||
|
.where("habit = ?", habit.getId())
|
||||||
|
.orderBy("end desc")
|
||||||
|
.limit(1)
|
||||||
|
.executeSingle();
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
private List<Streak> recordsToStreaks(List<StreakRecord> records)
|
private List<Streak> recordsToStreaks(List<StreakRecord> records)
|
||||||
{
|
{
|
||||||
@@ -111,11 +113,4 @@ public class SQLiteStreakList extends StreakList
|
|||||||
|
|
||||||
return streaks;
|
return streaks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void removeNewestComputed()
|
|
||||||
{
|
|
||||||
StreakRecord newestStreak = getNewestRecord();
|
|
||||||
if (newestStreak != null) newestStreak.delete();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,14 +17,13 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite.records;
|
||||||
|
|
||||||
import com.activeandroid.Model;
|
import com.activeandroid.*;
|
||||||
import com.activeandroid.annotation.Column;
|
import com.activeandroid.annotation.*;
|
||||||
import com.activeandroid.annotation.Table;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Checkmark;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.sqlite.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQLite database record corresponding to a {@link Checkmark}.
|
* The SQLite database record corresponding to a {@link Checkmark}.
|
||||||
@@ -17,20 +17,18 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite.records;
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.*;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
import android.support.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.activeandroid.Model;
|
import com.activeandroid.*;
|
||||||
import com.activeandroid.annotation.Column;
|
import com.activeandroid.annotation.*;
|
||||||
import com.activeandroid.annotation.Table;
|
import com.activeandroid.query.*;
|
||||||
import com.activeandroid.query.Delete;
|
import com.activeandroid.util.*;
|
||||||
import com.activeandroid.util.SQLiteUtils;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.utils.DatabaseUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQLite database record corresponding to a {@link Habit}.
|
* The SQLite database record corresponding to a {@link Habit}.
|
||||||
@@ -83,7 +81,7 @@ public class HabitRecord extends Model
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static HabitRecord get(Long id)
|
public static HabitRecord get(long id)
|
||||||
{
|
{
|
||||||
return HabitRecord.load(HabitRecord.class, id);
|
return HabitRecord.load(HabitRecord.class, id);
|
||||||
}
|
}
|
||||||
@@ -17,14 +17,13 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite.records;
|
||||||
|
|
||||||
import com.activeandroid.Model;
|
import com.activeandroid.*;
|
||||||
import com.activeandroid.annotation.Column;
|
import com.activeandroid.annotation.*;
|
||||||
import com.activeandroid.annotation.Table;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Repetition;
|
import org.isoron.uhabits.models.sqlite.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQLite database record corresponding to a {@link Repetition}.
|
* The SQLite database record corresponding to a {@link Repetition}.
|
||||||
@@ -17,14 +17,13 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite.records;
|
||||||
|
|
||||||
import com.activeandroid.Model;
|
import com.activeandroid.*;
|
||||||
import com.activeandroid.annotation.Column;
|
import com.activeandroid.annotation.*;
|
||||||
import com.activeandroid.annotation.Table;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Score;
|
import org.isoron.uhabits.models.sqlite.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQLite database record corresponding to a Score.
|
* The SQLite database record corresponding to a Score.
|
||||||
@@ -17,14 +17,13 @@
|
|||||||
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
* with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.isoron.uhabits.models.sqlite;
|
package org.isoron.uhabits.models.sqlite.records;
|
||||||
|
|
||||||
import com.activeandroid.Model;
|
import com.activeandroid.*;
|
||||||
import com.activeandroid.annotation.Column;
|
import com.activeandroid.annotation.*;
|
||||||
import com.activeandroid.annotation.Table;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Streak;
|
import org.isoron.uhabits.models.sqlite.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The SQLite database record corresponding to a Streak.
|
* The SQLite database record corresponding to a Streak.
|
||||||
@@ -51,10 +51,10 @@ import java.util.Random;
|
|||||||
public class HabitScoreView extends ScrollableDataView
|
public class HabitScoreView extends ScrollableDataView
|
||||||
implements HabitDataView, ModelObservable.Listener
|
implements HabitDataView, ModelObservable.Listener
|
||||||
{
|
{
|
||||||
public static final PorterDuffXfermode XFERMODE_CLEAR =
|
private static final PorterDuffXfermode XFERMODE_CLEAR =
|
||||||
new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
|
new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
|
||||||
|
|
||||||
public static final PorterDuffXfermode XFERMODE_SRC =
|
private static final PorterDuffXfermode XFERMODE_SRC =
|
||||||
new PorterDuffXfermode(PorterDuff.Mode.SRC);
|
new PorterDuffXfermode(PorterDuff.Mode.SRC);
|
||||||
|
|
||||||
public static int DEFAULT_BUCKET_SIZES[] = {1, 7, 31, 92, 365};
|
public static int DEFAULT_BUCKET_SIZES[] = {1, 7, 31, 92, 365};
|
||||||
|
|||||||
@@ -19,25 +19,17 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.utils;
|
package org.isoron.uhabits.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.*;
|
||||||
import android.database.Cursor;
|
import android.database.*;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.*;
|
||||||
|
|
||||||
import com.activeandroid.ActiveAndroid;
|
import com.activeandroid.*;
|
||||||
import com.activeandroid.Cache;
|
|
||||||
import com.activeandroid.Configuration;
|
|
||||||
|
|
||||||
import org.isoron.uhabits.BuildConfig;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.HabitsApplication;
|
import org.isoron.uhabits.models.sqlite.records.*;
|
||||||
import org.isoron.uhabits.models.sqlite.CheckmarkRecord;
|
|
||||||
import org.isoron.uhabits.models.sqlite.HabitRecord;
|
|
||||||
import org.isoron.uhabits.models.sqlite.RepetitionRecord;
|
|
||||||
import org.isoron.uhabits.models.sqlite.ScoreRecord;
|
|
||||||
import org.isoron.uhabits.models.sqlite.StreakRecord;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
import java.text.*;
|
||||||
import java.text.SimpleDateFormat;
|
|
||||||
|
|
||||||
public abstract class DatabaseUtils
|
public abstract class DatabaseUtils
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -18,15 +18,14 @@
|
|||||||
*/
|
*/
|
||||||
package org.isoron.uhabits.widgets;
|
package org.isoron.uhabits.widgets;
|
||||||
|
|
||||||
import android.app.PendingIntent;
|
import android.app.*;
|
||||||
import android.content.Context;
|
import android.content.*;
|
||||||
import android.view.View;
|
import android.view.*;
|
||||||
|
|
||||||
import org.isoron.uhabits.HabitBroadcastReceiver;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.R;
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.models.Habit;
|
import org.isoron.uhabits.ui.habits.show.views.*;
|
||||||
import org.isoron.uhabits.widgets.views.CheckmarkWidgetView;
|
import org.isoron.uhabits.widgets.views.*;
|
||||||
import org.isoron.uhabits.ui.habits.show.views.HabitDataView;
|
|
||||||
|
|
||||||
public class CheckmarkWidgetProvider extends BaseWidgetProvider
|
public class CheckmarkWidgetProvider extends BaseWidgetProvider
|
||||||
{
|
{
|
||||||
@@ -38,18 +37,6 @@ public class CheckmarkWidgetProvider extends BaseWidgetProvider
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void refreshCustomViewData(View view)
|
|
||||||
{
|
|
||||||
((HabitDataView) view).refreshData();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected PendingIntent getOnClickPendingIntent(Context context, Habit habit)
|
|
||||||
{
|
|
||||||
return HabitBroadcastReceiver.buildCheckIntent(context, habit, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getDefaultHeight()
|
protected int getDefaultHeight()
|
||||||
{
|
{
|
||||||
@@ -68,5 +55,18 @@ public class CheckmarkWidgetProvider extends BaseWidgetProvider
|
|||||||
return R.layout.widget_wrapper;
|
return R.layout.widget_wrapper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PendingIntent getOnClickPendingIntent(Context context,
|
||||||
|
Habit habit)
|
||||||
|
{
|
||||||
|
return HabitBroadcastReceiver.buildCheckIntent(context, habit, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void refreshCustomViewData(View view)
|
||||||
|
{
|
||||||
|
((HabitDataView) view).refreshData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import org.isoron.uhabits.BaseUnitTest;
|
import org.isoron.uhabits.BaseUnitTest;
|
||||||
|
import org.isoron.uhabits.models.Habit;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.DateUtils;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|||||||
@@ -19,20 +19,17 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import org.hamcrest.MatcherAssert;
|
import org.hamcrest.*;
|
||||||
import org.isoron.uhabits.BaseUnitTest;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.junit.Test;
|
import org.junit.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.StringWriter;
|
import java.util.*;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static junit.framework.Assert.fail;
|
import static junit.framework.Assert.*;
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.hamcrest.CoreMatchers.nullValue;
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.hamcrest.core.IsEqual.equalTo;
|
import static org.hamcrest.core.IsEqual.equalTo;
|
||||||
|
|
||||||
public class HabitListTest extends BaseUnitTest
|
public class HabitListTest extends BaseUnitTest
|
||||||
@@ -73,7 +70,7 @@ public class HabitListTest extends BaseUnitTest
|
|||||||
@Test
|
@Test
|
||||||
public void test_count()
|
public void test_count()
|
||||||
{
|
{
|
||||||
assertThat(list.count(), equalTo(6));
|
assertThat(list.countActive(), equalTo(6));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ package org.isoron.uhabits.models;
|
|||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import org.isoron.uhabits.BaseUnitTest;
|
import org.isoron.uhabits.BaseUnitTest;
|
||||||
|
import org.isoron.uhabits.models.*;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.DateUtils;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -33,7 +34,7 @@ import java.util.GregorianCalendar;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
import static org.hamcrest.core.Is.is;
|
import static org.hamcrest.core.Is.is;
|
||||||
import static org.hamcrest.core.IsEqual.equalTo;
|
import static org.hamcrest.core.IsEqual.equalTo;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public class ScoreListTest extends BaseUnitTest
|
|||||||
int actualValues[] = new int[expectedValues.length];
|
int actualValues[] = new int[expectedValues.length];
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (Score s : habit.getScores().getAll())
|
for (Score s : habit.getScores())
|
||||||
actualValues[i++] = s.getValue();
|
actualValues[i++] = s.getValue();
|
||||||
|
|
||||||
assertThat(actualValues, equalTo(expectedValues));
|
assertThat(actualValues, equalTo(expectedValues));
|
||||||
|
|||||||
@@ -19,16 +19,15 @@
|
|||||||
|
|
||||||
package org.isoron.uhabits.models;
|
package org.isoron.uhabits.models;
|
||||||
|
|
||||||
import org.isoron.uhabits.BaseUnitTest;
|
import org.isoron.uhabits.*;
|
||||||
import org.isoron.uhabits.utils.DateUtils;
|
import org.isoron.uhabits.utils.*;
|
||||||
import org.junit.Test;
|
import org.junit.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.*;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.hamcrest.MatcherAssert.*;
|
import static org.hamcrest.MatcherAssert.*;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.*;
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
|
|
||||||
public class StreakListTest extends BaseUnitTest
|
public class StreakListTest extends BaseUnitTest
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user