Persist repetition values

pull/157/merge
Alinson S. Xavier 9 years ago
parent ac32460859
commit 5b9e90fe7a

@ -12,7 +12,7 @@ android {
minSdkVersion 15
targetSdkVersion 25
buildConfigField "Integer", "databaseVersion", "15"
buildConfigField "Integer", "databaseVersion", "16"
buildConfigField "String", "databaseFilename", "\"uhabits.db\""
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

@ -37,6 +37,7 @@ import java.util.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.core.IsNot.not;
import static org.isoron.uhabits.models.Checkmark.*;
@RunWith(AndroidJUnit4.class)
@MediumTest
@ -67,7 +68,7 @@ public class SQLiteRepetitionListTest extends BaseAndroidTest
RepetitionRecord record = getByTimestamp(today + day);
assertThat(record, is(nullValue()));
Repetition rep = new Repetition(today + day);
Repetition rep = new Repetition(today + day, CHECKED_EXPLICITLY);
habit.getRepetitions().add(rep);
record = getByTimestamp(today + day);

@ -0,0 +1,2 @@
alter table Habits add column type integer not null default 0;
alter table Repetitions add column value integer not null default 2;

@ -323,7 +323,11 @@ public class HistoryChart extends ScrollableChart
int checkmarkOffset)
{
if (checkmarkOffset >= checkmarks.length) pSquareBg.setColor(colors[0]);
else pSquareBg.setColor(colors[checkmarks[checkmarkOffset]]);
else
{
int checkmark = checkmarks[checkmarkOffset];
pSquareBg.setColor(colors[Integer.min(2, checkmark)]);
}
pSquareFg.setColor(reverseTextColor);
canvas.drawRect(location, pSquareBg);

@ -20,7 +20,6 @@
package org.isoron.uhabits.activities.habits.list;
import android.support.annotation.*;
import android.util.*;
import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.*;
@ -169,9 +168,9 @@ public class ListHabitsController
{
int oldValue = habit.getCheckmarks().getTodayValue();
screen.showNumberPicker(oldValue, newValue -> {
Log.d("ListHabitsController",
String.format("%s %d %d", habit.getName(), timestamp,
newValue));
commandRunner.execute(
new CreateRepetitionCommand(habit, timestamp, newValue),
habit.getId());
});
}

@ -104,11 +104,13 @@ public class HabitCardView extends FrameLayout
public void setValues(int values[])
{
checkmarkPanel.setValues(values);
numberPanel.setValues(values);
numberPanel.setThreshold(10);
int[] magnitudes = new int[]{10, 100, 1000, 10000};
int threshold = magnitudes[new Random().nextInt(4)];
numberPanel.setThreshold(threshold);
numberPanel.initEditMode();
// int[] magnitudes = new int[]{10, 100, 1000, 10000};
// int threshold = magnitudes[new Random().nextInt(4)];
// numberPanel.setThreshold(threshold);
// numberPanel.initEditMode();
postInvalidate();
}
@ -237,7 +239,7 @@ public class HabitCardView extends FrameLayout
checkmarkPanel.setColor(color);
numberPanel.setColor(color);
boolean isNumberHabit = false; //(new Random().nextInt(3) == 0);
boolean isNumberHabit = true; //(new Random().nextInt(3) == 0);
checkmarkPanel.setVisibility(isNumberHabit ? GONE : VISIBLE);
numberPanel.setVisibility(isNumberHabit ? VISIBLE : GONE);

@ -0,0 +1,78 @@
/*
* 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.commands;
import android.support.annotation.*;
import org.isoron.uhabits.models.*;
/**
* Command to toggle a repetition.
*/
public class CreateRepetitionCommand extends Command
{
@NonNull
private final Habit habit;
private final long timestamp;
private final int value;
private Repetition previousRep;
private Repetition newRep;
public CreateRepetitionCommand(@NonNull Habit habit,
long timestamp,
int value)
{
this.timestamp = timestamp;
this.habit = habit;
this.value = value;
}
@Override
public void execute()
{
RepetitionList reps = habit.getRepetitions();
previousRep = reps.getByTimestamp(timestamp);
if (previousRep != null) reps.remove(previousRep);
newRep = new Repetition(timestamp, value);
reps.add(newRep);
habit.invalidateNewerThan(timestamp);
}
@NonNull
public Habit getHabit()
{
return habit;
}
@Override
public void undo()
{
habit.getRepetitions().remove(newRep);
if (previousRep != null) habit.getRepetitions().add(previousRep);
habit.invalidateNewerThan(timestamp);
}
}

@ -27,6 +27,9 @@ import java.io.*;
import java.text.*;
import java.util.*;
import static org.isoron.uhabits.models.Checkmark.CHECKED_EXPLICITLY;
import static org.isoron.uhabits.models.Checkmark.CHECKED_IMPLICITLY;
/**
* The collection of {@link Checkmark}s belonging to a habit.
*/
@ -239,7 +242,7 @@ public abstract class CheckmarkList
for (Repetition rep : reps)
{
int offset = (int) ((rep.getTimestamp() - fromExtended) / day);
checks[nDaysExtended - offset - 1] = Checkmark.CHECKED_EXPLICITLY;
checks[nDaysExtended - offset - 1] = rep.getValue();
}
for (int i = 0; i < nDays; i++)
@ -247,11 +250,11 @@ public abstract class CheckmarkList
int counter = 0;
for (int j = 0; j < freq.getDenominator(); j++)
if (checks[i + j] == 2) counter++;
if (checks[i + j] == CHECKED_EXPLICITLY) counter++;
if (counter >= freq.getNumerator())
if (checks[i] != Checkmark.CHECKED_EXPLICITLY)
checks[i] = Checkmark.CHECKED_IMPLICITLY;
if (checks[i] != CHECKED_EXPLICITLY)
checks[i] = CHECKED_IMPLICITLY;
}
List<Checkmark> checkmarks = new LinkedList<>();

