From b9a6badadf9c0ab9f1f90913bdc2b8eb3de28e66 Mon Sep 17 00:00:00 2001 From: Debucquoy Date: Sun, 19 Mar 2023 22:24:59 +0100 Subject: [PATCH] WIP: Refactoring file parser --- app/build.gradle | 1 + .../BinaryParser.java} | 85 +++++++++++-------- .../school_project/Parsers/FileParser.java | 23 +++++ .../Parsers/FileParserFactory.java | 43 ++++++++++ .../school_project/Parsers/TxtParser.java | 13 +++ 5 files changed, 128 insertions(+), 37 deletions(-) rename app/src/main/java/school_project/{MapParser.java => Parsers/BinaryParser.java} (74%) create mode 100644 app/src/main/java/school_project/Parsers/FileParser.java create mode 100644 app/src/main/java/school_project/Parsers/FileParserFactory.java create mode 100644 app/src/main/java/school_project/Parsers/TxtParser.java diff --git a/app/build.gradle b/app/build.gradle index 3f8d793..52532f1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -9,6 +9,7 @@ plugins { // Apply the application plugin to add support for building a CLI application in Java. id 'application' + id 'checkstyle' id 'org.openjfx.javafxplugin' version '0.0.13' } diff --git a/app/src/main/java/school_project/MapParser.java b/app/src/main/java/school_project/Parsers/BinaryParser.java similarity index 74% rename from app/src/main/java/school_project/MapParser.java rename to app/src/main/java/school_project/Parsers/BinaryParser.java index adac1a4..0486f72 100644 --- a/app/src/main/java/school_project/MapParser.java +++ b/app/src/main/java/school_project/Parsers/BinaryParser.java @@ -1,52 +1,24 @@ -package school_project; +package school_project.Parsers; +import school_project.Map; +import school_project.Piece; import school_project.Utils.Bitwise; import java.io.*; import java.util.Arrays; -public class MapParser { +public class BinaryParser implements FileParser { - /** - * Parse the file and create a Map with its shape and pieces setup - * @param file file to parse - * @return Map Object parsed with file data - * @see "TODO: Add Specification when done" - */ - public static Map ParseMapFile(File file) throws IllegalArgumentException, IllegalAccessException, IOException { + public Map getLevel(File file) throws IOException { Map ret; - // Get the file and check that this file exists and can be read FileInputStream fileStream = new FileInputStream(file); - if(!file.isFile()) throw new IllegalArgumentException("The argument should be a file"); - if(!file.canRead()) throw new IllegalAccessException("This file can't be read"); - // Read the file an array of byte, then look for the HEADER (SMS) and then the FOOTER (SME) - // Then Put everything that is in between in level_data[] - byte[] bytes = fileStream.readAllBytes(); - int start_position = 0, end_position = 0; - for (int i = 0; i < bytes.length; i++) { - if(bytes[i] == 83 && bytes[i+1] == 77 && bytes[i+2] == 83){ // SMS - start_position = i+3; - break; - } - } + byte[] level_data = ExtractLevelData(fileStream); - for (int i = start_position; i < bytes.length; i++) { - if(bytes[i] == 83 && bytes[i+1] == 77 && bytes[i+2] == 69){ // SME - end_position = i; - break; - } - } - byte[] level_data = Arrays.copyOfRange(bytes, start_position, end_position); - - // Get the 2 first byte as the map width and height - // Then get the map data. This map data is every bit of the byte that represent either a true if it is a 1 or false if it is a 0 - int map_width = level_data[0], map_height = level_data[1]; - byte[] map_data = Arrays.copyOfRange(level_data, 2, 2 + map_width * map_height / 8 + (map_height * map_width % 8 != 0 ? 1 : 0)); - boolean[][] map_matrix = BuildMatrixFromBytes(map_width, map_height, map_data); - ret = new Map(map_matrix); + ret = new Map(ExtractMapFromLevelData(level_data)); + // TODO: 3/18/23 Cursor: have to make this into a method // Get the amount of pieces // For each of these pieces, get the size of the piece on 1 octet, 4 byte are for width then 4 byte are for height // the same method as the map is used to get the piece shape. @@ -67,6 +39,45 @@ public class MapParser { return ret; } + /** + * Get the Map Matrix out of the level data + * @param level_data full data of the level without header and footer + * @return boolean matrix of the map + */ + private static boolean[][] ExtractMapFromLevelData(byte[] level_data){ + int map_width = level_data[0], map_height = level_data[1]; + byte[] map_data = Arrays.copyOfRange(level_data, 2, 2 + map_width * map_height / 8 + (map_height * map_width % 8 != 0 ? 1 : 0)); + return BuildMatrixFromBytes(map_width, map_height, map_data); + } + + /** + * Extract Level data from file content + * @param fileStream + * @return Level data as an array of byte + * @throws IOException Expected if we can't read the file + */ + private static byte[] ExtractLevelData(FileInputStream fileStream) throws IOException { + + byte[] bytes = fileStream.readAllBytes(); + + int start_position = 0, end_position = 0; + for (int i = 0; i < bytes.length; i++) { + if(bytes[i] == 83 && bytes[i+1] == 77 && bytes[i+2] == 83){ // SMS + start_position = i+3; + break; + } + } + + for (int i = start_position; i < bytes.length; i++) { + if(bytes[i] == 83 && bytes[i+1] == 77 && bytes[i+2] == 69){ // SME + end_position = i; + break; + } + } + + return Arrays.copyOfRange(bytes, start_position, end_position); + } + /** * Build a boolean Matrix From a byte array * Each Byte is composed of 8 bit, each bit is 1 or 0 @@ -98,4 +109,4 @@ public class MapParser { } return ret; } -} +} \ No newline at end of file diff --git a/app/src/main/java/school_project/Parsers/FileParser.java b/app/src/main/java/school_project/Parsers/FileParser.java new file mode 100644 index 0000000..c0459f1 --- /dev/null +++ b/app/src/main/java/school_project/Parsers/FileParser.java @@ -0,0 +1,23 @@ +package school_project.Parsers; + +import school_project.Map; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; + +public interface FileParser { + + /** + * Parse the file and create a Map with its shape and pieces setup + * Ignore the rest of the file! (ie: save data) + * + * @param file file to parse + * @return Map Object parsed with file data + * @see "TODO: Add Specification when done" + */ + Map getLevel(File file) throws IOException; + + // TODO: 3/18/23 tonitch: Add getSavedData, for when piece could be added to map file + +} diff --git a/app/src/main/java/school_project/Parsers/FileParserFactory.java b/app/src/main/java/school_project/Parsers/FileParserFactory.java new file mode 100644 index 0000000..e50c1ee --- /dev/null +++ b/app/src/main/java/school_project/Parsers/FileParserFactory.java @@ -0,0 +1,43 @@ +package school_project.Parsers; + +import java.io.File; +import java.io.NotSerializableException; + +/** + * This is used to find the right parser to parser a save/level file. + * + *

+ * Mor file format can be added in the future by adding a new class that implement parser and making it recognisable by + * the CreateParser class + *

+ * + * @author tonitch + */ +public class FileParserFactory { + public static FileParser createParser(File file) throws NotSerializableException{ + if(isBinaryFile(file)) + return new BinaryParser(); + else if (isTextFile(file)) + return new TxtParser(); + else + throw new NotSerializableException("This file format is not supported"); + } + + /** + * Check if the file is a binary file suited for parsing + * @return true if it is a binary File + */ + private static boolean isBinaryFile(File file){ + // TODO: 3/18/23 + return false; + } + + /** + * Check if the file is a text file + * @return true if it is a text File + */ + private static boolean isTextFile(File file){ + return false; + // TODO: 3/18/23 + } +} diff --git a/app/src/main/java/school_project/Parsers/TxtParser.java b/app/src/main/java/school_project/Parsers/TxtParser.java new file mode 100644 index 0000000..aefd6f6 --- /dev/null +++ b/app/src/main/java/school_project/Parsers/TxtParser.java @@ -0,0 +1,13 @@ +package school_project.Parsers; + +import school_project.Map; + +import java.io.File; + +public class TxtParser implements FileParser{ + @Override + public Map getLevel(File file) { + return null; + // TODO: 3/18/23 + } +}