diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml
new file mode 100644
index 000000000..bed9d7ad2
--- /dev/null
+++ b/.github/workflows/run-tests.yml
@@ -0,0 +1,73 @@
+name: Run JUnit Tests
+
+on:
+ push:
+ branches:
+ - master
+ - dev
+ pull_request:
+ branches:
+ - master
+ - dev
+
+jobs:
+ ubuntu-test:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Check Out Code
+ uses: actions/checkout@v2
+
+ - name: Set up JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: 11
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Build with Gradle
+ run: ./gradlew build -x test
+
+ - name: Run JUnit Tests on Linux
+ run: |
+ ./gradlew test
+
+ test-macos:
+ runs-on: macos-latest
+
+ steps:
+ - name: Check Out Code
+ uses: actions/checkout@v2
+
+ - name: Set up JDK 11
+ uses: actions/setup-java@v1
+ with:
+ java-version: 11
+
+ - name: Grant execute permission for gradlew
+ run: chmod +x gradlew
+
+ - name: Build with Gradle
+ run: ./gradlew build -x test
+
+ - name: Run JUnit Tests on macOS
+ run: |
+ ./gradlew test
+
+ test-windows:
+ runs-on: windows-latest
+
+ steps:
+ - name: Check Out Code
+ uses: actions/checkout@v2
+
+ - name: Set up JDK and Gradle on Windows
+ uses: actions/setup-java@v2
+ with:
+ java-version: 11
+ distribution: 'adopt'
+
+ - name: Run JUnit Tests on Windows
+ run: |
+ .\gradlew.bat test
\ No newline at end of file
diff --git a/bin/main/edu/rpi/legup/legup/config b/bin/main/edu/rpi/legup/legup/config
index bb7da871a..24fdcf365 100644
--- a/bin/main/edu/rpi/legup/legup/config
+++ b/bin/main/edu/rpi/legup/legup/config
@@ -27,7 +27,7 @@
+ fileCreationDisabled="false"/>
diff --git a/puzzles files/shorttruthtable/empty_test.xml b/puzzles files/shorttruthtable/empty_test.xml
new file mode 100644
index 000000000..2d8e4b6c8
--- /dev/null
+++ b/puzzles files/shorttruthtable/empty_test.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/java/edu/rpi/legup/app/GameBoardFacade.java b/src/main/java/edu/rpi/legup/app/GameBoardFacade.java
index 2686086a8..55273ab4f 100644
--- a/src/main/java/edu/rpi/legup/app/GameBoardFacade.java
+++ b/src/main/java/edu/rpi/legup/app/GameBoardFacade.java
@@ -1,23 +1,22 @@
package edu.rpi.legup.app;
+import edu.rpi.legup.history.History;
import edu.rpi.legup.history.IHistoryListener;
import edu.rpi.legup.history.IHistorySubject;
+import edu.rpi.legup.model.Puzzle;
import edu.rpi.legup.model.PuzzleImporter;
import edu.rpi.legup.model.gameboard.Board;
-import edu.rpi.legup.model.Puzzle;
import edu.rpi.legup.model.tree.Tree;
+import edu.rpi.legup.save.InvalidFileFormatException;
+import edu.rpi.legup.ui.LegupUI;
import edu.rpi.legup.ui.ProofEditorPanel;
import edu.rpi.legup.ui.PuzzleEditorPanel;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
-import edu.rpi.legup.save.InvalidFileFormatException;
-import edu.rpi.legup.ui.LegupUI;
-import edu.rpi.legup.history.History;
-
-import org.apache.logging.log4j.LogManager;
-import org.apache.logging.log4j.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -144,6 +143,30 @@ public boolean validateDimensions(String game, int rows, int columns) throws Run
}
}
+ /**
+ * Validates the given text input for the given puzzle
+ *
+ * @param game the name of the puzzle
+ * @param statements an array of statements
+ * @return true if it is possible to create a board for the given game with the given statements,
+ * false otherwise
+ * @throws RuntimeException if any of the input is invalid
+ */
+ public boolean validateTextInput(String game, String[] statements) throws RuntimeException {
+ String qualifiedClassName = config.getPuzzleClassForName(game);
+ try {
+ Class> c = Class.forName(qualifiedClassName);
+ Constructor> constructor = c.getConstructor();
+ Puzzle puzzle = (Puzzle) constructor.newInstance();
+ return puzzle.isValidTextInput(statements);
+ }
+ catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException |
+ InstantiationException e) {
+ LOGGER.error(e);
+ throw new RuntimeException("Error validating puzzle text input");
+ }
+ }
+
/**
* Loads an empty puzzle
*
@@ -159,7 +182,6 @@ public void loadPuzzle(String game, int rows, int columns) throws RuntimeExcepti
Class> c = Class.forName(qualifiedClassName);
Constructor> cons = c.getConstructor();
Puzzle puzzle = (Puzzle) cons.newInstance();
- setWindowTitle(puzzle.getName(), "New " + puzzle.getName() + " Puzzle");
PuzzleImporter importer = puzzle.getImporter();
if (importer == null) {
@@ -167,6 +189,13 @@ public void loadPuzzle(String game, int rows, int columns) throws RuntimeExcepti
throw new RuntimeException("Puzzle importer null");
}
+ // Theoretically, this exception should never be thrown, since LEGUP should not be
+ // allowing the user to give row/column input for a puzzle that doesn't support it
+ if (!importer.acceptsRowsAndColumnsInput()) {
+ throw new IllegalArgumentException(puzzle.getName() + " does not accept rows and columns input");
+ }
+
+ setWindowTitle(puzzle.getName(), "New " + puzzle.getName() + " Puzzle");
importer.initializePuzzle(rows, columns);
puzzle.initializeView();
@@ -183,6 +212,45 @@ public void loadPuzzle(String game, int rows, int columns) throws RuntimeExcepti
}
}
+ public void loadPuzzle(String game, String[] statements) {
+ String qualifiedClassName = config.getPuzzleClassForName(game);
+ LOGGER.debug("Loading " + qualifiedClassName);
+
+ try {
+ Class> c = Class.forName(qualifiedClassName);
+ Constructor> cons = c.getConstructor();
+ Puzzle puzzle = (Puzzle) cons.newInstance();
+
+ PuzzleImporter importer = puzzle.getImporter();
+ if (importer == null) {
+ LOGGER.error("Puzzle importer is null");
+ throw new RuntimeException("Puzzle importer null");
+ }
+
+ // Theoretically, this exception should never be thrown, since LEGUP should not be
+ // allowing the user to give text input for a puzzle that doesn't support it
+ if (!importer.acceptsTextInput()) {
+ throw new IllegalArgumentException(puzzle.getName() + " does not accept text input");
+ }
+
+ setWindowTitle(puzzle.getName(), "New " + puzzle.getName() + " Puzzle");
+ importer.initializePuzzle(statements);
+
+ puzzle.initializeView();
+// puzzle.getBoardView().onTreeElementChanged(puzzle.getTree().getRootNode());
+ setPuzzleEditor(puzzle);
+ }
+ catch (IllegalArgumentException exception) {
+ throw new IllegalArgumentException(exception.getMessage());
+ }
+ catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException |
+ IllegalAccessException | InstantiationException e) {
+ LOGGER.error(e);
+ throw new RuntimeException("Puzzle creation error");
+ }
+
+ }
+
/**
* Loads a puzzle file
*
diff --git a/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java b/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java
index c5f8f0831..a0f58a571 100644
--- a/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java
+++ b/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java
@@ -86,9 +86,17 @@ public void executeCommand() {
}
else {
TreeTransitionView transitionView = (TreeTransitionView) firstSelectedView;
- finalTreeElement = transitionView.getChildView().getTreeElement();
+ if (transitionView.getChildView() != null) {
+ finalTreeElement = transitionView.getChildView().getTreeElement();
+ }
+ else {
+ finalTreeElement = null;
+ }
+ }
+
+ if (finalTreeElement != null) {
+ puzzle.notifyBoardListeners(listener -> listener.onTreeElementChanged(finalTreeElement));
}
- puzzle.notifyBoardListeners(listener -> listener.onTreeElementChanged(finalTreeElement));
puzzle.notifyTreeListeners(listener -> listener.onTreeSelectionChanged(newSelection));
}
diff --git a/src/main/java/edu/rpi/legup/model/Puzzle.java b/src/main/java/edu/rpi/legup/model/Puzzle.java
index d25afa2cb..18614131b 100644
--- a/src/main/java/edu/rpi/legup/model/Puzzle.java
+++ b/src/main/java/edu/rpi/legup/model/Puzzle.java
@@ -204,12 +204,26 @@ public boolean isValidDimensions(int rows, int columns) {
return rows > 0 && columns > 0;
}
+ /**
+ * Checks if the given array of statements is valid text input for the given puzzle
+ *
+ * @param statements
+ * @return
+ */
+ public boolean isValidTextInput(String[] statements) {
+ return statements.length > 0;
+ }
+
/**
* Determines if the edu.rpi.legup.puzzle was solves correctly
*
* @return true if the board was solved correctly, false otherwise
*/
public boolean isPuzzleComplete() {
+ if (tree == null) {
+ return false;
+ }
+
boolean isComplete = tree.isValid();
if (isComplete) {
for (TreeElement leaf : tree.getLeafTreeElements()) {
diff --git a/src/main/java/edu/rpi/legup/model/PuzzleExporter.java b/src/main/java/edu/rpi/legup/model/PuzzleExporter.java
index a2f662772..613d2ed1c 100644
--- a/src/main/java/edu/rpi/legup/model/PuzzleExporter.java
+++ b/src/main/java/edu/rpi/legup/model/PuzzleExporter.java
@@ -29,6 +29,7 @@ public abstract class PuzzleExporter {
/**
* PuzzleExporter Constructor exports the puzzle object to a file
+ *
* @param puzzle puzzle that is to be exported
*/
public PuzzleExporter(Puzzle puzzle) {
diff --git a/src/main/java/edu/rpi/legup/model/PuzzleImporter.java b/src/main/java/edu/rpi/legup/model/PuzzleImporter.java
index c2b5b37fc..327a92773 100644
--- a/src/main/java/edu/rpi/legup/model/PuzzleImporter.java
+++ b/src/main/java/edu/rpi/legup/model/PuzzleImporter.java
@@ -12,10 +12,7 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
public abstract class PuzzleImporter {
private static final Logger LOGGER = LogManager.getLogger(PuzzleImporter.class.getName());
@@ -24,12 +21,17 @@ public abstract class PuzzleImporter {
/**
* PuzzleImporter Constructor creates the puzzle object
+ *
* @param puzzle puzzle that is imported
*/
public PuzzleImporter(Puzzle puzzle) {
this.puzzle = puzzle;
}
+ public abstract boolean acceptsRowsAndColumnsInput();
+
+ public abstract boolean acceptsTextInput();
+
/**
* Initializes an empty puzzle
*
@@ -46,6 +48,13 @@ public void initializePuzzle(int rows, int columns) throws RuntimeException {
}
}
+ public void initializePuzzle(String[] statements) throws InputMismatchException, IllegalArgumentException {
+ // Note: Error checking for the statements will be left up to the puzzles that support
+ // text input. For example, some puzzles may be okay with "blank" statements (Strings with
+ // length = 0) while others may not.
+ initializeBoard(statements);
+ }
+
/**
* Initializes the puzzle attributes
*
@@ -116,6 +125,8 @@ public void initializePuzzle(Node node) throws InvalidFileFormatException {
*/
public abstract void initializeBoard(Node node) throws InvalidFileFormatException;
+ public abstract void initializeBoard(String[] statements) throws UnsupportedOperationException, IllegalArgumentException;
+
/**
* Creates the proof for building
*
diff --git a/src/main/java/edu/rpi/legup/model/rules/DirectRule.java b/src/main/java/edu/rpi/legup/model/rules/DirectRule.java
index 940bbe32f..4acc7573e 100644
--- a/src/main/java/edu/rpi/legup/model/rules/DirectRule.java
+++ b/src/main/java/edu/rpi/legup/model/rules/DirectRule.java
@@ -29,18 +29,12 @@ public DirectRule(String ruleID, String ruleName, String description, String ima
*/
public String checkRule(TreeTransition transition) {
Board finalBoard = transition.getBoard();
-
- if (!finalBoard.isModified()) {
- return "State must be modified";
+ if (transition.getParents().size() != 1 ||
+ transition.getParents().get(0).getChildren().size() != 1) {
+ return "State must have only 1 parent and 1 child";
}
else {
- if (transition.getParents().size() != 1 ||
- transition.getParents().get(0).getChildren().size() != 1) {
- return "State must have only 1 parent and 1 child";
- }
- else {
- return checkRuleRaw(transition);
- }
+ return checkRuleRaw(transition);
}
}
diff --git a/src/main/java/edu/rpi/legup/model/tree/Tree.java b/src/main/java/edu/rpi/legup/model/tree/Tree.java
index 31ef92359..79c0bcece 100644
--- a/src/main/java/edu/rpi/legup/model/tree/Tree.java
+++ b/src/main/java/edu/rpi/legup/model/tree/Tree.java
@@ -101,6 +101,7 @@ public Set getLeafTreeElements() {
/**
* Gets a Set of TreeNodes that are leaf nodes from the sub tree rooted at the specified node
+ *
* @param node node that is input
* @return Set of TreeNodes that are leaf nodes from the sub tree
*/
diff --git a/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipExporter.java b/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipExporter.java
index b954a1065..4205d0125 100644
--- a/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipExporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipExporter.java
@@ -2,6 +2,7 @@
import edu.rpi.legup.model.PuzzleExporter;
import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard;
import org.w3c.dom.Document;
public class BattleshipExporter extends PuzzleExporter {
@@ -18,7 +19,13 @@ public BattleshipExporter(Battleship battleShip) {
*/
@Override
protected org.w3c.dom.Element createBoardElement(Document newDocument) {
- BattleshipBoard board = (BattleshipBoard) puzzle.getTree().getRootNode().getBoard();
+ BattleshipBoard board;
+ if (puzzle.getTree() != null) {
+ board = (BattleshipBoard) puzzle.getTree().getRootNode().getBoard();
+ }
+ else {
+ board = (BattleshipBoard) puzzle.getBoardView().getBoard();
+ }
org.w3c.dom.Element boardElement = newDocument.createElement("board");
boardElement.setAttribute("width", String.valueOf(board.getWidth()));
diff --git a/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipImporter.java b/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipImporter.java
index aa7209f71..749ceaaa9 100644
--- a/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/battleship/BattleshipImporter.java
@@ -13,6 +13,16 @@ public BattleshipImporter(Battleship battleShip) {
super(battleShip);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -177,4 +187,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
"unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Battleship cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixExporter.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixExporter.java
index f7dc9d375..757d14cd8 100644
--- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixExporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixExporter.java
@@ -2,6 +2,7 @@
import edu.rpi.legup.model.PuzzleExporter;
import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard;
import org.w3c.dom.Document;
public class FillapixExporter extends PuzzleExporter {
@@ -12,7 +13,13 @@ public FillapixExporter(Fillapix fillapix) {
@Override
protected org.w3c.dom.Element createBoardElement(Document newDocument) {
- FillapixBoard board = (FillapixBoard) puzzle.getTree().getRootNode().getBoard();
+ FillapixBoard board;
+ if (puzzle.getTree() != null) {
+ board = (FillapixBoard) puzzle.getTree().getRootNode().getBoard();
+ }
+ else {
+ board = (FillapixBoard) puzzle.getBoardView().getBoard();
+ }
org.w3c.dom.Element boardElement = newDocument.createElement("board");
boardElement.setAttribute("width", String.valueOf(board.getWidth()));
diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java
index 45ad786e8..6c30b2272 100644
--- a/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/FillapixImporter.java
@@ -13,6 +13,16 @@ public FillapixImporter(Fillapix fillapix) {
super(fillapix);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -88,4 +98,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
throw new InvalidFileFormatException("Fillapix Importer: unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Fillapix cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeExporter.java b/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeExporter.java
index a23273ab4..344a0be92 100644
--- a/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeExporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeExporter.java
@@ -2,6 +2,7 @@
import edu.rpi.legup.model.PuzzleExporter;
import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard;
import org.w3c.dom.Document;
public class HeyawakeExporter extends PuzzleExporter {
@@ -12,7 +13,13 @@ public HeyawakeExporter(Heyawake heyawake) {
@Override
protected org.w3c.dom.Element createBoardElement(Document newDocument) {
- HeyawakeBoard board = (HeyawakeBoard) puzzle.getTree().getRootNode().getBoard();
+ HeyawakeBoard board;
+ if (puzzle.getTree() != null) {
+ board = (HeyawakeBoard) puzzle.getTree().getRootNode().getBoard();
+ }
+ else {
+ board = (HeyawakeBoard) puzzle.getBoardView().getBoard();
+ }
org.w3c.dom.Element boardElement = newDocument.createElement("board");
boardElement.setAttribute("width", String.valueOf(board.getWidth()));
diff --git a/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeImporter.java b/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeImporter.java
index d09a15389..7527c717f 100644
--- a/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/heyawake/HeyawakeImporter.java
@@ -14,6 +14,16 @@ public HeyawakeImporter(Heyawake heyawake) {
super(heyawake);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -91,4 +101,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
throw new InvalidFileFormatException("Heyawake Importer: unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Hey Awake cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpCell.java b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpCell.java
index 3189eff7a..36e5a5088 100644
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpCell.java
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpCell.java
@@ -1,8 +1,10 @@
package edu.rpi.legup.puzzle.lightup;
+import edu.rpi.legup.model.elements.Element;
import edu.rpi.legup.model.gameboard.GridCell;
import java.awt.*;
+import java.awt.event.MouseEvent;
public class LightUpCell extends GridCell {
private boolean isLite;
@@ -12,6 +14,41 @@ public LightUpCell(int valueInt, Point location) {
this.isLite = false;
}
+ @Override
+ public void setType(Element e, MouseEvent m) {
+ switch (e.getElementID()) {
+ case "LTUP-PLAC-0001":
+ this.data = -4;
+ break;
+ case "LTUP-UNPL-0002":
+ this.data = -1;
+ break;
+ case "LTUP-UNPL-0003":
+ this.data = -2;
+ break;
+ case "LTUP-UNPL-0001":
+ switch (m.getButton()){
+ case MouseEvent.BUTTON1:
+ if (this.data < 0 || this.data > 3) {
+ this.data = 0;
+ }
+ else {
+ this.data = this.data + 1;
+ }
+ break;
+ case MouseEvent.BUTTON3:
+ if (this.data > 0) {
+ this.data = this.data - 1;
+ }
+ else {
+ this.data = 4;
+ }
+ break;
+ }
+ break;
+ }
+ }
+
public LightUpCellType getType() {
switch (data) {
case -4:
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpExporter.java b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpExporter.java
index 78270e112..89024ad6c 100644
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpExporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpExporter.java
@@ -2,6 +2,7 @@
import edu.rpi.legup.model.PuzzleExporter;
import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard;
import org.w3c.dom.Document;
public class LightUpExporter extends PuzzleExporter {
@@ -12,7 +13,13 @@ public LightUpExporter(LightUp lightUp) {
@Override
protected org.w3c.dom.Element createBoardElement(Document newDocument) {
- LightUpBoard board = (LightUpBoard) puzzle.getTree().getRootNode().getBoard();
+ LightUpBoard board;
+ if (puzzle.getTree() != null) {
+ board = (LightUpBoard) puzzle.getTree().getRootNode().getBoard();
+ }
+ else {
+ board = (LightUpBoard) puzzle.getBoardView().getBoard();
+ }
org.w3c.dom.Element boardElement = newDocument.createElement("board");
boardElement.setAttribute("width", String.valueOf(board.getWidth()));
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpImporter.java b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpImporter.java
index fd9fd49e9..7ef24ca69 100644
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUpImporter.java
@@ -13,6 +13,16 @@ public LightUpImporter(LightUp lightUp) {
super(lightUp);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -102,4 +112,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
throw new InvalidFileFormatException("lightup Importer: unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Light Up cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/elements/BlackTile.java b/src/main/java/edu/rpi/legup/puzzle/lightup/elements/BlackTile.java
index b72ae1fab..d3e8cf506 100644
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/elements/BlackTile.java
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/elements/BlackTile.java
@@ -1,9 +1,9 @@
package edu.rpi.legup.puzzle.lightup.elements;
-import edu.rpi.legup.model.elements.PlaceableElement;
+import edu.rpi.legup.model.elements.NonPlaceableElement;
-public class BlackTile extends PlaceableElement {
+public class BlackTile extends NonPlaceableElement {
public BlackTile() {
- super("LTUP-PLAC-0002", "Black Tile", "The black tile", "edu/rpi/legup/images/lightup/black.gif");
+ super("LTUP-UNPL-0002", "Black Tile", "The black tile", "edu/rpi/legup/images/lightup/black.gif");
}
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/elements/UnknownTile.java b/src/main/java/edu/rpi/legup/puzzle/lightup/elements/UnknownTile.java
new file mode 100644
index 000000000..6839e70de
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/elements/UnknownTile.java
@@ -0,0 +1,9 @@
+package edu.rpi.legup.puzzle.lightup.elements;
+
+import edu.rpi.legup.model.elements.NonPlaceableElement;
+
+public class UnknownTile extends NonPlaceableElement {
+ public UnknownTile() {
+ super("LTUP-UNPL-0003", "Unknown Tile", "A blank tile", "edu/rpi/legup/images/lightup/UnknownTile.png");
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuExporter.java b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuExporter.java
index 471be22f1..e5fb071b4 100644
--- a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuExporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuExporter.java
@@ -2,6 +2,7 @@
import edu.rpi.legup.model.PuzzleExporter;
import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard;
import org.w3c.dom.Document;
public class MasyuExporter extends PuzzleExporter {
@@ -12,7 +13,13 @@ public MasyuExporter(Masyu masyu) {
@Override
protected org.w3c.dom.Element createBoardElement(Document newDocument) {
- MasyuBoard board = (MasyuBoard) puzzle.getTree().getRootNode().getBoard();
+ MasyuBoard board;
+ if (puzzle.getTree() != null) {
+ board = (MasyuBoard) puzzle.getTree().getRootNode().getBoard();
+ }
+ else {
+ board = (MasyuBoard) puzzle.getBoardView().getBoard();
+ }
org.w3c.dom.Element boardElement = newDocument.createElement("board");
boardElement.setAttribute("width", String.valueOf(board.getWidth()));
diff --git a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuImporter.java b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuImporter.java
index 50bf0c0c7..3e0d328c4 100644
--- a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuImporter.java
@@ -13,6 +13,16 @@ public MasyuImporter(Masyu masyu) {
super(masyu);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -90,4 +100,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
throw new InvalidFileFormatException("Masyu Importer: unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Masyu cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeImporter.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeImporter.java
index 7665a4865..2cbcc9ad0 100644
--- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeImporter.java
@@ -13,6 +13,16 @@ public NurikabeImporter(Nurikabe nurikabe) {
super(nurikabe);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -100,4 +110,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
throw new InvalidFileFormatException("nurikabe Importer: unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Nurikabe cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeUtilities.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeUtilities.java
index 34278ff9f..024cf6bb2 100644
--- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeUtilities.java
+++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeUtilities.java
@@ -241,4 +241,67 @@ public static HashMap getWhiteRegionMap(NurikabeBoard boa
}
return whiteRegionMap;
}
+
+ /**
+ * Gets all the non-black cells connected to the given cell
+ *
+ * @param board nurikabe board
+ * @param center nurikabe cell
+ * @return a set of all white/numbered cells in the region
+ */
+ public static Set getSurroundedRegionOf(NurikabeBoard board, NurikabeCell center) {
+ int width = board.getWidth();
+ int height = board.getHeight();
+
+ // Mark all the vertices as not visited(By default
+ // set as false)
+ Set visited = new HashSet<>();
+
+ // Create a queue for BFS
+ LinkedList queue = new LinkedList<>();
+
+ // Mark the current node as visited and enqueue it
+ visited.add(center);
+ queue.add(center);
+
+ // Set of cells in the current region
+ Set connected = new HashSet<>();
+
+ while (queue.size() != 0) {
+ // Dequeue a vertex from queue and print it
+ // s is the source node in the graph
+ NurikabeCell s = queue.poll();
+ System.out.print(s + " ");
+
+ // Make a set of all adjacent squares
+ Set adj = new HashSet<>();
+
+ Point loc = s.getLocation();
+ // First check if the side is on the board
+ if (loc.x >= 1) {
+ adj.add(board.getCell(loc.x - 1, loc.y));
+ }
+ if (loc.x < width - 1) {
+ adj.add(board.getCell(loc.x + 1, loc.y));
+ }
+ if (loc.y >= 1) {
+ adj.add(board.getCell(loc.x, loc.y - 1));
+ }
+ if (loc.y < height - 1) {
+ adj.add(board.getCell(loc.x, loc.y + 1));
+ }
+ // Get all adjacent vertices of the dequeued vertex s
+ // If a adjacent has not been visited, then mark it
+ // visited and enqueue it
+ for (NurikabeCell n : adj) {
+ if (!visited.contains(n) && n.getType() != NurikabeType.BLACK) {
+ connected.add(n);
+ visited.add(n);
+ queue.add(n);
+ }
+ }
+ }
+
+ return connected;
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/NoNumberContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/NoNumberContradictionRule.java
index 06eb9d2eb..c2752da7a 100644
--- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/NoNumberContradictionRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/NoNumberContradictionRule.java
@@ -42,20 +42,18 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
return super.getInvalidUseOfRuleMessage() + ": " + this.INVALID_USE_MESSAGE;
}
-// If the transition creates a room of white cells with no number, a contradiction occurs.
- DisjointSets anotherRegion = NurikabeUtilities.getPossibleWhiteRegions(nurikabeBoard);
- List> allsets = anotherRegion.getAllSets();
- for (Set s : allsets) {
- boolean numberExists = false;
- for (NurikabeCell c : s) {
- if (c.getType() == NurikabeType.NUMBER) {
- numberExists = true;
- }
- }
- if (!numberExists) {
- return null;
+ Set region = NurikabeUtilities.getSurroundedRegionOf(nurikabeBoard, cell);
+
+ boolean numberExists = false;
+ for (NurikabeCell c : region) {
+ if (c.getType() == NurikabeType.NUMBER) {
+ numberExists = true;
+ break;
}
}
+ if (!numberExists) {
+ return null;
+ }
return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE;
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTable.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTable.java
index 3ce185b6c..e8f9ffc0d 100644
--- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTable.java
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTable.java
@@ -25,6 +25,7 @@ public ShortTruthTable() {
public void initializeView() {
ShortTruthTableBoard sttBoard = (ShortTruthTableBoard) currentBoard;
boardView = new ShortTruthTableView(sttBoard);
+ boardView.setBoard(currentBoard);
addBoardListener(boardView);
}
@@ -48,8 +49,32 @@ public Board generatePuzzle(int difficulty) {
* @return true if the given dimensions are valid for Short Truth Table, false otherwise
*/
public boolean isValidDimensions(int rows, int columns) {
- // This is a placeholder, this method needs to be implemented
- throw new UnsupportedOperationException();
+ // Number of rows must be odd to allow for proper spacing between the statements
+ if (rows % 2 != 1) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Determines if the given statements are valid for Short Truth Table
+ *
+ * @param statements
+ * @return true if the statements are valid for Short Truth Table, false otherwise
+ */
+ public boolean isValidTextInput(String[] statements) {
+ if (statements.length == 0) {
+ return false;
+ }
+
+ ShortTruthTableImporter importer = (ShortTruthTableImporter) this.getImporter();
+ for (String s : statements) {
+ if (!importer.validGrammar(s)) {
+ return false;
+ }
+ }
+ return true;
}
/**
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableCell.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableCell.java
index 768b4ed2a..59b5f4272 100644
--- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableCell.java
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableCell.java
@@ -1,15 +1,17 @@
package edu.rpi.legup.puzzle.shorttruthtable;
+import edu.rpi.legup.model.elements.Element;
import edu.rpi.legup.model.gameboard.GridCell;
import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableStatement;
import java.awt.Point;
+import java.awt.event.MouseEvent;
public class ShortTruthTableCell extends GridCell {
//The symbol on the cell
- private final char symbol;
+ private char symbol;
//This is a reference to the statement that contains this cell
private ShortTruthTableStatement statement;
@@ -127,5 +129,104 @@ public ShortTruthTableCell copy() {
return copy;
}
+ /**
+ * Sets the type of this ShortTruthTableCell
+ *
+ * @param e element to set the type of this Short Truth Table cell to
+ */
+ @Override
+ public void setType(Element e, MouseEvent m) {
+ // Do not allow odd rows to be modified since they are spacer rows
+ if (this.getLocation().getY() % 2 == 1) {
+ return;
+ }
+ // Red Element
+ if (e.getElementID().equals("STTT-PLAC-0002")) {
+ this.data = ShortTruthTableCellType.FALSE;
+ }
+ // Green Element
+ else {
+ if (e.getElementID().equals("STTT-PLAC-0001")) {
+ this.data = ShortTruthTableCellType.TRUE;
+ }
+ // Unknown Element
+ else {
+ if (e.getElementID().equals("STTT-PLAC-0003")) {
+ this.data = ShortTruthTableCellType.UNKNOWN;
+ }
+ // Argument Element
+ else {
+ if (e.getElementID().equals("STTT-UNPL-0001")) {
+ // Prevents non-argument symbols from being changed
+ if (!(this.symbol >= 'A' && this.symbol <= 'Z')) {
+ return;
+ }
+
+ if (m.getButton() == MouseEvent.BUTTON1) {
+ this.symbol += 1;
+ if (this.symbol > 'Z') {
+ this.symbol = 'A';
+ }
+ }
+ else {
+ if (m.getButton() == MouseEvent.BUTTON3) {
+ this.symbol -= 1;
+ if (this.symbol < 'A') {
+ this.symbol = 'Z';
+ }
+ }
+ }
+ }
+ // And/Or Element
+ else {
+ if (e.getElementID().equals("STTT-UNPL-0002")) {
+ if (m.getButton() == MouseEvent.BUTTON1) {
+ if (this.symbol == '^') {
+ this.symbol = '|';
+ }
+ else {
+ if (this.symbol == '|') {
+ this.symbol = '>';
+ }
+ else {
+ if (this.symbol == '>') {
+ this.symbol = '-';
+ }
+ else {
+ if (this.symbol == '-') {
+ this.symbol = '^';
+ }
+ }
+ }
+ }
+ }
+ else {
+ if (m.getButton() == MouseEvent.BUTTON3) {
+ if (this.symbol == '^') {
+ this.symbol = '-';
+ }
+ else {
+ if (this.symbol == '|') {
+ this.symbol = '^';
+ }
+ else {
+ if (this.symbol == '>') {
+ this.symbol = '|';
+ }
+ else {
+ if (this.symbol == '-') {
+ this.symbol = '>';
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableCellType.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableCellType.java
index c01fe74d8..c997faf5f 100644
--- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableCellType.java
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableCellType.java
@@ -26,6 +26,7 @@ public static ShortTruthTableCellType valueOf(int cellType) {
/**
* Gets the char value of a cell, Used for debugging
+ *
* @param type cell type input
* @return true if value is 1, false if value is 0, ? if value is -1, or blank otherwise
*/
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableController.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableController.java
index ccf4e9274..bddde44a5 100644
--- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableController.java
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableController.java
@@ -12,7 +12,7 @@ public void changeCell(MouseEvent e, PuzzleElement data) {
System.out.println("STTController: Cell change");
- //cast the data to a short truth table cell
+ // cast the data to a short truth table cell
ShortTruthTableCell cell = (ShortTruthTableCell) data;
if (e.getButton() == MouseEvent.BUTTON1) {
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableExporter.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableExporter.java
index bcb744789..9d6553c7c 100644
--- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableExporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableExporter.java
@@ -2,6 +2,7 @@
import edu.rpi.legup.model.PuzzleExporter;
import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.puzzle.nurikabe.NurikabeBoard;
import org.w3c.dom.Document;
public class ShortTruthTableExporter extends PuzzleExporter {
@@ -12,7 +13,13 @@ public ShortTruthTableExporter(ShortTruthTable stt) {
@Override
protected org.w3c.dom.Element createBoardElement(Document newDocument) {
- ShortTruthTableBoard board = (ShortTruthTableBoard) puzzle.getTree().getRootNode().getBoard();
+ ShortTruthTableBoard board;
+ if (puzzle.getTree() != null) {
+ board = (ShortTruthTableBoard) puzzle.getTree().getRootNode().getBoard();
+ }
+ else {
+ board = (ShortTruthTableBoard) puzzle.getBoardView().getBoard();
+ }
org.w3c.dom.Element boardElement = newDocument.createElement("board");
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableImporter.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableImporter.java
index cccdbca19..84d04fb45 100644
--- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/ShortTruthTableImporter.java
@@ -3,16 +3,15 @@
import edu.rpi.legup.model.PuzzleImporter;
import edu.rpi.legup.save.InvalidFileFormatException;
import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
-import org.w3c.dom.NamedNodeMap;
+import javax.swing.*;
import java.awt.*;
-
-import java.util.List;
import java.util.ArrayList;
-
-import javax.swing.*;
+import java.util.LinkedList;
+import java.util.List;
class ShortTruthTableImporter extends PuzzleImporter {
@@ -55,8 +54,8 @@ private List getCells(String statement, int y) {
* @return the length, in chars, of the longest statement
*/
private int parseAllStatementsAndCells(final NodeList statementData,
- List> allCells,
- List statements) throws InvalidFileFormatException {
+ List> allCells,
+ List statements) throws InvalidFileFormatException {
int maxStatementLength = 0;
@@ -65,7 +64,10 @@ private int parseAllStatementsAndCells(final NodeList statementData,
//Get the atributes from the statement i in the file
NamedNodeMap attributeList = statementData.item(i).getAttributes();
+
String statementRep = attributeList.getNamedItem("representation").getNodeValue();
+ System.out.println("STATEMENT REP: " + statementRep);
+ System.out.println("ROW INDEX: " + attributeList.getNamedItem("row_index").getNodeValue());
//parser time (on statementRep)
//if (!validGrammar(statementRep)) throw some error
if (!validGrammar(statementRep)) {
@@ -85,10 +87,32 @@ private int parseAllStatementsAndCells(final NodeList statementData,
}
return maxStatementLength;
+ }
+
+ private int parseAllStatementsAndCells(String[] statementData,
+ List> allCells,
+ List statements) throws IllegalArgumentException {
+ int maxStatementLength = 0;
+
+ for (int i = 0; i < statementData.length; i++) {
+ if (!validGrammar(statementData[i])) {
+ JOptionPane.showMessageDialog(null, "ERROR: Invalid file syntax");
+ throw new IllegalArgumentException("shorttruthtable importer: invalid sentence syntax");
+ }
+
+ //get the cells for the statement
+ List rowOfCells = getCells(statementData[i], i * 2);
+ allCells.add(rowOfCells);
+ statements.add(new ShortTruthTableStatement(statementData[i], rowOfCells));
+
+ //keep track of the length of the longest statement
+ maxStatementLength = Math.max(maxStatementLength, statementData[i].length());
+ }
+ return maxStatementLength;
}
- private boolean validGrammar(String sentence) {
+ protected boolean validGrammar(String sentence) {
int open = 0;
int close = 0;
char[] valid_characters = new char[]{'^', 'v', '!', '>', '-', '&', '|', '~', '$', '%'};
@@ -217,6 +241,16 @@ private void setGivenCells(ShortTruthTableBoard sttBoard,
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return false;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return true;
+ }
+
/**
* Creates an empty board for building
*
@@ -278,9 +312,37 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
catch (NumberFormatException e) {
throw new InvalidFileFormatException("short truth table Importer: unknown value where integer expected");
}
+ }
+ /**
+ * Creates the board for building using statements
+ *
+ * @param statementInput
+ * @throws UnsupportedOperationException
+ * @throws IllegalArgumentException
+ */
+ public void initializeBoard(String[] statementInput) throws UnsupportedOperationException, IllegalArgumentException {
+ List statementsList = new LinkedList<>();
+ for (String s : statementInput) {
+ if (s.strip().length() > 0) {
+ statementsList.add(s);
+ }
+ }
+ String[] statementData = statementsList.toArray(new String[statementsList.size()]);
- }
+ if (statementData.length == 0) {
+ throw new IllegalArgumentException("short truth table Importer: no statements found for board");
+ }
+ // Store all cells and statements
+ List> allCells = new ArrayList<>();
+ List statements = new ArrayList<>();
+ // Parse the data
+ int maxStatementLength = parseAllStatementsAndCells(statementData, allCells, statements);
+
+ // Generate and set the board - don't set given cell values since none are given
+ ShortTruthTableBoard sttBoard = generateBoard(allCells, statements, maxStatementLength);
+ puzzle.setCurrentBoard(sttBoard);
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/ArgumentElement.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/ArgumentElement.java
new file mode 100644
index 000000000..9f238a9bf
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/ArgumentElement.java
@@ -0,0 +1,9 @@
+package edu.rpi.legup.puzzle.shorttruthtable.elements;
+
+import edu.rpi.legup.model.elements.NonPlaceableElement;
+
+public class ArgumentElement extends NonPlaceableElement {
+ public ArgumentElement() {
+ super("STTT-UNPL-0001", "Argument Element", "Argument of logic statement element", "edu/rpi/legup/images/shorttruthtable/tiles/LetterTile.png");
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/GreenElement.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/GreenElement.java
new file mode 100644
index 000000000..605f6a207
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/GreenElement.java
@@ -0,0 +1,9 @@
+package edu.rpi.legup.puzzle.shorttruthtable.elements;
+
+import edu.rpi.legup.model.elements.PlaceableElement;
+
+public class GreenElement extends PlaceableElement {
+ public GreenElement() {
+ super("STTT-PLAC-0001", "Green Element", "A green tile to set certain tiles to true", "edu/rpi/legup/images/shorttruthtable/tiles/GreenTile.png");
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/LogicSymbolElement.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/LogicSymbolElement.java
new file mode 100644
index 000000000..b2adfddef
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/LogicSymbolElement.java
@@ -0,0 +1,9 @@
+package edu.rpi.legup.puzzle.shorttruthtable.elements;
+
+import edu.rpi.legup.model.elements.NonPlaceableElement;
+
+public class LogicSymbolElement extends NonPlaceableElement {
+ public LogicSymbolElement() {
+ super("STTT-UNPL-0002", "Logic Symbol Element", "Logic symbol element", "edu/rpi/legup/images/shorttruthtable/tiles/ConditionalBiconditionalTile.png");
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/RedElement.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/RedElement.java
new file mode 100644
index 000000000..ecc7d5a02
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/RedElement.java
@@ -0,0 +1,9 @@
+package edu.rpi.legup.puzzle.shorttruthtable.elements;
+
+import edu.rpi.legup.model.elements.PlaceableElement;
+
+public class RedElement extends PlaceableElement {
+ public RedElement() {
+ super("STTT-PLAC-0002", "Red Element", "A red tile to set certain tiles to false", "edu/rpi/legup/images/shorttruthtable/tiles/RedTile.png");
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/UnknownElement.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/UnknownElement.java
new file mode 100644
index 000000000..9a9ab8b84
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/UnknownElement.java
@@ -0,0 +1,9 @@
+package edu.rpi.legup.puzzle.shorttruthtable.elements;
+
+import edu.rpi.legup.model.elements.PlaceableElement;
+
+public class UnknownElement extends PlaceableElement {
+ public UnknownElement() {
+ super("STTT-PLAC-0003", "Unknown Element", "A blank tile", "edu/rpi/legup/images/shorttruthtable/tiles/UnknownTile.png");
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/shorttruthtable_elements_reference_sheet b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/shorttruthtable_elements_reference_sheet
new file mode 100644
index 000000000..471631553
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/elements/shorttruthtable_elements_reference_sheet
@@ -0,0 +1,6 @@
+STTT-UNPL-0001 : ArgumentElement
+STTT-UNPL-0002 : ConditionalBiconditionalElement
+
+STTT-PLAC-0001 : GreenElement
+STTT-PLAC-0002 : RedElement
+STTT-PLAC-0003 : UnknownElement
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/shorttruthtable_reference_sheet.txt b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/shorttruthtable_rules_reference_sheet.txt
similarity index 100%
rename from src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/shorttruthtable_reference_sheet.txt
rename to src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/shorttruthtable_rules_reference_sheet.txt
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersCellFactory.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersCellFactory.java
index d276c8bff..da6899f75 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersCellFactory.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersCellFactory.java
@@ -35,7 +35,7 @@ public PuzzleElement importCell(Node node, Board board) throws InvalidFileFormat
if (x >= width || y >= height) {
throw new InvalidFileFormatException("TreeTent Factory: cell location out of bounds");
}
- if (value < 0 || value > 3) {
+ if (value < 0 || value > width) {
throw new InvalidFileFormatException("TreeTent Factory: cell unknown value");
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersExporter.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersExporter.java
index dac09bd16..155a1466c 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersExporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersExporter.java
@@ -2,6 +2,7 @@
import edu.rpi.legup.model.PuzzleExporter;
import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.puzzle.shorttruthtable.ShortTruthTableBoard;
import org.w3c.dom.Document;
public class SkyscrapersExporter extends PuzzleExporter {
@@ -12,11 +13,16 @@ public SkyscrapersExporter(Skyscrapers skyscrapers) {
@Override
protected org.w3c.dom.Element createBoardElement(Document newDocument) {
- SkyscrapersBoard board = (SkyscrapersBoard) puzzle.getTree().getRootNode().getBoard();
+ SkyscrapersBoard board;
+ if (puzzle.getTree() != null) {
+ board = (SkyscrapersBoard) puzzle.getTree().getRootNode().getBoard();
+ }
+ else {
+ board = (SkyscrapersBoard) puzzle.getBoardView().getBoard();
+ }
org.w3c.dom.Element boardElement = newDocument.createElement("board");
- boardElement.setAttribute("width", String.valueOf(board.getWidth()));
- boardElement.setAttribute("height", String.valueOf(board.getHeight()));
+ boardElement.setAttribute("size", String.valueOf(board.getWidth()));
org.w3c.dom.Element cellsElement = newDocument.createElement("cells");
for (PuzzleElement puzzleElement : board.getPuzzleElements()) {
@@ -30,20 +36,20 @@ protected org.w3c.dom.Element createBoardElement(Document newDocument) {
org.w3c.dom.Element axisEast = newDocument.createElement("axis");
axisEast.setAttribute("side", "east");
- for (SkyscrapersClue clue : board.getEastClues()) {
+ for (int i=0; i {
- JOptionPane.showMessageDialog(null, "Version: 2.0.0");
+ JOptionPane.showMessageDialog(null, "Version: 5.1.0");
});
about.add(helpLegup);
diff --git a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
index cce4feec5..2c4f37c85 100644
--- a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
+++ b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
@@ -64,6 +64,7 @@ public PuzzleEditorPanel(FileDialog fileDialog, JFrame frame, LegupUI legupUI) {
this.frame = frame;
this.legupUI = legupUI;
setLayout(new BorderLayout());
+ setPreferredSize(new Dimension(800, 700));
}
protected void setupContent() {
@@ -202,7 +203,7 @@ public void actionPerformed(ActionEvent e) {
});
menus[2].add(aboutLegup);
aboutLegup.addActionListener(l -> {
- JOptionPane.showMessageDialog(null, "Version: 2.0.0");
+ JOptionPane.showMessageDialog(null, "Version: 5.1.0");
});
// add menus to menubar
for (JMenu menu : menus) {
@@ -327,6 +328,20 @@ public void loadPuzzleFromHome(String game, int rows, int columns) throws Illega
}
}
+ public void loadPuzzleFromHome(String game, String[] statements) {
+ GameBoardFacade facade = GameBoardFacade.getInstance();
+ try {
+ facade.loadPuzzle(game, statements);
+ }
+ catch (IllegalArgumentException exception) {
+ throw new IllegalArgumentException(exception.getMessage());
+ }
+ catch (RuntimeException e) {
+ e.printStackTrace();
+ LOGGER.error(e.getMessage());
+ }
+ }
+
// File opener
public Object[] promptPuzzle() {
GameBoardFacade facade = GameBoardFacade.getInstance();
diff --git a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java
index a2d37e800..0fe03d476 100644
--- a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java
+++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java
@@ -70,7 +70,7 @@ protected boolean shouldRotateTabRuns(int i) {
setLayout(new BorderLayout());
setMinimumSize(new Dimension(250, 256));
- setPreferredSize(new Dimension(330, 256));
+ setPreferredSize(new Dimension(355, 256));
add(tabbedPane);
add(status, BorderLayout.SOUTH);
diff --git a/src/main/resources/edu/rpi/legup/images/lightup/UnknownTile.png b/src/main/resources/edu/rpi/legup/images/lightup/UnknownTile.png
new file mode 100644
index 000000000..850fbf127
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/lightup/UnknownTile.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/AndOrTile.png b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/AndOrTile.png
new file mode 100644
index 000000000..9ea932502
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/AndOrTile.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/ConditionalBiconditionalTile.png b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/ConditionalBiconditionalTile.png
new file mode 100644
index 000000000..b1af3468e
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/ConditionalBiconditionalTile.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/GreenTile.png b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/GreenTile.png
new file mode 100644
index 000000000..a438e3037
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/GreenTile.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/LetterTile.png b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/LetterTile.png
new file mode 100644
index 000000000..5f94da225
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/LetterTile.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/RedTile.png b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/RedTile.png
new file mode 100644
index 000000000..7955c8f92
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/RedTile.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/UnknownTile.png b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/UnknownTile.png
new file mode 100644
index 000000000..850fbf127
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/shorttruthtable/tiles/UnknownTile.png differ
diff --git a/src/main/resources/edu/rpi/legup/legup/config b/src/main/resources/edu/rpi/legup/legup/config
index bb7da871a..24fdcf365 100644
--- a/src/main/resources/edu/rpi/legup/legup/config
+++ b/src/main/resources/edu/rpi/legup/legup/config
@@ -27,7 +27,7 @@
+ fileCreationDisabled="false"/>
diff --git a/src/test/java/legup/TestRunner.java b/src/test/java/legup/TestRunner.java
index 7e2dbe737..9d79c590e 100644
--- a/src/test/java/legup/TestRunner.java
+++ b/src/test/java/legup/TestRunner.java
@@ -9,6 +9,9 @@
import puzzles.nurikabe.rules.*;
import puzzles.treetent.rules.*;
+/**
+ * This class runs all of the tests for the project without needing to run build scripts.
+ */
public class TestRunner {
public static void main(String[] args) {
// Battleship Tests
@@ -103,6 +106,4 @@ private static void printTestResults(Result result) {
System.out.println("All tests passed: " + result.wasSuccessful());
System.out.println();
}
-
-
-}
\ No newline at end of file
+}
diff --git a/src/test/java/legup/TestUtilities.java b/src/test/java/legup/TestUtilities.java
index d49529921..9f203b223 100644
--- a/src/test/java/legup/TestUtilities.java
+++ b/src/test/java/legup/TestUtilities.java
@@ -6,11 +6,6 @@
import edu.rpi.legup.model.tree.TreeNode;
import edu.rpi.legup.model.tree.TreeTransition;
import edu.rpi.legup.save.InvalidFileFormatException;
-import org.junit.runner.JUnitCore;
-import org.junit.runner.Result;
-import org.junit.runner.notification.Failure;
-import puzzles.battleship.rules.AdjacentShipsContradictionRuleTest;
-import puzzles.battleship.rules.FinishWithShipsDirectRuleTests;
public final class TestUtilities {
public static void importTestBoard(String fileName, Puzzle puzzle) throws InvalidFileFormatException {
@@ -21,8 +16,4 @@ public static void importTestBoard(String fileName, Puzzle puzzle) throws Invali
TreeTransition transition = new TreeTransition(rootNode, board);
rootNode.getChildren().add(transition);
}
-
-
}
-
-