diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerBoard.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerBoard.java index 01a6ac918..7ced15f52 100644 --- a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerBoard.java @@ -1,17 +1,15 @@ package edu.rpi.legup.puzzle.thermometer; import edu.rpi.legup.model.gameboard.GridBoard; -import edu.rpi.legup.model.gameboard.PuzzleElement; -import edu.rpi.legup.puzzle.thermometer.elements.Vial; import java.util.ArrayList; -import static edu.rpi.legup.puzzle.thermometer.elements.Vial.verifyVial; +import static edu.rpi.legup.puzzle.thermometer.ThermometerVial.verifyVial; public class ThermometerBoard extends GridBoard{ //an array containing all of our vials on the board - private ArrayList vials; + private ArrayList thermometerVials; //representations of the number requirements along rows and columns of the board private ArrayList colNumbers; @@ -31,7 +29,7 @@ public ThermometerBoard(int width, int height){ rowNumbers.add(0); } - vials = new ArrayList<>(); + thermometerVials = new ArrayList<>(); } public ThermometerBoard(int size){ super(size, size); @@ -44,19 +42,15 @@ public ThermometerBoard(int size){ rowNumbers.add(0); } - vials = new ArrayList<>(); + thermometerVials = new ArrayList<>(); } //setters and accessors for our array of vials - public boolean addVial(ThermometerCell headCell, ThermometerCell tipCell) { - if(verifyVial(headCell, tipCell, this)) { - vials.add(new Vial(headCell, tipCell, this)); - return true; - } - return false; + public void addVial(ThermometerVial v) { + thermometerVials.add(v); } - public ArrayList getVials() { - return vials; + public ArrayList getVials() { + return thermometerVials; } diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerCell.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerCell.java index 771a08b80..6792bb53a 100644 --- a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerCell.java +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerCell.java @@ -5,41 +5,51 @@ import java.awt.Point; public class ThermometerCell extends GridCell { - public ThermometerCell(int valueInt, Point location) { - super(valueInt, location); + private ThermometerType type; + private ThermometerFill fill; + public ThermometerCell(Point location) { + //since we do not use get/set data value int can be any value + super(0, location); + type = ThermometerType.UNKNOWN; + fill = ThermometerFill.UNKNOWN; } + + + + //Note: setdata does not work for our purposes + public void setType(ThermometerType t){ + type = t; + } + + public ThermometerType getType() { - switch (data) { - case 0: - return ThermometerType.UNKNOWN; - case 1: - return ThermometerType.HEAD; - case 2: - return ThermometerType.SHAFT; - case 3: - return ThermometerType.TIP; - } - return null; + return switch (type.ordinal()) { + case 0 -> ThermometerType.UNKNOWN; + case 1 -> ThermometerType.HEAD; + case 2 -> ThermometerType.SHAFT; + case 3 -> ThermometerType.TIP; + default -> null; + }; + } + + public void setFill(ThermometerFill f){ + fill = f; } public ThermometerFill getFill() { - switch (data) { - case 0: - return ThermometerFill.UNKNOWN; - case 1: - return ThermometerFill.FILLED; - case 2: - return ThermometerFill.EMPTY; - case 3: - return ThermometerFill.BLOCKED; - } - return null; + return switch (fill.ordinal()) { + case 0 -> ThermometerFill.UNKNOWN; + case 1 -> ThermometerFill.FILLED; + case 2 -> ThermometerFill.EMPTY; + case 3 -> ThermometerFill.BLOCKED; + default -> null; + }; } @Override public ThermometerCell copy() { - ThermometerCell copy = new ThermometerCell(data, (Point) location.clone()); + ThermometerCell copy = new ThermometerCell((Point) location.clone()); copy.setIndex(index); copy.setModifiable(isModifiable); copy.setGiven(isGiven); diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerController.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerController.java index 253cf8706..8d12f00ea 100644 --- a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerController.java +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerController.java @@ -15,26 +15,26 @@ public void changeCell(MouseEvent e, PuzzleElement data) { this.boardView.getSelectionPopupMenu().show(boardView, this.boardView.getCanvas().getX() + e.getX(), this.boardView.getCanvas().getY() + e.getY()); } else { - if (cell.getData() == ThermometerFill.EMPTY.ordinal()) { - data.setData(ThermometerFill.FILLED.ordinal()); + if (cell.getFill() == ThermometerFill.EMPTY) { + cell.setFill(ThermometerFill.FILLED); } - else if (cell.getData() == ThermometerFill.FILLED.ordinal()) { - data.setData(ThermometerFill.BLOCKED.ordinal()); + else if (cell.getFill() == ThermometerFill.FILLED) { + cell.setFill(ThermometerFill.BLOCKED); } else { - data.setData(ThermometerFill.EMPTY.ordinal()); + cell.setFill(ThermometerFill.EMPTY); } } } else if (e.getButton() == MouseEvent.BUTTON2) { - if (cell.getData() == ThermometerFill.EMPTY.ordinal()) { - data.setData(ThermometerFill.BLOCKED.ordinal()); + if (cell.getFill() == ThermometerFill.EMPTY) { + cell.setFill(ThermometerFill.BLOCKED); } - else if (cell.getData() == ThermometerFill.BLOCKED.ordinal()) { - data.setData(ThermometerFill.FILLED.ordinal()); + else if (cell.getFill() == ThermometerFill.BLOCKED) { + cell.setFill(ThermometerFill.FILLED); } else { - data.setData(ThermometerFill.EMPTY.ordinal()); + cell.setFill(ThermometerFill.EMPTY); } } } diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerExporter.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerExporter.java new file mode 100644 index 000000000..4a6764702 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerExporter.java @@ -0,0 +1,4 @@ +package edu.rpi.legup.puzzle.thermometer; + +public class ThermometerExporter { +} diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerImporter.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerImporter.java new file mode 100644 index 000000000..5af4f478b --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerImporter.java @@ -0,0 +1,98 @@ +package edu.rpi.legup.puzzle.thermometer; + +import edu.rpi.legup.model.PuzzleImporter; +import edu.rpi.legup.puzzle.thermometer.ThermometerVialFactory; +import edu.rpi.legup.save.InvalidFileFormatException; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +import java.awt.*; + +public class ThermometerImporter extends PuzzleImporter { + public ThermometerImporter(Thermometer thermometer) { + super(thermometer); + } + + @Override + public boolean acceptsRowsAndColumnsInput() { + return false; + } + + @Override + public boolean acceptsTextInput() { + return false; + } + + @Override + public void initializeBoard(int rows, int columns) { + + } + + @Override + public void initializeBoard(Node node) throws InvalidFileFormatException { + try { + if (!node.getNodeName().equalsIgnoreCase("board")) { + throw new InvalidFileFormatException("thermometer Importer: cannot find board puzzleElement"); + } + Element boardElement = (Element) node; + if (boardElement.getElementsByTagName("vials").getLength() == 0) { + throw new InvalidFileFormatException("thermometer Importer: no puzzleElement found for board"); + } + Element dataElement = (Element) boardElement.getElementsByTagName("cells").item(0); + NodeList elementDataList = dataElement.getElementsByTagName("cell"); + + ThermometerBoard thermometerBoard = null; + if (!boardElement.getAttribute("size").isEmpty()) { + int size = Integer.parseInt(boardElement.getAttribute("size")); + thermometerBoard = new ThermometerBoard(size); + if (boardElement.getElementsByTagName("rowNumbers").getLength() != size) { + throw new InvalidFileFormatException("thermometer Importer: no rowNumbers found for board"); + } + if (boardElement.getElementsByTagName("colNumbers").getLength() != size) { + throw new InvalidFileFormatException("thermometer Importer: no colNumbers found for board"); + } + } else if (!boardElement.getAttribute("width").isEmpty() && !boardElement.getAttribute("height").isEmpty()) { + int width = Integer.parseInt(boardElement.getAttribute("width")); + int height = Integer.parseInt(boardElement.getAttribute("height")); + if (boardElement.getElementsByTagName("colNumbers").getLength() != width) { + throw new InvalidFileFormatException("thermometer Importer: no colNumbers found for board"); + } + if (boardElement.getElementsByTagName("rowNumbers").getLength() != height) { + throw new InvalidFileFormatException("thermometer Importer: no rowNumbers found for board"); + } + //TODO: potentially have to deal with size issues and non interactable cells + thermometerBoard = new ThermometerBoard(width, height); + } + + if (thermometerBoard == null) { + throw new InvalidFileFormatException("thermometer Importer: invalid board dimensions"); + } + + int width = thermometerBoard.getWidth(); + int height = thermometerBoard.getHeight(); + + for (int i = 0; i < elementDataList.getLength(); i++) { + ThermometerVialFactory.importThermometerVial(elementDataList.item(i), thermometerBoard); + } + + //verifying all vials were used + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (thermometerBoard.getCell(x, y) == null) { + throw new InvalidFileFormatException("thermometer Importer: invalid puzzle, unused tiles"); + } + } + } + + puzzle.setCurrentBoard(thermometerBoard); + } catch (NumberFormatException e) { + throw new InvalidFileFormatException("thermometer Importer: unknown value where integer expected"); + } + } + + @Override + public void initializeBoard(String[] statements) throws UnsupportedOperationException, IllegalArgumentException { + + } +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/elements/Vial.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerVial.java similarity index 79% rename from src/main/java/edu/rpi/legup/puzzle/thermometer/elements/Vial.java rename to src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerVial.java index 93b7fe491..19f6c4ce2 100644 --- a/src/main/java/edu/rpi/legup/puzzle/thermometer/elements/Vial.java +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerVial.java @@ -1,33 +1,21 @@ -package edu.rpi.legup.puzzle.thermometer.elements; - -import edu.rpi.legup.puzzle.thermometer.ThermometerCell; -import edu.rpi.legup.puzzle.thermometer.ThermometerBoard; -import edu.rpi.legup.puzzle.thermometer.ThermometerFill; -import edu.rpi.legup.puzzle.thermometer.ThermometerType; -import edu.rpi.legup.model.elements.PlaceableElement; +package edu.rpi.legup.puzzle.thermometer; import java.awt.*; import java.util.ArrayList; import static java.lang.Math.*; -public class Vial { +public class ThermometerVial { private ArrayList cells; - public Vial(ThermometerCell headCell, ThermometerCell tipCell, ThermometerBoard board) { + public ThermometerVial(int headX, int headY, int tipX, int tipY, ThermometerBoard board) { cells = new ArrayList<>(); - fillData(headCell, tipCell, board); + fillData(headX, headY, tipX, tipY, board); } //function called by the constructor which adds in all of the cells to the array //as well as updates their type on the board - private void fillData(ThermometerCell headCell, ThermometerCell tipCell, ThermometerBoard board) { - //shorthand for useful variables - int headX = (int) headCell.getLocation().getX(); - int headY = (int) headCell.getLocation().getY(); - int tipX = (int) tipCell.getLocation().getX(); - int tipY = (int) tipCell.getLocation().getY(); - + private void fillData(int headX, int headY, int tipX, int tipY, ThermometerBoard board) { //not totally happy with layout of code but most readable version I can think of atm //top left coordinate is 0,0 cells are added from head to tip always //because cells have already been verified by time constructor is called @@ -65,9 +53,11 @@ else if (headX < tipX){ //helper function for adding a single cell private void addCell(int x, int y, ThermometerType t, ThermometerBoard board){ - - //this very likely is not updating the data in the way we want it to - board.getCell(x, y).setData(t.ordinal()); + ThermometerCell cell = new ThermometerCell(new Point(x, y)); + cell.setIndex(y * board.getHeight() + x); + cell.setModifiable(true); + board.setCell(x, y, cell); + board.getCell(x, y).setType(t); cells.add(board.getCell(x, y)); } @@ -114,7 +104,7 @@ public static boolean verifyVial(ThermometerCell headCell, ThermometerCell tipCe //verifying that every cell along path is currently unclaimed for (int i = top; i < bottom; i++) { - if(board.getCell(headX, i).getType() != ThermometerType.UNKNOWN) return false; + if(board.getCell(headX, i) != null || board.getCell(headX, i).getType() != ThermometerType.UNKNOWN) return false; } } else if (headY == tipY) { diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerVialFactory.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerVialFactory.java new file mode 100644 index 000000000..d1bef94d8 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/ThermometerVialFactory.java @@ -0,0 +1,71 @@ +package edu.rpi.legup.puzzle.thermometer; + +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.ElementFactory; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.save.InvalidFileFormatException; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import java.awt.*; + +import static edu.rpi.legup.puzzle.thermometer.ThermometerVial.verifyVial; +import static java.lang.Math.max; +import static java.lang.Math.min; + +public class ThermometerVialFactory extends ElementFactory{ + //We do not import single cells at a time, instead we are + //importing/exporting entire vials hence these functions + //remain empty + @Override + public PuzzleElement importCell(Node node, Board board) throws InvalidFileFormatException { + return null; + } + @Override + public Element exportCell(Document document, PuzzleElement puzzleElement) { + return null; + } + + public static void importThermometerVial(Node node, ThermometerBoard board) throws InvalidFileFormatException{ + int headX = Integer.parseInt(node.getAttributes().getNamedItem("headx").getNodeValue()); + int headY = Integer.parseInt(node.getAttributes().getNamedItem("heady").getNodeValue()); + int tipX = Integer.parseInt(node.getAttributes().getNamedItem("tailx").getNodeValue()); + int tipY = Integer.parseInt(node.getAttributes().getNamedItem("taily").getNodeValue()); + + + if(verifyVial(headX, headY, tipX, tipY, board)) { + board.addVial(new ThermometerVial(headX, headY, tipX, tipY, board)); + } + throw new InvalidFileFormatException("thermometer Importer: overlapping vials"); + } + + private static boolean verifyVial(int headX, int headY, int tipX, int tipY, ThermometerBoard board) { + //figuring out which axis the thermometer travels along + if(headX == tipX) { + //finding start and end of Vial + int top = min(headY, tipY); + int bottom = max(headY, tipY); + + //verifying that every cell along path is currently unconstructed + for (int i = top; i < bottom; i++) { + if(board.getCell(headX, i) != null) return false; + } + } + else if (headY == tipY) { + //finding start and end of Vial + int top = min(headX, tipX); + int bottom = max(headX, tipX); + + //verifying that every cell along path is currently unconstructed + for (int i = top; i < bottom; i++) { + if(board.getCell(headX, i) != null) return false; + } + } + else{ + //thermometer does not line up along a single axis + return false; + } + return true; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/thermometer/rules/DiscontinuousMercuryContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/thermometer/rules/DiscontinuousMercuryContradictionRule.java index a24e2b403..8a8ef00f6 100644 --- a/src/main/java/edu/rpi/legup/puzzle/thermometer/rules/DiscontinuousMercuryContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/thermometer/rules/DiscontinuousMercuryContradictionRule.java @@ -5,7 +5,7 @@ import edu.rpi.legup.model.rules.ContradictionRule; import edu.rpi.legup.puzzle.thermometer.ThermometerBoard; import edu.rpi.legup.puzzle.thermometer.ThermometerCell; -import edu.rpi.legup.puzzle.thermometer.elements.Vial; +import edu.rpi.legup.puzzle.thermometer.ThermometerVial; import java.util.ArrayList; @@ -30,15 +30,15 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { ThermometerCell cell = (ThermometerCell) thermometerBoard.getPuzzleElement(puzzleElement); - ArrayList vials = thermometerBoard.getVials(); + ArrayList thermometerVials = thermometerBoard.getVials(); //finding out which vial contains the specified cell - for (int i = 0; i < vials.size(); i++) { - Vial vial = vials.get(i); + for (int i = 0; i < thermometerVials.size(); i++) { + ThermometerVial thermometerVial = thermometerVials.get(i); //if a vial contains the clicked on cell //checking if the vial has a break in the flow - if(vial.containsCell(cell)){ - if(vial.continuousFlow()){ + if(thermometerVial.containsCell(cell)){ + if(thermometerVial.continuousFlow()){ return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; } else{