From 08113a57ace0f875a8d9c839c7a48d8896f4f6b4 Mon Sep 17 00:00:00 2001 From: Dharanish Date: Tue, 25 Jun 2024 12:06:40 +0200 Subject: [PATCH] Remove SkipDays feature --- .../habits/show/views/SubtitleCardView.kt | 7 ---- .../org/isoron/uhabits/core/models/Habit.kt | 23 ++++++++++- .../isoron/uhabits/core/models/ScoreList.kt | 17 +++++++- .../isoron/uhabits/core/models/SkipDays.kt | 41 ------------------- .../core/models/sqlite/records/HabitRecord.kt | 10 +++++ .../screens/habits/show/views/HistoryCard.kt | 4 +- .../screens/habits/show/views/SubtitleCard.kt | 3 -- .../screens/habits/show/views/TargetCard.kt | 40 ++++++++---------- 8 files changed, 64 insertions(+), 81 deletions(-) delete mode 100644 uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/SkipDays.kt diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt index 5e49755be..c29894c18 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/activities/habits/show/views/SubtitleCardView.kt @@ -33,7 +33,6 @@ import org.isoron.uhabits.core.ui.screens.habits.show.views.SubtitleCardState import org.isoron.uhabits.databinding.ShowHabitSubtitleBinding import org.isoron.uhabits.utils.InterfaceUtils import org.isoron.uhabits.utils.formatTime -import org.isoron.uhabits.utils.toFormattedString class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { @@ -79,12 +78,6 @@ class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(con if (state.question.isEmpty()) { binding.questionLabel.visibility = View.GONE } - if (state.skipDays.isSkipDays) { - binding.skipLabel.visibility = View.VISIBLE - binding.skipLabel.text = context.getString(R.string.skip_day) + " " + state.skipDays.days.toFormattedString(context) - } else { - binding.skipLabel.visibility = View.GONE - } postInvalidate() } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt index a06d01ec9..ff57e823e 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/Habit.kt @@ -39,12 +39,15 @@ data class Habit( val computedEntries: EntryList, val originalEntries: EntryList, val scores: ScoreList, - val streaks: StreakList + val streaks: StreakList, + var parentID: Long? = null, + var parentUUID: String? = null ) { init { if (uuid == null) this.uuid = UUID.randomUUID().toString().replace("-", "") } + var parent: HabitGroup? = null var observable = ModelObservable() val isNumerical: Boolean @@ -104,6 +107,18 @@ data class Habit( ) } + fun firstEntryDate(): Timestamp { + return computedEntries.getKnown().lastOrNull()?.timestamp ?: DateUtils.getTodayWithOffset() + } + + fun hierarchyLevel(): Int { + return if (parentID == null) { + 0 + } else { + 1 + parent!!.hierarchyLevel() + } + } + fun copyFrom(other: Habit) { this.color = other.color this.description = other.description @@ -119,6 +134,8 @@ data class Habit( this.type = other.type this.unit = other.unit this.uuid = other.uuid + this.parentID = other.parentID + this.parentUUID = other.parentUUID } override fun equals(other: Any?): Boolean { @@ -139,6 +156,8 @@ data class Habit( if (type != other.type) return false if (unit != other.unit) return false if (uuid != other.uuid) return false + if (parentID != other.parentID) return false + if (parentUUID != other.parentUUID) return false return true } @@ -158,6 +177,8 @@ data class Habit( result = 31 * result + type.value result = 31 * result + unit.hashCode() result = 31 * result + (uuid?.hashCode() ?: 0) + result = 31 * result + (parentID?.hashCode() ?: 0) + result = 31 * result + (parentUUID?.hashCode() ?: 0) return result } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt index 3acc19e1c..bc6d139a1 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/ScoreList.kt @@ -19,8 +19,6 @@ package org.isoron.uhabits.core.models import org.isoron.uhabits.core.models.Score.Companion.compute -import java.util.ArrayList -import java.util.HashMap import javax.annotation.concurrent.ThreadSafe import kotlin.math.max import kotlin.math.min @@ -138,4 +136,19 @@ class ScoreList { map[timestamp] = Score(timestamp, previousValue) } } + + @Synchronized + fun combineFrom( + habitList: HabitList, + from: Timestamp, + to: Timestamp + ) { + var current = to + while (current >= from) { + val habitScores = habitList.map { it.scores[current].value } + val averageScore = habitScores.average() + map[current] = Score(current, averageScore) + current = current.minus(1) + } + } } diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/SkipDays.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/SkipDays.kt deleted file mode 100644 index 4d386fe59..000000000 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/SkipDays.kt +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2016-2021 Álinson Santos Xavier - * - * 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 . - */ -package org.isoron.uhabits.core.models - -data class SkipDays( - val isSkipDays: Boolean, - val days: WeekdayList -) { - fun isDaySkipped(day: Int): Boolean { - return isSkipDays && days.isDayTrue(day) - } - - fun isDaySkipped(day: Timestamp): Boolean { - return isSkipDays && days.isDayTrue(day.weekday) - } - - fun isDaySkipped(entry: Entry): Boolean { - return isSkipDays && days.isDayTrue(entry.timestamp.weekday) - } - - companion object { - @JvmField - val NONE = SkipDays(false, WeekdayList(0)) - } -} diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.kt index dc0386799..0a61f65f0 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/models/sqlite/records/HabitRecord.kt @@ -88,6 +88,12 @@ class HabitRecord { @field:Column var uuid: String? = null + @field:Column(name = "parent_id") + var parentID: Long? = null + + @field:Column(name = "parent_uuid") + var parentUUID: String? = null + fun copyFrom(model: Habit) { id = model.id name = model.name @@ -102,6 +108,8 @@ class HabitRecord { position = model.position question = model.question uuid = model.uuid + parentID = model.parentID + parentUUID = model.parentUUID val (numerator, denominator) = model.frequency freqNum = numerator freqDen = denominator @@ -130,6 +138,8 @@ class HabitRecord { habit.unit = unit!! habit.position = position!! habit.uuid = uuid + habit.parentID = parentID + habit.parentUUID = parentUUID if (reminderHour != null && reminderMin != null) { habit.reminder = Reminder( reminderHour!!, diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt index 73f7be416..0a28c801f 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/HistoryCard.kt @@ -67,7 +67,6 @@ class HistoryCardPresenter( override fun onDateLongPress(date: LocalDate) { val timestamp = Timestamp.fromLocalDate(date) screen.showFeedback() - if (habit.skipDays.isDaySkipped(timestamp)) return if (habit.isNumerical) { showNumberPopup(timestamp) } else { @@ -82,7 +81,6 @@ class HistoryCardPresenter( override fun onDateShortPress(date: LocalDate) { val timestamp = Timestamp.fromLocalDate(date) screen.showFeedback() - if (habit.skipDays.isDaySkipped(timestamp)) return if (habit.isNumerical) { showNumberPopup(timestamp) } else { @@ -163,7 +161,7 @@ class HistoryCardPresenter( ): HistoryCardState { val today = DateUtils.getTodayWithOffset() val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today - val entries = habit.computedEntries.getByInterval(oldest, today, habit.skipDays) + val entries = habit.computedEntries.getByInterval(oldest, today) val series = if (habit.isNumerical) { entries.map { when { diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt index 01784e2f2..fb839933c 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/SubtitleCard.kt @@ -24,14 +24,12 @@ import org.isoron.uhabits.core.models.Habit import org.isoron.uhabits.core.models.NumericalHabitType import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.Reminder -import org.isoron.uhabits.core.models.SkipDays import org.isoron.uhabits.core.ui.views.Theme data class SubtitleCardState( val color: PaletteColor, val frequency: Frequency, val isNumerical: Boolean, - val skipDays: SkipDays, val question: String, val reminder: Reminder?, val targetValue: Double = 0.0, @@ -49,7 +47,6 @@ class SubtitleCardPresenter { color = habit.color, frequency = habit.frequency, isNumerical = habit.isNumerical, - skipDays = habit.skipDays, question = habit.question, reminder = habit.reminder, targetValue = habit.targetValue, diff --git a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/TargetCard.kt b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/TargetCard.kt index 43a240dc6..f137de23e 100644 --- a/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/TargetCard.kt +++ b/uhabits-core/src/jvmMain/java/org/isoron/uhabits/core/ui/screens/habits/show/views/TargetCard.kt @@ -26,7 +26,6 @@ import org.isoron.uhabits.core.models.countSkippedDays import org.isoron.uhabits.core.models.groupedSum import org.isoron.uhabits.core.ui.views.Theme import org.isoron.uhabits.core.utils.DateUtils -import java.util.ArrayList import java.util.Calendar import kotlin.math.max @@ -46,61 +45,54 @@ class TargetCardPresenter { theme: Theme ): TargetCardState { val today = DateUtils.getTodayWithOffset() - val (yearBegin, yearEnd) = getYearRange(firstWeekday) val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today - val entriesForSkip = habit.computedEntries.getByInterval(yearBegin, yearEnd, habit.skipDays) - val entriesForSum = habit.computedEntries.getByInterval(oldest, today) + val entries = habit.computedEntries.getByInterval(oldest, today) - val valueToday = entriesForSum.groupedSum( + val valueToday = entries.groupedSum( truncateField = DateUtils.TruncateField.DAY, isNumerical = habit.isNumerical ).firstOrNull()?.value ?: 0 - val skippedDayToday = entriesForSkip.countSkippedDays( - truncateField = DateUtils.TruncateField.DAY, - skipDays = habit.skipDays + val skippedDayToday = entries.countSkippedDays( + truncateField = DateUtils.TruncateField.DAY ).firstOrNull()?.value ?: 0 - val valueThisWeek = entriesForSum.groupedSum( + val valueThisWeek = entries.groupedSum( truncateField = DateUtils.TruncateField.WEEK_NUMBER, firstWeekday = firstWeekday, isNumerical = habit.isNumerical ).firstOrNull()?.value ?: 0 - val skippedDaysThisWeek = entriesForSkip.countSkippedDays( + val skippedDaysThisWeek = entries.countSkippedDays( truncateField = DateUtils.TruncateField.WEEK_NUMBER, - firstWeekday = firstWeekday, - skipDays = habit.skipDays + firstWeekday = firstWeekday ).firstOrNull()?.value ?: 0 - val valueThisMonth = entriesForSum.groupedSum( + val valueThisMonth = entries.groupedSum( truncateField = DateUtils.TruncateField.MONTH, isNumerical = habit.isNumerical ).firstOrNull()?.value ?: 0 - val skippedDaysThisMonth = entriesForSkip.countSkippedDays( - truncateField = DateUtils.TruncateField.MONTH, - skipDays = habit.skipDays + val skippedDaysThisMonth = entries.countSkippedDays( + truncateField = DateUtils.TruncateField.MONTH ).firstOrNull()?.value ?: 0 - val valueThisQuarter = entriesForSum.groupedSum( + val valueThisQuarter = entries.groupedSum( truncateField = DateUtils.TruncateField.QUARTER, isNumerical = habit.isNumerical ).firstOrNull()?.value ?: 0 - val skippedDaysThisQuarter = entriesForSkip.countSkippedDays( - truncateField = DateUtils.TruncateField.QUARTER, - skipDays = habit.skipDays + val skippedDaysThisQuarter = entries.countSkippedDays( + truncateField = DateUtils.TruncateField.QUARTER ).firstOrNull()?.value ?: 0 - val valueThisYear = entriesForSum.groupedSum( + val valueThisYear = entries.groupedSum( truncateField = DateUtils.TruncateField.YEAR, isNumerical = habit.isNumerical ).firstOrNull()?.value ?: 0 - val skippedDaysThisYear = entriesForSkip.countSkippedDays( - truncateField = DateUtils.TruncateField.YEAR, - skipDays = habit.skipDays + val skippedDaysThisYear = entries.countSkippedDays( + truncateField = DateUtils.TruncateField.YEAR ).firstOrNull()?.value ?: 0 val cal = DateUtils.getStartOfTodayCalendarWithOffset()