Update leaderboard backend based on discussion with Jon

This commit is contained in:
AlexTheCoder 2017-05-10 02:49:21 -04:00
parent 3b3436d1af
commit adf6e35a1f
6 changed files with 80 additions and 50 deletions

View File

@ -18,12 +18,17 @@ public class Leaderboard
private String _display;
private Pair<String, String> _statDisplay;
private String[] _statIds;
private int _size;
private int _size, _start;
private LeaderboardSQLType _type;
private Location _loc;
private Hologram _holo;
public Leaderboard(String display, Pair<String, String> statDisplayNames, String[] statIds, LeaderboardSQLType type, Location displayLoc, int size)
{
this(display, statDisplayNames, statIds, type, displayLoc, size, 0);
}
public Leaderboard(String display, Pair<String, String> statDisplayNames, String[] statIds, LeaderboardSQLType type, Location displayLoc, int size, int start)
{
_display = display;
_statDisplay = statDisplayNames;
@ -40,6 +45,11 @@ public class Leaderboard
return _size;
}
public int getStart()
{
return _start;
}
public String[] getStatIds()
{
return _statIds;
@ -56,7 +66,7 @@ public class Leaderboard
LinkedList<String> display = new LinkedList<>();
display.add(C.cAqua + _display);
display.add(C.cRed + " ");
int place = 1;
int place = _start + 1;
for (Entry<String, Integer> entry : names.entrySet())
{
if (entry.getValue() == 1)

View File

@ -16,6 +16,7 @@ import mineplex.core.common.Rank;
import mineplex.core.common.util.F;
import mineplex.core.common.util.UtilMath;
import mineplex.core.hologram.HologramManager;
import mineplex.core.leaderboard.LeaderboardRepository.LeaderboardSQLType;
public class LeaderboardManager extends MiniPlugin
{
@ -86,6 +87,10 @@ public class LeaderboardManager extends MiniPlugin
return;
}
_leaderboards.put(identifier, board);
if (board.getType() == LeaderboardSQLType.MONTHLY || board.getType() == LeaderboardSQLType.MONTHLY_SEASON || board.getType() == LeaderboardSQLType.YEARLY || board.getType() == LeaderboardSQLType.YEARLY_SEASON)
{
log("Warning! You have selected a LeaderboardSQLType identified to be potentially expensive and intensive on Leaderboard ID: " + identifier);
}
_repo.loadLeaderboard(board, board::update);
}

View File

@ -1,7 +1,6 @@
package mineplex.core.leaderboard;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
@ -21,13 +20,21 @@ import mineplex.serverdata.database.column.ColumnVarChar;
public class LeaderboardRepository extends RepositoryBase
{
private static final int SEASON = 1;
private static final String CREATE = "CREATE TABLE Account.statLeaderboard (id INT NOT NULL AUTO_INCREMENT, accountId INT NOT NULL, statId INT NOT NULL, value INT NOT NULL, date DATE NOT NULL, season INT NOT NULL, PRIMARY KEY (id), UNIQUE INDEX accountStatIndex(accountId, statId, date), INDEX valueIndex(value), INDEX seasonIndex(season), FOREIGN KEY (accountId) REFERENCES Account.accounts(id), FOREIGN KEY (statId) REFERENCES Account.stats(id));";
private static final String INSERT_STAT = "INSERT INTO statLeaderboard (accountId, statId, value, date, season) VALUES (?, (SELECT id FROM stats WHERE name=?), ?, CURDATE(), " + SEASON + ") ON DUPLICATE KEY UPDATE value=value+VALUES(value);";
private static final String FETCH_STAT_ALL = "SELECT a.name, sl.value FROM statLeaderboard AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE sl.statId IN (SELECT id FROM stats WHERE name IN (%IDS%)) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %LIMIT%;";
private static final String FETCH_STAT_YEARLY = "SELECT a.name, sl.value FROM statLeaderboard AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE YEAR(sl.date) = YEAR(CURDATE()) AND sl.statId IN (SELECT id FROM stats WHERE name IN (%IDS%)) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %LIMIT%;";
private static final String FETCH_STAT_MONTHLY = "SELECT a.name, sl.value FROM statLeaderboard AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE MONTH(sl.date) = MONTH(CURDATE()) AND YEAR(`date`) = YEAR(CURDATE()) AND sl.statId IN (SELECT id FROM stats WHERE name IN (%IDS%)) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %LIMIT%;";
private static final String FETCH_STAT_WEEKLY = "SELECT a.name, sl.value FROM statLeaderboard AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE YEARWEEK(sl.date, 1) = YEARWEEK(CURDATE(), 1) AND sl.statId IN (SELECT id FROM stats WHERE name IN (%IDS%)) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %LIMIT%;";
private static final String FETCH_STAT_DAILY = "SELECT a.name, sl.value FROM statLeaderboard AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE sl.date = CURDATE() AND sl.statId IN (SELECT id FROM stats WHERE name IN (%IDS%)) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %LIMIT%;";
private static final String CREATE_ALL_TIME = "CREATE TABLE accountStatsAllTime (id INT NOT NULL AUTO_INCREMENT, accountId INT NOT NULL, statId INT NOT NULL, value INT NOT NULL, date DATE NOT NULL, PRIMARY KEY (id), UNIQUE INDEX accountStatIndex(accountId, statId, date), INDEX valueIndex(value), FOREIGN KEY (accountId) REFERENCES Account.accounts(id), FOREIGN KEY (statId) REFERENCES Account.stats(id));";
private static final String CREATE_SEASONAL = "CREATE TABLE accountStatsSeasonal (id INT NOT NULL AUTO_INCREMENT, accountId INT NOT NULL, statId INT NOT NULL, value INT NOT NULL, date DATE NOT NULL, season INT NOT NULL, PRIMARY KEY (id), UNIQUE INDEX accountStatIndex(accountId, statId, date, season), INDEX valueIndex(value), INDEX seasonIndex(season), FOREIGN KEY (accountId) REFERENCES Account.accounts(id), FOREIGN KEY (statId) REFERENCES Account.stats(id));";
private static final String INSERT_STAT = "INSERT INTO accountStatsSeasonal (accountId, statId, value, date, season) VALUES (?, (SELECT id FROM stats WHERE name=?), ?, CURDATE(), " + SEASON + ") ON DUPLICATE KEY UPDATE value=value+VALUES(value);";
private static final String FETCH_STAT_ALL = "SELECT a.name, sl.value FROM accountStatsAllTime AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE sl.statId=(SELECT id FROM stats WHERE name=%STAT%) ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_YEARLY = "SELECT a.name, sl.value FROM accountStatsAllTime AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE YEAR(sl.date) = YEAR(CURDATE()) AND sl.statId=(SELECT id FROM stats WHERE name=%STAT%) ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_MONTHLY = "SELECT a.name, sl.value FROM accountStatsAllTime AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE MONTH(sl.date) = MONTH(CURDATE()) AND YEAR(`date`) = YEAR(CURDATE()) AND sl.statId=(SELECT id FROM stats WHERE name=%STAT%) ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_WEEKLY = "SELECT a.name, sl.value FROM accountStatsAllTime AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE YEARWEEK(sl.date, 1) = YEARWEEK(CURDATE(), 1) AND sl.statId=(SELECT id FROM stats WHERE name=%STAT%) ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_DAILY = "SELECT a.name, sl.value FROM accountStatsAllTime AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE sl.date = CURDATE() AND sl.statId=(SELECT id FROM stats WHERE name=%STAT%) ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_ALL_SEASON = "SELECT a.name, sl.value FROM accountStatsSeasonal AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE sl.statId=(SELECT id FROM stats WHERE name=%STAT%) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_YEARLY_SEASON = "SELECT a.name, sl.value FROM accountStatsSeasonal AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE YEAR(sl.date) = YEAR(CURDATE()) AND sl.statId=(SELECT id FROM stats WHERE name=%STAT%) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_MONTHLY_SEASON = "SELECT a.name, sl.value FROM accountStatsSeasonal AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE MONTH(sl.date) = MONTH(CURDATE()) AND YEAR(`date`) = YEAR(CURDATE()) AND sl.statId=(SELECT id FROM stats WHERE name=%STAT%) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_WEEKLY_SEASON = "SELECT a.name, sl.value FROM accountStatsSeasonal AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE YEARWEEK(sl.date, 1) = YEARWEEK(CURDATE(), 1) AND sl.statId=(SELECT id FROM stats WHERE name=%STAT%) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
private static final String FETCH_STAT_DAILY_SEASON = "SELECT a.name, sl.value FROM accountStatsSeasonal AS sl INNER JOIN accounts AS a ON a.id=sl.accountId WHERE sl.date = CURDATE() AND sl.statId=(SELECT id FROM stats WHERE name=%STAT%) AND season=" + SEASON + " ORDER BY sl.value DESC LIMIT %START%,%LIMIT%;";
public LeaderboardRepository(JavaPlugin plugin)
{
@ -49,10 +56,20 @@ public class LeaderboardRepository extends RepositoryBase
try (Connection c = getConnection())
{
Map<String, Integer> names = new LinkedHashMap<>();
ResultSet rs = board.getType().getStatement(c, board.getStatIds(), board.getSize()).executeQuery();
while (rs.next())
Statement s = c.createStatement();
s.execute(board.getType().getStatement(board.getStatIds(), board.getStart(), board.getSize()));
for (int i = 0; i < board.getStatIds().length; i++)
{
names.put(rs.getString("name"), rs.getInt("value"));
ResultSet rs = s.getResultSet();
while (rs.next())
{
names.merge(rs.getString("name"), rs.getInt("value"), Integer::sum);
}
if (!s.getMoreResults())
{
break ;
}
}
UtilServer.runSync(() -> leaderboard.accept(names));
@ -77,7 +94,7 @@ public class LeaderboardRepository extends RepositoryBase
int i = 0;
for (Leaderboard board : boards)
{
queryBuilder.append(board.getType().getMultiStatement(board.getStatIds(), board.getSize()));
queryBuilder.append(board.getType().getStatement(board.getStatIds(), board.getStart(), board.getSize()));
leaderboards[i] = new LinkedHashMap<>();
i++;
}
@ -87,19 +104,23 @@ public class LeaderboardRepository extends RepositoryBase
{
Statement s = c.createStatement();
s.execute(queryBuilder.toString());
for (int i = 0; i < boards.size(); i++)
int index = 0;
mainBoardLoop: for (Leaderboard board : boards)
{
ResultSet rs = s.getResultSet();
while (rs.next())
for (int i = 0; i < board.getStatIds().length; i++)
{
leaderboards[i].put(rs.getString("name"), rs.getInt("value"));
}
if (!s.getMoreResults())
{
break;
ResultSet rs = s.getResultSet();
while (rs.next())
{
leaderboards[index].merge(rs.getString("name"), rs.getInt("value"), Integer::sum);
}
if (!s.getMoreResults())
{
break mainBoardLoop;
}
}
index++;
}
}
@ -115,10 +136,15 @@ public class LeaderboardRepository extends RepositoryBase
public static enum LeaderboardSQLType
{
DAILY(FETCH_STAT_DAILY),
DAILY_SEASON(FETCH_STAT_DAILY_SEASON),
WEEKLY(FETCH_STAT_WEEKLY),
WEEKLY_SEASON(FETCH_STAT_WEEKLY_SEASON),
MONTHLY(FETCH_STAT_MONTHLY),
MONTHLY_SEASON(FETCH_STAT_MONTHLY_SEASON),
YEARLY(FETCH_STAT_YEARLY),
ALL(FETCH_STAT_ALL)
YEARLY_SEASON(FETCH_STAT_YEARLY_SEASON),
ALL(FETCH_STAT_ALL),
ALL_SEASON(FETCH_STAT_ALL_SEASON)
;
private String _sql;
@ -128,25 +154,14 @@ public class LeaderboardRepository extends RepositoryBase
_sql = sql;
}
public PreparedStatement getStatement(Connection connection, String[] statIds, int limit) throws SQLException
public String getStatement(String[] statIds, int start, int limit) throws SQLException
{
StringBuilder idBuilder = new StringBuilder();
StringBuilder statementBuilder = new StringBuilder();
for (String id : statIds)
{
idBuilder.append("'" + id + "'").append(", ");
statementBuilder.append(_sql.replace("%STAT%", id).replace("%START%", String.valueOf(start)).replace("%LIMIT%", String.valueOf(limit)));
}
PreparedStatement ps = connection.prepareStatement(_sql.replace("%LIMIT%", String.valueOf(limit)).replace("%IDS%", idBuilder.substring(0, idBuilder.length() - 2)));
return ps;
}
public String getMultiStatement(String[] statIds, int limit)
{
StringBuilder idBuilder = new StringBuilder();
for (String id : statIds)
{
idBuilder.append("'" + id + "'").append(", ");
}
return _sql.replace("%LIMIT%", String.valueOf(limit)).replace("%IDS%", idBuilder.substring(0, idBuilder.length() - 2));
return statementBuilder.toString();
}
}
}

View File

@ -206,22 +206,22 @@ public class CastleAssault extends TeamGame
if (lobbyCustomLocs.containsKey("TOP_DAILY_WINS"))
{
Location loc = lobbyCustomLocs.get("TOP_DAILY_WINS").get(0);
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_DAILY_WINS", new Leaderboard("Top Daily Wins", Pair.create("Win", "Wins"), new String[] {"Castle Assault.Wins"}, LeaderboardSQLType.DAILY, loc, 10));
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_DAILY_WINS", new Leaderboard("Top Daily Wins", Pair.create("Win", "Wins"), new String[] {"Castle Assault.Wins"}, LeaderboardSQLType.DAILY_SEASON, loc, 10));
}
if (lobbyCustomLocs.containsKey("TOP_DAILY_KILLS"))
{
Location loc = lobbyCustomLocs.get("TOP_DAILY_KILLS").get(0);
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_DAILY_KILLS", new Leaderboard("Top Daily Kills", Pair.create("Kill", "Kills"), new String[] {"Castle Assault.Kills"}, LeaderboardSQLType.DAILY, loc, 10));
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_DAILY_KILLS", new Leaderboard("Top Daily Kills", Pair.create("Kill", "Kills"), new String[] {"Castle Assault.Kills"}, LeaderboardSQLType.DAILY_SEASON, loc, 10));
}
if (lobbyCustomLocs.containsKey("TOP_WINS"))
{
Location loc = lobbyCustomLocs.get("TOP_WINS").get(0);
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_WINS", new Leaderboard("Top Wins", Pair.create("Win", "Wins"), new String[] {"Castle Assault.Wins"}, LeaderboardSQLType.ALL, loc, 10));
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_WINS", new Leaderboard("Top Wins", Pair.create("Win", "Wins"), new String[] {"Castle Assault.Wins"}, LeaderboardSQLType.ALL_SEASON, loc, 10));
}
if (lobbyCustomLocs.containsKey("TOP_KILLS"))
{
Location loc = lobbyCustomLocs.get("TOP_KILLS").get(0);
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_KILLS", new Leaderboard("Top Kills", Pair.create("Kill", "Kills"), new String[] {"Castle Assault.Kills"}, LeaderboardSQLType.ALL, loc, 10));
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_KILLS", new Leaderboard("Top Kills", Pair.create("Kill", "Kills"), new String[] {"Castle Assault.Kills"}, LeaderboardSQLType.ALL_SEASON, loc, 10));
}
}
}

