266 lines
7.4 KiB
Java
266 lines
7.4 KiB
Java
package sudoku.io;
|
|
|
|
import java.io.File;
|
|
import java.io.FileWriter;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Paths;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
import org.json.JSONArray;
|
|
import org.json.JSONObject;
|
|
|
|
import sudoku.constraint.Constraint;
|
|
import sudoku.structure.Block;
|
|
import sudoku.structure.Cell;
|
|
import sudoku.structure.MultiDoku;
|
|
import sudoku.structure.Sudoku;
|
|
|
|
public class SudokuSerializer {
|
|
|
|
public static JSONObject serializeSudoku(final MultiDoku multidoku) {
|
|
List<Cell> cellIds = new ArrayList<>();
|
|
List<Block> blockIds = new ArrayList<>();
|
|
|
|
JSONObject jsonRoot = new JSONObject();
|
|
JSONArray jsonCells = new JSONArray();
|
|
JSONArray jsonBlocks = new JSONArray();
|
|
JSONArray jsonSudokus = new JSONArray(multidoku.getNbSubGrids());
|
|
|
|
for (int i = 0; i < multidoku.getNbSubGrids(); i++) {
|
|
Sudoku sudoku = multidoku.getSubGrid(i);
|
|
|
|
// init cells
|
|
for (Cell cell : sudoku.getCells()) {
|
|
if (cellIds.contains(cell))
|
|
continue;
|
|
|
|
cellIds.add(cell);
|
|
|
|
Block block = cell.getBlock();
|
|
if (!blockIds.contains(block)) {
|
|
blockIds.add(block);
|
|
}
|
|
|
|
int blockID = blockIds.indexOf(block);
|
|
assert(blockID >= 0);
|
|
int symbolIndex = cell.getSymbolIndex();
|
|
|
|
JSONObject cellJsonObject = new JSONObject();
|
|
cellJsonObject.put("blockID", blockID);
|
|
cellJsonObject.put("symbolIndex", symbolIndex);
|
|
if (!cell.isMutable()) {
|
|
cellJsonObject.put("immutable", true);
|
|
}
|
|
jsonCells.put(cellJsonObject);
|
|
}
|
|
|
|
}
|
|
|
|
// init blocks
|
|
|
|
for (Block blockId : blockIds) {
|
|
JSONObject blockJsonObject = new JSONObject();
|
|
JSONArray cellsJsonArray = new JSONArray();
|
|
for (Cell cell : blockId.getCells()) {
|
|
int cellID = cellIds.indexOf(cell);
|
|
assert (cellID >= 0);
|
|
cellsJsonArray.put(cellID);
|
|
}
|
|
blockJsonObject.put("cellIDs", cellsJsonArray);
|
|
jsonBlocks.put(blockJsonObject);
|
|
}
|
|
|
|
for (int i = 0; i < multidoku.getNbSubGrids(); i++) {
|
|
// serialise sub grid
|
|
JSONObject jsonSudoku = new JSONObject();
|
|
JSONArray cellsJsonArray = new JSONArray();
|
|
JSONArray blocksJsonArray = new JSONArray();
|
|
JSONArray constraintsJsonArray = new JSONArray();
|
|
|
|
Sudoku sudoku = multidoku.getSubGrid(i);
|
|
|
|
// serialize cells
|
|
|
|
for (Cell cell : sudoku.getCells()) {
|
|
int cellID = cellIds.indexOf(cell);
|
|
assert (cellID >= 0);
|
|
cellsJsonArray.put(cellID);
|
|
}
|
|
|
|
// serialize blocks
|
|
|
|
for (Block block : sudoku.getBlocks()) {
|
|
int blockID = blockIds.indexOf(block);
|
|
assert (blockID >= 0);
|
|
blocksJsonArray.put(blockID);
|
|
}
|
|
|
|
// serialize constraints
|
|
|
|
for (Constraint cons : sudoku.getConstraints()) {
|
|
constraintsJsonArray.put(cons.ordinal());
|
|
}
|
|
|
|
jsonSudoku.put("constraints", constraintsJsonArray);
|
|
jsonSudoku.put("cells", cellsJsonArray);
|
|
jsonSudoku.put("blocks", blocksJsonArray);
|
|
jsonSudoku.put("blockWidth", sudoku.getBlockWidth());
|
|
jsonSudokus.put(i, jsonSudoku);
|
|
}
|
|
|
|
jsonRoot.put("multidoku", jsonSudokus);
|
|
jsonRoot.put("cells", jsonCells);
|
|
jsonRoot.put("blocks", jsonBlocks);
|
|
|
|
return jsonRoot;
|
|
}
|
|
|
|
/**
|
|
* Save a serialized MultiDoku in a JSON file.
|
|
*
|
|
* @param doku MultiDoku, MultiDoku to save.
|
|
* @return String, the path of the save.
|
|
*/
|
|
public static String saveMultiDoku(final MultiDoku doku) {
|
|
JSONObject jsonRoot = serializeSudoku(doku);
|
|
File f = new File("save", "save.json");
|
|
int i = 0;
|
|
while (f.exists()) {
|
|
String newName = "save-" + ++i + ".json";
|
|
f = new File("save", newName);
|
|
}
|
|
try (FileWriter file = new FileWriter(f)) {
|
|
file.write(jsonRoot.toString(3));
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
return f.getAbsolutePath();
|
|
}
|
|
|
|
public static String saveMultiDoku(final MultiDoku doku, final int saveToOverwrite) {
|
|
File f;
|
|
if (saveToOverwrite == 0) {
|
|
f = new File("save", "save.json");
|
|
}
|
|
else {
|
|
f = new File("save", "save-" + saveToOverwrite + ".json");
|
|
}
|
|
if (!f.exists()) {
|
|
return saveMultiDoku(doku);
|
|
}
|
|
else {
|
|
try (FileWriter file = new FileWriter(f)) {
|
|
file.write(serializeSudoku(doku).toString(3));
|
|
} catch (IOException e) {
|
|
e.printStackTrace();
|
|
}
|
|
return f.getAbsolutePath();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get a MultiDoku from a pre-existing json save file.
|
|
*
|
|
* @param numberSave int, number of the save file to open.
|
|
* @return MultiDoku, MultoDoku contained in the file.
|
|
* @throws Exception when the given save file does not exist.
|
|
*/
|
|
public static MultiDoku getSavedMultiDoku(int numberSave) throws Exception {
|
|
String fileName;
|
|
if (numberSave < 1) {
|
|
fileName = "save.json";
|
|
} else {
|
|
fileName = "save-" + numberSave + ".json";
|
|
}
|
|
|
|
File f = new File("save", fileName);
|
|
String fileContent;
|
|
|
|
if (!f.exists()) {
|
|
throw new Exception("This save does not exist.");
|
|
} else {
|
|
fileContent = new String(Files.readAllBytes(Paths.get("save/" + fileName)));
|
|
return deserializeSudoku(fileContent);
|
|
}
|
|
}
|
|
|
|
public static MultiDoku deserializeSudoku(final String json) {
|
|
JSONObject jsonRoot = new JSONObject(json);
|
|
return deserializeSudoku(jsonRoot);
|
|
}
|
|
|
|
public static MultiDoku deserializeSudoku(final JSONObject jsonObject) {
|
|
|
|
List<Cell> cells = new ArrayList<>();
|
|
List<Block> blocks = new ArrayList<>();
|
|
List<Sudoku> sudokus = new ArrayList<>();
|
|
|
|
// init cells
|
|
JSONArray cellsJson = jsonObject.getJSONArray("cells");
|
|
for (int i = 0; i < cellsJson.length(); i++) {
|
|
JSONObject entry = cellsJson.getJSONObject(i);
|
|
int symbolIndex = entry.getInt("symbolIndex");
|
|
if (entry.has("immutable")) {
|
|
cells.add(new Cell(symbolIndex, false));
|
|
} else {
|
|
cells.add(new Cell(symbolIndex));
|
|
}
|
|
}
|
|
|
|
// init blocks
|
|
JSONArray blocksJson = jsonObject.getJSONArray("blocks");
|
|
for (int i = 0; i < blocksJson.length(); i++) {
|
|
JSONObject entry = blocksJson.getJSONObject(i);
|
|
JSONArray cellIds = entry.getJSONArray("cellIDs");
|
|
List<Cell> blockCells = new ArrayList<>();
|
|
Block newBlock = new Block(blockCells);
|
|
for (int j = 0; j < cellIds.length(); j++) {
|
|
int cellID = cellIds.getInt(j);
|
|
Cell blockCell = cells.get(cellID);
|
|
blockCell.setBlock(newBlock);
|
|
blockCells.add(blockCell);
|
|
}
|
|
blocks.add(newBlock);
|
|
}
|
|
|
|
JSONArray multidokuJsonObject = jsonObject.getJSONArray("multidoku");
|
|
for (int i = 0; i < multidokuJsonObject.length(); i++) {
|
|
JSONObject sudokuJsonObject = multidokuJsonObject.getJSONObject(i);
|
|
JSONArray sudokuCellsJsonArray = sudokuJsonObject.getJSONArray("cells");
|
|
JSONArray sudokuBlocksJsonArray = sudokuJsonObject.getJSONArray("blocks");
|
|
JSONArray sudokuConstraintsJsonArray = sudokuJsonObject.getJSONArray("constraints");
|
|
|
|
List<Cell> sudokuCells = new ArrayList<>();
|
|
List<Block> sudokuBlocks = new ArrayList<>();
|
|
List<Constraint> sudokuConstraints = new ArrayList<>();
|
|
|
|
for (int j = 0; j < sudokuCellsJsonArray.length(); j++) {
|
|
int cellID = sudokuCellsJsonArray.getInt(j);
|
|
sudokuCells.add(cells.get(cellID));
|
|
}
|
|
|
|
for (int j = 0; j < sudokuBlocksJsonArray.length(); j++) {
|
|
int blockID = sudokuBlocksJsonArray.getInt(j);
|
|
sudokuBlocks.add(blocks.get(blockID));
|
|
}
|
|
|
|
for (int j = 0; j < sudokuConstraintsJsonArray.length(); j++) {
|
|
int constraintID = sudokuConstraintsJsonArray.getInt(j);
|
|
sudokuConstraints.add(Constraint.values()[constraintID]);
|
|
}
|
|
|
|
Sudoku s = new Sudoku(sudokuCells, sudokuBlocks, sudokuConstraints);
|
|
s.setBlockWidth(sudokuJsonObject.getInt("blockWidth"));
|
|
for (Block block : s.getBlocks()) {
|
|
block.getSudokus().add(s);
|
|
}
|
|
sudokus.add(s);
|
|
}
|
|
|
|
return new MultiDoku(sudokus);
|
|
}
|
|
|
|
}
|