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)
.sum();
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;
}

View File

@ -52,8 +52,13 @@ public class BurningManCandidate {
private final Map<Date, Set<BurnOutputModel>> burnOutputModelsByMonth = new HashMap<>();
private long accumulatedBurnAmount;
private long accumulatedDecayedBurnAmount;
protected double burnAmountShare; // Share of accumulated decayed burn amounts in relation to total burned amounts
protected double cappedBurnAmountShare; // Capped burnAmountShare. Cannot be larger than boostedCompensationShare
// Share of accumulated decayed burn amounts in relation to total burned amounts
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() {
}
@ -93,11 +98,42 @@ public class BurningManCandidate {
public void calculateShares(double totalDecayedCompensationAmounts, double totalDecayedBurnAmounts) {
compensationShare = totalDecayedCompensationAmounts > 0 ? accumulatedDecayedCompensationAmount / totalDecayedCompensationAmounts : 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() {
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 burnAmountShare=" + burnAmountShare +
",\r\n cappedBurnAmountShare=" + cappedBurnAmountShare +
",\r\n adjustedBurnAmountShare=" + adjustedBurnAmountShare +
"\r\n}";
}
}

View File

@ -39,7 +39,7 @@ class BurningManListItem {
private final long burnTarget, maxBurnTarget, accumulatedDecayedBurnAmount, accumulatedBurnAmount,
accumulatedDecayedCompensationAmount, accumulatedCompensationAmount, expectedRevenue;
private final int numBurnOutputs, numIssuances;
private final double cappedBurnAmountShare, burnAmountShare, compensationShare;
private final double cappedBurnAmountShare, adjustedBurnAmountShare, compensationShare;
BurningManListItem(BurningManPresentationService burningManPresentationService,
String name,
@ -60,14 +60,14 @@ class BurningManListItem {
accumulatedDecayedBurnAmount = 0;
accumulatedDecayedBurnAmountAsBsq = "";
burnAmountShare = burningManCandidate.getBurnAmountShare();
adjustedBurnAmountShare = burningManCandidate.getAdjustedBurnAmountShare();
cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare();
// 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)) {
expectedRevenue = burningManPresentationService.getExpectedRevenue(burningManCandidate);
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(burnAmountShare);
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(adjustedBurnAmountShare);
} else {
expectedRevenue = 0;
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(0);
@ -94,12 +94,12 @@ class BurningManListItem {
accumulatedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedBurnAmount);
accumulatedDecayedBurnAmount = burningManCandidate.getAccumulatedDecayedBurnAmount();
accumulatedDecayedBurnAmountAsBsq = bsqFormatter.formatCoinWithCode(accumulatedDecayedBurnAmount);
burnAmountShare = burningManCandidate.getBurnAmountShare();
adjustedBurnAmountShare = burningManCandidate.getAdjustedBurnAmountShare();
cappedBurnAmountShare = burningManCandidate.getCappedBurnAmountShare();
if (burnAmountShare != cappedBurnAmountShare) {
if (adjustedBurnAmountShare != cappedBurnAmountShare) {
cappedBurnAmountShareAsString = Res.get("dao.burningman.table.burnAmountShare.capped",
FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare),
FormattingUtils.formatToPercentWithSymbol(burnAmountShare));
FormattingUtils.formatToPercentWithSymbol(adjustedBurnAmountShare));
} else {
cappedBurnAmountShareAsString = FormattingUtils.formatToPercentWithSymbol(cappedBurnAmountShare);
}