diff --git a/suripu-app/src/main/java/com/hello/suripu/app/v2/TimelineResource.java b/suripu-app/src/main/java/com/hello/suripu/app/v2/TimelineResource.java index 544b58489..91a29e16d 100644 --- a/suripu-app/src/main/java/com/hello/suripu/app/v2/TimelineResource.java +++ b/suripu-app/src/main/java/com/hello/suripu/app/v2/TimelineResource.java @@ -8,6 +8,7 @@ import com.hello.suripu.core.db.TrackerMotionDAO; import com.hello.suripu.core.logging.DataLogger; import com.hello.suripu.core.models.timeline.v2.ScoreCondition; +import com.hello.suripu.core.models.timeline.v2.SleepMetrics; import com.hello.suripu.core.models.timeline.v2.TimelineLog; import com.hello.suripu.core.models.AggregateSleepStats; import com.hello.suripu.core.models.Event; @@ -258,6 +259,16 @@ private void checkValidTimelineOrThrow(final long accountId,final Timeline timel LOGGER.info("rejected feedback from account_id {} for evening of {} because it resulted in an empty timeline",accountId,timeline.dateNight); throw new WebApplicationException(Response.status(Response.Status.PRECONDITION_FAILED).entity(new JsonError(Response.Status.PRECONDITION_FAILED.getStatusCode(), English.FEEDBACK_CAUSED_INVALID_SLEEP_SCORE)).build()); } + + for (final SleepMetrics sleepMetrics : timeline.metrics) { + if (!sleepMetrics.name.equals(SleepMetrics.TOTAL_SLEEP_NAME)) { + continue; + } + LOGGER.info("rejected feedback from account_id {} for evening of {} because it resulted in timeline with invalid sleep duration ",accountId,timeline.dateNight); + if (!sleepMetrics.value.isPresent() || (sleepMetrics.value.isPresent() && sleepMetrics.value.get() <= SleepMetrics.MINIMUM_TOTAL_SLEEP_DURATION_MINUTES)) { + throw new WebApplicationException(Response.status(Response.Status.PRECONDITION_FAILED).entity(new JsonError(Response.Status.PRECONDITION_FAILED.getStatusCode(), English.FEEDBACK_CAUSED_INVALID_SLEEP_SCORE)).build()); + } + } } private Timeline getTimelineForNightInternal(final long accountId, final String night, final Optional newFeedback) { diff --git a/suripu-core/src/main/java/com/hello/suripu/core/models/timeline/v2/SleepMetrics.java b/suripu-core/src/main/java/com/hello/suripu/core/models/timeline/v2/SleepMetrics.java index 28de49510..43515b16e 100644 --- a/suripu-core/src/main/java/com/hello/suripu/core/models/timeline/v2/SleepMetrics.java +++ b/suripu-core/src/main/java/com/hello/suripu/core/models/timeline/v2/SleepMetrics.java @@ -11,6 +11,14 @@ public class SleepMetrics { + public static final String TOTAL_SLEEP_NAME = "total_sleep"; + public static final String SOUND_SLEEP_NAME = "sound_sleep"; + public static final String TIME_TO_SLEEP_NAME = "time_to_sleep"; + public static final String TIMES_AWAKE_NAME = "times_awake"; + public static final String FELL_ASLEEP_NAME = "fell_asleep"; + public static final String WOKE_UP_NAME = "woke_up"; + public static final Integer MINIMUM_TOTAL_SLEEP_DURATION_MINUTES = 120; + @JsonProperty("name") public final String name; @@ -50,18 +58,18 @@ public static List fromV1(final com.hello.suripu.core.models.Timel if (maybeStatistics.isPresent() && !maybeStatistics.get().isFromNull()) { SleepStats statistics = maybeStatistics.get(); - metrics.add(create("total_sleep", Optional.of(statistics.sleepDurationInMinutes.longValue()), + metrics.add(create(TOTAL_SLEEP_NAME, Optional.of(statistics.sleepDurationInMinutes.longValue()), Unit.MINUTES, CurrentRoomState.State.Condition.IDEAL)); - metrics.add(create("sound_sleep", Optional.of(statistics.soundSleepDurationInMinutes.longValue()), + metrics.add(create(SOUND_SLEEP_NAME, Optional.of(statistics.soundSleepDurationInMinutes.longValue()), Unit.MINUTES, CurrentRoomState.State.Condition.IDEAL)); - metrics.add(create("time_to_sleep", Optional.of(statistics.sleepOnsetTimeMinutes.longValue()), + metrics.add(create(TIME_TO_SLEEP_NAME, Optional.of(statistics.sleepOnsetTimeMinutes.longValue()), Unit.MINUTES, CurrentRoomState.State.Condition.IDEAL)); - metrics.add(create("times_awake", Optional.of(statistics.numberOfMotionEvents.longValue()), + metrics.add(create(TIMES_AWAKE_NAME, Optional.of(statistics.numberOfMotionEvents.longValue()), Unit.QUANTITY, CurrentRoomState.State.Condition.IDEAL)); - metrics.add(create("fell_asleep", Optional.of(statistics.sleepTime), + metrics.add(create(FELL_ASLEEP_NAME, Optional.of(statistics.sleepTime), Unit.TIMESTAMP, CurrentRoomState.State.Condition.IDEAL)); - metrics.add(create("woke_up", Optional.of(statistics.wakeTime), + metrics.add(create(WOKE_UP_NAME, Optional.of(statistics.wakeTime), Unit.TIMESTAMP, CurrentRoomState.State.Condition.IDEAL)); }