Generator Changes and reworked the Saved Level Structure

This commit is contained in:
Christopher Beckmann 2017-06-25 20:14:34 +02:00
parent e35e16a2d9
commit 1aa5500c64
28 changed files with 1231 additions and 134 deletions

88
.idea/misc.xml Normal file
View file

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<expanded-state>
<State>
<id />
</State>
</expanded-state>
<selected-state>
<State>
<id>Android</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
<component name="masterDetails">
<states>
<state key="Copyright.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
<state key="ScopeChooserConfigurable.UI">
<settings>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>

View file

@ -9,7 +9,6 @@
<facet type="android" name="Android">
<configuration>
<option name="SELECTED_BUILD_VARIANT" value="debug" />
<option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
<option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
<option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
<afterSyncTasks>
@ -47,7 +46,6 @@
<sourceFolder url="file://$MODULE_DIR$/src/debug/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/debug/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/res" type="java-test-resource" />
@ -55,7 +53,6 @@
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/testDebug/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/res" type="java-resource" />
@ -63,43 +60,26 @@
<sourceFolder url="file://$MODULE_DIR$/src/main/assets" type="java-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/main/aidl" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/jni" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/rs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/shaders" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/jni" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/androidTest/shaders" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/res" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/resources" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/assets" type="java-test-resource" />
<sourceFolder url="file://$MODULE_DIR$/src/test/aidl" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/rs" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/test/shaders" isTestSource="true" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/assets" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/blame" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/builds" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/animated-vector-drawable/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/recyclerview-v7/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-compat/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-core-ui/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-core-utils/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-fragment/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-media-compat/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v13/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-vector-drawable/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/transition/25.0.0/jars" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-classes" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental-runtime-classes" />
@ -109,12 +89,12 @@
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/instant-run-support" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/jniLibs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/manifests" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/pre-dexed" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/reload-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/res" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/restart-dex" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/rs" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/shaders" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/split-apk" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/symbols" />
<excludeFolder url="file://$MODULE_DIR$/build/intermediates/transforms" />
<excludeFolder url="file://$MODULE_DIR$/build/outputs" />

View file

@ -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 {

View file

@ -38,6 +38,10 @@
<activity
android:name="org.secuso.privacyfriendlysudoku.ui.HelpActivity"
android:label="@string/title_activity_help" />
<service
android:name="org.secuso.privacyfriendlysudoku.controller.GeneratorService"
android:enabled="true"
android:exported="false" />
</application>
</manifest>

View file

@ -221,8 +221,43 @@ 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<GameCell> 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<GameCell> getConnectedCells(int row, int col) {
LinkedList<GameCell> list = new LinkedList<>();

View file

@ -203,6 +203,5 @@ public class GameStateManager {
SharedPreferences.Editor editor = settings.edit();
editor.putBoolean("savesChanged", true);
editor.commit();
}
}

View file

@ -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<Pair<GameType, GameDifficulty>> 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<GameType, GameDifficulty> 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<GameType, GameDifficulty> 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<int[]> 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;
}
}

View file

@ -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<int[]> result = new LinkedList<>();
LinkedList<Integer> 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<GameType> gameTypes = GameType.getValidGameTypes();
final LinkedList<GameDifficulty> gameDifficulties = GameDifficulty.getValidDifficultyList();

View file

@ -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;

View file

@ -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<Level> getLevels(GameDifficulty difficulty, GameType gameType) {
if(difficulty == null || gameType == null) {
throw new IllegalArgumentException("Arguments may not be null");
}
List<Level> levelList = new LinkedList<Level>();
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<Level> 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));
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
return GameDifficulty.Hard;
switch (gameType) {
case Default_6x6:
if (getHiddenSingleCount() > 0)
return GameDifficulty.Easy;
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.
//}
}
}

View file

@ -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.

View file

@ -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;
}

View file

@ -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();

View file

@ -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;

View file

@ -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));

View file

@ -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);
}
}
}

View file

@ -128,7 +128,7 @@
android:layout_height="match_parent"
android:orientation="vertical"
android:layout_weight="5.5"
android:weightSum="3">
android:weightSum="4">
<!-- ### first row -->
<LinearLayout
android:layout_width="match_parent"
@ -324,6 +324,72 @@
android:layout_below="@+id/third_min_text"/>
</RelativeLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<RatingBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="3"
android:layout_gravity="center"
android:id="@+id/fourth_diff_bar"
android:layout_below="@+id/fourth_diff_text"
style="?android:attr/ratingBarStyleSmall"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="diffi"
android:id="@+id/fourth_diff_text"
android:gravity="center_vertical"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/average_time"
android:id="@+id/fourth_av_text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="@+id/fourth_ava_time"
android:gravity="center_vertical"
android:layout_below="@+id/fourth_av_text"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/min_time"
android:id="@+id/fourth_min_text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="@+id/fourth_min_time"
android:gravity="center_vertical"
android:layout_below="@+id/fourth_min_text"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>

