ScoreList: Remove groupBy functions

pull/699/head
Alinson S. Xavier 5 years ago
parent 4a3a767cb2
commit 9bc0f44777

@ -19,20 +19,16 @@
package org.isoron.uhabits.activities.common.views;
import androidx.test.ext.junit.runners.*;
import androidx.test.filters.*;
import androidx.test.runner.*;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.isoron.uhabits.*;
import org.isoron.uhabits.activities.habits.show.views.*;
import org.isoron.uhabits.core.models.*;
import org.isoron.uhabits.core.utils.*;
import org.isoron.uhabits.utils.*;
import org.junit.*;
import org.junit.runner.*;
import java.util.*;
@RunWith(AndroidJUnit4.class)
@MediumTest
public class ScoreChartTest extends BaseViewTest
@ -43,6 +39,8 @@ public class ScoreChartTest extends BaseViewTest
private ScoreChart view;
private ScoreCardPresenter presenter;
@Override
@Before
public void setUp()
@ -51,15 +49,13 @@ public class ScoreChartTest extends BaseViewTest
fixtures.purgeHabits(habitList);
habit = fixtures.createLongHabit();
Timestamp today = DateUtils.getTodayWithOffset();
List<Entry> known = habit.getComputedEntries().getKnown();
Timestamp oldest = known.get(known.size() - 1).getTimestamp();
presenter = new ScoreCardPresenter(habit, prefs.getFirstWeekday());
ScoreCardViewModel model = presenter.present(0);
view = new ScoreChart(targetContext);
view.setScores(habit.getScores().getByInterval(oldest, today));
view.setColor(PaletteUtilsKt.toThemedAndroidColor(habit.getColor(), targetContext));
view.setBucketSize(7);
view.setScores(model.getScores());
view.setColor(PaletteUtilsKt.toFixedAndroidColor(model.getColor()));
view.setBucketSize(model.getBucketSize());
measureView(view, dpToPixels(300), dpToPixels(200));
}
@ -88,8 +84,9 @@ public class ScoreChartTest extends BaseViewTest
@Test
public void testRender_withMonthlyBucket() throws Throwable
{
view.setScores(habit.getScores().groupBy(DateUtils.TruncateField.MONTH, Calendar.SUNDAY));
view.setBucketSize(30);
ScoreCardViewModel model = presenter.present(2);
view.setScores(model.getScores());
view.setBucketSize(model.getBucketSize());
view.invalidate();
assertRenders(view, BASE_PATH + "renderMonthly.png");
@ -105,8 +102,9 @@ public class ScoreChartTest extends BaseViewTest
@Test
public void testRender_withYearlyBucket() throws Throwable
{
view.setScores(habit.getScores().groupBy(DateUtils.TruncateField.YEAR, Calendar.SUNDAY));
view.setBucketSize(365);
ScoreCardViewModel model = presenter.present(4);
view.setScores(model.getScores());
view.setBucketSize(model.getBucketSize());
view.invalidate();
assertRenders(view, BASE_PATH + "renderYearly.png");

@ -67,6 +67,7 @@ class ScoreCardPresenter(
val BUCKET_SIZES = intArrayOf(1, 7, 31, 92, 365)
fun getTruncateField(bucketSize: Int): DateUtils.TruncateField {
when (bucketSize) {
1 -> return DAY
7 -> return WEEK_NUMBER
31 -> return MONTH
92 -> return QUARTER
@ -78,12 +79,20 @@ class ScoreCardPresenter(
fun present(spinnerPosition: Int): ScoreCardViewModel {
val bucketSize = BUCKET_SIZES[spinnerPosition]
val scoreList = habit.scores
val today = DateUtils.getTodayWithOffset()
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
val scores = if (bucketSize == 1) scoreList.getByInterval(oldest, today)
else scoreList.groupBy(getTruncateField(bucketSize), firstWeekday)
val field = getTruncateField(bucketSize)
val scores = habit.scores.getByInterval(oldest, today).groupBy {
DateUtils.truncate(field, it.timestamp, firstWeekday)
}.map { (timestamp, scores) ->
Score(timestamp, scores.map {
it.value
}.average())
}.sortedBy {
it.timestamp
}.reversed()
return ScoreCardViewModel(
color = habit.color,
scores = scores,
@ -91,5 +100,4 @@ class ScoreCardPresenter(
spinnerPosition = spinnerPosition,
)
}
}

@ -38,23 +38,16 @@ class ScoreWidget(
pendingIntentFactory.showHabit(habit)
override fun refreshData(view: View) {
val size = ScoreCardPresenter.BUCKET_SIZES[prefs.scoreCardSpinnerPosition]
val today = DateUtils.getTodayWithOffset()
val oldest = habit.computedEntries.getKnown().lastOrNull()?.timestamp ?: today
val scores = when(size) {
1 -> habit.scores.getByInterval(oldest, today)
else -> habit.scores.groupBy(ScoreCardPresenter.getTruncateField(size), prefs.firstWeekday)
}
val presenter = ScoreCardPresenter(habit, prefs.firstWeekday)
val viewModel = presenter.present(prefs.scoreCardSpinnerPosition)
val widgetView = view as GraphWidgetView
widgetView.setBackgroundAlpha(preferedBackgroundAlpha)
if (preferedBackgroundAlpha >= 255) widgetView.setShadowAlpha(0x4f)
(widgetView.dataView as ScoreChart).apply {
setIsTransparencyEnabled(true)
setBucketSize(size)
setBucketSize(viewModel.bucketSize)
setColor(habit.color.toThemedAndroidColor(context))
setScores(scores)
setScores(viewModel.scores)
}
}

@ -77,7 +77,7 @@ data class Habit(
isNumerical = isNumerical,
)
val to = DateUtils.getTodayWithOffset()
val to = DateUtils.getTodayWithOffset().plus(30)
val entries = computedEntries.getKnown()
var from = entries.lastOrNull()?.timestamp ?: to
if (from.isNewerThan(to)) from = to

@ -21,8 +21,6 @@ package org.isoron.uhabits.core.models;
import androidx.annotation.*;
import org.isoron.uhabits.core.utils.*;
import java.util.*;
import static org.isoron.uhabits.core.models.Entry.*;
@ -68,22 +66,13 @@ public class ScoreList
return result;
}
public List<Score> groupBy(DateUtils.TruncateField field, int firstWeekday)
{
HashMap<Timestamp, ArrayList<Double>> groups = getGroupedValues(field, firstWeekday);
List<Score> scores = groupsToAvgScores(groups);
Collections.sort(scores, (s1, s2) -> s2.compareNewer(s1));
return scores;
}
public void recompute(
Frequency frequency,
boolean isNumerical,
double targetValue,
EntryList computedEntries,
Timestamp from,
Timestamp to
)
Timestamp to)
{
list.clear();
if (computedEntries.getKnown().isEmpty()) return;
@ -139,47 +128,4 @@ public class ScoreList
list.put(timestamp, new Score(timestamp, previousValue));
}
}
@NonNull
private HashMap<Timestamp, ArrayList<Double>> getGroupedValues(DateUtils.TruncateField field,
int firstWeekday)
{
HashMap<Timestamp, ArrayList<Double>> groups = new HashMap<>();
for (Score s : list.values())
{
Timestamp groupTimestamp = new Timestamp(
DateUtils.truncate(
field,
s.getTimestamp().getUnixTime(),
firstWeekday));
if (!groups.containsKey(groupTimestamp))
groups.put(groupTimestamp, new ArrayList<>());
groups.get(groupTimestamp).add(s.getValue());
}
return groups;
}
@NonNull
private List<Score> groupsToAvgScores(HashMap<Timestamp, ArrayList<Double>> groups)
{
List<Score> scores = new LinkedList<>();
for (Timestamp timestamp : groups.keySet())
{
double meanValue = 0.0;
ArrayList<Double> groupValues = groups.get(timestamp);
for (Double v : groupValues) meanValue += v;
meanValue /= groupValues.size();
scores.add(new Score(timestamp, meanValue));
}
return scores;
}
}

@ -266,6 +266,13 @@ public abstract class DateUtils
return Locale.getDefault();
}
public static Timestamp truncate(TruncateField field,
Timestamp timestamp,
int firstWeekday)
{
return new Timestamp(truncate(field, timestamp.getUnixTime(), firstWeekday));
}
public static Long truncate(TruncateField field,
long timestamp,
int firstWeekday)
@ -275,6 +282,9 @@ public abstract class DateUtils
switch (field)
{
case DAY:
return cal.getTimeInMillis();
case MONTH:
cal.set(DAY_OF_MONTH, 1);
return cal.getTimeInMillis();
@ -318,6 +328,6 @@ public abstract class DateUtils
public enum TruncateField
{
MONTH, WEEK_NUMBER, YEAR, QUARTER
DAY, MONTH, WEEK_NUMBER, YEAR, QUARTER
}
}

@ -222,19 +222,6 @@ public class ScoreListTest extends BaseUnitTest
assertThat(habit.getScores().get(today).getValue(), greaterThan(0.99));
}
@Test
public void test_groupBy()
{
Habit habit = fixtures.createLongHabit();
List<Score> list =
habit.getScores().groupBy(DateUtils.TruncateField.MONTH, Calendar.SATURDAY);
assertThat(list.size(), equalTo(5));
assertThat(list.get(0).getValue(), closeTo(0.644120, E));
assertThat(list.get(1).getValue(), closeTo(0.713651, E));
assertThat(list.get(2).getValue(), closeTo(0.571922, E));
}
@Test
public void test_recompute()
{

Loading…
Cancel
Save