PvP & PvE tab on Player inspect page

This commit is contained in:
Rsl1122 2018-07-11 12:46:37 +03:00
parent 5bf69b61aa
commit 46fa30d224
24 changed files with 445 additions and 73 deletions

View File

@ -0,0 +1,31 @@
package com.djrapitops.plan.data.container;
import com.djrapitops.plan.data.store.objects.DateHolder;
import java.util.UUID;
public class PlayerDeath implements DateHolder {
private final UUID killer;
private final long date;
private final String weapon;
public PlayerDeath(UUID killer, String weapon, long date) {
this.killer = killer;
this.date = date;
this.weapon = weapon;
}
public UUID getKiller() {
return killer;
}
@Override
public long getDate() {
return date;
}
public String getWeapon() {
return weapon;
}
}

View File

@ -37,6 +37,7 @@ public class Session extends DataContainer implements DateHolder {
putRawData(SessionKeys.START, sessionStart); putRawData(SessionKeys.START, sessionStart);
putRawData(SessionKeys.WORLD_TIMES, new WorldTimes(world, gm)); putRawData(SessionKeys.WORLD_TIMES, new WorldTimes(world, gm));
putRawData(SessionKeys.PLAYER_KILLS, new ArrayList<>()); putRawData(SessionKeys.PLAYER_KILLS, new ArrayList<>());
putRawData(SessionKeys.PLAYER_DEATHS, new ArrayList<>());
putSupplier(SessionKeys.MOB_KILL_COUNT, () -> mobKills); putSupplier(SessionKeys.MOB_KILL_COUNT, () -> mobKills);
putSupplier(SessionKeys.DEATH_COUNT, () -> deaths); putSupplier(SessionKeys.DEATH_COUNT, () -> deaths);
putSupplier(SessionKeys.AFK_TIME, () -> afkTime); putSupplier(SessionKeys.AFK_TIME, () -> afkTime);
@ -70,6 +71,7 @@ public class Session extends DataContainer implements DateHolder {
putRawData(SessionKeys.END, sessionEnd); putRawData(SessionKeys.END, sessionEnd);
putRawData(SessionKeys.WORLD_TIMES, new WorldTimes(new HashMap<>())); putRawData(SessionKeys.WORLD_TIMES, new WorldTimes(new HashMap<>()));
putRawData(SessionKeys.PLAYER_KILLS, new ArrayList<>()); putRawData(SessionKeys.PLAYER_KILLS, new ArrayList<>());
putRawData(SessionKeys.PLAYER_DEATHS, new ArrayList<>());
putSupplier(SessionKeys.MOB_KILL_COUNT, () -> mobKills); putSupplier(SessionKeys.MOB_KILL_COUNT, () -> mobKills);
putSupplier(SessionKeys.DEATH_COUNT, () -> deaths); putSupplier(SessionKeys.DEATH_COUNT, () -> deaths);
putSupplier(SessionKeys.AFK_TIME, () -> afkTime); putSupplier(SessionKeys.AFK_TIME, () -> afkTime);

View File

@ -1,5 +1,6 @@
package com.djrapitops.plan.data.store.keys; package com.djrapitops.plan.data.store.keys;
import com.djrapitops.plan.data.container.PlayerDeath;
import com.djrapitops.plan.data.container.PlayerKill; import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.Key; import com.djrapitops.plan.data.store.Key;
@ -33,6 +34,7 @@ public class CommonKeys {
public static final Key<WorldTimes> WORLD_TIMES = new Key<>(WorldTimes.class, "world_times"); public static final Key<WorldTimes> WORLD_TIMES = new Key<>(WorldTimes.class, "world_times");
public static final PlaceholderKey<Long> LAST_SEEN = new PlaceholderKey<>(Long.class, "lastSeen"); public static final PlaceholderKey<Long> LAST_SEEN = new PlaceholderKey<>(Long.class, "lastSeen");
public static final Key<List<PlayerDeath>> PLAYER_DEATHS = new Key<>(new Type<List<PlayerDeath>>() {}, "player_deaths");
public static final Key<List<PlayerKill>> PLAYER_KILLS = new Key<>(new Type<List<PlayerKill>>() {}, "player_kills"); public static final Key<List<PlayerKill>> PLAYER_KILLS = new Key<>(new Type<List<PlayerKill>>() {}, "player_kills");
public static final Key<Integer> PLAYER_KILL_COUNT = new Key<>(Integer.class, "player_kill_count"); public static final Key<Integer> PLAYER_KILL_COUNT = new Key<>(Integer.class, "player_kill_count");
public static final Key<Integer> MOB_KILL_COUNT = new Key<>(Integer.class, "mob_kill_count"); public static final Key<Integer> MOB_KILL_COUNT = new Key<>(Integer.class, "mob_kill_count");

View File

@ -1,5 +1,6 @@
package com.djrapitops.plan.data.store.keys; package com.djrapitops.plan.data.store.keys;
import com.djrapitops.plan.data.container.PlayerDeath;
import com.djrapitops.plan.data.container.PlayerKill; import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.Key; import com.djrapitops.plan.data.store.Key;
@ -27,6 +28,7 @@ public class PerServerKeys {
public static final Key<WorldTimes> WORLD_TIMES = CommonKeys.WORLD_TIMES; public static final Key<WorldTimes> WORLD_TIMES = CommonKeys.WORLD_TIMES;
public static final Key<List<PlayerKill>> PLAYER_KILLS = CommonKeys.PLAYER_KILLS; public static final Key<List<PlayerKill>> PLAYER_KILLS = CommonKeys.PLAYER_KILLS;
public static final Key<List<PlayerDeath>> PLAYER_DEATHS = CommonKeys.PLAYER_DEATHS;
public static final Key<Integer> PLAYER_KILL_COUNT = CommonKeys.PLAYER_KILL_COUNT; public static final Key<Integer> PLAYER_KILL_COUNT = CommonKeys.PLAYER_KILL_COUNT;
public static final Key<Integer> MOB_KILL_COUNT = CommonKeys.MOB_KILL_COUNT; public static final Key<Integer> MOB_KILL_COUNT = CommonKeys.MOB_KILL_COUNT;
public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT; public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT;

View File

@ -1,6 +1,7 @@
package com.djrapitops.plan.data.store.keys; package com.djrapitops.plan.data.store.keys;
import com.djrapitops.plan.data.container.GeoInfo; import com.djrapitops.plan.data.container.GeoInfo;
import com.djrapitops.plan.data.container.PlayerDeath;
import com.djrapitops.plan.data.container.PlayerKill; import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.Key; import com.djrapitops.plan.data.store.Key;
@ -40,6 +41,7 @@ public class PlayerKeys {
public static final Key<WorldTimes> WORLD_TIMES = CommonKeys.WORLD_TIMES; public static final Key<WorldTimes> WORLD_TIMES = CommonKeys.WORLD_TIMES;
public static final Key<List<PlayerKill>> PLAYER_KILLS = CommonKeys.PLAYER_KILLS; public static final Key<List<PlayerKill>> PLAYER_KILLS = CommonKeys.PLAYER_KILLS;
public static final Key<List<PlayerDeath>> PLAYER_DEATHS = CommonKeys.PLAYER_DEATHS;
public static final Key<Integer> PLAYER_KILL_COUNT = CommonKeys.PLAYER_KILL_COUNT; public static final Key<Integer> PLAYER_KILL_COUNT = CommonKeys.PLAYER_KILL_COUNT;
public static final Key<Integer> MOB_KILL_COUNT = CommonKeys.MOB_KILL_COUNT; public static final Key<Integer> MOB_KILL_COUNT = CommonKeys.MOB_KILL_COUNT;
public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT; public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT;

View File

@ -1,5 +1,6 @@
package com.djrapitops.plan.data.store.keys; package com.djrapitops.plan.data.store.keys;
import com.djrapitops.plan.data.container.PlayerDeath;
import com.djrapitops.plan.data.container.PlayerKill; import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.store.Key; import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.time.WorldTimes; import com.djrapitops.plan.data.time.WorldTimes;
@ -29,6 +30,7 @@ public class SessionKeys {
public static final Key<Integer> PLAYER_KILL_COUNT = CommonKeys.PLAYER_KILL_COUNT; public static final Key<Integer> PLAYER_KILL_COUNT = CommonKeys.PLAYER_KILL_COUNT;
public static final Key<Integer> MOB_KILL_COUNT = CommonKeys.MOB_KILL_COUNT; public static final Key<Integer> MOB_KILL_COUNT = CommonKeys.MOB_KILL_COUNT;
public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT; public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT;
public static final Key<List<PlayerDeath>> PLAYER_DEATHS = CommonKeys.PLAYER_DEATHS;
private SessionKeys() { private SessionKeys() {
/* Static variable class */ /* Static variable class */

View File

@ -0,0 +1,57 @@
package com.djrapitops.plan.data.store.mutators;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.DataContainer;
import java.util.List;
public class PvpInfoMutator {
private final SessionsMutator sessionsMutator;
private PvpInfoMutator(SessionsMutator sessionsMutator) {
this.sessionsMutator = sessionsMutator;
}
public PvpInfoMutator(List<Session> sessions) {
this(new SessionsMutator(sessions));
}
public static PvpInfoMutator forContainer(DataContainer container) {
return new PvpInfoMutator(SessionsMutator.forContainer(container));
}
public static PvpInfoMutator forMutator(SessionsMutator sessionsMutator) {
return new PvpInfoMutator(sessionsMutator);
}
public double killDeathRatio() {
int deathCount = sessionsMutator.toPlayerDeathCount();
return sessionsMutator.toPlayerKillCount() * 1.0 / (deathCount != 0 ? deathCount : 1);
}
public int mobCausedDeaths() {
return sessionsMutator.toDeathCount() - sessionsMutator.toPlayerDeathCount();
}
public double mobKillDeathRatio() {
int deathCount = mobCausedDeaths();
return sessionsMutator.toMobKillCount() * 1.0 / (deathCount != 0 ? deathCount : 1);
}
public int mobKills() {
return sessionsMutator.toMobKillCount();
}
public int playerKills() {
return sessionsMutator.toPlayerKillCount();
}
public int deaths() {
return sessionsMutator.toDeathCount();
}
public int playerCausedDeaths() {
return sessionsMutator.toPlayerDeathCount();
}
}

View File

@ -1,5 +1,6 @@
package com.djrapitops.plan.data.store.mutators; package com.djrapitops.plan.data.store.mutators;
import com.djrapitops.plan.data.container.PlayerDeath;
import com.djrapitops.plan.data.container.PlayerKill; import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.containers.DataContainer; import com.djrapitops.plan.data.store.containers.DataContainer;
@ -67,6 +68,13 @@ public class SessionsMutator {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
public List<PlayerDeath> toPlayerDeathList() {
return sessions.stream()
.map(session -> session.getValue(SessionKeys.PLAYER_DEATHS).orElse(new ArrayList<>()))
.flatMap(Collection::stream)
.collect(Collectors.toList());
}
public int toMobKillCount() { public int toMobKillCount() {
return sessions.stream() return sessions.stream()
.mapToInt(session -> session.getValue(SessionKeys.MOB_KILL_COUNT).orElse(0)) .mapToInt(session -> session.getValue(SessionKeys.MOB_KILL_COUNT).orElse(0))
@ -178,4 +186,8 @@ public class SessionsMutator {
return (after <= start && start <= before) || (after <= end && end <= before); return (after <= start && start <= before) || (after <= end && end <= before);
}; };
} }
public int toPlayerDeathCount() {
return toPlayerDeathList().size();
}
} }

View File

@ -2,7 +2,6 @@ package com.djrapitops.plan.data.store.mutators.formatting;
import com.djrapitops.plan.data.store.PlaceholderKey; import com.djrapitops.plan.data.store.PlaceholderKey;
import com.djrapitops.plan.data.store.containers.DataContainer; import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plugin.api.utility.log.Log;
import org.apache.commons.text.StringSubstitutor; import org.apache.commons.text.StringSubstitutor;
import java.io.Serializable; import java.io.Serializable;
@ -19,11 +18,7 @@ public class PlaceholderReplacer extends HashMap<String, Serializable> implement
if (!container.supports(key)) { if (!container.supports(key)) {
return; return;
} }
long ns = System.nanoTime();
Log.debug(key.getPlaceholder());
put(key.getPlaceholder(), container.getSupplier(key).get().toString()); put(key.getPlaceholder(), container.getSupplier(key).get().toString());
ns = System.nanoTime() - ns;
Log.debug(key.getPlaceholder() + ": " + Formatters.benchmark().apply(ns));
} }
public void addAllPlaceholdersFrom(DataContainer container, PlaceholderKey... keys) { public void addAllPlaceholdersFrom(DataContainer container, PlaceholderKey... keys) {

View File

@ -24,6 +24,7 @@ public class Nickname implements DateHolder {
return name; return name;
} }
@Override
public long getDate() { public long getDate() {
return date; return date;
} }

View File

@ -236,6 +236,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putSupplier(PerServerKeys.LAST_SEEN, () -> SessionsMutator.forContainer(container).toLastSeen()); container.putSupplier(PerServerKeys.LAST_SEEN, () -> SessionsMutator.forContainer(container).toLastSeen());
container.putSupplier(PerServerKeys.WORLD_TIMES, () -> SessionsMutator.forContainer(container).toTotalWorldTimes()); container.putSupplier(PerServerKeys.WORLD_TIMES, () -> SessionsMutator.forContainer(container).toTotalWorldTimes());
container.putSupplier(PerServerKeys.PLAYER_DEATHS, () -> SessionsMutator.forContainer(container).toPlayerDeathList());
container.putSupplier(PerServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList()); container.putSupplier(PerServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
container.putSupplier(PerServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(PerServerKeys.PLAYER_KILLS).size()); container.putSupplier(PerServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(PerServerKeys.PLAYER_KILLS).size());
container.putSupplier(PerServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount()); container.putSupplier(PerServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
@ -279,6 +280,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putSupplier(PlayerKeys.LAST_SEEN, () -> SessionsMutator.forContainer(container).toLastSeen()); container.putSupplier(PlayerKeys.LAST_SEEN, () -> SessionsMutator.forContainer(container).toLastSeen());
container.putSupplier(PlayerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList()); container.putSupplier(PlayerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
container.putSupplier(PlayerKeys.PLAYER_DEATHS, () -> SessionsMutator.forContainer(container).toPlayerDeathList());
container.putSupplier(PlayerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(PlayerKeys.PLAYER_KILLS).size()); container.putSupplier(PlayerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(PlayerKeys.PLAYER_KILLS).size());
container.putSupplier(PlayerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount()); container.putSupplier(PlayerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
container.putSupplier(PlayerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount()); container.putSupplier(PlayerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
@ -313,6 +315,7 @@ public class SQLFetchOps extends SQLOps implements FetchOperations {
container.putSupplier(PerServerKeys.WORLD_TIMES, () -> SessionsMutator.forContainer(container).toTotalWorldTimes()); container.putSupplier(PerServerKeys.WORLD_TIMES, () -> SessionsMutator.forContainer(container).toTotalWorldTimes());
container.putSupplier(PerServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList()); container.putSupplier(PerServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(container).toPlayerKillList());
container.putSupplier(PerServerKeys.PLAYER_DEATHS, () -> SessionsMutator.forContainer(container).toPlayerDeathList());
container.putSupplier(PerServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(PerServerKeys.PLAYER_KILLS).size()); container.putSupplier(PerServerKeys.PLAYER_KILL_COUNT, () -> container.getUnsafe(PerServerKeys.PLAYER_KILLS).size());
container.putSupplier(PerServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount()); container.putSupplier(PerServerKeys.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
container.putSupplier(PerServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount()); container.putSupplier(PerServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());

View File

@ -1,8 +1,10 @@
package com.djrapitops.plan.system.database.databases.sql.tables; package com.djrapitops.plan.system.database.databases.sql.tables;
import com.djrapitops.plan.api.exceptions.database.DBInitException; import com.djrapitops.plan.api.exceptions.database.DBInitException;
import com.djrapitops.plan.data.container.PlayerDeath;
import com.djrapitops.plan.data.container.PlayerKill; import com.djrapitops.plan.data.container.PlayerKill;
import com.djrapitops.plan.data.container.Session; import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.store.keys.SessionKeys;
import com.djrapitops.plan.system.database.databases.sql.SQLDB; import com.djrapitops.plan.system.database.databases.sql.SQLDB;
import com.djrapitops.plan.system.database.databases.sql.processing.ExecStatement; import com.djrapitops.plan.system.database.databases.sql.processing.ExecStatement;
import com.djrapitops.plan.system.database.databases.sql.processing.QueryAllStatement; import com.djrapitops.plan.system.database.databases.sql.processing.QueryAllStatement;
@ -121,6 +123,43 @@ public class KillsTable extends UserIDTable {
}); });
} }
public void addDeathsToSessions(UUID uuid, Map<Integer, Session> sessions) {
String usersIDColumn = usersTable + "." + UsersTable.Col.ID;
String usersUUIDColumn = usersTable + "." + UsersTable.Col.UUID + " as killer_uuid";
String sql = "SELECT " +
Col.SESSION_ID + ", " +
Col.DATE + ", " +
Col.WEAPON + ", " +
usersUUIDColumn +
" FROM " + tableName +
" INNER JOIN " + usersTable + " on " + usersIDColumn + "=" + Col.KILLER_ID +
" WHERE " + Col.VICTIM_ID + "=" + usersTable.statementSelectID;
query(new QueryStatement<Object>(sql, 50000) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, uuid.toString());
}
@Override
public Object processResults(ResultSet set) throws SQLException {
while (set.next()) {
int sessionID = set.getInt(Col.SESSION_ID.get());
Session session = sessions.get(sessionID);
if (session == null) {
continue;
}
String uuidS = set.getString("killer_uuid");
UUID killer = UUID.fromString(uuidS);
long date = set.getLong(Col.DATE.get());
String weapon = set.getString(Col.WEAPON.get());
session.getUnsafe(SessionKeys.PLAYER_DEATHS).add(new PlayerDeath(killer, weapon, date));
}
return null;
}
});
}
public void savePlayerKills(UUID uuid, int sessionID, List<PlayerKill> playerKills) { public void savePlayerKills(UUID uuid, int sessionID, List<PlayerKill> playerKills) {
if (Verify.isEmpty(playerKills)) { if (Verify.isEmpty(playerKills)) {
return; return;

View File

@ -225,6 +225,7 @@ public class SessionsTable extends UserIDTable {
Map<Integer, Session> allSessions = sessions.values().stream().flatMap(Collection::stream).collect(Collectors.toMap(Session::getSessionID, Function.identity())); Map<Integer, Session> allSessions = sessions.values().stream().flatMap(Collection::stream).collect(Collectors.toMap(Session::getSessionID, Function.identity()));
db.getKillsTable().addKillsToSessions(uuid, allSessions); db.getKillsTable().addKillsToSessions(uuid, allSessions);
db.getKillsTable().addDeathsToSessions(uuid, allSessions);
db.getWorldTimesTable().addWorldTimesToSessions(uuid, allSessions); db.getWorldTimesTable().addWorldTimesToSessions(uuid, allSessions);
return sessions; return sessions;
} }

View File

@ -11,6 +11,7 @@ import com.djrapitops.plan.data.store.containers.PlayerContainer;
import com.djrapitops.plan.data.store.keys.PlayerKeys; import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.mutators.ActivityIndex; import com.djrapitops.plan.data.store.mutators.ActivityIndex;
import com.djrapitops.plan.data.store.mutators.PerServerDataMutator; import com.djrapitops.plan.data.store.mutators.PerServerDataMutator;
import com.djrapitops.plan.data.store.mutators.PvpInfoMutator;
import com.djrapitops.plan.data.store.mutators.SessionsMutator; import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.data.store.mutators.formatting.Formatter; import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters; import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
@ -34,9 +35,7 @@ import com.djrapitops.plan.utilities.html.graphs.pie.ServerPreferencePie;
import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie; import com.djrapitops.plan.utilities.html.graphs.pie.WorldPie;
import com.djrapitops.plan.utilities.html.structure.ServerAccordion; import com.djrapitops.plan.utilities.html.structure.ServerAccordion;
import com.djrapitops.plan.utilities.html.structure.SessionAccordion; import com.djrapitops.plan.utilities.html.structure.SessionAccordion;
import com.djrapitops.plan.utilities.html.tables.GeoInfoTable; import com.djrapitops.plan.utilities.html.tables.*;
import com.djrapitops.plan.utilities.html.tables.NicknameTable;
import com.djrapitops.plan.utilities.html.tables.PlayerSessionTable;
import com.djrapitops.plugin.api.Benchmark; import com.djrapitops.plugin.api.Benchmark;
import com.djrapitops.plugin.api.TimeAmount; import com.djrapitops.plugin.api.TimeAmount;
@ -159,6 +158,38 @@ public class InspectPage implements Page {
SessionsMutator weekSessionsMutator = sessionsMutator.filterSessionsBetween(weekAgo, now); SessionsMutator weekSessionsMutator = sessionsMutator.filterSessionsBetween(weekAgo, now);
SessionsMutator monthSessionsMutator = sessionsMutator.filterSessionsBetween(monthAgo, now); SessionsMutator monthSessionsMutator = sessionsMutator.filterSessionsBetween(monthAgo, now);
sessionsAndPlaytime(replacer, sessionsMutator, daySessionsMutator, weekSessionsMutator, monthSessionsMutator);
String punchCardData = new PunchCardGraph(allSessions).toHighChartsSeries();
WorldTimes worldTimes = container.getValue(PlayerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>()));
WorldPie worldPie = new WorldPie(worldTimes);
replacer.put("worldPieSeries", worldPie.toHighChartsSeries());
replacer.put("gmSeries", worldPie.toHighChartsDrilldown());
replacer.put("punchCardSeries", punchCardData);
pvpAndPve(replacer, sessionsMutator, weekSessionsMutator, monthSessionsMutator);
ActivityIndex activityIndex = container.getActivityIndex(now);
replacer.put("activityIndexNumber", activityIndex.getFormattedValue());
replacer.put("activityIndexColor", activityIndex.getColor());
replacer.put("activityIndex", activityIndex.getGroup());
replacer.put("playerStatus", HtmlStructure.playerStatus(online,
container.getValue(PlayerKeys.BANNED).orElse(false),
container.getValue(PlayerKeys.OPERATOR).orElse(false)));
if (!InfoSystem.getInstance().getConnectionSystem().isServerAvailable()) {
replacer.put("networkName", Settings.SERVER_NAME.toString().replaceAll("[^a-zA-Z0-9_\\s]", "_"));
}
return replacer.apply(FileUtil.getStringFromResource("web/player.html"));
}
private void sessionsAndPlaytime(PlaceholderReplacer replacer, SessionsMutator sessionsMutator, SessionsMutator daySessionsMutator, SessionsMutator weekSessionsMutator, SessionsMutator monthSessionsMutator) {
long playtime = sessionsMutator.toPlaytime(); long playtime = sessionsMutator.toPlaytime();
long playtimeDay = daySessionsMutator.toPlaytime(); long playtimeDay = daySessionsMutator.toPlaytime();
long playtimeWeek = weekSessionsMutator.toPlaytime(); long playtimeWeek = weekSessionsMutator.toPlaytime();
@ -223,39 +254,41 @@ public class InspectPage implements Page {
replacer.put("sessionCountDay", sessionCountDay); replacer.put("sessionCountDay", sessionCountDay);
replacer.put("sessionCountWeek", sessionCountWeek); replacer.put("sessionCountWeek", sessionCountWeek);
replacer.put("sessionCountMonth", sessionCountMonth); replacer.put("sessionCountMonth", sessionCountMonth);
}
String punchCardData = new PunchCardGraph(allSessions).toHighChartsSeries(); private void pvpAndPve(PlaceholderReplacer replacer, SessionsMutator sessionsMutator, SessionsMutator weekSessionsMutator, SessionsMutator monthSessionsMutator) {
WorldTimes worldTimes = container.getValue(PlayerKeys.WORLD_TIMES).orElse(new WorldTimes(new HashMap<>())); String playerKillsTable = new KillsTable(sessionsMutator.toPlayerKillList()).parseHtml();
String playerDeathTable = new DeathsTable(sessionsMutator.toPlayerDeathList()).parseHtml();
WorldPie worldPie = new WorldPie(worldTimes); PvpInfoMutator pvpInfoMutator = PvpInfoMutator.forMutator(sessionsMutator);
PvpInfoMutator pvpInfoMutatorMonth = PvpInfoMutator.forMutator(monthSessionsMutator);
PvpInfoMutator pvpInfoMutatorWeek = PvpInfoMutator.forMutator(weekSessionsMutator);
replacer.put("worldPieSeries", worldPie.toHighChartsSeries()); replacer.put("tablePlayerKills", playerKillsTable);
replacer.put("gmSeries", worldPie.toHighChartsDrilldown()); replacer.put("tablePlayerDeaths", playerDeathTable);
replacer.put("punchCardSeries", punchCardData); replacer.put("playerKillCount", pvpInfoMutator.playerKills());
replacer.put("mobKillCount", pvpInfoMutator.mobKills());
replacer.put("playerDeathCount", pvpInfoMutator.playerCausedDeaths());
replacer.put("mobDeathCount", pvpInfoMutator.mobCausedDeaths());
replacer.put("deathCount", pvpInfoMutator.deaths());
replacer.put("KDR", FormatUtils.cutDecimals(pvpInfoMutator.killDeathRatio()));
replacer.put("mobKDR", FormatUtils.cutDecimals(pvpInfoMutator.mobKillDeathRatio()));
long playerKillCount = allSessions.stream().map(Session::getPlayerKills).mapToLong(Collection::size).sum(); replacer.put("playerKillCountMonth", pvpInfoMutatorMonth.playerKills());
long mobKillCount = allSessions.stream().mapToLong(Session::getMobKills).sum(); replacer.put("mobKillCountMonth", pvpInfoMutatorMonth.mobKills());
long deathCount = allSessions.stream().mapToLong(Session::getDeaths).sum(); replacer.put("playerDeathCountMonth", pvpInfoMutatorMonth.playerCausedDeaths());
replacer.put("mobDeathCountMonth", pvpInfoMutatorMonth.mobCausedDeaths());
replacer.put("deathCountMonth", pvpInfoMutatorMonth.deaths());
replacer.put("KDRMonth", FormatUtils.cutDecimals(pvpInfoMutatorMonth.killDeathRatio()));
replacer.put("mobKDRMonth", FormatUtils.cutDecimals(pvpInfoMutatorMonth.mobKillDeathRatio()));
replacer.put("playerKillCount", playerKillCount); replacer.put("playerKillCountWeek", pvpInfoMutatorWeek.playerKills());
replacer.put("mobKillCount", mobKillCount); replacer.put("mobKillCountWeek", pvpInfoMutatorWeek.mobKills());
replacer.put("deathCount", deathCount); replacer.put("playerDeathCountWeek", pvpInfoMutatorWeek.playerCausedDeaths());
replacer.put("mobDeathCountWeek", pvpInfoMutatorWeek.mobCausedDeaths());
ActivityIndex activityIndex = container.getActivityIndex(now); replacer.put("deathCountWeek", pvpInfoMutatorWeek.deaths());
replacer.put("KDRWeek", FormatUtils.cutDecimals(pvpInfoMutatorWeek.killDeathRatio()));
replacer.put("activityIndexNumber", activityIndex.getFormattedValue()); replacer.put("mobKDRWeek", FormatUtils.cutDecimals(pvpInfoMutatorWeek.mobKillDeathRatio()));
replacer.put("activityIndexColor", activityIndex.getColor());
replacer.put("activityIndex", activityIndex.getGroup());
replacer.put("playerStatus", HtmlStructure.playerStatus(online,
container.getValue(PlayerKeys.BANNED).orElse(false),
container.getValue(PlayerKeys.OPERATOR).orElse(false)));
if (!InfoSystem.getInstance().getConnectionSystem().isServerAvailable()) {
replacer.put("networkName", Settings.SERVER_NAME.toString().replaceAll("[^a-zA-Z0-9_\\s]", "_"));
}
return replacer.apply(FileUtil.getStringFromResource("web/player.html"));
} }
} }

View File

@ -0,0 +1,18 @@
package com.djrapitops.plan.utilities.comparators;
import com.djrapitops.plan.data.store.objects.DateHolder;
import java.util.Comparator;
/**
* Compares DateHolder objects so that most recent is first.
*
* @author Rsl1122
*/
public class DateHolderRecentComparator implements Comparator<DateHolder> {
@Override
public int compare(DateHolder one, DateHolder two) {
return Long.compare(two.getDate(), one.getDate());
}
}

View File

@ -1,19 +1,10 @@
package com.djrapitops.plan.utilities.comparators; package com.djrapitops.plan.utilities.comparators;
import com.djrapitops.plan.data.container.GeoInfo;
import java.util.Comparator;
/** /**
* Comparator for comparing GeoInfo so that most recent is the first component. * Comparator for comparing GeoInfo so that most recent is the first component.
* *
* @author Rsl1122 * @author Rsl1122
*/ */
public class GeoInfoComparator implements Comparator<GeoInfo> { public class GeoInfoComparator extends DateHolderRecentComparator {
@Override
public int compare(GeoInfo o1, GeoInfo o2) {
return -Long.compare(o1.getDate(), o2.getDate());
}
} }

View File

@ -1,17 +1,10 @@
package com.djrapitops.plan.utilities.comparators; package com.djrapitops.plan.utilities.comparators;
import com.djrapitops.plan.data.container.PlayerKill;
import java.util.Comparator;
/** /**
* @author Fuzzlemann * Compares PlayerKills so that most recent is first.
*
* @author Rsl1122
*/ */
public class PlayerKillComparator implements Comparator<PlayerKill> { public class PlayerKillComparator extends DateHolderRecentComparator {
@Override
public int compare(PlayerKill o1, PlayerKill o2) {
return Long.compare(o1.getDate(), o2.getDate());
}
} }

View File

@ -1,18 +1,10 @@
package com.djrapitops.plan.utilities.comparators; package com.djrapitops.plan.utilities.comparators;
import com.djrapitops.plan.data.container.Session;
import java.util.Comparator;
/** /**
* Comparator for Sessions in descending start order (Most recent first). * Comparator for Sessions in descending start order (Most recent first).
* *
* @author Rsl1122 * @author Rsl1122
*/ */
public class SessionStartComparator implements Comparator<Session> { public class SessionStartComparator extends DateHolderRecentComparator {
@Override
public int compare(Session s1, Session s2) {
return -Long.compare(s1.getSessionStart(), s2.getSessionStart());
}
} }

View File

@ -9,6 +9,7 @@ import com.djrapitops.plan.system.database.databases.Database;
import com.djrapitops.plan.system.info.server.Server; import com.djrapitops.plan.system.info.server.Server;
import com.djrapitops.plan.system.info.server.ServerInfo; import com.djrapitops.plan.system.info.server.ServerInfo;
import com.djrapitops.plan.system.info.server.ServerProperties; import com.djrapitops.plan.system.info.server.ServerProperties;
import com.djrapitops.plan.utilities.FormatUtils;
import com.djrapitops.plan.utilities.html.graphs.line.OnlineActivityGraph; import com.djrapitops.plan.utilities.html.graphs.line.OnlineActivityGraph;
import com.djrapitops.plan.utilities.html.icon.Color; import com.djrapitops.plan.utilities.html.icon.Color;
import com.djrapitops.plan.utilities.html.icon.Icon; import com.djrapitops.plan.utilities.html.icon.Icon;
@ -98,7 +99,7 @@ public class HtmlStructure {
ServerProperties properties = ServerInfo.getServerProperties(); ServerProperties properties = ServerInfo.getServerProperties();
int maxPlayers = properties.getMaxPlayers(); int maxPlayers = properties.getMaxPlayers();
int online = properties.getOnlinePlayers(); int online = properties.getOnlinePlayers();
String refresh = "-"; String refresh = FormatUtils.formatTimeStampClock(System.currentTimeMillis());
Server server = ServerInfo.getServer(); Server server = ServerInfo.getServer();
@ -141,7 +142,7 @@ public class HtmlStructure {
"<p><i class=\"col-deep-orange far fa-compass\"></i> Type " + "<p><i class=\"col-deep-orange far fa-compass\"></i> Type " +
"<span class=\"pull-right\">" + serverType + "</span></p></div>" + "<span class=\"pull-right\">" + serverType + "</span></p></div>" +
"<div class=\"col-md-4\">" + "<div class=\"col-md-4\">" +
"<p><i class=\"far fa-clock\"></i> Last Refresh" + "<p><i class=\"far fa-clock\"></i> Last Updated" +
"<span class=\"pull-right\"><b>" + refresh + "</b></span></p>" + "<span class=\"pull-right\"><b>" + refresh + "</b></span></p>" +
"<br>" + "<br>" +
"<a href=\"" + address + "\"><button href=\"" + address + "\" type=\"button\" class=\"pull-right btn bg-light-green waves-effect\">" + "<a href=\"" + address + "\"><button href=\"" + address + "\" type=\"button\" class=\"pull-right btn bg-light-green waves-effect\">" +

View File

@ -12,7 +12,7 @@ public class Icons {
public static final Icon AFK_LENGTH = Icon.called("clock").of(Color.GREY).of(Family.REGULAR).build(); public static final Icon AFK_LENGTH = Icon.called("clock").of(Color.GREY).of(Family.REGULAR).build();
public static final Icon PLAYER_KILLS = Icon.called("crosshairs").of(Color.RED).build(); public static final Icon PLAYER_KILLS = Icon.called("crosshairs").of(Color.RED).build();
public static final Icon MOB_KILLS = Icon.called("crosshairs").of(Color.GREEN).build(); public static final Icon MOB_KILLS = Icon.called("crosshairs").of(Color.GREEN).build();
public static final Icon DEATHS = Icon.called("frown").of(Color.RED).of(Family.REGULAR).build(); public static final Icon DEATHS = Icon.called("skull").build();
public static final Icon SESSION_COUNT = Icon.called("calendar-check").of(Color.TEAL).of(Family.REGULAR).build(); public static final Icon SESSION_COUNT = Icon.called("calendar-check").of(Color.TEAL).of(Family.REGULAR).build();
public static final Icon OPERATOR = Icon.called("superpowers").of(Color.BLUE).of(Family.BRAND).build(); public static final Icon OPERATOR = Icon.called("superpowers").of(Color.BLUE).of(Family.BRAND).build();
public static final Icon BANNED = Icon.called("gavel").of(Color.RED).build(); public static final Icon BANNED = Icon.called("gavel").of(Color.RED).build();

View File

@ -0,0 +1,57 @@
package com.djrapitops.plan.utilities.html.tables;
import com.djrapitops.plan.api.PlanAPI;
import com.djrapitops.plan.data.container.PlayerDeath;
import com.djrapitops.plan.data.element.TableContainer;
import com.djrapitops.plan.data.store.mutators.formatting.Formatter;
import com.djrapitops.plan.data.store.mutators.formatting.Formatters;
import com.djrapitops.plan.data.store.objects.DateHolder;
import com.djrapitops.plan.system.cache.DataCache;
import com.djrapitops.plan.utilities.comparators.DateHolderRecentComparator;
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.Collections;
import java.util.List;
/**
* @author Rsl1122
*/
public class DeathsTable extends TableContainer {
public DeathsTable(List<PlayerDeath> playerPlayerDeaths) {
super(Icon.called("clock").of(Family.REGULAR) + " Time", "Killed by", "With");
setColor("red");
if (playerPlayerDeaths.isEmpty()) {
addRow("No Player caused Deaths");
} else {
addValues(playerPlayerDeaths);
}
}
private void addValues(List<PlayerDeath> playerPlayerDeaths) {
playerPlayerDeaths.sort(new DateHolderRecentComparator());
Collections.reverse(playerPlayerDeaths);
Formatter<DateHolder> timestamp = Formatters.year();
int i = 0;
DataCache dataCache = DataCache.getInstance();
for (PlayerDeath death : playerPlayerDeaths) {
if (i >= 20) {
break;
}
String name = dataCache.getName(death.getKiller());
addRow(
timestamp.apply(death),
Html.LINK.parse(PlanAPI.getInstance().getPlayerInspectPageLink(name), name),
death.getWeapon()
);
i++;
}
}
}

View File

@ -22,7 +22,8 @@ public class KillsTable extends TableContainer {
public KillsTable(List<PlayerKill> playerKills) { public KillsTable(List<PlayerKill> playerKills) {
super(Icon.called("clock").of(Family.REGULAR) + " Time", "Killed", "With"); super(Icon.called("clock").of(Family.REGULAR) + " Time", "Killed", "With");
setColor("red");
if (playerKills.isEmpty()) { if (playerKills.isEmpty()) {
addRow("No Kills"); addRow("No Kills");
} else { } else {

View File

@ -119,6 +119,12 @@
<span>Overview</span> <span>Overview</span>
</a> </a>
</li> </li>
<li>
<a class="nav-button" href="javascript:void(0)">
<i class="material-icons">nature_people</i>
<span>PvP & PvE</span>
</a>
</li>
<li> <li>
<a href="javascript:void(0);" class="menu-toggle"> <a href="javascript:void(0);" class="menu-toggle">
<i class="material-icons">extension</i> <i class="material-icons">extension</i>
@ -286,7 +292,7 @@
<p><i class="col-red fa fa-crosshairs"></i> Player Kills: ${playerKillCount} <p><i class="col-red fa fa-crosshairs"></i> Player Kills: ${playerKillCount}
</p> </p>
<p><i class="col-green fa fa-crosshairs"></i> Mob Kills: ${mobKillCount}</p> <p><i class="col-green fa fa-crosshairs"></i> Mob Kills: ${mobKillCount}</p>
<p><i class="col-red far fa-frown"></i> Deaths: ${deathCount}</p> <p><i class="fa fa-skull"></i> Deaths: ${deathCount}</p>
</div> </div>
</div> </div>
</div> </div>
@ -633,12 +639,143 @@
</div> </div>
</div> </div>
<!-- #END# Tab Overview --> <!-- #END# Tab Overview -->
<div id="tab-versus" class="tab">
<div class="row clearfix">
<!-- Information -->
<!-- Overall -->
<div class="col-xs-12 col-sm-12 col-md-4 col-lg-4">
<div class="card">
<div class="body bg-white">
<div class="m-b--35 font-bold">OVERVIEW</div>
<ul class="dashboard-stat-list">
<li><i class="col-red fa fa-crosshairs"></i> KDR <span
class="pull-right"><b>${KDR}</b></span></li>
<li><i class="col-red fa fa-crosshairs"></i> Player Kills <span
class="pull-right">${playerKillCount}</span></li>
<li><i class="col-red fa fa-skull"></i> Player caused Deaths <span
class="pull-right">${playerDeathCount}</span></li>
<li></li>
<li><i class="col-green fa fa-crosshairs"></i> Mob KDR <span
class="pull-right"><b>${mobKDR}</b></span></li>
<li><i class="col-green fa fa-crosshairs"></i> Mob Kills <span
class="pull-right">${mobKillCount}</span></li>
<li><i class="col-green fa fa-skull"></i> Mob caused Deaths <span
class="pull-right">${mobDeathCount}</span></li>
<li></li>
<li><i class="fa fa-skull"></i> Deaths <span
class="pull-right">${deathCount}</span></li>
</ul>
</div>
</div>
</div>
<!-- #END# Overall -->
<!-- Last 30 Days -->
<div class="col-xs-12 col-sm-12 col-md-4 col-lg-4">
<div class="card">
<div class="body bg-white">
<div class="m-b--35 font-bold">LAST 30 DAYS</div>
<ul class="dashboard-stat-list">
<li><i class="col-red fa fa-crosshairs"></i> KDR <span
class="pull-right"><b>${KDRMonth}</b></span></li>
<li><i class="col-red fa fa-crosshairs"></i> Player Kills <span
class="pull-right">${playerKillCountMonth}</span></li>
<li><i class="col-red fa fa-skull"></i> Player caused Deaths <span
class="pull-right">${playerDeathCountMonth}</span></li>
<li></li>
<li><i class="col-green fa fa-crosshairs"></i> Mob KDR <span
class="pull-right"><b>${mobKDRMonth}</b></span></li>
<li><i class="col-green fa fa-crosshairs"></i> Mob Kills <span
class="pull-right">${mobKillCountMonth}</span></li>
<li><i class="col-green fa fa-skull"></i> Mob caused Deaths <span
class="pull-right">${mobDeathCountMonth}</span></li>
<li></li>
<li><i class="fa fa-skull"></i> Deaths <span
class="pull-right">${deathCountMonth}</span></li>
</ul>
</div>
</div>
</div>
<!-- #END# Last 30 Days -->
<!-- Last 7d -->
<div class="col-xs-12 col-sm-12 col-md-4 col-lg-4">
<div class="card">
<div class="body bg-white">
<div class="font-bold m-b--35">LAST 7 DAYS</div>
<ul class="dashboard-stat-list">
<li><i class="col-red fa fa-crosshairs"></i> KDR <span
class="pull-right"><b>${KDRWeek}</b></span></li>
<li><i class="col-red fa fa-crosshairs"></i> Player Kills <span
class="pull-right">${playerKillCountWeek}</span></li>
<li><i class="col-red fa fa-skull"></i> Player caused Deaths <span
class="pull-right">${playerDeathCountWeek}</span></li>
<li></li>
<li><i class="col-green fa fa-crosshairs"></i> Mob KDR <span
class="pull-right"><b>${mobKDRWeek}</b></span></li>
<li><i class="col-green fa fa-crosshairs"></i> Mob Kills <span
class="pull-right">${mobKillCountWeek}</span></li>
<li><i class="col-green fa fa-skull"></i> Mob caused Deaths <span
class="pull-right">${mobDeathCountWeek}</span></li>
<li></li>
<li><i class="fa fa-skull"></i> Deaths <span
class="pull-right">${deathCountWeek}</span></li>
</ul>
</div>
</div>
</div>
<!-- #END# Last 7d -->
<!-- #END# Information -->
</div>
<div class="row clearfix">
<!-- Tables -->
<!-- Kill info -->
<div class="col-xs-12 col-sm-12 col-md-6 col-lg-6">
<div class="card">
<div class="header">
<div class="row clearfix">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<h2><i class="col-red fa fa-crosshairs"></i> Player Kills</h2>
</div>
</div>
</div>
<div class="panel panel-default">
${tablePlayerKills}
</div>
</div>
</div>
<!-- #END# Kill info -->
<!-- Death info -->
<div class="col-xs-12 col-sm-12 col-md-6 col-lg-6">
<div class="card">
<div class="header">
<div class="row clearfix">
<div class="col-xs-8 col-sm-8 col-lg-8">
<h2><i class="col-red fa fa-skull"></i> Player caused Deaths</h2>
</div>
<div class="col-xs-4 col-sm-4 col-lg-4">
<a href="javascript:void(0)" class="help material-icons pull-right"
tabindex="0" data-trigger="focus" data-toggle="popover" data-placement="left"
data-container="body" data-html="true"
data-original-title="Player caused Deaths"
data-content="Table of Player caused deaths calculated from Plan kill data."
>help_outline</a>
</div>
</div>
</div>
<div class="panel panel-default">
${tablePlayerDeaths}
</div>
</div>
</div>
<!-- #END# Death info -->
<!-- #END# Tables -->
</div>
</div>
<!-- #END# Tab PVP -->
${pluginsTabs} ${pluginsTabs}
<!-- #END# Tabs Plugins --> <!-- #END# Tabs Plugins -->
<div class="tab"></div> <div class="tab"></div>
<div class="tab"></div> <div class="tab"></div>
<div class="tab"></div> <div class="tab"></div>
<div class="tab"></div>
</div> </div>
</div> </div>
</section> </section>

View File

@ -423,7 +423,7 @@
<b>${mobKillCount}</b> <b>${mobKillCount}</b>
</span></li> </span></li>
<li> <li>
<i class="col-red far fa-frown"></i> Deaths<span class="pull-right"> <i class="fa fa-skull"></i> Deaths<span class="pull-right">
<b>${deaths}</b> <b>${deaths}</b>
</span> </span>
</li> </li>