2323import javafx .scene .image .ImageView ;
2424import javafx .scene .layout .HBox ;
2525import javafx .scene .layout .StackPane ;
26-
26+ /**
27+ * Controller for the Anagram puzzle screen.
28+ * Handles UI binding, difficulty configuration, hints/attempts tracking,
29+ * saving and loading progress per user, and basic UI actions (submit, hint,
30+ * save, quit).
31+ */
2732public class AnagramPuzzleController implements Initializable {
2833
2934 @ FXML private StackPane rootPane ;
@@ -47,7 +52,17 @@ public class AnagramPuzzleController implements Initializable {
4752 private static final String DEV_FALLBACK = "file:/mnt/data/Screenshot 2025-11-22 202825.png" ;
4853
4954 private String chosenDifficulty = "MEDIUM" ;
50-
55+ /**
56+ * Initialize controller after FXML is loaded.
57+ * Reads chosen difficulty from the application, configures puzzle state,
58+ * binds background image sizing, refreshes UI elements, and attempts to
59+ * load saved progress for the current user. If saved state indicates the
60+ * puzzle is solved or attempts exhausted, the save is cleared and the
61+ * puzzle is reset.
62+ *
63+ * @param location location used to resolve relative paths
64+ * @param resources resources bundle
65+ */
5166 @ Override
5267 public void initialize (URL location , ResourceBundle resources ) {
5368 System .out .println ("AnagramPuzzleController.initialize() start" );
@@ -116,7 +131,11 @@ public void initialize(URL location, ResourceBundle resources) {
116131
117132 System .out .println ("AnagramPuzzleController.initialize() done (difficulty=" + chosenDifficulty + ")" );
118133 }
119-
134+
135+ /**
136+ * Configure puzzle variables for a given difficulty.
137+ * @param difficulty difficulty string (case insensitive)
138+ */
120139 private void configureForDifficulty (String difficulty ) {
121140 switch (String .valueOf (difficulty ).toUpperCase ()) {
122141 case "EASY" :
@@ -177,7 +196,13 @@ private void configureForDifficulty(String difficulty) {
177196 if (promptLabel != null ) promptLabel .setText ("Prompt: " + PROMPT );
178197 if (hintsLabel != null ) hintsLabel .setText (hintsLeft + " hint(s) available" );
179198 }
180-
199+ /**
200+ * Determine the save file for the current user.
201+ * Attempts to get a user id from App.getCurrentUser(); falls back to
202+ * {@code guest} if unavailable. The filename includes difficulty so each
203+ * difficulty has its own save file per user.
204+ * @return File object pointing to the user's save file in the user's home directory.
205+ */
181206 private File getSaveFileForCurrentUser () {
182207 String userId = "guest" ;
183208 try {
@@ -210,7 +235,11 @@ private File getSaveFileForCurrentUser() {
210235 String filename = ".escapegame_anagram_" + clean + "_" + chosenDifficulty .toLowerCase () + ".properties" ;
211236 return new File (System .getProperty ("user.home" ), filename );
212237 }
213-
238+ /**
239+ * Refresh heart icons that show remaining attempts.
240+ * Clears the hearts box and adds one heart per remaining attempt. If
241+ * attempts are exhausted, disables submit and answer field.
242+ */
214243 private void refreshHearts () {
215244 if (heartsBox == null ) return ;
216245 heartsBox .getChildren ().clear ();
@@ -224,7 +253,11 @@ private void refreshHearts() {
224253 if (answerField != null ) answerField .setDisable (true );
225254 }
226255 }
227-
256+ /**
257+ * Handler for the Submit button.
258+ * Normalizes user input, checks against accepted answers, handles
259+ * win/lose logic, updates UI, shows alerts, and saves progress.
260+ */
228261 @ FXML
229262 private void onSubmit () {
230263 if (solved ) {
@@ -267,7 +300,12 @@ private void onSubmit() {
267300 }
268301 }
269302 }
270-
303+
304+ /**
305+ * Handler for the Hint button.
306+ * Shows the next hint, if available , decrements hints left, updates UI,
307+ * and saves progress.
308+ */
271309 @ FXML
272310 private void onHint () {
273311 if (solved ) {
@@ -286,17 +324,26 @@ private void onHint() {
286324 new Alert (Alert .AlertType .INFORMATION , hint ).showAndWait ();
287325 saveProgress ();
288326 }
289-
327+ /**
328+ * Handler for the Save button.
329+ * Attempts to save progress and shows a short status message.
330+ */
290331 @ FXML
291332 private void onSave () {
292333 if (statusLabel != null ) statusLabel .setText (saveProgress () ? "Progress saved." : "Save failed." );
293334 }
294-
335+ /**
336+ * Handler for the Quit button.
337+ * Switches to the previous view using App.setRoot
338+ */
295339 @ FXML
296340 private void onQuit () {
297341 try { App .setRoot ("opened4" ); } catch (IOException e ) { e .printStackTrace (); }
298342 }
299-
343+ /**
344+ * Persist current progress to the user's save file.
345+ * @return true if save succeeded, false on error
346+ */
300347 private boolean saveProgress () {
301348 try {
302349 Properties p = new Properties ();
@@ -315,7 +362,11 @@ private boolean saveProgress() {
315362 return false ;
316363 }
317364 }
318-
365+ /**
366+ * Load saved progress from the user's save file, if present.
367+ * Updates attemptsLeft, hintsLeft, solved and nextHintIndex from the
368+ * file and refreshes relevant UI elements.
369+ */
319370 private void loadSave () {
320371 try {
321372 File f = getSaveFileForCurrentUser ();
@@ -347,7 +398,12 @@ private void loadSave() {
347398 System .err .println ("Load save failed: " + e .getMessage ());
348399 }
349400 }
350-
401+ /**
402+ * Parse an integer from a string, returning a fallback on parse failure.
403+ * @param s fallback string to parse
404+ * @param fallback value to return if parse fails
405+ * @return parsed integer or fallback
406+ */
351407 private int getSafeInt (String s , int fallback ) {
352408 if (s == null ) return fallback ;
353409 try { return Integer .parseInt (s .trim ()); }
@@ -356,7 +412,13 @@ private int getSafeInt(String s, int fallback) {
356412 return fallback ;
357413 }
358414 }
359-
415+ /**
416+ * Normalize a raw input string for comparison.
417+ * Performs Unicode normalization, lowercasing, removes punctuation,
418+ * trims whitespace, and strips leading articles ("a", "an", "the").
419+ * @param raw raw input
420+ * @return normalized string
421+ */
360422 private static String normalize (String raw ) {
361423 if (raw == null ) return "" ;
362424 String n = Normalizer .normalize (raw , Normalizer .Form .NFKC )
@@ -369,7 +431,10 @@ private static String normalize(String raw) {
369431 else if (n .startsWith ("the " )) n = n .substring (4 ).trim ();
370432 return n ;
371433 }
372-
434+ /**
435+ * Delete the user's save file for this puzzle/difficulty.
436+ * @return true if the file was deleted or didn't exist; false if deletion failed
437+ */
373438 private boolean clearSaveForCurrentUser () {
374439 File f = getSaveFileForCurrentUser ();
375440 if (f .exists ()) {
0 commit comments