From 45b594e89ad7316d969b27a60e12accd57118f44 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Sun, 14 Jul 2024 10:13:28 -0400 Subject: [PATCH 1/6] Lock transition states before a future case rule, flash background red when an error occurs --- .../edu/rpi/legup/history/CommandError.java | 1 + .../rpi/legup/history/EditDataCommand.java | 37 ++++++++++---- .../java/edu/rpi/legup/history/History.java | 2 + .../edu/rpi/legup/history/MergeCommand.java | 2 +- .../legup/model/gameboard/PuzzleElement.java | 20 ++++++++ .../java/edu/rpi/legup/model/tree/Tree.java | 7 +++ .../edu/rpi/legup/ui/ProofEditorPanel.java | 2 - .../ui/proofeditorui/treeview/TreeView.java | 50 ++++++++++++++++--- 8 files changed, 99 insertions(+), 22 deletions(-) diff --git a/src/main/java/edu/rpi/legup/history/CommandError.java b/src/main/java/edu/rpi/legup/history/CommandError.java index 35b7bb15b..093143704 100644 --- a/src/main/java/edu/rpi/legup/history/CommandError.java +++ b/src/main/java/edu/rpi/legup/history/CommandError.java @@ -5,6 +5,7 @@ public enum CommandError { ONE_SELECTED_VIEW("The selection must have exactly one tree element."), UNMODIFIABLE_BOARD("The selection contains a board which is not modifiable."), UNMODIFIABLE_DATA("The selection contains a board where the data element is not modifiable."), + UNMODIFIABLE_DATA_CASE_RULE("The proof tree contains a future case rule, causing previous transitions to become unmodifiable."), CONTAINS_ROOT("The selection contains the root tree node."), ONE_CHILD("The selection contains a tree node that does not have exactly one child."), ADD_WITH_CHILD("The selection contains a tree transition that already has a child tree node."), diff --git a/src/main/java/edu/rpi/legup/history/EditDataCommand.java b/src/main/java/edu/rpi/legup/history/EditDataCommand.java index d65f03d66..511cd803f 100644 --- a/src/main/java/edu/rpi/legup/history/EditDataCommand.java +++ b/src/main/java/edu/rpi/legup/history/EditDataCommand.java @@ -9,7 +9,11 @@ import edu.rpi.legup.model.tree.*; import edu.rpi.legup.ui.boardview.BoardView; import edu.rpi.legup.ui.boardview.ElementView; +import edu.rpi.legup.ui.lookandfeel.materialdesign.MaterialColors; import edu.rpi.legup.ui.proofeditorui.treeview.*; + +import javax.swing.*; +import java.awt.*; import java.awt.event.MouseEvent; import java.util.List; @@ -26,7 +30,7 @@ public class EditDataCommand extends PuzzleCommand { * EditDataCommand Constructor create a puzzle command for editing a board * * @param elementView currently selected puzzle puzzleElement view that is being edited - * @param selection currently selected tree puzzleElement views that is being edited + * @param selection currently selected tree puzzleElement views that are being edited * @param event mouse event */ public EditDataCommand(ElementView elementView, TreeViewSelection selection, MouseEvent event) { @@ -54,16 +58,13 @@ public void executeCommand() { if (treeElement.getType() == TreeElementType.NODE) { TreeNode treeNode = (TreeNode) treeElement; - if (treeNode.getChildren().isEmpty()) { if (transition == null) { transition = tree.addNewTransition(treeNode); } puzzle.notifyTreeListeners(listener -> listener.onTreeElementAdded(transition)); } - board = transition.getBoard(); - puzzleElement = board.getPuzzleElement(selectedPuzzleElement); savePuzzleElement = puzzleElement.copy(); } else { @@ -73,7 +74,6 @@ public void executeCommand() { } Board prevBoard = transition.getParents().get(0).getBoard(); - boardView.getElementController().changeCell(event, puzzleElement); if (prevBoard.getPuzzleElement(selectedPuzzleElement).equalsData(puzzleElement)) { @@ -102,35 +102,50 @@ public void executeCommand() { public String getErrorString() { List selectedViews = selection.getSelectedViews(); if (selectedViews.size() != 1) { + flashTreeViewRed(); return CommandError.ONE_SELECTED_VIEW.toString(); } TreeElementView selectedView = selection.getFirstSelection(); Board board = selectedView.getTreeElement().getBoard(); PuzzleElement selectedPuzzleElement = elementView.getPuzzleElement(); if (selectedView.getType() == TreeElementType.NODE) { - TreeNodeView nodeView = (TreeNodeView) selectedView; if (!nodeView.getChildrenViews().isEmpty()) { + flashTreeViewRed(); return CommandError.UNMODIFIABLE_BOARD.toString(); - } else { - if (!board.getPuzzleElement(selectedPuzzleElement).isModifiable()) { - return CommandError.UNMODIFIABLE_DATA.toString(); - } + } else if (!board.getPuzzleElement(selectedPuzzleElement).isModifiable()) { + flashTreeViewRed(); + return CommandError.UNMODIFIABLE_DATA.toString(); } } else { TreeTransitionView transitionView = (TreeTransitionView) selectedView; if (!transitionView.getTreeElement().getBoard().isModifiable()) { + flashTreeViewRed(); return CommandError.UNMODIFIABLE_BOARD.toString(); } else { if (!board.getPuzzleElement(selectedPuzzleElement).isModifiable()) { + flashTreeViewRed(); return CommandError.UNMODIFIABLE_DATA.toString(); + } else if (!board.getPuzzleElement(selectedPuzzleElement).isModifiableCaseRule()) { + flashTreeViewRed(); + return CommandError.UNMODIFIABLE_DATA_CASE_RULE.toString(); } } } return null; } - /** Undoes an command */ + /** Causes the TreeView background to flash red for a short duration. */ + private void flashTreeViewRed() { + TreeView treeView = getInstance().getLegupUI().getTreePanel().getTreeView(); + Color originalColor = treeView.getBackground(); + treeView.setBackground(MaterialColors.RED_700); + Timer timer = new Timer(400, e -> treeView.setBackground(originalColor)); + timer.setRepeats(false); + timer.start(); + } + + /** Undoes a command */ @SuppressWarnings("unchecked") @Override public void undoCommand() { diff --git a/src/main/java/edu/rpi/legup/history/History.java b/src/main/java/edu/rpi/legup/history/History.java index 371284f8c..dca6af3f3 100644 --- a/src/main/java/edu/rpi/legup/history/History.java +++ b/src/main/java/edu/rpi/legup/history/History.java @@ -51,6 +51,8 @@ public void undo() { ICommand command = history.get(curIndex--); command.undo(); LOGGER.info("Undoed " + command.getClass().getSimpleName()); + + GameBoardFacade.getInstance() .notifyHistoryListeners( l -> l.onUndo(curIndex < 0, curIndex == history.size() - 1)); diff --git a/src/main/java/edu/rpi/legup/history/MergeCommand.java b/src/main/java/edu/rpi/legup/history/MergeCommand.java index f234a0884..d7a7f97f1 100644 --- a/src/main/java/edu/rpi/legup/history/MergeCommand.java +++ b/src/main/java/edu/rpi/legup/history/MergeCommand.java @@ -24,7 +24,7 @@ public MergeCommand(TreeViewSelection selection) { this.transition = null; } - /** Executes an command */ + /** Executes a command */ @Override public void executeCommand() { List selectedViews = selection.getSelectedViews(); diff --git a/src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java b/src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java index 4ce030a04..719d524da 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/PuzzleElement.java @@ -8,6 +8,7 @@ public abstract class PuzzleElement { protected T data; protected boolean isModifiable; protected boolean isModified; + protected boolean isModifiableCaseRule; protected boolean isGiven; protected boolean isValid; protected int casesDepended; @@ -17,6 +18,7 @@ public PuzzleElement() { this.index = -1; this.data = null; this.isModifiable = true; + this.isModifiableCaseRule = true; this.isModified = false; this.isGiven = false; this.isValid = true; @@ -73,6 +75,24 @@ public void setModifiable(boolean isModifiable) { this.isModifiable = isModifiable; } + /** + * Gets whether this puzzle element is modifiable as a result of a case rule. + * + * @return true if this puzzle element is modifiable, false otherwise + */ + public boolean isModifiableCaseRule() { + return isModifiableCaseRule; + } + + /** + * Sets whether this puzzle element is modifiable as a result of a case rule. + * + * @param isModifiableCaseRule true if this puzzle element is modifiable, false otherwise + */ + public void setModifiableCaseRule(boolean isModifiableCaseRule) { + this.isModifiableCaseRule = isModifiableCaseRule; + } + /** * Gets whether the puzzle element has been modified. * 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 3cdab80c2..56cfbff07 100644 --- a/src/main/java/edu/rpi/legup/model/tree/Tree.java +++ b/src/main/java/edu/rpi/legup/model/tree/Tree.java @@ -1,6 +1,10 @@ package edu.rpi.legup.model.tree; +import edu.rpi.legup.controller.TreeController; import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.rules.CaseRule; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeView; + import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -95,6 +99,9 @@ public void removeTreeElement(TreeElement element) { System.out.println("Deleted arrow: " + transition); transition.getParents().forEach(n -> n.removeChild(transition)); + TreeController treeController = new TreeController(); + TreeView treeView = new TreeView(treeController); + treeView.removeTreeTransition(transition); transition.getParents().get(0).getChildren().forEach(TreeTransition::reverify); } } diff --git a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java index f78281c89..b6117cb4f 100644 --- a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java +++ b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java @@ -9,11 +9,9 @@ import edu.rpi.legup.model.Puzzle; import edu.rpi.legup.model.PuzzleExporter; import edu.rpi.legup.model.gameboard.Board; -import edu.rpi.legup.model.gameboard.PuzzleElement; import edu.rpi.legup.model.tree.Tree; import edu.rpi.legup.model.tree.TreeNode; import edu.rpi.legup.model.tree.TreeTransition; -import edu.rpi.legup.puzzle.binary.BinaryType; import edu.rpi.legup.save.ExportFileException; import edu.rpi.legup.save.InvalidFileFormatException; import edu.rpi.legup.ui.boardview.BoardView; diff --git a/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java index ea622881c..5a7af1e95 100644 --- a/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java @@ -460,11 +460,41 @@ private void removeTreeNode(TreeNode node) { node.getChildren().forEach(t -> removeTreeTransition(t)); } - private void removeTreeTransition(TreeTransition trans) { + public void removeTreeTransition(TreeTransition trans) { viewMap.remove(trans); if (trans.getChildNode() != null) { removeTreeNode(trans.getChildNode()); } + + // Update transition modifiability if removing a case rule + List parents = trans.getParents(); + for (TreeNode parent : parents) { + System.out.println(parent.getParent().getRule()); + + // if transition is a case rule, unlock ancestor elements up until latest case rule or root node + boolean nextAncestorIsCaseRule = false; + Rule rule = trans.getRule(); + if (rule instanceof CaseRule) { + List ancestors = parent.getAncestors(); + for (int i = 0; i < ancestors.size(); i++) { + if (ancestors.get(i).getParent() == null) { + continue; + } + if (nextAncestorIsCaseRule) { + break; + } + for (PuzzleElement element : parent.getBoard().getPuzzleElements()) { + PuzzleElement curElement = ancestors.get(i).getParent().getBoard().getPuzzleElement(element); + if (!curElement.isModifiableCaseRule()) { + curElement.setModifiableCaseRule(true); + } + } + if (ancestors.get(i).getParent().getRule() instanceof CaseRule) { + nextAncestorIsCaseRule = true; + } + } + } + } } private void addTreeNode(TreeNode node) { @@ -519,7 +549,7 @@ private void addTreeTransition(TreeTransition trans) { // if transition is a new case rule, lock dependent ancestor elements Rule rule = trans.getRule(); if (rule instanceof CaseRule && parent.getChildren().size() == 1) { - CaseRule caseRule = (CaseRule) rule; + //CaseRule caseRule = (CaseRule) rule; List ancestors = parent.getAncestors(); for (TreeNode ancestor : ancestors) { @@ -527,13 +557,17 @@ private void addTreeTransition(TreeTransition trans) { if (ancestor.getParent() == null) { continue; } - for (PuzzleElement element : - caseRule.dependentElements(parent.getBoard(), trans.getSelection())) { - // increment and lock - PuzzleElement oldElement = - ancestor.getParent().getBoard().getPuzzleElement(element); - oldElement.setCasesDepended(oldElement.getCasesDepended() + 1); + + for (PuzzleElement element : parent.getBoard().getPuzzleElements()) { + PuzzleElement curElement = ancestor.getParent().getBoard().getPuzzleElement(element); + curElement.setModifiableCaseRule(false); } +// for (PuzzleElement element : caseRule.dependentElements(parent.getBoard(), trans.getSelection())) { +// // increment and lock +// PuzzleElement oldElement = ancestor.getParent().getBoard().getPuzzleElement(element); +// oldElement.setCasesDepended(oldElement.getCasesDepended() + 1); +// oldElement.setModifiable(false); +// } } } } From 39dbef4f3e918e5a6d3fe6b62b6155ac27c4b7f9 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Sun, 14 Jul 2024 10:13:53 -0400 Subject: [PATCH 2/6] Modified finish room case rule to allow a minimum of only one state --- .../rpi/legup/puzzle/nurikabe/rules/FinishRoomCaseRule.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/FinishRoomCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/FinishRoomCaseRule.java index 0dfbc7686..dd8943cdb 100644 --- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/FinishRoomCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/FinishRoomCaseRule.java @@ -28,7 +28,7 @@ public FinishRoomCaseRule() { "Room can be finished in up to nine ways", "edu/rpi/legup/images/nurikabe/cases/FinishRoom.png"); this.MAX_CASES = 9; - this.MIN_CASES = 2; + this.MIN_CASES = 1; this.uniqueCases = new HashSet<>(); } @@ -49,7 +49,7 @@ public String checkRuleRaw(TreeTransition transition) { } if (childTransitions.size() < MIN_CASES) { return super.getInvalidUseOfRuleMessage() - + ": This case rule must have 2 or more children."; + + ": This case rule must have 1 or more children."; } if (childTransitions.size() != legitCases) { return super.getInvalidUseOfRuleMessage() From c2c3aab82bdc583ad586415265d991ec2039b895 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Sun, 14 Jul 2024 10:19:56 -0400 Subject: [PATCH 3/6] Updated finish room case rule test to match current functionality --- .../rules/FinishRoomCaseRuleTest.java | 37 ++----------------- 1 file changed, 4 insertions(+), 33 deletions(-) diff --git a/src/test/java/puzzles/nurikabe/rules/FinishRoomCaseRuleTest.java b/src/test/java/puzzles/nurikabe/rules/FinishRoomCaseRuleTest.java index 5f5b6d35a..a29a1c934 100644 --- a/src/test/java/puzzles/nurikabe/rules/FinishRoomCaseRuleTest.java +++ b/src/test/java/puzzles/nurikabe/rules/FinishRoomCaseRuleTest.java @@ -28,13 +28,12 @@ public static void setUp() { } /** - * Tests the Finish Room case rule by ensuring that it results in 5 or less children, that - * contain a modified cell that is white + * Tests the Finish Room case rule by ensuring it produces the correct number of children */ + @Test public void FinishRoomCaseRule_FinishRoomCaseRuleBaseTest() throws InvalidFileFormatException { - TestUtilities.importTestBoard( - "puzzles/nurikabe/rules/FinishRoomCaseRule/FinishRoomCaseRuleBase", nurikabe); + TestUtilities.importTestBoard("puzzles/nurikabe/rules/FinishRoomCaseRule/FinishRoomCaseRuleBase", nurikabe); TreeNode rootNode = nurikabe.getTree().getRootNode(); TreeTransition transition = rootNode.getChildren().get(0); transition.setRule(RULE); @@ -81,34 +80,6 @@ public void FinishRoomCaseRule_FinishRoomCaseRuleBaseTest() throws InvalidFileFo NurikabeCell cell2 = board.getCell(4, 2); ArrayList cases2 = RULE.getCases(board, cell2); - Assert.assertEquals(6, cases2.size()); // correctly stops generating possible cases after - // more than 5 (the max) is found. Would have generated 8 cases - // FinishRoomCaseRule finny = new FinishRoomCaseRule(); - // finny.checkRuleRaw(); - // "Invalid use of the case rule FinishRoom: This case rule must have 5 or less children." - - // getErrorString in auto case rule - // should display "The selection can produce a max of 5 cases." - // AutoCaseRuleCommand autoCaseRuleCommand = new AutoCaseRuleCommand(elementView, selection, - // caseBoard.getCaseRule(), caseBoard, e); - - // NurikabeBoard caseyBoard = (NurikabeBoard) cases2.get(0); - // NurikabeBoard caseyBoard2 = (NurikabeBoard) cases2.get(1); - // NurikabeBoard caseyBoard3 = (NurikabeBoard) cases2.get(2); - // NurikabeBoard caseyBoard4 = (NurikabeBoard) cases2.get(3); - // NurikabeBoard caseyBoard5 = (NurikabeBoard) cases2.get(4); - // NurikabeBoard caseyBoard6 = (NurikabeBoard) cases2.get(5); - // NurikabeBoard caseyBoard7 = (NurikabeBoard) cases2.get(6); - // NurikabeBoard caseyBoard8 = (NurikabeBoard) cases2.get(7); - // - // NurikabeType boardy1Type = caseyBoard.getCell(5,5).getType(); - // NurikabeType boardy2Type = caseyBoard2.getCell(6,6).getType(); - // NurikabeType boardy3Type = caseyBoard.getCell(5,5).getType(); - // NurikabeType boardy4Type = caseyBoard2.getCell(6,6).getType(); - // NurikabeType boardy5Type = caseyBoard.getCell(5,5).getType(); - // NurikabeType boardy6Type = caseyBoard2.getCell(6,6).getType(); - // NurikabeType boardy7Type = caseyBoard.getCell(5,5).getType(); - // NurikabeType boardy8Type = caseyBoard2.getCell(6,6).getType(); - + Assert.assertEquals(9, cases2.size()); } } From 3e8a438658b511f3b4f6b4717f681267cf31a18b Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Sun, 14 Jul 2024 10:41:09 -0400 Subject: [PATCH 4/6] Fixed bug that prevented user from deleting transition from the root node --- .../java/edu/rpi/legup/history/DeleteTreeElementCommand.java | 2 +- src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java | 2 +- .../java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java b/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java index 258aaacc0..35a56c652 100644 --- a/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java +++ b/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java @@ -72,7 +72,7 @@ public String getErrorString() { return null; } - /** Undoes an command */ + /** Undoes a command */ @Override public void undoCommand() { Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule(); diff --git a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java index b6117cb4f..624ac102a 100644 --- a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java +++ b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java @@ -168,7 +168,7 @@ public JMenuBar getMenuBar() { } proof.add(add); - delete = new JMenuItem("D\"Check All\"elete"); + delete = new JMenuItem("Delete"); delete.addActionListener(a -> treePanel.delete()); if (os.equals("mac")) { delete.setAccelerator( diff --git a/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java index 5a7af1e95..d7fffd1bf 100644 --- a/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java +++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/treeview/TreeView.java @@ -469,8 +469,6 @@ public void removeTreeTransition(TreeTransition trans) { // Update transition modifiability if removing a case rule List parents = trans.getParents(); for (TreeNode parent : parents) { - System.out.println(parent.getParent().getRule()); - // if transition is a case rule, unlock ancestor elements up until latest case rule or root node boolean nextAncestorIsCaseRule = false; Rule rule = trans.getRule(); From 616ff8883e3111f137dc2bf96aeacc710ce67b13 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Sun, 14 Jul 2024 20:03:01 -0400 Subject: [PATCH 5/6] Updated images to binary puzzle --- .../EliminateTheImpossibleDirectRule.java | 2 +- .../rules/CompleteRowColumnDirectRule.png | Bin 2835 -> 2174 bytes .../EliminateTheImpossibleDirectRule.png | Bin 0 -> 2204 bytes .../binary/rules/OneTileGapDirectRule.png | Bin 2751 -> 1944 bytes .../binary/rules/SurroundPairDirectRule.png | Bin 2982 -> 2251 bytes 5 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/EliminateTheImpossibleDirectRule.png diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/EliminateTheImpossibleDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/EliminateTheImpossibleDirectRule.java index cb4aab59a..14bcafc4e 100644 --- a/src/main/java/edu/rpi/legup/puzzle/binary/rules/EliminateTheImpossibleDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/EliminateTheImpossibleDirectRule.java @@ -23,7 +23,7 @@ public EliminateTheImpossibleDirectRule() { "BINA-BASC-0004", "Eliminate The Impossible", "If three adjacent empty cells are open, prevents a trio of numbers to exist", - "edu/rpi/legup/images/binary/rules/OneTileGapDirectRule.png"); + "edu/rpi/legup/images/binary/rules/EliminateTheImpossibleDirectRule.png"); } // Function to generate all binary strings diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/CompleteRowColumnDirectRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/CompleteRowColumnDirectRule.png index a74654d4301f75defc639727604f3d59f05612a3..27ccec97290109fe20d727d468465a57af330906 100644 GIT binary patch literal 2174 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 W-$D%jr3*N)f}HK$?8r8Oq<;bxYC}%| diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/EliminateTheImpossibleDirectRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/EliminateTheImpossibleDirectRule.png new file mode 100644 index 0000000000000000000000000000000000000000..7695ae2da1303c723d962d0da95bbb4fb9abee98 GIT binary patch literal 2204 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 TsFd*d-xT0zciFbm8lC(vAL*4l literal 2751 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 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/SurroundPairDirectRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/SurroundPairDirectRule.png index 67a4e47f363222af68afe45acacd0783f0f35319..ecbed51abe90907b89be11f355ac3ab7c9751c63 100644 GIT binary patch literal 2251 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 From 621b5812ab39a275a32a9f25d479b2229cdf923d Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Tue, 16 Jul 2024 12:27:29 -0400 Subject: [PATCH 6/6] Updated binary contradiction images --- .../rules/CompleteRowColumnDirectRule.java | 2 +- ...uplicateRowsColumnsContradictionRule.java} | 10 +++++----- .../EliminateTheImpossibleDirectRule.java | 2 +- ...UnbalancedRowColumnContradictionRule.java} | 7 +++---- .../DuplicateRowOrColumnContradictionRule.png | Bin 3455 -> 0 bytes .../DuplicateRowsColumnsContradictionRule.png | Bin 0 -> 2124 bytes .../rules/ThreeAdjacentContradictionRule.png | Bin 2508 -> 2071 bytes .../UnbalancedRowColumnContradictionRule.png | Bin 2793 -> 1783 bytes 8 files changed, 10 insertions(+), 11 deletions(-) rename src/main/java/edu/rpi/legup/puzzle/binary/rules/{DuplicateRowsOrColumnsContradictionRule.java => DuplicateRowsColumnsContradictionRule.java} (82%) rename src/main/java/edu/rpi/legup/puzzle/binary/rules/{UnbalancedRowOrColumnContradictionRule.java => UnbalancedRowColumnContradictionRule.java} (91%) delete mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png create mode 100644 src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowsColumnsContradictionRule.png diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/CompleteRowColumnDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/CompleteRowColumnDirectRule.java index 795535352..527223f5c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/binary/rules/CompleteRowColumnDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/CompleteRowColumnDirectRule.java @@ -18,7 +18,7 @@ public class CompleteRowColumnDirectRule extends DirectRule { public CompleteRowColumnDirectRule() { super( "BINA-BASC-0003", - "Complete Row Column", + "Complete Row/Column", "If a row/column of length n contains n/2 of a single value, the remaining cells must contain the other value", "edu/rpi/legup/images/binary/rules/CompleteRowColumnDirectRule.png"); } diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsOrColumnsContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsColumnsContradictionRule.java similarity index 82% rename from src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsOrColumnsContradictionRule.java rename to src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsColumnsContradictionRule.java index 8b0d88ae4..575c62d92 100644 --- a/src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsOrColumnsContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/DuplicateRowsColumnsContradictionRule.java @@ -8,17 +8,17 @@ import edu.rpi.legup.puzzle.binary.BinaryType; import java.util.ArrayList; -public class DuplicateRowsOrColumnsContradictionRule extends ContradictionRule { +public class DuplicateRowsColumnsContradictionRule extends ContradictionRule { private final String NO_CONTRADICTION_MESSAGE = "Does not contain a contradiction at this index"; private final String INVALID_USE_MESSAGE = "Row or column must have a value in each cell"; - public DuplicateRowsOrColumnsContradictionRule() { + public DuplicateRowsColumnsContradictionRule() { super( "BINA-CONT-0003", - "Duplicate Rows Or Columns", - "There must not be two rows or two columns that are duplicates", - "edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png"); + "Duplicate Rows/Columns", + "There must not be two of the same row or two of the same column in the puzzle", + "edu/rpi/legup/images/binary/rules/DuplicateRowsColumnsContradictionRule.png"); } @Override diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/EliminateTheImpossibleDirectRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/EliminateTheImpossibleDirectRule.java index 14bcafc4e..117a639cb 100644 --- a/src/main/java/edu/rpi/legup/puzzle/binary/rules/EliminateTheImpossibleDirectRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/EliminateTheImpossibleDirectRule.java @@ -22,7 +22,7 @@ public EliminateTheImpossibleDirectRule() { super( "BINA-BASC-0004", "Eliminate The Impossible", - "If three adjacent empty cells are open, prevents a trio of numbers to exist", + "Out of the remaining empty cells in this row or column, this digit must go here, otherwise there will be a future contradiction", "edu/rpi/legup/images/binary/rules/EliminateTheImpossibleDirectRule.png"); } diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowColumnContradictionRule.java similarity index 91% rename from src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java rename to src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowColumnContradictionRule.java index ea110ef2c..388528c8b 100644 --- a/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowColumnContradictionRule.java @@ -7,19 +7,18 @@ import edu.rpi.legup.puzzle.binary.BinaryCell; import edu.rpi.legup.puzzle.binary.BinaryType; -import java.util.ArrayList; import java.util.Set; -public class UnbalancedRowOrColumnContradictionRule extends ContradictionRule { +public class UnbalancedRowColumnContradictionRule extends ContradictionRule { private final String NO_CONTRADICTION_MESSAGE = "Does not contain a contradiction at this index"; private final String INVALID_USE_MESSAGE = "Row or column must have a value in each cell"; - public UnbalancedRowOrColumnContradictionRule() { + public UnbalancedRowColumnContradictionRule() { super( "BINA-CONT-0002", - "Unbalanced Row Or Column", + "Unbalanced Row/Column", "Each row or column must contain an equal number of zeros and ones", "edu/rpi/legup/images/binary/rules/UnbalancedRowColumnContradictionRule.png"); } diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowOrColumnContradictionRule.png deleted file mode 100644 index 214aa53483ccc0f6749bffda004ccfc2f70ded29..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3455 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 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowsColumnsContradictionRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/DuplicateRowsColumnsContradictionRule.png new file mode 100644 index 0000000000000000000000000000000000000000..5cc030a7671f6e567d56c9d71ddd640bd5a33336 GIT binary patch literal 2124 zcmai0dpHy7AK#k$t&OG`5l(UtO|E4!*H&_gL#7RLmI>}({(;9>v(KoWh< z@)AFL^MfEF#9!U;*d%@ek}lbp1Ij)s%=3YO59%Tc04Prv-}4gWW6>Mu+(-bxk;K0O zn9g1!006?1XiJnc8Ml<@cP`si;eAxdTlw4PoMme-AL_3WIsbEx`aO5Z9S5;G;v)n& zyu8*yZ*W+w$t10wU^;F$H_Lsq5Vh_Z>5vOty! zH$*BKk?HSeL$8mISDVc46dI{4NC`KBgr3#M3R||!EiZ>i`FzZ$hL7v%85mgC21<|B zQfzF}6ejDtxPj8K)9K*XT==}4qB5QwpELTc`V6`Zybm({wV&ATmrn8^7$^pPWT+-}W<4rav_N-04uiopVBb`D!IC6EO@!pk9(TKYRcH{co<$T`mUOF)%prE2wwz&_NyoPge()RX^(*3lPC+#F* zt3^9_@<}7eCI!~G?ccBga~iLUV0mwRdSFr712gc4rOKU3V0n5c`y@)pHL+kQ50SV6yzwyg2mOQ6=NX!w7J+d_NHhp=#zB85< z+ZGfQ^r^qpJ*+i$(>8`o%h+BS?-UmhFp8J_!0X5}?CtHf9H|WO_OhkO`4^f-v~7*O z3)MM8@UVnh_+Z@J&{Qfl|I z(nBPL^C|PV{fqTPnVRz?|2dn}J|&s^_K=Y-D?_gn4cju=9ZeBd%7|vDHjv4iAMw^I=~I z1j5|}1Zq1ac(H%&GBR+?1XCNXZ!I{hwmWnDvCQ!{z_b9FNTapY=-Jr1XM!tGUj z6yh=l!|x2exzMM%WjS6HT7aZvsoB!Z0^Bc0j#oP5Kw6b=k6JFmJK-+vgFH}G{A(MF6^7^@DCQ4CadHYILqr2V zY^6_DY(4;&ZI;mR$rPgBK2cL$dcrKuvkM5s8UTUeDhtu{nM+ZFjbknSFFM6n1V6M^ z_-0^7?huTf!-`SZp+|;dSkaor?*Wavy9)yr{2?yzJNrm~B+A*9v*$NZ`NtnEWRn$1 zwQ3G0Bv;=rYvUDU95nN>;Q2BQ0S>t7m$PtY^9Qe-lSJ?pmRAl>tpv7eZLHM;>b~2o>t&zStShF+ zRLJ53$f}k_0t+&kY0uDm27`>QpV?1;V*2 z95`PwLykw*&51?soQ&8F3ML$k@3U7J!Ag|>iX|v literal 0 HcmV?d00001 diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/ThreeAdjacentContradictionRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/ThreeAdjacentContradictionRule.png index 862408b63a9c6d72d815b79064ea587657bc5e5e..e292ec9faabb7c263093b94a3bacdaf56e0d05d7 100644 GIT binary patch literal 2071 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 HUy1z(|GtR) diff --git a/src/main/resources/edu/rpi/legup/images/binary/rules/UnbalancedRowColumnContradictionRule.png b/src/main/resources/edu/rpi/legup/images/binary/rules/UnbalancedRowColumnContradictionRule.png index 029bd12ac8782f97428d092ee56187d0aa7d77cf..bd66c16a7fdb3b876bf8e39b54c9a84d2928a3e9 100644 GIT binary patch literal 1783 zcmeAS@N?(olHy`uVBq!ia0vp^sUXb31|&mjbk74R#^NA%Cx&(BWL^R}Ea{HEjtmSN z`?>!lvI6;>1s;*b3=FdEAk5hR^dnF^TaTxUV@O5Z+qtnBA?_l_`#aUNvW^_-pP<1p zal!872SaxB0&~Jselbu9a!kszQbh58x zsH{|SIl4hf`h*noN9E3&&+O0TWbclAe?~4Eue)&J^5x0K_8AWzG%HS-W@KyYJ9+YC ztJL$ix98tCKE-1t%^!q&MqQt9U44>ff7oK3=k3vJ2n+O zbc))NG12d4a72X1(W6JLp0ee9Xl&+hd!u%JYxebm!lZz0~kUwa{Az2VK> zyLWwidwZ>p%l&aQ%fGiK_*=mTM*ddDMJY8q>i$-#P4#*?MOs!?*6P`@UTO1^GrW9u z61q;3!5^mh`1-z_Vyn^rz**wy^IPoAXZE4GAJbzV8jEydcTJh58@(*}TY`Sl$w{gR zA6@#pv-o+&JsXv`2Od2;+|HkQv`bWLM}yU`-@jMx+js9~+rfj5t5&V*+QP4^tE)9n z^y!a}kH5USs_n8?LrZH>gw8Uv@@e|`SyQje0y_qaoM>TnM3QI zFZG`OqTT-SIkP_%KZ<`nJM(_xw}Tx*84Jo^Djz;}y-nligm4iayJs!z^VsHGbC}2b zV!h#J$NkySVn1#PxXOR(YU+A-XQ#8ce%zAJ&(B|;tnR<2@1lr^NPyAICEvc4y?Xt6 z@zHMa*VYF=ZdL5EJEO(bb8zEKVRgR?zrMZ>wXgp5<>i`3@=X3mPEXf=`R3+ktvwYV zo5XY?7QAOWe7$YOFN4(@0Yb(97cNx1TH@{Hb!Ch3R4>hBdzL!OWz*aFWP>uNFMFTu z98!DYcF?io$EONPESS(Xaee&$ZBiz&&)%@bOD}qLc+H{*%py}v6?m^+Tz<<&_nG+Z zKY~2_%v`RvN4i#ie#V=7V?(1^-klX}yDnY~ytOS?dTq?kAWc~oi^eL3Uun_HYjQhQ z@o(;85;b&?wJdVkE61F*ecLvz!%YqU#Mx{rJ~YglH7g?}#bxQmn&wAf$3$EI+FSbi z+Qol=e_s_kvMO{n)A#im%Vykve|PtEzj-#E?0hl-{*pXf4jyL%hhfqzJuQRq+0VM? zwA2lj7Xn+5g`9J^kF)=Qq-Kzq}zo9h|5B zX})XMu97poyUX9dnjtMyV-WR3_C<4({~E{TGj|?vcoi)7W7>0I;UN;(Qh;6}V9ikv z8fLv!+*;r4J5S;HhEESa|7HZ1FgO2BIo>b-_z}y!t)Y>TE6qA$4sd1L$Snuviq|sL z1v({{m-&LzbU~9)it9o9(n8kz35UWtPMtbc(kE-t(J*~M?%iFX&u=uF-@bbFDlnhR z)Eu~|-27eb`kCNqp35&=J#|Y@U*5OV@Ny8MOeknM_B1<}&7^kDrw@!~KMouurceMD zgA>+hL@X)c-SOnBEV>r&6` YvemvPddB(hz{-lj)78&qol`;+093R}SpWb4 literal 2793 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