diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/LotteryApp.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/LotteryApp.java index e2cd46c..06b8c42 100644 --- a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/LotteryApp.java +++ b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/LotteryApp.java @@ -1,13 +1,64 @@ package com.fluxtion.example.cookbook.lottery; -import com.fluxtion.compiler.Fluxtion; -import com.fluxtion.example.cookbook.lottery.nodes.LotteryGameNode; -import com.fluxtion.runtime.EventProcessor; +import com.fluxtion.compiler.extern.spring.FluxtionSpring; +import com.fluxtion.example.cookbook.lottery.api.LotteryGame; +import com.fluxtion.example.cookbook.lottery.api.Ticket; +import com.fluxtion.example.cookbook.lottery.api.TicketStore; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.support.ClassPathXmlApplicationContext; +import java.util.function.Consumer; + +/** + * A simple lottery game to demonstrate event processing logic built with Fluxtion + */ +@Slf4j public class LotteryApp { - public void start(){ - EventProcessor lotteryGame = Fluxtion.interpret(new LotteryGameNode()); -// lotteryGame.getExportedService() + private static LotteryGame lotteryGame; + private static TicketStore ticketStore; + + public static void main(String[] args) { + start(LotteryApp::ticketReceipt, LotteryApp::lotteryResult); + //try and buy a ticket - store is closed + ticketStore.buyTicket(new Ticket(12_65_56)); + + //open store and buy ticket + ticketStore.openStore(); + ticketStore.buyTicket(new Ticket(12_65_56)); + ticketStore.buyTicket(new Ticket(36_58_58)); + ticketStore.buyTicket(new Ticket(73_00_12)); + + //bad numbers + ticketStore.buyTicket(new Ticket(25)); + + //close the store and run the lottery + ticketStore.closeStore(); + + //try and buy a ticket - store is closed + ticketStore.buyTicket(new Ticket(12_65_56)); + + //run the lottery + lotteryGame.selectWinningTicket(); } + + public static void start(Consumer ticketReceiptHandler, Consumer resultsPublisher){ + var lotteryEventProcessor = FluxtionSpring.interpret( + new ClassPathXmlApplicationContext("com/fluxtion/example/cookbook/lottery/spring-lottery.xml")); + lotteryEventProcessor.init(); + lotteryGame = lotteryEventProcessor.getExportedService(); + ticketStore = lotteryEventProcessor.getExportedService(); + lotteryGame.setResultPublisher(resultsPublisher); + ticketStore.setTicketSalesPublisher(ticketReceiptHandler); + lotteryEventProcessor.start(); + } + + public static void ticketReceipt(String receipt){ + log.info(receipt); + } + + public static void lotteryResult(String receipt){ + log.info(receipt); + } + } diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/LotteryGame.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/LotteryGame.java deleted file mode 100644 index c361cf2..0000000 --- a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/LotteryGame.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.fluxtion.example.cookbook.lottery; - -import java.util.function.Consumer; - -public interface LotteryGame { - - void pickTicket(); - void setResultPublisher(Consumer resultPublisher); -} diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/Ticket.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/Ticket.java deleted file mode 100644 index 752677f..0000000 --- a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/Ticket.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.fluxtion.example.cookbook.lottery; - -public record Ticket(int number) { -} diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/TicketStore.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/TicketStore.java deleted file mode 100644 index 7b41512..0000000 --- a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/TicketStore.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.fluxtion.example.cookbook.lottery; - -import java.util.function.Consumer; - -public interface TicketStore { - boolean buyTicket(Ticket ticket); - void openStore(); - void closeStore(); - - void setTicketSalesPublisher(Consumer receiptReceiver); -} diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/LotteryGame.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/LotteryGame.java new file mode 100644 index 0000000..0336a92 --- /dev/null +++ b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/LotteryGame.java @@ -0,0 +1,14 @@ +package com.fluxtion.example.cookbook.lottery.api; + +import java.util.function.Consumer; + +/** + * Service that runs the lottery, picks a ticket and publishes the results to a supplied Consumer. + * * If no resultPublisher is set the LotteryGame should fail with an exception at startup + */ +public interface LotteryGame { + + void selectWinningTicket(); + + void setResultPublisher(Consumer resultPublisher); +} diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/Ticket.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/Ticket.java new file mode 100644 index 0000000..28591d9 --- /dev/null +++ b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/Ticket.java @@ -0,0 +1,10 @@ +package com.fluxtion.example.cookbook.lottery.api; + +import java.util.UUID; + +public record Ticket(int number, UUID id) { + + public Ticket(int number){ + this(number, UUID.randomUUID()); + } +} diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/TicketStore.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/TicketStore.java new file mode 100644 index 0000000..4a881a7 --- /dev/null +++ b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/api/TicketStore.java @@ -0,0 +1,14 @@ +package com.fluxtion.example.cookbook.lottery.api; + +import java.util.function.Consumer; + +/** + * Ticket store for lottery tickets. The store must be open before tickets can be bought. + * If no ticketSalesPublisher is set the TicketStore should fail with an exception + */ +public interface TicketStore { + boolean buyTicket(Ticket ticket); + void openStore(); + void closeStore(); + void setTicketSalesPublisher(Consumer ticketSalesPublisher); +} diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/nodes/LotteryGameNode.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/nodes/LotteryGameNode.java index e65ae5a..9f95061 100644 --- a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/nodes/LotteryGameNode.java +++ b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/nodes/LotteryGameNode.java @@ -1,36 +1,55 @@ package com.fluxtion.example.cookbook.lottery.nodes; -import com.fluxtion.example.cookbook.lottery.LotteryGame; +import com.fluxtion.example.cookbook.lottery.api.Ticket; +import com.fluxtion.example.cookbook.lottery.api.LotteryGame; import com.fluxtion.runtime.annotations.ExportService; import com.fluxtion.runtime.annotations.OnTrigger; - +import com.fluxtion.runtime.annotations.Start; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; import java.util.function.Consumer; +import java.util.function.Supplier; -public class LotteryGameNode implements @ExportService LotteryGame { +@Slf4j +@RequiredArgsConstructor +public class LotteryGameNode implements + @ExportService LotteryGame { - private final TicketStoreNode ticketStoreNode; + private final Supplier ticketSupplier; + private final transient List ticketsBought = new ArrayList<>(); private Consumer resultPublisher; - public LotteryGameNode(){ - this(new TicketStoreNode()); - } - - public LotteryGameNode(TicketStoreNode ticketStoreNode) { - this.ticketStoreNode = ticketStoreNode; - } - @Override public void setResultPublisher(Consumer resultPublisher) { this.resultPublisher = resultPublisher; } + @Start + public void start(){ + Objects.requireNonNull(resultPublisher, "must set a results publisher before starting the lottery game"); + log.info("started"); + } + @OnTrigger - public boolean newTicketSale(){ + public boolean processNewTicketSale() { + ticketsBought.add(ticketSupplier.get()); + log.info("tickets sold:{}", ticketsBought.size()); return false; } @Override - public void pickTicket() { - + public void selectWinningTicket() { + if(ticketsBought.isEmpty()){ + log.info("no tickets bought - no winning ticket"); + }else { + Collections.shuffle(ticketsBought); + log.info("WINNING ticket {}", ticketsBought.get(0)); + } + ticketsBought.clear(); } } diff --git a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/nodes/TicketStoreNode.java b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/nodes/TicketStoreNode.java index 6da0df8..c4093fa 100644 --- a/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/nodes/TicketStoreNode.java +++ b/cookbook/src/main/java/com/fluxtion/example/cookbook/lottery/nodes/TicketStoreNode.java @@ -1,53 +1,68 @@ package com.fluxtion.example.cookbook.lottery.nodes; -import com.fluxtion.example.cookbook.lottery.Ticket; -import com.fluxtion.example.cookbook.lottery.TicketStore; +import com.fluxtion.example.cookbook.lottery.api.Ticket; +import com.fluxtion.example.cookbook.lottery.api.TicketStore; import com.fluxtion.runtime.annotations.ExportService; import com.fluxtion.runtime.annotations.NoPropagateFunction; import com.fluxtion.runtime.annotations.Start; +import lombok.extern.slf4j.Slf4j; import java.util.Objects; import java.util.function.Consumer; +import java.util.function.Supplier; -public class TicketStoreNode implements @ExportService TicketStore { +@Slf4j +public class TicketStoreNode implements + Supplier, + @ExportService TicketStore { private boolean storeOpen; - private Consumer receiptReceiver; + private Consumer ticketSalesPublisher; private Ticket ticket; @Override @NoPropagateFunction - public void setTicketSalesPublisher(Consumer receiptReceiver) { - this.receiptReceiver = receiptReceiver; + public void setTicketSalesPublisher(Consumer ticketSalesPublisher) { + this.ticketSalesPublisher = ticketSalesPublisher; } @Start - public void start(){ - Objects.requireNonNull(receiptReceiver, "must have a receipt publisher set"); + public void start() { + Objects.requireNonNull(ticketSalesPublisher, "must have a ticketSalesPublisher set"); storeOpen = false; } @Override public boolean buyTicket(Ticket ticket) { - if(storeOpen){ + if (ticket.number() < 9_99_99 | ticket.number() > 99_99_99) { + ticketSalesPublisher.accept("invalid numbers " + ticket); + this.ticket = null; + } else if (storeOpen) { + ticketSalesPublisher.accept("good luck with " + ticket); this.ticket = ticket; + } else { + ticketSalesPublisher.accept("store shut - no tickets can be bought"); + this.ticket = null; } - return storeOpen; + return this.ticket != null; } - public Ticket lastTicketSold(){ + @Override + public Ticket get() { return ticket; } @Override @NoPropagateFunction public void openStore() { + log.info("store opened"); storeOpen = true; } @Override @NoPropagateFunction public void closeStore() { + log.info("store closed"); storeOpen = false; } } diff --git a/cookbook/src/main/resources/com/fluxtion/example/cookbook/lottery/spring-lottery.xml b/cookbook/src/main/resources/com/fluxtion/example/cookbook/lottery/spring-lottery.xml new file mode 100644 index 0000000..964fd8e --- /dev/null +++ b/cookbook/src/main/resources/com/fluxtion/example/cookbook/lottery/spring-lottery.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + \ No newline at end of file