Skip to content

Commit

Permalink
Merge pull request bisq-network#2753 from HenrikJannsen/Add-age-based…
Browse files Browse the repository at this point in the history
…-boost-factor-to-all-repuation-sources

Add age based boost factor to all repuation sources
  • Loading branch information
HenrikJannsen authored Sep 3, 2024
2 parents 87e4279 + eaccf81 commit 89e0ecd
Show file tree
Hide file tree
Showing 14 changed files with 225 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@

package bisq.desktop.main.content.bisq_easy.components;

import bisq.bisq_easy.BisqEasyTradeAmountLimits;
import bisq.common.currency.FiatCurrencyRepository;
import bisq.common.currency.Market;
import bisq.common.currency.MarketRepository;
import bisq.common.monetary.Coin;
import bisq.common.monetary.Fiat;
import bisq.common.monetary.Monetary;
import bisq.common.monetary.PriceQuote;
Expand Down Expand Up @@ -54,9 +54,6 @@

@Slf4j
public class AmountComponent {
public static final Coin MIN_RANGE_BASE_SIDE_VALUE = Coin.asBtcFromValue(10000);
public static final Coin MAX_RANGE_BASE_SIDE_VALUE = Coin.asBtcFromValue(1000000);

private final Controller controller;

public AmountComponent(ServiceProvider serviceProvider,
Expand Down Expand Up @@ -455,9 +452,9 @@ private static class Model implements bisq.desktop.common.view.Model {
private final BooleanProperty sliderFocus = new SimpleBooleanProperty();

@Setter
private ObjectProperty<Monetary> minRangeMonetary = new SimpleObjectProperty<>(MIN_RANGE_BASE_SIDE_VALUE);
private ObjectProperty<Monetary> minRangeMonetary = new SimpleObjectProperty<>(BisqEasyTradeAmountLimits.DEFAULT_MIN_BTC_TRADE_AMOUNT);
@Setter
private ObjectProperty<Monetary> maxRangeMonetary = new SimpleObjectProperty<>(MAX_RANGE_BASE_SIDE_VALUE);
private ObjectProperty<Monetary> maxRangeMonetary = new SimpleObjectProperty<>(BisqEasyTradeAmountLimits.DEFAULT_MAX_BTC_TRADE_AMOUNT);
@Setter
private ObjectProperty<Monetary> minRangeBaseSideValue = new SimpleObjectProperty<>();
@Setter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import bisq.account.payment_method.BitcoinPaymentMethod;
import bisq.account.payment_method.FiatPaymentMethod;
import bisq.bisq_easy.BisqEasyService;
import bisq.bisq_easy.BisqEasyTradeAmountLimits;
import bisq.bonded_roles.market_price.MarketPriceService;
import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookChannel;
import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookChannelService;
Expand Down Expand Up @@ -53,6 +54,7 @@
import bisq.user.identity.UserIdentityService;
import bisq.user.profile.UserProfile;
import bisq.user.profile.UserProfileService;
import bisq.user.reputation.ReputationScore;
import bisq.user.reputation.ReputationService;
import javafx.beans.property.ReadOnlyBooleanProperty;
import javafx.beans.property.ReadOnlyObjectProperty;
Expand Down Expand Up @@ -132,6 +134,7 @@ public void setMarket(Market market) {
minAmountComponent.setMarket(market);
maxOrFixAmountComponent.setMarket(market);
model.setMarket(market);
applyMinMaxRange();
}

public void setBitcoinPaymentMethods(List<BitcoinPaymentMethod> bitcoinPaymentMethods) {
Expand Down Expand Up @@ -231,6 +234,8 @@ public ReadOnlyBooleanProperty getIsMinAmountEnabled() {

@Override
public void onActivate() {
applyMinMaxRange();

if (model.getPriceQuote().get() == null && minAmountComponent.getQuote().get() != null) {
model.getPriceQuote().set(minAmountComponent.getQuote().get());
}
Expand Down Expand Up @@ -485,4 +490,21 @@ private boolean filterOffers(BisqEasyOffer peersOffer) {
private Optional<PriceQuote> getMarketPriceQuote() {
return marketPriceService.findMarketPriceQuote(model.getMarket());
}

private void applyMinMaxRange() {
String myProfileId = userIdentityService.getSelectedUserIdentity().getUserProfile().getId();
ReputationScore myReputationScore = reputationService.getReputationScore(myProfileId);
BisqEasyTradeAmountLimits.getMinQuoteSideTradeAmount(marketPriceService, model.getMarket()).ifPresent(minRangeValue -> {
if (model.getDirection().isBuy()) {
Monetary maxRangeValue = BisqEasyTradeAmountLimits.MAX_USD_TRADE_AMOUNT;
minAmountComponent.setMinMaxRange(minRangeValue, maxRangeValue);
maxOrFixAmountComponent.setMinMaxRange(minRangeValue, maxRangeValue);
} else {
BisqEasyTradeAmountLimits.getMaxQuoteSideTradeAmount(marketPriceService, model.getMarket(), myReputationScore).ifPresent(maxRangeValue -> {
minAmountComponent.setMinMaxRange(minRangeValue, maxRangeValue);
maxOrFixAmountComponent.setMinMaxRange(minRangeValue, maxRangeValue);
});
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
import bisq.chat.reactions.*;
import bisq.chat.two_party.TwoPartyPrivateChatChannel;
import bisq.chat.two_party.TwoPartyPrivateChatMessage;
import bisq.common.application.DevMode;
import bisq.common.observable.Pin;
import bisq.common.observable.collection.CollectionObserver;
import bisq.desktop.ServiceProvider;
Expand Down Expand Up @@ -283,11 +282,11 @@ public void onTakeOffer(BisqEasyOfferbookMessage bisqEasyOfferbookMessage) {
return;
}

if (!(DevMode.isDevMode() || BisqEasyServiceUtil.offerMatchesMinRequiredReputationScore(reputationService,
if (!BisqEasyServiceUtil.offerMatchesMinRequiredReputationScore(reputationService,
bisqEasyService,
userIdentityService,
userProfileService,
bisqEasyOffer))) {
bisqEasyOffer)) {
if (bisqEasyOffer.getDirection().isSell()) {
long makerAsSellersScore = userProfileService.findUserProfile(bisqEasyOffer.getMakersUserProfileId())
.map(reputationService::getReputationScore)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ protected void onViewAttached() {
closeButton.setOnAction(e -> controller.onClose());

root.setPrefWidth(OverlayModel.WIDTH);
root.setPrefHeight(OverlayModel.HEIGHT + 80);
root.setPrefHeight(OverlayModel.HEIGHT + 110);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,25 @@

import bisq.common.util.MathUtils;
import bisq.desktop.components.controls.MaterialTextField;
import bisq.desktop.main.content.reputation.build_reputation.components.AgeSlider;
import bisq.i18n.Res;
import bisq.presentation.parser.DoubleParser;
import bisq.user.reputation.BondedReputationService;
import bisq.user.reputation.ProofOfBurnService;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription;

import java.util.concurrent.TimeUnit;

public class BondScoreSimulation {

private final Controller controller;
Expand All @@ -48,45 +55,66 @@ public static class Controller implements bisq.desktop.common.view.Controller {
@Getter
private final View view;
private final Model model;
private Subscription scorePin;
private Subscription agePin, ageAsStringPin, amountPin;

private Controller() {
model = new Model();
view = new View(model, this);

model.getAmount().set("100");
model.getAge().set(0);
model.getAgeAsString().set("0");
}

@Override
public void onActivate() {
scorePin = EasyBind.subscribe(model.getAmount(), amount -> model.getScore().set(calculateSimScore(amount)));
agePin = EasyBind.subscribe(model.getAge(), age -> model.getAgeAsString().set(String.valueOf(age)));
ageAsStringPin = EasyBind.subscribe(model.getAgeAsString(), ageAsString -> {
try {
model.getAge().set(Integer.parseInt(ageAsString));
calculateSimScore();
} catch (Exception e) {
}
});
amountPin = EasyBind.subscribe(model.getAmount(), amount -> calculateSimScore());
}

@Override
public void onDeactivate() {
scorePin.unsubscribe();
agePin.unsubscribe();
ageAsStringPin.unsubscribe();
amountPin.unsubscribe();
}

private String calculateSimScore(String value) {
private void calculateSimScore() {
try {
// amountAsLong is the smallest unit of BSQ (100 = 1 BSQ)
long amountAsLong = Math.max(0, MathUtils.roundDoubleToLong(DoubleParser.parse(value) * 100));
long totalScore = BondedReputationService.doCalculateScore(amountAsLong);
return String.valueOf(totalScore);
long amountAsLong = Math.max(0, MathUtils.roundDoubleToLong(DoubleParser.parse(model.getAmount().get()) * 100));
long ageInDays = Math.max(0, model.getAge().get());
long age = TimeUnit.DAYS.toMillis(ageInDays);
long blockTime = System.currentTimeMillis() - age;
long totalScore = BondedReputationService.doCalculateScore(amountAsLong, blockTime);
String score = String.valueOf(totalScore);
model.getScore().set(score);
} catch (Exception e) {
return "";
log.error("Failed to calculate simScore", e);
}
}
}

@Getter
private static class Model implements bisq.desktop.common.view.Model {
private final StringProperty amount = new SimpleStringProperty();
private final IntegerProperty age = new SimpleIntegerProperty();
private final StringProperty ageAsString = new SimpleStringProperty();
private final StringProperty score = new SimpleStringProperty();
}

private static class View extends bisq.desktop.common.view.View<VBox, Model, Controller> {
private final MaterialTextField amount, score;
private final MaterialTextField amount;
private final MaterialTextField score;
private final AgeSlider simAgeSlider;
private final MaterialTextField ageField;

private View(Model model,
Controller controller) {
Expand All @@ -95,23 +123,29 @@ private View(Model model,
Label simHeadline = new Label(Res.get("reputation.sim.headline"));
simHeadline.getStyleClass().addAll("bisq-text-1");
amount = getInputField("reputation.sim.burnAmount");
int width = 380;
amount.setMinWidth(width);
amount.setMaxWidth(width);
score = getField(Res.get("reputation.sim.score"));
ageField = getInputField("reputation.sim.age");
simAgeSlider = new AgeSlider(0, ProofOfBurnService.MAX_AGE_BOOST_DAYS, 0);
VBox.setMargin(simAgeSlider.getView().getRoot(), new Insets(15, 0, 0, 0));
root.getChildren().addAll(simHeadline,
amount,
ageField,
simAgeSlider.getView().getRoot(),
score);
}

@Override
protected void onViewAttached() {
simAgeSlider.valueProperty().bindBidirectional(model.getAge());
ageField.textProperty().bindBidirectional(model.getAgeAsString());
amount.textProperty().bindBidirectional(model.getAmount());
score.textProperty().bind(model.getScore());
}

@Override
protected void onViewDetached() {
simAgeSlider.valueProperty().unbindBidirectional(model.getAge());
ageField.textProperty().unbindBidirectional(model.getAgeAsString());
amount.textProperty().unbindBidirectional(model.getAmount());
score.textProperty().unbind();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ protected void onViewAttached() {
closeButton.setOnAction(e -> controller.onClose());

root.setPrefWidth(OverlayModel.WIDTH);
root.setPrefHeight(OverlayModel.HEIGHT + 60);
root.setPrefHeight(OverlayModel.HEIGHT + 110);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,24 @@

import bisq.common.util.MathUtils;
import bisq.desktop.components.controls.MaterialTextField;
import bisq.desktop.main.content.reputation.build_reputation.components.AgeSlider;
import bisq.i18n.Res;
import bisq.presentation.parser.DoubleParser;
import bisq.user.reputation.ProofOfBurnService;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.geometry.Insets;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription;

import java.util.concurrent.TimeUnit;

public class BurnScoreSimulation {

private final Controller controller;
Expand All @@ -48,46 +54,66 @@ public static class Controller implements bisq.desktop.common.view.Controller {
@Getter
private final View view;
private final Model model;
private Subscription scorePin;
private Subscription agePin, ageAsStringPin, amountPin;

private Controller() {
model = new Model();
view = new View(model, this);

model.getAmount().set("100");
model.getAge().set(0);
model.getAgeAsString().set("0");
}

@Override
public void onActivate() {
scorePin = EasyBind.subscribe(model.getAmount(), amount -> model.getScore().set(calculateSimScore(amount)));
agePin = EasyBind.subscribe(model.getAge(), age -> model.getAgeAsString().set(String.valueOf(age)));
ageAsStringPin = EasyBind.subscribe(model.getAgeAsString(), ageAsString -> {
try {
model.getAge().set(Integer.parseInt(ageAsString));
calculateSimScore();
} catch (Exception e) {
}
});
amountPin = EasyBind.subscribe(model.getAmount(), amount -> calculateSimScore());
}

@Override
public void onDeactivate() {
scorePin.unsubscribe();
agePin.unsubscribe();
ageAsStringPin.unsubscribe();
amountPin.unsubscribe();
}

private String calculateSimScore(String value) {
private void calculateSimScore() {
try {
// amountAsLong is the smallest unit of BSQ (100 = 1 BSQ)
long amountAsLong = Math.max(0, MathUtils.roundDoubleToLong(DoubleParser.parse(value) * 100));
long totalScore = ProofOfBurnService.doCalculateScore(amountAsLong);
return String.valueOf(totalScore);
long amountAsLong = Math.max(0, MathUtils.roundDoubleToLong(DoubleParser.parse(model.getAmount().get()) * 100));
long ageInDays = Math.max(0, model.getAge().get());
long age = TimeUnit.DAYS.toMillis(ageInDays);
long blockTime = System.currentTimeMillis() - age;
long totalScore = ProofOfBurnService.doCalculateScore(amountAsLong, blockTime);
String score = String.valueOf(totalScore);
model.getScore().set(score);
} catch (Exception e) {
return "";
log.error("Failed to calculate simScore", e);
}
}
}

@Getter
private static class Model implements bisq.desktop.common.view.Model {
private final StringProperty amount = new SimpleStringProperty();
private final IntegerProperty age = new SimpleIntegerProperty();
private final StringProperty ageAsString = new SimpleStringProperty();
private final StringProperty score = new SimpleStringProperty();
}

private static class View extends bisq.desktop.common.view.View<VBox, Model, Controller> {
private final MaterialTextField amount;
private final MaterialTextField score;
private final AgeSlider simAgeSlider;
private final MaterialTextField ageField;

private View(Model model,
Controller controller) {
Expand All @@ -97,19 +123,28 @@ private View(Model model,
simHeadline.getStyleClass().addAll("bisq-text-1");
amount = getInputField("reputation.sim.burnAmount");
score = getField(Res.get("reputation.sim.score"));
ageField = getInputField("reputation.sim.age");
simAgeSlider = new AgeSlider(0, ProofOfBurnService.MAX_AGE_BOOST_DAYS, 0);
VBox.setMargin(simAgeSlider.getView().getRoot(), new Insets(15, 0, 0, 0));
root.getChildren().addAll(simHeadline,
amount,
ageField,
simAgeSlider.getView().getRoot(),
score);
}

@Override
protected void onViewAttached() {
simAgeSlider.valueProperty().bindBidirectional(model.getAge());
ageField.textProperty().bindBidirectional(model.getAgeAsString());
amount.textProperty().bindBidirectional(model.getAmount());
score.textProperty().bind(model.getScore());
}

@Override
protected void onViewDetached() {
simAgeSlider.valueProperty().unbindBidirectional(model.getAge());
ageField.textProperty().unbindBidirectional(model.getAgeAsString());
amount.textProperty().unbindBidirectional(model.getAmount());
score.textProperty().unbind();
}
Expand All @@ -129,4 +164,4 @@ private MaterialTextField getInputField(String key) {
return field;
}
}
}
}
Loading

0 comments on commit 89e0ecd

Please sign in to comment.