View File

@ -165,22 +165,22 @@ public class CastleAssaultTDM extends TeamGame
if (lobbyCustomLocs.containsKey("TOP_DAILY_WINS"))
{
Location loc = lobbyCustomLocs.get("TOP_DAILY_WINS").get(0);
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_DAILY_WINS", new Leaderboard("Top Daily Wins", Pair.create("Win", "Wins"), new String[] {"Castle Assault TDM.Wins"}, LeaderboardSQLType.DAILY, loc, 10));
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_DAILY_WINS", new Leaderboard("Top Daily Wins", Pair.create("Win", "Wins"), new String[] {"Castle Assault TDM.Wins"}, LeaderboardSQLType.DAILY_SEASON, loc, 10));
}
if (lobbyCustomLocs.containsKey("TOP_DAILY_KILLS"))
{
Location loc = lobbyCustomLocs.get("TOP_DAILY_KILLS").get(0);
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_DAILY_KILLS", new Leaderboard("Top Daily Kills", Pair.create("Kill", "Kills"), new String[] {"Castle Assault TDM.Kills"}, LeaderboardSQLType.DAILY, loc, 10));
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_DAILY_KILLS", new Leaderboard("Top Daily Kills", Pair.create("Kill", "Kills"), new String[] {"Castle Assault TDM.Kills"}, LeaderboardSQLType.DAILY_SEASON, loc, 10));
}
if (lobbyCustomLocs.containsKey("TOP_WINS"))
{
Location loc = lobbyCustomLocs.get("TOP_WINS").get(0);
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_WINS", new Leaderboard("Top Wins", Pair.create("Win", "Wins"), new String[] {"Castle Assault TDM.Wins"}, LeaderboardSQLType.ALL, loc, 10));
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_WINS", new Leaderboard("Top Wins", Pair.create("Win", "Wins"), new String[] {"Castle Assault TDM.Wins"}, LeaderboardSQLType.ALL_SEASON, loc, 10));
}
if (lobbyCustomLocs.containsKey("TOP_KILLS"))
{
Location loc = lobbyCustomLocs.get("TOP_KILLS").get(0);
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_KILLS", new Leaderboard("Top Kills", Pair.create("Kill", "Kills"), new String[] {"Castle Assault TDM.Kills"}, LeaderboardSQLType.ALL, loc, 10));
Managers.get(LeaderboardManager.class).registerLeaderboard("TOP_CASTLEASSAULT_KILLS", new Leaderboard("Top Kills", Pair.create("Kill", "Kills"), new String[] {"Castle Assault TDM.Kills"}, LeaderboardSQLType.ALL_SEASON, loc, 10));
}
}
}

View File

@ -20,12 +20,12 @@ public abstract class KitPlayer extends ProgressingKit
public KitPlayer(ArcadeManager manager, String name, KitAvailability availability, String[] description, Perk[] perks, Material holding)
{
super(manager, name, "csii" + name.toLowerCase(), availability, description, perks, EntityType.ZOMBIE, new ItemStack(holding));
super(manager, name, "castleassault" + name.toLowerCase(), availability, description, perks, EntityType.ZOMBIE, new ItemStack(holding));
}
public KitPlayer(ArcadeManager manager, String name, KitAvailability availability, String[] description, Perk[][] perks, String[][] upgradeDetails, Material holding)
{
super(manager, name, "csii" + name.toLowerCase(), availability, description, perks, upgradeDetails, EntityType.ZOMBIE, new ItemStack(holding));
super(manager, name, "castleassault" + name.toLowerCase(), availability, description, perks, upgradeDetails, EntityType.ZOMBIE, new ItemStack(holding));
_progressionEnabled = true;
}