From 0d708a99f42a564cd23472883e84344d4c2a5706 Mon Sep 17 00:00:00 2001 From: AlexTheCoder Date: Mon, 10 Sep 2018 22:07:30 -0500 Subject: [PATCH] Update stats and leaderboard code to be cleaner and better organized --- .../core/leaderboard/LeaderboardManager.java | 5 - .../leaderboard/LeaderboardRepository.java | 88 ----- .../src/mineplex/core/stats/PlayerStats.java | 29 -- .../src/mineplex/core/stats/StatsManager.java | 163 +-------- .../mineplex/core/stats/StatsRepository.java | 316 +++++++----------- .../core/stats/command/GiveStatCommand.java | 6 + 6 files changed, 144 insertions(+), 463 deletions(-) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardManager.java b/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardManager.java index a0e88c4c0..c7f5f0e92 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardManager.java @@ -108,11 +108,6 @@ public class LeaderboardManager extends MiniPlugin }); } - public void handleStatIncrease(Map> stats) - { - _repo.insertStats(stats); - } - public void registerIfNotExists(String identifier, LeaderboardDisplay display) { if (_leaderboards.containsKey(identifier)) diff --git a/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardRepository.java index 88746ebf0..fa00c5ed5 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardRepository.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/leaderboard/LeaderboardRepository.java @@ -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; @@ -24,9 +23,6 @@ public class LeaderboardRepository extends RepositoryBase private static final String CREATE_DAILY = "CREATE TABLE accountStatsDaily (accountId INT NOT NULL, statId INT NOT NULL, date DATE NOT NULL, value BIGINT NOT NULL, PRIMARY KEY (accountId, statId), INDEX valueIndex (value DESC), INDEX dateIndex (date), FOREIGN KEY (accountId) REFERENCES accounts(id), FOREIGN KEY (statId) REFERENCES stats(id));"; private static final String CREATE_SEASON = "CREATE TABLE statSeasons (id SMALLINT NOT NULL, seasonName VARCHAR(50) NOT NULL, startDate TIMESTAMP NOT NULL DEFAULT '1969-12-31 18:00:01', endDate TIMESTAMP NOT NULL DEFAULT '1969-12-31 18:00:01', PRIMARY KEY (id), UNIQUE INDEX seasonIndex (seasonName), INDEX startIndex (startDate), INDEX endIndex (endDate));"; - private static final String INSERT_STAT = "INSERT INTO accountStatsAllTime (accountId, statId, value) VALUES (?, ?, ?);"; - private static final String UPDATE_STAT = "UPDATE accountStatsAllTime SET value=value + ? WHERE accountId=? AND statId=?;"; - private static final String FETCH_STAT_ALL = "SELECT a.name, a.uuid, sl.value FROM (SELECT accountId, value FROM accountStatsAllTime WHERE statId=(SELECT id FROM stats WHERE name='%STAT%') ORDER BY value DESC LIMIT %START%,%LIMIT%) AS sl INNER JOIN accounts AS a ON a.id=sl.accountId;"; private static final String FETCH_STAT_YEARLY = "SELECT a.name, a.uuid, sl.value FROM (SELECT accountId, value FROM accountStatsYearly WHERE (date BETWEEN MAKEDATE(YEAR(CURDATE()),1) AND CURDATE()) AND statId=(SELECT id FROM stats WHERE name='%STAT%') ORDER BY value DESC LIMIT %START%,%LIMIT%) AS sl INNER JOIN accounts AS a ON a.id=sl.accountId;"; @@ -41,90 +37,6 @@ public class LeaderboardRepository extends RepositoryBase super(DBPool.getAccount()); } - public void insertStats(Map> stats) - { - UtilServer.runAsync(() -> - { - try ( - Connection c = getConnection(); - PreparedStatement updateStat = c.prepareStatement(UPDATE_STAT); - PreparedStatement insertStat = c.prepareStatement(INSERT_STAT); - ) - { - for (Integer accountId : stats.keySet()) - { - for (Integer statId : stats.get(accountId).keySet()) - { - updateStat.setLong(1, stats.get(accountId).get(statId)); - updateStat.setInt(2, accountId); - updateStat.setInt(3, statId); - updateStat.addBatch(); - } - } - int[] rowsAffected = updateStat.executeBatch(); - int i = 0; - for (Integer accountId : stats.keySet()) - { - for (Integer statId : stats.get(accountId).keySet()) - { - if (rowsAffected[i] < 1) - { - insertStat.setInt(1, accountId); - insertStat.setInt(2, statId); - insertStat.setLong(3, stats.get(accountId).get(statId)); - insertStat.addBatch(); - } - i++; - } - } - insertStat.executeBatch(); - } - catch (SQLException e) - { - e.printStackTrace(); - } - }); - } - - public void insertStats(int accountId, Map stats) - { - UtilServer.runAsync(() -> - { - try ( - Connection c = getConnection(); - PreparedStatement updateStat = c.prepareStatement(UPDATE_STAT); - PreparedStatement insertStat = c.prepareStatement(INSERT_STAT); - ) - { - for (Integer statId : stats.keySet()) - { - updateStat.setLong(1, stats.get(statId)); - updateStat.setInt(2, accountId); - updateStat.setInt(3, statId); - updateStat.addBatch(); - } - int[] rowsAffected = updateStat.executeBatch(); - int i = 0; - for (Integer statId : stats.keySet()) - { - if (rowsAffected[i] < 1) - { - insertStat.setInt(1, accountId); - insertStat.setInt(2, statId); - insertStat.setLong(3, stats.get(statId)); - insertStat.addBatch(); - } - i++; - } - insertStat.executeBatch(); - } - catch (SQLException e) - { - e.printStackTrace(); - } - }); - } - public void loadLeaderboard(Leaderboard board, Consumer> leaderboard) { UtilServer.runAsync(() -> diff --git a/Plugins/Mineplex.Core/src/mineplex/core/stats/PlayerStats.java b/Plugins/Mineplex.Core/src/mineplex/core/stats/PlayerStats.java index 95eb54ffc..32e72acc6 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/stats/PlayerStats.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/stats/PlayerStats.java @@ -18,9 +18,6 @@ public class PlayerStats @GuardedBy("_lock") private Map _stats = new HashMap<>(); - @GuardedBy("_lock") - private Map _statsOld = new HashMap<>(); - private final boolean _temporary; public PlayerStats(boolean temporary) @@ -63,14 +60,6 @@ public class PlayerStats return value; } } - - void setStatOld(String statName, long value) - { - synchronized (_lock) - { - _statsOld.put(statName, value); - } - } /** * Gets the value for the specified stat @@ -79,24 +68,6 @@ public class PlayerStats * @return The value of the stat if it exists, or 0 if it does not */ public long getStat(String statName) - { - synchronized (_lock) - { - long cur = _stats.getOrDefault(statName, 0L); - long old = _statsOld.getOrDefault(statName, 0L); - return cur + (old > cur ? old - cur : 0); - } - } - - public long getStatOld(String statName) - { - synchronized (_lock) - { - return _statsOld.getOrDefault(statName, 0L); - } - } - - public long getJustCurrentStat(String statName) { synchronized (_lock) { diff --git a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java index 7edcbdd91..b9d025009 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsManager.java @@ -39,7 +39,7 @@ import mineplex.core.utils.UtilScheduler; /** * This manager handles player statistics */ -public class StatsManager extends MiniClientPlugin//MiniDbClientPlugin +public class StatsManager extends MiniClientPlugin { public enum Perm implements Permission { @@ -52,63 +52,27 @@ public class StatsManager extends MiniClientPlugin//MiniDbClientPlu private final CoreClientManager _coreClientManager; private final StatsRepository _repository; - private final LeaderboardManager _leaderboard; private final Map _stats = new HashMap<>(); private final Map> _statUploadQueue = new HashMap<>(); - private final Map> _statUploadQueueOverRidable = new HashMap<>(); private final Set _loading = Collections.synchronizedSet(new HashSet<>()); public StatsManager(JavaPlugin plugin, CoreClientManager clientManager) { - //super("Stats Manager", plugin, clientManager); super("Stats Manager", plugin); _repository = new StatsRepository(); _coreClientManager = clientManager; - _leaderboard = new LeaderboardManager(this); - - /*clientManager.addStoredProcedureLoginProcessor(new ILoginProcessor() - { - public String getName() - { - return "Stat Old Selector"; - } - - @Override - public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException - { - PlayerStats stats = Get(uuid); - - while (resultSet.next()) - { - stats.setStatOld(resultSet.getString(1), resultSet.getLong(2)); - } - } - - @Override - public String getQuery(int accountId, String uuid, String name) - { - return "SELECT stats.name, value FROM accountStat INNER JOIN stats ON stats.id = accountStat.statId WHERE accountStat.accountId = '" + accountId + "';"; - } - });*/ + new LeaderboardManager(this); UtilScheduler.runAsyncEvery(UpdateType.SEC, () -> { save(_statUploadQueue, map -> { - //_repository.saveStats(map); - _repository.saveOnlyExisting(map); - _leaderboard.handleStatIncrease(map); + _repository.insertStats(map); }, "increment"); - save(_statUploadQueueOverRidable, map -> - { - //_repository.saveStats(map, true); - _repository.saveOnlyExisting(map); - _leaderboard.handleStatIncrease(map); - }, "override"); }); for (Stat stat : _repository.retrieveStats()) @@ -180,38 +144,13 @@ public class StatsManager extends MiniClientPlugin//MiniDbClientPlu return; } - long oldCompositeValue = snapshot.getStat(statName); + long oldValue = snapshot.getStat(statName); long newValue = snapshot.addStat(statName, value); - UtilServer.getServer().getPluginManager().callEvent(new StatChangeEvent(player, statName, oldCompositeValue, newValue)); + UtilServer.getServer().getPluginManager().callEvent(new StatChangeEvent(player, statName, oldValue, newValue)); registerNewStat(statName, () -> addToQueue(statName, client, value)); } - - /** - * Sets the value of a stat for the given player - * - * @param value The value, must be greater or equal to zero - */ - @Deprecated - public void setStat(Player player, String statName, long value) - { - if (value < 0) - return; - if (0 == 0) - { - return; - } - - CoreClient client = _coreClientManager.Get(player); - - long oldValue = Get(player).getStat(statName); - Get(player).setStat(statName, value); - - UtilServer.getServer().getPluginManager().callEvent(new StatChangeEvent(player, statName, oldValue, value)); - registerNewStat(statName, () -> addToOverRidableQueue(statName, client, value)); - } - /** * Increments a stat for the given account ID of an offline player by the specified amount */ @@ -219,58 +158,13 @@ public class StatsManager extends MiniClientPlugin//MiniDbClientPlu { registerNewStat(statName, () -> { - Map> uploadQueue = new HashMap<>(); - uploadQueue.computeIfAbsent(accountId, key -> new HashMap<>()).put(_stats.get(statName), value); - - _repository.saveStats(uploadQueue, false); + Map stats = new HashMap<>(); + stats.put(_stats.get(statName), value); + + _repository.insertStats(accountId, stats); }); } - /** - * Sets the value of a stat for the given account ID of an offline player - * - * @param value The value, must be greater or equal to zero - */ - @Deprecated - public void setStat(final int accountId, final String statName, final long value) - { - if (value < 0) - return; - if (0 == 0) - { - return; - } - - registerNewStat(statName, () -> - { - Map> uploadQueue = new HashMap<>(); - uploadQueue.computeIfAbsent(accountId, key -> new HashMap<>()).put(_stats.get(statName), value); - - _repository.saveStats(uploadQueue, true); - }); - } - - @Deprecated - private void addToOverRidableQueue(String statName, CoreClient client, long value) - { - if (0 == 0) - { - return; - } - if (client.getAccountId() == -1) - { - System.out.println(String.format("Error: Tried to add %s/%s to overridable queue with -1 account id", client.getName(), client.getUniqueId())); - return; - } - - synchronized (STATS_LOCK) - { - _statUploadQueueOverRidable - .computeIfAbsent(client, key -> new HashMap<>()) - .put(statName, value); - } - } - private void addToQueue(String statName, CoreClient client, long value) { if (client.getAccountId() == -1) @@ -369,17 +263,13 @@ public class StatsManager extends MiniClientPlugin//MiniDbClientPlu final UUID uuid = event.getPlayer().getUniqueId(); final int accountId = _coreClientManager.Get(event.getPlayer()).getAccountId(); UtilPlayer.message(event.getPlayer(), F.main(getName(), "Loading your stats...")); - runAsync(() -> + runSyncLater(() -> { - _repository.loadStatsFromOld(accountId, data -> + _repository.loadStats(accountId, data -> { PlayerStats stats = new PlayerStats(false); - data.forEach((stat, values) -> - { - stats.setStatOld(stat, values.getLeft()); - stats.addStat(stat, values.getRight()); - }); + data.forEach(stats::setStat); if (_loading.remove(uuid)) { @@ -431,33 +321,4 @@ public class StatsManager extends MiniClientPlugin//MiniDbClientPlu { return _coreClientManager; } - -/* @Override - public void processLoginResultSet(String playerName, UUID uuid, int accountId, ResultSet resultSet) throws SQLException - { - PlayerStats playerStats = new PlayerStats(); - - while (resultSet.next()) - { - try - { - playerStats.addStat(resultSet.getString(1), resultSet.getLong(2)); - } - catch (Exception ex) - { - ex.printStackTrace(); - playerStats.addStat(resultSet.getString(1), -1); - } - } - - Set(uuid, playerStats); - } - */ - -/* @Override - public String getQuery(int accountId, String uuid, String name) - { - return "SELECT stats.name, value FROM accountStatsAllTime INNER JOIN stats ON stats.id = accountStatsAllTime.statId WHERE accountStatsAllTime.accountId = '" + accountId + "';"; - } - */ } \ No newline at end of file diff --git a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsRepository.java b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsRepository.java index 4f6e38ab5..f64162b1a 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsRepository.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/stats/StatsRepository.java @@ -2,36 +2,29 @@ package mineplex.core.stats; import java.sql.Connection; import java.sql.PreparedStatement; -import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Map.Entry; -import java.util.Objects; import java.util.function.Consumer; -import org.jooq.DSLContext; -import org.jooq.Insert; -import org.jooq.Record2; -import org.jooq.Result; -import org.jooq.SQLDialect; -import org.jooq.Update; -import org.jooq.impl.DSL; -import org.jooq.types.ULong; - import com.mysql.jdbc.exceptions.jdbc4.MySQLDataException; -import mineplex.core.common.Pair; import mineplex.core.common.util.UtilServer; -import mineplex.database.Tables; import mineplex.serverdata.database.DBPool; import mineplex.serverdata.database.RepositoryBase; +import mineplex.serverdata.database.column.ColumnInt; import mineplex.serverdata.database.column.ColumnVarChar; public class StatsRepository extends RepositoryBase { + private static final String SELECT_ACCOUNT_STATS = "SELECT stats.name, accountStatsAllTime.value FROM accountStatsAllTime INNER JOIN stats ON stats.id = accountStatsAllTime.statId WHERE accountStatsAllTime.accountId=?;"; + private static final String SELECT_USER_STATS = "SELECT stats.name, accountStatsAllTime.value FROM accountStatsAllTime INNER JOIN stats ON stats.id = accountStatsAllTime.statId WHERE accountStatsAllTime.accountId=(SELECT id FROM accounts WHERE name=? ORDER BY lastLogin DESC LIMIT 1);"; + + private static final String INSERT_ACCOUNT_STAT = "INSERT INTO accountStatsAllTime (accountId, statId, value) VALUES (?, ?, ?);"; + private static final String UPDATE_ACCOUNT_STAT = "UPDATE accountStatsAllTime SET value=value + ? WHERE accountId=? AND statId=?;"; + private static final String RETRIEVE_STATS = "SELECT id, name FROM stats;"; private static final String INSERT_STAT = "INSERT INTO stats (name) VALUES (?);"; @@ -39,66 +32,6 @@ public class StatsRepository extends RepositoryBase { super(DBPool.getAccount()); } - - public void loadStatsFromOld(int accountId, Consumer>> callback) - { - try (Connection c = getConnection(); - PreparedStatement oldStatement = c.prepareStatement("SELECT stats.name, value FROM accountStat INNER JOIN stats ON stats.id = accountStat.statId WHERE accountStat.accountId=?;"); - PreparedStatement newStatement = c.prepareStatement("SELECT stats.name, value FROM accountStatsAllTime INNER JOIN stats ON stats.id = accountStatsAllTime.statId WHERE accountStatsAllTime.accountId=?;"); - ) - { - oldStatement.setInt(1, accountId); - newStatement.setInt(1, accountId); - try (ResultSet oldSet = oldStatement.executeQuery(); - ResultSet newSet = newStatement.executeQuery(); - ) - { - final Map> statMap = new HashMap<>(); - while (oldSet.next()) - { - String statName = oldSet.getString(1); - long oldValue; - try - { - oldValue = oldSet.getLong(2); - } - catch (MySQLDataException ex) - { - oldValue = 0; - } - statMap.put(statName, Pair.create(oldValue, 0L)); - } - while (newSet.next()) - { - String statName = newSet.getString(1); - long newValue; - try - { - newValue = newSet.getLong(2); - } - catch (MySQLDataException ex) - { - newValue = 0; - } - if (statMap.containsKey(statName)) - { - statMap.get(statName).setRight(newValue); - } - else - { - statMap.put(statName, Pair.create(0L, newValue)); - } - } - - UtilServer.runSync(() -> callback.accept(statMap)); - } - } - catch (SQLException e) - { - e.printStackTrace(); - UtilServer.runSync(() -> callback.accept(new HashMap<>())); - } - } /** * Retrieves all the remote registered stats @@ -129,7 +62,7 @@ public class StatsRepository extends RepositoryBase { try (Connection c = getConnection()) { - executeInsert(c, "INSERT INTO stats (name) VALUES (?);", rs -> onComplete.run(), () -> {}, new ColumnVarChar("name", 100, name)); + executeInsert(c, INSERT_STAT, rs -> onComplete.run(), () -> {}, new ColumnVarChar("name", 100, name)); } catch (SQLException e) { @@ -137,111 +70,33 @@ public class StatsRepository extends RepositoryBase } } - public void saveOnlyExisting(Map> uploadQueue) + public void loadStats(int accountId, Consumer> callback) { - try (Connection c = getConnection(); - PreparedStatement ps = c.prepareStatement("UPDATE accountStat SET value=value+? WHERE accountId=? AND statId=?;"); - ) + UtilServer.runAsync(() -> { - for (Entry> accountEntry : uploadQueue.entrySet()) + Map loaded = new HashMap<>(); + executeQuery(SELECT_ACCOUNT_STATS, resultSet -> { - int accountId = accountEntry.getKey(); - for (Entry statEntry : accountEntry.getValue().entrySet()) + while (resultSet.next()) { - int statId = statEntry.getKey(); - long delta = statEntry.getValue(); - ps.setLong(1, delta); - ps.setInt(2, accountId); - ps.setInt(3, statId); - ps.addBatch(); - } - } - ps.executeBatch(); - } - catch (SQLException e) - { - e.printStackTrace(); - } - } - - /** - * Saves the given stats - * - * @param uploadQueue A map of account ID to a map of stat IDS to values - */ - public void saveStats(Map> uploadQueue) - { - saveStats(uploadQueue, false); - } - - /** - * Saves the given stats - * - * @param uploadQueue A map of account ID to a map of stat IDS to values - * @param overrideStat Whether to replace the remote value, or to add to it - */ - public void saveStats(Map> uploadQueue, boolean overrideStat) - { - try - { - DSLContext context = DSL.using(getConnectionPool(), SQLDialect.MYSQL); - - List updates = new ArrayList<>(); - List inserts = new ArrayList<>(); - - for (int accountId : uploadQueue.keySet()) - { - for (Integer statId : uploadQueue.get(accountId).keySet()) - { - if (overrideStat) + String statName = resultSet.getString(1); + long value; + try { - Update update = context - .update(Tables.accountStat) - .set(Tables.accountStat.value, ULong.valueOf(uploadQueue.get(accountId).get(statId))) - .where(Tables.accountStat.accountId.eq(accountId)) - .and(Tables.accountStat.statId.eq(statId)); - updates.add(update); + value = resultSet.getLong(2); } - else + catch (MySQLDataException ex) { - Update update = context - .update(Tables.accountStat) - .set(Tables.accountStat.value, Tables.accountStat.value.plus(uploadQueue.get(accountId).get(statId))) - .where(Tables.accountStat.accountId.eq(accountId)) - .and(Tables.accountStat.statId.eq(statId)); - updates.add(update); + value = 0; } - - Insert insert = context - .insertInto(Tables.accountStat) - .set(Tables.accountStat.accountId, accountId) - .set(Tables.accountStat.statId, statId) - .set(Tables.accountStat.value, ULong.valueOf(uploadQueue.get(accountId).get(statId))); - - inserts.add(insert); + loaded.put(statName, value); } - } - - int[] updateResult = context.batch(updates).execute(); - - for (int i = 0; i < updateResult.length; i++) - { - if (updateResult[i] > 0) - inserts.set(i, null); - } - - inserts.removeIf(Objects::isNull); - - context.batch(inserts).execute(); - } - catch (Exception e) - { - System.out.println("Failed to save stats: " + uploadQueue); - e.printStackTrace(); - } + }, new ColumnInt("accountId", accountId)); + + UtilServer.runSync(() -> callback.accept(loaded)); + }); } - /** * Gets offline stats for the specified player name. This performs SQL on the current thread */ @@ -249,32 +104,113 @@ public class StatsRepository extends RepositoryBase { PlayerStats playerStats = null; - DSLContext context; - - synchronized (this) + Map loaded = new HashMap<>(); + executeQuery(SELECT_USER_STATS, resultSet -> { - context = DSL.using(getConnectionPool(), SQLDialect.MYSQL); - } + while (resultSet.next()) + { + String statName = resultSet.getString(1); + long value; + try + { + value = resultSet.getLong(2); + } + catch (MySQLDataException ex) + { + value = 0; + } + loaded.put(statName, value); + } + }, new ColumnVarChar("name", playerName.length(), playerName)); - Result> result = context.select(Tables.stats.name, Tables.accountStat.value).from(Tables.accountStat) - .join(Tables.stats) - .on(Tables.stats.id.eq(Tables.accountStat.statId)) - .where(Tables.accountStat.accountId.eq(DSL.select(Tables.accounts.id) - .from(Tables.accounts) - .where(Tables.accounts.name.eq(playerName)).limit(1)) - ) - .fetch(); - - - if (result.isNotEmpty()) + if (!loaded.isEmpty()) { playerStats = new PlayerStats(false); - for (Record2 record : result) - { - playerStats.addStat(record.value1(), record.value2().longValue()); - } + loaded.forEach(playerStats::addStat); } return playerStats; } -} + + public void insertStats(Map> stats) + { + UtilServer.runAsync(() -> + { + try (Connection c = getConnection(); + PreparedStatement updateStat = c.prepareStatement(UPDATE_ACCOUNT_STAT); + PreparedStatement insertStat = c.prepareStatement(INSERT_ACCOUNT_STAT); + ) + { + for (Integer accountId : stats.keySet()) + { + for (Integer statId : stats.get(accountId).keySet()) + { + updateStat.setLong(1, stats.get(accountId).get(statId)); + updateStat.setInt(2, accountId); + updateStat.setInt(3, statId); + updateStat.addBatch(); + } + } + int[] rowsAffected = updateStat.executeBatch(); + int i = 0; + for (Integer accountId : stats.keySet()) + { + for (Integer statId : stats.get(accountId).keySet()) + { + if (rowsAffected[i] < 1) + { + insertStat.setInt(1, accountId); + insertStat.setInt(2, statId); + insertStat.setLong(3, stats.get(accountId).get(statId)); + insertStat.addBatch(); + } + i++; + } + } + insertStat.executeBatch(); + } + catch (SQLException e) + { + e.printStackTrace(); + } + }); + } + + public void insertStats(int accountId, Map stats) + { + UtilServer.runAsync(() -> + { + try (Connection c = getConnection(); + PreparedStatement updateStat = c.prepareStatement(UPDATE_ACCOUNT_STAT); + PreparedStatement insertStat = c.prepareStatement(INSERT_ACCOUNT_STAT); + ) + { + for (Integer statId : stats.keySet()) + { + updateStat.setLong(1, stats.get(statId)); + updateStat.setInt(2, accountId); + updateStat.setInt(3, statId); + updateStat.addBatch(); + } + int[] rowsAffected = updateStat.executeBatch(); + int i = 0; + for (Integer statId : stats.keySet()) + { + if (rowsAffected[i] < 1) + { + insertStat.setInt(1, accountId); + insertStat.setInt(2, statId); + insertStat.setLong(3, stats.get(statId)); + insertStat.addBatch(); + } + i++; + } + insertStat.executeBatch(); + } + catch (SQLException e) + { + e.printStackTrace(); + } + }); + } +} \ No newline at end of file diff --git a/Plugins/Mineplex.Core/src/mineplex/core/stats/command/GiveStatCommand.java b/Plugins/Mineplex.Core/src/mineplex/core/stats/command/GiveStatCommand.java index 747259157..0a1dee810 100644 --- a/Plugins/Mineplex.Core/src/mineplex/core/stats/command/GiveStatCommand.java +++ b/Plugins/Mineplex.Core/src/mineplex/core/stats/command/GiveStatCommand.java @@ -37,6 +37,12 @@ public class GiveStatCommand extends CommandBase UtilPlayer.message(caller, F.main("Stats", F.elem(args[1]) + " is not a number")); return; } + + if (amount < 1) + { + UtilPlayer.message(caller, F.main("Stats", "That amount is invalid")); + return; + } String statName = StringUtils.join(args, " ", 2, args.length);