summaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorWillem Dalton <144246261+WillemDalton@users.noreply.github.com>2025-10-08 22:12:30 -0400
committerGitHub <noreply@github.com>2025-10-08 22:12:30 -0400
commit924fc4730aed92a0dc909fd10d2d3bc02a29e845 (patch)
treec09b5932dc8bea16469439fcc0bcce1cb4cfb808 /src/main/java
parent88564fc1e48ec1efbbfc91e99339b781146a9a75 (diff)
parentbf6b01e5005618e6ccdfb4217311a8f94dd5a0dd (diff)
downloaddesignproject-design-6-924fc4730aed92a0dc909fd10d2d3bc02a29e845.tar.gz
designproject-design-6-924fc4730aed92a0dc909fd10d2d3bc02a29e845.tar.bz2
designproject-design-6-924fc4730aed92a0dc909fd10d2d3bc02a29e845.zip
Merge branch 'main' into course-search
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/design/ParPal.java5
-rw-r--r--src/main/java/design/controller/userinput/Action.java2
-rw-r--r--src/main/java/design/controller/userinput/Menu.java8
-rw-r--r--src/main/java/design/controller/userinput/MenuOption.java4
-rw-r--r--src/main/java/design/controller/userinput/menus/AddClubMenu.java77
-rw-r--r--src/main/java/design/controller/userinput/menus/CourseSelectMenu.java78
-rw-r--r--src/main/java/design/controller/userinput/menus/HolePlayMenu.java45
-rw-r--r--src/main/java/design/controller/userinput/menus/MainMenu.java10
-rw-r--r--src/main/java/design/controller/userinput/menus/SelectUser.java60
-rw-r--r--src/main/java/design/controller/userinput/menus/StatisticsMenu.java2
-rw-r--r--src/main/java/design/controller/userinput/menus/UserSettings.java55
-rw-r--r--src/main/java/design/model/Club.java13
-rw-r--r--src/main/java/design/model/Golfer.java19
13 files changed, 318 insertions, 60 deletions
diff --git a/src/main/java/design/ParPal.java b/src/main/java/design/ParPal.java
index 4ed6949..6ea9872 100644
--- a/src/main/java/design/ParPal.java
+++ b/src/main/java/design/ParPal.java
@@ -1,9 +1,12 @@
package design;
+import design.controller.userinput.Action;
import design.controller.userinput.menus.MainMenu;
+import design.controller.userinput.menus.SelectUser;
public class ParPal {
public static void main(String[] args) {
- new MainMenu().present();
+ Action doAfter = () -> new MainMenu().present();
+ new SelectUser(doAfter).present();
}
}
diff --git a/src/main/java/design/controller/userinput/Action.java b/src/main/java/design/controller/userinput/Action.java
index 0b52bfc..2c95b2b 100644
--- a/src/main/java/design/controller/userinput/Action.java
+++ b/src/main/java/design/controller/userinput/Action.java
@@ -2,5 +2,5 @@ package design.controller.userinput;
@FunctionalInterface
public interface Action {
- void onCommand(String[] args);
+ void onAction();
}
diff --git a/src/main/java/design/controller/userinput/Menu.java b/src/main/java/design/controller/userinput/Menu.java
index 605b640..0b2fb26 100644
--- a/src/main/java/design/controller/userinput/Menu.java
+++ b/src/main/java/design/controller/userinput/Menu.java
@@ -9,18 +9,20 @@ public abstract class Menu {
public void present() {
var menuOptions = getMenuOptions();
+ System.out.println();
System.out.printf("-- %s --\n", getTitle().toUpperCase());
for (int i = 0; i < menuOptions.size(); i++) {
MenuOption menuOption = menuOptions.get(i);
System.out.printf("%s: %s\n", i, menuOption.getName());
}
+
+ System.out.print("Selection: ");
Scanner sc = new Scanner(System.in);
var line = sc.nextLine();
- var split = line.split(" ");
try {
- int i = Integer.parseInt(split[0]);
- menuOptions.get(i).onCommand(Arrays.copyOfRange(split, 1, split.length));
+ int i = Integer.parseInt(line);
+ menuOptions.get(i).onAction();
} catch (ArrayIndexOutOfBoundsException ex) {
System.err.printf("Invalid option \"%s\"\n", line);
present();
diff --git a/src/main/java/design/controller/userinput/MenuOption.java b/src/main/java/design/controller/userinput/MenuOption.java
index 9635ebd..f5707a9 100644
--- a/src/main/java/design/controller/userinput/MenuOption.java
+++ b/src/main/java/design/controller/userinput/MenuOption.java
@@ -13,7 +13,7 @@ public class MenuOption {
return name;
}
- public void onCommand(String[] args) {
- action.onCommand(args);
+ public void onAction() {
+ action.onAction();
}
}
diff --git a/src/main/java/design/controller/userinput/menus/AddClubMenu.java b/src/main/java/design/controller/userinput/menus/AddClubMenu.java
new file mode 100644
index 0000000..ea18ed5
--- /dev/null
+++ b/src/main/java/design/controller/userinput/menus/AddClubMenu.java
@@ -0,0 +1,77 @@
+package design.controller.userinput.menus;
+
+import design.controller.userinput.Menu;
+import design.controller.userinput.MenuOption;
+import design.model.Club;
+import design.model.Golfer;
+import design.persistence.PersonalDatabase;
+import design.runtime.Session;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Scanner;
+
+public class AddClubMenu extends Menu {
+
+ @Override
+ public String getTitle() {
+ return "add a club";
+ }
+
+ @Override
+ public List<MenuOption> getMenuOptions() {
+ List<MenuOption> opts = new ArrayList<>();
+
+ opts.add(new MenuOption("create new club", () -> {
+ Golfer g = Session.getCurrentGolfer();
+ if (g == null) {
+ System.out.println("No user loaded.");
+ new UserSettings().present();
+ return;
+ }
+
+ Scanner sc = new Scanner(System.in);
+
+ System.out.print("Manufacturer: ");
+ String manufacture = sc.nextLine().trim();
+
+ System.out.print("Nickname: ");
+ String nickname = sc.nextLine().trim();
+
+ // Pick type
+ Club.ClubType[] types = Club.ClubType.values();
+ System.out.println("Club type:");
+ for (int i = 0; i < types.length; i++) {
+ System.out.printf("%d: %s%n", i + 1, types[i]);
+ }
+
+ Club.ClubType type = null;
+ while (type == null) {
+ System.out.print("Select (1.." + types.length + "): ");
+ String line = sc.nextLine().trim();
+ int idx = Integer.parseInt(line);
+ if (idx < 1 || idx > types.length) {
+ System.out.println("Out of range. Try again.");
+ continue;
+ }
+ type = types[idx - 1];
+ }
+
+ g.addClub(manufacture, nickname, type);
+
+ // Add club to JSON
+ try {
+ PersonalDatabase.INSTANCE.updateGolfer(g);
+ System.out.println("Club added and saved.");
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to save club", e);
+ }
+ new UserSettings().present();
+ }));
+
+ opts.add(new MenuOption("cancel", () -> new UserSettings().present()));
+ return opts;
+ }
+}
diff --git a/src/main/java/design/controller/userinput/menus/CourseSelectMenu.java b/src/main/java/design/controller/userinput/menus/CourseSelectMenu.java
index 881c393..af825e0 100644
--- a/src/main/java/design/controller/userinput/menus/CourseSelectMenu.java
+++ b/src/main/java/design/controller/userinput/menus/CourseSelectMenu.java
@@ -26,27 +26,75 @@ public class CourseSelectMenu extends Menu {
List<MenuOption> opts = new ArrayList<>();
// 0) back
- opts.add(new MenuOption("back to main menu", a -> new MainMenu().present()));
+ opts.add(new MenuOption("back to main menu", () -> new MainMenu().present()));
- // 1) pick course by number TODO: add error checking
- opts.add(new MenuOption("pick course by number (1..1000)", a -> {
- Scanner sc = new Scanner(System.in);
-
- System.out.print("Course number (1..1000): ");
- int n = Integer.parseInt(sc.nextLine().trim());
- Course c = MasterDatabase.INSTANCE.getCourse(n - 1);
+ // 1) go to CourseSearchMenu to search for a course and add it profile
+ opts.add(new MenuOption("Add Course to Profile", () -> new MainMenu().present()));
- System.out.print("Starting hole (1..18, blank=1): ");
- String s = sc.nextLine().trim();
- int start = s.isEmpty() ? 1 : Integer.parseInt(s);
+ // 2) pick course from MY PROFILE only
+ opts.add(new MenuOption("pick course from my profile", () -> {
+ var golfer = Session.getCurrentGolfer();
+ Course[] mine = (golfer == null) ? new Course[0] : golfer.getCourses();
- Hole startHole = c.getHoles().get(start - 1);
+ // Checks user has courses of not informs them to add one to there profile
+ if (mine == null || mine.length == 0) {
+ System.out.println("You don't have any courses saved to your profile yet.");
+ System.out.println("Use the 'Add Course to Profile' menu first.");
+ this.present();
+ return;
+ }
+ // Select a course
+ Scanner sc = new Scanner(System.in);
- Round r = new Round(c, LocalDateTime.now(), startHole);
- Session.getCurrentGolfer().addRound(r);
- new HolePlayMenu(r).present();
+ // Prints all courses
+ System.out.println("-- MY COURSES --");
+ for (int i = 0; i < mine.length; i++) {
+ Course c = mine[i];
+ System.out.printf("%d: %s (%s) | Holes: %d | Total Par: %d | Difficulty: %.1f%n",
+ i + 1, c.getName(), c.getLocation(), c.getHoleCount(), c.getTotalPar(),
+ c.getDifficultyRating());
+ }
+ // Select course by number
+ Course selected = null;
+ while (selected == null) {
+ System.out.print("Select course # (1.." + mine.length + "): ");
+ String line = sc.nextLine().trim();
+ int idx = Integer.parseInt(line);
+ if (idx < 1 || idx > mine.length) {
+ System.out.println("Out of range. Try again.");
+ continue;
+ }
+ selected = mine[idx - 1];
+ }
+ // Gets starting hole on course
+ int startHoleNum = readStartingHole(sc, selected.getHoleCount());
+ // Starts round and sends user to HolePlayMenu
+ startRound(selected, startHoleNum);
}));
return opts;
}
+
+ private int readStartingHole(Scanner sc, int holeCount) {
+ // Asks for a hole number until a valid number is selected
+ while (true) {
+ System.out.print("Starting hole (1.." + holeCount + ", blank=1): ");
+ String s = sc.nextLine().trim();
+ if (s.isEmpty())
+ return 1;
+ int start = Integer.parseInt(s);
+ if (start < 1 || start > holeCount) {
+ System.out.println("Starting hole must be between 1 and " + holeCount + ".");
+ continue;
+ }
+ return start;
+ }
+ }
+
+ private void startRound(Course c, int startHoleNum) {
+ Hole startHole = c.getHoles().get(startHoleNum - 1);
+ Round r = new Round(c, LocalDateTime.now(), startHole);
+ Session.getCurrentGolfer().addRound(r);
+ new HolePlayMenu(r).present();
+ }
}
diff --git a/src/main/java/design/controller/userinput/menus/HolePlayMenu.java b/src/main/java/design/controller/userinput/menus/HolePlayMenu.java
index bcd7560..14e5345 100644
--- a/src/main/java/design/controller/userinput/menus/HolePlayMenu.java
+++ b/src/main/java/design/controller/userinput/menus/HolePlayMenu.java
@@ -36,21 +36,46 @@ public class HolePlayMenu extends Menu {
if (inSetup) {
// 0) Start hole
- opts.add(new MenuOption("start hole", (a) -> {
+ opts.add(new MenuOption("start hole", () -> {
ctx.startHole();
System.out.println("Started hole " + round.getCurrentHole().getNumber() + ".");
this.present();
}));
} else {
// 0) Take a shot
- opts.add(new MenuOption("take a shot", (a) -> {
- // Gets club
+ opts.add(new MenuOption("take a shot", () -> {
+ // loads golfers clubs
+ var golfer = Session.getCurrentGolfer();
+ Club[] clubs = (golfer == null) ? new Club[0] : golfer.getClubs();
+
+ if (clubs.length == 0) {
+ System.out.println("You don't have any clubs yet. Add one first.");
+ new AddClubMenu().present();
+ this.present();
+ return;
+ }
+
+ // list clubs
+ System.out.println("-- YOUR CLUBS --");
+ for (int i = 0; i < clubs.length; i++) {
+ Club c = clubs[i];
+ System.out.printf("%d: #%d %s - %s (%s)%n",
+ i + 1, c.getId(), c.getNickname(), c.getManufacture(), c.getClubType());
+ }
+
+ // user selects one of their clubs
Scanner sc = new Scanner(System.in);
- System.out.print("Club nickname: ");
- String nick = sc.nextLine().trim();
- // Defaulted to Driver for now
- // TODO update logic
- Club club = new Club("Generic", nick, Club.ClubType.DRIVER);
+ Club club = null;
+ while (club == null) {
+ System.out.print("Select club # (1.." + clubs.length + "): ");
+ String line = sc.nextLine().trim();
+ int idx = Integer.parseInt(line);
+ if (idx < 1 || idx > clubs.length) {
+ System.out.println("Out of range. Try again.");
+ continue;
+ }
+ club = clubs[idx - 1];
+ }
// Get shot distance (defaults to 0 of not stated)
System.out.print("Distance (yds, blank=0): ");
@@ -68,7 +93,7 @@ public class HolePlayMenu extends Menu {
}));
// 1) Hole out
- opts.add(new MenuOption("hole out", (a) -> {
+ opts.add(new MenuOption("hole out", () -> {
// Precedes to next hole
int prev = round.getCurrentHole().getNumber();
ctx.holeOut();
@@ -78,7 +103,7 @@ public class HolePlayMenu extends Menu {
}
// End round (always shown)
- opts.add(new MenuOption("end round", (a) -> {
+ opts.add(new MenuOption("end round", () -> {
ctx.endRoundNow();
System.out.println("Round ended.");
new MainMenu().present();
diff --git a/src/main/java/design/controller/userinput/menus/MainMenu.java b/src/main/java/design/controller/userinput/menus/MainMenu.java
index 8ee872e..71a93b0 100644
--- a/src/main/java/design/controller/userinput/menus/MainMenu.java
+++ b/src/main/java/design/controller/userinput/menus/MainMenu.java
@@ -14,10 +14,10 @@ public class MainMenu extends Menu {
@Override
public List<MenuOption> getMenuOptions() {
return List.of(
- new MenuOption("user settings...", (a) -> new UserSettings().present()),
- new MenuOption("add course to profile...", (a) -> new SearchMenu().present()),
- new MenuOption("statistics...", (a) -> new StatisticsMenu().present()),
- new MenuOption("log round...", (a) -> new CourseSelectMenu().present()),
- new MenuOption("quit", (a) -> {}));
+ new MenuOption("user settings...", () -> new UserSettings().present()),
+ new MenuOption("add course to profile...", () -> new SearchMenu().present()),
+ new MenuOption("statistics...", () -> new StatisticsMenu().present()),
+ new MenuOption("log round...", () -> new CourseSelectMenu().present()),
+ new MenuOption("quit", () -> {}));
}
}
diff --git a/src/main/java/design/controller/userinput/menus/SelectUser.java b/src/main/java/design/controller/userinput/menus/SelectUser.java
index 2f1a867..ffae559 100644
--- a/src/main/java/design/controller/userinput/menus/SelectUser.java
+++ b/src/main/java/design/controller/userinput/menus/SelectUser.java
@@ -1,16 +1,25 @@
package design.controller.userinput.menus;
+import design.controller.userinput.Action;
import design.controller.userinput.Menu;
import design.controller.userinput.MenuOption;
+import design.model.Golfer;
import design.runtime.Session;
import design.persistence.PersonalDatabase;
+import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
+import java.util.Scanner;
public class SelectUser extends Menu {
- PersonalDatabase personalDB = PersonalDatabase.INSTANCE;
+ private final PersonalDatabase personalDB = PersonalDatabase.INSTANCE;
+ private final Action doAfter;
+ private final Scanner scanner = new Scanner(System.in);
+
+ public SelectUser(Action doAfter) {
+ this.doAfter = doAfter;
+ }
@Override
public String getTitle() {
@@ -19,15 +28,44 @@ public class SelectUser extends Menu {
@Override
public List<MenuOption> getMenuOptions() {
- var l = new ArrayList<MenuOption>();
- // Sets user in Session too
- l.addAll(Arrays.stream(personalDB.getGolfers()).map(i -> new MenuOption(i.getUsername(), (a) -> {
- Session.setCurrentGolfer(i);
- System.out.printf("Loaded user: %s%n", i.getUsername());
- new UserSettings().present();
- })).toList());
- l.add(new MenuOption("<create>", (a) -> {
+ var opts = new ArrayList<MenuOption>();
+
+ for (Golfer i : personalDB.getGolfers()) {
+ MenuOption menuOption = new MenuOption(i.getUsername(), () -> {
+ System.out.print("Enter password: ");
+ var password = scanner.nextLine();
+ if (i.checkPassword(password)) {
+ // Sets user in Session too
+ Session.setCurrentGolfer(i);
+ System.out.printf("Loaded user: %s%n", i.getUsername());
+ doAfter.onAction();
+ } else {
+ System.out.println("Incorrect password. ");
+ this.present();
+ }
+ });
+ opts.add(menuOption);
+ }
+
+ opts.add(new MenuOption("<create>", () -> {
+
+ System.out.print("Enter username: ");
+ var username = scanner.nextLine();
+
+ System.out.print("Enter full name: ");
+ var fullName = scanner.nextLine();
+
+ System.out.print("Enter password: ");
+ var password = scanner.nextLine();
+
+ try {
+ personalDB.addGolfer(new Golfer(fullName, username, password));
+ } catch (IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ this.present();
}));
- return l;
+
+ return opts;
}
}
diff --git a/src/main/java/design/controller/userinput/menus/StatisticsMenu.java b/src/main/java/design/controller/userinput/menus/StatisticsMenu.java
index 66d60e3..c609177 100644
--- a/src/main/java/design/controller/userinput/menus/StatisticsMenu.java
+++ b/src/main/java/design/controller/userinput/menus/StatisticsMenu.java
@@ -15,7 +15,7 @@ public class StatisticsMenu extends Menu {
@Override
public List<MenuOption> getMenuOptions() {
return List.of(
- new MenuOption("return to main menu", (c) -> new MainMenu().present())
+ new MenuOption("return to main menu", () -> new MainMenu().present())
);
}
}
diff --git a/src/main/java/design/controller/userinput/menus/UserSettings.java b/src/main/java/design/controller/userinput/menus/UserSettings.java
index a866889..34b645d 100644
--- a/src/main/java/design/controller/userinput/menus/UserSettings.java
+++ b/src/main/java/design/controller/userinput/menus/UserSettings.java
@@ -1,12 +1,23 @@
package design.controller.userinput.menus;
+import design.controller.userinput.Action;
import design.controller.userinput.Menu;
import design.controller.userinput.MenuOption;
+import design.model.Golfer;
+import design.persistence.PersonalDatabase;
+import design.runtime.Session;
+import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Scanner;
public class UserSettings extends Menu {
+ private final Golfer golfer = Session.getCurrentGolfer();
+ private final PersonalDatabase personalDatabase = PersonalDatabase.INSTANCE;
+ private final Scanner scanner = new Scanner(System.in);
+
@Override
public String getTitle() {
return "user settings";
@@ -14,11 +25,43 @@ public class UserSettings extends Menu {
@Override
public List<MenuOption> getMenuOptions() {
- return List.of(
- new MenuOption("return to main menu", (a) -> new MainMenu().present()),
- new MenuOption("switch user...", (a) -> new SelectUser().present()),
- new MenuOption("set username...", (a -> {})),
- new MenuOption("set password...", (a) -> {})
- );
+ var opts = new ArrayList<MenuOption>();
+
+ opts.add(new MenuOption("return to main menu", () -> new MainMenu().present()));
+
+ opts.add(new MenuOption("switch user...", () -> {
+ Action doAfter = this::present;
+ new SelectUser(doAfter).present();
+ }));
+
+ opts.add(new MenuOption("set password...", () -> {
+ 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...", () -> {
+ 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();
+ }));
+
+ opts.add(new MenuOption("add a club...", () -> new AddClubMenu().present()));
+
+ return opts;
}
}
diff --git a/src/main/java/design/model/Club.java b/src/main/java/design/model/Club.java
index 57a43d1..9fa3c87 100644
--- a/src/main/java/design/model/Club.java
+++ b/src/main/java/design/model/Club.java
@@ -13,16 +13,22 @@ public class Club {
PUTTER
}
+ private final int id;
private final String manufacture;
private final String nickname;
private final ClubType clubType;
- public Club(String manufacture, String nickname, ClubType clubType) {
+ public Club(int id, String manufacture, String nickname, ClubType clubType) {
+ this.id = id;
this.manufacture = manufacture;
this.nickname = nickname;
this.clubType = clubType;
}
+ public int getId() {
+ return id;
+ }
+
public String getManufacture() {
return manufacture;
}
@@ -34,4 +40,9 @@ public class Club {
public ClubType getClubType() {
return clubType;
}
+
+ @Override
+ public String toString() {
+ return String.format("#%d %s - %s (%s)", id, nickname, manufacture, clubType);
+ }
}
diff --git a/src/main/java/design/model/Golfer.java b/src/main/java/design/model/Golfer.java
index 19d6ac6..d34073f 100644
--- a/src/main/java/design/model/Golfer.java
+++ b/src/main/java/design/model/Golfer.java
@@ -11,15 +11,19 @@ public class Golfer {
private String fullName;
private final List<Course> courses;
private final List<Round> rounds;
- private final List<Club> clubs = new ArrayList<>(); // Keep track of golfer's clubs
+ private final List<Club> clubs; // Keep track of golfer's clubs
+ private int nextClubId = 1;
@JsonCreator
- private Golfer(String username, int passwordHash, String fullName, List<Course> courses, List<Round> rounds) {
+ private Golfer(String username, int passwordHash, String fullName, List<Course> courses, List<Round> rounds,
+ List<Club> clubs) {
this.username = username;
this.passwordHash = passwordHash;
this.fullName = fullName;
this.courses = courses;
this.rounds = rounds;
+ this.clubs = clubs;
+ this.nextClubId = this.clubs.stream().mapToInt(Club::getId).max().orElse(0) + 1;
}
public Golfer(String fullName, String username, String password) {
@@ -28,6 +32,8 @@ public class Golfer {
this.passwordHash = password.hashCode();
this.courses = new ArrayList<>();
this.rounds = new ArrayList<>();
+ this.clubs = new ArrayList<>();
+ this.nextClubId = 1;
}
public String getUsername() {
@@ -74,12 +80,17 @@ public class Golfer {
rounds.add(round);
}
- // Helpers dealing with clubs
- public void addClub(Club c) {
+ public Club addClub(String manufacture, String nickname, Club.ClubType type) {
+ Club c = new Club(nextClubId++, manufacture, nickname, type);
clubs.add(c);
+ return c;
}
public boolean hasClub(Club c) {
return clubs.contains(c);
}
+
+ public Club[] getClubs() {
+ return clubs.toArray(Club[]::new);
+ }
}