@ -274,4 +274,11 @@ public class Habit
.append("archived", archived)
.toString();
}
public void invalidateNewerThan(long timestamp)
{
getScores().invalidateNewerThan(timestamp);
getCheckmarks().invalidateNewerThan(timestamp);
getStreaks().invalidateNewerThan(timestamp);
}
}

@ -30,6 +30,8 @@ public final class Repetition
private final long timestamp;
private final int value;
/**
* Creates a new repetition with given parameters.
* <p>
@ -38,9 +40,24 @@ public final class Repetition
*
* @param timestamp the time this repetition occurred.
*/
public Repetition(long timestamp)
public Repetition(long timestamp, int value)
{
this.timestamp = timestamp;
this.value = value;
}
@Override
public boolean equals(Object o)
{
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Repetition that = (Repetition) o;
return new EqualsBuilder()
.append(timestamp, that.timestamp)
.append(value, that.value)
.isEquals();
}
public long getTimestamp()
@ -48,11 +65,26 @@ public final class Repetition
return timestamp;
}
public int getValue()
{
return value;
}
@Override
public int hashCode()
{
return new HashCodeBuilder(17, 37)
.append(timestamp)
.append(value)
.toHashCode();
}
@Override
public String toString()
{
return new ToStringBuilder(this)
.append("timestamp", timestamp)
.append("value", value)
.toString();
}
}

@ -192,13 +192,11 @@ public abstract class RepetitionList
if (rep != null) remove(rep);
else
{
rep = new Repetition(timestamp);
rep = new Repetition(timestamp, Checkmark.CHECKED_EXPLICITLY);
add(rep);
}
habit.getScores().invalidateNewerThan(timestamp);
habit.getCheckmarks().invalidateNewerThan(timestamp);
habit.getStreaks().invalidateNewerThan(timestamp);
habit.invalidateNewerThan(timestamp);
return rep;
}

