Some PerServerContainer queries

- Deprecated PerServerKeys.PLAYER_KILLS
- Deprecated PerServerKeys.PLAYER_DEATHS
- Added PerServerKeys.PLAYER_DEATH_COUNT
- Added PerServerKeys.MOB_DEATH_COUNT
This commit is contained in:
Rsl1122 2019-02-06 15:37:05 +02:00
parent 2d07f27449
commit 3bbca4e8e8
5 changed files with 317 additions and 20 deletions

View File

@ -54,7 +54,9 @@ public class CommonKeys {
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<Integer> PLAYER_KILL_COUNT = new Key<>(Integer.class, "player_kill_count");
public static final Key<Integer> PLAYER_DEATH_COUNT = new Key<>(Integer.class, "player_death_count");
public static final Key<Integer> MOB_KILL_COUNT = new Key<>(Integer.class, "mob_kill_count");
public static final Key<Integer> MOB_DEATH_COUNT = new Key<>(Integer.class, "mob_death_count");
public static final Key<Integer> DEATH_COUNT = new Key<>(Integer.class, "death_count");
public static final Key<Boolean> BANNED = new Key<>(Boolean.class, "banned");

View File

@ -30,7 +30,7 @@ import java.util.List;
* Key objects for PerServerContainer container.
*
* @author Rsl1122
* @see com.djrapitops.plan.system.database.databases.sql.operation.SQLFetchOps For Suppliers for each key
* @see com.djrapitops.plan.db.access.queries.containers.PerServerContainerQuery For Suppliers for each key
* @see PerServerContainer For the DataContainer.
*/
public class PerServerKeys {
@ -45,10 +45,14 @@ public class PerServerKeys {
public static final Key<List<Session>> SESSIONS = CommonKeys.SESSIONS;
public static final Key<WorldTimes> WORLD_TIMES = CommonKeys.WORLD_TIMES;
@Deprecated
public static final Key<List<PlayerKill>> PLAYER_KILLS = CommonKeys.PLAYER_KILLS;
@Deprecated
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_DEATH_COUNT = CommonKeys.PLAYER_DEATH_COUNT;
public static final Key<Integer> MOB_KILL_COUNT = CommonKeys.MOB_KILL_COUNT;
public static final Key<Integer> MOB_DEATH_COUNT = CommonKeys.MOB_DEATH_COUNT;
public static final Key<Integer> DEATH_COUNT = CommonKeys.DEATH_COUNT;
public static final Key<Long> LAST_SEEN = CommonKeys.LAST_SEEN;

View File

@ -0,0 +1,242 @@
/*
* 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.db.access.queries;
import com.djrapitops.plan.data.time.GMTimes;
import com.djrapitops.plan.data.time.WorldTimes;
import com.djrapitops.plan.db.access.Query;
import com.djrapitops.plan.db.access.QueryStatement;
import com.djrapitops.plan.db.sql.tables.KillsTable;
import com.djrapitops.plan.db.sql.tables.SessionsTable;
import com.djrapitops.plan.db.sql.tables.WorldTable;
import com.djrapitops.plan.db.sql.tables.WorldTimesTable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* Static method class for queries that count together counts for a player on a per server basis.
* <p>
* Example:
* Fetch how much a player has played on servers
*
* @author Rsl1122
*/
public class PerServerAggregateQueries {
private PerServerAggregateQueries() {
/* Static method class */
}
/**
* Find last seen date on servers.
*
* @param playerUUID UUID of the player.
* @return Map: Server UUID - Last seen epoch ms.
*/
public static Query<Map<UUID, Long>> lastSeenOnServers(UUID playerUUID) {
String sql = "SELECT MAX(" + SessionsTable.SESSION_END + ") as last_seen, " +
SessionsTable.SERVER_UUID +
" FROM " + SessionsTable.TABLE_NAME +
" WHERE " + SessionsTable.USER_UUID + "=?" +
" GROUP BY " + SessionsTable.SERVER_UUID;
return new QueryStatement<Map<UUID, Long>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, playerUUID.toString());
}
@Override
public Map<UUID, Long> processResults(ResultSet set) throws SQLException {
Map<UUID, Long> lastSeenMap = new HashMap<>();
while (set.next()) {
UUID serverUUID = UUID.fromString(set.getString(SessionsTable.SERVER_UUID));
long lastSeen = set.getLong("last_seen");
lastSeenMap.put(serverUUID, lastSeen);
}
return lastSeenMap;
}
};
}
/**
* Find player kill count on servers.
*
* @param playerUUID UUID of the player.
* @return Map: Server UUID - Player kill count
*/
public static Query<Map<UUID, Integer>> playerKillCountOnServers(UUID playerUUID) {
String sql = "SELECT COUNT(1) as kill_count, " + KillsTable.SERVER_UUID + " FROM " + KillsTable.TABLE_NAME +
" WHERE " + KillsTable.KILLER_UUID + "=?" +
" GROUP BY " + KillsTable.SERVER_UUID;
return new QueryStatement<Map<UUID, Integer>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, playerUUID.toString());
}
@Override
public Map<UUID, Integer> processResults(ResultSet set) throws SQLException {
Map<UUID, Integer> killCountMap = new HashMap<>();
while (set.next()) {
UUID serverUUID = UUID.fromString(set.getString(SessionsTable.SERVER_UUID));
int lastSeen = set.getInt("kill_count");
killCountMap.put(serverUUID, lastSeen);
}
return killCountMap;
}
};
}
/**
* Find mob kill count on servers.
*
* @param playerUUID UUID of the player.
* @return Map: Server UUID - Mob kill count
*/
public static Query<Map<UUID, Integer>> mobKillCountOnServers(UUID playerUUID) {
String sql = "SELECT SUM(" + SessionsTable.MOB_KILLS + ") as kill_count, " +
SessionsTable.SERVER_UUID + " FROM " + SessionsTable.TABLE_NAME +
" WHERE " + SessionsTable.USER_UUID + "=?" +
" GROUP BY " + SessionsTable.SERVER_UUID;
return new QueryStatement<Map<UUID, Integer>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, playerUUID.toString());
}
@Override
public Map<UUID, Integer> processResults(ResultSet set) throws SQLException {
Map<UUID, Integer> killCountMap = new HashMap<>();
while (set.next()) {
UUID serverUUID = UUID.fromString(set.getString(SessionsTable.SERVER_UUID));
int lastSeen = set.getInt("kill_count");
killCountMap.put(serverUUID, lastSeen);
}
return killCountMap;
}
};
}
/**
* Find how many times a player killed the player on servers.
*
* @param playerUUID UUID of the player.
* @return Map: Server UUID - Mob kill count
*/
public static Query<Map<UUID, Integer>> playerDeathCountOnServers(UUID playerUUID) {
String sql = "SELECT COUNT(1) as death_count, " + KillsTable.SERVER_UUID + " FROM " + KillsTable.TABLE_NAME +
" WHERE " + KillsTable.VICTIM_UUID + "=?" +
" GROUP BY " + KillsTable.SERVER_UUID;
return new QueryStatement<Map<UUID, Integer>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, playerUUID.toString());
}
@Override
public Map<UUID, Integer> processResults(ResultSet set) throws SQLException {
Map<UUID, Integer> killCountMap = new HashMap<>();
while (set.next()) {
UUID serverUUID = UUID.fromString(set.getString(SessionsTable.SERVER_UUID));
int lastSeen = set.getInt("death_count");
killCountMap.put(serverUUID, lastSeen);
}
return killCountMap;
}
};
}
public static Query<Map<UUID, Integer>> totalDeathCountOnServers(UUID playerUUID) {
String sql = "SELECT SUM(" + SessionsTable.DEATHS + ") as death_count, " +
SessionsTable.SERVER_UUID + " FROM " + SessionsTable.TABLE_NAME +
" WHERE " + SessionsTable.USER_UUID + "=?" +
" GROUP BY " + SessionsTable.SERVER_UUID;
return new QueryStatement<Map<UUID, Integer>>(sql) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, playerUUID.toString());
}
@Override
public Map<UUID, Integer> processResults(ResultSet set) throws SQLException {
Map<UUID, Integer> killCountMap = new HashMap<>();
while (set.next()) {
UUID serverUUID = UUID.fromString(set.getString(SessionsTable.SERVER_UUID));
int lastSeen = set.getInt("death_count");
killCountMap.put(serverUUID, lastSeen);
}
return killCountMap;
}
};
}
/**
* Find total world times of the player on servers.
*
* @param playerUUID UUID of the player.
* @return Map: Server UUID - WorldTimes total for the server
*/
public static Query<Map<UUID, WorldTimes>> worldTimesOnServers(UUID playerUUID) {
String worldIDColumn = WorldTable.TABLE_NAME + "." + WorldTable.ID;
String worldNameColumn = WorldTable.TABLE_NAME + "." + WorldTable.NAME + " as world";
String sql = "SELECT " +
"SUM(" + WorldTimesTable.SURVIVAL + ") as survival, " +
"SUM(" + WorldTimesTable.CREATIVE + ") as creative, " +
"SUM(" + WorldTimesTable.ADVENTURE + ") as adventure, " +
"SUM(" + WorldTimesTable.SPECTATOR + ") as spectator, " +
worldNameColumn +
" FROM " + WorldTimesTable.TABLE_NAME +
" INNER JOIN " + WorldTable.TABLE_NAME + " on " + worldIDColumn + "=" + WorldTimesTable.WORLD_ID +
" WHERE " + WorldTimesTable.TABLE_NAME + "." + WorldTimesTable.USER_UUID + "=?" +
" GROUP BY world, " + WorldTimesTable.SERVER_UUID;
return new QueryStatement<Map<UUID, WorldTimes>>(sql, 1000) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
statement.setString(1, playerUUID.toString());
}
@Override
public Map<UUID, WorldTimes> processResults(ResultSet set) throws SQLException {
String[] gms = GMTimes.getGMKeyArray();
Map<UUID, WorldTimes> worldTimesMap = new HashMap<>();
while (set.next()) {
UUID serverUUID = UUID.fromString(set.getString(WorldTimesTable.SERVER_UUID));
WorldTimes worldTimes = worldTimesMap.getOrDefault(serverUUID, new WorldTimes(new HashMap<>()));
String worldName = set.getString("world");
Map<String, Long> gmMap = new HashMap<>();
gmMap.put(gms[0], set.getLong("survival"));
gmMap.put(gms[1], set.getLong("creative"));
gmMap.put(gms[2], set.getLong("adventure"));
gmMap.put(gms[3], set.getLong("spectator"));
GMTimes gmTimes = new GMTimes(gmMap);
worldTimes.setGMTimesForWorld(worldName, gmTimes);
worldTimesMap.put(serverUUID, worldTimes);
}
return worldTimesMap;
}
};
}
}

