Added more stuff to network health #601

This commit is contained in:
Rsl1122 2018-07-15 17:05:27 +03:00
parent af2c9a86f3
commit 161f79743c
9 changed files with 211 additions and 71 deletions

View File

@ -2,12 +2,11 @@ package com.djrapitops.plan.data.store.keys;
import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.PlaceholderKey;
import com.djrapitops.plan.data.store.Type;
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.system.info.server.Server;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.*;
/**
* Key objects for {@link com.djrapitops.plan.data.store.containers.NetworkContainer}.
@ -52,6 +51,7 @@ public class NetworkKeys {
public static final Key<Long> REFRESH_TIME_MONTH_AGO = new Key<>(Long.class, "REFRESH_TIME_MONTH_AGO");
public static final Key<PlayersMutator> PLAYERS_MUTATOR = CommonKeys.PLAYERS_MUTATOR;
public static final Key<Collection<Server>> BUKKIT_SERVERS = new Key<>(new Type<Collection<Server>>() {}, "BUKKIT_SERVERS");
public static final Key<TreeMap<Long, Map<String, Set<UUID>>>> ACTIVITY_DATA = CommonKeys.ACTIVITY_DATA;
private NetworkKeys() {

View File

@ -78,6 +78,13 @@ public class PlayersMutator {
return filterBy(player -> player.getActivityIndex(date).getValue() >= limit);
}
public PlayersMutator filterPlayedOnServer(UUID serverUUID) {
return filterBy(player -> !SessionsMutator.forContainer(player)
.filterPlayedOnServer(serverUUID)
.all().isEmpty()
);
}
public List<PlayerContainer> all() {
return players;
}

View File

@ -43,12 +43,24 @@ public class SessionsMutator {
return sessions;
}
public SessionsMutator filterSessionsBetween(long after, long before) {
public SessionsMutator filterBy(Predicate<Session> predicate) {
return new SessionsMutator(sessions.stream()
.filter(getBetweenPredicate(after, before))
.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);
}
@ -191,4 +203,6 @@ public class SessionsMutator {
public int toPlayerDeathCount() {
return toPlayerDeathList().size();
}
}

View File

@ -5,13 +5,15 @@ import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plan.utilities.html.icon.Icons;
import com.djrapitops.plugin.api.TimeAmount;
import java.util.*;
public abstract class AbstractHealthInfo {
protected final String subNote = "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
protected final List<String> notes;
protected final long now;
protected final long monthAgo;
@ -69,13 +71,13 @@ public abstract class AbstractHealthInfo {
String remainNote = "";
if (activeFWAGNum != 0) {
remainNote = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
remainNote = "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
if (percRemain > 50) {
remainNote += Html.GREEN_THUMB.parse();
remainNote += Icons.GREEN_THUMB;
} else if (percRemain > 20) {
remainNote += Html.YELLOW_FLAG.parse();
remainNote += Icons.YELLOW_FLAG;
} else {
remainNote += Html.RED_WARN.parse();
remainNote += Icons.RED_WARN;
serverHealth -= 2.5;
}
@ -83,22 +85,14 @@ public abstract class AbstractHealthInfo {
+ remain + "/" + activeFWAGNum + ")";
}
if (change > 0) {
notes.add(
"<p>" + Html.GREEN_THUMB.parse() + " Number of regular players has increased (+" + change + ")<br>" +
remainNote + "</p>");
addNote(Icons.GREEN_THUMB + " Number of regular players has increased (+" + change + ")" + remainNote);
} else if (change == 0) {
notes.add(
"<p>" + Html.GREEN_THUMB.parse() + " Number of regular players has stayed the same (+" + change + ")<br>" +
remainNote + "</p>");
addNote(Icons.GREEN_THUMB + " Number of regular players has stayed the same (+" + change + ")" + remainNote);
} else if (change > -20) {
notes.add(
"<p>" + Html.YELLOW_FLAG.parse() + " Number of regular players has decreased (" + change + ")<br>" +
remainNote + "</p>");
addNote(Icons.YELLOW_FLAG + " Number of regular players has decreased (" + change + ")" + remainNote);
serverHealth -= 5;
} else {
notes.add(
"<p>" + Html.RED_WARN.parse() + " Number of regular players has decreased (" + change + ")<br>" +
remainNote + "</p>");
addNote(Icons.RED_WARN + " Number of regular players has decreased (" + change + ")" + remainNote);
serverHealth -= 10;
}
}
@ -122,18 +116,18 @@ public abstract class AbstractHealthInfo {
String avgLastTwoWeeksString = Formatters.timeAmount().apply(avgLastTwoWeeks);
String avgFourToTwoWeeksString = Formatters.timeAmount().apply(avgFourToTwoWeeks);
if (avgFourToTwoWeeks >= avgLastTwoWeeks) {
notes.add("<p>" + Html.GREEN_THUMB.parse() + " Active players seem to have things to do (Played "
addNote(Icons.GREEN_THUMB + " Active players seem to have things to do (Played "
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
+ ", last two weeks vs weeks 2-4)</p>");
+ ", last two weeks vs weeks 2-4)");
} else if (avgFourToTwoWeeks - avgLastTwoWeeks > TimeAmount.HOUR.ms() * 2L) {
notes.add("<p>" + Html.RED_WARN.parse() + " Active players might be running out of things to do (Played "
addNote(Icons.RED_WARN + " Active players might be running out of things to do (Played "
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
+ ", last two weeks vs weeks 2-4)</p>");
+ ", last two weeks vs weeks 2-4)");
serverHealth -= 5;
} else {
notes.add("<p>" + Html.YELLOW_FLAG.parse() + " Active players might be running out of things to do (Played "
addNote(Icons.YELLOW_FLAG + " Active players might be running out of things to do (Played "
+ avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString
+ ", last two weeks vs weeks 2-4)</p>");
+ ", last two weeks vs weeks 2-4)");
}
}
}
@ -147,4 +141,8 @@ public abstract class AbstractHealthInfo {
regularNewCompareSet.removeAll(veryActiveFWAG);
return regularNewCompareSet.size();
}
protected void addNote(String note) {
notes.add("<p>" + note + "</p>");
}
}

View File

@ -14,7 +14,7 @@ import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.system.settings.Settings;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plan.utilities.html.icon.Icons;
import com.djrapitops.plugin.api.TimeAmount;
import java.util.ArrayList;
@ -65,11 +65,11 @@ public class HealthInformation extends AbstractHealthInfo {
.mapToInt(Optional::get)
.average().orElse(0);
if (avgOnlineOnRegister >= 1) {
notes.add("<p>" + Html.GREEN_THUMB.parse() + " New Players have players to play with when they join ("
+ FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)</p>");
addNote(Icons.GREEN_THUMB + " New Players have players to play with when they join ("
+ FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)");
} else {
notes.add("<p>" + Html.YELLOW_FLAG.parse() + " New Players may not have players to play with when they join ("
+ FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)</p>");
addNote(Icons.YELLOW_FLAG + " New Players may not have players to play with when they join ("
+ FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)");
serverHealth -= 5;
}
@ -79,11 +79,11 @@ public class HealthInformation extends AbstractHealthInfo {
if (playersNewMonth != 0) {
double retainPercentage = playersRetainedMonth / playersNewMonth;
if (retainPercentage >= 0.25) {
notes.add("<p>" + Html.GREEN_THUMB.parse() + " " + Formatters.percentage().apply(retainPercentage)
+ " of new players have stuck around (" + playersRetainedMonth + "/" + playersNewMonth + ")</p>");
addNote(Icons.GREEN_THUMB + " " + Formatters.percentage().apply(retainPercentage)
+ " of new players have stuck around (" + playersRetainedMonth + "/" + playersNewMonth + ")");
} else {
notes.add("<p>" + Html.YELLOW_FLAG.parse() + " " + Formatters.percentage().apply(retainPercentage)
+ "% of new players have stuck around (" + playersRetainedMonth + "/" + playersNewMonth + ")</p>");
addNote(Icons.YELLOW_FLAG + " " + Formatters.percentage().apply(retainPercentage)
+ "% of new players have stuck around (" + playersRetainedMonth + "/" + playersNewMonth + ")");
}
}
}
@ -95,49 +95,44 @@ public class HealthInformation extends AbstractHealthInfo {
double aboveThreshold = tpsMutator.percentageTPSAboveLowThreshold();
long tpsSpikeMonth = analysisContainer.getValue(AnalysisKeys.TPS_SPIKE_MONTH).orElse(0);
String avgLowThresholdString = "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
String avgLowThresholdString = "<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
if (aboveThreshold >= 0.96) {
avgLowThresholdString += Html.GREEN_THUMB.parse();
avgLowThresholdString += Icons.GREEN_THUMB;
} else if (aboveThreshold >= 0.9) {
avgLowThresholdString += Html.YELLOW_FLAG.parse();
avgLowThresholdString += Icons.YELLOW_FLAG;
serverHealth *= 0.9;
} else {
avgLowThresholdString += Html.RED_WARN.parse();
avgLowThresholdString += Icons.RED_WARN;
serverHealth *= 0.6;
}
avgLowThresholdString += " Average TPS was above Low Threshold "
+ FormatUtils.cutDecimals(aboveThreshold * 100.0) + "% of the time";
int threshold = Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber();
if (tpsSpikeMonth <= 5) {
notes.add("<p>" + Html.GREEN_THUMB.parse()
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
" " + tpsSpikeMonth + " times<br>" +
avgLowThresholdString + "</p>");
addNote(Icons.GREEN_THUMB + " Average TPS dropped below Low Threshold (" + threshold + ")" +
" " + tpsSpikeMonth + " times" +
avgLowThresholdString);
} else if (tpsSpikeMonth <= 25) {
notes.add("<p>" + Html.YELLOW_FLAG.parse()
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
" " + tpsSpikeMonth + " times<br>" +
avgLowThresholdString + "</p>");
addNote(Icons.YELLOW_FLAG + " Average TPS dropped below Low Threshold (" + threshold + ")" +
" " + tpsSpikeMonth + " times" +
avgLowThresholdString);
serverHealth *= 0.95;
} else {
notes.add("<p>" + Html.RED_WARN.parse()
+ " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" +
" " + tpsSpikeMonth + " times<br>" +
avgLowThresholdString + "</p>");
addNote(Icons.RED_WARN + " Average TPS dropped below Low Threshold (" + threshold + ")" +
" " + tpsSpikeMonth + " times" +
avgLowThresholdString);
serverHealth *= 0.8;
}
Formatter<Long> formatter = Formatters.timeAmount();
if (serverDownTime <= TimeAmount.DAY.ms()) {
notes.add("<p>" + Html.GREEN_THUMB.parse() + " Total Server downtime (No Data) was "
+ formatter.apply(serverDownTime) + "</p>");
addNote(Icons.GREEN_THUMB + " Total Server downtime (No Data) was " + formatter.apply(serverDownTime));
} else if (serverDownTime <= TimeAmount.WEEK.ms()) {
notes.add("<p>" + Html.YELLOW_FLAG.parse() + " Total Server downtime (No Data) was "
+ formatter.apply(serverDownTime) + "</p>");
addNote(Icons.YELLOW_FLAG + " Total Server downtime (No Data) was " + formatter.apply(serverDownTime));
serverHealth *= (TimeAmount.WEEK.ms() - serverDownTime) * 1.0 / TimeAmount.WEEK.ms();
} else {
notes.add("<p>" + Html.RED_WARN.parse() + " Total Server downtime (No Data) was "
+ formatter.apply(serverDownTime) + "</p>");
addNote(Icons.RED_WARN + " Total Server downtime (No Data) was " + formatter.apply(serverDownTime));
serverHealth *= (TimeAmount.MONTH.ms() - serverDownTime) * 1.0 / TimeAmount.MONTH.ms();
}
}

View File

@ -1,8 +1,18 @@
package com.djrapitops.plan.data.store.mutators.health;
import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.containers.NetworkContainer;
import com.djrapitops.plan.data.store.keys.AnalysisKeys;
import com.djrapitops.plan.data.store.keys.NetworkKeys;
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plan.utilities.html.icon.Icon;
import com.djrapitops.plan.utilities.html.icon.Icons;
import java.util.*;
public class NetworkHealthInformation extends AbstractHealthInfo {
@ -19,13 +29,126 @@ public class NetworkHealthInformation extends AbstractHealthInfo {
@Override
protected void calculate() {
perServerComparisonNotes(container.getUnsafe(NetworkKeys.PLAYERS_MUTATOR));
activityChangeNote(container.getUnsafe(NetworkKeys.ACTIVITY_DATA));
activePlayerPlaytimeChange(container.getUnsafe(NetworkKeys.PLAYERS_MUTATOR));
perServerComparisonNote(container.getUnsafe(NetworkKeys.PLAYERS_MUTATOR));
}
private void perServerComparisonNote(PlayersMutator playersMutator) {
private void perServerComparisonNotes(PlayersMutator playersMutator) {
Collection<Server> servers = container.getValue(NetworkKeys.BUKKIT_SERVERS)
.orElse(Collections.emptyList());
if (servers.isEmpty()) {
addNote(Icons.HELP_RING + " No Bukkit/Sponge servers to gather session data - These measures are inaccurate.");
return;
}
int serverCount = servers.size();
if (serverCount == 1) {
addNote(Icons.HELP_RING + " Single Bukkit/Sponge server to gather session data.");
return;
}
Key<Server> serverKey = new Key<>(Server.class, "SERVER");
List<DataContainer> perServerContainers = getPerServerContainers(playersMutator, servers, serverKey);
uniquePlayersNote(serverCount, serverKey, perServerContainers);
newPlayersNote(serverCount, serverKey, perServerContainers);
playersNote(serverCount, serverKey, perServerContainers);
}
private void uniquePlayersNote(int serverCount, Key<Server> serverKey, List<DataContainer> perServerContainers) {
Icon icon;
String uniquePlayersNote = " players visit on servers per day/server on average.";
double average = perServerContainers.stream()
.mapToInt(c -> c.getUnsafe(AnalysisKeys.AVG_PLAYERS_MONTH))
.average().orElse(0.0);
if (average < 1) {
icon = Icons.RED_WARN;
serverHealth -= 10.0;
} else if (average < serverCount) {
icon = Icons.YELLOW_FLAG;
serverHealth -= 5.0;
} else {
icon = Icons.GREEN_THUMB;
}
StringBuilder subNotes = new StringBuilder();
perServerContainers.stream()
.sorted(Comparator.comparingInt(c -> 0 - c.getUnsafe(AnalysisKeys.AVG_PLAYERS_MONTH)))
.map(c -> {
int playersPerMonth = c.getUnsafe(AnalysisKeys.AVG_PLAYERS_MONTH);
Server server = c.getUnsafe(serverKey);
return subNote + (playersPerMonth >= average && playersPerMonth > 0 ? Icons.GREEN_PLUS : Icons.RED_MINUS) + " " +
server.getName() + ": " + playersPerMonth;
}).forEach(subNotes::append);
addNote(icon + " " + FormatUtils.cutDecimals(average) + uniquePlayersNote + subNotes.toString());
}
private void newPlayersNote(int serverCount, Key<Server> serverKey, List<DataContainer> perServerContainers) {
Icon icon;
String newPlayersNote = " players register on servers per day/server on average.";
double average = perServerContainers.stream()
.mapToInt(c -> c.getUnsafe(AnalysisKeys.AVG_PLAYERS_NEW_MONTH))
.average().orElse(0.0);
if (average < 1) {
icon = Icons.RED_WARN;
serverHealth -= 10.0;
} else if (average < serverCount) {
icon = Icons.YELLOW_FLAG;
serverHealth -= 5.0;
} else {
icon = Icons.GREEN_THUMB;
}
StringBuilder subNotes = new StringBuilder();
perServerContainers.stream()
.sorted(Comparator.comparingInt(c -> 0 - c.getUnsafe(AnalysisKeys.AVG_PLAYERS_NEW_MONTH)))
.map(c -> {
int playersPerMonth = c.getUnsafe(AnalysisKeys.AVG_PLAYERS_NEW_MONTH);
Server server = c.getUnsafe(serverKey);
return subNote + (playersPerMonth >= average && playersPerMonth > 0 ? Icons.GREEN_PLUS : Icons.RED_MINUS) + " " +
server.getName() + ": " + playersPerMonth;
}).forEach(subNotes::append);
addNote(icon + " " + FormatUtils.cutDecimals(average) + newPlayersNote + subNotes.toString());
}
private List<DataContainer> getPerServerContainers(PlayersMutator playersMutator, Collection<Server> servers, Key<Server> serverKey) {
List<DataContainer> perServerContainers = new ArrayList<>();
for (Server server : servers) {
UUID serverUUID = server.getUuid();
DataContainer serverContainer = new DataContainer();
serverContainer.putRawData(serverKey, server);
PlayersMutator serverPlayers = playersMutator.filterPlayedOnServer(serverUUID);
PlayersMutator serverRegistered = serverPlayers.filterRegisteredBetween(monthAgo, now);
int averageNewPerDay = serverRegistered.averageNewPerDay();
serverContainer.putRawData(AnalysisKeys.AVG_PLAYERS_NEW_MONTH, averageNewPerDay);
SessionsMutator serverSessions = new SessionsMutator(serverPlayers.getSessions())
.filterSessionsBetween(monthAgo, now)
.filterPlayedOnServer(serverUUID);
int averageUniquePerDay = serverSessions.toAverageUniqueJoinsPerDay();
int uniquePlayers = serverSessions.toUniquePlayers();
serverContainer.putRawData(AnalysisKeys.AVG_PLAYERS_MONTH, averageUniquePerDay);
serverContainer.putRawData(AnalysisKeys.PLAYERS_MONTH, uniquePlayers);
perServerContainers.add(serverContainer);
}
return perServerContainers;
}
private void playersNote(int serverCount, Key<Server> serverKey, List<DataContainer> perServerContainers) {
Icon icon = Icons.HELP_RING;
String uniquePlayersNote = "${playersMonth} players played on the network:";
StringBuilder subNotes = new StringBuilder();
perServerContainers.stream()
.sorted(Comparator.comparingInt(c -> 0 - c.getUnsafe(AnalysisKeys.PLAYERS_MONTH)))
.map(c -> {
int playersPerMonth = c.getUnsafe(AnalysisKeys.PLAYERS_MONTH);
Server server = c.getUnsafe(serverKey);
return subNote + (playersPerMonth > 0 ? Icons.GREEN_PLUS : Icons.RED_MINUS) + " " +
server.getName() + ": " + playersPerMonth;
}).forEach(subNotes::append);
addNote(icon.toHtml() + " " + uniquePlayersNote + subNotes.toString());
}
}

View File

@ -6,10 +6,7 @@ import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.container.TPS;
import com.djrapitops.plan.data.container.UserInfo;
import com.djrapitops.plan.data.store.containers.*;
import com.djrapitops.plan.data.store.keys.PerServerKeys;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.keys.ServerKeys;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.data.store.keys.*;
import com.djrapitops.plan.data.store.mutators.PerServerMutator;
import com.djrapitops.plan.data.store.mutators.PlayersMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
@ -30,7 +27,9 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
@Override
public NetworkContainer getNetworkContainer() {
return new NetworkContainer(getBungeeServerContainer());
NetworkContainer networkContainer = new NetworkContainer(getBungeeServerContainer());
networkContainer.putSupplier(NetworkKeys.BUKKIT_SERVERS, () -> getBukkitServers().values());
return networkContainer;
}
private ServerContainer getBungeeServerContainer() {

View File

@ -38,9 +38,6 @@ public enum Html {
*/
@Deprecated
FA_COLORED_ICON("<i class=\"col-${0} fa fa-${1}\"></i>"),
GREEN_THUMB("<i class=\"fa fa-thumbs-up g\"></i>"),
YELLOW_FLAG("<i class=\"fa fa-flag o\"></i>"),
RED_WARN("<i class=\"fa fa-exclamation-circle r\"></i>"),
SPAN("${0}</span>"),
BUTTON("<a class=\"button\" href=\"${0}\">${1}</a>"),
BUTTON_CLASS("class=\"button\""),

View File

@ -18,6 +18,13 @@ public class Icons {
public static final Icon BANNED = Icon.called("gavel").of(Color.RED).build();
public static final Icon SERVER = Icon.called("server").of(Color.GREEN).build();
public static final Icon GREEN_THUMB = Icon.called("thumbs-up").of(Color.GREEN).build();
public static final Icon YELLOW_FLAG = Icon.called("flag").of(Color.AMBER).build();
public static final Icon RED_WARN = Icon.called("exclamation-circle").of(Color.RED).build();
public static final Icon GREEN_PLUS = Icon.called("plus").of(Color.GREEN).build();
public static final Icon RED_MINUS = Icon.called("minus").of(Color.RED).build();
public static final Icon HELP_RING = Icon.called("life-ring").of(Color.RED).of(Family.REGULAR).build();
private Icons() {
/* Static variable class */
}