From 653c816387052fec18c9d6f1dedffd7bcd4fe8cb Mon Sep 17 00:00:00 2001 From: Charles Tian <46334090+charlestian23@users.noreply.github.com> Date: Fri, 26 Jan 2024 13:03:33 -0500 Subject: [PATCH 01/10] Fixed Short Truth Table case rule bug (#707) * Revert "Bugfix 549 (#682)" This reverts commit 5048ee69d958fdde9b1bb35854c56c9920068346. * Case rule test fix (#705) Co-authored-by: Chase Grajeda <76405306+Chase-Grajeda@users.noreply.github.com> * Rapid fix for STT case rules Case rules broke at some point from legacy code or merge conflict. Provided is a quick fix in CaseRule and CaseRule_Generic * Revert "Revert "Bugfix 549 (#682)"" (#706) This reverts commit e9fe310378721aa4b4fa358aa57ec44f21d086c1. --------- Co-authored-by: Chase-Grajeda Co-authored-by: Chase Grajeda <76405306+Chase-Grajeda@users.noreply.github.com> --- bin/main/edu/rpi/legup/log4j2.properties | 28 +++++++++---------- .../edu/rpi/legup/model/rules/CaseRule.java | 10 ------- .../rules/caserule/CaseRule_Generic.java | 22 +++++++-------- .../rules/AndCaseRuleTest.java | 4 +-- .../shorttruthtable/rules/OrCaseRuleTest.java | 4 +-- .../rules/TrueOrFalseCaseRuleTest.java | 2 +- 6 files changed, 30 insertions(+), 40 deletions(-) diff --git a/bin/main/edu/rpi/legup/log4j2.properties b/bin/main/edu/rpi/legup/log4j2.properties index 4f2556c2d..de1fa02ed 100644 --- a/bin/main/edu/rpi/legup/log4j2.properties +++ b/bin/main/edu/rpi/legup/log4j2.properties @@ -1,15 +1,15 @@ -# Logging level -# Root logger option -log4j.rootLogger=DEBUG, stdout, file -# Redirect log messages to console -log4j.appender.stdout=org.apache.log4j.ConsoleAppender -log4j.appender.stdout.Target=System.out -log4j.appender.stdout.layout=org.apache.log4j.PatternLayout -log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n -# Redirect log messages to a log file, support file rolling. -log4j.appender.file=org.apache.log4j.RollingFileAppender -log4j.appender.file.File=Legup.log -log4j.appender.file.MaxFileSize=5MB -log4j.appender.file.MaxBackupIndex=10 -log4j.appender.file.layout=org.apache.log4j.PatternLayout +# Logging level +# Root logger option +log4j.rootLogger=DEBUG, stdout, file +# Redirect log messages to console +log4j.appender.stdout=org.apache.log4j.ConsoleAppender +log4j.appender.stdout.Target=System.out +log4j.appender.stdout.layout=org.apache.log4j.PatternLayout +log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n +# Redirect log messages to a log file, support file rolling. +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.File=Legup.log +log4j.appender.file.MaxFileSize=5MB +log4j.appender.file.MaxBackupIndex=10 +log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/model/rules/CaseRule.java b/src/main/java/edu/rpi/legup/model/rules/CaseRule.java index efb96e21a..a01db2b6d 100644 --- a/src/main/java/edu/rpi/legup/model/rules/CaseRule.java +++ b/src/main/java/edu/rpi/legup/model/rules/CaseRule.java @@ -60,20 +60,10 @@ public String checkRule(TreeTransition transition) { return "Must not have multiple parent nodes"; } - /*if (transition.getBoard().getModifiedData().size() != 0){ - return "Should not modify before case rule"; - }*/ - - for (TreeTransition childTrans : parentNodes.get(0).getChildren()) { if (childTrans.getRule() == null || !childTrans.getRule().getClass().equals(this.getClass())) { return "All children nodes must be justified with the same case rule."; } - else { - if (childTrans.getBoard().getModifiedData().isEmpty()) { - return "You must modify the board in each case node"; - } - } } String check = checkRuleRaw(transition); diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java index 1409f4baa..46163c2a3 100644 --- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java +++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/caserule/CaseRule_Generic.java @@ -38,20 +38,20 @@ public CaseRule_Generic(String ruleID, String ruleName, String title, String des public String checkRuleRaw(TreeTransition transition) { // Validate that two children are generated List childTransitions = transition.getParents().get(0).getChildren(); - if (childTransitions.size() >= 1) { + if (childTransitions.size() == 0) { return "ERROR: This case rule must spawn at least 1 child."; } - // Validate that the modified cells are of type UNKNOWN, TRUE, or FALSE - List cases = Arrays.asList(childTransitions.get(0), childTransitions.get(1)); - for (TreeTransition c : cases) { - ShortTruthTableCell mod1 = (ShortTruthTableCell)c.getBoard().getModifiedData().iterator().next(); - ShortTruthTableCell mod2 = (ShortTruthTableCell)c.getBoard().getModifiedData().iterator().next(); - if (!(mod1.getType() == ShortTruthTableCellType.TRUE || mod1.getType() == ShortTruthTableCellType.FALSE || mod1.getType() == ShortTruthTableCellType.UNKNOWN) && - (mod2.getType() == ShortTruthTableCellType.TRUE || mod2.getType() == ShortTruthTableCellType.FALSE || mod2.getType() == ShortTruthTableCellType.UNKNOWN)) { - return "ERROR: This case rule must be an unknown, true, or false cell."; - } - } + // // Validate that the modified cells are of type UNKNOWN, TRUE, or FALSE + // List cases = Arrays.asList(childTransitions.get(0), childTransitions.get(1)); + // for (TreeTransition c : cases) { + // ShortTruthTableCell mod1 = (ShortTruthTableCell)c.getBoard().getModifiedData().iterator().next(); + // ShortTruthTableCell mod2 = (ShortTruthTableCell)c.getBoard().getModifiedData().iterator().next(); + // if (!(mod1.getType() == ShortTruthTableCellType.TRUE || mod1.getType() == ShortTruthTableCellType.FALSE || mod1.getType() == ShortTruthTableCellType.UNKNOWN) && + // (mod2.getType() == ShortTruthTableCellType.TRUE || mod2.getType() == ShortTruthTableCellType.FALSE || mod2.getType() == ShortTruthTableCellType.UNKNOWN)) { + // return "ERROR: This case rule must be an unknown, true, or false cell."; + // } + // } return null; } diff --git a/src/test/java/puzzles/shorttruthtable/rules/AndCaseRuleTest.java b/src/test/java/puzzles/shorttruthtable/rules/AndCaseRuleTest.java index 5f0a1243a..4d4e95762 100644 --- a/src/test/java/puzzles/shorttruthtable/rules/AndCaseRuleTest.java +++ b/src/test/java/puzzles/shorttruthtable/rules/AndCaseRuleTest.java @@ -42,7 +42,7 @@ private void falseAndTest(String fileName, ArrayList cases = RULE.getCases(board, cell); // Make sure that the rule checks out - Assert.assertNotNull(RULE.checkRule(transition)); + Assert.assertNull(RULE.checkRule(transition)); // Make sure there are two branches Assert.assertEquals(2, cases.size()); @@ -120,7 +120,7 @@ private void trueAndTest(String fileName, ArrayList cases = RULE.getCases(board, cell); // Make sure that the rule checks out - Assert.assertNotNull(RULE.checkRule(transition)); + Assert.assertNull(RULE.checkRule(transition)); // There should only be 1 branch Assert.assertEquals(1, cases.size()); diff --git a/src/test/java/puzzles/shorttruthtable/rules/OrCaseRuleTest.java b/src/test/java/puzzles/shorttruthtable/rules/OrCaseRuleTest.java index 276e822cf..0f7e93db5 100644 --- a/src/test/java/puzzles/shorttruthtable/rules/OrCaseRuleTest.java +++ b/src/test/java/puzzles/shorttruthtable/rules/OrCaseRuleTest.java @@ -43,7 +43,7 @@ private void trueOrTest(String fileName, ArrayList cases = RULE.getCases(board, cell); // Make sure that the rule checks out - Assert.assertNotNull(RULE.checkRule(transition)); + Assert.assertNull(RULE.checkRule(transition)); // Make sure there are two branches Assert.assertEquals(2, cases.size()); @@ -121,7 +121,7 @@ private void falseOrTest(String fileName, ArrayList cases = RULE.getCases(board, cell); // Make sure that the rule checks out - Assert.assertNotNull(RULE.checkRule(transition)); + Assert.assertNull(RULE.checkRule(transition)); // There should only be 1 branch Assert.assertEquals(1, cases.size()); diff --git a/src/test/java/puzzles/shorttruthtable/rules/TrueOrFalseCaseRuleTest.java b/src/test/java/puzzles/shorttruthtable/rules/TrueOrFalseCaseRuleTest.java index 849e9f15c..2c0b9fb15 100644 --- a/src/test/java/puzzles/shorttruthtable/rules/TrueOrFalseCaseRuleTest.java +++ b/src/test/java/puzzles/shorttruthtable/rules/TrueOrFalseCaseRuleTest.java @@ -44,7 +44,7 @@ public void TwoBranchesTest() throws InvalidFileFormatException { ArrayList cases = RULE.getCases(board, cell); // Make sure that the rule checks out - Assert.assertNotNull(RULE.checkRule(transition)); + Assert.assertNull(RULE.checkRule(transition)); // Make sure there are two branches Assert.assertEquals(2, cases.size()); From b961f15c4bb74ad72742e32daf3d0a69082e9795 Mon Sep 17 00:00:00 2001 From: Kevin-771 <70790256+Kevin-771@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:00:20 -0500 Subject: [PATCH 02/10] working on an abstract GridRegion class (WIP) added some basic functions to GridRegion --- .../rpi/legup/model/gameboard/GridRegion.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java diff --git a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java new file mode 100644 index 000000000..233f443b3 --- /dev/null +++ b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java @@ -0,0 +1,39 @@ +package edu.rpi.legup.model.gameboard; + +import edu.rpi.legup.model.gameboard.GridCell; + +import java.util.ArrayList; +import java.util.List; + +public abstract class GridRegion { + + protected List regionCells; + + /** + * Region Constructor + */ + public GridRegion() { + this.regionCells = new ArrayList<>(); + } + + public void addCell(GridCell cell) { + regionCells.add(cell); + } + + public void removeCell(GridCell cell) { + regionCells.remove(cell); + } + + public List getCells() { + return regionCells; + } + + public int getSize(){ + return regionCells.size(); + } + + /* + public void colorRegion(){} + */ + +} From d84ad72fa716fff01ef388fa2f91ad44114a9ed1 Mon Sep 17 00:00:00 2001 From: Kevin-771 <70790256+Kevin-771@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:09:46 -0500 Subject: [PATCH 03/10] added comments to GridRegion --- .../rpi/legup/model/gameboard/GridRegion.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java index 233f443b3..ddf5919e1 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java @@ -16,18 +16,34 @@ public GridRegion() { this.regionCells = new ArrayList<>(); } + /** + * Adds the cell to the region + * @param cell cell to be added to the region + */ public void addCell(GridCell cell) { regionCells.add(cell); } + /** + * Removes the cell from the region + * @param cell cell to be remove from the region + */ public void removeCell(GridCell cell) { regionCells.remove(cell); } + /** + * Returns the list of cells in the region + * @return list of cells in region + */ public List getCells() { return regionCells; } + /** + * Returns the number of cells in the region + * @return number of cells in the region + */ public int getSize(){ return regionCells.size(); } From 79d3608de68a82105a197adba86e222458427980 Mon Sep 17 00:00:00 2001 From: Kevin-771 <70790256+Kevin-771@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:56:28 -0500 Subject: [PATCH 04/10] modified GridRegion to handle generic types --- .../java/edu/rpi/legup/model/gameboard/GridRegion.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java index ddf5919e1..a571c0f1b 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java @@ -5,9 +5,9 @@ import java.util.ArrayList; import java.util.List; -public abstract class GridRegion { +public abstract class GridRegion { - protected List regionCells; + protected List regionCells; /** * Region Constructor @@ -20,7 +20,7 @@ public GridRegion() { * Adds the cell to the region * @param cell cell to be added to the region */ - public void addCell(GridCell cell) { + public void addCell(T cell) { regionCells.add(cell); } @@ -28,7 +28,7 @@ public void addCell(GridCell cell) { * Removes the cell from the region * @param cell cell to be remove from the region */ - public void removeCell(GridCell cell) { + public void removeCell(T cell) { regionCells.remove(cell); } @@ -36,7 +36,7 @@ public void removeCell(GridCell cell) { * Returns the list of cells in the region * @return list of cells in region */ - public List getCells() { + public List getCells() { return regionCells; } From 2ae701774ea1814819c6ae0aa3705e1c73565702 Mon Sep 17 00:00:00 2001 From: Kevin-771 <70790256+Kevin-771@users.noreply.github.com> Date: Fri, 2 Feb 2024 16:57:35 -0500 Subject: [PATCH 05/10] Update GridRegion.java --- src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java index a571c0f1b..6718ab6f4 100644 --- a/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java +++ b/src/main/java/edu/rpi/legup/model/gameboard/GridRegion.java @@ -1,7 +1,5 @@ package edu.rpi.legup.model.gameboard; -import edu.rpi.legup.model.gameboard.GridCell; - import java.util.ArrayList; import java.util.List; From b5b73baf78e7ea4002a6785eb4edbdefea6db29e Mon Sep 17 00:00:00 2001 From: Chase-Grajeda Date: Fri, 2 Feb 2024 17:39:10 -0500 Subject: [PATCH 06/10] Added board initialization template Added rippleeffect folder within puzzles so we can begin implementing and rendering the demo puzzle Added RippleEffect.java Added RippleEffectCell.java Added RippleEffectImporter.java Added RippleEffectView.java --- .../puzzle/rippleeffect/RippleEffect.java | 99 +++++++++++++++++++ .../puzzle/rippleeffect/RippleEffectCell.java | 5 + .../rippleeffect/RippleEffectImporter.java | 64 ++++++++++++ .../puzzle/rippleeffect/RippleEffectView.java | 5 + 4 files changed, 173 insertions(+) create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectView.java diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java new file mode 100644 index 000000000..73efb46eb --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java @@ -0,0 +1,99 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +import edu.rpi.legup.model.Puzzle; +import edu.rpi.legup.model.RegisterPuzzle; +import edu.rpi.legup.model.gameboard.Board; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.model.rules.ContradictionRule; + + +/** + * 1) Number is duplicated in a row or a column, the space between the duplicated numbers must be equal to or larger than the value of the number. + * 2) Each Room contains consecutive numbers starting from 1. + * 3) If a number is duplicated in a row or a column, the space between the duplicated numbers must be equal to or larger than the value of the number. + */ + + + +@RegisterPuzzle +public class RippleEffect extends Puzzle { + + public RippleEffect() { + super(); + this.name = "RippleEffect"; + + // this.importer = new LightUpImporter(this); + // this.exporter = new LightUpExporter(this); + + // this.factory = new LightUpCellFactory(); + } + + /** + * Initializes the game board. Called by the invoker of the class + */ + @Override + public void initializeView() { + // boardView = new LightUpView((LightUpBoard) currentBoard); + // boardView.setBoard(currentBoard); + // addBoardListener(boardView); + } + + /** + * Generates a random edu.rpi.legup.puzzle based on the difficulty + * + * @param difficulty level of difficulty (1-10) + * @return board of the random edu.rpi.legup.puzzle + */ + @Override + public Board generatePuzzle(int difficulty) { + return null; + } + + @Override + /** + * Determines if the given dimensions are valid for Light Up + * + * @param rows the number of rows + * @param columns the number of columns + * @return true if the given dimensions are valid for Light Up, false otherwise + */ + public boolean isValidDimensions(int rows, int columns) { + return rows > 0 && columns > 0; + } + + /** + * Determines if the current board is a valid state + * + * @param board board to check for validity + * @return true if board is valid, false otherwise + */ + @Override + public boolean isBoardComplete(Board board) { + // LightUpBoard lightUpBoard = (LightUpBoard) board; + // lightUpBoard.fillWithLight(); + + // for (ContradictionRule rule : contradictionRules) { + // if (rule.checkContradiction(lightUpBoard) == null) { + // System.out.println(rule.getRuleName()); + // return false; + // } + // } + // for (PuzzleElement data : lightUpBoard.getPuzzleElements()) { + // LightUpCell cell = (LightUpCell) data; + // if ((cell.getType() == LightUpCellType.UNKNOWN || cell.getType() == LightUpCellType.EMPTY) && !cell.isLite()) { + // return false; + // } + // } + return true; + } + + /** + * Callback for when the board puzzleElement changes + * + * @param board the board that has changed + */ + @Override + public void onBoardChange(Board board) { + + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java new file mode 100644 index 000000000..b8a4da825 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java @@ -0,0 +1,5 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +public class RippleEffectCell { + +} diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java new file mode 100644 index 000000000..7b3b25bac --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java @@ -0,0 +1,64 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +import edu.rpi.legup.model.PuzzleImporter; +import edu.rpi.legup.save.InvalidFileFormatException; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class RippleEffectImporter extends PuzzleImporter { + public RippleEffectImporter(RippleEffect rippleEffect) { + super(rippleEffect); + } + + + /** + * Puzzle setting to support row and column inputs + */ + @Override + public boolean acceptsRowsAndColumnsInput() { + return true; + } + + /** + * Puzzle setting to disable support for text input + */ + @Override + public boolean acceptsTextInput() { + return false; + } + + + /** + * Constructs empty RippleEffect gameboard as per the provided dimensions + * @param rows number of rows for the gameboard + * @param columns number of columns for the gameboard + */ + @Override + public void initializeBoard(int rows, int columns) { + // Womp + } + + + + /** + * Constructs RippleEffect gameboard + * @param node xml document node + * @throws InvalidFileFormatException if file is invalid + */ + @Override + public void initializeBoard(Node node) throws InvalidFileFormatException { + if (node == null) throw new InvalidFileFormatException("Invalid format"); + } + + + + /** + * Initialize board via string of statements. + * @throws UnsupportedOperationException since RippleEffect does not support text input + */ + @Override + public void initializeBoard(String[] statements) throws UnsupportedOperationException { + throw new UnsupportedOperationException("Ripple Effect does not accept text input"); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectView.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectView.java new file mode 100644 index 000000000..46647299f --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectView.java @@ -0,0 +1,5 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +public class RippleEffectView { + +} From 6b066ae62b5cdc1ea47826bd6e7224d1b8b13731 Mon Sep 17 00:00:00 2001 From: Chase-Grajeda Date: Fri, 9 Feb 2024 16:16:32 -0500 Subject: [PATCH 07/10] RippleEffect importer Added more dependencies for RippleEffect board Added config for RippleEffect editing support --- bin/main/edu/rpi/legup/legup/config | 4 ++++ .../legup/puzzle/rippleeffect/RippleEffect.java | 2 +- .../puzzle/rippleeffect/RippleEffectBoard.java | 9 +++++++++ .../puzzle/rippleeffect/RippleEffectCell.java | 9 +++++++-- .../rippleeffect/RippleEffectCellType.java | 10 ++++++++++ .../rippleeffect/RippleEffectImporter.java | 16 ++++++++++++++-- src/main/resources/edu/rpi/legup/legup/config | 4 ++++ 7 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectBoard.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellType.java diff --git a/bin/main/edu/rpi/legup/legup/config b/bin/main/edu/rpi/legup/legup/config index 19e63a2a3..4428411c2 100644 --- a/bin/main/edu/rpi/legup/legup/config +++ b/bin/main/edu/rpi/legup/legup/config @@ -39,5 +39,9 @@ qualifiedClassName="edu.rpi.legup.puzzle.skyscrapers.Skyscrapers" fileType=".xml" fileCreationDisabled="true"/> + diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java index 73efb46eb..761331b9b 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java @@ -22,7 +22,7 @@ public RippleEffect() { super(); this.name = "RippleEffect"; - // this.importer = new LightUpImporter(this); + this.importer = new RippleEffectImporter(this); // this.exporter = new LightUpExporter(this); // this.factory = new LightUpCellFactory(); diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectBoard.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectBoard.java new file mode 100644 index 000000000..0c1abbe27 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectBoard.java @@ -0,0 +1,9 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +import edu.rpi.legup.model.gameboard.GridBoard; + +public class RippleEffectBoard extends GridBoard { + public RippleEffectBoard(int width, int height) { + super(width, height); + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java index b8a4da825..20edf27f5 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java @@ -1,5 +1,10 @@ package edu.rpi.legup.puzzle.rippleeffect; -public class RippleEffectCell { - +import edu.rpi.legup.model.gameboard.GridCell; +import java.awt.Point; + +public class RippleEffectCell extends GridCell { + public RippleEffectCell(RippleEffectCellType type, Point location) { + super(type, location); + } } diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellType.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellType.java new file mode 100644 index 000000000..2442b898e --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellType.java @@ -0,0 +1,10 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +public enum RippleEffectCellType { + EMPTY(0), FILLED(1); + public int value; + + RippleEffectCellType(int value) { + this.value = value; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java index 7b3b25bac..bff0765e3 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java @@ -5,13 +5,13 @@ import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import java.awt.Point; public class RippleEffectImporter extends PuzzleImporter { public RippleEffectImporter(RippleEffect rippleEffect) { super(rippleEffect); } - /** * Puzzle setting to support row and column inputs */ @@ -36,7 +36,19 @@ public boolean acceptsTextInput() { */ @Override public void initializeBoard(int rows, int columns) { - // Womp + RippleEffectBoard rippleEffectBoard = new RippleEffectBoard(rows, columns); + for (int y = 0; y < rows; y++) { + for (int x = 0; x < columns; x++) { + // new ripple effect cell + if (rippleEffectBoard.getCell(x, y) == null) { + RippleEffectCell cell = new RippleEffectCell(RippleEffectCellType.EMPTY, new Point(x, y)); + cell.setIndex(y * columns + x); + cell.setModifiable(true); + rippleEffectBoard.setCell(x, y, cell); + } + } + } + puzzle.setCurrentBoard(rippleEffectBoard); } diff --git a/src/main/resources/edu/rpi/legup/legup/config b/src/main/resources/edu/rpi/legup/legup/config index 19e63a2a3..4428411c2 100644 --- a/src/main/resources/edu/rpi/legup/legup/config +++ b/src/main/resources/edu/rpi/legup/legup/config @@ -39,5 +39,9 @@ qualifiedClassName="edu.rpi.legup.puzzle.skyscrapers.Skyscrapers" fileType=".xml" fileCreationDisabled="true"/> + From 4f5e1c2dfe7ca278650acce276d801cdf26cf65c Mon Sep 17 00:00:00 2001 From: Chase-Grajeda Date: Fri, 16 Feb 2024 16:31:26 -0500 Subject: [PATCH 08/10] Create RippleEffectExporter.java Added RippleEffect Exporter template. At this time it should not be used for file IO activities. --- .../rippleeffect/RippleEffectExporter.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectExporter.java diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectExporter.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectExporter.java new file mode 100644 index 000000000..47effd6c2 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectExporter.java @@ -0,0 +1,39 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +import edu.rpi.legup.model.PuzzleExporter; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import org.w3c.dom.Document; + +public class RippleEffectExporter extends PuzzleExporter { + + public RippleEffectExporter(RippleEffect rippleEffect) { + super(rippleEffect); + } + + @Override + protected org.w3c.dom.Element createBoardElement(Document newDocument) { + RippleEffectBoard board; + if (puzzle.getTree() != null) { + board = (RippleEffectBoard) puzzle.getTree().getRootNode().getBoard(); + } + else { + board = (RippleEffectBoard) puzzle.getBoardView().getBoard(); + } + + org.w3c.dom.Element boardElement = newDocument.createElement("board"); + boardElement.setAttribute("width", String.valueOf(board.getWidth())); + boardElement.setAttribute("height", String.valueOf(board.getHeight())); + + org.w3c.dom.Element cellsElement = newDocument.createElement("cells"); + for (PuzzleElement puzzleElement : board.getPuzzleElements()) { + RippleEffectCell cell = (RippleEffectCell) puzzleElement; + // if (cell.getData() != -2) { + // org.w3c.dom.Element cellElement = puzzle.getFactory().exportCell(newDocument, puzzleElement); + // cellsElement.appendChild(cellElement); + // } + } + + boardElement.appendChild(cellsElement); + return boardElement; + } +} From 2f0436c16b3fb51705de4d6c10dedcbf571f2551 Mon Sep 17 00:00:00 2001 From: pitbull51067 Date: Fri, 1 Mar 2024 20:45:17 -0500 Subject: [PATCH 09/10] Successfully imported an xml file with regions and cells that only consist of numbers. I have put no functions to change anything in the board after initialized. Each region has a different color with a max of 5 colors (5 regions) right now. --- puzzles files/rippleeffect/RippleEffect1 | 29 ++++++++ .../puzzle/rippleeffect/RippleEffect.java | 51 ++++---------- .../rippleeffect/RippleEffectBoard.java | 2 +- .../puzzle/rippleeffect/RippleEffectCell.java | 30 +++++++- .../RippleEffectCellController.java | 15 ++++ .../rippleeffect/RippleEffectCellType.java | 5 +- .../rippleeffect/RippleEffectElementView.java | 68 +++++++++++++++++++ .../rippleeffect/RippleEffectImporter.java | 58 ++++++++++++---- .../rippleeffect/RippleEffectRegion.java | 19 ++++++ .../puzzle/rippleeffect/RippleEffectView.java | 26 ++++++- 10 files changed, 244 insertions(+), 59 deletions(-) create mode 100644 puzzles files/rippleeffect/RippleEffect1 create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellController.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectElementView.java create mode 100644 src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectRegion.java diff --git a/puzzles files/rippleeffect/RippleEffect1 b/puzzles files/rippleeffect/RippleEffect1 new file mode 100644 index 000000000..d14c791a4 --- /dev/null +++ b/puzzles files/rippleeffect/RippleEffect1 @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java index 761331b9b..c4c3d99a8 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffect.java @@ -4,16 +4,8 @@ import edu.rpi.legup.model.RegisterPuzzle; import edu.rpi.legup.model.gameboard.Board; import edu.rpi.legup.model.gameboard.PuzzleElement; -import edu.rpi.legup.model.rules.ContradictionRule; - - -/** - * 1) Number is duplicated in a row or a column, the space between the duplicated numbers must be equal to or larger than the value of the number. - * 2) Each Room contains consecutive numbers starting from 1. - * 3) If a number is duplicated in a row or a column, the space between the duplicated numbers must be equal to or larger than the value of the number. - */ - - +import edu.rpi.legup.puzzle.lightup.LightUpBoard; +import edu.rpi.legup.puzzle.lightup.LightUpView; @RegisterPuzzle public class RippleEffect extends Puzzle { @@ -23,9 +15,8 @@ public RippleEffect() { this.name = "RippleEffect"; this.importer = new RippleEffectImporter(this); - // this.exporter = new LightUpExporter(this); - - // this.factory = new LightUpCellFactory(); + // Uncomment the following line if you have a RippleEffectExporter + // this.exporter = new RippleEffectExporter(this); } /** @@ -33,29 +24,29 @@ public RippleEffect() { */ @Override public void initializeView() { - // boardView = new LightUpView((LightUpBoard) currentBoard); - // boardView.setBoard(currentBoard); - // addBoardListener(boardView); + boardView = new RippleEffectView((RippleEffectBoard) currentBoard); + addBoardListener(boardView); } /** - * Generates a random edu.rpi.legup.puzzle based on the difficulty + * Generates a random puzzle based on the difficulty * * @param difficulty level of difficulty (1-10) - * @return board of the random edu.rpi.legup.puzzle + * @return board of the random puzzle */ @Override public Board generatePuzzle(int difficulty) { + // Implement if needed return null; } @Override /** - * Determines if the given dimensions are valid for Light Up + * Determines if the given dimensions are valid for RippleEffect * * @param rows the number of rows * @param columns the number of columns - * @return true if the given dimensions are valid for Light Up, false otherwise + * @return true if the given dimensions are valid for RippleEffect, false otherwise */ public boolean isValidDimensions(int rows, int columns) { return rows > 0 && columns > 0; @@ -69,21 +60,7 @@ public boolean isValidDimensions(int rows, int columns) { */ @Override public boolean isBoardComplete(Board board) { - // LightUpBoard lightUpBoard = (LightUpBoard) board; - // lightUpBoard.fillWithLight(); - - // for (ContradictionRule rule : contradictionRules) { - // if (rule.checkContradiction(lightUpBoard) == null) { - // System.out.println(rule.getRuleName()); - // return false; - // } - // } - // for (PuzzleElement data : lightUpBoard.getPuzzleElements()) { - // LightUpCell cell = (LightUpCell) data; - // if ((cell.getType() == LightUpCellType.UNKNOWN || cell.getType() == LightUpCellType.EMPTY) && !cell.isLite()) { - // return false; - // } - // } + // Implement if needed return true; } @@ -94,6 +71,6 @@ public boolean isBoardComplete(Board board) { */ @Override public void onBoardChange(Board board) { - + // Implement if needed } -} +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectBoard.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectBoard.java index 0c1abbe27..f1822c72d 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectBoard.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectBoard.java @@ -6,4 +6,4 @@ public class RippleEffectBoard extends GridBoard { public RippleEffectBoard(int width, int height) { super(width, height); } -} +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java index 20edf27f5..eb56368c0 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCell.java @@ -3,8 +3,32 @@ import edu.rpi.legup.model.gameboard.GridCell; import java.awt.Point; -public class RippleEffectCell extends GridCell { - public RippleEffectCell(RippleEffectCellType type, Point location) { +public class RippleEffectCell extends GridCell { + private int number; + + public RippleEffectCell(int type, Point location, int number) { super(type, location); + this.number = number; + } + + public RippleEffectCellType getType() { + switch (getData()) { + case 1: + return RippleEffectCellType.WHITE; + case 2: + return RippleEffectCellType.BLUE; + case 3: + return RippleEffectCellType.RED; + case 4: + return RippleEffectCellType.YELLOW; + case 5: + return RippleEffectCellType.GREEN; + default: + return null; + } + } + + public int getNumber(){ + return number; } -} +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellController.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellController.java new file mode 100644 index 000000000..b1b87da8e --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellController.java @@ -0,0 +1,15 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +import edu.rpi.legup.controller.ElementController; +import edu.rpi.legup.model.gameboard.PuzzleElement; + +import java.awt.event.MouseEvent; + +public class RippleEffectCellController extends ElementController { + + @Override + public void changeCell(MouseEvent e, PuzzleElement data) { + // Since we don't need to change any cell data in Ripple Effect, + // we leave this method empty. + } +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellType.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellType.java index 2442b898e..9be4b3582 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellType.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectCellType.java @@ -1,9 +1,10 @@ package edu.rpi.legup.puzzle.rippleeffect; public enum RippleEffectCellType { - EMPTY(0), FILLED(1); + WHITE(1), BLUE(2), RED(3), YELLOW(4), GREEN(5); + public int value; - + RippleEffectCellType(int value) { this.value = value; } diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectElementView.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectElementView.java new file mode 100644 index 000000000..df528e9e8 --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectElementView.java @@ -0,0 +1,68 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.ui.boardview.GridElementView; + +import java.awt.*; + +public class RippleEffectElementView extends GridElementView { + + public RippleEffectElementView(RippleEffectCell cell) { + super(cell); + } + + /** + * Gets the PuzzleElement associated with this view + * + * @return PuzzleElement associated with this view + */ + @Override + public RippleEffectCell getPuzzleElement() { + return (RippleEffectCell) super.getPuzzleElement(); + } + + @Override + public void drawElement(Graphics2D graphics2D) { + RippleEffectCell cell = getPuzzleElement(); + RippleEffectCellType type = cell.getType(); + + // Draw the cell based on its type + switch (type) { + case WHITE: + graphics2D.setColor(Color.WHITE); + break; + case BLUE: + graphics2D.setColor(Color.BLUE); + break; + case RED: + graphics2D.setColor(Color.RED); + break; + case YELLOW: + graphics2D.setColor(Color.YELLOW); + break; + case GREEN: + graphics2D.setColor(Color.GREEN); + break; + default: + // For BLACK and any other type + graphics2D.setColor(Color.BLACK); + break; + } + + // Fill the cell with the color + graphics2D.fillRect(location.x, location.y, size.width, size.height); + + // Draw a black border + graphics2D.setColor(Color.BLACK); + graphics2D.drawRect(location.x, location.y, size.width, size.height); + + // Draw the number inside the cell + graphics2D.setColor(Color.BLACK); + graphics2D.setFont(new Font("Arial", Font.BOLD, 14)); + String data = String.valueOf(cell.getNumber()); + FontMetrics metrics = graphics2D.getFontMetrics(); + int x = location.x + (size.width - metrics.stringWidth(data)) / 2; + int y = location.y + ((size.height - metrics.getHeight()) / 2) + metrics.getAscent(); + graphics2D.drawString(data, x, y); + } +} \ No newline at end of file diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java index bff0765e3..2dfea3713 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectImporter.java @@ -6,12 +6,17 @@ import org.w3c.dom.Node; import org.w3c.dom.NodeList; import java.awt.Point; - +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class RippleEffectImporter extends PuzzleImporter { public RippleEffectImporter(RippleEffect rippleEffect) { super(rippleEffect); } + private Map regionsMap; + /** * Puzzle setting to support row and column inputs */ @@ -37,17 +42,6 @@ public boolean acceptsTextInput() { @Override public void initializeBoard(int rows, int columns) { RippleEffectBoard rippleEffectBoard = new RippleEffectBoard(rows, columns); - for (int y = 0; y < rows; y++) { - for (int x = 0; x < columns; x++) { - // new ripple effect cell - if (rippleEffectBoard.getCell(x, y) == null) { - RippleEffectCell cell = new RippleEffectCell(RippleEffectCellType.EMPTY, new Point(x, y)); - cell.setIndex(y * columns + x); - cell.setModifiable(true); - rippleEffectBoard.setCell(x, y, cell); - } - } - } puzzle.setCurrentBoard(rippleEffectBoard); } @@ -60,7 +54,45 @@ public void initializeBoard(int rows, int columns) { */ @Override public void initializeBoard(Node node) throws InvalidFileFormatException { - if (node == null) throw new InvalidFileFormatException("Invalid format"); + Element puzzleElement = (Element) node; + + NodeList regionNodes = puzzleElement.getElementsByTagName("region"); + if (regionNodes.getLength() == 0) { + throw new InvalidFileFormatException("No regions found for the RippleEffect puzzle"); + } + + int width = Integer.parseInt(puzzleElement.getAttribute("width")); + int height = Integer.parseInt(puzzleElement.getAttribute("height")); + + RippleEffectBoard rippleEffectBoard = new RippleEffectBoard(width, height); // Initialize the board with width and height from XML + int cellType = 1; // Start with cell type 1 + + for (int i = 0; i < regionNodes.getLength(); i++) { + Element regionElement = (Element) regionNodes.item(i); + NodeList cellNodes = regionElement.getElementsByTagName("cell"); + + for (int j = 0; j < cellNodes.getLength(); j++) { + Element cellElement = (Element) cellNodes.item(j); + int x = Integer.parseInt(cellElement.getAttribute("x")); + int y = Integer.parseInt(cellElement.getAttribute("y")); + int value = Integer.parseInt(cellElement.getAttribute("value")); + + Point cellPoint = new Point(x, y); + + // Create the RippleEffectCell with the cell type and value + RippleEffectCell cell = new RippleEffectCell(cellType, cellPoint, value); + cell.setIndex(y * width + x); // Calculate the index based on width and height + cell.setModifiable(true); + + // Add the cell to the board + rippleEffectBoard.setCell(x, y, cell); + } + + // Increment cell type for the next region + cellType++; + } + + puzzle.setCurrentBoard(rippleEffectBoard); } diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectRegion.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectRegion.java new file mode 100644 index 000000000..80b534a2d --- /dev/null +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectRegion.java @@ -0,0 +1,19 @@ +package edu.rpi.legup.puzzle.rippleeffect; + +import java.awt.Color; + +public class RippleEffectRegion { + private char color; + + public RippleEffectRegion(char color) { + this.color = color; + } + + public char getColor() { + return color; + } + + public void setColor(char color) { + this.color = color; + } +} diff --git a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectView.java b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectView.java index 46647299f..09699a244 100644 --- a/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectView.java +++ b/src/main/java/edu/rpi/legup/puzzle/rippleeffect/RippleEffectView.java @@ -1,5 +1,25 @@ package edu.rpi.legup.puzzle.rippleeffect; -public class RippleEffectView { - -} +import edu.rpi.legup.controller.BoardController; +import edu.rpi.legup.model.gameboard.PuzzleElement; +import edu.rpi.legup.puzzle.lightup.LightUpCellController; +import edu.rpi.legup.ui.boardview.GridBoardView; + +import java.awt.*; + +public class RippleEffectView extends GridBoardView { + + public RippleEffectView(RippleEffectBoard board) { + super(new BoardController(), new RippleEffectCellController(), board.getDimension()); + + for (PuzzleElement puzzleElement : board.getPuzzleElements()) { + RippleEffectCell cell = (RippleEffectCell) puzzleElement; + Point loc = cell.getLocation(); + RippleEffectElementView elementView = new RippleEffectElementView(cell); + elementView.setIndex(cell.getIndex()); + elementView.setSize(elementSize); + elementView.setLocation(new Point(loc.x * elementSize.width, loc.y * elementSize.height)); + elementViews.add(elementView); + } + } +} \ No newline at end of file From 4081156c9e525817f5acaa70d798c067bc55b011 Mon Sep 17 00:00:00 2001 From: pitbull51067 Date: Fri, 1 Mar 2024 20:46:31 -0500 Subject: [PATCH 10/10] Also created a file for testing. --- puzzles files/rippleeffect/RippleEffect1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/puzzles files/rippleeffect/RippleEffect1 b/puzzles files/rippleeffect/RippleEffect1 index d14c791a4..66f22404c 100644 --- a/puzzles files/rippleeffect/RippleEffect1 +++ b/puzzles files/rippleeffect/RippleEffect1 @@ -6,11 +6,11 @@ - +