У меня есть плагин, который я сделал для Minecraft. Он используется для массовых боев эндеродонтов, чтобы справедливо разделить опыт между всеми, основываясь на нанесенном уроне.
Это работает, но есть сбой, из-за которого уравнение пропускает опыт.
Вот код:
private void divideExpAmongstPlayersBasedOnDamageDealt(int exp, Map<Player, Double> damageMap) {
double totalDamageDealt = 0.0d;
for (Double value : damageMap.values()) {
totalDamageDealt += value;
}
while (exp > 0 && !damageMap.isEmpty()) {
Player maxHitterInList = Collections.max(damageMap.entrySet(),
Comparator.comparingDouble(Map.Entry::getValue)).getKey();
double damageShare = damageMap.get(maxHitterInList) / totalDamageDealt;
int expShare = (int) Math.round(exp * damageShare);
if (expShare == 0)
break;
if (maxHitterInList.isOnline()) {
sendPlayerMessage(maxHitterInList, damageShare, expShare);
maxHitterInList.giveExp(expShare);
}
exp -= expShare;
damageMap.remove(maxHitterInList);
}
}
Он находит максимального нападающего, присуждает им свою долю опыта и удаляет их из списка, пока не останется больше опыта, чтобы дать.
Проблема в том, что он пропускает очки, вынуждая меня добавить && !damageMap.isEmpty()
к условию while, чтобы избежать исключений. Он всегда печатает проценты точно (сумма складывается до 100).
Я думаю, что это связано с функцией Math.round, хотя я нахожусь в неведении относительно того, как отладить это. Когда я делаю вычисления вручную, они работают.
Пример (это буквально произошло): моб дарует 10
опыта. Игрок1 нанес 57%
урона, Игрок2 нанес 43%
. Процентные значения печатаются правильно, но Player1 получает 6
EXP, а Player2 получает 2
?? В прошлый раз я проверял 0.57 * 10
равно 5.7 = 6
и 0.43 * 10
равно 4.3 = 4
.
Что мне не хватает? Это связано с функцией округления или с тем, как удваивается работа?
Спасибо