From 1c413a97efba80faf08190565d6dea10b559508a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20K=C3=B6nnecke?= <simonkoennecke@gmail.com> Date: Sun, 3 Jul 2016 23:47:54 +0200 Subject: [PATCH] moved SuperVisorAction class, create statistic class and added to wallet, add snapshot (as json files), create new configuration called Statistics, automated communication between wallets over StatisticsWalletConfiguration --- .gitignore | 1 + pom.xml | 7 ++ src/main/java/fucoin/AbstractNode.java | 34 +++++- .../{transaction => }/SuperVisorAction.java | 2 +- .../control/ActionAnnounceWalletCreation.java | 2 +- .../ActionCreateSuperVisorSnapshot.java | 26 +++++ .../control/ActionCreateWalletSnapshot.java | 29 +++++ .../fucoin/actions/join/ServerActionJoin.java | 2 +- .../statistics/ActionInterchangeState.java | 26 +++++ .../transaction/CoordinatorTransaction.java | 1 + .../configurations/AbstractConfiguration.java | 6 +- .../MassWalletConfiguration.java | 2 +- .../StatisticsWalletConfiguration.java | 102 ++++++++++++++++++ .../java/fucoin/gui/SuperVisorGuiControl.java | 6 +- .../fucoin/gui/SuperVisorGuiControlImpl.java | 5 + .../fucoin/supervisor/ActionUpdateQueue.java | 2 +- .../fucoin/supervisor/AmountTableModel.java | 4 +- .../fucoin/supervisor/SuperVisorImpl.java | 15 ++- .../java/fucoin/wallet/AbstractWallet.java | 15 +++ src/main/java/fucoin/wallet/WalletImpl.java | 39 ++++++- .../java/fucoin/wallet/WalletStatistics.java | 65 +++++++++++ 21 files changed, 372 insertions(+), 19 deletions(-) rename src/main/java/fucoin/actions/{transaction => }/SuperVisorAction.java (80%) create mode 100644 src/main/java/fucoin/actions/control/ActionCreateSuperVisorSnapshot.java create mode 100644 src/main/java/fucoin/actions/control/ActionCreateWalletSnapshot.java create mode 100644 src/main/java/fucoin/actions/statistics/ActionInterchangeState.java create mode 100644 src/main/java/fucoin/configurations/StatisticsWalletConfiguration.java create mode 100644 src/main/java/fucoin/wallet/WalletStatistics.java diff --git a/.gitignore b/.gitignore index 064cdbf..02efb3d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ .idea/ *.iml .DS_Store +snapshots \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1a37142..b32c125 100644 --- a/pom.xml +++ b/pom.xml @@ -56,5 +56,12 @@ <artifactId>reflections</artifactId> <version>0.9.10</version> </dependency> + <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> + <dependency> + <groupId>com.google.code.gson</groupId> + <artifactId>gson</artifactId> + <version>2.7</version> + </dependency> + </dependencies> </project> \ No newline at end of file diff --git a/src/main/java/fucoin/AbstractNode.java b/src/main/java/fucoin/AbstractNode.java index 9777980..fb3d50e 100644 --- a/src/main/java/fucoin/AbstractNode.java +++ b/src/main/java/fucoin/AbstractNode.java @@ -3,10 +3,18 @@ package fucoin; import akka.actor.ActorRef; import akka.actor.Address; import akka.actor.UntypedActor; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import fucoin.actions.transaction.ActionGetAmount; import fucoin.wallet.AbstractWallet; +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; import java.io.Serializable; +import java.time.LocalTime; import java.util.HashMap; public abstract class AbstractNode extends UntypedActor implements Serializable { @@ -68,4 +76,28 @@ public abstract class AbstractNode extends UntypedActor implements Serializable public HashMap<String, ActorRef> getKnownNeighbors() { return knownNeighbors; } -} \ No newline at end of file + + public void createDump(String name, String content, LocalTime time) { + String filename = "snapshots/Dump_" + time.getNano() + "_" + name + ".json"; + + try { + File theDir = new File("snapshots"); + + // if the directory does not exist, create it + if (!theDir.exists()) { + theDir.mkdir(); + } + + File myFile = new File(filename); + myFile.createNewFile(); + FileOutputStream fOut = new FileOutputStream(myFile); + OutputStreamWriter myOutWriter = new OutputStreamWriter(fOut); + myOutWriter.append(content); + myOutWriter.close(); + fOut.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } +} + diff --git a/src/main/java/fucoin/actions/transaction/SuperVisorAction.java b/src/main/java/fucoin/actions/SuperVisorAction.java similarity index 80% rename from src/main/java/fucoin/actions/transaction/SuperVisorAction.java rename to src/main/java/fucoin/actions/SuperVisorAction.java index 19e93a8..1cae3ea 100644 --- a/src/main/java/fucoin/actions/transaction/SuperVisorAction.java +++ b/src/main/java/fucoin/actions/SuperVisorAction.java @@ -1,4 +1,4 @@ -package fucoin.actions.transaction; +package fucoin.actions; import fucoin.actions.Action; import fucoin.supervisor.SuperVisorImpl; diff --git a/src/main/java/fucoin/actions/control/ActionAnnounceWalletCreation.java b/src/main/java/fucoin/actions/control/ActionAnnounceWalletCreation.java index ee897f7..205424d 100644 --- a/src/main/java/fucoin/actions/control/ActionAnnounceWalletCreation.java +++ b/src/main/java/fucoin/actions/control/ActionAnnounceWalletCreation.java @@ -2,7 +2,7 @@ package fucoin.actions.control; import akka.actor.ActorRef; import akka.actor.UntypedActorContext; -import fucoin.actions.transaction.SuperVisorAction; +import fucoin.actions.SuperVisorAction; import fucoin.supervisor.SuperVisorImpl; /** diff --git a/src/main/java/fucoin/actions/control/ActionCreateSuperVisorSnapshot.java b/src/main/java/fucoin/actions/control/ActionCreateSuperVisorSnapshot.java new file mode 100644 index 0000000..7bfa9d1 --- /dev/null +++ b/src/main/java/fucoin/actions/control/ActionCreateSuperVisorSnapshot.java @@ -0,0 +1,26 @@ +package fucoin.actions.control; + +import akka.actor.ActorRef; +import akka.actor.UntypedActorContext; +import fucoin.actions.SuperVisorAction; +import fucoin.supervisor.SuperVisorImpl; + +import java.time.LocalTime; + +public class ActionCreateSuperVisorSnapshot extends SuperVisorAction { + /** + * Timestamp for the file name + */ + private final LocalTime time; + + + public ActionCreateSuperVisorSnapshot(LocalTime time) { + this.time = time; + } + + + @Override + protected void onAction(ActorRef sender, ActorRef self, UntypedActorContext context, SuperVisorImpl abstractNode) { + abstractNode.createDump(time); + } +} diff --git a/src/main/java/fucoin/actions/control/ActionCreateWalletSnapshot.java b/src/main/java/fucoin/actions/control/ActionCreateWalletSnapshot.java new file mode 100644 index 0000000..f730419 --- /dev/null +++ b/src/main/java/fucoin/actions/control/ActionCreateWalletSnapshot.java @@ -0,0 +1,29 @@ +package fucoin.actions.control; + +import akka.actor.ActorRef; +import akka.actor.UntypedActorContext; +import com.google.gson.Gson; +import fucoin.actions.ClientAction; +import fucoin.wallet.AbstractWallet; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.OutputStreamWriter; +import java.time.LocalTime; + +public class ActionCreateWalletSnapshot extends ClientAction { + /** + * Timestamp for the file name + */ + private final LocalTime time; + + + public ActionCreateWalletSnapshot(LocalTime time) { + this.time = time; + } + + @Override + protected void onAction(ActorRef sender, ActorRef self, UntypedActorContext context, AbstractWallet abstractNode) { + abstractNode.createDump(time); + } +} diff --git a/src/main/java/fucoin/actions/join/ServerActionJoin.java b/src/main/java/fucoin/actions/join/ServerActionJoin.java index 18a1cf6..f203170 100644 --- a/src/main/java/fucoin/actions/join/ServerActionJoin.java +++ b/src/main/java/fucoin/actions/join/ServerActionJoin.java @@ -3,7 +3,7 @@ package fucoin.actions.join; import akka.actor.ActorRef; import akka.actor.UntypedActorContext; import fucoin.actions.transaction.ActionInvokeDistributedCommittedTransfer; -import fucoin.actions.transaction.SuperVisorAction; +import fucoin.actions.SuperVisorAction; import fucoin.supervisor.SuperVisorImpl; /** diff --git a/src/main/java/fucoin/actions/statistics/ActionInterchangeState.java b/src/main/java/fucoin/actions/statistics/ActionInterchangeState.java new file mode 100644 index 0000000..8d06ab5 --- /dev/null +++ b/src/main/java/fucoin/actions/statistics/ActionInterchangeState.java @@ -0,0 +1,26 @@ +package fucoin.actions.statistics; + +import akka.actor.ActorRef; +import akka.actor.UntypedActorContext; +import fucoin.actions.ClientAction; +import fucoin.wallet.AbstractWallet; +import fucoin.wallet.WalletStatistics; + +/** + * Wallet A sends a Wallet B current Amount and statistic's. + * Wallet B updates his statistic's. + * @see WalletStatistics + */ +public class ActionInterchangeState extends ClientAction { + + private final int currentAmount; + + public ActionInterchangeState(int currentAmount) { + this.currentAmount = currentAmount; + } + + @Override + protected void onAction(ActorRef sender, ActorRef self, UntypedActorContext context, AbstractWallet abstractNode) { + abstractNode.getStatistics().update(currentAmount); + } +} diff --git a/src/main/java/fucoin/actions/transaction/CoordinatorTransaction.java b/src/main/java/fucoin/actions/transaction/CoordinatorTransaction.java index b28dc56..d9844e0 100644 --- a/src/main/java/fucoin/actions/transaction/CoordinatorTransaction.java +++ b/src/main/java/fucoin/actions/transaction/CoordinatorTransaction.java @@ -2,6 +2,7 @@ package fucoin.actions.transaction; import akka.actor.ActorRef; import akka.actor.UntypedActorContext; +import fucoin.actions.SuperVisorAction; import fucoin.supervisor.SuperVisorImpl; public abstract class CoordinatorTransaction extends SuperVisorAction { diff --git a/src/main/java/fucoin/configurations/AbstractConfiguration.java b/src/main/java/fucoin/configurations/AbstractConfiguration.java index 8493704..8fb57e7 100644 --- a/src/main/java/fucoin/configurations/AbstractConfiguration.java +++ b/src/main/java/fucoin/configurations/AbstractConfiguration.java @@ -28,11 +28,11 @@ import java.util.concurrent.ThreadLocalRandom; */ public abstract class AbstractConfiguration extends AbstractNode { - private ActorRef superVisor; + protected ActorRef superVisor; - private final List<ActorRef> activeActors = new ArrayList<>(); + protected final List<ActorRef> activeActors = new ArrayList<>(); - private Timeout timeout = new Timeout(Duration.create(10, "seconds")); + protected Timeout timeout = new Timeout(Duration.create(10, "seconds")); private int remainingTransactions; diff --git a/src/main/java/fucoin/configurations/MassWalletConfiguration.java b/src/main/java/fucoin/configurations/MassWalletConfiguration.java index fcaaadf..b0f222f 100644 --- a/src/main/java/fucoin/configurations/MassWalletConfiguration.java +++ b/src/main/java/fucoin/configurations/MassWalletConfiguration.java @@ -11,7 +11,7 @@ public class MassWalletConfiguration extends AbstractConfiguration { public void run() { initSupervisor(); try { - spawnWallets(200, false); + spawnWallets(20, false); System.out.println("Wallet spawning done!"); } catch (Exception e) { System.out.println("Wallet spawning timed out!"); diff --git a/src/main/java/fucoin/configurations/StatisticsWalletConfiguration.java b/src/main/java/fucoin/configurations/StatisticsWalletConfiguration.java new file mode 100644 index 0000000..5a5fc7c --- /dev/null +++ b/src/main/java/fucoin/configurations/StatisticsWalletConfiguration.java @@ -0,0 +1,102 @@ +package fucoin.configurations; + +import akka.actor.ActorRef; +import akka.pattern.Patterns; +import fucoin.actions.control.ActionCreateSuperVisorSnapshot; +import fucoin.actions.control.ActionCreateWalletSnapshot; +import fucoin.actions.statistics.ActionInterchangeState; +import fucoin.actions.transaction.ActionGetAmount; +import fucoin.actions.transaction.ActionGetAmountAnswer; +import fucoin.configurations.internal.ConfigurationName; +import scala.concurrent.Await; +import scala.concurrent.Future; + +import java.time.LocalTime; +import java.util.Collections; +import java.util.List; + +/** + * This configuration spawns 200 wallets to demonstrate the spawning of many headless wallets + */ +@ConfigurationName("Statistics") +public class StatisticsWalletConfiguration extends AbstractConfiguration { + /** + * Spawn the number of wallets. + */ + private final static int sNumberOfWallets = 10; + + private int numberOfInterchangeStatistic = 20; + + @Override + public void run() { + initSupervisor(); + try { + spawnWallets(sNumberOfWallets, false); + System.out.println("Wallet spawning done!"); + } catch (Exception e) { + System.out.println("Wallet spawning timed out!"); + } + + randomTransactions(10, 10); + + try { + //Busy wait + while (activeActors.size() < sNumberOfWallets) { + + } + try { + Thread.sleep(4000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + System.out.println("=========== Stats runs"); + interchangeStatistic(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void interchangeStatistic() throws Exception { + if (!(numberOfInterchangeStatistic > 0)) { + //stop interchange statistics + return; + } + + List<ActorRef> wallets = wallets(); + Collections.shuffle(wallets); + + ActorRef sender = wallets.get(0); + ActorRef recipient = wallets.get(1); + + Future<Object> future = Patterns.ask(sender, new ActionGetAmount(), timeout); + ActionGetAmountAnswer answer = (ActionGetAmountAnswer) Await.result(future, timeout.duration()); + + recipient.tell(new ActionInterchangeState(answer.amount), sender); + + numberOfInterchangeStatistic--; + if (numberOfInterchangeStatistic == 0) { + createDump(); + } else { + interchangeStatistic(); + } + } + + /** + * Create a Dump of the SuperVisor and all active Wallets. + */ + private void createDump() { + System.out.println("Create Dumps"); + LocalTime time = LocalTime.now(); + superVisor.tell(new ActionCreateSuperVisorSnapshot(time), superVisor); + for (ActorRef wallet: activeActors) { + wallet.tell(new ActionCreateWalletSnapshot(time), wallet); + } + } + + @Override + public void onReceive(Object message) { + super.onReceive(message); + } + + +} diff --git a/src/main/java/fucoin/gui/SuperVisorGuiControl.java b/src/main/java/fucoin/gui/SuperVisorGuiControl.java index b8b29e5..9c2fbef 100644 --- a/src/main/java/fucoin/gui/SuperVisorGuiControl.java +++ b/src/main/java/fucoin/gui/SuperVisorGuiControl.java @@ -1,5 +1,7 @@ package fucoin.gui; +import fucoin.supervisor.AmountTableModel; + public interface SuperVisorGuiControl extends TransactionLogger { /** @@ -7,6 +9,8 @@ public interface SuperVisorGuiControl extends TransactionLogger { */ void onLeave(); - public void updateTable(String address, String name, int amount); + void updateTable(String address, String name, int amount); + + AmountTableModel getTable(); } diff --git a/src/main/java/fucoin/gui/SuperVisorGuiControlImpl.java b/src/main/java/fucoin/gui/SuperVisorGuiControlImpl.java index b0c9a12..f5d75e4 100644 --- a/src/main/java/fucoin/gui/SuperVisorGuiControlImpl.java +++ b/src/main/java/fucoin/gui/SuperVisorGuiControlImpl.java @@ -48,6 +48,11 @@ public class SuperVisorGuiControlImpl implements SuperVisorGuiControl { this.amountTableModel.updateTable(address, name, amount); } + @Override + public AmountTableModel getTable() { + return this.amountTableModel; + } + private void log(LogMessage logMessage) { if (logActive) { threadGUI.log(logMessage); diff --git a/src/main/java/fucoin/supervisor/ActionUpdateQueue.java b/src/main/java/fucoin/supervisor/ActionUpdateQueue.java index e15ce4b..81ac1a5 100644 --- a/src/main/java/fucoin/supervisor/ActionUpdateQueue.java +++ b/src/main/java/fucoin/supervisor/ActionUpdateQueue.java @@ -3,7 +3,7 @@ package fucoin.supervisor; import akka.actor.ActorRef; import akka.actor.UntypedActorContext; import fucoin.actions.transaction.ActionCommitDistributedCommittedTransfer; -import fucoin.actions.transaction.SuperVisorAction; +import fucoin.actions.SuperVisorAction; import java.util.List; diff --git a/src/main/java/fucoin/supervisor/AmountTableModel.java b/src/main/java/fucoin/supervisor/AmountTableModel.java index 80378e9..8ed4172 100644 --- a/src/main/java/fucoin/supervisor/AmountTableModel.java +++ b/src/main/java/fucoin/supervisor/AmountTableModel.java @@ -1,10 +1,10 @@ package fucoin.supervisor; -import javax.swing.*; import javax.swing.table.DefaultTableModel; +import java.io.Serializable; import java.util.Vector; -public class AmountTableModel extends DefaultTableModel { +public class AmountTableModel extends DefaultTableModel implements Serializable { public AmountTableModel() { super(new Object[]{"Address", "Name", "Amount"}, 0); diff --git a/src/main/java/fucoin/supervisor/SuperVisorImpl.java b/src/main/java/fucoin/supervisor/SuperVisorImpl.java index 8b4ec17..9b9778b 100644 --- a/src/main/java/fucoin/supervisor/SuperVisorImpl.java +++ b/src/main/java/fucoin/supervisor/SuperVisorImpl.java @@ -2,17 +2,19 @@ package fucoin.supervisor; import akka.actor.ActorRef; import akka.actor.Props; +import com.google.gson.Gson; import fucoin.actions.Action; import fucoin.actions.control.ActionWalletCreationDone; import fucoin.actions.persist.ActionInvokeUpdate; import fucoin.actions.transaction.ActionGetAmountAnswer; import fucoin.actions.transaction.ActionNotifyObserver; -import fucoin.actions.transaction.SuperVisorAction; +import fucoin.actions.SuperVisorAction; import fucoin.gui.SuperVisorGuiControl; import fucoin.AbstractNode; import fucoin.gui.TransactionLogger; import javax.swing.*; +import java.time.LocalTime; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -23,12 +25,12 @@ public class SuperVisorImpl extends AbstractNode implements TransactionLogger { //private AmountTableModel amountTableModel; - private Map<Long, DistributedCommittedTransferRequest> requestQueue; + private transient Map<Long, DistributedCommittedTransferRequest> requestQueue; - private SuperVisorGuiControl gui; + private transient SuperVisorGuiControl gui; private int pendingBankCommits = 0; - private ActorRef bankCommitObserver = null; + private transient ActorRef bankCommitObserver = null; public SuperVisorImpl() { @@ -167,4 +169,9 @@ public class SuperVisorImpl extends AbstractNode implements TransactionLogger { public void setBankCommitObserver(ActorRef bankCommitObserver) { this.bankCommitObserver = bankCommitObserver; } + + public void createDump(LocalTime time) { + String str = new Gson().toJson(this.gui.getTable()); + super.createDump("SuperVisor", str, time); + } } diff --git a/src/main/java/fucoin/wallet/AbstractWallet.java b/src/main/java/fucoin/wallet/AbstractWallet.java index 882c2a5..ec1e0ae 100644 --- a/src/main/java/fucoin/wallet/AbstractWallet.java +++ b/src/main/java/fucoin/wallet/AbstractWallet.java @@ -6,12 +6,17 @@ import fucoin.gui.TransactionLogger; import scala.concurrent.Future; import java.io.Serializable; +import java.time.LocalTime; /** * */ public abstract class AbstractWallet extends AbstractNode implements Serializable, TransactionLogger { + /** + * + */ + protected WalletStatistics statistics = new WalletStatistics(); /** * Currently amount of this wallet */ @@ -77,6 +82,14 @@ public abstract class AbstractWallet extends AbstractNode implements Serializabl */ public abstract void setActive(boolean isActive); + public WalletStatistics getStatistics() { + return statistics; + } + + public void setStatistics(WalletStatistics statistics) { + this.statistics = statistics; + } + /** * Returns the * @@ -114,4 +127,6 @@ public abstract class AbstractWallet extends AbstractNode implements Serializabl * @param observer */ public abstract void send(String address, int amount, ActorRef observer); + + public abstract void createDump(LocalTime time); } diff --git a/src/main/java/fucoin/wallet/WalletImpl.java b/src/main/java/fucoin/wallet/WalletImpl.java index 951a151..f25e0a0 100644 --- a/src/main/java/fucoin/wallet/WalletImpl.java +++ b/src/main/java/fucoin/wallet/WalletImpl.java @@ -2,6 +2,10 @@ package fucoin.wallet; import akka.actor.ActorRef; import akka.actor.Props; +import com.google.gson.ExclusionStrategy; +import com.google.gson.FieldAttributes; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import fucoin.actions.ClientAction; import fucoin.actions.join.ActionJoin; import fucoin.actions.join.ActionJoinAnswer; @@ -16,16 +20,17 @@ import scala.concurrent.Future; import static akka.dispatch.Futures.future; +import java.time.LocalTime; import java.util.concurrent.ConcurrentLinkedQueue; public class WalletImpl extends AbstractWallet { - private ActorRef preKnownNeighbour; - private ActorRef remoteSuperVisorActor; + private transient ActorRef preKnownNeighbour; + private transient ActorRef remoteSuperVisorActor; private transient WalletGuiControl gui; private String preKnownNeighbourName; private boolean isActive; - private ConcurrentLinkedQueue<ActorRef> deferedSupervisorReceivers = new ConcurrentLinkedQueue<>(); + private transient ConcurrentLinkedQueue<ActorRef> deferedSupervisorReceivers = new ConcurrentLinkedQueue<>(); public WalletImpl(String name) { super(name); @@ -245,4 +250,32 @@ public class WalletImpl extends AbstractWallet { System.out.println(message); } } + + public void createDump(LocalTime time){ + Gson gson = new GsonBuilder() + .setExclusionStrategies(new ExcludeAttributes()) + //.serializeNulls() <-- uncomment to serialize NULL fields as well + .create(); + String s = gson.toJson(this); + super.createDump(getName(), s, time); + } + + class ExcludeAttributes implements ExclusionStrategy { + + public boolean shouldSkipClass(Class<?> arg0) { + return false; + } + + public boolean shouldSkipField(FieldAttributes f) { + + return !(f.getName().equals("statistics") || + f.getName().equals("min") || + f.getName().equals("max") || + f.getName().equals("sum") || + f.getName().equals("count") || + f.getName().equals("amount") || + f.getName().equals("name")); + } + + } } diff --git a/src/main/java/fucoin/wallet/WalletStatistics.java b/src/main/java/fucoin/wallet/WalletStatistics.java new file mode 100644 index 0000000..833fa21 --- /dev/null +++ b/src/main/java/fucoin/wallet/WalletStatistics.java @@ -0,0 +1,65 @@ +package fucoin.wallet; + +import java.io.Serializable; + +/** + * + */ +public class WalletStatistics implements Serializable { + private int min; + private int max; + private int sum; + private int count; + + public WalletStatistics() { + this.min = Integer.MAX_VALUE; + this.max = Integer.MIN_VALUE; + this.sum = 0; + this.count = 0; + } + + public WalletStatistics(int min, int max, int sum, int count) { + this.min = min; + this.max = max; + this.sum = sum; + this.count = count; + } + + public void update(int currentWalletAmount) { + setMin(currentWalletAmount); + setMax(currentWalletAmount); + setSum(currentWalletAmount); + } + + public int getMin() { + return min; + } + + public void setMin(int min) { + this.min = Math.min(this.min, min); + } + + public int getMax() { + return max; + } + + public void setMax(int max) { + this.max = Math.max(this.max, max); + } + + public int getSum() { + return sum; + } + + public void setSum(int sum) { + this.sum = (this.sum + sum) / 2; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = (this.count + count) / 2; + } +} -- GitLab