diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/keys/SessionKeys.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/keys/SessionKeys.java index 21b2f0269..8f1ac3ee9 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/keys/SessionKeys.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/keys/SessionKeys.java @@ -57,6 +57,7 @@ public class SessionKeys { */ @Deprecated public static final Key LONGEST_WORLD_PLAYED = new Key<>(String.class, "longest_world_played"); + public static final Key AVERAGE_PING = new Key<>(Double.class, "averagePing"); private SessionKeys() { /* Static variable class */ diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/PingMutator.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/PingMutator.java index faaccb675..034daa861 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/PingMutator.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/PingMutator.java @@ -16,14 +16,15 @@ */ package com.djrapitops.plan.delivery.domain.mutators; +import com.djrapitops.plan.delivery.domain.DateHolder; 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.gathering.domain.Ping; +import com.djrapitops.plan.gathering.domain.Session; +import com.djrapitops.plan.utilities.comparators.DateHolderOldestComparator; -import java.util.Collections; -import java.util.List; -import java.util.SortedMap; -import java.util.UUID; +import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -60,6 +61,52 @@ public class PingMutator { }).collect(Collectors.toList())); } + public static Map> sortByServers(List pings) { + Map> sorted = new HashMap<>(); + for (Ping ping : pings) { + UUID serverUUID = ping.getServerUUID(); + SortedMap serverSessions = sorted.getOrDefault(serverUUID, new TreeMap<>()); + serverSessions.put(ping.getDate(), ping); + sorted.put(serverUUID, serverSessions); + } + return sorted; + } + + public void addPingToSessions(List sessions) { + if (sessions.isEmpty()) return; + + Comparator comparator = new DateHolderOldestComparator(); + sessions.sort(comparator); + pings.sort(comparator); + Map> pingByServer = sortByServers(pings); + Map> sessionsByServer = SessionsMutator.sortByServers(sessions); + for (Map.Entry> entry : pingByServer.entrySet()) { + UUID serverUUID = entry.getKey(); + SortedMap pingOfServer = entry.getValue(); + if (pingOfServer.isEmpty()) continue; + + List sessionsOfServer = sessionsByServer.getOrDefault(serverUUID, Collections.emptyList()); + double pingCount = 0.0; + int pingEntries = 0; + + for (Session session : sessionsOfServer) { + long start = session.getDate(); + Long end = session.getValue(SessionKeys.END).orElseGet(System::currentTimeMillis); + // Calcuclate average ping for each session with a Ping submap + SortedMap duringSession = pingOfServer.subMap(start, end); + for (Ping ping : duringSession.values()) { + pingCount += ping.getAverage(); + pingEntries++; + } + if (pingEntries != 0) { + session.putRawData(SessionKeys.AVERAGE_PING, pingCount / pingEntries); + } + pingCount = 0.0; + pingEntries = 0; + } + } + } + public List all() { return pings; } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java index 5eccac2b0..eb93e6c2a 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/domain/mutators/SessionsMutator.java @@ -210,6 +210,17 @@ public class SessionsMutator { return sorted; } + public static Map> sortByServersToMaps(List sessions) { + Map> sorted = new HashMap<>(); + for (Session session : sessions) { + UUID serverUUID = session.getUnsafe(SessionKeys.SERVER_UUID); + TreeMap serverSessions = sorted.getOrDefault(serverUUID, new TreeMap<>()); + serverSessions.put(session.getDate(), session); + sorted.put(serverUUID, serverSessions); + } + return sorted; + } + public int toPlayerDeathCount() { return sessions.stream().mapToInt(session -> session.getValue(SessionKeys.DEATH_COUNT).orElse(0)).sum(); } @@ -281,6 +292,10 @@ public class SessionsMutator { 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()); + + session.getValue(SessionKeys.AVERAGE_PING).ifPresent(averagePing -> + sessionMap.put("avg_ping", formatters.decimals().apply(averagePing) + " ms") + ); return sessionMap; }).collect(Collectors.toList()); } diff --git a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/PlayerJSONParser.java b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/PlayerJSONParser.java index 5a177769f..6afbf2617 100644 --- a/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/PlayerJSONParser.java +++ b/Plan/common/src/main/java/com/djrapitops/plan/delivery/rendering/json/PlayerJSONParser.java @@ -96,6 +96,8 @@ public class PlayerJSONParser { List kills = player.getValue(PlayerKeys.PLAYER_KILLS).orElse(Collections.emptyList()); List deaths = player.getValue(PlayerKeys.PLAYER_DEATHS_KILLS).orElse(Collections.emptyList()); + PingMutator.forContainer(player).addPingToSessions(sessionsMutator.all()); + Map data = new HashMap<>(); data.put("info", createInfoJSONMap(player, serverNames)); data.put("online_activity", createOnlineActivityJSONMap(sessionsMutator)); diff --git a/Plan/common/src/main/java/com/djrapitops/plan/utilities/comparators/DateHolderOldestComparator.java b/Plan/common/src/main/java/com/djrapitops/plan/utilities/comparators/DateHolderOldestComparator.java new file mode 100644 index 000000000..f26a71497 --- /dev/null +++ b/Plan/common/src/main/java/com/djrapitops/plan/utilities/comparators/DateHolderOldestComparator.java @@ -0,0 +1,32 @@ +/* + * 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 . + */ +package com.djrapitops.plan.utilities.comparators; + +import com.djrapitops.plan.delivery.domain.DateHolder; + +/** + * Compares DateHolder objects so that most recent is last. + * + * @author Rsl1122 + */ +public class DateHolderOldestComparator extends DateHolderRecentComparator { + + @Override + public int compare(DateHolder one, DateHolder two) { + return -super.compare(one, two); + } +} diff --git a/Plan/common/src/main/resources/assets/plan/web/js/sessionAccordion.js b/Plan/common/src/main/resources/assets/plan/web/js/sessionAccordion.js index e5d5db79f..337601d14 100644 --- a/Plan/common/src/main/resources/assets/plan/web/js/sessionAccordion.js +++ b/Plan/common/src/main/resources/assets/plan/web/js/sessionAccordion.js @@ -81,7 +81,9 @@ function createAccordionBody(i, session) { '

Ended' + session.end + '

' + '

Length' + session.length + '

' + '

AFK Time' + session.afk_time + '

' + - '

Server' + session.server_name + '


' + + '

Server' + session.server_name + '

' + + (session.avg_ping ? '

Average Ping' + session.avg_ping + '

' : '') + + '
' + '

Player Kills' + session.player_kills.length + '

' + '

Mob Kills' + session.mob_kills + '

' + '

Deaths' + session.deaths + '


' +