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/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/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/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/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/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/SkyscrapersImporter.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java
index 22af18a4c..6dded9764 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java
@@ -13,6 +13,16 @@ public SkyscrapersImporter(Skyscrapers skyscrapers) {
super(skyscrapers);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -150,4 +160,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
throw new InvalidFileFormatException("Skyscraper Importer: unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Skyscrapers cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuImporter.java b/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuImporter.java
index f77a68d7a..dccec52d4 100644
--- a/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/sudoku/SudokuImporter.java
@@ -13,6 +13,16 @@ public SudokuImporter(Sudoku sudoku) {
super(sudoku);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -112,4 +122,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
throw new InvalidFileFormatException("Sudoku Importer: unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Sudoku cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java
index e48122a7a..2b4861c9f 100644
--- a/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/treetent/TreeTentImporter.java
@@ -13,6 +13,16 @@ public TreeTentImporter(TreeTent treeTent) {
super(treeTent);
}
+ @Override
+ public boolean acceptsRowsAndColumnsInput() {
+ return true;
+ }
+
+ @Override
+ public boolean acceptsTextInput() {
+ return false;
+ }
+
/**
* Creates an empty board for building
*
@@ -174,4 +184,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
throw new InvalidFileFormatException("TreeTent Importer: unknown value where integer expected");
}
}
+
+ @Override
+ public void initializeBoard(String[] statements) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("Tree Tent cannot accept text input");
+ }
}
diff --git a/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java b/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java
index 8e0858b72..fa049ab38 100644
--- a/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java
+++ b/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java
@@ -9,35 +9,71 @@
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
+import java.util.Objects;
public class CreatePuzzleDialog extends JDialog {
private HomePanel homePanel;
private String[] games;
private JComboBox gameBox;
+ private ActionListener gameBoxListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ JComboBox comboBox = (JComboBox) e.getSource();
+ String puzzleName = (String) comboBox.getSelectedItem();
+ if (puzzleName.equals("ShortTruthTable")) {
+ textInputScrollPane.setVisible(true);
+ rowsLabel.setVisible(false);
+ rows.setVisible(false);
+ columnsLabel.setVisible(false);
+ columns.setVisible(false);
+ }
+ else {
+ textInputScrollPane.setVisible(false);
+ rowsLabel.setVisible(true);
+ rows.setVisible(true);
+ columnsLabel.setVisible(true);
+ columns.setVisible(true);
+ }
+ }
+ };
- private JLabel puzzleLabel = new JLabel("Puzzle:");
+ private JLabel puzzleLabel;
+ private JLabel rowsLabel;
private JTextField rows;
+ private JLabel columnsLabel;
private JTextField columns;
+ private JTextArea textArea;
+ private JScrollPane textInputScrollPane;
+
private JButton ok = new JButton("Ok");
private ActionListener okButtonListener = new ActionListener() {
/**
* Attempts to open the puzzle editor interface for the given game with the given dimensions
- * @param e the event to be processed
+ * @param ae the event to be processed
*/
@Override
public void actionPerformed(ActionEvent ae) {
String game = Config.convertDisplayNameToClassName((String) gameBox.getSelectedItem());
// Check if all 3 TextFields are filled
- if (game.equals("") || rows.getText().equals("") || columns.getText().equals("")) {
+ if (game.equals("ShortTruthTable") && textArea.getText().equals("")) {
+ System.out.println("Unfilled fields");
+ return;
+ }
+ if (!game.equals("ShortTruthTable") && (game.equals("") || rows.getText().equals("") || columns.getText().equals(""))) {
System.out.println("Unfilled fields");
return;
}
try {
- homePanel.openEditorWithNewPuzzle(game, Integer.valueOf(rows.getText()), Integer.valueOf(columns.getText()));
+ if (game.equals("ShortTruthTable")) {
+ homePanel.openEditorWithNewPuzzle("ShortTruthTable", textArea.getText().split("\n"));
+ }
+ else {
+ homePanel.openEditorWithNewPuzzle(game, Integer.valueOf(rows.getText()), Integer.valueOf(columns.getText()));
+ }
setVisible(false);
}
catch (IllegalArgumentException e) {
@@ -75,6 +111,7 @@ public CreatePuzzleDialog(JFrame parent, HomePanel homePanel) {
Container c = getContentPane();
c.setLayout(null);
+ puzzleLabel = new JLabel("Puzzle:");
puzzleLabel.setBounds(10, 30, 70, 25);
gameBox.setBounds(80, 30, 190, 25);
@@ -87,8 +124,8 @@ public CreatePuzzleDialog(JFrame parent, HomePanel homePanel) {
rows = new JTextField();
columns = new JTextField();
- JLabel rowsLabel = new JLabel("Rows:");
- JLabel columnsLabel = new JLabel("Columns:");
+ rowsLabel = new JLabel("Rows:");
+ columnsLabel = new JLabel("Columns:");
rowsLabel.setBounds(30, 70, 60, 25);
columnsLabel.setBounds(30, 95, 60, 25);
@@ -102,9 +139,31 @@ public CreatePuzzleDialog(JFrame parent, HomePanel homePanel) {
c.add(rows);
c.add(columns);
+ textArea = new JTextArea();
+ textInputScrollPane = new JScrollPane(textArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ textInputScrollPane.setBounds(10, 70, this.getWidth() - 30, 50);
+ c.add(textInputScrollPane);
+
c.add(ok);
c.add(cancel);
+ if (Objects.equals(this.gameBox.getSelectedItem(), "ShortTruthTable")) {
+ textInputScrollPane.setVisible(true);
+ rowsLabel.setVisible(false);
+ rows.setVisible(false);
+ columnsLabel.setVisible(false);
+ columns.setVisible(false);
+ }
+ else {
+ textInputScrollPane.setVisible(false);
+ rowsLabel.setVisible(true);
+ rows.setVisible(true);
+ columnsLabel.setVisible(true);
+ columns.setVisible(true);
+ }
+
+ ActionListener cursorSelectedGame = CursorController.createListener(this, gameBoxListener);
+ gameBox.addActionListener(cursorSelectedGame);
ActionListener cursorPressedOk = CursorController.createListener(this, okButtonListener);
ok.addActionListener(cursorPressedOk);
ActionListener cursorPressedCancel = CursorController.createListener(this, cancelButtonListener);
@@ -123,7 +182,13 @@ public void actionPerformed(ActionEvent e) {
String game = Config.convertDisplayNameToClassName((String) gameBox.getSelectedItem());
try {
- this.homePanel.openEditorWithNewPuzzle(game, Integer.valueOf(this.rows.getText()), Integer.valueOf(this.columns.getText()));
+ if (game.equals("ShortTruthTable")) {
+ this.homePanel.openEditorWithNewPuzzle("ShortTruthTable", this.textArea.getText().split("\n"));
+ }
+ else {
+ this.homePanel.openEditorWithNewPuzzle(game, Integer.valueOf(this.rows.getText()), Integer.valueOf(this.columns.getText()));
+
+ }
this.setVisible(false);
}
catch (IllegalArgumentException exception) {
diff --git a/src/main/java/edu/rpi/legup/ui/HomePanel.java b/src/main/java/edu/rpi/legup/ui/HomePanel.java
index f72694cc0..48f0d03d7 100644
--- a/src/main/java/edu/rpi/legup/ui/HomePanel.java
+++ b/src/main/java/edu/rpi/legup/ui/HomePanel.java
@@ -1,11 +1,9 @@
package edu.rpi.legup.ui;
-import edu.rpi.legup.Legup;
import edu.rpi.legup.app.GameBoardFacade;
import edu.rpi.legup.app.LegupPreferences;
import edu.rpi.legup.controller.CursorController;
import edu.rpi.legup.save.InvalidFileFormatException;
-import edu.rpi.legup.app.LegupPreferences;
import edu.rpi.legup.model.Puzzle;
import edu.rpi.legup.model.PuzzleExporter;
import edu.rpi.legup.save.ExportFileException;
@@ -29,7 +27,6 @@
import java.io.FileWriter;
import java.net.URI;
import java.net.URL;
-import java.util.Objects;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -640,4 +637,28 @@ public void openEditorWithNewPuzzle(String game, int rows, int columns) throws I
this.legupUI.displayPanel(2);
this.legupUI.getPuzzleEditor().loadPuzzleFromHome(game, rows, columns);
}
+
+ /**
+ * Opens the puzzle editor for the specified game with the given statements
+ *
+ * @param game a String containing the name of the game
+ * @param statements an array of statements
+ */
+ public void openEditorWithNewPuzzle(String game, String[] statements) {
+ // Validate the text input
+ GameBoardFacade facade = GameBoardFacade.getInstance();
+ boolean isValidTextInput = facade.validateTextInput(game, statements);
+ if (!isValidTextInput) {
+ JOptionPane.showMessageDialog(null,
+ "The input you entered is invalid. Please double check \n" +
+ "your statements and try again.",
+ "ERROR: Invalid Text Input",
+ JOptionPane.ERROR_MESSAGE);
+ throw new IllegalArgumentException("ERROR: Invalid dimensions given");
+ }
+
+ // Set game type on the puzzle editor
+ this.legupUI.displayPanel(2);
+ this.legupUI.getPuzzleEditor().loadPuzzleFromHome(game, statements);
+ }
}
diff --git a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
index cce4feec5..90f0c3cdf 100644
--- a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
+++ b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
@@ -327,6 +327,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/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 f6694bc14..0f24e2249 100644
--- a/src/test/java/legup/TestRunner.java
+++ b/src/test/java/legup/TestRunner.java
@@ -10,6 +10,9 @@
import puzzles.skyscrapers.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
@@ -119,6 +122,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);
}
-
-
}
-
-