From 9fbb412b51ab6363d183c3971c598fa1921373d1 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Fri, 28 Jun 2024 13:55:02 -0400 Subject: [PATCH 01/10] Modified EliminateTheImpossible so it produces the correct combination of binary possibilities for any input --- .../EliminateTheImpossibleDirectRule.java | 71 +++++++++++-------- 1 file changed, 40 insertions(+), 31 deletions(-) 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 c9a962973..f03e1ad6d 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 @@ -102,42 +102,51 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem BinaryBoard origBoard = (BinaryBoard) transition.getParents().get(0).getBoard(); BinaryCell binaryCell = (BinaryCell) puzzleElement; - ArrayList rowResult = new ArrayList(); + //Getting the row where the user clicked + ArrayList row = origBoard.listRowCells(binaryCell.getLocation().y); + int size = row.size(); + int rowNumZeros = 0; + int rowNumOnes = 0; + + for (BinaryCell item : row) { + if (item.getType() == BinaryType.ZERO) { + rowNumZeros++; + } else if (item.getType() == BinaryType.ONE) { + rowNumOnes++; + } + } - int zerosLeft = 3; - int onesLeft = 1; + ArrayList rowResult = new ArrayList(); // To call generatePossibilitites(), you must call it and pass in the amount of - // spots left, + // unknown spots left, // an ArrayList that will be populated with the possible results (in String // form), the amount of zeros left and ones left - generatePossibilitites(4, rowResult, zerosLeft, onesLeft); - - //Getting the row and col where the user clicked - ArrayList row = origBoard.listRowCells(binaryCell.getLocation().y); - - for(BinaryCell t : row){ - System.out.println(t.getType()); - // if(t.equals(BinaryType.UNKNOWN)); - } - - // ArrayList> rowCopies = new ArrayList<>(); - // for(int i = 0; i < rowResult.size(); i++){ - // rowCopies.add( new ArrayList(row) ); - // } - - // for(ArrayList curRow : rowCopies){ - // int idx = 0; - // for(int i = 0; i < curRow.size(); i++ ){ - // if(curRow.get(i).getType().equals(BinaryType.UNKNOWN)){ - // curRow.get(i).setType(); - // } - // - // } - // - // } - - + generatePossibilitites((size - rowNumZeros - rowNumOnes), rowResult, size / 2 - rowNumZeros, size / 2 - rowNumOnes); + + for (String s : rowResult) + System.out.println(s); + + ArrayList> rowCopies = new ArrayList<>(); + for(int i = 0; i < rowResult.size(); i++){ + rowCopies.add( new ArrayList(row) ); + } + System.out.println("Number of possible binary combinations: " + rowCopies.size()); + +// for(ArrayList curRow : rowCopies){ +// int idx = 0; +// for(int i = 0; i < curRow.size(); i++ ){ +// if(curRow.get(i).getType().equals(BinaryType.UNKNOWN)){ +// if (rowResult.get(i).equals("0")) +// curRow.get(i).setData(0); +// else if (rowResult.get(i).equals("1")) +// curRow.get(i).setData(1); +// idx++; +// } +// System.out.print(curRow.get(i)); +// } +// System.out.println(""); +// } // System.out.println("printing result"); // for (String s : rowResult) { From 1441f933476f88f097337cc392af3caccee418f2 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Fri, 28 Jun 2024 14:46:15 -0400 Subject: [PATCH 02/10] Each possible binary string combination is added to row --- .../EliminateTheImpossibleDirectRule.java | 56 +++++++++---------- 1 file changed, 26 insertions(+), 30 deletions(-) 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 f03e1ad6d..2cf33d088 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 @@ -124,36 +124,32 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem // form), the amount of zeros left and ones left generatePossibilitites((size - rowNumZeros - rowNumOnes), rowResult, size / 2 - rowNumZeros, size / 2 - rowNumOnes); - for (String s : rowResult) - System.out.println(s); - - ArrayList> rowCopies = new ArrayList<>(); - for(int i = 0; i < rowResult.size(); i++){ - rowCopies.add( new ArrayList(row) ); - } - System.out.println("Number of possible binary combinations: " + rowCopies.size()); - -// for(ArrayList curRow : rowCopies){ -// int idx = 0; -// for(int i = 0; i < curRow.size(); i++ ){ -// if(curRow.get(i).getType().equals(BinaryType.UNKNOWN)){ -// if (rowResult.get(i).equals("0")) -// curRow.get(i).setData(0); -// else if (rowResult.get(i).equals("1")) -// curRow.get(i).setData(1); -// idx++; -// } -// System.out.print(curRow.get(i)); -// } -// System.out.println(""); -// } - - // System.out.println("printing result"); - // for (String s : rowResult) { - // System.out.println(s); - // } - - return "Grouping of Three Ones or Zeros not found TEST"; + ArrayList> rowCopies = new ArrayList<>(); + for(int i = 0; i < rowResult.size(); i++){ + rowCopies.add( new ArrayList(row) ); + } + + System.out.println("Number of possible binary combinations: " + rowCopies.size()); + + int rowIdx = 0; + for(ArrayList curRow : rowCopies){ + int charIdx = 0; + System.out.println(rowResult.get(rowIdx)); + for(int i = 0; i < curRow.size(); i++ ) { + if (curRow.get(i).getData() == 2) { + if (rowResult.get(rowIdx).charAt(charIdx) == '0') + curRow.get(i).setData(0); + else if (rowResult.get(rowIdx).charAt(charIdx) == '1') + curRow.get(i).setData(1); + charIdx++; + } + System.out.print(curRow.get(i).getData() + " "); + } + rowIdx++; + System.out.println(); + } + + return "Grouping of Three Ones or Zeros not found"; } From 541edffa9358a88376b408a6e28e549432995672 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Fri, 28 Jun 2024 14:54:07 -0400 Subject: [PATCH 03/10] Fixed EliminateTheImpossible so each row is a deep copy of original --- .../binary/rules/EliminateTheImpossibleDirectRule.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 2cf33d088..aea921766 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 @@ -124,9 +124,14 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem // form), the amount of zeros left and ones left generatePossibilitites((size - rowNumZeros - rowNumOnes), rowResult, size / 2 - rowNumZeros, size / 2 - rowNumOnes); + // Create deep copies of each row ArrayList> rowCopies = new ArrayList<>(); - for(int i = 0; i < rowResult.size(); i++){ - rowCopies.add( new ArrayList(row) ); + for (int i = 0; i < rowResult.size(); i++) { + ArrayList newRow = new ArrayList<>(); + for (BinaryCell cell : row) { + newRow.add(cell.copy()); + } + rowCopies.add(newRow); } System.out.println("Number of possible binary combinations: " + rowCopies.size()); From 7575f17cb46e320bcd4b62002084ad3fa4e0d4c5 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Fri, 28 Jun 2024 16:27:20 -0400 Subject: [PATCH 04/10] Fixed curly brace checkstyle error --- .../binary/rules/EliminateTheImpossibleDirectRule.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 aea921766..724edf113 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 @@ -142,10 +142,12 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem System.out.println(rowResult.get(rowIdx)); for(int i = 0; i < curRow.size(); i++ ) { if (curRow.get(i).getData() == 2) { - if (rowResult.get(rowIdx).charAt(charIdx) == '0') + if (rowResult.get(rowIdx).charAt(charIdx) == '0') { curRow.get(i).setData(0); - else if (rowResult.get(rowIdx).charAt(charIdx) == '1') + } + else if (rowResult.get(rowIdx).charAt(charIdx) == '1') { curRow.get(i).setData(1); + } charIdx++; } System.out.print(curRow.get(i).getData() + " "); From 81483ded3da2297c13f95410fa3367d6edfa7ca2 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Sun, 30 Jun 2024 00:23:10 -0400 Subject: [PATCH 05/10] Modified Puzzle Solver -> when opened, a blank board is shown with no rules. Added an Open toolbar button --- src/main/java/edu/rpi/legup/ui/HomePanel.java | 76 ++----- .../edu/rpi/legup/ui/ProofEditorPanel.java | 206 ++++++++++-------- .../edu/rpi/legup/ui/PuzzleEditorPanel.java | 10 +- 3 files changed, 134 insertions(+), 158 deletions(-) diff --git a/src/main/java/edu/rpi/legup/ui/HomePanel.java b/src/main/java/edu/rpi/legup/ui/HomePanel.java index dd0061feb..29e3600d8 100644 --- a/src/main/java/edu/rpi/legup/ui/HomePanel.java +++ b/src/main/java/edu/rpi/legup/ui/HomePanel.java @@ -40,14 +40,15 @@ public class HomePanel extends LegupPanel { new ActionListener() { @Override public void actionPerformed(ActionEvent e) { - Object[] items = legupUI.getProofEditor().promptPuzzle(); - if (items == null) { - // The attempt to prompt a puzzle ended gracefully (cancel) - return; - } - String fileName = (String) items[0]; - File puzzleFile = (File) items[1]; - legupUI.getProofEditor().loadPuzzle(fileName, puzzleFile); +// Object[] items = legupUI.getProofEditor().promptPuzzle(); +// if (items == null) { +// // The attempt to prompt a puzzle ended gracefully (cancel) +// return; +// } +// String fileName = (String) items[0]; +// File puzzleFile = (File) items[1]; + legupUI.getProofEditor().loadPuzzle("", null); +// legupUI.getProofEditor().loadPuzzle(); } }; @@ -116,10 +117,10 @@ private static ImageIcon resizeButtonIcon(ImageIcon icon, int width, int height) } private void initButtons() { - this.buttons = new JButton[4]; + this.buttons = new JButton[3]; this.buttons[0] = - new JButton("Solve Puzzle") { + new JButton("Puzzle Solver") { { setSize(buttonSize, buttonSize); setMaximumSize(getSize()); @@ -136,23 +137,6 @@ private void initButtons() { this.buttons[0].setVerticalTextPosition(AbstractButton.BOTTOM); this.buttons[0].addActionListener(CursorController.createListener(this, openProofListener)); -// this.buttons[1] = -// new JButton("Create Puzzle") { -// { -// setSize(buttonSize, buttonSize); -// setMaximumSize(getSize()); -// } -// }; -// URL button1IconLocation = -// ClassLoader.getSystemClassLoader() -// .getResource("edu/rpi/legup/images/Legup/homepanel/new_puzzle_file.png"); -// ImageIcon button1Icon = new ImageIcon(button1IconLocation); -// this.buttons[1].setFocusPainted(false); -// this.buttons[1].setIcon(resizeButtonIcon(button1Icon, this.buttonSize, this.buttonSize)); -// this.buttons[1].setHorizontalTextPosition(AbstractButton.CENTER); -// this.buttons[1].setVerticalTextPosition(AbstractButton.BOTTOM); -// this.buttons[1].addActionListener(l -> this.openNewPuzzleDialog()); - this.buttons[1] = new JButton("Puzzle Editor") { { @@ -169,37 +153,16 @@ private void initButtons() { this.buttons[1].setHorizontalTextPosition(AbstractButton.CENTER); this.buttons[1].setVerticalTextPosition(AbstractButton.BOTTOM); this.buttons[1].addActionListener(l -> this.openPuzzleEditorDialog()); - //this.buttons[1].addActionListener(l -> this.openNewPuzzleDialog()); - - this.buttons[2] = - new JButton("Edit Existing Puzzle") { - { - setSize(buttonSize, buttonSize); - setMaximumSize(getSize()); - } - }; - URL button2IconLocation = - ClassLoader.getSystemClassLoader() - .getResource("edu/rpi/legup/images/Legup/homepanel/puzzle_file.png"); - ImageIcon button2Icon = new ImageIcon(button2IconLocation); - this.buttons[2].setFocusPainted(false); - this.buttons[2].setIcon(resizeButtonIcon(button2Icon, this.buttonSize, this.buttonSize)); - this.buttons[2].setHorizontalTextPosition(AbstractButton.CENTER); - this.buttons[2].setVerticalTextPosition(AbstractButton.BOTTOM); - this.buttons[2].addActionListener( - CursorController.createListener(this, openPuzzleListener)); // PLACEHOLDER - - this.buttons[2].setVisible(false); for (int i = 0; i < this.buttons.length - 1; i++) { // -1 to avoid the batch grader button this.buttons[i].setBounds(200, 200, 700, 700); } - this.buttons[3] = new JButton("Batch Grader"); - this.buttons[3].setFocusPainted(false); - this.buttons[3].setHorizontalTextPosition(AbstractButton.CENTER); - this.buttons[3].setVerticalTextPosition(AbstractButton.BOTTOM); + this.buttons[2] = new JButton("Batch Grader"); + this.buttons[2].setFocusPainted(false); + this.buttons[2].setHorizontalTextPosition(AbstractButton.CENTER); + this.buttons[2].setVerticalTextPosition(AbstractButton.BOTTOM); - this.buttons[3].addActionListener( + this.buttons[2].addActionListener( new ActionListener() { @Override public void actionPerformed(ActionEvent e) { @@ -293,7 +256,7 @@ public void checkFolder() { } } catch (IOException ex) { LOGGER.error(ex.getMessage()); - this.buttons[3].addActionListener((ActionEvent e) -> use_xml_to_check()); + this.buttons[2].addActionListener((ActionEvent e) -> use_xml_to_check()); } } @@ -531,11 +494,8 @@ private void render() { buttons.add(Box.createRigidArea(new Dimension(5, 0))); buttons.add(this.buttons[1]); buttons.add(Box.createRigidArea(new Dimension(5, 0))); - buttons.add(this.buttons[2]); - buttons.add(Box.createRigidArea(new Dimension(5, 0))); - JPanel batchGraderButton = new JPanel(); - batchGraderButton.add(this.buttons[3]); + batchGraderButton.add(this.buttons[2]); batchGraderButton.setAlignmentX(Component.CENTER_ALIGNMENT); this.add(Box.createRigidArea(new Dimension(0, 5))); diff --git a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java index 99b08f963..eba0daba0 100644 --- a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java +++ b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java @@ -46,8 +46,8 @@ public class ProofEditorPanel extends LegupPanel implements IHistoryListener { private DynamicView dynamicBoardView; private JSplitPane topHalfPanel, mainPanel; private TitledBorder boardBorder; - - private JButton[] toolBarButtons; + private JButton[] toolBar1Buttons; + private JButton[] toolBar2Buttons; private JMenu file; private JMenuItem newPuzzle, resetPuzzle, @@ -67,7 +67,8 @@ public class ProofEditorPanel extends LegupPanel implements IHistoryListener { private JMenu about, help; private JMenuItem helpLegup, aboutLegup; - private JToolBar toolBar; + private JToolBar toolBar1; + private JToolBar toolBar2; private BoardView boardView; private JFileChooser folderBrowser; @@ -81,7 +82,6 @@ public class ProofEditorPanel extends LegupPanel implements IHistoryListener { public static final int IMD_FEEDBACK = 32; public static final int INTERN_RO = 64; public static final int AUTO_JUST = 128; - static final int[] TOOLBAR_SEPARATOR_BEFORE = {1}; private static final String[] PROFILES = { "No Assistance", "Rigorous Proof", @@ -123,7 +123,7 @@ public ProofEditorPanel(FileDialog fileDialog, JFrame frame, LegupUI legupUI) { public void makeVisible() { this.removeAll(); - setupToolBar(); + setupToolBar1(); setupContent(); frame.setJMenuBar(getMenuBar()); } @@ -521,6 +521,9 @@ public void loadPuzzle() { } public void loadPuzzle(String fileName, File puzzleFile) { + if (puzzleFile == null && fileName.equals("")) { + legupUI.displayPanel(1); + } if (puzzleFile != null && puzzleFile.exists()) { try { legupUI.displayPanel(1); @@ -741,98 +744,122 @@ protected void setupContent() { revalidate(); } - private void setupToolBar() { - setToolBarButtons(new JButton[ToolbarName.values().length]); - for (int i = 0; i < ToolbarName.values().length; i++) { - String toolBarName = ToolbarName.values()[i].toString(); - URL resourceLocation = - ClassLoader.getSystemClassLoader() - .getResource("edu/rpi/legup/images/Legup/" + toolBarName + ".png"); - - // Scale the image icons down to make the buttons smaller - ImageIcon imageIcon = new ImageIcon(resourceLocation); - Image image = imageIcon.getImage(); - imageIcon = - new ImageIcon( - image.getScaledInstance( - this.TOOLBAR_ICON_SCALE, - this.TOOLBAR_ICON_SCALE, - Image.SCALE_SMOOTH)); - - JButton button = new JButton(toolBarName, imageIcon); - button.setFocusPainted(false); - getToolBarButtons()[i] = button; - } + private void setupToolBar1() { + toolBar1 = new JToolBar(); + toolBar1.setFloatable(false); + toolBar1.setRollover(true); + setToolBar2Buttons(new JButton[1]); - toolBar = new JToolBar(); - toolBar.setFloatable(false); - toolBar.setRollover(true); + URL open_url = + ClassLoader.getSystemClassLoader() + .getResource("edu/rpi/legup/images/Legup/Open.png"); - for (int i = 0; i < getToolBarButtons().length; i++) { - for (int s = 0; s < TOOLBAR_SEPARATOR_BEFORE.length; s++) { - if (i == TOOLBAR_SEPARATOR_BEFORE[s]) { - toolBar.addSeparator(); - } - } - String toolBarName = ToolbarName.values()[i].toString(); + // Scale the image icons down to make the buttons smaller + ImageIcon OpenImageIcon = new ImageIcon(open_url); + Image OpenImage = OpenImageIcon.getImage(); + OpenImageIcon = + new ImageIcon( + OpenImage.getScaledInstance( + this.TOOLBAR_ICON_SCALE, + this.TOOLBAR_ICON_SCALE, + Image.SCALE_SMOOTH)); - toolBar.add(getToolBarButtons()[i]); - getToolBarButtons()[i].setToolTipText(toolBarName); + JButton open = new JButton("Open", OpenImageIcon); + open.setFocusPainted(false); - getToolBarButtons()[i].setVerticalTextPosition(SwingConstants.BOTTOM); - getToolBarButtons()[i].setHorizontalTextPosition(SwingConstants.CENTER); - } + open.addActionListener((ActionEvent) -> loadPuzzle()); + + getToolBar2Buttons()[0] = open; + toolBar1.add(getToolBar2Buttons()[0]); + + this.add(toolBar1, BorderLayout.NORTH); + } + + private void setupToolBar2() { + toolBar2 = new JToolBar(); + toolBar2.setFloatable(false); + toolBar2.setRollover(true); + setToolBar2Buttons(new JButton[2]); + + URL directions_url = + ClassLoader.getSystemClassLoader() + .getResource("edu/rpi/legup/images/Legup/Directions.png"); + + // Scale the image icons down to make the buttons smaller + ImageIcon DirectionsImageIcon = new ImageIcon(directions_url); + Image DirectionsImage = DirectionsImageIcon.getImage(); + DirectionsImageIcon = + new ImageIcon( + DirectionsImage.getScaledInstance( + this.TOOLBAR_ICON_SCALE, + this.TOOLBAR_ICON_SCALE, + Image.SCALE_SMOOTH)); + + JButton directions = new JButton("Directions", DirectionsImageIcon); + directions.setFocusPainted(false); + directions.addActionListener((ActionEvent) -> directionsToolButton()); + + getToolBar2Buttons()[0] = directions; + toolBar2.add(getToolBar2Buttons()[0]); + + URL check_url = + ClassLoader.getSystemClassLoader() + .getResource("edu/rpi/legup/images/Legup/Check.png"); + + // Scale the image icons down to make the buttons smaller + ImageIcon CheckImageIcon = new ImageIcon(check_url); + Image CheckImage = CheckImageIcon.getImage(); + CheckImageIcon = + new ImageIcon( + CheckImage.getScaledInstance( + this.TOOLBAR_ICON_SCALE, + this.TOOLBAR_ICON_SCALE, + Image.SCALE_SMOOTH)); + + JButton check = new JButton("Check", CheckImageIcon); + check.setFocusPainted(false); + check.addActionListener((ActionEvent) -> checkProof()); + + getToolBar2Buttons()[1] = check; + toolBar2.add(getToolBar2Buttons()[1]); + + this.add(toolBar2, BorderLayout.NORTH); + } + + /** + * Sets the toolbar1 buttons + * + * @param toolBar1Buttons toolbar buttons + */ + public void setToolBar1Buttons(JButton[] toolBar1Buttons) { + this.toolBar1Buttons = toolBar1Buttons; + } - // toolBarButtons[ToolbarName.OPEN_PUZZLE.ordinal()].addActionListener((ActionEvent - // e) -> - // promptPuzzle()); - // toolBarButtons[ToolbarName.SAVE.ordinal()].addActionListener((ActionEvent e) -> - // saveProof()); - // toolBarButtons[ToolbarName.UNDO.ordinal()].addActionListener((ActionEvent e) -> - // GameBoardFacade.getInstance().getHistory().undo()); - // toolBarButtons[ToolbarName.REDO.ordinal()].addActionListener((ActionEvent e) -> - // GameBoardFacade.getInstance().getHistory().redo()); - //toolBarButtons[ToolbarName.HINT.ordinal()].addActionListener((ActionEvent e) -> {}); - toolBarButtons[ToolbarName.CHECK.ordinal()].addActionListener( - (ActionEvent e) -> checkProof()); - //toolBarButtons[ToolbarName.SUBMIT.ordinal()].addActionListener((ActionEvent e) -> {}); - toolBarButtons[ToolbarName.DIRECTIONS.ordinal()].addActionListener((ActionEvent e) -> directionsToolButton()); - -// toolBarButtons[ToolbarName.CHECK_ALL.ordinal()].addActionListener( -// (ActionEvent e) -> checkProofAll()); - - // toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(false); - // toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(false); - // toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); - //toolBarButtons[ToolbarName.HINT.ordinal()].setEnabled(false); - toolBarButtons[ToolbarName.CHECK.ordinal()].setEnabled(true); - //toolBarButtons[ToolbarName.SUBMIT.ordinal()].setEnabled(false); - toolBarButtons[ToolbarName.DIRECTIONS.ordinal()].setEnabled(true); - //toolBarButtons[ToolbarName.CHECK_ALL.ordinal()].setEnabled(false); - -// toolBarButtons[ToolbarName.HINT.ordinal()].setVisible(false); -// toolBarButtons[ToolbarName.SUBMIT.ordinal()].setVisible(false); -// toolBarButtons[ToolbarName.CHECK_ALL.ordinal()].setVisible(false); - - this.add(toolBar, BorderLayout.NORTH); + /** + * Sets the toolbar2 buttons + * + * @param toolBar2Buttons toolbar buttons + */ + public void setToolBar2Buttons(JButton[] toolBar2Buttons) { + this.toolBar2Buttons = toolBar2Buttons; } /** - * Sets the toolbar buttons + * Gets the toolbar1 buttons * - * @param toolBarButtons toolbar buttons + * @return toolbar1 buttons */ - public void setToolBarButtons(JButton[] toolBarButtons) { - this.toolBarButtons = toolBarButtons; + public JButton[] getToolBar1Buttons() { + return toolBar1Buttons; } /** - * Gets the toolbar buttons + * Gets the toolbar2 buttons * - * @return toolbar buttons + * @return toolbar2 buttons */ - public JButton[] getToolBarButtons() { - return toolBarButtons; + public JButton[] getToolBar2Buttons() { + return toolBar2Buttons; } /** Checks the proof for correctness */ @@ -918,9 +945,8 @@ public void setPuzzleView(Puzzle puzzle) { ruleFrame.getContradictionPanel().setRules(puzzle.getContradictionRules()); ruleFrame.getSearchPanel().setSearchBar(puzzle); - toolBarButtons[ToolbarName.CHECK.ordinal()].setEnabled(true); - // toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(true); - + toolBar1.setVisible(false); + setupToolBar2(); reloadGui(); } @@ -1057,9 +1083,7 @@ public TreePanel getTreePanel() { public void onPushChange(ICommand command) { LOGGER.info("Pushing " + command.getClass().getSimpleName() + " to stack."); undo.setEnabled(true); - // toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(true); redo.setEnabled(false); - // toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); @@ -1070,9 +1094,9 @@ public void onPushChange(ICommand command) { @Override public void onClearHistory() { // undo.setEnabled(false); - // toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(false); + // toolBar2Buttons[ToolbarName.UNDO.ordinal()].setEnabled(false); // redo.setEnabled(false); - // toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(false); + // toolBar2Buttons[ToolbarName.REDO.ordinal()].setEnabled(false); } /** @@ -1084,9 +1108,7 @@ public void onClearHistory() { @Override public void onRedo(boolean isBottom, boolean isTop) { undo.setEnabled(!isBottom); - // toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(!isBottom); redo.setEnabled(!isTop); - // toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(!isTop); if (isBottom) { String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); @@ -1107,9 +1129,7 @@ public void onRedo(boolean isBottom, boolean isTop) { @Override public void onUndo(boolean isBottom, boolean isTop) { undo.setEnabled(!isBottom); - // toolBarButtons[ToolbarName.UNDO.ordinal()].setEnabled(!isBottom); redo.setEnabled(!isTop); - // toolBarButtons[ToolbarName.REDO.ordinal()].setEnabled(!isTop); String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); if (isBottom) { diff --git a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java index 723085658..6d4c35616 100644 --- a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java +++ b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java @@ -309,6 +309,9 @@ private void setupToolBar1() { } private void setupToolBar2() { + toolBar2 = new JToolBar(); + toolBar2.setFloatable(false); + toolBar2.setRollover(true); setToolBar2Buttons(new JButton[2]); URL save_as = @@ -328,10 +331,6 @@ private void setupToolBar2() { saveas.addActionListener((ActionEvent) -> savePuzzle()); getToolBar2Buttons()[0] = saveas; - - toolBar2 = new JToolBar(); - toolBar2.setFloatable(false); - toolBar2.setRollover(true); toolBar2.add(getToolBar2Buttons()[0]); URL save_and_solve = @@ -369,9 +368,6 @@ public void actionPerformed(ActionEvent e) { } }); getToolBar2Buttons()[1] = saveandsolve; - - toolBar2.setFloatable(false); - toolBar2.setRollover(true); toolBar2.add(getToolBar2Buttons()[1]); this.add(toolBar2, BorderLayout.NORTH); From 3b5b7d03c7af190cf9a2b6530a66873e722433f9 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Tue, 2 Jul 2024 15:41:35 -0400 Subject: [PATCH 06/10] Fixed case rule bug that causes proof tree to lock when deleting if the number of case branches is 0 --- .../legup/history/AutoCaseRuleCommand.java | 2 +- .../history/DeleteTreeElementCommand.java | 7 ++--- .../edu/rpi/legup/model/gameboard/Board.java | 2 ++ .../java/edu/rpi/legup/model/tree/Tree.java | 28 ++++++++++++++++++- .../binary/rules/OneOrZeroCaseRule.java | 7 ++++- .../fillapix/rules/BlackOrWhiteCaseRule.java | 3 ++ .../fillapix/rules/SatisfyClueCaseRule.java | 3 ++ .../lightup/rules/LightOrEmptyCaseRule.java | 4 +++ .../lightup/rules/SatisfyNumberCaseRule.java | 6 +++- .../nurikabe/rules/BlackOrWhiteCaseRule.java | 4 +++ .../nurikabe/rules/FinishRoomCaseRule.java | 4 +++ .../rules/caserule/CaseRuleAtomic.java | 3 ++ .../caserule/CaseRule_GenericStatement.java | 5 ++++ .../rules/CellForNumberCaseRule.java | 3 ++ .../rules/NumberForCellCaseRule.java | 3 ++ .../starbattle/rules/StarOrEmptyCaseRule.java | 4 +++ .../sudoku/rules/PossibleCellCaseRule.java | 4 +++ .../sudoku/rules/PossibleNumberCaseRule.java | 4 +++ .../treetent/rules/FillinRowCaseRule.java | 4 +++ .../treetent/rules/LinkTentCaseRule.java | 4 +++ .../treetent/rules/LinkTreeCaseRule.java | 4 +++ .../edu/rpi/legup/ui/ProofEditorPanel.java | 9 ++++++ .../ui/proofeditorui/treeview/TreeView.java | 1 - 23 files changed, 109 insertions(+), 9 deletions(-) diff --git a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java index 97192e145..fd15a7ae2 100644 --- a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java @@ -60,7 +60,7 @@ public void executeCommand() { caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()); for (Board board : cases) { final TreeTransition transition = (TreeTransition) tree.addTreeElement(node); - board.setModifiable(false); + //board.setModifiable(false); transition.setBoard(board); transition.setRule(caseRule); transition.setSelection(elementView.getPuzzleElement().copy()); diff --git a/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java b/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java index 0469685c1..258aaacc0 100644 --- a/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java +++ b/src/main/java/edu/rpi/legup/history/DeleteTreeElementCommand.java @@ -39,16 +39,15 @@ public void executeCommand() { } for (TreeElementView selectedView : selectedViews) { + System.out.println("DELETED"); TreeElement element = selectedView.getTreeElement(); tree.removeTreeElement(element); puzzle.notifyTreeListeners(listener -> listener.onTreeElementRemoved(element)); } final TreeViewSelection newSelection = new TreeViewSelection(newSelectedView); - puzzle.notifyBoardListeners( - listener -> listener.onTreeElementChanged(newSelectedView.getTreeElement())); - puzzle.notifyTreeListeners( - (ITreeListener listener) -> listener.onTreeSelectionChanged(newSelection)); + puzzle.notifyBoardListeners(listener -> listener.onTreeElementChanged(newSelectedView.getTreeElement())); + puzzle.notifyTreeListeners((ITreeListener listener) -> listener.onTreeSelectionChanged(newSelection)); } /** diff --git a/src/main/java/edu/rpi/legup/model/gameboard/Board.java b/src/main/java/edu/rpi/legup/model/gameboard/Board.java index d8bdf5199..b6d3ed995 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/Board.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/Board.java @@ -37,6 +37,8 @@ public Board(int size) { * @return equivalent puzzleElement on this board */ public PuzzleElement getPuzzleElement(PuzzleElement puzzleElement) { + if (puzzleElement == null) + return null; int index = puzzleElement.getIndex(); return index < puzzleElements.size() ? puzzleElements.get(index) : null; } 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 a0746db87..08e594801 100644 --- a/src/main/java/edu/rpi/legup/model/tree/Tree.java +++ b/src/main/java/edu/rpi/legup/model/tree/Tree.java @@ -46,7 +46,7 @@ public TreeElement addTreeElement(TreeElement element) { } else { TreeTransition transition = (TreeTransition) element; Board copyBoard = transition.board.copy(); - copyBoard.setModifiable(false); + copyBoard.setModifiable(true); return addTreeElement(transition, new TreeNode(copyBoard)); } } @@ -63,17 +63,43 @@ public TreeElement addTreeElement(TreeTransition transition, TreeNode treeNode) return treeNode; } +// public void removeTreeElement(TreeElement element) { +// if (element.getType() == TreeElementType.NODE) { +// TreeNode node = (TreeNode) element; +// node.getParent().setChildNode(null); +// } else { +// TreeTransition transition = (TreeTransition) element; +// System.out.println("DELETED CHILD"); +// transition.getParents().forEach(n -> n.removeChild(transition)); +// transition.getParents().get(0).getChildren().forEach(TreeTransition::reverify); +// } +// } + public void removeTreeElement(TreeElement element) { if (element.getType() == TreeElementType.NODE) { TreeNode node = (TreeNode) element; + + // Output when node has children + if (!node.getChildren().isEmpty()) { + System.out.println("Deleting children of node: " + node); + for (TreeTransition child : new ArrayList<>(node.getChildren())) { + removeTreeElement(child); + } + } + node.getParent().setChildNode(null); + System.out.println("Deleted node: " + node); } else { TreeTransition transition = (TreeTransition) element; + System.out.println("Deleted arrow: " + transition); + transition.getParents().forEach(n -> n.removeChild(transition)); transition.getParents().get(0).getChildren().forEach(TreeTransition::reverify); } } + + /** * Determines if the tree is valid by checking whether this tree puzzleElement and all * descendants of this tree puzzleElement is justified and justified correctly diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneOrZeroCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneOrZeroCaseRule.java index 62230f469..7ce6f1589 100644 --- a/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneOrZeroCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/OneOrZeroCaseRule.java @@ -53,7 +53,8 @@ public String checkRuleRaw(TreeTransition transition) { public CaseBoard getCaseBoard(Board board) { BinaryBoard binaryBoard = (BinaryBoard) board.copy(); CaseBoard caseBoard = new CaseBoard(binaryBoard, this); - binaryBoard.setModifiable(false); + caseBoard.setModifiable(true); + //binaryBoard.setModifiable(false); for (PuzzleElement element : binaryBoard.getPuzzleElements()) { if (((BinaryCell) element).getType() == BinaryType.UNKNOWN) { caseBoard.addPickableElement(element); @@ -65,6 +66,10 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } + Board case1 = board.copy(); PuzzleElement data1 = case1.getPuzzleElement(puzzleElement); data1.setData(BinaryType.ZERO.toValue()); diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/BlackOrWhiteCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/BlackOrWhiteCaseRule.java index 860a6c011..f0194bd39 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/BlackOrWhiteCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/BlackOrWhiteCaseRule.java @@ -37,6 +37,9 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } Board case1 = board.copy(); FillapixCell cell1 = (FillapixCell) case1.getPuzzleElement(puzzleElement); diff --git a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/SatisfyClueCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/SatisfyClueCaseRule.java index 7db833f76..f8bb2d4f5 100644 --- a/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/SatisfyClueCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/fillapix/rules/SatisfyClueCaseRule.java @@ -45,6 +45,9 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList(); + if (puzzleElement == null) { + return cases; + } // get value of cell FillapixBoard fillapixBoard = (FillapixBoard) board.copy(); diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/LightOrEmptyCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/LightOrEmptyCaseRule.java index 4ba754731..53efb6587 100644 --- a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/LightOrEmptyCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/LightOrEmptyCaseRule.java @@ -44,6 +44,10 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } + Board case1 = board.copy(); PuzzleElement data1 = case1.getPuzzleElement(puzzleElement); data1.setData(-4); diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/SatisfyNumberCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/SatisfyNumberCaseRule.java index 490122874..f73a34b2d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/SatisfyNumberCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/SatisfyNumberCaseRule.java @@ -47,6 +47,11 @@ public CaseBoard getCaseBoard(Board board) { */ @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { + ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } + LightUpBoard lightUpBoard = (LightUpBoard) board; LightUpCell cell = (LightUpCell) puzzleElement; Point loc = cell.getLocation(); @@ -96,7 +101,6 @@ public ArrayList getCases(Board board, PuzzleElement puzzleElement) { } } - ArrayList cases = new ArrayList<>(); if (numNeeded == 0) { return cases; } diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/BlackOrWhiteCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/BlackOrWhiteCaseRule.java index ac0ab6df6..209ce47d5 100644 --- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/BlackOrWhiteCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/BlackOrWhiteCaseRule.java @@ -84,6 +84,10 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } + Board case1 = board.copy(); PuzzleElement data1 = case1.getPuzzleElement(puzzleElement); data1.setData(NurikabeType.WHITE.toValue()); 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 e941922fd..e1b7ca18d 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 @@ -115,6 +115,10 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); // makes array list of cases + if (puzzleElement == null) { + return cases; + } + NurikabeBoard nuriBoard = (NurikabeBoard) board.copy(); // nurikabe board to edit NurikabeCell numberCell = nuriBoard.getCell(((NurikabeCell) puzzleElement).getLocation().x, ((NurikabeCell) puzzleElement).getLocation().y); // number cell whose room we want to fill diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java index 58d2068b2..22b49fd77 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRuleAtomic.java @@ -44,6 +44,9 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } Board case1 = board.copy(); PuzzleElement data1 = case1.getPuzzleElement(puzzleElement); diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java index 99f771246..8aeb51a46 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_GenericStatement.java @@ -85,6 +85,11 @@ public CaseBoard getCaseBoard(Board board) { @SuppressWarnings("unchecked") @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { + + if (puzzleElement == null) { + return new ArrayList(); + } + ShortTruthTableBoard sttBoard = ((ShortTruthTableBoard) board); ShortTruthTableCell cell = sttBoard.getCellFromElement(puzzleElement); diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java index 45bdadea3..b48962c41 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java @@ -61,6 +61,9 @@ public CaseBoard getCaseBoard(Board board) { public ArrayList getCasesFor(Board board, PuzzleElement puzzleElement, Integer number) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } SkyscrapersClue clue = (SkyscrapersClue) puzzleElement; SkyscrapersBoard skyscrapersboard = (SkyscrapersBoard) board; diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java index 145dd6ee2..4f8e1df6b 100644 --- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java @@ -47,6 +47,9 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } SkyscrapersCell cell = (SkyscrapersCell) puzzleElement; SkyscrapersBoard skyscrapersboard = (SkyscrapersBoard) board; diff --git a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/StarOrEmptyCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/StarOrEmptyCaseRule.java index df900dcd5..efd86bd7b 100644 --- a/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/StarOrEmptyCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/starbattle/rules/StarOrEmptyCaseRule.java @@ -84,6 +84,10 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } + Board case1 = board.copy(); PuzzleElement data1 = case1.getPuzzleElement(puzzleElement); data1.setData(StarBattleCellType.STAR.value); diff --git a/src/main/java/edu/rpi/legup/puzzle/sudoku/rules/PossibleCellCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/sudoku/rules/PossibleCellCaseRule.java index fb6da62d4..ccc428486 100644 --- a/src/main/java/edu/rpi/legup/puzzle/sudoku/rules/PossibleCellCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/sudoku/rules/PossibleCellCaseRule.java @@ -67,6 +67,10 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } + SudokuBoard sudokuBoard = (SudokuBoard) board; SudokuCell cell = (SudokuCell) puzzleElement; diff --git a/src/main/java/edu/rpi/legup/puzzle/sudoku/rules/PossibleNumberCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/sudoku/rules/PossibleNumberCaseRule.java index e6ab0e64c..a516a06fb 100644 --- a/src/main/java/edu/rpi/legup/puzzle/sudoku/rules/PossibleNumberCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/sudoku/rules/PossibleNumberCaseRule.java @@ -84,6 +84,10 @@ public ArrayList getCases(Board board, PuzzleElement puzzleElement) { public ArrayList getCases( Board board, PuzzleElement puzzleElement, int value, GroupType groupType) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } + SudokuBoard sudokuBoard = (SudokuBoard) board; List caseCells = new ArrayList<>(); SudokuCell cell = (SudokuCell) puzzleElement; diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/FillinRowCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/FillinRowCaseRule.java index aaa1a8fbc..8fe9b6873 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/FillinRowCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/FillinRowCaseRule.java @@ -61,7 +61,11 @@ public CaseBoard getCaseBoard(Board board) { */ @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { + if (puzzleElement == null) { + return new ArrayList(); + } ArrayList cases; + List group; int tentsLeft; TreeTentClue clue = ((TreeTentClue) puzzleElement); diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTentCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTentCaseRule.java index bd303174a..cbe91c3a7 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTentCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTentCaseRule.java @@ -60,6 +60,10 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList(); + if (puzzleElement == null) { + return cases; + } + TreeTentCell cell = (TreeTentCell) puzzleElement; List adj = ((TreeTentBoard) board).getAdjacent(cell, TreeTentType.TREE); List lines = ((TreeTentBoard) board).getLines(); diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTreeCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTreeCaseRule.java index 03d039898..153692ad0 100644 --- a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTreeCaseRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/LinkTreeCaseRule.java @@ -62,6 +62,10 @@ public CaseBoard getCaseBoard(Board board) { @Override public ArrayList getCases(Board board, PuzzleElement puzzleElement) { ArrayList cases = new ArrayList<>(); + if (puzzleElement == null) { + return cases; + } + TreeTentBoard treeTentBoard = (TreeTentBoard) board; TreeTentCell cell = (TreeTentCell) puzzleElement; List adjCells = treeTentBoard.getAdjacent(cell, TreeTentType.TENT); diff --git a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java index eba0daba0..3802e4de7 100644 --- a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java +++ b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java @@ -9,9 +9,11 @@ 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; @@ -1088,6 +1090,13 @@ public void onPushChange(ICommand command) { String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName(); File puzzleFile = new File(GameBoardFacade.getInstance().getCurFileName()); frame.setTitle(puzzleName + " - " + puzzleFile.getName() + " *"); +// Board curBoard = GameBoardFacade.getInstance().getBoard(); +// List allElements = curBoard.getPuzzleElements(); +// for (PuzzleElement p : allElements) { +// if (p.getData() == BinaryType.UNKNOWN) { +// p.setModifiable(true); +// } +// } } /** Called when the history is cleared */ 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 f491009b4..ea622881c 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 @@ -533,7 +533,6 @@ private void addTreeTransition(TreeTransition trans) { PuzzleElement oldElement = ancestor.getParent().getBoard().getPuzzleElement(element); oldElement.setCasesDepended(oldElement.getCasesDepended() + 1); - oldElement.setModifiable(false); } } } From 88c6f69cf658768d27dec342b0b5a1c006c731bf Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Mon, 8 Jul 2024 10:31:18 -0400 Subject: [PATCH 07/10] Enhanced finish room case rule in nurikabe to inlucde options of rooms bigger than 2 --- .../legup/history/AutoCaseRuleCommand.java | 9 +- .../nurikabe/rules/FinishRoomCaseRule.java | 173 +++++++++++------- 2 files changed, 114 insertions(+), 68 deletions(-) diff --git a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java index fd15a7ae2..6eccc80ec 100644 --- a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java @@ -56,8 +56,7 @@ public void executeCommand() { TreeNode node = (TreeNode) selection.getFirstSelection().getTreeElement(); if (caseTrans.isEmpty()) { - List cases = - caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()); + List cases = caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()); for (Board board : cases) { final TreeTransition transition = (TreeTransition) tree.addTreeElement(node); //board.setModifiable(false); @@ -111,13 +110,11 @@ public String getErrorString() { return "The selected data element is not pickable with this case rule."; } - if (caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()).size() - == 0) { + if (caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()).size() == 0) { return "The selection must produce at least one case"; } - int numberOfCaseRules = - caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()).size(); + int numberOfCaseRules = caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()).size(); System.out.println("Number of cases:" + numberOfCaseRules); if (numberOfCaseRules > caseRule.MAX_CASES) { return "The selection can produce a max of " + caseRule.MAX_CASES + " cases"; 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 e1b7ca18d..0dfbc7686 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 @@ -17,24 +17,24 @@ import java.util.Set; public class FinishRoomCaseRule extends CaseRule { - private int legitCases = - 0; // placeholder for amount of cases originally generated in case user tries to delete - + private int legitCases = 0; // placeholder for amount of cases originally generated in case user tries to delete + private Set uniqueCases; // stores the unique case hashes // cases public FinishRoomCaseRule() { super( "NURI-CASE-0002", "Finish Room", - "Room can be finished in up to five ways", + "Room can be finished in up to nine ways", "edu/rpi/legup/images/nurikabe/cases/FinishRoom.png"); - this.MAX_CASES = 5; + this.MAX_CASES = 9; this.MIN_CASES = 2; + this.uniqueCases = new HashSet<>(); } /** * Checks whether the {@link TreeTransition} logically follows from the parent node using this - * rule. This method is the one that should overridden in child classes. + * rule. This method is the one that should have overridden in child classes. * * @param transition transition to check * @return null if the child node logically follow from the parent node, otherwise error message @@ -43,11 +43,11 @@ public FinishRoomCaseRule() { public String checkRuleRaw(TreeTransition transition) { NurikabeBoard destBoardState = (NurikabeBoard) transition.getBoard(); List childTransitions = transition.getParents().get(0).getChildren(); - if (childTransitions.size() > 5) { + if (childTransitions.size() > MAX_CASES) { return super.getInvalidUseOfRuleMessage() - + ": This case rule must have 5 or less children."; + + ": This case rule must have 9 or less children."; } - if (childTransitions.size() < 2) { + if (childTransitions.size() < MIN_CASES) { return super.getInvalidUseOfRuleMessage() + ": This case rule must have 2 or more children."; } @@ -97,7 +97,7 @@ public CaseBoard getCaseBoard(Board board) { } } // if size of region is 1 less than the number block and the number block is only number block in the region - if (disRow.size() + 1 == ((NurikabeCell) element).getData() && only) { + if (disRow.size() < ((NurikabeCell) element).getData() && only) { caseBoard.addPickableElement(element); // add that room as a pickable element } } @@ -120,11 +120,13 @@ public ArrayList getCases(Board board, PuzzleElement puzzleElement) { } NurikabeBoard nuriBoard = (NurikabeBoard) board.copy(); // nurikabe board to edit - NurikabeCell numberCell = nuriBoard.getCell(((NurikabeCell) puzzleElement).getLocation().x, - ((NurikabeCell) puzzleElement).getLocation().y); // number cell whose room we want to fill + NurikabeCell numberCell = nuriBoard.getCell( + ((NurikabeCell) puzzleElement).getLocation().x, + ((NurikabeCell) puzzleElement).getLocation().y + ); // number cell whose room we want to fill + Point origPoint = new Point(numberCell.getLocation().x, numberCell.getLocation().y); int filledRoomSize = numberCell.getData(); // size of room we want afterward - Set locations = new HashSet<>(); // locations where white space is added to finish room Point left = new Point(-1, 0); Point right = new Point(1, 0); @@ -138,64 +140,111 @@ public ArrayList getCases(Board board, PuzzleElement puzzleElement) { Set checkedPoints = new HashSet<>(); // add all into checked points and continue at start of loop if inside DisjointSets regions = NurikabeUtilities.getNurikabeRegions(nuriBoard); // gathers regions - Set disRow = regions.getSet(numberCell); // set of white spaces - for (NurikabeCell d : disRow) { // loops through white spaces - if (cases.size() >= 6) { // no need to check this many cases - // throw new IllegalStateException("Too many cases"); - continue; // crash/runtime protection + Set numberCellRegion = regions.getSet(numberCell); // set of white spaces + + for (NurikabeCell d : numberCellRegion) { // loops through white spaces + generateCases(nuriBoard, d, filledRoomSize, directions, checkedPoints, cases, origPoint); + } + + legitCases = cases.size(); + return cases; + } + + /** + * Recursively generates possible cases for filling a room with white cells based on the current + * board state and specified parameters. + * + * @param nuriBoard the current Nurikabe board state + * @param currentCell the current cell being evaluated + * @param filledRoomSize the target size for the room being filled + * @param directions the set of possible directions to expand the room + * @param checkedPoints the set of points already evaluated to avoid redundancy + * @param cases the list of valid board cases generated + * @param origPoint the original point of the number cell initiating the room filling + */ + private void generateCases(NurikabeBoard nuriBoard, NurikabeCell currentCell, int filledRoomSize, + Set directions, Set checkedPoints, ArrayList cases, Point origPoint) { + for (Point direction : directions) { + Point newPoint = new Point( + currentCell.getLocation().x + direction.x, + currentCell.getLocation().y + direction.y + ); + + if (newPoint.x < 0 || newPoint.y < 0 || + newPoint.x >= nuriBoard.getWidth() || newPoint.y >= nuriBoard.getHeight()) { + continue; // out of bounds } - for (Point direction : directions) { - if (cases.size() >= 6) { // no need to check this many cases - // throw new IllegalStateException("Too many cases"); - continue; // crash/runtime protection - } - if (!((nuriBoard.getWidth() > (d.getLocation().x + direction.x) - && (nuriBoard.getHeight() > d.getLocation().y + direction.y) - && (d.getLocation().x + direction.x >= 0) - && (d.getLocation().y + direction.y >= 0)))) { - continue; // if next location check would be outside of grid then continue - } - NurikabeCell curr = nuriBoard.getCell(d.getLocation().x + direction.x, d.getLocation().y + direction.y); - if (checkedPoints.contains(curr.getLocation())) { - continue; // if we already checked whether making this tile white would complete the room then continue - } - checkedPoints.add(curr.getLocation()); // adds location to checkedPoints so we don't check it again and accidentally add - - if (curr.getType() == NurikabeType.UNKNOWN) { // found adjacent space to region that is currently unknown - curr.setData(NurikabeType.WHITE.toValue()); // changes adjacent cell color to white - //nuriBoard.addModifiedData(curr); // adds modified before check - regions = NurikabeUtilities.getNurikabeRegions(nuriBoard); // update regions - Set disCreatedRow = regions.getSet(curr); // gets set of created row with new white cell added - - if (disCreatedRow.size() == filledRoomSize) { // If adding white fills the room to exact size of - // number block and doesn't connect with another room - Point here = curr.getLocation(); // gets current location of new white tile that fills room - boolean alreadyIn = false; // sets whether the tile has already been added to false - for (Point p : locations) { // loops through locations of previously added tiles - if (p == here) { // if point is already in - alreadyIn = true; // change already in to true + + NurikabeCell newCell = nuriBoard.getCell(newPoint.x, newPoint.y); + if (checkedPoints.contains(newPoint)) { + continue; // already checked + } + + if (newCell.getType() == NurikabeType.UNKNOWN) { + newCell.setData(NurikabeType.WHITE.toValue()); // changes adjacent cell color to white + newCell.setModifiable(false); + checkedPoints.add(newPoint); + + DisjointSets regions = NurikabeUtilities.getNurikabeRegions(nuriBoard); // update regions variable + Set newRoomSet = regions.getSet(newCell); // gets set of cells in room with new white cell added + + if (!touchesDifferentRoom(nuriBoard, newCell, filledRoomSize, directions, origPoint)) { + if (newRoomSet.size() == filledRoomSize) { // if adding white fills the room to exact size of + // number block and doesn't connect with another room + Board caseBoard = nuriBoard.copy(); + // check if case for board already exists + boolean unique = true; + for (Board board : cases) { + if (caseBoard.equalsBoard(board)) { + unique = false; break; } } - - if (!alreadyIn) { // if point wasn't already in - Board casey = nuriBoard.copy(); // copy the current board with white tile changed - PuzzleElement datacasey = curr; // gets changed white tile as a puzzle element - datacasey.setData(NurikabeType.WHITE.toValue()); // ensure set to white, probably redundant - casey.addModifiedData(datacasey); // ensure confirmed white change - regions = NurikabeUtilities.getNurikabeRegions(nuriBoard); // update regions - cases.add(casey); // add this case to list of cases - locations.add(here); // add location of new white tile to list of locations so - // that we don't accidentally add it again later + if (unique) { + caseBoard.addModifiedData(newCell); + cases.add(caseBoard); } + } else if (newRoomSet.size() < filledRoomSize) { + generateCases(nuriBoard, newCell, filledRoomSize, directions, checkedPoints, cases, origPoint); } - curr.setData(NurikabeType.UNKNOWN.toValue()); // set cell type back to unknown - regions = NurikabeUtilities.getNurikabeRegions(nuriBoard); // updates regions } + newCell.setData(NurikabeType.UNKNOWN.toValue()); + newCell.setModifiable(true); + checkedPoints.remove(newPoint); } - legitCases = cases.size(); } - return cases; + } + + /** + * Determines if a given cell touches a different room by checking adjacent cells in specified directions. + * + * @param board the current Nurikabe board state + * @param cell the cell being evaluated + * @param origRoomSize the size of the original room being filled + * @param directions the set of possible directions to check around the cell + * @param origPoint the original point of the number cell initiating the room filling + * @return true if the cell touches a different room, false otherwise + */ + private boolean touchesDifferentRoom(NurikabeBoard board, NurikabeCell cell, int origRoomSize, Set directions, Point origPoint) { + for (Point direction : directions) { + Point adjacentPoint = new Point( + cell.getLocation().x + direction.x, + cell.getLocation().y + direction.y + ); + + if (adjacentPoint.x >= 0 && adjacentPoint.y >= 0 && + adjacentPoint.x < board.getWidth() && adjacentPoint.y < board.getHeight()) { // check if out of bounds + NurikabeCell adjacentCell = board.getCell(adjacentPoint.x, adjacentPoint.y); + // check if the adjacent cell is a number cell + if (adjacentCell.getType() == NurikabeType.NUMBER) { + // check if it's different from the original number cell + if (origRoomSize != adjacentCell.getData() || (adjacentPoint.x != origPoint.x || adjacentPoint.y != origPoint.y)) { + return true; + } + } + } + } + return false; } /** From 925ff9c902c7e03b18de57b9ca22454d9e3a9c75 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Tue, 9 Jul 2024 13:43:40 -0400 Subject: [PATCH 08/10] Added undo and redo buttons to puzzle solver tool bar, fixed major redo bugs, fixed unbalanced row/col contra rule for binary --- .../edu/rpi/legup/history/PuzzleCommand.java | 10 +- .../ValidateContradictionRuleCommand.java | 7 +- .../history/ValidateDirectRuleCommand.java | 114 +++++++++++++++++- .../java/edu/rpi/legup/model/tree/Tree.java | 1 + ...nbalancedRowOrColumnContradictionRule.java | 10 +- .../edu/rpi/legup/ui/ProofEditorPanel.java | 52 +++++++- 6 files changed, 174 insertions(+), 20 deletions(-) diff --git a/src/main/java/edu/rpi/legup/history/PuzzleCommand.java b/src/main/java/edu/rpi/legup/history/PuzzleCommand.java index 3768e3cbd..fb57e7af2 100644 --- a/src/main/java/edu/rpi/legup/history/PuzzleCommand.java +++ b/src/main/java/edu/rpi/legup/history/PuzzleCommand.java @@ -52,13 +52,13 @@ public final String getError() { */ public abstract String getErrorString(); - /** Executes an command */ + /** Executes a command */ public abstract void executeCommand(); - /** Undoes an command */ + /** Undoes a command */ public abstract void undoCommand(); - /** Redoes an command */ + /** Redoes a command */ public void redoCommand() { if (state == CommandState.UNDOED) { executeCommand(); @@ -68,7 +68,7 @@ public void redoCommand() { } } - /** Undoes an command */ + /** Undoes a command */ @Override public final void undo() { if (state == CommandState.EXECUTED || state == CommandState.REDOED) { @@ -79,7 +79,7 @@ public final void undo() { } } - /** Redoes an command */ + /** Redoes a command */ public final void redo() { if (state == CommandState.UNDOED) { redoCommand(); diff --git a/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java b/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java index 8737b4008..6c95202c9 100644 --- a/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/ValidateContradictionRuleCommand.java @@ -84,7 +84,12 @@ public void executeCommand() { final TreeElement finalTreeElement; if (firstSelectedView.getType() == TreeElementType.NODE) { TreeNodeView nodeView = (TreeNodeView) firstSelectedView; - finalTreeElement = nodeView.getChildrenViews().get(0).getTreeElement(); + if (!nodeView.getChildrenViews().isEmpty()) { + finalTreeElement = nodeView.getChildrenViews().get(0).getTreeElement(); + } + else { + finalTreeElement = null; + } } else { TreeTransitionView transitionView = (TreeTransitionView) firstSelectedView; if (transitionView.getChildView() != null) { diff --git a/src/main/java/edu/rpi/legup/history/ValidateDirectRuleCommand.java b/src/main/java/edu/rpi/legup/history/ValidateDirectRuleCommand.java index d9c063464..a2b6632d2 100644 --- a/src/main/java/edu/rpi/legup/history/ValidateDirectRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/ValidateDirectRuleCommand.java @@ -6,11 +6,15 @@ import edu.rpi.legup.model.rules.Rule; import edu.rpi.legup.model.tree.*; import edu.rpi.legup.ui.proofeditorui.treeview.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + import java.util.HashMap; import java.util.List; import java.util.Map; public class ValidateDirectRuleCommand extends PuzzleCommand { + private static final Logger LOGGER = LogManager.getLogger(History.class.getName()); private TreeViewSelection selection; private Map oldRules; @@ -30,7 +34,60 @@ public ValidateDirectRuleCommand(TreeViewSelection selection, DirectRule rule) { this.addNode = new HashMap<>(); } - /** Executes an command */ +// /** Executes a command */ +// @Override +// public void executeCommand() { +// Tree tree = GameBoardFacade.getInstance().getTree(); +// TreeView treeView = GameBoardFacade.getInstance().getLegupUI().getTreePanel().getTreeView(); +// Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule(); +// final TreeViewSelection newSelection = new TreeViewSelection(); +// +// List selectedViews = selection.getSelectedViews(); +// int count = 1; +// for (TreeElementView selectedView : selectedViews) { +// System.out.println(count); +// count++; +// TreeElement element = selectedView.getTreeElement(); +// TreeTransitionView transitionView; +// if (element.getType() == TreeElementType.NODE) { +// TreeNodeView nodeView = (TreeNodeView) selectedView; +// transitionView = nodeView.getChildrenViews().get(0); +// } else { +// transitionView = (TreeTransitionView) selectedView; +// } +// TreeTransition transition = transitionView.getTreeElement(); +// +// oldRules.put(transition, transition.getRule()); +// transition.setRule(newRule); +// +// TreeNode childNode = transition.getChildNode(); +// if (childNode == null) { +// childNode = addNode.get(transition); +// if (childNode == null) { +// childNode = (TreeNode) tree.addTreeElement(transition); +// addNode.put(transition, childNode); +// } else { +// tree.addTreeElement(transition, childNode); +// } +// +// final TreeNode finalNode = childNode; +// puzzle.notifyTreeListeners(listener -> listener.onTreeElementAdded(finalNode)); +// } +// newSelection.addToSelection(treeView.getElementView(childNode)); +// } +// TreeElementView firstSelectedView = selection.getFirstSelection(); +// final TreeElement finalTreeElement; +// if (firstSelectedView.getType() == TreeElementType.NODE) { +// TreeNodeView nodeView = (TreeNodeView) firstSelectedView; +// finalTreeElement = nodeView.getChildrenViews().get(0).getTreeElement(); +// } else { +// TreeTransitionView transitionView = (TreeTransitionView) firstSelectedView; +// finalTreeElement = transitionView.getChildView().getTreeElement(); +// } +// puzzle.notifyBoardListeners(listener -> listener.onTreeElementChanged(finalTreeElement)); +// puzzle.notifyTreeListeners(listener -> listener.onTreeSelectionChanged(newSelection)); +// } + /** Executes a command */ @Override public void executeCommand() { Tree tree = GameBoardFacade.getInstance().getTree(); @@ -42,14 +99,24 @@ public void executeCommand() { for (TreeElementView selectedView : selectedViews) { TreeElement element = selectedView.getTreeElement(); TreeTransitionView transitionView; + if (element.getType() == TreeElementType.NODE) { TreeNodeView nodeView = (TreeNodeView) selectedView; + if (nodeView.getChildrenViews().isEmpty()) { + LOGGER.error("NodeView has no children views"); + continue; + } transitionView = nodeView.getChildrenViews().get(0); } else { transitionView = (TreeTransitionView) selectedView; } - TreeTransition transition = transitionView.getTreeElement(); + if (transitionView == null) { + LOGGER.error("Transition view is null"); + continue; + } + + TreeTransition transition = transitionView.getTreeElement(); oldRules.put(transition, transition.getRule()); transition.setRule(newRule); @@ -66,21 +133,58 @@ public void executeCommand() { final TreeNode finalNode = childNode; puzzle.notifyTreeListeners(listener -> listener.onTreeElementAdded(finalNode)); } - newSelection.addToSelection(treeView.getElementView(childNode)); + + TreeElementView childView = treeView.getElementView(childNode); + if (childView == null) { + LOGGER.error("Child view is null for child node: " + childNode); + continue; + } + newSelection.addToSelection(childView); } + TreeElementView firstSelectedView = selection.getFirstSelection(); + if (firstSelectedView == null) { + LOGGER.error("First selected view is null"); + return; + } + final TreeElement finalTreeElement; if (firstSelectedView.getType() == TreeElementType.NODE) { TreeNodeView nodeView = (TreeNodeView) firstSelectedView; + if (nodeView.getChildrenViews().isEmpty()) { + LOGGER.error("NodeView has no children views"); + return; + } finalTreeElement = nodeView.getChildrenViews().get(0).getTreeElement(); } else { TreeTransitionView transitionView = (TreeTransitionView) firstSelectedView; + TreeNodeView childView = transitionView.getChildView(); + if (childView == null) { + LOGGER.error("Child view is null for transition view: " + transitionView); + TreeNode childNode = transitionView.getTreeElement().getChildNode(); + if (childNode == null) { + LOGGER.error("Child node is null for transition: " + transitionView.getTreeElement()); + return; + } + childView = (TreeNodeView) treeView.getElementView(childNode); + if (childView == null) { + LOGGER.error("Failed to initialize child view for node: " + childNode); + return; + } + transitionView.setChildView(childView); + } + TreeTransition transition = transitionView.getTreeElement(); + if (transition.getParents().get(0).getChildren().isEmpty()) { + transition.getParents().get(0).addChild(transition); + } finalTreeElement = transitionView.getChildView().getTreeElement(); } + puzzle.notifyBoardListeners(listener -> listener.onTreeElementChanged(finalTreeElement)); puzzle.notifyTreeListeners(listener -> listener.onTreeSelectionChanged(newSelection)); } + /** * Gets the reason why the command cannot be executed * @@ -110,7 +214,7 @@ public String getErrorString() { return null; } - /** Undoes an command */ + /** Undoes a command */ @Override public void undoCommand() { Tree tree = GameBoardFacade.getInstance().getTree(); @@ -124,8 +228,10 @@ public void undoCommand() { transitionView = nodeView.getChildrenViews().get(0); } else { transitionView = (TreeTransitionView) selectedView; + } TreeTransition transition = transitionView.getTreeElement(); + transition.setRule(oldRules.get(transition)); if (addNode.get(transition) != null) { 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 08e594801..3cdab80c2 100644 --- a/src/main/java/edu/rpi/legup/model/tree/Tree.java +++ b/src/main/java/edu/rpi/legup/model/tree/Tree.java @@ -88,6 +88,7 @@ public void removeTreeElement(TreeElement element) { } node.getParent().setChildNode(null); + System.out.println("Deleted node: " + node); } else { TreeTransition transition = (TreeTransition) element; diff --git a/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java index 3688c4866..ea110ef2c 100644 --- a/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java +++ b/src/main/java/edu/rpi/legup/puzzle/binary/rules/UnbalancedRowOrColumnContradictionRule.java @@ -44,8 +44,8 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { } } - if (rowNumZeros == size / 2 && rowNumOnes == size / 2) { - return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; + if (rowNumZeros > size / 2 || rowNumOnes > size / 2) { + return null; } Set col = binaryBoard.getColCells(cell.getLocation().x); @@ -62,10 +62,10 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) { } } - if (colNumZeros == size / 2 && colNumOnes == size / 2) { - return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; + if (colNumZeros > size / 2 || colNumOnes > size / 2) { + return null; } - return null; + return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE; } } diff --git a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java index 3802e4de7..f78281c89 100644 --- a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java +++ b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java @@ -19,6 +19,7 @@ import edu.rpi.legup.ui.boardview.BoardView; import edu.rpi.legup.ui.proofeditorui.rulesview.RuleFrame; import edu.rpi.legup.ui.proofeditorui.treeview.TreePanel; +import edu.rpi.legup.ui.proofeditorui.treeview.TreeTransitionView; import edu.rpi.legup.ui.proofeditorui.treeview.TreeViewSelection; import edu.rpi.legup.user.Submission; import java.awt.*; @@ -781,13 +782,12 @@ private void setupToolBar2() { toolBar2 = new JToolBar(); toolBar2.setFloatable(false); toolBar2.setRollover(true); - setToolBar2Buttons(new JButton[2]); + setToolBar2Buttons(new JButton[4]); URL directions_url = ClassLoader.getSystemClassLoader() .getResource("edu/rpi/legup/images/Legup/Directions.png"); - // Scale the image icons down to make the buttons smaller ImageIcon DirectionsImageIcon = new ImageIcon(directions_url); Image DirectionsImage = DirectionsImageIcon.getImage(); DirectionsImageIcon = @@ -804,11 +804,52 @@ private void setupToolBar2() { getToolBar2Buttons()[0] = directions; toolBar2.add(getToolBar2Buttons()[0]); + URL undo_url = + ClassLoader.getSystemClassLoader() + .getResource("edu/rpi/legup/images/Legup/Undo.png"); + + ImageIcon UndoImageIcon = new ImageIcon(undo_url); + Image UndoImage = UndoImageIcon.getImage(); + UndoImageIcon = + new ImageIcon( + UndoImage.getScaledInstance( + this.TOOLBAR_ICON_SCALE, + this.TOOLBAR_ICON_SCALE, + Image.SCALE_SMOOTH)); + + JButton undo = new JButton("Undo", UndoImageIcon); + undo.setFocusPainted(false); + undo.addActionListener((ActionEvent) -> GameBoardFacade.getInstance().getHistory().undo()); + + getToolBar2Buttons()[1] = undo; + toolBar2.add(getToolBar2Buttons()[1]); + + URL redo_url = + ClassLoader.getSystemClassLoader() + .getResource("edu/rpi/legup/images/Legup/Redo.png"); + + ImageIcon RedoImageIcon = new ImageIcon(redo_url); + Image RedoImage = RedoImageIcon.getImage(); + RedoImageIcon = + new ImageIcon( + RedoImage.getScaledInstance( + this.TOOLBAR_ICON_SCALE, + this.TOOLBAR_ICON_SCALE, + Image.SCALE_SMOOTH)); + + JButton redo = new JButton("Redo", RedoImageIcon); + redo.setFocusPainted(false); + redo.addActionListener((ActionEvent) -> { + GameBoardFacade.getInstance().getHistory().redo(); + }); + + getToolBar2Buttons()[2] = redo; + toolBar2.add(getToolBar2Buttons()[2]); + URL check_url = ClassLoader.getSystemClassLoader() .getResource("edu/rpi/legup/images/Legup/Check.png"); - // Scale the image icons down to make the buttons smaller ImageIcon CheckImageIcon = new ImageIcon(check_url); Image CheckImage = CheckImageIcon.getImage(); CheckImageIcon = @@ -822,8 +863,9 @@ private void setupToolBar2() { check.setFocusPainted(false); check.addActionListener((ActionEvent) -> checkProof()); - getToolBar2Buttons()[1] = check; - toolBar2.add(getToolBar2Buttons()[1]); + getToolBar2Buttons()[3] = check; + toolBar2.add(getToolBar2Buttons()[3]); + this.add(toolBar2, BorderLayout.NORTH); } From d69e6341d52dad596524c1b95ab2c34aabbd5903 Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Tue, 9 Jul 2024 13:45:27 -0400 Subject: [PATCH 09/10] Removed unnecessary logger error info --- .../history/ValidateDirectRuleCommand.java | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/src/main/java/edu/rpi/legup/history/ValidateDirectRuleCommand.java b/src/main/java/edu/rpi/legup/history/ValidateDirectRuleCommand.java index a2b6632d2..c5a36ddb3 100644 --- a/src/main/java/edu/rpi/legup/history/ValidateDirectRuleCommand.java +++ b/src/main/java/edu/rpi/legup/history/ValidateDirectRuleCommand.java @@ -102,20 +102,11 @@ public void executeCommand() { if (element.getType() == TreeElementType.NODE) { TreeNodeView nodeView = (TreeNodeView) selectedView; - if (nodeView.getChildrenViews().isEmpty()) { - LOGGER.error("NodeView has no children views"); - continue; - } transitionView = nodeView.getChildrenViews().get(0); } else { transitionView = (TreeTransitionView) selectedView; } - if (transitionView == null) { - LOGGER.error("Transition view is null"); - continue; - } - TreeTransition transition = transitionView.getTreeElement(); oldRules.put(transition, transition.getRule()); transition.setRule(newRule); @@ -143,10 +134,6 @@ public void executeCommand() { } TreeElementView firstSelectedView = selection.getFirstSelection(); - if (firstSelectedView == null) { - LOGGER.error("First selected view is null"); - return; - } final TreeElement finalTreeElement; if (firstSelectedView.getType() == TreeElementType.NODE) { @@ -162,15 +149,7 @@ public void executeCommand() { if (childView == null) { LOGGER.error("Child view is null for transition view: " + transitionView); TreeNode childNode = transitionView.getTreeElement().getChildNode(); - if (childNode == null) { - LOGGER.error("Child node is null for transition: " + transitionView.getTreeElement()); - return; - } childView = (TreeNodeView) treeView.getElementView(childNode); - if (childView == null) { - LOGGER.error("Failed to initialize child view for node: " + childNode); - return; - } transitionView.setChildView(childView); } TreeTransition transition = transitionView.getTreeElement(); From b5c10beeafc560fd7c44b7a23afbb0bc264e7e2f Mon Sep 17 00:00:00 2001 From: Zachary Bonagura Date: Tue, 9 Jul 2024 13:47:18 -0400 Subject: [PATCH 10/10] Fixed checkStyle error in Board --- src/main/java/edu/rpi/legup/model/gameboard/Board.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/edu/rpi/legup/model/gameboard/Board.java b/src/main/java/edu/rpi/legup/model/gameboard/Board.java index b6d3ed995..5ad6fcf60 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/Board.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/Board.java @@ -37,8 +37,9 @@ public Board(int size) { * @return equivalent puzzleElement on this board */ public PuzzleElement getPuzzleElement(PuzzleElement puzzleElement) { - if (puzzleElement == null) + if (puzzleElement == null) { return null; + } int index = puzzleElement.getIndex(); return index < puzzleElements.size() ? puzzleElements.get(index) : null; }