In case we have capped burn shares we redistribute the share from the over-burned amount to the non capped candidates.

This helps to avoid that the legacy BM would get the rest in case there are capped shares.
It still can be that a candidate exceeds the cap and by the adjustment becomes capped. We take that into account and the legacy BM would get some share in that case.

Signed-off-by: HenrikJannsen <boilingfrog@gmx.com>
This commit is contained in:
HenrikJannsen 2022-12-14 21:44:54 -05:00
parent 4860c1177a
commit d0539e17ef
No known key found for this signature in database
GPG Key ID: 02AA2BAE387C8307
3 changed files with 58 additions and 10 deletions

View File

@ -189,6 +189,17 @@ public class BurningManService {
.mapToDouble(BurningManCandidate::getAccumulatedDecayedBurnAmount) .mapToDouble(BurningManCandidate::getAccumulatedDecayedBurnAmount)
.sum(); .sum();
burningManCandidates.forEach(candidate -> candidate.calculateShares(totalDecayedCompensationAmounts, totalDecayedBurnAmounts)); burningManCandidates.forEach(candidate -> candidate.calculateShares(totalDecayedCompensationAmounts, totalDecayedBurnAmounts));
double sumAllCappedBurnAmountShares = burningManCandidates.stream()
.filter(candidate -> candidate.getBurnAmountShare() >= candidate.getMaxBoostedCompensationShare())
.mapToDouble(BurningManCandidate::getMaxBoostedCompensationShare)
.sum();
double sumAllNonCappedBurnAmountShares = burningManCandidates.stream()
.filter(candidate -> candidate.getBurnAmountShare() < candidate.getMaxBoostedCompensationShare())
.mapToDouble(BurningManCandidate::getBurnAmountShare)
.sum();
burningManCandidates.forEach(candidate -> candidate.calculateCappedBurnAmountShare(sumAllCappedBurnAmountShares, sumAllNonCappedBurnAmountShares));
return burningManCandidatesByName; return burningManCandidatesByName;
} }

View File

@ -52,8 +52,13 @@ public class BurningManCandidate {
private final Map<Date, Set<BurnOutputModel>> burnOutputModelsByMonth = new HashMap<>(); private final Map<Date, Set<BurnOutputModel>> burnOutputModelsByMonth = new HashMap<>();
private long accumulatedBurnAmount; private long accumulatedBurnAmount;
private long accumulatedDecayedBurnAmount; private long accumulatedDecayedBurnAmount;
protected double burnAmountShare; // Share of accumulated decayed burn amounts in relation to total burned amounts // Share of accumulated decayed burn amounts in relation to total burned amounts
protected double cappedBurnAmountShare; // Capped burnAmountShare. Cannot be larger than boostedCompensationShare protected double burnAmountShare;
// Capped burnAmountShare. Cannot be larger than boostedCompensationShare
protected double cappedBurnAmountShare;
// The burnAmountShare adjusted in case there are cappedBurnAmountShare.
// We redistribute the over-burned amounts to the group of not capped candidates.
private double adjustedBurnAmountShare;
public BurningManCandidate() { public BurningManCandidate() {
} }
@ -93,11 +98,42 @@ public class BurningManCandidate {
public void calculateShares(double totalDecayedCompensationAmounts, double totalDecayedBurnAmounts) { public void calculateShares(double totalDecayedCompensationAmounts, double totalDecayedBurnAmounts) {
compensationShare = totalDecayedCompensationAmounts > 0 ? accumulatedDecayedCompensationAmount / totalDecayedCompensationAmounts : 0; compensationShare = totalDecayedCompensationAmounts > 0 ? accumulatedDecayedCompensationAmount / totalDecayedCompensationAmounts : 0;
burnAmountShare = totalDecayedBurnAmounts > 0 ? accumulatedDecayedBurnAmount / totalDecayedBurnAmounts : 0; burnAmountShare = totalDecayedBurnAmounts > 0 ? accumulatedDecayedBurnAmount / totalDecayedBurnAmounts : 0;
cappedBurnAmountShare = Math.min(getMaxBoostedCompensationShare(), burnAmountShare);
} }
public void calculateCappedBurnAmountShare(double sumAllCappedBurnAmountShares,
double sumAllNonCappedBurnAmountShares) {
double maxBoostedCompensationShare = getMaxBoostedCompensationShare();
adjustedBurnAmountShare = burnAmountShare;
if (burnAmountShare < maxBoostedCompensationShare) {
if (sumAllCappedBurnAmountShares == 0) {
// If no one is capped we do not need to do any adjustment
cappedBurnAmountShare = burnAmountShare;
} else {
// The difference of the cappedBurnAmountShare and burnAmountShare will get redistributed to all
// non-capped candidates.
double distributionBase = 1 - sumAllCappedBurnAmountShares;
if (sumAllNonCappedBurnAmountShares == 0) {
// In case we get sumAllNonCappedBurnAmountShares our burnAmountShare is also 0.
cappedBurnAmountShare = burnAmountShare;
} else {
double adjustment = distributionBase / sumAllNonCappedBurnAmountShares;
adjustedBurnAmountShare = burnAmountShare * adjustment;
if (adjustedBurnAmountShare < maxBoostedCompensationShare) {
cappedBurnAmountShare = adjustedBurnAmountShare;
} else {
// We exceeded the cap by the adjustment. This will lead to the legacy BM getting the
// difference of the adjusted amount and the maxBoostedCompensationShare.
cappedBurnAmountShare = maxBoostedCompensationShare;
}
}
}
} else {
cappedBurnAmountShare = maxBoostedCompensationShare;
}
}
public double getMaxBoostedCompensationShare() { public double getMaxBoostedCompensationShare() {
return Math.min(BurningManService.MAX_BURN_SHARE, compensationShare * BurningManService.ISSUANCE_BOOST_FACTOR); return Math.min(BurningManService.MAX_BURN_SHARE, compensationShare * BurningManService.ISSUANCE_BOOST_FACTOR);
} }
@ -115,6 +151,7 @@ public class BurningManCandidate {
",\r\n accumulatedDecayedBurnAmount=" + accumulatedDecayedBurnAmount + ",\r\n accumulatedDecayedBurnAmount=" + accumulatedDecayedBurnAmount +
",\r\n burnAmountShare=" + burnAmountShare + ",\r\n burnAmountShare=" + burnAmountShare +
",\r\n cappedBurnAmountShare=" + cappedBurnAmountShare + ",\r\n cappedBurnAmountShare=" + cappedBurnAmountShare +
",\r\n adjustedBurnAmountShare=" + adjustedBurnAmountShare +
"\r\n}"; "\r\n}";
} }
} }

