diff --git a/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/MainMenu.java b/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/MainMenu.java new file mode 100644 index 0000000..70f9821 --- /dev/null +++ b/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/MainMenu.java @@ -0,0 +1,49 @@ +package thb.jeanluc.adventure.menu; + +import thb.jeanluc.adventure.io.GameIO; +import thb.jeanluc.adventure.save.SaveService; +import thb.jeanluc.adventure.save.SaveSlotInfo; + +import java.util.ArrayList; +import java.util.List; + +/** Frontend-agnostic main menu, slot picker, and new-game name prompt. */ +public final class MainMenu { + + private MainMenu() { + } + + /** Shows the main menu and returns the chosen action. */ + public static MenuAction show(GameIO io) { + int i = io.choose("HAUNTED MANOR", + List.of("New Game", "Load Game", "Settings", "Quit")); + return MenuAction.values()[i]; + } + + /** Prompts for a new save name; blank input yields {@code defaultName}. */ + public static String promptName(GameIO io, String defaultName) { + io.write("Name your save (Enter for \"" + defaultName + "\"):"); + String line = io.readLine(); + return (line == null || line.isBlank()) ? defaultName : line.trim(); + } + + /** + * Lets the player pick a save slot to load. Returns the chosen + * {@link SaveSlotInfo}, or {@code null} if there are none or the player + * picks "Back". + */ + public static SaveSlotInfo pickSlot(GameIO io, SaveService saves) { + List slots = saves.list(); + if (slots.isEmpty()) { + io.write("No saved games."); + return null; + } + List labels = new ArrayList<>(); + for (SaveSlotInfo s : slots) { + labels.add(s.slotName() + " (" + s.roomId() + ", turn " + s.turn() + ")"); + } + labels.add("Back"); + int i = io.choose("LOAD GAME", labels); + return i < slots.size() ? slots.get(i) : null; + } +} diff --git a/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/MenuAction.java b/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/MenuAction.java new file mode 100644 index 0000000..9af99cf --- /dev/null +++ b/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/MenuAction.java @@ -0,0 +1,6 @@ +package thb.jeanluc.adventure.menu; + +/** Top-level main-menu choices, in display order. */ +public enum MenuAction { + NEW_GAME, LOAD, SETTINGS, QUIT +} diff --git a/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/SettingsMenu.java b/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/SettingsMenu.java new file mode 100644 index 0000000..3661505 --- /dev/null +++ b/Semesterprojekt/src/main/java/thb/jeanluc/adventure/menu/SettingsMenu.java @@ -0,0 +1,67 @@ +package thb.jeanluc.adventure.menu; + +import thb.jeanluc.adventure.io.ConsoleIO; +import thb.jeanluc.adventure.io.GameIO; +import thb.jeanluc.adventure.save.Settings; +import thb.jeanluc.adventure.save.SettingsStore; + +import java.util.List; + +/** Minimal settings screen: toggle colour and glyph mode; persists + applies. */ +public final class SettingsMenu { + + private SettingsMenu() { + } + + /** + * Loops the settings screen until the player picks "Back", persisting and + * applying each change. Returns the final settings. + * + * @param io active IO + * @param current starting settings + * @param store where to persist + * @param consoleIo the console IO to apply changes to live, or null if not console + */ + public static Settings show(GameIO io, Settings current, SettingsStore store, ConsoleIO consoleIo) { + Settings s = current; + while (true) { + int i = io.choose("SETTINGS", List.of( + "Colour: " + s.colorMode(), + "Glyphs: " + s.glyphMode(), + "Back")); + if (i == 0) { + s = new Settings(nextColor(s.colorMode()), s.glyphMode()); + } else if (i == 1) { + s = new Settings(s.colorMode(), nextGlyph(s.glyphMode())); + } else { + return s; + } + store.save(s); + apply(s, consoleIo); + } + } + + /** Applies colour/glyph settings to the console IO (no-op if null). */ + public static void apply(Settings s, ConsoleIO consoleIo) { + if (consoleIo != null) { + consoleIo.setColorMode(s.colorMode()); + consoleIo.setGlyphMode(s.glyphMode()); + } + } + + private static ConsoleIO.ColorMode nextColor(ConsoleIO.ColorMode m) { + return switch (m) { + case AUTO -> ConsoleIO.ColorMode.ON; + case ON -> ConsoleIO.ColorMode.OFF; + case OFF -> ConsoleIO.ColorMode.AUTO; + }; + } + + private static ConsoleIO.GlyphMode nextGlyph(ConsoleIO.GlyphMode m) { + return switch (m) { + case UNICODE -> ConsoleIO.GlyphMode.ASCII; + case ASCII -> ConsoleIO.GlyphMode.GLYPH; + case GLYPH -> ConsoleIO.GlyphMode.UNICODE; + }; + } +} diff --git a/Semesterprojekt/src/test/java/thb/jeanluc/adventure/menu/MenuTest.java b/Semesterprojekt/src/test/java/thb/jeanluc/adventure/menu/MenuTest.java new file mode 100644 index 0000000..40419cf --- /dev/null +++ b/Semesterprojekt/src/test/java/thb/jeanluc/adventure/menu/MenuTest.java @@ -0,0 +1,49 @@ +package thb.jeanluc.adventure.menu; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import thb.jeanluc.adventure.io.TestIO; +import thb.jeanluc.adventure.save.SaveService; +import thb.jeanluc.adventure.save.Settings; +import thb.jeanluc.adventure.save.SettingsStore; +import thb.jeanluc.adventure.io.ConsoleIO; + +import java.nio.file.Path; + +import static org.assertj.core.api.Assertions.assertThat; + +class MenuTest { + + @Test + void mainMenuMapsChoiceToAction() { + // options order: New Game(1) / Load(2) / Settings(3) / Quit(4) + assertThat(MainMenu.show(new TestIO().enqueue("1"))).isEqualTo(MenuAction.NEW_GAME); + assertThat(MainMenu.show(new TestIO().enqueue("2"))).isEqualTo(MenuAction.LOAD); + assertThat(MainMenu.show(new TestIO().enqueue("3"))).isEqualTo(MenuAction.SETTINGS); + assertThat(MainMenu.show(new TestIO().enqueue("4"))).isEqualTo(MenuAction.QUIT); + } + + @Test + void promptNameUsesDefaultOnBlank() { + assertThat(MainMenu.promptName(new TestIO().enqueue(""), "Manor")).isEqualTo("Manor"); + assertThat(MainMenu.promptName(new TestIO().enqueue("Spooky"), "Manor")).isEqualTo("Spooky"); + } + + @Test + void pickSlotReturnsNullWhenEmpty(@TempDir Path dir) { + TestIO io = new TestIO(); + assertThat(MainMenu.pickSlot(io, new SaveService(dir))).isNull(); + assertThat(io.allOutput()).contains("No saved games"); + } + + @Test + void settingsMenuTogglesGlyphAndPersists(@TempDir Path dir) { + SettingsStore store = new SettingsStore(dir.resolve("settings.json")); + // choose "Glyph mode" (assume option 2) → its toggle, then "Back" (last) + TestIO io = new TestIO().enqueue("2").enqueue("3"); + Settings result = SettingsMenu.show(io, Settings.defaults(), store, new ConsoleIO()); + // UNICODE default toggles to ASCII; persisted + assertThat(result.glyphMode()).isEqualTo(ConsoleIO.GlyphMode.ASCII); + assertThat(store.load().glyphMode()).isEqualTo(ConsoleIO.GlyphMode.ASCII); + } +}