2018-02-26 14:27:32 +01:00
|
|
|
/* Copyright (C) 2015-2018 Andreas Shimokawa, Carsten Pfeiffer, Daniele
|
2017-08-25 11:25:01 +02:00
|
|
|
Gobbetti, Vebryn
|
2017-03-10 14:53:19 +01:00
|
|
|
|
|
|
|
This file is part of Gadgetbridge.
|
|
|
|
|
|
|
|
Gadgetbridge is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Affero General Public License as published
|
|
|
|
by the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
Gadgetbridge 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 Affero General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
2015-08-03 23:09:49 +02:00
|
|
|
package nodomain.freeyourgadget.gadgetbridge.activities.charts;
|
2015-07-14 00:29:32 +02:00
|
|
|
|
2017-05-14 23:09:27 +02:00
|
|
|
import java.util.HashMap;
|
2015-07-14 00:29:32 +02:00
|
|
|
import java.util.List;
|
2017-05-14 23:09:27 +02:00
|
|
|
import java.util.Map;
|
2015-07-14 00:29:32 +02:00
|
|
|
|
2017-08-23 23:38:30 +02:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2015-08-03 23:09:49 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmount;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityAmounts;
|
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
2015-07-27 23:49:53 +02:00
|
|
|
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
2015-07-14 00:29:32 +02:00
|
|
|
|
2017-02-21 16:20:42 +01:00
|
|
|
class ActivityAnalysis {
|
2017-08-23 23:38:30 +02:00
|
|
|
private static final Logger LOG = LoggerFactory.getLogger(ActivityAnalysis.class);
|
|
|
|
|
2017-05-14 23:09:27 +02:00
|
|
|
// store raw steps and duration
|
|
|
|
protected HashMap<Integer, Long> stats = new HashMap<Integer, Long>();
|
|
|
|
// max speed determined from samples
|
|
|
|
private int maxSpeed = 0;
|
|
|
|
|
2017-02-21 16:20:42 +01:00
|
|
|
ActivityAmounts calculateActivityAmounts(List<? extends ActivitySample> samples) {
|
2015-07-14 00:29:32 +02:00
|
|
|
ActivityAmount deepSleep = new ActivityAmount(ActivityKind.TYPE_DEEP_SLEEP);
|
|
|
|
ActivityAmount lightSleep = new ActivityAmount(ActivityKind.TYPE_LIGHT_SLEEP);
|
2015-08-28 14:54:49 +02:00
|
|
|
ActivityAmount notWorn = new ActivityAmount(ActivityKind.TYPE_NOT_WORN);
|
2015-07-14 00:29:32 +02:00
|
|
|
ActivityAmount activity = new ActivityAmount(ActivityKind.TYPE_ACTIVITY);
|
|
|
|
|
|
|
|
ActivityAmount previousAmount = null;
|
2015-07-27 23:49:53 +02:00
|
|
|
ActivitySample previousSample = null;
|
|
|
|
for (ActivitySample sample : samples) {
|
2016-08-02 00:30:05 +02:00
|
|
|
ActivityAmount amount;
|
2015-07-27 23:49:53 +02:00
|
|
|
switch (sample.getKind()) {
|
|
|
|
case ActivityKind.TYPE_DEEP_SLEEP:
|
2015-07-14 00:29:32 +02:00
|
|
|
amount = deepSleep;
|
|
|
|
break;
|
2015-07-27 23:49:53 +02:00
|
|
|
case ActivityKind.TYPE_LIGHT_SLEEP:
|
2015-07-14 00:29:32 +02:00
|
|
|
amount = lightSleep;
|
|
|
|
break;
|
2015-08-28 14:54:49 +02:00
|
|
|
case ActivityKind.TYPE_NOT_WORN:
|
|
|
|
amount = notWorn;
|
|
|
|
break;
|
2015-07-27 23:49:53 +02:00
|
|
|
case ActivityKind.TYPE_ACTIVITY:
|
2015-07-14 00:29:32 +02:00
|
|
|
default:
|
|
|
|
amount = activity;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2017-02-26 00:40:50 +01:00
|
|
|
int steps = sample.getSteps();
|
|
|
|
if (steps > 0) {
|
2017-05-14 23:09:27 +02:00
|
|
|
amount.addSteps(steps);
|
2017-02-26 00:40:50 +01:00
|
|
|
}
|
|
|
|
|
2015-07-14 00:29:32 +02:00
|
|
|
if (previousSample != null) {
|
|
|
|
long timeDifference = sample.getTimestamp() - previousSample.getTimestamp();
|
2015-07-27 23:49:53 +02:00
|
|
|
if (previousSample.getRawKind() == sample.getRawKind()) {
|
2015-07-14 00:29:32 +02:00
|
|
|
amount.addSeconds(timeDifference);
|
|
|
|
} else {
|
|
|
|
long sharedTimeDifference = (long) (timeDifference / 2.0f);
|
|
|
|
previousAmount.addSeconds(sharedTimeDifference);
|
|
|
|
amount.addSeconds(sharedTimeDifference);
|
|
|
|
}
|
2017-05-14 23:09:27 +02:00
|
|
|
|
|
|
|
// add time
|
|
|
|
if (steps > 0 && sample.getKind() == ActivityKind.TYPE_ACTIVITY) {
|
|
|
|
if (steps > maxSpeed) {
|
|
|
|
maxSpeed = steps;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!stats.containsKey(steps)) {
|
2018-04-20 20:30:01 +02:00
|
|
|
// LOG.debug("Adding: " + steps);
|
2017-05-14 23:09:27 +02:00
|
|
|
stats.put(steps, timeDifference);
|
|
|
|
} else {
|
|
|
|
long time = stats.get(steps);
|
2018-04-20 20:30:01 +02:00
|
|
|
// LOG.debug("Updating: " + steps + " " + timeDifference + time);
|
2017-05-14 23:09:27 +02:00
|
|
|
stats.put(steps, timeDifference + time);
|
|
|
|
}
|
|
|
|
}
|
2015-07-14 00:29:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
previousAmount = amount;
|
|
|
|
previousSample = sample;
|
|
|
|
}
|
|
|
|
|
|
|
|
ActivityAmounts result = new ActivityAmounts();
|
|
|
|
if (deepSleep.getTotalSeconds() > 0) {
|
|
|
|
result.addAmount(deepSleep);
|
|
|
|
}
|
|
|
|
if (lightSleep.getTotalSeconds() > 0) {
|
|
|
|
result.addAmount(lightSleep);
|
|
|
|
}
|
|
|
|
if (activity.getTotalSeconds() > 0) {
|
|
|
|
result.addAmount(activity);
|
|
|
|
}
|
|
|
|
result.calculatePercentages();
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2015-07-29 16:30:19 +02:00
|
|
|
|
2017-02-21 16:20:42 +01:00
|
|
|
int calculateTotalSteps(List<? extends ActivitySample> samples) {
|
2015-07-29 16:30:19 +02:00
|
|
|
int totalSteps = 0;
|
|
|
|
for (ActivitySample sample : samples) {
|
2016-08-02 00:30:05 +02:00
|
|
|
int steps = sample.getSteps();
|
|
|
|
if (steps > 0) {
|
|
|
|
totalSteps += sample.getSteps();
|
|
|
|
}
|
2015-07-29 16:30:19 +02:00
|
|
|
}
|
|
|
|
return totalSteps;
|
|
|
|
}
|
2015-07-14 00:29:32 +02:00
|
|
|
}
|