diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..8aa5b81e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,32 @@
+*~
+*.synctex.gz
+*.checkstyle
+local.properties
+*.tex~
+*.dvi
+*.glo
+*.gls
+*.glg
+*.ist
+*.lyx
+*.log
+*.backup
+*.aux
+*.out
+*.toc
+*.kilepr
+*.nav
+*.snm
+*.class
+*.cfg
+lint.xml
+sudoq-model/bin
+test-model/bin
+sudoq-app/bin
+sudoq-app/gen
+sudoq-app/assets
+sudoq-app/libs/model.jar
+test-app/bin
+test-app/gen
+test-app/coverage/
+tmp
diff --git a/sudokus/HyperSudoku/difficult/sudoku_1.xml b/sudokus/HyperSudoku/difficult/sudoku_1.xml
new file mode 100644
index 00000000..cb848012
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_10.xml b/sudokus/HyperSudoku/difficult/sudoku_10.xml
new file mode 100644
index 00000000..540afa42
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_2.xml b/sudokus/HyperSudoku/difficult/sudoku_2.xml
new file mode 100644
index 00000000..e87a07b2
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_3.xml b/sudokus/HyperSudoku/difficult/sudoku_3.xml
new file mode 100644
index 00000000..79a19f76
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_4.xml b/sudokus/HyperSudoku/difficult/sudoku_4.xml
new file mode 100644
index 00000000..77cad741
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_5.xml b/sudokus/HyperSudoku/difficult/sudoku_5.xml
new file mode 100644
index 00000000..452cf7cd
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_6.xml b/sudokus/HyperSudoku/difficult/sudoku_6.xml
new file mode 100644
index 00000000..9098a133
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_7.xml b/sudokus/HyperSudoku/difficult/sudoku_7.xml
new file mode 100644
index 00000000..b68197a6
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_8.xml b/sudokus/HyperSudoku/difficult/sudoku_8.xml
new file mode 100644
index 00000000..a336d999
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/difficult/sudoku_9.xml b/sudokus/HyperSudoku/difficult/sudoku_9.xml
new file mode 100644
index 00000000..958ff97c
--- /dev/null
+++ b/sudokus/HyperSudoku/difficult/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_1.xml b/sudokus/HyperSudoku/easy/sudoku_1.xml
new file mode 100644
index 00000000..2a94f10e
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_10.xml b/sudokus/HyperSudoku/easy/sudoku_10.xml
new file mode 100644
index 00000000..767c36a8
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_2.xml b/sudokus/HyperSudoku/easy/sudoku_2.xml
new file mode 100644
index 00000000..efc11382
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_3.xml b/sudokus/HyperSudoku/easy/sudoku_3.xml
new file mode 100644
index 00000000..d4b3f4bd
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_4.xml b/sudokus/HyperSudoku/easy/sudoku_4.xml
new file mode 100644
index 00000000..551cf854
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_5.xml b/sudokus/HyperSudoku/easy/sudoku_5.xml
new file mode 100644
index 00000000..95b0aa44
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_6.xml b/sudokus/HyperSudoku/easy/sudoku_6.xml
new file mode 100644
index 00000000..9b742752
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_7.xml b/sudokus/HyperSudoku/easy/sudoku_7.xml
new file mode 100644
index 00000000..e60ad025
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_8.xml b/sudokus/HyperSudoku/easy/sudoku_8.xml
new file mode 100644
index 00000000..60ab3df1
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/easy/sudoku_9.xml b/sudokus/HyperSudoku/easy/sudoku_9.xml
new file mode 100644
index 00000000..9c0ed1be
--- /dev/null
+++ b/sudokus/HyperSudoku/easy/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_1.xml b/sudokus/HyperSudoku/infernal/sudoku_1.xml
new file mode 100644
index 00000000..fa7acecc
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_10.xml b/sudokus/HyperSudoku/infernal/sudoku_10.xml
new file mode 100644
index 00000000..1c60b0e4
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_2.xml b/sudokus/HyperSudoku/infernal/sudoku_2.xml
new file mode 100644
index 00000000..c3e6fcf7
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_3.xml b/sudokus/HyperSudoku/infernal/sudoku_3.xml
new file mode 100644
index 00000000..a1faf6bf
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_4.xml b/sudokus/HyperSudoku/infernal/sudoku_4.xml
new file mode 100644
index 00000000..39f49158
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_5.xml b/sudokus/HyperSudoku/infernal/sudoku_5.xml
new file mode 100644
index 00000000..d4ff6668
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_6.xml b/sudokus/HyperSudoku/infernal/sudoku_6.xml
new file mode 100644
index 00000000..6086cd4d
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_7.xml b/sudokus/HyperSudoku/infernal/sudoku_7.xml
new file mode 100644
index 00000000..55bf29b2
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_8.xml b/sudokus/HyperSudoku/infernal/sudoku_8.xml
new file mode 100644
index 00000000..fb0c86ee
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/infernal/sudoku_9.xml b/sudokus/HyperSudoku/infernal/sudoku_9.xml
new file mode 100644
index 00000000..f46618a8
--- /dev/null
+++ b/sudokus/HyperSudoku/infernal/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_1.xml b/sudokus/HyperSudoku/medium/sudoku_1.xml
new file mode 100644
index 00000000..54cf8eca
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_10.xml b/sudokus/HyperSudoku/medium/sudoku_10.xml
new file mode 100644
index 00000000..1b45f32c
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_2.xml b/sudokus/HyperSudoku/medium/sudoku_2.xml
new file mode 100644
index 00000000..33c8803d
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_3.xml b/sudokus/HyperSudoku/medium/sudoku_3.xml
new file mode 100644
index 00000000..79eafce8
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_4.xml b/sudokus/HyperSudoku/medium/sudoku_4.xml
new file mode 100644
index 00000000..5a075ea7
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_5.xml b/sudokus/HyperSudoku/medium/sudoku_5.xml
new file mode 100644
index 00000000..1d34a9c9
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_6.xml b/sudokus/HyperSudoku/medium/sudoku_6.xml
new file mode 100644
index 00000000..f3c535c8
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_7.xml b/sudokus/HyperSudoku/medium/sudoku_7.xml
new file mode 100644
index 00000000..a9f1468f
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_8.xml b/sudokus/HyperSudoku/medium/sudoku_8.xml
new file mode 100644
index 00000000..34023f05
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/HyperSudoku/medium/sudoku_9.xml b/sudokus/HyperSudoku/medium/sudoku_9.xml
new file mode 100644
index 00000000..d5ef69f8
--- /dev/null
+++ b/sudokus/HyperSudoku/medium/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_1.xml b/sudokus/Xsudoku/difficult/sudoku_1.xml
new file mode 100644
index 00000000..d246f6b4
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_10.xml b/sudokus/Xsudoku/difficult/sudoku_10.xml
new file mode 100644
index 00000000..383cb732
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_2.xml b/sudokus/Xsudoku/difficult/sudoku_2.xml
new file mode 100644
index 00000000..5a9725bf
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_3.xml b/sudokus/Xsudoku/difficult/sudoku_3.xml
new file mode 100644
index 00000000..38b917ce
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_4.xml b/sudokus/Xsudoku/difficult/sudoku_4.xml
new file mode 100644
index 00000000..924a1027
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_5.xml b/sudokus/Xsudoku/difficult/sudoku_5.xml
new file mode 100644
index 00000000..90c1f2ff
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_6.xml b/sudokus/Xsudoku/difficult/sudoku_6.xml
new file mode 100644
index 00000000..91e4c243
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_7.xml b/sudokus/Xsudoku/difficult/sudoku_7.xml
new file mode 100644
index 00000000..9fd00d70
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_8.xml b/sudokus/Xsudoku/difficult/sudoku_8.xml
new file mode 100644
index 00000000..a5314e3e
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/difficult/sudoku_9.xml b/sudokus/Xsudoku/difficult/sudoku_9.xml
new file mode 100644
index 00000000..4f65d8ab
--- /dev/null
+++ b/sudokus/Xsudoku/difficult/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_1.xml b/sudokus/Xsudoku/easy/sudoku_1.xml
new file mode 100644
index 00000000..b438d8ac
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_10.xml b/sudokus/Xsudoku/easy/sudoku_10.xml
new file mode 100644
index 00000000..ac8f66f2
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_2.xml b/sudokus/Xsudoku/easy/sudoku_2.xml
new file mode 100644
index 00000000..7594a88f
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_3.xml b/sudokus/Xsudoku/easy/sudoku_3.xml
new file mode 100644
index 00000000..857fa7cd
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_4.xml b/sudokus/Xsudoku/easy/sudoku_4.xml
new file mode 100644
index 00000000..041aa325
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_5.xml b/sudokus/Xsudoku/easy/sudoku_5.xml
new file mode 100644
index 00000000..39992132
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_6.xml b/sudokus/Xsudoku/easy/sudoku_6.xml
new file mode 100644
index 00000000..6bee4959
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_7.xml b/sudokus/Xsudoku/easy/sudoku_7.xml
new file mode 100644
index 00000000..cf8ee49a
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_8.xml b/sudokus/Xsudoku/easy/sudoku_8.xml
new file mode 100644
index 00000000..32b7fe36
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/easy/sudoku_9.xml b/sudokus/Xsudoku/easy/sudoku_9.xml
new file mode 100644
index 00000000..f2a643a2
--- /dev/null
+++ b/sudokus/Xsudoku/easy/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_1.xml b/sudokus/Xsudoku/infernal/sudoku_1.xml
new file mode 100644
index 00000000..080d3d31
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_10.xml b/sudokus/Xsudoku/infernal/sudoku_10.xml
new file mode 100644
index 00000000..27ac0177
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_2.xml b/sudokus/Xsudoku/infernal/sudoku_2.xml
new file mode 100644
index 00000000..7947b689
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_3.xml b/sudokus/Xsudoku/infernal/sudoku_3.xml
new file mode 100644
index 00000000..154f6b42
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_4.xml b/sudokus/Xsudoku/infernal/sudoku_4.xml
new file mode 100644
index 00000000..81d6c74c
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_5.xml b/sudokus/Xsudoku/infernal/sudoku_5.xml
new file mode 100644
index 00000000..de72583a
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_6.xml b/sudokus/Xsudoku/infernal/sudoku_6.xml
new file mode 100644
index 00000000..b6d30871
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_7.xml b/sudokus/Xsudoku/infernal/sudoku_7.xml
new file mode 100644
index 00000000..e6b53967
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_8.xml b/sudokus/Xsudoku/infernal/sudoku_8.xml
new file mode 100644
index 00000000..5fe6b0b1
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/infernal/sudoku_9.xml b/sudokus/Xsudoku/infernal/sudoku_9.xml
new file mode 100644
index 00000000..ce195a51
--- /dev/null
+++ b/sudokus/Xsudoku/infernal/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_1.xml b/sudokus/Xsudoku/medium/sudoku_1.xml
new file mode 100644
index 00000000..00be37ce
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_10.xml b/sudokus/Xsudoku/medium/sudoku_10.xml
new file mode 100644
index 00000000..60327c49
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_2.xml b/sudokus/Xsudoku/medium/sudoku_2.xml
new file mode 100644
index 00000000..861e3e45
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_3.xml b/sudokus/Xsudoku/medium/sudoku_3.xml
new file mode 100644
index 00000000..16103b14
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_4.xml b/sudokus/Xsudoku/medium/sudoku_4.xml
new file mode 100644
index 00000000..35abdd4d
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_5.xml b/sudokus/Xsudoku/medium/sudoku_5.xml
new file mode 100644
index 00000000..6ae39081
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_6.xml b/sudokus/Xsudoku/medium/sudoku_6.xml
new file mode 100644
index 00000000..ffe8fc46
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_7.xml b/sudokus/Xsudoku/medium/sudoku_7.xml
new file mode 100644
index 00000000..2b6c0ce2
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_8.xml b/sudokus/Xsudoku/medium/sudoku_8.xml
new file mode 100644
index 00000000..0b7151e9
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/Xsudoku/medium/sudoku_9.xml b/sudokus/Xsudoku/medium/sudoku_9.xml
new file mode 100644
index 00000000..c07261c8
--- /dev/null
+++ b/sudokus/Xsudoku/medium/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_1.xml b/sudokus/samurai/difficult/sudoku_1.xml
new file mode 100644
index 00000000..575c3d1a
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_1.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_10.xml b/sudokus/samurai/difficult/sudoku_10.xml
new file mode 100644
index 00000000..dedcd440
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_10.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_2.xml b/sudokus/samurai/difficult/sudoku_2.xml
new file mode 100644
index 00000000..b22acf97
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_2.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_3.xml b/sudokus/samurai/difficult/sudoku_3.xml
new file mode 100644
index 00000000..b1df43fb
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_3.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_4.xml b/sudokus/samurai/difficult/sudoku_4.xml
new file mode 100644
index 00000000..6a904b8c
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_4.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_5.xml b/sudokus/samurai/difficult/sudoku_5.xml
new file mode 100644
index 00000000..3b94eeb4
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_5.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_6.xml b/sudokus/samurai/difficult/sudoku_6.xml
new file mode 100644
index 00000000..a1379b8a
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_6.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_7.xml b/sudokus/samurai/difficult/sudoku_7.xml
new file mode 100644
index 00000000..5a7a018e
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_7.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_8.xml b/sudokus/samurai/difficult/sudoku_8.xml
new file mode 100644
index 00000000..a22ac2e5
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_8.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/difficult/sudoku_9.xml b/sudokus/samurai/difficult/sudoku_9.xml
new file mode 100644
index 00000000..37f8f3bd
--- /dev/null
+++ b/sudokus/samurai/difficult/sudoku_9.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_1.xml b/sudokus/samurai/easy/sudoku_1.xml
new file mode 100644
index 00000000..a72049ec
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_1.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_10.xml b/sudokus/samurai/easy/sudoku_10.xml
new file mode 100644
index 00000000..2863bec5
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_10.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_2.xml b/sudokus/samurai/easy/sudoku_2.xml
new file mode 100644
index 00000000..11ab7c03
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_2.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_3.xml b/sudokus/samurai/easy/sudoku_3.xml
new file mode 100644
index 00000000..0ce5dc4b
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_3.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_4.xml b/sudokus/samurai/easy/sudoku_4.xml
new file mode 100644
index 00000000..0f34cf1e
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_4.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_5.xml b/sudokus/samurai/easy/sudoku_5.xml
new file mode 100644
index 00000000..79075755
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_5.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_6.xml b/sudokus/samurai/easy/sudoku_6.xml
new file mode 100644
index 00000000..99f1cfd1
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_6.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_7.xml b/sudokus/samurai/easy/sudoku_7.xml
new file mode 100644
index 00000000..9b6f5873
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_7.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_8.xml b/sudokus/samurai/easy/sudoku_8.xml
new file mode 100644
index 00000000..415bd44d
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_8.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/easy/sudoku_9.xml b/sudokus/samurai/easy/sudoku_9.xml
new file mode 100644
index 00000000..96fdfd0b
--- /dev/null
+++ b/sudokus/samurai/easy/sudoku_9.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_1.xml b/sudokus/samurai/infernal/sudoku_1.xml
new file mode 100644
index 00000000..bbfc6614
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_1.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_10.xml b/sudokus/samurai/infernal/sudoku_10.xml
new file mode 100644
index 00000000..1299b631
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_10.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_2.xml b/sudokus/samurai/infernal/sudoku_2.xml
new file mode 100644
index 00000000..123c374e
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_2.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_3.xml b/sudokus/samurai/infernal/sudoku_3.xml
new file mode 100644
index 00000000..a2c7a7f5
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_3.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_4.xml b/sudokus/samurai/infernal/sudoku_4.xml
new file mode 100644
index 00000000..d2558484
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_4.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_5.xml b/sudokus/samurai/infernal/sudoku_5.xml
new file mode 100644
index 00000000..052ae7f1
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_5.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_6.xml b/sudokus/samurai/infernal/sudoku_6.xml
new file mode 100644
index 00000000..a6ddb589
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_6.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_7.xml b/sudokus/samurai/infernal/sudoku_7.xml
new file mode 100644
index 00000000..f2a26b27
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_7.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_8.xml b/sudokus/samurai/infernal/sudoku_8.xml
new file mode 100644
index 00000000..5aeb3ecf
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_8.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/infernal/sudoku_9.xml b/sudokus/samurai/infernal/sudoku_9.xml
new file mode 100644
index 00000000..46cf6291
--- /dev/null
+++ b/sudokus/samurai/infernal/sudoku_9.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_1.xml b/sudokus/samurai/medium/sudoku_1.xml
new file mode 100644
index 00000000..6312b29a
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_1.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_10.xml b/sudokus/samurai/medium/sudoku_10.xml
new file mode 100644
index 00000000..57b3036e
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_10.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_2.xml b/sudokus/samurai/medium/sudoku_2.xml
new file mode 100644
index 00000000..bcf3a18f
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_2.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_3.xml b/sudokus/samurai/medium/sudoku_3.xml
new file mode 100644
index 00000000..f2912278
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_3.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_4.xml b/sudokus/samurai/medium/sudoku_4.xml
new file mode 100644
index 00000000..0c57abb4
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_4.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_5.xml b/sudokus/samurai/medium/sudoku_5.xml
new file mode 100644
index 00000000..d76691dd
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_5.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_6.xml b/sudokus/samurai/medium/sudoku_6.xml
new file mode 100644
index 00000000..261fd0df
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_6.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_7.xml b/sudokus/samurai/medium/sudoku_7.xml
new file mode 100644
index 00000000..39498f72
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_7.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_8.xml b/sudokus/samurai/medium/sudoku_8.xml
new file mode 100644
index 00000000..202a3f4b
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_8.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/samurai/medium/sudoku_9.xml b/sudokus/samurai/medium/sudoku_9.xml
new file mode 100644
index 00000000..fc24963c
--- /dev/null
+++ b/sudokus/samurai/medium/sudoku_9.xml
@@ -0,0 +1,1111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_1.xml b/sudokus/squigglya/difficult/sudoku_1.xml
new file mode 100644
index 00000000..a339c94a
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_10.xml b/sudokus/squigglya/difficult/sudoku_10.xml
new file mode 100644
index 00000000..c2cedbbc
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_2.xml b/sudokus/squigglya/difficult/sudoku_2.xml
new file mode 100644
index 00000000..4b33592c
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_3.xml b/sudokus/squigglya/difficult/sudoku_3.xml
new file mode 100644
index 00000000..9ae8f9a8
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_4.xml b/sudokus/squigglya/difficult/sudoku_4.xml
new file mode 100644
index 00000000..2f4f19d2
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_5.xml b/sudokus/squigglya/difficult/sudoku_5.xml
new file mode 100644
index 00000000..19afa5b4
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_6.xml b/sudokus/squigglya/difficult/sudoku_6.xml
new file mode 100644
index 00000000..a6f6f127
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_7.xml b/sudokus/squigglya/difficult/sudoku_7.xml
new file mode 100644
index 00000000..cd7daabf
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_8.xml b/sudokus/squigglya/difficult/sudoku_8.xml
new file mode 100644
index 00000000..60b9e570
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/difficult/sudoku_9.xml b/sudokus/squigglya/difficult/sudoku_9.xml
new file mode 100644
index 00000000..ca71c32e
--- /dev/null
+++ b/sudokus/squigglya/difficult/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_1.xml b/sudokus/squigglya/easy/sudoku_1.xml
new file mode 100644
index 00000000..59069b54
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_10.xml b/sudokus/squigglya/easy/sudoku_10.xml
new file mode 100644
index 00000000..8e7af941
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_2.xml b/sudokus/squigglya/easy/sudoku_2.xml
new file mode 100644
index 00000000..496aed4c
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_3.xml b/sudokus/squigglya/easy/sudoku_3.xml
new file mode 100644
index 00000000..b2a86fa8
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_4.xml b/sudokus/squigglya/easy/sudoku_4.xml
new file mode 100644
index 00000000..39bbad36
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_5.xml b/sudokus/squigglya/easy/sudoku_5.xml
new file mode 100644
index 00000000..501220d1
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_6.xml b/sudokus/squigglya/easy/sudoku_6.xml
new file mode 100644
index 00000000..c458cfe5
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_7.xml b/sudokus/squigglya/easy/sudoku_7.xml
new file mode 100644
index 00000000..944ff472
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_8.xml b/sudokus/squigglya/easy/sudoku_8.xml
new file mode 100644
index 00000000..7e521353
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/easy/sudoku_9.xml b/sudokus/squigglya/easy/sudoku_9.xml
new file mode 100644
index 00000000..c1ff3bab
--- /dev/null
+++ b/sudokus/squigglya/easy/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_1.xml b/sudokus/squigglya/infernal/sudoku_1.xml
new file mode 100644
index 00000000..f76b4b01
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_10.xml b/sudokus/squigglya/infernal/sudoku_10.xml
new file mode 100644
index 00000000..a4a3e0f1
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_2.xml b/sudokus/squigglya/infernal/sudoku_2.xml
new file mode 100644
index 00000000..9fff50b8
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_3.xml b/sudokus/squigglya/infernal/sudoku_3.xml
new file mode 100644
index 00000000..bf917742
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_4.xml b/sudokus/squigglya/infernal/sudoku_4.xml
new file mode 100644
index 00000000..1f9ed584
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_5.xml b/sudokus/squigglya/infernal/sudoku_5.xml
new file mode 100644
index 00000000..d6a83cba
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_6.xml b/sudokus/squigglya/infernal/sudoku_6.xml
new file mode 100644
index 00000000..cddc0e41
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_7.xml b/sudokus/squigglya/infernal/sudoku_7.xml
new file mode 100644
index 00000000..db39434f
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_8.xml b/sudokus/squigglya/infernal/sudoku_8.xml
new file mode 100644
index 00000000..518cddeb
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/infernal/sudoku_9.xml b/sudokus/squigglya/infernal/sudoku_9.xml
new file mode 100644
index 00000000..10665929
--- /dev/null
+++ b/sudokus/squigglya/infernal/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_1.xml b/sudokus/squigglya/medium/sudoku_1.xml
new file mode 100644
index 00000000..9d731628
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_10.xml b/sudokus/squigglya/medium/sudoku_10.xml
new file mode 100644
index 00000000..af621020
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_2.xml b/sudokus/squigglya/medium/sudoku_2.xml
new file mode 100644
index 00000000..4cac59ca
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_3.xml b/sudokus/squigglya/medium/sudoku_3.xml
new file mode 100644
index 00000000..85268e65
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_4.xml b/sudokus/squigglya/medium/sudoku_4.xml
new file mode 100644
index 00000000..2c579c4e
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_5.xml b/sudokus/squigglya/medium/sudoku_5.xml
new file mode 100644
index 00000000..d5035eaf
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_6.xml b/sudokus/squigglya/medium/sudoku_6.xml
new file mode 100644
index 00000000..516b9259
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_7.xml b/sudokus/squigglya/medium/sudoku_7.xml
new file mode 100644
index 00000000..89541d42
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_8.xml b/sudokus/squigglya/medium/sudoku_8.xml
new file mode 100644
index 00000000..e550e86e
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglya/medium/sudoku_9.xml b/sudokus/squigglya/medium/sudoku_9.xml
new file mode 100644
index 00000000..cbc0a681
--- /dev/null
+++ b/sudokus/squigglya/medium/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_1.xml b/sudokus/squigglyb/difficult/sudoku_1.xml
new file mode 100644
index 00000000..60855e47
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_10.xml b/sudokus/squigglyb/difficult/sudoku_10.xml
new file mode 100644
index 00000000..bac1d9b1
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_2.xml b/sudokus/squigglyb/difficult/sudoku_2.xml
new file mode 100644
index 00000000..71a12be5
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_3.xml b/sudokus/squigglyb/difficult/sudoku_3.xml
new file mode 100644
index 00000000..350ef0a7
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_4.xml b/sudokus/squigglyb/difficult/sudoku_4.xml
new file mode 100644
index 00000000..9c37d090
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_5.xml b/sudokus/squigglyb/difficult/sudoku_5.xml
new file mode 100644
index 00000000..3a7aa143
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_6.xml b/sudokus/squigglyb/difficult/sudoku_6.xml
new file mode 100644
index 00000000..5f6ea1aa
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_7.xml b/sudokus/squigglyb/difficult/sudoku_7.xml
new file mode 100644
index 00000000..0077a8db
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_8.xml b/sudokus/squigglyb/difficult/sudoku_8.xml
new file mode 100644
index 00000000..fd5f6da8
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/difficult/sudoku_9.xml b/sudokus/squigglyb/difficult/sudoku_9.xml
new file mode 100644
index 00000000..55955939
--- /dev/null
+++ b/sudokus/squigglyb/difficult/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_1.xml b/sudokus/squigglyb/easy/sudoku_1.xml
new file mode 100644
index 00000000..150e29c3
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_10.xml b/sudokus/squigglyb/easy/sudoku_10.xml
new file mode 100644
index 00000000..e1e5971e
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_2.xml b/sudokus/squigglyb/easy/sudoku_2.xml
new file mode 100644
index 00000000..df168868
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_3.xml b/sudokus/squigglyb/easy/sudoku_3.xml
new file mode 100644
index 00000000..3cefb85a
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_4.xml b/sudokus/squigglyb/easy/sudoku_4.xml
new file mode 100644
index 00000000..3872d8b2
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_5.xml b/sudokus/squigglyb/easy/sudoku_5.xml
new file mode 100644
index 00000000..6d41eb35
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_6.xml b/sudokus/squigglyb/easy/sudoku_6.xml
new file mode 100644
index 00000000..a13b6e09
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_7.xml b/sudokus/squigglyb/easy/sudoku_7.xml
new file mode 100644
index 00000000..4443d549
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_8.xml b/sudokus/squigglyb/easy/sudoku_8.xml
new file mode 100644
index 00000000..0ffa427a
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/easy/sudoku_9.xml b/sudokus/squigglyb/easy/sudoku_9.xml
new file mode 100644
index 00000000..2bd90c3a
--- /dev/null
+++ b/sudokus/squigglyb/easy/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_1.xml b/sudokus/squigglyb/infernal/sudoku_1.xml
new file mode 100644
index 00000000..b47935e6
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_10.xml b/sudokus/squigglyb/infernal/sudoku_10.xml
new file mode 100644
index 00000000..9508e507
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_2.xml b/sudokus/squigglyb/infernal/sudoku_2.xml
new file mode 100644
index 00000000..197c5095
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_3.xml b/sudokus/squigglyb/infernal/sudoku_3.xml
new file mode 100644
index 00000000..454474d2
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_4.xml b/sudokus/squigglyb/infernal/sudoku_4.xml
new file mode 100644
index 00000000..8e8a672a
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_5.xml b/sudokus/squigglyb/infernal/sudoku_5.xml
new file mode 100644
index 00000000..8df4f263
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_6.xml b/sudokus/squigglyb/infernal/sudoku_6.xml
new file mode 100644
index 00000000..e200dee8
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_7.xml b/sudokus/squigglyb/infernal/sudoku_7.xml
new file mode 100644
index 00000000..42bef16c
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_8.xml b/sudokus/squigglyb/infernal/sudoku_8.xml
new file mode 100644
index 00000000..57a6c78a
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/infernal/sudoku_9.xml b/sudokus/squigglyb/infernal/sudoku_9.xml
new file mode 100644
index 00000000..9d36da9e
--- /dev/null
+++ b/sudokus/squigglyb/infernal/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_1.xml b/sudokus/squigglyb/medium/sudoku_1.xml
new file mode 100644
index 00000000..6b408268
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_10.xml b/sudokus/squigglyb/medium/sudoku_10.xml
new file mode 100644
index 00000000..2d4f330a
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_2.xml b/sudokus/squigglyb/medium/sudoku_2.xml
new file mode 100644
index 00000000..c42ec0da
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_3.xml b/sudokus/squigglyb/medium/sudoku_3.xml
new file mode 100644
index 00000000..2cc90a03
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_4.xml b/sudokus/squigglyb/medium/sudoku_4.xml
new file mode 100644
index 00000000..3cdd59fd
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_5.xml b/sudokus/squigglyb/medium/sudoku_5.xml
new file mode 100644
index 00000000..1c0abc8b
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_6.xml b/sudokus/squigglyb/medium/sudoku_6.xml
new file mode 100644
index 00000000..2618ff83
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_7.xml b/sudokus/squigglyb/medium/sudoku_7.xml
new file mode 100644
index 00000000..5a4e3d1b
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_8.xml b/sudokus/squigglyb/medium/sudoku_8.xml
new file mode 100644
index 00000000..8f903e92
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/squigglyb/medium/sudoku_9.xml b/sudokus/squigglyb/medium/sudoku_9.xml
new file mode 100644
index 00000000..38e3b302
--- /dev/null
+++ b/sudokus/squigglyb/medium/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_1.xml b/sudokus/stairstep/difficult/sudoku_1.xml
new file mode 100644
index 00000000..ffd4eb62
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_10.xml b/sudokus/stairstep/difficult/sudoku_10.xml
new file mode 100644
index 00000000..0a847c58
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_2.xml b/sudokus/stairstep/difficult/sudoku_2.xml
new file mode 100644
index 00000000..4e5dbd72
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_3.xml b/sudokus/stairstep/difficult/sudoku_3.xml
new file mode 100644
index 00000000..826ea576
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_4.xml b/sudokus/stairstep/difficult/sudoku_4.xml
new file mode 100644
index 00000000..fb1d5d42
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_5.xml b/sudokus/stairstep/difficult/sudoku_5.xml
new file mode 100644
index 00000000..47e2bbbd
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_6.xml b/sudokus/stairstep/difficult/sudoku_6.xml
new file mode 100644
index 00000000..7a2c006b
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_7.xml b/sudokus/stairstep/difficult/sudoku_7.xml
new file mode 100644
index 00000000..b1061ff4
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_8.xml b/sudokus/stairstep/difficult/sudoku_8.xml
new file mode 100644
index 00000000..5ad511c4
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/difficult/sudoku_9.xml b/sudokus/stairstep/difficult/sudoku_9.xml
new file mode 100644
index 00000000..d761e40e
--- /dev/null
+++ b/sudokus/stairstep/difficult/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_1.xml b/sudokus/stairstep/easy/sudoku_1.xml
new file mode 100644
index 00000000..5af44f68
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_10.xml b/sudokus/stairstep/easy/sudoku_10.xml
new file mode 100644
index 00000000..fae04448
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_2.xml b/sudokus/stairstep/easy/sudoku_2.xml
new file mode 100644
index 00000000..21fcf500
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_3.xml b/sudokus/stairstep/easy/sudoku_3.xml
new file mode 100644
index 00000000..9134de0d
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_4.xml b/sudokus/stairstep/easy/sudoku_4.xml
new file mode 100644
index 00000000..43924f8c
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_5.xml b/sudokus/stairstep/easy/sudoku_5.xml
new file mode 100644
index 00000000..c1e89381
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_6.xml b/sudokus/stairstep/easy/sudoku_6.xml
new file mode 100644
index 00000000..1ea73023
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_7.xml b/sudokus/stairstep/easy/sudoku_7.xml
new file mode 100644
index 00000000..1f03fd16
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_8.xml b/sudokus/stairstep/easy/sudoku_8.xml
new file mode 100644
index 00000000..e239a4ef
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/easy/sudoku_9.xml b/sudokus/stairstep/easy/sudoku_9.xml
new file mode 100644
index 00000000..c705e8e7
--- /dev/null
+++ b/sudokus/stairstep/easy/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_1.xml b/sudokus/stairstep/infernal/sudoku_1.xml
new file mode 100644
index 00000000..0087d9bf
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_10.xml b/sudokus/stairstep/infernal/sudoku_10.xml
new file mode 100644
index 00000000..92bac3a1
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_2.xml b/sudokus/stairstep/infernal/sudoku_2.xml
new file mode 100644
index 00000000..848cf680
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_3.xml b/sudokus/stairstep/infernal/sudoku_3.xml
new file mode 100644
index 00000000..993b2ebf
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_4.xml b/sudokus/stairstep/infernal/sudoku_4.xml
new file mode 100644
index 00000000..019a60be
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_5.xml b/sudokus/stairstep/infernal/sudoku_5.xml
new file mode 100644
index 00000000..73358d7f
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_6.xml b/sudokus/stairstep/infernal/sudoku_6.xml
new file mode 100644
index 00000000..9106c883
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_7.xml b/sudokus/stairstep/infernal/sudoku_7.xml
new file mode 100644
index 00000000..b143a40b
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_8.xml b/sudokus/stairstep/infernal/sudoku_8.xml
new file mode 100644
index 00000000..0dd22613
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/infernal/sudoku_9.xml b/sudokus/stairstep/infernal/sudoku_9.xml
new file mode 100644
index 00000000..9b815b17
--- /dev/null
+++ b/sudokus/stairstep/infernal/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_1.xml b/sudokus/stairstep/medium/sudoku_1.xml
new file mode 100644
index 00000000..c2e54eb5
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_10.xml b/sudokus/stairstep/medium/sudoku_10.xml
new file mode 100644
index 00000000..12757d91
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_2.xml b/sudokus/stairstep/medium/sudoku_2.xml
new file mode 100644
index 00000000..64bf3830
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_3.xml b/sudokus/stairstep/medium/sudoku_3.xml
new file mode 100644
index 00000000..53e5101a
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_4.xml b/sudokus/stairstep/medium/sudoku_4.xml
new file mode 100644
index 00000000..54ceab66
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_5.xml b/sudokus/stairstep/medium/sudoku_5.xml
new file mode 100644
index 00000000..39470f91
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_6.xml b/sudokus/stairstep/medium/sudoku_6.xml
new file mode 100644
index 00000000..c74f9ade
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_7.xml b/sudokus/stairstep/medium/sudoku_7.xml
new file mode 100644
index 00000000..aa249e34
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_8.xml b/sudokus/stairstep/medium/sudoku_8.xml
new file mode 100644
index 00000000..df33bcae
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/stairstep/medium/sudoku_9.xml b/sudokus/stairstep/medium/sudoku_9.xml
new file mode 100644
index 00000000..3f19f0d1
--- /dev/null
+++ b/sudokus/stairstep/medium/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_1.xml b/sudokus/standard16x16/difficult/sudoku_1.xml
new file mode 100644
index 00000000..3285fa2b
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_1.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_10.xml b/sudokus/standard16x16/difficult/sudoku_10.xml
new file mode 100644
index 00000000..8018a807
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_10.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_2.xml b/sudokus/standard16x16/difficult/sudoku_2.xml
new file mode 100644
index 00000000..92c512fb
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_2.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_3.xml b/sudokus/standard16x16/difficult/sudoku_3.xml
new file mode 100644
index 00000000..df3871b7
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_3.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_4.xml b/sudokus/standard16x16/difficult/sudoku_4.xml
new file mode 100644
index 00000000..178d7cd1
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_4.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_5.xml b/sudokus/standard16x16/difficult/sudoku_5.xml
new file mode 100644
index 00000000..2687a1bb
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_5.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_6.xml b/sudokus/standard16x16/difficult/sudoku_6.xml
new file mode 100644
index 00000000..46fc38f2
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_6.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_7.xml b/sudokus/standard16x16/difficult/sudoku_7.xml
new file mode 100644
index 00000000..89b73138
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_7.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_8.xml b/sudokus/standard16x16/difficult/sudoku_8.xml
new file mode 100644
index 00000000..4048fd01
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_8.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/difficult/sudoku_9.xml b/sudokus/standard16x16/difficult/sudoku_9.xml
new file mode 100644
index 00000000..0072b231
--- /dev/null
+++ b/sudokus/standard16x16/difficult/sudoku_9.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_1.xml b/sudokus/standard16x16/easy/sudoku_1.xml
new file mode 100644
index 00000000..13638066
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_1.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_10.xml b/sudokus/standard16x16/easy/sudoku_10.xml
new file mode 100644
index 00000000..5adeaf00
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_10.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_2.xml b/sudokus/standard16x16/easy/sudoku_2.xml
new file mode 100644
index 00000000..21e93019
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_2.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_3.xml b/sudokus/standard16x16/easy/sudoku_3.xml
new file mode 100644
index 00000000..ee1faa52
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_3.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_4.xml b/sudokus/standard16x16/easy/sudoku_4.xml
new file mode 100644
index 00000000..f895514f
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_4.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_5.xml b/sudokus/standard16x16/easy/sudoku_5.xml
new file mode 100644
index 00000000..e0db9c89
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_5.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_6.xml b/sudokus/standard16x16/easy/sudoku_6.xml
new file mode 100644
index 00000000..f965d39a
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_6.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_7.xml b/sudokus/standard16x16/easy/sudoku_7.xml
new file mode 100644
index 00000000..3e8bacd0
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_7.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_8.xml b/sudokus/standard16x16/easy/sudoku_8.xml
new file mode 100644
index 00000000..945c810e
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_8.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/easy/sudoku_9.xml b/sudokus/standard16x16/easy/sudoku_9.xml
new file mode 100644
index 00000000..3f98143c
--- /dev/null
+++ b/sudokus/standard16x16/easy/sudoku_9.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_1.xml b/sudokus/standard16x16/infernal/sudoku_1.xml
new file mode 100644
index 00000000..73ba312d
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_1.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_10.xml b/sudokus/standard16x16/infernal/sudoku_10.xml
new file mode 100644
index 00000000..d163ff65
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_10.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_2.xml b/sudokus/standard16x16/infernal/sudoku_2.xml
new file mode 100644
index 00000000..d487a35f
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_2.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_3.xml b/sudokus/standard16x16/infernal/sudoku_3.xml
new file mode 100644
index 00000000..4b823b5d
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_3.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_4.xml b/sudokus/standard16x16/infernal/sudoku_4.xml
new file mode 100644
index 00000000..40f584e0
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_4.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_5.xml b/sudokus/standard16x16/infernal/sudoku_5.xml
new file mode 100644
index 00000000..f558aad6
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_5.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_6.xml b/sudokus/standard16x16/infernal/sudoku_6.xml
new file mode 100644
index 00000000..ee6f24a0
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_6.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_7.xml b/sudokus/standard16x16/infernal/sudoku_7.xml
new file mode 100644
index 00000000..76f34f21
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_7.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_8.xml b/sudokus/standard16x16/infernal/sudoku_8.xml
new file mode 100644
index 00000000..696c14e0
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_8.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/infernal/sudoku_9.xml b/sudokus/standard16x16/infernal/sudoku_9.xml
new file mode 100644
index 00000000..61586207
--- /dev/null
+++ b/sudokus/standard16x16/infernal/sudoku_9.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_1.xml b/sudokus/standard16x16/medium/sudoku_1.xml
new file mode 100644
index 00000000..08750389
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_1.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_10.xml b/sudokus/standard16x16/medium/sudoku_10.xml
new file mode 100644
index 00000000..a421335c
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_10.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_2.xml b/sudokus/standard16x16/medium/sudoku_2.xml
new file mode 100644
index 00000000..a4c9eadb
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_2.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_3.xml b/sudokus/standard16x16/medium/sudoku_3.xml
new file mode 100644
index 00000000..8b15d29f
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_3.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_4.xml b/sudokus/standard16x16/medium/sudoku_4.xml
new file mode 100644
index 00000000..608ef634
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_4.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_5.xml b/sudokus/standard16x16/medium/sudoku_5.xml
new file mode 100644
index 00000000..20fc20d7
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_5.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_6.xml b/sudokus/standard16x16/medium/sudoku_6.xml
new file mode 100644
index 00000000..c730e2f0
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_6.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_7.xml b/sudokus/standard16x16/medium/sudoku_7.xml
new file mode 100644
index 00000000..355319db
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_7.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_8.xml b/sudokus/standard16x16/medium/sudoku_8.xml
new file mode 100644
index 00000000..1d15a8ea
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_8.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard16x16/medium/sudoku_9.xml b/sudokus/standard16x16/medium/sudoku_9.xml
new file mode 100644
index 00000000..b0828110
--- /dev/null
+++ b/sudokus/standard16x16/medium/sudoku_9.xml
@@ -0,0 +1,772 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_1.xml b/sudokus/standard4x4/difficult/sudoku_1.xml
new file mode 100644
index 00000000..7b77df8c
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_1.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_10.xml b/sudokus/standard4x4/difficult/sudoku_10.xml
new file mode 100644
index 00000000..3f2c6c3e
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_10.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_2.xml b/sudokus/standard4x4/difficult/sudoku_2.xml
new file mode 100644
index 00000000..0f2bca21
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_2.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_3.xml b/sudokus/standard4x4/difficult/sudoku_3.xml
new file mode 100644
index 00000000..17bb961a
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_3.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_4.xml b/sudokus/standard4x4/difficult/sudoku_4.xml
new file mode 100644
index 00000000..c92a1b61
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_4.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_5.xml b/sudokus/standard4x4/difficult/sudoku_5.xml
new file mode 100644
index 00000000..619d5930
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_5.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_6.xml b/sudokus/standard4x4/difficult/sudoku_6.xml
new file mode 100644
index 00000000..1edaecb2
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_6.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_7.xml b/sudokus/standard4x4/difficult/sudoku_7.xml
new file mode 100644
index 00000000..71c5cf98
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_7.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_8.xml b/sudokus/standard4x4/difficult/sudoku_8.xml
new file mode 100644
index 00000000..2388c9bc
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_8.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/difficult/sudoku_9.xml b/sudokus/standard4x4/difficult/sudoku_9.xml
new file mode 100644
index 00000000..f82dc323
--- /dev/null
+++ b/sudokus/standard4x4/difficult/sudoku_9.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_1.xml b/sudokus/standard4x4/easy/sudoku_1.xml
new file mode 100644
index 00000000..45a878a3
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_1.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_10.xml b/sudokus/standard4x4/easy/sudoku_10.xml
new file mode 100644
index 00000000..68d2e9a2
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_10.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_2.xml b/sudokus/standard4x4/easy/sudoku_2.xml
new file mode 100644
index 00000000..576f29da
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_2.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_3.xml b/sudokus/standard4x4/easy/sudoku_3.xml
new file mode 100644
index 00000000..9cf244d4
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_3.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_4.xml b/sudokus/standard4x4/easy/sudoku_4.xml
new file mode 100644
index 00000000..97c8925d
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_4.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_5.xml b/sudokus/standard4x4/easy/sudoku_5.xml
new file mode 100644
index 00000000..96844988
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_5.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_6.xml b/sudokus/standard4x4/easy/sudoku_6.xml
new file mode 100644
index 00000000..133ba34f
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_6.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_7.xml b/sudokus/standard4x4/easy/sudoku_7.xml
new file mode 100644
index 00000000..d8203ce5
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_7.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_8.xml b/sudokus/standard4x4/easy/sudoku_8.xml
new file mode 100644
index 00000000..e633f003
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_8.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/easy/sudoku_9.xml b/sudokus/standard4x4/easy/sudoku_9.xml
new file mode 100644
index 00000000..98aa4952
--- /dev/null
+++ b/sudokus/standard4x4/easy/sudoku_9.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_1.xml b/sudokus/standard4x4/infernal/sudoku_1.xml
new file mode 100644
index 00000000..8b50e950
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_1.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_10.xml b/sudokus/standard4x4/infernal/sudoku_10.xml
new file mode 100644
index 00000000..827ae516
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_10.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_2.xml b/sudokus/standard4x4/infernal/sudoku_2.xml
new file mode 100644
index 00000000..91bacec7
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_2.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_3.xml b/sudokus/standard4x4/infernal/sudoku_3.xml
new file mode 100644
index 00000000..35781940
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_3.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_4.xml b/sudokus/standard4x4/infernal/sudoku_4.xml
new file mode 100644
index 00000000..faae3906
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_4.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_5.xml b/sudokus/standard4x4/infernal/sudoku_5.xml
new file mode 100644
index 00000000..791b98f7
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_5.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_6.xml b/sudokus/standard4x4/infernal/sudoku_6.xml
new file mode 100644
index 00000000..b1d0219a
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_6.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_7.xml b/sudokus/standard4x4/infernal/sudoku_7.xml
new file mode 100644
index 00000000..5691a92b
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_7.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_8.xml b/sudokus/standard4x4/infernal/sudoku_8.xml
new file mode 100644
index 00000000..8191082f
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_8.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/infernal/sudoku_9.xml b/sudokus/standard4x4/infernal/sudoku_9.xml
new file mode 100644
index 00000000..006dc7b6
--- /dev/null
+++ b/sudokus/standard4x4/infernal/sudoku_9.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_1.xml b/sudokus/standard4x4/medium/sudoku_1.xml
new file mode 100644
index 00000000..f84d2732
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_1.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_10.xml b/sudokus/standard4x4/medium/sudoku_10.xml
new file mode 100644
index 00000000..d358d1cd
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_10.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_2.xml b/sudokus/standard4x4/medium/sudoku_2.xml
new file mode 100644
index 00000000..07fbdc27
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_2.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_3.xml b/sudokus/standard4x4/medium/sudoku_3.xml
new file mode 100644
index 00000000..62e13770
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_3.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_4.xml b/sudokus/standard4x4/medium/sudoku_4.xml
new file mode 100644
index 00000000..279ce42f
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_4.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_5.xml b/sudokus/standard4x4/medium/sudoku_5.xml
new file mode 100644
index 00000000..20a8c46b
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_5.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_6.xml b/sudokus/standard4x4/medium/sudoku_6.xml
new file mode 100644
index 00000000..9d8e452c
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_6.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_7.xml b/sudokus/standard4x4/medium/sudoku_7.xml
new file mode 100644
index 00000000..c04b0b69
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_7.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_8.xml b/sudokus/standard4x4/medium/sudoku_8.xml
new file mode 100644
index 00000000..da9b5f42
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_8.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard4x4/medium/sudoku_9.xml b/sudokus/standard4x4/medium/sudoku_9.xml
new file mode 100644
index 00000000..a4b2f37c
--- /dev/null
+++ b/sudokus/standard4x4/medium/sudoku_9.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_1.xml b/sudokus/standard6x6/difficult/sudoku_1.xml
new file mode 100644
index 00000000..4cb063e3
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_1.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_10.xml b/sudokus/standard6x6/difficult/sudoku_10.xml
new file mode 100644
index 00000000..f2f2d92e
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_10.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_2.xml b/sudokus/standard6x6/difficult/sudoku_2.xml
new file mode 100644
index 00000000..3ba7eec8
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_2.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_3.xml b/sudokus/standard6x6/difficult/sudoku_3.xml
new file mode 100644
index 00000000..480ba5a5
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_3.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_4.xml b/sudokus/standard6x6/difficult/sudoku_4.xml
new file mode 100644
index 00000000..f235ded4
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_4.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_5.xml b/sudokus/standard6x6/difficult/sudoku_5.xml
new file mode 100644
index 00000000..ee7e1f85
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_5.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_6.xml b/sudokus/standard6x6/difficult/sudoku_6.xml
new file mode 100644
index 00000000..2120d649
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_6.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_7.xml b/sudokus/standard6x6/difficult/sudoku_7.xml
new file mode 100644
index 00000000..c6308475
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_7.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_8.xml b/sudokus/standard6x6/difficult/sudoku_8.xml
new file mode 100644
index 00000000..0b37d87f
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_8.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/difficult/sudoku_9.xml b/sudokus/standard6x6/difficult/sudoku_9.xml
new file mode 100644
index 00000000..ae513b2d
--- /dev/null
+++ b/sudokus/standard6x6/difficult/sudoku_9.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_1.xml b/sudokus/standard6x6/easy/sudoku_1.xml
new file mode 100644
index 00000000..cdf2c481
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_1.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_10.xml b/sudokus/standard6x6/easy/sudoku_10.xml
new file mode 100644
index 00000000..24901d7e
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_10.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_2.xml b/sudokus/standard6x6/easy/sudoku_2.xml
new file mode 100644
index 00000000..c644760f
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_2.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_3.xml b/sudokus/standard6x6/easy/sudoku_3.xml
new file mode 100644
index 00000000..5f4112df
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_3.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_4.xml b/sudokus/standard6x6/easy/sudoku_4.xml
new file mode 100644
index 00000000..ee20c379
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_4.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_5.xml b/sudokus/standard6x6/easy/sudoku_5.xml
new file mode 100644
index 00000000..7d8f4996
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_5.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_6.xml b/sudokus/standard6x6/easy/sudoku_6.xml
new file mode 100644
index 00000000..3fa1ad2f
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_6.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_7.xml b/sudokus/standard6x6/easy/sudoku_7.xml
new file mode 100644
index 00000000..32ce0c01
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_7.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_8.xml b/sudokus/standard6x6/easy/sudoku_8.xml
new file mode 100644
index 00000000..18a9cf10
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_8.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/easy/sudoku_9.xml b/sudokus/standard6x6/easy/sudoku_9.xml
new file mode 100644
index 00000000..8ca8634a
--- /dev/null
+++ b/sudokus/standard6x6/easy/sudoku_9.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_1.xml b/sudokus/standard6x6/infernal/sudoku_1.xml
new file mode 100644
index 00000000..5eb41148
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_1.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_10.xml b/sudokus/standard6x6/infernal/sudoku_10.xml
new file mode 100644
index 00000000..e1681112
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_10.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_2.xml b/sudokus/standard6x6/infernal/sudoku_2.xml
new file mode 100644
index 00000000..54f7b75a
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_2.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_3.xml b/sudokus/standard6x6/infernal/sudoku_3.xml
new file mode 100644
index 00000000..9853b538
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_3.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_4.xml b/sudokus/standard6x6/infernal/sudoku_4.xml
new file mode 100644
index 00000000..6861f7b5
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_4.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_5.xml b/sudokus/standard6x6/infernal/sudoku_5.xml
new file mode 100644
index 00000000..80672911
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_5.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_6.xml b/sudokus/standard6x6/infernal/sudoku_6.xml
new file mode 100644
index 00000000..dce7842f
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_6.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_7.xml b/sudokus/standard6x6/infernal/sudoku_7.xml
new file mode 100644
index 00000000..e7d94a9e
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_7.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_8.xml b/sudokus/standard6x6/infernal/sudoku_8.xml
new file mode 100644
index 00000000..59f49e47
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_8.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/infernal/sudoku_9.xml b/sudokus/standard6x6/infernal/sudoku_9.xml
new file mode 100644
index 00000000..bc746fca
--- /dev/null
+++ b/sudokus/standard6x6/infernal/sudoku_9.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_1.xml b/sudokus/standard6x6/medium/sudoku_1.xml
new file mode 100644
index 00000000..e9299499
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_1.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_10.xml b/sudokus/standard6x6/medium/sudoku_10.xml
new file mode 100644
index 00000000..8faeab00
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_10.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_2.xml b/sudokus/standard6x6/medium/sudoku_2.xml
new file mode 100644
index 00000000..ca3c0962
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_2.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_3.xml b/sudokus/standard6x6/medium/sudoku_3.xml
new file mode 100644
index 00000000..7ecb9dcc
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_3.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_4.xml b/sudokus/standard6x6/medium/sudoku_4.xml
new file mode 100644
index 00000000..bca2a8fa
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_4.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_5.xml b/sudokus/standard6x6/medium/sudoku_5.xml
new file mode 100644
index 00000000..6e2138bc
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_5.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_6.xml b/sudokus/standard6x6/medium/sudoku_6.xml
new file mode 100644
index 00000000..a2180940
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_6.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_7.xml b/sudokus/standard6x6/medium/sudoku_7.xml
new file mode 100644
index 00000000..9d60c515
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_7.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_8.xml b/sudokus/standard6x6/medium/sudoku_8.xml
new file mode 100644
index 00000000..762d8857
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_8.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard6x6/medium/sudoku_9.xml b/sudokus/standard6x6/medium/sudoku_9.xml
new file mode 100644
index 00000000..0255bb0a
--- /dev/null
+++ b/sudokus/standard6x6/medium/sudoku_9.xml
@@ -0,0 +1,112 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_1.xml b/sudokus/standard9x9/difficult/sudoku_1.xml
new file mode 100644
index 00000000..236cc73d
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_10.xml b/sudokus/standard9x9/difficult/sudoku_10.xml
new file mode 100644
index 00000000..3a002796
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_2.xml b/sudokus/standard9x9/difficult/sudoku_2.xml
new file mode 100644
index 00000000..9008b4ce
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_3.xml b/sudokus/standard9x9/difficult/sudoku_3.xml
new file mode 100644
index 00000000..14d19789
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_4.xml b/sudokus/standard9x9/difficult/sudoku_4.xml
new file mode 100644
index 00000000..114ef67b
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_5.xml b/sudokus/standard9x9/difficult/sudoku_5.xml
new file mode 100644
index 00000000..fc03eb1b
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_6.xml b/sudokus/standard9x9/difficult/sudoku_6.xml
new file mode 100644
index 00000000..db72b640
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_7.xml b/sudokus/standard9x9/difficult/sudoku_7.xml
new file mode 100644
index 00000000..6dc21abf
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_8.xml b/sudokus/standard9x9/difficult/sudoku_8.xml
new file mode 100644
index 00000000..148c1761
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/difficult/sudoku_9.xml b/sudokus/standard9x9/difficult/sudoku_9.xml
new file mode 100644
index 00000000..df59f204
--- /dev/null
+++ b/sudokus/standard9x9/difficult/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_1.xml b/sudokus/standard9x9/easy/sudoku_1.xml
new file mode 100644
index 00000000..662631a3
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_10.xml b/sudokus/standard9x9/easy/sudoku_10.xml
new file mode 100644
index 00000000..890196ee
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_2.xml b/sudokus/standard9x9/easy/sudoku_2.xml
new file mode 100644
index 00000000..6a253baa
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_3.xml b/sudokus/standard9x9/easy/sudoku_3.xml
new file mode 100644
index 00000000..036357af
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_4.xml b/sudokus/standard9x9/easy/sudoku_4.xml
new file mode 100644
index 00000000..dc217ed9
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_5.xml b/sudokus/standard9x9/easy/sudoku_5.xml
new file mode 100644
index 00000000..810a222a
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_6.xml b/sudokus/standard9x9/easy/sudoku_6.xml
new file mode 100644
index 00000000..6dde3473
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_7.xml b/sudokus/standard9x9/easy/sudoku_7.xml
new file mode 100644
index 00000000..2e8765cf
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_8.xml b/sudokus/standard9x9/easy/sudoku_8.xml
new file mode 100644
index 00000000..b482da27
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/easy/sudoku_9.xml b/sudokus/standard9x9/easy/sudoku_9.xml
new file mode 100644
index 00000000..57a266c4
--- /dev/null
+++ b/sudokus/standard9x9/easy/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_1.xml b/sudokus/standard9x9/infernal/sudoku_1.xml
new file mode 100644
index 00000000..e3205a9c
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_10.xml b/sudokus/standard9x9/infernal/sudoku_10.xml
new file mode 100644
index 00000000..5036b692
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_2.xml b/sudokus/standard9x9/infernal/sudoku_2.xml
new file mode 100644
index 00000000..ce7f23fc
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_3.xml b/sudokus/standard9x9/infernal/sudoku_3.xml
new file mode 100644
index 00000000..f515593c
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_4.xml b/sudokus/standard9x9/infernal/sudoku_4.xml
new file mode 100644
index 00000000..8be589b1
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_5.xml b/sudokus/standard9x9/infernal/sudoku_5.xml
new file mode 100644
index 00000000..7d99ac82
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_6.xml b/sudokus/standard9x9/infernal/sudoku_6.xml
new file mode 100644
index 00000000..92268efe
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_7.xml b/sudokus/standard9x9/infernal/sudoku_7.xml
new file mode 100644
index 00000000..35be1f10
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_8.xml b/sudokus/standard9x9/infernal/sudoku_8.xml
new file mode 100644
index 00000000..c2afe871
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/infernal/sudoku_9.xml b/sudokus/standard9x9/infernal/sudoku_9.xml
new file mode 100644
index 00000000..9aa737ae
--- /dev/null
+++ b/sudokus/standard9x9/infernal/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_1.xml b/sudokus/standard9x9/medium/sudoku_1.xml
new file mode 100644
index 00000000..e057af76
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_1.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_10.xml b/sudokus/standard9x9/medium/sudoku_10.xml
new file mode 100644
index 00000000..560de7d8
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_10.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_2.xml b/sudokus/standard9x9/medium/sudoku_2.xml
new file mode 100644
index 00000000..730b10be
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_2.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_3.xml b/sudokus/standard9x9/medium/sudoku_3.xml
new file mode 100644
index 00000000..bd5a5677
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_3.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_4.xml b/sudokus/standard9x9/medium/sudoku_4.xml
new file mode 100644
index 00000000..0e4e45a1
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_4.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_5.xml b/sudokus/standard9x9/medium/sudoku_5.xml
new file mode 100644
index 00000000..8df015ca
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_5.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_6.xml b/sudokus/standard9x9/medium/sudoku_6.xml
new file mode 100644
index 00000000..338efee0
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_6.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_7.xml b/sudokus/standard9x9/medium/sudoku_7.xml
new file mode 100644
index 00000000..b5d2634d
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_7.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_8.xml b/sudokus/standard9x9/medium/sudoku_8.xml
new file mode 100644
index 00000000..e9ac5889
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_8.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudokus/standard9x9/medium/sudoku_9.xml b/sudokus/standard9x9/medium/sudoku_9.xml
new file mode 100644
index 00000000..e596ce60
--- /dev/null
+++ b/sudokus/standard9x9/medium/sudoku_9.xml
@@ -0,0 +1,247 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudoq-app/.classpath b/sudoq-app/.classpath
new file mode 100644
index 00000000..a4763d1e
--- /dev/null
+++ b/sudoq-app/.classpath
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/sudoq-app/.project b/sudoq-app/.project
new file mode 100644
index 00000000..1e87910b
--- /dev/null
+++ b/sudoq-app/.project
@@ -0,0 +1,33 @@
+
+
+ sudoq-app
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/sudoq-app/AndroidManifest.xml b/sudoq-app/AndroidManifest.xml
new file mode 100644
index 00000000..30162772
--- /dev/null
+++ b/sudoq-app/AndroidManifest.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/build.xml b/sudoq-app/build.xml
new file mode 100644
index 00000000..122e90be
--- /dev/null
+++ b/sudoq-app/build.xml
@@ -0,0 +1,90 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudoq-app/project.properties b/sudoq-app/project.properties
new file mode 100644
index 00000000..85aac540
--- /dev/null
+++ b/sudoq-app/project.properties
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-8
diff --git a/sudoq-app/res/drawable-hdpi/background.png b/sudoq-app/res/drawable-hdpi/background.png
new file mode 100644
index 00000000..0a5c2c85
Binary files /dev/null and b/sudoq-app/res/drawable-hdpi/background.png differ
diff --git a/sudoq-app/res/drawable-hdpi/ic_launcher.png b/sudoq-app/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 00000000..8074c4c5
Binary files /dev/null and b/sudoq-app/res/drawable-hdpi/ic_launcher.png differ
diff --git a/sudoq-app/res/drawable-ldpi/ic_launcher.png b/sudoq-app/res/drawable-ldpi/ic_launcher.png
new file mode 100644
index 00000000..1095584e
Binary files /dev/null and b/sudoq-app/res/drawable-ldpi/ic_launcher.png differ
diff --git a/sudoq-app/res/drawable-mdpi/background.png b/sudoq-app/res/drawable-mdpi/background.png
new file mode 100644
index 00000000..4b5be84e
Binary files /dev/null and b/sudoq-app/res/drawable-mdpi/background.png differ
diff --git a/sudoq-app/res/drawable-mdpi/ic_launcher.png b/sudoq-app/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 00000000..a07c69fa
Binary files /dev/null and b/sudoq-app/res/drawable-mdpi/ic_launcher.png differ
diff --git a/sudoq-app/res/drawable-xhdpi/background.png b/sudoq-app/res/drawable-xhdpi/background.png
new file mode 100644
index 00000000..a7d2ad6c
Binary files /dev/null and b/sudoq-app/res/drawable-xhdpi/background.png differ
diff --git a/sudoq-app/res/drawable/action_tree.png b/sudoq-app/res/drawable/action_tree.png
new file mode 100644
index 00000000..bb31386c
Binary files /dev/null and b/sudoq-app/res/drawable/action_tree.png differ
diff --git a/sudoq-app/res/drawable/action_tree_tutorial.png b/sudoq-app/res/drawable/action_tree_tutorial.png
new file mode 100644
index 00000000..a9917e6d
Binary files /dev/null and b/sudoq-app/res/drawable/action_tree_tutorial.png differ
diff --git a/sudoq-app/res/drawable/background_gradient.xml b/sudoq-app/res/drawable/background_gradient.xml
new file mode 100644
index 00000000..ebeef6ec
--- /dev/null
+++ b/sudoq-app/res/drawable/background_gradient.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/sudoq-app/res/drawable/empty_sudoku.png b/sudoq-app/res/drawable/empty_sudoku.png
new file mode 100644
index 00000000..f4632fdf
Binary files /dev/null and b/sudoq-app/res/drawable/empty_sudoku.png differ
diff --git a/sudoq-app/res/drawable/gesture_button_selector.xml b/sudoq-app/res/drawable/gesture_button_selector.xml
new file mode 100644
index 00000000..5f35296f
--- /dev/null
+++ b/sudoq-app/res/drawable/gesture_button_selector.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/drawable/gesture_checked.png b/sudoq-app/res/drawable/gesture_checked.png
new file mode 100644
index 00000000..3e32f7cd
Binary files /dev/null and b/sudoq-app/res/drawable/gesture_checked.png differ
diff --git a/sudoq-app/res/drawable/gesture_unchecked.png b/sudoq-app/res/drawable/gesture_unchecked.png
new file mode 100644
index 00000000..687b822e
Binary files /dev/null and b/sudoq-app/res/drawable/gesture_unchecked.png differ
diff --git a/sudoq-app/res/drawable/help.png b/sudoq-app/res/drawable/help.png
new file mode 100644
index 00000000..27147d63
Binary files /dev/null and b/sudoq-app/res/drawable/help.png differ
diff --git a/sudoq-app/res/drawable/help_tutorial.png b/sudoq-app/res/drawable/help_tutorial.png
new file mode 100644
index 00000000..28a70313
Binary files /dev/null and b/sudoq-app/res/drawable/help_tutorial.png differ
diff --git a/sudoq-app/res/drawable/launcher.png b/sudoq-app/res/drawable/launcher.png
new file mode 100644
index 00000000..aed29a4b
Binary files /dev/null and b/sudoq-app/res/drawable/launcher.png differ
diff --git a/sudoq-app/res/drawable/logo.png b/sudoq-app/res/drawable/logo.png
new file mode 100644
index 00000000..fb1b1671
Binary files /dev/null and b/sudoq-app/res/drawable/logo.png differ
diff --git a/sudoq-app/res/drawable/logo_land.png b/sudoq-app/res/drawable/logo_land.png
new file mode 100644
index 00000000..262b526d
Binary files /dev/null and b/sudoq-app/res/drawable/logo_land.png differ
diff --git a/sudoq-app/res/drawable/redo.png b/sudoq-app/res/drawable/redo.png
new file mode 100644
index 00000000..7ddb1452
Binary files /dev/null and b/sudoq-app/res/drawable/redo.png differ
diff --git a/sudoq-app/res/drawable/rootkuh.png b/sudoq-app/res/drawable/rootkuh.png
new file mode 100644
index 00000000..b0aee000
Binary files /dev/null and b/sudoq-app/res/drawable/rootkuh.png differ
diff --git a/sudoq-app/res/drawable/squiggly.png b/sudoq-app/res/drawable/squiggly.png
new file mode 100644
index 00000000..ac7e2ea3
Binary files /dev/null and b/sudoq-app/res/drawable/squiggly.png differ
diff --git a/sudoq-app/res/drawable/sudoku_tutorial.png b/sudoq-app/res/drawable/sudoku_tutorial.png
new file mode 100644
index 00000000..ebc68ebf
Binary files /dev/null and b/sudoq-app/res/drawable/sudoku_tutorial.png differ
diff --git a/sudoq-app/res/drawable/undo.png b/sudoq-app/res/drawable/undo.png
new file mode 100644
index 00000000..701b5562
Binary files /dev/null and b/sudoq-app/res/drawable/undo.png differ
diff --git a/sudoq-app/res/drawable/xsudoku.png b/sudoq-app/res/drawable/xsudoku.png
new file mode 100644
index 00000000..fe97b694
Binary files /dev/null and b/sudoq-app/res/drawable/xsudoku.png differ
diff --git a/sudoq-app/res/layout-land/mainmenu.xml b/sudoq-app/res/layout-land/mainmenu.xml
new file mode 100644
index 00000000..4d79326c
--- /dev/null
+++ b/sudoq-app/res/layout-land/mainmenu.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout-land/playerpreferences.xml b/sudoq-app/res/layout-land/playerpreferences.xml
new file mode 100644
index 00000000..28886032
--- /dev/null
+++ b/sudoq-app/res/layout-land/playerpreferences.xml
@@ -0,0 +1,149 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout-land/splash.xml b/sudoq-app/res/layout-land/splash.xml
new file mode 100644
index 00000000..ded488ff
--- /dev/null
+++ b/sudoq-app/res/layout-land/splash.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout-land/sudoku.xml b/sudoq-app/res/layout-land/sudoku.xml
new file mode 100644
index 00000000..702c7353
--- /dev/null
+++ b/sudoq-app/res/layout-land/sudoku.xml
@@ -0,0 +1,207 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout-land/sudokupreferences.xml b/sudoq-app/res/layout-land/sudokupreferences.xml
new file mode 100644
index 00000000..e4deede1
--- /dev/null
+++ b/sudoq-app/res/layout-land/sudokupreferences.xml
@@ -0,0 +1,103 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/gametypeselection.xml b/sudoq-app/res/layout/gametypeselection.xml
new file mode 100644
index 00000000..49e97b0d
--- /dev/null
+++ b/sudoq-app/res/layout/gametypeselection.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/gesturebuilder.xml b/sudoq-app/res/layout/gesturebuilder.xml
new file mode 100644
index 00000000..a0311f6a
--- /dev/null
+++ b/sudoq-app/res/layout/gesturebuilder.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/mainmenu.xml b/sudoq-app/res/layout/mainmenu.xml
new file mode 100644
index 00000000..93404d30
--- /dev/null
+++ b/sudoq-app/res/layout/mainmenu.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/playerpreferences.xml b/sudoq-app/res/layout/playerpreferences.xml
new file mode 100644
index 00000000..6f6652b0
--- /dev/null
+++ b/sudoq-app/res/layout/playerpreferences.xml
@@ -0,0 +1,142 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/splash.xml b/sudoq-app/res/layout/splash.xml
new file mode 100644
index 00000000..b1cbdbfc
--- /dev/null
+++ b/sudoq-app/res/layout/splash.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/statistics.xml b/sudoq-app/res/layout/statistics.xml
new file mode 100644
index 00000000..93afd7e2
--- /dev/null
+++ b/sudoq-app/res/layout/statistics.xml
@@ -0,0 +1,107 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/sudoku.xml b/sudoq-app/res/layout/sudoku.xml
new file mode 100644
index 00000000..90e79093
--- /dev/null
+++ b/sudoq-app/res/layout/sudoku.xml
@@ -0,0 +1,205 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/sudokuloading.xml b/sudoq-app/res/layout/sudokuloading.xml
new file mode 100644
index 00000000..69680117
--- /dev/null
+++ b/sudoq-app/res/layout/sudokuloading.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/sudokuloadingitem.xml b/sudoq-app/res/layout/sudokuloadingitem.xml
new file mode 100644
index 00000000..2b557451
--- /dev/null
+++ b/sudoq-app/res/layout/sudokuloadingitem.xml
@@ -0,0 +1,62 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/sudokupreferences.xml b/sudoq-app/res/layout/sudokupreferences.xml
new file mode 100644
index 00000000..d9458327
--- /dev/null
+++ b/sudoq-app/res/layout/sudokupreferences.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/tutorial.xml b/sudoq-app/res/layout/tutorial.xml
new file mode 100644
index 00000000..bac84e6b
--- /dev/null
+++ b/sudoq-app/res/layout/tutorial.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/tutorial_actiontree.xml b/sudoq-app/res/layout/tutorial_actiontree.xml
new file mode 100644
index 00000000..632a949d
--- /dev/null
+++ b/sudoq-app/res/layout/tutorial_actiontree.xml
@@ -0,0 +1,179 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/tutorial_assistances.xml b/sudoq-app/res/layout/tutorial_assistances.xml
new file mode 100644
index 00000000..550e030e
--- /dev/null
+++ b/sudoq-app/res/layout/tutorial_assistances.xml
@@ -0,0 +1,213 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/layout/tutorial_sudoku.xml b/sudoq-app/res/layout/tutorial_sudoku.xml
new file mode 100644
index 00000000..9ee9b192
--- /dev/null
+++ b/sudoq-app/res/layout/tutorial_sudoku.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/raw/gestures b/sudoq-app/res/raw/gestures
new file mode 100644
index 00000000..cfb01f96
Binary files /dev/null and b/sudoq-app/res/raw/gestures differ
diff --git a/sudoq-app/res/values-de/strings.xml b/sudoq-app/res/values-de/strings.xml
new file mode 100644
index 00000000..97cdbc46
--- /dev/null
+++ b/sudoq-app/res/values-de/strings.xml
@@ -0,0 +1,156 @@
+
+
+
+
+
+
+
+
+ Fehler! Profil Ordner konnte nicht gefunden werden!
+ Fehler! Einstellungen unvollstaendig!
+ Gesten nicht verfügbar!
+ Miniaturansicht konnte nicht erstellt werden!
+ Erhaltene Miniaturansicht konnte nicht gespeichert werden!
+ Miniaturansicht konnte nicht geladen werden!
+ Du musst zuerst im Profil für alle Symbole Gesten definieren!
+ Kein alternativer Symbolsatz verfügbar!
+
+
+ Ein Feld wurde nicht korrekt gelöst
+ Alle Felder sind korrekt gelöst
+ Ungültiges Symbol
+ Eingeschränktes Symbol
+
+
+ SudoQ wird für die erste Benutzung vorbereitet
+
+
+ Tutorial
+ Gesten für Ziffern
+ Gesten für Buchstaben
+ Alle Gesten löschen
+ Spezifische Geste löschen
+
+
+ Ja
+ Nein
+ Du hast gewonnen!
+ Du hast aufgegeben!
+ Willst du das Sudoku schließen?
+ Statistik
+ Gespielte Zeit
+ Punkte
+
+
+ Statistik
+ Zähler
+ Gespielte Sudokus
+ Gespielte einfache Sudokus
+ Gespielte mittlere Sudokus
+ Gespielte schwere Sudokus
+ Gespielte infernale Sudokus
+ Rekorde
+ Höchste Punktzahl
+ Schnellste Lösezeit
+
+
+ Benutzereinstellungen
+ Name
+ Gesteneingabe
+ Profileinstellungen
+ Hilfestellungen
+ Zeile/Spalte markieren
+ Falsche Symbole markieren
+ Eingabehilfe
+ Ausgewähltes Feld lösen
+ Zufälliges Feld lösen
+ Tipps
+ Notizen automatisch anpassen
+ Profil wechseln
+ Profil
+ Neues Profil erstellen
+ Profil löschen
+ Statistik
+ Gesten definieren
+ Speichern
+ unbennant
+
+
+ Profil geändert zu
+
+
+ Profil wechseln
+
+
+ Neues Sudoku
+ Fortsetzen
+ Sudoku Laden
+ Profil
+
+
+ Zeichne die gewünschte Geste
+
+
+ Sudoku
+ Offizielles Sudoku
+ Erstellen
+ Beitreten
+
+
+ Sudokutyp:
+ Schwierigkeit:
+ Start
+ Sudokutyp auswählen
+ Schwierigkeitsgrad auswählen
+ Hilfestellungen konfigurieren
+ Vorlagen werden gerade kopiert. Bitte warten Sie einen Moment.
+
+
+ Lesezeichen
+ Schließen
+ Hilfestellungen
+ Lösung prüfen
+ Ausgewähltes Feld lösen
+ Zufälliges Feld lösen
+ Aufgeben
+ Zurück zum letzten korrekten Stand
+ Symboleingabe durch Geste
+ Aktionsverlauf
+
+
+ SudoQ
+ Neues Sudoku
+
+
+ Multiplayer
+
+
+ Einfach
+ Mittel
+ Schwer
+ Infernal
+
+
+ Standard-Sudoku 9x9
+ Standard-Sudoku 16x16
+ Standard-Sudoku 6x6
+ Standard-Sudoku 4x4
+ Squiggly-Sudoku Typ A 9x9
+ Squiggly-Sudoku Typ B 9x9
+ Stairstep-Sudoku 9x9
+ Samurai-Sudoku
+ Hyper-Sudoku
+ XSudoku
+ Sudoku-Einstellungen
+
+
+ gelöst
+
+
+ Keine gespeicherten Sudokus vorhanden.
+ Zu löschendes Sudoku wählen…
+ Gelöste Sudokus löschen
+ Bestimmtes Sudoku löschen
+ Zurück
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/values-de/tutorial.xml b/sudoq-app/res/values-de/tutorial.xml
new file mode 100644
index 00000000..eb96f841
--- /dev/null
+++ b/sudoq-app/res/values-de/tutorial.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+ Sudoku
+ Ein Sudoku ist ein Logikrätsel, bei dem Ziffern in die richtigen Felder gesetzt werden müssen. Das Original-Sudoku
+ ist ein 9x9 Gitter, das mit den Ziffern 1-9 so zu befüllen ist, dass jede Zeile, jede Spalte und jeder der neun 3x3 Blöcke alle Ziffern enthält.
+ Zu Beginn ist das Sudoku teilweise ausgefüllt und hat nur eine richtige Lösung.
+ Weitere Sudokutypen haben nicht die 3x3 Blöcke sondern andere Gruppen von Feldern,
+ die in dieser App durch eine schwarze Umrandung oder grau hinterlegte Felder dargestellt werden.
+ Die folgenden Bilder zeigen beide Arten der Darstellung die sich überschneiden können:
+ Squiggly Typ A Sudoku
+ X-Sudoku Typ
+
+
+ Hilfestellungen
+ Es stehen mehrere Hilfestellungen zur Verfügung die es einfacher machen, ein Sudoku zu lösen.
+ Diese Hilfestellungen können in "passive" und "aktive" Hilfestellungen unterteilt werden.
+ Aber: Das Aktivieren einer passiven bzw. das Benutzen einer aktiven
+ Hilfestellung führt dazu, dass sich der Highscore verringert.
+
+ Passive Hilfestellungen
+ Passive Hilfestellungen können im Profil oder vor Beginn eines neuen Spiels aktiviert werden.
+ Diese Hilfestellungen müssen nicht im Spiel aufgerufen werden, können daher im Spiel aber auch nicht aktiviert bzw. deaktiviert werden.
+ Zeile/Spalte markieren
+ Wenn diese Hilfestellung aktiv ist, werden alle Felder in der momentan ausgewählten Zeile und Spalte hervorgehoben.
+ Notizen automatisch anpassen
+ Diese Hilfestellung aktualisiert deine Notizen, wenn du eine Ziffer in ein Feld eingibst.
+ Steht diese Ziffer in einem Feld der gleichen Zeile, Spalte oder demselben Block als Notiz so wird diese Notiz gelöscht.
+ Falsche Symbole markieren
+ Wenn eine Ziffer in ein Feld eingegeben wird obwohl sie bereits
+ in einem Feld in derselben Zeile, Spalte oder demselben Block steht wird sie rot markiert, da nicht in beiden Feldern die gleiche Ziffer stehen kann.
+ Eingabehilfe
+ Wenn diese Hilfestellung aktiviert ist, kann eine Ziffer nur in ein Feld eingetragen werden wenn sie noch nicht
+ in einem Feld in derselben Zeile, Spalte oder demselben Block eingetragen ist. Alle anderen Ziffern sind ausgegraut.
+
+ Aktive Hilfestellungen
+ Aktive Hilfestellungen können im Spiel aufgerufen werden wenn man sie braucht.
+ Sie werden über den links gezeigten Button erreicht.
+ Zufälliges Feld lösen
+ Es wird automatisch ein zufälliges Feld gelöst.
+ Ausgewähltes Feld lösen
+ Das zur Zeit ausgewählte Feld wird gelöst.
+ Lösung prüfen
+ Deine aktuelle Lösung wird geprüft und eine Nachricht teilt dir mit ob alle deine ausgefüllten Felder korrekt gelöst sind,
+ oder ob es ein Feld gibt, das nicht korrekt gelöst ist.
+ Zurück zum letzten korrekten Stand
+ Diese Hilfestellung setzt das Spiel auf den letzten Stand zurück zu dem alle Felder, die du ausgefüllt hast korrekt gelöst waren.
+ Der bisherige falsche Spielstand kann im Aktionsverlauf wiederhergestellt werden.
+ Aufgeben
+ Dies ist keine Hilfestellung als solche.
+ Wenn sie aufgerufen wird, wird das Sudoku automatisch gelöst und man kann sich die Lösung ansehen. Für ein aufgegebenes Spiel erhält man keine Punkte.
+
+
+ Aktionsverlauf
+ Der Aktionsverlauf speichert alles was du in einem Spiel machst. Jedes Feld das du entweder durch Lösen oder Notitzen setzen veränderst
+ wird im Aktionsverlauf gespeichert. Das ermöglicht es dir eine Lösung auszuprobieren und zurückzugehen falls sie falsch war ohne dass du dir jeden einzelnen Schritt merken musst,
+ seit das Spiel zuletzt korrekt ausgefüllt war.
+
+ Mit dem Button links kannst du diesen Verlauf in einem Spiel öffnen und dich durch deine Aktionen navigieren.
+ Wenn du dich im Verlauf zurückbewegst und von dort weiterspielst wird ein neuer Ast erzeugt, so dass du jederzeit zu deiner alten Lösung zurückkehren kannst.
+ Das Bild links zeigt eine einzelne Aktion die du ausgeführt hast im Verlauf.
+ Im Aktionsverlauf kannst du Lesezeichen setzen um dir einen Status zu merken. Ein Lesezeichen wird dargestellt wie auf der linken Seite zu sehen ist.
+ Das Bild auf der linken Seite zeigt wie der Zustand in dem du dich gerade befindest markiert wird.
+ Wenn du von einem Zustand aus zwei verschiedene Lösungen probiert hast, gibt es zwei Äste und der Zustand ist markiert wie links zu sehen ist.
+ Wiederherstellen / Rückgängig machen
+ Mit den Buttons links kannst du eine Aktion einfach wiederherstellen oder rückgängig machen ohne den Aktionsverlauf zu öffnen.
+
\ No newline at end of file
diff --git a/sudoq-app/res/values-fr/strings.xml b/sudoq-app/res/values-fr/strings.xml
new file mode 100644
index 00000000..1a1fa00e
--- /dev/null
+++ b/sudoq-app/res/values-fr/strings.xml
@@ -0,0 +1,153 @@
+
+
+
+
+
+
+
+
+ Erreur! Le dossier Profile n’a pas pu être trouvé!
+ Erreur! Paramètres incomplets!
+ Gestes non disponibles!
+Vignette n’a pas pu être créé!
+ Reçu miniature n’a pas pu être sauvé!
+ Les vignettes peuvent ne pas être chargé!
+ Certains symboles ne sont pas liées à un geste!
+ Pas de symbole alternatif fixe disponible!
+
+
+ Une case n’a pas été résolue correctement
+ Toutes les cases ont été résolues correctement
+ Symbole invalide
+ Symbole restreint
+
+
+ SudoQ se prépare pour la première utilisation
+
+
+ Tutorial
+Gestes pour les chiffres
+ Gestes pour les lettres
+ Supprimer tous les gestes
+ Supprimer geste spécifique
+
+
+ Oui
+ Non
+ Tu as gagné!
+ Tu as abandonné!
+ Veux-tu fermer ce sudoku?
+ Statistiques
+ Temps joué
+ Score
+
+
+ Statistiques
+ Compteur
+ Sudokus joués
+ Sudokus faciles joués
+ Sudokus moyens joués
+ Sudokus difficiles joués
+ Sudokus infernales joués
+ Records
+ Score maximal
+ Temps de résolution le plus rapide
+
+
+ Paramètres
+ Nom
+ Entrée de gestes
+ Paramètres du profil
+ Aide
+ Séléctionner la ligne/ la colonne
+ Séléctionner les symboles faux
+ Aide de saisie
+ Résoudre la case choisie
+ Résoudre une case au hasard
+ Conseils
+ Adapter les remarques automatiquement
+ Changer de profil
+ Profil
+ Créer un nouveau profil
+ Effacer ce profil
+ Statistiques
+définir des gestes
+ Sauvegarder
+ nouveau profil
+
+
+ Profil changé
+
+
+ Changer de profil
+
+
+ Nouveau sudoku
+ Continuer
+ Charger un sudoku
+ Profil
+
+
+ Sudoku
+ Sudoku officiel
+ Créer
+ Adhérer
+
+
+ Type du sudoku:
+ Difficulté:
+ Départ
+ Choisir le type du sudoku
+ Choisir le degré de difficulté
+ Configurer l’aide
+ Les modèles sont en train d’être copiés. Veuillez patienter.
+
+
+ Marque-page
+ Fermer
+ Aide
+ Vérifier la solution
+ Résoudre la case choisie
+ Résoudre une case au hasard
+ Abandonner
+ Retourner au dernier état correct
+ Entrée de l’icône par un geste
+ Les dernières actions…
+
+
+ SudoQ
+ Nouveau sudoku
+
+
+ Multiplayer
+
+
+ Facile
+ Moyen
+ Difficile
+ Infernal
+
+
+ Sudoku standard 9x9
+ Sudoku standard 16x16
+ Sudoku standard 6x6
+ Sudoku standard 4x4
+ Squiggly-Sudoku de type A 9x9
+ Squiggly-Sudoku de type B 9x9
+ Stairstep-Sudoku 9x9
+ Samurai-Sudoku
+ Hyper-Sudoku
+ XSudoku
+ Paramètres du sudoku
+
+
+ Résolu
+
+
+ Aucun sudoku sauvegardé disponible.
+ Séléctionner le suduko à effacer…
+ Effacer les sudokus résolus
+ Effacer un certain sudoku
+ Retour
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/values-fr/tutorial.xml b/sudoq-app/res/values-fr/tutorial.xml
new file mode 100644
index 00000000..90b2a35b
--- /dev/null
+++ b/sudoq-app/res/values-fr/tutorial.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+ Sudoku
+ Un Sudoku est un jeu de logique dans lequel on doit placer les chiffres dans la case appropriée.
+ Le Sudoku standard est une grille de 9x9, dont chaque ligne, chaque colonne et chaque bloc de 3x3 cases doit contenir tous les chiffres de 1 à 9.
+ Au début, le Sudoku est partiellement rempli, et il n’existe qu’une seule solution.
+ Il existe d’autres types de Sudoku,
+ dont les blocs ne sont pas forcément
+ de forme 3x3. Dans cette app,
+ ces blocs sont délimités par une
+ bordure noire ou bien 9 cases
+ grisées. Les images suivantes montrent
+ ces deux types de forme pour un bloc,
+ qui peuvent se superposer:
+ Sudoku Squiggly de type A
+ X-Sudoku Type
+
+
+ Aide
+ Plusieures aides sont à votre disposition afin de faciliter la résolution du Sudoku.
+ Ces aides peuvent être divisées en „aide passive“ ou „aide active“.
+ Aide passive
+ L’aide passive peut être activée dans le profil ou encore au début d’une nouvelle partie.
+ Cette aide ne doit pas être appelée au cours de la partie, et ne peut de ce fait pas être activée ou désactivée durant le jeu.
+
+Mais: L’activation d’une assistance passive ou l’utilisation d’une aide active diminue le highscore
+ Sélectionner la ligne/la colonne
+ Si il s’agit d’une aide active, alors toutes les cases de la ligne et de la colonne sélectionnées sont mises en évidence.
+ Adapter les remarques automatiquement
+ Cette aide actualise tes remarques lorsque tu entres un chiffre dans une case.
+ Si ce chiffre se trouve déjà dans la même ligne, colonne ou du même bloc en tant que remarque, alors celle-ci est effacée.
+ Sélectionner les symboles faux
+ Lorsqu’un chiffre est entré dans une case alors qu’il se trouve déjà dans une autre case de la même ligne,
+ colonne ou du même bloc, alors il apparaît rouge, car ce chiffre ne peut se trouver simultanément dans les deux cases.
+ Aide de saisie
+ Lorsque cette aide est activée, il est seulement possible d’entrer un chiffre dans une case s’il n’a pas
+ encore été entré dans une autre case de cette même ligne, colonne ou du même bloc.
+ Toutes les autres cases apparaissent grisées.
+ Aide active
+ L’aide active peut être appelée au cours de la partie.
+ Elle est accessible par l’icone affiché à gauche.
+ Résoudre une case au hasard.
+ Automatiquement, une case prise au hasard est résolue.
+ Résoudre la case choisie
+ La case actuellement sélectionnée.
+ Vérifier la solution
+ Votre solution actuelle se fait vérifier et un message vous préviendra si toutes vos cases sont justes ou si une case n’a pas été résolue correctement.
+ Retourner au dernier état correct
+ Avec cette aide, la partie est reprise au dernier stade où toutes les cases ont été résolues de manière correcte.
+ La liste des actions annulées peut être retrouvé dans l’historique.
+ Abandonner
+ Ceci n’est pas une aide en soi.
+ Lorsqu’elle est appellée, le Sudoku est résolu automatiquement et l’on peut voir la solution.
+ Une partie abandonnée ne rapporte pas de points.
+
+
+ Historique
+ L’historique sauvegarde toutes vos actions au cours du jeu.
+ Chaque case que vous modifiez par résolution ou mise de remarques, est sauvegardée dans l’historique.
+ Ceci vous permet de tester une solution et de revenir en arrière au cas où une case a été mal résolue jusqu’au dernier stade correct.
+ De cette manière vous n’êtes obligé de vous souvenir de chaque étape depuis votre faux-pas.
+ Avec l’icone à gauche, vous pouvez ouvrir l’historique pendant le jeu et naviguer parmi vos actions.
+ Lorsque vous retournez dans l’historique et que vous choisissez de continuer la partie à partir d’un autre moment, l’historique forme une nouvelle branche.
+ Ainsi vous pouvez recourir à vos anciennes solutions à tout moment.
+ L’image à gauche représente l’une de vos actions dans l’historique.
+ Dans l’historique vous pouvez créer un marque-page afin de vous souvenir d’un certain stade.
+ Un marque-page est représenté sur l’image à gauche.
+ L’image à gauche montre comment votre stade actuel est marqué.
+ Lorsque vous avez essayé deux solutions différentes à partir d’un certain stade,
+ l’historique forme deux branches et le stade est marqué comme l’on peut le voir à gauche.
+ Annuler/Restaurer
+ Avec les icones à gauche vous pouvez restaurer une action ou l’annuler sans ouvrir l’historique.
+
\ No newline at end of file
diff --git a/sudoq-app/res/values/strings.xml b/sudoq-app/res/values/strings.xml
new file mode 100644
index 00000000..0c9a2d05
--- /dev/null
+++ b/sudoq-app/res/values/strings.xml
@@ -0,0 +1,185 @@
+
+
+
+
+
+
+
+ SudoQ
+
+
+ 1.0
+ Release
+
+
+ Tutorial
+ Gestures for digits
+ Gestures for letters
+ Delete all gestures
+ Delete specific gestures
+
+
+ Error! Profile folder could not be located!
+ Error! Settings are incomplete!
+ Gestures not available!
+ Cannot capture screen on pause!
+ Cannot save captured thumbnail!
+ Cannot load thumbnail for given game!
+ You need to define Gestures for all Symbols in your Profile!
+ No alternate symbolset available!
+
+
+ A field is not solved correctly
+ Everything is solved correctly
+ Invalid symbol
+ Symbol is restricted
+
+
+ SudoQ is being initialized for the first start
+
+
+ Yes
+ No
+ You won!
+ You surrendered!
+ Do you want to quit?
+ Statistics
+ Time needed
+ Score
+
+
+ Statistics
+ Counters
+ Played sudokus
+ Played easy sudokus
+ Played medium sudokus
+ Played difficult sudokus
+ Played infernal sudokus
+ Records
+ Highscore
+ Fastest solving time
+
+
+ User Preferences
+ Name
+ Gesture Input
+ Profile-Settings
+ Assistances
+ Mark Row/Column
+ Mark wrong Symbols
+ Input Assistance
+ Solve Specific Field
+ Solve Random Field
+ Hint For Easy Field
+ Auto Adjust Notices
+ Switch Profile
+ Profile
+ Create New Profile
+ Delete Profile
+ Statistics
+ Gesture Builder
+ Save
+ unnamed
+
+
+ Profile changed to
+
+
+ Change Profile
+
+
+ New Sudoku
+ Continue
+ Load Sudoku
+ Profile
+
+
+ Define a Gesture
+
+
+ Sudoku
+ Official Sudoku
+ Create
+ Join
+
+
+ Sudoku Type:
+ Difficulty:
+ Start
+ Choose Sudoku Type
+ Choose Difficulty
+ Adjust Assistances
+ Templates are currently being copied. Please wait a moment.
+
+
+ Bookmark
+ Close
+ Assistances
+ Check solution
+ Solve selected field
+ Solve random field
+ Surrender
+ Back to last correct status
+ Input symbol via gesture
+ Action History
+
+
+ SudoQ
+ New Sudoku
+
+
+ Multiplayer
+
+
+ Easy
+ Medium
+ Difficult
+ Infernal
+
+
+ Standard-Sudoku 9x9
+ Standard-Sudoku 16x16
+ Standard-Sudoku 6x6
+ Standard-Sudoku 4x4
+ Squiggly-Sudoku Type A 9x9
+ Squiggly-Sudoku Type B 9x9
+ Stairstep-Sudoku 9x9
+ Samurai-Sudoku
+ Hyper-Sudoku
+ XSudoku
+ Sudoku-Preferences
+
+
+
+
+ finished
+
+
+ No saved Sudokus available.
+ Select Sudoku to delete…
+ Delete finished Sudokus
+ Select Sudoku to delete
+ HH:mm:ss dd.MM.yyyy
+ Go back!
+
+
+
+ profile_id
+ deleted
+ current_game
+ name
+ gesture
+ profilesettings
+ assistances
+
+
+ profile_
+ game_
+ sudoku_
+ current_profile
+
+
+ profiles
+ sudokus
+
+
diff --git a/sudoq-app/res/values/styles.xml b/sudoq-app/res/values/styles.xml
new file mode 100644
index 00000000..39d369bd
--- /dev/null
+++ b/sudoq-app/res/values/styles.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/values/sudoku_preferences_arrays.xml b/sudoq-app/res/values/sudoku_preferences_arrays.xml
new file mode 100644
index 00000000..6e6a1884
--- /dev/null
+++ b/sudoq-app/res/values/sudoku_preferences_arrays.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+ - @string/sudoku_type_standard_9x9
+ - @string/sudoku_type_standard_4x4
+ - @string/sudoku_type_standard_6x6
+ - @string/sudoku_type_standard_16x16
+ - @string/sudoku_type_squiggly_a_9x9
+ - @string/sudoku_type_squiggly_b_9x9
+ - @string/sudoku_type_stairstep_9x9
+ - @string/sudoku_type_samurai
+ - @string/sudoku_type_hyper
+ - @string/sudoku_type_xsudoku
+
+
+
+ - @string/complexity_easy
+ - @string/complexity_medium
+ - @string/complexity_difficult
+ - @string/complexity_infernal
+
+
\ No newline at end of file
diff --git a/sudoq-app/res/values/tutorial.xml b/sudoq-app/res/values/tutorial.xml
new file mode 100644
index 00000000..c53607f2
--- /dev/null
+++ b/sudoq-app/res/values/tutorial.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+ Sudoku
+ A sudoku is a logic-based, combinatorial number-placement puzzle. The original sudoku
+ is a 9x9 grid that has to be filled with digits so hat each column, each row and each of the nine 3x3 sub-grids contains
+ all the digits from 1 to 9. At the beginning a sudoku is partially completed and has only one correct solution.
+ Further sudoku types do not define the 3x3 sub-grids but other sets of fields which are
+ represented by a black edging or gray shaded fields in this app. The following images show both types of representation which can
+ overlap:
+ Squiggly Type A Sudoku
+ X-Sudoku Type
+
+
+ Assistances
+ There are several assistances available to make it easier to solve a sudoku.
+ These assistances can be classified as "passive" and "active" assistances.
+ But: Activating a passive assistance or using an active assistance implies
+ your highscore to be lowered.
+
+ Passive assistances
+ Passive assistances are those that can be activated in the profile or before
+ starting a game. These assistances do not have to be called in a game but therefore they cannot be activated or deactivated in the
+ game.
+ Mark row / column
+ Activating this assistance emphasises the fields in the
+ currently selected row and column.
+ Auto adjust notes
+ This assistance updates your notes when a digit is put into a field.
+ If that digit is in the notes of a field in the same row, column or block you put it in, it is removed from those notes.
+ Mark wrong symbols
+ If a digit is put into a field although it is already
+ in a field of the same row, column or block it is marked red because there cannot be the same digit in both fields.
+ Input assistance
+ With this assistance activated you can only put a digit into a
+ field that is not in one of the fields of the same row, column or block yet. All other digits are grayed out.
+
+ Active assistances
+ Active assistances can be used as you need them during a game.
+ You can reach them by clicking on the button shown left.
+ Solve random field
+ A random field is automatically solved for you.
+ Solve current field
+ The field you have currently selected is solved for you.
+ Check solution
+ Your current solution is checked and a message tells you if your
+ currently solved fields are all correct or if there is a field that is solved wrong.
+ Back to last correct status
+ Using this assistance reverts the game to the last state
+ where all fields you have solved were correct. Although all your action that are reverted are saved in the action history and can
+ be redone.
+ Surrender
+ This is not an ordinary assistance. Using this the whole sudoku
+ is automatically solved and you can take a look at the solution. You will get no score for a game you surrendered.
+
+
+ Action History
+ The action history saves everything you do in a sudoku game. Every field you modify by either
+ solving it or by setting notes is saved into an action history. This enables you to try a solution and go back if it was
+ wrong without having to memorise every step you made since your solution was right for the last time.
+ With the button at the left you can open this history in a game and navigate through the
+ actions you did.
+ If you move back in the history and start playing from there a new branch is the history
+ is created, so you can even go back to your old solution again.
+ The image on the left shows a single action you did in the history.
+ In the action history you can set bookmarks to remember a state. Such a bookmark is represented
+ as you can see in the image on the left.
+ The image on the left shows how the state you are currently in is marked.
+ If there is a state from which you tried two different solutions there are two branches and
+ the state is marked as you can see on the left.
+ Undo / Redo
+ With the buttons on the left you can easily undo or redo an action without
+ opening the action history.
+
\ No newline at end of file
diff --git a/sudoq-app/src/de/sudoq/controller/SudoqActivity.java b/sudoq-app/src/de/sudoq/controller/SudoqActivity.java
new file mode 100644
index 00000000..099c8e84
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/SudoqActivity.java
@@ -0,0 +1,91 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import de.sudoq.R;
+import de.sudoq.controller.tutorial.TutorialActivity;
+import de.sudoq.model.files.FileManager;
+
+/**
+ * Eine Activity, welche die für einwandfreie Funktionalität der SudoQ-App
+ * notwendigen Initialisierungsarbeiten ausführt.
+ */
+public class SudoqActivity extends Activity {
+
+ /**
+ * Konstante für den Tutorial Menü-Eintrag
+ */
+ private static final int MENU_TUTORIAL = -1;
+
+ /**
+ * Initialisiert eine neue Activity, setzt dabei die für die App notwendigen
+ * System-Properties und initialisiert den FileManager.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver");
+ FileManager.initialize(getDir(getString(R.string.path_rel_profiles), Context.MODE_PRIVATE),
+ getDir(getString(R.string.path_rel_sudokus), Context.MODE_PRIVATE));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ System.gc();
+ }
+
+ /**
+ * Erstellt das Optionsmenü mit einem Tutorial-Eintrag.
+ *
+ * @param menu
+ * Das Menü
+ * @return true
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.clear();
+ prepareOptionsMenu(menu);
+ return true;
+ }
+
+ /**
+ * Fügt dem übergebenen Menü die globalen Einträge (Tutorial) hinzu.
+ *
+ * @param menu
+ * Das Menü
+ */
+ protected void prepareOptionsMenu(Menu menu) {
+ menu.add(0, MENU_TUTORIAL, 0, getString(R.string.optionsmenu_tutorial));
+ }
+
+ /**
+ * Verarbeitet das Auswählen des Tutorial-Menüeintrags.
+ *
+ * @param item
+ * Das ausgewählte Menü-Item
+ * @return true
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == MENU_TUTORIAL) {
+ startActivity(new Intent(this, TutorialActivity.class));
+ }
+ return true;
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/SudoqListActivity.java b/sudoq-app/src/de/sudoq/controller/SudoqListActivity.java
new file mode 100644
index 00000000..814cf34e
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/SudoqListActivity.java
@@ -0,0 +1,80 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuItem;
+import de.sudoq.R;
+import de.sudoq.controller.tutorial.TutorialActivity;
+import de.sudoq.model.files.FileManager;
+
+/**
+ * Eine ListActivity, welche die für einwandfreie Funktionalität der SudoQ-App
+ * notwendigen Initialisierungsarbeiten ausführt.
+ */
+public class SudoqListActivity extends ListActivity {
+
+ /**
+ * Konstante für den Tutorial Menü-Eintrag
+ */
+ private static final int MENU_TUTORIAL = -1;
+
+ /**
+ * Initialisiert eine neue Activity, setzt dabei die für die App notwendigen
+ * System-Properties und initialisiert den FileManager.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ System.setProperty("org.xml.sax.driver", "org.xmlpull.v1.sax2.Driver");
+ FileManager.initialize(getDir(getString(R.string.path_rel_profiles), Context.MODE_PRIVATE),
+ getDir(getString(R.string.path_rel_sudokus), Context.MODE_PRIVATE));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ System.gc();
+ }
+
+ /**
+ * Erstellt das Optionsmenü mit einem Tutorial-Eintrag.
+ *
+ * @param menu
+ * Das Menü
+ * @return true
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add(0, MENU_TUTORIAL, 0, getString(R.string.optionsmenu_tutorial));
+ return true;
+ }
+
+ /**
+ * Verarbeitet das Auswählen des Tutorial-Menüeintrags.
+ *
+ * @param item
+ * Das ausgewählte Menü-Item
+ * @return true
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == MENU_TUTORIAL) {
+ startActivity(new Intent(this, TutorialActivity.class));
+ }
+ return true;
+ }
+
+}
\ No newline at end of file
diff --git a/sudoq-app/src/de/sudoq/controller/menus/AssistancesPreferencesActivity.java b/sudoq-app/src/de/sudoq/controller/menus/AssistancesPreferencesActivity.java
new file mode 100644
index 00000000..328b3c17
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/AssistancesPreferencesActivity.java
@@ -0,0 +1,140 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.LinearLayout;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqActivity;
+import de.sudoq.model.ModelChangeListener;
+import de.sudoq.model.game.Assistances;
+import de.sudoq.model.profile.Profile;
+
+/**
+ * Activity um Profile zu bearbeiten und zu verwalten
+ */
+public class AssistancesPreferencesActivity extends SudoqActivity implements ModelChangeListener {
+ /** Attributes */
+ private static final String LOG_TAG = AssistancesPreferencesActivity.class.getSimpleName();
+
+ CheckBox gesture;
+ CheckBox autoAdjustNotes;
+ CheckBox markRowColumn;
+ CheckBox markWrongSymbol;
+ CheckBox restrictCandidates;
+
+ /**
+ * Wird aufgerufen, falls die Activity zum ersten Mal gestartet wird. Läd
+ * die Preferences anhand der zur Zeit aktiven Profil-ID.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.setContentView(R.layout.playerpreferences);
+
+ gesture = (CheckBox) findViewById(R.id.checkbox_gesture);
+ autoAdjustNotes = (CheckBox) findViewById(R.id.checkbox_autoAdjustNotes);
+ markRowColumn = (CheckBox) findViewById(R.id.checkbox_markRowColumn);
+ markWrongSymbol = (CheckBox) findViewById(R.id.checkbox_markWrongSymbol);
+ restrictCandidates = (CheckBox) findViewById(R.id.checkbox_restrictCandidates);
+
+ LinearLayout layout = (LinearLayout) findViewById(R.id.playerpreferences_layout_everything);
+
+ /* Aufruf aus SudokuPreferenceActivity */
+ Log.d(LOG_TAG, "Short assistances");
+
+ layout = (LinearLayout) findViewById(R.id.playerpreferences_layout_everything);
+ layout.removeView(findViewById(R.id.button_showStatistics));
+ layout.removeView(findViewById(R.id.playerpreferences_layout_profilename));
+
+ Profile.getInstance().registerListener(this);
+ }
+
+
+ /**
+ * Wird aufgerufen, falls die Activity erneut den Eingabefokus erhält. Läd
+ * die Preferences anhand der zur Zeit aktiven Profil-ID.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ refreshValues();
+ }
+
+ /**
+ * Aktualisiert die Werte in den Views
+ */
+ private void refreshValues() {
+ gesture.setChecked(Profile.getInstance().isGestureActive());
+ autoAdjustNotes.setChecked(SudokuPreferencesActivity.assistances.getAssistance(Assistances.autoAdjustNotes));
+ markRowColumn.setChecked(SudokuPreferencesActivity.assistances.getAssistance(Assistances.markRowColumn));
+ markWrongSymbol.setChecked(SudokuPreferencesActivity.assistances.getAssistance(Assistances.markWrongSymbol));
+ restrictCandidates.setChecked(SudokuPreferencesActivity.assistances.getAssistance(Assistances.restrictCandidates));
+ }
+
+
+ /**
+ * Speichert die Profiländerungen.
+ *
+ * @param view
+ * unbenutzt
+ */
+ public void saveChanges(View view) {
+ onBackPressed();
+ }
+
+ /**
+ * Wird aufgerufen, falls eine andere Activity den Eingabefokus erhält.
+ * Speichert die Einstellungen.
+ */
+ @Override
+ public void onPause() {
+ super.onPause();
+ adjustValuesAndSave();
+ }
+
+ /**
+ * Uebernimmt die Werte der Views im Profil und speichert die aenderungen
+ */
+ private void adjustValuesAndSave() {
+ Profile.getInstance().setGestureActive(gesture.isChecked());
+ saveCheckbox(autoAdjustNotes, Assistances.autoAdjustNotes);
+ saveCheckbox(markRowColumn, Assistances.markRowColumn);
+ saveCheckbox(markWrongSymbol, Assistances.markWrongSymbol);
+ saveCheckbox(restrictCandidates, Assistances.restrictCandidates);
+
+ Profile.getInstance().saveChanges();
+ }
+
+ private void saveCheckbox(CheckBox cb, Assistances a){
+ if(cb.isChecked())
+ SudokuPreferencesActivity.assistances.setAssistance(a);
+ else
+ SudokuPreferencesActivity.assistances.clearAssistance(a);
+ }
+
+ public void onModelChanged(Profile obj) {
+ this.refreshValues();
+ }
+
+ /**
+ * Öffnet den GestureBuilder.
+ *
+ * @param view
+ * unbenutzt
+ */
+ public void openGestureBuilder(View view) {
+ Intent gestureBuilderIntent = new Intent(this, GestureBuilder.class);
+ startActivity(gestureBuilderIntent);
+ }
+
+}
\ No newline at end of file
diff --git a/sudoq-app/src/de/sudoq/controller/menus/GestureBuilder.java b/sudoq-app/src/de/sudoq/controller/menus/GestureBuilder.java
new file mode 100644
index 00000000..5090f818
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/GestureBuilder.java
@@ -0,0 +1,249 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.Set;
+
+import android.gesture.Gesture;
+import android.gesture.GestureOverlayView;
+import android.gesture.GestureOverlayView.OnGesturePerformedListener;
+import android.gesture.GestureStore;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqActivity;
+import de.sudoq.controller.sudoku.FieldViewPainter;
+import de.sudoq.controller.sudoku.FieldViewStates;
+import de.sudoq.controller.sudoku.InputListener;
+import de.sudoq.controller.sudoku.Symbol;
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.profile.Profile;
+import de.sudoq.view.VirtualKeyboardLayout;
+
+/**
+ * Der GestureBuilder gestattet es dem Benutzer selber Gesten für die Benutzung im Spiel zu definieren, das ermöglicht eine wesentlich höhere Erkennungsrate als mitgelieferte Gesten.
+ * @author Anrion
+ *
+ */
+public class GestureBuilder extends SudoqActivity implements OnGesturePerformedListener, InputListener {
+
+ /**
+ * Fängt Gesteneingaben des Benutzers ab
+ */
+ private GestureOverlayView gestureOverlay;
+
+ /**
+ * Hält die von der Activity unterstützten Gesten
+ */
+ private GestureStore gestureStore = new GestureStore();
+
+ /**
+ * ID des OptionsMenu-Eintrags zum Löschen aller Gesten.
+ */
+ private static final int MENU_FLUSH_GESTURE_LIBRARY = 2;
+
+ /**
+ * ID des OptionsMenu-Eintrags zum Löschen einer bestimmten Geste.
+ */
+ private static final int MENU_DELETE_GESTURE = 3;
+
+ private static final String LOG_TAG = GestureBuilder.class.getSimpleName();
+
+ /**
+ * Flag für das Löschen von einer Gesten.
+ */
+ private boolean deleteSpecific = false;
+
+ /**
+ * Der aktuelle Symbolsatz, für den Gesten eingetragen werden können.
+ */
+ private String[] currentSymbolSet = Symbol.MAPPING_NUMBERS_HEX_LETTERS;
+
+ /**
+ * Das aktuell ausgewählte Symbol, dass der GestureLibrary hinzugefügt werden soll.
+ */
+ private String currentSelectedSymbol;
+
+ /**
+ * Virtuelles Keyboard, zum Auswählen des Symbols, für das eine Geste angelegt werden soll.
+ */
+ private VirtualKeyboardLayout virtualKeyboard;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.gesturebuilder);
+ Symbol.createSymbol(currentSymbolSet);
+ this.virtualKeyboard = (VirtualKeyboardLayout) findViewById(R.id.gesture_builder_virtual_keyboard);
+ inflateGestures();
+ refreshKeyboard();
+ }
+
+ @Override
+ protected void onResume() {
+ refreshKeyboard();
+ super.onResume();
+ }
+
+ /**
+ * Erzeugt die View für die Gesteneingabe
+ */
+ private void inflateGestures() {
+ File gestureFile = FileManager.getCurrentGestureFile();
+ try {
+ this.gestureStore.load(new FileInputStream(gestureFile));
+ } catch (FileNotFoundException e) {
+ try {
+ gestureFile.createNewFile();
+ } catch (IOException ioe) {
+ Log.w(LOG_TAG, "Gesture file cannot be loaded!");
+ }
+ } catch (IOException e) {
+ Profile.getInstance().setGestureActive(false);
+ Toast.makeText(this, R.string.error_gestures_no_library, Toast.LENGTH_SHORT).show();
+ }
+
+ this.gestureOverlay = new GestureOverlayView(this);
+ this.gestureOverlay.addOnGesturePerformedListener(this);
+ LayoutParams gestureLayoutParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+ this.gestureOverlay.setLayoutParams(gestureLayoutParams);
+ this.gestureOverlay.setBackgroundColor(Color.BLACK);
+ this.gestureOverlay.getBackground().setAlpha(127);
+ this.gestureOverlay.setVisibility(View.INVISIBLE);
+ this.gestureOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
+
+ FrameLayout frameLayout = (FrameLayout) findViewById(R.id.gesture_builder_layout);
+ frameLayout.addView(this.gestureOverlay);
+ }
+
+ @Override
+ protected void prepareOptionsMenu(Menu menu) {
+ super.prepareOptionsMenu(menu);
+ menu.add(0, MENU_FLUSH_GESTURE_LIBRARY, 0, getString(R.string.optionsmenu_gesture_builder_flush));
+ menu.add(0, MENU_DELETE_GESTURE, 0, getString(R.string.optionsmenu_gesture_builder_delete_single));
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case MENU_FLUSH_GESTURE_LIBRARY:
+ Set gestures = this.gestureStore.getGestureEntries();
+ for (Iterator gestureIterator = gestures.iterator(); gestureIterator.hasNext();) {
+ String gestureName = (String) gestureIterator.next();
+ gestureIterator.remove();
+ }
+ saveGestures();
+ refreshKeyboard();
+ break;
+ case MENU_DELETE_GESTURE:
+ this.deleteSpecific = true;
+ break;
+ }
+
+ return super.onOptionsItemSelected(item);
+ }
+
+ /**
+ * Speichert den aktuellen Satz an Gesten om Profile Ordner des aktuellen Benutzers
+ */
+ private void saveGestures() {
+ File gestureFile = FileManager.getCurrentGestureFile();
+ try {
+ this.gestureStore.save(new FileOutputStream(gestureFile));
+ } catch (IOException e) {
+ Profile.getInstance().setGestureActive(false);
+ Toast.makeText(this, R.string.error_gestures_no_library, Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ /**
+ * Wurde eine Geste akzeptiert, wird diese im GestureStore gespeichert. (Das ist noch nicht persistent)
+ */
+ public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
+ this.gestureStore.addGesture(this.currentSelectedSymbol, gesture);
+ saveGestures();
+ this.gestureOverlay.setVisibility(View.INVISIBLE);
+ refreshKeyboard();
+ }
+
+ /**
+ * Markiert die Tasten der Tastatur so, dass alle Tasten mit Symbolen, für die bereits Gesten existieren Gelb markiert sind.
+ */
+ private void markAlreadyCapturedSymbols() {
+ Set gestures = this.gestureStore.getGestureEntries();
+ for (int i = 0; i < this.currentSymbolSet.length; i++) {
+ if (gestures.contains(this.currentSymbolSet[i])) {
+ this.virtualKeyboard.markField(Symbol.getInstance().getAbstract(this.currentSymbolSet[i]), FieldViewStates.SELECTED_NOTE);
+ }
+ }
+ }
+
+ /**
+ * Aktuallisiert die Tastatur.
+ */
+ private void refreshKeyboard() {
+ FieldViewPainter.getInstance().setMarking(this.virtualKeyboard, FieldViewStates.KEYBOARD);
+ Symbol.createSymbol(currentSymbolSet);
+ this.virtualKeyboard.refresh(currentSymbolSet.length);
+ this.virtualKeyboard.setActivated(true);
+ this.virtualKeyboard.enableAllButtons();
+ markAlreadyCapturedSymbols();
+ this.virtualKeyboard.registerListener(this);
+ }
+
+ @Override
+ public void onBackPressed() {
+ if (this.gestureOverlay.isShown()) {
+ this.gestureOverlay.setVisibility(View.INVISIBLE);
+ } else {
+ saveGestures();
+ Set gestures = this.gestureStore.getGestureEntries();
+ super.onBackPressed();
+ }
+ }
+
+ /**
+ * Wird auf eine Taste gedrückt, wird die Prozedur zum eingeben von Gesten gestartet.
+ *
+ * @param int symbol Das ausgewählte Symbol
+ */
+ public void onInput(int symbol) {
+ Set gestures = this.gestureStore.getGestureEntries();
+ if (this.deleteSpecific) {
+ if (gestures.contains(Symbol.getInstance().getMapping(symbol))) {
+ this.gestureStore.removeEntry(Symbol.getInstance().getMapping(symbol));
+ refreshKeyboard();
+ }
+ saveGestures();
+ this.deleteSpecific = false;
+ } else {
+ this.currentSelectedSymbol = Symbol.getInstance().getMapping(symbol);
+ final TextView textView = new TextView(gestureOverlay.getContext());
+ textView.setTextColor(Color.YELLOW);
+ textView.setText(" " + gestureOverlay.getContext().getString(R.string.gesture_builder_define_gesture) + " ");
+ textView.setTextSize(18);
+ this.gestureOverlay.addView(textView, new GestureOverlayView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
+ this.gestureOverlay.setVisibility(View.VISIBLE);
+ }
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/menus/MainActivity.java b/sudoq-app/src/de/sudoq/controller/menus/MainActivity.java
new file mode 100644
index 00000000..ab0bc839
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/MainActivity.java
@@ -0,0 +1,133 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import java.io.File;
+
+import android.content.Intent;
+import android.graphics.BitmapFactory;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqActivity;
+import de.sudoq.controller.sudoku.SudokuActivity;
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.profile.Profile;
+
+/**
+ * Verwaltet das Hauptmenü der App.
+ */
+public class MainActivity extends SudoqActivity {
+
+ /**
+ * Der Log-Tag für den LogCat
+ */
+ @SuppressWarnings("unused")
+ private static final String LOG_TAG = MainActivity.class.getSimpleName();
+
+ /** Methods */
+
+ /**
+ * Wird beim ersten Anzeigen des Hauptmenüs aufgerufen. Inflated das Layout.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.mainmenu);
+ }
+
+ /**
+ * Wird aufgerufen, falls die Acitivity wieder den Eingabefokus erhält.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ Button continueButton = (Button) findViewById(R.id.button_mainmenu_continue);
+ if (Profile.getInstance().getCurrentGame() == Profile.NO_GAME) {
+ continueButton.setEnabled(false);
+ } else {
+ continueButton.setEnabled(true);
+ File currentThumbnailFile = FileManager.getGameThumbnailFile(Profile.getInstance().getCurrentGame());
+ BitmapFactory bitmapFactory = new BitmapFactory();
+// bitmapFactory.decodeStream(InputStream)
+// Bitmap currentThumbnailBitmap = new
+// continueButton.setBackgroundDrawable(new Drawable() {
+//
+// @Override
+// public void setColorFilter(ColorFilter cf) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// @Override
+// public void setAlpha(int alpha) {
+// // TODO Auto-generated method stub
+//
+// }
+//
+// @Override
+// public int getOpacity() {
+// // TODO Auto-generated method stub
+// return 0;
+// }
+//
+// @Override
+// public void draw(Canvas canvas) {
+// // TODO Auto-generated method stub
+//
+// }
+// });
+ }
+ }
+
+ /**
+ * Wechselt zu einer Activity, entsprechend der Auswahl eines Menübuttons.
+ * Ist der übergebene Button null oder unbekannt, so wird nichts getan.
+ *
+ * @param button
+ * Vom Benutzer ausgewählter Menübutton
+ */
+ public void switchActivity(View button) {
+ switch (button.getId()) {
+ case R.id.button_mainmenu_new_sudoku:
+ // Intent newSudokuIntent = new Intent(this,
+ // GameTypeSelection.class);
+ // startActivity(newSudokuIntent);
+ Intent startLocalIntent = new Intent(this, SudokuPreferencesActivity.class);
+ startLocalIntent.putExtra(SudokuPreferencesActivity.DESIRED_GAME_TYPE, SudokuPreferencesActivity.LOCAL_GAME);
+ startActivity(startLocalIntent);
+ break;
+
+ case R.id.button_mainmenu_continue:
+ Intent continueSudokuIntent = new Intent(this, SudokuActivity.class);
+ startActivity(continueSudokuIntent);
+ overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
+ break;
+
+ case R.id.button_mainmenu_load_sudoku:
+ Intent loadSudokuIntent = new Intent(this, SudokuLoadingActivity.class);
+ startActivity(loadSudokuIntent);
+ break;
+
+ case R.id.button_mainmenu_profile:
+ Intent preferencesIntent = new Intent(this, PlayerPreferencesActivity.class);
+ startActivity(preferencesIntent);
+ break;
+ }
+ }
+
+ /*
+ * {@inheritDoc}
+ */
+ // @Override
+ // public void onConfigurationChanged(Configuration newConfig) {
+ // super.onConfigurationChanged(newConfig);
+ // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ // }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/menus/PlayerPreferencesActivity.java b/sudoq-app/src/de/sudoq/controller/menus/PlayerPreferencesActivity.java
new file mode 100644
index 00000000..08e05678
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/PlayerPreferencesActivity.java
@@ -0,0 +1,297 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import java.util.List;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.LinearLayout;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqActivity;
+import de.sudoq.model.ModelChangeListener;
+import de.sudoq.model.game.Assistances;
+import de.sudoq.model.profile.Profile;
+
+/**
+ * Activity um Profile zu bearbeiten und zu verwalten
+ */
+public class PlayerPreferencesActivity extends SudoqActivity implements ModelChangeListener {
+ /** Attributes */
+ private static final String LOG_TAG = PlayerPreferencesActivity.class.getSimpleName();
+
+ /**
+ * Konstante um anzuzeigen, dass nur die Assistences konfiguriert werden
+ * sollen
+ */
+ public static final String INTENT_ONLYASSISTANCES = "only_assistances";
+ /**
+ * Konstante um anzuzeigen, dass nur ein neues Profil erzeugt werden soll
+ */
+ public static final String INTENT_CREATEPROFILE = "create_profile";
+
+ private static boolean createProfile;
+
+ EditText name;
+ CheckBox gesture;
+ CheckBox autoAdjustNotes;
+ CheckBox markRowColumn;
+ CheckBox markWrongSymbol;
+ CheckBox restrictCandidates;
+
+ boolean firstStartup;
+
+ /**
+ * Wird aufgerufen, falls die Activity zum ersten Mal gestartet wird. Läd
+ * die Preferences anhand der zur Zeit aktiven Profil-ID.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.setContentView(R.layout.playerpreferences);
+
+ firstStartup = false;
+
+ name = (EditText) findViewById(R.id.edittext_profilename);
+ name.clearFocus();
+ name.setSingleLine(true);// no multiline names
+
+ gesture = (CheckBox) findViewById(R.id.checkbox_gesture);
+ autoAdjustNotes = (CheckBox) findViewById(R.id.checkbox_autoAdjustNotes);
+ markRowColumn = (CheckBox) findViewById(R.id.checkbox_markRowColumn);
+ markWrongSymbol = (CheckBox) findViewById(R.id.checkbox_markWrongSymbol);
+ restrictCandidates = (CheckBox) findViewById(R.id.checkbox_restrictCandidates);
+
+ LinearLayout layout = (LinearLayout) findViewById(R.id.playerpreferences_layout_everything);
+
+ createProfile = true;
+
+ /* Aufruf aus SudokuPreferenceActivity */
+ if (getIntent().hasExtra(INTENT_ONLYASSISTANCES) && getIntent().getExtras().getBoolean(INTENT_ONLYASSISTANCES)) {
+ Log.d(LOG_TAG, "Short assistances");
+
+ createProfile = false;
+
+ layout = (LinearLayout) findViewById(R.id.playerpreferences_layout_everything);
+ layout.removeView(findViewById(R.id.button_showStatistics));
+ layout.removeView(findViewById(R.id.playerpreferences_layout_profilename));
+ } else {
+ layout.removeView(findViewById(R.id.button_saveChanges));
+ }
+
+ Profile.getInstance().registerListener(this);
+ }
+
+ /**
+ * Wird aufgerufen, falls die Activity erneut den Eingabefokus erhält. Läd
+ * die Preferences anhand der zur Zeit aktiven Profil-ID.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ refreshValues();
+ }
+
+ /**
+ * Aktualisiert die Werte in den Views
+ */
+ private void refreshValues() {
+ name.setText(Profile.getInstance().getName());
+ gesture.setChecked(Profile.getInstance().isGestureActive());
+ autoAdjustNotes.setChecked(Profile.getInstance().getAssistance(Assistances.autoAdjustNotes));
+ markRowColumn.setChecked(Profile.getInstance().getAssistance(Assistances.markRowColumn));
+ markWrongSymbol.setChecked(Profile.getInstance().getAssistance(Assistances.markWrongSymbol));
+ restrictCandidates.setChecked(Profile.getInstance().getAssistance(Assistances.restrictCandidates));
+ }
+
+ /**
+ * Wird beim Buttonklick aufgerufen und erstellt ein neues Profil
+ *
+ * @param view
+ * von android xml übergebene View
+ */
+ public void createProfile(View view) {
+ if (!firstStartup) {
+ adjustValuesAndSave();
+
+ String newProfileName = getString(R.string.profile_preference_new_profile);
+
+ int newIndex = 0;
+ /* increment newIndex to be bigger than the others */
+ List l = Profile.getInstance().getProfilesNameList();
+ for (String s : l)
+ if (s.startsWith(newProfileName)) {
+ String currentIndex = s.substring(newProfileName.length());
+ try {
+ int otherIndex = currentIndex.equals("") ? 0 : Integer.parseInt(currentIndex);
+ newIndex = newIndex <= otherIndex ? otherIndex + 1 : newIndex;
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+ }
+
+ if (newIndex != 0)
+ newProfileName += newIndex;
+
+ Profile.getInstance().createProfile();
+ name.setText(newProfileName);
+ } else {
+ adjustValuesAndSave();
+ this.finish();
+ }
+ }
+
+ /**
+ * Zeigt die Statistik des aktuellen Profils.
+ *
+ * @param view
+ * unbenutzt
+ */
+ public void viewStatistics(View view) {
+ Intent statisticsIntent = new Intent(this, StatisticsActivity.class);
+ startActivity(statisticsIntent);
+ }
+
+ /**
+ * Öffnet den GestureBuilder.
+ *
+ * @param view
+ * unbenutzt
+ */
+ public void openGestureBuilder(View view) {
+ Intent gestureBuilderIntent = new Intent(this, GestureBuilder.class);
+ startActivity(gestureBuilderIntent);
+ }
+
+ /**
+ * Speichert die Profiländerungen.
+ *
+ * @param view
+ * unbenutzt
+ */
+ public void saveChanges(View view) {
+ onBackPressed();
+ }
+
+ /**
+ * Wird aufgerufen, falls eine andere Activity den Eingabfokus erhält.
+ * Speichert die Einstellungen.
+ */
+ @Override
+ public void onPause() {
+ super.onPause();
+ adjustValuesAndSave();
+ }
+
+ /**
+ * Uebernimmt die Werte der Views im Profil und speichert die aenderungen
+ */
+ private void adjustValuesAndSave() {
+ Profile.getInstance().setName(name.getText().toString());
+ Profile.getInstance().setGestureActive(gesture.isChecked());
+ Profile.getInstance().setAssistance(Assistances.autoAdjustNotes, autoAdjustNotes.isChecked());
+ Profile.getInstance().setAssistance(Assistances.markRowColumn, markRowColumn.isChecked());
+ Profile.getInstance().setAssistance(Assistances.markWrongSymbol, markWrongSymbol.isChecked());
+ Profile.getInstance().setAssistance(Assistances.restrictCandidates, restrictCandidates.isChecked());
+
+ Profile.getInstance().saveChanges();
+ }
+
+ /**
+ * wechselt zur Profil Liste
+ *
+ * @param view
+ * von der android xml übergebene view
+ */
+ public void switchToProfileList(View view) {
+ Intent profileListIntent = new Intent(this, ProfileListActivity.class);
+ startActivity(profileListIntent);
+ }
+
+ /**
+ * Löscht das ausgewählte Profil
+ *
+ * @param view
+ * von der android xml übergebene view
+ */
+ public void deleteProfile(View view) {
+ Profile.getInstance().deleteProfile();
+ }
+
+ /*
+ * {@inheritDoc}
+ */
+ // @Override
+ // public void onConfigurationChanged(Configuration newConfig) {
+ // super.onConfigurationChanged(newConfig);
+ // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ // }
+
+ public void onModelChanged(Profile obj) {
+ this.refreshValues();
+ }
+
+ // ///////////////////////////////////////optionsMenue
+
+ private static final int MENU_SWITCH_PROFILE = 0;
+ private static final int MENU_CREATE_PROFILE = 1;
+ private static final int MENU_DELETE_PROFILE = 2;
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ if (createProfile)
+ menu.clear();
+
+ // onPrepareOptionsMenu(menu);
+
+ return true;
+ }
+
+ /**
+ * Stellt das OptionsMenu bereit
+ *
+ * @param item
+ * Das ausgewählte Menü-Item
+ * @return true
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ super.onOptionsItemSelected(item);
+ if (item.getItemId() == MENU_SWITCH_PROFILE) {
+ switchToProfileList(null);
+ } else if (item.getItemId() == MENU_CREATE_PROFILE) {
+ createProfile(null);
+ } else if (item.getItemId() == MENU_DELETE_PROFILE) {
+ deleteProfile(null);
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ if (createProfile) {
+ menu.clear();
+
+ menu.add(0, MENU_CREATE_PROFILE, 0, getString(R.string.profile_preference_title_createprofile));
+ if (Profile.getInstance().getNumberOfAvailableProfiles() > 1) {
+ menu.add(0, MENU_DELETE_PROFILE, 0, getString(R.string.profile_preference_title_deleteprofile));
+ menu.add(0, MENU_SWITCH_PROFILE, 0, getString(R.string.profile_preference_title_switchprofile));
+ }
+ }
+ super.prepareOptionsMenu(menu);
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/sudoq-app/src/de/sudoq/controller/menus/ProfileListActivity.java b/sudoq-app/src/de/sudoq/controller/menus/ProfileListActivity.java
new file mode 100644
index 00000000..3b91e002
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/ProfileListActivity.java
@@ -0,0 +1,86 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import java.util.ArrayList;
+
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqListActivity;
+import de.sudoq.model.profile.Profile;
+
+/**
+ * Diese Klasse stellt eine Acitivity zur Anzeige und Auswahl von
+ * Spielerprofilen dar.
+ */
+public class ProfileListActivity extends SudoqListActivity implements OnItemClickListener {
+ /** Attributes */
+
+ private static final String LOG_TAG = ProfileListActivity.class.getSimpleName();
+
+ /**
+ * Ein Array der Profil-Dateinamen der Form "Profile_ID", wobei ID der
+ * jeweiligen ID des Profils entspricht.
+ */
+ private ArrayList profileIds;
+
+ /**
+ * Ein Array der Profilnamen
+ */
+ private ArrayList profileNames;
+
+ /** Methods */
+
+ /**
+ * Wird beim ersten Start der Activity aufgerufen.
+ *
+ * @param savedInstanceState
+ * Der Zustand eines vorherigen Aufrufs dieser Activity
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ this.setTitle(this.getString(R.string.profile_preference_title_switchprofile));
+
+ profileIds = Profile.getInstance().getProfilesIdList();
+ profileNames = Profile.getInstance().getProfilesNameList();
+
+ Log.d(LOG_TAG, "Array length: " + Profile.getInstance().getProfilesNameList().size());
+
+ ArrayAdapter adapter = new ArrayAdapter(this,
+ android.R.layout.simple_list_item_1, Profile.getInstance().getProfilesNameList());
+ setListAdapter(adapter);
+ getListView().setOnItemClickListener(this);
+ }
+
+ /**
+ * Wird aufgerufen, falls der Benutzer einen Eintrag in der ListView
+ * anklickt.
+ *
+ * @param parent
+ * AdapterView auf welcher der Benutzer etwas angeklickt hat
+ * @param view
+ * Vom Benutzer angeklickte View
+ * @param position
+ * Position der View im Adapter
+ * @param id
+ * ID der ausgewählten View
+ */
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ Log.d(LOG_TAG, "Clicked on name " + profileNames.get(position) + " with id:" + profileIds.get(position));
+ Profile.getInstance().changeProfile(profileIds.get(position));
+ this.finish();
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/menus/SplashActivity.java b/sudoq-app/src/de/sudoq/controller/menus/SplashActivity.java
new file mode 100644
index 00000000..411c0423
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/SplashActivity.java
@@ -0,0 +1,283 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.LinkedList;
+import java.util.List;
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.AssetManager;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqActivity;
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.profile.Profile;
+
+/**
+ * Eine Splash Activity für die SudoQ-App, welche einen Splash-Screen zeigt,
+ * sowie den FileManager initialisiert und die Daten für den ersten Start
+ * vorbereitet.
+ */
+public class SplashActivity extends SudoqActivity {
+ /**
+ * Das Log-Tag für das LogCat.
+ */
+ private static final String LOG_TAG = SplashActivity.class.getSimpleName();
+
+ /**
+ * Konstante für das Speichern der bereits gewarteten Zeit.
+ */
+ private static final int SAVE_WAITED = 0;
+
+ /**
+ * Konstante für das Speichern des bereits begonnenen Kopiervorgangs.
+ */
+ private static final int SAVE_STARTED_COPYING = 1;
+
+ /**
+ * Die minimale Anzeigedauer des SplashScreens
+ */
+ public static int splashTime = 2500;
+
+ /**
+ * Die Zeit, die schon vergangen ist, seit der SplashScreen gestartet wurde
+ */
+ private int waited;
+
+ /**
+ * Besagt, ob der Kopiervorgang der Templates bereits gestartet wurde
+ */
+ private boolean startedCopying;
+
+ /**
+ * Der SplashThread
+ */
+ private Thread splashThread;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.splash);
+
+ // If there is no profile initialize one
+ if (FileManager.getNumberOfProfiles() == 0) {
+ String name = getUserName();
+ if (name != null) {
+ Profile.getInstance().setName(name);
+ Log.d(LOG_TAG, name);
+ }
+ }
+
+ // Restore waited time after interruption or set it to 0
+ if (savedInstanceState == null) {
+ this.waited = 0;
+ } else {
+ this.waited = savedInstanceState.getInt(SAVE_WAITED + "");
+ this.startedCopying = savedInstanceState.getBoolean(SAVE_STARTED_COPYING + "");
+ }
+
+ // Get the preferences and look if assets where completely copied before
+ SharedPreferences settings = getSharedPreferences("Prefs", 0);
+ if (!settings.getBoolean("Initialized", false) && !this.startedCopying) {
+ new Initialization().execute(null, null, null);
+ startedCopying = true;
+ }
+
+ this.splashThread = new Thread() {
+ @Override
+ public void run() {
+ try {
+ while ((waited < splashTime)) {
+ sleep(100);
+ if (waited < splashTime) {
+ waited += 100;
+ }
+ }
+ goToMainMenu();
+ } catch (InterruptedException e) {
+ // do nothing
+ }
+ }
+ };
+ splashThread.start();
+ }
+
+ /**
+ * Speichert die bereits im Splash gewartete Zeit.
+ */
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putInt(SAVE_WAITED + "", this.waited);
+ outState.putBoolean(SAVE_STARTED_COPYING + "", this.startedCopying);
+ }
+
+ /**
+ * Im Splash wird kein Optionsmenü angezeigt.
+ */
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ @Override
+ public void onPause() {
+ super.onPause();
+ splashThread.interrupt();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ @Override
+ public void onBackPressed() {
+ super.onBackPressed();
+ splashThread.interrupt();
+ finish();
+ }
+
+ /**
+ * Gibt den Benutzernamen des GoogleAccounts zurück.
+ *
+ * @return Der Benutzername des Google-Accounts
+ */
+ private String getUserName() {
+ AccountManager manager = AccountManager.get(this);
+ Account[] accounts = manager.getAccountsByType("com.google");
+ List possibleEmails = new LinkedList();
+
+ Log.d(LOG_TAG, "# of accounts: " + accounts.length);
+
+ for (Account account : accounts) {
+ possibleEmails.add(account.name);
+ Log.d(LOG_TAG, "got account-name: " + account.name);
+ }
+
+ if (!possibleEmails.isEmpty() && possibleEmails.get(0) != null) {
+ return possibleEmails.get(0).substring(0, possibleEmails.get(0).indexOf("@"));
+ }
+
+ return null;
+ }
+
+ /**
+ * Wechselt in die MainMenu-Activity
+ */
+ private void goToMainMenu() {
+ finish();
+ // overridePendingTransition(android.R.anim.fade_in,
+ // android.R.anim.fade_out);
+ Intent startMainMenuIntent = new Intent(this, MainActivity.class);
+ // startMainMenuIntent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
+ startActivity(startMainMenuIntent);
+ // overridePendingTransition(android.R.anim.fade_in,
+ // android.R.anim.fade_out);
+ }
+
+ /**
+ * Ein AsyncTask zur Initialisierung des Benutzers und der Vorlagen für den
+ * ersten Start.
+ */
+ private class Initialization extends AsyncTask {
+ @Override
+ public void onPostExecute(Void v) {
+ SharedPreferences settings = getSharedPreferences("Prefs", 0);
+ settings.edit().putBoolean("Initialized", true).commit();
+ Log.d(LOG_TAG, "Assets completely copied");
+ }
+
+ /**
+ * Kopiert alle Sudoku Vorlagen.
+ */
+ private void copyAssets() {
+ copyDirectory("sudokus");
+ }
+
+ /**
+ * Kopiert den Ordner mit dem angegebenen Pfad.
+ *
+ * @param relPath
+ * Der relative Pfad
+ */
+ private void copyDirectory(String relPath) {
+ AssetManager assetManager = getAssets();
+ String[] files = null;
+ try {
+ files = assetManager.list(relPath);
+ } catch (IOException e) {
+ Log.e(LOG_TAG, e.getMessage());
+ }
+
+ for (String filename : files) {
+ String subFilePath = relPath + File.separator + filename;
+ // sudoku pre path must be removed
+ File subFile = new File(FileManager.getSudokuDir().getAbsolutePath(), subFilePath.substring(8));
+
+ if (!subFile.exists() && !subFile.isDirectory()) {
+ InputStream in = null;
+ OutputStream out = null;
+ try {
+ in = assetManager.open(subFilePath);
+ out = new FileOutputStream(subFile.getAbsolutePath());
+ copyFile(in, out);
+ in.close();
+ out.flush();
+ out.close();
+ } catch (Exception e) {
+ Log.e(LOG_TAG, e.getMessage());
+ }
+ } else {
+ copyDirectory(subFilePath);
+ }
+ }
+ }
+
+ /**
+ * Kopiert die Dateie zwischen den angegeben Streams
+ *
+ * @param in
+ * Der Eingabestream
+ * @param out
+ * Der Ausgabestream
+ * @throws IOException
+ * Wird geworfen, falls beim Lesen/Schreiben der Streams ein
+ * Fehler auftritt
+ */
+ private void copyFile(InputStream in, OutputStream out) throws IOException {
+ byte[] buffer = new byte[1024];
+ int read;
+ while ((read = in.read(buffer)) != -1) {
+ out.write(buffer, 0, read);
+ }
+ }
+
+ @Override
+ protected Void doInBackground(Void... params) {
+ Log.d(LOG_TAG, "Starting to copy templates");
+ copyAssets();
+ return null;
+ }
+
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/menus/StatisticsActivity.java b/sudoq-app/src/de/sudoq/controller/menus/StatisticsActivity.java
new file mode 100644
index 00000000..3e0df1d2
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/StatisticsActivity.java
@@ -0,0 +1,66 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.widget.TextView;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqActivity;
+import de.sudoq.model.profile.Profile;
+import de.sudoq.model.profile.Statistics;
+
+/**
+ * Diese Klasse stellt eine Activity zur Anzeige der Statisik des aktuellen
+ * Spielerprofils dar.
+ */
+public class StatisticsActivity extends SudoqActivity {
+ /** Methods */
+
+ /**
+ * Wird beim ersten Start der Activity aufgerufen.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.statistics);
+ TextView current = (TextView) findViewById(R.id.text_played_sudokus);
+ current.setText(getString(R.string.statistics_played_sudokus) + ": " + Profile.getInstance().getStatistic(Statistics.playedSudokus));
+ current = (TextView) findViewById(R.id.text_played_easy_sudokus);
+ current.setText(getString(R.string.statistics_played_easy_sudokus) + ": " + Profile.getInstance().getStatistic(Statistics.playedEasySudokus));
+ current = (TextView) findViewById(R.id.text_played_medium_sudokus);
+ current.setText(getString(R.string.statistics_played_medium_sudokus) + ": " + Profile.getInstance().getStatistic(Statistics.playedMediumSudokus));
+ current = (TextView) findViewById(R.id.text_played_difficult_sudokus);
+ current.setText(getString(R.string.statistics_played_difficult_sudokus) + ": " + Profile.getInstance().getStatistic(Statistics.playedDifficultSudokus));
+ current = (TextView) findViewById(R.id.text_played_infernal_sudokus);
+ current.setText(getString(R.string.statistics_played_infernal_sudokus) + ": " + Profile.getInstance().getStatistic(Statistics.playedInfernalSudokus));
+ current = (TextView) findViewById(R.id.text_score);
+ current.setText(getString(R.string.statistics_score) + ": " + Profile.getInstance().getStatistic(Statistics.maximumPoints));
+ current = (TextView) findViewById(R.id.text_fastest_solving_time);
+ int fullTime = Profile.getInstance().getStatistic(Statistics.fastestSolvingTime);
+ String timeString = "---";
+ if (fullTime != 5999) {
+ timeString = fullTime / 60 + ":";
+ if (fullTime % 60 < 10) {
+ timeString += "0";
+ }
+ timeString += fullTime % 60;
+ }
+ current.setText(getString(R.string.statistics_fastest_solving_time) + ": " + timeString);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/menus/SudokuLoadingActivity.java b/sudoq-app/src/de/sudoq/controller/menus/SudokuLoadingActivity.java
new file mode 100644
index 00000000..0a4cf0a3
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/SudokuLoadingActivity.java
@@ -0,0 +1,195 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import java.util.List;
+
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.TextView;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqListActivity;
+import de.sudoq.controller.sudoku.SudokuActivity;
+import de.sudoq.model.game.GameData;
+import de.sudoq.model.game.GameManager;
+import de.sudoq.model.profile.Profile;
+
+/**
+ * Diese Klasse repräsentiert den Lade-Controller des Sudokuspiels. Mithilfe von
+ * SudokuLoading können Sudokus geladen werden und daraufhin zur SudokuActivity
+ * gewechselt werden.
+ */
+public class SudokuLoadingActivity extends SudoqListActivity implements OnItemClickListener {
+
+ /**
+ * Der Log-Tag für das LogCat
+ */
+ private static final String LOG_TAG = SudokuLoadingActivity.class.getSimpleName();
+
+ /** Attributes */
+
+ private SudokuLoadingAdapter adapter;
+
+ private List games;
+
+ protected static MenuItem menuDeleteFinished;
+ private static final int MENU_DELETE_FINISHED = 0;
+
+ protected static MenuItem menuDeleteSpecific;
+ private static final int MENU_DELETE_SPECIFIC = 1;
+
+ private boolean deleteMode = false;
+
+ /** Constructors */
+
+ /** Methods */
+
+ /**
+ * Wird aufgerufen, wenn SudokuLoading nach Programmstart zum ersten Mal
+ * geladen aufgerufen wird. Hier wird das Layout inflated und es werden
+ * nötige Initialisierungen vorgenommen.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.sudokuloading);
+ initialiseGames();
+ }
+
+ /**
+ * Wird beim ersten Anzeigen des Options-Menü von SudokuLoading aufgerufen
+ * und initialisiert das Optionsmenü indem das Layout inflated wird.
+ *
+ * @return true falls das Options-Menü angezeigt werden kann, sonst false
+ */
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menuDeleteSpecific = menu.add(0, MENU_DELETE_SPECIFIC, 0, R.string.sudokuloading_delete_specific);
+ menuDeleteFinished = menu.add(0, MENU_DELETE_FINISHED, 0, R.string.sudokuloading_delete_finished);
+ super.onCreateOptionsMenu(menu);
+
+ return true;
+ }
+
+ /**
+ * Wird beim Auswählen eines Menü-Items im Options-Menü aufgerufen. Ist das
+ * spezifizierte MenuItem null oder ungültig, so wird nichts getan.
+ *
+ * @param item
+ * Das ausgewählte Menü-Item
+ * @return true, falls die Selection hier bearbeitet wird, false falls nicht
+ */
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ super.onOptionsItemSelected(item);
+
+ if (item.getItemId() == MENU_DELETE_FINISHED) {
+ GameManager.getInstance().deleteFinishedGames();
+ } else if (item.getItemId() == MENU_DELETE_SPECIFIC) {
+ this.deleteMode = true;
+ }
+
+ onContentChanged();
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onContentChanged() {
+ super.onContentChanged();
+ initialiseGames();
+ }
+
+ /**
+ * Wird aufgerufen, falls ein Element (eine View) in der AdapterView
+ * angeklickt wird.
+ *
+ * @param parent
+ * AdapterView in welcher die View etwas angeklickt wurde
+ * @param view
+ * View, welche angeklickt wurde
+ * @param position
+ * Position der angeklickten View im Adapter
+ * @param id
+ * ID der angeklickten View
+ */
+ public void onItemClick(AdapterView> parent, View view, int position, long id) {
+ Log.d(LOG_TAG, position + "");
+
+ if (!this.deleteMode) {
+ Profile.getInstance().setCurrentGame(adapter.getItem(position).getId());
+ startActivity(new Intent(this, SudokuActivity.class));
+ overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
+ } else {
+ this.deleteMode = false;
+ GameManager.getInstance().deleteGame(adapter.getItem(position).getId());
+ onContentChanged();
+ }
+ }
+
+ private void initialiseGames() {
+ games = GameManager.getInstance().getGameList();
+ // initialize ArrayAdapter for the profile names and set it
+ adapter = new SudokuLoadingAdapter(this, games);
+ setListAdapter(adapter);
+ getListView().setOnItemClickListener(this);
+
+ TextView noGamesTextView = (TextView) findViewById(R.id.no_games_text_view);
+ TextView noGamesBackButton = (TextView) findViewById(R.id.no_games_back_button);
+ if (games.isEmpty()) {
+ noGamesTextView.setVisibility(View.VISIBLE);
+ noGamesBackButton.setVisibility(View.VISIBLE);
+ } else {
+ noGamesTextView.setVisibility(View.INVISIBLE);
+ noGamesBackButton.setVisibility(View.INVISIBLE);
+ }
+
+ TextView deleteSpecific = (TextView) findViewById(R.id.delete_specific_game_text_view);
+ if (this.deleteMode) {
+ deleteSpecific.setVisibility(View.VISIBLE);
+ } else {
+ deleteSpecific.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ /**
+ * Führt die onBackPressed-Methode aus.
+ *
+ * @param view
+ * unbenutzt
+ */
+ public void goBack(View view) {
+ super.onBackPressed();
+ }
+
+ /**
+ * Just for testing!
+ */
+ public int getSize() {
+ return games.size();
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/menus/SudokuLoadingAdapter.java b/sudoq-app/src/de/sudoq/controller/menus/SudokuLoadingAdapter.java
new file mode 100644
index 00000000..495d9b50
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/SudokuLoadingAdapter.java
@@ -0,0 +1,144 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.TimeZone;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import de.sudoq.R;
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.game.GameData;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+
+/**
+ * Adapter für die Anzeige aller Spiele des Spielers
+ */
+public class SudokuLoadingAdapter extends ArrayAdapter {
+ private static final float THUMBNAIL_SIZE = 0.5f;
+ private static final String LOG_TAG = SudokuLoadingAdapter.class.getSimpleName();
+ private final Context context;
+ private final List gameDatas;
+ private String[] typeStrings;
+ private String[] complexityStrings;
+
+ /**
+ * Erzeugt einen neuen SudokuLoadingAdpater mit den gegebenen Parametern
+ *
+ * @param context
+ * der Applikationskontext
+ * @param games
+ * die Liste der games
+ */
+ public SudokuLoadingAdapter(Context context, List games) {
+ super(context, R.layout.sudokuloadingitem, games);
+ this.context = context;
+ this.gameDatas = games;
+ initialiseTypes();
+ initialiseComplexities();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ View rowView = inflater.inflate(R.layout.sudokuloadingitem, parent, false);
+ ImageView thumbnail = (ImageView) rowView.findViewById(R.id.sudoku_loading_item_thumbnail);
+ TextView sudokuType = (TextView) rowView.findViewById(R.id.type_label);
+ TextView sudokuComplexity = (TextView) rowView.findViewById(R.id.complexity_label);
+ TextView sudokuTime = (TextView) rowView.findViewById(R.id.time_label);
+ TextView sudokuState = (TextView) rowView.findViewById(R.id.state_label);
+
+ File currentThumbnailFile = FileManager.getGameThumbnailFile(gameDatas.get(position).getId());
+ try {
+ Bitmap currentThumbnailBitmap = BitmapFactory.decodeStream(new FileInputStream(currentThumbnailFile));
+ int thumbnailWidth = currentThumbnailBitmap.getWidth();
+ int thumbnailHeight = currentThumbnailBitmap.getHeight();
+
+ Matrix matrix = new Matrix();//identity matrix
+ matrix.postScale(THUMBNAIL_SIZE, THUMBNAIL_SIZE);//scaled matrix
+
+ Bitmap resizedBitmap = Bitmap.createBitmap(currentThumbnailBitmap, 0, 0, thumbnailWidth, thumbnailHeight, matrix, false);
+
+ //Setting Layout of the ImageView
+ LinearLayout.LayoutParams visibleLayoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
+ visibleLayoutParams.gravity = Gravity.CENTER;
+ thumbnail.setLayoutParams(visibleLayoutParams);
+ thumbnail.setImageBitmap(resizedBitmap);
+ thumbnail.setVisibility(View.VISIBLE);
+
+ } catch (FileNotFoundException e) {
+ Log.w(LOG_TAG, this.context.getString(R.string.error_thumbnail_load));
+ }
+
+ sudokuType.setText(typeStrings[gameDatas.get(position).getType().ordinal()]);
+ sudokuComplexity.setText(complexityStrings[gameDatas.get(position).getComplexity().ordinal()]);
+
+ TimeZone tz = TimeZone.getDefault();
+ SimpleDateFormat sdf = new SimpleDateFormat(context.getString(R.string.time_format));
+ sdf.setTimeZone(tz);
+
+ String date = sdf.format(gameDatas.get(position).getPlayedAt());
+
+ sudokuTime.setText(date);
+
+ if (gameDatas.get(position).isFinished()) {
+ // TODO finished durch Haken ersetzen
+ sudokuState.setText(context.getString(R.string.game_finished));
+ sudokuType.setTextColor(Color.GRAY);
+ sudokuComplexity.setTextColor(Color.GRAY);
+ sudokuTime.setTextColor(Color.GRAY);
+ sudokuState.setTextColor(Color.GRAY);
+ }
+
+ return rowView;
+ }
+
+ private void initialiseTypes() {
+ typeStrings = new String[SudokuTypes.values().length];
+ typeStrings[SudokuTypes.standard4x4.ordinal()] = context.getString(R.string.sudoku_type_standard_4x4);
+ typeStrings[SudokuTypes.standard6x6.ordinal()] = context.getString(R.string.sudoku_type_standard_6x6);
+ typeStrings[SudokuTypes.standard9x9.ordinal()] = context.getString(R.string.sudoku_type_standard_9x9);
+ typeStrings[SudokuTypes.standard16x16.ordinal()] = context.getString(R.string.sudoku_type_standard_16x16);
+ typeStrings[SudokuTypes.Xsudoku.ordinal()] = context.getString(R.string.sudoku_type_xsudoku);
+ typeStrings[SudokuTypes.HyperSudoku.ordinal()] = context.getString(R.string.sudoku_type_hyper);
+ typeStrings[SudokuTypes.stairstep.ordinal()] = context.getString(R.string.sudoku_type_stairstep_9x9);
+ typeStrings[SudokuTypes.squigglya.ordinal()] = context.getString(R.string.sudoku_type_squiggly_a_9x9);
+ typeStrings[SudokuTypes.squigglyb.ordinal()] = context.getString(R.string.sudoku_type_squiggly_b_9x9);
+ typeStrings[SudokuTypes.samurai.ordinal()] = context.getString(R.string.sudoku_type_samurai);
+
+ }
+
+ private void initialiseComplexities() {
+ complexityStrings = new String[Complexity.values().length];
+ complexityStrings[Complexity.easy.ordinal()] = context.getString(R.string.complexity_easy);
+ complexityStrings[Complexity.medium.ordinal()] = context.getString(R.string.complexity_medium);
+ complexityStrings[Complexity.difficult.ordinal()] = context.getString(R.string.complexity_difficult);
+ complexityStrings[Complexity.infernal.ordinal()] = context.getString(R.string.complexity_infernal);
+ }
+}
\ No newline at end of file
diff --git a/sudoq-app/src/de/sudoq/controller/menus/SudokuPreferencesActivity.java b/sudoq-app/src/de/sudoq/controller/menus/SudokuPreferencesActivity.java
new file mode 100644
index 00000000..caec561a
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/menus/SudokuPreferencesActivity.java
@@ -0,0 +1,244 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.menus;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemSelectedListener;
+import android.widget.ArrayAdapter;
+import android.widget.Spinner;
+import android.widget.Toast;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqActivity;
+import de.sudoq.controller.sudoku.SudokuActivity;
+import de.sudoq.model.game.AssistanceSet;
+import de.sudoq.model.game.Game;
+import de.sudoq.model.game.GameManager;
+import de.sudoq.model.game.GameType;
+import de.sudoq.model.profile.Profile;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+
+/**
+ * SudokuPreferences ermöglicht das Verwalten von Einstellungen eines zu
+ * startenden Sudokus.
+ */
+public class SudokuPreferencesActivity extends SudoqActivity {
+ /** Attributes */
+ private Intent startGameIntent;
+
+ /**
+ * Konstante für den Key des GameTypes
+ */
+ public static final String DESIRED_GAME_TYPE = "desired_game_type";
+
+ /**
+ * Konstante für den Wert des Game Typs
+ */
+ public static final int NO_GAME_TYPE = 0;
+ /**
+ * Konstante für den Wert des Game Typs
+ */
+ public static final int LOCAL_GAME = 1;
+ /**
+ * Konstante für den Wert des Game Typs
+ */
+ public static final int MULTIPLAYER_GAME = 2;
+
+ private static final String LOG_TAG = SudokuPreferencesActivity.class.getSimpleName();
+
+ private SudokuTypes sudokuType;
+
+ private GameType gameType;
+
+ private Complexity complexity;
+
+ public static AssistanceSet assistances;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert ein neues SudokuPreferences-Objekt.
+ */
+
+ /** Methods */
+
+ /**
+ * Wird beim ersten Aufruf der SudokuPreferences aufgerufen. Die Methode
+ * inflated das Layout der Preferences.
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.setContentView(R.layout.sudokupreferences);
+
+ Spinner typeSpinner = (Spinner) findViewById(R.id.spinner_sudokutype);
+ Spinner complexitySpinner = (Spinner) findViewById(R.id.spinner_sudokucomplexity);
+
+ ArrayAdapter typeAdapter = ArrayAdapter.createFromResource(
+ this, R.array.sudokutype_values, android.R.layout.simple_spinner_item);
+ typeAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ typeSpinner.setAdapter(typeAdapter);
+
+ ArrayAdapter complexityAdapter = ArrayAdapter.createFromResource(
+ this, R.array.sudokucomplexity_values, android.R.layout.simple_spinner_item);
+ complexityAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ complexitySpinner.setAdapter(complexityAdapter);
+
+ // nested Listener for typeSpinner
+ complexitySpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView> parent,
+ View view, int pos, long id) {
+ String item = parent.getItemAtPosition(pos).toString();
+
+ if (item.equals(getResources().getString(R.string.complexity_easy))) {
+ setSudokuDifficulty(Complexity.easy);
+ } else if (item.equals(getResources().getString(R.string.complexity_medium))) {
+ setSudokuDifficulty(Complexity.medium);
+ } else if (item.equals(getResources().getString(R.string.complexity_difficult))) {
+ setSudokuDifficulty(Complexity.difficult);
+ } else if (item.equals(getResources().getString(R.string.complexity_infernal))) {
+ setSudokuDifficulty(Complexity.infernal);
+ }
+ }
+
+ public void onNothingSelected(AdapterView> parent) {
+ // do nothing
+ }
+ });
+
+ // nested Listener for complexitySpinner
+ typeSpinner.setOnItemSelectedListener(new OnItemSelectedListener() {
+ public void onItemSelected(AdapterView> parent,
+ View view, int pos, long id) {
+ String item = parent.getItemAtPosition(pos).toString();
+
+ if (item.equals(getResources().getString(R.string.sudoku_type_standard_9x9))) {
+ setSudokuType(SudokuTypes.standard9x9);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_standard_16x16))) {
+ setSudokuType(SudokuTypes.standard16x16);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_standard_6x6))) {
+ setSudokuType(SudokuTypes.standard6x6);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_standard_4x4))) {
+ setSudokuType(SudokuTypes.standard4x4);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_squiggly_a_9x9))) {
+ setSudokuType(SudokuTypes.squigglya);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_squiggly_b_9x9))) {
+ setSudokuType(SudokuTypes.squigglyb);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_stairstep_9x9))) {
+ setSudokuType(SudokuTypes.stairstep);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_hyper))) {
+ setSudokuType(SudokuTypes.HyperSudoku);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_xsudoku))) {
+ setSudokuType(SudokuTypes.Xsudoku);
+ } else if (item.equals(getResources().getString(R.string.sudoku_type_samurai))) {
+ setSudokuType(SudokuTypes.samurai);
+ }
+ }
+
+ public void onNothingSelected(AdapterView> parent) {
+ // do nothing
+ }
+ });
+
+ this.assistances = AssistanceSet.fromString(Profile.getInstance().getAssistances().convertToString());
+ }
+
+ /**
+ * Wird aufgerufen, wenn die Activity in den Vordergrund gelangt. Die
+ * Preferences werden hier neu geladen.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ int desiredGameType = getIntent().getIntExtra(DESIRED_GAME_TYPE, NO_GAME_TYPE);
+ switch (desiredGameType) {
+ case LOCAL_GAME:
+ this.startGameIntent = new Intent(this, SudokuActivity.class);
+ this.gameType = GameType.LOCAL;
+ break;
+ // TODO: Enable MP in SudokuPreferences
+ // case MULTIPLAYER_GAME:
+ // this.startGameIntent = new Intent(this,
+ // SudokuMultiplayerActivity.class);
+ // this.gameType = GameType.MULTIPLAYER;
+ // break;
+ }
+ }
+
+ /*
+ * {@inheritDoc}
+ */
+ // @Override
+ // public void onConfigurationChanged(Configuration newConfig) {
+ // super.onConfigurationChanged(newConfig);
+ // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+ // }
+
+ /**
+ * Die Methode startet per Intent ein Sudokus mit den eingegebenen
+ * Einstellungen.
+ *
+ * @param view
+ * von android xml übergebene View
+ */
+ public void startGame(View view) {
+ if (this.sudokuType != null && this.complexity != null && this.gameType != null && this.assistances != null) {
+ try {
+ Game game = GameManager.getInstance().newGame(this.sudokuType, this.complexity, this.gameType, this.assistances);
+ Profile.getInstance().setCurrentGame(game.getId());
+ startActivity(this.startGameIntent);
+ overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
+ } catch (IllegalArgumentException e) {
+ Toast.makeText(this, getString(R.string.sf_sudokupreferences_copying), Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ Toast.makeText(this, getString(R.string.error_sudoku_preference_incomplete), Toast.LENGTH_SHORT);
+ }
+ }
+
+ /**
+ * Setzt den Sudokutyp des zu startenden Sudokus. Ist dieser null oder
+ * ungültig, so wird nichts getan
+ *
+ * @param type
+ * Typ des zu startenden Sudokus
+ */
+ public void setSudokuType(SudokuTypes type) {
+ this.sudokuType = type;
+ Log.d(LOG_TAG, "type changed to:" + type.toString());
+ }
+
+ /**
+ * Setzt die Schwierigkeit des zu startenden Sudokus. Ist diese null, so
+ * wird nichts getan.
+ *
+ * @param difficulty
+ * Schwierigkeit des zu startenden Sudokus
+ */
+ public void setSudokuDifficulty(Complexity difficulty) {
+ this.complexity = difficulty;
+ Log.d(LOG_TAG, "complexity changed to:" + difficulty.toString());
+ }
+
+ /**
+ * Ruft die PrefererencesActivityNew auf mit dem Intent, dort nur
+ * Assistances einzustellen.
+ *
+ * @param view
+ * von android xml übergebene View
+ */
+ public void switchToAssistances(View view) {
+ Intent assistancesIntent = new Intent(this, AssistancesPreferencesActivity.class);
+// assistancesIntent.putExtra(PlayerPreferencesActivity.INTENT_ONLYASSISTANCES, true);
+ startActivity(assistancesIntent);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/ActionListener.java b/sudoq-app/src/de/sudoq/controller/sudoku/ActionListener.java
new file mode 100644
index 00000000..f729c190
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/ActionListener.java
@@ -0,0 +1,76 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Dieses Interface ermöglicht es Klassen zu reagieren, sobald Actions geaendert werde sollen.
+ */
+public interface ActionListener {
+ /**
+ * Wird aufgerufen, falls der Benutzer die ReDo-Funktion ausgewählt hat
+ *
+ */
+ public void onRedo();
+
+ /**
+ * Wird aufgerufen, falls der Benutzer die Rückgängig-Funktion ausgewählt
+ * hat
+ *
+ */
+ public void onUndo();
+
+ /**
+ * Wird aufgerufen, falls der Benutzer einem Feld eine Notiz hinzufügt.
+ *
+ * @param field
+ * Das Feld, welchem eine Notiz hinzugefügt werden soll
+ * @param value
+ * Der Wert der hinzugefügten Notiz
+ * @throw IllegalArgumentException Wird geworfen, falls das übergebene Field
+ * null ist
+ */
+ public void onNoteAdd(Field field, int value);
+
+ /**
+ * Wird aufgerufen, falls der Benutzer eine Notiz entfernd.
+ *
+ * @param field
+ * Das Feld, dessen Notiz entfernd werden soll
+ * @param value
+ * Der Wert der Notiz, die zu entfernen ist.
+ * @throw IllegalArgumentException Wird geworfen, falls das übergebene Field
+ * null ist
+ */
+ public void onNoteDelete(Field field, int value);
+
+ /**
+ * Wird aufgerufen, falls der Benutzer einem Feld einen Lösungswert
+ * hinzufügt.
+ *
+ * @param field
+ * Das Feld, welchem der Lösungswert hinzugefügt werden soll
+ * @param value
+ * Der Wert der Eingabe
+ * @throw IllegalArgumentException Wird geworfen, falls das übergebene Field
+ * null ist
+ */
+ public void onAddEntry(Field field, int value);
+
+ /**
+ * Wird aufgerufen, falls der Benutzer einen Eintrag aus einem Feld
+ * entfernt.
+ *
+ * @param field
+ * Das Feld, aus welchem der Eintrag entfernt werden soll
+ * @throw IllegalArgumentException Wird geworfen, falls das übergebene Field
+ * null ist
+ */
+ public void onDeleteEntry(Field field);
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/ActionTreeController.java b/sudoq-app/src/de/sudoq/controller/sudoku/ActionTreeController.java
new file mode 100644
index 00000000..238805d9
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/ActionTreeController.java
@@ -0,0 +1,323 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import android.content.res.Configuration;
+import android.util.Log;
+import android.view.View;
+import android.widget.RelativeLayout;
+import de.sudoq.R;
+import de.sudoq.model.ModelChangeListener;
+import de.sudoq.model.actionTree.ActionTreeElement;
+import de.sudoq.view.FullScrollLayout;
+import de.sudoq.view.actionTree.ActionElement;
+import de.sudoq.view.actionTree.ActionTreeElementView;
+import de.sudoq.view.actionTree.ActiveElement;
+import de.sudoq.view.actionTree.BookmarkedElement;
+import de.sudoq.view.actionTree.BranchingElement;
+import de.sudoq.view.actionTree.BranchingLine;
+
+/**
+ * Reagiert auf Interaktionen des Benutzers mit dem Aktionsbaum.
+ */
+public class ActionTreeController implements ActionTreeNavListener, ModelChangeListener {
+ /** Attributes */
+
+ /**
+ * Der Log-Tag
+ */
+ private static final String LOG_TAG = ActionTreeController.class.getSimpleName();
+
+ /**
+ * Kontext, von dem der ActionTreeController verwendet wird
+ */
+ private SudokuActivity context;
+
+ /**
+ * Die ScrolLView des ActionTrees
+ */
+ private FullScrollLayout actionTreeScroll;
+
+ /**
+ * Das Layout, in dem der ActionTree angezeigt wird
+ */
+ private RelativeLayout relativeLayout;
+
+ /**
+ * Die View des aktuellen Elements
+ */
+ private ActionTreeElementView activeElementView;
+
+ /**
+ * Das aktuelle Element
+ */
+ private ActionTreeElement active;
+
+ /**
+ * Die aktuelle X-Position der ScrollView
+ */
+ private int activeX;
+
+ /**
+ * Die aktuelle Y-Position der ScrollView
+ */
+ private int activeY;
+
+ /**
+ * Die Größe des intern verwendeten Rasters in Pixeln
+ */
+ public static final int AT_RASTER_SIZE = 70;
+
+ /**
+ * Maximale erlaubte Größe in Pixeln eines Elements
+ */
+ public static final int MAX_ELEMENT_VIEW_SIZE = 68;
+
+ /**
+ * Initial x coord of the ActionTrees root element.
+ */
+ private int rootElementInitX;
+
+ /**
+ * Initial y coord of the ActionTrees root element.
+ */
+ private int rootElementInitY;
+
+ /**
+ * Das Layout in dem sich der ActionTree befindet.
+ */
+ private RelativeLayout actionTreeLayout;
+
+ /**
+ * Die Höhe des Aktionsbaumes beim letzten Zeichnen.
+ */
+ private int actionTreeHeight;
+
+ /**
+ * Die Breite des Aktionsbaumes beim letzten Zeichnen.
+ */
+ private int actionTreeWidht;
+
+ /**
+ * Die aktuelle Ausrichtung des Geräts
+ */
+ private int orientation;
+
+ /** Constructors */
+
+ /**
+ * Erstellt einen neuen ActionTreeController. Wirft eine IllegalArgumentException, falls der context null ist.
+ *
+ * @param context
+ * Kontext, von welchem der ActionTreeController verwendet werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls der übergebene Context null ist
+ */
+ public ActionTreeController(SudokuActivity context) {
+ if (context == null) {
+ throw new IllegalArgumentException("Unvalid param context!");
+ }
+ this.context = context;
+ this.context.getGame().getStateHandler().registerListener(this);
+
+ this.actionTreeLayout = (RelativeLayout) context.findViewById(R.id.sudoku_action_tree_layout);
+ this.actionTreeScroll = (FullScrollLayout) context.findViewById(R.id.sudoku_action_tree_scroll);
+ }
+
+ /**
+ * Erzeugt die View des ActionTrees.
+ */
+ private void inflateActionTree() {
+ this.rootElementInitX = 1;// frameLayout.getHeight() / 2;
+ this.rootElementInitY = 1;// frameLayout.getWidth() / 2;
+
+ this.relativeLayout = new RelativeLayout(context);
+
+ // Setting active element
+ active = context.getGame().getStateHandler().getCurrentState();
+ ActionTreeElement root = context.getGame().getStateHandler().getActionTree().getRoot();
+
+ // Get screen orientation
+ orientation = context.getResources().getConfiguration().orientation;
+
+ // Draw elements
+ this.actionTreeHeight = 0;
+ this.actionTreeWidht = 0;
+ drawElementsUnder(root, this.rootElementInitX, this.rootElementInitY);
+
+ // Dummy element for a margin at bottom
+ Log.d(LOG_TAG, "ActionTree height: " + this.actionTreeHeight);
+ Log.d(LOG_TAG, "ActionTree width: " + this.actionTreeWidht);
+ View view = new View(context);
+ RelativeLayout.LayoutParams viewLayoutParams = new RelativeLayout.LayoutParams(AT_RASTER_SIZE, AT_RASTER_SIZE);
+ viewLayoutParams.topMargin = (this.actionTreeHeight + 1) * AT_RASTER_SIZE;
+ viewLayoutParams.leftMargin = (this.actionTreeWidht + 1) * AT_RASTER_SIZE;
+ view.setLayoutParams(viewLayoutParams);
+ this.relativeLayout.addView(view);
+
+ // Add active element view
+ this.relativeLayout.addView(this.activeElementView);
+
+ // Put the new RelativeLayout containing the ActionTree into the
+ // ScrollView
+ this.actionTreeScroll.addView(relativeLayout);
+ }
+
+ /**
+ * Zeichnet die Elemente unter dem spezifizierten.
+ *
+ * @param root
+ * Das Ausgangselement
+ * @param x
+ * Die Position des Elements in x-Richtung
+ * @param y
+ * Die Position des Elements in y-Richtung
+ * @return Die Anzahl der unter dem übergebenen Element gezeichneten Elemente
+ */
+ private int drawElementsUnder(ActionTreeElement root, int x, int y) {
+ int dy = 0;
+ for (ActionTreeElement child : root) {
+ if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+ drawLine(x, y, x + 1, y + dy);
+ dy += drawElementsUnder(child, x + 1, y + dy);
+ } else {
+ drawLine(x, y, x + dy, y + 1);
+ dy += drawElementsUnder(child, x + dy, y + 1);
+ }
+ }
+ drawElementAt(root, x, y);
+ this.actionTreeHeight = x > this.actionTreeHeight ? x : this.actionTreeHeight;
+ this.actionTreeWidht = y > this.actionTreeWidht ? y : this.actionTreeWidht;
+ return dy > 0 ? dy : 1;
+ }
+
+ /**
+ * Zeichnet an der angegebenen Stelle das spezifizierte Element.
+ *
+ * @param element
+ * Das zu zeichnende Element
+ * @param x
+ * Die x-Position an der gezeichnet werden soll
+ * @param y
+ * Die y-Position an der gezeichnet werden soll
+ */
+ private void drawElementAt(ActionTreeElement element, int x, int y) {
+ ActionTreeElementView view = new ActionElement(this.context, null, element);
+
+ if (element.isMarked()) {
+ view = new BookmarkedElement(this.context, view, element);
+ }
+ if (element.isSplitUp()) {
+ view = new BranchingElement(this.context, view, element);
+ }
+
+ view.registerActionTreeNavListener(this.context);
+ view.registerActionTreeNavListener(this);
+
+ if (element == this.active) {
+ this.activeElementView = new ActiveElement(this.context, view, element);
+
+ this.activeX = x * AT_RASTER_SIZE;
+ this.activeY = y * AT_RASTER_SIZE;
+ RelativeLayout.LayoutParams viewLayoutParams = new RelativeLayout.LayoutParams(AT_RASTER_SIZE,
+ AT_RASTER_SIZE);
+ viewLayoutParams.topMargin = x * AT_RASTER_SIZE;
+ viewLayoutParams.leftMargin = y * AT_RASTER_SIZE;
+ this.activeElementView.setLayoutParams(viewLayoutParams);
+ } else {
+ RelativeLayout.LayoutParams viewLayoutParams = new RelativeLayout.LayoutParams(AT_RASTER_SIZE,
+ AT_RASTER_SIZE);
+ viewLayoutParams.topMargin = x * AT_RASTER_SIZE;
+ viewLayoutParams.leftMargin = y * AT_RASTER_SIZE;
+ view.setLayoutParams(viewLayoutParams);
+ }
+
+ if (element.isCorrect()) {
+ view.changeColor(ActionTreeElementView.CORRECT_COLOR);
+ }
+ if (element.isMistake()) {
+ view.changeColor(ActionTreeElementView.WRONG_COLOR);
+ }
+
+ this.relativeLayout.addView(view);
+ }
+
+ /**
+ * Zeichnet eine Linie von/bis zu den spezifizierten Positionen.
+ *
+ * @param fromX
+ * Startposition x-Richtung
+ * @param fromY
+ * Startposition y-Richtung
+ * @param toX
+ * Endposition x-Richtung
+ * @param toY
+ * Endposition y-Richtung
+ */
+ private void drawLine(int fromX, int fromY, int toX, int toY) {
+ BranchingLine branchingLine = new BranchingLine(this.context, fromX * AT_RASTER_SIZE, fromY * AT_RASTER_SIZE,
+ (toX * AT_RASTER_SIZE + AT_RASTER_SIZE / 2), (toY * AT_RASTER_SIZE));
+ RelativeLayout.LayoutParams branchingLineLayoutParams = new RelativeLayout.LayoutParams((toY * AT_RASTER_SIZE
+ - fromY * AT_RASTER_SIZE + AT_RASTER_SIZE),
+ (toX * AT_RASTER_SIZE - fromX * AT_RASTER_SIZE + AT_RASTER_SIZE));
+ branchingLineLayoutParams.topMargin = fromX * AT_RASTER_SIZE;
+ branchingLineLayoutParams.leftMargin = fromY * AT_RASTER_SIZE;
+ branchingLine.setLayoutParams(branchingLineLayoutParams);
+ this.relativeLayout.addView(branchingLine);
+ }
+
+ /**
+ * Aktualisiert die ActionTree Ansicht neu
+ */
+ public void refresh() {
+ inflateActionTree();
+ this.actionTreeLayout.setVisibility(View.VISIBLE);
+ }
+
+ /** Methods */
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onHoverTreeElement(ActionTreeElement ate) {
+ context.getGame().goToState(ate);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onLoadState(ActionTreeElement ate) {
+ context.getGame().goToState(ate);
+ }
+
+ /**
+ * Macht den ActionTree sichtbar oder auch nicht gemäß dem Parameter
+ *
+ * @param show
+ * true falls der Baum sichtbar sein soll false falls nicht
+ */
+ public void setVisibility(boolean show) {
+ if (show) {
+ inflateActionTree();
+ this.actionTreeScroll.scrollTo(this.activeY + this.AT_RASTER_SIZE / 2, this.activeX + this.AT_RASTER_SIZE
+ / 2);
+ this.actionTreeLayout.setVisibility(View.VISIBLE);
+ } else {
+ this.actionTreeLayout.setVisibility(View.INVISIBLE);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onModelChanged(ActionTreeElement obj) {
+ if (this.context.isActionTreeShown()) {
+ refresh();
+ }
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/ActionTreeNavListener.java b/sudoq-app/src/de/sudoq/controller/sudoku/ActionTreeNavListener.java
new file mode 100644
index 00000000..1a7a584f
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/ActionTreeNavListener.java
@@ -0,0 +1,44 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import de.sudoq.model.actionTree.ActionTreeElement;
+
+/**
+ * Das Interface ActionTreeNavListener stellt die Möglichkeit bereit, auf
+ * Interaktionen des Benutzers mit dem Aktionsbaum zu reagieren.
+ */
+public interface ActionTreeNavListener {
+ /** Methods */
+
+ /**
+ * Wird aufgerufen, wenn der Benutzer über ein Element des Aktionsbaumes
+ * fährt. Wird verwendet um das Sudoku im Hintergrund auf den Stand des vom
+ * Nutzer gerade angewählten Knotens zu bringen.
+ *
+ * @param ate
+ * ActionTreeElement, welches der Nutzer angewählt hat
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene ActionTreeElement null
+ * ist
+ */
+ public void onHoverTreeElement(ActionTreeElement ate);
+
+ /**
+ * Wird aufgerufen, wenn der Stand eines ausgewählten ActionTreeElementes
+ * geladen werden soll.
+ *
+ * @param ate
+ * Wom Benutzer ausgewähltes ActionTreeElement
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene ActionTreeElement null
+ * ist
+ */
+ public void onLoadState(ActionTreeElement ate);
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/AssistanceRequestListener.java b/sudoq-app/src/de/sudoq/controller/sudoku/AssistanceRequestListener.java
new file mode 100644
index 00000000..edfcb259
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/AssistanceRequestListener.java
@@ -0,0 +1,44 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Dieses Listenerinterface stellt Methoden bereit, sodass die implementierende
+ * Klasse auf Hilfestellungsanfragen reagieren kann und diese gegebenenfalls
+ * ausführt.
+ */
+public interface AssistanceRequestListener {
+ /**
+ *
+ * Löst im aktuellen Sudoku ein beliebiges Feld.
+ *
+ * @return true, sollte das lösen eines Feldes erfolgreich sein, ansonsten
+ * false.
+ */
+ public boolean onSolveOne();
+
+ /**
+ * Löst im aktuellen Sudoku das aktuell ausgewählte Feld.
+ *
+ * @param field
+ * das zu lösende Feld
+ * @return true, sollte das lösen des aktuellen Feldes erfolgreich sein,
+ * ansonsten false.
+ */
+ public boolean onSolveCurrent(Field field);
+
+ /**
+ * Löst das komplette Sudoku. Das entspricht der Aufgabe des Spielenden.
+ *
+ * @return true, sollte das lösen des Sudokus erfolgreich sein, ansonsten
+ * false.
+ */
+ public boolean onSolveAll();
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/FieldInteractionListener.java b/sudoq-app/src/de/sudoq/controller/sudoku/FieldInteractionListener.java
new file mode 100644
index 00000000..e4e2bacf
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/FieldInteractionListener.java
@@ -0,0 +1,34 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import de.sudoq.view.SudokuFieldView;
+
+/**
+ * Ein Listener für Änderungen an Sudoku-Feldern, wie das Auswählen eines Feld
+ * bzw. die Änderung des Feldinhaltes.
+ */
+public interface FieldInteractionListener {
+
+ /**
+ * Wird aufgerufen, falls ein neues Feld ausgewählt wurde.
+ *
+ * @param view
+ * Die View, welche neu ausgewählt wurde
+ */
+ public void onFieldSelected(SudokuFieldView view);
+
+ /**
+ * Wird aufgerufen, falls ein Feld geändert wurde.
+ *
+ * @param view
+ * Die View, welche geändert wurde
+ */
+ public void onFieldChanged(SudokuFieldView view);
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/FieldViewPainter.java b/sudoq-app/src/de/sudoq/controller/sudoku/FieldViewPainter.java
new file mode 100644
index 00000000..952d7d8f
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/FieldViewPainter.java
@@ -0,0 +1,295 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import java.util.Hashtable;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.graphics.Typeface;
+import android.view.View;
+
+/**
+ * Stellt eine Klasse zur Verfügung, welche für Animationen bzw. Markierungen
+ * von Feldern zuständig ist.
+ */
+public class FieldViewPainter {
+ /** Attributes */
+
+ /**
+ * Mappt ein Field auf einen Animation-Wert, welcher beschreibt, wie das
+ * Feld zu zeichnen ist
+ */
+ private Hashtable markings;
+
+ /**
+ * Die Singleton-Instanz des Handlers
+ */
+ private static FieldViewPainter instance;
+
+ /** Constructors */
+
+ /**
+ * Privater Konstruktor, da diese Klasse statisch ist.
+ */
+ private FieldViewPainter() {
+ this.markings = new Hashtable();
+ }
+
+ /**
+ * Gibt die Singleton-Instanz des Handlers zurück.
+ *
+ * @return Die Instanz dieses Handlers
+ */
+ public static FieldViewPainter getInstance() {
+ if (instance == null) {
+ instance = new FieldViewPainter();
+ }
+
+ return instance;
+ }
+
+ /** Methods */
+
+ /**
+ * Bemalt das spezifizierte Canvas entsprechend der in der Hashtable für das
+ * spezifizierte Feld eingetragenen Animation. Ist eines der beiden
+ * Argumente null, so wird nichts getan.
+ *
+ * @param canvas
+ * Das Canvas, welches bemalt werden soll
+ * @param field
+ * Das Feld, anhand dessen Animation-Einstellung das Canvas
+ * bemalt werden soll
+ * @param symbol
+ * Das Symbol das gezeichnet werden soll
+ * @param justText
+ * Definiert, dass nur Text geschrieben wird
+ * @param darken
+ * Verdunkelt das Feld
+ */
+ public void markField(Canvas canvas, View field, String symbol, boolean justText, boolean darken) {
+ FieldViewStates fieldState = this.markings.get(field);
+ if (fieldState != null && !justText) {
+ switch (fieldState) {
+ case SELECTED_INPUT_BORDER:
+ drawBackground(canvas, field, Color.DKGRAY, true, darken);
+ drawInner(canvas, field, Color.rgb(255, 100, 100), true, darken);
+ drawText(canvas, field, Color.BLACK, false, symbol);
+ break;
+ case SELECTED_INPUT:
+ drawBackground(canvas, field, Color.rgb(255, 100, 100), true, darken);
+ drawText(canvas, field, Color.BLACK, false, symbol);
+ break;
+ case SELECTED_INPUT_WRONG:
+ drawBackground(canvas, field, Color.rgb(255, 100, 100), true, darken);
+ drawText(canvas, field, Color.RED, false, symbol);
+ break;
+ case SELECTED_NOTE_BORDER:
+ drawBackground(canvas, field, Color.DKGRAY, true, darken);
+ drawInner(canvas, field, Color.YELLOW, true, darken);
+ drawText(canvas, field, Color.BLACK, false, symbol);
+ break;
+ case SELECTED_NOTE:
+ drawBackground(canvas, field, Color.YELLOW, true, darken);
+ drawText(canvas, field, Color.BLACK, false, symbol);
+ break;
+ case SELECTED_NOTE_WRONG:
+ drawBackground(canvas, field, Color.YELLOW, true, darken);
+ drawText(canvas, field, Color.RED, false, symbol);
+ break;
+ case SELECTED_FIXED:
+ drawBackground(canvas, field, Color.rgb(220, 220, 255), true, darken);
+ drawText(canvas, field, Color.rgb(0, 100, 0), true, symbol);
+ break;
+ case CONNECTED:
+ drawBackground(canvas, field, Color.rgb(220, 220, 255), true, darken);
+ drawText(canvas, field, Color.BLACK, false, symbol);
+ break;
+ case CONNECTED_WRONG:
+ drawBackground(canvas, field, Color.rgb(220, 220, 255), true, darken);
+ drawText(canvas, field, Color.RED, false, symbol);
+ break;
+ case FIXED:
+ drawBackground(canvas, field, Color.rgb(250, 250, 250), true, darken);
+ drawText(canvas, field, Color.rgb(0, 100, 0), true, symbol);
+ break;
+ case DEFAULT_BORDER:
+ drawBackground(canvas, field, Color.DKGRAY, true, darken);
+ drawInner(canvas, field, Color.rgb(250, 250, 250), true, darken);
+ drawText(canvas, field, Color.BLACK, false, symbol);
+ break;
+ case DEFAULT_WRONG:
+ drawBackground(canvas, field, Color.rgb(250, 250, 250), true, darken);
+ drawText(canvas, field, Color.RED, false, symbol);
+ break;
+ case DEFAULT:
+ drawBackground(canvas, field, Color.rgb(250, 250, 250), true, darken);
+ drawText(canvas, field, Color.BLACK, false, symbol);
+ break;
+ case CONTROLS:
+ drawBackground(canvas, field, Color.rgb(40, 40, 40), false, darken);
+ // drawInner(canvas, field, Color.rgb(40, 40, 40), false);
+ break;
+ case KEYBOARD:
+ drawBackground(canvas, field, Color.rgb(230, 230, 230), false, darken);
+ drawInner(canvas, field, Color.rgb(40, 40, 40), false, darken);
+ break;
+ case SUDOKU:
+ drawBackground(canvas, field, Color.rgb(200, 200, 200), false, darken);
+ // drawInner(canvas, field, Color.LTGRAY, false);
+ break;
+ }
+ } else if (fieldState != null) {
+ switch (fieldState) {
+ case SELECTED_INPUT_BORDER:
+ case SELECTED_INPUT:
+ case SELECTED_NOTE_BORDER:
+ case SELECTED_NOTE:
+ case CONNECTED:
+ case DEFAULT_BORDER:
+ case DEFAULT:
+ drawText(canvas, field, Color.BLACK, false, symbol);
+ break;
+ case SELECTED_INPUT_WRONG:
+ case SELECTED_NOTE_WRONG:
+ case DEFAULT_WRONG:
+ case CONNECTED_WRONG:
+ drawText(canvas, field, Color.RED, false, symbol);
+ break;
+ case SELECTED_FIXED:
+ case FIXED:
+ drawText(canvas, field, Color.rgb(0, 100, 0), true, symbol);
+ break;
+ }
+ }
+ }
+
+ /**
+ * Zeichnet den Hintergrund.
+ *
+ * @param canvas
+ * Das Canvas
+ * @param field
+ * Das Field, das gezeichnet wird
+ * @param color
+ * Die Hintergrundfarbe
+ * @param round
+ * Gibt an, ob die Ecken rund gezeichnet werden sollen
+ * @param darken
+ * Gibt an, ob das Feld verdunkelt werden soll
+ */
+ private void drawBackground(Canvas canvas, View field, int color, boolean round, boolean darken) {
+ Paint mainPaint = new Paint();
+ Paint darkenPaint = null;
+ if (darken) {
+ darkenPaint = new Paint();
+ darkenPaint.setARGB(60, 0, 0, 0);
+ }
+ mainPaint.setColor(color);
+ RectF rect = new RectF(0, 0, field.getWidth(), field.getHeight());
+ if (round) {
+ canvas.drawRoundRect(rect, field.getWidth() / 20.0f, field.getHeight() / 20.0f, mainPaint);
+ if (darken) {
+ canvas.drawRoundRect(rect, field.getWidth() / 20.0f, field.getHeight() / 20.0f, darkenPaint);
+ }
+ } else {
+ canvas.drawRect(rect, mainPaint);
+ if (darken) {
+ canvas.drawRect(rect, darkenPaint);
+ }
+ }
+ }
+
+ /**
+ * Malt den inneren Bereich (lässt einen Rahmen).
+ *
+ * @param canvas
+ * Das Canvas
+ * @param field
+ * Das Field, das gezeichnet wird
+ * @param color
+ * Die Farbe
+ * @param round
+ * Gibt an, ob die Ecken rund gezeichnet werden sollen
+ * @param darken
+ * Gibt an, ob das Feld verdunkelt werden soll
+ */
+ private void drawInner(Canvas canvas, View field, int color, boolean round, boolean darken) {
+ Paint mainPaint = new Paint();
+ Paint darkenPaint = null;
+ if (darken) {
+ darkenPaint = new Paint();
+ darkenPaint.setARGB(60, 0, 0, 0);
+ }
+ mainPaint.setColor(color);
+ RectF rect = new RectF(2, 2, field.getWidth() - 2, field.getHeight() - 2);
+ if (round) {
+ canvas.drawRoundRect(rect, field.getWidth() / 20.0f, field.getHeight() / 20.0f, mainPaint);
+ if (darken) {
+ canvas.drawRoundRect(rect, field.getWidth() / 20.0f, field.getHeight() / 20.0f, darkenPaint);
+ }
+ } else {
+ canvas.drawRect(rect, mainPaint);
+ if (darken) {
+ canvas.drawRect(rect, darkenPaint);
+ }
+ }
+ }
+
+ /**
+ * Schreibt den Text
+ *
+ * @param canvas
+ * Das Canvas
+ * @param field
+ * Das Field, das gezeichnet wird
+ * @param color
+ * Die Farbe des Textes
+ * @param bold
+ * Definiert, ob der Text fett ist
+ * @param symbol
+ * Das Symbol, welches geschrieben wird
+ */
+ private void drawText(Canvas canvas, View field, int color, boolean bold, String symbol) {
+ Paint paint = new Paint();
+ paint.setColor(color);
+ if (bold) {
+ paint.setTypeface(Typeface.DEFAULT_BOLD);
+ }
+ paint.setAntiAlias(true);
+ paint.setTextSize(Math.min(field.getHeight() * 3 / 4, field.getWidth() * 3 / 4));
+ paint.setTextAlign(Paint.Align.CENTER);
+ canvas.drawText(symbol + "", field.getWidth() / 2, field.getHeight() / 2 + Math.min(field.getHeight() / 4, field.getWidth() / 4), paint);
+ }
+
+ /**
+ * Setzt die spezifizierte Animation für das spezifizierte Feld, sodass beim
+ * Aufruf der markField Methode für dieses Feld die übergebene Animation auf
+ * diesem gezeichnet wird. Ist eines der beiden Argumente null, so wird
+ * nichts getan.
+ *
+ * @param field
+ * Das Field für das Animation eingetragen werden soll
+ * @param marking
+ * Die Animation die eingetragen werden soll
+ */
+ public void setMarking(View field, FieldViewStates marking) {
+ this.markings.put(field, marking);
+ }
+
+ /**
+ * Löscht alle hinzugefügten Markierungen auf Default.
+ */
+ public void flushMarkings() {
+ this.markings.clear();
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/FieldViewStates.java b/sudoq-app/src/de/sudoq/controller/sudoku/FieldViewStates.java
new file mode 100644
index 00000000..cbb79109
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/FieldViewStates.java
@@ -0,0 +1,96 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+/**
+ * Dieses Enum definiert Konstanten für Animationen bzw. Markierungen für
+ * Felder.
+ */
+public enum FieldViewStates {
+ /** Animation */
+
+ /**
+ * Animation für ein zur Eingabe selektiertes Feld
+ */
+ SELECTED_INPUT,
+
+ /**
+ * Animation für ein für Notizen selektiertes Feld
+ */
+ SELECTED_NOTE,
+
+ /**
+ * Zur Eingabe selektiertes Feld mit Rahmen
+ */
+ SELECTED_INPUT_BORDER,
+
+ /**
+ * Für Notizen selektiertes Feld mit Rahmen
+ */
+ SELECTED_NOTE_BORDER,
+
+ /**
+ * Zur Eingabe selektiertes Feld mit falschem Inhalt
+ */
+ SELECTED_INPUT_WRONG,
+
+ /**
+ * Für Notizen selektiertes Feld mit falschem Inhalt
+ */
+ SELECTED_NOTE_WRONG,
+
+ /**
+ * Animation für ein ausgewähltes, nicht editierbares Feld
+ */
+ SELECTED_FIXED,
+
+ /**
+ * Animation für ein mit dem selektierten verbundenes Feld
+ */
+ CONNECTED,
+
+ /**
+ * Verbundenes Feld mit falschem Eintrag
+ */
+ CONNECTED_WRONG,
+
+ /**
+ * Ein Feld, welches vorgegeben ist
+ */
+ FIXED,
+
+ /**
+ * Zeichnet das Standart-Feld-Aussehen
+ */
+ DEFAULT,
+
+ /**
+ * Zeichnet das Standard Feld Ausstehen mit Rahmen
+ */
+ DEFAULT_BORDER,
+
+ /**
+ * Zeichnet das Standard Feld Aussehen mit falschem Eintrag
+ */
+ DEFAULT_WRONG,
+
+ /**
+ * Zeichnet den Hintergrund für die Controls
+ */
+ CONTROLS,
+
+ /**
+ * Zeichnet den Hintergrund für die Tastatur
+ */
+ KEYBOARD,
+
+ /**
+ * Zeichnet den Hintergrund für das Sudoku
+ */
+ SUDOKU,
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/InputListener.java b/sudoq-app/src/de/sudoq/controller/sudoku/InputListener.java
new file mode 100644
index 00000000..ca25336e
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/InputListener.java
@@ -0,0 +1,23 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+/**
+ * Dieses Interface ermöglicht es Klassen zu reagieren, sobald ein Wert auf der
+ * Tastatur eingegeben wurde.
+ */
+public interface InputListener {
+ /**
+ * Wird aufgerufen, falls etwas eingegeben wird.
+ *
+ * @param symbol
+ * Das eingegebene Symbol
+ */
+ public void onInput(int symbol);
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/ObservableActionCaster.java b/sudoq-app/src/de/sudoq/controller/sudoku/ObservableActionCaster.java
new file mode 100644
index 00000000..4b26a484
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/ObservableActionCaster.java
@@ -0,0 +1,39 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+/**
+ * Interface, welches von Klassen implementiert werden kann, die Actions in
+ * einem Sudoku ausführen.
+ *
+ * @see ActionListener
+ */
+public interface ObservableActionCaster {
+
+ /**
+ * Benachrichtigt die Listener.
+ */
+ void notifyListener();
+
+ /**
+ * Registriert einen Listener. Ist dieser null, so wird nichts getan.
+ *
+ * @param listener
+ * Der Listener der hinzugefügt werden soll.
+ */
+ void registerListener(ActionListener listener);
+
+ /**
+ * Entfernt einen Listener. Ist dieser nicht registriert, so wird nichts
+ * getan.
+ *
+ * @param listener
+ * Der Listener der entfernt werden soll.
+ */
+ void removeListener(ActionListener listener);
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/ObservableFieldInteraction.java b/sudoq-app/src/de/sudoq/controller/sudoku/ObservableFieldInteraction.java
new file mode 100644
index 00000000..dfdb45e2
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/ObservableFieldInteraction.java
@@ -0,0 +1,39 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+/**
+ * Interface, welches von Klassen implementiert werden kann, die auf denen
+ * Feld-Interaktionen ausgeführt werden. einem Sudoku ausführen.
+ *
+ * @see FieldInteractionListener
+ */
+public interface ObservableFieldInteraction {
+
+ /**
+ * Benachrichtigt die Listener.
+ */
+ void notifyListener();
+
+ /**
+ * Registriert einen Listener. Ist dieser null, so wird nichts getan.
+ *
+ * @param listener
+ * Der Listener der hinzugefügt werden soll.
+ */
+ void registerListener(FieldInteractionListener listener);
+
+ /**
+ * Entfernt einen Listener. Ist dieser nicht registriert, so wird nichts
+ * getan.
+ *
+ * @param listener
+ * Der Listener der entfernt werden soll.
+ */
+ void removeListener(FieldInteractionListener listener);
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/ObservableInput.java b/sudoq-app/src/de/sudoq/controller/sudoku/ObservableInput.java
new file mode 100644
index 00000000..7dcedf83
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/ObservableInput.java
@@ -0,0 +1,44 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+/**
+ * Interface, welches von Klassen implementiert werden kann, die auf Eingaben in
+ * einem Sudoku reagieren.
+ *
+ * @see InputListener
+ */
+public interface ObservableInput {
+ /** Methods */
+
+ /**
+ * Beim Aufruf dieser Methode werden alle beobachtenden Objekte
+ * benachrichtigt.
+ */
+ public void notifyListeners();
+
+ /**
+ * Mit dieser Methode kann sich ein Objekt registrieren, um bei allen
+ * zukünfitgen Änderungen benachrichtigt zu werden.
+ *
+ * @param listener
+ * Das einzutragenden Objekt
+ */
+ public void registerListener(InputListener listener);
+
+ /**
+ * Mit diser Methode kann das gegebene Objekt aus der Beobachter-Liste
+ * entfernt werden. Bei zukünfitgen Änderugen wird das Objekt nicht mehr
+ * benachrichtigt. Ist das Objekt nicht in der Liste passiert nichts.
+ *
+ * @param listener
+ * Das zu entfernende Objekt.
+ */
+ public void removeListener(InputListener listener);
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/SudokuActivity.java b/sudoq-app/src/de/sudoq/controller/sudoku/SudokuActivity.java
new file mode 100644
index 00000000..0c2e44c9
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/SudokuActivity.java
@@ -0,0 +1,930 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Set;
+
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.gesture.GestureOverlayView;
+import android.gesture.GestureStore;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.CompressFormat;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Handler;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.View.MeasureSpec;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup.LayoutParams;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+import de.sudoq.R;
+import de.sudoq.controller.SudoqActivity;
+import de.sudoq.model.actionTree.ActionTreeElement;
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.game.Assistances;
+import de.sudoq.model.game.Game;
+import de.sudoq.model.game.GameManager;
+import de.sudoq.model.profile.Profile;
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.view.FullScrollLayout;
+import de.sudoq.view.SudokuFieldView;
+import de.sudoq.view.SudokuLayout;
+import de.sudoq.view.VirtualKeyboardLayout;
+
+/**
+ * Diese Klasse stellt die Activity des Sudokuspiels dar. Die Klasse hält das
+ * Game und mehrere Controller um auf Interaktionen des Benutzers mit dem
+ * Spielfeld zu reagieren. Die Klasse wird außerdem benutzt um zu verwalten,
+ * welche Navigationselemente dem Nutzer angezeigt werden.
+ */
+public class SudokuActivity extends SudoqActivity implements OnClickListener, ActionListener, ActionTreeNavListener {
+
+ /** Attributes */
+
+ /**
+ * Der Log-TAG
+ */
+ private static final String LOG_TAG = SudokuActivity.class.getSimpleName();
+
+ /**
+ * Konstante für das Speichern der Game ID
+ */
+ private static final int SAVE_GAME_ID = 0;
+
+ /**
+ * Konstante für das Speichern der X-Koordinate der ausgewählten FieldView
+ */
+ private static final int SAVE_FIELD_X = 1;
+
+ /**
+ * Konstante für das Speichern der Y-Koordinate der ausgewählten FieldView
+ */
+ private static final int SAVE_FIELD_Y = 2;
+
+ /**
+ * Konstante für das Speichern des Aktionsbaum-Status
+ */
+ private static final int SAVE_ACTION_TREE_SHOWN = 3;
+
+ /**
+ * Konstante für das Speichern der Gesteneingabe
+ */
+ private static final int SAVE_GESTURE_ACTIVE = 4;
+
+ /**
+ * Konstante für das Speichern des aktuellen Zoomfaktors
+ */
+ private static final int SAVE_ZOOM_FACTOR = 5;
+
+ /**
+ * Konstante für das Speichern des Scrollwertes in X-Richtung
+ */
+ private static final int SAVE_SCROLL_X = 6;
+
+ /**
+ * Konstante für das Speichern des Scrollwertes in Y-Richtung
+ */
+ private static final int SAVE_SCROLL_Y = 7;
+
+ /**
+ * Eine Referenz auf einen ActionTreeController, der die Verwaltung der
+ * ActionTree-Anzeige und Benutzerinteraktion übernimmt
+ */
+ private ActionTreeController actionTreeController;
+
+ /**
+ * Eine Referenz auf einen SudokuController, der Nutzereingaben verwaltet
+ * und mit dem Model interagiert
+ */
+ private SudokuController sudokuController;
+
+ /**
+ * Die View des aktuellen Sudokus
+ */
+ private SudokuLayout sudokuView;
+
+ /**
+ * Die ScrollView, welche die SudokuView beinhaltet
+ */
+ private FullScrollLayout sudokuScrollView;
+
+ /**
+ * Das Game, auf welchem gerade gespielt wird
+ */
+ private Game game;
+
+ /**
+ * Fängt Gesteneingaben des Benutzers ab
+ */
+ private GestureOverlayView gestureOverlay;
+
+ /**
+ * Hält die von der Activity unterstützten Gesten
+ */
+ private GestureStore gestureStore = new GestureStore();
+
+ /**
+ * Ein Flag welches aussagt, ob gerade der ActionTree angezeigt wird
+ */
+ private boolean actionTreeShown;
+
+ /**
+ * Die Anzeige der Zeit
+ */
+ private TextView timeView;
+
+ /**
+ * Der Handler für die Zeit
+ */
+ private final Handler timeHandler = new Handler();
+
+ /**
+ * Zeigt an, dass dieses Spiel beendet wurde
+ */
+ private boolean finished;
+
+ /**
+ * Der Vermittler zwischen Sudoku und Eingabemöglichkeiten
+ */
+ private UserInteractionMediator mediator;
+
+ private String[] currentSymbolSet;
+
+ /** Methods */
+
+ /**
+ * Wird beim ersten Aufruf der Activity aufgerufen. Setzt das Layout der
+ * Activity und nimmt Initialisierungen vor.
+ *
+ * @param savedInstanceState
+ * Gespeicherte Daten eines vorigen Aufrufs dieser Activity
+ */
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Log.d(LOG_TAG, "Created");
+ // Load the Game by using current game id
+ if (savedInstanceState != null) {
+ try {
+ this.game = GameManager.getInstance().load(savedInstanceState.getInt(SAVE_GAME_ID + ""));
+ } catch (Exception e) {
+ this.finish();
+ }
+ } else {
+ this.game = GameManager.getInstance().load(Profile.getInstance().getCurrentGame());
+ }
+
+ if (game != null) {
+ switch (this.game.getSudoku().getSudokuType().getNumberOfSymbols()) {
+ case 4:
+ Symbol.createSymbol(Symbol.MAPPING_NUMBERS_FOUR);
+ currentSymbolSet = Symbol.MAPPING_NUMBERS_FOUR;
+ break;
+
+ case 6:
+ Symbol.createSymbol(Symbol.MAPPING_NUMBERS_SIX);
+ currentSymbolSet = Symbol.MAPPING_NUMBERS_SIX;
+ break;
+
+ case 9:
+ Symbol.createSymbol(Symbol.MAPPING_NUMBERS_NINE);
+ currentSymbolSet = Symbol.MAPPING_NUMBERS_NINE;
+ break;
+
+ case 16:
+ Symbol.createSymbol(Symbol.MAPPING_NUMBERS_HEX_LETTERS);
+ currentSymbolSet = Symbol.MAPPING_NUMBERS_HEX_LETTERS;
+ break;
+
+ default:
+ Symbol.createSymbol(Symbol.MAPPING_NUMBERS_HEX_LETTERS);
+ currentSymbolSet = Symbol.MAPPING_NUMBERS_HEX_LETTERS;
+ break;
+ }
+ setContentView(R.layout.sudoku);
+ this.sudokuController = new SudokuController(this.game, this);
+ this.actionTreeController = new ActionTreeController(this);
+ Log.d(LOG_TAG, "Initialized");
+ inflateViewAndButtons();
+ Log.d(LOG_TAG, "Inflated view and buttons");
+ inflateGestures(savedInstanceState == null);
+ Log.d(LOG_TAG, "Inflated gestures");
+ // Scale SudokuView to LayoutSize, when inflating view is finished
+ final Bundle save = savedInstanceState;
+ ViewTreeObserver vto = sudokuView.getViewTreeObserver();
+ vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
+ public void onGlobalLayout() {
+ Log.d(LOG_TAG, "SudokuView height: " + sudokuView.getMeasuredHeight());
+ Log.d(LOG_TAG, "SudokuScrollView height: " + sudokuScrollView.getMeasuredHeight());
+ sudokuView.optiZoom(sudokuScrollView.getMeasuredWidth(), sudokuScrollView.getMeasuredHeight());
+ ViewTreeObserver obs = sudokuView.getViewTreeObserver();
+ if (save != null) {
+ float zoomFactor = save.getFloat(SAVE_ZOOM_FACTOR + "");
+ if (zoomFactor != 0.0f) {
+ sudokuView.setZoomFactor(zoomFactor);
+ sudokuScrollView.setZoomFactor(zoomFactor);
+ }
+ float scrollX = save.getFloat(SAVE_SCROLL_X + "") + sudokuView.getCurrentLeftMargin();
+ float scrollY = save.getFloat(SAVE_SCROLL_Y + "") + sudokuView.getCurrentTopMargin();
+ sudokuScrollView.scrollTo((int) scrollX, (int) scrollY);
+ }
+ obs.removeGlobalOnLayoutListener(this);
+ }
+ });
+ VirtualKeyboardLayout keyboardView = (VirtualKeyboardLayout) findViewById(R.id.virtual_keyboard);
+ this.mediator = new UserInteractionMediator(keyboardView, this.sudokuView, this.game, this.gestureOverlay, this.gestureStore);
+ this.mediator.registerListener(this.sudokuController);
+ this.mediator.registerListener(this);
+ if (this.game.isFinished()) {
+ setFinished(false, false);
+ }
+
+ setTypeText();
+ updateButtons();
+ Buttons.gestureButton.setSelected(Profile.getInstance().isGestureActive());
+ }
+ }
+
+ /**
+ * Speichert das markierte Feld und die Status des Aktionsbaumes, um bei
+ * Wiederherstellung der Activity nach einem Orientierungswechsel oder
+ * aufgrund einer temporären Verdrängung durch Speicherknappheit den alten
+ * Status wiederherzustellen.
+ *
+ * @param outState
+ * Der Status in den gespeichert wird
+ */
+ @Override
+ public void onSaveInstanceState(Bundle outState) {
+ outState.putFloat(SAVE_ZOOM_FACTOR + "", this.sudokuScrollView.getZoomFactor());
+ outState.putFloat(SAVE_SCROLL_X + "", this.sudokuScrollView.getScrollValueX() - this.sudokuView.getCurrentLeftMargin());
+ outState.putFloat(SAVE_SCROLL_Y + "", this.sudokuScrollView.getScrollValueY() - this.sudokuView.getCurrentTopMargin());
+ outState.putBoolean(SAVE_ACTION_TREE_SHOWN + "", this.actionTreeShown);
+ outState.putInt(SAVE_GAME_ID + "", game.getId());
+ outState.putBoolean(SAVE_GESTURE_ACTIVE + "", this.gestureOverlay != null && this.gestureOverlay.getVisibility() == View.VISIBLE);
+ if (this.sudokuView.getCurrentFieldView() != null) {
+ outState.putInt(SAVE_FIELD_X + "", game.getSudoku().getPosition(this.sudokuView.getCurrentFieldView().getField().getId()).getX());
+ outState.putInt(SAVE_FIELD_Y + "", game.getSudoku().getPosition(this.sudokuView.getCurrentFieldView().getField().getId()).getY());
+ } else {
+ outState.putInt(SAVE_FIELD_X + "", -1);
+ }
+ Log.d(LOG_TAG, "Saved state");
+ }
+
+ /**
+ * Stellt den Status der Activity wieder her, also insbesondere das
+ * markierte Feld und den Status der Aktionsbaumes.
+ *
+ * @param state
+ * Der wiederherzustellende Status
+ */
+ @Override
+ public void onRestoreInstanceState(Bundle state) {
+
+ if (state.getBoolean(SAVE_ACTION_TREE_SHOWN + "")) {
+ toogleActionTree();
+ }
+ if (state.getInt(SAVE_FIELD_X + "") != -1) {
+ this.sudokuView.getSudokuFieldViews()[state.getInt(SAVE_FIELD_X + "")][state.getInt(SAVE_FIELD_Y + "")].onTouchEvent(null);
+ }
+
+ if (state.getBoolean(SAVE_GESTURE_ACTIVE + "")) {
+ this.mediator.onFieldSelected(this.sudokuView.getCurrentFieldView());
+ }
+
+ Log.d(LOG_TAG, "Restored state");
+ }
+
+ /**
+ * Setzt den Text für Typ und Schwierigkeit des aktuellen Sudokus.
+ */
+ private void setTypeText() {
+ TextView type = (TextView) findViewById(R.id.sudoku_type);
+
+ switch (this.game.getSudoku().getSudokuType().getEnumType()) {
+ case HyperSudoku:
+ type.append(getString(R.string.sudoku_type_hyper));
+ break;
+ case samurai:
+ type.append(getString(R.string.sudoku_type_samurai));
+ break;
+ case squigglya:
+ type.append(getString(R.string.sudoku_type_squiggly_a_9x9));
+ break;
+ case squigglyb:
+ type.append(getString(R.string.sudoku_type_squiggly_b_9x9));
+ break;
+ case stairstep:
+ type.append(getString(R.string.sudoku_type_stairstep_9x9));
+ break;
+ case standard16x16:
+ type.append(getString(R.string.sudoku_type_standard_16x16));
+ break;
+ case standard4x4:
+ type.append(getString(R.string.sudoku_type_standard_4x4));
+ break;
+ case standard6x6:
+ type.append(getString(R.string.sudoku_type_standard_6x6));
+ break;
+ case standard9x9:
+ type.append(getString(R.string.sudoku_type_standard_9x9));
+ break;
+ case Xsudoku:
+ type.append(getString(R.string.sudoku_type_xsudoku));
+ break;
+ }
+
+ type.append(", ");
+
+ switch (this.game.getSudoku().getComplexity()) {
+ case difficult:
+ type.append(getString(R.string.complexity_difficult));
+ break;
+ case easy:
+ type.append(getString(R.string.complexity_easy));
+ break;
+ case infernal:
+ type.append(getString(R.string.complexity_infernal));
+ break;
+ case medium:
+ type.append(getString(R.string.complexity_medium));
+ break;
+ }
+ }
+
+ /**
+ * Erzeugt die View für die Gesteneingabe
+ *
+ * @param firstStart
+ * Gibt an, ob dies der erste Start der Activity ist und somit
+ * Hinweise angezeigt werden sollen
+ */
+ private void inflateGestures(boolean firstStart) {
+ File gestureFile = FileManager.getCurrentGestureFile();
+ try {
+ FileInputStream fis = new FileInputStream(gestureFile);
+ this.gestureStore.load(fis);
+ fis.close();
+ } catch (FileNotFoundException e) {
+ try {
+ OutputStream os = new FileOutputStream(gestureFile);
+ this.gestureStore.save(os);
+ } catch (IOException ioe) {
+ Log.w(LOG_TAG, "Gesture file cannot be loaded!");
+ }
+ } catch (IOException e) {
+ Profile.getInstance().setGestureActive(false);
+ Toast.makeText(this, R.string.error_gestures_no_library, Toast.LENGTH_SHORT).show();
+ }
+
+ if (firstStart && Profile.getInstance().isGestureActive()) {
+ boolean allGesturesSet = checkGesture();
+ if (!allGesturesSet) {
+ Profile.getInstance().setGestureActive(false);
+ Toast.makeText(this, getString(R.string.error_gestures_not_complete), Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ this.gestureOverlay = new GestureOverlayView(this);
+ LayoutParams gestureLayoutParams = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
+ this.gestureOverlay.setLayoutParams(gestureLayoutParams);
+ this.gestureOverlay.setBackgroundColor(Color.BLACK);
+ this.gestureOverlay.getBackground().setAlpha(127);
+ this.gestureOverlay.setVisibility(View.INVISIBLE);
+
+ FrameLayout frameLayout = (FrameLayout) findViewById(R.id.sudoku_frame_layout);
+ frameLayout.addView(this.gestureOverlay);
+ }
+
+ /**
+ * Erstellt die Views und Buttons für diese Activity
+ */
+ private void inflateViewAndButtons() {
+ this.timeView = (TextView) findViewById(R.id.sudoku_time);
+ this.timeView.setText(getTimeString());
+
+ this.sudokuScrollView = (FullScrollLayout) findViewById(R.id.sudoku_field);
+ this.sudokuView = new SudokuLayout(this);
+ Log.d(LOG_TAG, "Inflated sudoku layout");
+ this.sudokuView.setGravity(Gravity.CENTER);
+ this.sudokuScrollView.addView(this.sudokuView);
+
+ Buttons.redoButton = (ImageButton) findViewById(R.id.button_sudoku_redo);
+ Buttons.undoButton = (ImageButton) findViewById(R.id.button_sudoku_undo);
+ Buttons.actionTreeButton = (ImageButton) findViewById(R.id.button_sudoku_actionTree);
+ Buttons.gestureButton = (ImageButton) findViewById(R.id.button_sudoku_toggle_gesture);
+ Buttons.assistancesButton = (ImageButton) findViewById(R.id.button_sudoku_help);
+ Buttons.bookmarkButton = (Button) findViewById(R.id.sudoku_action_tree_button_bookmark);
+ Buttons.closeButton = (Button) findViewById(R.id.sudoku_action_tree_button_close);
+
+ LinearLayout currentControlsView = (LinearLayout) findViewById(R.id.sudoku_time_border);
+ FieldViewPainter.getInstance().setMarking(currentControlsView, FieldViewStates.CONTROLS);
+ currentControlsView = (LinearLayout) findViewById(R.id.sudoku_border);
+ FieldViewPainter.getInstance().setMarking(currentControlsView, FieldViewStates.SUDOKU);
+ currentControlsView = (LinearLayout) findViewById(R.id.controls);
+ FieldViewPainter.getInstance().setMarking(currentControlsView, FieldViewStates.KEYBOARD);
+ VirtualKeyboardLayout keyboardView = (VirtualKeyboardLayout) findViewById(R.id.virtual_keyboard);
+ FieldViewPainter.getInstance().setMarking(keyboardView, FieldViewStates.KEYBOARD);
+ keyboardView.refresh(this.game.getSudoku().getSudokuType().getNumberOfSymbols());
+ }
+
+ /**
+ * Reagiert auf TouchEvents des Benutzers.
+ *
+ * @param event
+ * Das Touch Event
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ this.sudokuScrollView.performZoomEvent(event);
+ if (this.sudokuScrollView.isZoomPerformed()) {
+ this.sudokuView.setZoomFactor(this.sudokuScrollView.getZoomFactor());
+ // this.sudokuScrollView.scrollCorrect();
+ // sudokuScrollView.scrollView(event);
+ }
+
+ return true;
+ }
+
+ /**
+ * Schaltet den ActionTree an bzw. aus.
+ */
+ public void toogleActionTree() {
+ if (actionTreeShown) {
+ this.actionTreeController.setVisibility(false);
+ actionTreeShown = false;
+ } else {
+ this.actionTreeController.setVisibility(true);
+ actionTreeShown = true;
+ }
+ updateButtons();
+ }
+
+ /**
+ * Behandelt die Klicks auf Buttons dieser Activity
+ */
+ public void onClick(View v) {
+ if (v == Buttons.undoButton) {
+ this.sudokuController.onUndo();
+ this.mediator.updateKeyboard();
+ } else if (v == Buttons.redoButton) {
+ this.sudokuController.onRedo();
+ this.mediator.updateKeyboard();
+ } else if (v == Buttons.actionTreeButton) {
+ toogleActionTree();
+ } else if (v == Buttons.gestureButton) {
+ if (checkGesture()) {
+ Profile.getInstance().setGestureActive(!Profile.getInstance().isGestureActive());
+ v.setSelected(Profile.getInstance().isGestureActive());
+ } else {
+ Profile.getInstance().setGestureActive(false);
+ v.setSelected(false);
+ Toast.makeText(this, getString(R.string.error_gestures_not_complete), Toast.LENGTH_LONG).show();
+ }
+ } else if (v == Buttons.assistancesButton) {
+ showAssistancesDialog();
+ } else if (v == Buttons.bookmarkButton) {
+ this.game.markCurrentState();
+ this.actionTreeController.refresh();
+ } else if (v == Buttons.closeButton) {
+ toogleActionTree();
+ } else if (v == Buttons.switchSymbols) {
+ if (currentSymbolSet.length < 9) {
+ if (currentSymbolSet[10].equals("10")) {
+ currentSymbolSet = Symbol.MAPPING_NUMBERS_HEX_LETTERS;
+ } else {
+ currentSymbolSet = Symbol.MAPPING_NUMBERS_HEX_DIGGITS;
+ }
+ Symbol.createSymbol(currentSymbolSet);
+ } else {
+ Toast.makeText(this, getString(R.string.error_cant_switch_symbols), Toast.LENGTH_SHORT).show();
+ }
+ }
+ updateButtons();
+ }
+
+ private boolean checkGesture() {
+ Set gestures = this.gestureStore.getGestureEntries();
+ boolean allGesturesSet = true;
+ for (int i = 0; i < Symbol.getInstance().getNumberOfSymbols(); i++) {
+ if (!gestures.contains(Symbol.getInstance().getMapping(i))) {
+ allGesturesSet = false;
+ }
+ }
+ return allGesturesSet;
+ }
+
+ /**
+ * Wird aufgerufen, falls die Activity in den Vordergrund der App gelangt.
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (!this.finished)
+ timeHandler.postDelayed(timeUpdate, 1000);
+ }
+
+ /**
+ * Wird aufgerufen, falls eine andere Activity in den Vordergrund der App
+ * gelangt.
+ */
+ @Override
+ public void onPause() {
+ this.timeHandler.removeCallbacks(timeUpdate);
+ GameManager.getInstance().save(this.game);
+
+ float prevZoomFactor = this.sudokuScrollView.getZoomFactor();
+ sudokuView.setDrawingCacheEnabled(true);
+ sudokuScrollView.resetZoom();
+ sudokuView.setZoomFactor(1.0f);
+ // Restoring measurements after zomming out.
+ this.sudokuView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
+ this.sudokuView.layout(0, 0, this.sudokuView.getMeasuredWidth(), this.sudokuView.getMeasuredHeight());
+ this.sudokuView.buildDrawingCache(true);
+ Bitmap sudokuCapture = sudokuView.getDrawingCache();
+ try {
+ if (sudokuCapture != null) {
+ sudokuCapture.compress(CompressFormat.PNG, 100, new FileOutputStream(FileManager.getGameThumbnailFile(Profile.getInstance().getCurrentGame())));
+ } else {
+ Log.d(LOG_TAG, getString(R.string.error_thumbnail_get));
+ }
+ } catch (FileNotFoundException e) {
+ Log.w(LOG_TAG, getString(R.string.error_thumbnail_saved));
+ }
+
+ this.sudokuScrollView.setZoomFactor(prevZoomFactor);
+
+ if (finished) {
+ Profile.getInstance().setCurrentGame(Profile.NO_GAME);
+ Profile.getInstance().saveChanges();
+ }
+ super.onPause();
+ }
+
+ /**
+ * Wird aufgerufen, falls die "Zurück"-Taste gedrückt wird.
+ */
+ @Override
+ public void onBackPressed() {
+ if (this.actionTreeShown) {
+ toogleActionTree();
+ } else if (this.gestureOverlay.getVisibility() == GestureOverlayView.VISIBLE) {
+ this.gestureOverlay.setVisibility(GestureOverlayView.INVISIBLE);
+ } else {
+ super.onBackPressed();
+ }
+ }
+
+ /**
+ * Wird aufgerufen, falls die Activity terminiert.
+ */
+ @Override
+ public void finish() {
+ if (this.game != null) {
+ GameManager.getInstance().save(this.game);
+ }
+ super.finish();
+ overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
+ }
+
+ /**
+ * Zeigt einen Dialog mit den verfügbaren Hilfestellungen an.
+ */
+ private void showAssistancesDialog() {
+ CharSequence[] temp_items = null;
+ if (this.sudokuView.getCurrentFieldView() != null
+ && this.sudokuView.getCurrentFieldView().getField().isEmpty()) {
+ temp_items = new CharSequence[] { getString(R.string.sf_sudoku_assistances_solve_surrender),
+ getString(R.string.sf_sudoku_assistances_back_to_valid_state),
+ getString(R.string.sf_sudoku_assistances_check),
+ getString(R.string.sf_sudoku_assistances_solve_random),
+ getString(R.string.sf_sudoku_assistances_solve_specific) };
+ } else {
+ temp_items = new CharSequence[] { getString(R.string.sf_sudoku_assistances_solve_surrender),
+ getString(R.string.sf_sudoku_assistances_back_to_valid_state),
+ getString(R.string.sf_sudoku_assistances_check),
+ getString(R.string.sf_sudoku_assistances_solve_random) };
+ }
+ final CharSequence[] items = temp_items;
+
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(getString(R.string.sf_sudoku_assistances_title));
+
+ builder.setItems(items, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int item) {
+ switch (item) {
+ case 0:
+ if (!SudokuActivity.this.sudokuController.onSolveAll()) {
+ Toast.makeText(SudokuActivity.this, R.string.toast_solved_wrong, Toast.LENGTH_SHORT).show();
+ }
+ break;
+ case 1:
+ SudokuActivity.this.game.goToLastCorrectState();
+ updateButtons();
+ break;
+ case 2:
+ if (SudokuActivity.this.game.checkSudoku()) {
+ Toast.makeText(SudokuActivity.this, R.string.toast_solved_correct, Toast.LENGTH_SHORT).show();
+ } else {
+ Toast.makeText(SudokuActivity.this, R.string.toast_solved_wrong, Toast.LENGTH_LONG).show();
+ }
+ break;
+ case 3:
+ if (!SudokuActivity.this.sudokuController.onSolveOne()) {
+ Toast.makeText(SudokuActivity.this, R.string.toast_solved_wrong, Toast.LENGTH_SHORT).show();
+ }
+ break;
+ case 4:
+ if (SudokuActivity.this.sudokuView.getCurrentFieldView() != null
+ && !SudokuActivity.this.sudokuController.onSolveCurrent(SudokuActivity.this.sudokuView.getCurrentFieldView().getField())) {
+ Toast.makeText(SudokuActivity.this, R.string.toast_solved_wrong, Toast.LENGTH_SHORT).show();
+ }
+ break;
+ }
+ updateButtons();
+ }
+ });
+ AlertDialog alert = builder.create();
+ alert.show();
+ }
+
+ /**
+ * Gibt das aktuelle Game zurück.
+ *
+ * @return Das Game
+ */
+ public Game getGame() {
+ return this.game;
+ }
+
+ /**
+ * Gibt die aktuell ausgewählte FieldView zurück.
+ *
+ * @return Die aktuell ausgewählte FieldView
+ */
+ public SudokuFieldView getCurrentFieldView() {
+ return this.sudokuView.getCurrentFieldView();
+ }
+
+ /**
+ * Setzt die aktuelle FieldView auf die spezifizierte.
+ *
+ * @param fieldView
+ * Die als aktuell zu setzende FieldView
+ */
+ public void setCurrentFieldView(SudokuFieldView fieldView) {
+ this.sudokuView.setCurrentFieldView(fieldView);
+ }
+
+ /**
+ * Gibt zurück, ob zurzeit der ActionTree angezeigt wird.
+ *
+ * @return true, falls der ActionTree gerade angezeigt wird, false falls
+ * nicht
+ */
+ public boolean isActionTreeShown() {
+ return this.actionTreeShown;
+ }
+
+ /**
+ * Setzt dieses Spiel auf beendet.
+ *
+ * @param showWinDialog
+ * Spezifiziert, ob ein Gewinn-Dialog angezeigt werden soll
+ * @param surrendered
+ * Gibt an, ob der Spieler aufgegeben hat
+ */
+ protected void setFinished(boolean showWinDialog, boolean surrendered) {
+ this.finished = true;
+
+ this.updateButtons();
+ if (this.sudokuView.getCurrentFieldView() != null)
+ this.sudokuView.getCurrentFieldView().select(this.game.isAssistanceAvailable(Assistances.markRowColumn));
+
+ VirtualKeyboardLayout keyView = (VirtualKeyboardLayout) findViewById(R.id.virtual_keyboard);
+ for (int i = 0; i < keyView.getChildCount(); i++) {
+ keyView.getChildAt(i).setLayoutParams(new VirtualKeyboardLayout.LayoutParams(1, 1));
+ }
+ keyView.setPadding(10, 10, 10, 10);
+ TextView text = new TextView(this);
+ text.setText(getStatisticsString());
+ text.setGravity(Gravity.CENTER);
+ keyView.addView(text);
+
+ if (showWinDialog)
+ showWinDialog(surrendered);
+ this.timeHandler.removeCallbacks(timeUpdate);
+ }
+
+ /**
+ * Gibt die vergangene Zeit als formatierten String zurück.
+ *
+ * @return Den String für die Zeitanzeige
+ */
+ protected String getTimeString() {
+ Date time = new Date();
+ time.setMinutes(game.getTime() / 60);
+ time.setSeconds(game.getTime() % 60);
+ String res = new SimpleDateFormat("mm:ss").format(time);
+ return res;
+ }
+
+ /**
+ * Zeigt einen Gewinndialog an, der fragt, ob das Spiel beendet werden soll.
+ *
+ * @param surrendered
+ * Gibt an, ob der Spieler aufgegeben hat
+ */
+ private void showWinDialog(boolean surrendered) {
+ AlertDialog deleteAlert = new AlertDialog.Builder(this).create();
+ if (surrendered) {
+ deleteAlert.setTitle(getString(R.string.dialog_surrender_title));
+ } else {
+ deleteAlert.setTitle(getString(R.string.dialog_won_title));
+ }
+ deleteAlert.setMessage(getString(R.string.dialog_won_text) + "\n\n" + getStatisticsString());
+ deleteAlert.setButton(getString(R.string.dialog_yes), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ finish();
+ }
+ });
+ deleteAlert.setButton2(getString(R.string.dialog_no), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ // Dummy: clicking no means staying in the game
+ }
+ });
+ deleteAlert.show();
+ }
+
+ /**
+ * Gibt einen String mit der Spielstatistik zurück.
+ *
+ * @return Die Spielstatistik als String
+ */
+ private String getStatisticsString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getString(R.string.dialog_won_statistics) + ":\n\n");
+ sb.append(getString(R.string.dialog_won_timeneeded) + ": " + getTimeString() + "\n");
+ sb.append(getString(R.string.dialog_won_score) + ": " + game.getScore());
+ return sb.toString();
+ }
+
+ /**
+ * Das Update-Runnable für die Zeit
+ */
+ private Runnable timeUpdate = new Runnable() {
+ public void run() {
+ game.addTime(1);
+ timeView.setText(getTimeString());
+ timeHandler.postDelayed(this, 1000);
+ }
+ };
+
+ /**
+ * Container-Klasse für die Buttons dieser Activity
+ */
+ private static class Buttons {
+ /**
+ * Der "Redo" Button
+ */
+ protected static ImageButton redoButton;
+
+ /**
+ * Der "Undo" Button
+ */
+ protected static ImageButton undoButton;
+
+ /**
+ * Der "ActionTree anzeigen" Button
+ */
+ protected static ImageButton actionTreeButton;
+
+ /**
+ * Der "Gesten umschalten" Button
+ */
+ protected static ImageButton gestureButton;
+
+ /**
+ * Der "Hilfestellungen anzeigen" Button
+ */
+ protected static ImageButton assistancesButton;
+
+ /**
+ * Der "Lesezeichen" Button des ActionTrees
+ */
+ protected static Button bookmarkButton;
+
+ /**
+ * Der "Schließen" Button des ActionTrees
+ */
+ protected static Button closeButton;
+
+ /**
+ * Der Button zum wechseln der Symbolsätze (HEX)
+ */
+ protected static Button switchSymbols;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onHoverTreeElement(ActionTreeElement ate) {
+ updateButtons();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onLoadState(ActionTreeElement ate) {
+ updateButtons();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onRedo() {
+ updateButtons();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onUndo() {
+ updateButtons();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onNoteAdd(Field field, int value) {
+ updateButtons();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onNoteDelete(Field field, int value) {
+ updateButtons();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onAddEntry(Field field, int value) {
+ updateButtons();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onDeleteEntry(Field field) {
+ updateButtons();
+ }
+
+ /**
+ * Aktualisiert alle Buttons, also den Redo, Undo und ActionTree-Button,
+ * sowie die Tastatur
+ */
+ private void updateButtons() {
+ Buttons.redoButton.setEnabled(game.getStateHandler().canRedo() && !actionTreeShown);
+ Buttons.undoButton.setEnabled(game.getStateHandler().canUndo() && !actionTreeShown);
+ Buttons.actionTreeButton.setEnabled(!actionTreeShown);
+ Buttons.assistancesButton.setEnabled(!actionTreeShown && !finished);
+ Buttons.gestureButton.setEnabled(!actionTreeShown);
+ this.mediator.setKeyboardState(!finished && this.sudokuView.getCurrentFieldView() != null);
+ }
+
+ /**
+ * JUST FOR TESTING PURPOSE!
+ *
+ * @return Das SudokuLayout des aktuellen Spiels
+ */
+ public SudokuLayout getSudokuLayout() {
+ return sudokuView;
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/SudokuController.java b/sudoq-app/src/de/sudoq/controller/sudoku/SudokuController.java
new file mode 100644
index 00000000..9247c7cb
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/SudokuController.java
@@ -0,0 +1,184 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import de.sudoq.model.actionTree.NoteActionFactory;
+import de.sudoq.model.actionTree.SolveActionFactory;
+import de.sudoq.model.game.Game;
+import de.sudoq.model.profile.Profile;
+import de.sudoq.model.profile.Statistics;
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Der SudokuController ist dafür zuständig auf Aktionen des Benutzers mit dem
+ * Spielfeld zu reagieren.
+ */
+public class SudokuController implements AssistanceRequestListener, ActionListener {
+ /** Attributes */
+
+ /**
+ * Hält eine Referenz auf das Game, welches Daten über das aktuelle Spiel
+ * enthält
+ */
+ private Game game;
+
+ /**
+ * Die SudokuActivity.
+ */
+ private SudokuActivity context;
+
+ /** Constructors */
+
+ /**
+ * Erstellt einen neuen SudokuController. Wirft eine
+ * IllegalArgumentException, falls null übergeben wird.
+ *
+ * @param game
+ * Game, auf welchem der SudokuController arbeitet
+ * @param context
+ * der Applikationskontext
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls null übergeben wird
+ */
+ public SudokuController(Game game, SudokuActivity context) {
+ if (game == null || context == null) {
+ throw new IllegalArgumentException("Unvalid param!");
+ }
+ this.game = game;
+ this.context = context;
+ }
+
+ /** Methods */
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onRedo() {
+ game.redo();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onUndo() {
+ game.undo();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onNoteAdd(Field field, int value) {
+ game.addAndExecute(new NoteActionFactory().createAction(value, field));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onNoteDelete(Field field, int value) {
+ game.addAndExecute(new NoteActionFactory().createAction(value, field));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onAddEntry(Field field, int value) {
+ game.addAndExecute(new SolveActionFactory().createAction(value, field));
+ if (this.game.isFinished()) {
+ updateStatistics();
+ handleFinish(false);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void onDeleteEntry(Field field) {
+ game.addAndExecute(new SolveActionFactory().createAction(Field.EMPTYVAL, field));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean onSolveOne() {
+ boolean res = this.game.solveField();
+ if (this.game.isFinished()) {
+ updateStatistics();
+ handleFinish(false);
+ }
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean onSolveCurrent(Field field) {
+ boolean res = this.game.solveField(field);
+ if (this.game.isFinished()) {
+ updateStatistics();
+ handleFinish(false);
+ }
+ return res;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean onSolveAll() {
+ boolean res = false;
+
+ for (Field f : this.game.getSudoku()) {
+ if (!f.isNotWrong()) {
+ this.game.addAndExecute(new SolveActionFactory().createAction(Field.EMPTYVAL, f));
+ }
+ }
+
+ res = game.solveAll();
+
+ if (res)
+ handleFinish(true);
+ return res;
+ }
+
+ /**
+ * Zeigt einen Gewinndialog an, der fragt, ob das Spiel beendet werden soll.
+ *
+ * @param surrendered
+ * TODO
+ */
+ private void handleFinish(boolean surrendered) {
+ context.setFinished(true, surrendered);
+ }
+
+ /**
+ * Updatet die Spielerstatistik des aktuellen Profils in der App.
+ */
+ private void updateStatistics() {
+ switch (game.getSudoku().getComplexity()) {
+ case infernal:
+ Profile.getInstance().setStatistic(Statistics.playedInfernalSudokus, Profile.getInstance().getStatistic(Statistics.playedInfernalSudokus) + 1);
+ break;
+ case difficult:
+ Profile.getInstance().setStatistic(Statistics.playedDifficultSudokus, Profile.getInstance().getStatistic(Statistics.playedDifficultSudokus) + 1);
+ break;
+ case medium:
+ Profile.getInstance().setStatistic(Statistics.playedMediumSudokus, Profile.getInstance().getStatistic(Statistics.playedMediumSudokus) + 1);
+ break;
+ case easy:
+ Profile.getInstance().setStatistic(Statistics.playedEasySudokus, Profile.getInstance().getStatistic(Statistics.playedEasySudokus) + 1);
+ break;
+ }
+ Profile.getInstance().setStatistic(Statistics.playedSudokus, Profile.getInstance().getStatistic(Statistics.playedSudokus) + 1);
+ if (Profile.getInstance().getStatistic(Statistics.fastestSolvingTime) > game.getTime()) {
+ Profile.getInstance().setStatistic(Statistics.fastestSolvingTime, game.getTime());
+ }
+ if (Profile.getInstance().getStatistic(Statistics.maximumPoints) < game.getScore()) {
+ Profile.getInstance().setStatistic(Statistics.maximumPoints, game.getScore());
+ }
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/Symbol.java b/sudoq-app/src/de/sudoq/controller/sudoku/Symbol.java
new file mode 100644
index 00000000..d7edd6f2
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/Symbol.java
@@ -0,0 +1,133 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+/**
+ * Klasse zum Mapping der intern genutzen Zahlen auf darstellbare Zeichen
+ */
+public class Symbol {
+ /**
+ * Die Standardsymbole für 1-4 Sudokus
+ */
+ public static final String[] MAPPING_NUMBERS_FOUR = new String[] { "1", "2", "3", "4" };
+
+ /**
+ * Die Standardsymbole für 1-4 Sudokus
+ */
+ public static final String[] MAPPING_NUMBERS_SIX = new String[] { "1", "2", "3", "4", "5", "6" };
+
+ /**
+ * Die Standardsymbole für 1-9 Sudokus
+ */
+ public static final String[] MAPPING_NUMBERS_NINE = new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+
+ /**
+ * Die Standardsymbole für 1-16 Sudokus
+ */
+ public static final String[] MAPPING_NUMBERS_HEX_LETTERS = new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G" };
+ public static final String[] MAPPING_NUMBERS_HEX_DIGGITS = new String[] { "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16" };
+
+ /**
+ * Die statische Instanz dieses Singletons.
+ */
+ private static Symbol instance;
+
+ /**
+ * Der aktuell verwendete Satz von Symbolen.
+ */
+ protected String[] symbolSet;
+
+ /**
+ * Setzt ein neues Mapping für die Symbole
+ *
+ * @param mapping
+ * Das zu setzende Mapping
+ */
+ private Symbol(String[] mapping) {
+ this.symbolSet = mapping;
+ }
+
+ /**
+ * Gibt die Instanz des Symbols zurück.
+ *
+ * @return Die Instanz des Symbols.
+ * @throws IllegalArgumentException
+ * wenn das Symbol noch nicht initialisiert wurde.
+ */
+ public static Symbol getInstance() {
+ if (instance != null) {
+ return instance;
+ } else {
+ throw new IllegalStateException("Symbol not instanciated!");
+ }
+ }
+
+ /**
+ * Erstellt eine neue Instanz des Symbols und setzt den zu verwendenden
+ * Symbolsatz.
+ *
+ * @param mapping
+ * Den Symbolsatz, der verwendet werden soll. Einige sind als
+ * statische Felder im Symbol verfügbar.
+ */
+ public static void createSymbol(String[] mapping) {
+ instance = new Symbol(mapping);
+ }
+
+ /**
+ * Diese Methode gibt das gemappte Symbol zurueck, dass von der View
+ * gezeichnet wird.
+ *
+ * @param abstractSymbol
+ * die interne id/Repräsentation des Symbols
+ * @return Das zu zeichnende Symbol.
+ */
+ public String getMapping(int abstractSymbol) {
+ return (abstractSymbol != -1 && abstractSymbol < this.symbolSet.length) ? this.symbolSet[abstractSymbol] : " ";
+ }
+
+ /**
+ * Gibt die Representation eines gegebenen Symbols als Ganzahl zurueck.
+ *
+ * @param symbol
+ * Das Symbol als String.
+ * @return Die Ganzahlrepresentation des gegebenen Symbols.
+ */
+ public int getAbstract(String symbol) {
+ int match = -1;
+ for (int i = 0; i < this.symbolSet.length; i++) {
+ if (String.valueOf(this.symbolSet[i]).equals(symbol)) {
+ match = i;
+ }
+ }
+ return match;
+ }
+
+ /**
+ * Gibt die Anzahl der Symbole in diesem Mapping zurueck.
+ *
+ * @return die Anzahl der Symbole.
+ */
+ public int getNumberOfSymbols() {
+ return symbolSet.length;
+ }
+
+ /**
+ * Gibt die Größe eines Feldes des Rasters für die Notizen innerhalb eines
+ * Feldes zurück.
+ *
+ * @return Die Feldgröße des Notizrasters.
+ */
+ public int getRasterSize() {
+ if (this.symbolSet != null) {
+ return (int) Math.ceil(Math.sqrt(this.symbolSet.length));
+ } else {
+ throw new IllegalStateException("No symbol set! Symbol not instanciated!");
+ }
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/sudoku/UserInteractionMediator.java b/sudoq-app/src/de/sudoq/controller/sudoku/UserInteractionMediator.java
new file mode 100644
index 00000000..5c88c964
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/sudoku/UserInteractionMediator.java
@@ -0,0 +1,280 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.sudoku;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.gesture.Gesture;
+import android.gesture.GestureOverlayView;
+import android.gesture.GestureOverlayView.OnGesturePerformedListener;
+import android.gesture.GestureStore;
+import android.gesture.Prediction;
+import android.graphics.Color;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.TextView;
+import android.widget.Toast;
+import de.sudoq.R;
+import de.sudoq.model.game.Assistances;
+import de.sudoq.model.game.Game;
+import de.sudoq.model.profile.Profile;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.view.SudokuFieldView;
+import de.sudoq.view.SudokuLayout;
+import de.sudoq.view.VirtualKeyboardLayout;
+
+/**
+ * Ein Vermittler zwischen einem Sudoku und den verschiedenen
+ * Eingabemöglichkeiten, also insbesondere Tastatur und Gesten-View.
+ */
+public class UserInteractionMediator implements OnGesturePerformedListener, InputListener, FieldInteractionListener, ObservableActionCaster {
+
+ /**
+ * Flag für den Notizmodus.
+ */
+ private boolean noteMode;
+
+ /**
+ * Die SudokuView, die die Anzeige eines Sudokus mit seinen Feldern
+ * übernimmt.
+ */
+ private SudokuLayout sudokuView;
+
+ /**
+ * Virtuelles Keyboard, welches beim Antippen eines Feldes angezeigt wird.
+ */
+ private VirtualKeyboardLayout virtualKeyboard;
+
+ /**
+ * Das aktuelle Spiel.
+ */
+ private Game game;
+
+ /**
+ * Eine Liste der ActionListener.
+ */
+ private List actionListener;
+
+ /**
+ * Die Gesten-View.
+ */
+ private GestureOverlayView gestureOverlay;
+
+ /**
+ * Die Bibliothek für die Gesteneingabe.
+ */
+ private GestureStore gestureStore;
+
+ /**
+ * Instanziiert einen neuen UserInteractionMediator.
+ *
+ * @param virtualKeyboard
+ * Das virtuelle Keyboard, auf dem der Benutzer Eingaben
+ * vornehmen kann
+ * @param sudokuView
+ * Die View des Sudokus
+ * @param game
+ * Das aktuelle Spiel
+ * @param gestureOverlay
+ * Die Gesten-View auf der der Benutzer Gesten eingeben kann
+ * @param gestureStore
+ * Die Bibliothek der Gesten
+ */
+ public UserInteractionMediator(VirtualKeyboardLayout virtualKeyboard, SudokuLayout sudokuView, Game game, GestureOverlayView gestureOverlay,
+ GestureStore gestureStore) {
+ this.actionListener = new ArrayList();
+
+ this.game = game;
+ this.sudokuView = sudokuView;
+ this.virtualKeyboard = virtualKeyboard;
+ this.virtualKeyboard.registerListener(this);
+ this.gestureOverlay = gestureOverlay;
+ this.gestureStore = gestureStore;
+ this.gestureOverlay.addOnGesturePerformedListener(this);
+ this.gestureOverlay.setGestureStrokeType(GestureOverlayView.GESTURE_STROKE_TYPE_MULTIPLE);
+ this.sudokuView.registerListener(this);
+ }
+
+ public void onInput(int symbol) {
+ SudokuFieldView currentField = this.sudokuView.getCurrentFieldView();
+ for (ActionListener listener : actionListener) {
+ if (this.noteMode) {
+ if (currentField.getField().isNoteSet(symbol)) {
+ listener.onNoteDelete(currentField.getField(), symbol);
+ } else {
+ listener.onNoteAdd(currentField.getField(), symbol);
+ }
+ } else {
+ if (symbol == currentField.getField().getCurrentValue()) {
+ listener.onDeleteEntry(currentField.getField());
+ } else {
+ listener.onAddEntry(currentField.getField(), symbol);
+ }
+ }
+ }
+
+ updateKeyboard();
+ }
+
+ public void onFieldSelected(SudokuFieldView view) {
+ SudokuFieldView currentField = this.sudokuView.getCurrentFieldView();
+ if (currentField != view) {
+ this.noteMode = Profile.getInstance().isGestureActive() && !game.isFinished();
+
+ if (currentField != null)
+ currentField.deselect(true);
+
+ this.sudokuView.setCurrentFieldView(view);
+ currentField = view;
+ if (currentField != null)
+ currentField.setNoteState(this.noteMode);
+ currentField.select(this.game.isAssistanceAvailable(Assistances.markRowColumn));
+ if (currentField.getField().isEditable() && !game.isFinished()) {
+ restrictCandidates();
+ this.virtualKeyboard.setActivated(true);
+ } else {
+ this.virtualKeyboard.setActivated(false);
+ }
+ } else if (!game.isFinished()) {
+ if (Profile.getInstance().isGestureActive() && this.sudokuView.getCurrentFieldView().getField().isEditable()) {
+ this.gestureOverlay.setVisibility(View.VISIBLE);
+ restrictCandidates();
+ final TextView textView = new TextView(gestureOverlay.getContext());
+ textView.setTextColor(Color.YELLOW);
+ textView.setText(" " + gestureOverlay.getContext().getString(R.string.sf_sudoku_title_gesture_input) + " ");
+ textView.setTextSize(18);
+ this.gestureOverlay.addView(textView, new GestureOverlayView.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL));
+ } else {
+ this.noteMode = !this.noteMode;
+ }
+ currentField.setNoteState(this.noteMode);
+ }
+
+ updateKeyboard();
+ }
+
+ /**
+ * Aktualisiert die Anzeige der Tastatur.
+ */
+ void updateKeyboard() {
+ SudokuFieldView currentField = this.sudokuView.getCurrentFieldView();
+ for (int i = 0; i < this.game.getSudoku().getSudokuType().getNumberOfSymbols(); i++) {
+ if (currentField != null && i == currentField.getField().getCurrentValue() && !this.noteMode) {
+ this.virtualKeyboard.markField(i, FieldViewStates.SELECTED_INPUT_BORDER);
+ } else if (currentField != null && currentField.getField().isNoteSet(i) && this.noteMode) {
+ this.virtualKeyboard.markField(i, FieldViewStates.SELECTED_NOTE_BORDER);
+ } else {
+ this.virtualKeyboard.markField(i, FieldViewStates.DEFAULT_BORDER);
+ }
+ }
+
+ this.virtualKeyboard.invalidate();
+ }
+
+ public void notifyListener() {
+
+ }
+
+ public void registerListener(ActionListener listener) {
+ this.actionListener.add(listener);
+ }
+
+ public void removeListener(ActionListener listener) {
+ this.actionListener.remove(listener);
+ }
+
+ /**
+ * Setzt den Zustand der Tastatur. Diese wird entsprechend (nicht)
+ * angezeigt.
+ *
+ * @param activated
+ * Gibt den zu setzenden Zustand an
+ */
+ public void setKeyboardState(boolean activated) {
+ this.virtualKeyboard.setActivated(activated);
+ }
+
+ public void onFieldChanged(SudokuFieldView view) {
+ updateKeyboard();
+
+ }
+
+ /**
+ * Wird aufgerufen, sobald der Benutzer eine Geste eingibt.
+ *
+ * @param overlay
+ * GestureOverlay, auf welchem die Geste eingegeben wurde
+ * @param gesture
+ * Geste, die der Benutzer eingegeben hat
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls eines der Argumente null ist
+ */
+ public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
+ ArrayList predictions = this.gestureStore.recognize(gesture);
+ if (predictions.size() > 0) {
+ Prediction prediction = predictions.get(0);
+ if (prediction.score > 1.5) {
+ for (ActionListener listener : this.actionListener) {
+ if (prediction.name.equals(String.valueOf(Symbol.getInstance().getMapping(this.sudokuView.getCurrentFieldView().getField().getCurrentValue())))) {
+ listener.onDeleteEntry(this.sudokuView.getCurrentFieldView().getField());
+ } else {
+ int number = Symbol.getInstance().getAbstract(prediction.name);
+ int save = this.sudokuView.getCurrentFieldView().getField().getCurrentValue();
+ if (number >= this.game.getSudoku().getSudokuType().getNumberOfSymbols())
+ number = -1;
+ if (number != -1 && this.game.isAssistanceAvailable(Assistances.restrictCandidates)) {
+ this.sudokuView.getCurrentFieldView().getField().setCurrentValue(number, false);
+ for (Constraint c : this.game.getSudoku().getSudokuType()) {
+ if (!c.isSaturated(this.game.getSudoku())) {
+ number = -2;
+ break;
+ }
+ }
+ this.sudokuView.getCurrentFieldView().getField().setCurrentValue(save, false);
+ }
+ if (number != -1 && number != -2) {
+ listener.onAddEntry(this.sudokuView.getCurrentFieldView().getField(), number);
+ this.gestureOverlay.setVisibility(View.INVISIBLE);
+ } else if (number == -1) {
+ Toast.makeText(this.sudokuView.getContext(),
+ this.sudokuView.getContext().getString(R.string.toast_invalid_symbol), Toast.LENGTH_SHORT).show();
+ } else if (number == -2) {
+ Toast.makeText(this.sudokuView.getContext(),
+ this.sudokuView.getContext().getString(R.string.toast_restricted_symbol), Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Schränkt die Kandidaten auf der Tastatur ein.
+ */
+ private void restrictCandidates() {
+ this.virtualKeyboard.enableAllButtons();
+ if (this.game.isAssistanceAvailable(Assistances.restrictCandidates)) {
+ int save = this.sudokuView.getCurrentFieldView().getField().getCurrentValue();
+ for (int i = 0; i < this.game.getSudoku().getSudokuType().getNumberOfSymbols(); i++) {
+ this.sudokuView.getCurrentFieldView().getField().setCurrentValue(i, false);
+ for (Constraint c : this.game.getSudoku().getSudokuType()) {
+ if (!c.isSaturated(this.game.getSudoku())) {
+ this.virtualKeyboard.disableButton(i);
+ break;
+ }
+ }
+ this.sudokuView.getCurrentFieldView().getField().setCurrentValue(Field.EMPTYVAL, false);
+ }
+ this.sudokuView.getCurrentFieldView().getField().setCurrentValue(save, false);
+ }
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/tutorial/TutorialActionTreeActivity.java b/sudoq-app/src/de/sudoq/controller/tutorial/TutorialActionTreeActivity.java
new file mode 100644
index 00000000..21278262
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/tutorial/TutorialActionTreeActivity.java
@@ -0,0 +1,50 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.tutorial;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.widget.RelativeLayout;
+import de.sudoq.R;
+import de.sudoq.model.actionTree.ActionTreeElement;
+import de.sudoq.model.actionTree.SolveActionFactory;
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.view.actionTree.ActionElement;
+import de.sudoq.view.actionTree.ActionTreeElementView;
+import de.sudoq.view.actionTree.ActiveElement;
+import de.sudoq.view.actionTree.BookmarkedElement;
+import de.sudoq.view.actionTree.BranchingElement;
+
+public class TutorialActionTreeActivity extends Activity {
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tutorial_actiontree);
+
+ RelativeLayout.LayoutParams viewLayoutParams = new RelativeLayout.LayoutParams(68, 68);
+ viewLayoutParams.topMargin = 0;
+ viewLayoutParams.leftMargin = 0;
+
+ ActionTreeElementView normal = new ActionElement(this, null, new ActionTreeElement(0, new SolveActionFactory().createAction(0, new Field(1, 9)), null));
+
+ ActionTreeElementView view = new BookmarkedElement(this, normal, new ActionTreeElement(0, new SolveActionFactory().createAction(0, new Field(1, 9)), null));
+ view.setLayoutParams(viewLayoutParams);
+ ((RelativeLayout) findViewById(R.id.tutorial_bookmark)).addView(view);
+
+ view = normal;
+ view.setLayoutParams(viewLayoutParams);
+ ((RelativeLayout) findViewById(R.id.tutorial_state)).addView(view);
+
+ view = new ActiveElement(this, normal, new ActionTreeElement(0, new SolveActionFactory().createAction(0, new Field(1, 9)), null));
+ view.setLayoutParams(viewLayoutParams);
+ ((RelativeLayout) findViewById(R.id.tutorial_current_state)).addView(view);
+
+ view = new BranchingElement(this, normal, new ActionTreeElement(0, new SolveActionFactory().createAction(0, new Field(1, 9)), null));
+ view.setLayoutParams(viewLayoutParams);
+ ((RelativeLayout) findViewById(R.id.tutorial_branching)).addView(view);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/tutorial/TutorialActivity.java b/sudoq-app/src/de/sudoq/controller/tutorial/TutorialActivity.java
new file mode 100644
index 00000000..5aae54fd
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/tutorial/TutorialActivity.java
@@ -0,0 +1,52 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.tutorial;
+
+import de.sudoq.R;
+import android.app.TabActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.widget.TabHost;
+import android.widget.TabHost.TabSpec;
+
+public class TutorialActivity extends TabActivity {
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tutorial);
+
+ TabHost tabHost = getTabHost();
+
+ // Tab for sudokus
+ TabSpec sudokuspec = tabHost.newTabSpec(getString(R.string.sf_tutorial_sudoku_title));
+ // setting Title and Icon for the Tab
+ sudokuspec.setIndicator(getString(R.string.sf_tutorial_sudoku_title), getResources().getDrawable(R.drawable.sudoku_tutorial));
+ Intent sudokuIntent = new Intent(this, TutorialSudokuActivity.class);
+ sudokuspec.setContent(sudokuIntent);
+
+ // Tab for assistances
+ TabSpec assistancesspec = tabHost.newTabSpec(getString(R.string.sf_tutorial_assistances_title));
+ // setting Title and Icon for the Tab
+ assistancesspec.setIndicator(getString(R.string.sf_tutorial_assistances_title), getResources().getDrawable(R.drawable.help_tutorial));
+ Intent assistancesIntent = new Intent(this, TutorialAssistancesActivity.class);
+ assistancesspec.setContent(assistancesIntent);
+
+ // Tab for actiontree
+ TabSpec actiontreespec = tabHost.newTabSpec(getString(R.string.sf_tutorial_action_title));
+ // setting Title and Icon for the Tab
+ actiontreespec.setIndicator(getString(R.string.sf_tutorial_action_title), getResources().getDrawable(R.drawable.action_tree_tutorial));
+ Intent actiontreeIntent = new Intent(this, TutorialActionTreeActivity.class);
+ actiontreespec.setContent(actiontreeIntent);
+
+ // Adding all TabSpec to TabHost
+ tabHost.addTab(sudokuspec); // Adding sudoku tab
+ tabHost.addTab(assistancesspec); // Adding assistances tab
+ tabHost.addTab(actiontreespec); // Adding actiontree tab
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/controller/tutorial/TutorialAssistancesActivity.java b/sudoq-app/src/de/sudoq/controller/tutorial/TutorialAssistancesActivity.java
new file mode 100644
index 00000000..d360ecd4
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/tutorial/TutorialAssistancesActivity.java
@@ -0,0 +1,19 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.tutorial;
+
+import de.sudoq.R;
+import android.app.Activity;
+import android.os.Bundle;
+
+public class TutorialAssistancesActivity extends Activity {
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tutorial_assistances);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/controller/tutorial/TutorialSudokuActivity.java b/sudoq-app/src/de/sudoq/controller/tutorial/TutorialSudokuActivity.java
new file mode 100644
index 00000000..f34a28cc
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/controller/tutorial/TutorialSudokuActivity.java
@@ -0,0 +1,19 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.controller.tutorial;
+
+import de.sudoq.R;
+import android.app.Activity;
+import android.os.Bundle;
+
+public class TutorialSudokuActivity extends Activity {
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tutorial_sudoku);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/view/FullScrollLayout.java b/sudoq-app/src/de/sudoq/view/FullScrollLayout.java
new file mode 100644
index 00000000..f3b70a83
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/FullScrollLayout.java
@@ -0,0 +1,355 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.view.View;
+import android.widget.HorizontalScrollView;
+import android.widget.LinearLayout;
+import android.widget.ScrollView;
+
+/**
+ * Eine ScrollView, welche sowohl horizontales, als auch vertikales Scrollen
+ * ermöglicht.
+ */
+public class FullScrollLayout extends LinearLayout {
+ /**
+ * Der maximale Zoom Faktor.
+ */
+ private static final float MAX_ZOOM = 3.0f;
+
+ /**
+ * Der Log-Tag
+ */
+ private static final String LOG_TAG = FullScrollLayout.class.getSimpleName();
+
+ /**
+ * Der aktuelle Zoom Faktor.
+ */
+ private float zoomFactor;
+
+ /**
+ * Flag, ob seit dem letzten Aufruf der isZoomPerformed-Methode gezoomt
+ * wurde.
+ */
+ private boolean zoomPerformed;
+
+ /**
+ * Der View, der horizontales Scrollen erlaubt und im View für vertikales
+ * Scrollen enthalten ist.
+ */
+ private HorizontalScroll horizontalScrollView;
+
+ /**
+ * Der View, der vertikales Scrollen erlaubt und den View für horizontales
+ * Scrollen enthällt.
+ */
+ private VerticalScroll verticalScrollView;
+
+ /**
+ * Aktueller X- und Y-Wert der ScrollViews.
+ */
+ private float currentX, currentY;
+
+ /**
+ * Der Zoom-Gesten-Detektor
+ */
+ private ScaleGestureDetector scaleGestureDetector;
+
+ /**
+ * Instanziiert ein neues ScrollLayout mit den gegebenen Parametern
+ *
+ * @param context
+ * der Applikationskontext
+ * @param set
+ * das Android AttributeSet
+ */
+ public FullScrollLayout(Context context, AttributeSet set) {
+ super(context, set);
+ initialize();
+ this.scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
+ }
+
+ /**
+ * Instanziiert ein neues FullScrollLayout, welches auf Wunsch als
+ * qudratisch festgelegt wird.
+ *
+ * @param context
+ * Der Kontext, in dem dieses Layout angelegt wird
+ */
+ public FullScrollLayout(Context context) {
+ super(context);
+ initialize();
+ this.scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
+ }
+
+ /**
+ * Initialisiert ein neues Layout.
+ */
+ private void initialize() {
+ this.removeAllViews();
+
+ if (this.zoomFactor == 0) {
+ this.zoomFactor = 1.0f;
+ }
+ this.zoomPerformed = false;
+
+ this.verticalScrollView = new VerticalScroll(getContext());
+ this.horizontalScrollView = new HorizontalScroll(getContext());
+
+ this.verticalScrollView.addView(this.horizontalScrollView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
+ this.addView(this.verticalScrollView, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
+ }
+
+ /**
+ * Fügt eine View zu diesem Layout hinzu. Ist bereits eine vorhanden, so
+ * wird diese gelöscht.
+ */
+ @Override
+ public void addView(View v) {
+ this.horizontalScrollView.removeAllViews();
+ this.horizontalScrollView.addView(v, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
+ }
+
+ /**
+ * Verarbeitet TouchEvents mit einem Finger, also klicken und scrollen.
+ *
+ * @param event
+ * Das MotionEvent
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (event.getPointerCount() == 1) {
+ this.horizontalScrollView.performTouch(event);
+ this.verticalScrollView.performTouch(event);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void scrollTo(int x, int y) {
+ // Has to be changed because the tree algo uses different coords.
+ currentX = x - getWidth() / 2;
+ currentY = y - getHeight() / 2;
+
+ this.verticalScrollView.post(new Runnable() {
+ public void run() {
+ verticalScrollView.scrollTo((int) currentX, (int) currentY);
+ currentY = verticalScrollView.getScrollY();
+ }
+ });
+ this.horizontalScrollView.post(new Runnable() {
+ public void run() {
+ horizontalScrollView.scrollTo((int) currentX, (int) currentY);
+ currentX = horizontalScrollView.getScrollX();
+ }
+ });
+ }
+
+ /**
+ * Verarbeitet ZoomEvents, also solche mit zwei Fingern.
+ *
+ * @param event
+ * Das MotionEvent
+ */
+ public void performZoomEvent(MotionEvent event) {
+ this.scaleGestureDetector.onTouchEvent(event);
+ }
+
+ /**
+ * Setzt den Zoom zurück.
+ */
+ public void resetZoom() {
+ setZoomFactor(1.0f);
+ scrollTo(0, 0);
+ }
+
+ /**
+ * Gibt zurück, ob ein Zoom performt wurde und setzt den Zustand zurück.
+ *
+ * @return true, falls ein Zoom performt wurde, false falls nicht
+ */
+ public boolean isZoomPerformed() {
+ boolean res = this.zoomPerformed;
+ this.zoomPerformed = false;
+ return res;
+ }
+
+ /**
+ * Scrollt an die korrekte Position.
+ */
+ public void scrollCorrect() {
+ scrollTo((int) (currentX * zoomFactor) + getWidth() / 2, (int) (currentY * zoomFactor) + getHeight() / 2);
+ }
+
+ /**
+ * Gibt den aktuellen Zoom-Faktor dieses Layouts zurück.
+ *
+ * @return Der aktuelle Zoom-Faktor
+ */
+ public float getZoomFactor() {
+ return this.zoomFactor;
+ }
+
+ /**
+ * Setzt den aktuellen Zoom-Faktor des Layouts.
+ *
+ * @param newZoom
+ * Der neue Zoomfaktor
+ */
+ public void setZoomFactor(float newZoom) {
+ this.zoomFactor = newZoom;
+ }
+
+ /**
+ * Gibt den aktuell gescrollten X-Wert zurück.
+ *
+ * @return der aktuell gescrollte X-Wert
+ */
+ public float getScrollValueX()
+ {
+ return this.currentX;
+ }
+
+ /**
+ * Gibt den aktuell gescrollten Y-Wert zurück.
+ *
+ * @return der aktuell gescrollte Y-Wert
+ */
+ public float getScrollValueY()
+ {
+ return this.currentY;
+ }
+
+ /**
+ * Diese Klasse überschreibt das onTouch-Event der ScrollView, sodass dieses
+ * an dieses FullScrollLayout weitergereicht wird. Durch die
+ * performTouch-Methode kann das Event zurückgereicht werden.
+ */
+ private class VerticalScroll extends ScrollView {
+ /**
+ * Instanziiert eine neue vertikale ScrollView.
+ *
+ * @param context
+ * Der Kontext
+ */
+ public VerticalScroll(Context context) {
+ super(context);
+ setVerticalScrollBarEnabled(false);
+ setHorizontalScrollBarEnabled(false);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return false;
+ }
+
+ /**
+ * Für das übergebene Touch-Event aus.
+ *
+ * @param event
+ * Das auszuführende Touch-Event
+ */
+ public void performTouch(MotionEvent event) {
+ try {
+ event.getX();
+ event.getY();
+ super.onTouchEvent(event);
+ currentY = this.getScrollY();
+ } catch (Exception e) {
+ // Old android versions sometimes throw an exception when
+ // putting and Event of one view in the onTouch of
+ // another view. We just catch that and do nothing
+ }
+ }
+ }
+
+ /**
+ * Diese Klasse überschreibt das onTouch-Event der HorizontalScrollView,
+ * sodass dieses an dieses FullScrollLayout weitergereicht wird. Durch die
+ * performTouch-Methode kann das Event zurückgereicht werden.
+ */
+ private class HorizontalScroll extends HorizontalScrollView {
+ /**
+ * Instanziiert eine neue horizontale ScrollView.
+ *
+ * @param context
+ * Der Kontext
+ */
+ public HorizontalScroll(Context context) {
+ super(context);
+ setVerticalScrollBarEnabled(false);
+ setHorizontalScrollBarEnabled(false);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return false;
+ }
+
+ /**
+ * Für das übergebene Touch-Event aus.
+ *
+ * @param event
+ * Das auszuführende Touch-Event
+ */
+ public void performTouch(MotionEvent event) {
+ try {
+ event.getX();
+ event.getY();
+ super.onTouchEvent(event);
+ currentX = this.getScrollX();
+ } catch (Exception e) {
+ // Old android versions sometimes throw an exception when
+ // putting and Event of one view in the onTouch of
+ // another view. We just catch that and do nothing
+ }
+ }
+ }
+
+ private class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
+ @Override
+ public boolean onScale(ScaleGestureDetector detector) {
+ float oldZoom = zoomFactor;
+ float scaleFactor = detector.getScaleFactor();
+ zoomFactor *= scaleFactor;
+ // Don't let the object get too large.
+ zoomFactor = Math.max(Math.min(zoomFactor, MAX_ZOOM), 1.0f);
+
+ // if (Math.abs(zoomFactor - oldZoom) > 0.0001f)
+ zoomPerformed = true;
+
+ currentX += detector.getFocusX() - detector.getFocusX() / scaleFactor;
+ currentY += detector.getFocusY() - detector.getFocusY() / scaleFactor;
+
+ // currentX = currentX < 0 ? 0 :
+ // (currentX > getMeasuredWidth() * zoomFactor - getMeasuredWidth()
+ // ? currentX = getMeasuredWidth() * zoomFactor - getMeasuredWidth()
+ // : currentX);
+ //
+ // currentY = currentY < 0 ? 0 :
+ // (currentY > getMeasuredHeight() * zoomFactor -
+ // getMeasuredHeight() ? currentY = getMeasuredHeight() * zoomFactor
+ // - getMeasuredHeight() : currentY);
+
+ scrollTo((int) currentX + getWidth() / 2, (int) currentY + getHeight() / 2);
+ // invalidate();
+ Log.d(LOG_TAG, "Scaled");
+ return true;
+ }
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/view/SudokuFieldView.java b/sudoq-app/src/de/sudoq/view/SudokuFieldView.java
new file mode 100644
index 00000000..ddba3347
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/SudokuFieldView.java
@@ -0,0 +1,402 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.view.MotionEvent;
+import android.view.View;
+import de.sudoq.controller.sudoku.FieldInteractionListener;
+import de.sudoq.controller.sudoku.FieldViewPainter;
+import de.sudoq.controller.sudoku.FieldViewStates;
+import de.sudoq.controller.sudoku.ObservableFieldInteraction;
+import de.sudoq.controller.sudoku.Symbol;
+import de.sudoq.model.ModelChangeListener;
+import de.sudoq.model.game.Game;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.ConstraintType;
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.model.sudoku.Position;
+
+/**
+ * Diese Subklasse des von der Android API bereitgestellten Views stellt ein
+ * einzelnes Feld innerhalb eines Sudokus dar. Es erweitert den Android View um
+ * Funktionalität zur Benutzerinteraktion und Färben.
+ */
+public class SudokuFieldView extends View implements ModelChangeListener, ObservableFieldInteraction {
+
+ /** Attributes */
+
+ /**
+ * Das Feld, das von diesem View representiert wird
+ *
+ * @see Field
+ */
+ private Field field;
+
+ /**
+ * List der Selektions-Listener
+ */
+ private ArrayList fieldSelectListener;
+
+ /**
+ * Ein Flag welches definiert, ob der Notizmodus eingeschaltet ist
+ */
+ private boolean noteMode;
+
+ /**
+ * Eine Liste von Feldern, die mit diesem in Verbindung stehen und markiert
+ * werden, falls dieses Feld ausgewählt wird
+ */
+ private ArrayList connectedFields;
+
+ /**
+ * Das Symbol was in diesem Feld steht
+ */
+ private String symbol;
+
+ /**
+ * Gibt an, ob dieses Feld zurzeit ausgewählt ist
+ */
+ private boolean selected;
+
+ /**
+ * Gibt an, ob dieses Feld mit dem zurzeit ausgewählten verbunden ist
+ */
+ private boolean connected;
+
+ /**
+ * Gibt an, ob dieses Feld in einem extraConstraint liegt
+ */
+ private boolean isInExtraConstraint;
+
+ /**
+ * Definiert, ob falsche Symbole markiert werden sollen
+ */
+ private boolean markWrongSymbol;
+
+ /**
+ * Das Game zu dem diese View gehört
+ */
+ private Game game;
+
+ /** Constructors */
+
+ /**
+ * Erstellt einen SudokuFieldView und initialisiert die Attribute der
+ * Klasse.
+ *
+ * @param context
+ * der Applikationskontext
+ * @param game
+ * Das Game zu dieser View
+ * @param field
+ * Das Feld, dass dieser SudokuFieldView representiert
+ * @param markWrongSymbol
+ * Gibt an, ob ein falsch eingegebenes Symbol markiert werden
+ * eoll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls eines der Argumente null ist
+ */
+ public SudokuFieldView(Context context, Game game, Field field, boolean markWrongSymbol) {
+ super(context);
+ this.markWrongSymbol = markWrongSymbol;
+ this.field = field;
+ this.symbol = Symbol.getInstance().getMapping(this.field.getCurrentValue());
+ this.game = game;
+
+ this.fieldSelectListener = new ArrayList();
+ this.connectedFields = new ArrayList();
+ this.selected = false;
+ this.connected = false;
+ this.noteMode = false;
+ this.isInExtraConstraint = false;
+
+ ArrayList constraints = game.getSudoku().getSudokuType().getConstraints();
+ for (int i = 0; i < constraints.size(); i++) {
+ if (constraints.get(i).getType().equals(ConstraintType.EXTRA) &&
+ constraints.get(i).includes(game.getSudoku().getPosition(field.getId()))) {
+ this.isInExtraConstraint = true;
+ break;
+ }
+ }
+
+ updateMarking();
+ }
+
+ /** Methods */
+
+ /**
+ * Zeichnet den Inhalt des Feldes auf das Canvas dieses SudokuFieldViews.
+ * Sollte den AnimationHandler nutzen um vorab Markierungen/Färbung an dem
+ * Canvas Objekt vorzunehmen.
+ *
+ * @param canvas
+ * Das Canvas Objekt auf das gezeichnet wird
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Canvas null ist
+ */
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ this.symbol = Symbol.getInstance().getMapping(this.field.getCurrentValue());
+ FieldViewPainter.getInstance().markField(canvas, this, this.symbol, false, this.isInExtraConstraint && !this.selected);
+
+ // Draw notes if field has no value
+ if (this.field.isEmpty()) {
+ drawNotes(canvas);
+ }
+ }
+
+ /**
+ * Zeichnet die Notizen in dieses Feld
+ *
+ * @param canvas
+ * Das Canvas in das gezeichnet werde nsoll
+ */
+ private void drawNotes(Canvas canvas) {
+ Paint notePaint = new Paint();
+ notePaint.setAntiAlias(true);
+ int noteTextSize = getHeight() / Symbol.getInstance().getRasterSize();
+ notePaint.setTextSize(noteTextSize);
+ notePaint.setTextAlign(Paint.Align.CENTER);
+ notePaint.setColor(Color.BLACK);
+ for (int i = 0; i < Symbol.getInstance().getNumberOfSymbols(); i++) {
+ if (this.field.isNoteSet(i)) {
+ String note = Symbol.getInstance().getMapping(i);
+ canvas.drawText(note + "", (i % Symbol.getInstance().getRasterSize()) * noteTextSize + noteTextSize / 2, (i / Symbol.getInstance().getRasterSize()) * noteTextSize + noteTextSize, notePaint);
+ }
+ }
+ }
+
+ /**
+ * notifyListener(); {@inheritDoc}
+ */
+ public void onModelChanged(Field obj) {
+ for (FieldInteractionListener listener : fieldSelectListener) {
+ listener.onFieldChanged(this);
+ }
+
+ updateMarking();
+ }
+
+ /**
+ * Diese Methode verarbeitet alle Touch Inputs, die der Benutzer macht und
+ * leitet sie an den ShowViewListener weiter.
+ *
+ * @param touchEvent
+ * Das TouchEvent das von der API kommt und diese Methode
+ * aufgerufen hat
+ * @return true falls das TouchEvent behandelt wurde, false falls nicht
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene MotionEvent null ist
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent touchEvent) {
+ for (FieldInteractionListener listener : fieldSelectListener) {
+ listener.onFieldSelected(this);
+ }
+
+ return false;
+ }
+
+ /**
+ * Benachrichtigt alle Registrierten Listener über Interaktion mit diesem
+ * SudokuFieldView.
+ */
+ public void notifyListener() {
+ for (FieldInteractionListener listener : fieldSelectListener) {
+ listener.onFieldSelected(this);
+ }
+ }
+
+ /**
+ * Gibt das Feld, welches von dieser View angezeigt wird zurück
+ *
+ * @return Das Feld dieser View
+ */
+ public Field getField() {
+ return this.field;
+ }
+
+ /**
+ * Setzt den Notizstatus gemäß des Parameters
+ *
+ * @param state
+ * true, um den Notizmodus ein-, bzw. false um ihn auszuschalten
+ */
+ public void setNoteState(boolean state) {
+ this.noteMode = state;
+ this.updateMarking();
+ }
+
+ /**
+ * Fügt die übergebene SudokuFieldView als mit diesem Feld verbunden hinzu,
+ * sodass bei Markierung dieses Feldes auch das verbundene Feld markiert
+ * wird. Ist sie null, so wird nichts getan
+ *
+ * @param view
+ * Die View, die mit dieser verbunden werden soll
+ */
+ public void addConnectedField(SudokuFieldView view) {
+ if (view != null && !this.connectedFields.contains(view)) {
+ this.connectedFields.add(view);
+ }
+ }
+
+ /**
+ * Setzt diese View als aktuel ausgewählt.
+ *
+ * @param markConnected
+ * Gibt an, ob mit diesem Feld verbundene Felder (Zeile / Spalte)
+ * auch markiert werden sollen
+ */
+ public void select(boolean markConnected) {
+ if (this.game.isFinished()) {
+ this.connected = true;
+ } else {
+ this.selected = true;
+ }
+ if (markConnected) {
+ for (SudokuFieldView f : this.connectedFields) {
+ f.markConnected();
+ }
+ }
+
+ this.updateMarking();
+ }
+
+ /**
+ * Setzt die Markierung für dieses und alle mit diesem Feld verbundenen
+ * FieldViews zurück.
+ *
+ * @param updateConnected
+ * Gibt an, ob mit diesem verbundenen Felder aktualisiert, also
+ * auch abgewählt werden sollen
+ */
+ public void deselect(boolean updateConnected) {
+ this.selected = false;
+ this.connected = false;
+ if (updateConnected) {
+ for (SudokuFieldView fv : this.connectedFields) {
+ fv.deselect(false);
+ }
+ }
+
+ this.updateMarking();
+ }
+
+ /**
+ * Makiert dieses Feld als mit dem aktuell selektierten verbunden.
+ */
+ public void markConnected() {
+ this.connected = true;
+ updateMarking();
+ }
+
+ /**
+ * Aktualisiert die Markierungen dieser FieldView
+ */
+ private void updateMarking() {
+ if (this.connected) {
+ if (this.field.isEditable()) {
+ if (this.markWrongSymbol && !this.field.isNotWrong() && checkConstraint()) {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.CONNECTED_WRONG);
+ } else {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.CONNECTED);
+ }
+ } else {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.SELECTED_FIXED);
+ }
+ } else if (this.selected) {
+ if (this.field.isEditable()) {
+ if (!this.noteMode) {
+ if (this.markWrongSymbol && !this.field.isNotWrong() && checkConstraint()) {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.SELECTED_INPUT_WRONG);
+ } else {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.SELECTED_INPUT);
+ }
+ } else {
+ if (this.markWrongSymbol && !this.field.isNotWrong() && checkConstraint()) {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.SELECTED_NOTE_WRONG);
+ } else {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.SELECTED_NOTE);
+ }
+ }
+ } else {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.SELECTED_FIXED);
+ }
+ } else {
+ if (this.field.isEditable()) {
+ if (this.markWrongSymbol && !this.field.isNotWrong() && checkConstraint()) {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.DEFAULT_WRONG);
+ } else {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.DEFAULT);
+ }
+ } else {
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.FIXED);
+ }
+ }
+ invalidate();
+ }
+
+ /**
+ * Gibt true zurück, falls der Wert dieses Feldes die Constraints verletzt.
+ * Überprüft werden nur UniqueConstraints. Befindet sich das Feld in einem
+ * anderen ConstraintTyp wird immer fals ezurückgegeben.
+ *
+ * @return true, falls der Wert dieses Feldes die UniqueConstraints verletzt
+ * oder sich in einem anderen ConstraintTyp befindet, false sonst
+ */
+ private boolean checkConstraint() {
+ ArrayList constraints = this.game.getSudoku().getSudokuType().getConstraints();
+ ArrayList positions;
+ for (int i = 0; i < constraints.size(); i++) {
+ if (constraints.get(i).includes(this.game.getSudoku().getPosition(this.field.getId()))) {
+ if (constraints.get(i).hasUniqueBehavior()) {
+ positions = constraints.get(i).getPositions();
+ for (int k = 0; k < positions.size(); k++) {
+ if (positions.get(k) != this.game.getSudoku().getPosition(this.field.getId())
+ && this.game.getSudoku().getField(positions.get(k)).getCurrentValue() == this.field.getCurrentValue()) {
+ return true;
+ }
+ }
+ } else {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Gibt zurück, ob sich das Feld gerade im Notizmodus befindet
+ *
+ * @return true, falls sich das Feld im Notizmodus befindet, false falls
+ * nicht
+ */
+ public boolean isNoteMode() {
+ return this.noteMode;
+ }
+
+ public void registerListener(FieldInteractionListener listener) {
+ this.fieldSelectListener.add(listener);
+ }
+
+ public void removeListener(FieldInteractionListener listener) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/view/SudokuLayout.java b/sudoq-app/src/de/sudoq/view/SudokuLayout.java
new file mode 100644
index 00000000..c9e0d8ba
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/SudokuLayout.java
@@ -0,0 +1,440 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.widget.RelativeLayout;
+import de.sudoq.controller.sudoku.FieldInteractionListener;
+import de.sudoq.controller.sudoku.FieldViewPainter;
+import de.sudoq.controller.sudoku.ObservableFieldInteraction;
+import de.sudoq.controller.sudoku.SudokuActivity;
+import de.sudoq.model.game.Assistances;
+import de.sudoq.model.game.Game;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.ConstraintType;
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.TypeBasic;
+
+/**
+ * Eine View als RealativeLayout, die eine Sudoku-Anzeige verwaltet.
+ */
+public class SudokuLayout extends RelativeLayout implements ObservableFieldInteraction {
+ /**
+ * Das Log-Tag für den LogCat
+ */
+ private static final String LOG_TAG = SudokuLayout.class.getSimpleName();
+
+ /**
+ * Das Game, welches diese Anzeige verwaltet
+ */
+ private Game game;
+
+ /**
+ * Der Kontext dieser View
+ */
+ private Context context;
+
+ /**
+ * Die Standardgröße eines Feldes
+ */
+ private int defaultFieldViewSize;
+
+ /**
+ * Die aktuelle Größe eines Feldes
+ */
+ // private int currentFieldViewSize;
+
+ /**
+ * Die aktuell ausgewählte FieldView
+ */
+ private SudokuFieldView currentFieldView;
+
+ private float zoomFactor;
+
+ /**
+ * Ein Array aller FieldViews
+ */
+ private SudokuFieldView[][] sudokuFieldViews;
+
+ /**
+ * Der linke Rand, verursacht durch ein zu niedriges Layout
+ */
+ private int leftMargin;
+
+ /**
+ * Der linke Rand, verursacht durch ein zu schmales Layout
+ */
+ private int topMargin;
+
+ /**
+ * Der Platz zwischen 2 Blöcken
+ */
+ private static int spacing = 2;
+
+ /**
+ * Instanziiert eine neue SudokuView in dem spezifizierten Kontext.
+ *
+ * @param context
+ * Der Kontext, in dem diese View angezeigt wird
+ */
+ public SudokuLayout(Context context) {
+ super(context);
+ this.context = context;
+ this.game = ((SudokuActivity) context).getGame();
+
+ this.defaultFieldViewSize = 40;
+ this.zoomFactor = 1.0f;
+ // this.currentFieldViewSize = this.defaultFieldViewSize;
+ this.setWillNotDraw(false);
+
+ inflateSudoku();
+ }
+
+ /**
+ * Erstellt die Anzeige des Sudokus.
+ */
+ private void inflateSudoku() {
+ FieldViewPainter.getInstance().flushMarkings();
+ this.removeAllViews();
+
+ Sudoku sudoku = this.game.getSudoku();
+ TypeBasic sudokuType = sudoku.getSudokuType();
+ this.sudokuFieldViews = new SudokuFieldView[sudokuType.getSize().getX() + 1][sudokuType.getSize().getY() + 1];
+ for (int x = 0; x <= sudokuType.getSize().getX(); x++) {
+ for (int y = 0; y <= sudokuType.getSize().getY(); y++) {
+ Field field = sudoku.getField(Position.get(x, y));
+ if (field != null) {
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams((int) this.getCurrentFieldViewSize(), (int) this.defaultFieldViewSize);
+ params.topMargin = (y * (int) this.getCurrentFieldViewSize()) + y;
+ params.leftMargin = (x * (int) this.getCurrentFieldViewSize()) + x;
+ this.sudokuFieldViews[x][y] = new SudokuFieldView(context, game, field, this.game.isAssistanceAvailable(Assistances.markWrongSymbol));
+ field.registerListener(this.sudokuFieldViews[x][y]);
+ this.addView(this.sudokuFieldViews[x][y], params);
+ } else if (sudoku.getSudokuType().getSize().getX() == x && sudoku.getSudokuType().getSize().getY() == y) {
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams((int) this.getCurrentFieldViewSize(), (int) this.defaultFieldViewSize);
+ params.topMargin = ((y - 1) * (int) this.getCurrentFieldViewSize()) + (y - 1) + getCurrentTopMargin();
+ params.leftMargin = ((x - 1) * (int) this.getCurrentFieldViewSize()) + (x - 1) + getCurrentLeftMargin();
+ this.sudokuFieldViews[x][y] = new SudokuFieldView(context, game, this.game.getSudoku().getField(Position.get(x - 1, y - 1)), this.game.isAssistanceAvailable(Assistances.markWrongSymbol));
+ this.addView(this.sudokuFieldViews[x][y], params);
+ this.sudokuFieldViews[x][y].setVisibility(INVISIBLE);
+ }
+ }
+ }
+
+ ArrayList allConstraints = this.game.getSudoku().getSudokuType().getConstraints();
+ ArrayList positions = null;
+ if (this.game.isAssistanceAvailable(Assistances.markRowColumn)) {
+ for (int constrNum = 0; constrNum < allConstraints.size(); constrNum++) {
+ if (allConstraints.get(constrNum).getType().equals(ConstraintType.LINE)) {
+ positions = allConstraints.get(constrNum).getPositions();
+ for (int i = 0; i < positions.size(); i++) {
+ for (int k = 0; k < positions.size(); k++) {
+ if (i != k)
+ this.sudokuFieldViews[positions.get(i).getX()][positions.get(i).getY()].addConnectedField(
+ this.sudokuFieldViews[positions.get(k).getX()][positions.get(k).getY()]);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Berechnet das aktuelle Spacing (gem. dem aktuellen ZoomFaktor) und gibt
+ * es zurück.
+ *
+ * @return Das aktuelle Spacing
+ */
+ private int getCurrentSpacing() {
+ return (int) (spacing * this.zoomFactor);
+ }
+
+ /**
+ * Berechnet das aktuelle obere Margin (gem. dem aktuellen ZoomFaktor) und
+ * gibt es zurück.
+ *
+ * @return Das aktuelle obere Margin
+ */
+ public int getCurrentTopMargin() {
+ return (int) (this.topMargin * this.zoomFactor);
+ }
+
+ /**
+ * Berechnet das aktuelle linke Margin (gem. dem aktuellen ZoomFaktor) und
+ * gibt es zurück.
+ *
+ * @return Das aktuelle linke Margin
+ */
+ public int getCurrentLeftMargin() {
+ return (int) (this.leftMargin * this.zoomFactor);
+ }
+
+ /**
+ * Aktualisiert die Sudoku-Anzeige bzw. der enthaltenen Felder.
+ */
+ private void refresh() {
+ if (this.sudokuFieldViews != null) {
+ TypeBasic sudokuType = this.game.getSudoku().getSudokuType();
+ for (int x = 0; x <= sudokuType.getSize().getX(); x++) {
+ for (int y = 0; y <= sudokuType.getSize().getY(); y++) {
+ if (game.getSudoku().getField(Position.get(x, y)) != null) {
+ RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) this.sudokuFieldViews[x][y].getLayoutParams();
+ params.width = (int) this.getCurrentFieldViewSize();
+ params.height = (int) this.getCurrentFieldViewSize();
+ params.topMargin = (int) (getCurrentTopMargin() + (y * (this.getCurrentFieldViewSize() + getCurrentSpacing())));
+ params.leftMargin = (int) (getCurrentLeftMargin() + (x * (this.getCurrentFieldViewSize() + getCurrentSpacing())));
+ this.sudokuFieldViews[x][y].setLayoutParams(params);
+ this.sudokuFieldViews[x][y].invalidate();
+ } else if (game.getSudoku().getSudokuType().getSize().getX() == x && game.getSudoku().getSudokuType().getSize().getY() == y) {
+ RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams((int) this.getCurrentFieldViewSize(), (int) this.defaultFieldViewSize);
+ params.width = (int) this.getCurrentFieldViewSize();
+ params.height = (int) this.getCurrentFieldViewSize();
+ params.topMargin = (int) (2 * getCurrentTopMargin() + ((y - 1) * (this.getCurrentFieldViewSize() + getCurrentSpacing())));
+ params.leftMargin = (int) (2 * getCurrentLeftMargin() + ((x - 1) * (this.getCurrentFieldViewSize() + getCurrentSpacing())));
+ this.sudokuFieldViews[x][y].setLayoutParams(params);
+ this.sudokuFieldViews[x][y].invalidate();
+ }
+ }
+ }
+ }
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ float edgeRadius = getCurrentFieldViewSize() / 20.0f;
+ Paint paint = new Paint();
+ paint.setColor(Color.BLACK);
+ ArrayList constraints = this.game.getSudoku().getSudokuType().getConstraints();
+ ArrayList positions = null;
+ Position p = null;
+ Constraint c = null;
+ for (int constrNum = 0; constrNum < constraints.size(); constrNum++) {
+ if (constraints.get(constrNum).getType().equals(ConstraintType.BLOCK)) {
+ c = constraints.get(constrNum);
+ positions = c.getPositions();
+ for (int pos = 0; pos < positions.size(); pos++) {
+ p = positions.get(pos);
+ boolean isLeft = p.getX() == 0 || !c.includes(Position.get(p.getX() - 1, p.getY()));
+ boolean isRight = !c.includes(Position.get(p.getX() + 1, p.getY()));
+ boolean isTop = p.getY() == 0 || !c.includes(Position.get(p.getX(), p.getY() - 1));
+ boolean isBottom = !c.includes(Position.get(p.getX(), p.getY() + 1));
+ for (int i = 1; i <= getCurrentSpacing(); i++) {
+ if (isLeft) {
+ canvas.drawLine(getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - i,
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - i,
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ paint);
+ }
+ if (isRight) {
+ canvas.drawLine(getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - 1 + i,
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - 1 + i,
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ paint);
+ }
+ if (isTop) {
+ canvas.drawLine(getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - i,
+ getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - i,
+ paint);
+ }
+ if (isBottom) {
+ canvas.drawLine(getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - 1 + i,
+ getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - 1 + i,
+ paint);
+ }
+
+ if (isLeft && isTop) {
+ canvas.drawCircle(getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ edgeRadius + i, paint);
+ } else if (isLeft && !isTop && (p.getX() == 0 || !c.includes(Position.get(p.getX() - 1, p.getY() - 1)))) {
+ canvas.drawLine(getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - i,
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - edgeRadius,
+ getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - i,
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ paint);
+ } else if (!isLeft && isTop && (p.getY() == 0 || !c.includes(Position.get(p.getX() - 1, p.getY() - 1)))) {
+ canvas.drawLine(getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - i,
+ getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - i,
+ paint);
+ }
+
+ if (isRight && isTop) {
+ canvas.drawCircle(getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - edgeRadius,
+ getCurrentTopMargin() + p.getY() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ edgeRadius + i, paint);
+ }
+
+ if (isLeft && isBottom) {
+ canvas.drawCircle(getCurrentLeftMargin() + p.getX() * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ edgeRadius + i, paint);
+ }
+ if (isRight && isBottom) {
+ canvas.drawCircle(getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ edgeRadius + i, paint);
+ } else if (isRight && !isBottom && !c.includes(Position.get(p.getX() + 1, p.getY() + 1))) {
+ canvas.drawLine(getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - 1 + i,
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - edgeRadius,
+ getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - 1 + i,
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ paint);
+ } else if (!isRight && isBottom && !c.includes(Position.get(p.getX() + 1, p.getY() + 1))) {
+ canvas.drawLine(getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - edgeRadius - getCurrentSpacing(),
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - 1 + i,
+ getCurrentLeftMargin() + (p.getX() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) + edgeRadius,
+ getCurrentTopMargin() + (p.getY() + 1) * (int) (this.getCurrentFieldViewSize() + getCurrentSpacing()) - getCurrentSpacing() - 1 + i,
+ paint);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Zoom so heraus, dass ein diese View optimal in ein Layout der
+ * spezifizierte Größe passt
+ *
+ * @param width
+ * Die Breite auf die optimiert werden soll
+ * @param height
+ * Die Höhe auf die optimiert werden soll
+ */
+ public void optiZoom(int width, int height) {
+ Log.d(LOG_TAG, "SudokuView height intern: " + this.getMeasuredHeight());
+ TypeBasic sudokuType = this.game.getSudoku().getSudokuType();
+ int size = width < height ? width : height;
+ int numberOfFields = width < height ? sudokuType.getSize().getX() : sudokuType.getSize().getY();
+ this.defaultFieldViewSize = (size - (numberOfFields + 1) * spacing) / numberOfFields;
+ // this.currentFieldViewSize = this.defaultFieldViewSize;
+
+ this.leftMargin = (int) (width - sudokuType.getSize().getX() *
+ (this.getCurrentFieldViewSize() + spacing) + spacing)
+ / 2;
+ this.topMargin = (int) (height - sudokuType.getSize().getY() *
+ (this.getCurrentFieldViewSize() + spacing) + spacing)
+ / 2;
+ Log.d(LOG_TAG, "Sudoku width: " + width);
+ Log.d(LOG_TAG, "Sudoku height: " + height);
+ this.refresh();
+ }
+
+ /**
+ * Touch-Events werden nicht verarbeitet.
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return false;
+
+ }
+
+ /**
+ * Gibt das Array der SudokuFieldViews zurück.
+ *
+ * @return Das Array der SudokuFieldViews
+ */
+ public SudokuFieldView[][] getSudokuFieldViews() {
+ return this.sudokuFieldViews;
+ }
+
+ /**
+ * Setzt den aktuellen Zoom-Faktor für diese View und refresh sie.
+ *
+ * @param factor
+ * Der Zoom-Faktor
+ */
+ public void setZoomFactor(float factor) {
+ this.zoomFactor = factor;
+ refresh();
+ }
+
+ /**
+ * Gibt die aktuell aktive SudokuFieldView dieser View zurück.
+ *
+ * @return Die aktive SudokuFieldView
+ */
+ public SudokuFieldView getCurrentFieldView() {
+ return this.currentFieldView;
+ }
+
+ /**
+ * Setzt die aktuelle SudokuFieldView
+ *
+ * @param currentFieldView
+ * die zu setzende SudokuFieldView
+ */
+ public void setCurrentFieldView(SudokuFieldView currentFieldView) {
+ this.currentFieldView = currentFieldView;
+ }
+
+ /**
+ * Gibt die aktuelle Größe einer FieldView zurück.
+ *
+ * @return die aktuelle Größe einer FieldView
+ */
+ private int getCurrentFieldViewSize() {
+ return (int) (this.defaultFieldViewSize * zoomFactor);
+ }
+
+ /**
+ * Unbenutzt.
+ *
+ * @throws UnsupportedOperationException
+ * Wirft immer eine UnsupportedOperationException
+ */
+ public void notifyListener() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void registerListener(FieldInteractionListener listener) {
+ TypeBasic sudokuType = this.game.getSudoku().getSudokuType();
+ for (int x = 0; x < sudokuType.getSize().getX(); x++) {
+ for (int y = 0; y < sudokuType.getSize().getY(); y++) {
+ if (this.game.getSudoku().getField(Position.get(x, y)) != null)
+ this.sudokuFieldViews[x][y].registerListener(listener);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeListener(FieldInteractionListener listener) {
+ TypeBasic sudokuType = this.game.getSudoku().getSudokuType();
+ for (int x = 0; x < sudokuType.getSize().getX(); x++) {
+ for (int y = 0; y < sudokuType.getSize().getY(); y++) {
+ if (this.game.getSudoku().getField(Position.get(x, y)) != null)
+ this.sudokuFieldViews[x][y].removeListener(listener);
+ }
+ }
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/view/VirtualKeyboardButtonView.java b/sudoq-app/src/de/sudoq/view/VirtualKeyboardButtonView.java
new file mode 100644
index 00000000..84804cf1
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/VirtualKeyboardButtonView.java
@@ -0,0 +1,143 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.TableLayout.LayoutParams;
+import de.sudoq.controller.sudoku.FieldViewPainter;
+import de.sudoq.controller.sudoku.FieldViewStates;
+import de.sudoq.controller.sudoku.InputListener;
+import de.sudoq.controller.sudoku.ObservableInput;
+import de.sudoq.controller.sudoku.Symbol;
+
+/**
+ * Diese Subklasse des Android internen Views stellt einen Button in der
+ * Eingabeansicht des Sudokus dar.
+ */
+public class VirtualKeyboardButtonView extends View implements ObservableInput {
+ /** Attributes */
+
+ /**
+ * Das mit diesem VirtualKeyboardButtonView assoziierte Symbol. Es handlet
+ * sich um einen int, da ein generische Zeichensatz unterstützt werden soll,
+ * in dem die Symbole durch int repräsentiert werden.
+ */
+ private int symbol;
+
+ /**
+ * Das Symbol, welches in diesem Button steht so, wie es gemalt wird
+ */
+ private String drawnSymbol;
+
+ /**
+ * Diese Listener werden benachrichtigt, wenn der Benutzer mit diesem
+ * VirtualKeyboardButtonView interagiert, bspw. durch Anlicken.
+ */
+ private ArrayList inputListener;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert eine neue VirtualKeyboardButtonView
+ *
+ * @param context
+ * Der Kontext, in dem diese View angezeigt wird
+ * @param symbol
+ * die interne Id des Symbols
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls der übergebene Kontext null ist
+ */
+ public VirtualKeyboardButtonView(Context context, int symbol) {
+ super(context);
+ this.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1.0f));
+ this.symbol = symbol;
+ this.drawnSymbol = Symbol.getInstance().getMapping(symbol);
+ this.inputListener = new ArrayList();
+
+ FieldViewPainter.getInstance().setMarking(this, FieldViewStates.DEFAULT_BORDER);
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode verarbeitet alle Touch Inputs, die der Benutzer macht und
+ * leitet sie an den InputListener weiter.
+ *
+ * @param motionEvent
+ * Das Event, das von der API generiert wird
+ * @return true, falls das Event bearbeitet wurde, false falls nicht
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene MotionEvent null ist
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent motionEvent) {
+ if (this.isEnabled())
+ notifyListeners();
+
+ return false;
+ }
+
+ /**
+ * Zeichnet den VirtualKeyboardButtonView inklusive dessen Symbol abhängig
+ * vom Status (an/aus).
+ *
+ * @param canvas
+ * Das Canvas Objekt auf das gezeichnet wird
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls canvas null ist
+ */
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ FieldViewPainter.getInstance().markField(canvas, this, this.drawnSymbol, false, false);
+ if (!this.isEnabled()) {
+ canvas.drawARGB(100, 10, 10, 10);
+ }
+ }
+
+ /**
+ * Fügt einen InputListener diesem VirtualKeyboardButtonView hinzu um ihn
+ * benachrichtigen zu können.
+ *
+ * @param listener
+ * Ein InputListener der bei interaktion mit diesem
+ * VirtualKeyboardButtonView benachricht wird
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls listener null ist
+ */
+ public void registerListener(InputListener listener) {
+ this.inputListener.add(listener);
+ }
+
+ /**
+ * Löscht einen InputListener aus diesem VirtualKeyboardButtonView der
+ * daraufhin nicht weiter benachricht wird.
+ *
+ * @param listener
+ * Ein InputListener der vom VirtualKeyboardButtonView gelöst
+ * werden soll
+ */
+ public void removeListener(InputListener listener) {
+ this.inputListener.remove(listener);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void notifyListeners() {
+ for (InputListener listener : this.inputListener) {
+ listener.onInput(this.symbol);
+ }
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/view/VirtualKeyboardLayout.java b/sudoq-app/src/de/sudoq/view/VirtualKeyboardLayout.java
new file mode 100644
index 00000000..1aac5eb7
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/VirtualKeyboardLayout.java
@@ -0,0 +1,224 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+import de.sudoq.controller.sudoku.FieldViewPainter;
+import de.sudoq.controller.sudoku.FieldViewStates;
+import de.sudoq.controller.sudoku.InputListener;
+import de.sudoq.controller.sudoku.ObservableInput;
+
+/**
+ * Dieses Layout stellt ein virtuelles Keyboard zur Verfügung, in dem sich die
+ * Buttons möglichst quadratisch ausrichten.
+ */
+public class VirtualKeyboardLayout extends LinearLayout implements ObservableInput {
+
+ /**
+ * Die Buttons des VirtualKeyboard
+ */
+ private VirtualKeyboardButtonView[][] buttons;
+
+ /**
+ * Beschreibt, ob die Tastatur deaktiviert ist.
+ */
+ private boolean deactivated;
+
+ /**
+ * Instanziiert ein neues VirtualKeyboardLayout mit den gegebenen Parametern
+ *
+ * @param context
+ * der Applikationskontext
+ * @param attrs
+ * das Android AttributeSet
+ */
+ public VirtualKeyboardLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ this.setWillNotDraw(false);
+ }
+
+ /**
+ * Aktualisiert das Keyboard, sodass für das angegebene Game die korrekten
+ * Buttons dargestellt werden.
+ *
+ * @param numberOfButtons
+ * Die Anzahl der Buttons für dieses Keyboard
+ */
+ public void refresh(int numberOfButtons) {
+ if (numberOfButtons < 0)
+ return;
+ this.deactivated = false;
+ inflate(numberOfButtons);
+ }
+
+ /**
+ * Inflatet das Keyboard.
+ *
+ * @param numberOfButtons
+ * Anzahl der Buttons dieser Tastatur
+ */
+ private void inflate(int numberOfButtons) {
+ this.removeAllViews();
+ int buttonsPerColumn = (int) Math.floor(Math.sqrt(numberOfButtons));
+ int buttonsPerRow = (int) Math.ceil(Math.sqrt(numberOfButtons));
+ this.buttons = new VirtualKeyboardButtonView[buttonsPerRow][buttonsPerColumn];
+
+ for (int y = 0; y < buttonsPerColumn; y++) {
+ LinearLayout la = new LinearLayout(getContext());
+ for (int x = 0; x < buttonsPerRow; x++) {
+ this.buttons[x][y] = new VirtualKeyboardButtonView(getContext(), x + y * buttonsPerRow);
+ this.buttons[x][y].setVisibility(View.INVISIBLE);
+ LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1.0f);
+ params.leftMargin = 2;
+ params.bottomMargin = 2;
+ params.topMargin = 2;
+ params.rightMargin = 2;
+ la.addView(this.buttons[x][y], params);
+ }
+ addView(la, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, 1.0f));
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+// FieldViewPainter.getInstance().markField(canvas, this, ' ', false);
+ }
+
+ /**
+ * Aktiviert bzw. deaktiviert dieses Keyboard.
+ *
+ * @param activated
+ * Spezifiziert, ob das Keyboard aktiviert oder deaktiviert sein
+ * soll
+ */
+ public void setActivated(boolean activated) {
+ this.deactivated = !activated;
+ int buttonsPerRow = this.buttons.length;
+ int buttonsPerColumn = this.buttons[0].length;
+ for (int x = 0; x < buttonsPerRow; x++) {
+ for (int y = 0; y < buttonsPerColumn; y++) {
+ if (deactivated) {
+ this.buttons[x][y].setVisibility(View.INVISIBLE);
+ } else {
+ this.buttons[x][y].setVisibility(View.VISIBLE);
+ }
+ }
+ }
+ }
+
+ /**
+ * Unbenutzt.
+ *
+ * @throws UnsupportedOperationException
+ * Wirft immer eine UnsupportedOperationException
+ */
+ public void notifyListeners() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void registerListener(InputListener listener) {
+ int buttonsPerRow = this.buttons.length;
+ int buttonsPerColumn = this.buttons[0].length;
+ for (int x = 0; x < buttonsPerRow; x++) {
+ for (int y = 0; y < buttonsPerColumn; y++) {
+ this.buttons[x][y].registerListener(listener);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void removeListener(InputListener listener) {
+ int buttonsPerRow = this.buttons.length;
+ int buttonsPerColumn = this.buttons[0].length;
+ for (int x = 0; x < buttonsPerRow; x++) {
+ for (int y = 0; y < buttonsPerColumn; y++) {
+ this.buttons[x][y].removeListener(listener);
+ }
+ }
+ }
+
+ /**
+ * Markiert das spezifizierte Feld mit dem übergebenen Status, um von dem
+ * FieldViewPainter entsprechend gezeichnet zu werden.
+ *
+ * @param symbol
+ * Das Symbol des Feldes
+ * @param state
+ * Der zu setzende Status
+ */
+ public void markField(int symbol, FieldViewStates state) {
+ int buttonsPerRow = this.buttons.length;
+ FieldViewPainter.getInstance().setMarking(this.buttons[symbol % buttonsPerRow][symbol / buttonsPerRow], state);
+ this.buttons[symbol % buttonsPerRow][symbol / buttonsPerRow].invalidate();
+ }
+
+ /**
+ * Aktiviert alle Buttons dieses Keyboards.
+ */
+ public void enableAllButtons() {
+ int buttonsPerRow = this.buttons.length;
+ int buttonsPerColumn = this.buttons[0].length;
+ for (int x = 0; x < buttonsPerRow; x++) {
+ for (int y = 0; y < buttonsPerColumn; y++) {
+ this.buttons[x][y].setEnabled(true);
+ }
+ }
+ }
+
+ /**
+ * Deaktiviert den spezifizierten Button.
+ *
+ * @param symbol
+ * Das Symbol des zu deaktivierenden Button
+ */
+ public void disableButton(int symbol) {
+ int buttonsPerRow = this.buttons.length;
+ this.buttons[symbol % buttonsPerRow][symbol / buttonsPerRow].setEnabled(false);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void invalidate() {
+ if (this.buttons == null) {
+ return;
+ }
+
+ int buttonsPerRow = this.buttons.length;
+ int buttonsPerColumn = this.buttons[0].length;
+ for (int x = 0; x < buttonsPerRow; x++) {
+ for (int y = 0; y < buttonsPerColumn; y++) {
+ if (this.buttons[x][y] != null)
+ this.buttons[x][y].invalidate();
+ }
+ }
+ }
+
+ /**
+ * Gibt zurueck ob die view angezeigt wird
+ *
+ * @return true falls aktive andernfalls false
+ */
+ public boolean isActivated() {
+ return !deactivated;
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/view/actionTree/ActionElement.java b/sudoq-app/src/de/sudoq/view/actionTree/ActionElement.java
new file mode 100644
index 00000000..3d8b5776
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/actionTree/ActionElement.java
@@ -0,0 +1,38 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view.actionTree;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import de.sudoq.controller.sudoku.ActionTreeController;
+import de.sudoq.model.actionTree.ActionTreeElement;
+
+/**
+ * Die ActionElementView stellt im ActionTree eine einfache Aktion dar.
+ *
+ */
+public class ActionElement extends ActionTreeElementView {
+
+ /** Methods */
+
+ public ActionElement(Context context, ActionTreeElementView inner, ActionTreeElement ate) {
+ super(context, inner, ate);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void paintCanvas(Canvas canvas) {
+ Paint elementPaint = new Paint();
+ elementPaint.setColor(actionColor);
+ int rectSize = (int) ((float) ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 3);
+ canvas.drawRect(rectSize, rectSize, ActionTreeController.MAX_ELEMENT_VIEW_SIZE - rectSize, ActionTreeController.MAX_ELEMENT_VIEW_SIZE - rectSize, elementPaint);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/view/actionTree/ActionTreeElementView.java b/sudoq-app/src/de/sudoq/view/actionTree/ActionTreeElementView.java
new file mode 100644
index 00000000..d9ac7edc
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/actionTree/ActionTreeElementView.java
@@ -0,0 +1,160 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view.actionTree;
+
+import java.util.ArrayList;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.view.MotionEvent;
+import android.view.View;
+import de.sudoq.controller.sudoku.ActionTreeNavListener;
+import de.sudoq.model.actionTree.ActionTreeElement;
+
+/**
+ * Diese Klasse ist ein angepasster View, der von der Android API als
+ * Interaktionselement genutzt wird. Es wird die Benutzerinteraktion sowie die
+ * Erscheinung definiert.
+ */
+public abstract class ActionTreeElementView extends View {
+
+ /** Attributes */
+
+ /**
+ * Default Action Color
+ */
+ public static final int DEFAULT_COLOR = 0xFFFFAD00;
+
+ public static final int WRONG_COLOR = 0xFFCC1F1F;
+
+ public static final int CORRECT_COLOR = 0xFF1FCC1F;
+
+ protected int actionColor = DEFAULT_COLOR;
+
+ protected ActionTreeElementView inner = null;
+
+ /**
+ * Das Element des Aktionsbaumes das von diesem View representiert wird
+ */
+ private ActionTreeElement actionTreeElement;
+
+ /**
+ * Die Objekte, die auf Navigations-Änderungen an diesem View reagieren
+ * sollen
+ */
+ private ArrayList actionTreeNavListener;
+
+ /** Constructors */
+
+ /**
+ * Erstellt ein neuen ActionTreeElementView und setzt das zugehörige
+ * ActionTreeElement und regestriert einen ActionTreeNavListener.
+ *
+ * @param context
+ * Der Kontekt, in dem die View angezeigt wird
+ * @param ate
+ * Das Element im Aktionsbaum, dass von diesem
+ * ActionTreeElementView dargestellt wird
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls eines der Argumente null ist
+ */
+ public ActionTreeElementView(Context context, ActionTreeElementView inner, ActionTreeElement ate) {
+ super(context);
+ this.actionTreeElement = ate;
+ this.actionTreeNavListener = new ArrayList();
+ this.inner = inner;
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode wird von der API aufgerufen, sollte dieser View berührt
+ * werden. An dieser Stelle wird auch die Art der Eingabe ermittelt und es
+ * werden die entsprechenden Aktionen ausgeführt bzw. Listener aufgerufen.
+ *
+ * @param motionEvent
+ * Das Event, das von der API generiert wird
+ * @return true, falls das Event bearbeitet wurde, sonst false
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene MotionEvent null ist
+ */
+ @Override
+ public boolean onTouchEvent(MotionEvent motionEvent) {
+ if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
+ for (ActionTreeNavListener listener : this.actionTreeNavListener) {
+ listener.onLoadState(this.actionTreeElement);
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Sets the color of this Element to draw
+ *
+ * @param color
+ * as an hex color
+ */
+ public void changeColor(int color) {
+ actionColor = color;
+ if (inner != null) {
+ inner.changeColor(color);
+ }
+ }
+
+ /**
+ * Diese Methode definiert die Erscheinung des Views. Auf dem von der API
+ * übergebenen Canvas Objekt wird programmatisch, oder via Bitmap das
+ * Aussehen gezeichnet.
+ *
+ * @param canvas
+ * Das Canvas Objekt auf das gezeichnet wird
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Canvas null ist
+ */
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ paint(canvas);
+ }
+
+ protected void paint(Canvas canvas) {
+ if (inner != null) {
+ inner.paint(canvas);
+ }
+ paintCanvas(canvas);
+ }
+
+ /**
+ * Template Methode, die das Canvas der View zeichnet.
+ *
+ * @param canvas
+ * Das Canvas, das bemalt werden soll.
+ */
+ public abstract void paintCanvas(Canvas canvas);
+
+ /**
+ * Erlaubt die Registrierung von Listenern
+ *
+ * @param actionTreeNavListener
+ * der zu registrierende Listener
+ */
+ public void registerActionTreeNavListener(ActionTreeNavListener actionTreeNavListener) {
+ this.actionTreeNavListener.add(actionTreeNavListener);
+ }
+
+ /**
+ * Erlaubt die deregistrierung von Listenern
+ *
+ * @param actionTreeNavListener
+ * der zu deregistrierende Listener
+ */
+ public void removeActionTreeNavListener(ActionTreeNavListener actionTreeNavListener) {
+ this.actionTreeNavListener.remove(actionTreeNavListener);
+ }
+
+}
diff --git a/sudoq-app/src/de/sudoq/view/actionTree/ActiveElement.java b/sudoq-app/src/de/sudoq/view/actionTree/ActiveElement.java
new file mode 100644
index 00000000..34d3b52e
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/actionTree/ActiveElement.java
@@ -0,0 +1,51 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view.actionTree;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import de.sudoq.controller.sudoku.ActionTreeController;
+import de.sudoq.model.actionTree.ActionTreeElement;
+
+/**
+ * Diese Subklasse des ActionTreeElements definiert das Aussehen des aktuellen
+ * Elements innerhalb des Aktionsbaumes.
+ */
+public class ActiveElement extends ActionTreeElementView {
+
+ /**
+ * Die Farbe für das aktive Element
+ */
+ public static final int ACTIVE_COLOR = 0xFFFF4B00;
+
+ /** Constructors */
+
+ public ActiveElement(Context context, ActionTreeElementView inner, ActionTreeElement ate) {
+ super(context, inner, ate);
+ }
+
+ /** Methods */
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void paintCanvas(Canvas canvas) {
+ Paint activePaint = new Paint();
+ activePaint.setColor(ACTIVE_COLOR);
+ int stroke = (int) ((float) ActionTreeController.MAX_ELEMENT_VIEW_SIZE * 0.1);
+ activePaint.setStrokeWidth(stroke);
+ activePaint.setStyle(Style.STROKE);
+ activePaint.setAntiAlias(true);
+ int radius = (int) ((float) ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2.1);
+
+ canvas.drawCircle(ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2, ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2, radius, activePaint);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/view/actionTree/BookmarkedElement.java b/sudoq-app/src/de/sudoq/view/actionTree/BookmarkedElement.java
new file mode 100644
index 00000000..ac9edd94
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/actionTree/BookmarkedElement.java
@@ -0,0 +1,51 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view.actionTree;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import de.sudoq.controller.sudoku.ActionTreeController;
+import de.sudoq.model.actionTree.ActionTreeElement;
+
+/**
+ * Diese Subklasse des ActionTreeElements definiert das Aussehen eines als
+ * Lesezeichen markierten Elements.
+ */
+public class BookmarkedElement extends ActionTreeElementView {
+
+ /**
+ * Die Farbe der Bookmark-Elemente
+ */
+ private static final int BOOKMARK_COLOR = 0xFFFF4B00;
+
+ public BookmarkedElement(Context context, ActionTreeElementView inner, ActionTreeElement ate) {
+ super(context, inner, ate);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void paintCanvas(Canvas canvas) {
+ // Paint elementPaint = new Paint();
+ // elementPaint.setColor(BOOKMARK_COLOR);
+ // elementPaint.setAntiAlias(true);
+ // int radius = (int) ((float)
+ // ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 3.1);
+ // canvas.drawCircle(ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2,
+ // ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2, radius,
+ // elementPaint);
+
+ Paint innerPaint = new Paint();
+ innerPaint.setColor(actionColor);
+ innerPaint.setAntiAlias(true);
+ int innerRadius = (int) (((float) ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 6) * 1.42);
+ canvas.drawCircle(ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2, ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2, innerRadius, innerPaint);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/view/actionTree/BranchingElement.java b/sudoq-app/src/de/sudoq/view/actionTree/BranchingElement.java
new file mode 100644
index 00000000..c666f88d
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/actionTree/BranchingElement.java
@@ -0,0 +1,53 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view.actionTree;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import de.sudoq.controller.sudoku.ActionTreeController;
+import de.sudoq.model.actionTree.ActionTreeElement;
+
+/**
+ * Diese Subklasse des ActionTreeElements definiert die Erscheinung eines
+ * gespeicherten Lesezeichens im Aktionsbaum.
+ */
+public class BranchingElement extends ActionTreeElementView {
+
+ /** Constructors */
+
+ public BranchingElement(Context context, ActionTreeElementView inner, ActionTreeElement ate) {
+ super(context, inner, ate);
+ }
+
+ /** Methods */
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void paintCanvas(Canvas canvas) {
+ Paint elementPaint = new Paint();
+ elementPaint.setColor(actionColor);
+ elementPaint.setStyle(Style.STROKE);
+ elementPaint.setStrokeWidth(8);
+ elementPaint.setAntiAlias(true);
+ int radius = (int) ((float) ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 3);
+ canvas.drawCircle(ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2, ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2, radius, elementPaint);
+
+ // Paint innerPaint = new Paint();
+ // innerPaint.setColor(actionColor);
+ // innerPaint.setAntiAlias(true);
+ // int innerRadius = (int) ((float)
+ // ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 6);
+ // canvas.drawCircle(ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2,
+ // ActionTreeController.MAX_ELEMENT_VIEW_SIZE / 2, innerRadius,
+ // innerPaint);
+ }
+}
diff --git a/sudoq-app/src/de/sudoq/view/actionTree/BranchingLine.java b/sudoq-app/src/de/sudoq/view/actionTree/BranchingLine.java
new file mode 100644
index 00000000..1ad19461
--- /dev/null
+++ b/sudoq-app/src/de/sudoq/view/actionTree/BranchingLine.java
@@ -0,0 +1,75 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.view.actionTree;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.view.View;
+import de.sudoq.controller.sudoku.ActionTreeController;
+
+/**
+ * Klasse zur Darstellung von Verbindungslinien zwischen Elementen im ActionTree
+ */
+public class BranchingLine extends View {
+
+ /** Attributes */
+ @SuppressWarnings("unused")
+ private static final String LOG_TAG = BranchingLine.class.getSimpleName();
+
+ /**
+ * Die Höhe der Linie
+ */
+ private int height;
+
+ /**
+ * Die Breite der Linie
+ */
+ private int width;
+
+ /** Constructors */
+
+ /**
+ * Erzeugt die View für die Darstellung einer Linie für den ActionTree
+ *
+ * @param context
+ * der Applikationskontext
+ * @param fromX
+ * der x Wert der Startposition in Rasterkoordinaten des
+ * ActionTreeControllers
+ * @param fromY
+ * der y Wert der Startposition in Rasterkoordinaten des
+ * ActionTreeControllers
+ * @param toX
+ * der x Wert der Endposition in Rasterkoordinaten des
+ * ActionTreeControllers
+ * @param toY
+ * der y Wert der Endposition in Rasterkoordinaten des
+ * ActionTreeControllers
+ */
+ public BranchingLine(Context context, int fromX, int fromY, int toX, int toY) {
+ super(context);
+ this.width = toY - fromY;
+ this.height = toX - fromX;
+ }
+
+ /** Methods */
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ Paint linePaint = new Paint();
+ linePaint.setStrokeWidth(5);
+ linePaint.setStyle(Style.STROKE);
+ linePaint.setColor(ActionTreeElementView.DEFAULT_COLOR);
+ linePaint.setAlpha(180);
+ linePaint.setAntiAlias(true);
+ canvas.drawLine(ActionTreeController.AT_RASTER_SIZE / 2, ActionTreeController.AT_RASTER_SIZE / 2, this.width + ActionTreeController.AT_RASTER_SIZE / 2, this.height, linePaint);
+ }
+}
diff --git a/sudoq-model/.classpath b/sudoq-model/.classpath
new file mode 100755
index 00000000..fb501163
--- /dev/null
+++ b/sudoq-model/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/sudoq-model/.project b/sudoq-model/.project
new file mode 100755
index 00000000..71f5f7df
--- /dev/null
+++ b/sudoq-model/.project
@@ -0,0 +1,17 @@
+
+
+ sudoqModel
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/sudoq-model/.settings/org.eclipse.ltk.core.refactoring.prefs b/sudoq-model/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 00000000..b196c64a
--- /dev/null
+++ b/sudoq-model/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,2 @@
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=false
diff --git a/sudoq-model/build.xml b/sudoq-model/build.xml
new file mode 100644
index 00000000..f14ceae9
--- /dev/null
+++ b/sudoq-model/build.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sudoq-model/src/de/sudoq/model/ModelChangeListener.java b/sudoq-model/src/de/sudoq/model/ModelChangeListener.java
new file mode 100644
index 00000000..f809b4df
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/ModelChangeListener.java
@@ -0,0 +1,29 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model;
+
+/**
+ * Dieses Interface definiert die Schnittstelle für alle Klassen die über
+ * Änderungen in einer Model-Klasse benachrichtigt werden wollen.
+ *
+ * @param
+ * der Typ des Objekts welches bei Änderungen mitgegeben wird
+ */
+public interface ModelChangeListener {
+ /** Methods */
+
+ /**
+ * Diese Methode wird aufgerufen, falls sich etwas im beobachteten Model
+ * ändert.
+ *
+ * @param obj
+ * Das Objekt, das sich geaendert hat. Kann auch null sein
+ */
+ public void onModelChanged(T obj);
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/ObservableModel.java b/sudoq-model/src/de/sudoq/model/ObservableModel.java
new file mode 100644
index 00000000..f0620878
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/ObservableModel.java
@@ -0,0 +1,50 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model;
+
+/**
+ * Dieses Interface wird von allen Model-Klassen implementiert, die beobachtet
+ * werden können. Bei Änderungen benachrichtigen sie alle beobachtenden Objekte.
+ *
+ * @param
+ * der Typ des Objekts welches bei Änderungen mitgegeben wird
+ */
+public interface ObservableModel {
+ /** Methods */
+
+ /**
+ * Beim Aufruf dieser Methode werden alle beobachtenden Objekte
+ * benachrichtigt.
+ *
+ * @param obj
+ * Das Objekt, das sich geaendert hat.
+ */
+ public void notifyListeners(T obj);
+
+ /**
+ * Mit dieser Methode kann sich ein Objekt registrieren, um bei allen
+ * zukünfitgen Änderungen benachrichtigt zu werden.
+ *
+ * @param listener
+ * Das einzutragenden Objekt
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls der übergebene Listener null ist
+ */
+ public void registerListener(ModelChangeListener listener);
+
+ /**
+ * Mit diser Methode kann das gegebene Objekt aus der Beobachter-Liste
+ * entfernt werden. Bei zukünfitgen Änderugen wird das Objekt nicht mehr
+ * benachrichtigt. Ist das Objekt nicht in der Liste passiert nichts.
+ *
+ * @param listener
+ * Das zu entfernende Objekt.
+ */
+ public void removeListener(ModelChangeListener listener);
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/ObservableModelImpl.java b/sudoq-model/src/de/sudoq/model/ObservableModelImpl.java
new file mode 100644
index 00000000..cac82198
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/ObservableModelImpl.java
@@ -0,0 +1,54 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Eine Default Implementierung fuer das ObservableModel Interface
+ *
+ * @param
+ * der sich aendernde Typ
+ * @see ObservableModel
+ */
+public abstract class ObservableModelImpl implements ObservableModel {
+
+ private List> listeners = new ArrayList>();
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyListeners(T obj) {
+ for (int i = 0; i < listeners.size(); i++) {
+ listeners.get(i).onModelChanged(obj);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void registerListener(ModelChangeListener listener) {
+ if (listener != null) {
+ listeners.add(listener);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void removeListener(ModelChangeListener listener) {
+ listeners.remove(listener);
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/Action.java b/sudoq-model/src/de/sudoq/model/actionTree/Action.java
new file mode 100644
index 00000000..9ef9e7d6
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/Action.java
@@ -0,0 +1,84 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Diese Klasse repräsentiert eine Aktion auf einem Sudoku-Feld die vorwärts und
+ * rückwärts ausgeführt werden kann.
+ */
+public abstract class Action {
+ /** Attributes */
+
+ /**
+ * Der Wert diff speichert die Unterschiede zwischen altem und neuem Wert.
+ */
+ protected int diff;
+
+ /**
+ * Das Sudoku-Feld auf dem die Action ausgeführt wird
+ */
+ protected Field field;
+
+ /** Constructors */
+
+ /**
+ * Ein geschützter Konstruktor um die Instanziierung von Actions außerhalb
+ * dieses Packages zu vermeiden. Wird er aufgerufen wird eine neue Action
+ * mit den gegebenen Parametern instanziiert. Ist das spezifizierte Field
+ * null, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param diff
+ * Der Unterschied zwischen altem und neuem Wert
+ * @param field
+ * Das zu bearbeitende Feld
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Field null ist
+ */
+ protected Action(int diff, Field field) {
+ this.diff = diff;
+ if (field != null) {
+ this.field = field;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ };
+
+ /**
+ * Führt diese Aktion aus.
+ */
+ abstract public void execute();
+
+ /**
+ * Macht diese Aktion rückgängig.
+ */
+ abstract public void undo();
+
+ /**
+ * Gibt die id des von dieser Action bearbeiteten Feldes zurück.
+ *
+ * @return die Feld id.
+ */
+ public int getFieldId() {
+ return field.getId();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o != null && o.getClass().equals(this.getClass())) {
+ Action other = (Action) o;
+ return this.diff == other.diff && this.field.equals(other.field);
+ }
+ return false;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/ActionFactory.java b/sudoq-model/src/de/sudoq/model/actionTree/ActionFactory.java
new file mode 100644
index 00000000..a543d395
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/ActionFactory.java
@@ -0,0 +1,33 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Dieses Interface definiert die Schnittstelle für Klassen, die konkrete
+ * Actions für das Arbeiten auf bestimmten Eigenschaften eines Sudoku-Feldes
+ * erzeugen und instanziieren können. Auf welcher Eigenschaft sie arbeitet
+ * definiert die implementierende Klasse.
+ */
+public interface ActionFactory {
+
+ /**
+ * Erzeugt eine neue Action die bei Ausführung den gegebenen Wert in die
+ * zugehörige Eigenschaft (die der implementierenden Klasse) des gegebenen
+ * Feldes einträgt.
+ *
+ * @param value
+ * Der einzutragende Wert
+ * @param field
+ * Das von der Action zu bearbeitende Feld
+ * @return Die erzeugt Aktion
+ */
+ public Action createAction(int value, Field field);
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/ActionTree.java b/sudoq-model/src/de/sudoq/model/actionTree/ActionTree.java
new file mode 100644
index 00000000..7de4d74a
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/ActionTree.java
@@ -0,0 +1,270 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Stack;
+
+import de.sudoq.model.ObservableModelImpl;
+
+/**
+ * Diese Klasse repräsentiert die Menge aller Züge auf einem Sudoku. Sie erlaubt
+ * von einem Zustand aus verschiedene Wege aus weiterzuverfolgen. Folglich
+ * ergeben die Züge einen Baum.
+ */
+public class ActionTree extends ObservableModelImpl implements Iterable {
+ /** Attributes */
+
+ /**
+ * Der Ursprungsknoten des Baumes
+ */
+ protected ActionTreeElement rootElement;
+ /**
+ * Zaehlt die Elemente um jedem Element eine eindeutige id zu geben.
+ */
+ private int idCounter;
+
+ /** Constructors */
+
+ /**
+ * Erzeugt und instanziiert einen neuen ActionTree
+ */
+ public ActionTree() {
+ idCounter = 1;
+ rootElement = null;
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode fügt die gegebene Action an der gegebenen Stelle zum Baum
+ * hinzu. Beide dürfen nicht null sein (NullPointerException).
+ *
+ * @param action
+ * Die hinzuzufügende Action
+ * @param mountingElement
+ * Das Element unter dem die Aktion eingehangen werden soll. Es
+ * wird NICHT überprüft, ob dieses Teil des Baums ist
+ * @return Das neue Element, das die gegebene Aktion enthält.
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls eines der übergebenen Attribute null ist
+ * (ausser der Baum ist noch leer, dann darf mountingElement
+ * null sein)
+ */
+ public ActionTreeElement add(Action action, ActionTreeElement mountingElement) {
+
+ ActionTreeElement ate = new ActionTreeElement(idCounter, action, mountingElement);
+
+ if (rootElement != null) {
+ if (mountingElement == null) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ rootElement = ate;
+ }
+
+ idCounter++;
+ notifyListeners(ate);
+ return ate;
+ }
+
+ /**
+ * Diese Methode durchsucht den Baum nach dem Element mit der gegebenen id.
+ * Gegebenenfalls wird es zurückgegeben, andernfalls null.
+ *
+ * @param id
+ * Die id des zu suchenden Elements
+ * @return Das gefundene Element oder null
+ */
+ public ActionTreeElement getElement(int id) {
+ if (id < idCounter && id >= 1) {
+ ActionTreeElement currentElement = rootElement;
+ Stack otherPaths = new Stack();
+
+ // earlier while (currentElement != null) but since an element will
+ // be found since the id range fits we can go with while true
+ while (true) {
+ if (currentElement.getId() == id) {
+ return currentElement;
+ }
+
+ for (int i = currentElement.getChildrenList().size() - 1; i >= 0; i--) {
+ if (currentElement.getChildrenList().get(i).getId() <= id) {
+ otherPaths.push(currentElement.getChildrenList().get(i));
+ }
+ }
+
+ currentElement = otherPaths.pop();
+ // if (!otherPaths.empty()) {
+ // currentElement = otherPaths.pop();
+ // } else {
+ // this will never be reached cause in the beginning we check
+ // that the searched id exists in this tree, so we can always
+ // pop
+ // currentElement = null;
+ // }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Gibt die Anzahl der Elemente im Baum zurück
+ *
+ * @return die Anzahl
+ */
+ public int getSize() {
+ return idCounter - 1;
+ }
+
+ /**
+ * Gibt zurück ob der Baum leer ist
+ *
+ * @return true falls er leer ist, false falls Elemente enthalten sind
+ */
+ public boolean isEmpty() {
+ return idCounter == 1;
+ }
+
+ /**
+ * Gibt das Wurzelelemtn dieses Baums zurueck
+ *
+ * @return das Wurzelelment
+ */
+ public ActionTreeElement getRoot() {
+ return rootElement;
+ }
+
+ /**
+ * Überprüft den Baum ausgehend vom Wurzelelement auf Konsistenz. Es dürfen
+ * keine Zyklen auftreten.
+ *
+ * @return true falls der Baum konsistent ist, andernfalls false
+ */
+ public boolean isConsitent() {
+ LinkedList elements = new LinkedList();
+ for (ActionTreeElement ate : this) {
+ if (elements.contains(ate)) {
+ return false;
+ }
+ elements.add(ate);
+ }
+ return true;
+ }
+
+ /**
+ * Gibt einen Weg zwischen den zwei gegebenen Elementen repraesentiert durch
+ * eine Liste zurueck. Die Liste beginnt mit start und endet mit end. Kann
+ * kein Weg gefunden werden (weil die Elemente in verschiedenen Baeumen
+ * sind) wird null zurueckgeben. Ist start gleich end wird eine leere Liste
+ * zurückgegeben
+ *
+ * @param start
+ * der Startpunkt
+ * @param end
+ * der Endpunkt
+ * @return den Weg
+ * @throws NullPointerException
+ * falls start oder end null sind
+ */
+ static public List findPath(ActionTreeElement start, ActionTreeElement end) {
+ if (start.equals(end)) {
+ return new LinkedList();
+ }
+
+ // Ways from Start or End Element to the tree root
+ LinkedList startToRoot = new LinkedList();
+ LinkedList endToRoot = new LinkedList();
+
+ ActionTreeElement current, other;
+ boolean path; // is start or end current
+ if (start.getId() > end.getId()) {
+ current = start;
+ other = end;
+ path = true;
+ } else {
+ current = end;
+ other = start;
+ path = false;
+ }
+
+ while (startToRoot.isEmpty() || endToRoot.isEmpty()
+ || (startToRoot.getLast() != endToRoot.getLast()
+ && (startToRoot.getLast().getParent() != null
+ || endToRoot.getLast().getParent() != null))) {
+
+ while (current != null && (other == null || current.getId() >= other.getId())) {
+ (path ? startToRoot : endToRoot).addLast(current);
+ current = current.getParent();
+ }
+
+ ActionTreeElement tmp = current;
+ current = other;
+ other = tmp;
+ path = !path;
+ }
+
+ // nodes not in the same tree?
+ if (startToRoot.getLast() != endToRoot.getLast()) {
+ return null;
+ }
+
+ // remove elements which are in both paths
+ while (!startToRoot.isEmpty() && !endToRoot.isEmpty() && startToRoot.getLast() == endToRoot.getLast()) {
+ startToRoot.removeLast();
+ endToRoot.removeLast();
+ }
+
+ // readd the last removed element
+ if (!startToRoot.isEmpty()) { // its itself a split up point
+ startToRoot.add(startToRoot.getLast().getParent());
+ } else { // its start itself
+ startToRoot.add(start);
+ }
+ // add the end-root way backwards
+ while (!endToRoot.isEmpty()) {
+ startToRoot.add(endToRoot.getLast());
+ endToRoot.removeLast();
+ }
+
+ return startToRoot;
+ }
+
+ /**
+ * Gibt einen Iterator für die ActionTreeElemente zurück.
+ *
+ * @return einen Iterator für die ActionTreeElemente
+ */
+ public Iterator iterator() {
+ return new ActionTreeIterator(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof ActionTree) {
+ ActionTree at = (ActionTree) obj;
+ if (this.getSize() == at.getSize()) {
+ Iterator at1 = this.iterator();
+ Iterator at2 = at.iterator();
+ while (at1.hasNext()) {
+ // since the sites are equals at2.hasNext() is true
+ if (!at1.next().equals(at2.next())) return false;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/ActionTreeElement.java b/sudoq-model/src/de/sudoq/model/actionTree/ActionTreeElement.java
new file mode 100644
index 00000000..8608668e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/ActionTreeElement.java
@@ -0,0 +1,299 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import de.sudoq.model.ObservableModelImpl;
+import de.sudoq.model.xml.XmlAttribute;
+import de.sudoq.model.xml.XmlTree;
+import de.sudoq.model.xml.Xmlable;
+
+/**
+ * Diese Klasse repräsentiert ein einzelnes Element des Aktionsbaums.
+ */
+public class ActionTreeElement extends ObservableModelImpl implements Comparable,
+ Iterable {
+ /** Attributes */
+
+ /**
+ * Eine eindeutige identifikationsnummer für dieses Element
+ */
+ private int id;
+ /**
+ * Die Aktion dieses Elements
+ */
+ private Action action;
+ /**
+ * Das Elternelement dieses Elements
+ */
+ private ActionTreeElement previous;
+ /**
+ * Die Liste aller Kindelemente dieses Elements
+ */
+ private ArrayList following;
+ /**
+ * Gibt an ob der Zustand im Baum markiert ist.
+ */
+ private boolean marked;
+ /**
+ * Gibt an ob dieser Zug bezüglich des zugrunde liegenden Sudokus ein falscher Zug war
+ * Wenn false bedeutet das nicht, dass der Zug keine Fehler sein kann.
+ */
+ private boolean mistake;
+ /**
+ * Gibt an, dass dieser Zug das Sudoku in einem korrekten Zustand hinterlässt.
+ * Wenn false bedeutet das nicht, dass dieser Zug falsch sein muss.
+ */
+ private boolean correct;
+
+ /**
+ * Konstante für XmlAttribut
+ */
+ public static final String ID = "id";
+ /**
+ * Konstante für XmlAttribut
+ */
+ public static final String PARENT = "parent";
+ /**
+ * Konstante für XmlAttribut
+ */
+ public static final String DIFF = "value";
+ /**
+ * Konstante für XmlAttribut
+ */
+ public static final String FIELD_ID = "field_id";
+ /**
+ * Konstante für XmlAttribut
+ */
+ public static final String ACTION_TYPE = "action_type";
+ /**
+ * Konstante für XmlAttribut
+ */
+ public static final String MARKED = "marked";
+ /**
+ * Konstante für XmlAttribut
+ */
+ public static final String MISTAKE = "mistake";
+ /**
+ * Konstante für XmlAttribut
+ */
+ public static final String CORRECT = "correct";
+
+ /** Constructors */
+
+ /**
+ * Erzeugt und instanziiert ein neues ActionTreeElement mit den gegebenen Parametern. Ist die ID ungültig oder das
+ * Elternelement null, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param id
+ * Die eindeutige ID für dieses Element
+ * @param action
+ * die diesem ActionTreeElement zugrundeliegende Aktion
+ * @param parent
+ * Das Elternelement
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls die ID ungültig oder die Action null ist.
+ */
+ public ActionTreeElement(int id, Action action, ActionTreeElement parent) {
+ if (action != null) {
+ this.id = id;
+ this.action = action;
+ this.marked = false;
+ this.mistake = false;
+ this.correct = false;
+
+ this.previous = parent;
+ if (previous != null) {
+ parent.addChild(this);
+ }
+
+ following = new ArrayList();
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /**
+ * Diese Methode führt die Aktion dieses Elementes aus.
+ *
+ * @see Action
+ */
+ public void execute() {
+ action.execute();
+ }
+
+ /**
+ * Diese Methode macht die Aktion dieses Elementes rückgängig.
+ *
+ * @return the parent ActionTreeElement
+ * @see Action
+ */
+ public ActionTreeElement undo() {
+ action.undo();
+ return previous;
+ }
+
+ /**
+ * Gibt die id dieses Elements zurueck.
+ *
+ * @return die id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Überprüft, ob dieses Element mehrere mögliche nachfolgende Elemente hat.
+ *
+ * @return true falls mehrere Kindelemente vorhanden sind, andernfalls false
+ */
+ public boolean isSplitUp() {
+ return following.size() > 1;
+ }
+
+ /**
+ * Fuegt der Liste der Kinderelemente das gegebene hinzu.\ Ist es null passiert nichts.
+ *
+ * @param child
+ * das hinzuzufuegende Kindelement
+ */
+ void addChild(ActionTreeElement child) {
+ if (child != null) {
+ following.add(child);
+ }
+ }
+
+ /**
+ * Gibt das Elternelement dieses Knotens zurück.
+ *
+ * @return Das Elternelement
+ */
+ public ActionTreeElement getParent() {
+ return previous;
+ }
+
+ /**
+ * Gibt die Liste aller Kindelemente zurück.
+ *
+ * @return Die Liste aller Kindelemente.
+ */
+ // ja, package scope
+ ArrayList getChildrenList() {
+ return following;
+ }
+
+ /**
+ * Gibt einen Iterator ueber die Liste aller Kindelemente zurück.
+ *
+ * @return Die Iterator aller Kindelemente.
+ */
+ public Iterator getChildren() {
+ return following.iterator();
+ }
+
+ /**
+ * Ueberprueft ob dieses Element im Baum markiert ist
+ *
+ * @return true falls markiert, andernfalls false
+ */
+ public boolean isMarked() {
+ return marked;
+ }
+
+ /**
+ * Markiert dieses Element
+ */
+ public void mark() {
+ marked = true;
+ notifyListeners(this);
+ }
+
+ /**
+ * Markiert diesen Zug als Fehler
+ */
+ public void markWrong() {
+ mistake = true;
+ }
+
+ /**
+ * gibt zurück ob dieser Zug in seinem Sudoku eine Fehler war
+ * @return true falls es ein Fehler war, false heißt, dass der Zug unbestimmt ist
+ */
+ public boolean isMistake() {
+ return mistake;
+ }
+
+ /**
+ * Markiert diesen Zug als in jedem Fall korrekt
+ */
+ public void markCorrect() {
+ correct = true;
+ }
+
+ /**
+ * gibt zurück ob dieser Zug in seinem Sudoku korrekt ist
+ * @return true falls er korrekt ist, false heißt, dass der Zug unbestimmt ist
+ */
+ public boolean isCorrect() {
+ return correct;
+ }
+
+ /**
+ * @see Xmlable#toXmlTree()
+ * @return den resultierenden XmlTree
+ */
+ public XmlTree toXml() {
+ if (action.field.getId() <= 0)
+ return null;
+ XmlTree xml = new XmlTree("action");
+
+ xml.addAttribute(new XmlAttribute(ID, Integer.toString(getId())));
+ xml.addAttribute(new XmlAttribute(PARENT, previous == null ? "" : Integer.toString(previous.getId())));
+ xml.addAttribute(new XmlAttribute(DIFF, Integer.toString(action.diff)));
+ xml.addAttribute(new XmlAttribute(FIELD_ID, Integer.toString(action.field.getId())));
+ xml.addAttribute(new XmlAttribute(ACTION_TYPE, action.getClass().getSimpleName()));
+ xml.addAttribute(new XmlAttribute(MARKED, Boolean.toString(marked)));
+ if (mistake) {
+ xml.addAttribute(new XmlAttribute(MISTAKE, Boolean.toString(mistake)));
+ }
+ if (correct) {
+ xml.addAttribute(new XmlAttribute(CORRECT, Boolean.toString(correct)));
+ }
+
+ return xml;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int compareTo(ActionTreeElement another) {
+ return this.id - another.id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof ActionTreeElement) {
+ ActionTreeElement ate = (ActionTreeElement) o;
+ return this.id == ate.id && this.marked == ate.marked && this.action.equals(ate.action);
+ }
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Iterator iterator() {
+ return getChildren();
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/ActionTreeIterator.java b/sudoq-model/src/de/sudoq/model/actionTree/ActionTreeIterator.java
new file mode 100644
index 00000000..b32c3293
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/ActionTreeIterator.java
@@ -0,0 +1,92 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.Stack;
+
+/**
+ * Diese Klasse stellt einen Iterator bereit, mit dem über ActionTreeElemente
+ * iteriert werden kann.
+ */
+public class ActionTreeIterator implements Iterator {
+ /** Attributes */
+
+ /**
+ * Der ActionTree über den iteriert wird
+ */
+ private ActionTree actionTree;
+
+ /**
+ * Das aktuelle Element beim Iterieren
+ */
+ private ActionTreeElement currentElement;
+
+ private Stack otherPaths;
+
+ /** Constructors */
+
+ /**
+ * Erzeugt und instanziiert ein neues ActionTreeElement mit den gegebenen
+ * Parametern. Ist der übergebene ActionTree null, so wird eine
+ * IllegalArgumentException geworfen.
+ *
+ * @param tree
+ * Der ActionTree über den iteriert werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls der übergebene ActionTree null ist
+ */
+ public ActionTreeIterator(ActionTree tree) {
+ this.actionTree = tree;
+ currentElement = actionTree.rootElement;
+ otherPaths = new Stack();
+ }
+
+ /** Methods */
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean hasNext() {
+ return currentElement != null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ActionTreeElement next() {
+ if (currentElement == null) {
+ throw new NoSuchElementException();
+ }
+
+ ActionTreeElement ret = currentElement;
+
+ for (int i = currentElement.getChildrenList().size() - 1; i >= 0; i--) {
+ otherPaths.push(currentElement.getChildrenList().get(i));
+ }
+
+ if (!otherPaths.empty()) {
+ currentElement = otherPaths.pop();
+ } else {
+ currentElement = null;
+ }
+
+ return ret;
+ }
+
+ /**
+ * Nicht unterstützt. Wirft eine UnsupportedOperationException.
+ *
+ * @throws UnsupportedOperationException
+ * Wird immer geworfen, da nicht unterstützt
+ */
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/NoteAction.java b/sudoq-model/src/de/sudoq/model/actionTree/NoteAction.java
new file mode 100644
index 00000000..94c8f2c1
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/NoteAction.java
@@ -0,0 +1,51 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Diese Klasse repräsentiert eine Aktion auf den Notizeinträgen eines
+ * Sudokufeldes.
+ */
+public class NoteAction extends Action {
+
+ /**
+ * Ein geschützter Konstruktor um die Instanziierung von Actions außerhalb
+ * dieses Packages zu vermeiden. Wird er aufgerufen wird eine neue
+ * NoteAction mit den gegebenen Parametern instanziiert. Ist das
+ * spezifizierte Field null, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param diff
+ * Der Unterschied zwischen altem und neuem Wert
+ * @param field
+ * Das zu bearbeitende Feld
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Field null ist
+ */
+ protected NoteAction(int diff, Field field) {
+ super(diff, field);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void execute() {
+ field.toggleNote(diff);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void undo() {
+ field.toggleNote(diff);
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/NoteActionFactory.java b/sudoq-model/src/de/sudoq/model/actionTree/NoteActionFactory.java
new file mode 100644
index 00000000..44a40062
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/NoteActionFactory.java
@@ -0,0 +1,26 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Diese Klasse dient der Erzeugung von NoteActions.
+ *
+ * @see NoteAction
+ */
+public class NoteActionFactory implements ActionFactory {
+
+ /**
+ * {@inheritDoc}
+ */
+ public Action createAction(int value, Field field) {
+ return new NoteAction(value, field);
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/SolveAction.java b/sudoq-model/src/de/sudoq/model/actionTree/SolveAction.java
new file mode 100644
index 00000000..365cec2c
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/SolveAction.java
@@ -0,0 +1,50 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Diese Klasse repräsentiert eine Aktion auf Eintrag eines Sudokufeldes.
+ */
+public class SolveAction extends Action {
+
+ /**
+ * Ein geschützter Konstruktor um die Instanziierung von Actions außerhalb
+ * dieses Packages zu vermeiden. Wird er aufgerufen wird eine neue
+ * SolveAction mit den gegebenen Parametern instanziiert. Ist das
+ * spezifizierte Field null, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param diff
+ * Der Unterschied zwischen altem und neuem Wert
+ * @param field
+ * Das zu bearbeitende Feld
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Field null ist
+ */
+ protected SolveAction(int diff, Field field) {
+ super(diff, field);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void execute() {
+ field.setCurrentValue(field.getCurrentValue() + diff);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void undo() {
+ field.setCurrentValue(field.getCurrentValue() - diff);
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/actionTree/SolveActionFactory.java b/sudoq-model/src/de/sudoq/model/actionTree/SolveActionFactory.java
new file mode 100644
index 00000000..dbc6c622
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/actionTree/SolveActionFactory.java
@@ -0,0 +1,30 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.actionTree;
+
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Diese Klasse dient der Erzeugung von NoteActions.
+ *
+ * @see NoteAction
+ */
+public class SolveActionFactory implements ActionFactory {
+
+ /**
+ * {@inheritDoc}
+ */
+ public Action createAction(int value, Field field) {
+ if (field != null) {
+ return new SolveAction(value - field.getCurrentValue(), field);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/files/FileManager.java b/sudoq-model/src/de/sudoq/model/files/FileManager.java
new file mode 100644
index 00000000..5467f588
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/files/FileManager.java
@@ -0,0 +1,415 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.files;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Random;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+import de.sudoq.model.xml.XmlHelper;
+import de.sudoq.model.xml.XmlTree;
+
+/**
+ * Die Klasse FileManager stellt eine Klasse zur Verwaltung des Dateisystems
+ * innerhalb der App bereit. Setzt das Singleton-Entwurfsmuster um. ACHTUNG
+ * nicht threadsave
+ */
+public final class FileManager {
+ /** Attributes */
+
+ private FileManager() {
+ }
+
+ /**
+ * Die Ordner für die jeweiligen Daten
+ */
+ private static File profiles;
+ private static File sudokus;
+
+ private static int currentProfileId = -1;
+
+ /** Methods */
+
+ /**
+ * Erstellt die Singleton-Instanz des FileManagers
+ *
+ * @param p
+ * Ein Ordner fuer die Profile
+ * @param s
+ * Ein Ordner fuer die Sudokus
+ * @throws IllegalArgumentException
+ * falls einer der Ordner null oder nicht schreibbar ist
+ */
+ public static void initialize(File p, File s) {
+ if (p == null || s == null || !p.canWrite() || !s.canWrite()) {
+ throw new IllegalArgumentException("unvalid directories");
+ }
+ profiles = p;
+ sudokus = s;
+
+ initSudokuDirectories();
+ }
+
+ /**
+ * Setzt die id des aktuellen Profils für den FileManager, sodass die Pfade
+ * zur Verfügung stehen
+ *
+ * @param id
+ */
+ public static void setCurrentProfile(int id) {
+ currentProfileId = id;
+ }
+
+ /**
+ * Löscht rekursiv das gegebene Verzeichnis
+ *
+ * @param f
+ * das Verzeichnis
+ * @throws IOException
+ * falls etwas nicht gelöscht werden konnte
+ */
+ public static void deleteDir(File f) throws IOException {
+ if (f.isDirectory()) {
+ for (File c : f.listFiles())
+ deleteDir(c);
+ }
+ if (!f.delete())
+ throw new FileNotFoundException("Failed to delete file: " + f);
+ }
+
+ // Profiles
+
+ /**
+ * Gibt die Anzahl der aktuell existierenden Profile zurück (macht keine
+ * Rechenfehler :-)
+ *
+ * @return die Anzahl der Profile
+ */
+ public static int getNumberOfProfiles() {
+ int count = profiles.list().length;
+ if (getProfilesFile().exists()) {
+ count--;
+ }
+ return count;
+ }
+
+ /**
+ * Gibt das Verzeichnis des aktuellen Profils zurueck
+ *
+ * @return File, welcher auf das aktuelle Profilverzeichnis zeigt
+ */
+ private static File getCurrentProfileDir() {
+ return getProfileDirFor(currentProfileId);
+ }
+
+ /**
+ * Gibt das Verzeichnis des Profils mit der gegebenen id zurueck
+ *
+ * @return File, welcher auf das Profilverzeichnis zeigt
+ */
+ private static File getProfileDirFor(int id) {
+ return new File(profiles.getAbsolutePath() + File.separator + "profile_" + id);
+ }
+
+ /**
+ * Gibt die XML-Datei das aktuellen Profils zurück
+ *
+ * @param id
+ * die id des Profils dessen xml gesucht ist
+ *
+ * @return File, welcher auf die XML Datei des aktuellen Profils zeigt
+ */
+ public static File getProfileXmlFor(int id) {
+ return new File(getProfileDirFor(id), "profile.xml");
+ }
+
+ /**
+ * Gibt das Verzeichis zurück, in denen die Profil-Ornder liegen
+ *
+ * @return File, welcher auf das Verzeichnis mit den Profilordnern zeigt
+ */
+ public static File getProfilesDir() {
+ return new File(profiles.getAbsolutePath());
+ }
+
+ /**
+ * Gibt die Date zurück, in der die Gesten des Benutzers gespeichert werden
+ *
+ * @return File, welcher auf die Gesten-Datei des Benutzers zeigt
+ */
+ public static File getCurrentGestureFile() {
+ return new File(getCurrentProfileDir(), "gestures");
+ }
+
+ /**
+ * Erstellt die Ordnerstruktur und nötige Dateien für das Profil mit der
+ * übergebenen ID
+ *
+ * @param id
+ * ID des Profils
+ */
+ public static void createProfileFiles(int id) {
+ new File(profiles.getAbsolutePath() + File.separator + "profile_" + id).mkdir();
+ new File(profiles.getAbsolutePath() + File.separator + "profile_" + id + File.separator + "games").mkdir();
+ File games = new File(profiles.getAbsolutePath() + File.separator + "profile_" + id + File.separator + "games.xml");
+ try {
+ new XmlHelper().saveXml(new XmlTree("games"), games);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unvalid Profil", e);
+ }
+ }
+
+ /**
+ * Erzeugt die profiles.xml Datei, wenn noch kein Profil vorhanden ist.
+ */
+ public static void createProfilesFile() {
+ File profilesXML = new File(profiles.getAbsolutePath() + File.separator + "profiles.xml");
+ try {
+ new XmlHelper().saveXml(new XmlTree("profiles"), profilesXML);
+ } catch (IOException e) {
+ throw new IllegalStateException("Couldnt create profiles.xml", e);
+ }
+ }
+
+ /**
+ * Gibt die Profilliste Datei zurueck
+ *
+ * @return das File welches auf die Profilliste zeigt
+ */
+ public static File getProfilesFile() {
+ return new File(getProfilesDir(), "profiles.xml");
+ }
+
+ /**
+ * Löscht das Profil der gegebenen ID und alle seine Daten Die Profil Liste
+ * bleibt unverändert! ACHTUNG: Überprüft nicht ob es noch andere Profile
+ * gibt. Setzt die currentProfileId nicht!
+ *
+ * @param id
+ * die id des zu löschenden Profils
+ */
+ public static void deleteProfile(int id) {
+ try {
+ File dir = getProfileDirFor(id);
+ if (dir.exists()) {
+ deleteDir(dir);
+ }
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Unable to delete given Profile");
+ }
+ }
+
+ // Games
+
+ /**
+ * Gibt die Spieleliste Datei des aktuellen Profils zurück
+ *
+ * @return das File welches auf die Spieleliste zeigt
+ */
+ public static File getGamesFile() {
+ return new File(getCurrentProfileDir(), "games.xml");
+ }
+
+ /**
+ * Gibt das Game-Verzeichnis des aktuellen Profils zurueck
+ *
+ * @return File, welcher auf das Game-Verzeichnis des aktuellen Profils
+ * zeigt
+ */
+ public static File getGamesDir() {
+ return new File(getCurrentProfileDir(), "games");
+ }
+
+ /**
+ * Gibt die XML eines Games des aktuellen Profils anhand seiner ID zurueck
+ *
+ * @param id
+ * ID des Games
+ * @return File, welcher auf die XML Datei des Games zeigt
+ */
+ public static File getGameFile(int id) {
+ return new File(getGamesDir(), "game_" + id + ".xml");
+ }
+
+ /**
+ * Loescht falls existierend das Spiel mit der gegebenen id des aktuellen
+ * Profils
+ *
+ * @param id
+ * die id des zu loeschenden Spiels
+ * @return ob es geloescht wurde.
+ */
+ public static boolean deleteGame(int id) {
+ boolean game = getGameFile(id).delete();
+ return game && getGameThumbnailFile(id).delete();
+ }
+
+ /**
+ * Gibt die naechste verfuegbare ID fuer ein Game zurueck
+ *
+ * @return naechste verfuegbare ID
+ */
+ public static int getNextFreeGameId() {
+ return getGamesDir().list().length + 1;
+ }
+
+ // Thumbnails
+
+ /**
+ * Returns the .png File for thumbnail of the game with id gameID
+ *
+ * @param gameID
+ * The ID of the game whos thumbnail is requested.
+ *
+ * @return The thumbnail File.
+ */
+ public static File getGameThumbnailFile(int gameID) {
+ return new File(getGamesDir() + File.separator + "game_" +
+ Integer.toString(gameID) + ".png");
+ }
+
+ // Sudokus
+
+ /**
+ * Gibt das Verzeichnis der Sudokus zurueck
+ *
+ * @return File, welcher auf das Verzeichnis mit den Sudokus zeigt
+ */
+ public static File getSudokuDir() {
+ return sudokus;
+ }
+
+ /**
+ * Gibt die Anzahl der Sudokus des gesuchten Typs zurueck
+ *
+ * @param t
+ * der gesuchte SudokuTyp
+ * @param c
+ * die gesuchte Sudoku Schwierigkeit
+ * @return die Anzahl
+ */
+ public static int getSudokuCountOf(SudokuTypes t, Complexity c) {
+ return getSudokuDir(t, c).list().length;
+ }
+
+ /**
+ * Gibt ein freies File fuer das gegebene Sudokus zurueck
+ *
+ * @param sudoku
+ * das zu speichernde Sudoku
+ * @return File, welcher auf die Datei des Sudokus zeigt
+ */
+ public static File getNewSudokuFile(Sudoku sudoku) {
+ return new File(getSudokuDir(sudoku).getAbsolutePath() + File.separator + "sudoku_" + getFreeSudokuIdFor(sudoku) + ".xml");
+ }
+
+ /**
+ * Loescht das uebergebene Sudoku von der Platte
+ *
+ * @param sudoku
+ * das zu loeschnde Sudoku
+ */
+ public static void deleteSudoku(Sudoku sudoku) {
+ if (!getSudokuFile(sudoku).delete()) {
+ throw new IllegalArgumentException("Sudoku doesnt exist");
+ }
+ }
+
+ /**
+ * Gibt eine Referenz auf ein zufaelliges zu den Parametern passendem Sudoku
+ * zurueck und null falls keins existiert
+ *
+ * @param type
+ * der Typ des Sudokus
+ * @param complexity
+ * die Schwierigkeit des Sudokus
+ * @return die Referenz auf die Datei
+ */
+ public static File getRandomSudoku(SudokuTypes type, Complexity complexity) {
+ File dir = getSudokuDir(type, complexity);
+ if (dir.list().length > 0) {
+ String fileName = dir.list()[new Random().nextInt(dir.list().length)];
+ return new File(dir.getAbsolutePath() + File.separator + fileName);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Gibt den zum Sudoku passenden Ordner zurueck
+ *
+ * @param s
+ * das einzuordnende Sudoku
+ * @return den Ordner
+ */
+ private static File getSudokuDir(Sudoku s) {
+ return getSudokuDir(s.getSudokuType().getEnumType(), s.getComplexity());
+ }
+
+ /**
+ * Gibt die zum gegebenen Sudoku gehoerende Datei zurueck
+ *
+ * @param s
+ * das Sudoku
+ * @return das File
+ */
+ public static File getSudokuFile(Sudoku s) {
+ return new File(getSudokuDir(s).getAbsolutePath(), "sudoku_" + s.getId() + ".xml");
+ }
+
+ /**
+ * Gibt den die Sudokus mit den gegebenen Parametern enthaltennden Ordner
+ * zurueck
+ *
+ * @param type
+ * der Typ des Sudokus
+ * @param complexity
+ * die Schwierigkeit des Sudokus
+ * @return der Ordner
+ */
+ private static File getSudokuDir(SudokuTypes type, Complexity complexity) {
+ return new File(sudokus.getAbsolutePath() + File.separator + type.toString() + File.separator + complexity.toString());
+ }
+
+ /**
+ * Gibt die nächste verfügbare Sudoku ID zurück
+ *
+ * @return nächste verfügbare Sudoku ID
+ */
+ private static int getFreeSudokuIdFor(Sudoku sudoku) {
+ ArrayList numbers = new ArrayList();
+ for (String s : getSudokuDir(sudoku).list()) {
+ numbers.add(Integer.parseInt(s.substring(7, s.length() - 4)));
+ }
+ int i = 1;
+ while (numbers.contains(i)) {
+ i++;
+ }
+ return i;
+ }
+
+ /**
+ * Erzeugt falls noetig alle Sudoku Ordner fuer die Typen und
+ * Schwierigkeiten
+ */
+ private static void initSudokuDirectories() {
+ for (SudokuTypes t : SudokuTypes.values()) {
+ File typeDir = new File(sudokus.getAbsoluteFile() + File.separator + t.toString());
+ if (!typeDir.exists()) typeDir.mkdir();
+
+ for (Complexity c : Complexity.values()) {
+ new File(typeDir.getAbsolutePath() + File.separator + c.toString()).mkdir();
+ }
+ }
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/game/AssistanceSet.java b/sudoq-model/src/de/sudoq/model/game/AssistanceSet.java
new file mode 100644
index 00000000..8c0a920d
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/game/AssistanceSet.java
@@ -0,0 +1,121 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.game;
+
+import java.util.BitSet;
+
+/**
+ * Diese Klasse repräsentiert einen Satz von Assistances, also für jede
+ * Assistance ob diese gesetzt ist oder nicht.
+ *
+ */
+public class AssistanceSet {
+ /**
+ * Ein BitSet, welches die gesetzten bzw. nicht gesetzten Assistances
+ * repräsentiert
+ */
+ private BitSet assistances;
+
+ /**
+ * Instanziiert ein neues AssistanceSet in welchem alle Assistances
+ * deaktiviert sind.
+ */
+ public AssistanceSet() {
+ this.assistances = new BitSet();
+ }
+
+ /**
+ * Setzt die spezifizierte Hilfestellung in diesem AssistanceSet. Ist diese
+ * null, so wird nichts getan
+ *
+ * @param assistance
+ * Die Hilfestellung die gesetzt werden soll
+ */
+ public void setAssistance(Assistances assistance) {
+ if (assistance == null)
+ return;
+
+ this.assistances.set((int) Math.pow(2, assistance.ordinal() + 1));
+ }
+
+ /**
+ * Löscht die spezifizierte Hilfestellung in diesem AssistanceSet. Ist diese
+ * null, so wird nichts getan.
+ *
+ * @param assistance
+ * Die Hilfestellung die gelöscht werden soll
+ */
+ public void clearAssistance(Assistances assistance) {
+ if (assistance == null)
+ return;
+
+ this.assistances.clear((int) Math.pow(2, assistance.ordinal() + 1));
+ }
+
+ /**
+ * Gibt zurück, ob in diesem AssistanceSet die gegebene Hilfestellung
+ * gesetzt ist. Ist diese< ungültig, so wird false zurückgegeben.
+ *
+ * @param assistance
+ * Die Hilfestellung die abgefragt werden soll
+ * @return true, falls die Hilfestellung gesetzt ist, false falls nicht oder
+ * falls das Assistance null ist
+ */
+ public boolean getAssistance(Assistances assistance) {
+ if (assistance == null)
+ return false;
+
+ return this.assistances.get((int) Math.pow(2, assistance.ordinal() + 1));
+ }
+
+ /**
+ * Generiert aus diesem AssistanceSet, einen String aus 0en und 1en. Dieser
+ * kann mittels der fromString-Methode wieder eingelesen werden.
+ *
+ * @return String Repräsentation dieses AssistanceSets
+ */
+ public String convertToString() {
+ StringBuilder bitstring = new StringBuilder();
+ for (Assistances assist : Assistances.values()) {
+ if (getAssistance(assist)) {
+ bitstring.append("1");
+ } else {
+ bitstring.append("0");
+ }
+ }
+ return bitstring.toString();
+ }
+
+ /**
+ * Generiert aus einer String Repräsentation der aktivierten Hilfestellungen
+ * durch 0en und 1en ein AssistanceSet
+ *
+ * @param representation
+ * String Repräsentation der Hilfestellungen
+ * @return AssistanceSet, welches die Hilfestellungen repräsentiert
+ * @throws IllegalArgumentException
+ * Wird geworfen, wenn aus dem angegebenen String kein
+ * AssistanceSet generiert werden kann.
+ */
+ public static AssistanceSet fromString(String representation) throws IllegalArgumentException {
+ AssistanceSet set = new AssistanceSet();
+ int i = 0;
+ for (Assistances assist : Assistances.values()) {
+ try {
+ if (representation.charAt(i) == '1') {
+ set.setAssistance(assist);
+ }
+ } catch (Exception exc) {
+ throw new IllegalArgumentException();
+ }
+ i++;
+ }
+ return set;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/game/Assistances.java b/sudoq-model/src/de/sudoq/model/game/Assistances.java
new file mode 100644
index 00000000..7ae7053f
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/game/Assistances.java
@@ -0,0 +1,49 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.game;
+
+/**
+ * Dieses Enum stellt Flags zur Verfügung, mit denen die Verfügbarkeit einer entsprechenden Hilfestellung repräsentiert
+ * werden kann. Dabei gibt es passive Hilfestellungen (solche die automatisch ausgeführt werden) und aktive
+ * Hilfestellungen, die vom Benutzer angefordert werden müssen.
+ */
+public enum Assistances {
+ /** Attributes */
+
+ /**
+ * Die Zeile und Spalte, in der sich das momentan ausgewählte Feld befindet, werden markiert (passiv).
+ */
+ markRowColumn,
+
+ /**
+ * Wird ein Symbol eingegeben und entspricht nicht der korrekten Lösung für dieses Feld, so wird dies angezeigt
+ * (passiv).
+ */
+ markWrongSymbol,
+
+ /**
+ * Es können nur Symbole in einem Feld eingetragen werden, welche bei deren Eingabe die Constraints des Sudokus
+ * nicht verletzen (passiv).
+ */
+ restrictCandidates,
+
+ /**
+ * Die Notizen werden bei Änderungen am Sudokus automatisch geändert, sodass nur Symbole als Notizen eingetragen
+ * sind, die bei ihrer Eingabe in das Feld die Constraints des Sudokus nicht verletzen würden.
+ */
+ autoAdjustNotes;
+
+ /**
+ * Konstante für Antworten im Multiplayer auf Requests
+ */
+ public static final int YES = 1;
+ /**
+ * Konstante für Antworten im Multiplayer auf Requests
+ */
+ public static final int NO = 0;
+}
diff --git a/sudoq-model/src/de/sudoq/model/game/Game.java b/sudoq-model/src/de/sudoq/model/game/Game.java
new file mode 100644
index 00000000..b0b15874
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/game/Game.java
@@ -0,0 +1,559 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.game;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+
+import de.sudoq.model.actionTree.Action;
+import de.sudoq.model.actionTree.ActionTreeElement;
+import de.sudoq.model.actionTree.NoteActionFactory;
+import de.sudoq.model.actionTree.SolveAction;
+import de.sudoq.model.actionTree.SolveActionFactory;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.SudokuManager;
+import de.sudoq.model.xml.XmlAttribute;
+import de.sudoq.model.xml.XmlTree;
+import de.sudoq.model.xml.Xmlable;
+
+/**
+ * Diese Klasse repräsentiert ein Sudoku-Spiel. Bezüglich der Controller stellt das Game eine Fassade dar.
+ */
+public class Game implements Xmlable {
+ /** Attributes */
+
+ /**
+ * Eine eindeutige Zahl, zur Identifikation
+ */
+ private int id;
+
+ /**
+ * Das zugehörige Sudoku
+ */
+ private Sudoku sudoku;
+
+ /**
+ * Der dazugehörige GameStateHandler, um den Zustand des Sudokus zu verwalten
+ */
+ private GameStateHandler stateHandler;
+
+ /**
+ * Die seit Spielstart verstrichene Zeit
+ */
+ private int time;
+
+ /**
+ * Die Summe der Kosten der bisher genutzten Hilfestellungen
+ */
+ private int assistancesCost;
+
+ /**
+ * Ein BitSet, welches die zur Verfügung stehenden Hilfestellungen darstellt
+ */
+ private AssistanceSet availableAssistances;
+
+ /**
+ * Zeigt an, ob das Sudoku beendet ist
+ */
+ private boolean finished;
+
+ /** Constructors */
+
+ /**
+ * Ein geschützter Konstruktor um die Instanziierung von Games außerhalb dieses Packages zu vermeiden. Wird er
+ * aufgerufen wird eine neues Game mit dem gegebenen Sudoku instanziiert. Die verfügbaren Hilfestellungen werden
+ * anhand der Einstellungen des aktuellen Profils gesetzt. Ist das übergebene Sudoku null, so wird eine
+ * IllegalArgumentException geworfen.
+ *
+ * @param die
+ * id dieses Spiels
+ * @param sudoku
+ * Das Sudoku, das bespielt werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Sudoku null ist
+ */
+ protected Game(int id, Sudoku sudoku) {
+ if (sudoku == null) {
+ throw new IllegalArgumentException("sudoku null");
+ }
+ time = 0;
+ this.id = id;
+ availableAssistances = new AssistanceSet();
+ this.sudoku = sudoku;
+ this.time = 0;
+ stateHandler = new GameStateHandler();
+ }
+
+ /**
+ * Erzeugt ein vollständig leeres Game, welches noch gefüllt werden muss.
+ */
+ // package scope!
+ Game() {
+ id = -1;
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode gibt die profilweit eindeutige id dieses Games zurück.
+ *
+ * @return Die id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Diese Methode gibt das Sudoku dieses Spiels zurück.
+ *
+ * @return Das Sudoku
+ */
+ public Sudoku getSudoku() {
+ return sudoku;
+ }
+
+ /**
+ * Fügt zur Zeit dieses Spiel die spezifizierte hinzu.
+ *
+ * @param time
+ * Die hinzuzufügende Zeit
+ */
+ public void addTime(int time) {
+ this.time += time;
+ }
+
+ /**
+ * Gibt die Zeit dieses Spiels zurück.
+ *
+ * @return Die Zeit dieses Spiels
+ */
+ public int getTime() {
+ return this.time;
+ }
+
+ /**
+ * Gibt den Highscorewert des Spiels zurück
+ *
+ * @return der ermittelte Wert
+ */
+ public int getScore() {
+ int scoreFactor = 0;
+ switch (sudoku.getComplexity()) {
+ case infernal:
+ scoreFactor = (int) Math.pow(sudoku.getSudokuType().getNumberOfSymbols(), 4.0f);
+ break;
+ case difficult:
+ scoreFactor = (int) Math.pow(sudoku.getSudokuType().getNumberOfSymbols(), 3.5f);
+ break;
+ case medium:
+ scoreFactor = (int) Math.pow(sudoku.getSudokuType().getNumberOfSymbols(), 3.0f);
+ break;
+ case easy:
+ scoreFactor = (int) Math.pow(sudoku.getSudokuType().getNumberOfSymbols(), 2.5f);
+ break;
+ }
+
+ return (int) (scoreFactor * 10 / (this.time / 60.0f + this.assistancesCost));
+ }
+
+ /**
+ * Überprüft das zugrundeliegende Sudoku auf Korrektheit. Dies wird als Assistance gewertet und die AssistanceCost
+ * wird um 1 erhöht.
+ *
+ * @return true, falls das Sudoku bisher korrekt gelöst ist, false falls nicht
+ */
+ public boolean checkSudoku() {
+ this.assistancesCost += 1;
+ return checkSudokuValidity();
+ }
+
+ /**
+ * Überprüft das zugrundeliegende Sudoku auf Korrektheit.
+ *
+ * @return true, falls das Sudoku bisher korrekt gelöst ist, false falls nicht
+ */
+ private boolean checkSudokuValidity() {
+ boolean correct = !sudoku.hasErrors();
+ if (correct) {
+ getCurrentState().markCorrect();
+ } else {
+ getCurrentState().markWrong();
+ }
+
+ return correct;
+ }
+
+ /**
+ * Gibt die Kosten für die Hilfestellungen zurück, welches ein Maß dafür ist, wieviele (bzw. wie schwere)
+ * Hilfestellung verfügbar waren bzw. tatsächlich genutzt wurden.
+ *
+ * @return Die Kosten für die Hilfestellungen
+ */
+ public int getAssistancesCost() {
+ return this.assistancesCost;
+ }
+
+ /**
+ * Diese Methode gibt den GameStateHandler dieses Spiels zurück.
+ *
+ * @return Der GameStateHandler
+ */
+ public GameStateHandler getStateHandler() {
+ return stateHandler;
+ }
+
+ /**
+ * Führt die gegebene Action aus und speichert sie ab.
+ *
+ * @param action
+ * Die auszuführende Aktion
+ */
+ public void addAndExecute(Action action) {
+ if (this.finished)
+ return;
+
+ this.stateHandler.addAndExecute(action);
+
+ updateNotes(sudoku.getField(action.getFieldId()));
+
+ if (isFinished())
+ this.finished = true;
+ }
+
+ /**
+ * Updatet die Notizen in den Constraints des spezifizierten Feldes so, dass der spezifizierte Wert aus diesen
+ * gelöscht wird. Dies wird nur ausgeführt, falls die entsprechende Hilfestellung im Game aktiviert ist.
+ *
+ * @param field
+ * Das Field, welches modifiziert wurde
+ */
+ private void updateNotes(Field field) {
+ if (!this.isAssistanceAvailable(Assistances.autoAdjustNotes))
+ return;
+
+ Position editedPos = sudoku.getPosition(field.getId());
+ int value = field.getCurrentValue();
+
+ for (Constraint c : this.sudoku.getSudokuType()) {
+ if (c.includes(editedPos)) {
+ for (Position changePos : c) {
+ if (this.sudoku.getField(changePos).isNoteSet(value)) {
+ this.addAndExecute(new NoteActionFactory().createAction(value, this.sudoku.getField(changePos)));
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Führt alle nötigen Aktionen aus, damit das Sudoku nach Ausführung dieser Methode wieder im gleichen Zustand wie
+ * nach der ersten Ausführung der gegebenen Aktion ist. Ist das übergebene Element null, so wird eine
+ * IllegalArgumentException geworfen.
+ *
+ * @param ate
+ * das ActionTreeElement in dessen Zustand das Sudoku überführt werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene ActionTreeElement null ist
+ */
+ public void goToState(ActionTreeElement ate) {
+ stateHandler.goToState(ate);
+ }
+
+ /**
+ * Macht die letzte Aktion rückgängig. Ein Schritt rückwärts in der Versionshistorie.
+ */
+ public void undo() {
+ stateHandler.undo();
+ }
+
+ /**
+ * Geht, falls möglich und eindeutig, einen Schritt vorwärts in der Versionshistorie. Ist diese verzweigt, aber der
+ * Schritt rückwärts erfolgte über undo(), wird dieses undo rückgängig gemacht.
+ */
+ public void redo() {
+ stateHandler.redo();
+ }
+
+ /**
+ * Diese Methode gibt das ActionTreeElement zurück, welches den aktuellen Zustand beinhaltet.
+ *
+ * @return Der aktuelle Zustand als ActionTreeElement
+ */
+ public ActionTreeElement getCurrentState() {
+ return stateHandler.getCurrentState();
+ }
+
+ /**
+ * Markiert den aktuellen Zustand um ihn später einfacher wiederzufinden
+ */
+ public void markCurrentState() {
+ stateHandler.markCurrentState();
+ }
+
+ /**
+ * Überprüft, ob das gegebene ActionTreeElement markiert ist.
+ *
+ * @param ate
+ * das zu überprüfende ActionTreeElement
+ * @return true falls es markiert ist und false falls nicht
+ */
+ public boolean isMarked(ActionTreeElement ate) {
+ return stateHandler.isMarked(ate);
+ }
+
+ /**
+ * Überprüft ob das Sudoku im aktuellen Zustand vollständig und korrekt gelöst ist.
+ *
+ * @return true falls gelöst, andernfalls false
+ */
+ public boolean isFinished() {
+ return this.finished || this.sudoku.isFinished();
+ }
+
+ /**
+ * Versucht das spezifizierte Feld zu lösen und gibt zurück, ob das Lösen möglich war. Ist das Sudoku ungültig oder
+ * gibt es Fehler im Sudoku, so wird false zurückgegeben.
+ *
+ * @param field
+ * Das zu lösende Feld
+ * @return true, falls das Feld gelöst werden konnte, false andernfalls
+ */
+ public boolean solveField(Field field) {
+ if (this.sudoku.hasErrors() || field == null)
+ return false;
+
+ this.assistancesCost += 3;
+ int solution = field.getSolution();
+ if (solution != Field.EMPTYVAL) {
+ stateHandler.addAndExecute(new SolveActionFactory().createAction(solution, field));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Versucht ein zufällig ausgewähltes Feld des Sudokus zu lösen und gibt zurück, ob dies möglich war.
+ *
+ * @return true, falls ein Feld gelöst werden konnte, false falls nicht
+ */
+ public boolean solveField() {
+ if (this.sudoku.hasErrors())
+ return false;
+
+ this.assistancesCost += 3;
+
+ for (Field f : this.sudoku) {
+ if (f.isEmpty()) {
+ this.addAndExecute(new SolveActionFactory().createAction(f.getSolution(), f));
+ break;
+ }
+ }
+ return true;
+
+ /*
+ * Solution solution = solver.getHint(); if (solution != null) {
+ * stateHandler.addAndExecute(solution.getAction()); return true; } else { return false; }
+ */
+ }
+
+ /**
+ * Löst das gesamte Sudoku. Bei Erfolg wird true zurückgegeben, sonst false.
+ *
+ * @return true, falls das Sudoku gelöst werden konnte, sonst false
+ */
+ public boolean solveAll() {
+ if (this.sudoku.hasErrors())
+ return false;
+
+ List unsolvedFields = new ArrayList();
+ for (Field f : this.sudoku) {
+ if (f.isEmpty()) {
+ unsolvedFields.add(f);
+ }
+ }
+
+ Random rnd = new Random();
+ while (!unsolvedFields.isEmpty()) {
+ int nr = rnd.nextInt(unsolvedFields.size());
+ this.addAndExecute(new SolveActionFactory().createAction(unsolvedFields.get(nr).getSolution(),
+ unsolvedFields.get(nr)));
+ unsolvedFields.remove(nr);
+ }
+
+ this.assistancesCost += Integer.MAX_VALUE / 2;
+ return true;
+ /*
+ * if (solver.solveAll(false, false, false) != null) { for (Field f : unsolvedFields) { this.addAndExecute(new
+ * SolveActionFactory().createAction(f.getCurrentValue(), f)); } return true; } else { return false; }
+ */
+ }
+
+ /**
+ * Geht zurück zum letzten korrekten gelösten Status im Aktionsbaum. Ist der aktuelle Status korrekt wird nichts
+ * getan. Dies wird als Assistance gewertet und die AssistanceCost wird um 3 erhöht.
+ */
+ public void goToLastCorrectState() {
+ this.assistancesCost += 3;
+ while (!this.checkSudokuValidity()) {
+ undo();
+ }
+ getCurrentState().markCorrect();
+ }
+
+ /**
+ * Gibt true zurück, falls die spezifizierte Hilfestellung verfügbar ist, false falls nicht oder falls die
+ * Hilfestellung ungültig ist.
+ *
+ * @param assist
+ * Die Hilfestellung, welche auf Verfügbarkeit geprüft werden soll
+ * @return true, falls die Hilfestellung verfügbar ist, false andernfalls
+ */
+ public boolean isAssistanceAvailable(Assistances assist) {
+ return this.availableAssistances.getAssistance(assist);
+ }
+
+ /**
+ * Setzt die für dieses Spiel verfügbaren Assistances auf die spezifizierten. Diese sollten für korrekte
+ * Funktionalität mithilfe der Methoden der {@link Assistances}-Klasse erstellt werden. Missbrauch kann zu
+ * unerwünschten Ergebnissen führen.
+ *
+ * @param assistances
+ * Die Assistances die für dieses Game gesetzt werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das spezifizierte BitSet null ist
+ */
+ public void setAssistances(AssistanceSet assistances) {
+ if (assistances == null)
+ throw new IllegalArgumentException("AssistanceSet was null");
+ this.availableAssistances = assistances;
+ if (isAssistanceAvailable(Assistances.autoAdjustNotes))
+ this.assistancesCost += 4;
+ if (isAssistanceAvailable(Assistances.markRowColumn))
+ this.assistancesCost += 2;
+ if (isAssistanceAvailable(Assistances.markWrongSymbol))
+ this.assistancesCost += 6;
+ if (isAssistanceAvailable(Assistances.restrictCandidates))
+ this.assistancesCost += 12;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public XmlTree toXmlTree() {
+ XmlTree representation = new XmlTree("game");
+ representation.addAttribute(new XmlAttribute("id", "" + id));
+ representation.addAttribute(new XmlAttribute("finished", "" + finished));
+ representation.addAttribute(new XmlAttribute("time", "" + time));
+ representation.addAttribute(new XmlAttribute("currentTurnId", "" + getCurrentState().getId()));
+ representation.addAttribute(new XmlAttribute("help", this.availableAssistances.convertToString()));
+ representation.addAttribute(new XmlAttribute("assistancesCost", "" + this.assistancesCost));
+
+ representation.addChild(sudoku.toXmlTree());
+
+ ArrayList actionList = new ArrayList();
+ for (ActionTreeElement ate : stateHandler.getActionTree()) {
+ actionList.add(ate);
+ }
+ Collections.sort(actionList);
+ for (ActionTreeElement ate : actionList) {
+ if (ate.toXml() != null)
+ representation.addChild(ate.toXml());
+ // TODO cant add child do for null just nothing?
+ }
+
+ return representation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void fillFromXml(XmlTree xmlTreeRepresentation) {
+
+ id = Integer.parseInt(xmlTreeRepresentation.getAttributeValue("id"));
+ // finished = Boolean.getBoolean(xmlTreeRepresentation.getAttributeValue("finished"));
+ time = Integer.parseInt(xmlTreeRepresentation.getAttributeValue("time"));
+ int currentStateId = Integer.parseInt(xmlTreeRepresentation.getAttributeValue("currentTurnId"));
+
+ // Problems:
+ // - What about corrupt files? is the game validated after it has been
+ // filled?
+
+ this.availableAssistances = AssistanceSet.fromString(xmlTreeRepresentation.getAttributeValue("help"));
+ this.assistancesCost = Integer.parseInt(xmlTreeRepresentation.getAttributeValue("assistancesCost"));
+
+ for (Iterator iterator = xmlTreeRepresentation.getChildren(); iterator.hasNext();) {
+ XmlTree sub = iterator.next();
+ if (sub.getName().equals("sudoku")) {
+ sudoku = SudokuManager.getEmptySudokuToFillWithXml();
+ sudoku.fillFromXml(sub);
+ }
+ }
+ stateHandler = new GameStateHandler();
+
+ for (Iterator iterator = xmlTreeRepresentation.getChildren(); iterator.hasNext();) {
+ XmlTree sub = iterator.next();
+ if (sub.getName().equals("action")) {
+ int diff = Integer.parseInt(sub.getAttributeValue(ActionTreeElement.DIFF));
+
+ // put the action to the parent action
+ goToState(stateHandler.getActionTree().getElement(
+ Integer.parseInt(sub.getAttributeValue(ActionTreeElement.PARENT))));
+ // if(!sub.getAttributeValue(ActionTreeElement.PARENT).equals(""))
+ // is not necessary since the root action comes from the gsh so
+ // every element has e parent
+
+ int field_id = Integer.parseInt(sub.getAttributeValue(ActionTreeElement.FIELD_ID));
+
+ if (sub.getAttributeValue(ActionTreeElement.ACTION_TYPE).equals(SolveAction.class.getSimpleName())) {
+ this.stateHandler.addAndExecute(new SolveActionFactory().createAction(sudoku.getField(field_id)
+ .getCurrentValue() + diff, sudoku.getField(field_id)));
+ } else { // if(sub.getAttributeValue(ActionTreeElement.ACTION_TYPE).equals(NoteAction.class.getSimpleName()))
+ this.stateHandler.addAndExecute(new NoteActionFactory().createAction(diff,
+ sudoku.getField(field_id)));
+ }
+
+ if (Boolean.parseBoolean(sub.getAttributeValue(ActionTreeElement.MARKED))) {
+ markCurrentState();
+ }
+ String s = sub.getAttributeValue(ActionTreeElement.MISTAKE);
+ if (s != null && Boolean.parseBoolean(s)) {
+ getCurrentState().markWrong();
+ }
+ s = sub.getAttributeValue(ActionTreeElement.CORRECT);
+ if (s != null && Boolean.parseBoolean(s)) {
+ getCurrentState().markCorrect();
+ }
+ }
+ }
+
+ goToState(stateHandler.getActionTree().getElement(currentStateId));
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Game) {
+ Game g = (Game) obj;
+ return this.id == g.id && this.sudoku.equals(g.sudoku)
+ && this.stateHandler.getActionTree().equals(g.stateHandler.getActionTree())
+ && this.getCurrentState().equals(g.getCurrentState());
+ }
+ return false;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/game/GameData.java b/sudoq-model/src/de/sudoq/model/game/GameData.java
new file mode 100644
index 00000000..7584a60a
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/game/GameData.java
@@ -0,0 +1,117 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.game;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+
+/**
+ * Eine Klasse um die zu einem Spiel zugehörigen Daten zu sammeln ohne jeweils
+ * das ganze Spiel laden zu müssen.
+ */
+public class GameData implements Comparable {
+
+ private int id;
+ private Date playedAt;
+ private boolean finished;
+ private SudokuTypes type;
+ protected final static String dateFormat = "yyyy:MM:dd HH:mm:ss";
+ private Complexity complexity;
+
+ /**
+ * Erzeugt ein GameData Objekt mit den gegebenen Paramtern zurück
+ *
+ * @param id
+ * die id des Spiels
+ * @param playedAt
+ * das Datum als es zuletzt gespielt wurde
+ * @param finished
+ * ob es beendet ist
+ * @param type
+ * der Typ des zugehörigen Sudokus
+ * @param complexity
+ * die Schwierigkeit des zugehörigen Sudokus
+ * @throws IllegalArgumentException
+ * falls playedAt null ist oder nicht zu einem Datum parsebar
+ * ist
+ */
+ public GameData(int id, String playedAt, boolean finished, SudokuTypes type, Complexity complexity) {
+ if (playedAt == null)
+ throw new IllegalArgumentException();
+ this.type = type;
+ this.id = id;
+ try {
+ this.playedAt = new SimpleDateFormat(dateFormat).parse(playedAt);
+ } catch (ParseException e) {
+ throw new IllegalArgumentException(e);
+ }
+ this.finished = finished;
+ this.complexity = complexity;
+
+ }
+
+ /**
+ * Gibt die Schwierigkeit des zum Spiel gehörenden Sudokus zurück
+ *
+ * @return die Schwierigkeit
+ */
+ public Complexity getComplexity() {
+ return complexity;
+ }
+
+ /**
+ * Gibt den Typ des zum Spiel zugehörigen Sudokus zurück
+ *
+ * @return die Schwierigkeit
+ */
+ public SudokuTypes getType() {
+ return type;
+ }
+
+ /**
+ * Gibt die id des Spiels zurück
+ *
+ * @return die id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Gibt das Datum, an dem das Spiel zuletzt gespielt wurde zurück
+ *
+ * @return das Datum
+ */
+ public Date getPlayedAt() {
+ return playedAt;
+ }
+
+ /**
+ * Gibt zurück ob das Spiel fertig gespielt wurde
+ *
+ * @return true falls fertig, false andernfalls
+ */
+ public boolean isFinished() {
+ return finished;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int compareTo(GameData another) {
+ if (this.finished == another.finished) {
+ return playedAt.compareTo(another.playedAt);
+ } else {
+ return this.finished ? -1 : 1;
+ }
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/game/GameManager.java b/sudoq-model/src/de/sudoq/model/game/GameManager.java
new file mode 100644
index 00000000..7b60f973
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/game/GameManager.java
@@ -0,0 +1,255 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.game;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.profile.Profile;
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.SudokuManager;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+import de.sudoq.model.xml.GameXmlHandler;
+import de.sudoq.model.xml.XmlAttribute;
+import de.sudoq.model.xml.XmlHandler;
+import de.sudoq.model.xml.XmlHelper;
+import de.sudoq.model.xml.XmlTree;
+
+/**
+ * Diese Klasse dient dem Erstellen und Laden von Sudokuspielen. Sie setzt das
+ * Singleton Pattern um.
+ */
+public class GameManager {
+ /** Attributes */
+
+ private static final String ID = "id";
+ private static final String FINISHED = "finished";
+ private static final String PLAYED_AT = "played_at";
+ private static final String SUDOKU_TYPE = "sudoku_type";
+ private static final String COMPLEXITY = "complexity";
+
+ /**
+ * Die einzige GameManager Instanz
+ */
+ private static GameManager manager = new GameManager();
+
+ private XmlHandler xmlHandler;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert ein neues GameManager Objekt. Das kann nur innerhalb dieser
+ * Klasse passieren.
+ */
+ private GameManager() {
+ xmlHandler = new GameXmlHandler();
+ };
+
+ /** Methods */
+
+ /**
+ * Gibt die einzige GameManager Instanz zurück.
+ *
+ * @return Der GameManager
+ */
+ public static GameManager getInstance() {
+ return manager;
+ }
+
+ /**
+ * Diese Methode erzeugt ein neues Spiel des gewünschten Typs und legt die
+ * nötigen Dateien an.
+ *
+ * @param type
+ * Der Typ des Sudokus
+ * @param complexity
+ * Die Schwierigkeit des Spiels
+ * @param gameType
+ * Der Typ des Spiels
+ * @param assists
+ * Die für dieses Game zu setzen Assistances
+ * @return Das neue Spiel
+ *
+ * @throws IllegalArgumentException
+ * falls gameType invalide ist.
+ * @see SudokuTypes
+ * @see Complexity
+ * @see GameType
+ * @see Game
+ */
+ public Game newGame(SudokuTypes type, Complexity complexity, GameType gameType, AssistanceSet assists) {
+ Sudoku sudoku = SudokuManager.getNewSudoku(type, complexity);
+
+ // switch (gameType) {
+ // case LOCAL:
+ // break;
+ // //TODO: Enable MP GameType in GameManager
+ // case MULTIPLAYER:
+ // // sudoku = new Sudoku();
+ // // new SudokuXmlHandler(type,
+ // // complexity).createObjectFromXml(sudoku);
+ // // TODO server client stuff
+ // // break;
+ // default:
+ // throw new IllegalArgumentException("UnsupportedGame");
+ // }
+ new SudokuManager().usedSudoku(sudoku);
+
+ Game game = new Game(FileManager.getNextFreeGameId(), sudoku);
+ game.setAssistances(assists);
+ xmlHandler.saveAsXml(game);
+
+ XmlTree games = getGamesXml();
+ XmlTree gameTree = new XmlTree("game");
+ gameTree.addAttribute(new XmlAttribute(ID, Integer.toString(game.getId())));
+ gameTree.addAttribute(new XmlAttribute(SUDOKU_TYPE, Integer.toString(game.getSudoku().getSudokuType().getEnumType().ordinal())));
+ gameTree.addAttribute(new XmlAttribute(COMPLEXITY, Integer.toString(game.getSudoku().getComplexity().ordinal())));
+ gameTree.addAttribute(new XmlAttribute(PLAYED_AT, new SimpleDateFormat(GameData.dateFormat).format(new Date())));
+
+ games.addChild(gameTree);
+ saveGamesFile(games);
+
+ return game;
+ }
+
+ /**
+ * Lädt ein bereits begonnenes Spiel des aktuellen Spielers mit der
+ * gegebenen ID. Ist diese ungültig, so wird eine IllegalArgumentException
+ * geworfen.
+ *
+ * @param id
+ * die Id des zu ladenden Spiels
+ * @return Das geladene Spiel, null falls kein Spiel zur angegebenen id
+ * existiert
+ * @throws IllegalArgumentException
+ * falls keine Spiel mit der entsprechenden id existiert
+ */
+ public Game load(int id) {
+ if (id <= 0) throw new IllegalArgumentException("unvalid id");
+ Game game = new Game();
+ // throws IllegalArgumentException
+ new GameXmlHandler(id).createObjectFromXml(game);
+ return game;
+ }
+
+ /**
+ * Gibt die nach Zeit und ob beendet oder nicht sortierte Liste aller Spiele
+ * des aktuellen Spielers zurück
+ *
+ * @return die Liste
+ */
+ public List getGameList() {
+ List list = new ArrayList();
+ for (XmlTree game : getGamesXml()) {
+ list.add(new GameData(Integer.parseInt(game.getAttributeValue(ID)),
+ game.getAttributeValue(PLAYED_AT), Boolean.parseBoolean(game.getAttributeValue(FINISHED)),
+ SudokuTypes.values()[Integer.parseInt(game.getAttributeValue(SUDOKU_TYPE))],
+ Complexity.values()[Integer.parseInt(game.getAttributeValue(COMPLEXITY))]));
+
+ }
+ java.util.Collections.sort(list);
+ java.util.Collections.reverse(list);
+ return list;
+ }
+
+ /**
+ * Speichert ein gegebenes Game in XML.
+ *
+ * @param game
+ * Das zu speichernde Game.
+ */
+ public void save(Game game) {
+ xmlHandler.saveAsXml(game);
+ XmlTree games = getGamesXml();
+ // boolean passed = false;
+ for (XmlTree g : games) {
+ if (Integer.parseInt(g.getAttributeValue(ID)) == game.getId()) {
+ // TODO anpassen
+ g.updateAttribute(new XmlAttribute(PLAYED_AT, new SimpleDateFormat(GameData.dateFormat).format(new Date())));
+ g.updateAttribute(new XmlAttribute(FINISHED, Boolean.toString(game.isFinished())));
+ // passed = true;
+ break;
+ }
+ }
+ // assert passed : "Broken games";
+ Profile.getInstance().saveChanges();
+ saveGamesFile(games);
+ }
+
+ /**
+ * Loescht nicht mehr existierende Spiele aus der Games Liste Existieren
+ * neue Spiele, die nicht in der Liste sind muss die Liste inkonsistent
+ * sein.
+ *
+ * @throws IllegalStateException
+ * Falls die Liste inkonsistent ist
+ */
+ public void updateGamesList() {
+ XmlTree games = getGamesXml();
+ XmlTree newGames = new XmlTree(games.getName());
+ // int counter = 0;
+ for (XmlTree g : games) {
+ if (FileManager.getGameFile(Integer.parseInt(g.getAttributeValue(ID))).exists()) {
+ newGames.addChild(g);
+ // counter++;
+ }
+ }
+ // assert counter == FileManager.getGamesDir().list().length :
+ // "Inconsistent games list";
+ saveGamesFile(newGames);
+ }
+
+ /**
+ * Loescht das Spiel mit der gegebenen Id aus dem Speicher und aus der
+ * Liste. Existiert kein Spiel mit der Id passiert nichts
+ *
+ * @param id
+ * die id des zu loeschenden Spiels
+ */
+ public void deleteGame(int id) {
+ if (id == Profile.getInstance().getCurrentGame()) {
+ Profile.getInstance().setCurrentGame(Profile.NO_GAME);
+ }
+ FileManager.deleteGame(id);
+ updateGamesList();
+ }
+
+ /**
+ * Loescht alle fertigen Spiele aus dem Speicher und aus der Spieleliste
+ */
+ public void deleteFinishedGames() {
+ XmlTree games = getGamesXml();
+ for (XmlTree g : games) {
+ if (Boolean.parseBoolean(g.getAttributeValue(FINISHED))) {
+ FileManager.deleteGame(Integer.parseInt(g.getAttributeValue(ID)));
+ }
+ }
+ updateGamesList();
+ }
+
+ private void saveGamesFile(XmlTree games) {
+ try {
+ new XmlHelper().saveXml(games, FileManager.getGamesFile());
+ } catch (IOException e) {
+ throw new IllegalStateException("Profil broken", e);
+ }
+ }
+
+ private XmlTree getGamesXml() {
+ try {
+ return new XmlHelper().loadXml(FileManager.getGamesFile());
+ } catch (IOException e) {
+ throw new IllegalStateException("Profil broken", e);
+ }
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/game/GameStateHandler.java b/sudoq-model/src/de/sudoq/model/game/GameStateHandler.java
new file mode 100644
index 00000000..3273cbbc
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/game/GameStateHandler.java
@@ -0,0 +1,232 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.game;
+
+import java.util.List;
+import java.util.Stack;
+
+import de.sudoq.model.ObservableModelImpl;
+import de.sudoq.model.actionTree.Action;
+import de.sudoq.model.actionTree.ActionTree;
+import de.sudoq.model.actionTree.ActionTreeElement;
+import de.sudoq.model.sudoku.Field;
+
+/**
+ * Diese Klasse verwaltet den Zustand eines Spiels durch einen ActionTree und stellt Funktionalität für die Verwaltung
+ * des Zustandes zur Verfügung.
+ */
+public class GameStateHandler extends ObservableModelImpl {
+ /** Attributes */
+
+ /**
+ * Die Datenstruktur um die Züge und ihre Abfolge zu speichern
+ */
+ private ActionTree actionTree;
+ /**
+ * Der aktuelle Zustand, die Aktion darin muss bereits ausgeführt sein
+ */
+ private ActionTreeElement currentState;
+ /**
+ * Ein Stack um bei undo über Verzweigungen hinweg den Rückweg zu speichern
+ */
+ private Stack undoStack;
+
+ /**
+ * Eine locking Variable um zu verhindern, dass durch Listener waehrend Veraenderungen weitere Veraenderung
+ * hinzugefuegt werden
+ */
+ private boolean locked;
+
+ /** Constructors */
+
+ /**
+ * Erzeugt und instanziiert einen neuen GameStateHandler.
+ */
+ public GameStateHandler() {
+ actionTree = new ActionTree();
+ undoStack = new Stack();
+
+ currentState = actionTree.add(new Action(0, new Field(-1, 1)) {
+ // Empty Action - do nothing
+ @Override
+ public void undo() {
+ }
+
+ @Override
+ public void execute() {
+ }
+ }, currentState);
+
+ locked = false;
+ }
+
+ /**
+ * Die Methode gibt den ActionTree zurück.
+ *
+ * @return Der ActionTree
+ */
+ public ActionTree getActionTree() {
+ return actionTree;
+ }
+
+ /**
+ * Die Methode gibt den aktuellen Zustand zurück.
+ *
+ * @return Das ActionTreeElement mit dem aktuellen Zustand
+ */
+ public ActionTreeElement getCurrentState() {
+ return currentState;
+ }
+
+ /**
+ * Fügt die gegebene Aktion dem ActionTree hinzu und führt sie aus.
+ *
+ * @param action
+ * Die auszuführende Aktion
+ * @throws IllegalArgumentException
+ * falls Action null ist
+ */
+ public void addAndExecute(Action action) {
+ // if another change is in progress dont execute!
+ if (!locked) {
+ locked = true;
+
+ currentState = actionTree.add(action, currentState);
+ currentState.execute();
+ notifyListeners(currentState);
+
+ locked = false;
+ }
+ }
+
+ /**
+ * Führt alle nötigen Aktionen aus, damit das Sudoku nach Ausführung dieser Methode wieder im gleichen Zustand wie
+ * nach der ersten Ausführung der gegebenen Aktion ist.
+ *
+ * @param target
+ * Das ActionTreeElement in dessen Zustand das Sudoku überführt werden soll
+ * @throws NullPointerException
+ * falls target null
+ */
+ public void goToState(ActionTreeElement target) {
+ locked = true;
+ boolean onlyUndo = true;
+
+ List listWay = ActionTree.findPath(currentState, target);
+ ActionTreeElement[] way = new ActionTreeElement[listWay.size()];
+ listWay.toArray(way);
+
+ for (int i = 1; i < way.length; i++) {
+ if (way[i - 1].getParent() == way[i]) {
+ way[i - 1].undo();
+ if (way[i].isSplitUp()) {
+ undoStack.push(way[i - 1]);
+ }
+
+ } else {
+ onlyUndo = false;
+ if (i - 2 >= 0 && way[i - 2].getParent() != way[i - 1]) {
+ way[i - 1].execute();
+ }
+ if (way[i] == target) {
+ target.execute();
+ }
+ }
+ }
+
+ if (!onlyUndo) {
+ undoStack.clear();
+ }
+ currentState = target;
+ notifyListeners(currentState);
+
+ locked = false;
+ }
+
+ /**
+ * Gibt zurück, ob die letzte Aktion rückgängig gemacht werden kann
+ *
+ * @return true, falls die letzte Aktion rückgängig gemacht werden kann, false falls es keine Aktion gibt, die
+ * rückgängig gemacht werden kann
+ */
+ public boolean canUndo() {
+ return currentState.getParent() != null;
+ }
+
+ /**
+ * Macht die letzte Aktion rückgängig. Ein Schritt rückwärts in der Versionshistorie.
+ */
+ public void undo() {
+ locked = true;
+
+ if (currentState.getParent() != null) {
+ ActionTreeElement oldElement = currentState;
+ currentState = currentState.undo();
+
+ if (currentState.isSplitUp()) {
+ undoStack.push(oldElement);
+ }
+
+ notifyListeners(currentState);
+ }
+
+ locked = false;
+ }
+
+ /**
+ * Gibt zurück, ob ub der Versionshistorie einen Schritt vorwärts gegangen werden kann.
+ *
+ * @return true, falls ein Schritt vorwärts gegangen werden kann, false falls nicht
+ */
+ public boolean canRedo() {
+ return (currentState.isSplitUp() && !undoStack.empty())
+ || (!currentState.isSplitUp() && currentState.getChildren().hasNext());
+ }
+
+ /**
+ * Geht falls möglich und eindeutig einen Schritt vorwärts in der Versionshistorie. Ist diese verzweigt, aber der
+ * Schritt rückwärts erfolgte über undo(), wird dieses undo rückgängig gemacht.
+ */
+ public void redo() {
+ locked = true;
+
+ if (currentState.isSplitUp()) {
+ if (!undoStack.empty()) {
+ currentState = undoStack.pop();
+ currentState.execute();
+ notifyListeners(currentState);
+ }
+ } else {
+ if (currentState.getChildren().hasNext()) {
+ currentState = currentState.getChildren().next();
+ currentState.execute();
+ notifyListeners(currentState);
+ }
+ }
+
+ locked = false;
+ }
+
+ /**
+ * Markiert den aktuellen Zustand um ihn später einfacher wiederzufinden
+ */
+ public void markCurrentState() {
+ currentState.mark();
+ }
+
+ /**
+ * Überprüft, ob das gegebene ActionTreeElement markiert ist.
+ *
+ * @param ate
+ * das zu überprüfende ActionTreeElement
+ * @return true falls es markiert ist und false falls nicht oder null ist
+ */
+ public boolean isMarked(ActionTreeElement ate) {
+ return ate != null && ate.isMarked();
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/game/GameType.java b/sudoq-model/src/de/sudoq/model/game/GameType.java
new file mode 100644
index 00000000..7e764f37
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/game/GameType.java
@@ -0,0 +1,29 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.game;
+
+/**
+ * Dieses Enum definiert die verschiedenen Arten von Spielen.
+ */
+public enum GameType {
+ /** Attributes */
+
+ /**
+ * Ein "normales" Spiel.
+ */
+ LOCAL;
+ //TODO: Enable GameType for Multiplayer
+ /*
+ * Ein von mehreren Spielern gegeneinander auf Zeit gespieltes Spiel.
+ */
+ //MULTIPLAYER;
+ /*
+ * Ein offizielles Spiel in ständiger Kommunikation mit dem Server.
+ */
+ // ONLINE;
+}
diff --git a/sudoq-model/src/de/sudoq/model/profile/Profile.java b/sudoq-model/src/de/sudoq/model/profile/Profile.java
new file mode 100644
index 00000000..d919993e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/profile/Profile.java
@@ -0,0 +1,476 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.profile;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import de.sudoq.model.ObservableModelImpl;
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.game.AssistanceSet;
+import de.sudoq.model.game.Assistances;
+import de.sudoq.model.xml.ProfileXmlHandler;
+import de.sudoq.model.xml.XmlAttribute;
+import de.sudoq.model.xml.XmlHandler;
+import de.sudoq.model.xml.XmlHelper;
+import de.sudoq.model.xml.XmlTree;
+import de.sudoq.model.xml.Xmlable;
+
+/**
+ * Diese statische Klasse ist ein Wrapper für das aktuell geladene und durch
+ * SharedPreferences von der Android-API verwaltete Spielerprofil.
+ *
+ */
+public class Profile extends ObservableModelImpl implements Xmlable {
+ /** Attributes */
+
+ private static final String ID = "id";
+ private static final String NAME = "name";
+ private static final String CURRENT = "current";
+
+ /**
+ * Konstante die signalisiert, dass es kein aktuelles Spiel gibt
+ */
+ public static final int NO_GAME = -1;
+
+ /**
+ * Konstante die signalisiert, dass ein neues Profil noch keinen namen hat
+ * */
+ public static final String DEFAULT_PROFILE_NAME = "unnamed";
+
+ private static Profile instance;
+ /**
+ * Name des Profils
+ */
+ private String name;
+
+ /**
+ * ID des Profils
+ */
+ private int profileId = -1;
+
+ /**
+ * ID des aktuellen Games
+ */
+ private int currentGameId;
+
+ /**
+ * Gibt die Aktivierung der Gestensteuerung an
+ */
+ private boolean gestureActive;
+
+ /**
+ * AssistanceSet mit den Hilfestellungen
+ */
+ private AssistanceSet assistances = new AssistanceSet();
+
+ int[] statistics;
+
+ private XmlHandler xmlHandler = new ProfileXmlHandler();
+
+ /** Constructors */
+
+ /**
+ * Da die Klasse statisch ist hat sie einen privaten Konstruktor.
+ */
+ private Profile() {
+ }
+
+ /**
+ * Diese Methode gibt eine Instance dieser Klasse zurück, wird sie erneut
+ * aufgerufen, so wird dieselbe Instanz zurückgegeben.
+ *
+ * @return Die Instanz dieses Profile Singletons
+ */
+ public static synchronized Profile getInstance() {
+ if (instance == null) {
+ instance = new Profile();
+ instance.loadCurrentProfile();
+ }
+
+ return instance;
+ }
+
+ /** Methods */
+
+ /**
+ * Laed das aktuelle Profil aus der profiles.xml
+ */
+ public void loadCurrentProfile() {
+ if (!FileManager.getProfilesFile().exists()) {
+ FileManager.createProfilesFile();
+ createProfile();
+ return;
+ }
+
+ XmlTree profiles = getProfilesXml();
+ this.profileId = Integer.parseInt(profiles.getAttributeValue(CURRENT));
+ xmlHandler.createObjectFromXml(this);
+ FileManager.setCurrentProfile(profileId);
+ notifyListeners(this);
+ }
+
+ /**
+ * Loescht das aktuelle Profil, falls mehr als 1 Profil vorhanden ist. Nimmt
+ * als neues Profil das erste nicht geloeschte in der profiles.xml
+ */
+ public void deleteProfile() {
+ if (getNumberOfAvailableProfiles() > 1) {
+ XmlTree oldProfiles = getProfilesXml();
+ XmlTree profiles = new XmlTree(oldProfiles.getName());
+
+ for (XmlTree profile : oldProfiles) {
+ if (Integer.valueOf((profile.getAttributeValue(ID))) != this.profileId) {
+ profiles.addChild(profile);
+ }
+ }
+ saveProfilesFile(profiles);
+ FileManager.deleteProfile(this.profileId);
+
+ this.setProfile(Integer.parseInt(profiles.getChildren().next().getAttributeValue(ID)));
+ }
+ }
+
+ /**
+ * Gibt die Anzahl der nicht geloeschten Profile zurueck
+ *
+ * @return Anzahl nicht geloeschter Profile
+ */
+ public int getNumberOfAvailableProfiles() {
+ return getProfilesXml().getNumberOfChildren();
+ }
+
+ /**
+ * Diese Methode ändert die Einstellungen, die mit dieser Klasse abgerufen
+ * werden können auf die spezifizierten SharedPreferences. Sind diese null,
+ * so wird nichts geändert und es wird false zurückgegeben. War die Änderung
+ * erfolgreich, so wird true zurückgegeben.
+ *
+ * @param profileID
+ * Die ID des Profils, zu dem gewechselt werden soll.
+ *
+ * @return boolean true, falls die Änderung erfolgreich war, false
+ * andernfalls
+ */
+ public boolean changeProfile(int profileID) {
+ int oldProfileID = getCurrentProfileID();
+ if (profileID == oldProfileID)
+ return true;
+ xmlHandler.saveAsXml(this); // save current
+ return setProfile(profileID);
+ }
+
+ /**
+ * Setzt das neue Profil ohne das alte zu speichern (zB nach löschen)
+ */
+ private boolean setProfile(int profileID) {
+ this.profileId = profileID;
+ xmlHandler.createObjectFromXml(this); // load new values
+
+ // set current profile in profiles.xml
+ XmlTree profiles = getProfilesXml();
+ profiles.updateAttribute(new XmlAttribute(CURRENT, Integer.toString(profileID)));
+ saveProfilesFile(profiles);
+ FileManager.setCurrentProfile(profileID);
+ notifyListeners(this);
+
+ return false;
+
+ }
+
+ /**
+ * Wird von der PlayerPreference aufgerufen, falls sie verlassen wird und
+ * speichert Aenderungen an der profile.xml fuer dieses Profil sowie an der
+ * profiles.xml, welche Informationen ueber alle Profile enthaelt
+ */
+ public void saveChanges() {
+ xmlHandler.saveAsXml(this);
+ XmlTree profiles = getProfilesXml();
+ for (XmlTree profile : profiles) {
+ if (Integer.valueOf(profile.getAttributeValue(ID)) == this.getCurrentProfileID()) {
+ profile.updateAttribute(new XmlAttribute(NAME, this.getName()));
+ }
+ }
+ saveProfilesFile(profiles);
+ }
+
+ /**
+ * Diese Methode erstellt ein neues Profil.
+ */
+ public void createProfile() {
+ int newProfileID = getNewProfileID();
+ if (getCurrentProfileID() != -1) {
+ xmlHandler.saveAsXml(this); // save current profile xml
+ }
+ this.profileId = newProfileID;
+ this.setDefaultValues();
+ FileManager.createProfileFiles(newProfileID);
+
+ // add into profiles.xml and save it
+ XmlTree profiles = getProfilesXml();
+ XmlTree profileTree = new XmlTree("profile");
+ profileTree.addAttribute(new XmlAttribute(ID, Integer.toString(newProfileID)));
+ profileTree.addAttribute(new XmlAttribute(NAME, getName()));
+ profiles.addChild(profileTree);
+ profiles.updateAttribute(new XmlAttribute(CURRENT, Integer.toString(newProfileID)));
+ saveProfilesFile(profiles);
+
+ // save new profile xml
+ xmlHandler.saveAsXml(this);
+ FileManager.setCurrentProfile(newProfileID);
+ notifyListeners(this);
+ }
+
+ private void setDefaultValues() {
+ this.name = DEFAULT_PROFILE_NAME;
+ this.currentGameId = -1;
+ this.gestureActive = false;
+ this.assistances = new AssistanceSet();
+ this.assistances.setAssistance(Assistances.markRowColumn);
+ this.statistics = new int[Statistics.values().length];
+ this.statistics[Statistics.fastestSolvingTime.ordinal()] = 5999;
+ notifyListeners(this);
+ }
+
+ /**
+ * Gibt eine neue Profil ID zurück. Bestehende Profile dürfen nicht gelöscht
+ * werden, sonder als solches markiert werden.
+ *
+ * @return
+ */
+ public int getNewProfileID() {
+ ArrayList used = new ArrayList();
+ for (XmlTree profile : getProfilesXml()) {
+ used.add(Integer.parseInt(profile.getAttributeValue(ID)));
+ }
+ int i = 1;
+ while (used.contains(i)) {
+ i++;
+ }
+ return i;
+ }
+
+ /**
+ * Diese Methode gibt die ID des aktuelen Profils zurück.
+ *
+ * @return Die ID des aktuellen Profils.
+ */
+ public int getCurrentProfileID() {
+ return this.profileId;
+ }
+
+ /**
+ * Diese Methode gibt die ID des aktuellen Spiels zurück, wenn es existiert,
+ * andernfalls -1.
+ *
+ * @return Die ID des aktuellen Spiels. -1, wenn es kein aktuelles Spiel
+ * gibt.
+ */
+ public int getCurrentGame() {
+ return this.currentGameId;
+ }
+
+ /**
+ * Diese Methode setzt das aktuelle Spiel auf die gegebene id
+ *
+ * @param id
+ * die id des nun aktuellen Spiels
+ */
+ public void setCurrentGame(int id) {
+ this.currentGameId = id;
+ }
+
+ /**
+ * Diese Methode gibt den Namen des aktuellen Spielerprofils zurück.
+ *
+ * @return Der Name des aktuellen Spielers
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * Setzt den Namen des aktuellen Spielerprofils
+ *
+ * @param name
+ * Der Name, der gesetzt werden soll
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Gibt ein AssistanceSet, welches die zurzeit im Profil aktivierten bzw.
+ * deaktivierten Hilfestellungen repräsentiert. Es kann durch die Methoden
+ * der {@link Assistances}-Klasse ausgelesen werden.
+ *
+ * @return Ein AssistanceSet, welches die im Profil aktivierten
+ * Hilfestellungen repräsentiert
+ */
+ public AssistanceSet getAssistances() {
+ return this.assistances;
+ }
+
+ /**
+ * Diese Methode gibt zurück, ob die Gesteneingabe im aktuellen
+ * Spielerprofil aktiv ist oder nicht.
+ *
+ * @return true, falls die Gesteneingabe im aktuellen Profil aktiv ist,
+ * false andernfalls
+ */
+ public boolean isGestureActive() {
+ return this.gestureActive;
+ }
+
+ /**
+ * Setzt die Verwendung von Gesten in den Preferences auf den übergebenen
+ * Wert.
+ *
+ * @param value
+ * true, falls Gesten gesetzt werden sollen, false falls nicht
+ */
+ public void setGestureActive(boolean value) {
+ this.gestureActive = value;
+ }
+
+ /**
+ * Gibt eine String Liste mit allen Profilnamen zurück.
+ *
+ * @return die Namensliste
+ */
+ public ArrayList getProfilesNameList() {
+ ArrayList profilesList = new ArrayList();
+ XmlTree profiles = getProfilesXml();
+ for (XmlTree profile : profiles) {
+ profilesList.add(profile.getAttributeValue(NAME));
+ }
+ return profilesList;
+ }
+
+ /**
+ * Gibt eine Integer Liste mit allen Profilids zurück.
+ *
+ * @return die Idliste
+ */
+ public ArrayList getProfilesIdList() {
+ ArrayList profilesList = new ArrayList();
+ XmlTree profiles = getProfilesXml();
+ for (XmlTree profile : profiles) {
+ profilesList.add(Integer.valueOf(profile.getAttributeValue(ID)));
+ }
+ return profilesList;
+ }
+
+ /**
+ * Setzt eine Assistance in den Preferences auf true oder false.
+ *
+ * @param assistance
+ * Assistance, welche gesetzt werden soll
+ * @param value
+ * true um die Assistance anzuschalten, sonst false
+ */
+ public void setAssistance(Assistances assistance, boolean value) {
+ if (value) this.assistances.setAssistance(assistance);
+ else this.assistances.clearAssistance(assistance);
+ // notifyListeners(this);
+ }
+
+ /**
+ * Diese Methode teilt mit, ob die spezifizierte Hilfestellung im aktuellen
+ * Spielerprofil aktiviert ist. Ist dies der Fall, so wird true
+ * zurückgegeben. Ist die Hilfestellung nicht aktiv oder ungültig, so wird
+ * false zurückgegeben.
+ *
+ * @param asst
+ * Die Hilfestellung von der überprüft werden soll, ob sie im
+ * aktuellen Profil aktiviert ist
+ * @return boolean true, falls die spezifizierte Hilfestellung im aktuellen
+ * Profil aktiviert ist, false falls sie es nicht oder ungültig ist
+ */
+ public boolean getAssistance(Assistances asst) {
+ return this.assistances.getAssistance(asst);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public XmlTree toXmlTree() {
+ XmlTree representation = new XmlTree("profile");
+ representation.addAttribute(new XmlAttribute("id", String.valueOf(getCurrentProfileID())));
+ representation.addAttribute(new XmlAttribute("currentGame", String.valueOf(getCurrentGame())));
+ representation.addAttribute(new XmlAttribute("name", getName()));
+ representation.addAttribute(new XmlAttribute("gestureActive", String.valueOf(isGestureActive())));
+ representation.addAttribute(new XmlAttribute("help", getAssistances().convertToString()));
+ for (Statistics stat : Statistics.values()) {
+ representation.addAttribute(new XmlAttribute(stat.name(), getStatistic(stat) + ""));
+ }
+ return representation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void fillFromXml(XmlTree xmlTreeRepresentation) {
+ setCurrentGame(Integer.parseInt(xmlTreeRepresentation.getAttributeValue("currentGame")));
+ setName(xmlTreeRepresentation.getAttributeValue("name"));
+ setGestureActive(Boolean.parseBoolean(xmlTreeRepresentation.getAttributeValue("gestureActive")));
+ this.assistances = AssistanceSet.fromString(xmlTreeRepresentation.getAttributeValue("help"));
+ this.statistics = new int[Statistics.values().length];
+ for (Statistics stat : Statistics.values()) {
+ this.statistics[stat.ordinal()] = Integer.parseInt(xmlTreeRepresentation.getAttributeValue(stat.name()));
+ }
+ }
+
+ private void saveProfilesFile(XmlTree profiles) {
+ try {
+ new XmlHelper().saveXml(profiles, FileManager.getProfilesFile());
+ } catch (IOException e) {
+ throw new IllegalStateException("Something went wrong writing profiles.xml", e);
+ }
+ }
+
+ private XmlTree getProfilesXml() {
+ try {
+ return new XmlHelper().loadXml(FileManager.getProfilesFile());
+ } catch (IOException e) {
+ throw new IllegalStateException("Something went wrong reading profiles.xml", e);
+ }
+ }
+
+ /**
+ * Setzt den Wert der gegebenen Statistik für dieses Profil auf den
+ * gegebenen Wert
+ *
+ * @param stat
+ * die zu setzende Statistik
+ * @param value
+ * der einzutragende Wert
+ */
+ public void setStatistic(Statistics stat, int value) {
+ if (stat == null)
+ return;
+ this.statistics[stat.ordinal()] = value;
+ }
+
+ /**
+ * Diese Methode gibt den Wert der spezifizierten Statistik im aktuellen
+ * Spielerprofil zurück. Ist die spezifizierte Statistik ungültig, so wird
+ * null zurückgegeben.
+ *
+ * @param stat
+ * Die Statistik, dessen Wert abgerufen werden soll
+ * @return Der Wert der spezifizierten Statistik als String, oder null falls
+ * diese ungültig ist
+ */
+ public int getStatistic(Statistics stat) {
+ if (stat == null)
+ return -1;
+ return this.statistics[stat.ordinal()];
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/profile/Statistics.java b/sudoq-model/src/de/sudoq/model/profile/Statistics.java
new file mode 100644
index 00000000..cc2c7af8
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/profile/Statistics.java
@@ -0,0 +1,55 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.profile;
+
+/**
+ * Dieses enum repräsentiert die verschiedenen Statistiken, die für ein
+ * Spielerprofil gespeichert und abgerufen werden können.
+ */
+public enum Statistics {
+ /**
+ * Die Anzahl der bereits beendeten Sudoku-Spiele
+ */
+ playedSudokus,
+
+ /**
+ * Die Anzahl der bereits beendeten Sudoku-Spiele mit Schwierigkeitsgrad
+ * einfach
+ */
+ playedEasySudokus,
+
+ /**
+ * Die Anzahl der bereits beendeten Sudoku-Spiele mit Schwierigkeitsgrad
+ * mittel
+ */
+ playedMediumSudokus,
+
+ /**
+ * Die Anzahl der bereits beendeten Sudoku-Spiele mit Schwierigkeitsgrad
+ * schwer
+ */
+ playedDifficultSudokus,
+
+ /**
+ * Die Anzahl der bereits beendeten Sudoku-Spiele mit Schwierigkeitsgrad
+ * höllisch
+ */
+ playedInfernalSudokus,
+
+ /**
+ * Die geringste Zeit in der ein Sudoku von diesem Spieler gelöst wurde
+ */
+ fastestSolvingTime,
+
+ /**
+ * Die maximale Anzahl an Punkten, die dieser Spieler in einem Spiel
+ * erreicht hat
+ */
+ maximumPoints;
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/Generator.java b/sudoq-model/src/de/sudoq/model/solverGenerator/Generator.java
new file mode 100644
index 00000000..b4db6815
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/Generator.java
@@ -0,0 +1,715 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import de.sudoq.model.solverGenerator.solver.ComplexityRelation;
+import de.sudoq.model.solverGenerator.solver.Solver;
+import de.sudoq.model.solverGenerator.solver.SolverSudoku;
+import de.sudoq.model.solverGenerator.transformations.Transformer;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.PositionMap;
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.SudokuBuilder;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+import de.sudoq.model.sudoku.sudokuTypes.StandardSudokuType;
+import de.sudoq.model.sudoku.sudokuTypes.StandardSudokuType16x16;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+import de.sudoq.model.sudoku.sudokuTypes.TypeStandard;
+
+/**
+ * Diese Klasse stellt verschiedene Methoden zum Erstellen eines validen, neuen
+ * Sudokus zur Verfügung. Dazu gibt es sowohl die Möglichkeit ein gänzlich neues
+ * Sudoku mit einer spezifizierten Schwierigkeit erzeugen zu lassen, als auch
+ * ein vorhandenes Sudoku durch Transformationen in ein Äquivalentes überführen
+ * zu lassen.
+ *
+ * @see Sudoku
+ * @see Solver
+ */
+public class Generator {
+ /** Attributes */
+
+ private Random random;
+
+ /** Constructors */
+
+ /**
+ * Initiiert ein neues Generator-Objekt.
+ */
+ public Generator() {
+ random = new Random();
+ }
+
+ /** Methods */
+
+ /**
+ * Erzeugt ein Sudoku entsprechend dem spezifizierten Typ und fügt dieses
+ * zusammen mit dem spezifizierten Callback-Objekt der Warteschlage zur
+ * Generierung von Sudokus hinzu. Zusätzlich wird dessen Schwierigkeit wie
+ * spezifiziert gesetzt. Ist die Warteschlange leer und läuft aktuell keine
+ * Generierung, so wird die Generierung dieses Sudokus sofort gestartet.
+ * Andernfalls wird die Generierung nach Beendigung aller in der
+ * Warteschlange befindlichen Sudokus gestartet.
+ *
+ * Ist das spezifizierte SudokuType-Objekt oder das GeneratorCallback-Objekt
+ * null, oder hat das Complexity-Argument einen ungültigen Wert, so wird
+ * false zurückgegeben. Ansonsten ist der Rückgabewert true.
+ *
+ * @param type
+ * Der SudokuTypes-Enum Wert, aus welchem ein Sudoku erstellt und
+ * generiert werden soll
+ * @param complexity
+ * Die Komplexität des zu erstellenden Sudokus
+ * @param callbackObject
+ * Das Objekt, dessen Callback-Methode aufgerufen werden soll,
+ * sobald der Generator fertig ist
+ * @return true, falls ein leeres Sudoku erzeugt und der Warteschlange
+ * hinzugefügt werden konnte, false andernfalls
+ */
+ public boolean generate(SudokuTypes type, Complexity complexity, GeneratorCallback callbackObject) {
+ if (type == null || complexity == null || callbackObject == null)
+ return false;
+
+ // Create sudoku
+ Sudoku sudoku = new SudokuBuilder(type).createSudoku();
+ sudoku.setComplexity(complexity);
+
+ if (sudoku.getSudokuType() instanceof StandardSudokuType
+ || sudoku.getSudokuType() instanceof StandardSudokuType16x16) {
+ new Thread(new SudokuGenerationStandardType(sudoku, callbackObject, random)).start();
+ } else {
+ new Thread(new SudokuGeneration(sudoku, callbackObject, random)).start();
+ }
+
+ // Initiate new random object
+ random = new Random();
+
+ return true;
+ }
+
+ /**
+ * NUR ZU DEBUG-ZWECKEN: Setzt das Random-Objekt dieses Sudokus, um einen
+ * reproduzierbaren, deterministischen Ablauf des Generator zu provozieren.
+ * Das Random-Objekt muss vor jedem Aufruf der generate-Methode neu gesetzt
+ * werden.
+ *
+ * @param rnd
+ * Das zu setzende random Objekt.
+ */
+ void setRandom(Random rnd) {
+ this.random = rnd;
+ }
+
+ /**
+ * Bietet die Möglichkeit Sudokus abgeleitet vom Typ {@link TypeStandard} zu
+ * genrieren. Für diese ist der Algorithmus wesentlich schneller als der von
+ * {@link SudokuGeneration}. Die Klasse implementiert das {@link Runnable}
+ * interface und kann daher in einem eigenen Thread ausgeführt werden.
+ */
+ private class SudokuGenerationStandardType implements Runnable {
+
+ /**
+ * Das Sudoku auf welchem die Generierung ausgeführt wird
+ */
+ private Sudoku sudoku;
+
+ /**
+ * Der Solver, der für Validierungsvorgänge genutzt wird
+ */
+ private Solver solver;
+
+ /**
+ * Das Objekt, auf dem nach Abschluss der Generierung die
+ * Callback-Methode aufgerufen wird
+ */
+ private GeneratorCallback callbackObject;
+
+ /**
+ * Eine Liste der aktuell definierten Felder
+ */
+ private List definedFields;
+
+ /**
+ * Die noch freien, also nicht belegten Felder des Sudokus
+ */
+ private List freeFields;
+
+ /**
+ * Das Zufallsobjekt für den Generator
+ */
+ private Random random;
+
+ /**
+ * Das gelöste Sudoku
+ */
+ private Sudoku solvedSudoku;
+
+ /**
+ * Definierte Felder
+ */
+ private int definedOnes;
+
+ /**
+ * Instanziiert ein neues Generierungsobjekt für das spezifizierte
+ * Sudoku. Da die Klasse privat ist wird keine Überprüfung der
+ * Eingabeparameter durchgeführt.
+ *
+ * @param sudoku
+ * Das Sudoku, auf dem die Generierung ausgeführt werden soll
+ * @param callbackObject
+ * Das Objekt, auf dem die Callback-Methode nach Abschluss
+ * der Generierung aufgerufen werden soll
+ * @param random
+ * Das Zufallsobjekt zur Erzeugung des Sudokus
+ */
+ public SudokuGenerationStandardType(Sudoku sudoku, GeneratorCallback callbackObject, Random random) {
+ this.sudoku = sudoku;
+ this.callbackObject = callbackObject;
+ this.solver = new Solver(sudoku);
+ this.freeFields = new ArrayList();
+ this.definedFields = new ArrayList();
+ this.random = random;
+ }
+
+ /**
+ * Die Methode, die die tatsächliche Generierung eines Sudokus mit der
+ * gewünschten Komplexität generiert.
+ */
+ public void run() {
+ // Reset, if it takes too long
+ // Create template sudoku of defined type and transform it
+ SudokuBuilder sub = new SudokuBuilder(sudoku.getSudokuType());
+ PositionMap solution = new PositionMap(sudoku.getSudokuType().getSize());
+ int sqrtSymbolNumber = (int) Math.sqrt(sudoku.getSudokuType().getNumberOfSymbols());
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+ sub.addSolution(Position.get(x, y),
+ ((y % sqrtSymbolNumber) * sqrtSymbolNumber + x + (y / sqrtSymbolNumber))
+ % (sqrtSymbolNumber * sqrtSymbolNumber));
+ }
+ }
+ solvedSudoku = sub.createSudoku();
+ Transformer.transform(solvedSudoku);
+
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+ solution.put(Position.get(x, y), solvedSudoku.getField(Position.get(x, y)).getSolution());
+ }
+ }
+
+ // Fill the sudoku being generated with template solutions
+
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+ sudoku.getField(Position.get(x, y)).setCurrentValue(
+ solvedSudoku.getField(Position.get(x, y)).getSolution(), false);
+ this.definedFields.add(Position.get(x, y));
+ }
+ }
+
+ ArrayList constraints = sudoku.getSudokuType().getConstraints();
+ ArrayList positions;
+ boolean emptyOne = false;
+ for (int i = 0; i < constraints.size(); i++) {
+ positions = constraints.get(i).getPositions();
+ emptyOne = false;
+ for (int j = 0; j < positions.size(); j++) {
+ if (sudoku.getField(positions.get(j)).isEmpty()) {
+ emptyOne = true;
+ break;
+ }
+ }
+ if (!emptyOne) {
+ int nr = random.nextInt(positions.size());
+ sudoku.getField(positions.get(nr)).setCurrentValue(Field.EMPTYVAL, false);
+ definedFields.remove(positions.get(nr));
+ freeFields.add(positions.get(nr));
+ definedOnes++;
+ }
+ }
+
+ ComplexityConstraint constr = sudoku.getSudokuType().buildComplexityConstraint(sudoku.getComplexity());
+
+ int nr = random.nextInt(definedFields.size());
+ int counter = definedFields.size();
+ while (counter >= 0 && definedFields.size() > constr.getAverageFields()) {
+ counter--;
+ sudoku.getField(definedFields.get(nr)).setCurrentValue(Field.EMPTYVAL, false);
+ ((SolverSudoku) solver.getSudoku()).resetCandidates();
+ if (((SolverSudoku) solver.getSudoku()).getCurrentCandidates(definedFields.get(nr)).cardinality() != 1) {
+ sudoku.getField(definedFields.get(nr)).setCurrentValue(
+ solvedSudoku.getField(definedFields.get(nr)).getSolution(), false);
+ nr = (nr + 1) % definedFields.size();
+ } else {
+ freeFields.add(definedFields.remove(nr));
+ definedOnes++;
+ if (nr >= definedFields.size())
+ nr = 0;
+ }
+ }
+
+ // ArrayList constraints =
+ // sudoku.getSudokuType().getConstraints();
+ // ArrayList positions;
+ // for (int i = 0; i < constraints.size(); i++) {
+ // positions = constraints.get(i).getPositions();
+ // int nr = random.nextInt(positions.size());
+ // sudoku.getField(positions.get(nr)).setCurrentValue(
+ // solvedSudoku.getField(positions.get(nr)).getSolution(), false);
+ // freeFields.remove(positions.get(nr));
+ // definedFields.add(positions.get(nr));
+ // }
+
+ int allocationFactor = sudoku.getSudokuType().getSize().getX() * sudoku.getSudokuType().getSize().getY()
+ / 20;
+
+ ComplexityRelation rel = ComplexityRelation.INVALID;
+ while (rel != ComplexityRelation.CONSTRAINT_SATURATION) {
+ // while (definedFields.size() > constr.getAverageFields()) {
+ // removeDefinedField();
+ // }
+
+ rel = solver.validate(solution, true);
+
+ switch (rel) {
+ case MUCH_TO_EASY:
+ for (int i = 0; i < allocationFactor / 2 && removeDefinedField(); i++) {
+ }
+ break;
+ case TO_EASY:
+ removeDefinedField();
+ break;
+ case INVALID:
+ case MUCH_TO_DIFFICULT:
+ for (int i = 0; i < allocationFactor && addDefinedField(); i++) {
+ }
+ break;
+ case TO_DIFFICULT:
+ addDefinedField();
+ break;
+ }
+ }
+
+ // Call the callback
+ SudokuBuilder suBi = new SudokuBuilder(sudoku.getSudokuType());
+ Position currentPos = null;
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+ currentPos = Position.get(x, y);
+ if (solvedSudoku.getField(currentPos) != null) {
+ int value = solvedSudoku.getField(currentPos).getSolution();
+ if (!sudoku.getField(currentPos).isEmpty())
+ suBi.setFixed(currentPos);
+ suBi.addSolution(currentPos, value);
+ }
+ }
+ }
+ Sudoku res = suBi.createSudoku();
+ res.setComplexity(sudoku.getComplexity());
+ callbackObject.generationFinished(res);
+ }
+
+ private boolean addDefinedField() {
+ if (freeFields.isEmpty()) return false;
+ else if (freeFields.size() == definedOnes) {
+ definedOnes--;
+ }
+ Position p = freeFields.remove(random.nextInt(freeFields.size() - definedOnes) + definedOnes);
+ sudoku.getField(p).setCurrentValue(solvedSudoku.getField(p).getSolution(), false);
+ definedFields.add(p);
+ return true;
+
+ // int y = random.nextInt(sudoku.getSudokuType().getSize().getY());
+ //
+ // int counter = sudoku.getSudokuType().getSize().getX() *
+ // sudoku.getSudokuType().getSize().getY();
+ // while (!markings[x][y] && counter >= 0) {
+ // x = (x + 1) % sudoku.getSudokuType().getSize().getX();
+ // y = x == 0 ? (y + 1) % sudoku.getSudokuType().getSize().getY() :
+ // y;
+ // counter--;
+ // }
+ //
+ // if (counter != -1) {
+ // sudoku.getField(Position.get(x, y)).setCurrentValue(
+ // solvedSudoku.getField(Position.get(x, y)).getSolution(), false);
+ // markings[x][y] = false;
+ // return true;
+ // } else {
+ // return false;
+ // }
+ }
+
+ /**
+ * Entfernt eines der definierten Felder.
+ *
+ * @return Die Position des entfernten Feldes
+ */
+ private boolean removeDefinedField() {
+ if (definedFields.isEmpty())
+ return false;
+ Position p = null;
+ p = definedFields.remove(random.nextInt(definedFields.size()));
+ sudoku.getField(p).setCurrentValue(Field.EMPTYVAL, false);
+ freeFields.add(p);
+ return true;
+
+ // int x = random.nextInt(sudoku.getSudokuType().getSize().getX());
+ // int y = random.nextInt(sudoku.getSudokuType().getSize().getY());
+ //
+ // int counter = sudoku.getSudokuType().getSize().getX() *
+ // sudoku.getSudokuType().getSize().getY();
+ // while (markings[x][y] && counter >= 0) {
+ // x = (x + 1) % sudoku.getSudokuType().getSize().getX();
+ // y = x == 0 ? (y + 1) % sudoku.getSudokuType().getSize().getY() :
+ // y;
+ // counter--;
+ // }
+ //
+ // if (counter != -1) {
+ // sudoku.getField(Position.get(x,
+ // y)).setCurrentValue(Field.EMPTYVAL, false);
+ // markings[x][y] = true;
+ // return true;
+ // } else {
+ // return false;
+ // }
+ }
+
+ }
+
+ /**
+ * Bietet die Möglichkeit Sudokus abgeleitet vom Typ {@link TypeStandard} zu
+ * genrieren. Für diese ist der Algorithmus wesentlich schneller als der von
+ * {@link SudokuGeneration}. Die Klasse implementiert das {@link Runnable}
+ * interface und kann daher in einem eigenen Thread ausgeführt werden.
+ */
+ private class SudokuGeneration implements Runnable {
+
+ /**
+ * Das Sudoku auf welchem die Generierung ausgeführt wird
+ */
+ private Sudoku sudoku;
+
+ /**
+ * Das Zufallsobjekt auf dem der Generator arbeitet.
+ */
+ private Random random;
+
+ /**
+ * Die Anzahl der Felder, die fest zu definieren ist
+ */
+ private int fieldsToDefine;
+
+ /**
+ * Ein Array von Markierungen zum Testen, welches Felder belegt werden
+ * können
+ */
+ boolean[][] markings;
+
+ /**
+ * Anzahl aktuell definierter Felder
+ */
+ private int currentFieldsDefined;
+
+ /**
+ * Der Solver, der für Validierungsvorgänge genutzt wird
+ */
+ private Solver solver;
+
+ /**
+ * Das Objekt, auf dem nach Abschluss der Generierung die
+ * Callback-Methode aufgerufen wird
+ */
+ private GeneratorCallback callbackObject;
+
+ /**
+ * Eine Liste der aktuell definierten Felder
+ */
+ private List definedFields;
+
+ /**
+ * Die noch freien, also nicht belegten Felder des Sudokus
+ */
+ private List freeFields;
+
+ /**
+ * ComplexityConstraint für ein Sudoku des definierten
+ * Schwierigkeitsgrades
+ */
+ private ComplexityConstraint currentConstraint;
+
+ /**
+ * Das gelöste Sudoku
+ */
+ private Sudoku solvedSudoku;
+
+ /**
+ * Instanziiert ein neues Generierungsobjekt für das spezifizierte
+ * Sudoku. Da die Klasse privat ist wird keine Überprüfung der
+ * Eingabeparameter durchgeführt.
+ *
+ * @param sudoku
+ * Das Sudoku, auf dem die Generierung ausgeführt werden soll
+ * @param callbackObject
+ * Das Objekt, auf dem die Callback-Methode nach Abschluss
+ * der Generierung aufgerufen werden soll
+ * @param random
+ * Das Zufallsobjekt zur Erzeugung des Sudokus
+ */
+ public SudokuGeneration(Sudoku sudoku, GeneratorCallback callbackObject, Random random) {
+ this.sudoku = sudoku;
+ this.callbackObject = callbackObject;
+ this.solver = new Solver(sudoku);
+ this.freeFields = new ArrayList();
+ this.definedFields = new ArrayList();
+ this.random = random;
+
+ this.currentConstraint = sudoku.getSudokuType().buildComplexityConstraint(sudoku.getComplexity());
+
+ for (int y = 0; y < this.sudoku.getSudokuType().getSize().getY(); y++) {
+ for (int x = 0; x < this.sudoku.getSudokuType().getSize().getX(); x++) {
+ if (this.sudoku.getField(Position.get(x, y)) != null)
+ freeFields.add(Position.get(x, y));
+ }
+ }
+ }
+
+ /**
+ * Die Methode, die die tatsächliche Generierung eines Sudokus mit der
+ * gewünschten Komplexität generiert.
+ */
+ public void run() {
+ boolean found = false;
+ // Calculate the number of fields to be filled
+ fieldsToDefine = Math.min((int) (sudoku.getSudokuType().getSize().getX()
+ * sudoku.getSudokuType().getSize().getY() * sudoku.getSudokuType().getStandardAllocationFactor()),
+ currentConstraint.getAverageFields());
+
+ markings = new boolean[sudoku.getSudokuType().getSize().getX()][sudoku.getSudokuType().getSize().getY()];
+ PositionMap solution = new PositionMap(this.sudoku.getSudokuType().getSize());
+ while (!found) {
+ // Remove some fields, because sudoku could not be validated
+ for (int i = 0; i < 5; i++) {
+ removeDefinedField();
+ }
+ // Define average number of fields
+ while (this.currentFieldsDefined < fieldsToDefine) {
+ if (addDefinedField() == null) {
+ for (int j = 0; j < 5 && this.currentFieldsDefined > 0; j++) {
+ removeDefinedField();
+ }
+ }
+ }
+
+ // Try to fill sudoku to have complexity constraint saturation
+ found = solver.solveAll(false, false);
+ }
+ // System.out.println("Found one");
+
+ Complexity saveCompl = solver.getSudoku().getComplexity();
+ solver.getSudoku().setComplexity(Complexity.arbitrary);
+ solver.validate(solution, false);
+ solver.getSudoku().setComplexity(saveCompl);
+
+ // Create the sudoku template generated before
+ SudokuBuilder sub = new SudokuBuilder(sudoku.getSudokuType());
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+ if (sudoku.getField(Position.get(x, y)) != null)
+ sub.addSolution(Position.get(x, y), solution.get(Position.get(x, y)));
+ }
+ }
+ solvedSudoku = sub.createSudoku();
+
+ while (!this.freeFields.isEmpty()) {
+ this.definedFields.add(this.freeFields.remove(0));
+ }
+
+ // Fill the sudoku being generated with template solutions
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+ if (sudoku.getField(Position.get(x, y)) != null) {
+ sudoku.getField(Position.get(x, y)).setCurrentValue(
+ solvedSudoku.getField(Position.get(x, y)).getSolution(), false);
+ }
+ }
+ }
+
+ int allocationFactor = sudoku.getSudokuType().getNumberOfSymbols()
+ * sudoku.getSudokuType().getNumberOfSymbols() / 20;
+ allocationFactor = allocationFactor == 0 ? 1 : allocationFactor;
+
+ ComplexityRelation rel = ComplexityRelation.INVALID;
+ while (rel != ComplexityRelation.CONSTRAINT_SATURATION) {
+ rel = solver.validate(null, false);
+
+ if (rel == ComplexityRelation.MUCH_TO_EASY) {
+ for (int i = 0; i < allocationFactor; i++)
+ removeDefinedField();
+ } else if (rel == ComplexityRelation.TO_EASY) {
+ removeDefinedField();
+ } else if (rel == ComplexityRelation.INVALID || rel == ComplexityRelation.TO_DIFFICULT
+ || rel == ComplexityRelation.MUCH_TO_DIFFICULT) {
+ for (int i = 0; i < allocationFactor && !freeFields.isEmpty(); i++) {
+ Position p = freeFields.remove(0);
+ sudoku.getField(p).setCurrentValue(solvedSudoku.getField(p).getSolution(), false);
+ definedFields.add(p);
+ }
+ }
+ }
+
+ // Call the callback
+ SudokuBuilder suBi = new SudokuBuilder(sudoku.getSudokuType());
+ Position currentPos = null;
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+ currentPos = Position.get(x, y);
+ if (solvedSudoku.getField(currentPos) != null) {
+ int value = solvedSudoku.getField(currentPos).getSolution();
+ if (!sudoku.getField(currentPos).isEmpty())
+ suBi.setFixed(currentPos);
+ suBi.addSolution(currentPos, value);
+ }
+ }
+ }
+ Sudoku res = suBi.createSudoku();
+ res.setComplexity(sudoku.getComplexity());
+ callbackObject.generationFinished(res);
+ }
+
+ /**
+ * Definiert ein weiteres Feld, sodass weiterhin Constraint Saturation
+ * vorhanden ist. Die Position des definierten Feldes wird
+ * zurückgegeben. Kann keines gefunden werden, so wird null
+ * zurückgegeben.
+ *
+ * @return Die Position des definierten Feldes oder null, falls keines
+ * gefunden wurde
+ */
+
+ private Position addDefinedField() {
+ // if (freeFields.isEmpty())
+ // return null;
+ //
+ // Position p =
+ // freeFields.remove(random.nextInt(freeFields.size()));
+ // if (solvedSudoku != null) {
+ // sudoku.getField(p).setCurrentValue(solvedSudoku.getField(p).getSolution(),
+ // false);
+ // } else {
+ // boolean valid = false;
+ // int offset =
+ // random.nextInt(sudoku.getSudokuType().getNumberOfSymbols());
+ // for (int j = 0; j < sudoku.getSudokuType().getNumberOfSymbols();
+ // j++) {
+ // sudoku.getField(p).setCurrentValue((j + offset) %
+ // sudoku.getSudokuType().getNumberOfSymbols(),
+ // false);
+ // valid = true;
+ // if (!sudoku.getSudokuType().checkSudoku(sudoku)) {
+ // valid = false;
+ // sudoku.getField(p).setCurrentValue(Field.EMPTYVAL, false);
+ // } else {
+ // break;
+ // }
+ // }
+ // if (!valid) {
+ // freeFields.add(p);
+ // p = null;
+ // }
+ // }
+ // if (p != null) {
+ // definedFields.add(p);
+ // currentFieldsDefined++;
+ // }
+ //
+ // return p;
+
+ int count = definedFields.size();
+
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+ markings[x][y] = false;
+ }
+ }
+
+ for (int i = 0; i < this.definedFields.size(); i++) {
+ count++;
+ markings[this.definedFields.get(i).getX()][this.definedFields.get(i).getY()] = true;
+ }
+
+ Position p = null;
+
+ while (p == null
+ && count != this.sudoku.getSudokuType().getSize().getX()
+ * this.sudoku.getSudokuType().getSize().getY()) {
+ int x = random.nextInt(sudoku.getSudokuType().getSize().getX());
+ int y = random.nextInt(sudoku.getSudokuType().getSize().getY());
+ if (sudoku.getField(Position.get(x, y)) == null) {
+ markings[x][y] = true;
+ count++;
+ } else if (markings[x][y] == false) {
+ markings[x][y] = true;
+ count++;
+ p = Position.get(x, y);
+ }
+ }
+
+ boolean valid = false;
+ int offset = random.nextInt(sudoku.getSudokuType().getNumberOfSymbols());
+ for (int j = 0; j < sudoku.getSudokuType().getNumberOfSymbols(); j++) {
+ sudoku.getField(p).setCurrentValue((j + offset) % sudoku.getSudokuType().getNumberOfSymbols(), false);
+ valid = true;
+ ArrayList constraints = this.sudoku.getSudokuType().getConstraints();
+ for (int i = 0; i < constraints.size(); i++) {
+ if (!constraints.get(i).isSaturated(sudoku)) {
+ valid = false;
+ sudoku.getField(p).setCurrentValue(Field.EMPTYVAL, false);
+ break;
+ }
+ }
+ if (valid) {
+ definedFields.add(p);
+ // freeFields.remove(p);
+ this.currentFieldsDefined++;
+ break;
+ }
+ }
+ if (!valid)
+ p = null;
+
+ return p;
+ }
+
+ /**
+ * Entfernt eines der definierten Felder.
+ *
+ * @return Die Position des entfernten Feldes
+ */
+ private Position removeDefinedField() {
+ if (definedFields.isEmpty())
+ return null;
+ Position p = null;
+ int nr = random.nextInt(definedFields.size());
+ p = definedFields.remove(nr);
+ sudoku.getField(p).setCurrentValue(Field.EMPTYVAL, false);
+ freeFields.add(p);
+ this.currentFieldsDefined--;
+ return p;
+ }
+
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/GeneratorCallback.java b/sudoq-model/src/de/sudoq/model/solverGenerator/GeneratorCallback.java
new file mode 100644
index 00000000..93a54b03
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/GeneratorCallback.java
@@ -0,0 +1,31 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator;
+
+import de.sudoq.model.sudoku.Sudoku;
+
+/**
+ * Dieses Interface muss implementiert werden, um die generate-Methode des
+ * Generator zu benutzen. Dieser führt die Generierung in einem anderen Thread
+ * aus und ruft die generationFinished-Methode dieses Callback-Objektes auf,
+ * sobald er fertig ist.
+ */
+public interface GeneratorCallback {
+ /** Methods */
+
+ /**
+ * Diese Methode wird vom Generator aufgerufen, nachdem er die Generierung
+ * eines Sudokus abgeschlossen hat. Das übergebene Sudoku soll dabei ein
+ * generiertes, valides Sudoku sein. Ist das spezifizierte Sudoku null, so
+ * wird nichts ausgeführt.
+ *
+ * @param sudoku
+ * Das vom Generator erzeugte, valide Sudoku
+ */
+ public void generationFinished(Sudoku sudoku);
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solution/DerivationBlock.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solution/DerivationBlock.java
new file mode 100644
index 00000000..3185a4c2
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solution/DerivationBlock.java
@@ -0,0 +1,48 @@
+package de.sudoq.model.solverGenerator.solution;
+
+import de.sudoq.model.sudoku.Constraint;
+
+/**
+ * Ein DerivationBlock stellt ein Constraint dar, welches für einen
+ * Lössungsschritt zum Lösen eines Sudoku-Feldes relevant ist.
+ */
+public class DerivationBlock {
+ /** Attributes */
+
+ /**
+ * Das Constraint, welches von diesem DerivationBlock als relevant für den
+ * zugehörigen Lösungsschritt repräsentiert wird
+ */
+ private Constraint block;
+
+ /** Constructors */
+
+ /**
+ * Dies Methode initiiert einen neuen DerivationBlock für das
+ * spezifiziertem, für einen Lössungsschritt relevante Constraint. Ist
+ * dieses null, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param block
+ * Das Constraint, welches von diesem DerivationBlock als für
+ * einen Lössungsschritt relevant repräsentiert werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das spezifizierten Constraint null ist
+ */
+ public DerivationBlock(Constraint block) {
+ if (block == null)
+ throw new IllegalArgumentException("specified block was null");
+ this.block = block;
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode gibt das Constraint zurück, welches diesem DerivationBlock
+ * zugewiesen wurde.
+ *
+ * @return Das Constraint, welches diesem DerivationBlock zugewiesen wurde
+ */
+ public Constraint getBlock() {
+ return block;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solution/DerivationField.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solution/DerivationField.java
new file mode 100644
index 00000000..f37057e2
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solution/DerivationField.java
@@ -0,0 +1,100 @@
+package de.sudoq.model.solverGenerator.solution;
+
+import java.util.BitSet;
+
+import de.sudoq.model.sudoku.Position;
+
+/**
+ * Ein DerivationField stellt die Kandidatenliste eines Feldes, sowie die
+ * relevanten Kandidaten eines Lösungsschrittes zum Lösen eines Sudoku-Feldes
+ * dar.
+ */
+public class DerivationField {
+ /** Attributes */
+
+ /**
+ * Die Position des Feldes, dessen Kandidaten dieses DerivationField
+ * repräsentiert
+ */
+ private Position position;
+
+ /**
+ * Die für die Lösung eines Feldes relevanten Kandidaten des zu diesem
+ * DerivationField gehörigen Feldes
+ */
+ private BitSet relevantCandidates;
+
+ /**
+ * Die in der Kandidatenliste vorhandenen, aber für den Lösungsschritt
+ * irrelevanten Kandidaten des zu diesem DerivationField gehörigen Feldes
+ */
+ private BitSet irrelevantCandidates;
+
+ /** Constructors */
+
+ /**
+ * Dieser Konstruktor initiiert ein neues DerivationField, welches einen
+ * Lösungsschritt für das Sudoku-Feld an der spezifizierten Position mit den
+ * übergebenen relevanten und irrelevanten Kandidaten repräsentiert. Ist
+ * einer der Parameter null, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param pos
+ * Die Position des Feldes, dessen Kandidaten dieses
+ * DerivationField repräsentieren soll
+ * @param relevantCandidates
+ * Die für den zugehörigen Lösungsschritt relevanten Kandidaten
+ * des Feldes an der angegebenen Position
+ * @param irrelevantCandidates
+ * Die in der Kandidatenliste vorhandenen, aber für den
+ * Lösungsschritt irrelevanten Kandidaten des Feldes an der
+ * angegebenen Position
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls einer der Parameter null ist
+ */
+ public DerivationField(Position pos, BitSet relevantCandidates, BitSet irrelevantCandidates) {
+ if (pos == null || relevantCandidates == null || irrelevantCandidates == null)
+ throw new IllegalArgumentException("one argument was null");
+ this.position = pos;
+ this.relevantCandidates = (BitSet) relevantCandidates.clone();
+ this.irrelevantCandidates = (BitSet) irrelevantCandidates.clone();
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode gibt die Position des Sudoku-Feldes zurück, auf dass sich
+ * dieses DerivationField bezieht.
+ *
+ * @return Die Position des Feldes, auf das sich dieses DerivationField
+ * bezieht
+ */
+ public Position getPosition() {
+ return position;
+ }
+
+ /**
+ * Diese Methode gibt das BitSet der für mit diesem DerivationField
+ * beschriebenen Lösungsschritt relevanten Kandidaten in dem der Position
+ * entsprechenden Sudoku-Feld zurück.
+ *
+ * @return Einen Klon des BitSets, welches die relevanten Kandidaten des
+ * zugehörigen Feldes für den Lösungsschritt repräsentiert
+ */
+ public BitSet getRelevantCandidates() {
+ return (BitSet) relevantCandidates.clone();
+ }
+
+ /**
+ * Diese Methode gibt das BitSet der in der Kandidatenliste vorhandenen,
+ * aber für den mit diesem DerivationField beschriebenen Lösungsschritt
+ * irrelevanten Kandidaten in dem der Position entsprechenden Sudoku-Feld
+ * zurück.
+ *
+ * @return Einen Klon des BitSets, welches die in der Kandidatenliste
+ * vorhandenen, aber für den Lösungsschritt irrelevanten Kandidaten
+ * des zugehörigen Feldes repräsentiert
+ */
+ public BitSet getIrrelevantCandidates() {
+ return (BitSet) irrelevantCandidates.clone();
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solution/Solution.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solution/Solution.java
new file mode 100644
index 00000000..a2c96731
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solution/Solution.java
@@ -0,0 +1,86 @@
+package de.sudoq.model.solverGenerator.solution;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import de.sudoq.model.actionTree.Action;
+
+/**
+ * Ein Solution-Objekt repräsentiert einen Lösungsschritt für ein Sudoku. Es
+ * setzt sich zusammen aus einer konkreten Action, die auf das Sudoku angewendet
+ * ein Feld löst und den Derivations, die die Herleitung für eine Lösung
+ * beschreiben (siehe dazu die Klassen SolveDerivation und Action).
+ */
+public class Solution {
+ /** Attributes */
+
+ /**
+ * Die Action, die das zu dieser Solution gehörige Feld löst oder null,
+ * falls diese Solution kein Feld löst
+ */
+ private Action action;
+
+ /**
+ * Eine Liste von SolveDerivations, die die Herleitung für die Action
+ * repräsentieren
+ */
+ private List derivations;
+
+ /** Constructors */
+
+ /**
+ * Initiiert ein neues Solution-Objekt.
+ */
+ public Solution() {
+ derivations = new ArrayList();
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode setzt die Action dieses Solution-Objektes auf die
+ * spezifizierte. Ist diese null, so wird nichts geändert.
+ *
+ * @param action
+ * Die Action, die diesem Solution-Objekt zugewiesen werden soll
+ */
+ public void setAction(Action action) {
+ if (action != null)
+ this.action = action;
+ }
+
+ /**
+ * Gibt die Action zurück, die diesem Solution-Objekt zugewiesen wurde.
+ *
+ * @return Die Action, die diesem Solution-Objekt zugewiesen wurde
+ */
+ public Action getAction() {
+ return action;
+ }
+
+ /**
+ * Diese Methode fügt die spezifizierten SolveDerivation zu der Liste der
+ * SolveDerivations dieses Solution-Objektes hinzu. Ist diese null, so wird
+ * sie nicht hinzugefügt.
+ *
+ * @param derivation
+ * Die SolveDerivation, die diesem Solution-Objekt hinzugefügt
+ * werden soll
+ */
+ public void addDerivation(SolveDerivation derivation) {
+ if (action != null)
+ derivations.add(derivation);
+ }
+
+ /**
+ * Diese methode gibt einen Iterator zurück, mithilfe dessen über die diesem
+ * Solution-Objekt hinzugefügten SolveDerivation iteriert werden kann.
+ *
+ * @return Einen Iterator, mit dem über die SolveDerivations dieses
+ * Solution-Objektes iteriert werden kann
+ */
+ public Iterator getDerivationIterator() {
+ return derivations.iterator();
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solution/SolveDerivation.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solution/SolveDerivation.java
new file mode 100644
index 00000000..ff49eaa7
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solution/SolveDerivation.java
@@ -0,0 +1,91 @@
+package de.sudoq.model.solverGenerator.solution;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Ein Objekt dieser Klasse stellt einen Herleitungsschritt für die Lösung eines
+ * Sudoku-Feldes dar. Dazu enthält es eine Liste von DerivationFields und
+ * DerivationBlocks, die Informationenen über die entsprechend relevanten
+ * Blöcke, sowie Kandidaten in den beteiligten Feldern enthalten.
+ */
+public class SolveDerivation {
+ /** Attributes */
+
+ /**
+ * Eine Liste von DerivationFields, die für diesen Lösungsschritt relevant
+ * sind
+ */
+ private List fields;
+
+ /**
+ * Eine Liste von DerivationBlocks, die für diesen Lösungsschritt relevant
+ * sind
+ */
+ private List blocks;
+
+ /** Constructors */
+
+ /**
+ * Initiiert ein neues SolveDerivation-Objekt.
+ */
+ public SolveDerivation() {
+ this.fields = new ArrayList();
+ this.blocks = new ArrayList();
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode fügt das spezifizierte DerivationField zur Liste der
+ * DerivationFields dieses SolveDerivation-Objektes hinzu. Ist das
+ * übergebene Objekt null, so wird es nicht hinzugefügt.
+ *
+ * @param field
+ * Das DerivationField, welches dieser SolveDerivation
+ * hinzugefügt werden soll
+ */
+ public void addDerivationField(DerivationField field) {
+ if (field == null)
+ return;
+ this.fields.add(field);
+ }
+
+ /**
+ * Diese Methode fügt den spezifizierten DerivationBlock zur Liste der
+ * DerivationBlocks dieses SolveDerivation-Objektes hinzu. Ist das übegebene
+ * Objekt null, so wird es nicht hinzugefügt.
+ *
+ * @param block
+ * Der DerivationBlock, welcher dieser SolveDerivation
+ * hinzugefügt werden soll
+ */
+ public void addDerivationBlock(DerivationBlock block) {
+ if (block == null)
+ return;
+ this.blocks.add(block);
+ }
+
+ /**
+ * Diese Methode gibt einen Iterator zurück, mit dem über die diesem Objekt
+ * hinzugefügten DerivationFields iteriert werden kann.
+ *
+ * @return Ein Iterator, mit dem über die DerivationFields dieses
+ * SolveDerivation-Objektes iteriert werden kann
+ */
+ public Iterator getFieldIterator() {
+ return fields.iterator();
+ }
+
+ /**
+ * Diese Methode gibt einen Iterator zurück, mithilfe dessen über die diesem
+ * Objekt hinzugefügten DerivationBlocks iteriert werden kann.
+ *
+ * @return Ein Iterator, mit dem über die DerivationBlocks dieses
+ * SolveDerivation-Objektes iteriert werden kann
+ */
+ public Iterator getBlockIterator() {
+ return blocks.iterator();
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/Backtracking.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/Backtracking.java
new file mode 100644
index 00000000..2564a3fb
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/Backtracking.java
@@ -0,0 +1,99 @@
+package de.sudoq.model.solverGenerator.solver;
+
+import java.util.BitSet;
+
+import de.sudoq.model.solverGenerator.solution.DerivationField;
+import de.sudoq.model.solverGenerator.solution.SolveDerivation;
+import de.sudoq.model.sudoku.Position;
+
+/**
+ * Dieser konkrete SolverHelper implementiert eine Vorgehensweise zum Lösen eines Sudokus. Das Backtracking ist ein Try
+ * & Error Verfahren, wobei beginnend bei einem Feld systematisch versucht wird ein Symbol einzutragen, sodass die
+ * Constraints weiterhin erfüllt sind. Ist dies der Fall, so wird dasselbe mit dem nächsten Feld getan, bis entweder in
+ * einem Feld beim Eintragen jedes Symbols die Constraints verletzt sind oder die Kandidatenliste eines anderen Feldes
+ * leer wird oder aber das gesamte Sudoku befüllt ist. In den ersten beiden Fällen wird ein Feld zurückgegangen
+ * (Backtracking) und dort mit dem nächsten Symbol fortgefahren.
+ */
+public class Backtracking extends SolveHelper {
+ /** Constructors */
+
+ /**
+ * Erzeugt einen neuen Backtracking Helfer für das spezifizierte Sudoku.
+ *
+ * @param sudoku
+ * Das Sudoku auf dem dieser Helper operieren soll
+ * @param complexity
+ * Die Schwierigkeit der Anwendbarkeit dieses Lösungshelfers
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das Sudoku null oder die complexity kleiner als 0 ist
+ */
+ protected Backtracking(SolverSudoku sudoku, int complexity) {
+ super(sudoku, complexity);
+ }
+
+ /** Methods */
+
+ /**
+ * Wendet das Backtracking-Verfahren an und ermittelt damit die Lösung für alle Felder des Sudokus. Es wird die
+ * Kandidatenliste desjenigen Feldes mit der kleinsten Kandidatenliste upgedated, sodass in dieser nur noch die
+ * korrekte Lösung vorhanden ist. Gibt es keine eindeutige kleinste Kandidatenliste, so wird diese zufällig
+ * ausgewählt.
+ *
+ * @param buildDerivation
+ * Bestimmt, ob beim Finden eines Subsets eine Herleitung dafür erstellt werden soll, welche daraufhin
+ * mit getDerivation abgerufen werden kann.
+ * @return true, falls das Backtracking angewendet werden konnte, false falls nicht
+ */
+ protected boolean update(boolean buildDerivation) {
+ Position leastCandidatesPosition = null;
+ lastDerivation = null;
+
+ int leastCandidates = -1;
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ if ((this.sudoku.getCurrentCandidates(this.sudoku.positions.get(i)).cardinality() < leastCandidates || leastCandidates == -1)
+ && this.sudoku.getCurrentCandidates(this.sudoku.positions.get(i)).cardinality() > 1) {
+ leastCandidates = this.sudoku.getCurrentCandidates(this.sudoku.positions.get(i)).cardinality();
+ leastCandidatesPosition = this.sudoku.positions.get(i);
+ }
+ }
+
+ if (leastCandidatesPosition == null)
+ return false;
+
+ int chosenCandidate = this.sudoku.getCurrentCandidates(leastCandidatesPosition).nextSetBit(0);
+ this.sudoku.startNewBranch(leastCandidatesPosition, chosenCandidate);
+
+ // UNCOMMENT THE FOLLOWING TO PRINT BACKTRACKING TRACE
+ /*
+ * for (int i = 0; i < sudoku.branchings.size(); i++) { System.out.print(" "); }
+ * System.out.println(leastCandidatesPosition + "(#" + leastCandidates + "): " + chosenCandidate);
+ */
+
+ if (buildDerivation) {
+ lastDerivation = new SolveDerivation();
+ BitSet irrelevantCandidates = (BitSet) this.sudoku.getCurrentCandidates(leastCandidatesPosition).clone();
+ BitSet relevantCandidates = new BitSet();
+ relevantCandidates.set(chosenCandidate);
+ irrelevantCandidates.clear(chosenCandidate);
+ DerivationField derivField = new DerivationField(leastCandidatesPosition, relevantCandidates,
+ irrelevantCandidates);
+ lastDerivation.addDerivationField(derivField);
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Als SolveDerivation wird lediglich die Kandidatenliste des gelösten Feldes als irrelevantCandidates, sowie die
+ * richtige Lösung des Feldes als relevantCandidate zurückgegeben.
+ *
+ * @return Eine SolveDerivation, die die Herleitung für den letzten update-Schritt enthält oder null, falls kein
+ * Backtracking möglich war
+ */
+ @Override
+ protected SolveDerivation getDerivation() {
+ return lastDerivation;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/BranchingPool.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/BranchingPool.java
new file mode 100644
index 00000000..53c330eb
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/BranchingPool.java
@@ -0,0 +1,133 @@
+package de.sudoq.model.solverGenerator.solver;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+import java.util.Stack;
+
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.PositionMap;
+
+class BranchingPool {
+ /**
+ * Eine Liste der erstellten, noch nicht vergebenen Maps
+ */
+ private Stack unusedBranchings;
+
+ /**
+ * Ein Stack der erstellten und bereits vergebenen Maps
+ */
+ private Stack usedBranchings;
+
+ /**
+ * Die Anzahl der im Pool befindlichen PositionMaps
+ */
+ private int numberOfAllocatedBranchings;
+
+ /**
+ * Initialisiert einen neues PositionMapPool mit PositionMaps der spezifizierten Größe. Ist diese null oder ist eine
+ * Dimension gleich 0, so wird eine IllegalArgumentException geworfen. Der Pool wird mit 2 PositionMaps
+ * initialisiert.
+ *
+ * @param dimension
+ * Die Größe der verwalteten PositionMaps
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls die Dimension null oder in einer Komponente 0 ist
+ */
+ BranchingPool() {
+ usedBranchings = new Stack();
+ unusedBranchings = new Stack();
+ numberOfAllocatedBranchings = 2;
+ unusedBranchings.push(new Branching());
+ unusedBranchings.push(new Branching());
+ }
+
+ /**
+ * Gibt eine PositionMap entsprechend der aktuell gesetzten Größe zurück. Ist der Pool leer, so wird seine Größe
+ * verdoppelt.
+ *
+ * @return Eine PositionMap entsprechend der aktuell gesetzten Größe
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls die spezifizierte Position null ist
+ */
+ Branching getBranching(Position p, int candidate) {
+ if (p == null)
+ throw new IllegalArgumentException("Position was null");
+ if (unusedBranchings.size() == 0) {
+ for (int i = 0; i < numberOfAllocatedBranchings; i++) {
+ unusedBranchings.add(new Branching());
+ }
+ numberOfAllocatedBranchings *= 2;
+ }
+
+ Branching ret = unusedBranchings.pop();
+ ret.position = p;
+ ret.candidate = candidate;
+ ret.complexityValue = 0;
+ usedBranchings.push(ret);
+ return ret;
+ }
+
+ /**
+ * Gibt die zuletzt geholte PositionMap an den Pool zurück.
+ */
+ void returnBranching() {
+ if (!usedBranchings.isEmpty()) {
+ Branching returnedMap = usedBranchings.pop();
+ returnedMap.solutionsSet.clear();
+ unusedBranchings.push(returnedMap);
+ }
+ }
+
+ /**
+ * Gibt alle PositionMaps an den Pool zurück.
+ */
+ void returnAll() {
+ while (!this.usedBranchings.isEmpty()) {
+ returnBranching();
+ }
+ }
+
+ /**
+ * Ein Branching-Objekt beschreibt einen Zweig der temporären Lösung mit dessen zugrundeliegender Einstiegsposition,
+ * dem Kandidaten, der für den Einstieg gewählt wurde und einer Liste von Lösungen, die in diesem Branch eingetragen
+ * wurden und nach dessen Entfernen zurückgesetzt werden müssen. Alle Attribute sind package scope verfügbar, um
+ * diese direkt bearbeiten zu können. Aus Performancegründen wurde auf einen Zugriff durch Getter/Setter-Methoden
+ * verzichtet.
+ */
+ class Branching {
+ /**
+ * Die Position, an der gebrancht wurde
+ */
+ Position position;
+
+ /**
+ * Der Kandidate mit dem gebrancht wurde
+ */
+ int candidate;
+
+ /**
+ * Die Liste von Positionen an denen in diesem Branch eine Lösung eingetragen wurde.
+ */
+ List solutionsSet;
+
+ /**
+ * Eine Map, welche für jede Position dessen Kandidaten vor dem Branchen speichert.
+ */
+ PositionMap candidates;
+
+ /**
+ * Der Komplexitätswert für diesen Branch
+ */
+ int complexityValue;
+
+ /**
+ * Erstellt ein neues Branching mit einem leeren SolutionSet. Alle anderen Attribute werden nicht initialisiert.
+ */
+ protected Branching() {
+ this.solutionsSet = new ArrayList();
+ }
+
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/ComplexityRelation.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/ComplexityRelation.java
new file mode 100644
index 00000000..cf877a7e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/ComplexityRelation.java
@@ -0,0 +1,36 @@
+package de.sudoq.model.solverGenerator.solver;
+
+/**
+ * Ein Enum um die Relationen zwischen Schwierigkeiten zu klassifizieren
+ */
+public enum ComplexityRelation {
+ /**
+ * Das Sudoku war gemäß den Constraints ungültig
+ */
+ INVALID,
+
+ /**
+ * Das Sudoku ist innerhalb der Constraints lösbar
+ */
+ CONSTRAINT_SATURATION,
+
+ /**
+ * Das Sudoku ist einfacher als die Constraints erlauben
+ */
+ TO_EASY,
+
+ /**
+ * Das Sudoku ist viel einfacher als die Constraints erlauben
+ */
+ MUCH_TO_EASY,
+
+ /**
+ * Das Sudoku ist schwieriger als die Constraints erlauben
+ */
+ TO_DIFFICULT,
+
+ /**
+ * Das Sudoku ist viel schwieriger als die Constraints erlauben
+ */
+ MUCH_TO_DIFFICULT
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/HiddenHelper.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/HiddenHelper.java
new file mode 100644
index 00000000..c1d526ae
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/HiddenHelper.java
@@ -0,0 +1,133 @@
+package de.sudoq.model.solverGenerator.solver;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+
+import de.sudoq.model.solverGenerator.solution.DerivationBlock;
+import de.sudoq.model.solverGenerator.solution.DerivationField;
+import de.sudoq.model.solverGenerator.solution.SolveDerivation;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Position;
+
+/**
+ * Dieser konkrete SolveHelper implementiert eine Vorgehensweise zum Lösen eines Sudokus. Der SubsetHelper sucht
+ * innerhalb der Constraints eines Sudokus nach n Kandidaten, die lediglich noch in denselben n Feldern vorkommen. (n
+ * entspricht dem level des Helpers). Ist dies der Fall, müssen diese n Kandidaten in den n Feldern in irgendeiner
+ * Kombination eingetragen werden und können somit aus den restlichen Kandidatnelisten entfernt werden.
+ */
+public class HiddenHelper extends SubsetHelper {
+
+ /**
+ * Erzeugt einen neuen HiddenHelper für das spezifizierte Suduoku mit dem spezifizierten level. Der level entspricht
+ * dabei der Größe der Symbolmenge nach der gesucht werden soll.
+ *
+ * @param sudoku
+ * Das Sudoku auf dem dieser Helper operieren soll
+ * @param level
+ * Das Größe der Symbolmenge auf die der Helper hin überprüft
+ * @param complexity
+ * Die Schwierigkeit der Anwendung dieser Vorgehensweise
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das Sudoku null oder das level oder die complexity kleiner oder gleich 0 ist
+ */
+ protected HiddenHelper(SolverSudoku sudoku, int level, int complexity) {
+ super(sudoku, level, complexity);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected boolean updateNext(Constraint constraint, boolean buildDerivation) {
+ boolean nextSetExists = true;
+ boolean foundSubset = false;
+ int subsetCount = 0;
+
+ ArrayList positions = constraint.getPositions();
+ while (nextSetExists) {
+ nextSetExists = false;
+ foundSubset = false;
+ // Count and save all the positions whose candidates are a subset of
+ // the one to be checked for,
+ // look if one of the other positions would be updated to prevent
+ // from finding one subset again
+ subsetCount = 0;
+ for (int posNum = 0; posNum < positions.size(); posNum++) {
+ if (this.sudoku.getCurrentCandidates(positions.get(posNum)).cardinality() > 0
+ && this.sudoku.getCurrentCandidates(positions.get(posNum)).intersects(currentSet)) {
+ if (subsetCount < this.level) {
+ subsetPositions[subsetCount] = positions.get(posNum);
+ subsetCount++;
+ } else {
+ subsetCount++;
+ break;
+ }
+ }
+ }
+
+ // If a subset was found, update the other candidates and look if
+ // something changed.
+ // If something changed, return this as update, otherwise continue
+ // searching
+ foundSubset = false;
+ if (subsetCount == this.level) {
+ for (int i = 0; i < subsetPositions.length; i++) {
+ localCopy.clear();
+ localCopy.or(this.sudoku.getCurrentCandidates(subsetPositions[i]));
+ this.sudoku.getCurrentCandidates(subsetPositions[i]).and(currentSet);
+ if (!this.sudoku.getCurrentCandidates(subsetPositions[i]).equals(localCopy)) {
+ // If something changed, a field could be updated, so
+ // the helper is applied
+ // If the derivation shell be returned, add the updated
+ // field to the derivation object
+ if (buildDerivation) {
+ if (!foundSubset) {
+ lastDerivation = new SolveDerivation();
+ lastDerivation.addDerivationBlock(new DerivationBlock(constraint));
+ }
+
+ BitSet relevantCandidates = (BitSet) this.sudoku.getCurrentCandidates(subsetPositions[i])
+ .clone();
+ BitSet irrelevantCandidates = localCopy;
+ irrelevantCandidates.andNot(currentSet);
+ DerivationField field = new DerivationField(subsetPositions[i], relevantCandidates,
+ irrelevantCandidates);
+ lastDerivation.addDerivationField(field);
+ }
+ foundSubset = true;
+ }
+ }
+ }
+
+ // System.out.println("H: " + constraint + ": " + set + ", " +
+ // subset + " (NI: " + (foundSubset) +
+ // "), (Count: " + (subsetCount)+ ")");
+
+ if (!foundSubset && constraintSet.cardinality() > this.level) {
+ nextSetExists = getNextSubset();
+ }
+ }
+
+ // If the derivation shell be returned, add the subset fields to the
+ // derivation object
+ if (foundSubset && buildDerivation) {
+ boolean foundOne = false;
+ for (int posNum = 0; posNum < positions.size(); posNum++) {
+ foundOne = false;
+ for (int i = 0; i < subsetCount; i++) {
+ if (positions.get(posNum) == subsetPositions[i])
+ foundOne = true;
+ }
+ if (!foundOne) {
+ BitSet irrelevantCandidates = (BitSet) this.sudoku.getCurrentCandidates(positions.get(posNum))
+ .clone();
+ DerivationField field = new DerivationField(positions.get(posNum), new BitSet(),
+ irrelevantCandidates);
+ lastDerivation.addDerivationField(field);
+ }
+ }
+ }
+
+ return foundSubset;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/NakedHelper.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/NakedHelper.java
new file mode 100644
index 00000000..daf14ce6
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/NakedHelper.java
@@ -0,0 +1,137 @@
+package de.sudoq.model.solverGenerator.solver;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+
+import de.sudoq.model.solverGenerator.solution.DerivationBlock;
+import de.sudoq.model.solverGenerator.solution.DerivationField;
+import de.sudoq.model.solverGenerator.solution.SolveDerivation;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Position;
+
+/**
+ * Dieser konkrete SolveHelper implementiert eine Vorgehensweise zum Lösen eines Sudokus. Der SubsetHelper sucht
+ * innerhalb der Constraints eines Sudokus nach n elementigen Teilmengen der Kandidaten, die in n Feldern vorkommen. (n
+ * entspricht dem level des Helpers). Kommen in n Feldern lediglich dieselben n Kandidaten vor, so können diese
+ * Kandidaten aus den anderen Listen des Constraints entfernt werden. Tauchen n Kandidaten lediglich in n Feldern auf,
+ * so können in diesen Feldern die restlichen Kandidaten entfernt werden.
+ */
+public class NakedHelper extends SubsetHelper {
+
+ /**
+ * Erzeugt einen neuen NakedHelper für das spezifizierte Suduoku mit dem spezifizierten level. Der level entspricht
+ * dabei der Größe der Symbolmenge nach der gesucht werden soll.
+ *
+ * @param sudoku
+ * Das Sudoku auf dem dieser Helper operieren soll
+ * @param level
+ * Das Größe der Symbolmenge auf die der Helper hin überprüft
+ * @param complexity
+ * Die Schwierigkeit der Anwendung dieser Vorgehensweise
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das Sudoku null oder das level oder die complexity kleiner oder gleich 0 ist
+ */
+ protected NakedHelper(SolverSudoku sudoku, int level, int complexity) throws IllegalArgumentException {
+ super(sudoku, level, complexity);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected boolean updateNext(Constraint constraint, boolean buildDerivation) {
+ boolean nextSetExists = true;
+ boolean foundSubset = false;
+ int subsetCount = 0;
+
+ ArrayList positions = constraint.getPositions();
+ while (nextSetExists) {
+ nextSetExists = false;
+ foundSubset = false;
+ // Count and save all the positions whose candidates are a subset of
+ // the one to be checked for,
+ // look if one of the other positions would be updated to prevent
+ // from finding one subset again
+ subsetCount = 0;
+ for (int i = 0; i < positions.size(); i++) {
+ if (this.sudoku.getCurrentCandidates(positions.get(i)).cardinality() > 0
+ && this.sudoku.getCurrentCandidates(positions.get(i)).cardinality() <= this.level) {
+ localCopy.clear();
+ localCopy.or(this.sudoku.getCurrentCandidates(positions.get(i)));
+ localCopy.and(currentSet);
+ if (this.sudoku.getCurrentCandidates(positions.get(i)).equals(localCopy)) {
+ if (subsetCount < this.level) {
+ subsetPositions[subsetCount] = positions.get(i);
+ subsetCount++;
+ } else {
+ subsetCount++;
+ break;
+ }
+ }
+ }
+ }
+
+ // If a subset was found, update the other candidates and look if
+ // something changed.
+ // If something changed, return this as update, otherwise continue
+ // searching
+ foundSubset = false;
+ boolean foundOne = false;
+ if (subsetCount == this.level) {
+ for (int posNum = 0; posNum < positions.size(); posNum++) {
+ foundOne = false;
+ for (int i = 0; i < subsetCount; i++) {
+ if (positions.get(posNum) == subsetPositions[i])
+ foundOne = true;
+ }
+ if (!foundOne) {
+ localCopy.clear();
+ localCopy.or(this.sudoku.getCurrentCandidates(positions.get(posNum)));
+ this.sudoku.getCurrentCandidates(positions.get(posNum)).andNot(currentSet);
+ if (!this.sudoku.getCurrentCandidates(positions.get(posNum)).equals(localCopy)) {
+ // If something changed, a field could be updated,
+ // so the helper is applied
+ // If the derivation shell be returned, add the
+ // updated field to the derivation object
+ if (buildDerivation) {
+ if (!foundSubset) {
+ lastDerivation = new SolveDerivation();
+ lastDerivation.addDerivationBlock(new DerivationBlock(constraint));
+ }
+ BitSet relevantCandidates = localCopy;
+ relevantCandidates.and(currentSet);
+ BitSet irrelevantCandidates = (BitSet) this.sudoku.getCurrentCandidates(
+ positions.get(posNum)).clone();
+ DerivationField field = new DerivationField(positions.get(posNum), relevantCandidates,
+ irrelevantCandidates);
+ lastDerivation.addDerivationField(field);
+ }
+ foundSubset = true;
+ }
+ }
+ }
+ }
+
+ // System.out.println("N: " + constraint + ": " + set + ", " +
+ // subset + " (NI: " + (foundSubset) +
+ // "), (Count: " + (subsetCount)+ ")");
+
+ if (!foundSubset && constraintSet.cardinality() > this.level) {
+ nextSetExists = getNextSubset();
+ }
+ }
+
+ // If the derivation shell be returned, add the subset fields to the
+ // derivation object
+ if (foundSubset && buildDerivation) {
+ for (int i = 0; i < subsetCount; i++) {
+ Position p = subsetPositions[i];
+ BitSet relevantCandidates = (BitSet) this.sudoku.getCurrentCandidates(p).clone();
+ DerivationField field = new DerivationField(p, relevantCandidates, new BitSet());
+ lastDerivation.addDerivationField(field);
+ }
+ }
+
+ return foundSubset;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SolveHelper.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SolveHelper.java
new file mode 100644
index 00000000..582d9041
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SolveHelper.java
@@ -0,0 +1,86 @@
+package de.sudoq.model.solverGenerator.solver;
+
+import de.sudoq.model.solverGenerator.solution.SolveDerivation;
+
+/**
+ * Dieses Interface definiert eine einheitliche Schnittstelle für verschiedene Vorgehensweisen zum Lösen eines Sudokus.
+ * Alle Helper aktualisieren bei erfolgreicher Anwendung der Vorgehensweise die Kandidatenlisten der Felder und
+ * schränken so die Möglichkeiten ein Symbol in ein Feld einzutragen ein, womit i. A. andere Helper ihre Vorgehensweise
+ * anwenden können.
+ */
+public abstract class SolveHelper {
+ /** Attributes */
+
+ /**
+ * Das Sudoku, auf welches dieser SolveHelper seine Vorgehensweise anwendet
+ */
+ protected SolverSudoku sudoku;
+
+ /**
+ * Die Schwierigkeit der Anwendbarkeit dieses Lösungshelfers
+ */
+ private int complexity;
+
+ /**
+ * Die Herleitung des letzten update-Schrittes;
+ */
+ protected SolveDerivation lastDerivation;
+
+ /** Constructors */
+
+ /**
+ * Erzeugt einen neues SolveHelper für das spezifizierte Sudoku mit der angegebenen Schwierigkeit.
+ *
+ * @param sudoku
+ * Das Sudoku auf dem operiert werden soll
+ * @param complexity
+ * Die Schwierigkeit der Anwendbarkeit dieses Helfers (muss >= 0 sein)
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das spezifizierte Sudoku null oder die angegebene Schwierigkeit kleiner als 0
+ * ist
+ */
+ protected SolveHelper(SolverSudoku sudoku, int complexity) {
+ if (sudoku == null)
+ throw new IllegalArgumentException("sudoku was null");
+ if (complexity < 0)
+ throw new IllegalArgumentException("complexity < 0 : " + complexity);
+
+ this.sudoku = sudoku;
+ this.complexity = complexity;
+ }
+
+ /** Methods */
+
+ /**
+ * Versucht die entsprechende Vorgehensweise solange auf das im konkreten SolveHelper gespeicherte Sudoku
+ * anzuwenden, bis sie zum ersten Mal zum Erfolg führt oder sie nirgendwo anwendbar ist. Kann die Vorgehensweise
+ * erfolgreich angewandt werden und wurde true für den Parameter buildDerivation übergeben, so wird dieses Vorgehen
+ * als SolveDerivation gespeichert und kann über getDerivation abgerfragt werden. Führt die Vorgehensweise bei dem
+ * spezifizierten Sudoku nicht zum Erfolg, so wird false zurückgegeben.
+ *
+ * @param buildDerivation
+ * Bestimmt, ob eine Herleitung erstellt werden soll, welche durch die getDerivation-Methode abgerufen
+ * werden kann oder nicht
+ * @return true, falls dieser Helper angewendet werden konnte, false falls nicht
+ */
+ abstract protected boolean update(boolean buildDerivation);
+
+ /**
+ * Gibt die Herleitung des letzten update-Schrittes zurück, sofern dieser mit dem Parameter buildDerivation
+ * aufgerufen wurde und erfolgreich war. Ansonsten wird false zurückgegeben.
+ *
+ * @return die Herleitung des letzten update-Schritte, falls vorhanden, sonst null
+ */
+ protected SolveDerivation getDerivation() {
+ return this.lastDerivation;
+ }
+
+ /**
+ * Gibt die Schwierigkeit der Anwendbarkeit dieses Helfers zurück. Dieser ist mit dem Konstruktor zu setzen.
+ *
+ * @return Die Schwierigkeit der Anwendbarkeit dieses Helfers
+ */
+ protected int getComplexity() {
+ return this.complexity;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/Solver.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/Solver.java
new file mode 100644
index 00000000..4749d7b8
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/Solver.java
@@ -0,0 +1,533 @@
+package de.sudoq.model.solverGenerator.solver;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+import java.util.Stack;
+
+import de.sudoq.model.actionTree.SolveAction;
+import de.sudoq.model.actionTree.SolveActionFactory;
+import de.sudoq.model.solverGenerator.solution.DerivationField;
+import de.sudoq.model.solverGenerator.solution.Solution;
+import de.sudoq.model.solverGenerator.solution.SolveDerivation;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.PositionMap;
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+/**
+ * Diese Klasse bietet Methoden zum Lösen eines Sudokus. Sowohl einzelne Felder, als auch gesamte Sudokus können gelöst
+ * werden. Auch das Validieren eines Sudokus auf Lösbarkeit ist möglich.
+ */
+public class Solver {
+ /** Attributes */
+
+ /**
+ * Das Sudoku, welches von diesem Solver gelöst wird
+ */
+ protected SolverSudoku sudoku;
+
+ /**
+ * Eine Liste von SolveHelpern, welche zum Lösen des Sudokus genutzt werden
+ */
+ private List helper;
+
+ /**
+ * Indikator dafür, ob für das weitere Lösen Kandidatenlisten benötigt werden oder nicht
+ */
+ private boolean candidatesNeeded;
+
+ /**
+ * Die Anzahl der verfügbaren Helfer;
+ */
+ private int numberOfHelpers;
+
+ /**
+ * Eine Liste der Lösungen des letzten solveAll-Aufrufes
+ */
+ private List lastSolutions;
+
+ /**
+ * Ein Stack von Branch-Punkten, damit bei einem Backtrack die Einträge aus der Herleitung gelöscht werden.
+ */
+ private Stack branchPoints;
+
+ /**
+ * Das ComplexityConstraint für die Schwierigkeit des Sudokus.
+ */
+ private ComplexityConstraint complConstr;
+
+ /** Constructors */
+
+ /**
+ * Initialisiert einen neuen Solver für das spezifizierte Sudoku-Objekt. Ist das Sudoku-Objekt null, so wird eine
+ * IllegalArgumentException geworfen. Alle Methoden dieser Klasse werden auf dem hier spezifizierten Sudoku
+ * ausgeführt.
+ *
+ * @param sudoku
+ * Das Sudoku, welches von diesem Solver gelöst werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das spezifizierte Sudoku null ist
+ */
+ public Solver(Sudoku sudoku) {
+ if (sudoku == null)
+ throw new IllegalArgumentException("sudoku was null");
+ this.sudoku = new SolverSudoku(sudoku);
+ this.complConstr = sudoku.getSudokuType().buildComplexityConstraint(sudoku.getComplexity());
+
+ // Initialize the helpers
+ helper = new ArrayList();
+
+ helper.add(new HiddenHelper(this.sudoku, 1, 21));
+ helper.add(new NakedHelper(this.sudoku, 2, 32));
+ helper.add(new NakedHelper(this.sudoku, 3, 40));
+ helper.add(new HiddenHelper(this.sudoku, 2, 42));
+ helper.add(new NakedHelper(this.sudoku, 4, 48));
+ helper.add(new HiddenHelper(this.sudoku, 3, 48));
+ helper.add(new NakedHelper(this.sudoku, 5, 49));
+ helper.add(new HiddenHelper(this.sudoku, 4, 54));
+ // helper.add(new HiddenHelper(this.sudoku, 5, 57));
+
+ helper.add(new Backtracking(this.sudoku, 70));
+ numberOfHelpers = helper.size();
+ }
+
+ /**
+ * Gibt das Sudoku zurück, auf dem der Solver arbeitet. Dieses Sudoku ist ein anderes als das originale!
+ *
+ * @return Das Sudoku-Objekt, auf dem der Solver arbeitet
+ */
+ public Sudoku getSudoku() {
+ return this.sudoku;
+ }
+
+ /** Methods */
+
+ /**
+ * Ermittelt die Lösung für ein Feld, sowie dessen Herleitung. Die Herleitung wird als Solution-Objekt
+ * zurückgegeben. Mit applySolution kann spezifiziert werden, dass die Lösung direkt in das Feld eingetragen werden
+ * soll. Kann keine Lösung ermittelt werden, z.B. weil ein Feld falsch gelöst ist, so wird null zurückgegeben.
+ * Hinweis: Ist ein Feld bereits inkorrekt gelöst, so kann der Aufruf dieser Methode dazu führen, dass ein weiteres
+ * Feld falsch gelöst wird.
+ *
+ * @param applySolution
+ * Gibt an, ob die Lösung direkt in das Feld eingetragen werden soll oder nicht
+ * @return Ein Solution-Objekt, welches Schritte zur Herleitung der Lösung eines Feldes enthält bzw null, falls
+ * keine Lösung gefunden wurde
+ */
+ public Solution solveOne(boolean applySolution) {
+ this.sudoku.resetCandidates();
+
+ // Look for constraint saturation at the beginning
+ for (Constraint con : this.sudoku.getSudokuType()) {
+ if (!con.isSaturated(this.sudoku))
+ return null;
+ }
+
+ Solution solution = new Solution();
+
+ boolean solvedField = false;
+ boolean didUpdate = true;
+ boolean isIncorrect = false;
+
+ while (!solvedField && didUpdate && !isIncorrect) {
+ didUpdate = false;
+
+ // try to solve the sudoku
+ if (isSolved())
+ return null;
+
+ if (!solvedField && isInvalid()) {
+ // if sudoku is invalid, has no branches and no solution was
+ // found, it is invalid
+ // if there was already a solution there is no further one, so
+ // it is solved correct
+ // if there is a branch, make a backstep
+ if (!this.sudoku.hasBranch()) {
+ isIncorrect = true;
+ } else {
+ this.sudoku.killCurrentBranch();
+ didUpdate = true;
+ }
+ }
+
+ for (Position p : this.sudoku.positions) {
+ BitSet b = this.sudoku.getCurrentCandidates(p);
+ if (b.cardinality() == 1) {
+ if (!this.sudoku.hasBranch()) {
+ solution.setAction(new SolveActionFactory().createAction(b.nextSetBit(0),
+ this.sudoku.getField(p)));
+ SolveDerivation deriv = new SolveDerivation();
+ deriv.addDerivationField(new DerivationField(p, (BitSet) b.clone(), new BitSet()));
+ solution.addDerivation(deriv);
+ solvedField = true;
+ } else {
+ this.sudoku.setSolution(p, b.nextSetBit(0));
+ didUpdate = true;
+ }
+ }
+ }
+
+ // According to their priority use the helpers until one of them can
+ // be applied
+ if (!solvedField && !didUpdate && !isIncorrect) {
+ for (SolveHelper hel : helper) {
+ if (hel.update(true)) {
+ solution.addDerivation(hel.getDerivation());
+ didUpdate = true;
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply solution if wanted
+ if (!isIncorrect && solvedField && applySolution) {
+ solution.getAction().execute();
+ }
+
+ return (!isIncorrect && solvedField) ? solution : null;
+ }
+
+ /**
+ * Löst das gesamte Sudoku, sofern keine Felder fehlerhaft gelöst sind. Ist buildDerivation true, so wird die
+ * Herleitung der Lösung erstellt und kann durch die getDerivation Methode abgerufen werden. Ist applySolutions
+ * true, so werden die Lösungen direkt in das Sudoku eingetragen, ist es false, so müssen die Lösungen aus der
+ * Herleitung selbst ausgeführt werden.
+ *
+ * @param buildDerivation
+ * Gibt an, ob eine Herleitung der Lösung erstellt werden soll
+ * @param applySolutions
+ * Gibt an, ob die Lösungen direkt in das Sudoku eingetragen werden sollen
+ * @return true, falls das Sudoku gelöst werden konnte, false falls nicht
+ */
+ public boolean solveAll(boolean buildDerivation, boolean applySolutions) {
+ boolean solved = false;
+ PositionMap copy = new PositionMap(this.sudoku.getSudokuType().getSize());
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ copy.put(this.sudoku.positions.get(i), this.sudoku.getField(this.sudoku.positions.get(i)).getCurrentValue());
+ }
+
+ solved = solveAll(buildDerivation, false, false);
+
+ // Restore old state if solutions shell not be applied or if sudoku could not be solved
+ if (!applySolutions || !solved) {
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ this.sudoku.getField(this.sudoku.positions.get(i)).setCurrentValue(
+ copy.get(this.sudoku.positions.get(i)), false);
+ }
+ }
+
+ return solved;
+ }
+
+ /**
+ * Gibt eine Liste von Lösungherleitungen zurück, die durch den letzten Aufruf der solveAll-Methode erzeigt wurde.
+ * Wurde die solveAll-Methode noch nicht bzw. ohne den Parameter buildSolution aufgerufen, so wird null
+ * zurückgegeben.
+ *
+ * @return Eine Liste der Herleitungen für den letzten Aufruf der solveAll-Methode, oder null, falls dieser Methode
+ * noch nicht oder ohne den Parameter buildSolution aufgerufen wurde
+ */
+ public List getSolutions() {
+ return this.lastSolutions;
+ }
+
+ /**
+ * Überprüft das gegebene Sudoku auf Validität entpsrechend dem spezifizierten ComplexityConstraint. Es wird
+ * versucht das Sudoku mithilfe der im ComplexityConstraint für die im Sudoku definierte Schwierigkeit definierten
+ * SolveHelper und Anzahl an Schritten versucht zu lösen. Das Ergbnis wird durch ein ComplexityRelation Objekt
+ * zurückgegeben. Wird eine PositionsMap übergeben, kann über den Parameter {@code in} spezifiziert werden, ob die
+ * eine Eingabe ist und dazu genutzt werden soll, die Lösung anzugeben und zu validieren oder ob das Objekt mit der
+ * Korrekten Lösung befüllt werden soll.
+ *
+ * @param solution
+ * In diese Map wird die ermittelte Lösung geschrieben
+ * @param in
+ * TODO
+ * @param in
+ * Spezifiziert, ob die solution Ein- oder Ausgabe ist
+ * @return Ein ComplexityRelation-Objekt, welches die Constraint-gemäße Lösbarkeit beschreibt
+ */
+ public ComplexityRelation validate(PositionMap solution, boolean in) {
+ ComplexityRelation result = ComplexityRelation.INVALID;
+
+ boolean solved = false;
+ boolean invalid = false;
+ PositionMap copy = new PositionMap(this.sudoku.getSudokuType().getSize());
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ copy.put(this.sudoku.positions.get(i), this.sudoku.getField(this.sudoku.positions.get(i)).getCurrentValue());
+ }
+
+ if (solveAll(false, true, false)) {
+ solved = true;
+ // store the correct solution
+ if (solution != null) {
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ if (!in) {
+ solution.put(this.sudoku.positions.get(i), this.sudoku.getField(this.sudoku.positions.get(i))
+ .getCurrentValue());
+ } else if (in
+ && solution.get(this.sudoku.positions.get(i)) != this.sudoku.getField(
+ this.sudoku.positions.get(i)).getCurrentValue()) {
+ solved = false;
+ }
+ }
+ }
+ }
+
+ if (this.sudoku.hasBranch()) {
+ this.sudoku.killCurrentBranch();
+ if (solved && solveAll(false, false, true))
+ invalid = true;
+ }
+
+ // restore initial state
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ this.sudoku.getField(this.sudoku.positions.get(i)).setCurrentValue(copy.get(this.sudoku.positions.get(i)),
+ false);
+ }
+
+ // depending on the result, return an int
+ if (!invalid && solved) {
+ if (this.sudoku.getComplexityValue() > complConstr.getMaxComplexityIdentifier()) {
+ if (this.sudoku.getComplexityValue() > complConstr.getMaxComplexityIdentifier() * 1.2)
+ result = ComplexityRelation.MUCH_TO_DIFFICULT;
+ else
+ result = ComplexityRelation.TO_DIFFICULT;
+ } else if (this.sudoku.getComplexityValue() < complConstr.getMinComplexityIdentifier()) {
+ if (this.sudoku.getComplexityValue() < complConstr.getMinComplexityIdentifier() * 0.8)
+ result = ComplexityRelation.MUCH_TO_EASY;
+ else
+ result = ComplexityRelation.TO_EASY;
+ } else {
+ result = ComplexityRelation.CONSTRAINT_SATURATION;
+ }
+ }
+
+ // System.out.println(sudoku.getComplexityValue() + "(" + sudoku.getComplexity() + ") " + result);
+
+ return result;
+ }
+
+ /**
+ * Löst das gesamte spezifizierte Sudoku. Die Lösung wird als Liste von Solution-Objekten zurückgeliefert, deren
+ * Reihenfolge die Reihenfolge der Lösungsschritte des Algorithmus, realisiert durch die SolveHelper, repräsentiert.
+ * Ist das Sudoku invalide und kann somit nicht eindeutig gelöst werden, so wird null zurückgegeben.
+ *
+ * @param returnDerivation
+ * Bestimmt, ob die Herleitung der Lösung oder lediglich eine leere Liste zurückgegeben werden soll
+ * @param followComplexityConstraints
+ * Bestimmt, ob zum Lösen die Constraints der Komplexität des Sudokus befolgt werden müssen
+ * @param validation
+ * Besagt, dass dieser Lösungsversuch zum Validieren gedacht ist und daher die Kandidatenlisten nicht
+ * zurückgesetzt werden sollen und ob die Schwierigkeit jedes Lösungsschrittes zum Sudoku hinzugefügt
+ * werden soll
+ * @return Eine Liste von Solution-Objekten, welche die Lösung und Herleitung für jedes Feld enthält oder null,
+ * falls kein Feld eindeutig gelöst werden kann
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls followComplexityConstraints true ist, jedoch keine Constraint-Definition für den
+ * Sudokutyp und die Schwierigkeit vorhanden ist
+ */
+ private boolean solveAll(boolean buildDerivation, boolean followComplexityConstraints, boolean validation) {
+ if (!validation)
+ this.sudoku.resetCandidates();
+ candidatesNeeded = false;
+
+ try {
+ if (followComplexityConstraints) {
+ complConstr = this.sudoku.getSudokuType().buildComplexityConstraint(this.sudoku.getComplexity());
+ numberOfHelpers = complConstr.getNumberOfAllowedHelpers();
+ } else {
+ numberOfHelpers = this.helper.size();
+ }
+ } catch (NullPointerException e) {
+ throw new IllegalArgumentException("Invalid sudoku complexity to follow constraints");
+ }
+
+ // Look for constraint saturation at the beginning
+ if (!this.sudoku.getSudokuType().checkSudoku(this.sudoku)) {
+ return false;
+ }
+
+ boolean solved = false;
+ boolean didUpdate = true;
+ boolean isIncorrect = false;
+
+ if (buildDerivation) {
+ lastSolutions = new ArrayList();
+ lastSolutions.add(new Solution());
+ branchPoints = new Stack();
+ }
+
+ while (!solved && didUpdate && !isIncorrect) {
+ didUpdate = false;
+
+ // try to solve the sudoku
+ solved = isSolved();
+
+ if (!solved && isInvalid()) {
+ /*
+ * if sudoku is invalid, has no branches and no solution was found, it is invalid if there was already a
+ * solution there is no further one, so it is solved correct if there is a branch, make a backstep
+ */
+ if (!this.sudoku.hasBranch()) {
+ isIncorrect = true;
+ } else {
+ if (buildDerivation) {
+ while (lastSolutions.size() > branchPoints.peek()) {
+ lastSolutions.remove(lastSolutions.size() - 1);
+ }
+ branchPoints.pop();
+ }
+ this.sudoku.killCurrentBranch();
+ didUpdate = true;
+ }
+ }
+
+ // try to update naked singles
+ if (!solved && !didUpdate && !isIncorrect) {
+ if (updateNakedSingles(buildDerivation, !validation)) {
+ didUpdate = true;
+ }
+ }
+
+ // According to their priority use the helpers until one of them can
+ // be applied
+ if (!solved && !didUpdate && !isIncorrect) {
+ for (int i = 0; i < numberOfHelpers; i++) {
+ if (i == 2)
+ candidatesNeeded = true;
+ SolveHelper hel = helper.get(i);
+ if (hel.update(buildDerivation)) {
+ if (!validation)
+ this.sudoku.addComplexityValue(hel.getComplexity(), !(hel instanceof Backtracking));
+ if (this.candidatesNeeded)
+ this.sudoku.addComplexityValue(30, !(hel instanceof Backtracking));
+ if (buildDerivation) {
+ if (hel instanceof Backtracking) {
+ branchPoints.push(lastSolutions.size());
+ }
+ lastSolutions.get(lastSolutions.size() - 1).addDerivation(hel.getDerivation());
+ }
+ didUpdate = true;
+ break;
+ }
+ }
+ }
+
+ // UNCOMMENT THE FOLLOWING TO PRINT THE WHOLE SUDOKU AFTER EACH LOOP
+
+ // StringBuilder sb = new StringBuilder();
+ // for (int j = 0; j < sudoku.getSudokuType().getSize().getY(); j++)
+ // {
+ // for (int i = 0; i
+ // < sudoku.getSudokuType().getSize().getX(); i++) {
+ // int value =
+ // sudoku.getField(new Position(i, j)).getCurrentValue();
+ // String op = value + "";
+ // if (value < 10)
+ // op = " " + value;
+ // if (value == -1)
+ // op = " x";
+ // sb.append(op + ", ");
+ // }
+ // sb.append("\n");
+ // }
+ // System.out.println(sb);
+
+ }
+
+ if (!solved) {
+ lastSolutions = null;
+ } else if (buildDerivation) {
+ lastSolutions.remove(lastSolutions.size() - 1);
+ }
+
+ // depending on the result, return an int
+ return solved;
+ }
+
+ boolean failed = false;
+
+ /**
+ * Sucht nach NakedSingles und trägt diese daraufhin als Lösung für das jeweilige Feld ein. Gibt zurück, ob ein
+ * NakedSingle gefunden wurde.
+ *
+ * @param returnDerivations
+ * Bestimmt, ob die Herleitung der Lösungen zurückgegeben oder lediglich eine leere Liste zurückgegeben
+ * werden soll
+ * @param addComplexity
+ * Bestimmt, ob der Schwierigkeitswert beim Finden eines NakedSingles dem Sudoku hinzugefügt werden soll
+ * @return Eine Liste der Herleitungen der Lösungen oder null, falls keine gefunden wurde
+ */
+ private boolean updateNakedSingles(boolean addDerivations, boolean addComplexity) {
+ boolean hasNakedSingle = false;
+ failed = false;
+ // Iterate trough the fields to look if each field has only one
+ // candidate left = solved
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ BitSet b = this.sudoku.getCurrentCandidates(this.sudoku.positions.get(i));
+ if (b.cardinality() == 1) {
+ if (addDerivations) {
+ Solution sol = lastSolutions.get(lastSolutions.size() - 1);
+ SolveDerivation deriv = new SolveDerivation();
+ deriv.addDerivationField(new DerivationField(this.sudoku.positions.get(i), (BitSet) b.clone(),
+ new BitSet()));
+ SolveAction action = (SolveAction) new SolveActionFactory().createAction(b.nextSetBit(0),
+ this.sudoku.getField(this.sudoku.positions.get(i)));
+ sol.setAction(action);
+ sol.addDerivation(deriv);
+ lastSolutions.add(new Solution());
+ }
+ sudoku.setSolution(this.sudoku.positions.get(i), b.nextSetBit(0));
+ if (addComplexity) {
+ this.sudoku.addComplexityValue(18, true);
+ if (this.candidatesNeeded)
+ this.sudoku.addComplexityValue(30, true);
+ }
+ hasNakedSingle = true;
+ }
+ }
+
+ return hasNakedSingle;
+ }
+
+ /**
+ * Überprüft, ob das Sudoku invalide ist, also ob es ein ungelöstes Feld gibt, für das keine Kandidaten mehr
+ * vorhanden sind.
+ *
+ * @return true, falls das Sudoku aktuell invalide ist, false falls nicht
+ */
+ private boolean isInvalid() {
+ boolean invalid = false;
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ if (this.sudoku.getCurrentCandidates(this.sudoku.positions.get(i)).cardinality() == 0
+ && this.sudoku.getField(this.sudoku.positions.get(i)).isEmpty()) {
+ invalid = true;
+ }
+ }
+
+ return invalid;
+ }
+
+ /**
+ * Überprüft, ob das Sudoku gelöst ist. Dies ist der Fall, wenn für jedes Feld eine Lösung eingetragen worden ist
+ * und alle Constraints des Sudokus erfüllt sind.
+ *
+ * @return true, falls das Sudoku gelöst ist, false andernfalls
+ */
+ private boolean isSolved() {
+ boolean solved = true;
+
+ for (int i = 0; i < this.sudoku.positions.size(); i++) {
+ if (this.sudoku.getField(this.sudoku.positions.get(i)).isEmpty()) {
+ solved = false;
+ }
+ }
+
+ return solved;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SolverSudoku.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SolverSudoku.java
new file mode 100644
index 00000000..792c6ec3
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SolverSudoku.java
@@ -0,0 +1,459 @@
+package de.sudoq.model.solverGenerator.solver;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+import java.util.Stack;
+
+import de.sudoq.model.solverGenerator.solver.BranchingPool.Branching;
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.PositionMap;
+import de.sudoq.model.sudoku.Sudoku;
+
+/**
+ * Eine für den Lösungsalgorithmus optimierte und erweiterte Sudoku Klasse
+ */
+public class SolverSudoku extends Sudoku {
+ /** Attributes */
+
+ /**
+ * Eine Liste aller Positionen dieses Sudokus
+ */
+ List positions;
+
+ /**
+ * Mappt die Positionen auf eine Liste von Constraints, zu welchen diese Position gehört
+ */
+ PositionMap> constraints;
+
+ /**
+ * Mappt die Positionen auf ein BitSet, welches die Kandidaten für dieses Feld repräsentiert nach jedem
+ * Branching-Schritt repräsentiert
+ */
+ private PositionMap currentCandidates;
+
+ /**
+ * Speichert die Positionen an denen gebrancht wurde.
+ */
+ Stack branchings;
+
+ /**
+ * Der BranchingPool zum Verwalten der Branchings.
+ */
+ private BranchingPool branchPool;
+
+ /**
+ * Der PositionMapPool zum Verwalten der für das Branching benötigten PositionMaps.
+ */
+ private PositionMapPool positionPool;
+
+ /**
+ * Die Summe der Schwierigkeit aller auf diesem Sudoku ausgeführten Operationen zum Lösen
+ */
+ private int complexityValue;
+
+ /**
+ * Instanziiert ein neues SolverSudoku, welches sich auf das spezifizierte Sudoku bezieht.
+ *
+ * @param sudoku
+ * Das Sudoku zu dem dieses SolverSudoku gehört
+ * @throws NullpointerException
+ * Wird geworfen, falls das spezifizierte Sudoku null ist
+ */
+ public SolverSudoku(Sudoku sudoku) {
+ super(sudoku.getSudokuType());
+ this.setComplexity(sudoku.getComplexity());
+
+ // initialize the list of positions
+ this.positions = new ArrayList();
+ for (Position p : fields.keySet()) {
+ this.positions.add(p);
+ }
+
+ // initialize new SolverSudoku with the fields of the specified one
+ for (int i = 0; i < this.positions.size(); i++) {
+ if (fields.remove(positions.get(i)) != null)
+ fields.put(positions.get(i), sudoku.getField(positions.get(i)));
+ }
+
+ // initialize the constraints lists for each position and the initial
+ // candidates for each field
+ this.constraints = new PositionMap>(this.getSudokuType().getSize());
+ for (int i = 0; i < this.positions.size(); i++) {
+ this.constraints.put(positions.get(i), new ArrayList());
+ }
+
+ // add the constraints each position belongs to to the list
+ ArrayList allConstraints = sudoku.getSudokuType().getConstraints();
+ ArrayList currentPositions;
+ for (int constrNum = 0; constrNum < allConstraints.size(); constrNum++) {
+ currentPositions = allConstraints.get(constrNum).getPositions();
+ for (int posNum = 0; posNum < currentPositions.size(); posNum++) {
+ this.constraints.get(currentPositions.get(posNum)).add(allConstraints.get(constrNum));
+ }
+ }
+
+ // initialize the candidates map
+ this.positionPool = new PositionMapPool(getSudokuType().getSize(), positions);
+ this.branchPool = new BranchingPool();
+ this.currentCandidates = this.positionPool.getPositionMap();
+
+ // initialize the candidate lists and branchings
+ this.branchings = new Stack();
+ this.resetCandidates();
+ }
+
+ /**
+ * Setzt die Kandidatenlisten aller Feldern zurück, sodass alle Kandidatenlisten komplett befüllt sind. "Komplett"
+ * wird anhand des größten Constraints in dem sich dieses Feld befindet bemessen. Anschließend werden die
+ * Kandidatenlisten bzgl. ConstraintSaturation upgedatet.
+ */
+ public void resetCandidates() {
+ this.complexityValue = 0;
+
+ // delete the branchings
+ this.branchPool.returnAll();
+ this.positionPool.returnAll();
+ this.branchings.clear();
+
+ this.currentCandidates = this.positionPool.getPositionMap();
+ // set the candidate lists of all fields to maximum
+ for (int i = 0; i < this.positions.size(); i++) {
+ if (fields.get(this.positions.get(i)).isEmpty()) {
+ this.currentCandidates.get(this.positions.get(i)).set(0, getSudokuType().getNumberOfSymbols());
+ }
+ }
+
+ updateCandidates();
+ }
+
+ /**
+ * Initialisiert einen neuen Zweig, indem der aktuelle Stand der Kandidatenlisten kopiert und auf den
+ * Branching-Stack gepusht wird. Der Branch wird an der spezifizierten Position vorgenommen. Dabei wird der
+ * spezifizierte Kandidat als temporäre Lösung für das übergebene Feld gesetzt.
+ *
+ * @param pos
+ * Die Position an der gebrancht werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls die spezifizierte Position null oder nicht in dem Sudoku vorhanden ist
+ */
+ void startNewBranch(Position pos, int candidate) {
+ if (pos == null || this.fields.get(pos) == null)
+ throw new IllegalArgumentException("Position was null or does not exist in this sudoku.");
+
+ // initialize a new branch and copy candidate lists of current branch
+ Branching branch = this.branchPool.getBranching(pos, candidate);
+ branch.candidates = currentCandidates;
+ this.currentCandidates = this.positionPool.getPositionMap();
+ for (int i = 0; i < this.positions.size(); i++) {
+ this.currentCandidates.get(this.positions.get(i)).or(branch.candidates.get(this.positions.get(i)));
+ }
+
+ this.branchings.push(branch);
+
+ this.currentCandidates.get(pos).clear();
+ this.currentCandidates.get(pos).set(candidate);
+ }
+
+ /**
+ * Entfernt den aktuellen Zweig und löscht den gesetzten Wert aus der Kandidatenliste des Feldes, welches für das
+ * Branching genutzt wurde. Alles Änderungen in dem Zweig werden zurückgesetzt. Ist kein aktueller Zweig vorhanden,
+ * so wird nichts getan.
+ */
+ Position killCurrentBranch() {
+ // if there is no branch, return
+ if (this.branchings.isEmpty())
+ return null;
+
+ // delete old branch and remove the candidate used for branching from
+ // candidates list
+ Branching lastBranching = this.branchings.pop();
+ currentCandidates = lastBranching.candidates;
+ for (int i = 0; i < lastBranching.solutionsSet.size(); i++) {
+ fields.get(lastBranching.solutionsSet.get(i)).setCurrentValue(Field.EMPTYVAL, false);
+ }
+ this.complexityValue -= lastBranching.complexityValue;
+
+ BitSet branchCandidates = this.currentCandidates.get(lastBranching.position);
+ branchCandidates.clear(lastBranching.candidate);
+ this.branchPool.returnBranching();
+ this.positionPool.returnPositionMap();
+ if (branchCandidates.cardinality() == 0) {
+ return killCurrentBranch();
+ } else {
+ return lastBranching.position;
+ }
+ }
+
+ /**
+ * Updatet die Kandidatenlisten aller Felder dahingehend, dass alle Kandidaten, die die Constraints bei deren
+ * Eintragung in ein Feld nicht erfüllen würden aus der jeweiligen Kandidatenliste entfernt werden.
+ */
+ void updateCandidates() {
+ ArrayList updatedConstraints;
+ ArrayList updatedPositions;
+ boolean isInvalid = false;
+
+ for (int posNum = 0; posNum < this.positions.size() && !isInvalid; posNum++) {
+ if (!getField(this.positions.get(posNum)).isEmpty()) {
+ // Update fields in unique constraints
+ updatedConstraints = this.constraints.get(this.positions.get(posNum));
+ for (int uc = 0; uc < updatedConstraints.size() && !isInvalid; uc++) {
+ if (updatedConstraints.get(uc).hasUniqueBehavior()) {
+ updatedPositions = updatedConstraints.get(uc).getPositions();
+ for (int up = 0; up < updatedPositions.size() && !isInvalid; up++) {
+ this.currentCandidates.get(updatedPositions.get(up)).clear(
+ getField(this.positions.get(posNum)).getCurrentValue());
+ if (this.currentCandidates.get(updatedPositions.get(up)).cardinality() == 0
+ && getField(updatedPositions.get(up)).isEmpty())
+ isInvalid = true;
+ }
+ }
+ }
+ } else {
+ // Update candidates in non-unique constraints
+ boolean hasNonUnique = false;
+ updatedConstraints = this.constraints.get(this.positions.get(posNum));
+ for (int i = 0; i < updatedConstraints.size(); i++) {
+ if (!updatedConstraints.get(i).hasUniqueBehavior()) {
+ hasNonUnique = true;
+ break;
+ }
+ }
+ if (hasNonUnique) {
+ Field currentField = null;
+ BitSet currentCandidatesSet = null;
+ currentField = this.fields.get(this.positions.get(posNum));
+ currentCandidatesSet = this.currentCandidates.get(this.positions.get(posNum));
+ int currentCandidate = -1;
+ int numberOfCandidates = currentCandidatesSet.cardinality();
+ for (int i = 0; i < numberOfCandidates; i++) {
+ currentCandidate = currentCandidatesSet.nextSetBit(currentCandidate + 1);
+ currentField.setCurrentValue(currentCandidate, false);
+ for (int constrNum = 0; constrNum < updatedConstraints.size(); constrNum++) {
+ if (!updatedConstraints.get(constrNum).isSaturated(this))
+ currentCandidatesSet.clear(currentCandidate);
+ }
+ currentField.setCurrentValue(Field.EMPTYVAL, false);
+ }
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Updatet die Kandidatenlisten aller Felder, die in einem Constraint liegen in dem sich auch die spezifizierte
+ * Position befindet dahingehend, dass alle Kandidaten, die die Constraints bei deren Eintragung in ein Feld nicht
+ * erfüllen würden aus der jeweiligen Kandidatenliste entfernt werden. Ist die übergebene Position null, so wird
+ * nichts getan
+ *
+ * @param pos
+ * Die Position des Feldes, wessen Veränderung ein Update der Kandidatenlisten erfordert
+ * @param candidate
+ * Der Kandidat, der in dem angegebenen Feld entfernt wurde
+ */
+ void updateCandidates(Position pos, int candidate) {
+ if (pos == null)
+ return;
+
+ ArrayList updatedConstraints = this.constraints.get(pos);
+ ArrayList updatedPositions;
+ ArrayList checkedConstraints;
+ for (int constrNum = 0; constrNum < updatedConstraints.size(); constrNum++) {
+ updatedPositions = updatedConstraints.get(constrNum).getPositions();
+ for (int posNum = 0; posNum < updatedPositions.size(); posNum++) {
+ if (this.fields.get(updatedPositions.get(posNum)).isEmpty()) {
+ if (updatedConstraints.get(constrNum).hasUniqueBehavior()) {
+ this.currentCandidates.get(updatedPositions.get(posNum)).clear(candidate);
+ } else {
+ int currentCandidate = -1;
+ int numberOfCandidates = this.currentCandidates.get(updatedPositions.get(posNum)).cardinality();
+ for (int i = 0; i < numberOfCandidates; i++) {
+ currentCandidate = this.currentCandidates.get(updatedPositions.get(posNum)).nextSetBit(
+ currentCandidate + 1);
+ this.fields.get(updatedPositions.get(posNum)).setCurrentValue(currentCandidate, false);
+ checkedConstraints = constraints.get(updatedPositions.get(posNum));
+ for (int upCon = 0; upCon < checkedConstraints.size(); upCon++) {
+ if (!checkedConstraints.get(upCon).isSaturated(this))
+ this.currentCandidates.get(updatedPositions.get(posNum)).clear(currentCandidate);
+ }
+ this.fields.get(updatedPositions.get(posNum)).setCurrentValue(Field.EMPTYVAL, false);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Setzt die temporären Lösung für das Feld an der spezifizierten Position auf den angegebenen Kandidaten. Es werden
+ * alle abhängigen Kandidatenlisten upgedatet. Beim Entfernene des aktuellen Zweiges wird die eingetragene Lösung
+ * wieder gelöscht.
+ *
+ * @param pos
+ * Die Position, an der die Lösung eingetragen werden soll
+ * @param candidate
+ * Die temporäre Lösung, die eingetragen werden soll
+ */
+ void setSolution(Position pos, int candidate) {
+ if (pos == null || candidate < 0)
+ return;
+
+ fields.get(pos).setCurrentValue(candidate, false);
+
+ currentCandidates.get(pos).clear();
+ if (!branchings.isEmpty())
+ branchings.peek().solutionsSet.add(pos);
+ updateCandidates(pos, candidate);
+ }
+
+ /**
+ * Gibt zurück, ob auf diesem Sudoku ein Branch erzeugt wurde oder nicht.
+ *
+ * @return true, falls auf diesem Sudoku ein Branch erzeugt wurde, false falls nicht
+ */
+ boolean hasBranch() {
+ return !branchings.isEmpty();
+ }
+
+ /**
+ * Gibt die Kandidatenliste der spezifizierten Position zurück.
+ *
+ * @param pos
+ * Die Position, dessen Kandidatenliste abgerufen werden soll
+ * @return Die Kandidatenliste der übergebenen Position
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls die spezifizierte Position ungültig ist
+ */
+ public BitSet getCurrentCandidates(Position pos) {
+ return this.currentCandidates.get(pos);
+ }
+
+ /**
+ * Erhöht den Schwierigkeitswert dieses Sudokus um den spezifizierten Wert. Ist dieser kleiner als 0, so wird nichts
+ * getan.
+ *
+ * @param value
+ * Der Wert, um den die Schwierigkeit dieses Sudokus erhöht werden soll
+ * @param applyToBranch
+ * Gibt an, ob der Wert auf den aktuellen Branch oder das gesamte Sudoku angewendet werden soll
+ */
+ void addComplexityValue(int value, boolean applyToBranch) {
+ if (value > 0) {
+ if (branchings.size() > 0)
+ branchings.peek().complexityValue += value;
+ this.complexityValue += value;
+ }
+ }
+
+ /**
+ * Gibt die Schwierigkeit dieses Sudokus zurück.
+ *
+ * @return Die Schwierigkeit dieses Sudokus
+ */
+ int getComplexityValue() {
+ return this.complexityValue;
+ }
+
+ /**
+ * Diese Klasse stellt einen Pool von PositionMaps auf BitSets zur Verfügung, sodass benutzte PositionMaps nicht
+ * verfallen, sondern im Pool behalten und für eine weitere Nutzung vorgehalten werden.
+ */
+ private static class PositionMapPool {
+ /**
+ * Eine Liste der erstellten, noch nicht vergebenen Maps
+ */
+ private Stack> unusedMaps;
+
+ /**
+ * Ein Stack der erstellten und bereits vergebenen Maps
+ */
+ private Stack> usedMaps;
+
+ /**
+ * Die Größe der Verwalteten PositionMaps
+ */
+ private Position currentDimension;
+
+ /**
+ * Die Positionen
+ */
+ private List positions;
+
+ /**
+ * Initialisiert einen neues PositionMapPool mit PositionMaps der spezifizierten Größe. Die dimension sollte
+ * nicht null oder gleich 0 sein, die positions sollten ebenfalls nicht null sein und denen des Sudokus
+ * entsprechen.
+ *
+ * @param dimension
+ * Die Größe der verwalteten PositionMaps
+ */
+ public PositionMapPool(Position dimension, List positions) {
+ // Keine Überprüfung der Eingabesituation, da nur lokal genutzt
+ this.positions = positions;
+ this.currentDimension = dimension;
+
+ usedMaps = new Stack>();
+ unusedMaps = new Stack>();
+ unusedMaps.push(initialisePositionMap());
+ unusedMaps.push(initialisePositionMap());
+ }
+
+ /**
+ * Gibt eine PositionMap entsprechend der aktuell gesetzten Größe zurück. Ist der Pool leer, so wird seine Größe
+ * verdoppelt.
+ *
+ * @return Eine PositionMap entsprechend der aktuell gesetzten Größe
+ */
+ public PositionMap getPositionMap() {
+ if (unusedMaps.size() == 0) {
+ unusedMaps.add(this.initialisePositionMap());
+ }
+
+ PositionMap ret = unusedMaps.pop();
+ usedMaps.push(ret);
+ return ret;
+ }
+
+ /**
+ * Gibt die zuletzt geholte PositionMap an den Pool zurück.
+ */
+ public void returnPositionMap() {
+ if (!usedMaps.isEmpty()) {
+ PositionMap returnedMap = usedMaps.pop();
+ for (int i = 0; i < this.positions.size(); i++) {
+ returnedMap.get(this.positions.get(i)).clear();
+ }
+ unusedMaps.push(returnedMap);
+ }
+ }
+
+ /**
+ * Initialisiert eine neue PositionMap der im Konstruktor definierten Größe und gibt diese zurück.
+ *
+ * @return Eine neue PositionMap der im Konstruktor definierten Größe
+ */
+ private PositionMap initialisePositionMap() {
+ PositionMap newMap = new PositionMap(currentDimension);
+ for (int i = 0; i < this.positions.size(); i++) {
+ newMap.put(this.positions.get(i), new BitSet());
+ }
+
+ return newMap;
+ }
+
+ /**
+ * Gibt alle PositionMaps an den Pool zurück.
+ */
+ public void returnAll() {
+ while (!this.usedMaps.empty()) {
+ returnPositionMap();
+ }
+ }
+
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SubsetHelper.java b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SubsetHelper.java
new file mode 100644
index 00000000..b61c171b
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/solver/SubsetHelper.java
@@ -0,0 +1,197 @@
+package de.sudoq.model.solverGenerator.solver;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Position;
+
+public abstract class SubsetHelper extends SolveHelper {
+ /** Attributes */
+
+ /**
+ * Die Stufe des Helpers, wobei diese die Anzahl der Ziffern und Felder angibt, welche die Naked-Bedingung erfüllen
+ * sollen
+ */
+ protected int level;
+
+ /**
+ * Ein BitSet, welches alle Kandidaten des aktuell untersuchten Constraints enthält. Aus Performancegründen nicht
+ * lokal definiert.
+ */
+ protected BitSet constraintSet;
+
+ /**
+ * Das BitSet, welches das gerade untersuchte Subset darstellt. Aus Performancegründen nicht lokal definiert.
+ */
+ protected BitSet currentSet;
+
+ /**
+ * Die Positionen, welche zum aktuell untersuchten Subset gehören. Aus Performancegründen nicht lokal definiert.
+ */
+ protected Position[] subsetPositions;
+
+ /**
+ * Ein BitSet für lokale Kopien zum vergleichen. Aus Performancegründen nicht lokal definiert.
+ */
+ protected BitSet localCopy;
+
+ /**
+ * Speichert alle Constraints des zugrundeliegenden Sudokus.
+ */
+ protected ArrayList allConstraints;
+
+ /** Constructors */
+
+ /**
+ * Erzeugt einen neuen NakedHelper für das spezifizierte Suduoku mit dem spezifizierten level. Der level entspricht
+ * dabei der Größe der Symbolmenge nach der gesucht werden soll.
+ *
+ * @param sudoku
+ * Das Sudoku auf dem dieser Helper operieren soll
+ * @param level
+ * Das Größe der Symbolmenge auf die der Helper hin überprüft
+ * @param complexity
+ * Die Schwierigkeit der Anwendung dieser Vorgehensweise
+ * @param hidden
+ * Definiert, ob nach versteckten oder nach sichtbaren Subsets gesucht werden soll
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das Sudoku null oder das level oder die complexity kleiner oder gleich 0 ist
+ */
+ protected SubsetHelper(SolverSudoku sudoku, int level, int complexity) {
+ super(sudoku, complexity);
+ if (level <= 0)
+ throw new IllegalArgumentException("level <= 0 : " + level);
+ this.level = level;
+
+ this.allConstraints = this.sudoku.getSudokuType().getConstraints();
+ this.constraintSet = new BitSet();
+ this.currentSet = new BitSet();
+ this.subsetPositions = new Position[this.level];
+ this.localCopy = new BitSet();
+ }
+
+ /** Methods */
+
+ /**
+ * Sucht so lange nach einem NakedSubset mit der im Konstruktor spezifizierten Größe level, bis entweder eines
+ * gefunden wird oder alle Möglichkeiten abgearbeitet sind. Wird ein Subset gefunden, werden die entsprechenden
+ * Kandidatenlisten upgedatet.
+ *
+ * Wurde eine Lösung gefunden, so wird eine SolveDerivation, die die Herleitung des NakedSubsets darstellt,
+ * erstellt. Dabei werden in der SolveDerivation die Kandidatenlisten des betroffenen Constraints als
+ * irrelevantCandidates, sowie das gefundene Subset als relevantCandidates dargestellt. Diese kann durch die
+ * getDerivation Methode abgefragt werden.
+ *
+ * @param buildDerivation
+ * Bestimmt, ob beim Finden eines Subsets eine Herleitung dafür erstellt werden soll, welche daraufhin
+ * mit getDerivation abgerufen werden kann.
+ * @return true, falls ein Subset gefunden wurde, false falls nicht
+ */
+ protected boolean update(boolean buildDerivation) {
+ int currentCandidate = -1;
+ lastDerivation = null;
+ boolean found = false;
+
+ ArrayList positions;
+ for (int constrNum = 0; constrNum < allConstraints.size(); constrNum++) {
+ if (allConstraints.get(constrNum).hasUniqueBehavior()) {
+ // Save the constraint being checked for naked subsets.
+ // Combine all the candidate lists in this constraint
+ constraintSet.clear();
+ positions = allConstraints.get(constrNum).getPositions();
+ for (int i = 0; i < positions.size(); i++) {
+ if (this instanceof HiddenHelper
+ || this.sudoku.getCurrentCandidates(positions.get(i)).cardinality() <= this.level)
+ constraintSet.or(this.sudoku.getCurrentCandidates(positions.get(i)));
+ }
+
+ if (constraintSet.cardinality() >= this.level) {
+ // Initialize the current set to check for naked subset by
+ // selecting the first candidates in this constraint
+ currentSet.clear();
+ currentCandidate = -1;
+ for (int i = 0; i < this.level; i++) {
+ currentCandidate = constraintSet.nextSetBit(currentCandidate + 1);
+ currentSet.set(currentCandidate);
+ }
+
+ found = updateNext(allConstraints.get(constrNum), buildDerivation);
+
+ // Stop searching if a subset was found
+ if (found) {
+ break;
+ }
+ }
+ }
+ }
+
+ return found;
+ }
+
+ /**
+ * Berechnet das nächste Subset des spezifizierten BitSets mit der im Konstruktor definierten Größe "level",
+ * ausgehend von demjenigen Subset, welches die niederwertigsten Kandidaten gesetzt hat. Das übergebene Subset muss
+ * bereits entsprechend viele Kandidaten gesetzt haben. Es wird immer der hochwertigste Kandidate erhöht bis dieser
+ * beim letzten Kandidaten angelangt ist, daraufhin wird der nächste Kandidat erhöht bis schließlich das
+ * hochwertigste Subset berechnet wurde.
+ *
+ * @param set
+ * Das Set aus dem das Subset berechnet werden soll
+ * @param subset
+ * Das Subset, aus dem das nächste Subset aus dem spezifizierten BitSet berechnet werden soll
+ * @return true, falls es noch ein Subset gibt, false falls nicht
+ */
+ protected boolean getNextSubset() {
+ boolean nextSetExists = false;
+
+ // Get the last set candidate
+ int currentCandidate = currentSet.length() - 1;
+
+ // Calculate next candidate set if existing
+ int nextCandidate = currentCandidate;
+ currentCandidate = constraintSet.nextSetBit(currentCandidate + 1);
+ if (currentCandidate != -1)
+ currentCandidate++;
+
+ while (!nextSetExists && nextCandidate != -1) {
+ // If the next candidate can be increased without interfering with
+ // the next one, do it
+ if (constraintSet.nextSetBit(nextCandidate + 1) != currentCandidate) {
+ nextSetExists = true;
+ currentSet.clear(nextCandidate);
+ currentCandidate = nextCandidate;
+ while (currentSet.cardinality() < this.level) {
+ currentCandidate = constraintSet.nextSetBit(currentCandidate + 1);
+ currentSet.set(currentCandidate);
+ }
+ }
+
+ // If no set was found, get the next candidate to manipulate it
+ if (!nextSetExists) {
+ currentCandidate = nextCandidate;
+ nextCandidate = -1;
+ while (currentSet.nextSetBit(nextCandidate + 1) < currentCandidate) {
+ nextCandidate = currentSet.nextSetBit(nextCandidate + 1);
+ }
+ currentSet.clear(currentCandidate);
+ }
+ }
+
+ return nextSetExists;
+ }
+
+ /**
+ * Sucht das nächste Subset der im Konstruktor definierten Größe {@code level} im spezifizierten {@link Constraint}
+ * mit dem spezifizierten Kandidaten-Set {@code set}, sowie dem aktuellen Subset. Es werden alle mittels der
+ * {@link getNextSubset}-Methode ab dem spezifizierten Subset ermittelten Kandidatenlisten überprüft.
+ *
+ * @param constraint
+ * Das Constraint, in dem ein NakedSubset gesucht werden soll
+ * @param buildDerivation
+ * Gibt an, ob eine Herleitung für ein gefundenes Subset erstellt werden soll, welche über die
+ * getDerivation Methode abgerufen werden kann
+ * @return true, falls ein Subset gefunden wurde, false falls nicht
+ */
+ abstract protected boolean updateNext(Constraint constraint, boolean buildDerivation);
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/HorizontalBlockPermutation.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/HorizontalBlockPermutation.java
new file mode 100644
index 00000000..bdac9ca6
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/HorizontalBlockPermutation.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class HorizontalBlockPermutation implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.horizontalBlockPermutation(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.horizontal_Blockshift;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/InBlockColumnPermutation.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/InBlockColumnPermutation.java
new file mode 100644
index 00000000..45daba87
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/InBlockColumnPermutation.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class InBlockColumnPermutation implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.inBlockCollumnPermutation(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.inBlock_Collumnshift;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/InBlockRowPermutation.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/InBlockRowPermutation.java
new file mode 100644
index 00000000..f09ede9e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/InBlockRowPermutation.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class InBlockRowPermutation implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.inBlockRowPermutation(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.inBlock_Rowshift;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorDiagonallyDown.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorDiagonallyDown.java
new file mode 100644
index 00000000..254637ed
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorDiagonallyDown.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class MirrorDiagonallyDown implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.mirrorDiagonallyDown(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.diagonal_down;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorDiagonallyUp.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorDiagonallyUp.java
new file mode 100644
index 00000000..00856ac0
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorDiagonallyUp.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class MirrorDiagonallyUp implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.mirrorDiagonallyUp(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.diagonal_up;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorHorizontally.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorHorizontally.java
new file mode 100644
index 00000000..f360c331
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorHorizontally.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class MirrorHorizontally implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.mirrorHorizontally(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.mirror_horizontal;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorVertically.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorVertically.java
new file mode 100644
index 00000000..3209f6a2
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/MirrorVertically.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class MirrorVertically implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.mirrorVertically(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.mirror_vertical;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Permutation.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Permutation.java
new file mode 100644
index 00000000..73903e3f
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Permutation.java
@@ -0,0 +1,18 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public interface Permutation {
+
+ public void permutate(Sudoku sudoku);
+
+ public PermutationProperties getCondition();
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate180.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate180.java
new file mode 100644
index 00000000..c696f220
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate180.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class Rotate180 implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.rotate180(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.rotate180;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate270.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate270.java
new file mode 100644
index 00000000..5c3555f0
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate270.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class Rotate270 implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.rotate270(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.rotate90;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate90.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate90.java
new file mode 100644
index 00000000..e7911c77
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Rotate90.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class Rotate90 implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.rotate90(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.rotate90;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/TransformationUtilities.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/TransformationUtilities.java
new file mode 100644
index 00000000..d89b5619
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/TransformationUtilities.java
@@ -0,0 +1,263 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import de.sudoq.model.sudoku.Field;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.Sudoku;
+
+public final class TransformationUtilities {
+
+ private TransformationUtilities() {
+ }
+
+ /* elementare Permutationen: alle Felder werden verschoben */
+
+ protected static void rotate90(Sudoku sudoku) {
+ mirrorDiagonallyDown(sudoku);
+ mirrorHorizontally(sudoku);
+ }
+
+ protected static void rotate180(Sudoku sudoku) {
+ rotate90(sudoku);
+ rotate90(sudoku);
+ }
+
+ protected static void rotate270(Sudoku sudoku) {
+ rotate90(sudoku);
+ rotate90(sudoku);
+ rotate90(sudoku);
+ }
+
+ protected static void mirrorHorizontally(Sudoku sudoku) {
+ int width = sudoku.getSudokuType().getSize().getX();
+
+ for (int i = 0; i < width / 2; i++) {
+ TransformationUtilities.swap_collums(sudoku, i, width - 1 - i);
+ }
+ }
+
+ protected static void mirrorVertically(Sudoku sudoku) {
+ mirrorHorizontally(sudoku);
+ rotate180(sudoku);
+ }
+
+ protected static void mirrorDiagonallyDown(Sudoku sudoku) {
+ int width = sudoku.getSudokuType().getSize().getX();
+
+ for (int i = 0; i < width - 1; i++) {// zeilen
+ for (int j = i + 1; j < width; j++) {// zeilenElemente
+ Field tmp = sudoku.getField(Position.get(i, j));
+ sudoku.setField(sudoku.getField(Position.get(j, i)), Position.get(i, j));
+ sudoku.setField(tmp, Position.get(j, i));
+ }
+ }
+ }
+
+ protected static void mirrorDiagonallyUp(Sudoku sudoku) {
+ mirrorHorizontally(sudoku);
+ rotate90(sudoku);
+ }
+
+ /* Spezielle Permutationen: nur manche Felder werden vertauscht */
+
+ /**
+ * Führt in jeder Blockzeile für jede Zeile eine Zeilenvertauschung durch.
+ *
+ * @param sudoku
+ * Das Sudoku auf dem die Permutation ausgeführt werden soll
+ */
+ protected static void inBlockRowPermutation(Sudoku sudoku) {
+ rotate90(sudoku);
+ TransformationUtilities.inBlockCollumnPermutation(sudoku, sudoku.getSudokuType().getBlockSize().getY());
+ rotate270(sudoku);
+ }
+
+ /**
+ * Führt in jeder Blockspalte für jede Spalte eine Spaltenvertauschung durch.
+ *
+ * @param sudoku
+ * Das Sudoku auf dem die Permutation ausgeführt werden soll
+ */
+ protected static void inBlockCollumnPermutation(Sudoku sudoku) {
+ inBlockCollumnPermutation(sudoku, sudoku.getSudokuType().getBlockSize().getX());
+ }
+
+ /**
+ * verschiebt Blöcke in horizontaler Richtung
+ *
+ * @param sudoku
+ * Das Sudoku auf dem die Permutation ausgeführt werden soll
+ */
+ protected static void horizontalBlockPermutation(Sudoku sudoku) {
+ int collumnsPerBlock = sudoku.getSudokuType().getBlockSize().getX();
+ int numberOfHorizontalBlocks = sudoku.getSudokuType().getSize().getX() / collumnsPerBlock;
+
+ rotate_horizontally_By1(sudoku, numberOfHorizontalBlocks, collumnsPerBlock);
+ horizontalBlockSwaps(sudoku, numberOfHorizontalBlocks, collumnsPerBlock);
+
+ }
+
+ /**
+ * verschiebt Blöcke in vertikaler Richtung
+ *
+ * @param sudoku
+ * Das Sudoku auf dem die Permutation ausgeführt werden soll
+ */
+ protected static void verticalBlockPermutation(Sudoku sudoku) {
+ int rowsPerBlock = sudoku.getSudokuType().getBlockSize().getY();
+ int numberOfVertikalBlocks = sudoku.getSudokuType().getSize().getY() / rowsPerBlock;
+
+ new Rotate90().permutate(sudoku);
+
+ rotate_horizontally_By1(sudoku, numberOfVertikalBlocks, rowsPerBlock);
+
+ horizontalBlockSwaps(sudoku, numberOfVertikalBlocks, rowsPerBlock);
+
+ new Rotate270().permutate(sudoku);
+ }
+
+ // collumn von 0 bis numberOfCollumnsInBlock - 1
+ private static void swapCollumOfBlocks(Sudoku sudoku, int collumn1, int collumn2, int numberOfCollumnsInBlock) {
+ if (collumn1 != collumn2) {
+ for (int i = 0; i < numberOfCollumnsInBlock; i++) {
+ TransformationUtilities.swap_collums(sudoku, collumn1 * numberOfCollumnsInBlock + i, collumn2
+ * numberOfCollumnsInBlock + i);
+ }
+ }
+ }
+
+ /* vertauscht zwei Spalten */
+ private static void swap_collums(Sudoku sudoku, int collum1, int collum2) {
+ int height = sudoku.getSudokuType().getSize().getY();
+
+ for (int j = 0; j < height; j++) {
+
+ Position a = Position.get(collum1, j);
+ Position b = Position.get(collum2, j);
+
+ Field tmp = sudoku.getField(a);
+
+ Field target = sudoku.getField(b);
+
+ sudoku.setField(target, a);
+
+ sudoku.setField(tmp, b);
+ }
+ }
+
+ /* verschiebt jeden Block um eins nach rechts */
+ private static void rotate_horizontally_By1(Sudoku sudoku, int numberOfHorizontalBlocks, int blocklength) {
+ for (int i = 0; i < numberOfHorizontalBlocks - 1; i++)
+ TransformationUtilities.swapCollumOfBlocks(sudoku, i, i + 1, blocklength);
+ }
+
+ /* Vertauscht Blockspalten */
+ private static void horizontalBlockSwaps(Sudoku sudoku, int numberOfHorizontalBlocks, int collumnsPerBlock) {
+ int limit = numberOfHorizontalBlocks / 2 - (1 - numberOfHorizontalBlocks % 2);
+
+ for (int i = 0; i < limit; i++) {
+
+ int first = Transformer.getRandom().nextInt(numberOfHorizontalBlocks);
+
+ int other = randomOtherNumber(first, numberOfHorizontalBlocks);
+
+ swapCollumOfBlocks(sudoku, first, other, collumnsPerBlock);
+
+ }
+ }
+
+ /**
+ * Führt in jeder Blockspalte blockWidth Spaltenvertauschungen aus
+ *
+ * @param sudoku
+ * Das Sudoku auf dem die Permutation ausgeführt werden soll
+ * @param blockWidth
+ * Anzahl an Spalten pro Block
+ */
+ private static void inBlockCollumnPermutation(Sudoku sudoku, int blockWidth) {
+ int numberOfHorizontalBlocks = sudoku.getSudokuType().getSize().getX()
+ / sudoku.getSudokuType().getBlockSize().getX();
+
+ for (int i = 0; i < numberOfHorizontalBlocks; i++) {
+ for (int j = 0; j < blockWidth; j++) {
+ int first = Transformer.getRandom().nextInt(blockWidth);
+ swap_collums(sudoku, i * blockWidth + first, i * blockWidth + randomOtherNumber(first, blockWidth));
+ }
+ }
+ }
+
+ /* Symbole vertauschen */
+ /**
+ * Vertauscht zufällig die Lösungen des Sudokus, wobei gleiche Lösungen gleiche neue Lösungen erhalten.
+ *
+ * @param sudoku
+ * das Sudoku dessen Felder manipuliert werden sollen
+ */
+ protected static void changeSymbols(Sudoku sudoku) {
+ Map permutationRule = TransformationUtilities.createPermutation(sudoku);
+
+ for (int x = 0; x < sudoku.getSudokuType().getSize().getX(); x++) {
+ for (int y = 0; y < sudoku.getSudokuType().getSize().getY(); y++) {
+
+ Field f = sudoku.getField(Position.get(x, y));
+ if (f != null && permutationRule.get(f.getSolution()) != f.getSolution()) // nur
+ // wenn
+ // sich
+ // was
+ // ändert
+ sudoku.setField(
+ new Field(f.isEditable(), permutationRule.get(f.getSolution()), f.getId(), f
+ .getNumberOfValues()), Position.get(x, y));
+ }
+ }
+ }
+
+ /*
+ * gibt eine Map mit einer Permutationsvorschrift zurück. Die Identität ist als Rückgabewert ausgeschlossen
+ */
+ private static Map createPermutation(Sudoku sudoku) {
+ Map permutationRule = new HashMap();
+ int numberOfSymbols = sudoku.getSudokuType().getNumberOfSymbols();
+ int tries = (int) Math.sqrt(numberOfSymbols); // wurzel(numberOfElements)
+ // versuche, damit wir
+ // deterministisch
+ // bleiben
+
+ boolean success;
+ for (int i = 0; i < numberOfSymbols; i++) {
+ success = false;
+ for (int j = 0; j < tries && !success; j++) {
+
+ int otherNum = randomOtherNumber(i, numberOfSymbols);
+ if (!permutationRule.containsValue(otherNum)) {
+ permutationRule.put(i, otherNum);
+ success = true;
+ }
+ }
+ for (int j = 0; !success && j < numberOfSymbols; j++) {
+ if (!permutationRule.containsValue(j)) {
+ permutationRule.put(i, j);
+ break;
+ }
+ }
+ }
+ return permutationRule;
+ }
+
+ /* gibt eine zahl < range zurück aber nicht num */
+ private static int randomOtherNumber(int num, int range) {
+
+ int distance = Transformer.getRandom().nextInt(range - 1) + 1;
+ return (num + distance) % range;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Transformer.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Transformer.java
new file mode 100644
index 00000000..a2808f2e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/Transformer.java
@@ -0,0 +1,136 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import java.util.List;
+import java.util.Random;
+import java.util.Vector;
+
+import de.sudoq.model.sudoku.Sudoku;
+
+/**
+ * Transformer Klasse. Transformiert ein quadratisches! Sudoku, so dass es nach wie vor mit den gleichen Schritten
+ * lösbar ist, aber völlig anders aussieht.
+ */
+public class Transformer {
+
+ static List elementaryList;
+
+ static {
+ elementaryList = new Vector();
+ elementaryList.add(new Rotate90());
+ elementaryList.add(new Rotate180());
+ elementaryList.add(new Rotate270());
+ elementaryList.add(new MirrorHorizontally());
+ elementaryList.add(new MirrorVertically());
+ elementaryList.add(new MirrorDiagonallyDown());
+ elementaryList.add(new MirrorDiagonallyUp());
+ }
+
+ static List subtleList;
+
+ static {
+ subtleList = new Vector();
+ subtleList.add(new HorizontalBlockPermutation());
+ subtleList.add(new VerticalBlockPermutation());
+ subtleList.add(new InBlockColumnPermutation());
+ subtleList.add(new InBlockRowPermutation());
+ }
+
+ static {
+ setRandom(new Random());
+ }
+
+ private static Random random;
+
+ /**
+ * Für Tests kann ein eigenes deterministisches 'random'-Object verwendet werden. Das Randomobjekt von Transformer
+ * ist standardmäßig nichtdeterministisch und wird nach jedem Aufruf von transform() wieder auf nichtdeterministisch
+ * gesetzt.
+ *
+ * @param r
+ * ein neues randomObject
+ */
+ public static void setRandom(Random r) {
+ random = r;
+ }
+
+ public static Random getRandom() {
+ return random;
+ }
+
+ /**
+ * Diese Methode transformiert das spezifizierte Sudoku falls möglich mehrmals auf folgende Weisen:
+ * 1. Vertauschen zweier Zeilen / Spalten von Blöcken
+ * 2. Vertauschen zweier Zeilen / Spalten von Feldern
+ * 3. Drehen 4. (Spiegeln) 5. Seien x und y zwei Symbole. Im gesamten Sudoku wird x durch y ersetzt und umgekehrt.
+ *
+ * Nach einer beliebigen, endlichen Anzahl solcher Modifikationen, ist das Sudoku noch immer eindeutig lösbar,
+ * unterscheidet sich aber im Allgemeinen gänzlich vom ursprünglichen Sudoku.
+ *
+ * @param sudoku
+ * Das zu modifizierende Sudoku
+ */
+ public static void transform(Sudoku sudoku) {
+ // not rotateClockwise and mirror! results in Clockrotation(grouptheory)
+
+ elementaryPermutation(sudoku);
+
+ subtlePermutation(sudoku);
+
+ elementaryPermutation(sudoku);
+
+ subtlePermutation(sudoku);
+
+ elementaryPermutation(sudoku);
+
+ TransformationUtilities.changeSymbols(sudoku);
+
+ sudoku.increaseTransformCount();
+
+ setRandom(new Random());
+ }
+
+ /**
+ * Führt elementare Permutationen auf dem übergebenen Sudoku aus, z.B. Spiegelungen und Drehungen
+ *
+ * @param sudoku
+ * das Sudoku dessen Felder permutiert werden
+ */
+ private static void elementaryPermutation(Sudoku sudoku) {
+ List l = new Vector();
+ for (Permutation p : elementaryList) {
+ if (sudoku.getSudokuType().getPermutationProperties().contains(p.getCondition())) {
+ l.add(p);
+ }
+ }
+ if (l.size() > 0) {
+ l.get(getRandom().nextInt(l.size())).permutate(sudoku);
+ }
+ }
+
+ /**
+ * Führt spezielle Permutationen auf dem übergebenen Sudoku aus, z.B. BlockPermutationen und ZeilenPermutationen
+ * innerhalb eines Blocks
+ *
+ * @param sudoku
+ * das Sudoku dessen Felder permutiert werden
+ */
+ private static void subtlePermutation(Sudoku sudoku) {
+ List l = new Vector();
+ for (Permutation p : subtleList) {
+ if (sudoku.getSudokuType().getPermutationProperties().contains(p.getCondition())) {
+ l.add(p);
+ }
+ }
+ for (Permutation p : l) {
+ p.permutate(sudoku);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/VerticalBlockPermutation.java b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/VerticalBlockPermutation.java
new file mode 100644
index 00000000..d20655cd
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/solverGenerator/transformations/VerticalBlockPermutation.java
@@ -0,0 +1,25 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.solverGenerator.transformations;
+
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.sudokuTypes.PermutationProperties;
+
+public class VerticalBlockPermutation implements Permutation {
+
+ @Override
+ public void permutate(Sudoku sudoku) {
+ TransformationUtilities.verticalBlockPermutation(sudoku);
+ }
+
+ @Override
+ public PermutationProperties getCondition() {
+ return PermutationProperties.vertical_Blockshift;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/Constraint.java b/sudoq-model/src/de/sudoq/model/sudoku/Constraint.java
new file mode 100644
index 00000000..8546536d
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/Constraint.java
@@ -0,0 +1,189 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Ein Constraint-Objekt beschreibt eine Zusammenfassung von Feldern (bzw. dessen Positionen) in einem Sudoku, sodass
+ * diese zusammen eine bestimmte Vorgabe erfüllen müssen, die von einem ConstraintBehavior-Objekt beschrieben wird. Im
+ * Standardsudoku sind beispielsweise die Zeilen, Spalten und Blöcke Constraint-Objekte.
+ */
+public class Constraint implements Iterable {
+ /** Attributes */
+
+ /**
+ * Eine Liste der Positionen aller Felder, die zusammen eine Vorgabe erfüllen müssen
+ */
+ private List positions;
+
+ /**
+ * Das Objekt welches die Vorgabe beschreibt, die die Felder dieses Constraint-Objektes erfüllen müssen
+ */
+ private ConstraintBehavior behavior;
+
+ /**
+ * Der Name dieses Constraints
+ */
+ private String name;
+
+ /**
+ * Der Typ des Constraints
+ */
+ private ConstraintType type;
+
+ /** Constructors */
+
+ /**
+ * Dieser Konstruktor instanziiert ein neues Constraint-Objekt mit dem spezifizierten ConstraintBehavior. Ist dieses
+ * null, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param behavior
+ * Das Verhalten, welches dieses Constraint haben soll
+ * @param type
+ * Der Typ des Constraints
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das spezifizierte ConstraintBehavior-Objekt null ist
+ */
+ public Constraint(ConstraintBehavior behavior, ConstraintType type) {
+ if (behavior != null && type != null) {
+ this.behavior = behavior;
+ positions = new ArrayList();
+ this.type = type;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ this.name = "Constraint with " + behavior;
+ }
+
+ /**
+ * Dieser Konstruktor instanziiert ein neues Constraint-Objekt mit dem spezifizierten ConstraintBehavior. Das
+ * Constraint erhält den spezifizierten Namen, welcher mit der toString-Methode ausgegeben wird. Ist der Name null,
+ * so wird "Constraint with (behavior)" als Name gespeichert.
+ *
+ * @param behavior
+ * Das Verhalten, welches dieses Constraint haben soll
+ * @param type
+ * Der Typ des Constraints
+ * @param name
+ * Die Bezeichnung dieses Constraints. Überlappende Constraints sollten mit "extra block" beginnen,
+ * Blöcke mit "Block", Spalten mit "Column", Zeilen mit "Row".
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das spezifizierte ConstraintBehavior-Objekt null ist
+ */
+ public Constraint(ConstraintBehavior behavior, ConstraintType type, String name) {
+ if (behavior != null && type != null) {
+ this.behavior = behavior;
+ positions = new ArrayList();
+ this.type = type;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ this.name = name == null ? "Constraint with " + behavior : name;
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode fügt diesem Constraint-Objekt die spezifizierte Position hinzu. Ist diese null, so wird nichts
+ * getan.
+ *
+ * @param position
+ * Die Position die diesem Constraint hinzugefügt werden soll
+ */
+ public void addPosition(Position position) {
+ if (position != null && !positions.contains(position)) {
+ positions.add(position);
+ }
+ }
+
+ /**
+ * Diese Methode ermittelt, ob das spezifizierte Sudoku dieses Constraint erfüllt, also auf den hinzugefügten
+ * Feldern, das spezifizierte ConstraintBehavior erfüllt. Ist dies nicht der Fall, ist das spezifizierte Sudoku null
+ * oder enthält das Sudoku nicht alle Positionen, die dieses Constraint überprüfen möchte, so wird false
+ * zurückgegeben. Erfüllt das Sudoku die Vorgaben, so wird true zurückgegeben.
+ *
+ * @param sudoku
+ * Das Sudoku bei dem überprüft werden soll, ob dieses Constraint erfüllt ist
+ * @return true falls das Sudoku die Vorgaben erfüllt, false falls es dies nicht tut oder null ist
+ */
+ public boolean isSaturated(Sudoku sudoku) {
+ return sudoku != null && behavior.check(this, sudoku);
+ }
+
+ /**
+ * Diese Methode gibt einen Iterator zurück, mithilfe dessen über die Positionen der Felder, die diesem Constraint
+ * zugewiesen sind iteriert werden kann.
+ *
+ * @return Einen Iterator mit dem über die diesem Constraint zugewiesen Positionen iteriert werden kann
+ */
+ @Override
+ public Iterator iterator() {
+ return positions.iterator();
+ }
+
+ /**
+ * Gibt zurück ob dieses Constraint die gegebene Position beinhaltet.
+ *
+ * @param p
+ * die Position von der Überprüft werden soll ob sie enthalten ist.
+ * @return true falls sie enthalten ist, andernfalls false.
+ */
+ public boolean includes(Position p) {
+ return positions.contains(p);
+ }
+
+ /**
+ * Gibt die Anzahl der Positions, welche laut dem Constraint eine bestimmte Vorgabe erfuellen müssen, zurueck.
+ *
+ * @return Die Anzahl an Positions, die diesem Constraint zugeordnet sind
+ */
+ public int getSize() {
+ return positions.size();
+ }
+
+ /**
+ * Gibt zurück, ob das Verhalten dieses Constraints das UniqueConstraintBehavior ist.
+ *
+ * @return true, falls dieses Constraint ein UniqueConstraint-Verhalten hat, false andernfalls
+ */
+ public boolean hasUniqueBehavior() {
+ return (behavior instanceof UniqueConstraintBehavior);
+ }
+
+ /**
+ * Gibt eine Kurzrepräsentation dieses Objektes als String zurück.
+ *
+ * @return eine Kurzrepräsentation dieses Objektes als String
+ */
+ @Override
+ public String toString() {
+ return this.name;
+ }
+
+ /**
+ * Gibt eine Liste der Positionen, welche zu diesem Constraint gehören zurück. Hinweis: Wenn möglich stattdessen den
+ * Iterator benutzen.
+ *
+ * @return Eine Liste der Positionen, welche zu diesem Constraint gehören.
+ */
+ public ArrayList getPositions() {
+ return (ArrayList) this.positions;
+ }
+
+ /**
+ * Gibt den Typ dieses Constraints zurück.
+ *
+ * @return Der Typ dieses Constraints
+ */
+ public ConstraintType getType() {
+ return this.type;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/ConstraintBehavior.java b/sudoq-model/src/de/sudoq/model/sudoku/ConstraintBehavior.java
new file mode 100644
index 00000000..448185ab
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/ConstraintBehavior.java
@@ -0,0 +1,32 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+/**
+ * Dieses Interface definiert eine check Methode, welche überprüft, ob ein
+ * spezifiziertes Constraint ein bestimmtes Verhalten erfüllt.
+ */
+public interface ConstraintBehavior {
+ /** Methods */
+
+ /**
+ * Diese Methode überprüft, ob ein bestimmtes (durch die Methode
+ * implementiertes) Verhalten auf den durch das Constraint spezifizierten
+ * Feldern des uebergebenen Sudokus erfüllt ist. Ist das Constraint oder das
+ * Sudoku null, so wird false zurückgegeben.
+ *
+ * @param constraint
+ * Das Constraint, welches auf ein bestimmtes Verhalten überprüft
+ * werden soll
+ * @param sudoku
+ * Sudoku, auf welchem das Constraint ueberprueft werden soll
+ * @return true, falls das Constraint die Vorgaben erfüllt, false falls es
+ * dies nicht tut oder null ist
+ */
+ public abstract boolean check(Constraint constraint, Sudoku sudoku);
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/ConstraintType.java b/sudoq-model/src/de/sudoq/model/sudoku/ConstraintType.java
new file mode 100644
index 00000000..91f876bd
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/ConstraintType.java
@@ -0,0 +1,29 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+/**
+ * Definiert die Typen von Constraints.
+ */
+public enum ConstraintType {
+ /**
+ * Eine Zeile oder Spalte
+ */
+ LINE,
+
+ /**
+ * Ein Block, wobei alle Blöcke eines Sudokus sich nicht überschneiden
+ */
+ BLOCK,
+
+ /**
+ * Ein gesondertes Constraints, was sich mit Blöcken überschneiden kann.
+ */
+ EXTRA;
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/Field.java b/sudoq-model/src/de/sudoq/model/sudoku/Field.java
new file mode 100644
index 00000000..c9eb5d36
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/Field.java
@@ -0,0 +1,281 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+import java.util.BitSet;
+
+import de.sudoq.model.ObservableModelImpl;
+
+/**
+ * Ein Field-Objekt beschreibt ein Feld eines Sudoku-Spielfeldes. Dabei enthält es Informationen über aktuellen Wert,
+ * Editierbarkeit, Notizen, sowie die korrekte Lösung für das Feld und stellt diese zur Verfügung. Außerdem ist es ein
+ * OberservableModel und kann damit auf Veränderungen hinsichtlich aktuellem Wert und Notizen beobachtet werden.
+ */
+public class Field extends ObservableModelImpl {
+ /** Attributes */
+
+ /**
+ * Eine Sudokuweit eindeutige Nummer für dieses Feld
+ */
+ private final int id;
+
+ /**
+ * Die korrekte Lösung für dieses Feld
+ */
+ private final int solution;
+
+ /**
+ * Der aktuell in diesem Feld eingetragene Wert
+ */
+ // package scope to increase performance and bypass the notifications
+ int currentVal;
+
+ /**
+ * Der Wert der ein leeres Feld repräsentiert
+ */
+ public static final int EMPTYVAL = -1;
+
+ /**
+ * Die Editierbarkeit dieses Feldes; vorgegebene Felder haben den Wert false
+ */
+ private final boolean editable;
+
+ /**
+ * Die gesetzten Notizen in diesem Feld; ist das n-te Bit 1, so ist das n-te Symbol als Notiz gesetzt
+ */
+ private BitSet noticeFlags;
+
+ /**
+ * Der höchste Wert, den dieses Feld annehmen kann
+ */
+ private int maxValue;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert ein neues Field-Objekt. Mit den Parametern wird spezifiziert, ob dieses Feld vom Spieler änderbar
+ * sein soll oder nicht und was die korrekte Lösung für dieses Feld ist.
+ *
+ * @param editable
+ * Gibt an, ob das Feld vom Spieler editierbar sein soll
+ * @param solution
+ * Die Richtige Belegung für dieses Feld
+ * @param id
+ * die id dieses Feldes
+ * @param numberOfValues
+ * Die Anzahl von Werten, die dieses Feld annehmen kann
+ */
+ public Field(boolean editable, int solution, int id, int numberOfValues) {
+ if (solution < 0 && solution != EMPTYVAL)
+ throw new IllegalArgumentException("Solution has to be positive.");
+
+ noticeFlags = new BitSet();
+
+ this.maxValue = numberOfValues - 1;
+ this.id = id;
+ this.editable = editable;
+ this.solution = solution;
+
+ if (!editable) {
+ currentVal = solution;
+ } else {
+ currentVal = EMPTYVAL;
+ }
+
+ }
+
+ /**
+ * Instanziiert ein neues editierbares Field-Objekt.
+ *
+ * @param id
+ * die id dieses Feldes
+ * @param numberOfValues
+ * Die Anzahl an Werten, die dieses Feld annehmen kann
+ */
+ public Field(int id, int numberOfValues) {
+ this(true, EMPTYVAL, id, numberOfValues);
+ }
+
+ /** Methods */
+
+ /**
+ * Gibt die id dieses Feldes zurück
+ *
+ * @return die id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Gibt die korrekte Lösung für dieses Feld zurück.
+ *
+ * @return Die Korrekte Lösung für dieses Feld
+ */
+ public int getSolution() {
+ return solution;
+ }
+
+ /**
+ * Gibt den aktuell in diesem Feld eingetragenen Wert zurück.
+ *
+ * @return Der aktuell in diesem Feld eingetragene Wert
+ */
+ public int getCurrentValue() {
+ return currentVal;
+ }
+
+ /**
+ * Setzt den aktuellen Wert dieses Feldes auf den Spezifizierten. Falls editable false ist passiert nichts.
+ *
+ * @param value
+ * Der in dieses Feld als aktuell einzutragende Wert
+ * @throws IllegalArgumentException
+ * Falls value < 0
+ */
+ public void setCurrentValue(int value) {
+ if (isEditable()) {
+ if ((value < 0 && value != EMPTYVAL) || value > maxValue) {
+ throw new IllegalArgumentException();
+ }
+
+ this.currentVal = value;
+ notifyListeners(this);
+ }
+ }
+
+ /**
+ * Setzt den aktuellen Wert dieses Feldes auf den Spezifizierten. Falls editable false ist passiert nichts. Es
+ * werden hierbei keine Listener benachrichtigt.
+ *
+ * @param value
+ * Der in dieses Feld als aktuell einzutragende Wert
+ * @param notify
+ * gibt an ob die Listener benachrichtigt werden sollen
+ * @throws IllegalArgumentException
+ * Falls value < 0
+ */
+
+ public void setCurrentValue(int value, boolean notify) {
+ if (isEditable()) {
+ if ((value < 0 && value != EMPTYVAL) || value > maxValue) {
+ throw new IllegalArgumentException();
+ }
+
+ this.currentVal = value;
+ if (notify)
+ notifyListeners(this);
+ }
+ }
+
+ /**
+ * Löscht den aktuellen Wert dieses Feldes. Falls das Feld nicht editierbar ist, so wird nichts getan.
+ */
+ public void clearCurrentValue() {
+ if (this.editable) {
+ currentVal = EMPTYVAL;
+ notifyListeners(this);
+ }
+ }
+
+ /**
+ * Gibt die Anzahl an Werten zurück, die dieses Feld annehmen kann.
+ *
+ * @return Die Anzahl an Werten, die dieses Feld annehmen kann
+ */
+ public int getNumberOfValues() {
+ return this.maxValue + 1;
+ }
+
+ /**
+ * Gibt zurück, ob dieses Feld leer ist.
+ *
+ * @return true, falls dieses Feld leer ist, false falls nicht
+ */
+ public boolean isEmpty() {
+ return this.currentVal == EMPTYVAL;
+ }
+
+ /**
+ * Gibt zurück, ob die Notiz mit dem gegebenen Wert gesetzt ist.
+ *
+ * @param value
+ * der Wert der Notiz
+ * @return true falls sie gesetzt ist, andernfalls false
+ */
+ public boolean isNoteSet(int value) {
+ if (value < 0) {
+ return false;
+ } else {
+ return noticeFlags.get(value);
+ }
+ }
+
+ /**
+ * Schaltet das spezifizierte Symbol als Notiz um. Ist der Parameter value kleiner als 0, so wird nichts getan.
+ *
+ * @param value
+ * Die Nummer des Symbols, welches als Notiz umgeschaltet werden soll
+ */
+ public void toggleNote(int value) {
+ if (value >= 0) {
+ noticeFlags.flip(value);
+ notifyListeners(this);
+ }
+ }
+
+ /**
+ * Überprüft, ob das Feld zur Belegung freigegeben ist.
+ *
+ * @return true wenn das Feld belegt werden darf, anderenfalls false
+ */
+ public boolean isEditable() {
+ return editable;
+ }
+
+ /**
+ * Überprüft, ob das Feld korrekt gelöst ist, also ob der aktuell eingetragene Wert der richtigen Lösung entspricht.
+ *
+ * @return true, falls das Feld korrekt gelöst ist, sonst false
+ */
+ public boolean isSolvedCorrect() {
+ return currentVal == solution && currentVal != EMPTYVAL;
+ }
+
+ /**
+ * Überprüft ob das Feld nicht falsch belegt ist d.h. korrekt gelöst oder unbelegt ist
+ *
+ * @return true, falls das Feld unbelegt oder korrekt gelöst ist
+ */
+ public boolean isNotWrong() {
+ return currentVal == solution || currentVal == EMPTYVAL;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof Field) {
+
+ Field other = (Field) obj;
+
+ return this.id == other.id && this.solution == other.solution && this.currentVal == other.currentVal
+ && this.editable == other.editable && this.noticeFlags.equals(other.noticeFlags);
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public String toString() {
+ return String.valueOf(this.currentVal);
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/Position.java b/sudoq-model/src/de/sudoq/model/sudoku/Position.java
new file mode 100644
index 00000000..a972d159
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/Position.java
@@ -0,0 +1,137 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+/**
+ * Eine Position repräsentiert eine zweidimensionale, kartesische Koordinate.
+ */
+public class Position {
+ /** Attributes */
+
+ /**
+ * Die x-Koordinate der Position
+ */
+ private int x;
+
+ /**
+ * Die y-Koordinate der Position
+ */
+ private int y;
+
+ /**
+ * Das statische Position-Array
+ */
+ private static Position[][] positions;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert ein neues Position-Objekt mit den spezifizierten x- und y-Koordinaten. Ist eine der Koordinaten
+ * kleiner als 0, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param x
+ * Die x-Koordinate der zu erzeugenden Position
+ * @param y
+ * Die y-Koordinate der zu erzeugenden Position
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls eine der Koordinaten kleiner als 0 ist
+ */
+ private Position(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+
+ /**
+ * Gibt ein Positions-Objekt mit den spezifizierten x- und y-Koordinaten. Ist eine der Koordinaten kleiner als 0, so
+ * wird eine IllegalArgumentException geworfen.
+ *
+ * @param x
+ * Die x-Koordinate der zu erzeugenden Position
+ * @param y
+ * Die y-Koordinate der zu erzeugenden Position
+ * @return das neue Position Objekt
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls eine der Koordinaten kleiner als 0 ist
+ */
+ public static Position get(int x, int y) {
+ if (x < 0 || y < 0) {
+ throw new IllegalArgumentException("a parameter is less than zero");
+ }
+
+ if (positions == null) {
+ initializePositions();
+ }
+ if (x < 25 && y < 25) {
+ return positions[x][y];
+ } else {
+ return new Position(x, y);
+ }
+ }
+
+ /**
+ * Initialisiert das Positions-Array für effiziere Positionsverwaltung.
+ */
+ private static void initializePositions() {
+ positions = new Position[25][25];
+ for (int x = 0; x < 25; x++) {
+ for (int y = 0; y < 25; y++) {
+ positions[x][y] = new Position(x, y);
+ }
+ }
+ }
+
+ /** Methods */
+
+ /**
+ * Gibt die x-Koordinate dieser Position zurück.
+ *
+ * @return Die x-Koordinate dieser Position
+ */
+ public int getX() {
+ return x;
+ }
+
+ /**
+ * Gibt die y-Koordinate dieser Position zurück.
+ *
+ * @return Die y-Koordinate dieser Position
+ */
+ public int getY() {
+ return y;
+ }
+
+ /**
+ * Vergleicht mit einem anderen Positionobjekt auf Gleichheit bzgl. der Koordinaten
+ *
+ * @return true wenn obj vom Typ Position und mit diesem Objekt in den Koordinaten übereinstimmt, sonst false
+ */
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof Position)) {
+ return false;
+ } else {
+ Position other = (Position) obj;
+ return this.x == other.getX() && this.y == other.getY();
+ }
+ }
+
+ /**
+ * Generiert einen eindeutigen hashcode für Koordinaten < 65519
+ */
+ public int hashCode() {
+ int p = 65519;
+ int q = 65521;
+ return x * p + y * q;
+ }
+
+ /**
+ * Gibt eine String-Repräsentation dieser Position zurück.
+ */
+ public String toString() {
+ return this.x + ", " + this.y;
+ }
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/PositionMap.java b/sudoq-model/src/de/sudoq/model/sudoku/PositionMap.java
new file mode 100644
index 00000000..f3dafb9a
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/PositionMap.java
@@ -0,0 +1,103 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+/**
+ * Diese Klasse stellt eine Map von Positions auf generische Objekte zur Verfügung. Da das Mapping direkt über die
+ * 2D-Koordinaten der Positions vorgenommen wird, ist dieses Mapping effizienter als HashMaps oder TreeMaps.
+ *
+ * @param
+ * Ein belibiger Typ, auf den Positions abgebildet werden sollen
+ */
+public class PositionMap implements Cloneable {
+ /**
+ * Die BoundingBox-Abmessungen der Positionen dieser PositionMap
+ */
+ Position dimension;
+
+ /**
+ * Das Werte-Array dieser PositionMap
+ */
+ T[][] values;
+
+ /**
+ * Initialisiert eine neue Position-Map für so viele Einträge, wie eine Matrix der spezifizierten Dimension hat. Die
+ * Größe muss in beiden Komponenten mindestens 1 sein.
+ *
+ * @param dimension
+ * Die Größe der PositionMap
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls die spezifizierte Position null oder eine der Dimensionskomponenten 0 ist
+ */
+ @SuppressWarnings("unchecked")
+ public PositionMap(Position dimension) {
+ if (dimension == null || dimension.getX() < 1 || dimension.getY() < 1)
+ throw new IllegalArgumentException("Specified dimension or one of its components was null.");
+
+ this.dimension = dimension;
+ this.values = (T[][]) new Object[dimension.getX()][dimension.getY()];
+ }
+
+ /**
+ * Fügt das spezifizierte Objekt an der spezifizierten Position ein. Ist dort bereits ein Objekt vorhanden, so wird
+ * dieses überschrieben.
+ *
+ * @param pos
+ * Die Position, an der das BitSet eingefügt werden soll
+ * @param object
+ * Das Objekt, welches eingefügt werden soll
+ * @return der Wert der vorher an pos lag, oder null falls es keinen gab
+ */
+ public T put(Position pos, T object) {
+ if (pos == null || object == null || pos.getX() > this.dimension.getX() || pos.getY() > this.dimension.getY())
+ throw new IllegalArgumentException();
+
+ T ret = values[pos.getX()][pos.getY()];
+ values[pos.getX()][pos.getY()] = object;
+ return ret;
+ }
+
+ /**
+ * Gibt das BitSet, welches der spezifizierten Position zugewiesen wurden zurück. Wurde keines zugewiesen, so wird
+ * null zurückgegeben.
+ *
+ * @param pos
+ * Die Position, dessen zugewiesenes BitSet abgefragt werden soll
+ * @return Das BitSet, welches der spezifizierten Position zugeordnet wurde oder null, falls keines zugewiesen wurde
+ */
+ public T get(Position pos) {
+ if (pos == null)
+ throw new IllegalArgumentException("pos was null");
+ if (pos.getX() > this.dimension.getX())
+ throw new IllegalArgumentException("x coordinate of pos was > " + this.dimension.getX() + ": " + pos.getX());
+ if (pos.getY() > this.dimension.getY())
+ throw new IllegalArgumentException("y coordinate of pos was > " + this.dimension.getY() + ": " + pos.getY());
+
+ return values[pos.getX()][pos.getY()];
+ }
+
+ /**
+ * Gibt eine "deep copy" dieser PositionMap zurück. Es wird dazu die clone-Methode aller in dieser PositionMap
+ * befindlichen Objekte aufgerufen.
+ *
+ * @return Eine "deep copy" dieser PositionMap
+ */
+ @Override
+ public PositionMap clone() {
+ PositionMap result = new PositionMap(this.dimension);
+ for (int i = 0; i < this.dimension.getX(); i++) {
+ for (int j = 0; j < this.dimension.getY(); j++) {
+ if (this.values[i][j] != null)
+ result.put(Position.get(i, j), this.values[i][j]);
+ }
+ }
+
+ return result;
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/Sudoku.java b/sudoq-model/src/de/sudoq/model/sudoku/Sudoku.java
new file mode 100644
index 00000000..cebdc07d
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/Sudoku.java
@@ -0,0 +1,396 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import de.sudoq.model.ModelChangeListener;
+import de.sudoq.model.ObservableModelImpl;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+import de.sudoq.model.sudoku.sudokuTypes.TypeBasic;
+import de.sudoq.model.xml.XmlAttribute;
+import de.sudoq.model.xml.XmlTree;
+import de.sudoq.model.xml.Xmlable;
+
+/**
+ * Diese Klasse repräsentiert ein Sudoku mit seinem Typ, seinen Feldern und seinem Schwierigkeitsgrad.
+ */
+public class Sudoku extends ObservableModelImpl implements Iterable, Xmlable, ModelChangeListener {
+ /** Attributes */
+
+ /**
+ * Eine Identifikationsnummer, die ein Sudoku eindeutig identifiziert
+ */
+ private int id;
+
+ private int transformCount = 0;
+
+ /**
+ * Eine Map, welche jeder Position des Sudokus ein Feld zuweist
+ */
+ protected HashMap fields;
+
+ private int fieldIdCounter;
+ private Map fieldPositions;
+
+ /**
+ * Der Typ dieses Sudokus
+ */
+ private TypeBasic type;
+
+ /**
+ * Der Schwierigkeitsgrad dieses Sudokus
+ */
+ private Complexity complexity;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert ein Sudoku-Objekt mit dem spezifizierten SudokuType. Ist dieser null, so wird eine
+ * IllegalArgumentException geworfen. Alle Felder werden als editierbar ohne vorgegebene Lösung gesetzt.
+ *
+ * @param type
+ * Der Typ des zu erstellenden Sudokus
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls der übergebene Typ null ist
+ */
+ public Sudoku(TypeBasic type) {
+ this(type, new PositionMap(type == null ? Position.get(1, 1) : type.getSize()),
+ new PositionMap(type == null ? Position.get(1, 1) : type.getSize()));
+ }
+
+ /**
+ * Instanziiert ein Sudoku-Objekt mit dem spezifizierten SudokuType. Ist dieser null, so wird eine
+ * IllegalArgumentException geworfen.
+ *
+ * @param type
+ * Der Typ des zu erstellenden Sudokus
+ * @param map
+ * Eine Map von Positions auf Lösungswerte. Werte in vorgegebenen Feldern sind verneint. (nicht negiert,
+ * sondern bitweise verneint)
+ * @param setValues
+ * Eine Map wo jede Position mit dem Wert true einen vorgegebenen Wert markiert
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls der übergebene Typ null ist
+ */
+ public Sudoku(TypeBasic type, PositionMap map, PositionMap setValues) {
+ if (type == null) {
+ throw new IllegalArgumentException();
+ }
+
+ fieldIdCounter = 1;
+ fieldPositions = new HashMap();
+
+ this.type = type;
+ this.fields = new HashMap();
+ this.complexity = null;
+
+ // iterate over the constraints of the type and create the fields
+ for (Constraint constraint : type) {
+ for (Position position : constraint) {
+ if (!fields.containsKey(position)) {
+
+ Field f;
+ Integer solution = map == null ? null : map.get(position);
+ if (solution != null) {
+ f = new Field(setValues == null || setValues.get(position) == null
+ || setValues.get(position) == false, solution, fieldIdCounter,
+ type.getNumberOfSymbols());
+ } else {
+ f = new Field(fieldIdCounter, type.getNumberOfSymbols());
+ }
+
+ fields.put(position, f);
+ fieldPositions.put(fieldIdCounter++, position);
+ f.registerListener(this);
+ }
+ }
+ }
+ }
+
+ /**
+ * Erzeugt ein vollständig leeres Sudoku, welches noch gefüllt werden muss. DO NOT USE THIS METHOD (if you are not
+ * from us)
+ */
+ Sudoku() {
+ id = -1;
+ }
+
+ /** Methods */
+
+ /**
+ * Gibt die id dieses Sudokus zurueck
+ *
+ * @return die id
+ */
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * Gibt an wie oft dieses Sudoku bereits transformiert wurde
+ *
+ * @return die anzahl der Transformationen
+ */
+ public int getTransformCount() {
+ return transformCount;
+ }
+
+ /**
+ * Zaehlt den transform Counter um 1 hoch
+ */
+ public void increaseTransformCount() {
+ transformCount++;
+ }
+
+ /**
+ * Gibt das Feld, welches sich an der spezifizierten Position befindet zurück. Ist position null oder in diesem
+ * Sudoku unbelegt, so wird null zurückgegeben.
+ *
+ * @param position
+ * Die Position, dessen Feld abgefragt werden soll
+ * @return Das Feld an der spezifizierten Position oder null, falls dies nicht existiert oder null übergeben wurde
+ */
+ public Field getField(Position position) {
+ if (position == null)
+ return null;
+ return fields.get(position);
+ }
+
+ /**
+ * Belegt die spezifizierte Position mit einem neuen Field
+ *
+ * @param field
+ * das neue Field
+ * @param position
+ * die Position des neuen Fields
+ */
+ public void setField(Field field, Position position) {
+ if (field == null || position == null)
+ return;
+ fields.put(position, field);
+ fieldPositions.put(field.getId(), position);
+ }
+
+ /**
+ * Gibt das Feld, das die gegebene id hat zurück. Ist id noch nicht vergeben wird null zurückgegeben
+ *
+ * @param id
+ * Die id des Feldes das ausgegeben werden soll
+ * @return Das Feld an der spezifizierten Position oder null, falls dies nicht existiert oder die id ungültig war
+ */
+ public Field getField(int id) {
+ return getField(fieldPositions.get(id));
+ }
+
+ /**
+ * Gibt die Position des Feldes, das die gegebene id hat zurück. Ist id noch nicht vergeben wird null zurückgegeben
+ *
+ * @param id
+ * Die id des Feldes der Position die ausgegeben werden soll
+ * @return Die spezifizierte Position oder null, falls diese nicht existiert oder die id ungültig war
+ */
+ public Position getPosition(int id) {
+ return fieldPositions.get(id);
+ }
+
+ /**
+ * Gibt einen Iterator zurück, mithilfe dessen über alle Felder dieses Sudokus iteriert werden kann.
+ *
+ * @return Ein Iterator mit dem über alle Felder dieses Sudokus iteriert werden kann
+ */
+ @Override
+ public Iterator iterator() {
+ return fields.values().iterator();
+ }
+
+ /**
+ * Gibt den Schwierigkeitsgrad dieses Sudokus zurück.
+ *
+ * @return Der Schwierigkeitsgrad dieses Sudokus
+ */
+ public Complexity getComplexity() {
+ return complexity;
+ }
+
+ /**
+ * Gibt den Typ dieses Sudokus zurück.
+ *
+ * @return Der Typ dieses Sudokus
+ */
+ public TypeBasic getSudokuType() {
+ return type;
+ }
+
+ /**
+ * Setzt den Schwierigkeitsgrad dieses Sudokus auf den Spezifizierten. Ist dieser ungültig so wird nichts getan.
+ *
+ * @param complexity
+ * Der Schwierigkeitsgrad auf den dieses Sudoku gesetzt werden soll
+ */
+ public void setComplexity(Complexity complexity) {
+ this.complexity = complexity;
+ }
+
+ /**
+ * Gibt an, ob das Sudoku vollstaendig ausgefuellt und korrekt geloest ist.
+ *
+ * @return true, falls das Sudoku ausgefüllt und gelöst ist, sonst false
+ */
+ public boolean isFinished() {
+ for (Field field : fields.values()) {
+ if (!field.isSolvedCorrect()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public XmlTree toXmlTree() {
+ XmlTree representation = new XmlTree("sudoku");
+ if (id > 0) {
+ representation.addAttribute(new XmlAttribute("id", "" + id));
+ }
+ representation.addAttribute(new XmlAttribute("transformCount", "" + transformCount));
+ representation.addAttribute(new XmlAttribute("type", "" + this.getSudokuType().getEnumType().ordinal()));
+ if (complexity != null) {
+ representation.addAttribute(new XmlAttribute("complexity", "" + this.getComplexity().ordinal()));
+ }
+
+ for (Map.Entry field : fields.entrySet()) {
+ if (field.getValue() != null) {
+ XmlTree fieldmap = new XmlTree("fieldmap");
+ fieldmap.addAttribute(new XmlAttribute("id", "" + field.getValue().getId()));
+ fieldmap.addAttribute(new XmlAttribute("editable", "" + field.getValue().isEditable()));
+ fieldmap.addAttribute(new XmlAttribute("solution", "" + field.getValue().getSolution()));
+ XmlTree position = new XmlTree("position");
+ position.addAttribute(new XmlAttribute("x", "" + field.getKey().getX()));
+ position.addAttribute(new XmlAttribute("y", "" + field.getKey().getY()));
+ fieldmap.addChild(position);
+ representation.addChild(fieldmap);
+ }
+ }
+
+ return representation;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void fillFromXml(XmlTree xmlTreeRepresentation) {
+ // initialisation
+
+ fieldIdCounter = 1;
+ fieldPositions = new HashMap();
+
+ fields = new HashMap();
+
+ try {
+ id = Integer.parseInt(xmlTreeRepresentation.getAttributeValue("id"));
+ } catch (NumberFormatException e) {
+ id = -1;
+ }
+ type = SudokuBuilder.createType(SudokuTypes.values()[Integer.parseInt(xmlTreeRepresentation
+ .getAttributeValue("type"))]);
+ transformCount = Integer.parseInt(xmlTreeRepresentation.getAttributeValue("transformCount"));
+
+ String compl = xmlTreeRepresentation.getAttributeValue("complexity");
+ complexity = compl == null ? null : Complexity.values()[Integer.parseInt(compl)];
+
+ // build the fields
+ for (Iterator iterator = xmlTreeRepresentation.getChildren(); iterator.hasNext();) {
+ XmlTree sub = iterator.next();
+ if (sub.getName().equals("fieldmap")) {
+ int fieldId = Integer.parseInt(sub.getAttributeValue("id"));
+ boolean editable = Boolean.parseBoolean(sub.getAttributeValue("editable"));
+ int solution = Integer.parseInt(sub.getAttributeValue("solution"));
+ int x = -1, y = -1;
+ // check if there is only one child element
+ if (sub.getNumberOfChildren() != 1) {
+ throw new IllegalArgumentException();
+ }
+ XmlTree position = sub.getChildren().next();
+ if (position.getName().equals("position")) {
+ x = Integer.parseInt(position.getAttributeValue("x"));
+ y = Integer.parseInt(position.getAttributeValue("y"));
+ }
+ Position pos = Position.get(x, y);
+ Field field = new Field(editable, solution, fieldId, type.getNumberOfSymbols());
+ field.registerListener(this);
+ fields.put(pos, field);
+ fieldPositions.put(new Integer(fieldId), pos);
+ fieldIdCounter++;
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void onModelChanged(Field changedField) {
+ notifyListeners(changedField);
+ }
+
+ /**
+ * Setzt die Identifikationsnummer des Sudokus.
+ *
+ * @param id
+ * Die eindeutige Identifikationsnummer
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (obj != null && obj instanceof Sudoku) {
+
+ boolean allEqual = true;
+ Sudoku other = (Sudoku) obj;
+
+ allEqual &= complexity == other.getComplexity();
+ allEqual &= other.getSudokuType().getEnumType().equals(type.getEnumType());
+
+ for (Map.Entry fieldpos : fields.entrySet()) {
+ Field field = fieldpos.getValue();
+ Field compare = other.getField(new Integer(field.getId()));
+ allEqual &= compare != null;
+ allEqual &= field.equals(compare);
+ }
+ return allEqual;
+ }
+ return false;
+ }
+
+ /**
+ * Gibt zurück, ob dieses Sudoku in den aktuell gesetzten Werten Fehler enthält, d.h. ob es ein Feld gibt, dessen
+ * aktueller Wert nicht der korrekten Lösung entspricht.
+ *
+ * @return true, falls es in dem Sudoku falsch gelöste Felder gibt, false andernfalls
+ */
+ public boolean hasErrors() {
+ for (Field f : this.fields.values()) {
+ if (!f.isNotWrong()) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/SudokuBuilder.java b/sudoq-model/src/de/sudoq/model/sudoku/SudokuBuilder.java
new file mode 100644
index 00000000..8f7baab2
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/SudokuBuilder.java
@@ -0,0 +1,141 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+import de.sudoq.model.sudoku.sudokuTypes.HyperSudoku;
+import de.sudoq.model.sudoku.sudokuTypes.SamuraiSudokuType;
+import de.sudoq.model.sudoku.sudokuTypes.SquigglyASudokuType9x9;
+import de.sudoq.model.sudoku.sudokuTypes.SquigglyBSudokuType9x9;
+import de.sudoq.model.sudoku.sudokuTypes.StairStepSudokuType9x9;
+import de.sudoq.model.sudoku.sudokuTypes.StandardSudokuType;
+import de.sudoq.model.sudoku.sudokuTypes.StandardSudokuType16x16;
+import de.sudoq.model.sudoku.sudokuTypes.StandardSudokuType4x4;
+import de.sudoq.model.sudoku.sudokuTypes.StandardSudokuType6x6;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+import de.sudoq.model.sudoku.sudokuTypes.TypeBasic;
+import de.sudoq.model.sudoku.sudokuTypes.XSudoku;
+
+/**
+ * Der SudokuBuilder stellt Methoden zur Verfügung, um einen Sudoku-Typ oder ein
+ * komplettes, leeres Sudoku zu erzeugen.
+ */
+public class SudokuBuilder {
+
+ private PositionMap solutions;
+ private PositionMap setValues;
+ private TypeBasic type;
+
+ /** Constructors */
+
+ /**
+ * Erstellt einen Builder fuer ein Sudoku des spezifizierten Typs.
+ *
+ * @param type
+ * der Enum-Typ des zu erstellenden Sudokus
+ * @throws NullPointerException
+ * falls type invalid ist.
+ */
+ public SudokuBuilder(SudokuTypes type) {
+ this(createType(type));
+ }
+
+ /**
+ * Erstellt einen Builder fuer ein Sudoku des spezifizierten Typs.
+ *
+ * @param type
+ * Das SudokuType-Objekt für das zu erstellende Sudokus
+ * @throws NullPointerException
+ * falls type null ist.
+ */
+ public SudokuBuilder(TypeBasic type) {
+ this.type = type;
+ solutions = new PositionMap(type.getSize());
+ setValues = new PositionMap(type.getSize());
+ }
+
+ /** Methods */
+
+ /**
+ * Erstellt ein Sudoku mit dem Sudoku Typ dieses Builders und den
+ * eingetragenen Loesungen.
+ *
+ * @return Das passende Sudoku
+ */
+ public Sudoku createSudoku() {
+ return new Sudoku(type, solutions, setValues);
+ }
+
+ /**
+ * Fügt dem aktuellen Sudoku die gegebene Lösung hinzu
+ *
+ * @param pos
+ * die Position der Lösung
+ * @param value
+ * der Wert der Lösung
+ * @throws IllegalArgumentException
+ * falls der gegebene Wert kleiner 0 oder größer dem maximalen
+ * für diesen Typ zugelassen Wert ist
+ */
+ public void addSolution(Position pos, int value) {
+ if (value < 0 || value >= type.getNumberOfSymbols()) {
+ throw new IllegalArgumentException("Unvalid value for given Sudoku Type");
+ }
+ solutions.put(pos, value);
+ }
+
+ /**
+ * Setzt die gegebene Position als Vorgabe für das Sudoku
+ *
+ * @param pos
+ * die Position der Vorgabe
+ */
+ public void setFixed(Position pos) {
+ setValues.put(pos, true);
+ }
+
+ /**
+ * Erstellt ein SudokuType-Objekt entsprechend dem spezifizierten Typ-Namen
+ * und gibt dieses zurück. Ist der übergebene Name null oder kann er nicht
+ * zugeordnet werden, so wird null zurückgegeben.
+ *
+ * @param type
+ * Der Enum-Typ des zu erstellenden Sudoku Types
+ * @return Ein SudokuType-Objekt entsprechend dem spezifizierten Typnamen
+ * oder null, falls der Name null ist oder nicht zugeordnet werden
+ * kann
+ */
+ public static TypeBasic createType(SudokuTypes type) {
+ if (type == null)
+ return null;
+
+ switch (type) {
+ case standard9x9:
+ return new StandardSudokuType();
+ case standard16x16:
+ return new StandardSudokuType16x16();
+ case standard4x4:
+ return new StandardSudokuType4x4();
+ case standard6x6:
+ return new StandardSudokuType6x6();
+ case Xsudoku:
+ return new XSudoku();
+ case HyperSudoku:
+ return new HyperSudoku();
+ case squigglya:
+ return new SquigglyASudokuType9x9();
+ case squigglyb:
+ return new SquigglyBSudokuType9x9();
+ case stairstep:
+ return new StairStepSudokuType9x9();
+ case samurai:
+ return new SamuraiSudokuType();
+ default:
+ return null;
+ }
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/SudokuManager.java b/sudoq-model/src/de/sudoq/model/sudoku/SudokuManager.java
new file mode 100644
index 00000000..30a65917
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/SudokuManager.java
@@ -0,0 +1,113 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.solverGenerator.Generator;
+import de.sudoq.model.solverGenerator.GeneratorCallback;
+import de.sudoq.model.solverGenerator.transformations.Transformer;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+import de.sudoq.model.xml.SudokuXmlHandler;
+
+/**
+ * Ist fuer die Verwaltung der vorhandenen Sudokus zuständig. Setzt das
+ * Singleton Pattern um.
+ */
+public class SudokuManager implements GeneratorCallback {
+
+ // private static final int[][] neccessaryCounts = new
+ // int[SudokuTypes.values().length][Complexity.values().length];
+ private Generator generator = new Generator();
+ private Sudoku used = null;
+
+ // neccessaryCounts[SudokuTypes.standard9x9.ordinal()][Complexity.easy.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.standard9x9.ordinal()][Complexity.medium.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.standard9x9.ordinal()][Complexity.difficult.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.standard9x9.ordinal()][Complexity.infernal.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.standard16x16.ordinal()][Complexity.easy.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.standard16x16.ordinal()][Complexity.medium.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.standard16x16.ordinal()][Complexity.difficult.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.standard16x16.ordinal()][Complexity.infernal.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.Xsudoku.ordinal()][Complexity.easy.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.Xsudoku.ordinal()][Complexity.medium.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.Xsudoku.ordinal()][Complexity.difficult.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.Xsudoku.ordinal()][Complexity.infernal.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.HyperSudoku.ordinal()][Complexity.easy.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.HyperSudoku.ordinal()][Complexity.medium.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.HyperSudoku.ordinal()][Complexity.difficult.ordinal()]
+ // = 10;
+ // neccessaryCounts[SudokuTypes.HyperSudoku.ordinal()][Complexity.infernal.ordinal()]
+ // = 10;
+
+ /**
+ * Das Callback fuer den Generator
+ */
+ public void generationFinished(Sudoku sudoku) {
+ new SudokuXmlHandler().saveAsXml(sudoku);
+ FileManager.deleteSudoku(used);
+ }
+
+ /**
+ * Markiert ein Sudoku als benutzt. Falls möglich wird es transformiert,
+ * andernfalls gelöscht und ein neues generiert.
+ *
+ * @param sudoku
+ * das genutzte Sudoku
+ */
+ public void usedSudoku(Sudoku sudoku) {
+ if (sudoku.getTransformCount() >= 10) {
+ used = sudoku;
+ generator.generate(sudoku.getSudokuType().getEnumType(), sudoku.getComplexity(), this);
+ } else {
+ Transformer.transform(sudoku);
+ new SudokuXmlHandler().saveAsXml(sudoku);
+ }
+ }
+
+ /**
+ * Gibt ein neues Sudoku des gewünschten Typs und der gewünschten
+ * Schwierigkeit zurück
+ *
+ * @param t
+ * Typ des Sudokus
+ * @param c
+ * Schwierigkeit des Sudokus
+ * @return das neue Sudoku
+ */
+ public static Sudoku getNewSudoku(SudokuTypes t, Complexity c) {
+ Sudoku sudoku = getEmptySudokuToFillWithXml();
+ new SudokuXmlHandler(t, c).createObjectFromXml(sudoku);
+ return sudoku;
+ }
+
+ /**
+ * Erzeugt ein vollständig leeres Sudoku, welches noch gefüllt werden muss.
+ * DO NOT USE THIS METHOD (if you are not from us)
+ *
+ * @return das neue Sudoku
+ */
+ public static Sudoku getEmptySudokuToFillWithXml() {
+ return new Sudoku();
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/SumConstraintBehavior.java b/sudoq-model/src/de/sudoq/model/sudoku/SumConstraintBehavior.java
new file mode 100644
index 00000000..e9b4104e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/SumConstraintBehavior.java
@@ -0,0 +1,62 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+/**
+ * Das SumConstraintBehavior repräsentiert ein Constraint-Verhalten, wobei die Summe der Feld-Werte eines Constraints
+ * eine vorgegebene Summe haben muss.
+ */
+public class SumConstraintBehavior implements ConstraintBehavior {
+ /** Attributes */
+
+ /**
+ * Die Summe, auf welche das SumConstraintBehavior die Felder des Constraints auf dem Sudoku ueberprueft.
+ */
+ private int sum;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert ein neues SumConstraintBehavior-Objekt, welches Constraints auf die spezifizierte Summe der
+ * zugehörigen Feldwerte überprüfen kann. Ist diese kleiner als 0, so wird eine IllegalArgumentException geworfen.
+ *
+ * @param sum
+ * Die Summe, die die Feldwerte in diesem Constraint haben müssen
+ */
+ public SumConstraintBehavior(int sum) {
+ if (sum >= 0) {
+ this.sum = sum;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ /** Methods */
+
+ /**
+ * Überprüft, ob das spezifizierte Constraint dieses Verhalten auf dem uebergebenen Sudoku erfüllt. Dies bedeutet,
+ * dass überprüft wird, ob die Summe der aktuellen Feldwerte des Constraints kleiner ist als der im Konstruktor
+ * dieses Verhaltens vorgegebene Wert bzw. gleich diesem ist, falls alle Felder des Constraints befüllt sind. Ist
+ * das Verhalten erfüllt, so wird true, andernfalls oder falls das spezifizierte Constraint null ist wird false
+ * zurückgegeben.
+ *
+ * @return true, falls das spezifizierte Constraint dieses Verhalten erfüllt bzw. false falls es dies nicht tut oder
+ * null übergeben wurde
+ */
+ @Override
+ public boolean check(Constraint constraint, Sudoku sudoku) {
+ int fieldSum = 0;
+ boolean fullySolved = true;
+ for (Position pos : constraint) {
+ fieldSum += sudoku.getField(pos).getCurrentValue();
+ if (sudoku.getField(pos).isEmpty())
+ fullySolved = false;
+ }
+ return (fieldSum == sum || (!fullySolved && fieldSum <= sum));
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/UniqueConstraintBehavior.java b/sudoq-model/src/de/sudoq/model/sudoku/UniqueConstraintBehavior.java
new file mode 100644
index 00000000..76d9f15e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/UniqueConstraintBehavior.java
@@ -0,0 +1,60 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Das UniqueConstraintBehavior repräsentiert ein Constraint-Verhalten, wobei kein Symbol innerhalb eines Constraints
+ * doppelt vorkommen darf.
+ */
+public class UniqueConstraintBehavior implements ConstraintBehavior {
+ /**
+ * Eine Liste der in der check-Methode gefundenen Ziffern. Wurde aus Performancegründen nicht lokal definiert.
+ */
+ List foundNumbers;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert ein neues UniqueConstraintBehavior-Objekt.
+ */
+ public UniqueConstraintBehavior() {
+ this.foundNumbers = new ArrayList();
+ }
+
+ /** Methods */
+
+ /**
+ * Überprüft, ob das spezifizierte Constraint das Unique-Verhalten erfüllt. D.h. es wird überprüft, ob innerhalb des
+ * Constraints kein Symbol in zwei Feldern eingetragen ist. Ist das Verhalten erfüllt, so wird true, andernfalls
+ * oder falls das spezifizierten Constraint null ist wird false zurückgegeben.
+ *
+ * @return true, falls das spezifizierte Constraint dieses Verhalten erfüllt bzw. false falls es dies nicht tut oder
+ * null übergeben wurde
+ */
+ public boolean check(Constraint constraint, Sudoku sudoku) {
+ int currentValue;
+ foundNumbers.clear();
+
+ ArrayList positions = constraint.getPositions();
+ for (int i = 0; i < positions.size(); i++) {
+ currentValue = sudoku.getField(positions.get(i)).getCurrentValue();
+ if (currentValue != -1) {
+ if (foundNumbers.contains(currentValue)) {
+ return false;
+ } else {
+ foundNumbers.add(currentValue);
+ }
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/complexity/Complexity.java b/sudoq-model/src/de/sudoq/model/sudoku/complexity/Complexity.java
new file mode 100644
index 00000000..ab4a24c0
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/complexity/Complexity.java
@@ -0,0 +1,52 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.complexity;
+
+/**
+ * Dieses enum repräsentiert die Schwierigkeit eines spezielles Sudokus, wobei
+ * invalid keine Schwierigkeit im eigentlichen Sinne, sondern eine Kennung für
+ * ein ungültiges Sudoku ist.
+ */
+public enum Complexity {
+ /**
+ * Der einfachste Schwierigkeitsgrad für ein Sudokus: Es sind viele Felder
+ * vorgegeben und diese sind leicht zu lösen.
+ */
+ easy,
+
+ /**
+ * Der mittlere Schwierigkeitsgrad für ein Sudoku: Es sind weniger Felder
+ * vorgegeben und es dieses sind schwerer zu lösen als bei easy.
+ */
+ medium,
+
+ /**
+ * Der hohe Schwierigkeitsgrad für ein Sudoku: Es sind wenige Felder
+ * vorgegeben und diese sind nur mit komplizierten Techniken lösbar.
+ */
+ difficult,
+
+ /**
+ * Der höchste Schwierigkeitsgrad für ein Sudoku: Es sind sehr wenige Felder
+ * vorgegeben und diese sind nur mit den schwersten Techniken (auch mit
+ * Raten bzw. Backtracking) lösbar.
+ */
+ infernal,
+
+ /**
+ * Dies ist kein Schwierigkeitsgrad im eigentlichen Sinne, sondern ein
+ * Kennzeichen für ein ungültiges Sudoku.
+ */
+ // invalid,
+
+ /**
+ * Ein Dummy für beliebige Schwierigkeit. Es werden keine Anforderungen
+ * gestellt.
+ */
+ arbitrary;
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/complexity/ComplexityConstraint.java b/sudoq-model/src/de/sudoq/model/sudoku/complexity/ComplexityConstraint.java
new file mode 100644
index 00000000..a8c28762
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/complexity/ComplexityConstraint.java
@@ -0,0 +1,140 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.complexity;
+
+/**
+ * Diese Klasse repräsentiert die Vorgaben, die ein Sudoku einer bestimmten Schwierigkeit erfüllen muss. Zu den Vorgaben
+ * zählen minimal und maximale Anzahl vorgegebener Felder, die Schwierigkeit der Lösung notwendigen Vorgehensweisen,
+ * sowie die Anzahl der überhaupt notwendigen verschiedenen Vorgehensweisen.
+ */
+public class ComplexityConstraint {
+ /** Attributes */
+
+ /**
+ * Der Schwierigkeitsgrade für den die Vorgaben gemacht werden
+ */
+ private Complexity complexity;
+
+ /**
+ * Die durchschnittliche Anzahl Felder, die bei dieser Schwierigkeit belegt sein sollte
+ */
+ private int averageFields;
+
+ /**
+ * Die minimale Höhe der Summe der Schwierigkeitsgrade (vorgegeben vom Lösungsalgorithmus als Ganzzahl) der zum
+ * Lösen eines Sudokus nötigen Vorgehensweisen
+ */
+ private int minComplexityIdentifier;
+
+ /**
+ * Die maximale Höhe der Summe der Schwierigkeitsgrade (vorgegeben vom Lösungsalgorithmus als Ganzzahl) der zum
+ * Lösen eines Sudokus nötigen Vorgehensweisen
+ */
+ private int maxComplexityIdentifier;
+
+ /**
+ * Die Anzahl der erlaubten Vorgehensweisen, wobei diese die im Lösungsalgorithmus mit der geringsten Schwierigkeit
+ * hinterlegten sind
+ */
+ private int numberOfAllowedHelpers;
+
+ /** Constructors */
+
+ /**
+ * Instanziiert ein neues ComplexityConstraint-Objekt mit den spezifizierten Attributen.
+ *
+ * @param complexity
+ * Die Schwierigkeit eines Sudokus für welche die Vorgaben dieses Objektes gelten sollen
+ * @param averageFields
+ * Die durchschnittliche Anzahl Felder, die bei dieser Schwierigkeit belegt sein sollte
+ * @param minComplexityIdentifier
+ * Die minimale Summe der Schwierigkeitsgrade (vorgegeben vom Lösungsalsgorithmus als Ganzzahl) der zum
+ * Lösen eines Sudokus nötigen Vorgehensweisen
+ * @param maxComplexityIdentifier
+ * Die minimale Summe der Schwierigkeitsgrade (vorgegeben vom Lösungsalsgorithmus als Ganzzahl) der zum
+ * Lösen eines Sudokus nötigen Vorgehensweisen
+ * @param numberOfAllowedHelpers
+ * Die Anzahl der erlaubten Vorgehensweisen (die im Lösungsalgorithmus hinterlegten mit geringstem
+ * Schwierigkeitsgrad)
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls complexity null bzw. averageFields, minComplexityIdentifier oder
+ * numberOfAllowedHelpers kleiner oder gleich 0 ist oder einer der minComplexityIdentifier größer ist
+ * als der zugehörige max-Wert
+ */
+ public ComplexityConstraint(Complexity complexity, int averageFields, int minComplexityIdentifier,
+ int maxComplexityIdentifier, int numberOfAllowedHelpers) {
+ if (complexity == null)
+ throw new IllegalArgumentException("Complexity was null");
+ if (minComplexityIdentifier <= 0)
+ throw new IllegalArgumentException("minComplexityIdentifier < 0: " + minComplexityIdentifier);
+ if (averageFields <= 0)
+ throw new IllegalArgumentException("averageFields < 0: " + averageFields);
+ if (numberOfAllowedHelpers <= 0)
+ throw new IllegalArgumentException("minComplexityIdentifier < 0: " + numberOfAllowedHelpers);
+ if (minComplexityIdentifier > maxComplexityIdentifier)
+ throw new IllegalArgumentException("minComplexityIdentifier > maxComplexityIdentifier: "
+ + minComplexityIdentifier + " > " + maxComplexityIdentifier);
+
+ this.complexity = complexity;
+ this.averageFields = averageFields;
+ this.minComplexityIdentifier = minComplexityIdentifier;
+ this.maxComplexityIdentifier = maxComplexityIdentifier;
+ this.numberOfAllowedHelpers = numberOfAllowedHelpers;
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode gibt die Schwierigkeit zurück, auf die sich die Vorgaben dieses Constraints beziehen.
+ *
+ * @return Die Schwierigkeit, auf die sich die Vorgaben dieses Constraints beziehen
+ */
+ public Complexity getComplexity() {
+ return complexity;
+ }
+
+ /**
+ * Gibt die durchschnittliche Anzahl belegter Felder bei Sudokus dieser Schwierigkeit zurück.
+ *
+ * @return Die durchschnittliche Anzahl belegter Felder in dieser Schwierigkeit
+ */
+ public int getAverageFields() {
+ return this.averageFields;
+ }
+
+ /**
+ * Diese Methode gibt die minimale Höhe der Summe der Schwierigkeitsgrade (vorgegeben vom Lösungsalgorithmus als
+ * Ganzzahl) der zum Lösen eines Sudokus des vorgegebenen Schwierigkeitsgrades nötigen Vorgehensweisen.
+ *
+ * @return Die minimale Summe der Schwierigkeitsgrade der zum Lösen eines Sudokus nötigen Vorgehensweisen
+ */
+ public int getMinComplexityIdentifier() {
+ return minComplexityIdentifier;
+ }
+
+ /**
+ * Diese Methode gibt die maximale Höhe der Summe der Schwierigkeitsgrade (vorgegeben vom Lösungsalgorithmus als
+ * Ganzzahl) der zum Lösen eines Sudokus des vorgegebenen Schwierigkeitsgrades nötigen Vorgehensweisen.
+ *
+ * @return Die maximale Summe der Schwierigkeitsgrade der zum Lösen eines Sudokus nötigen Vorgehensweisen
+ */
+ public int getMaxComplexityIdentifier() {
+ return maxComplexityIdentifier;
+ }
+
+ /**
+ * Diese Methode gibt die Anzahl der erlaubten verschiedenen Vorgehensweisen zum Lösen eines Sudokus des
+ * vorgegebenen Schwierigkeitsgrades zurück. Genutzt werden dann diejenigen, die im Lösungsalgorithmus mit dem
+ * geringsten Schwierigkeitsgrad hinterlegt sind.
+ *
+ * @return Die Anzahl der erlaubten verschiedenen Vorgehensweisen zum Lösen eines Sudokus
+ */
+ public int getNumberOfAllowedHelpers() {
+ return numberOfAllowedHelpers;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/complexity/ComplexityFactory.java b/sudoq-model/src/de/sudoq/model/sudoku/complexity/ComplexityFactory.java
new file mode 100644
index 00000000..e65da019
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/complexity/ComplexityFactory.java
@@ -0,0 +1,33 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.complexity;
+
+/**
+ * Diese statische Klassen bietet Methoden zum erzeugen von
+ * ComplexityConstraints entsprechend einer vorgegebenen Schwierigkeit.
+ */
+public interface ComplexityFactory {
+ /** Methods */
+
+ /**
+ * Diese Methode erzeugt ein ComplexityConstraint, welches Vorgaben für ein Sudokus des spezifizierten Schwierigkeites enthält.
+ * Ist die spezifizierten Complexity ungültig oder ist kein Constraint dafür definiert, so wird null zurückgegeben.
+ *
+ * @param complexity Die Schwierigkeit für die ein ComplexityConstraint-Objekt erzeugt werden soll
+ * @return Ein ComplexityConstraint-Objekt für die spezifizierten Schwierigkeit oder null, falls diese ungültig ist
+ */
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity);
+
+ /**
+ * Gibt den Faktor zurück, der die Anzahl der Felder angibt, welche mit dem das Sudoku durch den Generierungsalgorithmus gut zufällig belegt und
+ * gleichzeitig validiert werden kann.
+ *
+ * @return Der Standardfaktor für die Felderbelegung dieses Sudokutyps
+ */
+ public float getStandardAllocationFactor();
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/HyperSudoku.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/HyperSudoku.java
new file mode 100644
index 00000000..de87dd7c
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/HyperSudoku.java
@@ -0,0 +1,93 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.ConstraintType;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.UniqueConstraintBehavior;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+public class HyperSudoku extends TypeStandard {
+
+ /**
+ * Erzeugt einen neuen HyperSudokuTyp
+ */
+ public HyperSudoku() {
+ super(9);
+ addExtraConstraints(positionsGrid);
+ permutationProperties.remove(PermutationProperties.horizontal_Blockshift);
+ permutationProperties.remove(PermutationProperties.vertical_Blockshift);
+ permutationProperties.remove(PermutationProperties.inBlock_Collumnshift);
+ permutationProperties.remove(PermutationProperties.inBlock_Rowshift);
+ }
+
+ /**
+ * fügt die zusätzlichen Blockconstraints hinzu
+ *
+ * @param positionsGrid
+ * das Array das die Positions verwaltet
+ */
+ protected void addExtraConstraints(Position[][] positionsGrid) {
+ for (int i = 0; i < 4; i++) {
+ Constraint c = new Constraint(new UniqueConstraintBehavior(), ConstraintType.EXTRA, "Extra block " + i);
+
+ for (int j = 0; j < 9; j++) {
+ c.addPosition(positionsGrid[i % 2 * 4 + 1 + j % 3][i / 2 * 4 + 1 + j / 3]);
+ }
+ constraints.add(c);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.HyperSudoku;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 40, 500, 800, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 32, 750, 1050, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 28, 1000, 2500, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 27, 2500, 25000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 32, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.25f;
+ }
+
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/PermutationProperties.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/PermutationProperties.java
new file mode 100644
index 00000000..c085148f
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/PermutationProperties.java
@@ -0,0 +1,66 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+/**
+ * Dieses Enum definiert die auf einem Sudoku verfügbaren Permutationen.
+ */
+public enum PermutationProperties {
+ /** Attributes */
+
+ /**
+ * Rotation um 90°.
+ */
+ rotate90,
+
+ /**
+ * Rotation um 180°.
+ */
+ rotate180,
+
+ /**
+ * Permutation von BlockSpalten
+ */
+ horizontal_Blockshift,
+
+ /**
+ * Permutation von BlockZeilen
+ */
+ vertical_Blockshift,
+
+ /**
+ * Permutation von Spalten innerhalb von Blockgrenzen
+ */
+ inBlock_Collumnshift,
+
+ /**
+ * Permutation von Zeilen innerhalb von Blockgrenzen
+ */
+ inBlock_Rowshift,
+
+ /**
+ * Spiegelung an der Diagonalen von links unten nach recht oben
+ */
+ diagonal_up,
+
+ /**
+ * Spiegelung an der Diagonalen von links oben nach rechts unten
+ */
+ diagonal_down,
+
+ /**
+ * Spiegelung an einer mittigen Achse oben nach unten
+ */
+ mirror_horizontal,
+
+ /**
+ * Spiegelung an einer mittigen Achse links nach rechst
+ */
+ mirror_vertical
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SamuraiSudokuType.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SamuraiSudokuType.java
new file mode 100644
index 00000000..b0582924
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SamuraiSudokuType.java
@@ -0,0 +1,172 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.ConstraintType;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.UniqueConstraintBehavior;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+/**
+ * Erzeugt einen SamuraiSudokuType
+ */
+public class SamuraiSudokuType extends TypeUniversal {
+
+ /**
+ * Erzeugt einen neuen SamuraiSudokuTyp
+ */
+ public SamuraiSudokuType() {
+ super(21, 9);
+ addConstraints();
+ blockDimensions = Position.get(3, 3);
+ permutationProperties.add(PermutationProperties.rotate90);// we can do
+ // much mini
+ // permutations
+ // here, but
+ // not now
+ permutationProperties.add(PermutationProperties.rotate180);
+ permutationProperties.add(PermutationProperties.mirror_horizontal);
+ permutationProperties.add(PermutationProperties.mirror_vertical);
+ permutationProperties.add(PermutationProperties.diagonal_up);
+ permutationProperties.add(PermutationProperties.diagonal_down);
+ }
+
+ private void addConstraints() {
+
+ addRows();
+ addColumns();
+ for (int i = 0; i < 9; i++) {
+ addBlock(Position.get(0 + i % 3 * 3, 0 + i / 3 * 3), i);
+ }
+ for (int i = 0; i < 9; i++) {
+ addBlock(Position.get(12 + i % 3 * 3, 0 + i / 3 * 3), i + 9);
+ }
+ for (int i = 0; i < 9; i++) {
+ addBlock(Position.get(0 + i % 3 * 3, 12 + i / 3 * 3), i + 18);
+ }
+ for (int i = 0; i < 9; i++) {
+ addBlock(Position.get(12 + i % 3 * 3, 12 + i / 3 * 3), i + 27);
+ }
+
+ addBlock(Position.get(9, 6), 36);
+ addBlock(Position.get(6, 9), 37);
+ addBlock(Position.get(9, 9), 38);
+ addBlock(Position.get(12, 9), 39);
+ addBlock(Position.get(9, 12), 40);
+
+ }
+
+ private void addRows() {
+ for (int i = 0; i < 9; i++) {
+ addRow(Position.get(0, 0 + i), 9, i);
+ }
+ for (int i = 0; i < 9; i++) {
+ addRow(Position.get(12, 0 + i), 9, i + 9);
+ }
+ for (int i = 0; i < 9; i++) {
+ addRow(Position.get(0, 12 + i), 9, i + 18);
+ }
+ for (int i = 0; i < 9; i++) {
+ addRow(Position.get(12, 12 + i), 9, i + 27);
+ }
+ for (int i = 0; i < 9; i++) {
+ addRow(Position.get(6, 6 + i), 9, i + 36);
+ }
+ }
+
+ private void addColumns() {
+ for (int i = 0; i < 9; i++) {
+ addColumn(Position.get(0 + i, 0), 9, i);
+ }
+ for (int i = 0; i < 9; i++) {
+ addColumn(Position.get(12 + i, 0), 9, i + 9);
+ }
+ for (int i = 0; i < 9; i++) {
+ addColumn(Position.get(0 + i, 12), 9, i + 18);
+ }
+ for (int i = 0; i < 9; i++) {
+ addColumn(Position.get(12 + i, 12), 9, i + 27);
+ }
+ for (int i = 0; i < 9; i++) {
+ addColumn(Position.get(6 + i, 6), 9, i + 36);
+ }
+ }
+
+ private void addRow(Position start, int lenght, int number) {
+ Constraint c = new Constraint(new UniqueConstraintBehavior(), ConstraintType.LINE, "Row " + number);
+ for (int i = 0; i < lenght; i++) {
+ c.addPosition(positionsGrid[start.getX() + i][start.getY()]);
+ }
+ constraints.add(c);
+ }
+
+ private void addColumn(Position start, int lenght, int number) {
+ Constraint c = new Constraint(new UniqueConstraintBehavior(), ConstraintType.LINE, "Column " + number);
+ for (int i = 0; i < lenght; i++) {
+ c.addPosition(positionsGrid[start.getX()][start.getY() + i]);
+ }
+ constraints.add(c);
+ }
+
+ // length is 9
+ private void addBlock(Position start, int number) {
+ Constraint c = new Constraint(new UniqueConstraintBehavior(), ConstraintType.BLOCK, "Block " + number);
+ for (int i = 0; i < 9; i++) {
+ c.addPosition(positionsGrid[start.getX() + i % 3][start.getY() + i / 3]);
+ }
+ constraints.add(c);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.samurai;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 70, 1000, 1500, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 55, 1500, 2300, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 40, 2300, 4000, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 30, 4000, 25000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 32, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.05f;
+ }
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SquigglyASudokuType9x9.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SquigglyASudokuType9x9.java
new file mode 100644
index 00000000..c5b9db49
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SquigglyASudokuType9x9.java
@@ -0,0 +1,81 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+public class SquigglyASudokuType9x9 extends TypeSquiggly {
+
+ protected final static String PATTERN = "AABBBBBCC" +
+ "AAABBBCCC" +
+ "DAAABCCCE" +
+ "DDAFFFCEE" +
+ "DDDFFFEEE" +
+ "DDGFFFHEE" +
+ "DGGGIHHHE" +
+ "GGGIIIHHH" +
+ "GGIIIIIHH";
+ /**
+ * Erzeugt einen neuen SquigglyA-SudokuTyp
+ */
+ public SquigglyASudokuType9x9() {
+ super(PATTERN);
+ permutationProperties.add(PermutationProperties.mirror_horizontal);
+ permutationProperties.add(PermutationProperties.mirror_vertical);
+ permutationProperties.add(PermutationProperties.diagonal_down);
+ permutationProperties.add(PermutationProperties.diagonal_up);
+ permutationProperties.add(PermutationProperties.rotate90);
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.squigglya;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 40, 500, 800, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 32, 750, 1050, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 28, 1000, 2500, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 27, 2500, 25000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 32, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.25f;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SquigglyBSudokuType9x9.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SquigglyBSudokuType9x9.java
new file mode 100644
index 00000000..96a57a2e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SquigglyBSudokuType9x9.java
@@ -0,0 +1,77 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+public class SquigglyBSudokuType9x9 extends TypeSquiggly {
+
+ protected final static String PATTERN = "AAAAABBBB"
+ + "AACCCCDBB"
+ + "ACCEFCDDB"
+ + "AEEEFCCDB"
+ + "GEFFFFFDB"
+ + "GEHHFDDDI"
+ + "GEEHFDHHI"
+ + "GGEHHHHII"
+ + "GGGGIIIII";
+
+ /**
+ * Erzeugt einen neuen SquigglyB-Sudokutyp
+ */
+ public SquigglyBSudokuType9x9() {
+ super(PATTERN);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.squigglyb;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+
+ if (complexity != null) {
+
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 40, 500, 800, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 32, 750, 1050, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 28, 1000, 2500, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 27, 2500, 25000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 32, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.20f;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StairStepSudokuType9x9.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StairStepSudokuType9x9.java
new file mode 100644
index 00000000..b3b1bcbd
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StairStepSudokuType9x9.java
@@ -0,0 +1,85 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+public class StairStepSudokuType9x9 extends TypeSquiggly {
+
+ protected final static String PATTERN = "AAAABBBCC" +
+ "AAABBBCCC" +
+ "AABBBCCCC" +
+ "DDDDEEEFF" +
+ "DDDEEEFFF" +
+ "DDEEEFFFF" +
+ "GGGGHHHII" +
+ "GGGHHHIII" +
+ "GGHHHIIII";
+
+ /**
+ * Erzeugt einen neuen Stairstep-Sudokutyp
+ */
+ public StairStepSudokuType9x9() {
+ super(PATTERN);
+ permutationProperties.add(PermutationProperties.vertical_Blockshift);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Position getBlockSize() {
+ return Position.get(4, 3);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.stairstep;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 40, 500, 800, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 32, 750, 1050, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 28, 1000, 2500, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 27, 2500, 25000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 32, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.25f;
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType.java
new file mode 100644
index 00000000..af621730
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType.java
@@ -0,0 +1,70 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+/**
+ * Dieser spezielle Sudoku-Typ repräsentiert das Standard Sudoku (Lateinisches Quadrat der Größe 9).
+ */
+public class StandardSudokuType extends TypeStandard {
+
+ /**
+ * Erzeugt einen neuen Standard-Sudokutyp
+ */
+ public StandardSudokuType() {
+ super(9);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.standard9x9;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 40, 600, 1100, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 32, 1100, 2050, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 28, 1600, 3000, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 27, 2400, 25000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 32, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.35f;
+ }
+
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType16x16.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType16x16.java
new file mode 100644
index 00000000..8b5c6187
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType16x16.java
@@ -0,0 +1,69 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+public class StandardSudokuType16x16 extends TypeStandard {
+
+ /**
+ * Instanziiert einen neuen StandardSudokuType der Größe 16x16. Die
+ * Constraints des erzeugten Typs haben ein UniqueConstraintBehavior und
+ * entsprechen den Zeilen, Spalten und Blöcken des Standard-Sudokus.
+ */
+ public StandardSudokuType16x16() {
+ super(16);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.standard16x16;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 190, 900, 1300, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 140, 1400, 2200, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 120, 2400, 3000, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 105, 3000, 25000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 32, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.25f;
+ }
+
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType4x4.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType4x4.java
new file mode 100644
index 00000000..e10b1dbd
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType4x4.java
@@ -0,0 +1,66 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+public class StandardSudokuType4x4 extends TypeStandard {
+
+ /**
+ * Erzeugt einen StandartSudokuType der größe 4x4
+ */
+ public StandardSudokuType4x4() {
+ super(4);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.standard4x4;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 12, 100, 130, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 9, 125, 160, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 7, 150, 190, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 5, 175, 2500, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 10, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.25f;
+ }
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType6x6.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType6x6.java
new file mode 100644
index 00000000..2958f27e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/StandardSudokuType6x6.java
@@ -0,0 +1,72 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+public class StandardSudokuType6x6 extends TypeStandard {
+
+ /**
+ * Erzeugt einen StandardSudokuType der Größe 6x6
+ */
+ public StandardSudokuType6x6() {
+ super(6);
+ permutationProperties.remove(PermutationProperties.rotate90);
+ permutationProperties.remove(PermutationProperties.rotate180);
+ permutationProperties.remove(PermutationProperties.diagonal_up);
+ permutationProperties.remove(PermutationProperties.diagonal_down);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.standard6x6;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 26, 200, 350, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 17, 350, 550, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 12, 550, 800, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 10, 800, 10000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 10, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+
+ return ret;
+
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.35f;
+ }
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SudokuTypes.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SudokuTypes.java
new file mode 100644
index 00000000..174ddeab
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/SudokuTypes.java
@@ -0,0 +1,109 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+/**
+ * Dieses Enum definiert die verfügbaren Sudoku-Sorten.
+ */
+public enum SudokuTypes {
+ /** Attributes */
+
+ /**
+ * Ein Standard-Sudoku.
+ */
+ standard9x9,
+
+ /**
+ * Ein 4x4 Sudoku mit normalen Regeln.
+ */
+ standard4x4,
+ /**
+ * Ein 6x6 Sudoku mit normalen Regeln.
+ */
+ standard6x6,
+ /**
+ * Ein 16x16 Sudoku mit normalen Regeln.
+ */
+ standard16x16,
+
+ /**
+ * Fünf 9x9 Sudokus wobei sich je 4 einen Eckblock mit dem 5. zentralen
+ * Sudoku teilen
+ */
+ samurai,
+
+ /**
+ * Ein 9x9 Sudoku bei dem zusätzlich die Diagonalen mit 9 verschiedenen
+ * Symbolen gefüllt werden müssen.
+ */
+ Xsudoku,
+
+ /**
+ * Ein StandardSudoku bei dem zusätzlich folgende Constraints erfüllt sein
+ * müssen:
+ *
+ * .........
+ * .AAA.BBB.
+ * .AAA.BBB.
+ * .AAA.BBB.
+ * .........
+ * .CCC.DDD.
+ * .CCC.DDD.
+ * .CCC.DDD.
+ * .........
+ *
+ */
+ HyperSudoku,
+
+ /**
+ * Ein 9x9 Sudoku mit folgender Constraintbelegung:
+ *
+ * AA BBBBB CC
+ * AAA BBB CCC
+ * D AAA B CCC E
+ * DD A FFF C EE
+ * DDD FFF EEE
+ * DD G FFF H EE
+ * D GGG I HHH E
+ * GGG III HHH
+ * GG IIIII HH
+ *
+ */
+ squigglya,
+ /**
+ * Ein 9x9 Sudoku mit folgender Constraintbelegung:
+ *
+ * aaaaa bbbb
+ * aa cccc s bb
+ * a ccz # c ss b
+ * a zzz # cc s b
+ * g z ##### s b
+ * g z oo # sss i
+ * g zz o # s oo i
+ * gg z oooo ii
+ * gggg iiiii
+ *
+ */
+ squigglyb,
+ /**
+ * Ein 9x9 Sudoku mit folgender Constraintbelegung:
+ *
+ * aaaa bbb cc
+ * aaa bbb ccc
+ * aa bbb cccc
+ * dddd eee ff
+ * ddd eee fff
+ * dd eee ffff
+ * gggg hhh ii
+ * ggg hhh iii
+ * gg hhh iiii
+ *
+ */
+ stairstep;
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeBasic.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeBasic.java
new file mode 100644
index 00000000..5970f33e
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeBasic.java
@@ -0,0 +1,205 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+import de.sudoq.model.sudoku.complexity.ComplexityFactory;
+
+/**
+ * Ein SudokuType repräsentiert die Eigenschaften eines spezifischen Sudoku-Typs. Dazu gehören insbesondere die
+ * Constraints, die einen Sudoku-Typ beschreiben.
+ */
+public abstract class TypeBasic implements Iterable, ComplexityFactory {
+ /** Attributes */
+
+ /**
+ * Ein Positionobjekt das in seinen Koordinaten die Anzahl an Spalten und Zeilen hält
+ */
+ protected Position dimensions;
+
+ /**
+ * Ein Positionobjekt das in seinen Koordinaten die Anzahl an Spalten und Zeilen in einem Block hält
+ */
+ protected Position blockDimensions;
+
+ /**
+ * Die Anzahl von Symbolen die in die Felder eines Sudokus dieses Typs eingetragen werden können.
+ */
+ private int numberOfSymbols;
+
+ /**
+ * Die Liste der Constraints, die diesen Sudoku-Typ beschreiben
+ */
+ protected List constraints;
+
+ /**
+ * Ein Positionarray das alle Positionen hält
+ */
+ protected Position[][] positionsGrid;
+
+ /**
+ * die maximale Kantenlänge des Sudokus
+ */
+ protected int length;
+
+ /**
+ * eine List die zulässige Transformationen am Sudokutyp hält
+ */
+ protected List permutationProperties;
+
+ /**
+ * Konstruktor für einen SudokuTyp
+ *
+ * @param length
+ * die maximale Kantenlänge des SudokuTyps
+ * @param numberOfSymbols
+ * die Anzahl an Symbolen die dieses Sudoku verwendet
+ */
+ public TypeBasic(int length, int numberOfSymbols) {
+ if (numberOfSymbols < 0)
+ throw new IllegalArgumentException("Number of symbols < 0 : " + numberOfSymbols);
+ if (length < 0)
+ throw new IllegalArgumentException("Sudoku length < 0 : " + length);
+ this.length = length;
+ this.numberOfSymbols = numberOfSymbols;
+ dimensions = Position.get(length, length);
+ constraints = new ArrayList();
+ positionsGrid = new Position[length][length];
+ // füllen
+ for (int i = 0; i < length; i++) {
+ for (int j = 0; j < length; j++) {
+ positionsGrid[i][j] = Position.get(i, j);
+ }
+ }
+
+ permutationProperties = new ArrayList();
+ }
+
+ /** Methods */
+
+ /**
+ * Gibt die Größe eines Sudokus dieses Typs zurück. Die Größe wird durch ein Position-Objekt repräsentiert, wobei
+ * die x-Koordinate die maximale Anzahl horizontaler Felder eines Sudokus dieses Typs beschreibt, die y-Koordinaten
+ * die maximale Anzahl vertikaler Felder.
+ *
+ * @return Ein Position-Objekt, welches die maximale Anzahl horizontaler bzw. vertikaler Felder eines Sudokus dieses
+ * Typs beschreibt
+ */
+ public Position getSize() {
+ return dimensions;
+ }
+
+ /**
+ * Gibt die Größe des oberen linken Blocks eines Sudokus dieses Typs zurück. Die Größe wird durch ein
+ * Position-Objekt repräsentiert, wobei die x-Koordinate die maximale Anzahl horizontaler Felder eines Sudoku-Blocks
+ * dieses Typs beschreibt, die y-Koordinaten die maximale Anzahl vertikaler Felder.
+ *
+ * @return Ein Position-Objekt, welches die maximale Anzahl horizontaler bzw. vertikaler Felder des oberen linken
+ * Blocks eines Sudokus dieses Typs beschreibt
+ */
+ public Position getBlockSize() {
+ return blockDimensions;
+ }
+
+ /**
+ * Gibt eine Liste mit zulässigen Transformationen an diesem Sudoku aus.
+ *
+ * @return eine Liste mit zulässigen Transformationen an diesem Sudoku
+ */
+ public List getPermutationProperties() {
+ return permutationProperties;
+ }
+
+ /**
+ * Überprüft, ob das spezifizierte Sudoku die Vorgaben aller Constraints dieses SudokuTyps erfüllt. Ist dies der
+ * Fall, so wir true zurückgegeben. Erfüllt es die Vorgaben nicht, oder wird null übergeben, so wird false
+ * zurückgegeben.
+ *
+ * @param sudoku
+ * Das Sudoku, welches auf Erfüllung der Constraints überprüft werden soll
+ * @return true, falls das Sudoku alle Constraints erfüllt, false falls es dies nicht tut oder null ist
+ */
+ public boolean checkSudoku(Sudoku sudoku) {
+ if (sudoku == null)
+ return false;
+
+ boolean allSaturated = true;
+
+ for (int i = 0; i < this.constraints.size(); i++) {
+ if (!this.constraints.get(i).isSaturated(sudoku))
+ allSaturated = false;
+ }
+
+ return allSaturated;
+ }
+
+ /**
+ * Gibt einen Iterator für die Constraints dieses Sudoku-Typs zurück.
+ *
+ * @return Einen Iterator für die Constraints dieses Sudoku-Typs
+ */
+ public Iterator iterator() {
+ return constraints.iterator();
+ }
+
+ /**
+ * Gibt die Anzahl der Symbole eines Sudokus dieses Typs zurück.
+ *
+ * @return Die Anzahl der Symbole in einem Sudoku dieses Typs
+ */
+ public int getNumberOfSymbols() {
+ return this.numberOfSymbols;
+ }
+
+ /**
+ * Gibt den Sudoku-Typ als Enum zurück.
+ *
+ * @return Sudoku-Typ als Enum
+ */
+ public abstract SudokuTypes getEnumType();
+
+ /**
+ * Gibt einen ComplexityContraint für eine Schwierigkeit complexity zurück.
+ *
+ * @param complexity
+ * eine Schwierigkeit zu der ein ComplexityConstraint erzeugt werden soll
+ */
+ public abstract ComplexityConstraint buildComplexityConstraint(Complexity complexity);
+
+ /**
+ * Gibt den Standard Belegungsfaktor zurück
+ */
+ public abstract float getStandardAllocationFactor();
+
+ /**
+ * Gibt den Sudoku-Typ als String zurück.
+ *
+ * @return Sudoku-Typ als String
+ */
+ public String toString() {
+ return getEnumType().toString();
+ }
+
+ /**
+ * Gibt eine Liste der Constraints, welche zu diesem Sudokutyp gehören zurück. Hinweis: Wenn möglich stattdessen den
+ * Iterator benutzen.
+ *
+ * @return Eine Liste der Constraints dieses Sudokutyps.
+ */
+ public ArrayList getConstraints() {
+ return (ArrayList) this.constraints;
+ }
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeSquiggly.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeSquiggly.java
new file mode 100644
index 00000000..b38a170f
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeSquiggly.java
@@ -0,0 +1,87 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.ConstraintBehavior;
+import de.sudoq.model.sudoku.ConstraintType;
+import de.sudoq.model.sudoku.UniqueConstraintBehavior;
+
+public abstract class TypeSquiggly extends TypeUniversal {
+
+ /**
+ * Konstruktor zum weitervererben
+ *
+ * @param length
+ * die maximale Ausdehnung des Sudokutyps
+ * @param numberOfSymbols
+ * die maximale Anzahl an Symbolen
+ */
+ public TypeSquiggly(int length, int numberOfSymbols) {
+ super(length, numberOfSymbols);
+ addRowConstraints(new UniqueConstraintBehavior());
+ addCollumnConstraints(new UniqueConstraintBehavior());
+ }
+
+ /**
+ * Instanziiert einen neuen SquigglySudokuType. Die Constraints des erzeugten Typs haben ein
+ * UniqueConstraintBehavior und entsprechen den Zeilen, Spalten und Blöcken des Standard-Sudokus. Die Blöcke haben
+ * durch ein Pattern definierte Umrisse
+ *
+ * @param constraintPattern
+ * Ein constraintPattern für die Blöcke.
+ *
+ */
+ public TypeSquiggly(String constraintPattern) {
+ super((int) Math.sqrt(constraintPattern.length() + 0.0), (int) Math.sqrt(constraintPattern.length() + 0.0));
+
+ addRowConstraints(new UniqueConstraintBehavior());
+ addCollumnConstraints(new UniqueConstraintBehavior());
+
+ addBlockConstraints(constraintPattern, new UniqueConstraintBehavior());
+
+ }
+
+ /**
+ * Erzeugt die Zeilen-Constraints
+ *
+ * @param constraintBehavior
+ * Constraintverhalten für alle Constraints
+ * @throws IllegalArgumentException
+ * falls constraintBehavior null ist
+ */
+ private void addRowConstraints(ConstraintBehavior constraintBehavior) {
+
+ for (int j = 0; j < length; j++) {
+ Constraint c = new Constraint(constraintBehavior, ConstraintType.LINE, "Row " + j);
+ for (int i = 0; i < length; i++) {
+ c.addPosition(positionsGrid[i][j]);
+ }
+ constraints.add(c);
+ }
+ }
+
+ /**
+ * Erzeugt die Spalten-Constraints
+ *
+ * @param constraintBehavior
+ * Constraintverhalten für alle Constraints
+ * @throws IllegalArgumentException
+ * falls constraintBehavior null ist
+ */
+ private void addCollumnConstraints(ConstraintBehavior constraintBehavior) {
+
+ for (int i = 0; i < length; i++) {
+ Constraint c = new Constraint(constraintBehavior, ConstraintType.LINE, "Column " + i);
+ for (int j = 0; j < length; j++) {
+ c.addPosition(positionsGrid[i][j]);
+ }
+ constraints.add(c);
+ }
+ }
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeStandard.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeStandard.java
new file mode 100644
index 00000000..61375f56
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeStandard.java
@@ -0,0 +1,78 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.ConstraintType;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.UniqueConstraintBehavior;
+
+public abstract class TypeStandard extends TypeSquiggly {
+
+ /**
+ * Instanziiert einen neuen StandardSudokuType. Die Constraints des erzeugten Typs haben ein
+ * UniqueConstraintBehavior und entsprechen den Zeilen, Spalten und Blöcken des Standard-Sudokus.
+ *
+ * @param length
+ * die Seitenlänge des Sudokus
+ */
+ public TypeStandard(int length) {
+ super(length, length);
+ blockDimensions = getBlockDimensions(length);
+ addBlockConstraints();
+ initialisePermutationProperties();
+ }
+
+ private void initialisePermutationProperties() {
+ permutationProperties.add(PermutationProperties.rotate90);
+ permutationProperties.add(PermutationProperties.rotate180);
+ permutationProperties.add(PermutationProperties.horizontal_Blockshift);
+ permutationProperties.add(PermutationProperties.vertical_Blockshift);
+ permutationProperties.add(PermutationProperties.inBlock_Collumnshift);
+ permutationProperties.add(PermutationProperties.inBlock_Rowshift);
+ permutationProperties.add(PermutationProperties.diagonal_up);
+ permutationProperties.add(PermutationProperties.diagonal_down);
+ permutationProperties.add(PermutationProperties.mirror_horizontal);
+ permutationProperties.add(PermutationProperties.mirror_vertical);
+ }
+
+ /**
+ * Fügt BlockConstraints hinzu. Sind n Felder in einer Zeile, so werden n Blöcke zu je n Elementen hinzugefügt. Ist
+ * n keine Quadratzahl so sind die Blöcke breiter als hoch und dabei so quadratisch wie möglich.
+ */
+ protected void addBlockConstraints() {
+ int length = positionsGrid.length;
+
+ int blockheight = blockDimensions.getY();
+ int blockwidth = blockDimensions.getX();
+
+ for (int i = 0; i < length; i++) {// Blöcke
+ Constraint c = new Constraint(new UniqueConstraintBehavior(), ConstraintType.BLOCK, "Block " + i);
+ for (int j = 0; j < length; j++) {// Elemente
+
+ c.addPosition(positionsGrid[i % blockheight * blockwidth + j % blockwidth][i / blockheight
+ * blockheight + j / blockwidth]);
+ }
+ constraints.add(c);
+ }
+ }
+
+ /**
+ * Errechnet aus der Länge des Sudokus die Abmessungen der Blöcke wobei die Differenz aus Höhe und Breite der Blöcke
+ * so klein wie möglich gehalten wird. Es gilt Breite >= Höhe
+ */
+ protected Position getBlockDimensions(int length) {
+ int y = (int) Math.sqrt(length + 0.0);
+ while (length / y * y != length)
+ y--;
+ int x = length / y;
+
+ return Position.get(x, y);
+ }
+
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeUniversal.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeUniversal.java
new file mode 100644
index 00000000..69feb0c5
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/TypeUniversal.java
@@ -0,0 +1,139 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import java.util.Map;
+
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.ConstraintBehavior;
+import de.sudoq.model.sudoku.ConstraintType;
+
+public abstract class TypeUniversal extends TypeBasic {
+
+ /**
+ * Konstruktor zum weitervererben
+ *
+ * @param length
+ * die maximale Ausdehnung des Sudokutyps
+ * @param numberOfSymbols
+ * die maximale Anzahl an Symbolen
+ */
+ public TypeUniversal(int length, int numberOfSymbols) {
+ super(length, numberOfSymbols);
+ }
+
+ /**
+ * Instanziiert einen universellen SudokuTyp. Die Constraints des erzeugten Typs werden durch constraintPattern
+ * festgelegt: Sich nicht überschneidende Constraints gleichen behaviors werden in einem String durch jeweils
+ * gleiche chars gekennzeichnet. Achtung: '.' kennzeichnet die Zugehörigkeit zu keinem Constraint. '\' ist der
+ * Escape-char von Java und sollte nicht verwendet werden. Bsp. für 4x4 Sudoku: pattern1= "aaaa" +"bbbb" +"cccc"
+ * +"dddd"
+ *
+ * pattern2= "abcd" <- chars wiederverwenden geht wird aber +"abcd" nicht empfohlen, da nun in +"abcd" 8 Constraints
+ * je 2 den gleichennamen haben(blöd beim Testen). +"abcd"
+ *
+ * pattern3= "eeff" +"eeff" +"gg.." +"gg.."
+ *
+ * pattern4= "...." +"...." +"..hh" +"..hh"
+ *
+ * Wann immer möglich sollte eine mathematische Zuordnung der Constraints den Pattern vorgezogen werden.
+ *
+ * @param lenght
+ * Länge des Sudokus
+ * @param numberOfSymbols
+ * Anzahl vorkommender Symbole
+ * @param constraintPatterns
+ * Map mit Constraintpattern und zugehörigem behavior.
+ *
+ */
+ public TypeUniversal(int lenght, int numberOfSymbols, Map constraintPatterns) {
+ super(lenght, numberOfSymbols);
+
+ if (!validCollection(constraintPatterns))
+ throw new IllegalArgumentException("constraintPatterns not valid");
+
+ for (Map.Entry e : constraintPatterns.entrySet()) {
+ addBlockConstraints(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * Setzt ein constraintPattern mit dediziertem behavior in Constraints um.
+ *
+ * @param constraintPattern
+ * ein ConstraintPattern
+ * @param constraintBehavior
+ * das zugehörige Behavior
+ */
+ protected void addBlockConstraints(String constraintPattern, ConstraintBehavior constraintBehavior) {
+ if (constraintPattern == null || constraintBehavior == null)
+ throw new IllegalArgumentException();
+ if (constraintPattern.length() != dimensions.getX() * dimensions.getX())
+ throw new IllegalArgumentException("arg constraintPattern has wrong size.");
+
+ for (char s : extractSymbols(constraintPattern)) {// für jeden Constraint
+ if (s != '.') {
+ addExtraConstraint(constraintPattern, s, constraintBehavior);
+ }
+ }
+ }
+
+ /**
+ * extrahiert alle im String vorkommenden Symbole und gibt sie als char-Array zurück.
+ */
+ private char[] extractSymbols(String constraintPattern) {
+
+ String symbols = "";
+ for (char c : constraintPattern.toCharArray())
+ if (!symbols.contains("" + c))
+ symbols += c;
+ return symbols.toCharArray();
+ }
+
+ /**
+ * Erzeugt einen neuen Constraint aus einem String.
+ *
+ * @param constraintPattern
+ * Ein String der die Information über die Positionen des Constraints enthält.
+ * @param signChar
+ * char der die Zugehörigkeit zum Constraint kennzeichnet. Alle anderen werden igroriert.
+ * @param constraintBehavior
+ * das ConstraintBehavior des neuen Constraints.
+ * @throws IllegalArgumentException
+ * wenn das constraintPattern nicht die richtige Länge hat oder constraintBehavior null ist.
+ */
+ protected void addExtraConstraint(String constraintPattern, char signChar, ConstraintBehavior constraintBehavior) {
+ if (constraintPattern == null || constraintBehavior == null)
+ throw new IllegalArgumentException();
+ if (constraintPattern.length() != dimensions.getX() * dimensions.getX())
+ throw new IllegalArgumentException("arg constraintPattern has wrong size.");
+
+ Constraint c = new Constraint(constraintBehavior, ConstraintType.BLOCK, "Block " + signChar);
+
+ for (int i = 0; i < constraintPattern.length(); i++) {// Positionen
+ // suchen
+ if (constraintPattern.charAt(i) == signChar) {
+ c.addPosition(positionsGrid[i % positionsGrid.length][i / positionsGrid.length]);
+ }
+ }
+ constraints.add(c);
+ }
+
+ private boolean validCollection(Map col) {
+
+ if (col == null)
+ return false;
+
+ for (Map.Entry e : col.entrySet()) {
+ if (e.getKey() == null || e.getKey().length() != Math.pow(length + 0.0, 2.0) || e.getValue() == null)
+ return false;
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/XSudoku.java b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/XSudoku.java
new file mode 100644
index 00000000..dff2f9d3
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/sudoku/sudokuTypes/XSudoku.java
@@ -0,0 +1,102 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.sudoku.sudokuTypes;
+
+import de.sudoq.model.sudoku.Constraint;
+import de.sudoq.model.sudoku.ConstraintType;
+import de.sudoq.model.sudoku.Position;
+import de.sudoq.model.sudoku.UniqueConstraintBehavior;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.complexity.ComplexityConstraint;
+
+/**
+ * Erzeugt ein StandardSudokuType der Größe 9x9 bei dem zusätzlich die Diagonalen ein UniqueConstraintBehaviour erfüllen
+ * müssen
+ *
+ */
+public class XSudoku extends TypeStandard {
+
+ /**
+ * Erzeugt einen neuen XSudokutyp
+ */
+ public XSudoku() {
+ super(9);
+ addXConstraints(positionsGrid);
+ permutationProperties.remove(PermutationProperties.horizontal_Blockshift);
+ permutationProperties.remove(PermutationProperties.vertical_Blockshift);
+ permutationProperties.remove(PermutationProperties.inBlock_Collumnshift);
+ permutationProperties.remove(PermutationProperties.inBlock_Rowshift);
+ }
+
+ /**
+ * fügt Constraints für die Diagonalen hinzu
+ *
+ * @param positionsGrid
+ * das Array dem die Positions entnommen werden
+ */
+ protected void addXConstraints(Position[][] positionsGrid) {
+ int length = positionsGrid.length;
+ Constraint c1 = new Constraint(new UniqueConstraintBehavior(), ConstraintType.EXTRA,
+ "Extra block diagonal down right");
+ Constraint c2 = new Constraint(new UniqueConstraintBehavior(), ConstraintType.EXTRA,
+ "Extra block diagonal up right");
+
+ for (int i = 0; i < 9; i++) {
+ c1.addPosition(positionsGrid[i][i]);
+ c2.addPosition(positionsGrid[i][length - 1 - i]);
+ }
+
+ constraints.add(c1);
+ constraints.add(c2);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public SudokuTypes getEnumType() {
+ return SudokuTypes.Xsudoku;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ComplexityConstraint buildComplexityConstraint(Complexity complexity) {
+ ComplexityConstraint ret = null;
+
+ if (complexity != null) {
+ switch (complexity) {
+ case easy:
+ ret = new ComplexityConstraint(Complexity.easy, 40, 450, 750, 2);
+ break;
+ case medium:
+ ret = new ComplexityConstraint(Complexity.medium, 32, 700, 1050, 3);
+ break;
+ case difficult:
+ ret = new ComplexityConstraint(Complexity.difficult, 28, 1000, 2500, Integer.MAX_VALUE);
+ break;
+ case infernal:
+ ret = new ComplexityConstraint(Complexity.infernal, 27, 2500, 25000, Integer.MAX_VALUE);
+ break;
+ case arbitrary:
+ ret = new ComplexityConstraint(Complexity.arbitrary, 32, 1, Integer.MAX_VALUE, Integer.MAX_VALUE);
+ break;
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float getStandardAllocationFactor() {
+ return 0.25f;
+ }
+}
\ No newline at end of file
diff --git a/sudoq-model/src/de/sudoq/model/xml/GameXmlHandler.java b/sudoq-model/src/de/sudoq/model/xml/GameXmlHandler.java
new file mode 100644
index 00000000..307be4da
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/xml/GameXmlHandler.java
@@ -0,0 +1,48 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.xml;
+
+import java.io.File;
+
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.game.Game;
+
+/**
+ * Eine Klasse um konkret Games aus Xml zu bekommen bzw in Xml umzuwandeln
+ */
+public class GameXmlHandler extends XmlHandler {
+
+ private int id;
+
+ /**
+ * Erzeugt einen GameXmlHandler um ein Game zu speichern
+ */
+ public GameXmlHandler() {
+ this(-1);
+ }
+
+ /**
+ * Erzeugt einen GameXmlHandler, der auf das Game mit der gegebenen ID
+ * schreibt und liest.
+ *
+ * @param loadingId
+ * die id des zu aendernden/erstellenden games
+ */
+ public GameXmlHandler(int loadingId) {
+ this.id = loadingId;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected File getFileFor(Game g) {
+ return FileManager.getGameFile(id > 0 ? id : g.getId());
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/xml/ProfileXmlHandler.java b/sudoq-model/src/de/sudoq/model/xml/ProfileXmlHandler.java
new file mode 100644
index 00000000..511a2277
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/xml/ProfileXmlHandler.java
@@ -0,0 +1,28 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.xml;
+
+import java.io.File;
+
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.profile.Profile;
+
+/**
+ * Der konkrete XmlHandler für Profile
+ */
+public class ProfileXmlHandler extends XmlHandler {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected File getFileFor(Profile obj) {
+ return FileManager.getProfileXmlFor(obj.getCurrentProfileID());
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/xml/SudokuXmlHandler.java b/sudoq-model/src/de/sudoq/model/xml/SudokuXmlHandler.java
new file mode 100644
index 00000000..cae3f6fd
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/xml/SudokuXmlHandler.java
@@ -0,0 +1,65 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.xml;
+
+import java.io.File;
+
+import de.sudoq.model.files.FileManager;
+import de.sudoq.model.sudoku.Sudoku;
+import de.sudoq.model.sudoku.complexity.Complexity;
+import de.sudoq.model.sudoku.sudokuTypes.SudokuTypes;
+
+/**
+ * Der XmlHandler zum Laden und Speichern von Sudokus
+ */
+public class SudokuXmlHandler extends XmlHandler {
+
+ private Complexity complexity;
+ private SudokuTypes type;
+
+ /**
+ * Erzeugt einen SudokuXmlHandler, der ein neues sudoku file anlegt
+ */
+ public SudokuXmlHandler() {
+ this(null, null);
+ }
+
+ /**
+ * Erzeugt einen SudokuXmlHandler zum Laden eines zufälligen Sudokus mit den
+ * gegebenen Parametern
+ *
+ * @param type
+ * der Typ des zu ladenden Sudokus
+ * @param complexity
+ * die Schwierigkeit des zu ladenden Sudokus
+ */
+ public SudokuXmlHandler(SudokuTypes type, Complexity complexity) {
+ this.type = type;
+ this.complexity = complexity;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected File getFileFor(Sudoku s) {
+ if (type != null && complexity != null) {
+ return FileManager.getRandomSudoku(type, complexity);
+ } else if (s.getId() <= 0) {
+ return FileManager.getNewSudokuFile(s);
+ } else {
+ return FileManager.getSudokuFile(s);
+ }
+ }
+
+ @Override
+ protected void modifySaveTree(XmlTree tree) {
+ tree.addAttribute(new XmlAttribute("id", file.getName().substring(7, file.getName().length() - 4)));
+ }
+
+}
diff --git a/sudoq-model/src/de/sudoq/model/xml/XmlAttribute.java b/sudoq-model/src/de/sudoq/model/xml/XmlAttribute.java
new file mode 100644
index 00000000..672c2f4d
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/xml/XmlAttribute.java
@@ -0,0 +1,98 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.xml;
+
+/**
+ * Diese Klasse repräsentiert ein Attribut eines Xml Baumes
+ *
+ * @see XmlTree
+ */
+public class XmlAttribute {
+
+ /** Attributes */
+
+ /**
+ * Name des Attributes
+ */
+ private String name;
+
+ /**
+ * Wert des Xml Attributes
+ */
+ private String value;
+
+ /** Constructors */
+
+ /**
+ * Dieser Konstruktor initialisiert ein neues Attribut mit gegebenem Wert.
+ *
+ * @param name
+ * Name des Attributes
+ * @param value
+ * Wert des Attributes
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls einer der übergebenen Strings null oder
+ * der name leer ist
+ */
+ public XmlAttribute(String name, String value) throws IllegalArgumentException {
+ if (name == null || name.equals("") || value == null) {
+ throw new IllegalArgumentException();
+ }
+ this.name = name;
+ this.value = value;
+ }
+
+ /** Methods */
+
+ /**
+ * Diese Methode gibt des Namen des Attributes zurück.
+ *
+ * @return String Name des Attributes
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Diese Methode gibt den Wert des Attributes zurück.
+ *
+ * @return String Wert des Attributes
+ */
+ public String getValue() {
+ return value;
+ }
+
+ /**
+ * Setzt falls der Parameter nicht null ist value auf diesen
+ *
+ * @param value
+ * der einzutragende Wert
+ */
+ protected void setValue(String value) {
+ if (value != null) {
+ this.value = value;
+ }
+ }
+
+ /**
+ * Diese Methode prüft ob ein weiteres Attribut des selben Typs ist, also
+ * den gleichen Namen tragen
+ *
+ * @param attribute
+ * Das zu vergleichende Attribut
+ * @return True, wenn beide den selben Namen haben, sonst false
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Attribut null ist
+ */
+ public boolean isSameAttribute(XmlAttribute attribute) throws IllegalArgumentException {
+ if (attribute == null) {
+ throw new IllegalArgumentException();
+ }
+ return ((XmlAttribute) attribute).getName().equals(name);
+ }
+}
diff --git a/sudoq-model/src/de/sudoq/model/xml/XmlHandler.java b/sudoq-model/src/de/sudoq/model/xml/XmlHandler.java
new file mode 100644
index 00000000..4ba22838
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/xml/XmlHandler.java
@@ -0,0 +1,98 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.xml;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * Diese Generische Klasse dient zur Handhabung der XML Repräsentation von
+ * Objekten, die das Xmlable Interface implementieren.
+ *
+ * @param
+ * der Typ der konkret umgewandelt werden soll
+ */
+public abstract class XmlHandler {
+
+ /** Attributes */
+
+ /**
+ * Helfer für das Speichern und Laden von XML Dateien
+ */
+ private XmlHelper helper;
+
+ protected File file;
+
+ /** Constructors */
+
+ /**
+ * Dieser Konstruktor initialisiert einen neuen XmlHandler.
+ */
+ public XmlHandler() {
+ helper = new XmlHelper();
+ }
+
+ /** Methods */
+
+ /**
+ * Speichert ein übegebenes Objekt, das das Xmlable Interface implementiert,
+ * in eine XML Datei.
+ *
+ * @param obj
+ * Objekt, das Xmlable implementiert
+ * @see Xmlable
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Objekt null ist
+ */
+ public void saveAsXml(T obj) {
+ try {
+ file = getFileFor(obj);
+ XmlTree tree = obj.toXmlTree();
+ modifySaveTree(tree);
+ helper.saveXml(tree, file);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Something went wrong when writing xml", e);
+ }
+ }
+
+ /**
+ * Lädt ein Objekt, das Xmlable implementiert, aus einer XML Datei.
+ *
+ * @param obj
+ * leeres Objekt, das Xmlable implementiert
+ * @return Objekt, welches Xmlable implementiert
+ * @see Xmlable
+ */
+ public T createObjectFromXml(T obj) {
+ try {
+ obj.fillFromXml(helper.loadXml(getFileFor(obj)));
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Something went wrong when reading xml " + getFileFor(obj), e);
+ }
+ return obj;
+ }
+
+ /**
+ * Lässt Subklassen den XMLTree falls nötig anpassen
+ *
+ * @param tree
+ * der Ursprüngliche Baum
+ */
+ protected void modifySaveTree(XmlTree tree) {
+ }
+
+ /**
+ * Gibt ein File welches auf den Speicherort des gegebenen Objektes zeigt
+ * zurueck
+ *
+ * @param obj
+ * das zu speichernde/ladende Objekt
+ * @return das darauf zeigende File
+ */
+ abstract protected File getFileFor(T obj);
+}
diff --git a/sudoq-model/src/de/sudoq/model/xml/XmlHelper.java b/sudoq-model/src/de/sudoq/model/xml/XmlHelper.java
new file mode 100644
index 00000000..becc8979
--- /dev/null
+++ b/sudoq-model/src/de/sudoq/model/xml/XmlHelper.java
@@ -0,0 +1,268 @@
+/*
+ * SudoQ is a Sudoku-App for Adroid Devices with Version 2.2 at least.
+ * Copyright (C) 2012 Haiko Klare, Julian Geppert, Jan-Bernhard Kordaß, Jonathan Kieling, Tim Zeitz, Timo Abele
+ * This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License along with this program; if not, see .
+ */
+package de.sudoq.model.xml;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.util.Iterator;
+import java.util.Stack;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLReaderFactory;
+
+/**
+ * Dies ist eine Helfer-Klasse, die das Laden und Speichern von XmlTree Objekten
+ * in Xml Dateien ermöglicht.
+ *
+ * @see XmlTree
+ */
+public class XmlHelper {
+
+ /** Attributes */
+
+ /**
+ * Unterstützte Typen von Xml Dateien
+ */
+ private final String[] SUPPORTEDDTDS = { "sudoku", "game", "games", "profile", "profiles" };
+
+ /**
+ * Prämbel für geschriebene Xml Dateien
+ */
+ private final String XmlPREAMBLE = "\n";
+
+ /**
+ * Systempfad, an dem die DTD Spezifikationen hinterlegt wurden
+ */
+ private final String XmlDTDPATH = "./";
+
+ /**
+ * Wurzel einer eingelesenen Xml Baumstruktur
+ */
+ private XmlTree xmlReadTreeRoot;
+
+ /**
+ * Stack für das Einlesen von Xml Dateien, speichert derzeitige
+ * Hierarchietiefe
+ */
+ private Stack xmlReadStack;
+
+ /** Methods */
+
+ /**
+ * Diese Methode lädt den Inhalt einer Xml Datei in ein XmlTree Objekt.
+ *
+ * @param xmlFile
+ * Xml Datei aus der gelesen werden soll
+ * @return Xml Baum der eingelesenen Datei
+ * @see XmlTree
+ * @throws FileNotFoundException
+ * Wird geworfen, falls die spezifizierte Datei nicht existiert
+ * @throws IllegalArgumentException
+ * Wird geworfen, falls das übergebene Argument null ist
+ * @throws IOException
+ * Wird geworfen, wenn Probleme beim Lesen der Datei auftraten
+ * oder z.B. die Xml Datei kompromittiert ist
+ */
+ public XmlTree loadXml(File xmlFile) throws FileNotFoundException, IllegalArgumentException, IOException {
+ if (xmlFile == null) {
+ throw new IllegalArgumentException();
+ }
+ if (!xmlFile.exists()) {
+ throw new FileNotFoundException();
+ }
+ return readXmlTree(new InputSource(xmlFile.getAbsolutePath()));
+ }
+
+ /**
+ * Diese Methode generiert einen Xml-Baum aus einem String, der eine valide
+ * Struktur besitzt.
+ *
+ * @param structure
+ * Xml-Baum in einer String Repaesentation
+ * @return XmlTree Repraesentation der Xml Struktur
+ * @throws IllegalArgumentException
+ * Wird geworfen, wenn der gegebene Xml String eine invalide
+ * Struktur aufweist.
+ */
+ // public XmlTree buildXmlTree(String structure) throws
+ // IllegalArgumentException {
+ // try {
+ // return readXmlTree(new InputSource(new StringReader(structure)));
+ // } catch (IOException exc) {
+ // throw new IllegalArgumentException();
+ // }
+ // }
+
+ /**
+ * Bereitet das Lesen einer Xml Quelle zu einem XmlTree Objekt vor und
+ * fuehrt diese Operation aus.
+ */
+ private XmlTree readXmlTree(InputSource input) throws IllegalArgumentException, IOException {
+ XMLReader xr;
+ xmlReadTreeRoot = null;
+ xmlReadStack = new Stack