V1 of skip days

pull/610/head
KristianTashkov 5 years ago
parent 34c73e89db
commit 3cff51ea42

@ -362,6 +362,7 @@ public class HistoryChart extends ScrollableChart
GregorianCalendar date,
int checkmarkOffset)
{
pSquareFg.setStrikeThruText(false);
if (checkmarkOffset >= checkmarks.length) pSquareBg.setColor(colors[0]);
else
{
@ -371,13 +372,18 @@ public class HistoryChart extends ScrollableChart
{
pSquareBg.setColor(isNumerical ? textColor : colors[1]);
}
else if (!isNumerical && checkmark == 3) {
pSquareFg.setStrikeThruText(true);
pSquareBg.setColor(colors[1]);
}
else pSquareBg.setColor(colors[2]);
}
pSquareFg.setColor(reverseTextColor);
float round = dpToPixels(getContext(), 2);
canvas.drawRoundRect(location, round, round, pSquareBg);
String text = Integer.toString(date.get(Calendar.DAY_OF_MONTH));
String text = Integer.toString(date.get(Calendar.DAY_OF_MONTH)) ;
canvas.drawText(text, location.centerX(),
location.centerY() + squareTextOffset, pSquareFg);
}

@ -63,7 +63,8 @@ class CheckmarkButtonView(
fun performToggle() {
onToggle()
value = when (value) {
CHECKED_EXPLICITLY -> UNCHECKED
CHECKED_EXPLICITLY -> SKIPPED_EXPLICITLY
SKIPPED_EXPLICITLY -> UNCHECKED
else -> CHECKED_EXPLICITLY
}
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
@ -95,6 +96,9 @@ class CheckmarkButtonView(
private inner class Drawer {
private val rect = RectF()
private val lowContrastColor = sres.getColor(R.attr.lowContrastTextColor)
private val mediumContrastTextColor = sres.getColor(R.attr.mediumContrastTextColor)
private val paint = TextPaint().apply {
typeface = getFontAwesome()
@ -106,9 +110,11 @@ class CheckmarkButtonView(
fun draw(canvas: Canvas) {
paint.color = when (value) {
CHECKED_EXPLICITLY -> color
SKIPPED_EXPLICITLY -> mediumContrastTextColor
else -> lowContrastColor
}
val id = when (value) {
SKIPPED_EXPLICITLY -> R.string.fa_skipped
UNCHECKED -> R.string.fa_times
else -> R.string.fa_check
}

@ -160,7 +160,7 @@ public class OverviewCard extends HabitCard
cache.todayScore = (float) scores.getTodayValue();
cache.lastMonthScore = (float) scores.getValue(lastMonth);
cache.lastYearScore = (float) scores.getValue(lastYear);
cache.totalCount = habit.getRepetitions().getTotalCount();
cache.totalCount = habit.getRepetitions().getTotalSuccessfulCount();
}
@Override

@ -21,6 +21,7 @@
<resources>
<string translatable="false" name="fa_star_half_o">&#xf123;</string>
<string translatable="false" name="fa_arrow_circle_up">&#xf0aa;</string>
<string translatable="false" name="fa_skipped">&#xf101;</string>
<string translatable="false" name="fa_check">&#xf00c;</string>
<string translatable="false" name="fa_times">&#xf00d;</string>
<string translatable="false" name="fa_bell_o">&#xf0a2;</string>

@ -70,6 +70,7 @@ public class ToggleRepetitionCommand extends Command
public void undo()
{
execute();
execute();
}
public static class Record

@ -37,6 +37,11 @@ import static org.isoron.uhabits.core.utils.StringUtils.defaultToStringStyle;
@ThreadSafe
public final class Checkmark
{
/**
* Indicates that there was an explicit skip at the timestamp.
*/
public static final int SKIPPED_EXPLICITLY = 3;
/**
* Indicates that there was a repetition at the timestamp.
*/
@ -59,7 +64,7 @@ public final class Checkmark
/**
* The value of the checkmark.
* <p>
* For boolean habits, this equals either UNCHECKED, CHECKED_EXPLICITLY,
* For boolean habits, this equals either UNCHECKED, SKIPPED_EXPLICITLY, CHECKED_EXPLICITLY,
* or CHECKED_IMPLICITLY.
* <p>
* For numerical habits, this number is stored in thousandths. That

@ -79,7 +79,7 @@ public abstract class CheckmarkList
{
Timestamp date = rep.getTimestamp();
int offset = date.daysUntil(today);
checkmarks.set(offset, new Checkmark(date, CHECKED_EXPLICITLY));
checkmarks.set(offset, new Checkmark(date, rep.getValue()));
}
return checkmarks;
@ -379,7 +379,14 @@ public abstract class CheckmarkList
private void computeYesNo(Repetition[] reps)
{
ArrayList<Interval> intervals;
intervals = buildIntervals(habit.getFrequency(), reps);
List<Repetition> successful_repetitions = new ArrayList<>();
for (Repetition rep : reps) {
if (rep.getValue() != SKIPPED_EXPLICITLY) {
successful_repetitions.add(rep);
}
}
intervals = buildIntervals(
habit.getFrequency(), successful_repetitions.toArray(new Repetition[0]));
snapIntervalsTogether(intervals);
add(buildCheckmarksFromIntervals(reps, intervals));
}

@ -30,7 +30,7 @@ import java.util.GregorianCalendar;
import static org.isoron.uhabits.core.utils.StringUtils.defaultToStringStyle;
/**
* Represents a record that the user has performed a certain habit at a certain
* Represents a record that the user has performed or skipped a certain habit at a certain
* date.
*/
public final class Repetition
@ -41,7 +41,8 @@ public final class Repetition
/**
* The value of the repetition.
*
* For boolean habits, this always equals Checkmark.CHECKED_EXPLICITLY.
* For boolean habits, this equals Checkmark.CHECKED_EXPLICITLY if performed
* or Checkmark.SKIPPED_EXPLICITLY if skipped.
* For numerical habits, this number is stored in thousandths. That
* is, if the user enters value 1.50 on the app, it is here stored as 1500.
*/

@ -119,15 +119,15 @@ public abstract class RepetitionList
public abstract Repetition getNewest();
/**
* Returns the total number of repetitions for each month, from the first
* Returns the total number of successful repetitions for each month, from the first
* repetition until today, grouped by day of week.
* <p>
* The repetitions are returned in a HashMap. The key is the timestamp for
* the first day of the month, at midnight (00:00). The value is an integer
* array with 7 entries. The first entry contains the total number of
* repetitions during the specified month that occurred on a Saturday. The
* successful repetitions during the specified month that occurred on a Saturday. The
* second entry corresponds to Sunday, and so on. If there are no
* repetitions during a certain month, the value is null.
* successful repetitions during a certain month, the value is null.
*
* @return total number of repetitions by month versus day of week
*/
@ -140,6 +140,11 @@ public abstract class RepetitionList
for (Repetition r : reps)
{
if ((habit.getData().type == Habit.YES_NO_HABIT)
&& (r.getValue() == Checkmark.SKIPPED_EXPLICITLY)) {
continue;
}
Calendar date = r.getTimestamp().toCalendar();
int weekday = r.getTimestamp().getWeekday();
date.set(Calendar.DAY_OF_MONTH, 1);
@ -191,7 +196,13 @@ public abstract class RepetitionList
throw new IllegalStateException("habit must NOT be numerical");
Repetition rep = getByTimestamp(timestamp);
if (rep != null) remove(rep);
if (rep != null) {
remove(rep);
if (rep.getValue() == Checkmark.CHECKED_EXPLICITLY) {
rep = new Repetition(timestamp, Checkmark.SKIPPED_EXPLICITLY);
add(rep);
}
}
else
{
rep = new Repetition(timestamp, Checkmark.CHECKED_EXPLICITLY);
@ -203,12 +214,12 @@ public abstract class RepetitionList
}
/**
* Returns the number of all repetitions
* Returns the number of all successful repetitions
*
* @return number of all repetitions
* @return number of all successful repetitions
*/
@NonNull
public abstract long getTotalCount();
public abstract long getTotalSuccessfulCount();
public void toggle(Timestamp timestamp, int value)
{

@ -283,9 +283,13 @@ public abstract class ScoreList implements Iterable<Score>
value = Math.min(1, value);
}
if (!habit.isNumerical() && value > 0) value = 1;
if (!habit.isNumerical() & value > 0) {
value = value != Checkmark.SKIPPED_EXPLICITLY ? 1 : -1;
}
if (value > -1) {
previousValue = Score.compute(freq, previousValue, value);
}
scores.add(new Score(from.plus(i), previousValue));
}

@ -119,9 +119,15 @@ public class MemoryRepetitionList extends RepetitionList
}
@Override
public long getTotalCount()
public long getTotalSuccessfulCount()
{
return list.size();
int count = 0;
for (Repetition rep : list) {
if (rep.getValue() != Checkmark.SKIPPED_EXPLICITLY) {
++count;
}
}
return count;
}
@Override

@ -129,10 +129,10 @@ public class SQLiteRepetitionList extends RepetitionList
}
@Override
public long getTotalCount()
public long getTotalSuccessfulCount()
{
loadRecords();
return list.getTotalCount();
return list.getTotalSuccessfulCount();
}
public void reload()

@ -53,11 +53,19 @@ public class ToggleRepetitionCommandTest extends BaseUnitTest
{
assertTrue(habit.getRepetitions().containsTimestamp(today));
command.execute();
assertEquals(
habit.getRepetitions().getByTimestamp(today).getValue(),
Checkmark.SKIPPED_EXPLICITLY
);
command.execute();
assertFalse(habit.getRepetitions().containsTimestamp(today));
command.undo();
assertTrue(habit.getRepetitions().containsTimestamp(today));
assertEquals(
habit.getRepetitions().getByTimestamp(today).getValue(),
Checkmark.SKIPPED_EXPLICITLY
);
command.execute();
assertFalse(habit.getRepetitions().containsTimestamp(today));

@ -31,6 +31,7 @@ import static java.util.Calendar.*;
import static junit.framework.TestCase.assertFalse;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.IsEqual.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.*;
@ -157,16 +158,20 @@ public class RepetitionListTest extends BaseUnitTest
@Test
public void test_toggle()
{
assertTrue(reps.containsTimestamp(today));
assertEquals(reps.getByTimestamp(today).getValue(), Checkmark.CHECKED_EXPLICITLY);
reps.toggle(today);
assertEquals(reps.getByTimestamp(today).getValue(), Checkmark.SKIPPED_EXPLICITLY);
reps.toggle(today);
assertFalse(reps.containsTimestamp(today));
verify(listener).onModelChange();
verify(listener, times(3)).onModelChange();
reset(listener);
assertFalse(reps.containsTimestamp(today.minus(1)));
reps.toggle(today.minus(1));
assertTrue(reps.containsTimestamp(today.minus(1)));
verify(listener).onModelChange();
assertEquals(reps.getByTimestamp(today.minus(1)).getValue(), Checkmark.CHECKED_EXPLICITLY);
reps.toggle(today.minus(1));
assertEquals(reps.getByTimestamp(today.minus(1)).getValue(), Checkmark.SKIPPED_EXPLICITLY);
verify(listener, times(3)).onModelChange();
reset(listener);
habit.setType(Habit.NUMBER_HABIT);

@ -172,6 +172,8 @@ public class ListHabitsBehaviorTest extends BaseUnitTest
@Test
public void testOnToggle()
{
assertTrue(habit1.isCompletedToday());
behavior.onToggle(habit1, DateUtils.getToday());
assertTrue(habit1.isCompletedToday());
behavior.onToggle(habit1, DateUtils.getToday());
assertFalse(habit1.isCompletedToday());

Loading…
Cancel
Save