diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..50282c1
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Android
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/app.iml b/app/app.iml
index bc02165..44f924e 100644
--- a/app/app.iml
+++ b/app/app.iml
@@ -9,7 +9,6 @@
-
@@ -47,7 +46,6 @@
-
@@ -55,7 +53,6 @@
-
@@ -63,43 +60,26 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -109,12 +89,12 @@
-
+
diff --git a/app/build.gradle b/app/build.gradle
index c1375be..87e81d7 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -2,7 +2,7 @@ apply plugin: 'com.android.application'
android {
compileSdkVersion 25
- buildToolsVersion '24.0.1'
+ buildToolsVersion '25.0.0'
testOptions {
unitTests.returnDefaultValues = true
@@ -12,8 +12,8 @@ android {
applicationId "org.secuso.privacyfriendlysudoku"
minSdkVersion 16
targetSdkVersion 25
- versionCode 3
- versionName "2.0.1"
+ versionCode 4
+ versionName "2.1.1"
}
buildTypes {
release {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 85f10a2..7a8d93b 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -38,6 +38,10 @@
+
\ No newline at end of file
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GameController.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GameController.java
index 695dc06..8cb12b9 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GameController.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GameController.java
@@ -221,9 +221,44 @@ public class GameController implements IModelChangedListener, Parcelable {
updateList.addAll(gameBoard.getSection(cell.getRow(), cell.getCol()));
deleteNotes(updateList, value);
}
+
+ if(settings != null && settings.getBoolean("pref_highlightInputError",true)) {
+ checkInputError(row, col);
+ }
}
}
+ private void checkInputError(int row, int col) {
+ if(isValidNumber(row+1) && isValidNumber(col+1)) {
+
+ if (errorList == null) {
+ errorList = new CellConflictList();
+ }
+
+ errorList.addAll(checkInputErrorList(gameBoard.getCell(row,col), gameBoard.getRow(row)));
+ errorList.addAll(checkInputErrorList(gameBoard.getCell(row, col), gameBoard.getColumn(col)));
+ errorList.addAll(checkInputErrorList(gameBoard.getCell(row, col), gameBoard.getSection(row, col)));
+ }
+ }
+
+
+ private CellConflictList checkInputErrorList(GameCell cell, List list) {
+ CellConflictList errorList = new CellConflictList();
+ for (int i = 0; i < list.size(); i++) {
+ GameCell c2 = list.get(i);
+
+ if (!cell.equals(c2) && cell.getValue() != 0 && c2.getValue() != 0) {
+
+ // Same value in one set should not exist
+ if (cell.getValue() == c2.getValue()) {
+ // we found an error..
+ errorList.add(new CellConflict(cell, c2));
+ }
+ }
+ }
+ return errorList;
+ }
+
public LinkedList getConnectedCells(int row, int col) {
LinkedList list = new LinkedList<>();
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GameStateManager.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GameStateManager.java
index 64db4e8..bebec31 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GameStateManager.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GameStateManager.java
@@ -203,6 +203,5 @@ public class GameStateManager {
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("savesChanged", true);
editor.commit();
-
}
}
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GeneratorService.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GeneratorService.java
new file mode 100644
index 0000000..8fb7363
--- /dev/null
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/GeneratorService.java
@@ -0,0 +1,309 @@
+package org.secuso.privacyfriendlysudoku.controller;
+
+import android.app.IntentService;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.IBinder;
+import android.support.annotation.IntDef;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.NotificationCompat;
+import android.util.Log;
+import android.util.Pair;
+
+import org.secuso.privacyfriendlysudoku.controller.database.DatabaseHelper;
+import org.secuso.privacyfriendlysudoku.controller.database.model.Level;
+import org.secuso.privacyfriendlysudoku.controller.qqwing.Action;
+import org.secuso.privacyfriendlysudoku.controller.qqwing.PrintStyle;
+import org.secuso.privacyfriendlysudoku.controller.qqwing.QQWing;
+import org.secuso.privacyfriendlysudoku.controller.qqwing.Symmetry;
+import org.secuso.privacyfriendlysudoku.game.GameBoard;
+import org.secuso.privacyfriendlysudoku.game.GameDifficulty;
+import org.secuso.privacyfriendlysudoku.game.GameType;
+import org.secuso.privacyfriendlysudoku.ui.MainActivity;
+import org.secuso.privacyfriendlysudoku.ui.view.R;
+
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static android.app.PendingIntent.FLAG_UPDATE_CURRENT;
+import static org.secuso.privacyfriendlysudoku.controller.NewLevelManager.PRE_SAVES_MIN;
+
+/**
+ *
+ * @author Christopher Beckmann
+ */
+public class GeneratorService extends IntentService {
+
+ private static final String TAG = GeneratorService.class.getSimpleName();
+ public static final String ACTION_GENERATE = TAG + " ACTION_GENERATE";
+ public static final String ACTION_STOP = TAG + " ACTION_STOP";
+ public static final String EXTRA_GAMETYPE = TAG + " EXTRA_GAMETYPE";
+ public static final String EXTRA_DIFFICULTY = TAG + " EXTRA_DIFFICULTY";
+
+ private final QQWingOptions opts = new QQWingOptions();
+
+ private final List> generationList = new LinkedList<>();
+ private final DatabaseHelper dbHelper = new DatabaseHelper(this);
+
+
+ public GeneratorService() {
+ super("Generator Service");
+ }
+
+ private void buildGenerationList() {
+ generationList.clear();
+
+ for(GameType validType : GameType.getValidGameTypes()) {
+ for(GameDifficulty validDifficulty : GameDifficulty.getValidDifficultyList()) {
+ int levelCount = dbHelper.getLevels(validDifficulty, validType).size();
+ Log.d(TAG, "\tType: "+ validType.name() + " Difficulty: " + validDifficulty.name() + "\t: " + levelCount);
+ // add the missing levels to the list
+ for(int i = levelCount; i < PRE_SAVES_MIN; i++) {
+ generationList.add(new Pair<>(validType, validDifficulty));
+ }
+ }
+ }
+
+ // PrintGenerationList
+ Log.d(TAG, "### Missing Levels: ###");
+ int i = 0;
+ for(Pair dataPair : generationList) {
+ Log.d(TAG, "\t" + i++ + ":\tType: "+ dataPair.first.name() + " Difficulty: " + dataPair.second.name());
+ }
+ }
+
+ private void handleGenerationStop() {
+ stopForeground(true);
+ stopSelf();
+ }
+
+ private void handleGenerationStart(Intent intent) {
+ GameType gameType = intent.getParcelableExtra(EXTRA_GAMETYPE);
+ GameDifficulty gameDifficulty = intent.getParcelableExtra(EXTRA_DIFFICULTY);
+
+ if(gameType == null || gameDifficulty == null) {
+ generateLevels();
+ } else {
+ generateLevel(gameType, gameDifficulty);
+ }
+ }
+
+ private void generateLevels() {
+ // if we start this service multiple times while we are already generating...
+ // we ignore this call and just keep generating
+ buildGenerationList();
+
+ // generate from the list
+ if(generationList.size() > 0) {
+
+ // generate 1 level and wait for it to be done.
+ Pair dataPair = generationList.get(0);
+ GameType type = dataPair.first;
+ GameDifficulty diff = dataPair.second;
+
+ generateLevel(type, diff);
+ }
+ }
+
+ private void generateLevel(final GameType gameType, final GameDifficulty gameDifficulty) {
+ showNotification(gameType, gameDifficulty);
+
+ generated.clear();
+ opts.gameDifficulty = gameDifficulty;
+ opts.action = Action.GENERATE;
+ opts.needNow = true;
+ opts.printSolution = false;
+ opts.gameType = gameType;
+ if(gameDifficulty == GameDifficulty.Easy && gameType == GameType.Default_9x9) {
+ opts.symmetry = Symmetry.ROTATE90;
+ } else {
+ opts.symmetry = Symmetry.NONE;
+ }
+ if(gameType == GameType.Default_12x12 && gameDifficulty != GameDifficulty.Challenge) {
+ opts.symmetry = Symmetry.ROTATE90;
+ }
+
+ final AtomicInteger puzzleCount = new AtomicInteger(0);
+ final AtomicBoolean done = new AtomicBoolean(false);
+
+ Runnable generationRunnable = new Runnable() {
+ // Create a new puzzle board
+ // and set the options
+ private QQWing ss = createQQWing();
+
+ private QQWing createQQWing() {
+ QQWing ss = new QQWing(opts.gameType, opts.gameDifficulty);
+ ss.setRecordHistory(opts.printHistory || opts.printInstructions || opts.printStats || opts.gameDifficulty != GameDifficulty.Unspecified);
+ ss.setLogHistory(opts.logHistory);
+ ss.setPrintStyle(opts.printStyle);
+ return ss;
+ }
+
+ @Override
+ public void run() {
+ //android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
+ try {
+
+ // Solve puzzle or generate puzzles
+ // until end of input for solving, or
+ // until we have generated the specified number.
+ while (!done.get()) {
+
+ // Record whether the puzzle was possible or
+ // not,
+ // so that we don't try to solve impossible
+ // givens.
+ boolean havePuzzle;
+ boolean solveImpossible;
+
+ if (opts.action == Action.GENERATE) {
+ // Generate a puzzle
+ havePuzzle = ss.generatePuzzleSymmetry(opts.symmetry);
+
+ } else {
+ // Read the next puzzle on STDIN
+ int[] puzzle = new int[QQWing.BOARD_SIZE];
+ if (getPuzzleToSolve(puzzle)) {
+ havePuzzle = ss.setPuzzle(puzzle);
+ if (havePuzzle) {
+ puzzleCount.getAndDecrement();
+ } else {
+ // Puzzle to solve is impossible.
+ solveImpossible = true;
+ }
+ } else {
+ // Set loop to terminate when nothing is
+ // left on STDIN
+ havePuzzle = false;
+ done.set(true);
+ }
+ puzzle = null;
+ }
+
+ if(opts.gameDifficulty != GameDifficulty.Unspecified) {
+ ss.solve();
+ }
+
+ if (havePuzzle) {
+ // Bail out if it didn't meet the difficulty
+ // standards for generation
+ if (opts.action == Action.GENERATE) {
+
+ // save the level anyways but keep going if the desired level is not yet generated
+ Level level = new Level();
+ level.setGameType(opts.gameType);
+ level.setDifficulty(ss.getDifficulty());
+ level.setPuzzle(ss.getPuzzle());
+ dbHelper.addLevel(level);
+ Log.d(TAG, "Generated: " + level.getGameType().name() + ",\t"+level.getDifficulty().name());
+
+ if (opts.gameDifficulty != GameDifficulty.Unspecified && opts.gameDifficulty != ss.getDifficulty()) {
+ havePuzzle = false;
+ // check if other threads have finished the job
+ if (puzzleCount.get() >= opts.numberToGenerate)
+ done.set(true);
+ } else {
+ int numDone = puzzleCount.incrementAndGet();
+ if (numDone >= opts.numberToGenerate) done.set(true);
+ if (numDone > opts.numberToGenerate) havePuzzle = false;
+ }
+ }
+ if (havePuzzle) {
+ generated.add(ss.getPuzzle());
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e("QQWing", "Exception Occured", e);
+ return;
+ }
+ generationDone();
+ }
+ };
+
+ generationRunnable.run();
+ }
+
+ // this is called whenever a generation is done..
+ private void generationDone() {
+ // check if more can be generated
+ if(generationList.size() > 0) {
+ generateLevels();
+ } else {
+ // we are done and can close this service
+ handleGenerationStop();
+ }
+ }
+
+ private void showNotification(GameType gameType, GameDifficulty gameDifficulty) {
+ NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
+ builder.setContentTitle(getString(R.string.app_name));
+ builder.setContentText(getString(R.string.generating));
+ builder.setSubText(getString(gameType.getStringResID()) + ", " + getString(gameDifficulty.getStringResID()));
+ builder.setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), FLAG_UPDATE_CURRENT));
+ builder.setColor(ContextCompat.getColor(this, R.color.colorAccent));
+ builder.setPriority(NotificationCompat.PRIORITY_HIGH);
+ builder.setWhen(0);
+ builder.setSmallIcon(R.drawable.splash_icon);
+ startForeground(50, builder.build());
+ }
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return null;
+ }
+
+ @Override
+ protected void onHandleIntent(@Nullable Intent intent) {
+ if (intent != null) {
+
+ String action = intent.getAction();
+
+ if (ACTION_GENERATE.equals(action)) handleGenerationStart(intent);
+ else if (ACTION_STOP.equals(action)) handleGenerationStop();
+ }
+ }
+
+ private int[] level;
+ private LinkedList generated = new LinkedList<>();
+
+ private static class QQWingOptions {
+ // defaults for options
+ boolean needNow = false;
+ boolean printPuzzle = false;
+ boolean printSolution = false;
+ boolean printHistory = false;
+ boolean printInstructions = false;
+ boolean timer = false;
+ boolean countSolutions = false;
+ Action action = Action.NONE;
+ boolean logHistory = false;
+ PrintStyle printStyle = PrintStyle.READABLE;
+ int numberToGenerate = 1;
+ boolean printStats = false;
+ GameDifficulty gameDifficulty = GameDifficulty.Unspecified;
+ GameType gameType = GameType.Unspecified;
+ Symmetry symmetry = Symmetry.NONE;
+ int threads = Runtime.getRuntime().availableProcessors();
+ }
+
+ private boolean getPuzzleToSolve(int[] puzzle) {
+ if(level != null) {
+ if(puzzle.length == level.length) {
+ for(int i = 0; i < level.length; i++) {
+ puzzle[i] = level[i];
+ }
+ }
+ level = null;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/NewLevelManager.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/NewLevelManager.java
index 79aa4a7..3ad7c9a 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/NewLevelManager.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/NewLevelManager.java
@@ -1,10 +1,13 @@
package org.secuso.privacyfriendlysudoku.controller;
import android.content.Context;
+import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Log;
+import org.secuso.privacyfriendlysudoku.controller.database.DatabaseHelper;
+import org.secuso.privacyfriendlysudoku.controller.database.model.Level;
import org.secuso.privacyfriendlysudoku.game.GameDifficulty;
import org.secuso.privacyfriendlysudoku.game.GameType;
@@ -25,12 +28,14 @@ public class NewLevelManager {
private SharedPreferences settings;
private static NewLevelManager instance;
+ private DatabaseHelper dbHelper;
private static String FILE_EXTENSION = ".txt";
private static String LEVEL_PREFIX = "level_";
private static String LEVELS_DIR = "level";
private static File DIR;
- private static int PRE_SAVES = 5;
+ public static int PRE_SAVES_MIN = 3;
+ public static int PRE_SAVES_MAX = 10;
public static NewLevelManager getInstance(Context context, SharedPreferences settings) {
if(instance == null) {
@@ -42,10 +47,16 @@ public class NewLevelManager {
private NewLevelManager(Context context, SharedPreferences settings) {
this.context = context;
this.settings = settings;
+ this.dbHelper = new DatabaseHelper(context);
DIR = context.getDir(LEVELS_DIR, 0);
}
public boolean isLevelLoadable(GameType type, GameDifficulty diff) {
+ return dbHelper.getLevels(diff, type).size() > 0;
+ }
+
+ @Deprecated
+ public boolean isLevelLoadableOld(GameType type, GameDifficulty diff) {
for(File file : DIR.listFiles()) {
if (file.isFile()) {
String name = file.getName().substring(0, file.getName().lastIndexOf("_"));
@@ -65,8 +76,34 @@ public class NewLevelManager {
}
public int[] loadLevel(GameType type, GameDifficulty diff) {
+ Level level = dbHelper.getLevel(diff, type);
+ dbHelper.deleteLevel(level.getId());
+ return level.getPuzzle();
+
+// for(Level level : levels) {
+//
+// // delete level from database
+// dbHelper.deleteLevel(level.getId());
+//
+// // test if it has the correct length
+// int length = type.getSize() * type.getSize();
+// if (level.getPuzzle().length != length) {
+// // Level is not correctly saved -> discard it and try again
+// continue;
+// } else {
+// return level.getPuzzle();
+// }
+// }
+//
+// // if there is no level or every level has the wrong length
+// throw new RuntimeException("No level to load with specified parameters");
+ }
+
+ @Deprecated
+ public int[] loadLevelOld(GameType type, GameDifficulty diff) {
List result = new LinkedList<>();
LinkedList availableFiles = new LinkedList<>();
+ Random r = new Random();
// go through every file
for(File file : DIR.listFiles()) {
@@ -117,7 +154,6 @@ public class NewLevelManager {
}
if(result.size() > 0) {
- Random r = new Random();
int i = r.nextInt(availableFiles.size());
int chosen = availableFiles.get(i);
int[] resultPuzzle = result.get(i);
@@ -144,10 +180,81 @@ public class NewLevelManager {
}
public void checkAndRestock() {
- new AsyncGenerationTask().execute();
+ // Start Generation Service
+ Intent i = new Intent(context, GeneratorService.class);
+ i.setAction(GeneratorService.ACTION_GENERATE);
+ //i.putExtra(ProtocolService.EXTRA_PROTOCOL, current.componentName().flattenToString());
+ context.startService(i);
+
+ //new AsyncGenerationTask().execute();
}
public void loadFirstStartLevels() {
+ saveToDb(GameType.Default_9x9, GameDifficulty.Moderate, "000208090027000000000400000090100706408090201000030080200001000100300469000000007");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Moderate, "000000052000003007500206830002040700070000046640508003000400000000005000050301008");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Moderate, "950710600063200500100300200078000032016000000000000050000001869029000000800003000");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Moderate, "679000300000000050000700020020300001000006000167240000030020004004000500001003792");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Moderate, "000465000000000008000320500060000709900006053000043200600000902024070600000030005");
+
+ saveToDb(GameType.Default_9x9, GameDifficulty.Hard, "000800400008004093009003060000700000000400000060002900091000670200000100403006802");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Hard, "000006040000050000600040080043000200500810000100300605209080460004500000001030000");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Hard, "080000000040000000000071300050130700004006000003508014000000081012600405070000002");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Hard, "030200000008000096700600050013720009006000700802009000000903082500010070000000000");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Hard, "007500200120093700004007050000000305500800090040300018000000009000715000000400030");
+
+ saveToDb(GameType.Default_9x9, GameDifficulty.Challenge, "086000000000000070090000304968027030000100060200900000072006100000000296000000740");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Challenge, "450900001001400000600010004006700000500000000100024060002000030000062400040005700");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Challenge, "100000020006020091000600000030070000260040000008010000000380060700000049040100002");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Challenge, "040100800059408061700000002500000009080700000007004000000000090801009200000000685");
+ saveToDb(GameType.Default_9x9, GameDifficulty.Challenge, "007000050300710000140000000000500406001000907000370005790030001060004000005620000");
+
+ saveToDb(GameType.Default_12x12, GameDifficulty.Moderate, "B30050A100701600070030800002894000007008000000B550100004020300B0000090000060000A010000000032050C0407008006A000000000400001000C290000000008005000");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Moderate, "00B4008A09C002A030C00008007850003000030C000408AB000B00052000000000000070069500030C00B00010467000008000000A100000000800000C0020700001700000095400");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Moderate, "90B08A00300100A000007B500054000B90000320000C05B0A00C0000090200050200000000000094C2000006000200303140000008006C0800000000003000C0010050007009AC60");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Moderate, "74000010000B000005400000900000000000000090000005000B075A0C240208B00007000009000C000207020B000860800300020190C000A000604800470009B00000A068003200");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Moderate, "00B000003050000AC06000700000030001800500000040000008A50402000A00100070000000069B200009130A0000000070020195C000A409000300003600000B21B00030000800");
+
+ saveToDb(GameType.Default_12x12, GameDifficulty.Hard, "00600500000004000000002050004C00800A28049000050000A900C000000000B00000A00B0560000C900C708A00000B0002000000769000008000B002B0C6000017C00107400908");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Hard, "020000B000A608070530000B9050200A03800030980010B001000B6C30900000032000CAB0000000000000067000B000000500000A000C09000081302B0100070950836000100000");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Hard, "0A00070050B107B0060A8000005090020C0A500040001060000000A000040B00219000000107B000602C8090C000001700400A00058B00000000000620000B400090090400800000");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Hard, "000000908A0002900080006B0000C000007005800B2C00006020300000043B090806500C090400C000300060A700040500A00400002800000CA0000900000060B000A0B0003970C6");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Hard, "0070000000000020009B0100000A030000000C039002004800904005000B100B008070507040C20005A0000870B32000C5000810070980100000000000000A070C000A0500000090");
+
+ saveToDb(GameType.Default_12x12, GameDifficulty.Challenge, "2000000000000B070C00000000AC100000000020050CA00BB60002097800079001000C60400000B0070A0000A7000298005048000010004000070009A10600C00B000C00B0000020");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Challenge, "01000002000C00640A800070000A0000082020000008100B0C081090000050A0060C079009BC000A04010500097000000000000000000000904000866070B100020000000C00B009");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Challenge, "000C0B020600400900600A020800140000C000000013050000040600900300000C0500B49A0250000000B0C0002000300143C000B0060000800064000000000B10000000020A8B09");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Challenge, "08060000000100000765A0000C00400000B0605001C7000019C0A4000002A000000B0040000000000100B500000080740020100005690A000000048B706000009020000020807000");
+ saveToDb(GameType.Default_12x12, GameDifficulty.Challenge, "B000730000000000090040000C00B00000003A07180000C00000000CB0000000400A200040B2000000A8000020006700710A06000C00000BA0200170A700603002B0043000090060");
+
+ saveToDb(GameType.Default_6x6, GameDifficulty.Moderate, "000000050004013000004003006050040010");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Moderate, "000450000600104306630000060005010000");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Moderate, "020003040006000000406000000050060042");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Moderate, "024000510042002054000020000060600000");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Moderate, "610030400001004000000200060000002600");
+
+ saveToDb(GameType.Default_6x6, GameDifficulty.Hard, "630010002000001000040020400006003040");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Hard, "000000060130006000050603030005000041");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Hard, "502360000040430050000030650000000000");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Hard, "000004300050006010001003000561000000");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Hard, "000000042000003140064030000320200000");
+
+ saveToDb(GameType.Default_6x6, GameDifficulty.Challenge, "004200200000003002600050300400046000");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Challenge, "003050200003502000000000640002000045");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Challenge, "004030000000003020205004400000006500");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Challenge, "001650000320100000000060000000065000");
+ saveToDb(GameType.Default_6x6, GameDifficulty.Challenge, "500004013005004020000000042500100000");
+ }
+
+ private void saveToDb(GameType gametype, GameDifficulty difficulty, String levelString) {
+ Level level = new Level();
+ level.setDifficulty(difficulty);
+ level.setGameType(gametype);
+ level.setPuzzle(levelString);
+ dbHelper.addLevel(level);
+ }
+
+ @Deprecated
+ public void loadFirstStartLevelsOld() {
// Default_9x9
// Default_12x12
// Default_6x6
@@ -159,62 +266,63 @@ public class NewLevelManager {
// 0
// 1
- saveToFile(GameType.Default_9x9, GameDifficulty.Easy, 0, "000208090027000000000400000090100706408090201000030080200001000100300469000000007");
- saveToFile(GameType.Default_9x9, GameDifficulty.Easy, 1, "000000052000003007500206830002040700070000046640508003000400000000005000050301008");
- saveToFile(GameType.Default_9x9, GameDifficulty.Easy, 2, "950710600063200500100300200078000032016000000000000050000001869029000000800003000");
- saveToFile(GameType.Default_9x9, GameDifficulty.Easy, 3, "679000300000000050000700020020300001000006000167240000030020004004000500001003792");
- saveToFile(GameType.Default_9x9, GameDifficulty.Easy, 4, "000465000000000008000320500060000709900006053000043200600000902024070600000030005");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 0, "000208090027000000000400000090100706408090201000030080200001000100300469000000007");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 1, "000000052000003007500206830002040700070000046640508003000400000000005000050301008");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 2, "950710600063200500100300200078000032016000000000000050000001869029000000800003000");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 3, "679000300000000050000700020020300001000006000167240000030020004004000500001003792");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 4, "000465000000000008000320500060000709900006053000043200600000902024070600000030005");
- saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 0, "000800400008004093009003060000700000000400000060002900091000670200000100403006802");
- saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 1, "000006040000050000600040080043000200500810000100300605209080460004500000001030000");
- saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 2, "080000000040000000000071300050130700004006000003508014000000081012600405070000002");
- saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 3, "030200000008000096700600050013720009006000700802009000000903082500010070000000000");
- saveToFile(GameType.Default_9x9, GameDifficulty.Moderate, 4, "007500200120093700004007050000000305500800090040300018000000009000715000000400030");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 0, "000800400008004093009003060000700000000400000060002900091000670200000100403006802");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 1, "000006040000050000600040080043000200500810000100300605209080460004500000001030000");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 2, "080000000040000000000071300050130700004006000003508014000000081012600405070000002");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 3, "030200000008000096700600050013720009006000700802009000000903082500010070000000000");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 4, "007500200120093700004007050000000305500800090040300018000000009000715000000400030");
- saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 0, "086000000000000070090000304968027030000100060200900000072006100000000296000000740");
- saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 1, "450900001001400000600010004006700000500000000100024060002000030000062400040005700");
- saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 2, "100000020006020091000600000030070000260040000008010000000380060700000049040100002");
- saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 3, "040100800059408061700000002500000009080700000007004000000000090801009200000000685");
- saveToFile(GameType.Default_9x9, GameDifficulty.Hard, 4, "007000050300710000140000000000500406001000907000370005790030001060004000005620000");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Challenge, 0, "086000000000000070090000304968027030000100060200900000072006100000000296000000740");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Challenge, 1, "450900001001400000600010004006700000500000000100024060002000030000062400040005700");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Challenge, 2, "100000020006020091000600000030070000260040000008010000000380060700000049040100002");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Challenge, 3, "040100800059408061700000002500000009080700000007004000000000090801009200000000685");
+ saveToFile(GameType.Default_9x9, GameDifficulty.Challenge, 4, "007000050300710000140000000000500406001000907000370005790030001060004000005620000");
- saveToFile(GameType.Default_12x12, GameDifficulty.Easy, 0, "B30050A100701600070030800002894000007008000000B550100004020300B0000090000060000A010000000032050C0407008006A000000000400001000C290000000008005000");
- saveToFile(GameType.Default_12x12, GameDifficulty.Easy, 1, "00B4008A09C002A030C00008007850003000030C000408AB000B00052000000000000070069500030C00B00010467000008000000A100000000800000C0020700001700000095400");
- saveToFile(GameType.Default_12x12, GameDifficulty.Easy, 2, "90B08A00300100A000007B500054000B90000320000C05B0A00C0000090200050200000000000094C2000006000200303140000008006C0800000000003000C0010050007009AC60");
- saveToFile(GameType.Default_12x12, GameDifficulty.Easy, 3, "74000010000B000005400000900000000000000090000005000B075A0C240208B00007000009000C000207020B000860800300020190C000A000604800470009B00000A068003200");
- saveToFile(GameType.Default_12x12, GameDifficulty.Easy, 4, "00B000003050000AC06000700000030001800500000040000008A50402000A00100070000000069B200009130A0000000070020195C000A409000300003600000B21B00030000800");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 0, "B30050A100701600070030800002894000007008000000B550100004020300B0000090000060000A010000000032050C0407008006A000000000400001000C290000000008005000");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 1, "00B4008A09C002A030C00008007850003000030C000408AB000B00052000000000000070069500030C00B00010467000008000000A100000000800000C0020700001700000095400");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 2, "90B08A00300100A000007B500054000B90000320000C05B0A00C0000090200050200000000000094C2000006000200303140000008006C0800000000003000C0010050007009AC60");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 3, "74000010000B000005400000900000000000000090000005000B075A0C240208B00007000009000C000207020B000860800300020190C000A000604800470009B00000A068003200");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 4, "00B000003050000AC06000700000030001800500000040000008A50402000A00100070000000069B200009130A0000000070020195C000A409000300003600000B21B00030000800");
- saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 0, "00600500000004000000002050004C00800A28049000050000A900C000000000B00000A00B0560000C900C708A00000B0002000000769000008000B002B0C6000017C00107400908");
- saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 1, "020000B000A608070530000B9050200A03800030980010B001000B6C30900000032000CAB0000000000000067000B000000500000A000C09000081302B0100070950836000100000");
- saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 2, "0A00070050B107B0060A8000005090020C0A500040001060000000A000040B00219000000107B000602C8090C000001700400A00058B00000000000620000B400090090400800000");
- saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 3, "000000908A0002900080006B0000C000007005800B2C00006020300000043B090806500C090400C000300060A700040500A00400002800000CA0000900000060B000A0B0003970C6");
- saveToFile(GameType.Default_12x12, GameDifficulty.Moderate, 4, "0070000000000020009B0100000A030000000C039002004800904005000B100B008070507040C20005A0000870B32000C5000810070980100000000000000A070C000A0500000090");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 0, "00600500000004000000002050004C00800A28049000050000A900C000000000B00000A00B0560000C900C708A00000B0002000000769000008000B002B0C6000017C00107400908");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 1, "020000B000A608070530000B9050200A03800030980010B001000B6C30900000032000CAB0000000000000067000B000000500000A000C09000081302B0100070950836000100000");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 2, "0A00070050B107B0060A8000005090020C0A500040001060000000A000040B00219000000107B000602C8090C000001700400A00058B00000000000620000B400090090400800000");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 3, "000000908A0002900080006B0000C000007005800B2C00006020300000043B090806500C090400C000300060A700040500A00400002800000CA0000900000060B000A0B0003970C6");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 4, "0070000000000020009B0100000A030000000C039002004800904005000B100B008070507040C20005A0000870B32000C5000810070980100000000000000A070C000A0500000090");
- saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 0, "2000000000000B070C00000000AC100000000020050CA00BB60002097800079001000C60400000B0070A0000A7000298005048000010004000070009A10600C00B000C00B0000020");
- saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 1, "01000002000C00640A800070000A0000082020000008100B0C081090000050A0060C079009BC000A04010500097000000000000000000000904000866070B100020000000C00B009");
- saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 2, "000C0B020600400900600A020800140000C000000013050000040600900300000C0500B49A0250000000B0C0002000300143C000B0060000800064000000000B10000000020A8B09");
- saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 3, "08060000000100000765A0000C00400000B0605001C7000019C0A4000002A000000B0040000000000100B500000080740020100005690A000000048B706000009020000020807000");
- saveToFile(GameType.Default_12x12, GameDifficulty.Hard, 4, "B000730000000000090040000C00B00000003A07180000C00000000CB0000000400A200040B2000000A8000020006700710A06000C00000BA0200170A700603002B0043000090060");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Challenge, 0, "2000000000000B070C00000000AC100000000020050CA00BB60002097800079001000C60400000B0070A0000A7000298005048000010004000070009A10600C00B000C00B0000020");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Challenge, 1, "01000002000C00640A800070000A0000082020000008100B0C081090000050A0060C079009BC000A04010500097000000000000000000000904000866070B100020000000C00B009");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Challenge, 2, "000C0B020600400900600A020800140000C000000013050000040600900300000C0500B49A0250000000B0C0002000300143C000B0060000800064000000000B10000000020A8B09");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Challenge, 3, "08060000000100000765A0000C00400000B0605001C7000019C0A4000002A000000B0040000000000100B500000080740020100005690A000000048B706000009020000020807000");
+ saveToFile(GameType.Default_12x12, GameDifficulty.Challenge, 4, "B000730000000000090040000C00B00000003A07180000C00000000CB0000000400A200040B2000000A8000020006700710A06000C00000BA0200170A700603002B0043000090060");
- saveToFile(GameType.Default_6x6, GameDifficulty.Easy, 0, "000000050004013000004003006050040010");
- saveToFile(GameType.Default_6x6, GameDifficulty.Easy, 1, "000450000600104306630000060005010000");
- saveToFile(GameType.Default_6x6, GameDifficulty.Easy, 2, "020003040006000000406000000050060042");
- saveToFile(GameType.Default_6x6, GameDifficulty.Easy, 3, "024000510042002054000020000060600000");
- saveToFile(GameType.Default_6x6, GameDifficulty.Easy, 4, "610030400001004000000200060000002600");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 0, "000000050004013000004003006050040010");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 1, "000450000600104306630000060005010000");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 2, "020003040006000000406000000050060042");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 3, "024000510042002054000020000060600000");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 4, "610030400001004000000200060000002600");
- saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 0, "630010002000001000040020400006003040");
- saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 1, "000000060130006000050603030005000041");
- saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 2, "502360000040430050000030650000000000");
- saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 3, "000004300050006010001003000561000000");
- saveToFile(GameType.Default_6x6, GameDifficulty.Moderate, 4, "000000042000003140064030000320200000");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 0, "630010002000001000040020400006003040");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 1, "000000060130006000050603030005000041");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 2, "502360000040430050000030650000000000");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 3, "000004300050006010001003000561000000");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 4, "000000042000003140064030000320200000");
- saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 0, "004200200000003002600050300400046000");
- saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 1, "003050200003502000000000640002000045");
- saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 2, "004030000000003020205004400000006500");
- saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 3, "001650000320100000000060000000065000");
- saveToFile(GameType.Default_6x6, GameDifficulty.Hard, 4, "500004013005004020000000042500100000");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Challenge, 0, "004200200000003002600050300400046000");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Challenge, 1, "003050200003502000000000640002000045");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Challenge, 2, "004030000000003020205004400000006500");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Challenge, 3, "001650000320100000000060000000065000");
+ saveToFile(GameType.Default_6x6, GameDifficulty.Challenge, 4, "500004013005004020000000042500100000");
}
/** Don't use this if you don't know what you are doing! **/
+ @Deprecated
private void saveToFile(GameType gameType, GameDifficulty gameDifficulty, int saveNumber, String puzzle) {
StringBuilder sb = new StringBuilder();
sb.append(LEVEL_PREFIX);
@@ -249,7 +357,7 @@ public class NewLevelManager {
@Override
protected String doInBackground(int[][] ... params) {
- int preSaves = PRE_SAVES;
+ int preSaves = PRE_SAVES_MIN;
// init
final LinkedList gameTypes = GameType.getValidGameTypes();
final LinkedList gameDifficulties = GameDifficulty.getValidDifficultyList();
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/Symbol.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/Symbol.java
index 4135a30..96265f0 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/Symbol.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/Symbol.java
@@ -10,8 +10,8 @@ public enum Symbol {
Roman(new String[] {"I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII", "XIII", "XIV", "XV", "XVI", "XVII", "XVIII", "XIX", "XX", "XXI", "XXII"}),
Fancy(new String[] {"♪", "♫", "☼", "♥", "♦", "♣", "♠", "•", "○", "A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N" }),
Chinese(new String[] {"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二", "十三", "十四", "十五", "十六" }),
- Greek(new String[] { "α", "β", "γ", "δ", "ε", "ϛ", "ζ", "η", "θ", "ι", "ια", "ιβ", "ιγ", "ιδ", "ιε", "ιϛ", "ιζ", "ιη", "ιθ", "κ"}),
- Indian(new String[] { "१", "२", "३", "४", "५", "६", "७", "८", "९", "१०", "११", "१२", "१३", "१४", "१५", "१६", "१७"});
+ Greek(new String[] {"α", "β", "γ", "δ", "ε", "ϛ", "ζ", "η", "θ", "ι", "ια", "ιβ", "ιγ", "ιδ", "ιε", "ιϛ", "ιζ", "ιη", "ιθ", "κ"}),
+ Indian(new String[] {"१", "२", "३", "४", "५", "६", "७", "८", "९", "१०", "११", "१२", "१३", "१४", "१५", "१६", "१७"});
private String[] map;
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/DatabaseHelper.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/DatabaseHelper.java
new file mode 100644
index 0000000..59fdae0
--- /dev/null
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/DatabaseHelper.java
@@ -0,0 +1,97 @@
+package org.secuso.privacyfriendlysudoku.controller.database;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+
+import org.secuso.privacyfriendlysudoku.controller.database.columns.LevelColumns;
+import org.secuso.privacyfriendlysudoku.controller.database.model.Level;
+import org.secuso.privacyfriendlysudoku.game.GameDifficulty;
+import org.secuso.privacyfriendlysudoku.game.GameType;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+public class DatabaseHelper extends SQLiteOpenHelper {
+
+ public static final int DATABASE_VERSION = 1;
+ public static final String DATABASE_NAME = "Database.db";
+
+ public DatabaseHelper(Context context) {
+ super(context, DATABASE_NAME, null, DATABASE_VERSION);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db) {
+ db.execSQL(LevelColumns.SQL_CREATE_ENTRIES);
+ }
+
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ db.execSQL(LevelColumns.SQL_DELETE_ENTRIES);
+ onCreate(db);
+ }
+
+ public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
+ onUpgrade(db, oldVersion, newVersion);
+ }
+
+ public List getLevels(GameDifficulty difficulty, GameType gameType) {
+ if(difficulty == null || gameType == null) {
+ throw new IllegalArgumentException("Arguments may not be null");
+ }
+
+ List levelList = new LinkedList();
+
+ SQLiteDatabase database = getWritableDatabase();
+
+ String selection = LevelColumns.DIFFICULTY + " = ? AND " + LevelColumns.GAMETYPE + " = ?";
+ String[] selectionArgs = {difficulty.name(), gameType.name()};
+
+ // How you want the results sorted in the resulting Cursor
+ Cursor c = database.query(
+ LevelColumns.TABLE_NAME, // The table to query
+ LevelColumns.PROJECTION, // The columns to return
+ selection, // The columns for the WHERE clause
+ selectionArgs, // The values for the WHERE clause
+ null, // don't group the rows
+ null, // don't filter by row groups
+ null // The sort order
+ );
+
+ if (c != null) {
+ while(c.moveToNext()) {
+ levelList.add(LevelColumns.getLevel(c));
+ }
+ }
+
+ c.close();
+ return levelList;
+ }
+
+ public Level getLevel(GameDifficulty difficulty, GameType gameType) {
+ List levelList = getLevels(difficulty, gameType);
+ if(levelList.size() == 0) {
+ throw new IllegalArgumentException("There is no level");
+ }
+ return levelList.get(0);
+ }
+
+ public void deleteLevel(int id) {
+ SQLiteDatabase database = getWritableDatabase();
+
+ String selection = LevelColumns._ID + " = ?";
+ String[] selectionArgs = {id+""};
+
+ database.delete(LevelColumns.TABLE_NAME, selection, selectionArgs);
+ }
+
+ public long addLevel(Level level) {
+ SQLiteDatabase database = getWritableDatabase();
+ return database.insert(LevelColumns.TABLE_NAME, null, LevelColumns.getValues(level));
+ }
+}
+
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/columns/LevelColumns.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/columns/LevelColumns.java
new file mode 100644
index 0000000..d6deebc
--- /dev/null
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/columns/LevelColumns.java
@@ -0,0 +1,90 @@
+package org.secuso.privacyfriendlysudoku.controller.database.columns;
+
+import android.content.ContentValues;
+import android.database.Cursor;
+import android.provider.BaseColumns;
+
+import org.secuso.privacyfriendlysudoku.controller.Symbol;
+import org.secuso.privacyfriendlysudoku.controller.database.model.*;
+import org.secuso.privacyfriendlysudoku.game.GameDifficulty;
+import org.secuso.privacyfriendlysudoku.game.GameType;
+
+public class LevelColumns implements BaseColumns {
+
+ public static final String TABLE_NAME = "levels";
+
+ public static final String DIFFICULTY = "level_difficulty";
+ public static final String GAMETYPE = "level_gametype";
+ public static final String PUZZLE = "level_puzzle";
+
+ private static final String TEXT_TYPE = " TEXT ";
+ private static final String INTEGER_TYPE = " INTEGER ";
+ private static final String COMMA_SEP = ",";
+
+ public static final String[] PROJECTION = {
+ _ID,
+ DIFFICULTY,
+ GAMETYPE,
+ PUZZLE
+ };
+
+ public static String SQL_CREATE_ENTRIES =
+ "CREATE TABLE " + TABLE_NAME + " (" +
+ _ID + INTEGER_TYPE + " PRIMARY KEY AUTOINCREMENT" + COMMA_SEP +
+ DIFFICULTY + TEXT_TYPE + COMMA_SEP +
+ GAMETYPE + TEXT_TYPE + COMMA_SEP +
+ PUZZLE + TEXT_TYPE + " )";
+ public static String SQL_DELETE_ENTRIES =
+ "DROP TABLE IF EXISTS " + TABLE_NAME;
+
+ public static Level getLevel(Cursor c) {
+ Level level = new Level();
+
+ // *** ID ***
+ level.setId(c.getInt(c.getColumnIndexOrThrow(LevelColumns._ID)));
+
+ // *** GAME TYPE ***
+ String gameTypeString = c.getString(c.getColumnIndexOrThrow(LevelColumns.GAMETYPE));
+ GameType gameType = GameType.valueOf(gameTypeString);
+ level.setGameType(gameType);
+
+ // *** DIFFICULTY ***
+ String difficultyString = c.getString(c.getColumnIndexOrThrow(LevelColumns.DIFFICULTY));
+ level.setDifficulty(GameDifficulty.valueOf(difficultyString));
+
+ // *** PUZZLE ***
+ String puzzleString = c.getString(c.getColumnIndexOrThrow(LevelColumns.PUZZLE));
+ int[] puzzle = new int[gameType.getSize()*gameType.getSize()];
+
+ if(puzzle.length != puzzleString.length()) {
+ throw new IllegalArgumentException("Saved level does not have the correct size.");
+ }
+
+ for(int i = 0; i < puzzleString.length(); i++) {
+ puzzle[i] = Symbol.getValue(Symbol.SaveFormat, String.valueOf(puzzleString.charAt(i)))+1;
+ }
+ level.setPuzzle(puzzle);
+
+ return level;
+ }
+
+ public static ContentValues getValues(Level record) {
+ ContentValues values = new ContentValues();
+ if(record.getId() != -1) {
+ values.put(LevelColumns._ID, record.getId());
+ }
+ values.put(LevelColumns.GAMETYPE, record.getGameType().name());
+ values.put(LevelColumns.DIFFICULTY, record.getDifficulty().name());
+
+ StringBuilder sb = new StringBuilder();
+ for(int i = 0; i < record.getPuzzle().length; i++) {
+ if (record.getPuzzle()[i] == 0) {
+ sb.append(0);
+ } else {
+ sb.append(Symbol.getSymbol(Symbol.SaveFormat, record.getPuzzle()[i]-1));
+ }
+ }
+ values.put(LevelColumns.PUZZLE, sb.toString());
+ return values;
+ }
+}
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/model/Level.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/model/Level.java
new file mode 100644
index 0000000..589d365
--- /dev/null
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/database/model/Level.java
@@ -0,0 +1,65 @@
+package org.secuso.privacyfriendlysudoku.controller.database.model;
+
+import org.secuso.privacyfriendlysudoku.controller.Symbol;
+import org.secuso.privacyfriendlysudoku.game.GameDifficulty;
+import org.secuso.privacyfriendlysudoku.game.GameType;
+
+public class Level {
+ private int id = -1;
+ private GameDifficulty difficulty = GameDifficulty.Unspecified;
+ private GameType gameType = GameType.Unspecified;
+ private int[] puzzle;
+
+ public Level() {}
+
+ public Level(int id, GameDifficulty difficulty, GameType gameType, int[] puzzle) {
+ this.id = id;
+ this.difficulty = difficulty;
+ this.gameType = gameType;
+ this.puzzle = puzzle;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public GameDifficulty getDifficulty() {
+ return difficulty;
+ }
+
+ public void setDifficulty(GameDifficulty difficulty) {
+ this.difficulty = difficulty;
+ }
+
+ public GameType getGameType() {
+ return gameType;
+ }
+
+ public void setGameType(GameType gameType) {
+ this.gameType = gameType;
+ }
+
+ public int[] getPuzzle() {
+ return puzzle;
+ }
+
+ public void setPuzzle(int[] puzzle) {
+ this.puzzle = puzzle;
+ }
+ public void setPuzzle(String puzzleString) {
+ int[] puzzle = new int[gameType.getSize()*gameType.getSize()];
+
+ if(puzzle.length != puzzleString.length()) {
+ throw new IllegalArgumentException("Saved level does not have the correct size.");
+ }
+
+ for(int i = 0; i < puzzleString.length(); i++) {
+ puzzle[i] = Symbol.getValue(Symbol.SaveFormat, String.valueOf(puzzleString.charAt(i)))+1;
+ }
+ this.puzzle = puzzle;
+ }
+}
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/qqwing/QQWing.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/qqwing/QQWing.java
index 2e152f9..f57efd5 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/qqwing/QQWing.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/controller/qqwing/QQWing.java
@@ -22,6 +22,8 @@
// @formatter:on
package org.secuso.privacyfriendlysudoku.controller.qqwing;
+import android.util.Log;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -228,17 +230,33 @@ public class QQWing {
*/
public GameDifficulty getDifficulty() {
if (getGuessCount() > 0)
- return GameDifficulty.Hard;
+ return GameDifficulty.Challenge;
if (getBoxLineReductionCount() > 0)
- return GameDifficulty.Moderate;
+ return GameDifficulty.Hard;
if (getPointingPairTripleCount() > 0)
- return GameDifficulty.Moderate;
+ return GameDifficulty.Hard;
if (getHiddenPairCount() > 0)
- return GameDifficulty.Moderate;
+ return GameDifficulty.Hard;
if (getNakedPairCount() > 0)
- return GameDifficulty.Moderate;
- if (getHiddenSingleCount() > 0)
- return GameDifficulty.Easy;
+ return GameDifficulty.Hard;
+ switch (gameType) {
+ case Default_6x6:
+ if (getHiddenSingleCount() > 0)
+ return GameDifficulty.Moderate;
+ break;
+ case Default_9x9:
+ if (getHiddenSingleCount() > 10)
+ return GameDifficulty.Moderate;
+ break;
+ case Default_12x12:
+ Log.d("GeneratorService", "# HiddenSingleCount: "+ getHiddenSingleCount());
+ if (getHiddenSingleCount() > 20)
+ return GameDifficulty.Moderate;
+ break;
+ default:
+ if(getHiddenSingleCount() > 10)
+ return GameDifficulty.Moderate;
+ }
if (getSingleCount() > 0)
return GameDifficulty.Easy;
@@ -450,9 +468,9 @@ public class QQWing {
rollbackRound(i);
// Some hack to make easy levels on 12x12 .. because the generator wasn't able to create some
- if(gameType == GameType.Default_12x12 && difficulty == GameDifficulty.Easy ) {
- i += 4; // skip every 2nd round to find "easy" levels more frequent. Still takes about 20 Seconds.
- }
+ //if(difficulty == GameDifficulty.Easy && gameType == GameType.Default_12x12) {
+ // i += 2; // skip every 2nd round to find "easy" levels more frequent. Still takes about 20 Seconds.
+ //}
}
}
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/game/GameBoard.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/game/GameBoard.java
index 95f5081..ba7c64f 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/game/GameBoard.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/game/GameBoard.java
@@ -145,6 +145,8 @@ public class GameBoard implements Cloneable, Parcelable {
return solved;
}
+
+
/**
* Checks the given list if every number occurs only once.
* This method will automatically build the errorList.
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/game/GameDifficulty.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/game/GameDifficulty.java
index 44dfe0d..fbf9f9c 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/game/GameDifficulty.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/game/GameDifficulty.java
@@ -16,7 +16,8 @@ public enum GameDifficulty implements Parcelable {
Unspecified(R.string.gametype_unspecified),
Easy(R.string.difficulty_easy),
Moderate(R.string.difficulty_moderate),
- Hard(R.string.difficulty_hard);
+ Hard(R.string.difficulty_hard),
+ Challenge(R.string.difficulty_challenge);
private int resID;
@@ -34,6 +35,7 @@ public enum GameDifficulty implements Parcelable {
validList.add(Easy);
validList.add(Moderate);
validList.add(Hard);
+ validList.add(Challenge);
return validList;
}
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/LoadGameActivity.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/LoadGameActivity.java
index 8de62ad..0ead53c 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/LoadGameActivity.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/LoadGameActivity.java
@@ -217,6 +217,8 @@ public class LoadGameActivity extends BaseActivity implements IDeleteDialogFragm
}
gameType.setText(gic.getGameType().getStringResID());
difficulty.setText(gic.getDifficulty().getStringResID());
+ difficultyBar.setNumStars(GameDifficulty.getValidDifficultyList().size());
+ difficultyBar.setMax(GameDifficulty.getValidDifficultyList().size());
difficultyBar.setRating(GameDifficulty.getValidDifficultyList().indexOf(gic.getDifficulty())+1);
int time = gic.getTimePlayed();
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/MainActivity.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/MainActivity.java
index 9c05354..7bbc155 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/MainActivity.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/MainActivity.java
@@ -48,6 +48,7 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
SharedPreferences settings;
ImageView arrowLeft, arrowRight;
DrawerLayout drawer;
+ NavigationView mNavigationView;
/**
* The {@link ViewPager} that will host the section contents.
@@ -168,8 +169,10 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
drawer.setDrawerListener(toggle);
toggle.syncState();
- NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view_main);
- navigationView.setNavigationItemSelectedListener(this);
+ mNavigationView = (NavigationView) findViewById(R.id.nav_view_main);
+ mNavigationView.setNavigationItemSelectedListener(this);
+
+ selectNavigationItem(R.id.nav_newgame_main);
overridePendingTransition(0, 0);
}
@@ -247,6 +250,8 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
public void onResume() {
super.onResume();
+ selectNavigationItem(R.id.nav_newgame_main);
+
refreshContinueButton();
}
@@ -269,6 +274,13 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
// Handle navigation view item clicks here.
final int id = item.getItemId();
+ drawer.closeDrawer(GravityCompat.START);
+
+ // return if we are not going to another page
+ if(id == R.id.nav_newgame_main) {
+ return true;
+ }
+
// delay transition so the drawer can close
mHandler.postDelayed(new Runnable() {
@Override
@@ -277,16 +289,23 @@ public class MainActivity extends BaseActivity implements NavigationView.OnNavig
}
}, NAVDRAWER_LAUNCH_DELAY);
- drawer.closeDrawer(GravityCompat.START);
-
// fade out the active activity
View mainContent = findViewById(R.id.main_content);
if (mainContent != null) {
mainContent.animate().alpha(0).setDuration(MAIN_CONTENT_FADEOUT_DURATION);
}
+
return true;
}
+ // set active navigation item
+ private void selectNavigationItem(int itemId) {
+ for(int i = 0 ; i < mNavigationView.getMenu().size(); i++) {
+ boolean b = itemId == mNavigationView.getMenu().getItem(i).getItemId();
+ mNavigationView.getMenu().getItem(i).setChecked(b);
+ }
+ }
+
private boolean goToNavigationItem(int id) {
Intent intent;
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/StatsActivity.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/StatsActivity.java
index 93c0ef5..fe29654 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/StatsActivity.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/StatsActivity.java
@@ -21,6 +21,7 @@ import android.widget.TextView;
import org.secuso.privacyfriendlysudoku.controller.SaveLoadStatistics;
import org.secuso.privacyfriendlysudoku.controller.helper.HighscoreInfoContainer;
+import org.secuso.privacyfriendlysudoku.game.GameDifficulty;
import org.secuso.privacyfriendlysudoku.game.GameType;
import org.secuso.privacyfriendlysudoku.ui.view.R;
@@ -243,9 +244,17 @@ public class StatsActivity extends BaseActivity {
averageTimeView = (TextView) rootView.findViewById(R.id.third_ava_time);
minTimeView = (TextView) rootView.findViewById(R.id.third_min_time);
break;
+ case 3:
+ difficultyBarView = (RatingBar) rootView.findViewById(R.id.fourth_diff_bar);
+ difficultyView = (TextView) rootView.findViewById(R.id.fourth_diff_text);
+ averageTimeView = (TextView) rootView.findViewById(R.id.fourth_ava_time);
+ minTimeView = (TextView) rootView.findViewById(R.id.fourth_min_time);
+ break;
default: return;
}
- difficultyBarView.setRating(pos+1);
+ difficultyBarView.setMax(GameDifficulty.getValidDifficultyList().size());
+ difficultyBarView.setNumStars(GameDifficulty.getValidDifficultyList().size());
+ difficultyBarView.setRating(infos.getDifficulty().ordinal());
difficultyView.setText(rootView.getResources().getString(infos.getDifficulty().getStringResID()));
t= (infos.getTimeNoHints() == 0)?0:(infos.getTimeNoHints() / infos.getNumberOfGamesNoHints());
averageTimeView.setText(formatTime(t));
diff --git a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/SudokuFieldLayout.java b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/SudokuFieldLayout.java
index 4e3783d..7b997fd 100644
--- a/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/SudokuFieldLayout.java
+++ b/app/src/main/java/org/secuso/privacyfriendlysudoku/ui/view/SudokuFieldLayout.java
@@ -216,48 +216,42 @@ public class SudokuFieldLayout extends RelativeLayout implements IHighlightChang
p.setStrokeWidth(4);
p.setColor(Color.RED);
- float offset1=0;
- float offset2= 0;
+ float offsetX = 0;
+ float offsetY = 0;
int row;
int col;
int row2;
int col2;
- float radius;
+
+ float radius = gameCellWidth / 2 - gameCellWidth / 16;
+
for(CellConflict conflict : gameController.getErrorList()) {
- //gamecells[conflict.getRowCell1()][conflict.getColCell1()].
-
+ // draw the circles around the numbers
row = conflict.getRowCell1();
col = conflict.getColCell1();
- radius = gameCellWidth/2 - gameCellWidth / 8;
canvas.drawCircle(gameCellWidth * col + gameCellWidth / 2, gameCellHeight * row + gameCellHeight / 2, radius, p);
row2 = conflict.getRowCell2();
col2 = conflict.getColCell2();
canvas.drawCircle(gameCellWidth * col2 + gameCellWidth / 2, gameCellHeight * row2 + gameCellHeight / 2, radius, p);
+ // draw the line between the circles
+ // either offset is 0 or it is the radius pointing in the direction of the other cell
+ offsetX = (col == col2) ? 0f : (col < col2) ? radius : -radius;
+ offsetY = (row == row2) ? 0f : (row < row2) ? radius : -radius;
-
-
- if (col == col2 || row == row2) {
- offset1 = (col > col2)? 0-radius:radius;
- offset2 = (row > row2)? 0-radius:radius;
- offset1 = (col == col2)?0f:offset1;
- offset2 = (row == row2)?0f:offset2;
- } else {
- double alpha = Math.atan((Math.abs(col2-col))/(Math.abs(row2 - row)));
- offset1 = (col > col2)? 0-radius:radius;
- offset2 = (row > row2)? 0-radius:radius;
- offset1*=Math.sin(alpha);
- offset2*=Math.cos(alpha);
+ if(col != col2 && row != row2) {
+ double alpha = Math.atan(((float)Math.abs(col2 - col))/((float)Math.abs(row2 - row)));
+ offsetX *= Math.sin(alpha);
+ offsetY *= Math.cos(alpha);
}
-
canvas.drawLine(
- (gameCellWidth * col + gameCellWidth / 2)+offset1,
- (gameCellHeight * row + gameCellHeight / 2)+offset2,
- (gameCellWidth * col2 + gameCellWidth / 2)-offset1,
- (gameCellHeight * row2 + gameCellHeight / 2)-offset2, p);
+ (gameCellWidth * col + gameCellWidth / 2)+offsetX,
+ (gameCellHeight * row + gameCellHeight / 2)+offsetY,
+ (gameCellWidth * col2 + gameCellWidth / 2)-offsetX,
+ (gameCellHeight * row2 + gameCellHeight / 2)-offsetY, p);
}
}
}
diff --git a/app/src/main/res/layout-land/fragment_stats.xml b/app/src/main/res/layout-land/fragment_stats.xml
index bc719a9..80160d4 100644
--- a/app/src/main/res/layout-land/fragment_stats.xml
+++ b/app/src/main/res/layout-land/fragment_stats.xml
@@ -128,7 +128,7 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="5.5"
- android:weightSum="3">
+ android:weightSum="4">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout-xlarge-land/fragment_stats.xml b/app/src/main/res/layout-xlarge-land/fragment_stats.xml
index 34a4496..035860f 100644
--- a/app/src/main/res/layout-xlarge-land/fragment_stats.xml
+++ b/app/src/main/res/layout-xlarge-land/fragment_stats.xml
@@ -309,6 +309,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout-xlarge/fragment_stats.xml b/app/src/main/res/layout-xlarge/fragment_stats.xml
index 34a4496..26997f5 100644
--- a/app/src/main/res/layout-xlarge/fragment_stats.xml
+++ b/app/src/main/res/layout-xlarge/fragment_stats.xml
@@ -105,7 +105,7 @@
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="4"
- android:weightSum="3"
+ android:weightSum="4"
android:orientation="vertical">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_stats.xml b/app/src/main/res/layout/fragment_stats.xml
index 34a4496..9e12962 100644
--- a/app/src/main/res/layout/fragment_stats.xml
+++ b/app/src/main/res/layout/fragment_stats.xml
@@ -6,7 +6,7 @@
android:paddingBottom="@dimen/activity_vertical_margin"
android:weightSum="10"
android:orientation="vertical"
- tools:context="tu_darmstadt.sudoku.ui.StatsActivity$PlaceholderFragment">
+ tools:context="org.secuso.privacyfriendlysudoku.ui.StatsActivity$PlaceholderFragment">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/menu_drawer_main.xml b/app/src/main/res/menu/menu_drawer_main.xml
index 222c2a7..f47ca5a 100644
--- a/app/src/main/res/menu/menu_drawer_main.xml
+++ b/app/src/main/res/menu/menu_drawer_main.xml
@@ -1,9 +1,16 @@