mirror of https://github.com/iSoron/uhabits.git
parent
78d4f86cab
commit
2b23b36e36
@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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.memory;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.isoron.uhabits.models.Habit;
|
||||
import org.isoron.uhabits.models.Score;
|
||||
import org.isoron.uhabits.models.ScoreList;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MemoryScoreList extends ScoreList
|
||||
{
|
||||
List<Score> list;
|
||||
|
||||
public MemoryScoreList(Habit habit)
|
||||
{
|
||||
super(habit);
|
||||
list = new LinkedList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getValue(long timestamp)
|
||||
{
|
||||
Score s = get(timestamp);
|
||||
if (s != null) return s.getValue();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invalidateNewerThan(long timestamp)
|
||||
{
|
||||
List<Score> discard = new LinkedList<>();
|
||||
|
||||
for (Score s : list)
|
||||
if (s.getTimestamp() >= timestamp) discard.add(s);
|
||||
|
||||
list.removeAll(discard);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
public List<Score> getAll()
|
||||
{
|
||||
computeAll();
|
||||
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
|
||||
protected Score get(long timestamp)
|
||||
{
|
||||
computeAll();
|
||||
for (Score s : list)
|
||||
if (s.getTimestamp() == timestamp) return s;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected Score getNewestComputed()
|
||||
{
|
||||
if(list.isEmpty()) return null;
|
||||
return list.get(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import org.isoron.uhabits.BaseUnitTest;
|
||||
import org.isoron.uhabits.utils.DateUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
|
||||
public class ScoreListTest extends BaseUnitTest
|
||||
{
|
||||
private Habit habit;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp()
|
||||
{
|
||||
super.setUp();
|
||||
habit = fixtures.createEmptyHabit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getAll()
|
||||
{
|
||||
toggleRepetitions(0, 20);
|
||||
|
||||
int expectedValues[] = {
|
||||
12629351,
|
||||
12266245,
|
||||
11883254,
|
||||
11479288,
|
||||
11053198,
|
||||
10603773,
|
||||
10129735,
|
||||
9629735,
|
||||
9102352,
|
||||
8546087,
|
||||
7959357,
|
||||
7340494,
|
||||
6687738,
|
||||
5999234,
|
||||
5273023,
|
||||
4507040,
|
||||
3699107,
|
||||
2846927,
|
||||
1948077,
|
||||
1000000
|
||||
};
|
||||
|
||||
int actualValues[] = new int[expectedValues.length];
|
||||
|
||||
int i = 0;
|
||||
for (Score s : habit.getScores().getAll())
|
||||
actualValues[i++] = s.getValue();
|
||||
|
||||
assertThat(actualValues, equalTo(expectedValues));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getTodayValue()
|
||||
{
|
||||
toggleRepetitions(0, 20);
|
||||
assertThat(habit.getScores().getTodayValue(), equalTo(12629351));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getValue()
|
||||
{
|
||||
toggleRepetitions(0, 20);
|
||||
|
||||
int expectedValues[] = {
|
||||
12629351,
|
||||
12266245,
|
||||
11883254,
|
||||
11479288,
|
||||
11053198,
|
||||
10603773,
|
||||
10129735,
|
||||
9629735,
|
||||
9102352,
|
||||
8546087,
|
||||
7959357,
|
||||
7340494,
|
||||
6687738,
|
||||
5999234,
|
||||
5273023,
|
||||
4507040,
|
||||
3699107,
|
||||
2846927,
|
||||
1948077,
|
||||
1000000
|
||||
};
|
||||
|
||||
long current = DateUtils.getStartOfToday();
|
||||
for (int expectedValue : expectedValues)
|
||||
{
|
||||
assertThat(habit.getScores().getValue(current),
|
||||
equalTo(expectedValue));
|
||||
current -= DateUtils.millisecondsInOneDay;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_groupBy()
|
||||
{
|
||||
Habit habit = fixtures.createLongHabit();
|
||||
List<Score> list =
|
||||
habit.getScores().groupBy(DateUtils.TruncateField.MONTH);
|
||||
|
||||
assertThat(list.size(), equalTo(5));
|
||||
assertThat(list.get(0).getValue(), equalTo(14634077));
|
||||
assertThat(list.get(1).getValue(), equalTo(12969133));
|
||||
assertThat(list.get(2).getValue(), equalTo(10595391));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_invalidateNewerThan()
|
||||
{
|
||||
assertThat(habit.getScores().getTodayValue(), equalTo(0));
|
||||
|
||||
toggleRepetitions(0, 2);
|
||||
assertThat(habit.getScores().getTodayValue(), equalTo(1948077));
|
||||
|
||||
habit.setFreqNum(1);
|
||||
habit.setFreqDen(2);
|
||||
habit.getScores().invalidateNewerThan(0);
|
||||
|
||||
assertThat(habit.getScores().getTodayValue(), equalTo(1974654));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_writeCSV() throws IOException
|
||||
{
|
||||
Habit habit = fixtures.createShortHabit();
|
||||
|
||||
String expectedCSV = "2015-01-25,0.2649\n" +
|
||||
"2015-01-24,0.2205\n" +
|
||||
"2015-01-23,0.2283\n" +
|
||||
"2015-01-22,0.2364\n" +
|
||||
"2015-01-21,0.1909\n" +
|
||||
"2015-01-20,0.1439\n" +
|
||||
"2015-01-19,0.0952\n" +
|
||||
"2015-01-18,0.0986\n" +
|
||||
"2015-01-17,0.1021\n" +
|
||||
"2015-01-16,0.0519\n";
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
habit.getScores().writeCSV(writer);
|
||||
|
||||
assertThat(writer.toString(), equalTo(expectedCSV));
|
||||
}
|
||||
|
||||
private void log(List<Score> list)
|
||||
{
|
||||
SimpleDateFormat df = DateUtils.getCSVDateFormat();
|
||||
for (Score s : list)
|
||||
log("%s %d", df.format(new Date(s.getTimestamp())), s.getValue());
|
||||
}
|
||||
|
||||
private void toggleRepetitions(final int from, final int to)
|
||||
{
|
||||
RepetitionList reps = habit.getRepetitions();
|
||||
long today = DateUtils.getStartOfToday();
|
||||
long day = DateUtils.millisecondsInOneDay;
|
||||
|
||||
for (int i = from; i < to; i++)
|
||||
reps.toggleTimestamp(today - i * day);
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
import org.isoron.uhabits.BaseUnitTest;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
|
||||
public class DateUtilsTest extends BaseUnitTest
|
||||
{
|
||||
@Test
|
||||
public void testTruncate_dayOfWeek()
|
||||
{
|
||||
DateUtils.TruncateField field = DateUtils.TruncateField.WEEK_NUMBER;
|
||||
|
||||
long expected = timestamp(2015, Calendar.JANUARY, 11);
|
||||
long t0 = timestamp(2015, Calendar.JANUARY, 11);
|
||||
long t1 = timestamp(2015, Calendar.JANUARY, 16);
|
||||
long t2 = timestamp(2015, Calendar.JANUARY, 17);
|
||||
|
||||
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
|
||||
expected = timestamp(2015, Calendar.JANUARY, 18);
|
||||
t0 = timestamp(2015, Calendar.JANUARY, 18);
|
||||
t1 = timestamp(2015, Calendar.JANUARY, 19);
|
||||
t2 = timestamp(2015, Calendar.JANUARY, 24);
|
||||
|
||||
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncate_month()
|
||||
{
|
||||
long expected = timestamp(2016, Calendar.JUNE, 1);
|
||||
long t0 = timestamp(2016, Calendar.JUNE, 1);
|
||||
long t1 = timestamp(2016, Calendar.JUNE, 15);
|
||||
long t2 = timestamp(2016, Calendar.JUNE, 20);
|
||||
|
||||
DateUtils.TruncateField field = DateUtils.TruncateField.MONTH;
|
||||
|
||||
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
|
||||
expected = timestamp(2016, Calendar.DECEMBER, 1);
|
||||
t0 = timestamp(2016, Calendar.DECEMBER, 1);
|
||||
t1 = timestamp(2016, Calendar.DECEMBER, 15);
|
||||
t2 = timestamp(2016, Calendar.DECEMBER, 31);
|
||||
|
||||
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncate_quarter()
|
||||
{
|
||||
DateUtils.TruncateField field = DateUtils.TruncateField.QUARTER;
|
||||
|
||||
long expected = timestamp(2016, Calendar.JANUARY, 1);
|
||||
long t0 = timestamp(2016, Calendar.JANUARY, 20);
|
||||
long t1 = timestamp(2016, Calendar.FEBRUARY, 15);
|
||||
long t2 = timestamp(2016, Calendar.MARCH, 30);
|
||||
|
||||
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
|
||||
expected = timestamp(2016, Calendar.APRIL, 1);
|
||||
t0 = timestamp(2016, Calendar.APRIL, 1);
|
||||
t1 = timestamp(2016, Calendar.MAY, 30);
|
||||
t2 = timestamp(2016, Calendar.JUNE, 20);
|
||||
|
||||
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTruncate_year()
|
||||
{
|
||||
DateUtils.TruncateField field = DateUtils.TruncateField.YEAR;
|
||||
|
||||
long expected = timestamp(2016, Calendar.JANUARY, 1);
|
||||
long t0 = timestamp(2016, Calendar.JANUARY, 1);
|
||||
long t1 = timestamp(2016, Calendar.FEBRUARY, 25);
|
||||
long t2 = timestamp(2016, Calendar.DECEMBER, 31);
|
||||
|
||||
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
|
||||
expected = timestamp(2017, Calendar.JANUARY, 1);
|
||||
t0 = timestamp(2017, Calendar.JANUARY, 1);
|
||||
t1 = timestamp(2017, Calendar.MAY, 30);
|
||||
t2 = timestamp(2017, Calendar.DECEMBER, 31);
|
||||
|
||||
assertThat(DateUtils.truncate(field, t0), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t1), equalTo(expected));
|
||||
assertThat(DateUtils.truncate(field, t2), equalTo(expected));
|
||||
}
|
||||
|
||||
private void log(long timestamp)
|
||||
{
|
||||
DateFormat df = SimpleDateFormat.getDateTimeInstance();
|
||||
df.setTimeZone(TimeZone.getTimeZone("GMT"));
|
||||
log("%s", df.format(new Date(timestamp)));
|
||||
}
|
||||
|
||||
public long timestamp(int year, int month, int day)
|
||||
{
|
||||
GregorianCalendar cal = DateUtils.getStartOfTodayCalendar();
|
||||
cal.set(year, month, day);
|
||||
return cal.getTimeInMillis();
|
||||
}
|
||||
}
|
Loading…
Reference in new issue