mirror of
https://github.com/iSoron/uhabits.git
synced 2025-12-06 01:08:50 -06:00
Migrate Scores to pure Kotlin; display correct score on main screen
This commit is contained in:
@@ -43,6 +43,8 @@ class Backend(databaseName: String,
|
|||||||
|
|
||||||
val checkmarks = mutableMapOf<Habit, CheckmarkList>()
|
val checkmarks = mutableMapOf<Habit, CheckmarkList>()
|
||||||
|
|
||||||
|
val scores = mutableMapOf<Habit, ScoreList>()
|
||||||
|
|
||||||
val mainScreenDataSource: MainScreenDataSource
|
val mainScreenDataSource: MainScreenDataSource
|
||||||
|
|
||||||
val strings = localeHelper.getStringsForCurrentLocale()
|
val strings = localeHelper.getStringsForCurrentLocale()
|
||||||
@@ -68,11 +70,13 @@ class Backend(databaseName: String,
|
|||||||
val checks = checkmarkRepository.findAll(key)
|
val checks = checkmarkRepository.findAll(key)
|
||||||
checkmarks[habit] = CheckmarkList(habit.frequency, habit.type)
|
checkmarks[habit] = CheckmarkList(habit.frequency, habit.type)
|
||||||
checkmarks[habit]?.setManualCheckmarks(checks)
|
checkmarks[habit]?.setManualCheckmarks(checks)
|
||||||
|
scores[habit] = ScoreList(checkmarks[habit]!!)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mainScreenDataSource = MainScreenDataSource(preferences,
|
mainScreenDataSource = MainScreenDataSource(preferences,
|
||||||
habits,
|
habits,
|
||||||
checkmarks,
|
checkmarks,
|
||||||
|
scores,
|
||||||
taskRunner)
|
taskRunner)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,14 +27,15 @@ import org.isoron.uhabits.models.Checkmark.Companion.UNCHECKED
|
|||||||
class MainScreenDataSource(val preferences: Preferences,
|
class MainScreenDataSource(val preferences: Preferences,
|
||||||
val habits: MutableMap<Int, Habit>,
|
val habits: MutableMap<Int, Habit>,
|
||||||
val checkmarks: MutableMap<Habit, CheckmarkList>,
|
val checkmarks: MutableMap<Habit, CheckmarkList>,
|
||||||
|
val scores: MutableMap<Habit, ScoreList>,
|
||||||
val taskRunner: TaskRunner) {
|
val taskRunner: TaskRunner) {
|
||||||
|
|
||||||
val maxNumberOfButtons = 60
|
val maxNumberOfButtons = 60
|
||||||
private val today = LocalDate(2019, 3, 30) /* TODO */
|
private val today = LocalDate(2019, 3, 30) /* TODO */
|
||||||
|
|
||||||
data class Data(val habits: List<Habit>,
|
data class Data(val habits: List<Habit>,
|
||||||
val currentScore: Map<Habit, Double>,
|
val scores: Map<Habit, Score>,
|
||||||
val checkmarkValues: Map<Habit, List<Int>>)
|
val checkmarks: Map<Habit, List<Checkmark>>)
|
||||||
|
|
||||||
val observable = Observable<Listener>()
|
val observable = Observable<Listener>()
|
||||||
|
|
||||||
@@ -50,26 +51,26 @@ class MainScreenDataSource(val preferences: Preferences,
|
|||||||
filtered = filtered.filter { !it.isArchived }
|
filtered = filtered.filter { !it.isArchived }
|
||||||
}
|
}
|
||||||
|
|
||||||
val recentCheckmarks = filtered.associate { habit ->
|
val checkmarks = filtered.associate { habit ->
|
||||||
val allValues = checkmarks.getValue(habit).getValuesUntil(today)
|
val allValues = checkmarks.getValue(habit).getUntil(today)
|
||||||
if (allValues.size <= maxNumberOfButtons) habit to allValues
|
if (allValues.size <= maxNumberOfButtons) habit to allValues
|
||||||
else habit to allValues.subList(0, maxNumberOfButtons)
|
else habit to allValues.subList(0, maxNumberOfButtons)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preferences.showCompleted) {
|
if (!preferences.showCompleted) {
|
||||||
filtered = filtered.filter { habit ->
|
filtered = filtered.filter { habit ->
|
||||||
(habit.type == HabitType.BOOLEAN_HABIT && recentCheckmarks.getValue(habit)[0] == UNCHECKED) ||
|
(habit.type == HabitType.BOOLEAN_HABIT && checkmarks.getValue(habit)[0].value == UNCHECKED) ||
|
||||||
(habit.type == HabitType.NUMERICAL_HABIT && recentCheckmarks.getValue(habit)[0] * 1000 < habit.target)
|
(habit.type == HabitType.NUMERICAL_HABIT && checkmarks.getValue(habit)[0].value * 1000 < habit.target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentScores = filtered.associate {
|
val scores = filtered.associate { habit ->
|
||||||
it to 0.0 /* TODO */
|
habit to scores[habit]!!.getAt(today)
|
||||||
}
|
}
|
||||||
|
|
||||||
taskRunner.runInForeground {
|
taskRunner.runInForeground {
|
||||||
observable.notifyListeners { listener ->
|
observable.notifyListeners { listener ->
|
||||||
val data = Data(filtered, currentScores, recentCheckmarks)
|
val data = Data(filtered, scores, checkmarks)
|
||||||
listener.onDataChanged(data)
|
listener.onDataChanged(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,11 +24,11 @@ import org.isoron.uhabits.models.Checkmark.Companion.CHECKED_AUTOMATIC
|
|||||||
import org.isoron.uhabits.models.Checkmark.Companion.CHECKED_MANUAL
|
import org.isoron.uhabits.models.Checkmark.Companion.CHECKED_MANUAL
|
||||||
import org.isoron.uhabits.models.Checkmark.Companion.UNCHECKED
|
import org.isoron.uhabits.models.Checkmark.Companion.UNCHECKED
|
||||||
|
|
||||||
class CheckmarkList(private val frequency: Frequency,
|
class CheckmarkList(val frequency: Frequency,
|
||||||
private val habitType: HabitType) {
|
val habitType: HabitType) {
|
||||||
|
|
||||||
private val manualCheckmarks = mutableListOf<Checkmark>()
|
private val manualCheckmarks = mutableListOf<Checkmark>()
|
||||||
private val automaticCheckmarks = mutableListOf<Checkmark>()
|
private val computedCheckmarks = mutableListOf<Checkmark>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replaces the entire list of manual checkmarks by the ones provided. The
|
* Replaces the entire list of manual checkmarks by the ones provided. The
|
||||||
@@ -36,13 +36,13 @@ class CheckmarkList(private val frequency: Frequency,
|
|||||||
*/
|
*/
|
||||||
fun setManualCheckmarks(checks: List<Checkmark>) {
|
fun setManualCheckmarks(checks: List<Checkmark>) {
|
||||||
manualCheckmarks.clear()
|
manualCheckmarks.clear()
|
||||||
automaticCheckmarks.clear()
|
computedCheckmarks.clear()
|
||||||
manualCheckmarks.addAll(checks)
|
manualCheckmarks.addAll(checks)
|
||||||
if (habitType == HabitType.NUMERICAL_HABIT) {
|
if (habitType == HabitType.NUMERICAL_HABIT) {
|
||||||
automaticCheckmarks.addAll(checks)
|
computedCheckmarks.addAll(checks)
|
||||||
} else {
|
} else {
|
||||||
val computed = computeAutomaticCheckmarks(checks, frequency)
|
val computed = computeCheckmarks(checks, frequency)
|
||||||
automaticCheckmarks.addAll(computed)
|
computedCheckmarks.addAll(computed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,22 +54,23 @@ class CheckmarkList(private val frequency: Frequency,
|
|||||||
* That is, the first element of the returned list corresponds to the date
|
* That is, the first element of the returned list corresponds to the date
|
||||||
* provided.
|
* provided.
|
||||||
*/
|
*/
|
||||||
fun getValuesUntil(date: LocalDate): List<Int> {
|
fun getUntil(date: LocalDate): List<Checkmark> {
|
||||||
if (automaticCheckmarks.isEmpty()) return listOf()
|
if (computedCheckmarks.isEmpty()) return listOf()
|
||||||
|
|
||||||
val result = mutableListOf<Int>()
|
val result = mutableListOf<Checkmark>()
|
||||||
val newest = automaticCheckmarks.first().date
|
val newest = computedCheckmarks.first().date
|
||||||
val distToNewest = newest.distanceTo(date)
|
val distToNewest = newest.distanceTo(date)
|
||||||
|
|
||||||
|
var k = 0
|
||||||
var fromIndex = 0
|
var fromIndex = 0
|
||||||
val toIndex = automaticCheckmarks.size
|
val toIndex = computedCheckmarks.size
|
||||||
if (newest.isOlderThan(date)) {
|
if (newest.isOlderThan(date)) {
|
||||||
repeat(distToNewest) { result.add(UNCHECKED) }
|
repeat(distToNewest) { result.add(Checkmark(date.minus(k++), UNCHECKED)) }
|
||||||
} else {
|
} else {
|
||||||
fromIndex = distToNewest
|
fromIndex = distToNewest
|
||||||
}
|
}
|
||||||
val subList = automaticCheckmarks.subList(fromIndex, toIndex)
|
val subList = computedCheckmarks.subList(fromIndex, toIndex)
|
||||||
result.addAll(subList.map { it.value })
|
result.addAll(subList.map { Checkmark(date.minus(k++), it.value) })
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,9 +78,9 @@ class CheckmarkList(private val frequency: Frequency,
|
|||||||
/**
|
/**
|
||||||
* Computes the list of automatic checkmarks a list of manual ones.
|
* Computes the list of automatic checkmarks a list of manual ones.
|
||||||
*/
|
*/
|
||||||
fun computeAutomaticCheckmarks(checks: List<Checkmark>,
|
fun computeCheckmarks(checks: List<Checkmark>,
|
||||||
frequency: Frequency
|
frequency: Frequency
|
||||||
): MutableList<Checkmark> {
|
): MutableList<Checkmark> {
|
||||||
|
|
||||||
val intervals = buildIntervals(checks, frequency)
|
val intervals = buildIntervals(checks, frequency)
|
||||||
snapIntervalsTogether(intervals)
|
snapIntervalsTogether(intervals)
|
||||||
|
|||||||
@@ -21,6 +21,11 @@ package org.isoron.uhabits.models
|
|||||||
|
|
||||||
data class Frequency(val numerator: Int,
|
data class Frequency(val numerator: Int,
|
||||||
val denominator: Int) {
|
val denominator: Int) {
|
||||||
|
|
||||||
|
fun toDouble(): Double {
|
||||||
|
return numerator.toDouble() / denominator
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val WEEKLY = Frequency(1, 7)
|
val WEEKLY = Frequency(1, 7)
|
||||||
val DAILY = Frequency(1, 1)
|
val DAILY = Frequency(1, 1)
|
||||||
|
|||||||
@@ -20,10 +20,9 @@
|
|||||||
package org.isoron.uhabits.models
|
package org.isoron.uhabits.models
|
||||||
|
|
||||||
import org.isoron.platform.time.*
|
import org.isoron.platform.time.*
|
||||||
|
import kotlin.math.*
|
||||||
|
|
||||||
class ScoreList(private val frequency: Frequency,
|
class ScoreList(private val checkmarkList: CheckmarkList) {
|
||||||
private val checkmarkList: CheckmarkList) {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all scores, from the beginning of the habit history
|
* Returns a list of all scores, from the beginning of the habit history
|
||||||
* until the specified date.
|
* until the specified date.
|
||||||
@@ -32,7 +31,40 @@ class ScoreList(private val frequency: Frequency,
|
|||||||
* That is, the first element of the returned list corresponds to the date
|
* That is, the first element of the returned list corresponds to the date
|
||||||
* provided.
|
* provided.
|
||||||
*/
|
*/
|
||||||
fun getValuesUntil(date: LocalDate): List<Double> {
|
fun getUntil(date: LocalDate): List<Score> {
|
||||||
TODO()
|
val frequency = checkmarkList.frequency
|
||||||
|
val checks = checkmarkList.getUntil(date)
|
||||||
|
val scores = mutableListOf<Score>()
|
||||||
|
val type = checkmarkList.habitType
|
||||||
|
|
||||||
|
var currentScore = 0.0
|
||||||
|
checks.reversed().forEach { check ->
|
||||||
|
val value = if (type == HabitType.BOOLEAN_HABIT) {
|
||||||
|
min(1, check.value)
|
||||||
|
} else {
|
||||||
|
check.value
|
||||||
|
}
|
||||||
|
currentScore = compute(frequency, currentScore, value)
|
||||||
|
scores.add(Score(check.date, currentScore))
|
||||||
|
}
|
||||||
|
return scores.reversed()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAt(date: LocalDate): Score {
|
||||||
|
return getUntil(date)[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Given the frequency of the habit, the previous score, and the value of
|
||||||
|
* the current checkmark, computes the current score for the habit.
|
||||||
|
*/
|
||||||
|
fun compute(frequency: Frequency,
|
||||||
|
previousScore: Double,
|
||||||
|
checkmarkValue: Int): Double {
|
||||||
|
val multiplier = 0.5.pow(frequency.toDouble() / 13.0)
|
||||||
|
val score = previousScore * multiplier + checkmarkValue * (1 - multiplier)
|
||||||
|
return floor(score * 1e6) / 1e6
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,8 +114,7 @@ class CheckmarkListTest : BaseTest() {
|
|||||||
Checkmark(day(8), CHECKED_AUTOMATIC),
|
Checkmark(day(8), CHECKED_AUTOMATIC),
|
||||||
Checkmark(day(9), CHECKED_AUTOMATIC),
|
Checkmark(day(9), CHECKED_AUTOMATIC),
|
||||||
Checkmark(day(10), CHECKED_MANUAL))
|
Checkmark(day(10), CHECKED_MANUAL))
|
||||||
val actual = CheckmarkList.buildCheckmarksFromIntervals(checks,
|
val actual = CheckmarkList.buildCheckmarksFromIntervals(checks, intervals)
|
||||||
intervals)
|
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,8 +128,7 @@ class CheckmarkListTest : BaseTest() {
|
|||||||
Checkmark(day(3), CHECKED_AUTOMATIC),
|
Checkmark(day(3), CHECKED_AUTOMATIC),
|
||||||
Checkmark(day(4), CHECKED_AUTOMATIC),
|
Checkmark(day(4), CHECKED_AUTOMATIC),
|
||||||
Checkmark(day(5), CHECKED_AUTOMATIC))
|
Checkmark(day(5), CHECKED_AUTOMATIC))
|
||||||
val actual = CheckmarkList.buildCheckmarksFromIntervals(reps,
|
val actual = CheckmarkList.buildCheckmarksFromIntervals(reps, intervals)
|
||||||
intervals)
|
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,38 +150,37 @@ class CheckmarkListTest : BaseTest() {
|
|||||||
Checkmark(day(8), CHECKED_AUTOMATIC),
|
Checkmark(day(8), CHECKED_AUTOMATIC),
|
||||||
Checkmark(day(9), CHECKED_AUTOMATIC),
|
Checkmark(day(9), CHECKED_AUTOMATIC),
|
||||||
Checkmark(day(10), CHECKED_MANUAL))
|
Checkmark(day(10), CHECKED_MANUAL))
|
||||||
val actual = CheckmarkList.computeAutomaticCheckmarks(checks,
|
val actual = CheckmarkList.computeCheckmarks(checks, Frequency(1, 3))
|
||||||
Frequency(1, 3))
|
|
||||||
assertEquals(expected, actual)
|
assertEquals(expected, actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGetValuesUntil() {
|
fun testGetUntil() {
|
||||||
val list = CheckmarkList(Frequency(1, 2), HabitType.BOOLEAN_HABIT)
|
val list = CheckmarkList(Frequency(1, 2), HabitType.BOOLEAN_HABIT)
|
||||||
list.setManualCheckmarks(listOf(Checkmark(day(4), CHECKED_MANUAL),
|
list.setManualCheckmarks(listOf(Checkmark(day(4), CHECKED_MANUAL),
|
||||||
Checkmark(day(7), CHECKED_MANUAL)))
|
Checkmark(day(7), CHECKED_MANUAL)))
|
||||||
val expected = listOf(UNCHECKED,
|
val expected = listOf(Checkmark(day(0), UNCHECKED),
|
||||||
UNCHECKED,
|
Checkmark(day(1), UNCHECKED),
|
||||||
UNCHECKED,
|
Checkmark(day(2), UNCHECKED),
|
||||||
CHECKED_AUTOMATIC,
|
Checkmark(day(3), CHECKED_AUTOMATIC),
|
||||||
CHECKED_MANUAL,
|
Checkmark(day(4), CHECKED_MANUAL),
|
||||||
UNCHECKED,
|
Checkmark(day(5), UNCHECKED),
|
||||||
CHECKED_AUTOMATIC,
|
Checkmark(day(6), CHECKED_AUTOMATIC),
|
||||||
CHECKED_MANUAL)
|
Checkmark(day(7), CHECKED_MANUAL))
|
||||||
assertEquals(expected, list.getValuesUntil(day(0)))
|
assertEquals(expected, list.getUntil(day(0)))
|
||||||
|
|
||||||
val expected2 = listOf(CHECKED_AUTOMATIC,
|
val expected2 = listOf(Checkmark(day(3), CHECKED_AUTOMATIC),
|
||||||
CHECKED_MANUAL,
|
Checkmark(day(4), CHECKED_MANUAL),
|
||||||
UNCHECKED,
|
Checkmark(day(5), UNCHECKED),
|
||||||
CHECKED_AUTOMATIC,
|
Checkmark(day(6), CHECKED_AUTOMATIC),
|
||||||
CHECKED_MANUAL)
|
Checkmark(day(7), CHECKED_MANUAL))
|
||||||
assertEquals(expected2, list.getValuesUntil(day(3)))
|
assertEquals(expected2, list.getUntil(day(3)))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testGetValuesUntil2() {
|
fun testGetValuesUntil2() {
|
||||||
val list = CheckmarkList(Frequency(1, 2), HabitType.BOOLEAN_HABIT)
|
val list = CheckmarkList(Frequency(1, 2), HabitType.BOOLEAN_HABIT)
|
||||||
val expected = listOf<Int>()
|
val expected = listOf<Checkmark>()
|
||||||
assertEquals(expected, list.getValuesUntil(day(0)))
|
assertEquals(expected, list.getUntil(day(0)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016-2019 Á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.models
|
||||||
|
|
||||||
|
import org.isoron.platform.time.*
|
||||||
|
import org.isoron.uhabits.models.Checkmark.Companion.CHECKED_MANUAL
|
||||||
|
import org.isoron.uhabits.models.Frequency.Companion.DAILY
|
||||||
|
import org.isoron.uhabits.models.HabitType.*
|
||||||
|
import org.isoron.uhabits.models.ScoreList.Companion.compute
|
||||||
|
import org.junit.Assert.*
|
||||||
|
import org.junit.Test
|
||||||
|
import java.lang.Math.*
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class ScoreListTest {
|
||||||
|
val epsilon = 1e-6
|
||||||
|
val today = LocalDate(2019, 1, 1)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `compute with daily habit`() {
|
||||||
|
val freq = DAILY
|
||||||
|
var check = 1
|
||||||
|
assertEquals(compute(freq, 0.0, check), 0.051922, epsilon)
|
||||||
|
assertEquals(compute(freq, 0.5, check), 0.525961, epsilon)
|
||||||
|
assertEquals(compute(freq, 0.75, check), 0.762980, epsilon)
|
||||||
|
|
||||||
|
check = 0
|
||||||
|
assertEquals(compute(freq, 0.0, check), 0.0, epsilon)
|
||||||
|
assertEquals(compute(freq, 0.5, check), 0.474039, epsilon)
|
||||||
|
assertEquals(compute(freq, 0.75, check), 0.711058, epsilon)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `compute with non-daily habit`() {
|
||||||
|
var check = 1
|
||||||
|
val freq = Frequency(1, 3)
|
||||||
|
assertEquals(compute(freq, 0.0, check), 0.017615, epsilon)
|
||||||
|
assertEquals(compute(freq, 0.5, check), 0.508807, epsilon)
|
||||||
|
assertEquals(compute(freq, 0.75, check), 0.754404, epsilon)
|
||||||
|
|
||||||
|
check = 0
|
||||||
|
assertEquals(compute(freq, 0.0, check), 0.0, epsilon)
|
||||||
|
assertEquals(compute(freq, 0.5, check), 0.491192, epsilon)
|
||||||
|
assertEquals(compute(freq, 0.75, check), 0.736788, epsilon)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `getValueUntil with boolean habit`() {
|
||||||
|
val checks = CheckmarkList(DAILY, BOOLEAN_HABIT)
|
||||||
|
checks.setManualCheckmarks((0..19).map {
|
||||||
|
Checkmark(today.minus(it), CHECKED_MANUAL)
|
||||||
|
})
|
||||||
|
val scoreList = ScoreList(checks)
|
||||||
|
val actual = scoreList.getUntil(today)
|
||||||
|
val expected = listOf(Score(today.minus(0), 0.655741),
|
||||||
|
Score(today.minus(1), 0.636888),
|
||||||
|
Score(today.minus(2), 0.617002),
|
||||||
|
Score(today.minus(3), 0.596027),
|
||||||
|
Score(today.minus(4), 0.573903),
|
||||||
|
Score(today.minus(5), 0.550568),
|
||||||
|
Score(today.minus(6), 0.525955),
|
||||||
|
Score(today.minus(7), 0.499994),
|
||||||
|
Score(today.minus(8), 0.472611),
|
||||||
|
Score(today.minus(9), 0.443729),
|
||||||
|
Score(today.minus(10), 0.413265),
|
||||||
|
Score(today.minus(11), 0.381132),
|
||||||
|
Score(today.minus(12), 0.347240),
|
||||||
|
Score(today.minus(13), 0.311491),
|
||||||
|
Score(today.minus(14), 0.273785),
|
||||||
|
Score(today.minus(15), 0.234014),
|
||||||
|
Score(today.minus(16), 0.192065),
|
||||||
|
Score(today.minus(17), 0.147818),
|
||||||
|
Score(today.minus(18), 0.101148),
|
||||||
|
Score(today.minus(19), 0.051922))
|
||||||
|
assertEquals(expected, actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,7 +31,7 @@ class MainScreenCell : UITableViewCell {
|
|||||||
fatalError()
|
fatalError()
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(habit: Habit, values: [KotlinInt], theme: Theme, nButtons: Int) {
|
func update(habit: Habit, checkmarks: [Checkmark], score: Score, theme: Theme, nButtons: Int) {
|
||||||
if buttons.count != nButtons {
|
if buttons.count != nButtons {
|
||||||
buttons.removeAll()
|
buttons.removeAll()
|
||||||
for v in contentView.subviews { v.removeFromSuperview() }
|
for v in contentView.subviews { v.removeFromSuperview() }
|
||||||
@@ -68,7 +68,7 @@ class MainScreenCell : UITableViewCell {
|
|||||||
label.text = habit.name
|
label.text = habit.name
|
||||||
label.textColor = color.uicolor
|
label.textColor = color.uicolor
|
||||||
ring.component = Ring(color: color,
|
ring.component = Ring(color: color,
|
||||||
percentage: Double.random(in: 0...1),
|
percentage: score.value,
|
||||||
thickness: 2.5,
|
thickness: 2.5,
|
||||||
radius: 7,
|
radius: 7,
|
||||||
theme: theme,
|
theme: theme,
|
||||||
@@ -78,12 +78,12 @@ class MainScreenCell : UITableViewCell {
|
|||||||
for i in 0..<buttons.count {
|
for i in 0..<buttons.count {
|
||||||
if habit.type == .numerical {
|
if habit.type == .numerical {
|
||||||
buttons[i].component = NumberButton(color: color,
|
buttons[i].component = NumberButton(color: color,
|
||||||
value: Double(truncating: values[i]) / 1000.0,
|
value: Double(checkmarks[i].value) / 1000.0,
|
||||||
threshold: habit.target,
|
threshold: habit.target,
|
||||||
units: habit.unit,
|
units: habit.unit,
|
||||||
theme: theme)
|
theme: theme)
|
||||||
} else {
|
} else {
|
||||||
buttons[i].component = CheckmarkButton(value: Int32(truncating: values[i]),
|
buttons[i].component = CheckmarkButton(value: checkmarks[i].value,
|
||||||
color: color,
|
color: color,
|
||||||
theme: theme)
|
theme: theme)
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,11 @@ class MainScreenController: UITableViewController, MainScreenDataSourceListener
|
|||||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MainScreenCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MainScreenCell
|
||||||
let habit = data!.habits[indexPath.row]
|
let habit = data!.habits[indexPath.row]
|
||||||
cell.update(habit: habit, values: data!.checkmarkValues[habit]!, theme: theme, nButtons: nButtons)
|
cell.update(habit: habit,
|
||||||
|
checkmarks: data!.checkmarks[habit]!,
|
||||||
|
score: data!.scores[habit]!,
|
||||||
|
theme: theme,
|
||||||
|
nButtons: nButtons)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user