View File

@ -90,6 +90,9 @@ public class AllPlayerContainersQuery implements Query<List<PlayerContainer>> {
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.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
container.putSupplier(PerServerKeys.MOB_DEATH_COUNT, () ->
container.getUnsafe(PerServerKeys.DEATH_COUNT) - container.getUnsafe(PerServerKeys.PLAYER_DEATH_COUNT)
);
perServerContainer.put(serverUUID, container);
perServerContainers.put(uuid, perServerContainer);
}

View File

@ -18,6 +18,7 @@ package com.djrapitops.plan.db.access.queries.containers;
import com.djrapitops.plan.data.container.Session;
import com.djrapitops.plan.data.container.UserInfo;
import com.djrapitops.plan.data.store.Key;
import com.djrapitops.plan.data.store.containers.DataContainer;
import com.djrapitops.plan.data.store.containers.PerServerContainer;
import com.djrapitops.plan.data.store.keys.PerServerKeys;
@ -25,6 +26,7 @@ import com.djrapitops.plan.data.store.keys.PlayerKeys;
import com.djrapitops.plan.data.store.mutators.SessionsMutator;
import com.djrapitops.plan.db.SQLDB;
import com.djrapitops.plan.db.access.Query;
import com.djrapitops.plan.db.access.queries.PerServerAggregateQueries;
import com.djrapitops.plan.db.access.queries.PlayerFetchQueries;
import java.util.List;
@ -48,15 +50,19 @@ public class PerServerContainerQuery implements Query<PerServerContainer> {
public PerServerContainer executeQuery(SQLDB db) {
PerServerContainer perServerContainer = new PerServerContainer();
List<UserInfo> userInformation = db.query(PlayerFetchQueries.playerServerSpecificUserInformation(playerUUID));
for (UserInfo userInfo : userInformation) {
UUID serverUUID = userInfo.getServerUUID();
userInformation(db, perServerContainer);
lastSeen(db, perServerContainer);
playerKillCount(db, perServerContainer);
playerDeathCount(db, perServerContainer);
mobKillCount(db, perServerContainer);
totalDeathCount(db, perServerContainer);
worldTimes(db, perServerContainer);
DataContainer container = perServerContainer.getOrDefault(serverUUID, new DataContainer());
container.putRawData(PlayerKeys.REGISTERED, userInfo.getRegistered());
container.putRawData(PlayerKeys.BANNED, userInfo.isBanned());
container.putRawData(PlayerKeys.OPERATOR, userInfo.isOperator());
perServerContainer.put(serverUUID, container);
// After-values that can be calculated without database.
for (DataContainer serverContainer : perServerContainer.values()) {
serverContainer.putSupplier(PerServerKeys.MOB_DEATH_COUNT, () ->
serverContainer.getUnsafe(PerServerKeys.DEATH_COUNT) - serverContainer.getUnsafe(PerServerKeys.PLAYER_DEATH_COUNT)
);
}
Map<UUID, List<Session>> sessions = db.getSessionsTable().getSessions(playerUUID);
@ -64,21 +70,61 @@ public class PerServerContainerQuery implements Query<PerServerContainer> {
UUID serverUUID = entry.getKey();
List<Session> serverSessions = entry.getValue();
DataContainer container = perServerContainer.getOrDefault(serverUUID, new DataContainer());
container.putRawData(PerServerKeys.SESSIONS, serverSessions);
DataContainer serverContainer = perServerContainer.getOrDefault(serverUUID, new DataContainer());
serverContainer.putRawData(PerServerKeys.SESSIONS, serverSessions);
container.putSupplier(PerServerKeys.LAST_SEEN, () -> SessionsMutator.forContainer(container).toLastSeen());
serverContainer.putSupplier(PerServerKeys.PLAYER_KILLS, () -> SessionsMutator.forContainer(serverContainer).toPlayerKillList());
serverContainer.putSupplier(PerServerKeys.PLAYER_DEATHS, () -> SessionsMutator.forContainer(serverContainer).toPlayerDeathList());
container.putSupplier(PerServerKeys.WORLD_TIMES, () -> SessionsMutator.forContainer(container).toTotalWorldTimes());
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.MOB_KILL_COUNT, () -> SessionsMutator.forContainer(container).toMobKillCount());
container.putSupplier(PerServerKeys.DEATH_COUNT, () -> SessionsMutator.forContainer(container).toDeathCount());
perServerContainer.put(serverUUID, container);
perServerContainer.put(serverUUID, serverContainer);
}
return perServerContainer;
}
private void totalDeathCount(SQLDB db, PerServerContainer container) {
matchingEntrySet(PerServerKeys.DEATH_COUNT, PerServerAggregateQueries.totalDeathCountOnServers(playerUUID), db, container);
}
private void worldTimes(SQLDB db, PerServerContainer container) {
matchingEntrySet(PerServerKeys.WORLD_TIMES, PerServerAggregateQueries.worldTimesOnServers(playerUUID), db, container);
}
private void playerDeathCount(SQLDB db, PerServerContainer container) {
matchingEntrySet(PerServerKeys.PLAYER_DEATH_COUNT, PerServerAggregateQueries.playerDeathCountOnServers(playerUUID), db, container);
}
private void mobKillCount(SQLDB db, PerServerContainer container) {
matchingEntrySet(PerServerKeys.MOB_KILL_COUNT, PerServerAggregateQueries.mobKillCountOnServers(playerUUID), db, container);
}
private void playerKillCount(SQLDB db, PerServerContainer container) {
matchingEntrySet(PerServerKeys.PLAYER_KILL_COUNT, PerServerAggregateQueries.playerKillCountOnServers(playerUUID), db, container);
}
private void lastSeen(SQLDB db, PerServerContainer container) {
matchingEntrySet(PerServerKeys.LAST_SEEN, PerServerAggregateQueries.lastSeenOnServers(playerUUID), db, container);
}
private void userInformation(SQLDB db, PerServerContainer perServerContainer) {
List<UserInfo> userInformation = db.query(PlayerFetchQueries.playerServerSpecificUserInformation(playerUUID));
for (UserInfo userInfo : userInformation) {
UUID serverUUID = userInfo.getServerUUID();
placeToPerServerContainer(serverUUID, PlayerKeys.REGISTERED, userInfo.getRegistered(), perServerContainer);
placeToPerServerContainer(serverUUID, PlayerKeys.BANNED, userInfo.isBanned(), perServerContainer);
placeToPerServerContainer(serverUUID, PlayerKeys.OPERATOR, userInfo.isOperator(), perServerContainer);
}
}
private <T> void matchingEntrySet(Key<T> key, Query<Map<UUID, T>> map, SQLDB db, PerServerContainer container) {
for (Map.Entry<UUID, T> lastSeen : db.query(map).entrySet()) {
placeToPerServerContainer(lastSeen.getKey(), key, lastSeen.getValue(), container);
}
}
private <T> void placeToPerServerContainer(UUID serverUUID, Key<T> key, T value, PerServerContainer perServerContainer) {
DataContainer container = perServerContainer.getOrDefault(serverUUID, new DataContainer());
container.putRawData(key, value);
perServerContainer.put(serverUUID, container);
}
}