@ -86,7 +86,6 @@ public class MemoryRepetitionList extends RepetitionList
oldestRep = rep;
oldestTime = rep.getTimestamp();
}
}
return oldestRep;
@ -106,7 +105,6 @@ public class MemoryRepetitionList extends RepetitionList
newestRep = rep;
newestTime = rep.getTimestamp();
}
}
return newestRep;
@ -119,7 +117,6 @@ public class MemoryRepetitionList extends RepetitionList
observable.notifyListeners();
}
@NonNull
@Override
public long getTotalCount()
{

@ -73,7 +73,7 @@ public class SQLiteRepetitionList extends RepetitionList
public List<Repetition> getByInterval(long timeFrom, long timeTo)
{
check(habit.getId());
String query = "select habit, timestamp " +
String query = "select habit, timestamp, value " +
"from Repetitions " +
"where habit = ? and timestamp >= ? and timestamp <= ? " +
"order by timestamp";
@ -93,7 +93,7 @@ public class SQLiteRepetitionList extends RepetitionList
public Repetition getByTimestamp(long timestamp)
{
check(habit.getId());
String query = "select habit, timestamp " +
String query = "select habit, timestamp, value " +
"from Repetitions " +
"where habit = ? and timestamp = ? " +
"limit 1";
@ -111,7 +111,7 @@ public class SQLiteRepetitionList extends RepetitionList
public Repetition getOldest()
{
check(habit.getId());
String query = "select habit, timestamp " +
String query = "select habit, timestamp, value " +
"from Repetitions " +
"where habit = ? " +
"order by timestamp asc " +
@ -129,7 +129,7 @@ public class SQLiteRepetitionList extends RepetitionList
public Repetition getNewest()
{
check(habit.getId());
String query = "select habit, timestamp " +
String query = "select habit, timestamp, value " +
"from Repetitions " +
"where habit = ? " +
"order by timestamp desc " +
@ -182,7 +182,6 @@ public class SQLiteRepetitionList extends RepetitionList
return reps;
}
@NonNull
@Override
public long getTotalCount()
{

@ -38,6 +38,9 @@ public class RepetitionRecord extends Model implements SQLiteRecord
@Column(name = "timestamp")
public Long timestamp;
@Column(name = "value")
public int value;
public static RepetitionRecord get(Long id)
{
return RepetitionRecord.load(RepetitionRecord.class, id);
@ -46,16 +49,18 @@ public class RepetitionRecord extends Model implements SQLiteRecord
public void copyFrom(Repetition repetition)
{
timestamp = repetition.getTimestamp();
value = repetition.getValue();
}
@Override
public void copyFrom(Cursor c)
{
timestamp = c.getLong(1);
value = c.getInt(2);
}
public Repetition toRepetition()
{
return new Repetition(timestamp);
return new Repetition(timestamp, value);
}
}

@ -0,0 +1,70 @@
/*
* 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.commands;
import org.isoron.uhabits.*;
import org.isoron.uhabits.models.*;
import org.isoron.uhabits.utils.*;
import org.junit.*;
import static junit.framework.Assert.*;
import static org.isoron.uhabits.models.Checkmark.CHECKED_EXPLICITLY;
public class CreateRepetitionCommandTest extends BaseUnitTest
{
private CreateRepetitionCommand command;
private Habit habit;
private long today;
@Override
@Before
public void setUp()
{
super.setUp();
habit = fixtures.createShortHabit();
today = DateUtils.getStartOfToday();
command = new CreateRepetitionCommand(habit, today, 100);
}
@Test
public void testExecuteUndoRedo()
{
RepetitionList reps = habit.getRepetitions();
Repetition rep = reps.getByTimestamp(today);
assertNotNull(rep);
assertEquals(CHECKED_EXPLICITLY, rep.getValue());
command.execute();
rep = reps.getByTimestamp(today);
assertNotNull(rep);
assertEquals(100, rep.getValue());
command.undo();
rep = reps.getByTimestamp(today);
assertNotNull(rep);
assertEquals(CHECKED_EXPLICITLY, rep.getValue());
}
}
Loading…
Cancel
Save