From 12611a5f0116351ab9114f5403222aead7a8329f Mon Sep 17 00:00:00 2001 From: Kostya Date: Fri, 14 Aug 2026 18:49:26 +0000 Subject: Implement in-memory repositories, XML load validation, and menu exit/list commands - Add generic Repository interface; EventRepository/UserRepository extend it - Implement InMemoryEventRepository/InMemoryUserRepository backed by ArrayList - Rename XMLLoader to XMLLoaderV1, add LoadValidator and mapper/v2 package - Add OrderBookTradingMechanism - Add User(String, int) convenience constructor - Add ListEventsMenuCommand and ExitMenuCommand, isExit() on MenuCommand - Menu now sizes selection range by max command index and exits on isExit() - LoadFileMenuCommand reports validation issues on failed loads - Untrack test-data/ and config.properties from .gitignore --- .../src/main/java/market/guess/ui/console/App.java | 10 ++++- .../main/java/market/guess/ui/console/Menu.java | 8 ++-- .../guess/ui/console/command/ExitMenuCommand.java | 37 ++++++++++++++++ .../ui/console/command/ListEventsMenuCommand.java | 51 ++++++++++++++++++++++ .../ui/console/command/LoadFileMenuCommand.java | 6 +++ .../guess/ui/console/command/MenuCommand.java | 4 ++ 6 files changed, 111 insertions(+), 5 deletions(-) create mode 100644 ui-console/src/main/java/market/guess/ui/console/command/ExitMenuCommand.java create mode 100644 ui-console/src/main/java/market/guess/ui/console/command/ListEventsMenuCommand.java (limited to 'ui-console/src/main/java/market/guess/ui') 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 2bff741..34638ac 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 @@ -4,12 +4,15 @@ 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.mapper.v1.EventMapperV1; import market.guess.service.infrastructure.provider.Loader; -import market.guess.service.infrastructure.provider.v1.XMLLoader; +import market.guess.service.infrastructure.provider.v1.XMLLoaderV1; 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.ExitMenuCommand; +import market.guess.ui.console.command.ListEventsMenuCommand; import market.guess.ui.console.command.LoadFileMenuCommand; import market.guess.ui.console.io.ConsoleInputProvider; import market.guess.ui.console.io.ConsoleOutputProvider; @@ -27,10 +30,13 @@ public class App { pico.addComponent(UserRepository.class, InMemoryUserRepository.class); pico.addComponent(TradingOperation.class, TradingOperationImpl.class); - pico.addComponent(Loader.class, XMLLoader.class); + pico.addComponent(EventMapperV1.class); + pico.addComponent(Loader.class, XMLLoaderV1.class); pico.addComponent(GuessMarketContext.class, LocalGuessMarketContext.class); pico.addComponent(LoadFileMenuCommand.class); + pico.addComponent(ListEventsMenuCommand.class); + pico.addComponent(ExitMenuCommand.class); pico.addComponent(InputProvider.class, ConsoleInputProvider.class); pico.addComponent(OutputProvider.class, ConsoleOutputProvider.class); 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 0521e5f..c1762dc 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 @@ -19,12 +19,12 @@ public final class Menu implements Startable { @Override public void start() { + var max = commands.stream().mapToInt(MenuCommand::getIndex).max().orElse(0); out.splashScreen(); - while (true) { printMenu(); - var selection = in.readInt("Choose a command: ", 1, commands.size()); + var selection = in.readInt("Choose a command: ", 1, max); var commandOptional = commands.stream().filter(c -> c.getIndex() == selection).findFirst(); if (commandOptional.isEmpty()) { @@ -34,6 +34,8 @@ public final class Menu implements Startable { var command = commandOptional.get(); command.execute(); + + if (command.isExit()) return; } } @@ -45,7 +47,7 @@ public final class Menu implements Startable { private void printMenu() { out.newLine(); for (var command : commands) { - out.println(" %d -- %s".formatted(command.getIndex(), command.getName())); + out.println(" [%d]->> %s".formatted(command.getIndex(), command.getName())); } } } diff --git a/ui-console/src/main/java/market/guess/ui/console/command/ExitMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/ExitMenuCommand.java new file mode 100644 index 0000000..372c686 --- /dev/null +++ b/ui-console/src/main/java/market/guess/ui/console/command/ExitMenuCommand.java @@ -0,0 +1,37 @@ +package market.guess.ui.console.command; + +import market.guess.ui.console.io.OutputProvider; + +public final class ExitMenuCommand implements MenuCommand { + private final OutputProvider out; + + public ExitMenuCommand(OutputProvider out) { + super(); + this.out = out; + } + + @Override + public int getIndex() { + return 6; + } + + @Override + public String getName() { + return "Exit"; + } + + @Override + public boolean allowed() { + return true; + } + + @Override + public boolean isExit() { + return true; + } + + @Override + public void execute() { + out.println("Goodbye."); + } +} diff --git a/ui-console/src/main/java/market/guess/ui/console/command/ListEventsMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/ListEventsMenuCommand.java new file mode 100644 index 0000000..6e6ace9 --- /dev/null +++ b/ui-console/src/main/java/market/guess/ui/console/command/ListEventsMenuCommand.java @@ -0,0 +1,51 @@ +package market.guess.ui.console.command; + +import market.guess.api.CommissionTiming; +import market.guess.api.GuessMarketContext; +import market.guess.ui.console.io.OutputProvider; + +public final class ListEventsMenuCommand implements MenuCommand { + private final GuessMarketContext context; + private final OutputProvider out; + + public ListEventsMenuCommand(GuessMarketContext context, OutputProvider out) { + super(); + this.context = context; + this.out = out; + } + + @Override + public int getIndex() { + return 2; + } + + @Override + public String getName() { + return "List events"; + } + + @Override + public boolean allowed() { + return !context.listEvents().isEmpty(); + } + + @Override + public void execute() { + var events = context.listEvents(); + + for (var event : events) { + out.newLine(); + out.println(" %s".formatted(event.name())); + out.println(" %s".formatted(event.description())); + out.println( + " Commission: %d%% (%s)" + .formatted(event.commissionPercent(), timing(event.commissionTiming()))); + out.println(" Options: " + String.join(" | ", event.optionNames())); + out.println(" Status: " + event.status()); + } + } + + private static String timing(CommissionTiming timing) { + return timing == CommissionTiming.ON_CLOSE ? "charged on close" : "charged on purchase"; + } +} 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 index 5a91fe0..4a56483 100644 --- 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 @@ -40,5 +40,11 @@ public final class LoadFileMenuCommand implements MenuCommand { out.println("Loaded %d event(s) from %s.".formatted(result.eventsLoaded(), result.source())); return; } + + out.println( + "The file was not loaded. %d problem(s) were found: ".formatted(result.issues().size())); + for (var issue : result.issues()) { + out.println(" - %s: %s".formatted(issue.location(), issue.humanizedMessage())); + } } } 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 index 8a28dfe..50acdac 100644 --- 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 @@ -8,4 +8,8 @@ public interface MenuCommand { boolean allowed(); void execute(); + + default boolean isExit() { + return false; + } } -- cgit v1.2.3