From 98ebc2b0f6fdde1f7502a35ebe067fb95e5ee336 Mon Sep 17 00:00:00 2001 From: Kostya Date: Fri, 14 Aug 2026 11:02:33 +0000 Subject: Wire buyShares and menu commands, replace factory interfaces with DI Implement LocalGuessMarketContext.buyShares/loadEvents via a new TradingOperation and Loader, backed by in-memory repositories. Replace the ConsoleInputProviderFactory/ConsoleOutputProviderFactory pattern with picocontainer-injected providers, and drive the menu from a list of MenuCommand implementations instead of a hardcoded printout. --- .../java/market/guess/api/GuessMarketContext.java | 2 +- .../guess/service/LocalGuessMarketContext.java | 28 +++++++++++++--- .../market/guess/service/TradingOperation.java | 13 ++++++++ .../market/guess/service/TradingOperationImpl.java | 22 ++++++++++++ .../java/market/guess/service/domain/Event.java | 7 ++++ .../market/guess/service/domain/Settlement.java | 6 ++++ .../service/infrastructure/provider/XMLLoader.java | 13 ++++++++ .../repository/InMemoryEventRepository.java | 19 +++++++++++ .../service/repository/InMemoryUserRepository.java | 13 ++++++++ ui-console/.classpath | 1 + ui-console/.project | 1 + .../src/main/java/market/guess/ui/console/App.java | 39 ++++++++++++---------- .../ui/console/ConsoleInputProviderFactory.java | 9 ----- .../guess/ui/console/ConsoleOutputProvider.java | 5 +++ .../ui/console/ConsoleOutputProviderFactory.java | 9 ----- .../guess/ui/console/InputProviderFactory.java | 5 --- .../main/java/market/guess/ui/console/Menu.java | 30 +++++++++-------- .../market/guess/ui/console/OutputProvider.java | 2 ++ .../guess/ui/console/OutputProviderFactory.java | 5 --- .../ui/console/command/LoadFileMenuCommand.java | 35 +++++++++++++++++++ .../guess/ui/console/command/MenuCommand.java | 11 ++++++ 21 files changed, 211 insertions(+), 64 deletions(-) create mode 100644 service/src/main/java/market/guess/service/TradingOperation.java create mode 100644 service/src/main/java/market/guess/service/TradingOperationImpl.java create mode 100644 service/src/main/java/market/guess/service/domain/Settlement.java create mode 100644 service/src/main/java/market/guess/service/infrastructure/provider/XMLLoader.java create mode 100644 service/src/main/java/market/guess/service/repository/InMemoryEventRepository.java create mode 100644 service/src/main/java/market/guess/service/repository/InMemoryUserRepository.java delete mode 100644 ui-console/src/main/java/market/guess/ui/console/ConsoleInputProviderFactory.java delete mode 100644 ui-console/src/main/java/market/guess/ui/console/ConsoleOutputProviderFactory.java delete mode 100644 ui-console/src/main/java/market/guess/ui/console/InputProviderFactory.java delete mode 100644 ui-console/src/main/java/market/guess/ui/console/OutputProviderFactory.java create mode 100644 ui-console/src/main/java/market/guess/ui/console/command/LoadFileMenuCommand.java create mode 100644 ui-console/src/main/java/market/guess/ui/console/command/MenuCommand.java diff --git a/api/src/main/java/market/guess/api/GuessMarketContext.java b/api/src/main/java/market/guess/api/GuessMarketContext.java index f010e1c..d959de6 100644 --- a/api/src/main/java/market/guess/api/GuessMarketContext.java +++ b/api/src/main/java/market/guess/api/GuessMarketContext.java @@ -13,7 +13,7 @@ public interface GuessMarketContext { EventDetailDTO getEvent(String eventKey); - PurchaseReceiptDTO buyShares(String userName, String eventKey, String optionKey, long quantity) + PurchaseReceiptDTO buyShares(String userName, String eventKey, String optionKey, int quantity) throws GuessMarketException; EventDetailDTO closeEvent(String userName, String eventKey, String winningOptionKey) diff --git a/service/src/main/java/market/guess/service/LocalGuessMarketContext.java b/service/src/main/java/market/guess/service/LocalGuessMarketContext.java index 67e263f..16ee1b8 100644 --- a/service/src/main/java/market/guess/service/LocalGuessMarketContext.java +++ b/service/src/main/java/market/guess/service/LocalGuessMarketContext.java @@ -10,19 +10,33 @@ import market.guess.api.LoadResultDTO; import market.guess.api.PurchaseReceiptDTO; import market.guess.exception.GuessMarketException; import market.guess.service.domain.Event; +import market.guess.service.infrastructure.provider.Loader; import market.guess.service.repository.EventRepository; +import market.guess.service.repository.UserRepository; public final class LocalGuessMarketContext implements GuessMarketContext { private final EventRepository eventRepository; + private final UserRepository userRepository; - public LocalGuessMarketContext(EventRepository eventRepository) { + private final TradingOperation tradingOperation; + + private final Loader provider; + + public LocalGuessMarketContext( + Loader provider, + EventRepository eventRepository, + UserRepository userRepository, + TradingOperation tradingOperation) { super(); + this.provider = provider; this.eventRepository = eventRepository; + this.userRepository = userRepository; + this.tradingOperation = tradingOperation; } @Override public LoadResultDTO loadEvents(Path path) { - throw new UnsupportedOperationException("Unimplemented method 'loadEvents'"); + return provider.load(path); } @Override @@ -42,15 +56,19 @@ public final class LocalGuessMarketContext implements GuessMarketContext { @Override public PurchaseReceiptDTO buyShares( - String userName, String eventKey, String optionKey, long quantity) + String userName, String eventKey, String optionKey, int quantity) throws GuessMarketException { - throw new UnsupportedOperationException("Unimplemented method 'buyShares'"); + var event = eventRepository.getEvent(eventKey); + var option = event.getOption(optionKey); + var user = userRepository.getUser(userName); + var trade = tradingOperation.buy(event, user, option, quantity); + return new PurchaseReceiptDTO(); } @Override public EventDetailDTO closeEvent(String userName, String eventKey, String winningOptionKey) throws GuessMarketException { - throw new UnsupportedOperationException("Unimplemented method 'closeEvent'"); + throw new UnsupportedOperationException("Unimplemented method 'account'"); } @Override diff --git a/service/src/main/java/market/guess/service/TradingOperation.java b/service/src/main/java/market/guess/service/TradingOperation.java new file mode 100644 index 0000000..c8153c2 --- /dev/null +++ b/service/src/main/java/market/guess/service/TradingOperation.java @@ -0,0 +1,13 @@ +package market.guess.service; + +import market.guess.service.domain.Event; +import market.guess.service.domain.Option; +import market.guess.service.domain.Settlement; +import market.guess.service.domain.Trade; +import market.guess.service.domain.User; + +public interface TradingOperation { + Trade buy(Event event, User user, Option Option, int quantity); + + Settlement settle(Event event, String winningOption); +} diff --git a/service/src/main/java/market/guess/service/TradingOperationImpl.java b/service/src/main/java/market/guess/service/TradingOperationImpl.java new file mode 100644 index 0000000..f6c9aa1 --- /dev/null +++ b/service/src/main/java/market/guess/service/TradingOperationImpl.java @@ -0,0 +1,22 @@ +package market.guess.service; + +import market.guess.service.domain.Event; +import market.guess.service.domain.Option; +import market.guess.service.domain.Settlement; +import market.guess.service.domain.Trade; +import market.guess.service.domain.User; + +public final class TradingOperationImpl implements TradingOperation { + + @Override + public Trade buy(Event event, User user, Option Option, int quantity) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'buy'"); + } + + @Override + public Settlement settle(Event event, String winningOption) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'settle'"); + } +} diff --git a/service/src/main/java/market/guess/service/domain/Event.java b/service/src/main/java/market/guess/service/domain/Event.java index 2d7ac39..cef0840 100644 --- a/service/src/main/java/market/guess/service/domain/Event.java +++ b/service/src/main/java/market/guess/service/domain/Event.java @@ -165,4 +165,11 @@ public final class Event { getOptionsNames(), account.getBalance().toPlainString()); } + + public Option getOption(String optionKey) { + return options.stream() + .filter(option -> option.getKey().equalsIgnoreCase(optionKey)) + .findFirst() + .orElseThrow(() -> new IllegalArgumentException("No such option.")); + } } diff --git a/service/src/main/java/market/guess/service/domain/Settlement.java b/service/src/main/java/market/guess/service/domain/Settlement.java new file mode 100644 index 0000000..cfc61f5 --- /dev/null +++ b/service/src/main/java/market/guess/service/domain/Settlement.java @@ -0,0 +1,6 @@ +package market.guess.service.domain; + +import java.math.BigDecimal; + +public record Settlement( + String winningOption, BigDecimal commission, BigDecimal paidOutToHolders) {} diff --git a/service/src/main/java/market/guess/service/infrastructure/provider/XMLLoader.java b/service/src/main/java/market/guess/service/infrastructure/provider/XMLLoader.java new file mode 100644 index 0000000..443cd87 --- /dev/null +++ b/service/src/main/java/market/guess/service/infrastructure/provider/XMLLoader.java @@ -0,0 +1,13 @@ +package market.guess.service.infrastructure.provider; + +import java.nio.file.Path; +import market.guess.api.LoadResultDTO; + +public final class XMLLoader implements Loader { + + @Override + public LoadResultDTO load(Path path) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'load'"); + } +} diff --git a/service/src/main/java/market/guess/service/repository/InMemoryEventRepository.java b/service/src/main/java/market/guess/service/repository/InMemoryEventRepository.java new file mode 100644 index 0000000..dad1055 --- /dev/null +++ b/service/src/main/java/market/guess/service/repository/InMemoryEventRepository.java @@ -0,0 +1,19 @@ +package market.guess.service.repository; + +import java.util.List; +import market.guess.service.domain.Event; + +public final class InMemoryEventRepository implements EventRepository { + + @Override + public Event getEvent(String id) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getEvent'"); + } + + @Override + public List getAllEvents() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getAllEvents'"); + } +} diff --git a/service/src/main/java/market/guess/service/repository/InMemoryUserRepository.java b/service/src/main/java/market/guess/service/repository/InMemoryUserRepository.java new file mode 100644 index 0000000..e71c94c --- /dev/null +++ b/service/src/main/java/market/guess/service/repository/InMemoryUserRepository.java @@ -0,0 +1,13 @@ +package market.guess.service.repository; + + +import market.guess.service.domain.User; + +public final class InMemoryUserRepository implements UserRepository { + + @Override + public User getUser(String name) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'getUser'"); + } +} diff --git a/ui-console/.classpath b/ui-console/.classpath index cfc0f9a..47b6ad0 100644 --- a/ui-console/.classpath +++ b/ui-console/.classpath @@ -7,6 +7,7 @@ + diff --git a/ui-console/.project b/ui-console/.project index d620a57..ca461d9 100644 --- a/ui-console/.project +++ b/ui-console/.project @@ -4,6 +4,7 @@ guess-market-api + guess-market-service diff --git a/ui-console/src/main/java/market/guess/ui/console/App.java b/ui-console/src/main/java/market/guess/ui/console/App.java index 5158478..ccffc06 100644 --- a/ui-console/src/main/java/market/guess/ui/console/App.java +++ b/ui-console/src/main/java/market/guess/ui/console/App.java @@ -1,5 +1,16 @@ package market.guess.ui.console; +import market.guess.api.GuessMarketContext; +import market.guess.service.LocalGuessMarketContext; +import market.guess.service.TradingOperation; +import market.guess.service.TradingOperationImpl; +import market.guess.service.infrastructure.provider.Loader; +import market.guess.service.infrastructure.provider.XMLLoader; +import market.guess.service.repository.EventRepository; +import market.guess.service.repository.InMemoryEventRepository; +import market.guess.service.repository.InMemoryUserRepository; +import market.guess.service.repository.UserRepository; +import market.guess.ui.console.command.LoadFileMenuCommand; import org.picocontainer.DefaultPicoContainer; import org.picocontainer.behaviors.Caching; @@ -7,25 +18,19 @@ public class App { public static void main() { var pico = new DefaultPicoContainer(new Caching()); - pico.addComponent(ConsoleInputProviderFactory.class); - pico.addComponent(ConsoleOutputProviderFactory.class); + pico.addComponent(EventRepository.class, InMemoryEventRepository.class); + pico.addComponent(UserRepository.class, InMemoryUserRepository.class); + + pico.addComponent(TradingOperation.class, TradingOperationImpl.class); + pico.addComponent(Loader.class, XMLLoader.class); + pico.addComponent(GuessMarketContext.class, LocalGuessMarketContext.class); + + pico.addComponent(LoadFileMenuCommand.class); + + pico.addComponent(InputProvider.class, ConsoleInputProvider.class); + pico.addComponent(OutputProvider.class, ConsoleOutputProvider.class); pico.addComponent(Menu.class); pico.start(); - // var context = new LocalGuessMarketContext(); - // var factory = new ConsoleInputProviderFactory(); - // var oFactory = new ConsoleOutputProviderFactory(); - // - // context.LoadAsync(); - // printMenu(oFactory.create()); - // - // try (var provider = factory.create()) { - // var input = provider.nextInt(); - // while (input != 0) { - // input = provider.nextInt(); - // } - // } catch (Exception ex) { - // ex.printStackTrace(); - // } } diff --git a/ui-console/src/main/java/market/guess/ui/console/ConsoleInputProviderFactory.java b/ui-console/src/main/java/market/guess/ui/console/ConsoleInputProviderFactory.java deleted file mode 100644 index a7433b7..0000000 --- a/ui-console/src/main/java/market/guess/ui/console/ConsoleInputProviderFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -package market.guess.ui.console; - -public class ConsoleInputProviderFactory implements InputProviderFactory { - - @Override - public InputProvider create() { - return new ConsoleInputProvider(); - } -} diff --git a/ui-console/src/main/java/market/guess/ui/console/ConsoleOutputProvider.java b/ui-console/src/main/java/market/guess/ui/console/ConsoleOutputProvider.java index 84017ac..3009d95 100644 --- a/ui-console/src/main/java/market/guess/ui/console/ConsoleOutputProvider.java +++ b/ui-console/src/main/java/market/guess/ui/console/ConsoleOutputProvider.java @@ -11,4 +11,9 @@ public class ConsoleOutputProvider implements OutputProvider { public void println(Object object) { IO.println(object); } + + @Override + public void newLine() { + IO.println(""); + } } diff --git a/ui-console/src/main/java/market/guess/ui/console/ConsoleOutputProviderFactory.java b/ui-console/src/main/java/market/guess/ui/console/ConsoleOutputProviderFactory.java deleted file mode 100644 index 3665df3..0000000 --- a/ui-console/src/main/java/market/guess/ui/console/ConsoleOutputProviderFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -package market.guess.ui.console; - -public class ConsoleOutputProviderFactory implements OutputProviderFactory { - - @Override - public OutputProvider create() { - return new ConsoleOutputProvider(); - } -} diff --git a/ui-console/src/main/java/market/guess/ui/console/InputProviderFactory.java b/ui-console/src/main/java/market/guess/ui/console/InputProviderFactory.java deleted file mode 100644 index dcbb1c6..0000000 --- a/ui-console/src/main/java/market/guess/ui/console/InputProviderFactory.java +++ /dev/null @@ -1,5 +0,0 @@ -package market.guess.ui.console; - -public interface InputProviderFactory { - InputProvider create(); -} diff --git a/ui-console/src/main/java/market/guess/ui/console/Menu.java b/ui-console/src/main/java/market/guess/ui/console/Menu.java index 81dade0..1f3f2be 100644 --- a/ui-console/src/main/java/market/guess/ui/console/Menu.java +++ b/ui-console/src/main/java/market/guess/ui/console/Menu.java @@ -1,17 +1,24 @@ package market.guess.ui.console; +import java.util.List; +import market.guess.ui.console.command.MenuCommand; import org.picocontainer.Startable; -public class Menu implements Startable { - private final OutputProvider outputProvider; +public final class Menu implements Startable { + private final OutputProvider out; + private final InputProvider in; + private final List commands; - public Menu(OutputProviderFactory factory) { - this.outputProvider = factory.create(); + public Menu( + List commands, OutputProvider outputProvider, InputProvider inputProvider) { + this.commands = commands; + this.out = outputProvider; + this.in = inputProvider; } @Override public void start() { - printMenu(outputProvider); + printMenu(); } @Override @@ -19,13 +26,10 @@ public class Menu implements Startable { // Do nothing. } - private static void printMenu(OutputProvider provider) { - provider.println("[1] Load Marketplace"); - provider.println("[2] Save Marketplace"); - provider.println("[3] Show All Events"); - provider.println("[4] Event Info"); - provider.println("[5] Participate In Event"); - provider.println("[6] Close Event"); - provider.println("[7] Exit"); + private void printMenu() { + out.newLine(); + for (var command : commands) { + out.println(" %d -- %s".formatted(command.getIndex(), command.getName())); + } } } diff --git a/ui-console/src/main/java/market/guess/ui/console/OutputProvider.java b/ui-console/src/main/java/market/guess/ui/console/OutputProvider.java index 57ff001..e49bec5 100644 --- a/ui-console/src/main/java/market/guess/ui/console/OutputProvider.java +++ b/ui-console/src/main/java/market/guess/ui/console/OutputProvider.java @@ -3,5 +3,7 @@ package market.guess.ui.console; public interface OutputProvider { void print(Object object); + void newLine(); + void println(Object object); } diff --git a/ui-console/src/main/java/market/guess/ui/console/OutputProviderFactory.java b/ui-console/src/main/java/market/guess/ui/console/OutputProviderFactory.java deleted file mode 100644 index 6d6601f..0000000 --- a/ui-console/src/main/java/market/guess/ui/console/OutputProviderFactory.java +++ /dev/null @@ -1,5 +0,0 @@ -package market.guess.ui.console; - -public interface OutputProviderFactory { - OutputProvider create(); -} diff --git a/ui-console/src/main/java/market/guess/ui/console/command/LoadFileMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/LoadFileMenuCommand.java new file mode 100644 index 0000000..eddc68f --- /dev/null +++ b/ui-console/src/main/java/market/guess/ui/console/command/LoadFileMenuCommand.java @@ -0,0 +1,35 @@ +package market.guess.ui.console.command; + +import market.guess.api.GuessMarketContext; +import market.guess.ui.console.OutputProvider; + +public final class LoadFileMenuCommand implements MenuCommand { + private final GuessMarketContext context; + private final OutputProvider out; + + public LoadFileMenuCommand(GuessMarketContext context, OutputProvider out) { + this.context = context; + this.out = out; + } + + @Override + public int getIndex() { + return 1; + } + + @Override + public String getName() { + return "Load events from file"; + } + + @Override + public boolean allowed() { + return true; + } + + @Override + public void execute() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'execute'"); + } +} diff --git a/ui-console/src/main/java/market/guess/ui/console/command/MenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/MenuCommand.java new file mode 100644 index 0000000..8a28dfe --- /dev/null +++ b/ui-console/src/main/java/market/guess/ui/console/command/MenuCommand.java @@ -0,0 +1,11 @@ +package market.guess.ui.console.command; + +public interface MenuCommand { + int getIndex(); + + String getName(); + + boolean allowed(); + + void execute(); +} -- cgit v1.2.3