/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see
* Old formula for activity index was not linear and difficult to turn into a query due to conditional multipliers. * Thus a new formula was written. *
* {@code T} - Time played after someone is considered active on a particular week * {@code t1, t2, t3} - Time played that week *
* Activity index takes into account last 3 weeks. *
* Activity for a single week is calculated using {@code A(t) = (1 / (pi/2 * (t/T) + 1))}. * A(t) is based on function f(x) = 1 / (x + 1), which has property f(0) = 1, decreasing from there, but not in a straight line. * You can see the function plotted here https://www.wolframalpha.com/input/?i=1+%2F+(x%2B1)+from+-1+to+2 *
* To fine tune the curve pi/2 is used since it felt like a good curve. *
* Activity index A is calculated by using the formula: * {@code A = 5 - 5 * [A(t1) + A(t2) + A(t3)] / 3} *
* Plot for A and limits * https://www.wolframalpha.com/input/?i=plot+y+%3D+5+-+5+*+(1+%2F+(pi%2F2+*+x%2B1))+and+y+%3D1+and+y+%3D+2+and+y+%3D+3+and+y+%3D+3.75+from+-0.5+to+3 *
* New Limits for A would thus be
* {@code < 1: Inactive}
* {@code > 1: Irregular}
* {@code > 2: Regular}
* {@code > 3: Active}
* {@code > 3.75: Very Active}
*/
public class ActivityIndex {
public static final double VERY_ACTIVE = 3.75;
public static final double ACTIVE = 3.0;
public static final double REGULAR = 2.0;
public static final double IRREGULAR = 1.0;
private final double value;
private final long date;
private long playtimeMsThreshold;
public ActivityIndex(DataContainer container, long date, long playtimeMsThreshold) {
this.playtimeMsThreshold = playtimeMsThreshold;
this.date = date;
value = calculate(container);
}
public ActivityIndex(List> sessionsValue = container.getValue(PlayerKeys.SESSIONS);
return sessionsValue
.map(sessions -> calculate(new SessionsMutator(sessions)))
.orElse(0.0);
}
private double calculate(SessionsMutator sessionsMutator) {
if (sessionsMutator.all().isEmpty()) {
return 0.0;
}
long week = TimeAmount.WEEK.toMillis(1L);
long weekAgo = date - week;
long twoWeeksAgo = date - 2L * week;
long threeWeeksAgo = date - 3L * week;
SessionsMutator weekOne = sessionsMutator.filterSessionsBetween(weekAgo, date);
SessionsMutator weekTwo = sessionsMutator.filterSessionsBetween(twoWeeksAgo, weekAgo);
SessionsMutator weekThree = sessionsMutator.filterSessionsBetween(threeWeeksAgo, twoWeeksAgo);
long playtime1 = weekOne.toActivePlaytime();
long playtime2 = weekTwo.toActivePlaytime();
long playtime3 = weekThree.toActivePlaytime();
double indexW1 = 1.0 / (Math.PI / 2.0 * (playtime1 * 1.0 / playtimeMsThreshold) + 1.0);
double indexW2 = 1.0 / (Math.PI / 2.0 * (playtime2 * 1.0 / playtimeMsThreshold) + 1.0);
double indexW3 = 1.0 / (Math.PI / 2.0 * (playtime3 * 1.0 / playtimeMsThreshold) + 1.0);
double average = (indexW1 + indexW2 + indexW3) / 3.0;
return 5.0 - (5.0 * average);
}
public double getValue() {
return value;
}
public long getDate() {
return date;
}
public String getFormattedValue(Formatter