diff --git a/conf/nodes.xml b/conf/nodes.xml index c1de579..e327af1 100644 --- a/conf/nodes.xml +++ b/conf/nodes.xml @@ -13,7 +13,7 @@ MEAT PURCHASE;VEGETABLE PURCHASE;FRUIT PURCHASE - 5 + 10 MEAT SALE_AND_PURCHASE;VEGETABLE SALE_AND_PURCHASE;FRUIT SALE_AND_PURCHASE diff --git a/conf/scenarios.xml b/conf/scenarios.xml index b5434a5..68f28ef 100644 --- a/conf/scenarios.xml +++ b/conf/scenarios.xml @@ -6,18 +6,19 @@ type CDATA #REQUIRED> ]> + generate - generate - generate - generate - generate - generate - generate - generate - generate + sendreq SALE FRUIT jablko \ No newline at end of file diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java index a79add1..0f0b984 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/channel/ChannelBase.java @@ -1,5 +1,6 @@ package cz.cvut.fel.sit.omo.foodchain.channel; +import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; import cz.cvut.fel.sit.omo.foodchain.operation.Transaction; import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import cz.cvut.fel.sit.omo.foodchain.requirement.Requirement; @@ -32,9 +33,9 @@ public abstract class ChannelBase implements Observable { this.productType = ProductType.OTHER; } - public Queue getTransactions() + public Queue getTransactions(NodeBase node) { - return this.transactions; + return this.transactions.stream().filter(t -> t.getNodeReceiver().equals(node)).collect(Collectors.toCollection(LinkedList::new)); } public Queue getCurrentRequirements() diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/factory/ScenarioFactory.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/factory/ScenarioFactory.java index 5282eb9..d52163b 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/factory/ScenarioFactory.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/factory/ScenarioFactory.java @@ -60,8 +60,11 @@ public class ScenarioFactory scenarioStep = new DoActionStep(node, ProductOperationType.valueOf(parts[1]), p); } break; - case "sendreq": - scenarioStep = new SendRequirementStep(node, TransactionType.valueOf(parts[1]), ProductType.valueOf(parts[2]), parts[3], Double.parseDouble(parts[4])); + case "sell": + scenarioStep = new SendRequirementStep(node, TransactionType.SALE, ProductType.valueOf(parts[1]), parts[2], Double.parseDouble(parts[3])); + break; + case "buy": + scenarioStep = new SendRequirementStep(node, TransactionType.PURCHASE, ProductType.valueOf(parts[1]), parts[2]); break; case "pass": scenarioStep = new PassStep(); @@ -75,10 +78,6 @@ public class ScenarioFactory { System.err.println("! Wrong type of enum in ScenarioFactory: " + e); } - catch (Exception e) - { - System.err.println("! Fatal error in ScenarioFactory: " + e); - } return s; } diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java index 73e8b9a..7490577 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/node/base/NodeBase.java @@ -14,6 +14,7 @@ import cz.cvut.fel.sit.omo.foodchain.util.ChannelObserver; import org.javamoney.moneta.Money; import javax.money.MonetaryAmount; +import javax.naming.InsufficientResourcesException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -25,7 +26,7 @@ public class NodeBase implements ChannelObserver { private final List products; private final List refusedTransactions; - private final MonetaryAmount money; + private MonetaryAmount money; protected NodeType allowedSeller; protected NodeType allowedPurchaser; @@ -45,42 +46,64 @@ public class NodeBase implements ChannelObserver { public void sendTransaction(Product product, NodeBase node) { - Transaction transaction = new ProductTransaction(this, node, TransactionType.SALE, product); - - subscribedChannels.keySet().stream() - .filter(ch -> ch.getProductType().equals(product.getProductType())) - .findAny().ifPresent(channel -> channel.addTransaction(transaction)); + try { + Transaction transaction = new ProductTransaction(this, node, TransactionType.SALE, product); + subscribedChannels.keySet().stream() + .filter(ch -> ch.getProductType().equals(product.getProductType())) + .findAny().ifPresent(channel -> channel.addTransaction(transaction)); + } catch (InsufficientResourcesException e) { + e.printStackTrace(); + } } public void sendTransaction(MonetaryAmount amount, NodeBase node, ProductTransaction prevTransaction) { - Transaction transaction = new FinancialTransaction(this, node, TransactionType.PURCHASE, amount, prevTransaction); - - subscribedChannels.keySet().stream() - .filter(ch -> ch.getProductType().equals(prevTransaction.getProduct().getProductType())) - .findAny().ifPresent(channel -> channel.addTransaction(transaction)); + try { + Transaction transaction = new FinancialTransaction(this, node, TransactionType.PURCHASE, amount, prevTransaction); + subscribedChannels.keySet().stream() + .filter(ch -> ch.getProductType().equals(prevTransaction.getProduct().getProductType())) + .findAny().ifPresent(channel -> channel.addTransaction(transaction)); + } catch (InsufficientResourcesException e) { + e.printStackTrace(); + } } + public void receiveTransaction(Transaction transaction) { + try { + receiveTransaction((ProductTransaction) transaction); + } + catch (Exception e) { + try { + receiveTransaction((FinancialTransaction) transaction); + } + catch (Exception ex) { + System.err.println(ex.getMessage()); + } + } + } public void receiveTransaction(ProductTransaction transaction) { + if (validateSignature(transaction)) { + transaction.endTransaction(); + sendTransaction(transaction.getProduct().getPrice(), transaction.getNodeCreator(), transaction); + } + else refuseTransaction(transaction); } - public void receiveTransaction(FinancialTransaction transaction) { - + if (validateSignature(transaction)) transaction.endTransaction(); + else refuseTransaction(transaction); } public void refuseTransaction(Transaction transaction) { transaction.endTransaction(); - refusedTransactions.add(transaction); //TODO maybe need more work on it + refusedTransactions.add(transaction); } - public Transaction readNextTransaction(ChannelBase channel) { - //TODO - return null; -// return channel.getNextTransaction(); + public void receiveTransactions() { + subscribedChannels.keySet().forEach(ch -> ch.getTransactions(this).forEach(t -> {receiveTransaction(t); ch.disposeOf(t);})); } @@ -153,7 +176,11 @@ public class NodeBase implements ChannelObserver { } public void addMoney(MonetaryAmount m) { - this.money.add(m); + this.money = this.money.add(m); + } + + public void subtractMoney(MonetaryAmount m) { + this.money = this.money.subtract(m); } public boolean validateSignature(Transaction transaction) { @@ -194,4 +221,9 @@ public class NodeBase implements ChannelObserver { acceptRequirement(requirement); } } + + public void tick() { + receiveTransactions(); + System.out.println(this.getClass().getSimpleName() + ": " + money.getNumber()); + } } diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/FinancialTransaction.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/FinancialTransaction.java index 4be879b..bbcc732 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/FinancialTransaction.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/FinancialTransaction.java @@ -3,17 +3,20 @@ package cz.cvut.fel.sit.omo.foodchain.operation; import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; import javax.money.MonetaryAmount; +import javax.naming.InsufficientResourcesException; public class FinancialTransaction extends Transaction { private final MonetaryAmount amount; private final ProductTransaction transactionPaid; - public FinancialTransaction(NodeBase creator, NodeBase receiver, TransactionType type, MonetaryAmount amount, ProductTransaction transactionPaid) { + public FinancialTransaction(NodeBase creator, NodeBase receiver, TransactionType type, MonetaryAmount amount, ProductTransaction transactionPaid) throws InsufficientResourcesException { super(creator, receiver, type); this.amount = amount; this.transactionPaid = transactionPaid; - creator.addMoney(amount.negate()); + if (creator.getMoney().isLessThan(amount)) throw new InsufficientResourcesException("not enough money"); + creator.subtractMoney(amount); + System.out.println(toString()); } @Override @@ -29,4 +32,12 @@ public class FinancialTransaction extends Transaction { public ProductTransaction getTransactionPaid() { return transactionPaid; } + + @Override + public String toString() { + return "FinancialTransaction{" + + "amount=" + amount.getNumber() + + ", transactionPaid=" + transactionPaid + + '}'; + } } diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java index 58966de..640ca63 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/operation/ProductTransaction.java @@ -2,6 +2,9 @@ package cz.cvut.fel.sit.omo.foodchain.operation; import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; import cz.cvut.fel.sit.omo.foodchain.product.Product; +import cz.cvut.fel.sit.omo.foodchain.product.ProductState; + +import javax.naming.InsufficientResourcesException; public class ProductTransaction extends Transaction { @@ -9,19 +12,22 @@ public class ProductTransaction extends Transaction { private final Product product; private final ProductOperationType type; - public ProductTransaction(NodeBase creator, NodeBase receiver, TransactionType transactionType, Product product) { + public ProductTransaction(NodeBase creator, NodeBase receiver, TransactionType transactionType, Product product) throws InsufficientResourcesException { super(creator, receiver, transactionType); this.product = product; type = null; lastOperation = product.getCurrentOperation(); + if (product == null || product.getProductState() != ProductState.AVAILABLE) throw new InsufficientResourcesException("product not available"); product.setCurrentOperation(this); product.setStateToReadyForDispatch(); + creator.getStorage().remove(product); System.out.println(toString()); } @Override public void endTransaction() { super.endTransaction(); + getNodeReceiver().storeProduct(product); product.setStateToAvailable(); } diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/requirement/Requirement.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/requirement/Requirement.java index 44f0f20..5e513cf 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/requirement/Requirement.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/requirement/Requirement.java @@ -2,10 +2,12 @@ package cz.cvut.fel.sit.omo.foodchain.requirement; import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; import cz.cvut.fel.sit.omo.foodchain.operation.TransactionType; +import cz.cvut.fel.sit.omo.foodchain.product.ProductState; import cz.cvut.fel.sit.omo.foodchain.product.ProductType; import org.javamoney.moneta.Money; import javax.money.MonetaryAmount; +import javax.naming.InsufficientResourcesException; public class Requirement { diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/SendRequirementStep.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/SendRequirementStep.java index c7bc813..862cc42 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/SendRequirementStep.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/scenario/SendRequirementStep.java @@ -3,20 +3,31 @@ package cz.cvut.fel.sit.omo.foodchain.scenario; import cz.cvut.fel.sit.omo.foodchain.node.base.NodeBase; import cz.cvut.fel.sit.omo.foodchain.operation.TransactionType; import cz.cvut.fel.sit.omo.foodchain.product.ProductType; +import org.javamoney.moneta.Money; + +import javax.money.MonetaryAmount; public class SendRequirementStep extends ScenarioStep { private final NodeBase node; private final TransactionType tType; private final ProductType pType; private final String pName; - private final double pPrice; + private final MonetaryAmount pPrice; - public SendRequirementStep(NodeBase node, TransactionType tType, ProductType pType, String pName, double pPrice) { + public SendRequirementStep(NodeBase node, TransactionType tType, ProductType pType, String pName) { this.node = node; this.tType = tType; this.pType = pType; this.pName = pName; - this.pPrice = pPrice; + this.pPrice = Money.of(0, "USD"); + } + + public SendRequirementStep(NodeBase node, TransactionType tType, ProductType pType, String pName, Double price) { + this.node = node; + this.tType = tType; + this.pType = pType; + this.pName = pName; + this.pPrice = Money.of(price, "USD"); } @Override diff --git a/src/main/java/cz/cvut/fel/sit/omo/foodchain/util/Ticker.java b/src/main/java/cz/cvut/fel/sit/omo/foodchain/util/Ticker.java index 7fbf1c6..7ccf9b7 100644 --- a/src/main/java/cz/cvut/fel/sit/omo/foodchain/util/Ticker.java +++ b/src/main/java/cz/cvut/fel/sit/omo/foodchain/util/Ticker.java @@ -14,12 +14,12 @@ public class Ticker { public static void start() { timer = new Timer(500, actionEvent -> { - System.out.println("tick"); + System.out.println("-----tick-----"); PoolDatabase db = FoodChain.getFactoryManager().getPoolDatabaseInstance(); boolean productBool = db.getProductPoolInstance().findAll().stream().filter(Product::tick).count() == 0; // change duration of action boolean scenarioBool = db.getScenarioPoolInstance().findAll().stream().filter(Scenario::tick).count() == 0; // do next step in scenario boolean channelBool = db.getChannelPoolInstance().findAll().stream().filter(ChannelBase::tick).count() == 0; // change TTL of requirements -// db.getNodePoolInstance().findAll().forEach(n -> n.tick()); // maybe unnecessary + db.getNodePoolInstance().findAll().forEach(n -> n.tick()); // receive transactions if (channelBool && productBool && scenarioBool) stop(); }); timer.start();