diff --git a/.gitignore b/.gitignore
index a09e801d8..baee37e51 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,38 +2,9 @@
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
-# User-specific stuff
-.idea/**/workspace.xml
-.idea/**/tasks.xml
-.idea/**/usage.statistics.xml
-.idea/**/dictionaries
-.idea/**/shelf
-
-# AWS User-specific
-.idea/**/aws.xml
-
-# Generated files
-.idea/**/contentModel.xml
-
-# Sensitive or high-churn files
-.idea/**/dataSources/
-.idea/**/dataSources.ids
-.idea/**/dataSources.local.xml
-.idea/**/sqlDataSources.xml
-.idea/**/dynamic.xml
-.idea/**/uiDesigner.xml
-.idea/**/dbnavigator.xml
-
-# Gradle
-.idea/**/gradle.xml
-.idea/**/libraries
-
# CMake
cmake-build-*/
-# Mongo Explorer plugin
-.idea/**/mongoSettings.xml
-
# File-based project format
*.iws
@@ -52,32 +23,19 @@ native/windows/bin/*
# JIRA plugin
atlassian-ide-plugin.xml
-# Cursive Clojure plugin
-.idea/replstate.xml
-
-# SonarLint plugin
-.idea/sonarlint/
-
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
-# Editor-based Rest Client
-.idea/httpRequests
-
-# Android studio 3.1+ serialized cache file
-.idea/caches/build_file_checksums.ser
-
### Intellij+all Patch ###
# Ignore everything but code style settings and run configurations
# that are supposed to be shared within teams.
-.idea/*
-
-!.idea/codeStyles
-!.idea/runConfigurations
+**/.idea
+!.idea/codeStyles/*
+!.idea/runConfigurations/*
### Java ###
# Compiled class file
@@ -132,3 +90,6 @@ gradle-app.setting
**/.DS_Store
gradle/wrapper/gradle-wrapper.properties
+
+# Visual Studio Code configs
+.vscode/*
\ No newline at end of file
diff --git a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml b/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml
deleted file mode 100644
index 105ea7e2b..000000000
--- a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
diff --git a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml b/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml
deleted file mode 100644
index 63d411340..000000000
--- a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
- %date [%thread] %-5level %logger{35} - %msg%n
-
-
- OFF
-
-
-
-
- ${org.eclipse.m2e.log.dir}/0.log
-
- ${org.eclipse.m2e.log.dir}/%i.log
- 1
- 10
-
-
- 100MB
-
-
- %date [%thread] %-5level %logger{35} - %msg%n
-
-
-
-
-
- WARN
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml b/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
deleted file mode 100644
index c00d6ca9e..000000000
--- a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
diff --git a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml b/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml
deleted file mode 100644
index 541da6a75..000000000
--- a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
diff --git a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml b/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
deleted file mode 100644
index 01f7412af..000000000
--- a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
diff --git a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml b/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
deleted file mode 100644
index ef53d8bf2..000000000
--- a/bin/main/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml b/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml
deleted file mode 100644
index 0bf6a8c76..000000000
--- a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
diff --git a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml b/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml
deleted file mode 100644
index 63d411340..000000000
--- a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
- %date [%thread] %-5level %logger{35} - %msg%n
-
-
- OFF
-
-
-
-
- ${org.eclipse.m2e.log.dir}/0.log
-
- ${org.eclipse.m2e.log.dir}/%i.log
- 1
- 10
-
-
- 100MB
-
-
- %date [%thread] %-5level %logger{35} - %msg%n
-
-
-
-
-
- WARN
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml b/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
deleted file mode 100644
index c00d6ca9e..000000000
--- a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
diff --git a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml b/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
deleted file mode 100644
index d2ff1eed0..000000000
--- a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
diff --git a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml b/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
deleted file mode 100644
index 5e61d80ea..000000000
--- a/bin/main/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/bin/main/edu/rpi/legup/legup/config b/bin/main/edu/rpi/legup/legup/config
index cfa1ebeac..8e3b4b84c 100644
--- a/bin/main/edu/rpi/legup/legup/config
+++ b/bin/main/edu/rpi/legup/legup/config
@@ -15,7 +15,7 @@
+ fileCreationDisabled="true"/>
+ fileCreationDisabled="true"/>
+
diff --git a/puzzles files/lightup/10x10 Easy/1514228 b/puzzles files/lightup/10x10 Easy/1514228
index 4eb263016..b60ba98df 100644
--- a/puzzles files/lightup/10x10 Easy/1514228
+++ b/puzzles files/lightup/10x10 Easy/1514228
@@ -30,4 +30,5 @@
+
diff --git a/puzzles files/lightup/10x10 Easy/1721067 b/puzzles files/lightup/10x10 Easy/1721067
index a4b113ddb..07665470d 100644
--- a/puzzles files/lightup/10x10 Easy/1721067
+++ b/puzzles files/lightup/10x10 Easy/1721067
@@ -30,4 +30,5 @@
+
diff --git a/puzzles files/lightup/10x10 Easy/5403393 b/puzzles files/lightup/10x10 Easy/5403393
index 7b316c678..75b55ed99 100644
--- a/puzzles files/lightup/10x10 Easy/5403393
+++ b/puzzles files/lightup/10x10 Easy/5403393
@@ -26,4 +26,5 @@
+
diff --git a/puzzles files/lightup/10x10 Easy/5774519 b/puzzles files/lightup/10x10 Easy/5774519
index 591d6366a..fdcf54e2f 100644
--- a/puzzles files/lightup/10x10 Easy/5774519
+++ b/puzzles files/lightup/10x10 Easy/5774519
@@ -26,4 +26,5 @@
+
diff --git a/puzzles files/lightup/10x10 Easy/954498 b/puzzles files/lightup/10x10 Easy/954498
index ef4680cb4..852899d94 100644
--- a/puzzles files/lightup/10x10 Easy/954498
+++ b/puzzles files/lightup/10x10 Easy/954498
@@ -26,4 +26,5 @@
+
diff --git a/puzzles files/lightup/10x10 Hard/5373598 b/puzzles files/lightup/10x10 Hard/5373598
index 67e0bbdb9..b7cc9791d 100644
--- a/puzzles files/lightup/10x10 Hard/5373598
+++ b/puzzles files/lightup/10x10 Hard/5373598
@@ -26,4 +26,5 @@
+
diff --git a/puzzles files/lightup/10x10 Hard/573404 b/puzzles files/lightup/10x10 Hard/573404
index 12d4ce960..6e4f67a61 100644
--- a/puzzles files/lightup/10x10 Hard/573404
+++ b/puzzles files/lightup/10x10 Hard/573404
@@ -26,4 +26,5 @@
+
diff --git a/puzzles files/lightup/10x10 Hard/5787104 b/puzzles files/lightup/10x10 Hard/5787104
index 03ef1fe87..59a6f95db 100644
--- a/puzzles files/lightup/10x10 Hard/5787104
+++ b/puzzles files/lightup/10x10 Hard/5787104
@@ -30,4 +30,5 @@
+
diff --git a/puzzles files/lightup/10x10 Hard/8003166 b/puzzles files/lightup/10x10 Hard/8003166
index fe4cb461b..3ea9496d9 100644
--- a/puzzles files/lightup/10x10 Hard/8003166
+++ b/puzzles files/lightup/10x10 Hard/8003166
@@ -26,4 +26,5 @@
+
diff --git a/puzzles files/lightup/10x10 Hard/8918995 b/puzzles files/lightup/10x10 Hard/8918995
index 22c95573a..f89fcce5d 100644
--- a/puzzles files/lightup/10x10 Hard/8918995
+++ b/puzzles files/lightup/10x10 Hard/8918995
@@ -34,4 +34,5 @@
+
diff --git a/puzzles files/lightup/10x10 Normal/2761230 b/puzzles files/lightup/10x10 Normal/2761230
index c2f5dee6f..32a8e2b7b 100644
--- a/puzzles files/lightup/10x10 Normal/2761230
+++ b/puzzles files/lightup/10x10 Normal/2761230
@@ -30,4 +30,5 @@
+
diff --git a/puzzles files/lightup/10x10 Normal/343176 b/puzzles files/lightup/10x10 Normal/343176
index 2a6160327..7b34df834 100644
--- a/puzzles files/lightup/10x10 Normal/343176
+++ b/puzzles files/lightup/10x10 Normal/343176
@@ -30,4 +30,5 @@
+
diff --git a/puzzles files/lightup/10x10 Normal/632466 b/puzzles files/lightup/10x10 Normal/632466
index f8a6c6d99..7501eb7ef 100644
--- a/puzzles files/lightup/10x10 Normal/632466
+++ b/puzzles files/lightup/10x10 Normal/632466
@@ -26,4 +26,5 @@
+
diff --git a/puzzles files/lightup/10x10 Normal/7752941 b/puzzles files/lightup/10x10 Normal/7752941
index 52397a6b2..100de78cd 100644
--- a/puzzles files/lightup/10x10 Normal/7752941
+++ b/puzzles files/lightup/10x10 Normal/7752941
@@ -26,4 +26,5 @@
+
diff --git a/puzzles files/lightup/10x10 Normal/8090631 b/puzzles files/lightup/10x10 Normal/8090631
index f481414c9..f0ea906e9 100644
--- a/puzzles files/lightup/10x10 Normal/8090631
+++ b/puzzles files/lightup/10x10 Normal/8090631
@@ -30,4 +30,5 @@
+
diff --git a/puzzles files/lightup/14x14 Easy/1412335 b/puzzles files/lightup/14x14 Easy/1412335
index 5959d9bb6..29863daae 100644
--- a/puzzles files/lightup/14x14 Easy/1412335
+++ b/puzzles files/lightup/14x14 Easy/1412335
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Easy/1949915 b/puzzles files/lightup/14x14 Easy/1949915
index 3742cdba8..f11c997f5 100644
--- a/puzzles files/lightup/14x14 Easy/1949915
+++ b/puzzles files/lightup/14x14 Easy/1949915
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Easy/6778348 b/puzzles files/lightup/14x14 Easy/6778348
index 074f1d836..a2025b627 100644
--- a/puzzles files/lightup/14x14 Easy/6778348
+++ b/puzzles files/lightup/14x14 Easy/6778348
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Easy/976495 b/puzzles files/lightup/14x14 Easy/976495
index 7321a5b87..4abc0813a 100644
--- a/puzzles files/lightup/14x14 Easy/976495
+++ b/puzzles files/lightup/14x14 Easy/976495
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Easy/9949966 b/puzzles files/lightup/14x14 Easy/9949966
index 8ae7d5abe..9a363631c 100644
--- a/puzzles files/lightup/14x14 Easy/9949966
+++ b/puzzles files/lightup/14x14 Easy/9949966
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/lightup/14x14 Hard/1974912 b/puzzles files/lightup/14x14 Hard/1974912
index 3ac9c44a6..9174bbd50 100644
--- a/puzzles files/lightup/14x14 Hard/1974912
+++ b/puzzles files/lightup/14x14 Hard/1974912
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Hard/3618696 b/puzzles files/lightup/14x14 Hard/3618696
index 91f02e1ba..5e555d8ec 100644
--- a/puzzles files/lightup/14x14 Hard/3618696
+++ b/puzzles files/lightup/14x14 Hard/3618696
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Hard/578987 b/puzzles files/lightup/14x14 Hard/578987
index 3ccfaa1e7..281effef3 100644
--- a/puzzles files/lightup/14x14 Hard/578987
+++ b/puzzles files/lightup/14x14 Hard/578987
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Hard/8087653 b/puzzles files/lightup/14x14 Hard/8087653
index 1f7c77e99..dfd8f161c 100644
--- a/puzzles files/lightup/14x14 Hard/8087653
+++ b/puzzles files/lightup/14x14 Hard/8087653
@@ -62,4 +62,5 @@
+
diff --git a/puzzles files/lightup/14x14 Hard/9554192 b/puzzles files/lightup/14x14 Hard/9554192
index 120adddb2..c0ef178d7 100644
--- a/puzzles files/lightup/14x14 Hard/9554192
+++ b/puzzles files/lightup/14x14 Hard/9554192
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Normal/2659779 b/puzzles files/lightup/14x14 Normal/2659779
index d367b6c65..e54876bfa 100644
--- a/puzzles files/lightup/14x14 Normal/2659779
+++ b/puzzles files/lightup/14x14 Normal/2659779
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Normal/448333 b/puzzles files/lightup/14x14 Normal/448333
index b93938bfe..3a1a2b999 100644
--- a/puzzles files/lightup/14x14 Normal/448333
+++ b/puzzles files/lightup/14x14 Normal/448333
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Normal/5063453 b/puzzles files/lightup/14x14 Normal/5063453
index e3cc8578c..579622ab9 100644
--- a/puzzles files/lightup/14x14 Normal/5063453
+++ b/puzzles files/lightup/14x14 Normal/5063453
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/lightup/14x14 Normal/606275 b/puzzles files/lightup/14x14 Normal/606275
index 0b5bb6590..377747988 100644
--- a/puzzles files/lightup/14x14 Normal/606275
+++ b/puzzles files/lightup/14x14 Normal/606275
@@ -54,4 +54,5 @@
+
diff --git a/puzzles files/lightup/14x14 Normal/830231 b/puzzles files/lightup/14x14 Normal/830231
index 118c41d24..cfc8fbf43 100644
--- a/puzzles files/lightup/14x14 Normal/830231
+++ b/puzzles files/lightup/14x14 Normal/830231
@@ -61,4 +61,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/2408448 b/puzzles files/lightup/7x7 Easy/2408448
index b8fe2d7fe..de29dc419 100644
--- a/puzzles files/lightup/7x7 Easy/2408448
+++ b/puzzles files/lightup/7x7 Easy/2408448
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/2736784 b/puzzles files/lightup/7x7 Easy/2736784
index 1160ced8b..a5041796e 100644
--- a/puzzles files/lightup/7x7 Easy/2736784
+++ b/puzzles files/lightup/7x7 Easy/2736784
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/2855683 b/puzzles files/lightup/7x7 Easy/2855683
index 47e9cff0d..fc84f34b8 100644
--- a/puzzles files/lightup/7x7 Easy/2855683
+++ b/puzzles files/lightup/7x7 Easy/2855683
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/3535701 b/puzzles files/lightup/7x7 Easy/3535701
index 27b4be065..7a1e79aaa 100644
--- a/puzzles files/lightup/7x7 Easy/3535701
+++ b/puzzles files/lightup/7x7 Easy/3535701
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/393454 b/puzzles files/lightup/7x7 Easy/393454
index 039718e13..f10385f1c 100644
--- a/puzzles files/lightup/7x7 Easy/393454
+++ b/puzzles files/lightup/7x7 Easy/393454
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/4238934 b/puzzles files/lightup/7x7 Easy/4238934
index 58108606d..6106f8f73 100644
--- a/puzzles files/lightup/7x7 Easy/4238934
+++ b/puzzles files/lightup/7x7 Easy/4238934
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/4604288 b/puzzles files/lightup/7x7 Easy/4604288
index 0cc8d862a..c74b7a07a 100644
--- a/puzzles files/lightup/7x7 Easy/4604288
+++ b/puzzles files/lightup/7x7 Easy/4604288
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/4608986 b/puzzles files/lightup/7x7 Easy/4608986
index eb6fd1405..b80712533 100644
--- a/puzzles files/lightup/7x7 Easy/4608986
+++ b/puzzles files/lightup/7x7 Easy/4608986
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/517362 b/puzzles files/lightup/7x7 Easy/517362
index a6b7c32e7..e2242e266 100644
--- a/puzzles files/lightup/7x7 Easy/517362
+++ b/puzzles files/lightup/7x7 Easy/517362
@@ -19,4 +19,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/5229613 b/puzzles files/lightup/7x7 Easy/5229613
index f755e6a27..78fa909ac 100644
--- a/puzzles files/lightup/7x7 Easy/5229613
+++ b/puzzles files/lightup/7x7 Easy/5229613
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/5435528 b/puzzles files/lightup/7x7 Easy/5435528
index 6c5c133d1..a34ef0587 100644
--- a/puzzles files/lightup/7x7 Easy/5435528
+++ b/puzzles files/lightup/7x7 Easy/5435528
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/5488697 b/puzzles files/lightup/7x7 Easy/5488697
index 18c21eb4f..538665943 100644
--- a/puzzles files/lightup/7x7 Easy/5488697
+++ b/puzzles files/lightup/7x7 Easy/5488697
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/6110408 b/puzzles files/lightup/7x7 Easy/6110408
index 302dfb1a7..8905837d8 100644
--- a/puzzles files/lightup/7x7 Easy/6110408
+++ b/puzzles files/lightup/7x7 Easy/6110408
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/6300100 b/puzzles files/lightup/7x7 Easy/6300100
index 37855feba..4e4578de6 100644
--- a/puzzles files/lightup/7x7 Easy/6300100
+++ b/puzzles files/lightup/7x7 Easy/6300100
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/6506194 b/puzzles files/lightup/7x7 Easy/6506194
index a21e6b9ec..1feeead80 100644
--- a/puzzles files/lightup/7x7 Easy/6506194
+++ b/puzzles files/lightup/7x7 Easy/6506194
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/69495 b/puzzles files/lightup/7x7 Easy/69495
index a3b048963..71a0914c5 100644
--- a/puzzles files/lightup/7x7 Easy/69495
+++ b/puzzles files/lightup/7x7 Easy/69495
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/7936304 b/puzzles files/lightup/7x7 Easy/7936304
index bd4a81f6d..3fdc7c5f1 100644
--- a/puzzles files/lightup/7x7 Easy/7936304
+++ b/puzzles files/lightup/7x7 Easy/7936304
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/7982513 b/puzzles files/lightup/7x7 Easy/7982513
index d140be9cf..4246b04e1 100644
--- a/puzzles files/lightup/7x7 Easy/7982513
+++ b/puzzles files/lightup/7x7 Easy/7982513
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/8949430 b/puzzles files/lightup/7x7 Easy/8949430
index a4c87729f..45eb4e763 100644
--- a/puzzles files/lightup/7x7 Easy/8949430
+++ b/puzzles files/lightup/7x7 Easy/8949430
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Easy/9080685 b/puzzles files/lightup/7x7 Easy/9080685
index a5ef8e22f..d1071de3b 100644
--- a/puzzles files/lightup/7x7 Easy/9080685
+++ b/puzzles files/lightup/7x7 Easy/9080685
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/1130370 b/puzzles files/lightup/7x7 Hard/1130370
index afab8ece1..a5d6ab650 100644
--- a/puzzles files/lightup/7x7 Hard/1130370
+++ b/puzzles files/lightup/7x7 Hard/1130370
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/2790971 b/puzzles files/lightup/7x7 Hard/2790971
index 2f91d1aff..87b7dc5fc 100644
--- a/puzzles files/lightup/7x7 Hard/2790971
+++ b/puzzles files/lightup/7x7 Hard/2790971
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/3421347 b/puzzles files/lightup/7x7 Hard/3421347
index f16a9ecf1..68c6cb4fe 100644
--- a/puzzles files/lightup/7x7 Hard/3421347
+++ b/puzzles files/lightup/7x7 Hard/3421347
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/4159457 b/puzzles files/lightup/7x7 Hard/4159457
index d08b1c012..05b3a0bc5 100644
--- a/puzzles files/lightup/7x7 Hard/4159457
+++ b/puzzles files/lightup/7x7 Hard/4159457
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/4674087 b/puzzles files/lightup/7x7 Hard/4674087
index ca79fb87f..ed4dd0002 100644
--- a/puzzles files/lightup/7x7 Hard/4674087
+++ b/puzzles files/lightup/7x7 Hard/4674087
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/507817 b/puzzles files/lightup/7x7 Hard/507817
index 64a53c371..0bedc7cd5 100644
--- a/puzzles files/lightup/7x7 Hard/507817
+++ b/puzzles files/lightup/7x7 Hard/507817
@@ -19,4 +19,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/5280094 b/puzzles files/lightup/7x7 Hard/5280094
index cda81c889..36e4fe127 100644
--- a/puzzles files/lightup/7x7 Hard/5280094
+++ b/puzzles files/lightup/7x7 Hard/5280094
@@ -19,4 +19,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/5677803 b/puzzles files/lightup/7x7 Hard/5677803
index d7fee9e79..6fa56c0d9 100644
--- a/puzzles files/lightup/7x7 Hard/5677803
+++ b/puzzles files/lightup/7x7 Hard/5677803
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/6178908 b/puzzles files/lightup/7x7 Hard/6178908
index bc3febaf0..0cb8be391 100644
--- a/puzzles files/lightup/7x7 Hard/6178908
+++ b/puzzles files/lightup/7x7 Hard/6178908
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Hard/8122162 b/puzzles files/lightup/7x7 Hard/8122162
index cfd808ccf..539fb9641 100644
--- a/puzzles files/lightup/7x7 Hard/8122162
+++ b/puzzles files/lightup/7x7 Hard/8122162
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/2637310 b/puzzles files/lightup/7x7 Normal/2637310
index c1e88ea4f..8fd9d073b 100644
--- a/puzzles files/lightup/7x7 Normal/2637310
+++ b/puzzles files/lightup/7x7 Normal/2637310
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/2979943 b/puzzles files/lightup/7x7 Normal/2979943
index 7164eff19..6cf281463 100644
--- a/puzzles files/lightup/7x7 Normal/2979943
+++ b/puzzles files/lightup/7x7 Normal/2979943
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/3710905 b/puzzles files/lightup/7x7 Normal/3710905
index 9ae7304dd..235b91e00 100644
--- a/puzzles files/lightup/7x7 Normal/3710905
+++ b/puzzles files/lightup/7x7 Normal/3710905
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/3727425 b/puzzles files/lightup/7x7 Normal/3727425
index 96495d463..c06aa1903 100644
--- a/puzzles files/lightup/7x7 Normal/3727425
+++ b/puzzles files/lightup/7x7 Normal/3727425
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/3787583 b/puzzles files/lightup/7x7 Normal/3787583
index a3972a249..192fe831d 100644
--- a/puzzles files/lightup/7x7 Normal/3787583
+++ b/puzzles files/lightup/7x7 Normal/3787583
@@ -19,4 +19,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/5570754 b/puzzles files/lightup/7x7 Normal/5570754
index 5e94bc9c3..01e6224cd 100644
--- a/puzzles files/lightup/7x7 Normal/5570754
+++ b/puzzles files/lightup/7x7 Normal/5570754
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/7270504 b/puzzles files/lightup/7x7 Normal/7270504
index a5a539f40..57d3f0fa8 100644
--- a/puzzles files/lightup/7x7 Normal/7270504
+++ b/puzzles files/lightup/7x7 Normal/7270504
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/8000000 b/puzzles files/lightup/7x7 Normal/8000000
index bad645ee2..6de8dd8ba 100644
--- a/puzzles files/lightup/7x7 Normal/8000000
+++ b/puzzles files/lightup/7x7 Normal/8000000
@@ -19,4 +19,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/9489812 b/puzzles files/lightup/7x7 Normal/9489812
index e342523b8..fb5bd3113 100644
--- a/puzzles files/lightup/7x7 Normal/9489812
+++ b/puzzles files/lightup/7x7 Normal/9489812
@@ -15,4 +15,5 @@
+
diff --git a/puzzles files/lightup/7x7 Normal/9806740 b/puzzles files/lightup/7x7 Normal/9806740
index cd87ca7dc..f3493a021 100644
--- a/puzzles files/lightup/7x7 Normal/9806740
+++ b/puzzles files/lightup/7x7 Normal/9806740
@@ -19,4 +19,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Easy/6E_b0011 b/puzzles files/masyu/6x6 Masyu Easy/6E_b0011
index d88dc4abb..637567c9f 100644
--- a/puzzles files/masyu/6x6 Masyu Easy/6E_b0011
+++ b/puzzles files/masyu/6x6 Masyu Easy/6E_b0011
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Easy/6E_b0012 b/puzzles files/masyu/6x6 Masyu Easy/6E_b0012
index ea47166ce..304f51bd8 100644
--- a/puzzles files/masyu/6x6 Masyu Easy/6E_b0012
+++ b/puzzles files/masyu/6x6 Masyu Easy/6E_b0012
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Easy/6E_b0013 b/puzzles files/masyu/6x6 Masyu Easy/6E_b0013
index af7040555..4c8c5171a 100644
--- a/puzzles files/masyu/6x6 Masyu Easy/6E_b0013
+++ b/puzzles files/masyu/6x6 Masyu Easy/6E_b0013
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Easy/6E_b0014 b/puzzles files/masyu/6x6 Masyu Easy/6E_b0014
index a02ef4068..209eb2863 100644
--- a/puzzles files/masyu/6x6 Masyu Easy/6E_b0014
+++ b/puzzles files/masyu/6x6 Masyu Easy/6E_b0014
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Easy/6E_b0015 b/puzzles files/masyu/6x6 Masyu Easy/6E_b0015
index 9e66c9eb1..6ec496107 100644
--- a/puzzles files/masyu/6x6 Masyu Easy/6E_b0015
+++ b/puzzles files/masyu/6x6 Masyu Easy/6E_b0015
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Hard/6H_b0011 b/puzzles files/masyu/6x6 Masyu Hard/6H_b0011
index 4e4ddc3bc..bafaa7bdb 100644
--- a/puzzles files/masyu/6x6 Masyu Hard/6H_b0011
+++ b/puzzles files/masyu/6x6 Masyu Hard/6H_b0011
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Hard/6H_b0012 b/puzzles files/masyu/6x6 Masyu Hard/6H_b0012
index 57b5ace30..15212f451 100644
--- a/puzzles files/masyu/6x6 Masyu Hard/6H_b0012
+++ b/puzzles files/masyu/6x6 Masyu Hard/6H_b0012
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Hard/6H_b0013 b/puzzles files/masyu/6x6 Masyu Hard/6H_b0013
index ed78214e7..9c5b410bd 100644
--- a/puzzles files/masyu/6x6 Masyu Hard/6H_b0013
+++ b/puzzles files/masyu/6x6 Masyu Hard/6H_b0013
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Hard/6H_b0014 b/puzzles files/masyu/6x6 Masyu Hard/6H_b0014
index 24cd73827..c271db9a4 100644
--- a/puzzles files/masyu/6x6 Masyu Hard/6H_b0014
+++ b/puzzles files/masyu/6x6 Masyu Hard/6H_b0014
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Hard/6H_b0015 b/puzzles files/masyu/6x6 Masyu Hard/6H_b0015
index 30bb3ecf2..ae37a1e41 100644
--- a/puzzles files/masyu/6x6 Masyu Hard/6H_b0015
+++ b/puzzles files/masyu/6x6 Masyu Hard/6H_b0015
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Medium/6M_b0011 b/puzzles files/masyu/6x6 Masyu Medium/6M_b0011
index 3dcd13d61..bc378de72 100644
--- a/puzzles files/masyu/6x6 Masyu Medium/6M_b0011
+++ b/puzzles files/masyu/6x6 Masyu Medium/6M_b0011
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Medium/6M_b0012 b/puzzles files/masyu/6x6 Masyu Medium/6M_b0012
index 52a5e16ad..564245639 100644
--- a/puzzles files/masyu/6x6 Masyu Medium/6M_b0012
+++ b/puzzles files/masyu/6x6 Masyu Medium/6M_b0012
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Medium/6M_b0013 b/puzzles files/masyu/6x6 Masyu Medium/6M_b0013
index e7ccb2980..388908083 100644
--- a/puzzles files/masyu/6x6 Masyu Medium/6M_b0013
+++ b/puzzles files/masyu/6x6 Masyu Medium/6M_b0013
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Medium/6M_b0014 b/puzzles files/masyu/6x6 Masyu Medium/6M_b0014
index 3274804b3..01b2baafa 100644
--- a/puzzles files/masyu/6x6 Masyu Medium/6M_b0014
+++ b/puzzles files/masyu/6x6 Masyu Medium/6M_b0014
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/masyu/6x6 Masyu Medium/6M_b0015 b/puzzles files/masyu/6x6 Masyu Medium/6M_b0015
index a645a3936..cf246c891 100644
--- a/puzzles files/masyu/6x6 Masyu Medium/6M_b0015
+++ b/puzzles files/masyu/6x6 Masyu Medium/6M_b0015
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/narukabe_export tet b/puzzles files/narukabe_export tet
index 9a76535e0..b24ae3073 100644
--- a/puzzles files/narukabe_export tet
+++ b/puzzles files/narukabe_export tet
@@ -1,31 +1,32 @@
-
-
-
- |
- |
- |
- |
- |
-
-
-
-
-
-
- |
- |
- |
- |
- |
- |
- |
- |
-
-
-
-
-
-
+
+
+
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+
+
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+ |
+
+
+
+
+
+
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Hard/3323808 b/puzzles files/nurikabe/10x10 Nurikabe Hard/3323808
index ffdfee88f..755fb9411 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Hard/3323808
+++ b/puzzles files/nurikabe/10x10 Nurikabe Hard/3323808
@@ -17,4 +17,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Hard/7675382 b/puzzles files/nurikabe/10x10 Nurikabe Hard/7675382
index 414f9bb47..87681726a 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Hard/7675382
+++ b/puzzles files/nurikabe/10x10 Nurikabe Hard/7675382
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Hard/8264437 b/puzzles files/nurikabe/10x10 Nurikabe Hard/8264437
index e3d993ca7..92fc60999 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Hard/8264437
+++ b/puzzles files/nurikabe/10x10 Nurikabe Hard/8264437
@@ -21,4 +21,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Hard/8991218 b/puzzles files/nurikabe/10x10 Nurikabe Hard/8991218
index f707c9edb..52babddd6 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Hard/8991218
+++ b/puzzles files/nurikabe/10x10 Nurikabe Hard/8991218
@@ -19,4 +19,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Hard/9120893 b/puzzles files/nurikabe/10x10 Nurikabe Hard/9120893
index d30061ab6..c846329f9 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Hard/9120893
+++ b/puzzles files/nurikabe/10x10 Nurikabe Hard/9120893
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Normal/2852229 b/puzzles files/nurikabe/10x10 Nurikabe Normal/2852229
index 7752cc3a9..159d5d405 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Normal/2852229
+++ b/puzzles files/nurikabe/10x10 Nurikabe Normal/2852229
@@ -18,4 +18,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Normal/5759900 b/puzzles files/nurikabe/10x10 Nurikabe Normal/5759900
index 4f9eaeb45..064b04617 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Normal/5759900
+++ b/puzzles files/nurikabe/10x10 Nurikabe Normal/5759900
@@ -19,4 +19,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Normal/6274292 b/puzzles files/nurikabe/10x10 Nurikabe Normal/6274292
index ccffd35da..834e61259 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Normal/6274292
+++ b/puzzles files/nurikabe/10x10 Nurikabe Normal/6274292
@@ -22,4 +22,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Normal/8920015 b/puzzles files/nurikabe/10x10 Nurikabe Normal/8920015
index 273dc5ecc..4ac1c391a 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Normal/8920015
+++ b/puzzles files/nurikabe/10x10 Nurikabe Normal/8920015
@@ -22,4 +22,5 @@
+
diff --git a/puzzles files/nurikabe/10x10 Nurikabe Normal/9757357 b/puzzles files/nurikabe/10x10 Nurikabe Normal/9757357
index da3ab0a74..a014eb32d 100644
--- a/puzzles files/nurikabe/10x10 Nurikabe Normal/9757357
+++ b/puzzles files/nurikabe/10x10 Nurikabe Normal/9757357
@@ -17,4 +17,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Hard/1276535 b/puzzles files/nurikabe/12x12 Nurikabe Hard/1276535
index bbfa5ed1f..70fbdfe8a 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Hard/1276535
+++ b/puzzles files/nurikabe/12x12 Nurikabe Hard/1276535
@@ -22,4 +22,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Hard/4284912 b/puzzles files/nurikabe/12x12 Nurikabe Hard/4284912
index 401e68fb7..bdc358496 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Hard/4284912
+++ b/puzzles files/nurikabe/12x12 Nurikabe Hard/4284912
@@ -22,4 +22,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Hard/4459392 b/puzzles files/nurikabe/12x12 Nurikabe Hard/4459392
index a715a8bca..949683386 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Hard/4459392
+++ b/puzzles files/nurikabe/12x12 Nurikabe Hard/4459392
@@ -23,4 +23,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Hard/7738199 b/puzzles files/nurikabe/12x12 Nurikabe Hard/7738199
index bba566af4..107b1f1a8 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Hard/7738199
+++ b/puzzles files/nurikabe/12x12 Nurikabe Hard/7738199
@@ -21,4 +21,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Hard/9205907 b/puzzles files/nurikabe/12x12 Nurikabe Hard/9205907
index 3757c89c9..185f1959b 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Hard/9205907
+++ b/puzzles files/nurikabe/12x12 Nurikabe Hard/9205907
@@ -22,4 +22,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Normal/1570101 b/puzzles files/nurikabe/12x12 Nurikabe Normal/1570101
index f1eef204e..74cdcc65a 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Normal/1570101
+++ b/puzzles files/nurikabe/12x12 Nurikabe Normal/1570101
@@ -24,4 +24,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Normal/3731930 b/puzzles files/nurikabe/12x12 Nurikabe Normal/3731930
index 67114d31e..071d482de 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Normal/3731930
+++ b/puzzles files/nurikabe/12x12 Nurikabe Normal/3731930
@@ -27,4 +27,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Normal/3755957 b/puzzles files/nurikabe/12x12 Nurikabe Normal/3755957
index 04cd4c0ce..10313d422 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Normal/3755957
+++ b/puzzles files/nurikabe/12x12 Nurikabe Normal/3755957
@@ -24,4 +24,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Normal/786806 b/puzzles files/nurikabe/12x12 Nurikabe Normal/786806
index 99f2ff3a2..c0d9d97f6 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Normal/786806
+++ b/puzzles files/nurikabe/12x12 Nurikabe Normal/786806
@@ -23,4 +23,5 @@
+
diff --git a/puzzles files/nurikabe/12x12 Nurikabe Normal/9946063 b/puzzles files/nurikabe/12x12 Nurikabe Normal/9946063
index b82e4ff98..5746d1373 100644
--- a/puzzles files/nurikabe/12x12 Nurikabe Normal/9946063
+++ b/puzzles files/nurikabe/12x12 Nurikabe Normal/9946063
@@ -22,4 +22,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Hard/1125631 b/puzzles files/nurikabe/15x15 Nurikabe Hard/1125631
index 65ea67b8c..04c045ce8 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Hard/1125631
+++ b/puzzles files/nurikabe/15x15 Nurikabe Hard/1125631
@@ -40,4 +40,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Hard/5955292 b/puzzles files/nurikabe/15x15 Nurikabe Hard/5955292
index d086a352a..2dc656c36 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Hard/5955292
+++ b/puzzles files/nurikabe/15x15 Nurikabe Hard/5955292
@@ -38,4 +38,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Hard/6763936 b/puzzles files/nurikabe/15x15 Nurikabe Hard/6763936
index ba2d0a248..4be19301f 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Hard/6763936
+++ b/puzzles files/nurikabe/15x15 Nurikabe Hard/6763936
@@ -38,4 +38,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Hard/7005298 b/puzzles files/nurikabe/15x15 Nurikabe Hard/7005298
index 6270e7930..79d16ffd0 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Hard/7005298
+++ b/puzzles files/nurikabe/15x15 Nurikabe Hard/7005298
@@ -40,4 +40,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Hard/9975093 b/puzzles files/nurikabe/15x15 Nurikabe Hard/9975093
index 92b2e2212..bf7cf35ef 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Hard/9975093
+++ b/puzzles files/nurikabe/15x15 Nurikabe Hard/9975093
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Normal/141420 b/puzzles files/nurikabe/15x15 Nurikabe Normal/141420
index 9897588c8..affb5d2e9 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Normal/141420
+++ b/puzzles files/nurikabe/15x15 Nurikabe Normal/141420
@@ -46,4 +46,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Normal/4123443 b/puzzles files/nurikabe/15x15 Nurikabe Normal/4123443
index f92577c26..0acf06e84 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Normal/4123443
+++ b/puzzles files/nurikabe/15x15 Nurikabe Normal/4123443
@@ -42,4 +42,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Normal/731385 b/puzzles files/nurikabe/15x15 Nurikabe Normal/731385
index b1dfd7580..db29874c5 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Normal/731385
+++ b/puzzles files/nurikabe/15x15 Nurikabe Normal/731385
@@ -41,4 +41,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Normal/8213677 b/puzzles files/nurikabe/15x15 Nurikabe Normal/8213677
index f9b4c63b4..62c27f67d 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Normal/8213677
+++ b/puzzles files/nurikabe/15x15 Nurikabe Normal/8213677
@@ -41,4 +41,5 @@
+
diff --git a/puzzles files/nurikabe/15x15 Nurikabe Normal/8372309 b/puzzles files/nurikabe/15x15 Nurikabe Normal/8372309
index 97a6eae91..cf2728b1a 100644
--- a/puzzles files/nurikabe/15x15 Nurikabe Normal/8372309
+++ b/puzzles files/nurikabe/15x15 Nurikabe Normal/8372309
@@ -45,4 +45,5 @@
+
diff --git a/puzzles files/nurikabe/20x20 Nurikabe Normal/175081 b/puzzles files/nurikabe/20x20 Nurikabe Normal/175081
index bfd66a5be..67c0ed170 100644
--- a/puzzles files/nurikabe/20x20 Nurikabe Normal/175081
+++ b/puzzles files/nurikabe/20x20 Nurikabe Normal/175081
@@ -76,4 +76,5 @@
+
diff --git a/puzzles files/nurikabe/20x20 Nurikabe Normal/3131243 b/puzzles files/nurikabe/20x20 Nurikabe Normal/3131243
index 7f85c4b35..8b9ade2de 100644
--- a/puzzles files/nurikabe/20x20 Nurikabe Normal/3131243
+++ b/puzzles files/nurikabe/20x20 Nurikabe Normal/3131243
@@ -81,4 +81,5 @@
+
diff --git a/puzzles files/nurikabe/20x20 Nurikabe Normal/4400487 b/puzzles files/nurikabe/20x20 Nurikabe Normal/4400487
index 1c65e93f3..143d1a6c9 100644
--- a/puzzles files/nurikabe/20x20 Nurikabe Normal/4400487
+++ b/puzzles files/nurikabe/20x20 Nurikabe Normal/4400487
@@ -75,4 +75,5 @@
+
diff --git a/puzzles files/nurikabe/20x20 Nurikabe Normal/5096090 b/puzzles files/nurikabe/20x20 Nurikabe Normal/5096090
index f8ad5b129..47ec237e4 100644
--- a/puzzles files/nurikabe/20x20 Nurikabe Normal/5096090
+++ b/puzzles files/nurikabe/20x20 Nurikabe Normal/5096090
@@ -76,4 +76,5 @@
+
diff --git a/puzzles files/nurikabe/20x20 Nurikabe Normal/8595641 b/puzzles files/nurikabe/20x20 Nurikabe Normal/8595641
index 84f1c9f08..82df8e7a7 100644
--- a/puzzles files/nurikabe/20x20 Nurikabe Normal/8595641
+++ b/puzzles files/nurikabe/20x20 Nurikabe Normal/8595641
@@ -79,4 +79,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Easy/118040 b/puzzles files/nurikabe/5x5 Nurikabe Easy/118040
index fdd9c438f..29b2585e1 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Easy/118040
+++ b/puzzles files/nurikabe/5x5 Nurikabe Easy/118040
@@ -11,4 +11,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Easy/235235 b/puzzles files/nurikabe/5x5 Nurikabe Easy/235235
index 635f48456..59ca2a706 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Easy/235235
+++ b/puzzles files/nurikabe/5x5 Nurikabe Easy/235235
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Hard/118040 b/puzzles files/nurikabe/5x5 Nurikabe Hard/118040
index abff61ac5..8b6c004e3 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Hard/118040
+++ b/puzzles files/nurikabe/5x5 Nurikabe Hard/118040
@@ -9,4 +9,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Hard/1726232 b/puzzles files/nurikabe/5x5 Nurikabe Hard/1726232
index f3e6785a9..a28ba98fc 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Hard/1726232
+++ b/puzzles files/nurikabe/5x5 Nurikabe Hard/1726232
@@ -9,4 +9,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Hard/2168054 b/puzzles files/nurikabe/5x5 Nurikabe Hard/2168054
index f9f4e6a5e..1ed31751c 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Hard/2168054
+++ b/puzzles files/nurikabe/5x5 Nurikabe Hard/2168054
@@ -9,4 +9,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Hard/7209030 b/puzzles files/nurikabe/5x5 Nurikabe Hard/7209030
index e179e74ad..2b1d486c4 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Hard/7209030
+++ b/puzzles files/nurikabe/5x5 Nurikabe Hard/7209030
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Hard/7897030 b/puzzles files/nurikabe/5x5 Nurikabe Hard/7897030
index b6d770487..64b4b6819 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Hard/7897030
+++ b/puzzles files/nurikabe/5x5 Nurikabe Hard/7897030
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Normal/1795638 b/puzzles files/nurikabe/5x5 Nurikabe Normal/1795638
index 509569d0b..9ae7d9480 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Normal/1795638
+++ b/puzzles files/nurikabe/5x5 Nurikabe Normal/1795638
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Normal/2663893 b/puzzles files/nurikabe/5x5 Nurikabe Normal/2663893
index 75b801777..3a2c2c411 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Normal/2663893
+++ b/puzzles files/nurikabe/5x5 Nurikabe Normal/2663893
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Normal/3282122 b/puzzles files/nurikabe/5x5 Nurikabe Normal/3282122
index 3f0c5c591..6f3316b3b 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Normal/3282122
+++ b/puzzles files/nurikabe/5x5 Nurikabe Normal/3282122
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Normal/6403086 b/puzzles files/nurikabe/5x5 Nurikabe Normal/6403086
index 1f0d68b19..c0b7a51be 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Normal/6403086
+++ b/puzzles files/nurikabe/5x5 Nurikabe Normal/6403086
@@ -12,4 +12,5 @@
+
diff --git a/puzzles files/nurikabe/5x5 Nurikabe Normal/7587733 b/puzzles files/nurikabe/5x5 Nurikabe Normal/7587733
index 26995e095..0ed10b168 100644
--- a/puzzles files/nurikabe/5x5 Nurikabe Normal/7587733
+++ b/puzzles files/nurikabe/5x5 Nurikabe Normal/7587733
@@ -11,4 +11,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Hard/4478248 b/puzzles files/nurikabe/7x7 Nurikabe Hard/4478248
index 6db0bf4fd..724c71cf0 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Hard/4478248
+++ b/puzzles files/nurikabe/7x7 Nurikabe Hard/4478248
@@ -11,4 +11,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Hard/5631322 b/puzzles files/nurikabe/7x7 Nurikabe Hard/5631322
index f8478f601..87220741e 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Hard/5631322
+++ b/puzzles files/nurikabe/7x7 Nurikabe Hard/5631322
@@ -12,4 +12,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Hard/6734769 b/puzzles files/nurikabe/7x7 Nurikabe Hard/6734769
index a85a959e4..c74abb042 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Hard/6734769
+++ b/puzzles files/nurikabe/7x7 Nurikabe Hard/6734769
@@ -12,4 +12,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Hard/8078467 b/puzzles files/nurikabe/7x7 Nurikabe Hard/8078467
index 7cb47794c..4212e5748 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Hard/8078467
+++ b/puzzles files/nurikabe/7x7 Nurikabe Hard/8078467
@@ -12,4 +12,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Hard/9225348 b/puzzles files/nurikabe/7x7 Nurikabe Hard/9225348
index 49d0def37..a34516063 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Hard/9225348
+++ b/puzzles files/nurikabe/7x7 Nurikabe Hard/9225348
@@ -11,4 +11,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Normal/42455 b/puzzles files/nurikabe/7x7 Nurikabe Normal/42455
index abc674184..9e2f4b265 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Normal/42455
+++ b/puzzles files/nurikabe/7x7 Nurikabe Normal/42455
@@ -11,4 +11,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Normal/4390561 b/puzzles files/nurikabe/7x7 Nurikabe Normal/4390561
index 7f802752b..d69bcb1f0 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Normal/4390561
+++ b/puzzles files/nurikabe/7x7 Nurikabe Normal/4390561
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Normal/4877172 b/puzzles files/nurikabe/7x7 Nurikabe Normal/4877172
index c67b48c7b..f9e72c054 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Normal/4877172
+++ b/puzzles files/nurikabe/7x7 Nurikabe Normal/4877172
@@ -14,4 +14,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Normal/7958242 b/puzzles files/nurikabe/7x7 Nurikabe Normal/7958242
index f7eaab0b1..0adc01651 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Normal/7958242
+++ b/puzzles files/nurikabe/7x7 Nurikabe Normal/7958242
@@ -12,4 +12,5 @@
+
diff --git a/puzzles files/nurikabe/7x7 Nurikabe Normal/8786625 b/puzzles files/nurikabe/7x7 Nurikabe Normal/8786625
index c6e01656a..7f7553915 100644
--- a/puzzles files/nurikabe/7x7 Nurikabe Normal/8786625
+++ b/puzzles files/nurikabe/7x7 Nurikabe Normal/8786625
@@ -12,4 +12,5 @@
+
diff --git a/puzzles files/shorttruthtable/DeMorgan.xml b/puzzles files/shorttruthtable/DeMorgan.xml
index d6acef677..70b806068 100644
--- a/puzzles files/shorttruthtable/DeMorgan.xml
+++ b/puzzles files/shorttruthtable/DeMorgan.xml
@@ -8,4 +8,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_01.xml b/puzzles files/shorttruthtable/Heuveln_01.xml
index b71e69f02..be62afcf9 100644
--- a/puzzles files/shorttruthtable/Heuveln_01.xml
+++ b/puzzles files/shorttruthtable/Heuveln_01.xml
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_02.xml b/puzzles files/shorttruthtable/Heuveln_02.xml
index 8446e568f..dde0fa162 100644
--- a/puzzles files/shorttruthtable/Heuveln_02.xml
+++ b/puzzles files/shorttruthtable/Heuveln_02.xml
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_03.xml b/puzzles files/shorttruthtable/Heuveln_03.xml
index 06259e63d..6f1fbaebc 100644
--- a/puzzles files/shorttruthtable/Heuveln_03.xml
+++ b/puzzles files/shorttruthtable/Heuveln_03.xml
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_04.xml b/puzzles files/shorttruthtable/Heuveln_04.xml
index 476115bda..fc7ad31ad 100644
--- a/puzzles files/shorttruthtable/Heuveln_04.xml
+++ b/puzzles files/shorttruthtable/Heuveln_04.xml
@@ -9,4 +9,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_04.xml_test02 b/puzzles files/shorttruthtable/Heuveln_04.xml_test02
index 917855ed3..bcfdbe2bd 100644
--- a/puzzles files/shorttruthtable/Heuveln_04.xml_test02
+++ b/puzzles files/shorttruthtable/Heuveln_04.xml_test02
@@ -1,26 +1,27 @@
-
-
-
-
-
-
- |
- |
- |
-
-
-
-
-
-
- |
- |
-
-
-
-
-
-
+
+
+
+
+
+
+ |
+ |
+ |
+
+
+
+
+
+
+ |
+ |
+
+
+
+
+
+
+
diff --git a/puzzles files/shorttruthtable/Heuveln_04_export test.xml b/puzzles files/shorttruthtable/Heuveln_04_export test.xml
index 3fd197411..5d9c3f2d1 100644
--- a/puzzles files/shorttruthtable/Heuveln_04_export test.xml
+++ b/puzzles files/shorttruthtable/Heuveln_04_export test.xml
@@ -65,4 +65,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_04_test.xml b/puzzles files/shorttruthtable/Heuveln_04_test.xml
index 97809fa02..2678f6b3a 100644
--- a/puzzles files/shorttruthtable/Heuveln_04_test.xml
+++ b/puzzles files/shorttruthtable/Heuveln_04_test.xml
@@ -23,4 +23,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_04_test01.xml b/puzzles files/shorttruthtable/Heuveln_04_test01.xml
index 967710d9d..fa5326e40 100644
--- a/puzzles files/shorttruthtable/Heuveln_04_test01.xml
+++ b/puzzles files/shorttruthtable/Heuveln_04_test01.xml
@@ -23,4 +23,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_04_test03.xml b/puzzles files/shorttruthtable/Heuveln_04_test03.xml
index 6120636f4..441b16a3a 100644
--- a/puzzles files/shorttruthtable/Heuveln_04_test03.xml
+++ b/puzzles files/shorttruthtable/Heuveln_04_test03.xml
@@ -23,4 +23,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_04_test_exprt.xml b/puzzles files/shorttruthtable/Heuveln_04_test_exprt.xml
index a46806253..60583987b 100644
--- a/puzzles files/shorttruthtable/Heuveln_04_test_exprt.xml
+++ b/puzzles files/shorttruthtable/Heuveln_04_test_exprt.xml
@@ -23,4 +23,5 @@
+
diff --git a/puzzles files/shorttruthtable/Heuveln_05.xml b/puzzles files/shorttruthtable/Heuveln_05.xml
index a93f5aec6..5ade9817e 100644
--- a/puzzles files/shorttruthtable/Heuveln_05.xml
+++ b/puzzles files/shorttruthtable/Heuveln_05.xml
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/shorttruthtable/invalid1.xml b/puzzles files/shorttruthtable/invalid1.xml
index dc0f3723d..e3be7fbb8 100644
--- a/puzzles files/shorttruthtable/invalid1.xml
+++ b/puzzles files/shorttruthtable/invalid1.xml
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/shorttruthtable/invalid2.xml b/puzzles files/shorttruthtable/invalid2.xml
index 08cacd95b..03a304db5 100644
--- a/puzzles files/shorttruthtable/invalid2.xml
+++ b/puzzles files/shorttruthtable/invalid2.xml
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/shorttruthtable/invalid3.xml b/puzzles files/shorttruthtable/invalid3.xml
index 2b352548d..e5ad96525 100644
--- a/puzzles files/shorttruthtable/invalid3.xml
+++ b/puzzles files/shorttruthtable/invalid3.xml
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/shorttruthtable/test.xml b/puzzles files/shorttruthtable/test.xml
index 78326985c..06298261c 100644
--- a/puzzles files/shorttruthtable/test.xml
+++ b/puzzles files/shorttruthtable/test.xml
@@ -10,4 +10,5 @@
+
diff --git a/puzzles files/skyscrapers/1646651 b/puzzles files/skyscrapers/1646651
index 3facc12fe..9e2536931 100644
--- a/puzzles files/skyscrapers/1646651
+++ b/puzzles files/skyscrapers/1646651
@@ -27,4 +27,5 @@
+
diff --git a/puzzles files/skyscrapers/4x4 Skyscrapers Easy1 b/puzzles files/skyscrapers/4x4 Skyscrapers Easy1
new file mode 100644
index 000000000..5b91e64ca
--- /dev/null
+++ b/puzzles files/skyscrapers/4x4 Skyscrapers Easy1
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/puzzles files/skyscrapers/easy b/puzzles files/skyscrapers/4x4 Skyscrapers Easy2
similarity index 77%
rename from puzzles files/skyscrapers/easy
rename to puzzles files/skyscrapers/4x4 Skyscrapers Easy2
index 48c255771..e30fbd89e 100644
--- a/puzzles files/skyscrapers/easy
+++ b/puzzles files/skyscrapers/4x4 Skyscrapers Easy2
@@ -1,22 +1,23 @@
-
+
-
-
+
+
+
-
-
+
+
diff --git a/puzzles files/skyscrapers/4x4 Skyscrapers Easy3 b/puzzles files/skyscrapers/4x4 Skyscrapers Easy3
new file mode 100644
index 000000000..61fa8054b
--- /dev/null
+++ b/puzzles files/skyscrapers/4x4 Skyscrapers Easy3
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/puzzles files/skyscrapers/5x5 Skyscrapers Easy1 b/puzzles files/skyscrapers/5x5 Skyscrapers Easy1
new file mode 100644
index 000000000..111d2bd87
--- /dev/null
+++ b/puzzles files/skyscrapers/5x5 Skyscrapers Easy1
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/puzzles files/skyscrapers/5x5 Skyscrapers Easy2 b/puzzles files/skyscrapers/5x5 Skyscrapers Easy2
new file mode 100644
index 000000000..45a1db188
--- /dev/null
+++ b/puzzles files/skyscrapers/5x5 Skyscrapers Easy2
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/puzzles files/skyscrapers/5x5 Skyscrapers Easy3 b/puzzles files/skyscrapers/5x5 Skyscrapers Easy3
new file mode 100644
index 000000000..87f7db3d7
--- /dev/null
+++ b/puzzles files/skyscrapers/5x5 Skyscrapers Easy3
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/puzzles files/skyscrapers/5x5 Skyscrapers Medium1 b/puzzles files/skyscrapers/5x5 Skyscrapers Medium1
new file mode 100644
index 000000000..9e79c6248
--- /dev/null
+++ b/puzzles files/skyscrapers/5x5 Skyscrapers Medium1
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/puzzles files/skyscrapers/5x5 Skyscrapers Medium2 b/puzzles files/skyscrapers/5x5 Skyscrapers Medium2
new file mode 100644
index 000000000..fab87f9f7
--- /dev/null
+++ b/puzzles files/skyscrapers/5x5 Skyscrapers Medium2
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/puzzles files/skyscrapers/5x5 Skyscrapers Medium3 b/puzzles files/skyscrapers/5x5 Skyscrapers Medium3
new file mode 100644
index 000000000..efd123165
--- /dev/null
+++ b/puzzles files/skyscrapers/5x5 Skyscrapers Medium3
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/puzzles files/skyscrapers/easy1.xml b/puzzles files/skyscrapers/easy1.xml
index 9233705e9..ce09cdf7b 100644
--- a/puzzles files/skyscrapers/easy1.xml
+++ b/puzzles files/skyscrapers/easy1.xml
@@ -34,6 +34,7 @@
+
-
-
-
-
- ${org.eclipse.m2e.log.dir}/0.log
-
- ${org.eclipse.m2e.log.dir}/%i.log
- 1
- 10
-
-
- 100MB
-
-
- %date [%thread] %-5level %logger{35} - %msg%n
-
-
-
-
-
- WARN
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup b/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup
deleted file mode 100644
index 1f73e14c1..000000000
--- a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml b/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
deleted file mode 100644
index c00d6ca9e..000000000
--- a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml b/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml
deleted file mode 100644
index 541da6a75..000000000
--- a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.intro/dialog_settings.xml
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml b/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
deleted file mode 100644
index 01f7412af..000000000
--- a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml b/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
deleted file mode 100644
index ef53d8bf2..000000000
--- a/src/main/java/edu/rpi/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/.metadata/version.ini b/src/main/java/edu/rpi/.metadata/version.ini
deleted file mode 100644
index a612e14df..000000000
--- a/src/main/java/edu/rpi/.metadata/version.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-#Wed Nov 06 12:29:47 EST 2019
-org.eclipse.core.runtime=2
-org.eclipse.platform=4.5.2.v20160212-1500
diff --git a/src/main/java/edu/rpi/legup/.metadata/.lock b/src/main/java/edu/rpi/legup/.metadata/.lock
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/main/java/edu/rpi/legup/.metadata/.mylyn/.taskListIndex/segments.gen b/src/main/java/edu/rpi/legup/.metadata/.mylyn/.taskListIndex/segments.gen
deleted file mode 100644
index 63a7ec9a3..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.mylyn/.taskListIndex/segments.gen and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.mylyn/.taskListIndex/segments_1 b/src/main/java/edu/rpi/legup/.metadata/.mylyn/.taskListIndex/segments_1
deleted file mode 100644
index adecb0619..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.mylyn/.taskListIndex/segments_1 and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version
deleted file mode 100644
index 25cb955ba..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/history.version
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index
deleted file mode 100644
index 7ea794608..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.index and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version
deleted file mode 100644
index 6b2aaa764..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/.indexes/properties.version
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/2.tree b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/2.tree
deleted file mode 100644
index 8a1fc9ec5..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.root/2.tree and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources
deleted file mode 100644
index f063e7caf..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.resources/.safetable/org.eclipse.core.resources and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs
deleted file mode 100644
index dffc6b513..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.core.resources.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-version=1
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs
deleted file mode 100644
index 1768a1e88..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs
+++ /dev/null
@@ -1,13 +0,0 @@
-content_assist_proposals_background=255,255,255
-content_assist_proposals_foreground=0,0,0
-eclipse.preferences.version=1
-fontPropagated=true
-org.eclipse.jdt.ui.editor.tab.width=
-org.eclipse.jdt.ui.formatterprofiles.version=12
-org.eclipse.jdt.ui.javadoclocations.migrated=true
-org.eclipse.jface.textfont=1|Monaco|11.0|0|COCOA|1|;
-proposalOrderMigrated=true
-spelling_locale_initialized=true
-tabWidthPropagated=true
-useAnnotationsPrefPage=true
-useQuickDiffPrefPage=true
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.m2e.discovery.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.m2e.discovery.prefs
deleted file mode 100644
index 67b1d96c9..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.m2e.discovery.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.m2e.discovery.pref.projects=
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs
deleted file mode 100644
index 43e97e405..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.context.core.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-mylyn.attention.migrated=true
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.monitor.ui.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.monitor.ui.prefs
deleted file mode 100644
index 8d462a6cf..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.monitor.ui.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-org.eclipse.mylyn.monitor.activity.tracking.enabled.checked=true
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.tasks.ui.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.tasks.ui.prefs
deleted file mode 100644
index 2b60c21d6..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.mylyn.tasks.ui.prefs
+++ /dev/null
@@ -1,5 +0,0 @@
-eclipse.preferences.version=1
-migrated.task.repositories.secure.store=true
-org.eclipse.mylyn.tasks.ui.filters.nonmatching=true
-org.eclipse.mylyn.tasks.ui.filters.nonmatching.encouraged=true
-org.eclipse.mylyn.tasks.ui.welcome.message=true
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs
deleted file mode 100644
index da2be0834..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.ide.prefs
+++ /dev/null
@@ -1,5 +0,0 @@
-PROBLEMS_FILTERS_MIGRATE=true
-eclipse.preferences.version=1
-platformState=1554955212164
-quickStart=false
-tipsAndTricks=true
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs
deleted file mode 100644
index 08076f236..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.prefs
+++ /dev/null
@@ -1,2 +0,0 @@
-eclipse.preferences.version=1
-showIntro=false
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs
deleted file mode 100644
index dd774965c..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.ui.workbench.prefs
+++ /dev/null
@@ -1,3 +0,0 @@
-//org.eclipse.ui.commands/state/org.eclipse.ui.navigator.resources.nested.changeProjectPresentation/org.eclipse.ui.commands.radioState=false
-PLUGINS_NOT_ACTIVATED_ON_STARTUP=org.eclipse.m2e.discovery;
-eclipse.preferences.version=1
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi
deleted file mode 100644
index 51f42e4ed..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.e4.workbench/workbench.xmi
+++ /dev/null
@@ -1,2308 +0,0 @@
-
-
-
- activeSchemeId:org.eclipse.ui.defaultAcceleratorConfiguration
- ModelMigrationProcessor.001
-
-
-
-
-
-
-
- topLevel
-
-
- Minimized
- MinimizedByZoom
-
-
- persp.actionSet:org.eclipse.mylyn.doc.actionSet
- persp.actionSet:org.eclipse.mylyn.tasks.ui.navigation
- persp.actionSet:org.eclipse.ui.cheatsheets.actionSet
- persp.actionSet:org.eclipse.search.searchActionSet
- persp.actionSet:org.eclipse.ui.edit.text.actionSet.annotationNavigation
- persp.actionSet:org.eclipse.ui.edit.text.actionSet.navigation
- persp.actionSet:org.eclipse.ui.edit.text.actionSet.convertLineDelimitersTo
- persp.actionSet:org.eclipse.ui.externaltools.ExternalToolsSet
- persp.actionSet:org.eclipse.ui.actionSet.keyBindings
- persp.actionSet:org.eclipse.ui.actionSet.openFiles
- persp.actionSet:org.eclipse.wb.core.ui.actionset
- persp.actionSet:org.eclipse.debug.ui.launchActionSet
- persp.actionSet:org.eclipse.jdt.ui.JavaActionSet
- persp.actionSet:org.eclipse.jdt.ui.JavaElementCreationActionSet
- persp.actionSet:org.eclipse.ui.NavigateActionSet
- persp.viewSC:org.eclipse.jdt.ui.PackageExplorer
- persp.viewSC:org.eclipse.jdt.ui.TypeHierarchy
- persp.viewSC:org.eclipse.jdt.ui.SourceView
- persp.viewSC:org.eclipse.jdt.ui.JavadocView
- persp.viewSC:org.eclipse.search.ui.views.SearchView
- persp.viewSC:org.eclipse.ui.console.ConsoleView
- persp.viewSC:org.eclipse.ui.views.ContentOutline
- persp.viewSC:org.eclipse.ui.views.ProblemView
- persp.viewSC:org.eclipse.ui.views.ResourceNavigator
- persp.viewSC:org.eclipse.ui.views.TaskList
- persp.viewSC:org.eclipse.ui.views.ProgressView
- persp.viewSC:org.eclipse.ui.navigator.ProjectExplorer
- persp.viewSC:org.eclipse.ui.texteditor.TemplatesView
- persp.viewSC:org.eclipse.pde.runtime.LogView
- persp.newWizSC:org.eclipse.jdt.ui.wizards.JavaProjectWizard
- persp.newWizSC:org.eclipse.jdt.ui.wizards.NewPackageCreationWizard
- persp.newWizSC:org.eclipse.jdt.ui.wizards.NewClassCreationWizard
- persp.newWizSC:org.eclipse.jdt.ui.wizards.NewInterfaceCreationWizard
- persp.newWizSC:org.eclipse.jdt.ui.wizards.NewEnumCreationWizard
- persp.newWizSC:org.eclipse.jdt.ui.wizards.NewAnnotationCreationWizard
- persp.newWizSC:org.eclipse.jdt.ui.wizards.NewSourceFolderCreationWizard
- persp.newWizSC:org.eclipse.jdt.ui.wizards.NewSnippetFileCreationWizard
- persp.newWizSC:org.eclipse.jdt.ui.wizards.NewJavaWorkingSetWizard
- persp.newWizSC:org.eclipse.ui.wizards.new.folder
- persp.newWizSC:org.eclipse.ui.wizards.new.file
- persp.newWizSC:org.eclipse.ui.editors.wizards.UntitledTextFileWizard
- persp.perspSC:org.eclipse.jdt.ui.JavaBrowsingPerspective
- persp.perspSC:org.eclipse.debug.ui.DebugPerspective
- persp.perspSC:com.android.ide.eclipse.ddms.Perspective
- persp.viewSC:org.eclipse.ant.ui.views.AntView
- persp.actionSet:org.eclipse.eclemma.ui.CoverageActionSet
- persp.showIn:org.eclipse.eclemma.ui.CoverageView
- persp.showIn:org.eclipse.egit.ui.RepositoriesView
- persp.actionSet:org.eclipse.debug.ui.breakpointActionSet
- persp.actionSet:org.eclipse.jdt.debug.ui.JDTDebugActionSet
- persp.newWizSC:org.eclipse.jdt.junit.wizards.NewTestCaseCreationWizard
- persp.actionSet:org.eclipse.jdt.junit.JUnitActionSet
- persp.showIn:org.eclipse.jdt.ui.PackageExplorer
- persp.showIn:org.eclipse.team.ui.GenericHistoryView
- persp.showIn:org.eclipse.ui.views.ResourceNavigator
- persp.showIn:org.eclipse.ui.navigator.ProjectExplorer
- persp.viewSC:org.eclipse.mylyn.tasks.ui.views.tasks
- persp.newWizSC:org.eclipse.mylyn.tasks.ui.wizards.new.repository.task
- persp.viewSC:org.eclipse.wb.core.StructureView
- persp.viewSC:org.eclipse.wb.core.PaletteView
-
-
-
- org.eclipse.e4.primaryNavigationStack
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- org.eclipse.e4.secondaryNavigationStack
-
-
-
-
-
-
-
- org.eclipse.e4.secondaryDataStack
-
-
-
-
-
-
-
-
-
-
-
-
-
- active
- Maximized
-
-
-
-
-
-
- View
- categoryTag:Help
-
-
-
- View
- categoryTag:General
- active
- activeOnClose
-
- ViewMenu
- menuContribution:menu
-
-
-
-
- View
- categoryTag:Help
-
-
-
- org.eclipse.e4.primaryDataStack
- EditorStack
-
-
-
-
- View
- categoryTag:Java
-
- ViewMenu
- menuContribution:menu
-
-
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
-
- View
- categoryTag:General
-
- ViewMenu
- menuContribution:menu
-
-
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
-
- View
- categoryTag:General
-
- ViewMenu
- menuContribution:menu
-
-
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:Ant
-
-
- View
- categoryTag:Git
-
-
- View
- categoryTag:Java
-
-
-
- View
- categoryTag:Mylyn
-
- ViewMenu
- menuContribution:menu
-
-
-
-
- View
- categoryTag:WindowBuilder
-
-
- View
- categoryTag:WindowBuilder
-
-
-
- toolbarSeparator
-
-
-
- Draggable
-
-
-
- toolbarSeparator
-
-
-
- Draggable
-
-
- Draggable
-
-
- Draggable
-
-
- toolbarSeparator
-
-
-
- Draggable
-
-
-
- toolbarSeparator
-
-
-
- toolbarSeparator
-
-
-
- Draggable
-
-
- stretch
- SHOW_RESTORE_MENU
-
-
- Draggable
- HIDEABLE
- SHOW_RESTORE_MENU
-
-
-
-
- stretch
-
-
- Draggable
-
-
- Draggable
-
-
-
-
-
- TrimStack
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
- platform:cocoa
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- platform:cocoa
-
-
-
- platform:cocoa
-
-
-
-
-
-
- platform:cocoa
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Editor
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Android
-
-
- View
- categoryTag:Tracer for OpenGL ES
-
-
- View
- categoryTag:Tracer for OpenGL ES
-
-
- View
- categoryTag:Tracer for OpenGL ES
-
-
- View
- categoryTag:Ant
-
-
- View
- categoryTag:Debug
-
-
- View
- categoryTag:Debug
-
-
- View
- categoryTag:Debug
-
-
- View
- categoryTag:Debug
-
-
- View
- categoryTag:Debug
-
-
- View
- categoryTag:Debug
-
-
- View
- categoryTag:Debug
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:Git
-
-
- View
- categoryTag:Git
-
-
- View
- categoryTag:Git
-
-
- View
- categoryTag:Git
-
-
- View
- categoryTag:Git
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:Help
-
-
- View
- categoryTag:Debug
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:Java Browsing
-
-
- View
- categoryTag:Java Browsing
-
-
- View
- categoryTag:Java Browsing
-
-
- View
- categoryTag:Java Browsing
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:Java
-
-
- View
- categoryTag:Maven
-
-
- View
- categoryTag:Maven
-
-
- View
- categoryTag:Mylyn
-
-
- View
- categoryTag:Mylyn
-
-
- View
- categoryTag:Mylyn
-
-
- View
- categoryTag:Mylyn
-
-
- View
- categoryTag:Oomph
-
-
- View
- categoryTag:Code Recommenders
-
-
- View
- categoryTag:Code Recommenders
-
-
- View
- categoryTag:Code Recommenders
-
-
- View
- categoryTag:Code Recommenders
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:Team
-
-
- View
- categoryTag:Team
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:Help
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:WindowBuilder
-
-
- View
- categoryTag:WindowBuilder
-
-
- View
- categoryTag:General
-
-
- View
- categoryTag:XML
-
-
- View
- categoryTag:XML
-
-
-
- glue
- move_after:PerspectiveSpacer
- SHOW_RESTORE_MENU
-
-
- move_after:Spacer Glue
- HIDEABLE
- SHOW_RESTORE_MENU
-
-
- glue
- move_after:SearchField
- SHOW_RESTORE_MENU
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fdt b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fdt
deleted file mode 100644
index d5abf41cc..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fdt and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fdx b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fdx
deleted file mode 100644
index b8ee80957..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fdx and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fnm b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fnm
deleted file mode 100644
index 523c92e25..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.fnm
+++ /dev/null
@@ -1 +0,0 @@
-ýÿÿÿversion
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.frq b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.frq
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.nrm b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.nrm
deleted file mode 100644
index cf8dc7529..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.nrm
+++ /dev/null
@@ -1 +0,0 @@
-NRMÿ
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.tii b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.tii
deleted file mode 100644
index ebd518d6e..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.tii and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.tis b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.tis
deleted file mode 100644
index ebd518d6e..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/_0.tis and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/segments.gen b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/segments.gen
deleted file mode 100644
index 63a7ec9a3..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/segments.gen and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/segments_1 b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/segments_1
deleted file mode 100644
index 4f495c834..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/history/segments_1 and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fdt b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fdt
deleted file mode 100644
index d5abf41cc..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fdt and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fdx b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fdx
deleted file mode 100644
index b8ee80957..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fdx and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fnm b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fnm
deleted file mode 100644
index 523c92e25..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.fnm
+++ /dev/null
@@ -1 +0,0 @@
-ýÿÿÿversion
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.frq b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.frq
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.nrm b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.nrm
deleted file mode 100644
index cf8dc7529..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.nrm
+++ /dev/null
@@ -1 +0,0 @@
-NRMÿ
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.tii b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.tii
deleted file mode 100644
index ebd518d6e..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.tii and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.tis b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.tis
deleted file mode 100644
index ebd518d6e..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/_0.tis and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/segments.gen b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/segments.gen
deleted file mode 100644
index 63a7ec9a3..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/segments.gen and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/segments_1 b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/segments_1
deleted file mode 100644
index 4f495c834..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.epp.logging.aeri.ui/remote-index/segments_1 and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache
deleted file mode 100644
index 593f4708d..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/assumedExternalFilesCache and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache
deleted file mode 100644
index 593f4708d..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/externalFilesCache and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache
deleted file mode 100644
index 593f4708d..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/nonChainingJarsCache and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat
deleted file mode 100644
index 0edae4b20..000000000
Binary files a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.core/variablesAndContainers.dat and /dev/null differ
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml
deleted file mode 100644
index a4ee3cbc9..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/OpenTypeHistory.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml
deleted file mode 100644
index 9e390f501..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/QualifiedTypeNameHistory.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml
deleted file mode 100644
index 0bf6a8c76..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.jdt.ui/dialog_settings.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml
deleted file mode 100644
index 63d411340..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.m2e.logback.configuration/logback.1.6.0.20150526-2032.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-
-
-
- %date [%thread] %-5level %logger{35} - %msg%n
-
-
- OFF
-
-
-
-
- ${org.eclipse.m2e.log.dir}/0.log
-
- ${org.eclipse.m2e.log.dir}/%i.log
- 1
- 10
-
-
- 100MB
-
-
- %date [%thread] %-5level %logger{35} - %msg%n
-
-
-
-
-
- WARN
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup
deleted file mode 100644
index 1f73e14c1..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.oomph.setup/workspace.setup
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
deleted file mode 100644
index c00d6ca9e..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.ide/dialog_settings.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
deleted file mode 100644
index d2ff1eed0..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/dialog_settings.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-
-
diff --git a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml b/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
deleted file mode 100644
index 5e61d80ea..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/.plugins/org.eclipse.ui.workbench/workingsets.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/.metadata/version.ini b/src/main/java/edu/rpi/legup/.metadata/version.ini
deleted file mode 100644
index 026f9536e..000000000
--- a/src/main/java/edu/rpi/legup/.metadata/version.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-#Tue Oct 29 22:17:24 EDT 2019
-org.eclipse.core.runtime=2
-org.eclipse.platform=4.5.2.v20160212-1500
diff --git a/src/main/java/edu/rpi/legup/controller/EditorElementController.java b/src/main/java/edu/rpi/legup/controller/EditorElementController.java
index 211012c9f..80e7dd35a 100644
--- a/src/main/java/edu/rpi/legup/controller/EditorElementController.java
+++ b/src/main/java/edu/rpi/legup/controller/EditorElementController.java
@@ -5,7 +5,9 @@
import edu.rpi.legup.history.*;
import edu.rpi.legup.model.Puzzle;
import edu.rpi.legup.model.elements.Element;
+import edu.rpi.legup.model.gameboard.Board;
import edu.rpi.legup.model.gameboard.CaseBoard;
+import edu.rpi.legup.model.gameboard.PuzzleElement;
import edu.rpi.legup.model.rules.*;
import edu.rpi.legup.model.tree.TreeElement;
import edu.rpi.legup.model.tree.TreeElementType;
@@ -17,6 +19,8 @@
import edu.rpi.legup.ui.puzzleeditorui.elementsview.ElementButton;
import javax.swing.*;
+import javax.swing.border.Border;
+import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;
@@ -26,10 +30,12 @@
public class EditorElementController implements ActionListener {
protected Object lastSource;
protected ElementController elementController;
+ protected ElementButton prevButton;
public EditorElementController() {
super();
elementController = null;
+ prevButton = null;
}
public void setElementController(ElementController elementController) {
@@ -38,6 +44,7 @@ public void setElementController(ElementController elementController) {
public void buttonPressed(Element element) {
// TODO: implement what happens when element is pressed
+
System.out.printf("%s button pressed!\n", element.getElementName());
if (elementController != null) {
elementController.setSelectedElement(element);
@@ -49,5 +56,16 @@ public void actionPerformed(ActionEvent e) {
lastSource = e.getSource();
ElementButton button = (ElementButton) lastSource;
buttonPressed(button.getElement());
+
+ // reset border in previous selected button
+ if (this.prevButton != null) {
+ this.prevButton.resetBorder();
+ }
+
+ // change border color when select a button
+ button.setBorderToSelected();
+
+ this.prevButton = button;
+
}
}
diff --git a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java
index ae5f62f22..f6f67c8d7 100644
--- a/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java
+++ b/src/main/java/edu/rpi/legup/history/AutoCaseRuleCommand.java
@@ -105,6 +105,10 @@ public String getErrorString() {
return "The selected data element is not pickable with this case rule.";
}
+ if(caseRule.getCases(caseBoard.getBaseBoard(), elementView.getPuzzleElement()).size() == 0){
+ return "The selection must produce at least one case";
+ }
+
return null;
}
diff --git a/src/main/java/edu/rpi/legup/model/Puzzle.java b/src/main/java/edu/rpi/legup/model/Puzzle.java
index 2a98f9d46..27eceb412 100644
--- a/src/main/java/edu/rpi/legup/model/Puzzle.java
+++ b/src/main/java/edu/rpi/legup/model/Puzzle.java
@@ -638,4 +638,13 @@ public void removeTreeListener(ITreeListener listener) {
public void notifyTreeListeners(Consumer super ITreeListener> algorithm) {
treeListeners.forEach(algorithm);
}
+
+ /**
+ * Check if the puzzle is valid
+ *
+ * @return if the puzzle is valid
+ */
+ public boolean checkValidity() {
+ return true;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUp.java b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUp.java
index 22eee239f..b0ef17b65 100644
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/LightUp.java
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/LightUp.java
@@ -11,12 +11,12 @@ public class LightUp extends Puzzle {
public LightUp() {
super();
- name = "LightUp";
+ this.name = "LightUp";
- importer = new LightUpImporter(this);
- exporter = new LightUpExporter(this);
+ this.importer = new LightUpImporter(this);
+ this.exporter = new LightUpExporter(this);
- factory = new LightUpCellFactory();
+ this.factory = new LightUpCellFactory();
}
/**
@@ -47,8 +47,7 @@ public Board generatePuzzle(int difficulty) {
* @return true if the given dimensions are valid for Light Up, false otherwise
*/
public boolean isValidDimensions(int rows, int columns) {
- // This is a placeholder, this method needs to be implemented
- throw new UnsupportedOperationException();
+ return rows > 0 && columns > 0;
}
/**
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/elements/NumberTile.java b/src/main/java/edu/rpi/legup/puzzle/lightup/elements/NumberTile.java
index 5e9c14a9d..843be71a2 100644
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/elements/NumberTile.java
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/elements/NumberTile.java
@@ -6,6 +6,11 @@ public class NumberTile extends NonPlaceableElement {
int object_number;
+ // Follow the default format and resolves the NoSuchMethod error
+ public NumberTile() {
+ super("LTUP-UNPL-0001", "Number Tile", "The number tile", "edu/rpi/legup/images/lightup/1.gif");
+ }
+
public NumberTile(int num) {
super("LTUP-UNPL-0001", "Number Tile", "The number tile", "edu/rpi/legup/images/lightup/" + num + ".gif");
if (num > 3 || num < 1) num = 1;
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/BulbsOutsideDiagonalBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/BulbsOutsideDiagonalBasicRule.java
deleted file mode 100644
index 4a5e73f47..000000000
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/BulbsOutsideDiagonalBasicRule.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package edu.rpi.legup.puzzle.lightup.rules;
-
-import edu.rpi.legup.model.gameboard.Board;
-import edu.rpi.legup.model.gameboard.PuzzleElement;
-import edu.rpi.legup.model.rules.BasicRule;
-import edu.rpi.legup.model.tree.TreeNode;
-import edu.rpi.legup.model.tree.TreeTransition;
-
-public class BulbsOutsideDiagonalBasicRule extends BasicRule {
-
- public BulbsOutsideDiagonalBasicRule() {
- super("LTUP-BASC-0001", "Bulbs Outside Diagonal",
- "Cells on the external edges of a 3 diagonal to a numerical block must be bulbs.",
- "edu/rpi/legup/images/lightup/rules/BulbsOutsideDiagonal.png");
- }
-
- /**
- * Checks whether the child node logically follows from the parent node
- * at the specific puzzleElement index using this rule
- *
- * @param transition transition to check
- * @param puzzleElement equivalent puzzleElement
- * @return null if the child node logically follow from the parent node at the specified puzzleElement,
- * otherwise error message
- */
- @Override
- public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) {
- return "This rule is not implemented yet.";
- }
-
- /**
- * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}.
- *
- * @param node tree node used to create default transition board
- * @return default board or null if this rule cannot be applied to this tree node
- */
- @Override
- public Board getDefaultBoard(TreeNode node) {
- return null;
- }
-}
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/MustLightBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/MustLightBasicRule.java
index 2830a497a..6efaadd41 100644
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/MustLightBasicRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/MustLightBasicRule.java
@@ -38,9 +38,8 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
return super.getInvalidUseOfRuleMessage() + ": Modified cells must be bulbs";
}
- finalCell.setData(LightUpCellType.EMPTY.value);
finalBoard.fillWithLight();
- boolean isForced = isForcedBulb(finalBoard, finalCell.getLocation());
+ boolean isForced = isForcedBulb(parentBoard, parentCell.getLocation());
finalCell.setData(LightUpCellType.BULB.value);
finalBoard.fillWithLight();
@@ -54,55 +53,62 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
private boolean isForcedBulb(LightUpBoard board, Point loc) {
CannotLightACellContradictionRule cannotLite = new CannotLightACellContradictionRule();
- LightUpCell cell = board.getCell(loc.x, loc.y);
- if ((cell.getType() == LightUpCellType.EMPTY || cell.getType() == LightUpCellType.UNKNOWN) &&
- !cell.isLite() && cannotLite.checkContradictionAt(board, cell) == null) {
+ LightUpBoard modifiedBoard = board.copy();
+ LightUpCell modifiedCell = modifiedBoard.getCell(loc.x, loc.y);
+ modifiedCell.setData(LightUpCellType.EMPTY.value);
+ //Check if this cell itself (the one with the bulb) has no other lighting option
+ if ((modifiedCell.getType() == LightUpCellType.EMPTY || modifiedCell.getType() == LightUpCellType.UNKNOWN) &&
+ !modifiedCell.isLite() && cannotLite.checkContradictionAt(modifiedBoard, modifiedCell) == null) {
return true;
}
- for (int i = loc.x + 1; i < board.getWidth(); i++) {
- LightUpCell c = board.getCell(i, loc.y);
+ //Look right
+ for (int i = loc.x + 1; i < modifiedBoard.getWidth(); i++) {
+ LightUpCell c = modifiedBoard.getCell(i, loc.y);
if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) {
break;
}
else {
if (c.getType() == LightUpCellType.EMPTY &&
- !c.isLite() && cannotLite.checkContradictionAt(board, c) == null) {
+ !c.isLite() && cannotLite.checkContradictionAt(modifiedBoard, c) == null) {
return true;
}
}
}
+ //Look left
for (int i = loc.x - 1; i >= 0; i--) {
- LightUpCell c = board.getCell(i, loc.y);
+ LightUpCell c = modifiedBoard.getCell(i, loc.y);
if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) {
break;
}
else {
if (c.getType() == LightUpCellType.EMPTY &&
- !c.isLite() && cannotLite.checkContradictionAt(board, c) == null) {
+ !c.isLite() && cannotLite.checkContradictionAt(modifiedBoard, c) == null) {
return true;
}
}
}
- for (int i = loc.y + 1; i < board.getHeight(); i++) {
- LightUpCell c = board.getCell(loc.x, i);
+ //Look down
+ for (int i = loc.y + 1; i < modifiedBoard.getHeight(); i++) {
+ LightUpCell c = modifiedBoard.getCell(loc.x, i);
if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) {
break;
}
else {
if (c.getType() == LightUpCellType.EMPTY &&
- !c.isLite() && cannotLite.checkContradictionAt(board, c) == null) {
+ !c.isLite() && cannotLite.checkContradictionAt(modifiedBoard, c) == null) {
return true;
}
}
}
+ //Look up
for (int i = loc.y - 1; i >= 0; i--) {
- LightUpCell c = board.getCell(loc.x, i);
+ LightUpCell c = modifiedBoard.getCell(loc.x, i);
if (c.getType() == LightUpCellType.BLACK || c.getType() == LightUpCellType.NUMBER) {
break;
}
else {
if (c.getType() == LightUpCellType.EMPTY &&
- !c.isLite() && cannotLite.checkContradictionAt(board, c) == null) {
+ !c.isLite() && cannotLite.checkContradictionAt(modifiedBoard, c) == null) {
return true;
}
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/lightup_reference_sheet.txt b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/lightup_reference_sheet.txt
index a560b824e..81929bfe9 100644
--- a/src/main/java/edu/rpi/legup/puzzle/lightup/rules/lightup_reference_sheet.txt
+++ b/src/main/java/edu/rpi/legup/puzzle/lightup/rules/lightup_reference_sheet.txt
@@ -1,9 +1,8 @@
-LTUP-BASC-0001 : BulbsOutsideDiagonalBasicRule
-LTUP-BASC-0002 : EmptyCellInLightBasicRule
-LTUP-BASC-0003 : EmptyCornersBasicRule
-LTUP-BASC-0004 : FinishWithBulbsBasicRule
-LTUP-BASC-0005 : FinishWithEmptyBasicRule
-LTUP-BASC-0006 : MustLightBasicRule
+LTUP-BASC-0001 : EmptyCellInLightBasicRule
+LTUP-BASC-0002 : EmptyCornersBasicRule
+LTUP-BASC-0003 : FinishWithBulbsBasicRule
+LTUP-BASC-0004 : FinishWithEmptyBasicRule
+LTUP-BASC-0005 : MustLightBasicRule
LTUP-CONT-0001 : BulbsInPathContradictionRule
LTUP-CONT-0002 : CannotLightACellContradictionRule
diff --git a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuCell.java b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuCell.java
index b0a49d338..1510a3124 100644
--- a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuCell.java
+++ b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuCell.java
@@ -18,6 +18,8 @@ public MasyuType getType() {
return MasyuType.BLACK;
case 2:
return MasyuType.WHITE;
+ case 3:
+ return MasyuType.LINE;
default:
return null;
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuController.java b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuController.java
index 72c5e634a..67894f368 100644
--- a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuController.java
+++ b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuController.java
@@ -80,8 +80,22 @@ public void mouseReleased(MouseEvent e) {
masyuLine.clear();
}
+ /**
+ * Alters the cells as they are being dragged over or clicked
+ * @param e Mouse event being used
+ * @param data Data of selected cell
+ */
@Override
public void changeCell(MouseEvent e, PuzzleElement data) {
-
+ MasyuCell cell = (MasyuCell) data;
+ if(cell.getData() == 1 || cell.getData() == 2) {
+ return;
+ }
+ if(cell.getData() == 0) {
+ data.setData(3);
+ }
+ else {
+ data.setData(0);
+ }
}
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuType.java b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuType.java
index 9b23ed285..fa6abdfb6 100644
--- a/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuType.java
+++ b/src/main/java/edu/rpi/legup/puzzle/masyu/MasyuType.java
@@ -1,5 +1,5 @@
package edu.rpi.legup.puzzle.masyu;
public enum MasyuType {
- UNKNOWN, BLACK, WHITE
+ UNKNOWN, BLACK, WHITE, LINE
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeUtilities.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeUtilities.java
index f8125ad43..d3fea6a21 100644
--- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeUtilities.java
+++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/NurikabeUtilities.java
@@ -4,8 +4,9 @@
import edu.rpi.legup.utility.DisjointSets;
import java.awt.*;
-import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.Set;
public class NurikabeUtilities {
@@ -165,72 +166,79 @@ public static DisjointSets getPossibleWhiteRegions(NurikabeBoard b
}
/**
- * Gets a list of flood filled white regions with remaining white cells
+ * Makes a map where the keys are white/numbered cells
+ * and the values are the amount of cells that need
+ * to be added to the region
*
* @param board nurikabe board
- * @return a list of flood filled white regions
+ * @return a map of cell keys to integer values
*/
- public static ArrayList> getFloodFillWhite(NurikabeBoard board) {
+ public static HashMap getWhiteRegionMap(NurikabeBoard board) {
int width = board.getWidth();
int height = board.getHeight();
- DisjointSets whiteRegions = new DisjointSets<>();
- for (PuzzleElement data : board.getPuzzleElements()) {
- NurikabeCell cell = (NurikabeCell) data;
- whiteRegions.createSet(cell);
- }
-
- for (int x = 0; x < width; x++) {
- for (int y = 0; y < height; y++) {
- NurikabeCell cell = board.getCell(x, y);
- NurikabeCell rightCell = board.getCell(x + 1, y);
- NurikabeCell downCell = board.getCell(x, y + 1);
- if (cell.getType() == NurikabeType.WHITE || cell.getType() == NurikabeType.NUMBER) {
- if (rightCell != null && (rightCell.getType() == NurikabeType.WHITE ||
- rightCell.getType() == NurikabeType.NUMBER)) {
- whiteRegions.union(cell, rightCell);
- }
- if (downCell != null && (downCell.getType() == NurikabeType.WHITE ||
- downCell.getType() == NurikabeType.NUMBER)) {
- whiteRegions.union(cell, downCell);
- }
- }
- }
- }
-
Set numberedCells = getNurikabeNumberedCells(board);
- ArrayList> floodFilledRegions = new ArrayList<>();
- for (NurikabeCell numberCell : numberedCells) {
- int number = numberCell.getData();
- Set region = whiteRegions.getSet(numberCell);
- floodFilledRegions.add(region);
-
- int flood = number - region.size();
- for (int i = 0; i < flood; i++) {
- Set newSet = new HashSet<>();
- for (NurikabeCell c : region) {
- Point loc = c.getLocation();
- NurikabeCell upCell = board.getCell(loc.x, loc.y - 1);
- NurikabeCell rightCell = board.getCell(loc.x + 1, loc.y);
- NurikabeCell downCell = board.getCell(loc.x, loc.y + 1);
- NurikabeCell leftCell = board.getCell(loc.x - 1, loc.y);
- if (upCell != null) {
- newSet.add(upCell);
- }
- if (rightCell != null) {
- newSet.add(rightCell);
- }
- if (downCell != null) {
- newSet.add(downCell);
- }
- if (leftCell != null) {
- newSet.add(leftCell);
+ // Final mapping of cell to size
+ HashMap whiteRegionMap = new HashMap<>();
+ for (NurikabeCell center: numberedCells) {
+ //BFS for each center to find the size of the region
+ int size = 1;
+ // Mark all the vertices as not visited(By default
+ // set as false)
+ HashMap visited= new HashMap<>();
+
+ // Create a queue for BFS
+ LinkedList queue = new LinkedList<>();
+
+ // Mark the current node as visited and enqueue it
+ visited.put(center,true);
+ queue.add(center);
+
+ // Set of cells in the current region
+ Set connected = new HashSet<>();
+
+ while (queue.size() != 0) {
+ // Dequeue a vertex from queue and print it
+ // s is the source node in the graph
+ NurikabeCell s = queue.poll();
+ System.out.print(s+" ");
+
+ // Make a linked list of all adjacent squares
+ Set adj = new HashSet<>();
+
+ Point loc = s.getLocation();
+ // First check if the side is on the board
+ if (loc.x >= 1) {
+ adj.add(board.getCell(loc.x-1, loc.y));
+ }
+ if (loc.x < width-1) {
+ adj.add(board.getCell(loc.x+1, loc.y));
+ }
+ if (loc.y >= 1) {
+ adj.add(board.getCell(loc.x, loc.y-1));
+ }
+ if (loc.y < height-1) {
+ adj.add(board.getCell(loc.x, loc.y+1));
+ }
+ // Get all adjacent vertices of the dequeued vertex s
+ // If a adjacent has not been visited, then mark it
+ // visited and enqueue it
+ for (NurikabeCell n : adj) {
+ if (!visited.getOrDefault(n,false)
+ && n.getType() == NurikabeType.WHITE) {
+ connected.add(n);
+ visited.put(n,true);
+ queue.add(n);
+ ++size;
}
}
- region.addAll(newSet);
+ }
+ // Map the cells to the center-size (including the center)
+ whiteRegionMap.put(center,center.getData()-size);
+ for (NurikabeCell member : connected) {
+ whiteRegionMap.put(member,center.getData()-size);
}
}
-
- return floodFilledRegions;
+ return whiteRegionMap;
}
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/BlackBottleNeckBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/BlackBottleNeckBasicRule.java
index 9df8ac70b..a483236b8 100644
--- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/BlackBottleNeckBasicRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/BlackBottleNeckBasicRule.java
@@ -15,7 +15,7 @@ public class BlackBottleNeckBasicRule extends BasicRule {
public BlackBottleNeckBasicRule() {
super("NURI-BASC-0002",
"Black Bottle Neck",
- "If there is only one path for a black to escape, then those unknowns must be white.",
+ "If there is only one path for a black to escape, then those unknowns must be black.",
"edu/rpi/legup/images/nurikabe/rules/OneUnknownBlack.png");
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/CannotReachCellBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/CannotReachCellBasicRule.java
index 7b4deb4ae..4076ff9bd 100644
--- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/CannotReachCellBasicRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/CannotReachCellBasicRule.java
@@ -40,20 +40,12 @@ protected String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleE
NurikabeBoard origBoardState = (NurikabeBoard) transition.getParents().get(0).getBoard();
NurikabeBoard modified = origBoardState.copy();
- for (int i = 0; i < modified.getWidth(); i++) {
- for (int j = 0; j < modified.getHeight(); j++) {
- NurikabeCell currentCell = modified.getCell(i, j);
- if (currentCell.getType() == NurikabeType.WHITE) {
- currentCell.setData(NurikabeType.UNKNOWN.toValue());
- }
- }
- }
NurikabeCell modifiedCell = (NurikabeCell) modified.getPuzzleElement(puzzleElement);
modifiedCell.setData(NurikabeType.WHITE.toValue());
- if (contraRule.checkContradiction(modified) == null) {
+ if (contraRule.checkContradictionAt(modified,modifiedCell) == null) {
return null;
}
- return super.getInvalidUseOfRuleMessage() + ": This is not the only way for black to escape!";
+ return super.getInvalidUseOfRuleMessage() + ": Cell at this index can be reached";
}
/**
diff --git a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/UnreachableWhiteCellContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/UnreachableWhiteCellContradictionRule.java
index f12bdb57f..cdad16bcb 100644
--- a/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/UnreachableWhiteCellContradictionRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/nurikabe/rules/UnreachableWhiteCellContradictionRule.java
@@ -8,8 +8,8 @@
import edu.rpi.legup.puzzle.nurikabe.NurikabeType;
import edu.rpi.legup.puzzle.nurikabe.NurikabeUtilities;
-import java.util.ArrayList;
-import java.util.Set;
+import java.awt.*;
+import java.util.*;
public class UnreachableWhiteCellContradictionRule extends ContradictionRule {
@@ -40,14 +40,63 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
return super.getInvalidUseOfRuleMessage() + ": " + this.INVALID_USE_MESSAGE;
}
- ArrayList> regions = NurikabeUtilities.getFloodFillWhite(nurikabeBoard);
+ int height = nurikabeBoard.getHeight();
+ int width = nurikabeBoard.getWidth();
- for (Set region : regions) {
- for (NurikabeCell c : region) {
- if (c == cell) {
- return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE;
+ // Get regions
+ HashMap whiteRegionMap = NurikabeUtilities.getWhiteRegionMap(nurikabeBoard);
+ if (whiteRegionMap.containsKey(cell)) {
+ return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE;
+ }
+ // BFS to a region
+
+ // Create a queue for BFS
+ LinkedList queue = new LinkedList<>();
+
+ // Mark the current node as visited and enqueue it
+ HashMap visited= new HashMap<>();
+ visited.put(cell,true);
+ queue.add(cell);
+ int pathLength = 1;
+ while (queue.size() != 0) {
+ // Set of adjacent squares
+ Set adj = new HashSet<>();
+ while (queue.size() != 0) {
+ // Dequeue a vertex from queue and print it
+ NurikabeCell s = queue.poll();
+
+ Point loc = s.getLocation();
+ // First check if the side is on the board
+ if (loc.x >= 1) {
+ adj.add(nurikabeBoard.getCell(loc.x-1, loc.y));
+ }
+ if (loc.x < width-1) {
+ adj.add(nurikabeBoard.getCell(loc.x+1, loc.y));
+ }
+ if (loc.y >= 1) {
+ adj.add(nurikabeBoard.getCell(loc.x, loc.y-1));
+ }
+ if (loc.y < height-1) {
+ adj.add(nurikabeBoard.getCell(loc.x, loc.y+1));
+ }
+
+ for (NurikabeCell n :adj) {
+ int regionNeed = whiteRegionMap.getOrDefault(n,-1);
+ if (pathLength <= regionNeed) {
+ return super.getNoContradictionMessage() + ": " + this.NO_CONTRADICTION_MESSAGE;
+ }
+ }
+ }
+
+ for (NurikabeCell n : adj) {
+ if (!visited.getOrDefault(n,false)
+ && (n.getType() == NurikabeType.UNKNOWN ||
+ n.getType() == NurikabeType.WHITE)) {
+ visited.put(n,true);
+ queue.add(n);
}
}
+ ++pathLength;
}
return null;
diff --git a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/basic/BasicRule_Generic.java b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/basic/BasicRule_Generic.java
index 4a0fac4b2..4d1385e87 100644
--- a/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/basic/BasicRule_Generic.java
+++ b/src/main/java/edu/rpi/legup/puzzle/shorttruthtable/rules/basic/BasicRule_Generic.java
@@ -31,38 +31,29 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement element) {
return super.getInvalidUseOfRuleMessage() + ": Only assigned cells are allowed for basic rules";
}
- if (this.ELIMINATION_RULE) {
- // Strategy: If this is an elimination rule, simply check if there is a contradiction at the specified statement
-
- // This gets the operator of the parent statement, which is what we need for checking the contradiction
- PuzzleElement checkElement = cell.getStatementReference().getParentStatement().getCell();
-
- String contradictionMessage = CORRESPONDING_CONTRADICTION_RULE.checkContradictionAt(board, checkElement);
- if (contradictionMessage != null) {
- if (contradictionMessage.startsWith(CORRESPONDING_CONTRADICTION_RULE.getNoContradictionMessage())) {
- return null;
- }
- else {
- return super.getInvalidUseOfRuleMessage() + ": " + contradictionMessage;
- }
- }
- else {
- return super.getInvalidUseOfRuleMessage();
- }
- }
- else {
- // Strategy: Negate the modified cell and check if there is a contradiction. If there is one, then the
- // original statement must be true. If there isn't one, then the original statement must be false.
-
- ShortTruthTableBoard modifiedBoard = board.copy();
- ((ShortTruthTableCell) modifiedBoard.getPuzzleElement(element)).setType(cell.getType().getNegation());
-
- String contradictionMessage = CORRESPONDING_CONTRADICTION_RULE.checkContradictionAt(modifiedBoard, element);
- if (contradictionMessage == null) { // A contradiction exists in the modified statement; this is good!
- return null;
- }
- return super.getInvalidUseOfRuleMessage() + ": " + contradictionMessage;
+ // Strategy: Negate the modified cell and check if there is a contradiction. If there is one, then the
+ // original statement must be true. If there isn't one, then the original statement must be false.
+
+ ShortTruthTableBoard modifiedBoard = board.copy();
+
+ PuzzleElement checkElement =
+ this.ELIMINATION_RULE
+ ? cell.getStatementReference().getParentStatement().getCell()
+ : element;
+
+ ShortTruthTableCell checkCell =
+ this.ELIMINATION_RULE
+ ? (ShortTruthTableCell) modifiedBoard.getCell(cell.getX(), cell.getY())
+ : (ShortTruthTableCell) modifiedBoard.getPuzzleElement(element);
+
+ checkCell.setType(checkCell.getType().getNegation());
+
+ String contradictionMessage = CORRESPONDING_CONTRADICTION_RULE.checkContradictionAt(modifiedBoard, checkElement);
+ if (contradictionMessage == null) { // A contradiction exists in the modified statement; this is good!
+ return null;
}
+
+ return super.getInvalidUseOfRuleMessage();
}
/**
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/Skyscrapers.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/Skyscrapers.java
index a4853993d..71e8f8306 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/Skyscrapers.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/Skyscrapers.java
@@ -4,9 +4,6 @@
import edu.rpi.legup.model.gameboard.Board;
import edu.rpi.legup.model.gameboard.PuzzleElement;
import edu.rpi.legup.model.rules.ContradictionRule;
-import edu.rpi.legup.puzzle.lightup.LightUpBoard;
-import edu.rpi.legup.puzzle.lightup.LightUpCell;
-import edu.rpi.legup.puzzle.lightup.LightUpCellType;
public class Skyscrapers extends Puzzle {
@@ -26,7 +23,6 @@ public Skyscrapers() {
*/
@Override
public void initializeView() {
- SkyscrapersBoard board = (SkyscrapersBoard) currentBoard;
boardView = new SkyscrapersView((SkyscrapersBoard) currentBoard);
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersBoard.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersBoard.java
index 0e8786874..c23d2c46f 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersBoard.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersBoard.java
@@ -12,57 +12,90 @@ public class SkyscrapersBoard extends GridBoard {
private ArrayList lines;
- private ArrayList rowClues;
- private ArrayList colClues;
- private ArrayList row;
- private ArrayList col;
- public SkyscrapersBoard(int width, int height) {
- super(width, height);
+ private ArrayList eastClues;
+ //EAST clues
+ private ArrayList southClues;
+ //SOUTH clues
+ private ArrayList westClues;
+ //WEST clues
+ private ArrayList northClues;
+ //NORTH clues
+
+ private boolean viewFlag = false;
+ private boolean dupeFlag = false;
+
+ private SkyscrapersClue modClue = null;
+ //helper variable for case rule verification, tracks recently modified row/col
+
+ public SkyscrapersBoard(int size) {
+ super(size, size);
this.lines = new ArrayList<>();
- this.rowClues = new ArrayList<>();
- this.colClues = new ArrayList<>();
- this.row = new ArrayList<>();
- this.col = new ArrayList<>();
+ this.eastClues = new ArrayList<>();
+ this.southClues = new ArrayList<>();
+ this.westClues = new ArrayList<>();
+ this.northClues = new ArrayList<>();
- for (int i = 0; i < height; i++) {
- rowClues.add(null);
- }
- for (int i = 0; i < width; i++) {
- colClues.add(null);
- }
- for (int i = 0; i < height; i++) {
- row.add(null);
+ for (int i = 0; i < size; i++) {
+ eastClues.add(null);
+ southClues.add(null);
+ westClues.add(null);
+ northClues.add(null);
}
- for (int i = 0; i < width; i++) {
- col.add(null);
- }
- }
-
- public SkyscrapersBoard(int size) {
- this(size, size);
}
public ArrayList getLines() {
return lines;
}
- public ArrayList getRowClues() { //EAST CLUE
- return rowClues;
+ /**
+ * Returns a list of the eastern clues ordered from loc.y = 0->max
+ */
+ public ArrayList getEastClues() {
+ return eastClues;
+ }
+
+ /**
+ * Returns a list of the southern clues ordered from loc.x = 0->max
+ */
+ public ArrayList getSouthClues() {
+ return southClues;
+ }
+
+ /**
+ * Returns a list of the western clues ordered from loc.y = 0->max
+ */
+ public ArrayList getWestClues() {
+ return westClues;
}
- public ArrayList getColClues() { //SOUTH CLUE
- return colClues;
+ /**
+ * Returns a list of the northern clues ordered from loc.x = 0->max
+ */
+ public ArrayList getNorthClues() {
+ return northClues;
}
- public ArrayList getRow() { //WEST CLUE
- return row;
+ public boolean getDupeFlag(){
+ return dupeFlag;
+ }
+ public boolean getViewFlag(){
+ return viewFlag;
+ }
+ public void setDupeFlag(boolean newFlag){
+ dupeFlag = newFlag;
+ }
+ public void setViewFlag(boolean newFlag){
+ viewFlag = newFlag;
}
- public ArrayList getCol() { //NORTH CLUE
- return col;
+ public SkyscrapersClue getmodClue(){
+ return modClue;
+ }
+ public void setModClue(SkyscrapersClue newClue){
+ modClue = newClue;
}
@Override
@@ -70,6 +103,10 @@ public SkyscrapersCell getCell(int x, int y) {
return (SkyscrapersCell) super.getCell(x, y);
}
+ public int getSize() {
+ return this.getWidth();
+ }
+
@Override
public PuzzleElement getPuzzleElement(PuzzleElement element) {
switch (element.getIndex()) {
@@ -119,6 +156,13 @@ public void notifyDeletion(PuzzleElement puzzleElement) {
}
}
+ /**
+ * Gets the cells of a certain type directly adjacent to a given cell
+ *
+ * @param cell at the center,
+ * type of cell to collect
+ * @return list of cells of the given type
+ */
public List getAdjacent(SkyscrapersCell cell, SkyscrapersType type) {
List adj = new ArrayList<>();
Point loc = cell.getLocation();
@@ -126,21 +170,28 @@ public List getAdjacent(SkyscrapersCell cell, SkyscrapersType t
SkyscrapersCell right = getCell(loc.x + 1, loc.y);
SkyscrapersCell down = getCell(loc.x, loc.y + 1);
SkyscrapersCell left = getCell(loc.x - 1, loc.y);
- if (up != null && up.getType() == type) {
+ if (up != null && (up.getType() == type || type == SkyscrapersType.ANY)) {
adj.add(up);
}
- if (right != null && right.getType() == type) {
+ if (right != null && (right.getType() == type || type == SkyscrapersType.ANY)) {
adj.add(right);
}
- if (down != null && down.getType() == type) {
+ if (down != null && (down.getType() == type || type == SkyscrapersType.ANY)) {
adj.add(down);
}
- if (left != null && left.getType() == type) {
+ if (left != null && (left.getType() == type || type == SkyscrapersType.ANY)) {
adj.add(left);
}
return adj;
}
+ /**
+ * Gets the cells of a certain type directly diagonal to a given cell
+ *
+ * @param cell at the center,
+ * type of cell to collect
+ * @return list of cells of the given type
+ */
public List getDiagonals(SkyscrapersCell cell, SkyscrapersType type) {
List dia = new ArrayList<>();
Point loc = cell.getLocation();
@@ -148,40 +199,62 @@ public List getDiagonals(SkyscrapersCell cell, SkyscrapersType
SkyscrapersCell downRight = getCell(loc.x + 1, loc.y + 1);
SkyscrapersCell downLeft = getCell(loc.x - 1, loc.y + 1);
SkyscrapersCell upLeft = getCell(loc.x - 1, loc.y - 1);
- if (upRight != null && upRight.getType() == type) {
+ if (upRight != null && (upRight.getType() == type || type == SkyscrapersType.ANY)) {
dia.add(upRight);
}
- if (downLeft != null && downLeft.getType() == type) {
+ if (downLeft != null && (downLeft.getType() == type || type == SkyscrapersType.ANY)) {
dia.add(downLeft);
}
- if (downRight != null && downRight.getType() == type) {
+ if (downRight != null && (downRight.getType() == type || type == SkyscrapersType.ANY)) {
dia.add(downRight);
}
- if (upLeft != null && upLeft.getType() == type) {
+ if (upLeft != null && (upLeft.getType() == type || type == SkyscrapersType.ANY)) {
dia.add(upLeft);
}
return dia;
}
+ /**
+ * Gets the cells of a certain type in a given row/column
+ *
+ * @param index: y pos of row or x pos of col,
+ * type of cell to collect,
+ * boolean true if row, false if col
+ * @return list of cells of the given type, ordered west to east or north to south
+ */
public List getRowCol(int index, SkyscrapersType type, boolean isRow) {
List list = new ArrayList<>();
- if (isRow) {
- for (int i = 0; i < dimension.height; i++) {
- SkyscrapersCell cell = getCell(i, index);
- if (cell.getType() == type) {
- list.add(cell);
- }
+ for (int i = 0; i < dimension.height; i++) {
+ SkyscrapersCell cell;
+ if (isRow) {
+ cell = getCell(i, index);
+ }
+ else {
+ cell = getCell(index, i);
+ }
+
+ if (cell.getType() == type || type == SkyscrapersType.ANY) {
+ list.add(cell);
}
}
- else {
- for (int i = 0; i < dimension.width; i++) {
- SkyscrapersCell cell = getCell(index, i);
- if (cell.getType() == type) {
- list.add(cell);
+ return list;
+ }
+
+ /**
+ * Prints a semblance of the board to console (helps in debugging)
+ */
+ public void printBoard(){
+ for(int i =0; i getRowCol(int index, SkyscrapersType type, boolean
*/
@Override
public boolean equalsBoard(Board board) {
- SkyscrapersBoard treeTentBoard = (SkyscrapersBoard) board;
+ SkyscrapersBoard skyscrapersBoard= (SkyscrapersBoard) board;
for (SkyscrapersLine l1 : lines) {
boolean hasLine = false;
- for (SkyscrapersLine l2 : treeTentBoard.lines) {
+ for (SkyscrapersLine l2 : skyscrapersBoard.lines) {
if (l1.compare(l2)) {
hasLine = true;
}
@@ -204,12 +277,12 @@ public boolean equalsBoard(Board board) {
return false;
}
}
- return super.equalsBoard(treeTentBoard);
+ return super.equalsBoard(skyscrapersBoard);
}
@Override
public SkyscrapersBoard copy() {
- SkyscrapersBoard copy = new SkyscrapersBoard(dimension.width, dimension.height);
+ SkyscrapersBoard copy = new SkyscrapersBoard(dimension.width);
for (int x = 0; x < this.dimension.width; x++) {
for (int y = 0; y < this.dimension.height; y++) {
copy.setCell(x, y, getCell(x, y).copy());
@@ -223,10 +296,13 @@ public SkyscrapersBoard copy() {
for (PuzzleElement e : modifiedData) {
copy.getPuzzleElement(e).setModifiable(false);
}
- copy.rowClues = rowClues;
- copy.colClues = colClues;
- copy.row = row;
- copy.col = col;
+ copy.eastClues = eastClues;
+ copy.southClues = southClues;
+ copy.westClues = westClues;
+ copy.northClues = northClues;
+
+ copy.dupeFlag=dupeFlag;
+ copy.viewFlag=viewFlag;
return copy;
}
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersCellFactory.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersCellFactory.java
index 4e66708bd..b6329aac2 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersCellFactory.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersCellFactory.java
@@ -22,9 +22,10 @@ public class SkyscrapersCellFactory extends ElementFactory {
@Override
public PuzzleElement importCell(Node node, Board board) throws InvalidFileFormatException {
try {
- SkyscrapersBoard treeTentBoard = (SkyscrapersBoard) board;
- int width = treeTentBoard.getWidth();
- int height = treeTentBoard.getHeight();
+ //SkyscrapersBoard treeTentBoard = (SkyscrapersBoard) board;
+ SkyscrapersBoard skyscrapersBoard = (SkyscrapersBoard) board;
+ int width = skyscrapersBoard.getWidth();
+ int height = skyscrapersBoard.getHeight();
NamedNodeMap attributeList = node.getAttributes();
if (node.getNodeName().equalsIgnoreCase("cell")) {
@@ -52,8 +53,8 @@ public PuzzleElement importCell(Node node, Board board) throws InvalidFileFormat
throw new InvalidFileFormatException("TreeTent Factory: line location out of bounds");
}
- SkyscrapersCell c1 = treeTentBoard.getCell(x1, y1);
- SkyscrapersCell c2 = treeTentBoard.getCell(x2, y2);
+ SkyscrapersCell c1 = skyscrapersBoard.getCell(x1, y1);
+ SkyscrapersCell c2 = skyscrapersBoard.getCell(x2, y2);
return new SkyscrapersLine(c1, c2);
}
else {
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClue.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClue.java
index 70aacd76b..dc68f45c7 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClue.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClue.java
@@ -9,7 +9,7 @@ public class SkyscrapersClue extends PuzzleElement {
public SkyscrapersClue(int value, int clueIndex, SkyscrapersType type) {
super(value);
this.index = -2;
- this.clueIndex = clueIndex;
+ this.clueIndex = clueIndex;//index in list
this.type = type;
this.setModifiable(false);
}
@@ -38,10 +38,6 @@ public int getClueIndex() {
return clueIndex;
}
- public void setClueIndex(int clueIndex) {
- this.clueIndex = clueIndex;
- }
-
public SkyscrapersType getType() {
return type;
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClueView.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClueView.java
index 549789c01..d070fdf4d 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClueView.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersClueView.java
@@ -23,9 +23,15 @@ public SkyscrapersClue getPuzzleElement() {
return (SkyscrapersClue) super.getPuzzleElement();
}
- @Override
+ @Override
public void draw(Graphics2D graphics2D) {
drawElement(graphics2D);
+ if (this.isShowCasePicker() && this.isCaseRulePickable()) {
+ drawCase(graphics2D);
+ if(this.isHover()){
+ drawHover(graphics2D);
+ }
+ }
}
@Override
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersController.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersController.java
index fa771beca..0558213ab 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersController.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersController.java
@@ -85,17 +85,7 @@ public void mouseReleased(MouseEvent e) {
treePanel.updateError(edit.getError());
}
}
- } /*else if (lastCellPressed != null) {
- if (dragStart instanceof SkyscrapersElementView) {
- ICommand editLine = new EditLineCommand(selection, (SkyscrapersElementView) dragStart, lastCellPressed);
- if (editLine.canExecute()) {
- editLine.execute();
- getInstance().getHistory().pushChange(editLine);
- } else {
- treePanel.updateError(editLine.getError());
- }
- }
- }*/
+ }
}
}
dragStart = null;
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersElementView.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersElementView.java
index 8df3a18a8..533437d67 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersElementView.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersElementView.java
@@ -16,30 +16,7 @@ public SkyscrapersElementView(SkyscrapersCell cell) {
@Override
public void drawElement(Graphics2D graphics2D) {
- /*SkyscrapersCell cell = (SkyscrapersCell) puzzleElement;
- SkyscrapersType type = cell.getType();
- graphics2D.setStroke(new BasicStroke(0));
- if (type == SkyscrapersType.UNKNOWN) {
- graphics2D.setStroke(new BasicStroke(1));
- graphics2D.setColor(Color.LIGHT_GRAY);
- graphics2D.fill(new Rectangle2D.Double(location.x + 0.5f, location.y + 0.5f, size.width - 1, size.height - 1));
- graphics2D.setColor(Color.BLACK);
- graphics2D.draw(new Rectangle2D.Double(location.x + 0.5f, location.y + 0.5f, size.width - 1, size.height - 1));
- } else if (type == SkyscrapersType.TREE) {
- graphics2D.drawImage(SkyscrapersView.TREE, location.x, location.y, size.width, size.height, null, null);
- graphics2D.setColor(Color.BLACK);
- graphics2D.drawRect(location.x, location.y, size.width, size.height);
- } else if (type == SkyscrapersType.GRASS) {
- graphics2D.drawImage(SkyscrapersView.GRASS, location.x, location.y, size.width, size.height, null, null);
- graphics2D.setColor(Color.BLACK);
- graphics2D.drawRect(location.x, location.y, size.width, size.height);
- } else if (type == SkyscrapersType.TENT) {
- graphics2D.drawImage(SkyscrapersView.TENT, location.x, location.y, size.width, size.height, null, null);
- graphics2D.setColor(Color.BLACK);
- graphics2D.drawRect(location.x, location.y, size.width, size.height);
- }*/
-
- graphics2D.setStroke(new BasicStroke(1));
+ graphics2D.setStroke(new BasicStroke(1));
graphics2D.setColor(BACKGROUND_COLOR);
graphics2D.fillRect(location.x, location.y, size.width, size.height);
graphics2D.setColor(BORDER_COLOR);
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersExporter.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersExporter.java
index 96a41378f..dac09bd16 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersExporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersExporter.java
@@ -6,8 +6,8 @@
public class SkyscrapersExporter extends PuzzleExporter {
- public SkyscrapersExporter(Skyscrapers treeTent) {
- super(treeTent);
+ public SkyscrapersExporter(Skyscrapers skyscrapers) {
+ super(skyscrapers);
}
@Override
@@ -30,7 +30,7 @@ protected org.w3c.dom.Element createBoardElement(Document newDocument) {
org.w3c.dom.Element axisEast = newDocument.createElement("axis");
axisEast.setAttribute("side", "east");
- for (SkyscrapersClue clue : board.getRowClues()) {
+ for (SkyscrapersClue clue : board.getEastClues()) {
org.w3c.dom.Element clueElement = newDocument.createElement("clue");
clueElement.setAttribute("value", String.valueOf(clue.getData()));
clueElement.setAttribute("index", SkyscrapersClue.colNumToString(clue.getIndex()));
@@ -40,7 +40,7 @@ protected org.w3c.dom.Element createBoardElement(Document newDocument) {
org.w3c.dom.Element axisSouth = newDocument.createElement("axis");
axisSouth.setAttribute("side", "south");
- for (SkyscrapersClue clue : board.getRowClues()) {
+ for (SkyscrapersClue clue : board.getSouthClues()) {
org.w3c.dom.Element clueElement = newDocument.createElement("clue");
clueElement.setAttribute("value", String.valueOf(clue.getData()));
clueElement.setAttribute("index", String.valueOf(clue.getIndex()));
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java
index 68979881a..c4c909172 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersImporter.java
@@ -9,8 +9,8 @@
import java.awt.*;
public class SkyscrapersImporter extends PuzzleImporter {
- public SkyscrapersImporter(Skyscrapers treeTent) {
- super(treeTent);
+ public SkyscrapersImporter(Skyscrapers skyscrapers) {
+ super(skyscrapers);
}
/**
@@ -35,78 +35,74 @@ public void initializeBoard(int rows, int columns) {
public void initializeBoard(Node node) throws InvalidFileFormatException {
try {
if (!node.getNodeName().equalsIgnoreCase("board")) {
- throw new InvalidFileFormatException("TreeTent Importer: cannot find board puzzleElement");
+ throw new InvalidFileFormatException("Skyscrapers Importer: cannot find board puzzleElement");
}
Element boardElement = (Element) node;
if (boardElement.getElementsByTagName("cells").getLength() == 0) {
- throw new InvalidFileFormatException("TreeTent Importer: no puzzleElement found for board");
+ throw new InvalidFileFormatException("Skyscrapers Importer: no puzzleElement found for board");
}
Element dataElement = (Element) boardElement.getElementsByTagName("cells").item(0);
NodeList elementDataList = dataElement.getElementsByTagName("cell");
- SkyscrapersBoard treeTentBoard = null;
+
+
+ SkyscrapersBoard skyscrapersBoard = null;
+
if (!boardElement.getAttribute("size").isEmpty()) {
int size = Integer.valueOf(boardElement.getAttribute("size"));
- treeTentBoard = new SkyscrapersBoard(size);
- }
- else {
- if (!boardElement.getAttribute("width").isEmpty() && !boardElement.getAttribute("height").isEmpty()) {
- int width = Integer.valueOf(boardElement.getAttribute("width"));
- int height = Integer.valueOf(boardElement.getAttribute("height"));
- treeTentBoard = new SkyscrapersBoard(width, height);
- }
+ skyscrapersBoard = new SkyscrapersBoard(size);
}
- if (treeTentBoard == null) {
- throw new InvalidFileFormatException("TreeTent Importer: invalid board dimensions");
+ if (skyscrapersBoard == null) {
+ throw new InvalidFileFormatException("Skyscraper Importer: invalid board dimensions");
}
- int width = treeTentBoard.getWidth();
- int height = treeTentBoard.getHeight();
+ int size = skyscrapersBoard.getSize();
+
for (int i = 0; i < elementDataList.getLength(); i++) {
- SkyscrapersCell cell = (SkyscrapersCell) puzzle.getFactory().importCell(elementDataList.item(i), treeTentBoard);
+ SkyscrapersCell cell = (SkyscrapersCell) puzzle.getFactory().importCell(elementDataList.item(i), skyscrapersBoard);
Point loc = cell.getLocation();
if (cell.getData() != 0) {
cell.setModifiable(false);
cell.setGiven(true);
}
- treeTentBoard.setCell(loc.x, loc.y, cell);
+ skyscrapersBoard.setCell(loc.x, loc.y, cell);
}
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- if (treeTentBoard.getCell(x, y) == null) {
- SkyscrapersCell cell = new SkyscrapersCell(0, new Point(x, y), width);
- cell.setIndex(y * height + x);
+ for (int y = 0; y < size; y++) {
+ for (int x = 0; x < size; x++) {
+ if (skyscrapersBoard.getCell(x, y) == null) {
+ SkyscrapersCell cell = new SkyscrapersCell(0, new Point(x, y), size);
+ cell.setIndex(y * size + x);
cell.setModifiable(true);
- treeTentBoard.setCell(x, y, cell);
+ skyscrapersBoard.setCell(x, y, cell);
}
}
}
NodeList axes = boardElement.getElementsByTagName("axis");
if (axes.getLength() != 2) {
- throw new InvalidFileFormatException("TreeTent Importer: cannot find axes");
+ throw new InvalidFileFormatException("Skyscraper Importer: cannot find axes");
}
Element axis1 = (Element) axes.item(0);
Element axis2 = (Element) axes.item(1);
if (!axis1.hasAttribute("side") || !axis1.hasAttribute("side")) {
- throw new InvalidFileFormatException("TreeTent Importer: side attribute of axis not specified");
+ throw new InvalidFileFormatException("Skyscraper Importer: side attribute of axis not specified");
}
String side1 = axis1.getAttribute("side");
String side2 = axis2.getAttribute("side");
if (side1.equalsIgnoreCase(side2) || !(side1.equalsIgnoreCase("east") || side1.equalsIgnoreCase("south")) ||
!(side2.equalsIgnoreCase("east") || side2.equalsIgnoreCase("south"))) {
- throw new InvalidFileFormatException("TreeTent Importer: axes must be different and be {east | south}");
+ throw new InvalidFileFormatException("Skyscraper Importer: axes must be different and be {east | south}");
}
NodeList eastClues = side1.equalsIgnoreCase("east") ? axis1.getElementsByTagName("clue") : axis2.getElementsByTagName("clue");
NodeList southClues = side1.equalsIgnoreCase("south") ? axis1.getElementsByTagName("clue") : axis2.getElementsByTagName("clue");
- if (eastClues.getLength() != treeTentBoard.getHeight() || southClues.getLength() != treeTentBoard.getWidth()) {
- throw new InvalidFileFormatException("TreeTent Importer: there must be same number of clues as the dimension of the board");
+ if (eastClues.getLength() != skyscrapersBoard.getHeight() || southClues.getLength() != skyscrapersBoard.getWidth()) {
+ throw new InvalidFileFormatException("Skyscraper Importer: there must be same number of clues as the dimension of the board");
}
for (int i = 0; i < eastClues.getLength(); i++) {
@@ -114,15 +110,9 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
int value = Integer.valueOf(clue.getAttribute("value"));
//int index = SkyscrapersClue.colStringToColNum(clue.getAttribute("index"));
int index = Integer.valueOf(clue.getAttribute("index"));
- /*if (index - 1 < 0 || index - 1 > treeTentBoard.getHeight()) {
- throw new InvalidFileFormatException("TreeTent Importer: clue index out of bounds");
- }
- if (treeTentBoard.getRowClues().get(index - 1) != null) {
- throw new InvalidFileFormatException("TreeTent Importer: duplicate clue index");
- }*/
- treeTentBoard.getRow().set(/*index - 1*/i, new SkyscrapersClue(index, index, SkyscrapersType.CLUE_WEST));
- treeTentBoard.getRowClues().set(/*index - 1*/i, new SkyscrapersClue(value, index, SkyscrapersType.CLUE_EAST));
+ skyscrapersBoard.getWestClues().set(/*index - 1*/i, new SkyscrapersClue(index, i, SkyscrapersType.CLUE_WEST));
+ skyscrapersBoard.getEastClues().set(/*index - 1*/i, new SkyscrapersClue(value, i, SkyscrapersType.CLUE_EAST));
}
for (int i = 0; i < southClues.getLength(); i++) {
@@ -130,29 +120,35 @@ public void initializeBoard(Node node) throws InvalidFileFormatException {
int value = Integer.valueOf(clue.getAttribute("value"));
int index = Integer.valueOf(clue.getAttribute("index"));
- /*if (index - 1 < 0 || index - 1 > treeTentBoard.getWidth()) {
- throw new InvalidFileFormatException("TreeTent Importer: clue index out of bounds");
- }
- if (treeTentBoard.getColClues().get(index - 1) != null) {
- throw new InvalidFileFormatException("TreeTent Importer: duplicate clue index");
- }*/
- treeTentBoard.getCol().set(/*index - 1*/i, new SkyscrapersClue(index, index, SkyscrapersType.CLUE_NORTH));
- treeTentBoard.getColClues().set(/*index - 1*/i, new SkyscrapersClue(value, index, SkyscrapersType.CLUE_SOUTH));
+ skyscrapersBoard.getNorthClues().set(/*index - 1*/i, new SkyscrapersClue(index, i, SkyscrapersType.CLUE_NORTH));
+ skyscrapersBoard.getSouthClues().set(/*index - 1*/i, new SkyscrapersClue(value, i, SkyscrapersType.CLUE_SOUTH));
}
if (boardElement.getElementsByTagName("lines").getLength() == 1) {
Element linesElement = (Element) boardElement.getElementsByTagName("lines").item(0);
NodeList linesList = linesElement.getElementsByTagName("line");
for (int i = 0; i < linesList.getLength(); i++) {
- treeTentBoard.getLines().add((SkyscrapersLine) puzzle.getFactory().importCell(linesList.item(i), treeTentBoard));
+ skyscrapersBoard.getLines().add((SkyscrapersLine) puzzle.getFactory().importCell(linesList.item(i), skyscrapersBoard));
+ }
+ }
+
+ //Initialize present flags
+ NodeList flagList = boardElement.getElementsByTagName("flags");
+ if(flagList.getLength()==1){
+ Element flags = (Element) flagList.item(0);
+ if(flags.hasAttribute("dupe")){
+ skyscrapersBoard.setDupeFlag(Boolean.parseBoolean(flags.getAttribute("dupe")));
+ }
+ if(flags.hasAttribute("view")){
+ skyscrapersBoard.setViewFlag(Boolean.parseBoolean(flags.getAttribute("view")));
}
}
- puzzle.setCurrentBoard(treeTentBoard);
+ puzzle.setCurrentBoard(skyscrapersBoard);
}
catch (NumberFormatException e) {
- throw new InvalidFileFormatException("TreeTent Importer: unknown value where integer expected");
+ throw new InvalidFileFormatException("Skyscraper Importer: unknown value where integer expected");
}
}
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersLineView.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersLineView.java
index 2f0f30afd..02daa7a11 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersLineView.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersLineView.java
@@ -24,7 +24,6 @@ public void draw(Graphics2D graphics2D) {
int x2 = (p2.x + 1) * size.width + size.width / 2;
int y2 = (p2.y + 1) * size.height + size.height / 2;
- //graphics2D.setColor(LINE_COLOR);
graphics2D.setColor(line.isModified() ? Color.GREEN : Color.WHITE);
graphics2D.setStroke(LINE_STROKE);
graphics2D.drawLine(x1, y1, x2, y2);
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersType.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersType.java
index 3340af8bf..1fdd668c1 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersType.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersType.java
@@ -1,7 +1,7 @@
package edu.rpi.legup.puzzle.skyscrapers;
public enum SkyscrapersType {
- UNKNOWN(0), Number(1), GRASS(2), TENT(3), CLUE_NORTH(-1), CLUE_EAST(-2), CLUE_SOUTH(-3), CLUE_WEST(-4);
+ UNKNOWN(0), Number(1), ANY(2), CLUE_NORTH(-1), CLUE_EAST(-2), CLUE_SOUTH(-3), CLUE_WEST(-4);
public int value;
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersView.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersView.java
index e165686bb..b12867eda 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersView.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/SkyscrapersView.java
@@ -1,9 +1,9 @@
package edu.rpi.legup.puzzle.skyscrapers;
import edu.rpi.legup.controller.BoardController;
+import edu.rpi.legup.model.gameboard.Board;
import edu.rpi.legup.model.gameboard.CaseBoard;
import edu.rpi.legup.model.gameboard.PuzzleElement;
-import edu.rpi.legup.model.tree.TreeElement;
import edu.rpi.legup.ui.boardview.ElementView;
import edu.rpi.legup.ui.boardview.GridBoardView;
import org.apache.logging.log4j.LogManager;
@@ -16,21 +16,8 @@
public class SkyscrapersView extends GridBoardView {
private final static Logger LOGGER = LogManager.getLogger(SkyscrapersView.class.getName());
- static Image TREE, GRASS, TENT;
-
- static {
- try {
- TREE = ImageIO.read(ClassLoader.getSystemResourceAsStream("edu/rpi/legup/images/treetent/tree.png"));
- GRASS = ImageIO.read(ClassLoader.getSystemResourceAsStream("edu/rpi/legup/images/treetent/grass.png"));
- TENT = ImageIO.read(ClassLoader.getSystemResourceAsStream("edu/rpi/legup/images/treetent/tent.png"));
- }
- catch (IOException e) {
- LOGGER.error("Failed to open TreeTent images");
- }
- }
private ArrayList lineViews;
-
private ArrayList northClues;
private ArrayList eastClues;
private ArrayList southClues;
@@ -63,12 +50,11 @@ public SkyscrapersView(SkyscrapersBoard board) {
}
for (int i = 0; i < gridSize.height; i++) {
- //SkyscrapersClueView row = new SkyscrapersClueView(new SkyscrapersClue(i, i, SkyscrapersType.CLUE_WEST));
- SkyscrapersClueView row = new SkyscrapersClueView(board.getRow().get(i));
+ SkyscrapersClueView row = new SkyscrapersClueView(board.getWestClues().get(i));
row.setLocation(new Point(0, (i + 1) * elementSize.height));
row.setSize(elementSize);
- SkyscrapersClueView clue = new SkyscrapersClueView(board.getRowClues().get(i));
+ SkyscrapersClueView clue = new SkyscrapersClueView(board.getEastClues().get(i));
clue.setLocation(new Point((gridSize.height + 1) * elementSize.height, (i + 1) * elementSize.height));
clue.setSize(elementSize);
@@ -77,12 +63,11 @@ public SkyscrapersView(SkyscrapersBoard board) {
}
for (int i = 0; i < gridSize.width; i++) {
- //SkyscrapersClueView col = new SkyscrapersClueView(new SkyscrapersClue(i, i, SkyscrapersType.CLUE_NORTH));
- SkyscrapersClueView col = new SkyscrapersClueView(board.getCol().get(i));
+ SkyscrapersClueView col = new SkyscrapersClueView(board.getNorthClues().get(i));
col.setLocation(new Point((i + 1) * elementSize.width, 0));
col.setSize(elementSize);
- SkyscrapersClueView clue = new SkyscrapersClueView(board.getColClues().get(i));
+ SkyscrapersClueView clue = new SkyscrapersClueView(board.getSouthClues().get(i));
clue.setLocation(new Point((i + 1) * elementSize.width, (gridSize.width + 1) * elementSize.width));
clue.setSize(elementSize);
@@ -129,22 +114,10 @@ public ElementView getElement(Point point) {
return null;
}
- public ArrayList getLineViews() {
- return lineViews;
- }
-
public ArrayList getNorthClues() {
return northClues;
}
- public ArrayList getEastClues() {
- return eastClues;
- }
-
- public ArrayList getSouthClues() {
- return southClues;
- }
-
public ArrayList getWestClues() {
return westClues;
}
@@ -158,26 +131,57 @@ protected Dimension getProperSize() {
}
/**
- * Called when the tree element has changed.
+ * Sets the board associated with this view
*
- * @param treeElement tree element
+ * @param board board
*/
@Override
- public void onTreeElementChanged(TreeElement treeElement) {
- super.onTreeElementChanged(treeElement);
- SkyscrapersBoard treeTentBoard;
- if (board instanceof CaseBoard) {
- treeTentBoard = (SkyscrapersBoard) ((CaseBoard) board).getBaseBoard();
- }
- else {
- treeTentBoard = (SkyscrapersBoard) board;
+ public void setBoard(Board board) {
+ if (this.board != board) {
+ this.board = board;
+
+ if (board instanceof CaseBoard) {
+ setCasePickable();
+ }
+ else {
+ for (ElementView elementView : elementViews) {
+ elementView.setPuzzleElement(board.getPuzzleElement(elementView.getPuzzleElement()));
+ elementView.setShowCasePicker(false);
+ }
+ for (SkyscrapersClueView clueView : northClues) {
+ clueView.setPuzzleElement(board.getPuzzleElement(clueView.getPuzzleElement()));
+ clueView.setShowCasePicker(false);
+ }
+ for (SkyscrapersClueView clueView : westClues) {
+ clueView.setPuzzleElement(board.getPuzzleElement(clueView.getPuzzleElement()));
+ clueView.setShowCasePicker(false);
+ }
+ }
}
+ }
- lineViews.clear();
- for (SkyscrapersLine line : treeTentBoard.getLines()) {
- SkyscrapersLineView lineView = new SkyscrapersLineView(line);
- lineView.setSize(elementSize);
- lineViews.add(lineView);
+ @Override
+ protected void setCasePickable() {
+ CaseBoard caseBoard = (CaseBoard) board;
+ Board baseBoard = caseBoard.getBaseBoard();
+
+ for (ElementView elementView : elementViews) {
+ PuzzleElement puzzleElement = baseBoard.getPuzzleElement(elementView.getPuzzleElement());
+ elementView.setPuzzleElement(puzzleElement);
+ elementView.setShowCasePicker(true);
+ elementView.setCaseRulePickable(caseBoard.isPickable(puzzleElement, null));
+ }
+ for (SkyscrapersClueView clueView : northClues) {
+ PuzzleElement puzzleElement = baseBoard.getPuzzleElement(clueView.getPuzzleElement());
+ clueView.setPuzzleElement(puzzleElement);
+ clueView.setShowCasePicker(true);
+ clueView.setCaseRulePickable(caseBoard.isPickable(puzzleElement, null));
+ }
+ for (SkyscrapersClueView clueView : westClues) {
+ PuzzleElement puzzleElement = baseBoard.getPuzzleElement(clueView.getPuzzleElement());
+ clueView.setPuzzleElement(puzzleElement);
+ clueView.setShowCasePicker(true);
+ clueView.setCaseRulePickable(caseBoard.isPickable(puzzleElement, null));
}
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/TODO.md b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/TODO.md
deleted file mode 100644
index 76c86b32f..000000000
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/TODO.md
+++ /dev/null
@@ -1,11 +0,0 @@
-## TODO
-
-- Implement board class (`SkyscrapersBoard.java`)
-- Implement clues class (`SkyscrapersClue.java`)
-- Implement cell generation (`SkyscrapersCellFactory.java`)
-- Implement puzzle exporter (`SkyscrapersExporter.java`)
-- Add way to interact with puzzle (`SkyscrapersCellController.java`)
-- Add vision (`SkyscrapersVision.java`, `SkyscrapersVisionView.java`)
-- Puzzle GUI (`SkyscrapersView.java`, `SkyscrapersElementView.java`, `SkyscrapersClueView.java`)
-- Determine if puzzle is solved
-- Add rules (see Sudoku and the powerpoint)
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
new file mode 100644
index 000000000..01a1557b0
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/CellForNumberCaseRule.java
@@ -0,0 +1,135 @@
+package edu.rpi.legup.puzzle.skyscrapers.rules;
+
+import edu.rpi.legup.model.gameboard.Board;
+import edu.rpi.legup.model.gameboard.CaseBoard;
+import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.model.rules.CaseRule;
+import edu.rpi.legup.model.tree.TreeTransition;
+import edu.rpi.legup.puzzle.skyscrapers.*;
+import org.apache.commons.lang3.ObjectUtils;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+public class CellForNumberCaseRule extends CaseRule {
+ public CellForNumberCaseRule() {
+ super("SKYS-CASE-0002", "Cell For Number",
+ "A number (1-n) must appear in any given row/column",
+ "edu/rpi/legup/images/skyscrapers/cases/CellForNumber.png");
+ }
+
+ private Integer selectedNumber;
+
+ @Override
+ public CaseBoard getCaseBoard(Board board) {
+ SkyscrapersBoard currentBoard = (SkyscrapersBoard) board.copy();
+ currentBoard.setModifiable(false);
+ CaseBoard caseBoard = new CaseBoard(currentBoard, this);
+ for (SkyscrapersClue data : currentBoard.getWestClues()) {
+ //System.out.println(data.getType());
+ caseBoard.addPickableElement(data);
+ }
+ for (SkyscrapersClue data : currentBoard.getNorthClues()) {
+ //System.out.println(data.getType());
+ caseBoard.addPickableElement(data);
+ }
+
+ //selects integer before checking Command.canExecute for use in Command.getErrorString
+ int size = ((SkyscrapersBoard)board).getWidth();
+ Object[] possibleValues = new Object[size];
+ for(int i=0; i getCasesFor(Board board, PuzzleElement puzzleElement, Integer number){
+ ArrayList cases = new ArrayList<>();
+
+ SkyscrapersClue clue = (SkyscrapersClue) puzzleElement;
+ SkyscrapersBoard skyscrapersboard = (SkyscrapersBoard) board;
+
+ List openCells = skyscrapersboard.getRowCol(clue.getClueIndex(),SkyscrapersType.UNKNOWN,clue.getType()==SkyscrapersType.CLUE_WEST);
+ for(SkyscrapersCell cell : openCells){
+ SkyscrapersBoard newCase = skyscrapersboard.copy();
+ PuzzleElement newCell = newCase.getPuzzleElement(cell);
+ newCell.setData(number);
+ newCase.addModifiedData(newCell);
+ newCase.setModClue((SkyscrapersClue)newCase.getPuzzleElement(clue));
+
+ //if flags
+ boolean passed = true;
+ if(skyscrapersboard.getDupeFlag()){
+ DuplicateNumberContradictionRule DupeRule = new DuplicateNumberContradictionRule();
+ passed = passed && DupeRule.checkContradictionAt(newCase,newCell)!=null;
+ }
+ if(skyscrapersboard.getViewFlag()){
+ PreemptiveVisibilityContradictionRule ViewRule = new PreemptiveVisibilityContradictionRule();
+ passed = passed && ViewRule.checkContradictionAt(newCase,newCell)!=null;
+ }
+ if(passed){
+ cases.add(newCase);
+ }
+
+
+ }
+ return cases;
+ }
+
+ @Override
+ public ArrayList getCases(Board board, PuzzleElement puzzleElement) {
+ return getCasesFor(board,puzzleElement,selectedNumber);
+ }
+
+ @Override
+ public String checkRuleRaw(TreeTransition transition) {
+ List childTransitions = transition.getParents().get(0).getChildren();
+ SkyscrapersBoard oldBoard = (SkyscrapersBoard) transition.getParents().get(0).getBoard();
+ if (childTransitions.size() == 0) {
+ return "This case rule must have at least one child.";
+ }
+
+ //find changed row/col
+ SkyscrapersClue modClue = ((SkyscrapersBoard)childTransitions.get(0).getBoard()).getmodClue();
+
+ //System.out.println(modClue.getType());
+ //System.out.println(modClue.getClueIndex());
+ if(childTransitions.size() != getCasesFor(oldBoard,modClue,(Integer) childTransitions.get(0).getBoard().getModifiedData().iterator().next().getData()).size()){
+ //System.out.println("Wrong number of cases.");
+ return "Wrong number of cases.";
+ }
+
+ for(TreeTransition newTree : childTransitions){
+ SkyscrapersBoard newBoard = (SkyscrapersBoard) newTree.getBoard();
+ if(newBoard.getModifiedData().size()!=1){
+ //System.out.println("Only one cell should be modified.");
+ return "Only one cell should be modified.";
+ }
+ SkyscrapersCell newCell = (SkyscrapersCell) newBoard.getModifiedData().iterator().next();
+ if(newCell.getType() != SkyscrapersType.Number){
+ //System.out.println("Changed value should be a number.");
+ return "Changed value should be a number.";
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) {
+ return checkRuleRaw(transition);
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/DuplicateNumberContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/DuplicateNumberContradictionRule.java
index a7df882ff..c0508bf67 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/DuplicateNumberContradictionRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/DuplicateNumberContradictionRule.java
@@ -16,7 +16,7 @@ public class DuplicateNumberContradictionRule extends ContradictionRule {
public DuplicateNumberContradictionRule() {
super("SKYS-CONT-0001", "Duplicate Number",
"Skyscrapers of same height cannot be placed in the same row or column.",
- "edu/rpi/legup/images/skyscrapers/DuplicateNumber.png");
+ "edu/rpi/legup/images/skyscrapers/contradictions/DuplicateNumber.png");
}
/**
@@ -29,7 +29,8 @@ public DuplicateNumberContradictionRule() {
*/
@Override
public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
- SkyscrapersCell cell = (SkyscrapersCell) puzzleElement;
+ //TODO:? Refactor to count each row/col once rather than per cell (override checkContradiction)
+ SkyscrapersCell cell = (SkyscrapersCell) puzzleElement;
SkyscrapersBoard skyscrapersboard = (SkyscrapersBoard) board;
Point loc = cell.getLocation();
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/ExceedingVisibilityContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/ExceedingVisibilityContradictionRule.java
index 9a9c0bf8e..ef8f72711 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/ExceedingVisibilityContradictionRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/ExceedingVisibilityContradictionRule.java
@@ -8,7 +8,9 @@
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
import java.awt.*;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
public class ExceedingVisibilityContradictionRule extends ContradictionRule {
@@ -16,7 +18,7 @@ public class ExceedingVisibilityContradictionRule extends ContradictionRule {
public ExceedingVisibilityContradictionRule() {
super("SKYS-CONT-0002", "Exceeding Visibility",
"More skyscrapers are visible than there should be.",
- "edu/rpi/legup/images/skyscrapers/ExceedingVisibility.png");
+ "edu/rpi/legup/images/skyscrapers/contradictions/ExceedingVisibility.png");
}
/**
@@ -32,92 +34,106 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
SkyscrapersCell cell = (SkyscrapersCell) puzzleElement;
SkyscrapersBoard skyscrapersboard = (SkyscrapersBoard) board;
Point loc = cell.getLocation();
+
+ //get borders
+ int west = skyscrapersboard.getWestClues().get(loc.y).getData();
+ int east = skyscrapersboard.getEastClues().get(loc.y).getData();
+ int north = skyscrapersboard.getNorthClues().get(loc.x).getData();
+ int south = skyscrapersboard.getSouthClues().get(loc.x).getData();
- Set candidates = new HashSet();
+ //check row
+ int max = 0;
+ int count = 0;
+ List row = skyscrapersboard.getRowCol(loc.y,SkyscrapersType.Number,true);
+ if(row.size()==skyscrapersboard.getWidth()){
+ //from west border
+ for(SkyscrapersCell c : row){
+ if (c.getData() > max) {
+ System.out.print(c.getData());
+ //System.out.println(cell.getData());
+ max = c.getData();
+ count++;
+ }
+ }
+ if (count > west) {
+ return null;
+ }
- //check row
- int west = skyscrapersboard.getRow().get(loc.y).getData();
- int east = skyscrapersboard.getRowClues().get(loc.y).getData();
- int north = skyscrapersboard.getCol().get(loc.x).getData();
- int south = skyscrapersboard.getColClues().get(loc.x).getData();
- int max = 0;
- int count = 0;
- boolean complete = true;
- for (int i = 0; i < skyscrapersboard.getWidth(); i++) {
- SkyscrapersCell c = skyscrapersboard.getCell(i, loc.y);
- if (c.getType() == SkyscrapersType.Number && c.getData() > max) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- max = c.getData();
- count++;
- }
- if (c.getType() == SkyscrapersType.UNKNOWN) {
- complete = false;
- }
- }
- if (count > west && complete == true) {
- return null;
- }
+ max = 0;
+ count = 0;
+ //from east border
+ Collections.reverse(row);
+ for(SkyscrapersCell c : row){
+ if (c.getData() > max) {
+ System.out.print(c.getData());
+ //System.out.println(cell.getData());
+ max = c.getData();
+ count++;
+ }
+ }
+ if (count > east) {
+ return null;
+ }
+ }
+
+ //check column
+ List col = skyscrapersboard.getRowCol(loc.x,SkyscrapersType.Number,false);
+ if(col.size()==skyscrapersboard.getHeight()){
+ //from north border
+ max = 0;
+ count = 0;
+ for(SkyscrapersCell c : col){
+ System.out.println(c.getData());
+ if (c.getData() > max) {
- max = 0;
- count = 0;
- complete = true;
- for (int i = skyscrapersboard.getWidth() - 1; i >= 0; i--) {
- SkyscrapersCell c = skyscrapersboard.getCell(i, loc.y);
- if (c.getType() == SkyscrapersType.Number && c.getData() > max) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- max = c.getData();
- count = count + 1;
- }
- if (c.getType() == SkyscrapersType.UNKNOWN) {
- complete = false;
- }
- }
- if (count > east && complete == true) {
- return null;
- }
+ //System.out.println(cell.getData());
+ max = c.getData();
+ count++;
+ }
+ }
+ if (count > north) {
+ return null;
+ }
- // check column
- max = 0;
- count = 0;
- complete = true;
- for (int i = 0; i < skyscrapersboard.getHeight(); i++) {
- SkyscrapersCell c = skyscrapersboard.getCell(loc.x, i);
- if (c.getType() == SkyscrapersType.Number && c.getData() > max) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- max = c.getData();
- count = count + 1;
- }
- if (c.getType() == SkyscrapersType.UNKNOWN) {
- complete = false;
- }
- }
- if (count > north && complete == true) {
- return null;
- }
-
- max = 0;
- count = 0;
- complete = true;
- for (int i = skyscrapersboard.getHeight() - 1; i >= 0; i--) {
- SkyscrapersCell c = skyscrapersboard.getCell(loc.x, i);
- if (c.getType() == SkyscrapersType.Number && c.getData() > max) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- max = c.getData();
- count = count + 1;
- }
- if (c.getType() == SkyscrapersType.UNKNOWN) {
- complete = false;
- }
- }
- if (count > south && complete == true) {
- return null;
- }
+ //from south border
+ max = 0;
+ count = 0;
+ Collections.reverse(col);
+ for(SkyscrapersCell c : col){
+ System.out.println(c.getData());
+ if (c.getData() > max) {
+ //System.out.println(cell.getData());
+ max = c.getData();
+ count++;
+ }
+ }
+ if (count > south) {
+ return null;
+ }
+ }
+
//System.out.print("Does not contain a contradiction at this index");
return super.getNoContradictionMessage();
}
+
+ /**
+ * Checks whether the Skyscraper cell has a contradiction using this rule
+ *
+ * @param board board to check contradiction
+ * @return null if the Skyscraper cell contains a contradiction, otherwise error message
+ */
+ @Override
+ public String checkContradiction(Board board) {
+ SkyscrapersBoard skyscrapersBoard = (SkyscrapersBoard) board;
+ for (int i = 0; i < skyscrapersBoard.getWidth(); i++) {
+ //checks the middle diagonal (checkContradictionAt checks row/col off each)
+ String checkStr = checkContradictionAt(board, skyscrapersBoard.getCell(i,i));
+ if (checkStr == null) {
+ return checkStr;
+ }
+ }
+ return "No instance of the contradiction " + this.ruleName + " here";
+ }
+
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/InsufficientVisibilityContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/InsufficientVisibilityContradictionRule.java
index ef0968710..fb3764a2b 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/InsufficientVisibilityContradictionRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/InsufficientVisibilityContradictionRule.java
@@ -8,7 +8,9 @@
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
import java.awt.*;
+import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
public class InsufficientVisibilityContradictionRule extends ContradictionRule {
@@ -16,7 +18,7 @@ public class InsufficientVisibilityContradictionRule extends ContradictionRule {
public InsufficientVisibilityContradictionRule() {
super("SKYS-CONT-0003", "Insufficient Visibility",
"Less skyscrapers are visible than there should be.",
- "edu/rpi/legup/images/skyscrapers/InsufficientVisibility.png");
+ "edu/rpi/legup/images/skyscrapers/contradictions/InsufficientVisibility.png");
}
/**
@@ -33,91 +35,104 @@ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
SkyscrapersBoard skyscrapersboard = (SkyscrapersBoard) board;
Point loc = cell.getLocation();
- Set candidates = new HashSet();
+ //get borders
+ int west = skyscrapersboard.getWestClues().get(loc.y).getData();
+ int east = skyscrapersboard.getEastClues().get(loc.y).getData();
+ int north = skyscrapersboard.getNorthClues().get(loc.x).getData();
+ int south = skyscrapersboard.getSouthClues().get(loc.x).getData();
- //check row
- int west = skyscrapersboard.getRow().get(loc.y).getData();
- int east = skyscrapersboard.getRowClues().get(loc.y).getData();
- int north = skyscrapersboard.getCol().get(loc.x).getData();
- int south = skyscrapersboard.getColClues().get(loc.x).getData();
- int max = 0;
- int count = 0;
- boolean complete = true;
- for (int i = 0; i < skyscrapersboard.getWidth(); i++) {
- SkyscrapersCell c = skyscrapersboard.getCell(i, loc.y);
- if (c.getType() == SkyscrapersType.Number && c.getData() > max) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- max = c.getData();
- count++;
- }
- if (c.getType() == SkyscrapersType.UNKNOWN) {
- complete = false;
- }
- }
- if (count < west && complete == true) {
- return null;
- }
+ //check row
+ int max = 0;
+ int count = 0;
+ java.util.List row = skyscrapersboard.getRowCol(loc.y,SkyscrapersType.Number,true);
+ if(row.size()==skyscrapersboard.getWidth()){
+ //from west border
+ for(SkyscrapersCell c : row){
+ if (c.getData() > max) {
+ System.out.print(c.getData());
+ //System.out.println(cell.getData());
+ max = c.getData();
+ count++;
+ }
+ }
+ if (count < west) {
+ return null;
+ }
- max = 0;
- count = 0;
- complete = true;
- for (int i = skyscrapersboard.getWidth() - 1; i >= 0; i--) {
- SkyscrapersCell c = skyscrapersboard.getCell(i, loc.y);
- if (c.getType() == SkyscrapersType.Number && c.getData() > max) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- max = c.getData();
- count = count + 1;
- }
- if (c.getType() == SkyscrapersType.UNKNOWN) {
- complete = false;
- }
- }
- if (count < east && complete == true) {
- return null;
- }
+ max = 0;
+ count = 0;
+ //from east border
+ Collections.reverse(row);
+ for(SkyscrapersCell c : row){
+ if (c.getData() > max) {
+ System.out.print(c.getData());
+ //System.out.println(cell.getData());
+ max = c.getData();
+ count++;
+ }
+ }
+ if (count < east) {
+ return null;
+ }
+ }
- // check column
- max = 0;
- count = 0;
- complete = true;
- for (int i = 0; i < skyscrapersboard.getHeight(); i++) {
- SkyscrapersCell c = skyscrapersboard.getCell(loc.x, i);
- if (c.getType() == SkyscrapersType.Number && c.getData() > max) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- max = c.getData();
- count = count + 1;
- }
- if (c.getType() == SkyscrapersType.UNKNOWN) {
- complete = false;
- }
- }
- if (count < north && complete == true) {
- return null;
- }
+ //check column
+ List col = skyscrapersboard.getRowCol(loc.x,SkyscrapersType.Number,false);
+ if(col.size()==skyscrapersboard.getHeight()){
+ //from north border
+ max = 0;
+ count = 0;
+ for(SkyscrapersCell c : col){
+ System.out.println(c.getData());
+ if (c.getData() > max) {
- max = 0;
- count = 0;
- complete = true;
- for (int i = skyscrapersboard.getHeight() - 1; i >= 0; i--) {
- SkyscrapersCell c = skyscrapersboard.getCell(loc.x, i);
- if (c.getType() == SkyscrapersType.Number && c.getData() > max) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- max = c.getData();
- count = count + 1;
- }
- if (c.getType() == SkyscrapersType.UNKNOWN) {
- complete = false;
- }
- }
- if (count < south && complete == true) {
- return null;
- }
+ //System.out.println(cell.getData());
+ max = c.getData();
+ count++;
+ }
+ }
+ if (count < north) {
+ return null;
+ }
+ //from south border
+ max = 0;
+ count = 0;
+ Collections.reverse(col);
+ for(SkyscrapersCell c : col){
+ System.out.println(c.getData());
+ if (c.getData() > max) {
+
+ //System.out.println(cell.getData());
+ max = c.getData();
+ count++;
+ }
+ }
+ if (count < south) {
+ return null;
+ }
+ }
+
//System.out.print("Does not contain a contradiction at this index");
return super.getNoContradictionMessage();
}
+
+ /**
+ * Checks whether the Skyscraper cell has a contradiction using this rule
+ *
+ * @param board board to check contradiction
+ * @return null if the Skyscraper cell contains a contradiction, otherwise error message
+ */
+ @Override
+ public String checkContradiction(Board board) {
+ SkyscrapersBoard skyscrapersBoard = (SkyscrapersBoard) board;
+ for (int i = 0; i < skyscrapersBoard.getWidth(); i++) {
+ //checks the middle diagonal (checkContradictionAt checks row/col off each)
+ String checkStr = checkContradictionAt(board, skyscrapersBoard.getCell(i,i));
+ if (checkStr == null) {
+ return checkStr;
+ }
+ }
+ return "No instance of the contradiction " + this.ruleName + " here";
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastCellBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastCellBasicRule.java
deleted file mode 100644
index 524c36319..000000000
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastCellBasicRule.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package edu.rpi.legup.puzzle.skyscrapers.rules;
-
-import edu.rpi.legup.model.gameboard.Board;
-import edu.rpi.legup.model.gameboard.PuzzleElement;
-import edu.rpi.legup.model.rules.BasicRule;
-import edu.rpi.legup.model.tree.TreeNode;
-import edu.rpi.legup.model.tree.TreeTransition;
-import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersBoard;
-import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell;
-import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
-
-import java.awt.Point;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-public class LastCellBasicRule extends BasicRule {
-
- public LastCellBasicRule() {
- super("SKYS-BASC-0002", "Last Cell",
- "A certain number must go in a certain cell, because that cell is the last place that number can appear in that row/column.",
- "edu/rpi/legup/images/skyscrapers/LastCell.png");
- }
-
- /**
- * Checks whether the child node logically follows from the parent node
- * at the specific puzzleElement index using this rule
- *
- * @param transition transition to check
- * @param puzzleElement index of the puzzleElement
- * @return null if the child node logically follow from the parent node at the specified puzzleElement,
- * otherwise error message
- */
- @Override
- public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) {
- SkyscrapersBoard initialBoard = (SkyscrapersBoard) transition.getParents().get(0).getBoard();
- SkyscrapersCell initCell = (SkyscrapersCell) initialBoard.getPuzzleElement(puzzleElement);
- SkyscrapersBoard finalBoard = (SkyscrapersBoard) transition.getBoard();
- SkyscrapersCell finalCell = (SkyscrapersCell) finalBoard.getPuzzleElement(puzzleElement);
- if (!(initCell.getType() == SkyscrapersType.UNKNOWN && finalCell.getType() == SkyscrapersType.Number)) {
- return super.getInvalidUseOfRuleMessage() + ": Modified cells must be number";
- }
-
- SkyscrapersBoard emptyCase = initialBoard.copy();
- emptyCase.getPuzzleElement(finalCell).setData(0);
- Point loc = finalCell.getLocation();
-
- Set candidates = new HashSet();
- for (int i = 1; i <= initialBoard.getWidth(); i++) {
- candidates.add(i);
- }
-
- //check row
- for (int i = 0; i < initialBoard.getWidth(); i++) {
- SkyscrapersCell c = initialBoard.getCell(i, loc.y);
- if (i != loc.x && c.getType() == SkyscrapersType.Number) {
- candidates.remove(c.getData());
- //System.out.print(c.getData());
- //System.out.println(finalCell.getData());
- }
- }
- if (candidates.size() == 1) {
- Iterator it = candidates.iterator();
- if (it.next() == finalCell.getData()) {
- return null;
- }
- return super.getInvalidUseOfRuleMessage() + ": Wrong number in the cell.";
- }
-
- candidates.clear();
- for (int i = 1; i <= initialBoard.getWidth(); i++) {
- candidates.add(i);
- }
-
- // check column
- for (int i = 0; i < initialBoard.getHeight(); i++) {
- SkyscrapersCell c = initialBoard.getCell(loc.x, i);
- if (i != loc.y && c.getType() == SkyscrapersType.Number) {
- candidates.remove(c.getData());
- //System.out.print(c.getData());
- //System.out.println(finalCell.getData());
- }
- }
- if (candidates.size() == 1) {
- Iterator it = candidates.iterator();
- if (it.next() == finalCell.getData()) {
- return null;
- }
- return super.getInvalidUseOfRuleMessage() + ": Wrong number in the cell.";
- }
-
- return super.getInvalidUseOfRuleMessage() + ": This cell is not forced.";
- }
-
- private boolean isForced(SkyscrapersBoard board, SkyscrapersCell cell) {
- SkyscrapersBoard emptyCase = board.copy();
- emptyCase.getPuzzleElement(cell).setData(0);
- DuplicateNumberContradictionRule duplicate = new DuplicateNumberContradictionRule();
- if (duplicate.checkContradictionAt(emptyCase, cell) == null) {
- System.out.println("no contradiction ln");
- return true;
- }
- return false;
- }
-
- /**
- * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}.
- *
- * @param node tree node used to create default transition board
- * @return default board or null if this rule cannot be applied to this tree node
- */
- @Override
- public Board getDefaultBoard(TreeNode node) {
- SkyscrapersBoard initialBoard = (SkyscrapersBoard) node.getBoard();
- SkyscrapersBoard lightUpBoard = (SkyscrapersBoard) node.getBoard().copy();
- System.out.println(lightUpBoard.getPuzzleElements().size());
- for (PuzzleElement element : lightUpBoard.getPuzzleElements()) {
- System.out.println("123");
- SkyscrapersCell cell = (SkyscrapersCell) element;
- if (cell.getType() == SkyscrapersType.UNKNOWN && isForced(initialBoard, cell)) {
- //cell.setData(SkyscrapersType.BULB.value);
- lightUpBoard.addModifiedData(cell);
- }
- }
- if (lightUpBoard.getModifiedData().isEmpty()) {
- return null;
- }
- else {
- return lightUpBoard;
- }
- }
-}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastNumberBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastSingularCellBasicRule.java
similarity index 58%
rename from src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastNumberBasicRule.java
rename to src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastSingularCellBasicRule.java
index a4f36cd04..727559083 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastNumberBasicRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastSingularCellBasicRule.java
@@ -9,17 +9,14 @@
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell;
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
-import java.awt.Point;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+import java.util.ArrayList;
-public class LastNumberBasicRule extends BasicRule {
+public class LastSingularCellBasicRule extends BasicRule {
- public LastNumberBasicRule() {
- super("SKYS-BASC-0003", "Last Number",
- "A certain cell must contain a certain number since that number is the only one that can possibly appear in that cell.",
- "edu/rpi/legup/images/skyscrapers/LastNumber.png");
+ public LastSingularCellBasicRule() {
+ super("SKYS-BASC-0002", "Last Non-Duplicate Cell",
+ "There is only one cell on this row/col for this number that does not create a duplicate contradiction",
+ "edu/rpi/legup/images/skyscrapers/rules/LastCell.png");
}
/**
@@ -41,45 +38,41 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
return super.getInvalidUseOfRuleMessage() + ": Modified cells must be number";
}
- SkyscrapersBoard emptyCase = initialBoard.copy();
- emptyCase.getPuzzleElement(finalCell).setData(0);
- Point loc = finalCell.getLocation();
+ //set all rules used by case rule to false except for dupe, get all cases
+ boolean dupeTemp = initialBoard.getDupeFlag();
+ boolean viewTemp = initialBoard.getViewFlag();
+ initialBoard.setDupeFlag(true);
+ initialBoard.setViewFlag(false);
+ CellForNumberCaseRule caseRule = new CellForNumberCaseRule();
+ ArrayList XCandidates = caseRule.getCasesFor(initialBoard,initialBoard.getWestClues().get(finalCell.getLocation().y),(Integer)finalCell.getData());
+ ArrayList YCandidates = caseRule.getCasesFor(initialBoard,initialBoard.getNorthClues().get(finalCell.getLocation().x),(Integer)finalCell.getData());
+ initialBoard.setDupeFlag(dupeTemp);
+ initialBoard.setViewFlag(viewTemp);
- Set candidates = new HashSet();
- for (int i = 1; i <= initialBoard.getWidth(); i++) {
- candidates.add(i);
- }
+ System.out.println(XCandidates.size());
+ System.out.println(YCandidates.size());
- //check row
- for (int i = 0; i < initialBoard.getWidth(); i++) {
- SkyscrapersCell c = initialBoard.getCell(i, loc.y);
- if (i != loc.x && c.getType() == SkyscrapersType.Number) {
- candidates.remove(c.getData());
- //System.out.print(c.getData());
- //System.out.println(finalCell.getData());
- }
- }
-
- // check column
- for (int i = 0; i < initialBoard.getHeight(); i++) {
- SkyscrapersCell c = initialBoard.getCell(loc.x, i);
- if (i != loc.y && c.getType() == SkyscrapersType.Number) {
- candidates.remove(c.getData());
- //System.out.print(c.getData());
- //System.out.println(finalCell.getData());
- }
+ //return null if either pass, both messages otherwise
+ String xCheck = candidateCheck(XCandidates,puzzleElement,finalCell);
+ String yCheck = candidateCheck(YCandidates,puzzleElement,finalCell);
+ if(xCheck==null || yCheck==null){
+ return null;
}
+ return super.getInvalidUseOfRuleMessage() + "\nRow" + xCheck + "\nCol" + yCheck;
+ }
- DuplicateNumberContradictionRule duplicate = new DuplicateNumberContradictionRule();
- if (candidates.size() == 1 && duplicate.checkContradictionAt(emptyCase, finalCell) != null) {
- Iterator it = candidates.iterator();
- if (it.next() == finalCell.getData()) {
- return null;
+ //helper to check if candidate list is valid
+ private String candidateCheck(ArrayList candidates,PuzzleElement puzzleElement, SkyscrapersCell finalCell){
+ if(candidates.size() == 1){
+ if(((SkyscrapersCell) candidates.get(0).getPuzzleElement(puzzleElement)).getType() == SkyscrapersType.Number) {
+ if (candidates.get(0).getPuzzleElement(puzzleElement).getData() == finalCell.getData()) {
+ return null;
+ }
+ return ": Wrong number in the cell.";
}
- return super.getInvalidUseOfRuleMessage() + ": Wrong number in the cell.";
+ return ": No case for this cell.";
}
-
- return super.getInvalidUseOfRuleMessage() + ":This cell is not forced.";
+ return ": This cell is not forced.";
}
private boolean isForced(SkyscrapersBoard board, SkyscrapersCell cell) {
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/OneEdgeBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastSingularNumberBasicRule.java
similarity index 63%
rename from src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/OneEdgeBasicRule.java
rename to src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastSingularNumberBasicRule.java
index f883d7cee..248998e84 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/OneEdgeBasicRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastSingularNumberBasicRule.java
@@ -9,17 +9,14 @@
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell;
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
-import java.awt.Point;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+import java.util.ArrayList;
-public class OneEdgeBasicRule extends BasicRule {
+public class LastSingularNumberBasicRule extends BasicRule {
- public OneEdgeBasicRule() {
- super("SKYS-BASC-0005", "One Edge",
- "If you have a 1 on an edge, put n in the adjacent square.",
- "edu/rpi/legup/images/skyscrapers/OneEdge.png");
+ public LastSingularNumberBasicRule() {
+ super("SKYS-BASC-0003", "Last Non-Duplicate Number",
+ "There is only one number for this cell that does not create a duplicate contradiction",
+ "edu/rpi/legup/images/skyscrapers/rules/LastNumber.png");
}
/**
@@ -37,44 +34,28 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
SkyscrapersCell initCell = (SkyscrapersCell) initialBoard.getPuzzleElement(puzzleElement);
SkyscrapersBoard finalBoard = (SkyscrapersBoard) transition.getBoard();
SkyscrapersCell finalCell = (SkyscrapersCell) finalBoard.getPuzzleElement(puzzleElement);
- if (!(initCell.getType() == SkyscrapersType.UNKNOWN && finalCell.getType() == SkyscrapersType.Number)) {
- return super.getInvalidUseOfRuleMessage() + ": Modified cells must be number";
+ if (initCell.getType() != SkyscrapersType.UNKNOWN || finalCell.getType() != SkyscrapersType.Number) {
+ return super.getInvalidUseOfRuleMessage() + ": Modified cells must transition from unknown to number";
}
- SkyscrapersBoard emptyCase = initialBoard.copy();
- emptyCase.getPuzzleElement(finalCell).setData(0);
- Point loc = finalCell.getLocation();
+ //set all rules used by case rule to false except for dupe, get all cases
+ boolean dupeTemp = initialBoard.getDupeFlag();
+ boolean viewTemp = initialBoard.getViewFlag();
+ initialBoard.setDupeFlag(true);
+ initialBoard.setViewFlag(false);
+ NumberForCellCaseRule caseRule = new NumberForCellCaseRule();
+ ArrayList candidates = caseRule.getCases(initialBoard,puzzleElement);
+ initialBoard.setDupeFlag(dupeTemp);
+ initialBoard.setViewFlag(viewTemp);
- if (loc.x != 0 && loc.x != initialBoard.getWidth() - 1 && loc.y != 0 && loc.y != initialBoard.getHeight() - 1) {
- return super.getInvalidUseOfRuleMessage() + ": Modified cells must be on the edge";
- }
-
- if (finalCell.getData() != initialBoard.getWidth()) {
- return super.getInvalidUseOfRuleMessage() + ": Modified cells must be the max";
- }
-
- if (loc.x == 0 && initialBoard.getRow().get(loc.y).getData() == 1) {
- return null;
- }
- else {
- if (loc.x == initialBoard.getWidth() - 1 && initialBoard.getRowClues().get(loc.y).getData() == 1) {
+ //check if given value is the only remaining value
+ if(candidates.size() == 1){
+ if(candidates.get(0).getPuzzleElement(puzzleElement).getData() == finalCell.getData()){
return null;
}
- else {
- if (loc.y == 0 && initialBoard.getCol().get(loc.x).getData() == 1) {
- return null;
- }
- else {
- if (loc.y == initialBoard.getHeight() - 1 && initialBoard.getColClues().get(loc.x).getData() == 1) {
- return null;
- }
- else {
- return "This cell is not forced.";
- }
- }
- }
+ return super.getInvalidUseOfRuleMessage() + ": Wrong number in the cell.";
}
-
+ return super.getInvalidUseOfRuleMessage() + ":This cell is not forced.";
}
private boolean isForced(SkyscrapersBoard board, SkyscrapersCell cell) {
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastVisibleCellBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastVisibleCellBasicRule.java
new file mode 100644
index 000000000..d28ed6cbd
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastVisibleCellBasicRule.java
@@ -0,0 +1,117 @@
+package edu.rpi.legup.puzzle.skyscrapers.rules;
+
+import edu.rpi.legup.model.gameboard.Board;
+import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.model.rules.BasicRule;
+import edu.rpi.legup.model.tree.TreeNode;
+import edu.rpi.legup.model.tree.TreeTransition;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersBoard;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
+
+import java.util.ArrayList;
+
+public class LastVisibleCellBasicRule extends BasicRule {
+
+ public LastVisibleCellBasicRule() {
+ super("SKYS-BASC-0001", "Last Visible Cell",
+ "There is only one cell on this row/col for this number that does not create a visibility contradiction",
+ "edu/rpi/legup/images/skyscrapers/rules/FixedMax.png");
+ }
+
+ /**
+ * Checks whether the child node logically follows from the parent node
+ * at the specific puzzleElement index using this rule
+ *
+ * @param transition transition to check
+ * @param puzzleElement index of the puzzleElement
+ * @return null if the child node logically follow from the parent node at the specified puzzleElement,
+ * otherwise error message
+ */
+ @Override
+ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) {
+ //last cell for number based on preemptive visibility rules
+ SkyscrapersBoard initialBoard = (SkyscrapersBoard) transition.getParents().get(0).getBoard();
+ SkyscrapersCell initCell = (SkyscrapersCell) initialBoard.getPuzzleElement(puzzleElement);
+ SkyscrapersBoard finalBoard = (SkyscrapersBoard) transition.getBoard();
+ SkyscrapersCell finalCell = (SkyscrapersCell) finalBoard.getPuzzleElement(puzzleElement);
+ if (initCell.getType() != SkyscrapersType.UNKNOWN || finalCell.getType() != SkyscrapersType.Number) {
+ return super.getInvalidUseOfRuleMessage() + ": Modified cells must transition from unknown to number";
+ }
+
+ //set all rules used by case rule to false except for dupe, get all cases
+ boolean dupeTemp = initialBoard.getDupeFlag();
+ boolean viewTemp = initialBoard.getViewFlag();
+ initialBoard.setDupeFlag(false);
+ initialBoard.setViewFlag(true);
+ CellForNumberCaseRule caseRule = new CellForNumberCaseRule();
+ ArrayList XCandidates = caseRule.getCasesFor(initialBoard,initialBoard.getWestClues().get(finalCell.getLocation().y),(Integer)finalCell.getData());
+ ArrayList YCandidates = caseRule.getCasesFor(initialBoard,initialBoard.getNorthClues().get(finalCell.getLocation().x),(Integer)finalCell.getData());
+ initialBoard.setDupeFlag(dupeTemp);
+ initialBoard.setViewFlag(viewTemp);
+
+ System.out.println(XCandidates.size());
+ System.out.println(YCandidates.size());
+
+ //return null if either pass, both messages otherwise
+ String xCheck = candidateCheck(XCandidates,puzzleElement,finalCell);
+ String yCheck = candidateCheck(YCandidates,puzzleElement,finalCell);
+ if(xCheck==null || yCheck==null){
+ return null;
+ }
+ return super.getInvalidUseOfRuleMessage() + "\nRow" + xCheck + "\nCol" + yCheck;
+ }
+
+ //helper to check if candidate list is valid
+ private String candidateCheck(ArrayList candidates,PuzzleElement puzzleElement, SkyscrapersCell finalCell){
+ if(candidates.size() == 1){
+ if(((SkyscrapersCell) candidates.get(0).getPuzzleElement(puzzleElement)).getType() == SkyscrapersType.Number) {
+ if (candidates.get(0).getPuzzleElement(puzzleElement).getData() == finalCell.getData()) {
+ return null;
+ }
+ return ": Wrong number in the cell.";
+ }
+ return ": No case for this cell.";
+ }
+ return ": This cell is not forced.";
+ }
+
+ private boolean isForced(SkyscrapersBoard board, SkyscrapersCell cell) {
+ SkyscrapersBoard emptyCase = board.copy();
+ emptyCase.getPuzzleElement(cell).setData(0);
+ DuplicateNumberContradictionRule duplicate = new DuplicateNumberContradictionRule();
+ if (duplicate.checkContradictionAt(emptyCase, cell) == null) {
+ System.out.println("no contradiction ln");
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Creates a transition {@link Board} that has this rule applied to it using the {@link TreeNode}.
+ *
+ * @param node tree node used to create default transition board
+ * @return default board or null if this rule cannot be applied to this tree node
+ */
+ @Override
+ public Board getDefaultBoard(TreeNode node) {
+ SkyscrapersBoard initialBoard = (SkyscrapersBoard) node.getBoard();
+ SkyscrapersBoard modBoard = (SkyscrapersBoard) node.getBoard().copy();
+ System.out.println(modBoard.getPuzzleElements().size());
+ for (PuzzleElement element : modBoard.getPuzzleElements()) {
+ System.out.println("123");
+ SkyscrapersCell cell = (SkyscrapersCell) element;
+ if (cell.getType() == SkyscrapersType.UNKNOWN && isForced(initialBoard, cell)) {
+ //cell.setData(SkyscrapersType.BULB.value);
+ modBoard.addModifiedData(cell);
+ }
+ }
+ System.out.println(modBoard.getModifiedData().isEmpty());
+ if (modBoard.getModifiedData().isEmpty()) {
+ return null;
+ }
+ else {
+ return modBoard;
+ }
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/FixedMaxBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastVisibleNumberBasicRule.java
similarity index 63%
rename from src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/FixedMaxBasicRule.java
rename to src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastVisibleNumberBasicRule.java
index 85b6fe62d..7a4a7210a 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/FixedMaxBasicRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/LastVisibleNumberBasicRule.java
@@ -9,17 +9,14 @@
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell;
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
-import java.awt.Point;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+import java.util.ArrayList;
-public class FixedMaxBasicRule extends BasicRule {
+public class LastVisibleNumberBasicRule extends BasicRule {
- public FixedMaxBasicRule() {
- super("SKYS-BASC-0001", "Fixed Max",
- "If the sum of two opposing edges is n+1, the maximum number appears at a position k spaces away from the edge, where k is the number at that edge.",
- "edu/rpi/legup/images/skyscrapers/FixedMax.png");
+ public LastVisibleNumberBasicRule() {
+ super("SKYS-BASC-0005", "Last Visible Number",
+ "There is only one number for this cell that does not create a visibility contradiction",
+ "edu/rpi/legup/images/skyscrapers/rules/OneEdge.png");
}
/**
@@ -33,42 +30,33 @@ public FixedMaxBasicRule() {
*/
@Override
public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElement) {
+ //last number for cell based upon preemptive visibility rules
SkyscrapersBoard initialBoard = (SkyscrapersBoard) transition.getParents().get(0).getBoard();
SkyscrapersCell initCell = (SkyscrapersCell) initialBoard.getPuzzleElement(puzzleElement);
SkyscrapersBoard finalBoard = (SkyscrapersBoard) transition.getBoard();
SkyscrapersCell finalCell = (SkyscrapersCell) finalBoard.getPuzzleElement(puzzleElement);
- if (!(initCell.getType() == SkyscrapersType.UNKNOWN && finalCell.getType() == SkyscrapersType.Number)) {
- return super.getInvalidUseOfRuleMessage() + ": Modified cells must be number";
+ if (initCell.getType() != SkyscrapersType.UNKNOWN || finalCell.getType() != SkyscrapersType.Number) {
+ return super.getInvalidUseOfRuleMessage() + ": Modified cells must transition from unknown to number";
}
- SkyscrapersBoard emptyCase = initialBoard.copy();
- emptyCase.getPuzzleElement(finalCell).setData(0);
- Point loc = finalCell.getLocation();
- int north = initialBoard.getCol().get(loc.x).getData();
- int south = initialBoard.getColClues().get(loc.x).getData();
- int west = initialBoard.getRow().get(loc.y).getData();
- int east = initialBoard.getRowClues().get(loc.y).getData();
- int max = initialBoard.getHeight();
- System.out.println(north);
- System.out.println(south);
- if (north + south != max + 1 && west + east != max + 1) {
- System.out.println("111");
- return super.getInvalidUseOfRuleMessage() + ": Opposing clues must add up to max";
- }
-
- if (finalCell.getData() != initialBoard.getWidth()) {
- return super.getInvalidUseOfRuleMessage() + ": Modified cells must be the max";
- }
+ //set all rules used by case rule to false except for dupe, get all cases
+ boolean dupeTemp = initialBoard.getDupeFlag();
+ boolean viewTemp = initialBoard.getViewFlag();
+ initialBoard.setDupeFlag(false);
+ initialBoard.setViewFlag(true);
+ NumberForCellCaseRule caseRule = new NumberForCellCaseRule();
+ ArrayList candidates = caseRule.getCases(initialBoard,puzzleElement);
+ initialBoard.setDupeFlag(dupeTemp);
+ initialBoard.setViewFlag(viewTemp);
- if (north + south == max + 1 && loc.y + 1 == north) {
- return null;
- }
- if (west + east == max + 1 && loc.x + 1 == west) {
- return null;
+ //check if given value is the only remaining value
+ if(candidates.size() == 1){
+ if(candidates.get(0).getPuzzleElement(puzzleElement).getData() == finalCell.getData()){
+ return null;
+ }
+ return super.getInvalidUseOfRuleMessage() + ": Wrong number in the cell.";
}
-
- return super.getInvalidUseOfRuleMessage() + ": This cell is not forced.";
-
+ return super.getInvalidUseOfRuleMessage() + ":This cell is not forced.";
}
private boolean isForced(SkyscrapersBoard board, SkyscrapersCell cell) {
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NEdgeBasicRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NEdgeBasicRule.java
index d5c58220e..3bea76813 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NEdgeBasicRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NEdgeBasicRule.java
@@ -19,7 +19,7 @@ public class NEdgeBasicRule extends BasicRule {
public NEdgeBasicRule() {
super("SKYS-BASC-0004", "N Edge",
"If the maximum number appears on an edge, the row or column��s numbers appear in ascending order, starting at that edge.",
- "edu/rpi/legup/images/skyscrapers/NEdge.png");
+ "edu/rpi/legup/images/skyscrapers/rules/NEdge.png");
}
/**
@@ -46,16 +46,16 @@ public String checkRuleRawAt(TreeTransition transition, PuzzleElement puzzleElem
Point loc = finalCell.getLocation();
int max = initialBoard.getHeight();
- if (initialBoard.getRow().get(loc.y).getData() == max && finalCell.getData() == loc.x + 1) {
+ if (initialBoard.getWestClues().get(loc.y).getData() == max && finalCell.getData() == loc.x + 1) {
return null;
}
- if (initialBoard.getRowClues().get(loc.y).getData() == max && finalCell.getData() == max - loc.x) {
+ if (initialBoard.getEastClues().get(loc.y).getData() == max && finalCell.getData() == max - loc.x) {
return null;
}
- if (initialBoard.getCol().get(loc.x).getData() == max && finalCell.getData() == loc.y + 1) {
+ if (initialBoard.getNorthClues().get(loc.x).getData() == max && finalCell.getData() == loc.y + 1) {
return null;
}
- if (initialBoard.getColClues().get(loc.x).getData() == max && finalCell.getData() == max - loc.y) {
+ if (initialBoard.getSouthClues().get(loc.x).getData() == max && finalCell.getData() == max - loc.y) {
return null;
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/PossibleContentsCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java
similarity index 75%
rename from src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/PossibleContentsCaseRule.java
rename to src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java
index eb106ec05..abf6a10b0 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/PossibleContentsCaseRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/NumberForCellCaseRule.java
@@ -9,17 +9,18 @@
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell;
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
-import java.awt.Point;
+import java.awt.*;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
-import java.util.*;
+import java.util.Set;
-public class PossibleContentsCaseRule extends CaseRule {
+public class NumberForCellCaseRule extends CaseRule {
- public PossibleContentsCaseRule() {
- super("SKYS-CASE-0001", "Possible Contents",
- "Each blank cell is could have height of 1 to n.",
- "edu/rpi/legup/images/skyscrapers/PossibleContents.png");
+ public NumberForCellCaseRule() {
+ super("SKYS-CASE-0001", "Number For Cell",
+ "A blank cell must have height of 1 to n.",
+ "edu/rpi/legup/images/skyscrapers/cases/NumberForCell.png");
}
@Override
@@ -52,29 +53,25 @@ public ArrayList getCases(Board board, PuzzleElement puzzleElement) {
Set candidates = new HashSet();
for (int i = 1; i <= skyscrapersboard.getWidth(); i++) {
- candidates.add(i);
- }
+ Board newCase = board.copy();
+ PuzzleElement newCell = newCase.getPuzzleElement(puzzleElement);
+ newCell.setData(i);
+ newCase.addModifiedData(newCell);
- for (int i = 0; i < skyscrapersboard.getWidth(); i++) {
- SkyscrapersCell c = skyscrapersboard.getCell(i, loc.y);
- if (c.getType() == SkyscrapersType.Number) {
- candidates.remove(c.getData());
+ //if flags
+ boolean passed = true;
+ if(skyscrapersboard.getDupeFlag()){
+ DuplicateNumberContradictionRule DupeRule = new DuplicateNumberContradictionRule();
+ passed = passed && DupeRule.checkContradictionAt(newCase,newCell)!=null;
}
- }
- for (int i = 0; i < skyscrapersboard.getHeight(); i++) {
- SkyscrapersCell c = skyscrapersboard.getCell(loc.x, i);
- if (c.getType() == SkyscrapersType.Number) {
- candidates.remove(c.getData());
+ if(skyscrapersboard.getViewFlag()){
+ PreemptiveVisibilityContradictionRule ViewRule = new PreemptiveVisibilityContradictionRule();
+ passed = passed && ViewRule.checkContradictionAt(newCase,newCell)!=null;
+ }
+ //how should unresolved be handled? should it be?
+ if(passed){
+ cases.add(newCase);
}
- }
-
- Iterator it = candidates.iterator();
- while (it.hasNext()) {
- Board case1 = board.copy();
- PuzzleElement data = case1.getPuzzleElement(puzzleElement);
- data.setData(it.next());
- case1.addModifiedData(data);
- cases.add(case1);
}
return cases;
@@ -93,6 +90,9 @@ public String checkRuleRaw(TreeTransition transition) {
//System.out.println("0");
return "This case rule must have at least one child.";
}
+ else if (childTransitions.size() != getCases(transition.getBoard(), childTransitions.get(0).getBoard().getModifiedData().iterator().next()).size()){
+ return "Wrong number of children.";
+ }
//TreeTransition case1 = childTransitions.get(0);
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/PreemptiveVisibilityContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/PreemptiveVisibilityContradictionRule.java
new file mode 100644
index 000000000..1d96b3ed6
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/PreemptiveVisibilityContradictionRule.java
@@ -0,0 +1,193 @@
+package edu.rpi.legup.puzzle.skyscrapers.rules;
+
+import edu.rpi.legup.model.gameboard.Board;
+import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.model.rules.ContradictionRule;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersBoard;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
+
+import java.awt.*;
+import java.util.Queue;
+import java.util.LinkedList;
+import java.util.List;
+
+public class PreemptiveVisibilityContradictionRule extends ContradictionRule {
+
+ public PreemptiveVisibilityContradictionRule() {
+ super("SKYS-CONT-0006", "Preemptive Visibility",
+ "Visibility constraints are not met given an incomplete row/col",
+ "edu/rpi/legup/images/skyscrapers/contradictions/PreemptiveVisibility.png");
+ }
+
+ /**
+ * Checks whether there is an instance of a visibility contradiction in every possible row/col based on the specific
+ * puzzleElement index using this rule
+ *
+ * @param board board to check contradiction
+ * @param puzzleElement equivalent puzzleElement
+ * @return null if the all possible rows/cols contain a contradiction at the specified puzzleElement,
+ * otherwise error message
+ */
+ @Override
+ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
+ SkyscrapersBoard skyscrapersBoard = (SkyscrapersBoard) board;
+ SkyscrapersCell cell = (SkyscrapersCell) puzzleElement;
+ Point loc = cell.getLocation();
+
+ //Initialize instances of necessary contradiction and case rules
+ InsufficientVisibilityContradictionRule tooFew = new InsufficientVisibilityContradictionRule();
+ ExceedingVisibilityContradictionRule tooMany = new ExceedingVisibilityContradictionRule();
+ CellForNumberCaseRule caseRule = new CellForNumberCaseRule();
+
+ //Initialize skyscraperBoard queues for rows and cols
+ Queue rowQ = new LinkedList<>();
+ rowQ.add(skyscrapersBoard);
+ Queue colQ = new LinkedList<>();
+ colQ.add(skyscrapersBoard);
+
+ // find all cases for the corresponding row and column for each possible skyscraper height
+
+ //Add every possible case for all heights for each corresponding row and column
+ for(int i = 0; i < skyscrapersBoard.getWidth(); i++) {
+ int num = i + 1;
+
+ //check row west clue
+ List rows;
+
+ int size = rowQ.size();
+ for(int j = 0; j < size; j++) {
+ SkyscrapersBoard temp = rowQ.poll(); //get row from the top of the stack
+
+ //don't do anything if already in row
+ boolean exists = false;
+ for(SkyscrapersCell c : temp.getRowCol(loc.y,SkyscrapersType.Number,true)){
+ if(c.getData()==num) {
+ exists = true;
+ break;
+ }
+ }
+
+ if(exists) {
+ rowQ.add(temp);
+ }
+ else{
+ //set flags
+ boolean dupeTemp = temp.getDupeFlag();
+ boolean viewTemp = temp.getViewFlag();
+ temp.setDupeFlag(false);
+ temp.setViewFlag(false);
+
+ //get all cases for corresponding row based on west clue
+ rows = caseRule.getCasesFor(temp, skyscrapersBoard.getWestClues().get(loc.y), num);
+
+ //reset flags
+ temp.setDupeFlag(dupeTemp);
+ temp.setViewFlag(viewTemp);
+
+ //add all row cases to row queue
+ for (Board k : rows) {
+ rowQ.add((SkyscrapersBoard) k);
+ }
+ }
+ }
+
+ //check col north clue
+ List cols;
+
+ size = colQ.size();
+ for(int j = 0; j < size; j++) {
+ SkyscrapersBoard temp = colQ.poll(); //get row from the top of the stack
+
+ //don't do anything if already in col
+ boolean exists = false;
+ for(SkyscrapersCell c : temp.getRowCol(loc.x,SkyscrapersType.Number,false)){
+ if(c.getData()==num) {
+ exists = true;
+ break;
+ }
+ }
+
+ if(exists){
+ colQ.add(temp);
+ }
+ else{
+ //set flags
+ boolean dupeTemp = temp.getDupeFlag();
+ boolean viewTemp = temp.getViewFlag();
+ temp.setDupeFlag(false);
+ temp.setViewFlag(false);
+
+ //get all cases for corresponding col based on north clue
+ cols = caseRule.getCasesFor(temp, skyscrapersBoard.getNorthClues().get(loc.x), num);
+
+ //reset flags
+ temp.setDupeFlag(dupeTemp);
+ temp.setViewFlag(viewTemp);
+
+ //add all row cases to row queue
+ for(Board k : cols) {
+ colQ.add((SkyscrapersBoard) k);
+ }
+ }
+ }
+ }
+
+ String rowTooFew;
+ String rowTooMany;
+ boolean rowContradiction = true;
+ //check if each case board has a contradiction
+ while(rowQ.size()>0) {
+ SkyscrapersBoard fullRow = rowQ.poll();
+
+ //checks if there is a contradiction given the row based on the west clue
+ rowTooFew = tooFew.checkContradictionAt(fullRow, cell); // is cell the correct puzzle element to check?
+ rowTooMany = tooMany.checkContradictionAt(fullRow, cell);
+
+ //boolean that checks if there is a contradiction within all rows
+ rowContradiction = rowContradiction && (rowTooFew == null || rowTooMany == null);// !null means there isn't a contradiction, so there must be a valid permutation of the array
+ }
+
+ String colTooFew;
+ String colTooMany;
+ boolean colContradiction = true;
+ while(colQ.size()>0) {
+ SkyscrapersBoard fullCol = colQ.poll();
+
+ //checks if there is a contradiction given the col baesd on the north clue
+ colTooFew = tooFew.checkContradictionAt(fullCol, cell);
+ colTooMany = tooMany.checkContradictionAt(fullCol, cell);
+
+ //boolean that checks if there is a contradiction within all the cols
+ colContradiction = colContradiction && (colTooFew == null || colTooMany == null);
+ }
+
+ //if every possible permutation results in contradictions return null, else no contradiction
+ if(rowContradiction || colContradiction) {
+ return null;
+ }
+ return super.getNoContradictionMessage();
+ }
+
+ /**
+ * Checks whether the tree node has a contradiction using this rule
+ *
+ * @param board board to check contradiction
+ * @return null if the tree node contains a contradiction, otherwise error message
+ */
+ @Override
+ public String checkContradiction(Board board) {
+ SkyscrapersBoard skyscrapersBoard = (SkyscrapersBoard) board;
+ for (int i = 0; i < skyscrapersBoard.getWidth(); i++) {
+ //checks the middle diagonal (checkContradictionAt checks row/col off each)
+ String checkStr = checkContradictionAt(board, skyscrapersBoard.getCell(i,i));
+ if (checkStr == null) {
+ return checkStr;
+ }
+ }
+ return "No instance of the contradiction " + this.ruleName + " here";
+ }
+
+
+
+}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/Skyscrapers Ruleset.pdf b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/Skyscrapers Ruleset.pdf
new file mode 100644
index 000000000..3ff35c2fe
Binary files /dev/null and b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/Skyscrapers Ruleset.pdf differ
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/TODO.md b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/TODO.md
index 9ff730666..94ef1e214 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/TODO.md
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/TODO.md
@@ -1,16 +1,22 @@
## TODO
-1. Basic Rules:
- - Last Cell
- - Last Number
- - 1-Edge
- - N-Edge
- - Fixed Max
-2. Contradiction Rules:
- - Duplicate Number
- - Unresolved Cell
- - Exceeding Visibility
- - Insufficient Visibility
-3. Case Rules:
- - Possible Contents
- - Possible Places
+spreadsheet : https://docs.google.com/spreadsheets/d/1l7aUZtavtysM8dtGnaEIXhBKMRGxekhnLIVoYIHYZi8/edit#gid=0
+
+ 1. Basic Rules:
+ - Come up with better names for 1Edge and FixedMax, they are now more general
+ 2. Contradiction Rules:
+ 3. Case Rules:
+ - Don't highlight cells when selecting a row/col?
+ - (override draw() in SkyscrapersElementView)
+ 4. Refactoring:
+ - document utility functions in the reference sheet, COMMENTS!
+ - review and identify dead code
+ - remove all these damn print statments (commented ones too if they aren't useful)
+ - Edit to allow blank clues
+ - Display flags somewhere
+ 5. Flags
+ - edit exporter to include flags in xml file format (if needed)
+ 6. Documentation
+ - UML diagram(s)
+ 7. Merge Skyscrapers to dev
+ 8. Add 5 more easy/med puzzles to skyscrapers
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/UnresolvedCellContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/UnresolvedCellContradictionRule.java
index 98ed7e96d..c3abefd4d 100644
--- a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/UnresolvedCellContradictionRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/UnresolvedCellContradictionRule.java
@@ -8,6 +8,7 @@
import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
import java.awt.*;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -16,7 +17,7 @@ public class UnresolvedCellContradictionRule extends ContradictionRule {
public UnresolvedCellContradictionRule() {
super("SKYS-CONT-0004", "Unresolved Cell",
"Elimination leaves no possible number for a cell.",
- "edu/rpi/legup/images/skyscrapers/UnresolvedCell.png");
+ "edu/rpi/legup/images/skyscrapers/contradictions/UnresolvedCell.png");
}
/**
@@ -29,37 +30,14 @@ public UnresolvedCellContradictionRule() {
*/
@Override
public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
- SkyscrapersCell cell = (SkyscrapersCell) puzzleElement;
- SkyscrapersBoard skyscrapersboard = (SkyscrapersBoard) board;
- Point loc = cell.getLocation();
- Set candidates = new HashSet();
+ NumberForCellCaseRule caseRule = new NumberForCellCaseRule();
+ ArrayList cases = caseRule.getCases(board,puzzleElement);
- //check row
- for (int i = 0; i < skyscrapersboard.getWidth(); i++) {
- SkyscrapersCell c = skyscrapersboard.getCell(i, loc.y);
- if (i != loc.x && cell.getType() == SkyscrapersType.UNKNOWN && c.getType() == SkyscrapersType.Number) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- candidates.add(c.getData());
- }
- }
-
- // check column
- for (int i = 0; i < skyscrapersboard.getHeight(); i++) {
- SkyscrapersCell c = skyscrapersboard.getCell(loc.x, i);
- if (i != loc.y && cell.getType() == SkyscrapersType.UNKNOWN && c.getType() == SkyscrapersType.Number) {
- //System.out.print(c.getData());
- //System.out.println(cell.getData());
- candidates.add(c.getData());
- }
- }
-
- if (candidates.size() == skyscrapersboard.getWidth()) {
- System.out.print("violation");
+ if(cases.size()==0){
return null;
}
- //System.out.print("Does not contain a contradiction at this index");
+
return super.getNoContradictionMessage();
}
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/UnresolvedNumberContradictionRule.java b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/UnresolvedNumberContradictionRule.java
new file mode 100644
index 000000000..e3b27a777
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/puzzle/skyscrapers/rules/UnresolvedNumberContradictionRule.java
@@ -0,0 +1,97 @@
+package edu.rpi.legup.puzzle.skyscrapers.rules;
+
+
+import edu.rpi.legup.model.gameboard.Board;
+import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.model.rules.ContradictionRule;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersBoard;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersCell;
+import edu.rpi.legup.puzzle.skyscrapers.SkyscrapersType;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Set;
+
+public class UnresolvedNumberContradictionRule extends ContradictionRule {
+
+ public UnresolvedNumberContradictionRule() {
+ super("SKYS-CONT-0005", "Unresolved Number",
+ "No possible cell for a number without a duplicate contradiction.",
+ //specify a number? defaulting to every number for now. expand to more than duplicate?
+ "edu/rpi/legup/images/skyscrapers/contradictions/UnresolvedNumber.png");
+ }
+
+ /**
+ * Checks whether the transition has a contradiction at the specific puzzleElement index using this rule
+ *
+ * @param board board to check contradiction
+ * @param puzzleElement equivalent puzzleElement
+ * @return null if the transition contains a contradiction at the specified puzzleElement,
+ * otherwise error message
+ */
+ @Override
+ public String checkContradictionAt(Board board, PuzzleElement puzzleElement) {
+ SkyscrapersBoard skyscrapersBoard = (SkyscrapersBoard) board;
+ SkyscrapersCell cell = (SkyscrapersCell) puzzleElement;
+ Point loc = cell.getLocation();
+
+ CellForNumberCaseRule caseRule = new CellForNumberCaseRule();
+ for(int i=0;i elements = b.getPuzzleElements();
+ int treeCount = 0;
+ for (PuzzleElement element : elements) {
+ TreeTentCell c = (TreeTentCell) element;
+ if (c.getType() == TreeTentType.TREE) {
+ treeCount++;
+ }
+ }
+ return treeCount != 0;
+ }
}
diff --git a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/TentOrGrassCaseRule.java b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/TentOrGrassCaseRule.java
index 900f20381..9ef47097f 100644
--- a/src/main/java/edu/rpi/legup/puzzle/treetent/rules/TentOrGrassCaseRule.java
+++ b/src/main/java/edu/rpi/legup/puzzle/treetent/rules/TentOrGrassCaseRule.java
@@ -15,7 +15,7 @@
public class TentOrGrassCaseRule extends CaseRule {
public TentOrGrassCaseRule() {
- super("TREE-CASE-0004", "Tree or Grass",
+ super("TREE-CASE-0004", "Tent or Grass",
"Each blank cell is either a tent or grass.",
"edu/rpi/legup/images/treetent/caseTentOrGrass.png");
}
diff --git a/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java b/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java
index d95b547ad..0805a78cf 100644
--- a/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java
+++ b/src/main/java/edu/rpi/legup/ui/CreatePuzzleDialog.java
@@ -27,31 +27,39 @@ public class CreatePuzzleDialog extends JDialog {
* @param e the event to be processed
*/
@Override
- public void actionPerformed(ActionEvent e) {
+ public void actionPerformed(ActionEvent ae) {
String game = Config.convertDisplayNameToClassName((String) gameBox.getSelectedItem());
+
+ // Check if all 3 TextFields are filled
+ if (game.equals("") || rows.getText().equals("") || columns.getText().equals("")) {
+ System.out.println("Unfilled fields");
+ return;
+ }
+
try {
homePanel.openEditorWithNewPuzzle(game, Integer.valueOf(rows.getText()), Integer.valueOf(columns.getText()));
setVisible(false);
}
- catch (IllegalArgumentException exception) {
- // Don't do anything. This is here to prevent the dialog from closing if the dimensions are invalid.
+ catch (IllegalArgumentException e) {
+ System.out.println("Failed to open editor with new puzzle");
+ e.printStackTrace(System.out);
}
}
};
+
private JButton cancel = new JButton("Cancel");
private ActionListener cancelButtonListener = new ActionListener() {
/**
- * Hides the puzzle creation dialog
+ * Dispose the puzzle creation dialog
*
* @param e the event to be processed
*/
@Override
public void actionPerformed(ActionEvent e) {
- setVisible(false);
+ dispose();
}
};
-
public CreatePuzzleDialog(JFrame parent, HomePanel homePanel) {
super(parent, true);
@@ -106,24 +114,27 @@ public CreatePuzzleDialog(JFrame parent, HomePanel homePanel) {
public void initPuzzles() {
this.games = GameBoardFacade.getInstance().getConfig().getFileCreationEnabledPuzzles().toArray(new String[0]);
Arrays.sort(this.games);
- gameBox = new JComboBox(GameBoardFacade.getInstance().getConfig().getFileCreationEnabledPuzzleNames().toArray(new String[0]));
+ gameBox = new JComboBox(this.games);
}
+ // ^This method seems useless and never got covered
public void actionPerformed(ActionEvent e) {
if (e.getSource() == ok) {
String game = Config.convertDisplayNameToClassName((String) gameBox.getSelectedItem());
+
try {
this.homePanel.openEditorWithNewPuzzle(game, Integer.valueOf(this.rows.getText()), Integer.valueOf(this.columns.getText()));
- setVisible(false);
+ this.setVisible(false);
}
- catch (IllegalArgumentException exception) {
+ catch (IllegalArgumentException exception) {
// Don't do anything. This is here to prevent the dialog from closing if the dimensions are invalid.
}
}
- else {
- if (e.getSource() == cancel) {
- setVisible(false);
- }
+ else if (e.getSource() == cancel) {
+ this.setVisible(false);
+ }
+ else {
+ // Unknown Action Event
}
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/edu/rpi/legup/ui/HomePanel.java b/src/main/java/edu/rpi/legup/ui/HomePanel.java
index 3eb543e47..3eba9a3de 100644
--- a/src/main/java/edu/rpi/legup/ui/HomePanel.java
+++ b/src/main/java/edu/rpi/legup/ui/HomePanel.java
@@ -1,20 +1,36 @@
package edu.rpi.legup.ui;
+import edu.rpi.legup.Legup;
import edu.rpi.legup.app.GameBoardFacade;
+import edu.rpi.legup.app.LegupPreferences;
import edu.rpi.legup.controller.CursorController;
+import edu.rpi.legup.save.InvalidFileFormatException;
+import edu.rpi.legup.app.LegupPreferences;
+import edu.rpi.legup.model.Puzzle;
import javax.swing.*;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.io.File;
+import java.io.*;
+import java.util.Objects;
+
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
-import java.io.IOException;
+import java.io.FileWriter;
import java.net.URI;
import java.net.URL;
+import java.util.Objects;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
public class HomePanel extends LegupPanel {
private final static Logger LOGGER = LogManager.getLogger(HomePanel.class.getName());
@@ -23,6 +39,7 @@ public class HomePanel extends LegupPanel {
private JButton[] buttons;
private JLabel[] text;
private JMenuBar menuBar;
+ private JFileChooser folderBrowser;
private final int buttonSize = 100;
@@ -41,6 +58,9 @@ public void actionPerformed(ActionEvent e) {
@Override
public void actionPerformed(ActionEvent e) {
Object[] items = legupUI.getPuzzleEditor().promptPuzzle();
+ if (items == null) {
+ return;
+ }
String fileName = (String) items[0];
File puzzleFile = (File) items[1];
legupUI.displayPanel(2);
@@ -144,8 +164,367 @@ private void initButtons() {
this.buttons[3] = new JButton("Batch Grader");
this.buttons[3].setHorizontalTextPosition(AbstractButton.CENTER);
this.buttons[3].setVerticalTextPosition(AbstractButton.BOTTOM);
+
+ this.buttons[3].addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+// ProofEditorPanel panel=new ProofEditorPanel(new FileDialog(new Frame()),new JFrame(), legupUI);
+// //legupUI.setVisible(false);
+// panel.checkProofAll();
+ //checkfolder();
+
+ try {
+ use_xml_to_check();
+ }
+ catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ //checkallproof1();
+ System.out.println("finished checking the folder");
+
+ }
+ });
+ }
+public void checkfolder(){
+ GameBoardFacade facade = GameBoardFacade.getInstance();
+
+ /*
+ * Select dir to grade; recursively grade sub-dirs using traverseDir()
+ * Selected dir must have sub-dirs for each student:
+ * GradeThis
+ * |
+ * | -> Student 1
+ * | |
+ * | | -> Proofs
+ */
+
+ LegupPreferences preferences = LegupPreferences.getInstance();
+ File preferredDirectory = new File(preferences.getUserPref(LegupPreferences.WORK_DIRECTORY));
+ JFileChooser folderBrowser = new JFileChooser(preferredDirectory);
+
+
+ folderBrowser.setCurrentDirectory(new File(LegupPreferences.WORK_DIRECTORY));
+ folderBrowser.setDialogTitle("Select Directory");
+ folderBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ folderBrowser.setAcceptAllFileFilterUsed(false);
+ folderBrowser.showOpenDialog(this);
+ folderBrowser.setVisible(true);
+ File folder = folderBrowser.getSelectedFile();
+
+ File resultFile = new File(folder.getAbsolutePath() + File.separator +"result.csv");
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile))) {
+ writer.append("Name");
+ writer.append(",");
+ writer.append("File Name");
+ writer.append(",");
+ writer.append("Solved or not");
+ writer.append("\n");
+ //csvWriter.flush();
+ //csvWriter.close();
+
+ for (final File folderEntry : folder.listFiles(File::isDirectory)) {
+ writer.append(folderEntry.getName());
+ writer.append(",");
+ int count1 = 0;
+ for (final File fileEntry : folderEntry.listFiles()) {
+ if (fileEntry.getName().charAt(0) == '.'){
+ continue;
+ }
+ count1++;
+ if (count1 > 1){
+ writer.append(folderEntry.getName());
+ writer.append(",");
+ }
+ writer.append(fileEntry.getName());
+ writer.append(",");
+ String fileName = folderEntry.getAbsolutePath() + File.separator + fileEntry.getName();
+ System.out.println("This is path "+fileName);
+ File puzzleFile = new File(fileName);
+ if (puzzleFile != null && puzzleFile.exists()) {
+ try {
+ legupUI.displayPanel(1);
+ legupUI.getProofEditor();
+ GameBoardFacade.getInstance().loadPuzzle(fileName);
+ String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName();
+ legupUI.setTitle(puzzleName + " - " + puzzleFile.getName());
+ facade = GameBoardFacade.getInstance();
+ Puzzle puzzle = facade.getPuzzleModule();
+ if (puzzle.isPuzzleComplete()) {
+ writer.append("Solved");
+ System.out.println(fileEntry.getName() + " solved");
+ }
+ else {
+ writer.append("Not solved");
+ System.out.println(fileEntry.getName() + " not solved");
+ }
+ writer.append("\n");
+ }
+ catch (InvalidFileFormatException e) {
+ LOGGER.error(e.getMessage());
+ }
+ }
+ }
+ if (count1 == 0){
+ writer.append("No file");
+ writer.append("\n");
+ }
+ }
+ }
+ catch (IOException ex){
+ LOGGER.error(ex.getMessage());
+
+ this.buttons[3].addActionListener((ActionEvent e) -> checkProofAll());
+
+ }
}
+ /*
+ This function is use to check each function xml proof file have the flag = true.
+ Also, we will go to check each file is xml file or not which we have 3 result solve, unsolve and ungradeable
+ */
+ public void use_xml_to_check() throws Exception{
+ GameBoardFacade facade = GameBoardFacade.getInstance();
+
+ /*
+ * Select dir to grade; recursively grade sub-dirs using traverseDir()
+ * Selected dir must have sub-dirs for each student:
+ * GradeThis
+ * |
+ * | -> Student 1
+ * | |
+ * | | -> Proofs
+ */
+
+ LegupPreferences preferences = LegupPreferences.getInstance();
+ File preferredDirectory = new File(preferences.getUserPref(LegupPreferences.WORK_DIRECTORY));
+ JFileChooser folderBrowser = new JFileChooser(preferredDirectory);
+
+
+ folderBrowser.setCurrentDirectory(new File(LegupPreferences.WORK_DIRECTORY));
+ folderBrowser.setDialogTitle("Select Directory");
+ folderBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ folderBrowser.setAcceptAllFileFilterUsed(false);
+ folderBrowser.showOpenDialog(this);
+ folderBrowser.setVisible(true);
+ File folder = folderBrowser.getSelectedFile();
+
+ File resultFile = new File(folder.getAbsolutePath() + File.separator +"result.csv");
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ SAXParser saxParser = spf.newSAXParser();
+// String path = "C:\\Users\\LiWeiJun\\Desktop\\TestSet\\TestSet\\roseh";
+ //read the xml file
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile))) {
+ writer.write("Name");
+ writer.write(",");
+ writer.write("File Name");
+ writer.write(",");
+ writer.write("Solved or not");
+ writer.write("\n");
+ for (final File folderEntry : folder.listFiles(File::isDirectory)) {
+ writer.write(folderEntry.getName());
+ writer.write(",");
+ int count1 = 0;
+ for (final File fileEntry : folderEntry.listFiles()) {
+ if (fileEntry.getName().charAt(0) == '.') {
+ continue;
+ }
+ count1++;
+ if (count1 > 1) {
+ writer.write(folderEntry.getName());
+ writer.write(",");
+ }
+ writer.write(fileEntry.getName());
+ writer.write(",");
+ String path =folderEntry.getAbsolutePath() + File.separator + fileEntry.getName();
+ System.out.println(path);
+ boolean is_xml_file = isxmlfile(fileEntry);
+ if(is_xml_file){
+ saxParser.parse(path, new DefaultHandler(){
+ @Override
+ public void startDocument() throws SAXException {
+ System.out.println("start doc");
+ }
+
+ @Override
+ public void endDocument() throws SAXException {
+ System.out.println("end doc");
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ int length = attributes.getLength();
+ for (int i = 0 ;i Student 1
+ * | |
+ * | | -> Proofs
+ */
+
+ LegupPreferences preferences = LegupPreferences.getInstance();
+ File preferredDirectory = new File(preferences.getUserPref(LegupPreferences.WORK_DIRECTORY));
+ JFileChooser folderBrowser = new JFileChooser(preferredDirectory);
+
+
+ folderBrowser.setCurrentDirectory(new File(LegupPreferences.WORK_DIRECTORY));
+ folderBrowser.setDialogTitle("Select Directory");
+ folderBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ folderBrowser.setAcceptAllFileFilterUsed(false);
+ folderBrowser.showOpenDialog(this);
+ folderBrowser.setVisible(true);
+
+ File folder = folderBrowser.getSelectedFile();
+
+ // Write csv file (Path,File-Name,Puzzle-Type,Score,Solved?)
+ File resultFile = new File(folder.getAbsolutePath() + File.separator + "result.csv");
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile))) {
+ writer.append("Name,File Name,Puzzle Type,Score,Solved?\n");
+
+ // Go through student folders
+ for (final File folderEntry : Objects.requireNonNull(folder.listFiles(File::isDirectory))) {
+ // Write path
+ String path = folderEntry.getName();
+ traverseDir1(folderEntry, writer, path);
+ }
+ }
+ catch (IOException ex) {
+ LOGGER.error(ex.getMessage());
+ }
+ JOptionPane.showMessageDialog(null, "Batch grading complete.");
+ }
+ public void traverseDir1(File folder, BufferedWriter writer, String path) throws IOException{
+ GameBoardFacade facade = GameBoardFacade.getInstance();
+
+ // Folder is empty
+ if (Objects.requireNonNull(folder.listFiles()).length == 0) {
+ writer.append(path).append(",Empty folder,,Ungradeable\n");
+ return;
+ }
+
+ // Travese directory, recurse if sub-directory found
+ // If ungradeable, do not leave a score (0, 1)
+ for (final File f : Objects.requireNonNull(folder.listFiles())) {
+ // Recurse
+ if (f.isDirectory()) {
+ traverseDir1(f, writer, path + "/" + f.getName());
+ continue;
+ }
+
+ // Set path name
+ writer.append(path).append(",");
+
+ // Load puzzle, run checker
+ // If wrong file type, ungradeable
+ String fName = f.getName();
+ String fPath = f.getAbsolutePath();
+ File puzzleFile = new File(fPath);
+ if (puzzleFile.exists()) {
+ // Try to load file. If invalid, note in csv
+ try {
+ // Load puzzle, run checker
+ GameBoardFacade.getInstance().loadPuzzle(fPath);
+ String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName();
+ frame.setTitle(puzzleName + " - " + puzzleFile.getName());
+ facade = GameBoardFacade.getInstance();
+ Puzzle puzzle = facade.getPuzzleModule();
+
+ // Write data
+ writer.append(fName).append(",");
+ writer.append(puzzle.getName()).append(",");
+ if (puzzle.isPuzzleComplete()) {
+ writer.append("1,Solved\n");
+ }
+ else {
+ writer.append("0,Unsolved\n");
+ }
+ }
+ catch (InvalidFileFormatException e) {
+ writer.append(fName).append(",Invalid,,Ungradeable\n");
+ }
+ }
+ else {
+ LOGGER.debug("Failed to run sim");
+ }
+ }
+ }
private void initText() {
// Note: until an auto-changing version label is implemented in the future, I removed
// the version text from the home screen to avoid confusion
@@ -189,6 +568,7 @@ private void render() {
batchGraderButton.add(this.buttons[3]);
batchGraderButton.setAlignmentX(Component.LEFT_ALIGNMENT);
+
this.add(Box.createRigidArea(new Dimension(0, 5)));
for (int i = 0; i < this.text.length; i++) {
this.add(this.text[i]);
@@ -203,6 +583,105 @@ private void openNewPuzzleDialog() {
cpd.setVisible(true);
}
+ private void checkProofAll() {
+ /*
+ * Select dir to grade; recursively grade sub-dirs using traverseDir()
+ * Selected dir must have sub-dirs for each student:
+ * GradeThis
+ * |
+ * | -> Student 1
+ * | |
+ * | | -> Proofs
+ */
+
+ LegupPreferences preferences = LegupPreferences.getInstance();
+ File preferredDirectory = new File(preferences.getUserPref(LegupPreferences.WORK_DIRECTORY));
+ folderBrowser = new JFileChooser(preferredDirectory);
+
+ folderBrowser.showOpenDialog(this);
+ folderBrowser.setVisible(true);
+ folderBrowser.setCurrentDirectory(new File(LegupPreferences.WORK_DIRECTORY));
+ folderBrowser.setDialogTitle("Select Directory");
+ folderBrowser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+ folderBrowser.setAcceptAllFileFilterUsed(false);
+
+ File folder = folderBrowser.getSelectedFile();
+
+ // Write csv file (Path,File-Name,Puzzle-Type,Score,Solved?)
+ File resultFile = new File(folder.getAbsolutePath() + File.separator + "result.csv");
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(resultFile))) {
+ writer.append("Name,File Name,Puzzle Type,Score,Solved?\n");
+
+ // Go through student folders
+ for (final File folderEntry : Objects.requireNonNull(folder.listFiles(File::isDirectory))) {
+ // Write path
+ String path = folderEntry.getName();
+ traverseDir(folderEntry, writer, path);
+ }
+ }
+ catch (IOException ex) {
+ LOGGER.error(ex.getMessage());
+ }
+ JOptionPane.showMessageDialog(null, "Batch grading complete.");
+ }
+
+ private void traverseDir(File folder, BufferedWriter writer, String path) throws IOException {
+ // Recursively traverse directory
+ GameBoardFacade facade = GameBoardFacade.getInstance();
+
+ // Folder is empty
+ if (Objects.requireNonNull(folder.listFiles()).length == 0) {
+ writer.append(path).append(",Empty folder,,Ungradeable\n");
+ return;
+ }
+
+ // Travese directory, recurse if sub-directory found
+ // If ungradeable, do not leave a score (0, 1)
+ for (final File f : Objects.requireNonNull(folder.listFiles())) {
+ // Recurse
+ if (f.isDirectory()) {
+ traverseDir(f, writer, path + "/" + f.getName());
+ continue;
+ }
+
+ // Set path name
+ writer.append(path).append(",");
+
+ // Load puzzle, run checker
+ // If wrong file type, ungradeable
+ String fName = f.getName();
+ String fPath = f.getAbsolutePath();
+ File puzzleFile = new File(fPath);
+ if (puzzleFile.exists()) {
+ // Try to load file. If invalid, note in csv
+ try {
+ // Load puzzle, run checker
+ GameBoardFacade.getInstance().loadPuzzle(fPath);
+ String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName();
+ frame.setTitle(puzzleName + " - " + puzzleFile.getName());
+ facade = GameBoardFacade.getInstance();
+ Puzzle puzzle = facade.getPuzzleModule();
+
+ // Write data
+ writer.append(fName).append(",");
+ writer.append(puzzle.getName()).append(",");
+ if (puzzle.isPuzzleComplete()) {
+ writer.append("1,Solved\n");
+ }
+ else {
+ writer.append("0,Unsolved\n");
+ }
+ }
+ catch (InvalidFileFormatException e) {
+ writer.append(fName).append(",Invalid,,Ungradeable\n");
+ }
+ }
+ else {
+ LOGGER.debug("Failed to run sim");
+ }
+ }
+ }
+
public void openEditorWithNewPuzzle(String game, int rows, int columns) throws IllegalArgumentException {
// Validate the dimensions
GameBoardFacade facade = GameBoardFacade.getInstance();
diff --git a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java
index 177fa183c..e661a4336 100644
--- a/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java
+++ b/src/main/java/edu/rpi/legup/ui/ProofEditorPanel.java
@@ -1,5 +1,7 @@
package edu.rpi.legup.ui;
-
+import org.xml.sax.*;
+import org.xml.sax.helpers.*;
+import javax.xml.parsers.*;
import edu.rpi.legup.app.GameBoardFacade;
import edu.rpi.legup.app.LegupPreferences;
import edu.rpi.legup.controller.BoardController;
@@ -27,6 +29,7 @@
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.io.BufferedWriter;
import java.io.File;
@@ -50,7 +53,7 @@ public class ProofEditorPanel extends LegupPanel implements IHistoryListener {
private JButton[] toolBarButtons;
private JMenu file;
- private JMenuItem newPuzzle, resetPuzzle, saveProof, preferences, exit;
+ private JMenuItem newPuzzle, resetPuzzle, saveProofAs,saveProofChange,helpTutorial, preferences, exit;
private JMenu edit;
private JMenuItem undo, redo, fitBoardToScreen, fitTreeToScreen;
@@ -115,8 +118,10 @@ public JMenuBar getMenuBar() {
newPuzzle = new JMenuItem("Open");
resetPuzzle = new JMenuItem("Reset Puzzle");
// genPuzzle = new JMenuItem("Puzzle Generators");
- saveProof = new JMenuItem("Save Proof");
+ saveProofAs = new JMenuItem("Save Proof As"); // create a new file to save
+ saveProofChange = new JMenuItem("Save Proof Change"); // save to the current file
preferences = new JMenuItem("Preferences");
+ helpTutorial = new JMenuItem("Help"); // jump to web page
exit = new JMenuItem("Exit");
edit = new JMenu("Edit");
@@ -242,21 +247,51 @@ public JMenuBar getMenuBar() {
}
file.addSeparator();
- file.add(saveProof);
- saveProof.addActionListener((ActionEvent) -> saveProof());
+ file.add(saveProofAs);
+ saveProofAs.addActionListener((ActionEvent) -> saveProofAs());
+
+
+ //save proof as
+ if (os.equals("mac")) {
+ saveProofAs.setAccelerator(KeyStroke.getKeyStroke('S', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ }
+ else {
+ saveProofAs.setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_DOWN_MASK));
+ }
+
+ // save proof change
if (os.equals("mac")) {
- saveProof.setAccelerator(KeyStroke.getKeyStroke('S', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ saveProofChange.setAccelerator(KeyStroke.getKeyStroke('A', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
}
else {
- saveProof.setAccelerator(KeyStroke.getKeyStroke('S', InputEvent.CTRL_DOWN_MASK));
+ saveProofChange.setAccelerator(KeyStroke.getKeyStroke('A', InputEvent.CTRL_DOWN_MASK));
}
+
+ file.add(saveProofChange);
+ saveProofChange.addActionListener((ActionEvent) -> saveProofChange());
+ file.addSeparator();
+
+ // preference
file.add(preferences);
preferences.addActionListener(a -> {
PreferencesDialog preferencesDialog = new PreferencesDialog(this.frame);
});
file.addSeparator();
+ // help function
+ if (os.equals("mac")) {
+ helpTutorial.setAccelerator(KeyStroke.getKeyStroke('H', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ }
+ else {
+ helpTutorial.setAccelerator(KeyStroke.getKeyStroke('H', InputEvent.CTRL_DOWN_MASK));
+ }
+ file.add(helpTutorial);
+ helpTutorial.addActionListener((ActionEvent) -> helpTutorial());
+ file.addSeparator();
+
+
+ //exit
file.add(exit);
exit.addActionListener((ActionEvent) -> this.legupUI.displayPanel(0));
if (os.equals("mac")) {
@@ -316,6 +351,7 @@ public JMenuBar getMenuBar() {
return mBar;
}
+ // File opener
public Object[] promptPuzzle() {
GameBoardFacade facade = GameBoardFacade.getInstance();
if (facade.getBoard() != null) {
@@ -324,19 +360,21 @@ public Object[] promptPuzzle() {
}
}
+ if (fileDialog == null) {
+ fileDialog = new FileDialog(this.frame);
+ }
LegupPreferences preferences = LegupPreferences.getInstance();
- File preferredDirectory = new File(preferences.getUserPref(LegupPreferences.WORK_DIRECTORY));
- folderBrowser = new JFileChooser(preferredDirectory);
- folderBrowser.setDialogTitle("Select Proof File");
- folderBrowser.showOpenDialog(this);
- folderBrowser.setFileSelectionMode(JFileChooser.FILES_ONLY);
- folderBrowser.setAcceptAllFileFilterUsed(true);
- folderBrowser.setVisible(true);
+ String preferredDirectory = preferences.getUserPref(LegupPreferences.WORK_DIRECTORY);
+ fileDialog.setMode(FileDialog.LOAD);
+ fileDialog.setTitle("Select Proof File");
+ fileDialog.setDirectory(preferredDirectory);
+ fileDialog.setVisible(true);
String fileName = null;
- File puzzleFile = folderBrowser.getSelectedFile();
- if (folderBrowser.getCurrentDirectory() != null && folderBrowser.getSelectedFile().getName() != null) {
- fileName = puzzleFile.getAbsolutePath() + File.separator;
+ File puzzleFile = null;
+
+ if (fileDialog.getDirectory() != null && fileDialog.getFile() != null) {
+ fileName = fileDialog.getDirectory() + File.separator + fileDialog.getFile();
puzzleFile = new File(fileName);
}
@@ -361,25 +399,49 @@ public void loadPuzzle(String fileName, File puzzleFile) {
LOGGER.error(e.getMessage());
if (e.getMessage().contains("Proof Tree construction error: could not find rule by ID")) { // TO DO: make error message not hardcoded
JOptionPane.showMessageDialog(null, "This file runs on an outdated version of Legup\nand is not compatible with the current version.", "Error", JOptionPane.ERROR_MESSAGE);
+ loadPuzzle();
}
else {
JOptionPane.showMessageDialog(null, "File does not exist or it cannot be read", "Error", JOptionPane.ERROR_MESSAGE);
+ loadPuzzle();
}
}
}
}
/**
- * Saves a proof
+ * direct Saves the current prdoof in current file
+ */
+ private void direct_save(){
+ Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule();
+ if (puzzle == null) {
+ return;
+ }
+ String fileName = GameBoardFacade.getInstance().getCurFileName();
+ if (fileName != null) {
+ try {
+ PuzzleExporter exporter = puzzle.getExporter();
+ if (exporter == null) {
+ throw new ExportFileException("Puzzle exporter null");
+ }
+ exporter.exportPuzzle(fileName);
+ }
+ catch (ExportFileException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ /**
+ * Create a new file and save proof to it
*/
- private void saveProof() {
+ private void saveProofAs() {
Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule();
if (puzzle == null) {
return;
}
fileDialog.setMode(FileDialog.SAVE);
- fileDialog.setTitle("Save Proof");
+ fileDialog.setTitle("Save Proof As");
String curFileName = GameBoardFacade.getInstance().getCurFileName();
if (curFileName == null) {
fileDialog.setDirectory(LegupPreferences.getInstance().getUserPref(LegupPreferences.WORK_DIRECTORY));
@@ -409,6 +471,63 @@ private void saveProof() {
}
}
+ // Hyperlink for help button; links to wiki page for tutorials
+ private void helpTutorial() {
+
+ Runtime rt = Runtime.getRuntime();
+ String url = "https://github.com/Bram-Hub/Legup/wiki/LEGUP-Tutorial"; // empty page 2022 Fall semester
+ try{
+ //rt.exec("rundll32 url.dll,FileProtocolHandler "+url);
+ java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));
+ }
+ catch(IOException e){
+ e.printStackTrace();
+ }
+ }
+ //add the new function need to implement
+ public void add_drop(){
+ // add the mouse event then we can use the new listener to implement and
+ // we should create a need jbuttom for it to ship the rule we select.
+ JPanel panel= new JPanel();
+ JButton moveing_buttom= new JButton();
+ moveing_buttom.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ //get the selected rule
+ }
+ });
+ panel.add(moveing_buttom);
+
+ }
+
+
+
+
+ // Quick save proof to the current file with a pop window to show "successfully saved"
+ private void saveProofChange(){
+ Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule();
+ if (puzzle == null) {
+ return;
+ }
+ String fileName = GameBoardFacade.getInstance().getCurFileName();
+ if (fileName != null) {
+ try {
+ PuzzleExporter exporter = puzzle.getExporter();
+ if (exporter == null) {
+ throw new ExportFileException("Puzzle exporter null");
+ }
+ exporter.exportPuzzle(fileName);
+ // Save confirmation
+ JOptionPane.showMessageDialog(null, "Successfully Saved","Confirm",JOptionPane.INFORMATION_MESSAGE);
+ }
+ catch (ExportFileException e) {
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+
//ask to edu.rpi.legup.save current proof
public boolean noquit(String instr) {
int n = JOptionPane.showConfirmDialog(null, instr, "Confirm", JOptionPane.YES_NO_CANCEL_OPTION);
@@ -595,6 +714,8 @@ public void setPuzzleView(Puzzle puzzle) {
ruleFrame.getBasicRulePanel().setRules(puzzle.getBasicRules());
ruleFrame.getCasePanel().setRules(puzzle.getCaseRules());
ruleFrame.getContradictionPanel().setRules(puzzle.getContradictionRules());
+ //ruleFrame.getSearchPanel().setRules(puzzle.getContradictionRules());
+ ruleFrame.getSearchPanel().setSearchBar(puzzle);
toolBarButtons[ToolbarName.CHECK.ordinal()].setEnabled(true);
// toolBarButtons[ToolbarName.SAVE.ordinal()].setEnabled(true);
diff --git a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
index 9f65f9119..7e178be4b 100644
--- a/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
+++ b/src/main/java/edu/rpi/legup/ui/PuzzleEditorPanel.java
@@ -9,6 +9,10 @@
import edu.rpi.legup.history.IHistoryListener;
import edu.rpi.legup.model.Puzzle;
import edu.rpi.legup.model.PuzzleExporter;
+import edu.rpi.legup.model.gameboard.PuzzleElement;
+import edu.rpi.legup.puzzle.treetent.TreeTentBoard;
+import edu.rpi.legup.puzzle.treetent.TreeTentCell;
+import edu.rpi.legup.puzzle.treetent.TreeTentType;
import edu.rpi.legup.save.ExportFileException;
import edu.rpi.legup.save.InvalidFileFormatException;
import edu.rpi.legup.ui.boardview.BoardView;
@@ -20,9 +24,14 @@
import javax.swing.border.TitledBorder;
import java.awt.*;
import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.io.File;
import java.net.URL;
+import java.util.List;
+import java.util.Objects;
+
+import static java.lang.System.exit;
public class PuzzleEditorPanel extends LegupPanel implements IHistoryListener {
@@ -103,8 +112,17 @@ public void setMenuBar() {
newPuzzle.setAccelerator(KeyStroke.getKeyStroke('N', InputEvent.CTRL_DOWN_MASK));
}
// file>save
- JMenuItem savePuzzle = new JMenuItem("Save");
+ JMenuItem savePuzzle = new JMenuItem("Save Proof As");
savePuzzle.addActionListener((ActionEvent) -> savePuzzle());
+ JMenuItem directSavePuzzle = new JMenuItem("Direct Save Proof ");
+ directSavePuzzle.addActionListener((ActionEvent) -> direct_save());
+ if (os.equals("mac")) {
+ newPuzzle.setAccelerator(KeyStroke.getKeyStroke('D', Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+ }
+ else {
+ newPuzzle.setAccelerator(KeyStroke.getKeyStroke('D', InputEvent.CTRL_DOWN_MASK));
+ }
+
JMenuItem exit = new JMenuItem("Exit");
exit.addActionListener((ActionEvent) -> this.legupUI.displayPanel(0));
if (os.equals("mac")) {
@@ -115,6 +133,7 @@ public void setMenuBar() {
}
menus[0].add(newPuzzle);
menus[0].add(savePuzzle);
+ menus[0].add(directSavePuzzle);
menus[0].add(exit);
// EDIT
@@ -168,8 +187,9 @@ public void makeVisible() {
}
private void setupToolBar() {
- setToolBarButtons(new JButton[ToolbarName.values().length]);
- for (int i = 0; i < ToolbarName.values().length; i++) {
+ setToolBarButtons(new JButton[ToolbarName.values().length+1]);
+ int lastone=0;
+ for (int i = 0; i < ToolbarName.values().length-1; i++) {
String toolBarName = ToolbarName.values()[i].toString();
URL resourceLocation = ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/Legup/" + toolBarName + ".png");
@@ -181,12 +201,44 @@ private void setupToolBar() {
JButton button = new JButton(toolBarName, imageIcon);
button.setFocusPainted(false);
getToolBarButtons()[i] = button;
+ lastone=i;
}
+
+
+
+ URL check_and_save= ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/Legup/Check.png");
+ ImageIcon imageIcon= new ImageIcon(check_and_save);
+ Image image = imageIcon.getImage();
+ imageIcon = new ImageIcon(image.getScaledInstance(this.TOOLBAR_ICON_SCALE, this.TOOLBAR_ICON_SCALE, Image.SCALE_SMOOTH));
+
+ JButton checkandsave= new JButton("check and Save",imageIcon);
+ checkandsave.setFocusPainted(false);
+ checkandsave.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ //savePuzzle();
+ String filename = savePuzzle();
+ File puzzlename= new File(filename);
+ System.out.println(filename);
+
+
+ GameBoardFacade.getInstance().getLegupUI().displayPanel(1);
+ GameBoardFacade.getInstance().getLegupUI().getProofEditor().loadPuzzle(filename,new File(filename));
+ String puzzleName = GameBoardFacade.getInstance().getPuzzleModule().getName();
+ frame.setTitle(puzzleName + " - " + puzzlename.getName());
+ }
+ });
+ getToolBarButtons()[lastone+1]=checkandsave;
+ System.out.println("it is create new file");
+
+
+
+
toolBar = new JToolBar();
toolBar.setFloatable(false);
toolBar.setRollover(true);
- for (int i = 0; i < getToolBarButtons().length; i++) {
+ for (int i = 0; i < getToolBarButtons().length-1; i++) {
for (int s = 0; s < TOOLBAR_SEPARATOR_BEFORE.length; s++) {
if (i == TOOLBAR_SEPARATOR_BEFORE[s]) {
toolBar.addSeparator();
@@ -236,6 +288,7 @@ public void loadPuzzleFromHome(String game, int rows, int columns) throws Illega
}
}
+ // File opener
public Object[] promptPuzzle() {
GameBoardFacade facade = GameBoardFacade.getInstance();
if (facade.getBoard() != null) {
@@ -246,8 +299,12 @@ public Object[] promptPuzzle() {
if (fileDialog == null) {
fileDialog = new FileDialog(this.frame);
}
+ LegupPreferences preferences = LegupPreferences.getInstance();
+ String preferredDirectory = preferences.getUserPref(LegupPreferences.WORK_DIRECTORY);
+
fileDialog.setMode(FileDialog.LOAD);
fileDialog.setTitle("Select Puzzle");
+ fileDialog.setDirectory(preferredDirectory);
fileDialog.setVisible(true);
String fileName = null;
File puzzleFile = null;
@@ -255,6 +312,9 @@ public Object[] promptPuzzle() {
fileName = fileDialog.getDirectory() + File.separator + fileDialog.getFile();
puzzleFile = new File(fileName);
}
+ else {
+ return null;
+ }
return new Object[]{fileName, puzzleFile};
}
@@ -275,6 +335,8 @@ public void loadPuzzle(String fileName, File puzzleFile) {
}
catch (InvalidFileFormatException e) {
LOGGER.error(e.getMessage());
+ JOptionPane.showMessageDialog(null, "File does not exist or it cannot be read", "Error", JOptionPane.ERROR_MESSAGE);
+ loadPuzzle();
}
}
}
@@ -346,11 +408,42 @@ public void setPuzzleView(Puzzle puzzle) {
/**
* Saves a puzzle
*/
- private void savePuzzle() {
+
+ private void direct_save(){
Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule();
if (puzzle == null) {
return;
}
+ String fileName = GameBoardFacade.getInstance().getCurFileName();
+ if (fileName != null) {
+ try {
+ PuzzleExporter exporter = puzzle.getExporter();
+ if (exporter == null) {
+ throw new ExportFileException("Puzzle exporter null");
+ }
+ exporter.exportPuzzle(fileName);
+ }
+ catch (ExportFileException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ private String savePuzzle() {
+ Puzzle puzzle = GameBoardFacade.getInstance().getPuzzleModule();
+ if (puzzle == null) {
+ return"";
+ }
+
+ // for TreeTent, need to check validity before saving
+ if (Objects.equals(puzzle.getName(), "TreeTent")) {
+ if (!puzzle.checkValidity()) {
+ int input = JOptionPane.showConfirmDialog(null, "The puzzle you edited is not " +
+ "valid, would you still like to save? ");
+ if (input != 0) {
+ return "";
+ }
+ }
+ }
if (fileDialog == null) {
fileDialog = new FileDialog(this.frame);
@@ -385,10 +478,15 @@ private void savePuzzle() {
e.printStackTrace();
}
}
+ return fileName;
}
+
+
public DynamicView getDynamicBoardView() {
return dynamicBoardView;
}
+
+
}
diff --git a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleButton.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleButton.java
index 12cae7de1..7e2e30bf5 100644
--- a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleButton.java
+++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleButton.java
@@ -13,7 +13,7 @@ public class RuleButton extends JButton {
* @param rule rule to create the button
*/
RuleButton(Rule rule) {
- super(rule.getImageIcon());
+ super(rule.getRuleName(), rule.getImageIcon()); // display rules' name under rule when load the icon
this.rule = rule;
}
diff --git a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java
index dd60f8dc3..d3e3799f9 100644
--- a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java
+++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RuleFrame.java
@@ -9,13 +9,8 @@
import java.awt.BorderLayout;
import java.awt.Dimension;
-import javax.swing.ButtonGroup;
-import javax.swing.JLabel;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTabbedPane;
+import javax.swing.*;
-import javax.swing.BorderFactory;
import javax.swing.border.TitledBorder;
public class RuleFrame extends JPanel {
@@ -28,6 +23,8 @@ public class RuleFrame extends JPanel {
private ContradictionRulePanel contradictionPanel;
private CaseRulePanel casePanel;
+ private SearchBarPanel searchPanel;
+
private JTabbedPane tabbedPane;
private JLabel status;
private ButtonGroup buttonGroup;
@@ -66,6 +63,11 @@ protected boolean shouldRotateTabRuns(int i) {
newp.getVerticalScrollBar().setUnitIncrement(16);
tabbedPane.addTab(contradictionPanel.name, contradictionPanel.icon, newp, contradictionPanel.toolTip);
+ searchPanel = new SearchBarPanel(this);
+ JScrollPane newsp = new JScrollPane(searchPanel);
+ newsp.getVerticalScrollBar().setUnitIncrement(16);
+ tabbedPane.addTab(searchPanel.name, searchPanel.icon, newsp, searchPanel.toolTip);
+
setLayout(new BorderLayout());
setMinimumSize(new Dimension(250, 256));
setPreferredSize(new Dimension(330, 256));
@@ -91,6 +93,7 @@ public void setSelectionByRule(Rule rule) {
basicRulePanel.setSelectionByRule(rule);
casePanel.setSelectionByRule(rule);
contradictionPanel.setSelectionByRule(rule);
+
}
/**
@@ -136,6 +139,7 @@ public void setRules(Puzzle puzzle) {
basicRulePanel.setRules(puzzle.getBasicRules());
contradictionPanel.setRules(puzzle.getContradictionRules());
casePanel.setRules(puzzle.getCaseRules());
+
}
/**
@@ -171,4 +175,7 @@ public CaseRulePanel getCasePanel() {
public ContradictionRulePanel getContradictionPanel() {
return contradictionPanel;
}
+ public SearchBarPanel getSearchPanel() {
+ return searchPanel;
+ }
}
diff --git a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RulePanel.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RulePanel.java
index c6bc2ee0a..78a07cdda 100644
--- a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RulePanel.java
+++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/RulePanel.java
@@ -1,10 +1,13 @@
package edu.rpi.legup.ui.proofeditorui.rulesview;
+import edu.rpi.legup.model.Puzzle;
import edu.rpi.legup.model.rules.Rule;
import edu.rpi.legup.ui.WrapLayout;
-import javax.swing.ImageIcon;
-import javax.swing.JPanel;
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
@@ -14,6 +17,8 @@ public abstract class RulePanel extends JPanel {
protected String toolTip;
protected RuleButton[] ruleButtons;
+ protected JPanel searchBarPanel;
+ JTextField textField;
protected RuleFrame ruleFrame;
protected List extends Rule> rules;
@@ -50,16 +55,189 @@ public void setRules(List extends Rule> rules) {
for (int i = 0; i < rules.size(); i++) {
Rule rule = rules.get(i);
+
ruleButtons[i] = new RuleButton(rule);
- ruleFrame.getButtonGroup().add(ruleButtons[i]);
+ ruleButtons[i].setPreferredSize(new Dimension(150,150));// adjust the size of each RuleButton
+ ruleButtons[i].setHorizontalTextPosition(JButton.CENTER);
+ ruleButtons[i].setVerticalTextPosition(JButton.BOTTOM);
- ruleButtons[i].setToolTipText(rule.getRuleName() + ": " + rule.getDescription());
+ ruleFrame.getButtonGroup().add(ruleButtons[i]);
+ ruleButtons[i].setToolTipText(rule.getRuleName() + ": " + rule.getDescription()); // showing description
ruleButtons[i].addActionListener(ruleFrame.getController());
add(ruleButtons[i]);
+
}
revalidate();
}
+
+ /**
+ * Search a certain rule in all the puzzles and set it for the searchBarPanel
+ *
+ * @param puzzle, ruleName
+ *
+ * This function is the searching algorithm for "public void setSearchBar(Puzzle allPuzzle)" (below)
+ *
+ * It takes two param Puzzle puzzle and String ruleName
+ * puzzle contains rules, this function will compare each rule of puzzle with ruleName,
+ * to find exact same, similar rules, or all the rules with same start letter (if input is a signal letter)
+ */
+ public void searchForRule(Puzzle puzzle, String ruleName) {
+
+ List> allrules = new ArrayList>(3);
+ allrules.add(0, puzzle.getBasicRules());
+ allrules.add(1, puzzle.getCaseRules());
+ allrules.add(2, puzzle.getContradictionRules());
+
+ ruleButtons = new RuleButton[100];
+ int similarfound = 0;
+
+
+ for(int i = 0; i < allrules.size(); i++) {
+ for (int j = 0; j < allrules.get(i).size(); j++) {
+ Rule rule = allrules.get(i).get(j);
+ if ((ruleName).equals(rule.getRuleName().toUpperCase())) {
+
+ ruleButtons[0] = new RuleButton(rule);
+ ruleFrame.getButtonGroup().add(ruleButtons[0]);
+
+ ruleButtons[0].setToolTipText(rule.getRuleName() + ": " + rule.getDescription());
+ ruleButtons[0].addActionListener(ruleFrame.getController());
+ add(ruleButtons[0]);
+ revalidate();
+ return;
+
+ }
+ else if(similarityCheck(ruleName, rule.getRuleName().toUpperCase())>0.2){
+ ruleButtons[similarfound] = new RuleButton(rule);
+ ruleFrame.getButtonGroup().add(ruleButtons[similarfound]);
+
+ ruleButtons[similarfound].setToolTipText(rule.getRuleName() + ": " + rule.getDescription());
+ ruleButtons[similarfound].addActionListener(ruleFrame.getController());
+ add(ruleButtons[similarfound]);
+ similarfound+=1;
+ revalidate();
+ }
+ else if((ruleName.charAt(0)) == (rule.getRuleName().toUpperCase()).charAt(0)){
+ ruleButtons[similarfound] = new RuleButton(rule);
+ ruleFrame.getButtonGroup().add(ruleButtons[similarfound]);
+
+ ruleButtons[similarfound].setToolTipText(rule.getRuleName() + ": " + rule.getDescription());
+ ruleButtons[similarfound].addActionListener(ruleFrame.getController());
+ add(ruleButtons[similarfound]);
+ similarfound+=1;
+ revalidate();
+ }
+ }
+ }
+
+ if(ruleButtons[0] == null) {
+ JOptionPane.showMessageDialog(null, "Please input the correct rule name", "Confirm", JOptionPane.INFORMATION_MESSAGE);
+ }
+ }
+
+ /**
+ * Calculates the similarity (a number within 0 and 1) between two strings.
+ * This funtion will take two para String s1 and String s2, which s1 is the user's input
+ * and s2 is the compared really rule name
+ *
+ * similarityCheck will use a helper function to calculate a similarity degree(from 0 to 1).
+ * closer to 0 means less similar, and closer to 1 means more similar.
+ */
+ public static double similarityCheck(String s1, String s2) {
+ String longer = s1, shorter = s2;
+ if (s1.length() < s2.length()) { // longer should always have greater length
+ longer = s2; shorter = s1;
+ }
+ int longerLength = longer.length();
+ if (longerLength == 0) {
+ return 1.0; /* both strings are zero length */
+ }
+ return (longerLength - editDistance(longer, shorter)) / (double) longerLength;
+ }
+ /**
+ * Help function for similarityCheck();
+ */
+ public static int editDistance(String s1, String s2) {
+ s1 = s1.toLowerCase();
+ s2 = s2.toLowerCase();
+
+ int[] costs = new int[s2.length() + 1];
+ for (int i = 0; i <= s1.length(); i++) {
+ int lastValue = i;
+ for (int j = 0; j <= s2.length(); j++) {
+ if (i == 0) {
+ costs[j] = j;
+ }
+ else {
+ if (j > 0) {
+ int newValue = costs[j - 1];
+ if (s1.charAt(i - 1) != s2.charAt(j - 1)) {
+ newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
+ }
+ costs[j - 1] = lastValue;
+ lastValue = newValue;
+ }
+ }
+ }
+ if (i > 0) {
+ costs[s2.length()] = lastValue;
+ }
+ }
+ return costs[s2.length()];
+ }
+
+ /**
+ * Sets the search bar for SearchBarPanel
+ * search bar allows user to input a name to get relative rules
+ * once a name is entered and click ok will load (a/several) rule icon,
+ * which has all the functions just as other rule icons.
+ */
+ public void setSearchBar(Puzzle allPuzzle){
+
+ searchBarPanel = new JPanel(new FlowLayout(SwingConstants.LEADING, 6, 6));
+ add(searchBarPanel);
+ JLabel findLabel = new JLabel("Search:");
+ searchBarPanel.add(findLabel);
+ searchBarPanel.add(Box.createRigidArea(new Dimension(1, 0)));
+ textField = new JTextField(8);
+ searchBarPanel.add(textField);
+ searchBarPanel.add(Box.createRigidArea(new Dimension(1, 0)));
+ JButton findButton = new JButton("Go");
+ findButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent event) {
+ if (ruleButtons != null) {
+ for(int i = 0; i != ruleButtons.length; i++) {
+ if(ruleButtons[i]==null){
+ continue;
+ }
+ ruleButtons[i].removeActionListener(ruleFrame.getController());
+ }
+ }
+ String inputRule = textField.getText().toUpperCase().trim();
+
+ if (!inputRule.isEmpty()) {
+ if (ruleButtons != null) {
+
+ for (int x = 0; x < ruleButtons.length; ++x) {
+ if(ruleButtons[x]==null){
+ continue;
+ }
+ remove(ruleButtons[x]);
+ }
+ }
+ searchForRule(allPuzzle, inputRule);
+ }
+ else {
+ JOptionPane.showMessageDialog(null, "Please give a name","Confirm",JOptionPane.INFORMATION_MESSAGE);
+ }
+
+ }
+ });
+ searchBarPanel.add(findButton);
+ }
+
/**
* Sets the selection by the specified rule
*
diff --git a/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/SearchBarPanel.java b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/SearchBarPanel.java
new file mode 100644
index 000000000..2c32b6e88
--- /dev/null
+++ b/src/main/java/edu/rpi/legup/ui/proofeditorui/rulesview/SearchBarPanel.java
@@ -0,0 +1,19 @@
+package edu.rpi.legup.ui.proofeditorui.rulesview;
+
+import javax.swing.*;
+
+public class SearchBarPanel extends RulePanel {
+ /**
+ * SearchBarPanel Constructor creates a SearchBarPanel
+ *
+ * @param ruleFrame rule frame that this SearchBarPanel is contained in
+ *
+ * This class is used to create a panel named "search bar"
+ */
+ SearchBarPanel(RuleFrame ruleFrame) {
+ super(ruleFrame);
+ this.icon = new ImageIcon(ClassLoader.getSystemClassLoader().getResource("edu/rpi/legup/images/Legup/Zoom In.png"));
+ this.name = "Search Rules";
+ this.toolTip = "Search Rules";
+ }
+}
diff --git a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementButton.java b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementButton.java
index 037782225..dfe879379 100644
--- a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementButton.java
+++ b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementButton.java
@@ -4,14 +4,18 @@
import edu.rpi.legup.model.rules.Rule;
import javax.swing.*;
+import javax.swing.border.Border;
+import java.awt.*;
public class ElementButton extends JButton {
private Element element;
+ private final Border originalBorder;
ElementButton(Element e) {
super(e.getImageIcon());
this.element = e;
+ this.originalBorder = this.getBorder();
}
public Element getElement() {
@@ -21,4 +25,14 @@ public Element getElement() {
public void setElement(Element e) {
this.element = e;
}
+
+ public void setBorderToSelected() {
+ Border newBorderIn = BorderFactory.createLineBorder(new Color(20, 140, 70), 2, true);
+ Border newBorder = BorderFactory.createCompoundBorder(newBorderIn, this.originalBorder);
+ this.setBorder(newBorder);
+ }
+
+ public void resetBorder() {
+ this.setBorder(this.originalBorder);
+ }
}
diff --git a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementFrame.java b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementFrame.java
index 3316379df..1fc2b3792 100644
--- a/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementFrame.java
+++ b/src/main/java/edu/rpi/legup/ui/puzzleeditorui/elementsview/ElementFrame.java
@@ -2,6 +2,7 @@
import edu.rpi.legup.controller.EditorElementController;
import edu.rpi.legup.model.Puzzle;
+import edu.rpi.legup.ui.lookandfeel.components.MaterialTabbedPaneUI;
import javax.swing.*;
import javax.swing.border.TitledBorder;
@@ -22,16 +23,28 @@ public class ElementFrame extends JPanel {
public ElementFrame(EditorElementController controller) {
this.controller = controller;
+ MaterialTabbedPaneUI tabOverride = new MaterialTabbedPaneUI() {
+ //this prevents the tabs from moving around when you select them
+ @Override
+ protected boolean shouldRotateTabRuns(int i) {
+ return false;
+ }
+ };
this.tabbedPane = new JTabbedPane();
+ tabbedPane.setUI(tabOverride);
JLabel status = new JLabel("", SwingConstants.CENTER);
this.buttonGroup = new ButtonGroup();
nonPlaceableElementPanel = new NonPlaceableElementPanel(this);
+ //nonPlaceableElementPanel.setMinimumSize(new Dimension(100,200));
tabbedPane.addTab(nonPlaceableElementPanel.getName(), nonPlaceableElementPanel.getIcon(), new JScrollPane(nonPlaceableElementPanel), nonPlaceableElementPanel.getToolTip());
placeableElementPanel = new PlaceableElementPanel(this);
+ //placeableElementPanel.setMinimuSize(new Dimension(100,200));
tabbedPane.addTab(placeableElementPanel.getName(), placeableElementPanel.getIcon(), new JScrollPane(placeableElementPanel), placeableElementPanel.getToolTip());
+ tabbedPane.setTabPlacement(JTabbedPane.TOP);
+
setLayout(new BorderLayout());
setMinimumSize(new Dimension(250, 256));
diff --git a/src/main/resources/edu/rpi/legup/images/skyscraper/DuplicateNumber.png b/src/main/resources/edu/rpi/legup/images/skyscraper/DuplicateNumber.png
deleted file mode 100644
index 64fb4fc86..000000000
Binary files a/src/main/resources/edu/rpi/legup/images/skyscraper/DuplicateNumber.png and /dev/null differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscraper/LastNumber.png b/src/main/resources/edu/rpi/legup/images/skyscraper/LastNumber.png
deleted file mode 100644
index 1c219e328..000000000
Binary files a/src/main/resources/edu/rpi/legup/images/skyscraper/LastNumber.png and /dev/null differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscraper/PossibleContents.png b/src/main/resources/edu/rpi/legup/images/skyscraper/PossibleContents.png
deleted file mode 100644
index 7eaee5d06..000000000
Binary files a/src/main/resources/edu/rpi/legup/images/skyscraper/PossibleContents.png and /dev/null differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/cases/CellForNumber.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/cases/CellForNumber.png
new file mode 100644
index 000000000..7ab0cdbef
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/cases/CellForNumber.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/cases/NumberForCell.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/cases/NumberForCell.png
new file mode 100644
index 000000000..fedbbbac8
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/cases/NumberForCell.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/DuplicateNumber.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/DuplicateNumber.png
new file mode 100644
index 000000000..7ba489c2b
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/DuplicateNumber.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/ExceedingVisibility.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/ExceedingVisibility.png
new file mode 100644
index 000000000..ff999f4bc
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/ExceedingVisibility.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/InsufficientVisibility.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/InsufficientVisibility.png
new file mode 100644
index 000000000..cfe04a503
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/InsufficientVisibility.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/PreemptiveVisibility.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/PreemptiveVisibility.png
new file mode 100644
index 000000000..6d330baa6
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/PreemptiveVisibility.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/UnresolvedCell.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/UnresolvedCell.png
new file mode 100644
index 000000000..76947671d
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/UnresolvedCell.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/UnresolvedNumber.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/UnresolvedNumber.png
new file mode 100644
index 000000000..8862702f1
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/contradictions/UnresolvedNumber.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/FixedMax.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/FixedMax.png
new file mode 100644
index 000000000..8a26bbfeb
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/FixedMax.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/LastCell.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/LastCell.png
new file mode 100644
index 000000000..216a0f3a1
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/LastCell.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/LastNumber.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/LastNumber.png
new file mode 100644
index 000000000..1e0555648
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/LastNumber.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/NEdge.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/NEdge.png
new file mode 100644
index 000000000..d3dd36bbc
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/NEdge.png differ
diff --git a/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/OneEdge.png b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/OneEdge.png
new file mode 100644
index 000000000..40d6ff65f
Binary files /dev/null and b/src/main/resources/edu/rpi/legup/images/skyscrapers/rules/OneEdge.png differ
diff --git a/src/main/resources/edu/rpi/legup/legup/config b/src/main/resources/edu/rpi/legup/legup/config
index 8e3b4b84c..bb7da871a 100644
--- a/src/main/resources/edu/rpi/legup/legup/config
+++ b/src/main/resources/edu/rpi/legup/legup/config
@@ -15,7 +15,7 @@
+ fileCreationDisabled="false"/>