package design.model.holeplay; import java.io.IOException; import java.util.ArrayList; import design.model.*; import design.persistence.PersonalDatabase; 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; private HoleState state; private Play currentPlay; private int strokes; public HolePlayContext(Golfer golfer, Round round, PersonalDatabase pdb) { this.golfer = golfer; this.round = round; this.pdb = pdb; setState(new SetupState()); } public void setState(HoleState next) { this.state = next; next.enter(this); } // API the PTUI/Commands will call: public void startHole() { state.handleStart(this); } public void recordShot(Club club, Integer distanceYds) { state.handleShot(this, club, distanceYds); } public void holeOut() { state.handleHoleOut(this); } void beginNewPlay(int holeNumber) { this.currentPlay = new Play(holeNumber); this.strokes = 0; } void addSwing(Club club, Integer distanceYds) { // Checks golfer owns club maybe not necessary // if (golfer.hasClub(club)) { // throw new IllegalArgumentException("Club not in golfer's bag"); // } int d = (distanceYds == null ? 0 : distanceYds); this.currentPlay.addSwing(new Swing(d, club)); this.strokes++; } void finalizePlayAndPersist() { round.addPlay(currentPlay); round.nextHole(); currentPlay = null; strokes = 0; // Not sure if try catch is necessary try { pdb.updateGolfer(golfer); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public void clearInProgressPlay() { this.setCurrentPlay(null); this.setStrokes(0); } public void endRoundNow() { try { pdb.updateGolfer(golfer); // persist whatever’s done so far } catch (IOException e) { e.printStackTrace(); } setState(new SetupState()); } // getters you’ll want: public Golfer getGolfer() { return golfer; } public Round getRound() { return round; } public Play getCurrentPlay() { return currentPlay; } public int getStrokes() { return strokes; } // setters used internally void setCurrentPlay(Play p) { this.currentPlay = p; } void setStrokes(int s) { 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() { return new HolePlayMemento(this); } @Override 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(); } } }