From eed9265be711432f40247f149c07f9e33511192a Mon Sep 17 00:00:00 2001 From: Kostya Date: Sun, 16 Aug 2026 18:50:15 +0000 Subject: Split DTOs into api/model, extract order matching into service/matching Moves Event/Ledger DTOs out of the flat api package into api/model/{event,ledger}, and moves LocalCatalogContext and order matching logic into dedicated service/catalog and service/matching packages, replacing TradingOperation/TradingOperationImpl. --- .../src/main/java/market/guess/ui/console/App.java | 6 ++-- .../guess/ui/console/command/BuyMenuCommand.java | 14 ++++---- .../console/command/EventDetailsMenuCommand.java | 39 ++++++++++++++++++++-- .../ui/console/command/ListEventsMenuCommand.java | 1 + .../ui/console/command/LoadFileMenuCommand.java | 11 ++---- .../command/LoadMarketStateMenuCommand.java | 10 +++--- .../command/SaveMarketStateMenuCommand.java | 10 +++--- .../market/guess/ui/console/io/InputProcessor.java | 11 ++++-- 8 files changed, 71 insertions(+), 31 deletions(-) (limited to 'ui-console/src/main/java') 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 330498c..a628a36 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,9 +1,9 @@ package market.guess.ui.console; +import market.guess.api.CatalogContext; import market.guess.api.GuessMarketContext; import market.guess.service.LocalGuessMarketContext; -import market.guess.service.TradingOperation; -import market.guess.service.TradingOperationImpl; +import market.guess.service.catalog.LocalCatalogContext; import market.guess.service.infrastructure.MarketContext; import market.guess.service.infrastructure.mapper.v1.EventMapperV1; import market.guess.service.infrastructure.provider.Loader; @@ -31,10 +31,10 @@ public class App { pico.addComponent(EventRepository.class, InMemoryEventRepository.class); pico.addComponent(UserRepository.class, InMemoryUserRepository.class); pico.addComponent(MarketContext.class); - pico.addComponent(TradingOperation.class, TradingOperationImpl.class); pico.addComponent(EventMapperV1.class); pico.addComponent(Loader.class, XMLLoaderV1.class); pico.addComponent(GuessMarketContext.class, LocalGuessMarketContext.class); + pico.addComponent(CatalogContext.class, LocalCatalogContext.class); pico.addComponent(LoadFileMenuCommand.class); pico.addComponent(ListEventsMenuCommand.class); diff --git a/ui-console/src/main/java/market/guess/ui/console/command/BuyMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/BuyMenuCommand.java index df40aa8..87da340 100644 --- a/ui-console/src/main/java/market/guess/ui/console/command/BuyMenuCommand.java +++ b/ui-console/src/main/java/market/guess/ui/console/command/BuyMenuCommand.java @@ -1,8 +1,8 @@ package market.guess.ui.console.command; import market.guess.api.CatalogContext; -import market.guess.api.EventStatus; import market.guess.api.GuessMarketContext; +import market.guess.model.event.EventStatus; import market.guess.ui.console.io.InputProcessor; public final class BuyMenuCommand implements MenuCommand { @@ -59,14 +59,16 @@ public final class BuyMenuCommand implements MenuCommand { io.readSelect( "Choose a market: ", event.state().markets(), - o -> "%s [value %d, %d shares helds]".formatted(o.name(), o.price(), o.volume())); + o -> "%s [value %s, %s shares helds]".formatted(o.name(), o.price(), o.volume())); var amount = io.readInt("How many shares? ", 1, Integer.MAX_VALUE); - var receipt = context.buyShares("", event.summary().key(), market.key(), amount); - if (receipt.isSuccess()) return; - + var buyResult = context.buyShares("Tester", event.summary().key(), market.key(), amount); + if (buyResult.isSuccess()) { + io.printReceipt(buyResult.getData()); + return; + } io.newLine(); - io.println("Purchase declined: %s".formatted(receipt.getMessage())); + io.println("Purchase declined: %s".formatted(buyResult.getMessage())); } } diff --git a/ui-console/src/main/java/market/guess/ui/console/command/EventDetailsMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/EventDetailsMenuCommand.java index ab60a1f..881acfa 100644 --- a/ui-console/src/main/java/market/guess/ui/console/command/EventDetailsMenuCommand.java +++ b/ui-console/src/main/java/market/guess/ui/console/command/EventDetailsMenuCommand.java @@ -1,6 +1,18 @@ package market.guess.ui.console.command; +import market.guess.api.CatalogContext; +import market.guess.model.event.EventStatus; +import market.guess.ui.console.io.InputProcessor; + public final class EventDetailsMenuCommand implements MenuCommand { + private final CatalogContext catalog; + private final InputProcessor io; + + public EventDetailsMenuCommand(CatalogContext catalog, InputProcessor io) { + super(); + this.catalog = catalog; + this.io = io; + } @Override public int getIndex() { @@ -14,7 +26,30 @@ public final class EventDetailsMenuCommand implements MenuCommand { @Override public void execute() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'execute'"); + var result = catalog.getAllEvents(); + + if (!result.isSuccess()) { + io.println("Failed to list events"); + return; + } + + var events = result.getData(); + var active = events.stream().filter(event -> event.status() == EventStatus.ACTIVE).toList(); + + if (active.isEmpty()) { + io.println("There are currently no active events to trade on."); + return; + } + + var pick = io.readSelect("Pick an event: ", active, event -> "%s".formatted(event.name())); + + var result2 = catalog.getEvent(pick.key()); + var event = result2.getData(); + if (event == null) { + io.println("That event is no longer available."); + return; + } + + io.printState(event.state()); } } 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 index a97ab9f..755bf37 100644 --- 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 @@ -29,6 +29,7 @@ public final class ListEventsMenuCommand implements MenuCommand { var result = catalog.getAllEvents(); if (!result.isSuccess()) { + io.println("Failed to list events due to %s.".formatted(result.getMessage())); return; } var events = result.getData(); 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 065ac6e..46312e4 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 @@ -25,8 +25,8 @@ public final class LoadFileMenuCommand implements MenuCommand { @Override public void execute() { - // var path = io.readPath("Pleae enter the full file path to the XML file: "); - // var result = context.loadEvents(Path.of(path)); + // var path = io.readPath("Pleae enter the full file path to the XML file: "); + // var result = context.loadEvents(Path.of(path)); var result = catalog.loadEvents( Path.of("/home/hex-dev/projects/guess-market/test-data/ex-1/multiple.xml")); @@ -38,11 +38,6 @@ public final class LoadFileMenuCommand implements MenuCommand { return; } - io.println( - "The file was not loaded. %d problem(s) were found: " - .formatted(result.getData().issues().size())); - for (var issue : result.getData().issues()) { - io.println(" - %s: %s".formatted(issue.location(), issue.humanizedMessage())); - } + io.println("The file was not loaded, %s ".formatted(result.getMessage())); } } diff --git a/ui-console/src/main/java/market/guess/ui/console/command/LoadMarketStateMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/LoadMarketStateMenuCommand.java index defb402..26d00c1 100644 --- a/ui-console/src/main/java/market/guess/ui/console/command/LoadMarketStateMenuCommand.java +++ b/ui-console/src/main/java/market/guess/ui/console/command/LoadMarketStateMenuCommand.java @@ -1,16 +1,16 @@ package market.guess.ui.console.command; import java.nio.file.Path; -import market.guess.api.GuessMarketContext; +import market.guess.api.CatalogContext; import market.guess.ui.console.io.InputProcessor; public final class LoadMarketStateMenuCommand implements MenuCommand { - private final GuessMarketContext context; + private final CatalogContext catalog; private final InputProcessor io; - public LoadMarketStateMenuCommand(GuessMarketContext context, InputProcessor io) { + public LoadMarketStateMenuCommand(CatalogContext catalog, InputProcessor io) { super(); - this.context = context; + this.catalog = catalog; this.io = io; } @@ -27,7 +27,7 @@ public final class LoadMarketStateMenuCommand implements MenuCommand { @Override public void execute() { var path = io.readPath("Which state file to load? "); - var result = context.restoreState(Path.of(path)); + var result = catalog.restoreState(Path.of(path)); if (result.isSuccess()) { io.println("Restored %d event(s) from %s.".formatted(result.getData().eventsLoaded(), path)); diff --git a/ui-console/src/main/java/market/guess/ui/console/command/SaveMarketStateMenuCommand.java b/ui-console/src/main/java/market/guess/ui/console/command/SaveMarketStateMenuCommand.java index 27dfdde..77400d2 100644 --- a/ui-console/src/main/java/market/guess/ui/console/command/SaveMarketStateMenuCommand.java +++ b/ui-console/src/main/java/market/guess/ui/console/command/SaveMarketStateMenuCommand.java @@ -1,16 +1,16 @@ package market.guess.ui.console.command; import java.nio.file.Path; -import market.guess.api.GuessMarketContext; +import market.guess.api.CatalogContext; import market.guess.ui.console.io.InputProcessor; public final class SaveMarketStateMenuCommand implements MenuCommand { - private final GuessMarketContext context; + private final CatalogContext catalog; private final InputProcessor io; - public SaveMarketStateMenuCommand(GuessMarketContext context, InputProcessor io) { + public SaveMarketStateMenuCommand(CatalogContext catalog, InputProcessor io) { super(); - this.context = context; + this.catalog = catalog; this.io = io; } @@ -29,7 +29,7 @@ public final class SaveMarketStateMenuCommand implements MenuCommand { var path = io.readPath("Save to: "); try { - context.saveState(Path.of(path)); + catalog.saveState(Path.of(path)); io.println("Saved current state to %s.".formatted(path)); } catch (Exception e) { io.println("Failed to save: %s".formatted(e.getMessage())); diff --git a/ui-console/src/main/java/market/guess/ui/console/io/InputProcessor.java b/ui-console/src/main/java/market/guess/ui/console/io/InputProcessor.java index 912ca25..d644a9b 100644 --- a/ui-console/src/main/java/market/guess/ui/console/io/InputProcessor.java +++ b/ui-console/src/main/java/market/guess/ui/console/io/InputProcessor.java @@ -4,6 +4,7 @@ import java.util.List; import java.util.Scanner; import java.util.function.Function; import market.guess.api.MarketStateDTO; +import market.guess.api.PurchaseReceiptDTO; public final class InputProcessor { private final Scanner scanner = new Scanner(System.in); @@ -32,6 +33,8 @@ public final class InputProcessor { .formatted( padAround("Option", 18), space(10), padLeft("Value", 8), padRight("Shares", 8))); + println("-".repeat(46)); + for (var market : state.markets()) { println( "%s|%s%s|%s" @@ -43,8 +46,8 @@ public final class InputProcessor { } newLine(); - print("Event ledger balance: ".formatted(state.accountBalance())); - print("Commission collected: ".formatted(state.commissionCollected())); + println("Event ledger balance: ".formatted(state.accountBalance())); + println("Commission collected: ".formatted(state.commissionCollected())); } private static String space(int width) { @@ -136,4 +139,8 @@ public final class InputProcessor { private String nextLine() { return scanner.hasNextLine() ? scanner.nextLine() : null; } + + public void printReceipt(PurchaseReceiptDTO receipt) { + println(receipt); + } } -- cgit v1.2.3