View file

@ -309,6 +309,71 @@
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<RatingBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="3"
android:layout_gravity="center"
android:id="@+id/fourth_diff_bar"
android:layout_below="@+id/fourth_diff_text"
style="?android:attr/ratingBarStyleSmall"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="diffi"
android:id="@+id/fourth_diff_text"
android:gravity="center_vertical"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/average_time"
android:id="@+id/fourth_av_text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="@+id/fourth_ava_time"
android:gravity="center_vertical"
android:layout_below="@+id/fourth_av_text"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/min_time"
android:id="@+id/fourth_min_text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="@+id/fourth_min_time"
android:gravity="center_vertical"
android:layout_below="@+id/fourth_min_text"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>

View file

@ -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">
<!-- ### first row -->
<LinearLayout
@ -309,6 +309,71 @@
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<RatingBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="3"
android:layout_gravity="center"
android:id="@+id/fourth_diff_bar"
android:layout_below="@+id/fourth_diff_text"
style="?android:attr/ratingBarStyleSmall"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="diffi"
android:id="@+id/fourth_diff_text"
android:gravity="center_vertical"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/average_time"
android:id="@+id/fourth_av_text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="@+id/fourth_ava_time"
android:gravity="center_vertical"
android:layout_below="@+id/fourth_av_text"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/min_time"
android:id="@+id/fourth_min_text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="@+id/fourth_min_time"
android:gravity="center_vertical"
android:layout_below="@+id/fourth_min_text"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>

View file

@ -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">
<LinearLayout
android:layout_width="fill_parent"
@ -86,6 +86,7 @@
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
@ -105,7 +106,7 @@
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="4"
android:weightSum="3"
android:weightSum="4"
android:orientation="vertical">
<!-- ### first row -->
<LinearLayout
@ -310,6 +311,71 @@
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<RatingBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:numStars="3"
android:layout_gravity="center"
android:id="@+id/fourth_diff_bar"
android:layout_below="@+id/fourth_diff_text"
style="?android:attr/ratingBarStyleSmall"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="diffi"
android:id="@+id/fourth_diff_text"
android:gravity="center_vertical"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/average_time"
android:id="@+id/fourth_av_text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="@+id/fourth_ava_time"
android:gravity="center_vertical"
android:layout_below="@+id/fourth_av_text"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/min_time"
android:id="@+id/fourth_min_text"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:id="@+id/fourth_min_time"
android:gravity="center_vertical"
android:layout_below="@+id/fourth_min_text"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>

View file

@ -1,9 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/group4"
android:checkableBehavior="all">
<item android:id="@+id/nav_newgame_main" android:icon="@android:drawable/ic_menu_today"
android:title="@string/menu_main" />
<item android:id="@+id/nav_highscore_main" android:icon="@android:drawable/ic_menu_myplaces"
android:title="@string/menu_highscore" />
</group>
<group android:id="@+id/group2">
<group android:id="@+id/group2"
android:checkableBehavior="all">
<item android:id="@+id/menu_settings_main" android:icon="@android:drawable/ic_menu_manage"
android:title="@string/menu_settings" />
<item android:id="@+id/menu_help_main" android:icon="@android:drawable/ic_menu_help"

View file

@ -57,7 +57,7 @@
<!-- ###ABOUT### -->
<string name="app_name_long" translatable="false">Privacy Friendly Sudoku</string>
<string name="version_number" translatable="false">2.0.1</string>
<string name="version_number" translatable="false">2.1.1</string>
<string name="about_author">Author:</string>
<string name="about_author_names" translatable="false">Christopher Beckmann, Timm Lippert</string>
<string name="about_author_contributors">and contributors.</string>
@ -140,4 +140,6 @@
<string name="help_permissions_summary">Privacy Friendly Sudoku does not use any permissions.</string>
<string name="okay">Okay</string>
<string name="view_help">View Help</string>
<string name="difficulty_challenge">Challenge</string>
<string name="pref_highlightInputError">Highlight input mistakes</string>
</resources>

View file

@ -41,6 +41,11 @@
android:title="@string/pref_highlight_notes"
android:summary=""
android:defaultValue="true"/>
<SwitchPreference android:id="@+id/pref_highlightInputError"
android:key="pref_highlightInputError"
android:title="@string/pref_highlightInputError"
android:summary=""
android:defaultValue="true"/>
</PreferenceCategory>
<!-- NOTE: EditTextPreference accepts EditText attributes. -->

View file

@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.2'
classpath 'com.android.tools.build:gradle:2.3.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

View file

@ -1,6 +1,6 @@
#Wed Oct 05 22:51:31 CEST 2016
#Thu May 18 12:33:34 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip