Remove SkipDays feature

pull/2020/head
Dharanish 1 year ago
parent 2146ce71a0
commit 08113a57ac

@ -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.databinding.ShowHabitSubtitleBinding
import org.isoron.uhabits.utils.InterfaceUtils import org.isoron.uhabits.utils.InterfaceUtils
import org.isoron.uhabits.utils.formatTime import org.isoron.uhabits.utils.formatTime
import org.isoron.uhabits.utils.toFormattedString
class SubtitleCardView(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) { 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()) { if (state.question.isEmpty()) {
binding.questionLabel.visibility = View.GONE 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() postInvalidate()
} }

@ -39,12 +39,15 @@ data class Habit(
val computedEntries: EntryList, val computedEntries: EntryList,
val originalEntries: EntryList, val originalEntries: EntryList,
val scores: ScoreList, val scores: ScoreList,
val streaks: StreakList val streaks: StreakList,
var parentID: Long? = null,
var parentUUID: String? = null
) { ) {
init { init {
if (uuid == null) this.uuid = UUID.randomUUID().toString().replace("-", "") if (uuid == null) this.uuid = UUID.randomUUID().toString().replace("-", "")
} }
var parent: HabitGroup? = null
var observable = ModelObservable() var observable = ModelObservable()
val isNumerical: Boolean 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) { fun copyFrom(other: Habit) {
this.color = other.color this.color = other.color
this.description = other.description this.description = other.description
@ -119,6 +134,8 @@ data class Habit(
this.type = other.type this.type = other.type
this.unit = other.unit this.unit = other.unit
this.uuid = other.uuid this.uuid = other.uuid
this.parentID = other.parentID
this.parentUUID = other.parentUUID
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@ -139,6 +156,8 @@ data class Habit(
if (type != other.type) return false if (type != other.type) return false
if (unit != other.unit) return false if (unit != other.unit) return false
if (uuid != other.uuid) return false if (uuid != other.uuid) return false
if (parentID != other.parentID) return false
if (parentUUID != other.parentUUID) return false
return true return true
} }
@ -158,6 +177,8 @@ data class Habit(
result = 31 * result + type.value result = 31 * result + type.value
result = 31 * result + unit.hashCode() result = 31 * result + unit.hashCode()
result = 31 * result + (uuid?.hashCode() ?: 0) result = 31 * result + (uuid?.hashCode() ?: 0)
result = 31 * result + (parentID?.hashCode() ?: 0)
result = 31 * result + (parentUUID?.hashCode() ?: 0)
return result return result
} }
} }

@ -19,8 +19,6 @@
package org.isoron.uhabits.core.models package org.isoron.uhabits.core.models
import org.isoron.uhabits.core.models.Score.Companion.compute import org.isoron.uhabits.core.models.Score.Companion.compute
import java.util.ArrayList
import java.util.HashMap
import javax.annotation.concurrent.ThreadSafe import javax.annotation.concurrent.ThreadSafe
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
@ -138,4 +136,19 @@ class ScoreList {
map[timestamp] = Score(timestamp, previousValue) 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)
}
}
} }

