diff --git a/src/main/java/edu/ntnu/idatt2003/Controller/MainPageController.java b/src/main/java/edu/ntnu/idatt2003/Controller/MainPageController.java index 19bdf780bdb71e8b7a9114d9214c36e297645a77..f4890b24a425d31e459092a5dfb1e66bea5fd524 100644 --- a/src/main/java/edu/ntnu/idatt2003/Controller/MainPageController.java +++ b/src/main/java/edu/ntnu/idatt2003/Controller/MainPageController.java @@ -6,12 +6,20 @@ import edu.ntnu.idatt2003.model.ChaosGameFileHandler; import edu.ntnu.idatt2003.view.MainPageView; import java.io.File; -import java.io.FileNotFoundException; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.FileNotFoundException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.util.InputMismatchException; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; /** * The controller class for the main page of the ChaosGame application. @@ -23,6 +31,23 @@ public class MainPageController { private final MainPageView view; private static final String TRANSFORMATIONS_PATH = "src/main/resources/transformations/"; + private static final String SERIALIZED_GAME_PATH = "src/main/resources/savedTransformation.ser"; + private static final Logger LOGGER = Logger.getLogger(MainPageController.class.getName()); + + static { + try { + // Ensure the logs directory exists + new File("logs").mkdirs(); + + FileHandler fileHandler = new FileHandler("logs/application.log", false); + fileHandler.setFormatter(new SimpleFormatter()); + fileHandler.setLevel(Level.WARNING); + LOGGER.addHandler(fileHandler); + LOGGER.setLevel(Level.ALL); + } catch (IOException e) { + e.printStackTrace(); + } + } /** * The constructor for the MainPageController class. @@ -30,12 +55,12 @@ public class MainPageController { * and renders the view. */ public MainPageController() { - this.game = new ChaosGame(ChaosGameDescriptionFactory - .get(ChaosGameDescriptionFactory.descriptionTypeEnum.SIERPINSKI_TRIANGLE), - 600, 600); + this.game = loadGameState(); this.view = new MainPageView(this); this.game.registerObserver(view); this.view.render(); + Runtime.getRuntime().addShutdownHook(new Thread(this::saveGameState)); + LOGGER.log(Level.INFO, "MainPageController initialized successfully."); } /** @@ -64,6 +89,7 @@ public class MainPageController { */ public void runSteps(int steps) { game.runSteps(steps); + LOGGER.log(Level.INFO, "Chaos game simulation ran {0} steps successfully.", steps); } /** @@ -74,25 +100,21 @@ public class MainPageController { * @throws InputMismatchException If the file is not found or the input is invalid. */ public void uploadFile(File file) { - try { - validateFile(file); - if (!Files.exists(Path.of(TRANSFORMATIONS_PATH + file.getName())) - || view.askConfirmation("File already exists. Do you want to overwrite it?")) { - storeFile(file); - } - } catch (Exception e) { - view.showAlert(e.getMessage()); + LOGGER.log(Level.INFO, "Uploading file: {0}", file.getName()); + validateFile(file); + if (!Files.exists(Path.of(TRANSFORMATIONS_PATH + file.getName())) + || view.askConfirmation("File already exists. Do you want to overwrite it?")) { + storeFile(file); } + } - private void validateFile(File file) - throws InputMismatchException, FileNotFoundException { + private void validateFile(File file) { try { new ChaosGameFileHandler().readFromFile(file); - } catch (InputMismatchException e) { - throw new InputMismatchException(e.getMessage()); - } catch (FileNotFoundException e) { - throw new FileNotFoundException(e.getMessage()); + } catch (InputMismatchException | FileNotFoundException e) { + view.showAlert(e.getMessage()); + LOGGER.log(Level.WARNING, "Error uploading file. File was not uploaded."); } } @@ -107,10 +129,13 @@ public class MainPageController { String destinationPath = projectPath + File.separator + TRANSFORMATIONS_PATH + file.getName(); Files.copy(file.toPath(), Path.of(destinationPath), StandardCopyOption.REPLACE_EXISTING); + LOGGER.log(Level.INFO, "File stored successfully in {0}", destinationPath); } catch (IOException e) { - throw new InputMismatchException("Error copying file: " + e.getMessage()); + view.showAlert("Error storing file. Please try again."); + LOGGER.log(Level.WARNING, "Error storing file. File was not stored."); } } + /** * Change the transformation-type of the chaos game. * @@ -119,6 +144,39 @@ public class MainPageController { public void changeTransformation(ChaosGameDescriptionFactory .descriptionTypeEnum descriptionType) { game.changeTransformation(descriptionType); + LOGGER.log(Level.INFO, "Transformation was changed successfully to {0}" + , descriptionType); + } + + private void saveGameState() { + LOGGER.log(Level.INFO, "Saving game state."); + game.removeObserver(view); + try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SERIALIZED_GAME_PATH))) { + oos.writeObject(game); + LOGGER.log(Level.INFO, "Game state saved successfully in {0}", SERIALIZED_GAME_PATH); + } catch (IOException e) { + LOGGER.log(Level.WARNING, "Failed to save game state. Next time the application is" + + " started, the game will be launched in same game state as this time."); + } + } + + public ChaosGame loadGameState() { + LOGGER.log(Level.INFO, "Loading game state."); + File file = new File(SERIALIZED_GAME_PATH); + if (file.exists()) { + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { + ChaosGame loadedGame = (ChaosGame) ois.readObject(); + LOGGER.log(Level.INFO, "Game state loaded successfully."); + return loadedGame; + } catch (IOException | ClassNotFoundException e) { + LOGGER.log(Level.WARNING, "Failed to load game state. Creating new game."); + } + } else { + LOGGER.log(Level.WARNING, "No saved game state found. Creating new game."); + } + return new ChaosGame(ChaosGameDescriptionFactory + .get(ChaosGameDescriptionFactory.descriptionTypeEnum.SIERPINSKI_TRIANGLE), + 600, 600); } } diff --git a/src/main/java/edu/ntnu/idatt2003/model/AffineTransform2D.java b/src/main/java/edu/ntnu/idatt2003/model/AffineTransform2D.java index fd130834e780b3aa28f541750fb3574cefe05678..35d5520f4b2cee57bfb19fdbd9a89c2785e34289 100644 --- a/src/main/java/edu/ntnu/idatt2003/model/AffineTransform2D.java +++ b/src/main/java/edu/ntnu/idatt2003/model/AffineTransform2D.java @@ -1,5 +1,7 @@ package edu.ntnu.idatt2003.model; +import java.io.Serializable; + /** * Represents a 2-dimensional affine transformation. * Contains a constructor and a method for transforming a 2-dimensional vector. @@ -7,7 +9,7 @@ package edu.ntnu.idatt2003.model; * autor: nicklapt */ -public class AffineTransform2D implements Transform2D { +public class AffineTransform2D implements Transform2D, Serializable { /** * The 2x2 matrix of the affine transformation. diff --git a/src/main/java/edu/ntnu/idatt2003/model/ChaosCanvas.java b/src/main/java/edu/ntnu/idatt2003/model/ChaosCanvas.java index 9a2e64c9c224604b899accb24a59ea80d209868f..5a3ac1e30e58d6a741afd447e582a3f0c3a770c2 100644 --- a/src/main/java/edu/ntnu/idatt2003/model/ChaosCanvas.java +++ b/src/main/java/edu/ntnu/idatt2003/model/ChaosCanvas.java @@ -1,5 +1,7 @@ package edu.ntnu.idatt2003.model; +import java.io.Serializable; + /** * Class for creating a canvas for the chaos game. * Contains methods for converting coordinates to indices on the canvas, and for displaying the canvas. @@ -7,7 +9,7 @@ package edu.ntnu.idatt2003.model; * Goal: act as a model for a canvas for the chaos game. */ -public class ChaosCanvas { +public class ChaosCanvas implements Serializable { private final int[][] canvas; private final int width; diff --git a/src/main/java/edu/ntnu/idatt2003/model/ChaosGame.java b/src/main/java/edu/ntnu/idatt2003/model/ChaosGame.java index 517d3caec469c07dfa51df5f24cd9525a2cf7511..052773cb75db434f31eea07ce04075635e1601cc 100644 --- a/src/main/java/edu/ntnu/idatt2003/model/ChaosGame.java +++ b/src/main/java/edu/ntnu/idatt2003/model/ChaosGame.java @@ -1,5 +1,6 @@ package edu.ntnu.idatt2003.model; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Random; @@ -11,7 +12,7 @@ import java.util.Random; * Goal: act as a model for a chaos game. */ -public class ChaosGame { +public class ChaosGame implements Serializable { private ChaosCanvas canvas; private ChaosGameDescription description; diff --git a/src/main/java/edu/ntnu/idatt2003/model/ChaosGameDescription.java b/src/main/java/edu/ntnu/idatt2003/model/ChaosGameDescription.java index a1938d47bfcb0a49f5633545f34df0a167a60add..877d9e5b75e77699c87239104147246c7a133693 100644 --- a/src/main/java/edu/ntnu/idatt2003/model/ChaosGameDescription.java +++ b/src/main/java/edu/ntnu/idatt2003/model/ChaosGameDescription.java @@ -1,5 +1,6 @@ package edu.ntnu.idatt2003.model; +import java.io.Serializable; import java.util.List; /** @@ -8,7 +9,7 @@ import java.util.List; * the game, and the transformations to be used. * Goal: act as a model for a chaos game description. */ -public class ChaosGameDescription { +public class ChaosGameDescription implements Serializable { /** * The minimum (bottom left) coordinates of the game. */ diff --git a/src/main/java/edu/ntnu/idatt2003/model/Complex.java b/src/main/java/edu/ntnu/idatt2003/model/Complex.java index bb947e24c0a3989fcca978dc4663b2070d32729a..86752586bab99882f1c87be680aad2889e9658ff 100644 --- a/src/main/java/edu/ntnu/idatt2003/model/Complex.java +++ b/src/main/java/edu/ntnu/idatt2003/model/Complex.java @@ -1,5 +1,7 @@ package edu.ntnu.idatt2003.model; +import java.io.Serializable; + /** * Represents a subclass that extends the {@link Vector2d}. * It adds the additional functionality of finding the square root of a complex number. @@ -7,7 +9,7 @@ package edu.ntnu.idatt2003.model; * * @author svhaa */ -public class Complex extends Vector2d { +public class Complex extends Vector2d implements Serializable { /** * Constructs a Complex object. * diff --git a/src/main/java/edu/ntnu/idatt2003/model/JuliaTransform.java b/src/main/java/edu/ntnu/idatt2003/model/JuliaTransform.java index 7ad93e64d7a0e4c1af1adb3dab9dd01d5531731b..0ed9503bec436190bd53b27b5387c0757c865a40 100644 --- a/src/main/java/edu/ntnu/idatt2003/model/JuliaTransform.java +++ b/src/main/java/edu/ntnu/idatt2003/model/JuliaTransform.java @@ -1,5 +1,7 @@ package edu.ntnu.idatt2003.model; +import java.io.Serializable; + /** * Represents a Julia transformation applied to 2D vectors. * Contains a constructor and a method for transforming a 2D vector. @@ -7,7 +9,7 @@ package edu.ntnu.idatt2003.model; * * @author sverrgha */ -public class JuliaTransform implements Transform2D { +public class JuliaTransform implements Transform2D, Serializable { /** * The point to transform the 2D vector by. diff --git a/src/main/java/edu/ntnu/idatt2003/model/Matrix2x2.java b/src/main/java/edu/ntnu/idatt2003/model/Matrix2x2.java index b509c8eab44c4324f5e2e1960de349b6dd2ac8f0..7fafa8bf627362f5bb617e9fbc45ceff750175f5 100644 --- a/src/main/java/edu/ntnu/idatt2003/model/Matrix2x2.java +++ b/src/main/java/edu/ntnu/idatt2003/model/Matrix2x2.java @@ -1,5 +1,6 @@ package edu.ntnu.idatt2003.model; +import java.io.Serializable; import java.util.Locale; /** @@ -7,7 +8,7 @@ import java.util.Locale; * * @author nicklapt */ -public class Matrix2x2 { +public class Matrix2x2 implements Serializable { private final double a00; private final double a01; diff --git a/src/main/java/edu/ntnu/idatt2003/model/Vector2d.java b/src/main/java/edu/ntnu/idatt2003/model/Vector2d.java index c14168e0dd8245325bdb4ab1abe158c9ed399294..b6b449797a71dd80cb9f5dd0863204b5bd62e68e 100644 --- a/src/main/java/edu/ntnu/idatt2003/model/Vector2d.java +++ b/src/main/java/edu/ntnu/idatt2003/model/Vector2d.java @@ -1,5 +1,7 @@ package edu.ntnu.idatt2003.model; +import java.io.Serializable; + /** * Represents a 2-dimensional vector. * Contains a constructor and getters for the x0 and x1 attributes. @@ -8,7 +10,7 @@ package edu.ntnu.idatt2003.model; * * @author sverrgha */ -public class Vector2d { +public class Vector2d implements Serializable { /** * The first coordinate of the vector.