From c8306a0794c470c282dd0c52e8cc06d68781dbc8 Mon Sep 17 00:00:00 2001 From: Michael Lizzio Date: Sun, 9 Nov 2025 14:57:49 -0500 Subject: Basic undo Mememto Pattern --- src/main/java/design/model/undo/Memento.java | 4 ++ src/main/java/design/model/undo/Originator.java | 7 ++ src/main/java/design/model/undo/UndoManager.java | 91 ++++++++++++++++++++++++ 3 files changed, 102 insertions(+) create mode 100644 src/main/java/design/model/undo/Memento.java create mode 100644 src/main/java/design/model/undo/Originator.java create mode 100644 src/main/java/design/model/undo/UndoManager.java (limited to 'src/main') diff --git a/src/main/java/design/model/undo/Memento.java b/src/main/java/design/model/undo/Memento.java new file mode 100644 index 0000000..162c3f3 --- /dev/null +++ b/src/main/java/design/model/undo/Memento.java @@ -0,0 +1,4 @@ +package design.model.undo; + +public interface Memento { +} diff --git a/src/main/java/design/model/undo/Originator.java b/src/main/java/design/model/undo/Originator.java new file mode 100644 index 0000000..63eac38 --- /dev/null +++ b/src/main/java/design/model/undo/Originator.java @@ -0,0 +1,7 @@ +package design.model.undo; + +public interface Originator { + Memento createMemento(); + + void restore(Memento memento); +} \ No newline at end of file diff --git a/src/main/java/design/model/undo/UndoManager.java b/src/main/java/design/model/undo/UndoManager.java new file mode 100644 index 0000000..5c6a4a0 --- /dev/null +++ b/src/main/java/design/model/undo/UndoManager.java @@ -0,0 +1,91 @@ +package design.model.undo; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; +import java.util.stream.Collectors; + +// Singleton caretaker that handles undo and redo stacks. +public final class UndoManager { + + private static final UndoManager INSTANCE = new UndoManager(); + + public static UndoManager instance() { + return INSTANCE; + } + + private UndoManager() { + } + + // Stack entry + private static class Entry { + final Originator originator; + final Memento memento; + final String label; + + Entry(Originator originator, Memento memento, String label) { + this.originator = originator; + this.memento = memento; + this.label = label; + } + } + + private final Deque undoStack = new ArrayDeque<>(); + private final Deque redoStack = new ArrayDeque<>(); + + // Capture state + public void capture(Originator originator, String label) { + undoStack.push(new Entry(originator, originator.createMemento(), label)); + redoStack.clear(); + } + + // Undo / Redo ops + public boolean canUndo() { + return !undoStack.isEmpty(); + } + + public boolean canRedo() { + return !redoStack.isEmpty(); + } + + public String peekUndoLabel() { + return canUndo() ? undoStack.peek().label : null; + } + + public String peekRedoLabel() { + return canRedo() ? redoStack.peek().label : null; + } + + public List getUndoHistoryLabels() { + return undoStack.stream() + .map(e -> e.label) + .collect(Collectors.toList()); + } + + public void undo() { + if (!canUndo()) { + System.out.println("Nothing to undo."); + return; + } + + Entry entry = undoStack.pop(); + redoStack.push(new Entry(entry.originator, entry.originator.createMemento(), entry.label)); + entry.originator.restore(entry.memento); + } + + public void redo() { + if (!canRedo()) { + System.out.println("Nothing to redo."); + return; + } + + Entry entry = redoStack.pop(); + undoStack.push(new Entry(entry.originator, entry.originator.createMemento(), entry.label)); + entry.originator.restore(entry.memento); + } + + public void purge() { + undoStack.clear(); + redoStack.clear(); + } +} -- cgit v1.2.3 From 873c9c81fab807127fb70e5abb88c8f96c9d8934 Mon Sep 17 00:00:00 2001 From: Michael Lizzio Date: Mon, 10 Nov 2025 14:19:24 -0500 Subject: Added GolferMememto, updated Golfer --- src/main/java/design/model/Golfer.java | 51 +++++++++++++++++++++- .../design/model/holeplay/HolePlayContext.java | 17 +++++++- 2 files changed, 66 insertions(+), 2 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/model/Golfer.java b/src/main/java/design/model/Golfer.java index 48daae8..0f4c914 100644 --- a/src/main/java/design/model/Golfer.java +++ b/src/main/java/design/model/Golfer.java @@ -6,8 +6,11 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.util.ArrayList; import java.util.List; +import design.model.undo.Memento; +import design.model.undo.Originator; + @JsonPropertyOrder({ "clubs", "nextClubId" }) -public class Golfer { +public class Golfer implements Originator { private String username; private int passwordHash; private String fullName; @@ -112,4 +115,50 @@ public class Golfer { public void removeClub(Club c) { clubs.remove(c); } + + // Takes a snapshot of the golfer + private static class GolferMemento implements Memento { + private final String username; + private final int passwordHash; + private final String fullName; + private final List courses; + private final List rounds; + private final List clubs; + private final int nextClubId; + + GolferMemento(Golfer g) { + this.username = g.username; + this.passwordHash = g.passwordHash; + this.fullName = g.fullName; + this.courses = new ArrayList<>(g.courses); + this.rounds = new ArrayList<>(g.rounds); + this.clubs = new ArrayList<>(g.clubs); + this.nextClubId = g.nextClubId; + } + } + + @Override + public Memento createMemento() { + return new GolferMemento(this); + } + + @Override + public void restore(Memento memento) { + GolferMemento gm = (GolferMemento) memento; + + this.username = gm.username; + this.passwordHash = gm.passwordHash; + this.fullName = gm.fullName; + + this.courses.clear(); + this.courses.addAll(gm.courses); + + this.rounds.clear(); + this.rounds.addAll(gm.rounds); + + this.clubs.clear(); + this.clubs.addAll(gm.clubs); + + this.nextClubId = gm.nextClubId; + } } diff --git a/src/main/java/design/model/holeplay/HolePlayContext.java b/src/main/java/design/model/holeplay/HolePlayContext.java index 7a5d8ef..16201b6 100644 --- a/src/main/java/design/model/holeplay/HolePlayContext.java +++ b/src/main/java/design/model/holeplay/HolePlayContext.java @@ -6,7 +6,10 @@ import java.util.ArrayList; import design.model.*; import design.persistence.PersonalDatabase; -public class HolePlayContext { +import design.model.undo.Memento; +import design.model.undo.Originator; + +public class HolePlayContext implements Originator { private final Golfer golfer; private final Round round; private final PersonalDatabase pdb; @@ -109,4 +112,16 @@ public class HolePlayContext { void setStrokes(int s) { this.strokes = s; } + + @Override + public Memento createMemento() { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'createMemento'"); + } + + @Override + public void restore(Memento memento) { + // TODO Auto-generated method stub + throw new UnsupportedOperationException("Unimplemented method 'restore'"); + } } \ No newline at end of file -- cgit v1.2.3 From a29285b3aaf19becc74ef5b2755052aed8782a57 Mon Sep 17 00:00:00 2001 From: Michael Lizzio Date: Mon, 10 Nov 2025 14:25:30 -0500 Subject: Added HolePlayMemento with sanpshots and restore --- .../design/model/holeplay/HolePlayContext.java | 54 ++++++++++++++++++++-- 1 file changed, 49 insertions(+), 5 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/model/holeplay/HolePlayContext.java b/src/main/java/design/model/holeplay/HolePlayContext.java index 16201b6..71fba32 100644 --- a/src/main/java/design/model/holeplay/HolePlayContext.java +++ b/src/main/java/design/model/holeplay/HolePlayContext.java @@ -113,15 +113,59 @@ public class HolePlayContext implements Originator { this.strokes = s; } + // Captures current State, current play (hole# + swings), and stroke counter + private static class HolePlayMemento implements Memento { + private final String stateName; + private final Play currentPlayCopy; + private final int strokesCopy; + + HolePlayMemento(HolePlayContext ctx) { + this.stateName = ctx.state.name(); + + // Copy currentPlay if it exists + Play src = ctx.currentPlay; + if (src != null) { + var copySwings = new ArrayList(); + for (Swing s : src.getSwings()) { + copySwings.add(new Swing(s.getDistance(), s.getClubUsed())); + } + this.currentPlayCopy = new Play(src.getHoleNumber(), copySwings); + } else { + this.currentPlayCopy = null; + } + + this.strokesCopy = ctx.strokes; + } + } + @Override public Memento createMemento() { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'createMemento'"); + return new HolePlayMemento(this); } @Override - public void restore(Memento memento) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'restore'"); + public void restore(Memento m) { + HolePlayMemento hm = (HolePlayMemento) m; + + // restore strokes + this.strokes = hm.strokesCopy; + + // restore currentPlay + if (hm.currentPlayCopy == null) { + this.currentPlay = null; + } else { + var copySwings = new ArrayList(); + for (Swing s : hm.currentPlayCopy.getSwings()) { + copySwings.add(new Swing(s.getDistance(), s.getClubUsed())); + } + this.currentPlay = new Play(hm.currentPlayCopy.getHoleNumber(), copySwings); + } + + // restore state based on name + switch (hm.stateName) { + case "SetupState" -> this.state = new SetupState(); + case "PlayState" -> this.state = new PlayState(); + case "HoleCompleteState" -> this.state = new HoleCompleteState(); + } } } \ No newline at end of file -- cgit v1.2.3 From 4e45988ddff84205d2c5c81466ae86f57b25de17 Mon Sep 17 00:00:00 2001 From: Michael Lizzio Date: Mon, 10 Nov 2025 15:13:27 -0500 Subject: Used UndoManager in Menus to Capture Sanpshots --- .../controller/userinput/menus/CourseSearch.java | 8 ++++--- .../controller/userinput/menus/HolePlayMenu.java | 13 ++++++++++- .../controller/userinput/menus/MainMenu.java | 25 ++++++++++++++++++++-- .../controller/userinput/menus/ManageClubs.java | 9 +++++++- .../controller/userinput/menus/ManageCourses.java | 7 +++++- .../controller/userinput/menus/UserSettings.java | 6 ++++++ 6 files changed, 60 insertions(+), 8 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/CourseSearch.java b/src/main/java/design/controller/userinput/menus/CourseSearch.java index b84247a..4dd2cad 100644 --- a/src/main/java/design/controller/userinput/menus/CourseSearch.java +++ b/src/main/java/design/controller/userinput/menus/CourseSearch.java @@ -9,6 +9,7 @@ import design.model.course_search.CurrentSearchQuery; import design.model.course_search.ICourse; import design.persistence.PersonalDatabase; import design.runtime.Session; +import design.model.undo.UndoManager; import java.io.IOException; import java.util.ArrayList; @@ -71,7 +72,7 @@ public class CourseSearch extends Menu { } // recursively go through tree structure of courselist to make menu options. - // this is all for displaying the menu options, not the actual sorting. + // this is all for displaying the menu options, not the actual sorting. private void addCoursesRecursive(List menuOptions, CourseList list) { for (ICourse icourse : list.getCourses()) { // if we find a leaf (course), display it as a menu option @@ -79,6 +80,8 @@ public class CourseSearch extends Menu { var name = String.format("%s, %s, Difficulty: %s, %s holes, %s total par", c.getName(), c.getLocation(), c.getDifficultyRating(), c.getHoleCount(), c.getTotalPar()); menuOptions.add(new MenuOption(name, () -> { + UndoManager.instance().capture(golfer, "Add course " + c.getName()); + // add the course, try to save to DB. golfer.addCourse(c); try { @@ -89,8 +92,7 @@ public class CourseSearch extends Menu { System.out.println("\n Course added to profile. \n"); new MainMenu().present(); - } - )); + })); } // if not, we need to traverse another courselist else if (icourse instanceof CourseList sublist) { diff --git a/src/main/java/design/controller/userinput/menus/HolePlayMenu.java b/src/main/java/design/controller/userinput/menus/HolePlayMenu.java index e0d1572..2a7fc5d 100644 --- a/src/main/java/design/controller/userinput/menus/HolePlayMenu.java +++ b/src/main/java/design/controller/userinput/menus/HolePlayMenu.java @@ -3,12 +3,14 @@ package design.controller.userinput.menus; import design.controller.userinput.Menu; import design.controller.userinput.MenuOption; import design.model.Course; +import design.model.Golfer; import design.model.Hole; import design.runtime.Session; import design.model.Club; import design.model.Round; import design.model.holeplay.HolePlayContext; import design.persistence.PersonalDatabase; +import design.model.undo.UndoManager; import java.util.ArrayList; import java.util.List; @@ -18,10 +20,11 @@ public class HolePlayMenu extends Menu { private final Round round; private final HolePlayContext ctx; + private final Golfer golfer = Session.getCurrentGolfer(); public HolePlayMenu() { this.round = createRound(); - this.ctx = new HolePlayContext(Session.getCurrentGolfer(), round, PersonalDatabase.instance()); + this.ctx = new HolePlayContext(this.golfer, round, PersonalDatabase.instance()); } @Override @@ -60,6 +63,8 @@ public class HolePlayMenu extends Menu { dist = Integer.parseInt(ds); } + UndoManager.instance().capture(ctx, "Shot with " + club.getNickname() + " for " + dist + " yds"); + // Records shot ctx.recordShot(club, dist); System.out.println("Shot recorded: " + dist + " yds with " + club.getNickname()); @@ -71,6 +76,9 @@ public class HolePlayMenu extends Menu { opts.add(new MenuOption("hole out", () -> { // Precedes to next hole int prev = round.getCurrentHole().getNumber(); + + UndoManager.instance().capture(golfer, "Hole out on " + prev + " at " + round.getCourse().getName()); + ctx.holeOut(); System.out.println("Holed out on " + prev + ". Next: " + round.getCurrentHole().getNumber()); this.present(); @@ -79,6 +87,7 @@ public class HolePlayMenu extends Menu { // End round (always shown) opts.add(new MenuOption("end round", () -> { + UndoManager.instance().capture(golfer, "End round on " + round.getCourse().getName()); ctx.endRoundNow(); System.out.println("Round ended."); new MainMenu().present(); @@ -118,6 +127,8 @@ public class HolePlayMenu extends Menu { // Starts round and sends user to HolePlayMenu Hole startHole = course.getHoles().get(startHoleNum - 1); Round r = new Round(course, Session.getDateTime(), startHole); + // Undo puts golfer back to before round existed. + UndoManager.instance().capture(golfer, "Start round on " + course.getName() + " (hole " + startHoleNum + ")"); golfer.addRound(r); return r; } diff --git a/src/main/java/design/controller/userinput/menus/MainMenu.java b/src/main/java/design/controller/userinput/menus/MainMenu.java index 7522ceb..07caffa 100644 --- a/src/main/java/design/controller/userinput/menus/MainMenu.java +++ b/src/main/java/design/controller/userinput/menus/MainMenu.java @@ -2,6 +2,7 @@ package design.controller.userinput.menus; import design.controller.userinput.Menu; import design.controller.userinput.MenuOption; +import design.model.undo.UndoManager; import java.util.List; @@ -13,13 +14,33 @@ public class MainMenu extends Menu { @Override public List getMenuOptions() { + + UndoManager um = UndoManager.instance(); + return List.of( new MenuOption("quit", () -> System.exit(0)), + new MenuOption("undo", () -> { + if (!um.canUndo()) { + System.out.println("Nothing to undo."); + } else { + System.out.println("Undo: " + um.peekUndoLabel()); + um.undo(); + } + this.present(); + }), + new MenuOption("redo", () -> { + if (!um.canRedo()) { + System.out.println("Nothing to redo."); + } else { + System.out.println("Redo: " + um.peekRedoLabel()); + um.redo(); + } + this.present(); + }), new MenuOption("user settings...", () -> new UserSettings().present()), new MenuOption("manage courses...", () -> new ManageCourses().present()), new MenuOption("manage clubs...", () -> new ManageClubs().present()), new MenuOption("statistics...", () -> new StatisticsMenu().present()), - new MenuOption("log round...", () -> new HolePlayMenu().present()) - ); + new MenuOption("log round...", () -> new HolePlayMenu().present())); } } diff --git a/src/main/java/design/controller/userinput/menus/ManageClubs.java b/src/main/java/design/controller/userinput/menus/ManageClubs.java index 27b011c..d186cac 100644 --- a/src/main/java/design/controller/userinput/menus/ManageClubs.java +++ b/src/main/java/design/controller/userinput/menus/ManageClubs.java @@ -6,6 +6,7 @@ import design.model.Club; import design.model.Golfer; import design.persistence.PersonalDatabase; import design.runtime.Session; +import design.model.undo.UndoManager; import java.io.IOException; import java.util.Arrays; @@ -36,7 +37,11 @@ public class ManageClubs extends Menu { opts.add(new MenuOption("remove club...", () -> { var selector = new SelectClub(); selector.present(); - golfer.removeClub(selector.getResult()); + Club toRemove = selector.getResult(); + + UndoManager.instance().capture(golfer, "Remove club " + toRemove); + + golfer.removeClub(toRemove); try { personalDB.updateGolfer(golfer); } catch (IOException ex) { @@ -46,6 +51,8 @@ public class ManageClubs extends Menu { })); opts.add(new MenuOption("add club...", () -> { + UndoManager.instance().capture(golfer, "Add club"); + Scanner sc = new Scanner(System.in); System.out.print("Manufacturer: "); diff --git a/src/main/java/design/controller/userinput/menus/ManageCourses.java b/src/main/java/design/controller/userinput/menus/ManageCourses.java index b592cd2..4f3efe5 100644 --- a/src/main/java/design/controller/userinput/menus/ManageCourses.java +++ b/src/main/java/design/controller/userinput/menus/ManageCourses.java @@ -6,6 +6,7 @@ import design.model.Course; import design.model.Golfer; import design.persistence.PersonalDatabase; import design.runtime.Session; +import design.model.undo.UndoManager; import java.io.IOException; import java.util.List; @@ -34,7 +35,11 @@ public class ManageCourses extends Menu { opts.add(new MenuOption("remove course...", () -> { var selector = new SelectCourse(); selector.present(); - golfer.removeCourse(selector.getResult()); + Course course = selector.getResult(); + + UndoManager.instance().capture(golfer, "Remove course " + course.getName()); + + golfer.removeCourse(course); try { personalDB.updateGolfer(golfer); } catch (IOException ex) { diff --git a/src/main/java/design/controller/userinput/menus/UserSettings.java b/src/main/java/design/controller/userinput/menus/UserSettings.java index 47b0a5b..36d8d70 100644 --- a/src/main/java/design/controller/userinput/menus/UserSettings.java +++ b/src/main/java/design/controller/userinput/menus/UserSettings.java @@ -12,6 +12,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Scanner; +import design.model.undo.UndoManager; + public class UserSettings extends Menu { private final Golfer golfer = Session.getCurrentGolfer(); @@ -35,6 +37,8 @@ public class UserSettings extends Menu { })); opts.add(new MenuOption("set password...", () -> { + UndoManager.instance().capture(golfer, "Change password for @" + golfer.getUsername()); + System.out.print("Enter password: "); var password = scanner.nextLine(); @@ -48,6 +52,8 @@ public class UserSettings extends Menu { })); opts.add(new MenuOption("set full name...", () -> { + UndoManager.instance().capture(golfer, "Change full name for @" + golfer.getUsername()); + System.out.print("Enter full name: "); var fullName = scanner.nextLine(); -- cgit v1.2.3 From b58b98704f6b2d2b4a5938f5a8b87eda268ad88b Mon Sep 17 00:00:00 2001 From: Michael Lizzio Date: Mon, 10 Nov 2025 16:09:57 -0500 Subject: Fixed not updateing database on undo/redo --- .../design/controller/userinput/UndoActions.java | 51 ++++++++++++++++++++++ .../controller/userinput/menus/HolePlayMenu.java | 35 ++++++++++----- .../controller/userinput/menus/MainMenu.java | 19 ++------ .../controller/userinput/menus/SelectUser.java | 2 + 4 files changed, 80 insertions(+), 27 deletions(-) create mode 100644 src/main/java/design/controller/userinput/UndoActions.java (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/UndoActions.java b/src/main/java/design/controller/userinput/UndoActions.java new file mode 100644 index 0000000..6417284 --- /dev/null +++ b/src/main/java/design/controller/userinput/UndoActions.java @@ -0,0 +1,51 @@ +package design.controller.userinput; + +import design.model.undo.UndoManager; +import design.persistence.PersonalDatabase; +import design.runtime.Session; +import java.io.IOException; + +public final class UndoActions { + + private UndoActions() { + } + + public static void undoWithSave() { + UndoManager um = UndoManager.instance(); + if (!um.canUndo()) { + System.out.println("Nothing to undo."); + return; + } + + String label = um.peekUndoLabel(); + um.undo(); + System.out.println("Undo: " + label); + + saveCurrentGolfer(); + } + + public static void redoWithSave() { + UndoManager um = UndoManager.instance(); + if (!um.canRedo()) { + System.out.println("Nothing to redo."); + return; + } + + String label = um.peekRedoLabel(); + um.redo(); + System.out.println("Redo: " + label); + + saveCurrentGolfer(); + } + + private static void saveCurrentGolfer() { + try { + var g = Session.getCurrentGolfer(); + if (g != null) { + PersonalDatabase.instance().updateGolfer(g); + } + } catch (IOException e) { + System.err.println("Failed to save after undo/redo: " + e.getMessage()); + } + } +} diff --git a/src/main/java/design/controller/userinput/menus/HolePlayMenu.java b/src/main/java/design/controller/userinput/menus/HolePlayMenu.java index 2a7fc5d..6651500 100644 --- a/src/main/java/design/controller/userinput/menus/HolePlayMenu.java +++ b/src/main/java/design/controller/userinput/menus/HolePlayMenu.java @@ -11,6 +11,7 @@ import design.model.Round; import design.model.holeplay.HolePlayContext; import design.persistence.PersonalDatabase; import design.model.undo.UndoManager; +import design.controller.userinput.UndoActions; import java.util.ArrayList; import java.util.List; @@ -37,17 +38,37 @@ public class HolePlayMenu extends Menu { public List getMenuOptions() { List opts = new ArrayList<>(); + // End round (always shown) 1 + opts.add(new MenuOption("end round", () -> { + UndoManager.instance().capture(golfer, "End round on " + round.getCourse().getName()); + ctx.endRoundNow(); + System.out.println("Round ended."); + new MainMenu().present(); + })); + + // 2 + opts.add(new MenuOption("undo", () -> { + UndoActions.undoWithSave(); + this.present(); + })); + + // 3 + opts.add(new MenuOption("redo", () -> { + UndoActions.redoWithSave(); + this.present(); + })); + boolean inSetup = (ctx.getCurrentPlay() == null); if (inSetup) { - // 0) Start hole + // 4) Start hole opts.add(new MenuOption("start hole", () -> { ctx.startHole(); System.out.println("Started hole " + round.getCurrentHole().getNumber() + "."); this.present(); })); } else { - // 0) Take a shot + // 4) Take a shot opts.add(new MenuOption("take a shot", () -> { var selector = new SelectClub(); selector.present(); @@ -72,7 +93,7 @@ public class HolePlayMenu extends Menu { this.present(); })); - // 1) Hole out + // 5) Hole out opts.add(new MenuOption("hole out", () -> { // Precedes to next hole int prev = round.getCurrentHole().getNumber(); @@ -85,14 +106,6 @@ public class HolePlayMenu extends Menu { })); } - // End round (always shown) - opts.add(new MenuOption("end round", () -> { - UndoManager.instance().capture(golfer, "End round on " + round.getCourse().getName()); - ctx.endRoundNow(); - System.out.println("Round ended."); - new MainMenu().present(); - })); - return opts; } diff --git a/src/main/java/design/controller/userinput/menus/MainMenu.java b/src/main/java/design/controller/userinput/menus/MainMenu.java index 07caffa..4a221f0 100644 --- a/src/main/java/design/controller/userinput/menus/MainMenu.java +++ b/src/main/java/design/controller/userinput/menus/MainMenu.java @@ -2,7 +2,7 @@ package design.controller.userinput.menus; import design.controller.userinput.Menu; import design.controller.userinput.MenuOption; -import design.model.undo.UndoManager; +import design.controller.userinput.UndoActions; import java.util.List; @@ -14,27 +14,14 @@ public class MainMenu extends Menu { @Override public List getMenuOptions() { - - UndoManager um = UndoManager.instance(); - return List.of( new MenuOption("quit", () -> System.exit(0)), new MenuOption("undo", () -> { - if (!um.canUndo()) { - System.out.println("Nothing to undo."); - } else { - System.out.println("Undo: " + um.peekUndoLabel()); - um.undo(); - } + UndoActions.undoWithSave(); this.present(); }), new MenuOption("redo", () -> { - if (!um.canRedo()) { - System.out.println("Nothing to redo."); - } else { - System.out.println("Redo: " + um.peekRedoLabel()); - um.redo(); - } + UndoActions.redoWithSave(); this.present(); }), new MenuOption("user settings...", () -> new UserSettings().present()), diff --git a/src/main/java/design/controller/userinput/menus/SelectUser.java b/src/main/java/design/controller/userinput/menus/SelectUser.java index 4b7928c..a2c7071 100644 --- a/src/main/java/design/controller/userinput/menus/SelectUser.java +++ b/src/main/java/design/controller/userinput/menus/SelectUser.java @@ -6,6 +6,7 @@ import design.controller.userinput.MenuOption; import design.model.Golfer; import design.runtime.Session; import design.persistence.PersonalDatabase; +import design.model.undo.UndoManager; import java.io.IOException; import java.util.ArrayList; @@ -61,6 +62,7 @@ public class SelectUser extends Menu { if (g.checkPassword(password)) { // Sets user in Session too Session.setCurrentGolfer(g); + UndoManager.instance().purge(); System.out.printf("Loaded user: %s%n", g); doAfter.onAction(); } else { -- cgit v1.2.3 From fcf058c1999e4d23fd9e79e021901dbb39095367 Mon Sep 17 00:00:00 2001 From: Jacob Shimp Date: Tue, 11 Nov 2025 08:48:38 -0500 Subject: Added list of matches --- src/main/java/design/model/League.java | 3 ++- src/main/java/design/model/ScrambleLeague.java | 8 ++++---- src/main/java/design/model/StrokeLeague.java | 8 ++++---- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/model/League.java b/src/main/java/design/model/League.java index 0252f89..6621513 100644 --- a/src/main/java/design/model/League.java +++ b/src/main/java/design/model/League.java @@ -3,6 +3,7 @@ package design.model; import com.fasterxml.jackson.annotation.JsonCreator; import java.util.Date; +import java.util.List; public abstract class League { private int id; @@ -13,7 +14,7 @@ public abstract class League { private final Golfer owner; @JsonCreator - protected League(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner) { + protected League(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner, List schedule) { this.id = id; this.name = name; this.registrationDate = registrationDate; diff --git a/src/main/java/design/model/ScrambleLeague.java b/src/main/java/design/model/ScrambleLeague.java index 7ff966e..92e7099 100644 --- a/src/main/java/design/model/ScrambleLeague.java +++ b/src/main/java/design/model/ScrambleLeague.java @@ -10,13 +10,13 @@ public class ScrambleLeague extends League { private final List participants; @JsonCreator - private ScrambleLeague(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner, List participants) { - super(id, name, registrationDate, startDate, endDate, owner); + private ScrambleLeague(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner, List participants, List schedule) { + super(id, name, registrationDate, startDate, endDate, owner, schedule); this.participants = participants; } - public ScrambleLeague(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner) { - super(id, name, registrationDate, startDate, endDate, owner); + public ScrambleLeague(String name, Date registrationDate, Date startDate, Date endDate, Golfer owner) { + super(name, registrationDate, startDate, endDate, owner); this.participants = new ArrayList<>(); } diff --git a/src/main/java/design/model/StrokeLeague.java b/src/main/java/design/model/StrokeLeague.java index 6bdde0a..f09cabf 100644 --- a/src/main/java/design/model/StrokeLeague.java +++ b/src/main/java/design/model/StrokeLeague.java @@ -10,13 +10,13 @@ public class StrokeLeague extends League { private final List participants; @JsonCreator - private StrokeLeague(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner, List participants) { - super(id, name, registrationDate, startDate, endDate, owner); + private StrokeLeague(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner, List participants, List schedule) { + super(id, name, registrationDate, startDate, endDate, owner, schedule); this.participants = participants; } - public StrokeLeague(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner) { - super(id, name, registrationDate, startDate, endDate, owner); + public StrokeLeague(String name, Date registrationDate, Date startDate, Date endDate, Golfer owner) { + super(name, registrationDate, startDate, endDate, owner); this.participants = new ArrayList<>(); } -- cgit v1.2.3 From e334e4f87f8826bd3827e3dbd2179de30b42d828 Mon Sep 17 00:00:00 2001 From: Michael Lizzio Date: Tue, 11 Nov 2025 08:48:56 -0500 Subject: Added isGuest to Session and updated menus --- .../controller/userinput/menus/MainMenu.java | 43 +++++++++------ .../controller/userinput/menus/SelectUser.java | 7 +++ .../controller/userinput/menus/UserSettings.java | 62 ++++++++++++---------- src/main/java/design/runtime/Session.java | 10 ++++ 4 files changed, 78 insertions(+), 44 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/MainMenu.java b/src/main/java/design/controller/userinput/menus/MainMenu.java index 4a221f0..8a30258 100644 --- a/src/main/java/design/controller/userinput/menus/MainMenu.java +++ b/src/main/java/design/controller/userinput/menus/MainMenu.java @@ -3,6 +3,7 @@ package design.controller.userinput.menus; import design.controller.userinput.Menu; import design.controller.userinput.MenuOption; import design.controller.userinput.UndoActions; +import design.runtime.Session; import java.util.List; @@ -14,20 +15,32 @@ public class MainMenu extends Menu { @Override public List getMenuOptions() { - return List.of( - new MenuOption("quit", () -> System.exit(0)), - new MenuOption("undo", () -> { - UndoActions.undoWithSave(); - this.present(); - }), - new MenuOption("redo", () -> { - UndoActions.redoWithSave(); - this.present(); - }), - new MenuOption("user settings...", () -> new UserSettings().present()), - new MenuOption("manage courses...", () -> new ManageCourses().present()), - new MenuOption("manage clubs...", () -> new ManageClubs().present()), - new MenuOption("statistics...", () -> new StatisticsMenu().present()), - new MenuOption("log round...", () -> new HolePlayMenu().present())); + boolean guest = Session.isGuest(); + if (guest) { + return List.of( + new MenuOption("quit", () -> System.exit(0)), + new MenuOption("guest settings...", () -> new UserSettings().present()), + new MenuOption("browse courses...", () -> new SearchMenu().present()) + + ); + } else { + return List.of( + new MenuOption("quit", () -> System.exit(0)), + new MenuOption("undo", () -> { + UndoActions.undoWithSave(); + this.present(); + }), + new MenuOption("redo", () -> { + UndoActions.redoWithSave(); + this.present(); + }), + new MenuOption("user settings...", () -> new UserSettings().present()), + new MenuOption("manage courses...", () -> new ManageCourses().present()), + new MenuOption("manage clubs...", () -> new ManageClubs().present()), + new MenuOption("statistics...", () -> new StatisticsMenu().present()), + new MenuOption("log round...", () -> new HolePlayMenu().present()) + + ); + } } } diff --git a/src/main/java/design/controller/userinput/menus/SelectUser.java b/src/main/java/design/controller/userinput/menus/SelectUser.java index a2c7071..9ca2104 100644 --- a/src/main/java/design/controller/userinput/menus/SelectUser.java +++ b/src/main/java/design/controller/userinput/menus/SelectUser.java @@ -19,6 +19,7 @@ public class SelectUser extends Menu { private final Scanner scanner = new Scanner(System.in); public SelectUser(Action doAfter) { + Session.setGuest(false); this.doAfter = doAfter; } @@ -53,6 +54,12 @@ public class SelectUser extends Menu { this.present(); })); + opts.add(new MenuOption("", () -> { + Session.setCurrentGolfer(null); + Session.setGuest(true); + doAfter.onAction(); + })); + return opts; } diff --git a/src/main/java/design/controller/userinput/menus/UserSettings.java b/src/main/java/design/controller/userinput/menus/UserSettings.java index 36d8d70..1b2082d 100644 --- a/src/main/java/design/controller/userinput/menus/UserSettings.java +++ b/src/main/java/design/controller/userinput/menus/UserSettings.java @@ -27,6 +27,8 @@ public class UserSettings extends Menu { @Override public List getMenuOptions() { + boolean guest = Session.isGuest(); + var opts = new ArrayList(); opts.add(new MenuOption("return to main menu", () -> new MainMenu().present())); @@ -36,35 +38,37 @@ public class UserSettings extends Menu { new SelectUser(doAfter).present(); })); - opts.add(new MenuOption("set password...", () -> { - UndoManager.instance().capture(golfer, "Change password for @" + golfer.getUsername()); - - System.out.print("Enter password: "); - var password = scanner.nextLine(); - - golfer.setPassword(password); - try { - personalDatabase.updateGolfer(golfer); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - this.present(); - })); - - opts.add(new MenuOption("set full name...", () -> { - UndoManager.instance().capture(golfer, "Change full name for @" + golfer.getUsername()); - - System.out.print("Enter full name: "); - var fullName = scanner.nextLine(); - - golfer.setFullName(fullName); - try { - personalDatabase.updateGolfer(golfer); - } catch (IOException ex) { - throw new RuntimeException(ex); - } - this.present(); - })); + if (!guest) { + opts.add(new MenuOption("set password...", () -> { + UndoManager.instance().capture(golfer, "Change password for @" + golfer.getUsername()); + + System.out.print("Enter password: "); + var password = scanner.nextLine(); + + golfer.setPassword(password); + try { + personalDatabase.updateGolfer(golfer); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + this.present(); + })); + + opts.add(new MenuOption("set full name...", () -> { + UndoManager.instance().capture(golfer, "Change full name for @" + golfer.getUsername()); + + System.out.print("Enter full name: "); + var fullName = scanner.nextLine(); + + golfer.setFullName(fullName); + try { + personalDatabase.updateGolfer(golfer); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + this.present(); + })); + } return opts; } diff --git a/src/main/java/design/runtime/Session.java b/src/main/java/design/runtime/Session.java index 59d31d8..3af22e4 100644 --- a/src/main/java/design/runtime/Session.java +++ b/src/main/java/design/runtime/Session.java @@ -7,6 +7,7 @@ import java.time.LocalDateTime; public final class Session { private static Golfer currentGolfer; private static LocalDateTime timeOverride; + private static boolean isGuest = false; public static Golfer getCurrentGolfer() { return currentGolfer; @@ -23,4 +24,13 @@ public final class Session { public static void setTimeOverride(LocalDateTime timeOverride) { Session.timeOverride = timeOverride; } + + public static boolean isGuest() { + return isGuest; + } + + public static void setGuest(boolean g) { + isGuest = g; + } + } -- cgit v1.2.3 From be1e79c8b1196e61a3dc9b4b052f886243460ceb Mon Sep 17 00:00:00 2001 From: Michael Lizzio Date: Tue, 11 Nov 2025 08:55:58 -0500 Subject: setGuest to false on setCurrentGolfer --- src/main/java/design/controller/userinput/menus/SelectUser.java | 1 - src/main/java/design/runtime/Session.java | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/SelectUser.java b/src/main/java/design/controller/userinput/menus/SelectUser.java index 9ca2104..6931a4b 100644 --- a/src/main/java/design/controller/userinput/menus/SelectUser.java +++ b/src/main/java/design/controller/userinput/menus/SelectUser.java @@ -19,7 +19,6 @@ public class SelectUser extends Menu { private final Scanner scanner = new Scanner(System.in); public SelectUser(Action doAfter) { - Session.setGuest(false); this.doAfter = doAfter; } diff --git a/src/main/java/design/runtime/Session.java b/src/main/java/design/runtime/Session.java index 3af22e4..5b00e67 100644 --- a/src/main/java/design/runtime/Session.java +++ b/src/main/java/design/runtime/Session.java @@ -14,6 +14,7 @@ public final class Session { } public static void setCurrentGolfer(Golfer currentGolfer) { + Session.setGuest(false); Session.currentGolfer = currentGolfer; } -- cgit v1.2.3 From a0b662eccc6422348a1016dc71b8262eeeeee78f Mon Sep 17 00:00:00 2001 From: Jacob Shimp Date: Tue, 11 Nov 2025 09:02:20 -0500 Subject: working with matches in league --- src/main/java/design/model/League.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/main') diff --git a/src/main/java/design/model/League.java b/src/main/java/design/model/League.java index 6621513..6dab033 100644 --- a/src/main/java/design/model/League.java +++ b/src/main/java/design/model/League.java @@ -2,6 +2,7 @@ package design.model; import com.fasterxml.jackson.annotation.JsonCreator; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -12,6 +13,7 @@ public abstract class League { private final Date startDate; private final Date endDate; private final Golfer owner; + private List schedule; @JsonCreator protected League(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner, List schedule) { @@ -21,6 +23,7 @@ public abstract class League { this.startDate = startDate; this.endDate = endDate; this.owner = owner; + this.schedule = schedule; } public League(String name, Date registrationDate, Date startDate, Date endDate, Golfer owner) { @@ -30,6 +33,7 @@ public abstract class League { this.startDate = startDate; this.endDate = endDate; this.owner = owner; + this.schedule = new ArrayList<>(); } public int getId() { @@ -56,6 +60,18 @@ public abstract class League { return owner; } + public List getSchedule() { + return schedule; + } + + public void addMatchToSchedule(Match match) { + Date date = match.getDateScheduled(); + if(date.after(endDate)){ + throw new IllegalArgumentException("Cannot create match after league has ended"); + } + schedule.add(match); + } + public void setId(int id) { assert this.id == -1; this.id = id; -- cgit v1.2.3 From 9a0949d31a7a0e8c9c311b07e92852cff867cc66 Mon Sep 17 00:00:00 2001 From: sowgro Date: Wed, 12 Nov 2025 12:55:12 -0500 Subject: Fix some serialization stuff --- src/main/java/design/model/League.java | 19 +++++++++++++++---- src/main/java/design/model/ScrambleLeague.java | 12 ++++++++++++ src/main/java/design/model/StrokeLeague.java | 2 ++ .../java/design/persistence/JSONLeagueDatabase.java | 4 +++- .../java/design/persistence/JSONPersonalDatabase.java | 4 +++- 5 files changed, 35 insertions(+), 6 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/model/League.java b/src/main/java/design/model/League.java index 6dab033..881e25f 100644 --- a/src/main/java/design/model/League.java +++ b/src/main/java/design/model/League.java @@ -1,11 +1,22 @@ package design.model; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; import java.util.ArrayList; import java.util.Date; import java.util.List; +@JsonTypeInfo( + use = JsonTypeInfo.Id.NAME, + include = JsonTypeInfo.As.PROPERTY, + property = "type" +) +@JsonSubTypes({ + @JsonSubTypes.Type(value = ScrambleLeague.class, name = "scramble"), + @JsonSubTypes.Type(value = StrokeLeague.class, name = "stroke") +}) public abstract class League { private int id; private final String name; @@ -13,7 +24,7 @@ public abstract class League { private final Date startDate; private final Date endDate; private final Golfer owner; - private List schedule; + private final List schedule; @JsonCreator protected League(int id, String name, Date registrationDate, Date startDate, Date endDate, Golfer owner, List schedule) { @@ -23,7 +34,7 @@ public abstract class League { this.startDate = startDate; this.endDate = endDate; this.owner = owner; - this.schedule = schedule; + this.schedule = schedule != null ? schedule : new ArrayList<>(); } public League(String name, Date registrationDate, Date startDate, Date endDate, Golfer owner) { @@ -60,8 +71,8 @@ public abstract class League { return owner; } - public List getSchedule() { - return schedule; + public Match[] getSchedule() { + return schedule.toArray(Match[]::new); } public void addMatchToSchedule(Match match) { diff --git a/src/main/java/design/model/ScrambleLeague.java b/src/main/java/design/model/ScrambleLeague.java index 92e7099..d372264 100644 --- a/src/main/java/design/model/ScrambleLeague.java +++ b/src/main/java/design/model/ScrambleLeague.java @@ -1,11 +1,14 @@ package design.model; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.List; +@JsonTypeName("scramble") public class ScrambleLeague extends League { private final List participants; @@ -31,4 +34,13 @@ public class ScrambleLeague extends League { public Team[] getParticipants() { return participants.toArray(Team[]::new); } + + public Team locateTeam(Golfer golfer) { + for (Team participant : participants) { + if (List.of(participant.getMembers()).contains(golfer)) { + return participant; + } + } + return null; + } } diff --git a/src/main/java/design/model/StrokeLeague.java b/src/main/java/design/model/StrokeLeague.java index f09cabf..2b787b5 100644 --- a/src/main/java/design/model/StrokeLeague.java +++ b/src/main/java/design/model/StrokeLeague.java @@ -1,11 +1,13 @@ package design.model; import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; import java.util.ArrayList; import java.util.Date; import java.util.List; +@JsonTypeName("stroke") public class StrokeLeague extends League { private final List participants; diff --git a/src/main/java/design/persistence/JSONLeagueDatabase.java b/src/main/java/design/persistence/JSONLeagueDatabase.java index 8b201e6..8a55065 100644 --- a/src/main/java/design/persistence/JSONLeagueDatabase.java +++ b/src/main/java/design/persistence/JSONLeagueDatabase.java @@ -3,7 +3,9 @@ package design.persistence; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.StreamReadFeature; import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; @@ -36,7 +38,7 @@ public class JSONLeagueDatabase implements LeagueDatabase { public JSONLeagueDatabase(String filename) { this.file = new File(filename); this.cache = new HashMap<>(); - this.mapper = new ObjectMapper(); + this.mapper = JsonMapper.builder().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION).build(); SimpleModule module = new SimpleModule(); module.addDeserializer(Course.class, new Serializers.CourseIdDeserializer()); diff --git a/src/main/java/design/persistence/JSONPersonalDatabase.java b/src/main/java/design/persistence/JSONPersonalDatabase.java index 0e95437..30c280a 100644 --- a/src/main/java/design/persistence/JSONPersonalDatabase.java +++ b/src/main/java/design/persistence/JSONPersonalDatabase.java @@ -3,7 +3,9 @@ package design.persistence; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.StreamReadFeature; import com.fasterxml.jackson.databind.*; +import com.fasterxml.jackson.databind.json.JsonMapper; import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.fasterxml.jackson.module.paramnames.ParameterNamesModule; @@ -34,7 +36,7 @@ public class JSONPersonalDatabase implements PersonalDatabase { private JSONPersonalDatabase(String filename) { this.file = new File(filename); this.cache = new HashMap<>(); - this.mapper = new ObjectMapper(); + this.mapper = JsonMapper.builder().enable(StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION).build();; // TODO: Once the saved JSON matches the model, consider removing. // TEMP: tolerate unknown props while the model stabilizes -- cgit v1.2.3 From af23c48329b749ba3d0a4fcd841723d55a16ae95 Mon Sep 17 00:00:00 2001 From: sowgro Date: Wed, 12 Nov 2025 12:57:08 -0500 Subject: stub out some menus --- .../controller/userinput/menus/LeageMenu.java | 30 ++++++++ .../controller/userinput/menus/MainMenu.java | 3 +- .../controller/userinput/menus/SelectLeague.java | 83 ++++++++++++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/main/java/design/controller/userinput/menus/LeageMenu.java create mode 100644 src/main/java/design/controller/userinput/menus/SelectLeague.java (limited to 'src/main') diff --git a/src/main/java/design/controller/userinput/menus/LeageMenu.java b/src/main/java/design/controller/userinput/menus/LeageMenu.java new file mode 100644 index 0000000..d9afa91 --- /dev/null +++ b/src/main/java/design/controller/userinput/menus/LeageMenu.java @@ -0,0 +1,30 @@ +package design.controller.userinput.menus; + +import design.controller.userinput.Menu; +import design.controller.userinput.MenuOption; +import design.model.League; + +import java.util.ArrayList; +import java.util.List; + +public class LeageMenu extends Menu { + private final League league; + + public LeageMenu(League league) { + this.league = league; + } + + @Override + public String getTitle() { + return "League Menu"; + } + + @Override + public List getMenuOptions() { + List options = new ArrayList<>(); + options.add(new MenuOption("statistics...", () -> {})); + options.add(new MenuOption("leaderboard...", () -> {})); + options.add(new MenuOption("log round...", () -> {})); + return options; + } +} diff --git a/src/main/java/design/controller/userinput/menus/MainMenu.java b/src/main/java/design/controller/userinput/menus/MainMenu.java index 7522ceb..e476997 100644 --- a/src/main/java/design/controller/userinput/menus/MainMenu.java +++ b/src/main/java/design/controller/userinput/menus/MainMenu.java @@ -19,7 +19,8 @@ public class MainMenu extends Menu { new MenuOption("manage courses...", () -> new ManageCourses().present()), new MenuOption("manage clubs...", () -> new ManageClubs().present()), new MenuOption("statistics...", () -> new StatisticsMenu().present()), - new MenuOption("log round...", () -> new HolePlayMenu().present()) + new MenuOption("log round...", () -> new HolePlayMenu().present()), + new MenuOption("League play...", () -> new SelectLeague().present()) ); } } diff --git a/src/main/java/design/controller/userinput/menus/SelectLeague.java b/src/main/java/design/controller/userinput/menus/SelectLeague.java new file mode 100644 index 0000000..08f6c91 --- /dev/null +++ b/src/main/java/design/controller/userinput/menus/SelectLeague.java @@ -0,0 +1,83 @@ +package design.controller.userinput.menus; + +import design.controller.userinput.Menu; +import design.controller.userinput.MenuOption; +import design.model.Golfer; +import design.model.League; +import design.model.ScrambleLeague; +import design.model.StrokeLeague; +import design.persistence.LeagueDatabase; +import design.runtime.Session; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; + +public class SelectLeague extends Menu { + private final Golfer golfer = Session.getCurrentGolfer(); + + @Override + public String getTitle() { + return "Select League"; + } + + @Override + public List getMenuOptions() { + List options = new ArrayList<>(); + for (League l : LeagueDatabase.instance().getLeagues()) { + options.add(new MenuOption(l.getName(), () -> { + if (l instanceof ScrambleLeague sl && sl.locateTeam(golfer) == null) { + Scanner sc = new Scanner(System.in); + System.out.print("You are not a member of a team for this league. Would you like to create one (Y/n): "); + if (sc.next().equals("n")) { + new MainMenu().present(); + } else { + // create team + } + } else { + new LeageMenu(l).present(); + } + })); + } + options.add(new MenuOption("", this::createLeagueWizard)); + return options; + } + + private void createLeagueWizard() { + try { + Scanner scanner = new Scanner(System.in); + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); + + System.out.print("Enter league name: "); + String name = scanner.nextLine(); + + System.out.print("Enter registration date (yyyy-MM-dd): "); + Date registrationDate = dateFormat.parse(scanner.nextLine()); + + System.out.print("Enter start date (yyyy-MM-dd): "); + Date startDate = dateFormat.parse(scanner.nextLine()); + + System.out.print("Enter end date (yyyy-MM-dd): "); + Date endDate = dateFormat.parse(scanner.nextLine()); + + Golfer owner = Session.getCurrentGolfer(); + + System.out.print("Enter format (stroke/scramble): "); + String scramble = scanner.nextLine(); + + League league; + switch (scramble) { + case "scramble" -> league = new ScrambleLeague(name, registrationDate, startDate, endDate, owner); + case "stroke" -> league = new StrokeLeague(name, registrationDate, startDate, endDate, owner); + default -> throw new RuntimeException(); + } + LeagueDatabase.instance().addLeague(league); + } catch (ParseException ex) { + System.out.println("Invalid format"); + } catch (IOException ex) { + System.out.println("Error writing to file"); + } + this.present(); + } +} -- cgit v1.2.3 From 43530df067b1132b944e9619bdf60b72264829ec Mon Sep 17 00:00:00 2001 From: sowgro Date: Thu, 13 Nov 2025 08:22:39 -0500 Subject: fix constructor --- src/main/java/design/model/Golfer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/main') diff --git a/src/main/java/design/model/Golfer.java b/src/main/java/design/model/Golfer.java index 0f4c914..870b460 100644 --- a/src/main/java/design/model/Golfer.java +++ b/src/main/java/design/model/Golfer.java @@ -89,9 +89,9 @@ public class Golfer implements Originator { rounds.add(round); } - public Club addClub(String manufacture, String nickname, Club.ClubType type) { - Club c = new Club(nextClubId++, manufacture, nickname, type); + public Club addClub(Club c) { clubs.add(c); + c.setId(nextClubId++); return c; } -- cgit v1.2.3