diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/StreakChart.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/StreakChart.java index 705537ba4..ba0e4ece1 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/StreakChart.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/activities/common/views/StreakChart.java @@ -99,12 +99,14 @@ public class StreakChart extends View { Timestamp start = DateUtils.getToday(); LinkedList streaks = new LinkedList<>(); + Random random = new Random(); for (int i = 0; i < 10; i++) { - int length = new Random().nextInt(100); + int length = random.nextInt(100); + int skipDays = random.nextInt(Math.max(0, length - 2)); Timestamp end = start.plus(length); - streaks.add(new Streak(start, end)); + streaks.add(new Streak(start, end, skipDays)); start = end.plus(1); } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Streak.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Streak.java index 4a66bed7a..486d25abd 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Streak.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/Streak.java @@ -29,10 +29,13 @@ public final class Streak private final Timestamp end; - public Streak(Timestamp start, Timestamp end) + private final int skipDays; + + public Streak(Timestamp start, Timestamp end, int skipDays) { this.start = start; this.end = end; + this.skipDays = skipDays; } public int compareLonger(Streak other) @@ -55,7 +58,7 @@ public final class Streak public int getLength() { - return start.daysUntil(end) + 1; + return start.daysUntil(end) + 1 - skipDays; } public Timestamp getStart() @@ -69,6 +72,7 @@ public final class Streak return new ToStringBuilder(this, defaultToStringStyle()) .append("start", start) .append("end", end) + .append("skipDays", skipDays) .toString(); } @@ -84,6 +88,7 @@ public final class Streak return new EqualsBuilder() .append(start, streak.start) .append(end, streak.end) + .append(skipDays, streak.skipDays) .isEquals(); } @@ -93,6 +98,7 @@ public final class Streak return new HashCodeBuilder(17, 37) .append(start) .append(end) + .append(skipDays) .toHashCode(); } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/StreakList.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/StreakList.java index 464ab7f27..ba5245f2c 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/StreakList.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/models/StreakList.java @@ -89,84 +89,69 @@ public abstract class StreakList @NonNull protected List checkmarksToStreaks(Timestamp beginning, int[] checks) { - ArrayList transitions = getTransitions(beginning, checks); - List streaks = new LinkedList<>(); - for (int i = 0; i < transitions.size(); i += 2) - { - Timestamp start = transitions.get(i); - Timestamp end = transitions.get(i + 1); - streaks.add(new Streak(start, end)); - } - - return streaks; - } - - /** - * Finds the place where we should start when recomputing the streaks. - * - * @return - */ - @Nullable - protected Timestamp findBeginning() - { - Streak newestStreak = getNewestComputed(); - if (newestStreak != null) return newestStreak.getStart(); - - Repetition oldestRep = habit.getRepetitions().getOldestSuccessful(); - if (oldestRep != null) return oldestRep.getTimestamp(); - return null; - } - - /** - * Returns the timestamps where there was a transition from performing a - * habit to not performing a habit, and vice-versa. - * - * @param beginning the timestamp for the first checkmark - * @param checks the checkmarks, ordered by decreasing timestamp - * @return the list of transitions - */ - @NonNull - protected ArrayList getTransitions(Timestamp beginning, int[] checks) - { - ArrayList list = new ArrayList<>(); Timestamp current = beginning; Timestamp lastChecked = beginning; + Timestamp streakStart = beginning; boolean isInStreak = false; + int skipDaysInStreak = 0; for (int i = checks.length - 1; i >= 0; --i) { boolean isCurrentChecked = ( checks[i] == Checkmark.CHECKED_EXPLICITLY || - checks[i] == Checkmark.CHECKED_IMPLICITLY || - checks[i] == Checkmark.UNCHECKED_EXPLICITLY_UNNECESSARY + checks[i] == Checkmark.CHECKED_IMPLICITLY || + checks[i] == Checkmark.UNCHECKED_EXPLICITLY_UNNECESSARY ); boolean isCurrentUnchecked= ( checks[i] == Checkmark.UNCHECKED || - checks[i] == Checkmark.UNCHECKED_EXPLICITLY_NECESSARY + checks[i] == Checkmark.UNCHECKED_EXPLICITLY_NECESSARY ); if (habit.getData().type == Habit.NUMBER_HABIT || isCurrentChecked) lastChecked = current; - if (isInStreak && isCurrentUnchecked) + if (isInStreak && checks[i] == Checkmark.SKIPPED_EXPLICITLY) + skipDaysInStreak += 1; + else if (isInStreak && isCurrentUnchecked) { - list.add(lastChecked); + skipDaysInStreak -= lastChecked.daysUntil(current) - 1; + streaks.add(new Streak(streakStart, lastChecked, skipDaysInStreak)); isInStreak = false; } - if (!isInStreak && isCurrentChecked) + else if (!isInStreak && isCurrentChecked) { - list.add(current); + streakStart = current; isInStreak = true; + skipDaysInStreak = 0; } current = current.plus(1); } if (isInStreak) - list.add(lastChecked); + { + skipDaysInStreak -= lastChecked.daysUntil(current) - 1; + streaks.add(new Streak(streakStart, lastChecked, skipDaysInStreak)); + } - return list; + return streaks; + } + + /** + * Finds the place where we should start when recomputing the streaks. + * + * @return + */ + @Nullable + protected Timestamp findBeginning() + { + Streak newestStreak = getNewestComputed(); + if (newestStreak != null) return newestStreak.getStart(); + + Repetition oldestRep = habit.getRepetitions().getOldestSuccessful(); + if (oldestRep != null) return oldestRep.getTimestamp(); + return null; } protected abstract void add(@NonNull List streaks); diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/StreakListTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/StreakListTest.java index d970419c6..66f1f8bb9 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/StreakListTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/models/StreakListTest.java @@ -122,8 +122,8 @@ public class StreakListTest extends BaseUnitTest public void testToString() throws Exception { Timestamp time = Timestamp.ZERO.plus(100); - Streak streak = new Streak(time, time.plus(10)); + Streak streak = new Streak(time, time.plus(10), 3); assertThat(streak.toString(), equalTo( - "{start: 1970-04-11, end: 1970-04-21}")); + "{start: 1970-04-11, end: 1970-04-21, skipDays: 3}")); } } \ No newline at end of file