diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java index 8d896b3ff..847b2f051 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/AnalysisContainer.java @@ -9,6 +9,7 @@ import com.djrapitops.plan.data.store.keys.ServerKeys; import com.djrapitops.plan.data.store.mutators.*; import com.djrapitops.plan.data.store.mutators.combiners.MultiBanCombiner; import com.djrapitops.plan.data.store.mutators.formatting.Formatters; +import com.djrapitops.plan.data.store.mutators.health.HealthInformation; import com.djrapitops.plan.data.time.WorldTimes; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.info.server.ServerInfo; diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/NetworkContainer.java b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/NetworkContainer.java index 0d169ecd0..438d74baa 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/containers/NetworkContainer.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/containers/NetworkContainer.java @@ -8,13 +8,16 @@ import com.djrapitops.plan.data.store.keys.ServerKeys; import com.djrapitops.plan.data.store.mutators.PlayersMutator; import com.djrapitops.plan.data.store.mutators.TPSMutator; import com.djrapitops.plan.data.store.mutators.formatting.Formatters; +import com.djrapitops.plan.data.store.mutators.health.NetworkHealthInformation; import com.djrapitops.plan.system.database.databases.Database; import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.settings.theme.Theme; import com.djrapitops.plan.system.settings.theme.ThemeVal; import com.djrapitops.plan.utilities.MiscUtils; +import com.djrapitops.plan.utilities.html.graphs.ActivityStackGraph; import com.djrapitops.plan.utilities.html.graphs.WorldMap; import com.djrapitops.plan.utilities.html.graphs.line.OnlineActivityGraph; +import com.djrapitops.plan.utilities.html.graphs.pie.ActivityPie; import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.api.utility.log.Log; @@ -44,6 +47,14 @@ public class NetworkContainer extends DataContainer { addConstants(); addPlayerInformation(); + addNetworkHealth(); + } + + private void addNetworkHealth() { + Key healthInformation = new Key<>(NetworkHealthInformation.class, "HEALTH_INFORMATION"); + putSupplier(healthInformation, () -> new NetworkHealthInformation(this)); + putSupplier(NetworkKeys.HEALTH_INDEX, () -> getUnsafe(healthInformation).getServerHealth()); + putSupplier(NetworkKeys.HEALTH_NOTES, () -> getUnsafe(healthInformation).toHtml()); } public void putAnalysisContainer(AnalysisContainer analysisContainer) { @@ -91,6 +102,15 @@ public class NetworkContainer extends DataContainer { putSupplier(NetworkKeys.PLAYERS_ONLINE_SERIES, () -> new OnlineActivityGraph(TPSMutator.forContainer(bungeeContainer)).toHighChartsSeries() ); + Key activityStackGraph = new Key<>(ActivityStackGraph.class, "ACTIVITY_STACK_GRAPH"); + putSupplier(NetworkKeys.ACTIVITY_DATA, () -> getUnsafe(NetworkKeys.PLAYERS_MUTATOR).toActivityDataMap(getUnsafe(NetworkKeys.REFRESH_TIME))); + putSupplier(activityStackGraph, () -> new ActivityStackGraph(getUnsafe(NetworkKeys.ACTIVITY_DATA))); + putSupplier(NetworkKeys.ACTIVITY_STACK_CATEGORIES, () -> getUnsafe(activityStackGraph).toHighChartsLabels()); + putSupplier(NetworkKeys.ACTIVITY_STACK_SERIES, () -> getUnsafe(activityStackGraph).toHighChartsSeries()); + putSupplier(NetworkKeys.ACTIVITY_PIE_SERIES, () -> + new ActivityPie(getUnsafe(NetworkKeys.ACTIVITY_DATA).get(getUnsafe(NetworkKeys.REFRESH_TIME))).toHighChartsSeries() + ); + putSupplier(NetworkKeys.ALL_TIME_PEAK_TIME_F, () -> bungeeContainer.getValue(ServerKeys.ALL_TIME_PEAK_PLAYERS).map(Formatters.year()::apply).orElse("No data") ); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/keys/AnalysisKeys.java b/Plan/src/main/java/com/djrapitops/plan/data/store/keys/AnalysisKeys.java index 142c16d79..c7c152671 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/keys/AnalysisKeys.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/keys/AnalysisKeys.java @@ -50,7 +50,7 @@ public class AnalysisKeys { public static final PlaceholderKey SESSION_TABLE = new PlaceholderKey<>(String.class, "tableBodySessions"); public static final PlaceholderKey RECENT_LOGINS = new PlaceholderKey<>(String.class, "listRecentLogins"); public static final PlaceholderKey COMMAND_USAGE_TABLE = new PlaceholderKey<>(String.class, "tableCommandUsage"); - public static final PlaceholderKey HEALTH_NOTES = new PlaceholderKey<>(String.class, "healthNotes"); + public static final PlaceholderKey HEALTH_NOTES = CommonPlaceholderKeys.HEALTH_NOTES; public static final PlaceholderKey PLUGINS_TAB = new PlaceholderKey<>(String.class, "tabsPlugins"); public static final PlaceholderKey PLUGINS_TAB_NAV = new PlaceholderKey<>(String.class, "navPluginsTabs"); // Formatted time values @@ -69,7 +69,7 @@ public class AnalysisKeys { public static final PlaceholderKey DEATHS = new PlaceholderKey<>(Integer.class, "deaths"); public static final PlaceholderKey MOB_KILL_COUNT = new PlaceholderKey<>(Integer.class, "mobKillCount"); public static final PlaceholderKey PLAYER_KILL_COUNT = new PlaceholderKey<>(Integer.class, "killCount"); - public static final PlaceholderKey HEALTH_INDEX = new PlaceholderKey<>(Double.class, "healthIndex"); + public static final PlaceholderKey HEALTH_INDEX = CommonPlaceholderKeys.HEALTH_INDEX; public static final PlaceholderKey COMMAND_COUNT = new PlaceholderKey<>(Integer.class, "commandCount"); public static final PlaceholderKey COMMAND_COUNT_UNIQUE = new PlaceholderKey<>(Integer.class, "commandUniqueCount"); // @@ -123,9 +123,9 @@ public class AnalysisKeys { public static final PlaceholderKey CHUNK_SERIES = new PlaceholderKey<>(String.class, "chunkSeries"); public static final PlaceholderKey PUNCHCARD_SERIES = new PlaceholderKey<>(String.class, "punchCardSeries"); public static final PlaceholderKey WORLD_MAP_SERIES = CommonPlaceholderKeys.WORLD_MAP_SERIES; - public static final PlaceholderKey ACTIVITY_STACK_SERIES = new PlaceholderKey<>(String.class, "activityStackSeries"); - public static final PlaceholderKey ACTIVITY_STACK_CATEGORIES = new PlaceholderKey<>(String.class, "activityStackCategories"); - public static final PlaceholderKey ACTIVITY_PIE_SERIES = new PlaceholderKey<>(String.class, "activityPieSeries"); + public static final PlaceholderKey ACTIVITY_STACK_SERIES = CommonPlaceholderKeys.ACTIVITY_STACK_SERIES; + public static final PlaceholderKey ACTIVITY_STACK_CATEGORIES = CommonPlaceholderKeys.ACTIVITY_STACK_CATEGORIES; + public static final PlaceholderKey ACTIVITY_PIE_SERIES = CommonPlaceholderKeys.ACTIVITY_PIE_SERIES; public static final PlaceholderKey CALENDAR_SERIES = new PlaceholderKey<>(String.class, "calendarSeries"); // Variables used only during analysis public static final Key SESSIONS_MUTATOR = CommonKeys.SESSIONS_MUTATOR; @@ -138,7 +138,7 @@ public class AnalysisKeys { public static final Key ANALYSIS_TIME_WEEK_AGO = new Key<>(Long.class, "ANALYSIS_TIME_WEEK_AGO"); public static final Key ANALYSIS_TIME_MONTH_AGO = new Key<>(Long.class, "ANALYSIS_TIME_MONTH_AGO"); public static final Key> PLAYER_NAMES = new Key<>(new Type>() {}, "PLAYER_NAMES"); - public static final Key>>> ACTIVITY_DATA = new Key<>(new Type>>>() {}, "ACTIVITY_DATA"); + public static final Key>>> ACTIVITY_DATA = CommonKeys.ACTIVITY_DATA; public static final Key> BAN_DATA = new Key<>(new Type>() {}, "BAN_DATA"); private AnalysisKeys() { diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/keys/CommonKeys.java b/Plan/src/main/java/com/djrapitops/plan/data/store/keys/CommonKeys.java index a95619421..7fc6257f8 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/keys/CommonKeys.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/keys/CommonKeys.java @@ -11,8 +11,7 @@ import com.djrapitops.plan.data.store.mutators.SessionsMutator; import com.djrapitops.plan.data.store.mutators.TPSMutator; import com.djrapitops.plan.data.time.WorldTimes; -import java.util.List; -import java.util.UUID; +import java.util.*; /** * Class holding Key objects that are commonly used across multiple DataContainers. @@ -47,4 +46,6 @@ public class CommonKeys { public static final Key TPS_MUTATOR = new Key<>(TPSMutator.class, "TPS_MUTATOR"); public static final Key PLAYERS_MUTATOR = new Key<>(PlayersMutator.class, "PLAYERS_MUTATOR"); + public static final Key>>> ACTIVITY_DATA = new Key<>(new Type>>>() {}, "ACTIVITY_DATA"); + } \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/keys/CommonPlaceholderKeys.java b/Plan/src/main/java/com/djrapitops/plan/data/store/keys/CommonPlaceholderKeys.java index 07a6589b2..ba8bb5e4e 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/keys/CommonPlaceholderKeys.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/keys/CommonPlaceholderKeys.java @@ -19,6 +19,12 @@ class CommonPlaceholderKeys { static final PlaceholderKey PLAYERS_ONLINE = new PlaceholderKey<>(Integer.class, "playersOnline"); static final PlaceholderKey PLAYERS_TOTAL = new PlaceholderKey<>(Integer.class, "playersTotal"); static final PlaceholderKey WORLD_MAP_SERIES = new PlaceholderKey<>(String.class, "geoMapSeries"); + static final PlaceholderKey ACTIVITY_STACK_SERIES = new PlaceholderKey<>(String.class, "activityStackSeries"); + static final PlaceholderKey ACTIVITY_STACK_CATEGORIES = new PlaceholderKey<>(String.class, "activityStackCategories"); + static final PlaceholderKey ACTIVITY_PIE_SERIES = new PlaceholderKey<>(String.class, "activityPieSeries"); + + static final PlaceholderKey HEALTH_NOTES = new PlaceholderKey<>(String.class, "healthNotes"); + static final PlaceholderKey HEALTH_INDEX = new PlaceholderKey<>(Double.class, "healthIndex"); static final PlaceholderKey PLAYERS_DAY = new PlaceholderKey<>(Integer.class, "playersDay"); static final PlaceholderKey PLAYERS_WEEK = new PlaceholderKey<>(Integer.class, "playersWeek"); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/keys/NetworkKeys.java b/Plan/src/main/java/com/djrapitops/plan/data/store/keys/NetworkKeys.java index 3796387ff..66784f9c5 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/keys/NetworkKeys.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/keys/NetworkKeys.java @@ -4,6 +4,11 @@ import com.djrapitops.plan.data.store.Key; import com.djrapitops.plan.data.store.PlaceholderKey; import com.djrapitops.plan.data.store.mutators.PlayersMutator; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.UUID; + /** * Key objects for {@link com.djrapitops.plan.data.store.containers.NetworkContainer}. * @@ -35,6 +40,11 @@ public class NetworkKeys { public static final PlaceholderKey WORLD_MAP_SERIES = CommonPlaceholderKeys.WORLD_MAP_SERIES; public static final PlaceholderKey PLAYERS_ONLINE_SERIES = CommonPlaceholderKeys.PLAYERS_ONLINE_SERIES; + public static final PlaceholderKey ACTIVITY_STACK_SERIES = CommonPlaceholderKeys.ACTIVITY_STACK_SERIES; + public static final PlaceholderKey ACTIVITY_STACK_CATEGORIES = CommonPlaceholderKeys.ACTIVITY_STACK_CATEGORIES; + public static final PlaceholderKey ACTIVITY_PIE_SERIES = CommonPlaceholderKeys.ACTIVITY_PIE_SERIES; + public static final PlaceholderKey HEALTH_INDEX = CommonPlaceholderKeys.HEALTH_INDEX; + public static final PlaceholderKey HEALTH_NOTES = CommonPlaceholderKeys.HEALTH_NOTES; public static final Key REFRESH_TIME = new Key<>(Long.class, "REFRESH_TIME"); public static final Key REFRESH_TIME_DAY_AGO = new Key<>(Long.class, "REFRESH_TIME_DAY_AGO"); @@ -42,6 +52,8 @@ public class NetworkKeys { public static final Key REFRESH_TIME_MONTH_AGO = new Key<>(Long.class, "REFRESH_TIME_MONTH_AGO"); public static final Key PLAYERS_MUTATOR = CommonKeys.PLAYERS_MUTATOR; + public static final Key>>> ACTIVITY_DATA = CommonKeys.ACTIVITY_DATA; + private NetworkKeys() { /* static variable class */ } diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/HealthInformation.java b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/HealthInformation.java deleted file mode 100644 index ad44a4d42..000000000 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/HealthInformation.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * License is provided in the jar as LICENSE also here: - * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE - */ -package com.djrapitops.plan.data.store.mutators; - -import com.djrapitops.plan.data.store.Key; -import com.djrapitops.plan.data.store.containers.AnalysisContainer; -import com.djrapitops.plan.data.store.containers.PlayerContainer; -import com.djrapitops.plan.data.store.keys.AnalysisKeys; -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.plugin.api.TimeAmount; - -import java.util.*; - -/** - * Server Health analysis mutator. - * - * @author Rsl1122 - */ -public class HealthInformation { - - private final AnalysisContainer analysisContainer; - private final List notes; - private final long now; - private double serverHealth; - private long fourWeeksAgo; - - public HealthInformation(AnalysisContainer analysisContainer) { - this.analysisContainer = analysisContainer; - this.notes = new ArrayList<>(); - - now = analysisContainer.getUnsafe(AnalysisKeys.ANALYSIS_TIME); - fourWeeksAgo = analysisContainer.getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO); - - serverHealth = 100.0; - calculate(); - } - - public String toHtml() { - StringBuilder healthNoteBuilder = new StringBuilder(); - for (String healthNote : notes) { - healthNoteBuilder.append(healthNote); - } - return healthNoteBuilder.toString(); - } - - private void calculate() { - activityChangeNote(); - newPlayerNote(); - activePlayerPlaytimeChange(); - lowPerformance(); - } - - public double getServerHealth() { - return serverHealth; - } - - private void activityChangeNote() { - TreeMap>> activityData = analysisContainer.getUnsafe(AnalysisKeys.ACTIVITY_DATA); - - Map> activityNow = activityData.getOrDefault(now, new HashMap<>()); - Set veryActiveNow = activityNow.getOrDefault("Very Active", new HashSet<>()); - Set activeNow = activityNow.getOrDefault("Active", new HashSet<>()); - Set regularNow = activityNow.getOrDefault("Regular", new HashSet<>()); - - Map> activityFourWAgo = activityData.getOrDefault(fourWeeksAgo, new HashMap<>()); - Set veryActiveFWAG = activityFourWAgo.getOrDefault("Very Active", new HashSet<>()); - Set activeFWAG = activityFourWAgo.getOrDefault("Active", new HashSet<>()); - Set regularFWAG = activityFourWAgo.getOrDefault("Regular", new HashSet<>()); - - Set regularRemainCompareSet = new HashSet<>(regularFWAG); - regularRemainCompareSet.addAll(activeFWAG); - regularRemainCompareSet.addAll(veryActiveFWAG); - - int activeFWAGNum = regularRemainCompareSet.size(); - regularRemainCompareSet.removeAll(regularNow); - regularRemainCompareSet.removeAll(activeNow); - regularRemainCompareSet.removeAll(veryActiveNow); - int notRegularAnymore = regularRemainCompareSet.size(); - int remain = activeFWAGNum - notRegularAnymore; - double percRemain = remain * 100.0 / activeFWAGNum; - - int newActive = getNewActive(veryActiveNow, activeNow, regularNow, veryActiveFWAG, activeFWAG, regularFWAG); - - int change = newActive - notRegularAnymore; - - String remainNote = ""; - if (activeFWAGNum != 0) { - remainNote = "     "; - if (percRemain > 50) { - remainNote += Html.GREEN_THUMB.parse(); - } else if (percRemain > 20) { - remainNote += Html.YELLOW_FLAG.parse(); - } else { - remainNote += Html.RED_WARN.parse(); - serverHealth -= 2.5; - } - - remainNote += " " + FormatUtils.cutDecimals(percRemain) + "% of regular players have remained active (" - + remain + "/" + activeFWAGNum + ")"; - } - if (change > 0) { - notes.add( - "

" + Html.GREEN_THUMB.parse() + " Number of regular players has increased (+" + change + ")
" + - remainNote + "

"); - } else if (change == 0) { - notes.add( - "

" + Html.GREEN_THUMB.parse() + " Number of regular players has stayed the same (+" + change + ")
" + - remainNote + "

"); - } else if (change > -20) { - notes.add( - "

" + Html.YELLOW_FLAG.parse() + " Number of regular players has decreased (" + change + ")
" + - remainNote + "

"); - serverHealth -= 5; - } else { - notes.add( - "

" + Html.RED_WARN.parse() + " Number of regular players has decreased (" + change + ")
" + - remainNote + "

"); - serverHealth -= 10; - } - } - - private void newPlayerNote() { - Key newMonth = new Key<>(PlayersMutator.class, "NEW_MONTH"); - PlayersMutator newPlayersMonth = analysisContainer.getValue(newMonth).orElse(new PlayersMutator(new ArrayList<>())); - PlayersOnlineResolver onlineResolver = analysisContainer.getUnsafe(AnalysisKeys.PLAYERS_ONLINE_RESOLVER); - - double avgOnlineOnRegister = newPlayersMonth.registerDates().stream() - .mapToInt(date -> onlineResolver.getOnlineOn(date).orElse(-1)) - .filter(value -> value != -1) - .average().orElse(0); - if (avgOnlineOnRegister >= 1) { - notes.add("

" + Html.GREEN_THUMB.parse() + " New Players have players to play with when they join (" - + FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)

"); - } else { - notes.add("

" + Html.YELLOW_FLAG.parse() + " New Players may not have players to play with when they join (" - + FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)

"); - serverHealth -= 5; - } - - long playersNewMonth = analysisContainer.getValue(AnalysisKeys.PLAYERS_NEW_MONTH).orElse(0); - long playersRetainedMonth = analysisContainer.getValue(AnalysisKeys.PLAYERS_RETAINED_MONTH).orElse(0); - - if (playersNewMonth != 0) { - double retainPercentage = playersRetainedMonth / playersNewMonth; - if (retainPercentage >= 0.25) { - notes.add("

" + Html.GREEN_THUMB.parse() + " " + Formatters.percentage().apply(retainPercentage) - + " of new players have stuck around (" + playersRetainedMonth + "/" + playersNewMonth + ")

"); - } else { - notes.add("

" + Html.YELLOW_FLAG.parse() + " " + Formatters.percentage().apply(retainPercentage) - + "% of new players have stuck around (" + playersRetainedMonth + "/" + playersNewMonth + ")

"); - } - } - } - - private void activePlayerPlaytimeChange() { - PlayersMutator currentlyActive = analysisContainer.getUnsafe(AnalysisKeys.PLAYERS_MUTATOR).filterActive(now, 1.75); - long twoWeeksAgo = (now - (now - fourWeeksAgo)) / 2L; - - long totalFourToTwoWeeks = 0; - long totalLastTwoWeeks = 0; - for (PlayerContainer activePlayer : currentlyActive.all()) { - totalFourToTwoWeeks += SessionsMutator.forContainer(activePlayer) - .filterSessionsBetween(fourWeeksAgo, twoWeeksAgo).toActivePlaytime(); - totalLastTwoWeeks += SessionsMutator.forContainer(activePlayer) - .filterSessionsBetween(twoWeeksAgo, now).toActivePlaytime(); - } - int activeCount = currentlyActive.count(); - if (activeCount != 0) { - long avgFourToTwoWeeks = totalFourToTwoWeeks / (long) activeCount; - long avgLastTwoWeeks = totalLastTwoWeeks / (long) activeCount; - String avgLastTwoWeeksString = Formatters.timeAmount().apply(avgLastTwoWeeks); - String avgFourToTwoWeeksString = Formatters.timeAmount().apply(avgFourToTwoWeeks); - if (avgFourToTwoWeeks >= avgLastTwoWeeks) { - notes.add("

" + Html.GREEN_THUMB.parse() + " Active players seem to have things to do (Played " - + avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString - + ", last two weeks vs weeks 2-4)

"); - } else if (avgFourToTwoWeeks - avgLastTwoWeeks > TimeAmount.HOUR.ms() * 2L) { - notes.add("

" + Html.RED_WARN.parse() + " Active players might be running out of things to do (Played " - + avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString - + ", last two weeks vs weeks 2-4)

"); - serverHealth -= 5; - } else { - notes.add("

" + Html.YELLOW_FLAG.parse() + " Active players might be running out of things to do (Played " - + avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString - + ", last two weeks vs weeks 2-4)

"); - } - } - } - - private void lowPerformance() { - Key tpsMonth = new Key<>(TPSMutator.class, "TPS_MONTH"); - TPSMutator tpsMutator = analysisContainer.getUnsafe(tpsMonth); - long serverDownTime = tpsMutator.serverDownTime(); - double aboveThreshold = tpsMutator.percentageTPSAboveLowThreshold(); - long tpsSpikeMonth = analysisContainer.getValue(AnalysisKeys.TPS_SPIKE_MONTH).orElse(0); - - String avgLowThresholdString = "     "; - if (aboveThreshold >= 0.96) { - avgLowThresholdString += Html.GREEN_THUMB.parse(); - } else if (aboveThreshold >= 0.9) { - avgLowThresholdString += Html.YELLOW_FLAG.parse(); - serverHealth *= 0.9; - } else { - avgLowThresholdString += Html.RED_WARN.parse(); - serverHealth *= 0.6; - } - avgLowThresholdString += " Average TPS was above Low Threshold " - + FormatUtils.cutDecimals(aboveThreshold * 100.0) + "% of the time"; - - if (tpsSpikeMonth <= 5) { - notes.add("

" + Html.GREEN_THUMB.parse() - + " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" + - " " + tpsSpikeMonth + " times
" + - avgLowThresholdString + "

"); - } else if (tpsSpikeMonth <= 25) { - notes.add("

" + Html.YELLOW_FLAG.parse() - + " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" + - " " + tpsSpikeMonth + " times
" + - avgLowThresholdString + "

"); - serverHealth *= 0.95; - } else { - notes.add("

" + Html.RED_WARN.parse() - + " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" + - " " + tpsSpikeMonth + " times
" + - avgLowThresholdString + "

"); - serverHealth *= 0.8; - } - - Formatter formatter = Formatters.timeAmount(); - if (serverDownTime <= TimeAmount.DAY.ms()) { - notes.add("

" + Html.GREEN_THUMB.parse() + " Total Server downtime (No Data) was " - + formatter.apply(serverDownTime) + "

"); - } else if (serverDownTime <= TimeAmount.WEEK.ms()) { - notes.add("

" + Html.YELLOW_FLAG.parse() + " Total Server downtime (No Data) was " - + formatter.apply(serverDownTime) + "

"); - serverHealth *= (TimeAmount.WEEK.ms() - serverDownTime) * 1.0 / TimeAmount.WEEK.ms(); - } else { - notes.add("

" + Html.RED_WARN.parse() + " Total Server downtime (No Data) was " - + formatter.apply(serverDownTime) + "

"); - serverHealth *= (TimeAmount.MONTH.ms() - serverDownTime) * 1.0 / TimeAmount.MONTH.ms(); - } - } - - private int getNewActive(Set veryActiveNow, Set activeNow, Set regularNow, Set veryActiveFWAG, Set activeFWAG, Set regularFWAG) { - Set regularNewCompareSet = new HashSet<>(regularNow); - regularNewCompareSet.addAll(activeNow); - regularNewCompareSet.addAll(veryActiveNow); - regularNewCompareSet.removeAll(regularFWAG); - regularNewCompareSet.removeAll(activeFWAG); - regularNewCompareSet.removeAll(veryActiveFWAG); - return regularNewCompareSet.size(); - } -} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/NetworkPerServerMutator.java b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/NetworkPerServerMutator.java new file mode 100644 index 000000000..07f2bf2f6 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/NetworkPerServerMutator.java @@ -0,0 +1,48 @@ +package com.djrapitops.plan.data.store.mutators; + +import com.djrapitops.plan.data.store.containers.DataContainer; +import com.djrapitops.plan.data.store.containers.PerServerContainer; +import com.djrapitops.plan.data.store.containers.PlayerContainer; +import com.djrapitops.plan.data.store.keys.CommonKeys; +import com.djrapitops.plan.data.store.keys.PlayerKeys; + +import java.util.*; + +public class NetworkPerServerMutator { + + private final Map> perServerContainers; + + public NetworkPerServerMutator(PlayersMutator playersMutator) { + this.perServerContainers = perServerContainers(playersMutator); + } + + public static NetworkPerServerMutator forContainer(DataContainer container) { + return new NetworkPerServerMutator( + container.getValue(CommonKeys.PLAYERS_MUTATOR) + .orElse(PlayersMutator.forContainer(container)) + ); + } + + public Map> getPerServerContainers() { + return perServerContainers; + } + + private Map> perServerContainers(PlayersMutator playersMutator) { + Map> dataContainerMap = new HashMap<>(); + + for (PlayerContainer playerContainer : playersMutator.all()) { + UUID uuid = playerContainer.getUnsafe(PlayerKeys.UUID); + PerServerContainer perServerContainer = playerContainer.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer()); + for (Map.Entry entry : perServerContainer.entrySet()) { + UUID serverUUID = entry.getKey(); + DataContainer container = entry.getValue(); + container.putRawData(PlayerKeys.UUID, uuid); + List dataContainers = dataContainerMap.getOrDefault(serverUUID, new ArrayList<>()); + dataContainers.add(container); + dataContainerMap.put(serverUUID, dataContainers); + } + } + + return dataContainerMap; + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerDataMutator.java b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerMutator.java similarity index 91% rename from Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerDataMutator.java rename to Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerMutator.java index 77b34813e..ca453436e 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerDataMutator.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PerServerMutator.java @@ -15,16 +15,16 @@ import java.util.stream.Collectors; * * @author Rsl1122 */ -public class PerServerDataMutator { +public class PerServerMutator { private final PerServerContainer data; - public PerServerDataMutator(PerServerContainer data) { + public PerServerMutator(PerServerContainer data) { this.data = data; } - public static PerServerDataMutator forContainer(DataContainer container) { - return new PerServerDataMutator(container.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer())); + public static PerServerMutator forContainer(DataContainer container) { + return new PerServerMutator(container.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer())); } public List flatMapSessions() { diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PlayersMutator.java b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PlayersMutator.java index 710556820..a768bf0d0 100644 --- a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PlayersMutator.java +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/PlayersMutator.java @@ -107,7 +107,7 @@ public class PlayersMutator { Map> map = activityData.getOrDefault(time, new HashMap<>()); if (!players.isEmpty()) { for (PlayerContainer player : players) { - if (player.getValue(PlayerKeys.REGISTERED).orElse(0L) < time) { + if (player.getValue(PlayerKeys.REGISTERED).orElse(0L) > time) { continue; } ActivityIndex activityIndex = player.getActivityIndex(time); diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/AbstractHealthInfo.java b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/AbstractHealthInfo.java new file mode 100644 index 000000000..93257d7a5 --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/AbstractHealthInfo.java @@ -0,0 +1,150 @@ +package com.djrapitops.plan.data.store.mutators.health; + +import com.djrapitops.plan.data.store.containers.PlayerContainer; +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.plugin.api.TimeAmount; + +import java.util.*; + +public abstract class AbstractHealthInfo { + + protected final List notes; + protected final long now; + protected final long monthAgo; + + protected double serverHealth; + + public AbstractHealthInfo(long now, long monthAgo) { + this.now = now; + this.monthAgo = monthAgo; + serverHealth = 100.0; + + this.notes = new ArrayList<>(); + } + + protected abstract void calculate(); + + public double getServerHealth() { + return serverHealth; + } + + public String toHtml() { + StringBuilder healthNoteBuilder = new StringBuilder(); + for (String healthNote : notes) { + healthNoteBuilder.append(healthNote); + } + return healthNoteBuilder.toString(); + } + + protected void activityChangeNote(TreeMap>> activityData) { + Map> activityNow = activityData.getOrDefault(now, new HashMap<>()); + Set veryActiveNow = activityNow.getOrDefault("Very Active", new HashSet<>()); + Set activeNow = activityNow.getOrDefault("Active", new HashSet<>()); + Set regularNow = activityNow.getOrDefault("Regular", new HashSet<>()); + + Map> activityFourWAgo = activityData.getOrDefault(monthAgo, new HashMap<>()); + Set veryActiveFWAG = activityFourWAgo.getOrDefault("Very Active", new HashSet<>()); + Set activeFWAG = activityFourWAgo.getOrDefault("Active", new HashSet<>()); + Set regularFWAG = activityFourWAgo.getOrDefault("Regular", new HashSet<>()); + + Set regularRemainCompareSet = new HashSet<>(regularFWAG); + regularRemainCompareSet.addAll(activeFWAG); + regularRemainCompareSet.addAll(veryActiveFWAG); + + int activeFWAGNum = regularRemainCompareSet.size(); + regularRemainCompareSet.removeAll(regularNow); + regularRemainCompareSet.removeAll(activeNow); + regularRemainCompareSet.removeAll(veryActiveNow); + int notRegularAnymore = regularRemainCompareSet.size(); + int remain = activeFWAGNum - notRegularAnymore; + double percRemain = remain * 100.0 / activeFWAGNum; + + int newActive = getNewActive(veryActiveNow, activeNow, regularNow, veryActiveFWAG, activeFWAG, regularFWAG); + + int change = newActive - notRegularAnymore; + + String remainNote = ""; + if (activeFWAGNum != 0) { + remainNote = "     "; + if (percRemain > 50) { + remainNote += Html.GREEN_THUMB.parse(); + } else if (percRemain > 20) { + remainNote += Html.YELLOW_FLAG.parse(); + } else { + remainNote += Html.RED_WARN.parse(); + serverHealth -= 2.5; + } + + remainNote += " " + FormatUtils.cutDecimals(percRemain) + "% of regular players have remained active (" + + remain + "/" + activeFWAGNum + ")"; + } + if (change > 0) { + notes.add( + "

" + Html.GREEN_THUMB.parse() + " Number of regular players has increased (+" + change + ")
" + + remainNote + "

"); + } else if (change == 0) { + notes.add( + "

" + Html.GREEN_THUMB.parse() + " Number of regular players has stayed the same (+" + change + ")
" + + remainNote + "

"); + } else if (change > -20) { + notes.add( + "

" + Html.YELLOW_FLAG.parse() + " Number of regular players has decreased (" + change + ")
" + + remainNote + "

"); + serverHealth -= 5; + } else { + notes.add( + "

" + Html.RED_WARN.parse() + " Number of regular players has decreased (" + change + ")
" + + remainNote + "

"); + serverHealth -= 10; + } + } + + protected void activePlayerPlaytimeChange(PlayersMutator playersMutator) { + PlayersMutator currentlyActive = playersMutator.filterActive(now, 1.75); + long twoWeeksAgo = (now - (now - monthAgo)) / 2L; + + long totalFourToTwoWeeks = 0; + long totalLastTwoWeeks = 0; + for (PlayerContainer activePlayer : currentlyActive.all()) { + totalFourToTwoWeeks += SessionsMutator.forContainer(activePlayer) + .filterSessionsBetween(monthAgo, twoWeeksAgo).toActivePlaytime(); + totalLastTwoWeeks += SessionsMutator.forContainer(activePlayer) + .filterSessionsBetween(twoWeeksAgo, now).toActivePlaytime(); + } + int activeCount = currentlyActive.count(); + if (activeCount != 0) { + long avgFourToTwoWeeks = totalFourToTwoWeeks / (long) activeCount; + long avgLastTwoWeeks = totalLastTwoWeeks / (long) activeCount; + String avgLastTwoWeeksString = Formatters.timeAmount().apply(avgLastTwoWeeks); + String avgFourToTwoWeeksString = Formatters.timeAmount().apply(avgFourToTwoWeeks); + if (avgFourToTwoWeeks >= avgLastTwoWeeks) { + notes.add("

" + Html.GREEN_THUMB.parse() + " Active players seem to have things to do (Played " + + avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString + + ", last two weeks vs weeks 2-4)

"); + } else if (avgFourToTwoWeeks - avgLastTwoWeeks > TimeAmount.HOUR.ms() * 2L) { + notes.add("

" + Html.RED_WARN.parse() + " Active players might be running out of things to do (Played " + + avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString + + ", last two weeks vs weeks 2-4)

"); + serverHealth -= 5; + } else { + notes.add("

" + Html.YELLOW_FLAG.parse() + " Active players might be running out of things to do (Played " + + avgLastTwoWeeksString + " vs " + avgFourToTwoWeeksString + + ", last two weeks vs weeks 2-4)

"); + } + } + } + + private int getNewActive(Set veryActiveNow, Set activeNow, Set regularNow, Set veryActiveFWAG, Set activeFWAG, Set regularFWAG) { + Set regularNewCompareSet = new HashSet<>(regularNow); + regularNewCompareSet.addAll(activeNow); + regularNewCompareSet.addAll(veryActiveNow); + regularNewCompareSet.removeAll(regularFWAG); + regularNewCompareSet.removeAll(activeFWAG); + regularNewCompareSet.removeAll(veryActiveFWAG); + return regularNewCompareSet.size(); + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/HealthInformation.java b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/HealthInformation.java new file mode 100644 index 000000000..780f1399d --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/HealthInformation.java @@ -0,0 +1,143 @@ +/* + * License is provided in the jar as LICENSE also here: + * https://github.com/Rsl1122/Plan-PlayerAnalytics/blob/master/Plan/src/main/resources/LICENSE + */ +package com.djrapitops.plan.data.store.mutators.health; + +import com.djrapitops.plan.data.store.Key; +import com.djrapitops.plan.data.store.containers.AnalysisContainer; +import com.djrapitops.plan.data.store.keys.AnalysisKeys; +import com.djrapitops.plan.data.store.mutators.PlayersMutator; +import com.djrapitops.plan.data.store.mutators.PlayersOnlineResolver; +import com.djrapitops.plan.data.store.mutators.TPSMutator; +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.plugin.api.TimeAmount; + +import java.util.ArrayList; + +/** + * Server Health analysis mutator. + * + * @author Rsl1122 + */ +public class HealthInformation extends AbstractHealthInfo { + + private final AnalysisContainer analysisContainer; + + public HealthInformation(AnalysisContainer analysisContainer) { + super( + analysisContainer.getUnsafe(AnalysisKeys.ANALYSIS_TIME), + analysisContainer.getUnsafe(AnalysisKeys.ANALYSIS_TIME_MONTH_AGO) + ); + this.analysisContainer = analysisContainer; + calculate(); + } + + public String toHtml() { + StringBuilder healthNoteBuilder = new StringBuilder(); + for (String healthNote : notes) { + healthNoteBuilder.append(healthNote); + } + return healthNoteBuilder.toString(); + } + + @Override + protected void calculate() { + activityChangeNote(analysisContainer.getUnsafe(AnalysisKeys.ACTIVITY_DATA)); + newPlayerNote(); + activePlayerPlaytimeChange(analysisContainer.getUnsafe(AnalysisKeys.PLAYERS_MUTATOR)); + lowPerformance(); + } + + private void newPlayerNote() { + Key newMonth = new Key<>(PlayersMutator.class, "NEW_MONTH"); + PlayersMutator newPlayersMonth = analysisContainer.getValue(newMonth).orElse(new PlayersMutator(new ArrayList<>())); + PlayersOnlineResolver onlineResolver = analysisContainer.getUnsafe(AnalysisKeys.PLAYERS_ONLINE_RESOLVER); + + double avgOnlineOnRegister = newPlayersMonth.registerDates().stream() + .mapToInt(date -> onlineResolver.getOnlineOn(date).orElse(-1)) + .filter(value -> value != -1) + .average().orElse(0); + if (avgOnlineOnRegister >= 1) { + notes.add("

" + Html.GREEN_THUMB.parse() + " New Players have players to play with when they join (" + + FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)

"); + } else { + notes.add("

" + Html.YELLOW_FLAG.parse() + " New Players may not have players to play with when they join (" + + FormatUtils.cutDecimals(avgOnlineOnRegister) + " on average)

"); + serverHealth -= 5; + } + + long playersNewMonth = analysisContainer.getValue(AnalysisKeys.PLAYERS_NEW_MONTH).orElse(0); + long playersRetainedMonth = analysisContainer.getValue(AnalysisKeys.PLAYERS_RETAINED_MONTH).orElse(0); + + if (playersNewMonth != 0) { + double retainPercentage = playersRetainedMonth / playersNewMonth; + if (retainPercentage >= 0.25) { + notes.add("

" + Html.GREEN_THUMB.parse() + " " + Formatters.percentage().apply(retainPercentage) + + " of new players have stuck around (" + playersRetainedMonth + "/" + playersNewMonth + ")

"); + } else { + notes.add("

" + Html.YELLOW_FLAG.parse() + " " + Formatters.percentage().apply(retainPercentage) + + "% of new players have stuck around (" + playersRetainedMonth + "/" + playersNewMonth + ")

"); + } + } + } + + private void lowPerformance() { + Key tpsMonth = new Key<>(TPSMutator.class, "TPS_MONTH"); + TPSMutator tpsMutator = analysisContainer.getUnsafe(tpsMonth); + long serverDownTime = tpsMutator.serverDownTime(); + double aboveThreshold = tpsMutator.percentageTPSAboveLowThreshold(); + long tpsSpikeMonth = analysisContainer.getValue(AnalysisKeys.TPS_SPIKE_MONTH).orElse(0); + + String avgLowThresholdString = "     "; + if (aboveThreshold >= 0.96) { + avgLowThresholdString += Html.GREEN_THUMB.parse(); + } else if (aboveThreshold >= 0.9) { + avgLowThresholdString += Html.YELLOW_FLAG.parse(); + serverHealth *= 0.9; + } else { + avgLowThresholdString += Html.RED_WARN.parse(); + serverHealth *= 0.6; + } + avgLowThresholdString += " Average TPS was above Low Threshold " + + FormatUtils.cutDecimals(aboveThreshold * 100.0) + "% of the time"; + + if (tpsSpikeMonth <= 5) { + notes.add("

" + Html.GREEN_THUMB.parse() + + " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" + + " " + tpsSpikeMonth + " times
" + + avgLowThresholdString + "

"); + } else if (tpsSpikeMonth <= 25) { + notes.add("

" + Html.YELLOW_FLAG.parse() + + " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" + + " " + tpsSpikeMonth + " times
" + + avgLowThresholdString + "

"); + serverHealth *= 0.95; + } else { + notes.add("

" + Html.RED_WARN.parse() + + " Average TPS dropped below Low Threshold (" + Settings.THEME_GRAPH_TPS_THRESHOLD_MED.getNumber() + ")" + + " " + tpsSpikeMonth + " times
" + + avgLowThresholdString + "

"); + serverHealth *= 0.8; + } + + Formatter formatter = Formatters.timeAmount(); + if (serverDownTime <= TimeAmount.DAY.ms()) { + notes.add("

" + Html.GREEN_THUMB.parse() + " Total Server downtime (No Data) was " + + formatter.apply(serverDownTime) + "

"); + } else if (serverDownTime <= TimeAmount.WEEK.ms()) { + notes.add("

" + Html.YELLOW_FLAG.parse() + " Total Server downtime (No Data) was " + + formatter.apply(serverDownTime) + "

"); + serverHealth *= (TimeAmount.WEEK.ms() - serverDownTime) * 1.0 / TimeAmount.WEEK.ms(); + } else { + notes.add("

" + Html.RED_WARN.parse() + " Total Server downtime (No Data) was " + + formatter.apply(serverDownTime) + "

"); + serverHealth *= (TimeAmount.MONTH.ms() - serverDownTime) * 1.0 / TimeAmount.MONTH.ms(); + } + } + +} \ No newline at end of file diff --git a/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/NetworkHealthInformation.java b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/NetworkHealthInformation.java new file mode 100644 index 000000000..67eb5e12f --- /dev/null +++ b/Plan/src/main/java/com/djrapitops/plan/data/store/mutators/health/NetworkHealthInformation.java @@ -0,0 +1,31 @@ +package com.djrapitops.plan.data.store.mutators.health; + +import com.djrapitops.plan.data.store.containers.NetworkContainer; +import com.djrapitops.plan.data.store.keys.NetworkKeys; +import com.djrapitops.plan.data.store.mutators.PlayersMutator; + +public class NetworkHealthInformation extends AbstractHealthInfo { + + private final NetworkContainer container; + + public NetworkHealthInformation(NetworkContainer container) { + super( + container.getUnsafe(NetworkKeys.REFRESH_TIME), + container.getUnsafe(NetworkKeys.REFRESH_TIME_MONTH_AGO) + ); + this.container = container; + calculate(); + } + + @Override + protected void calculate() { + activityChangeNote(container.getUnsafe(NetworkKeys.ACTIVITY_DATA)); + activePlayerPlaytimeChange(container.getUnsafe(NetworkKeys.PLAYERS_MUTATOR)); + + perServerComparisonNote(container.getUnsafe(NetworkKeys.PLAYERS_MUTATOR)); + } + + private void perServerComparisonNote(PlayersMutator playersMutator) { + + } +} diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/operation/FetchOperations.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/operation/FetchOperations.java index 8d87d29e4..666385c97 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/operation/FetchOperations.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/operation/FetchOperations.java @@ -18,11 +18,11 @@ public interface FetchOperations { * Used to get a NetworkContainer, some limitations apply to values returned by DataContainer keys. *

* Limitations: - * - Bungee ServerContainer does not support: ServerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_KILL_COUNT + * - Bungee ServerContainer does not support: ServerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_DEATHS, PLAYER_KILL_COUNT * - Bungee ServerContainer ServerKeys.TPS only contains playersOnline values * - NetworkKeys.PLAYERS PlayerContainers: - * - do not support: PlayerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_KILL_COUNT - * - PlayerKeys.PER_SERVER does not support: PerServerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_KILL_COUNT + * - do not support: PlayerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_DEATHS, PLAYER_KILL_COUNT + * - PlayerKeys.PER_SERVER does not support: PerServerKeys WORLD_TIMES, PLAYER_KILLS, PLAYER_DEATHS, PLAYER_KILL_COUNT *

* Blocking methods are not called until DataContainer getter methods are called. * diff --git a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLFetchOps.java b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLFetchOps.java index 9e5a9fb26..b23e3a913 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLFetchOps.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/database/databases/sql/operation/SQLFetchOps.java @@ -10,7 +10,7 @@ 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.mutators.PerServerDataMutator; +import com.djrapitops.plan.data.store.mutators.PerServerMutator; import com.djrapitops.plan.data.store.mutators.PlayersMutator; import com.djrapitops.plan.data.store.mutators.SessionsMutator; import com.djrapitops.plan.data.store.objects.DateObj; @@ -137,7 +137,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations { // Calculating getters container.putSupplier(PlayerKeys.WORLD_TIMES, () -> { - WorldTimes worldTimes = new PerServerDataMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes(); + WorldTimes worldTimes = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes(); container.getValue(PlayerKeys.ACTIVE_SESSION) .ifPresent(session -> worldTimes.add( session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()))) @@ -182,7 +182,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations { container.putSupplier(PlayerKeys.PER_SERVER, () -> perServerInfo.get(uuid)); container.putSupplier(PlayerKeys.SESSIONS, () -> { - List playerSessions = PerServerDataMutator.forContainer(container).flatMapSessions(); + List playerSessions = PerServerMutator.forContainer(container).flatMapSessions(); container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(playerSessions::add); return playerSessions; } @@ -259,18 +259,18 @@ public class SQLFetchOps extends SQLOps implements FetchOperations { container.putSupplier(PlayerKeys.NICKNAMES, () -> nicknamesTable.getNicknameInformation(uuid)); container.putSupplier(PlayerKeys.PER_SERVER, () -> getPerServerData(uuid)); - container.putSupplier(PlayerKeys.BANNED, () -> new PerServerDataMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).isBanned()); - container.putSupplier(PlayerKeys.OPERATOR, () -> new PerServerDataMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).isOperator()); + container.putSupplier(PlayerKeys.BANNED, () -> new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).isBanned()); + container.putSupplier(PlayerKeys.OPERATOR, () -> new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).isOperator()); container.putSupplier(PlayerKeys.SESSIONS, () -> { - List sessions = new PerServerDataMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapSessions(); + List sessions = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapSessions(); container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(sessions::add); return sessions; } ); container.putSupplier(PlayerKeys.WORLD_TIMES, () -> { - WorldTimes worldTimes = new PerServerDataMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes(); + WorldTimes worldTimes = new PerServerMutator(container.getUnsafe(PlayerKeys.PER_SERVER)).flatMapWorldTimes(); container.getValue(PlayerKeys.ACTIVE_SESSION).ifPresent(session -> worldTimes.add( session.getValue(SessionKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()))) ); diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/pages/parsing/InspectPage.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/pages/parsing/InspectPage.java index 1b67ab53c..7d6b534ea 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/pages/parsing/InspectPage.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/pages/parsing/InspectPage.java @@ -10,7 +10,7 @@ import com.djrapitops.plan.data.store.containers.PerServerContainer; import com.djrapitops.plan.data.store.containers.PlayerContainer; import com.djrapitops.plan.data.store.keys.PlayerKeys; import com.djrapitops.plan.data.store.mutators.ActivityIndex; -import com.djrapitops.plan.data.store.mutators.PerServerDataMutator; +import com.djrapitops.plan.data.store.mutators.PerServerMutator; import com.djrapitops.plan.data.store.mutators.PvpInfoMutator; import com.djrapitops.plan.data.store.mutators.SessionsMutator; import com.djrapitops.plan.data.store.mutators.formatting.Formatter; @@ -107,15 +107,15 @@ public class InspectPage implements Page { replacer.put("kickCount", timesKicked); PerServerContainer perServerContainer = container.getValue(PlayerKeys.PER_SERVER).orElse(new PerServerContainer()); - PerServerDataMutator perServerDataMutator = new PerServerDataMutator(perServerContainer); + PerServerMutator perServerMutator = new PerServerMutator(perServerContainer); - Map worldTimesPerServer = perServerDataMutator.worldTimesPerServer(); + Map worldTimesPerServer = perServerMutator.worldTimesPerServer(); replacer.put("serverPieSeries", new ServerPreferencePie(serverNames, worldTimesPerServer).toHighChartsSeries()); replacer.put("worldPieColors", Theme.getValue(ThemeVal.GRAPH_WORLD_PIE)); replacer.put("gmPieColors", Theme.getValue(ThemeVal.GRAPH_GM_PIE)); replacer.put("serverPieColors", Theme.getValue(ThemeVal.GRAPH_SERVER_PREF_PIE)); - String favoriteServer = serverNames.getOrDefault(perServerDataMutator.favoriteServer(), "Unknown"); + String favoriteServer = serverNames.getOrDefault(perServerMutator.favoriteServer(), "Unknown"); replacer.put("favoriteServer", favoriteServer); replacer.put("tableBodyNicknames", new NicknameTable( diff --git a/Plan/src/main/java/com/djrapitops/plan/system/webserver/pages/parsing/NetworkPage.java b/Plan/src/main/java/com/djrapitops/plan/system/webserver/pages/parsing/NetworkPage.java index 0c3cf0316..5de8dda2f 100644 --- a/Plan/src/main/java/com/djrapitops/plan/system/webserver/pages/parsing/NetworkPage.java +++ b/Plan/src/main/java/com/djrapitops/plan/system/webserver/pages/parsing/NetworkPage.java @@ -36,7 +36,9 @@ public class NetworkPage implements Page { PLAYERS_ALL_TIME_PEAK, PLAYERS_RECENT_PEAK, PLAYERS_DAY, PLAYERS_WEEK, PLAYERS_MONTH, PLAYERS_NEW_DAY, PLAYERS_NEW_WEEK, PLAYERS_NEW_MONTH, - WORLD_MAP_SERIES, WORLD_MAP_HIGH_COLOR, WORLD_MAP_LOW_COLOR + WORLD_MAP_SERIES, WORLD_MAP_HIGH_COLOR, WORLD_MAP_LOW_COLOR, + HEALTH_INDEX, HEALTH_NOTES, + ACTIVITY_PIE_SERIES, ACTIVITY_STACK_SERIES, ACTIVITY_STACK_CATEGORIES ); NetworkPageContent networkPageContent = (NetworkPageContent) ResponseCache.loadResponse(PageId.NETWORK_CONTENT.id(), NetworkPageContent::new); diff --git a/Plan/src/main/resources/web/network.html b/Plan/src/main/resources/web/network.html index 82bb5ec94..3c69a7270 100644 --- a/Plan/src/main/resources/web/network.html +++ b/Plan/src/main/resources/web/network.html @@ -113,6 +113,12 @@ Servers +

  • + + local_hospital + Network Health + +
  • language @@ -333,6 +339,117 @@ ${tabContentServers} +
    +
    + + + + +
    +
    +
    +
    +
    +

    Last 30 Days

    +
    + +
    +
    +
    + ${healthNotes} +
    +
    +
    + +
    +
    +
    +
    +
    +
    +
    +

    Playerbase Development

    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    +

    Current Playerbase

    +
    + +
    +
    +
    +
    +
    +
    +
    +
    +
    +
    @@ -381,6 +498,8 @@ + + @@ -388,7 +507,10 @@ - + + + + @@ -440,8 +585,11 @@ openFunc(slideIndex)(); // Chart draw scripts - playersChart('playerChartDay', playersOnlineSeries, 2); - worldMap('worldMap', geolocationsLow, geolocationsHigh, geolocationsSeries); + playersChart('playerChartDay', series.playersOnline, 2); + activityPie('activityPie', series.activityPie); + stackChart('activityStackGraph', series.activityStackCategories, series.activityStack, 'Players'); + healthGauge('healthGauge', [v.data.healthIndex]); + worldMap('worldMap', v.colors.geolocationsLow, v.colors.geolocationsHigh, series.geolocations); function openFunc(i) { return function () {