View File

@ -39,7 +39,7 @@ class BurningManListItem {
private final long burnTarget, maxBurnTarget, accumulatedDecayedBurnAmount, accumulatedBurnAmount, private final long burnTarget, maxBurnTarget, accumulatedDecayedBurnAmount, accumulatedBurnAmount,
accumulatedDecayedCompensationAmount, accumulatedCompensationAmount, expectedRevenue; accumulatedDecayedCompensationAmount, accumulatedCompensationAmount, expectedRevenue;
private final int numBurnOutputs, numIssuances; private final int numBurnOutputs, numIssuances;
private final double cappedBurnAmountShare, burnAmountShare, compensationShare; private final double cappedBurnAmountShare, adjustedBurnAmountShare, compensationShare;
BurningManListItem(BurningManPresentationService burningManPresentationService, BurningManListItem(BurningManPresentationService burningManPresentationService,
String name, String name,
@ -60,14 +60,14 @@ class BurningManListItem {
accumulatedDecayedBurnAmount = 0; accumulatedDecayedBurnAmount = 0;
accumulatedDecayedBurnAmountAsBsq = ""; accumulatedDecayedBurnAmountAsBsq = "";
burnAmountShare = burningManCandidate.getBurnAmountShare(); adjustedBurnAmountShare = burningManCandidate.getAdjustedBurnAmountShare();
cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare(); cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare();
// LegacyBurningManForDPT is the one defined by DAO voting, so only that would receive BTC if new BM do not cover 100%. // LegacyBurningManForDPT is the one defined by DAO voting, so only that would receive BTC if new BM do not cover 100%.
if (burningManPresentationService.getLegacyBurningManForDPT().equals(burningManCandidate)) { if (burningManPresentationService.getLegacyBurningManForDPT().equals(burningManCandidate)) {
expectedRevenue = burningManPresentationService.getExpectedRevenue(burningManCandidate); expectedRevenue = burningManPresentationService.getExpectedRevenue(burningManCandidate);
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(burnAmountShare); cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(adjustedBurnAmountShare);
} else { } else {
expectedRevenue = 0; expectedRevenue = 0;
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(0); cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(0);
@ -94,12 +94,12 @@ class BurningManListItem {
accumulatedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedBurnAmount); accumulatedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedBurnAmount);
accumulatedDecayedBurnAmount = burningManCandidate.getAccumulatedDecayedBurnAmount(); accumulatedDecayedBurnAmount = burningManCandidate.getAccumulatedDecayedBurnAmount();
accumulatedDecayedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedDecayedBurnAmount); accumulatedDecayedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedDecayedBurnAmount);
burnAmountShare = burningManCandidate.getBurnAmountShare(); adjustedBurnAmountShare = burningManCandidate.getAdjustedBurnAmountShare();
cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare(); cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare();
if (burnAmountShare != cappedBurnAmountShare) { if (adjustedBurnAmountShare != cappedBurnAmountShare) {
cappedBurnAmountShareAsString = Res.get("dao.burningman.table.burnAmountShare.capped", cappedBurnAmountShareAsString = Res.get("dao.burningman.table.burnAmountShare.capped",
FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare), FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare),
FormattingUtils.formatToPercentWithSymbol(burnAmountShare)); FormattingUtils.formatToPercentWithSymbol(adjustedBurnAmountShare));
} else { } else {
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare); cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare);
} }