Plan/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java

287 lines
11 KiB
Java

/*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.delivery.domain.mutators;
import com.djrapitops.plan.delivery.domain.container.DataContainer;
import com.djrapitops.plan.delivery.domain.keys.CommonKeys;
import com.djrapitops.plan.delivery.domain.keys.SessionKeys;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.delivery.rendering.json.graphs.Graphs;
import com.djrapitops.plan.delivery.rendering.json.graphs.pie.WorldPie;
import com.djrapitops.plan.gathering.domain.PlayerKill;
import com.djrapitops.plan.gathering.domain.Session;
import com.djrapitops.plan.gathering.domain.WorldTimes;
import com.djrapitops.plan.settings.config.WorldAliasSettings;
import com.djrapitops.plan.utilities.analysis.Median;
import java.util.*;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Mutator for a list of Sessions.
* <p>
* Can be used to get properties of a large number of sessions easily.
*
* @author Rsl1122
*/
public class SessionsMutator {
private final List<Session> sessions;
public static SessionsMutator forContainer(DataContainer container) {
return new SessionsMutator(container.getValue(CommonKeys.SESSIONS).orElse(new ArrayList<>()));
}
public SessionsMutator(List<Session> sessions) {
this.sessions = sessions;
}
public List<Session> all() {
return sessions;
}
public SessionsMutator sort(Comparator<Session> sessionComparator) {
sessions.sort(sessionComparator);
return this;
}
public SessionsMutator filterBy(Predicate<Session> predicate) {
return new SessionsMutator(sessions.stream()
.filter(predicate)
.collect(Collectors.toList()));
}
public SessionsMutator filterSessionsBetween(long after, long before) {
return filterBy(getBetweenPredicate(after, before));
}
public SessionsMutator filterPlayedOnServer(UUID serverUUID) {
return filterBy(session ->
session.getValue(SessionKeys.SERVER_UUID)
.map(uuid -> uuid.equals(serverUUID))
.orElse(false)
);
}
public DateHoldersMutator<Session> toDateHoldersMutator() {
return new DateHoldersMutator<>(sessions);
}
public WorldTimes toTotalWorldTimes() {
WorldTimes total = new WorldTimes();
for (Session session : sessions) {
session.getValue(SessionKeys.WORLD_TIMES).ifPresent(total::add);
}
return total;
}
public List<PlayerKill> toPlayerKillList() {
return sessions.stream()
.map(session -> session.getValue(SessionKeys.PLAYER_KILLS).orElse(new ArrayList<>()))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
public int toMobKillCount() {
return sessions.stream()
.mapToInt(session -> session.getValue(SessionKeys.MOB_KILL_COUNT).orElse(0))
.sum();
}
public int toDeathCount() {
return sessions.stream()
.mapToInt(session -> session.getValue(SessionKeys.DEATH_COUNT).orElse(0))
.sum();
}
public long toPlaytime() {
return sessions.stream()
.mapToLong(Session::getLength)
.sum();
}
public long toAfkTime() {
return sessions.stream()
.mapToLong(session -> session.getValue(SessionKeys.AFK_TIME).orElse(0L))
.sum();
}
public long toActivePlaytime() {
return sessions.stream()
.mapToLong(session -> session.getValue(SessionKeys.ACTIVE_TIME).orElse(0L))
.sum();
}
public long toLastSeen() {
return sessions.stream()
.mapToLong(session -> Math.max(session.getUnsafe(
SessionKeys.START),
session.getValue(SessionKeys.END).orElse(System.currentTimeMillis()))
).max().orElse(-1);
}
public long toLongestSessionLength() {
OptionalLong longestSession = sessions.stream().mapToLong(Session::getLength).max();
if (longestSession.isPresent()) {
return longestSession.getAsLong();
}
return -1;
}
public long toAverageSessionLength() {
OptionalDouble average = sessions.stream().map(Session::getLength)
.mapToLong(i -> i)
.average();
if (average.isPresent()) {
return (long) average.getAsDouble();
}
return 0L;
}
public long toMedianSessionLength() {
List<Long> sessionLengths = sessions.stream().map(Session::getLength).collect(Collectors.toList());
return (long) Median.forList(sessionLengths).calculate();
}
public int toUniquePlayers() {
return (int) sessions.stream()
.map(session -> session.getUnsafe(SessionKeys.UUID))
.distinct()
.count();
}
public int count() {
return sessions.size();
}
public int toPlayerKillCount() {
return toPlayerKillList().size();
}
public boolean playedBetween(long after, long before) {
return sessions.stream().anyMatch(getBetweenPredicate(after, before));
}
private Predicate<Session> getBetweenPredicate(long after, long before) {
return session -> {
Long start = session.getUnsafe(SessionKeys.START);
Long end = session.getValue(SessionKeys.END).orElse(System.currentTimeMillis());
return (after <= start && start <= before) || (after <= end && end <= before);
};
}
public static Map<UUID, List<Session>> sortByPlayers(List<Session> sessions) {
Map<UUID, List<Session>> sorted = new HashMap<>();
for (Session session : sessions) {
UUID playerUUID = session.getUnsafe(SessionKeys.UUID);
List<Session> playerSessions = sorted.getOrDefault(playerUUID, new ArrayList<>());
playerSessions.add(session);
sorted.put(playerUUID, playerSessions);
}
return sorted;
}
public static Map<UUID, List<Session>> sortByServers(List<Session> sessions) {
Map<UUID, List<Session>> sorted = new HashMap<>();
for (Session session : sessions) {
UUID serverUUID = session.getUnsafe(SessionKeys.SERVER_UUID);
List<Session> serverSessions = sorted.getOrDefault(serverUUID, new ArrayList<>());
serverSessions.add(session);
sorted.put(serverUUID, serverSessions);
}
return sorted;
}
public int toPlayerDeathCount() {
return sessions.stream().mapToInt(session -> session.getValue(SessionKeys.DEATH_COUNT).orElse(0)).sum();
}
public List<Long> toSessionStarts() {
return sessions.stream()
.map(Session::getDate)
.sorted()
.collect(Collectors.toList());
}
public double toAveragePlayersOnline(PlayersOnlineResolver playersOnlineResolver) {
return sessions.stream().map(session -> playersOnlineResolver.getOnlineOn(session.getDate()))
.filter(Optional::isPresent)
.mapToDouble(Optional::get)
.average().orElse(0.0);
}
public List<Map<String, Object>> toPlayerNameJSONMaps(
Graphs graphs,
WorldAliasSettings worldAliasSettings,
Formatters formatters
) {
return toJSONMaps(graphs, worldAliasSettings, formatters,
sessionMap -> sessionMap.get("player_name"));
}
public List<Map<String, Object>> toServerNameJSONMaps(
Graphs graphs,
WorldAliasSettings worldAliasSettings,
Formatters formatters
) {
return toJSONMaps(graphs, worldAliasSettings, formatters,
sessionMap -> sessionMap.get("server_name"));
}
private List<Map<String, Object>> toJSONMaps(
Graphs graphs,
WorldAliasSettings worldAliasSettings,
Formatters formatters,
Function<Map<String, Object>, Object> nameFunction
) {
return sessions.stream().map(session -> {
Map<String, Object> sessionMap = new HashMap<>();
sessionMap.put("player_name", session.getValue(SessionKeys.NAME).orElse(session.getUnsafe(SessionKeys.UUID).toString()));
sessionMap.put("player_uuid", session.getUnsafe(SessionKeys.UUID).toString());
sessionMap.put("server_name", session.getValue(SessionKeys.SERVER_NAME).orElse(session.getUnsafe(SessionKeys.SERVER_UUID).toString()));
sessionMap.put("server_uuid", session.getUnsafe(SessionKeys.SERVER_UUID).toString());
sessionMap.put("name", nameFunction.apply(sessionMap));
sessionMap.put("start", session.getValue(SessionKeys.START).map(formatters.yearLong()).orElse("-") +
(session.supports(SessionKeys.END) ? "" : " (Online)"));
sessionMap.put("end", session.getValue(SessionKeys.END).map(formatters.yearLong()).orElse("Online"));
sessionMap.put("most_used_world", worldAliasSettings.getLongestWorldPlayed(session));
sessionMap.put("length", session.getValue(SessionKeys.LENGTH).map(formatters.timeAmount()).orElse("-"));
sessionMap.put("afk_time", session.getValue(SessionKeys.AFK_TIME).map(formatters.timeAmount()).orElse("-"));
sessionMap.put("mob_kills", session.getValue(SessionKeys.MOB_KILL_COUNT).orElse(0));
sessionMap.put("deaths", session.getValue(SessionKeys.DEATH_COUNT).orElse(0));
sessionMap.put("player_kills", session.getPlayerKills().stream().map(
kill -> {
Map<String, Object> killMap = new HashMap<>();
killMap.put("date", formatters.secondLong().apply(kill.getDate()));
killMap.put("victim", kill.getVictimName());
killMap.put("killer", sessionMap.get("player_name"));
killMap.put("weapon", kill.getWeapon());
return killMap;
}
).collect(Collectors.toList()));
sessionMap.put("first_session", session.getValue(SessionKeys.FIRST_SESSION).orElse(false));
WorldPie worldPie = graphs.pie().worldPie(session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes()));
sessionMap.put("world_series", worldPie.getSlices());
sessionMap.put("gm_series", worldPie.toHighChartsDrillDownMaps());
return sessionMap;
}).collect(Collectors.toList());
}
}