Fixed most recent players not showing up on player list

This commit is contained in:
Rsl1122 2019-08-25 10:48:53 +03:00
parent 4da469dcf4
commit 7f1212c1ac
7 changed files with 4 additions and 317 deletions

View File

@ -18,7 +18,6 @@ package com.djrapitops.plan.system;
import com.djrapitops.plan.utilities.formatting.Formatters; import com.djrapitops.plan.utilities.formatting.Formatters;
import com.djrapitops.plan.utilities.html.graphs.Graphs; import com.djrapitops.plan.utilities.html.graphs.Graphs;
import com.djrapitops.plan.utilities.html.tables.HtmlTables;
import dagger.Lazy; import dagger.Lazy;
import javax.inject.Inject; import javax.inject.Inject;
@ -28,17 +27,14 @@ import javax.inject.Singleton;
public class HtmlUtilities { public class HtmlUtilities {
private final Lazy<Formatters> formatters; private final Lazy<Formatters> formatters;
private final Lazy<HtmlTables> htmlTables;
private final Lazy<Graphs> graphs; private final Lazy<Graphs> graphs;
@Inject @Inject
public HtmlUtilities( public HtmlUtilities(
Lazy<Formatters> formatters, Lazy<Formatters> formatters,
Lazy<HtmlTables> htmlTables,
Lazy<Graphs> graphs Lazy<Graphs> graphs
) { ) {
this.formatters = formatters; this.formatters = formatters;
this.htmlTables = htmlTables;
this.graphs = graphs; this.graphs = graphs;
} }
@ -46,10 +42,6 @@ public class HtmlUtilities {
return formatters.get(); return formatters.get();
} }
public HtmlTables getHtmlTables() {
return htmlTables.get();
}
public Graphs getGraphs() { public Graphs getGraphs() {
return graphs.get(); return graphs.get();
} }

View File

@ -67,6 +67,8 @@ public class PlayersTableJSONParser {
) { ) {
// Data // Data
this.players = players; this.players = players;
this.players.sort(new PlayerContainerLastPlayedComparator());
this.extensionData = extensionData; this.extensionData = extensionData;
extensionDescriptives = new ArrayList<>(); extensionDescriptives = new ArrayList<>();

View File

@ -31,7 +31,6 @@ import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.theme.Theme; import com.djrapitops.plan.system.settings.theme.Theme;
import com.djrapitops.plan.system.update.VersionCheckSystem; import com.djrapitops.plan.system.update.VersionCheckSystem;
import com.djrapitops.plan.utilities.formatting.Formatters; import com.djrapitops.plan.utilities.formatting.Formatters;
import com.djrapitops.plan.utilities.html.tables.HtmlTables;
import com.djrapitops.plugin.benchmarking.Timings; import com.djrapitops.plugin.benchmarking.Timings;
import com.djrapitops.plugin.logging.debug.DebugLogger; import com.djrapitops.plugin.logging.debug.DebugLogger;
import com.djrapitops.plugin.logging.error.ErrorHandler; import com.djrapitops.plugin.logging.error.ErrorHandler;
@ -55,7 +54,6 @@ public class PageFactory {
private final Lazy<Theme> theme; private final Lazy<Theme> theme;
private final Lazy<DBSystem> dbSystem; private final Lazy<DBSystem> dbSystem;
private final Lazy<ServerInfo> serverInfo; private final Lazy<ServerInfo> serverInfo;
private final Lazy<HtmlTables> tables;
private final Lazy<Formatters> formatters; private final Lazy<Formatters> formatters;
private final Lazy<DebugLogger> debugLogger; private final Lazy<DebugLogger> debugLogger;
private final Lazy<Timings> timings; private final Lazy<Timings> timings;
@ -69,7 +67,6 @@ public class PageFactory {
Lazy<Theme> theme, Lazy<Theme> theme,
Lazy<DBSystem> dbSystem, Lazy<DBSystem> dbSystem,
Lazy<ServerInfo> serverInfo, Lazy<ServerInfo> serverInfo,
Lazy<HtmlTables> tables,
Lazy<Formatters> formatters, Lazy<Formatters> formatters,
Lazy<DebugLogger> debugLogger, Lazy<DebugLogger> debugLogger,
Lazy<Timings> timings, Lazy<Timings> timings,
@ -81,7 +78,6 @@ public class PageFactory {
this.theme = theme; this.theme = theme;
this.dbSystem = dbSystem; this.dbSystem = dbSystem;
this.serverInfo = serverInfo; this.serverInfo = serverInfo;
this.tables = tables;
this.formatters = formatters; this.formatters = formatters;
this.debugLogger = debugLogger; this.debugLogger = debugLogger;
this.timings = timings; this.timings = timings;
@ -96,9 +92,7 @@ public class PageFactory {
} }
public PlayersPage playersPage() { public PlayersPage playersPage() {
return new PlayersPage(versionCheckSystem.get(), fileSystem.get(), config.get(), return new PlayersPage(versionCheckSystem.get(), fileSystem.get(), config.get(), serverInfo.get());
dbSystem.get().getDatabase(), serverInfo.get(), tables.get(),
timings.get());
} }
public ServerPage serverPage(UUID serverUUID) throws NotFoundException { public ServerPage serverPage(UUID serverUUID) throws NotFoundException {

View File

@ -17,9 +17,6 @@
package com.djrapitops.plan.utilities.html.pages; package com.djrapitops.plan.utilities.html.pages;
import com.djrapitops.plan.api.exceptions.ParseException; import com.djrapitops.plan.api.exceptions.ParseException;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.db.Database;
import com.djrapitops.plan.db.access.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.system.file.PlanFiles; import com.djrapitops.plan.system.file.PlanFiles;
import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.settings.config.PlanConfig; import com.djrapitops.plan.system.settings.config.PlanConfig;
@ -27,10 +24,6 @@ import com.djrapitops.plan.system.settings.paths.PluginSettings;
import com.djrapitops.plan.system.settings.paths.ProxySettings; import com.djrapitops.plan.system.settings.paths.ProxySettings;
import com.djrapitops.plan.system.update.VersionCheckSystem; import com.djrapitops.plan.system.update.VersionCheckSystem;
import com.djrapitops.plan.utilities.formatting.PlaceholderReplacer; import com.djrapitops.plan.utilities.formatting.PlaceholderReplacer;
import com.djrapitops.plan.utilities.html.tables.HtmlTables;
import com.djrapitops.plugin.benchmarking.Timings;
import java.util.List;
/** /**
* Html String parser for /players page. * Html String parser for /players page.
@ -42,29 +35,18 @@ public class PlayersPage implements Page {
private final VersionCheckSystem versionCheckSystem; private final VersionCheckSystem versionCheckSystem;
private final PlanFiles files; private final PlanFiles files;
private final PlanConfig config; private final PlanConfig config;
private final Database database;
private final ServerInfo serverInfo; private final ServerInfo serverInfo;
private final HtmlTables tables;
private final Timings timings;
PlayersPage( PlayersPage(
VersionCheckSystem versionCheckSystem, VersionCheckSystem versionCheckSystem,
PlanFiles files, PlanFiles files,
PlanConfig config, PlanConfig config,
Database database, ServerInfo serverInfo
ServerInfo serverInfo,
HtmlTables tables,
Timings timings
) { ) {
this.versionCheckSystem = versionCheckSystem; this.versionCheckSystem = versionCheckSystem;
this.files = files; this.files = files;
this.config = config; this.config = config;
this.database = database;
this.serverInfo = serverInfo; this.serverInfo = serverInfo;
this.tables = tables;
this.timings = timings;
} }
@Override @Override
@ -80,11 +62,6 @@ public class PlayersPage implements Page {
placeholders.put("networkName", config.get(PluginSettings.SERVER_NAME)); placeholders.put("networkName", config.get(PluginSettings.SERVER_NAME));
} }
timings.start("Players page players table parsing");
List<PlayerContainer> playerContainers = database.query(ContainerFetchQueries.fetchAllPlayerContainers());
placeholders.put("playersTable", tables.playerTableForPlayersPage(playerContainers).parseHtml());
timings.end("Pages", "Players page players table parsing");
return placeholders.apply(files.getCustomizableResourceOrDefault("web/players.html").asString()); return placeholders.apply(files.getCustomizableResourceOrDefault("web/players.html").asString());
} catch (Exception e) { } catch (Exception e) {
throw new ParseException(e); throw new ParseException(e);

View File

@ -1,65 +0,0 @@
/*
* 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.utilities.html.tables;
import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.system.settings.config.PlanConfig;
import com.djrapitops.plan.system.settings.paths.DisplaySettings;
import com.djrapitops.plan.system.settings.paths.TimeSettings;
import com.djrapitops.plan.utilities.formatting.Formatters;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;
/**
* Factory class for objects that represent HTML tables.
*
* @author Rsl1122
*/
@Singleton
public class HtmlTables {
private final PlanConfig config;
private final Formatters formatters;
@Inject
public HtmlTables(
PlanConfig config,
Formatters formatters
) {
this.config = config;
this.formatters = formatters;
}
/**
* Create a Player table for a players page.
*
* @param players List of {@link PlayerContainer}s of players.
* @return a new {@link PlayersTable}.
*/
public TableContainer playerTableForPlayersPage(List<PlayerContainer> players) {
return new PlayersTable(
players, config.get(DisplaySettings.PLAYERS_PER_PLAYERS_PAGE),
config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD),
config.get(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB),
formatters.timeAmount(), formatters.yearLong(), formatters.decimals()
);
}
}

View File

@ -1,123 +0,0 @@
/*
* 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.utilities.html.tables;
import com.djrapitops.plan.api.PlanAPI;
import com.djrapitops.plan.data.container.GeoInfo;
import com.djrapitops.plan.data.element.TableContainer;
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.GeoInfoMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.utilities.comparators.PlayerContainerLastPlayedComparator;
import com.djrapitops.plan.utilities.formatting.Formatter;
import com.djrapitops.plan.utilities.html.Html;
import com.djrapitops.plan.utilities.html.icon.Family;
import com.djrapitops.plan.utilities.html.icon.Icon;
import java.util.List;
/**
* Html table that displays a lot of information about players.
*
* @author Rsl1122
*/
class PlayersTable extends TableContainer {
private final List<PlayerContainer> players;
private final int maxPlayers;
private final long activeMsThreshold;
private final boolean openPlayerPageInNewTab;
private final Formatter<Double> decimalFormatter;
PlayersTable(
List<PlayerContainer> players,
int maxPlayers,
long activeMsThreshold,
boolean openPlayerPageInNewTab,
Formatter<Long> timeAmountFormatter,
Formatter<Long> yearLongFormatter,
Formatter<Double> decimalFormatter
) {
super(
Icon.called("user") + " Name",
Icon.called("check") + " Activity Index",
Icon.called("clock").of(Family.REGULAR) + " Playtime",
Icon.called("calendar-plus").of(Family.REGULAR) + " Sessions",
Icon.called("user-plus") + " Registered",
Icon.called("calendar-check").of(Family.REGULAR) + " Last Seen",
Icon.called("globe") + " Geolocation"
);
this.players = players;
this.maxPlayers = maxPlayers;
this.activeMsThreshold = activeMsThreshold;
this.openPlayerPageInNewTab = openPlayerPageInNewTab;
this.decimalFormatter = decimalFormatter;
useJqueryDataTables("player-table");
setFormatter(2, timeAmountFormatter);
setFormatter(4, yearLongFormatter);
setFormatter(5, yearLongFormatter);
addRows();
}
private void addRows() {
PlanAPI planAPI = PlanAPI.getInstance();
long now = System.currentTimeMillis();
players.sort(new PlayerContainerLastPlayedComparator());
int i = 0;
for (PlayerContainer player : players) {
if (i >= maxPlayers) {
break;
}
String name = player.getValue(PlayerKeys.NAME).orElse("Unknown");
String url = planAPI.getPlayerInspectPageLink(name);
SessionsMutator sessionsMutator = SessionsMutator.forContainer(player);
int loginTimes = sessionsMutator.count();
long playtime = sessionsMutator.toPlaytime();
long registered = player.getValue(PlayerKeys.REGISTERED).orElse(0L);
long lastSeen = sessionsMutator.toLastSeen();
ActivityIndex activityIndex = player.getActivityIndex(now, activeMsThreshold);
boolean isBanned = player.getValue(PlayerKeys.BANNED).orElse(false);
String activityString = activityIndex.getFormattedValue(decimalFormatter)
+ (isBanned ? " (<b>Banned</b>)" : " (" + activityIndex.getGroup() + ")");
String geolocation = GeoInfoMutator.forContainer(player).mostRecent().map(GeoInfo::getGeolocation).orElse("-");
Html link = openPlayerPageInNewTab ? Html.LINK_EXTERNAL : Html.LINK;
addRow(
link.parse(url, name),
activityString,
playtime,
loginTimes,
registered,
lastSeen,
geolocation
);
i++;
}
}
}

View File

@ -1,90 +0,0 @@
/*
* 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.utilities.html.tables;
import com.djrapitops.plan.api.CommonAPI;
import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.system.database.DBSystem;
import com.djrapitops.plan.utilities.uuid.UUIDUtility;
import com.djrapitops.plugin.logging.console.TestPluginLogger;
import com.djrapitops.plugin.logging.error.ConsoleErrorLogger;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;
import java.util.concurrent.TimeUnit;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Tests for {@link PlayersTable}
*
* @author Rsl1122
*/
@RunWith(JUnitPlatform.class)
class PlayersTableTest {
@BeforeAll
static void setUpClass() {
new CommonAPI(
Mockito.mock(DBSystem.class),
Mockito.mock(UUIDUtility.class),
new TestPluginLogger(),
new ConsoleErrorLogger(new TestPluginLogger())
);
}
@Test
void noClassCastExceptionsFromFormatting() {
PlayerContainer container = new PlayerContainer();
container.putRawData(PlayerKeys.SESSIONS, new ArrayList<>());
List<PlayerContainer> players = Collections.singletonList(container);
String html = new PlayersTable(
players,
50, // maxPlayers
TimeUnit.MINUTES.toMillis(60), // activeMsThreshold
false,
l -> "",
l -> "",
d -> ""
).parseHtml();
testHtmlValidity(html);
}
private void testHtmlValidity(String html) {
Stack<String> stack = new Stack<>();
String[] split = html.split("<");
for (String s : split) {
if (s.startsWith("/")) {
String expectedElement = stack.pop();
assertTrue(s.startsWith("/" + expectedElement), () -> "Element not properly closed: " + expectedElement);
} else {
stack.push(s.split(" ", 2)[0].split(">", 2)[0]);
}
}
stack.pop(); // Pop the empty string since the html string starts with <
assertTrue(stack.empty(), () -> "Stack was not empty: " + stack.toString());
}
}