@ -1,41 +0,0 @@
/*
* Copyright (C) 2016-2021 Álinson Santos Xavier <git@axavier.org>
*
* 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.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))
}
}

@ -88,6 +88,12 @@ class HabitRecord {
@field:Column @field:Column
var uuid: String? = null 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) { fun copyFrom(model: Habit) {
id = model.id id = model.id
name = model.name name = model.name
@ -102,6 +108,8 @@ class HabitRecord {
position = model.position position = model.position
question = model.question question = model.question
uuid = model.uuid uuid = model.uuid
parentID = model.parentID
parentUUID = model.parentUUID
val (numerator, denominator) = model.frequency val (numerator, denominator) = model.frequency
freqNum = numerator freqNum = numerator
freqDen = denominator freqDen = denominator
@ -130,6 +138,8 @@ class HabitRecord {
habit.unit = unit!! habit.unit = unit!!
habit.position = position!! habit.position = position!!
habit.uuid = uuid habit.uuid = uuid
habit.parentID = parentID
habit.parentUUID = parentUUID
if (reminderHour != null && reminderMin != null) { if (reminderHour != null && reminderMin != null) {
habit.reminder = Reminder( habit.reminder = Reminder(
reminderHour!!, reminderHour!!,

@ -67,7 +67,6 @@ class HistoryCardPresenter(
override fun onDateLongPress(date: LocalDate) { override fun onDateLongPress(date: LocalDate) {
val timestamp = Timestamp.fromLocalDate(date) val timestamp = Timestamp.fromLocalDate(date)
screen.showFeedback() screen.showFeedback()
if (habit.skipDays.isDaySkipped(timestamp)) return
if (habit.isNumerical) { if (habit.isNumerical) {
showNumberPopup(timestamp) showNumberPopup(timestamp)
} else { } else {
@ -82,7 +81,6 @@ class HistoryCardPresenter(
override fun onDateShortPress(date: LocalDate) { override fun onDateShortPress(date: LocalDate) {
val timestamp = Timestamp.fromLocalDate(date) val timestamp = Timestamp.fromLocalDate(date)
screen.showFeedback() screen.showFeedback()
if (habit.skipDays.isDaySkipped(timestamp)) return
if (habit.isNumerical) { if (habit.isNumerical) {
showNumberPopup(timestamp) showNumberPopup(timestamp)
} else { } else {
@ -163,7 +161,7 @@ class HistoryCardPresenter(
): HistoryCardState { ): HistoryCardState {
val today = DateUtils.getTodayWithOffset() val today = DateUtils.getTodayWithOffset()
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today 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) { val series = if (habit.isNumerical) {
entries.map { entries.map {
when { when {

@ -24,14 +24,12 @@ import org.isoron.uhabits.core.models.Habit
import org.isoron.uhabits.core.models.NumericalHabitType import org.isoron.uhabits.core.models.NumericalHabitType
import org.isoron.uhabits.core.models.PaletteColor import org.isoron.uhabits.core.models.PaletteColor
import org.isoron.uhabits.core.models.Reminder import org.isoron.uhabits.core.models.Reminder
import org.isoron.uhabits.core.models.SkipDays
import org.isoron.uhabits.core.ui.views.Theme import org.isoron.uhabits.core.ui.views.Theme
data class SubtitleCardState( data class SubtitleCardState(
val color: PaletteColor, val color: PaletteColor,
val frequency: Frequency, val frequency: Frequency,
val isNumerical: Boolean, val isNumerical: Boolean,
val skipDays: SkipDays,
val question: String, val question: String,
val reminder: Reminder?, val reminder: Reminder?,
val targetValue: Double = 0.0, val targetValue: Double = 0.0,
@ -49,7 +47,6 @@ class SubtitleCardPresenter {
color = habit.color, color = habit.color,
frequency = habit.frequency, frequency = habit.frequency,
isNumerical = habit.isNumerical, isNumerical = habit.isNumerical,
skipDays = habit.skipDays,
question = habit.question, question = habit.question,
reminder = habit.reminder, reminder = habit.reminder,
targetValue = habit.targetValue, targetValue = habit.targetValue,

@ -26,7 +26,6 @@ import org.isoron.uhabits.core.models.countSkippedDays
import org.isoron.uhabits.core.models.groupedSum import org.isoron.uhabits.core.models.groupedSum
import org.isoron.uhabits.core.ui.views.Theme import org.isoron.uhabits.core.ui.views.Theme
import org.isoron.uhabits.core.utils.DateUtils import org.isoron.uhabits.core.utils.DateUtils
import java.util.ArrayList
import java.util.Calendar import java.util.Calendar
import kotlin.math.max import kotlin.math.max
@ -46,61 +45,54 @@ class TargetCardPresenter {
theme: Theme theme: Theme
): TargetCardState { ): TargetCardState {
val today = DateUtils.getTodayWithOffset() val today = DateUtils.getTodayWithOffset()
val (yearBegin, yearEnd) = getYearRange(firstWeekday)
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
val entriesForSkip = habit.computedEntries.getByInterval(yearBegin, yearEnd, habit.skipDays) val entries = habit.computedEntries.getByInterval(oldest, today)
val entriesForSum = habit.computedEntries.getByInterval(oldest, today)
val valueToday = entriesForSum.groupedSum( val valueToday = entries.groupedSum(
truncateField = DateUtils.TruncateField.DAY, truncateField = DateUtils.TruncateField.DAY,
isNumerical = habit.isNumerical isNumerical = habit.isNumerical
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val skippedDayToday = entriesForSkip.countSkippedDays( val skippedDayToday = entries.countSkippedDays(
truncateField = DateUtils.TruncateField.DAY, truncateField = DateUtils.TruncateField.DAY
skipDays = habit.skipDays
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val valueThisWeek = entriesForSum.groupedSum( val valueThisWeek = entries.groupedSum(
truncateField = DateUtils.TruncateField.WEEK_NUMBER, truncateField = DateUtils.TruncateField.WEEK_NUMBER,
firstWeekday = firstWeekday, firstWeekday = firstWeekday,
isNumerical = habit.isNumerical isNumerical = habit.isNumerical
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val skippedDaysThisWeek = entriesForSkip.countSkippedDays( val skippedDaysThisWeek = entries.countSkippedDays(
truncateField = DateUtils.TruncateField.WEEK_NUMBER, truncateField = DateUtils.TruncateField.WEEK_NUMBER,
firstWeekday = firstWeekday, firstWeekday = firstWeekday
skipDays = habit.skipDays
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val valueThisMonth = entriesForSum.groupedSum( val valueThisMonth = entries.groupedSum(
truncateField = DateUtils.TruncateField.MONTH, truncateField = DateUtils.TruncateField.MONTH,
isNumerical = habit.isNumerical isNumerical = habit.isNumerical
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val skippedDaysThisMonth = entriesForSkip.countSkippedDays( val skippedDaysThisMonth = entries.countSkippedDays(
truncateField = DateUtils.TruncateField.MONTH, truncateField = DateUtils.TruncateField.MONTH
skipDays = habit.skipDays
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val valueThisQuarter = entriesForSum.groupedSum( val valueThisQuarter = entries.groupedSum(
truncateField = DateUtils.TruncateField.QUARTER, truncateField = DateUtils.TruncateField.QUARTER,
isNumerical = habit.isNumerical isNumerical = habit.isNumerical
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val skippedDaysThisQuarter = entriesForSkip.countSkippedDays( val skippedDaysThisQuarter = entries.countSkippedDays(
truncateField = DateUtils.TruncateField.QUARTER, truncateField = DateUtils.TruncateField.QUARTER
skipDays = habit.skipDays
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val valueThisYear = entriesForSum.groupedSum( val valueThisYear = entries.groupedSum(
truncateField = DateUtils.TruncateField.YEAR, truncateField = DateUtils.TruncateField.YEAR,
isNumerical = habit.isNumerical isNumerical = habit.isNumerical
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val skippedDaysThisYear = entriesForSkip.countSkippedDays( val skippedDaysThisYear = entries.countSkippedDays(
truncateField = DateUtils.TruncateField.YEAR, truncateField = DateUtils.TruncateField.YEAR
skipDays = habit.skipDays
).firstOrNull()?.value ?: 0 ).firstOrNull()?.value ?: 0
val cal = DateUtils.getStartOfTodayCalendarWithOffset() val cal = DateUtils.getStartOfTodayCalendarWithOffset()

Loading…
Cancel
Save