From d038b41aae797266728304aa13e259ef70e1ce6f Mon Sep 17 00:00:00 2001 From: timo Date: Thu, 10 Aug 2017 22:52:33 +0200 Subject: [PATCH] 1.0.11c --- .../de/sudoq/test/CrossActivityTests.java | 4 +- .../java/de/sudoq/test/MenuTest.java | 10 +- .../java/de/sudoq/test/NormalFlowTest.java | 4 +- .../de/sudoq/test/SudokuActivityTests.java | 8 +- .../de/sudoq/test/SudokuInteractionTest.java | 6 +- .../sudoqapp/src/main/AndroidManifest.xml | 6 +- .../sudoq/controller/menus/MainActivity.java | 16 +- ...onActivity.java => NewSudokuActivity.java} | 4 +- .../controller/menus/ProfileListActivity.java | 2 +- .../controller/menus/SplashActivity.java | 147 +++++++++++------- .../menus/SudokuLoadingActivity.java | 6 +- .../AdvancedPreferencesActivity.java | 84 +++++++--- .../NewSudokuPreferencesActivity.java | 51 +++--- .../PlayerPreferencesActivity.java | 12 +- .../preferences/PreferencesActivity.java | 33 ++-- .../sudoku/board/FieldViewPainter.java | 23 ++- .../sudoku/hints/HintFormulator.java | 20 ++- .../java/de/sudoq/view/SudokuFieldView.java | 5 +- .../controller/menu/SplashUnitTests.java | 21 +++ .../sudoku/SudokuActivityTests.java | 0 .../de/sudoq/model/actionTree/Action.java | 4 +- .../de/sudoq/model/actionTree/ActionTree.java | 93 +++++------ .../model/actionTree/ActionTreeElement.java | 7 +- .../sudoq/model/actionTree/SolveAction.java | 8 + .../main/java/de/sudoq/model/game/Game.java | 22 +-- .../java/de/sudoq/model/game/GameManager.java | 2 +- .../de/sudoq/model/game/GameStateHandler.java | 97 +++++++++--- .../java/de/sudoq/model/profile/Profile.java | 2 +- .../java/de/sudoq/model/sudoku/Field.java | 2 +- .../de/sudoq/model/sudoku/PositionMap.java | 4 +- .../de/sudoq/model/sudoku/SudokuBuilder.java | 2 +- .../java/de/sudoq/model/xml/XmlAttribute.java | 2 + .../java/de/sudoq/model/xml/XmlHandler.java | 2 + .../ActionTreeAddElementsTests.java | 65 ++++++++ .../actionTree/ActionTreeIteratorTests.java | 45 +++++- .../model/actionTree/ActionTreeTests.java | 59 ++++--- .../model/game/GameStateHandlerTests.java | 43 ++++- .../java/de/sudoq/model/game/GameTests.java | 19 +-- 38 files changed, 638 insertions(+), 302 deletions(-) rename sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/{NewSudokuConfigurationActivity.java => NewSudokuActivity.java} (98%) create mode 100644 sudoq-app/sudoqapp/src/tests/java/de/sudoq/controller/menu/SplashUnitTests.java rename sudoq-app/sudoqapp/src/{test => tests}/java/de/sudoq/controller/sudoku/SudokuActivityTests.java (100%) create mode 100644 sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeAddElementsTests.java diff --git a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/CrossActivityTests.java b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/CrossActivityTests.java index 638e58f5..aa1cb990 100644 --- a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/CrossActivityTests.java +++ b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/CrossActivityTests.java @@ -3,7 +3,7 @@ import android.app.Activity; import de.sudoq.R; import de.sudoq.controller.menus.MainActivity; -import de.sudoq.controller.menus.NewSudokuConfigurationActivity; +import de.sudoq.controller.menus.NewSudokuActivity; import de.sudoq.controller.sudoku.SudokuActivity; public class CrossActivityTests extends SudoqTestCase { @@ -28,7 +28,7 @@ public void testSudokuStarting() { * assert we're in the right activity */ solo.clickOnText(newSudoku); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); assertTrue(solo.searchText(a.getString(R.string.complexity_easy))); assertTrue(solo.searchText(a.getString(R.string.sudoku_type_standard_9x9))); assertTrue(solo.searchText(a.getString(R.string.sf_sudokupreferences_start))); diff --git a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/MenuTest.java b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/MenuTest.java index 7d8c343a..c722c0b4 100644 --- a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/MenuTest.java +++ b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/MenuTest.java @@ -9,7 +9,7 @@ import de.sudoq.controller.menus.MainActivity; import de.sudoq.controller.menus.StatisticsActivity; import de.sudoq.controller.menus.SudokuLoadingActivity; -import de.sudoq.controller.menus.NewSudokuConfigurationActivity; +import de.sudoq.controller.menus.NewSudokuActivity; import de.sudoq.controller.menus.preferences.PlayerPreferencesActivity; import de.sudoq.controller.sudoku.SudokuActivity; @@ -32,7 +32,7 @@ public void testMenus() { assertTrue(solo.searchText(profile)); solo.clickOnText(newSudoku); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); assertTrue(solo.searchText(a.getString(R.string.complexity_easy))); assertTrue(solo.searchText(a.getString(R.string.sudoku_type_standard_9x9))); assertTrue(solo.searchText(a.getString(R.string.sf_sudokupreferences_start))); @@ -63,7 +63,7 @@ public void testMenus() { public void testAssistanceBeforeSudoku() { solo.sleep(2000); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_mainmenu_new_sudoku)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_sudokupreferences_assistances)); // solo.assertCurrentActivity("should be playerpreferences", @@ -74,7 +74,7 @@ public void testAssistanceBeforeSudoku() { // solo.clickOnCheckBox(checkBox.getId()); // solo.clickOnCheckBox(checkBox.getId()); solo.clickOnText(solo.getCurrentActivity().getString(R.string.profile_preference_button_save)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_sudokupreferences_start)); solo.assertCurrentActivity("should be in sudoku", SudokuActivity.class); @@ -105,7 +105,7 @@ public void testSudokuLoading() { Activity a = solo.getCurrentActivity(); solo.clickOnText(a.getString(R.string.sf_mainmenu_new_sudoku)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_sudokupreferences_start)); solo.assertCurrentActivity("should be in sudoku", SudokuActivity.class); solo.goBack(); diff --git a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/NormalFlowTest.java b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/NormalFlowTest.java index 79c745e3..b547d383 100644 --- a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/NormalFlowTest.java +++ b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/NormalFlowTest.java @@ -2,7 +2,7 @@ import android.app.Activity; import de.sudoq.R; -import de.sudoq.controller.menus.NewSudokuConfigurationActivity; +import de.sudoq.controller.menus.NewSudokuActivity; import de.sudoq.controller.sudoku.SudokuActivity; /** @@ -16,7 +16,7 @@ public void testStartTheGame() { Activity a = getActivity(); solo.clickOnText(a.getString(R.string.sf_mainmenu_new_sudoku)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); assertTrue(solo.searchText(a.getString(R.string.complexity_easy))); assertTrue(solo.searchText(a.getString(R.string.sudoku_type_standard_9x9))); assertTrue(solo.searchText(a.getString(R.string.sf_sudokupreferences_start))); diff --git a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/SudokuActivityTests.java b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/SudokuActivityTests.java index 158aa743..c4b65587 100644 --- a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/SudokuActivityTests.java +++ b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/SudokuActivityTests.java @@ -2,7 +2,7 @@ import android.view.View; import de.sudoq.R; -import de.sudoq.controller.menus.NewSudokuConfigurationActivity; +import de.sudoq.controller.menus.NewSudokuActivity; import de.sudoq.controller.sudoku.SudokuActivity; import de.sudoq.view.SudokuFieldView; @@ -11,7 +11,7 @@ public class SudokuActivityTests extends SudoqTestCase { // AT20 public void testSudokuSolveHelp() { solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_mainmenu_new_sudoku)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_sudokupreferences_start)); solo.assertCurrentActivity("should be in sudoku", SudokuActivity.class); @@ -27,7 +27,7 @@ public void testSudokuSolveHelp() { // AT 40 public void testSudokuTime() { solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_mainmenu_new_sudoku)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_sudokupreferences_start)); solo.assertCurrentActivity("should be in sudoku", SudokuActivity.class); @@ -66,7 +66,7 @@ public void testSudokuTime() { // AT80 public void testIsValidToast() { solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_mainmenu_new_sudoku)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_sudokupreferences_start)); solo.assertCurrentActivity("should be in sudoku", SudokuActivity.class); diff --git a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/SudokuInteractionTest.java b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/SudokuInteractionTest.java index b61d1e50..ae4256bf 100644 --- a/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/SudokuInteractionTest.java +++ b/sudoq-app/sudoqapp/src/androidTest/java/de/sudoq/test/SudokuInteractionTest.java @@ -1,7 +1,7 @@ package de.sudoq.test; import de.sudoq.R; -import de.sudoq.controller.menus.NewSudokuConfigurationActivity; +import de.sudoq.controller.menus.NewSudokuActivity; import de.sudoq.controller.sudoku.SudokuActivity; import de.sudoq.model.profile.Profile; import de.sudoq.model.sudoku.Field; @@ -13,7 +13,7 @@ public class SudokuInteractionTest extends SudoqTestCase { // MT30-MT80, MT100 public void testFieldSelection() { solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_mainmenu_new_sudoku)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_sudokupreferences_start)); solo.assertCurrentActivity("should be in sudoku", SudokuActivity.class); @@ -85,7 +85,7 @@ public void testFieldSelection() { // AT100 public void testUndoRedo() { solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_mainmenu_new_sudoku)); - solo.assertCurrentActivity("should be sudokupreferences", NewSudokuConfigurationActivity.class); + solo.assertCurrentActivity("should be sudokupreferences", NewSudokuActivity.class); solo.clickOnText(solo.getCurrentActivity().getString(R.string.sf_sudokupreferences_start)); solo.assertCurrentActivity("should be in sudoku", SudokuActivity.class); diff --git a/sudoq-app/sudoqapp/src/main/AndroidManifest.xml b/sudoq-app/sudoqapp/src/main/AndroidManifest.xml index f512edc4..43013318 100644 --- a/sudoq-app/sudoqapp/src/main/AndroidManifest.xml +++ b/sudoq-app/sudoqapp/src/main/AndroidManifest.xml @@ -5,8 +5,8 @@ @@ -26,7 +26,7 @@ - + Profile.NO_GAME); + + GameManager gm = GameManager.getInstance(); Button loadButton = (Button) findViewById(R.id.button_mainmenu_load_sudoku); - loadButton.setEnabled(p.getCurrentGame() > Profile.NO_GAME); + loadButton.setEnabled(!gm.getGameList().isEmpty()); } @@ -80,7 +83,7 @@ public void onResume() { public void switchActivity(View button) { switch (button.getId()) { case R.id.button_mainmenu_new_sudoku: - Intent newSudokuIntent = new Intent(this, NewSudokuConfigurationActivity.class); + Intent newSudokuIntent = new Intent(this, NewSudokuActivity.class); startActivity(newSudokuIntent); break; @@ -101,13 +104,4 @@ public void switchActivity(View button) { break; } } - - /* - * {@inheritDoc} - */ - // @Override - // public void onConfigurationChanged(Configuration newConfig) { - // super.onConfigurationChanged(newConfig); - // setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - // } } diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/NewSudokuConfigurationActivity.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/NewSudokuActivity.java similarity index 98% rename from sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/NewSudokuConfigurationActivity.java rename to sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/NewSudokuActivity.java index a5941321..3734f8a2 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/NewSudokuConfigurationActivity.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/NewSudokuActivity.java @@ -42,11 +42,11 @@ * * Hauptmenü -> "neues Sudoku" führt hierher */ -public class NewSudokuConfigurationActivity extends SudoqCompatActivity { +public class NewSudokuActivity extends SudoqCompatActivity { /** Attributes */ - private static final String LOG_TAG = NewSudokuConfigurationActivity.class.getSimpleName(); + private static final String LOG_TAG = NewSudokuActivity.class.getSimpleName(); private SudokuTypes sudokuType; diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/ProfileListActivity.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/ProfileListActivity.java index d5d10003..71ee86ed 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/ProfileListActivity.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/ProfileListActivity.java @@ -51,7 +51,7 @@ public class ProfileListActivity extends SudoqListActivity implements OnItemClic @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); -setContentView(R.layout.profilelist); + setContentView(R.layout.profilelist); this.setTitle(this.getString(R.string.action_switch_profile)); profileIds = Profile.getInstance().getProfilesIdList(); diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/SplashActivity.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/SplashActivity.java index 06dc8b7d..e0809be6 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/SplashActivity.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/SplashActivity.java @@ -23,6 +23,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import de.sudoq.R; import de.sudoq.controller.SudoqCompatActivity; @@ -74,34 +76,15 @@ public class SplashActivity extends SudoqCompatActivity { private final static String HEAD_DIRECTORY = "sudokus"; - private final static String INIIALIZED_TAG = "Initialized"; + private final static String INITIALIZED_TAG = "Initialized"; private final static String VERSION_TAG = "version"; private final static String NO_VERSION_YET = "0.0.0"; - private final static String NEWEST_ASSET_VERSION = "1.0.6"; + protected final static String NEWEST_ASSET_VERSION = "1.0.6"; + + private static String currentVersionName = ""; - private static String currentVersionValue = ""; - /* is version a older than b? - * a,b = "x.y.z" */ - boolean older(String a, String b){ - String[] aTokenized = a.split("[.]"); - String[] bTokenized = b.split("[.]"); - assert aTokenized.length == bTokenized.length; - - for(int i=0; i< aTokenized.length; i++){ - int aTok = Integer.parseInt(aTokenized[i]); - int bTok = Integer.parseInt(bTokenized[i]); - - if(aTok < bTok) - return true; - else if(aTok > bTok) - return false; - } - - return false; - } - /** * {@inheritDoc} */ @@ -129,42 +112,19 @@ public void onCreate(Bundle savedInstanceState) { SharedPreferences settings = getSharedPreferences("Prefs", 0); /* get version value */ - try - { - currentVersionValue = this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName; - } catch (NameNotFoundException e) - { + try { + currentVersionName = this.getPackageManager().getPackageInfo(this.getPackageName(), 0).versionName; + } catch (NameNotFoundException e) { Log.v(LOG_TAG, e.getMessage()); } /* is this a new version? */ String oldVersionName = settings.getString(VERSION_TAG, NO_VERSION_YET); - /* Specifies whether this is a regular start or an assets-update, i.e. version has changed and assets have to be copied*/ - Boolean updateSituation = older(oldVersionName, NEWEST_ASSET_VERSION); - if (updateSituation && !this.startedCopying) { + if (updateSituation(oldVersionName) && !this.startedCopying) { /*hint*/ - try { - String[] l = getAssets().list(""); - boolean foundSudokusinAssetfolder = Arrays.asList(l).contains(HEAD_DIRECTORY); - //TODO make this work: - //boolean fsaf = Stream.of(l).anyMatch(s -> s.equals(HEAD_DIRECTORY)); - if(!foundSudokusinAssetfolder){ - String msg = "This app will probably crash once you try to start a new sudoku. "+ - "This is because the person who compiled this app forgot about the 'assets' folder. "+ - "Please tell him that!"; - Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); - Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); - Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); - } - //Toast.makeText(this, l[0].equals(HEAD_DIRECTORY)+"", Toast.LENGTH_SHORT).show(); - - } catch (IOException e1) { - // TODO Auto-generated catch block - e1.printStackTrace(); - } - /*end of hint*/ + alertIfNoAssetFolder(); Log.v(LOG_TAG, "we will do an initialization"); new Initialization().execute(null, null, null); @@ -192,6 +152,87 @@ public void run() { splashThread.start(); } + /* Specifies whether this is a regular start or an assets-update, + * i.e. version has changed and assets have to be copied + * + * 'protected' for unit test + */ + protected boolean updateSituation(String oldVersionName) { + Boolean updateSituation; + try { + updateSituation = older(oldVersionName, NEWEST_ASSET_VERSION); + }catch(Exception e){ + updateSituation = true; //when in doubt DO an update! + } + return updateSituation; + } + + + /** is version a older than b? + * a,b = "12.68.87(abc..)" **/ + boolean older(String a, String b) throws Exception { + int[] aTokenized = versionToNumbers(a); + int[] bTokenized = versionToNumbers(b); + assert aTokenized.length == bTokenized.length; + + for(int i=0; i< aTokenized.length; i++){ + int aTok = aTokenized[i]; + int bTok = bTokenized[i]; + + if(aTok < bTok) + return true; + else if(aTok > bTok) + return false; + } + + return false; + } + + private int[] versionToNumbers (String version) throws Exception { + String pattern = "(\\d+)[.](\\d+)[.](\\d+)([a-z]?)"; + Pattern r = Pattern.compile(pattern); + Matcher m = r.matcher(version); + m.find(); + + int[] result = new int[4]; + + if (m.groupCount()==4) { + String letter = m.group(4); + if (letter.length() == 1) + result[3] = letter.charAt(0) - 'a' + 1; + } + + for(int i : new int[]{1, 2, 3}) + result[i-1] = Integer.parseInt(m.group(i)); + + + return result; + } + + + private void alertIfNoAssetFolder(){ + try { + String[] l = getAssets().list(""); + boolean foundSudokusInAssetfolder = Arrays.asList(l).contains(HEAD_DIRECTORY); + //TODO make this work: + //boolean fsaf = Stream.of(l).anyMatch(s -> s.equals(HEAD_DIRECTORY)); + if(!foundSudokusInAssetfolder){ + String msg = "This app will probably crash once you try to start a new sudoku. "+ + "This is because the person who compiled this app forgot about the 'assets' folder. "+ + "Please tell him that!"; + Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); + Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); + Toast.makeText(this, msg, Toast.LENGTH_LONG).show(); + } + //Toast.makeText(this, l[0].equals(HEAD_DIRECTORY)+"", Toast.LENGTH_SHORT).show(); + + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + + /** * Speichert die bereits im Splash gewartete Zeit. */ @@ -259,8 +300,8 @@ private class Initialization extends AsyncTask { @Override public void onPostExecute(Void v) { SharedPreferences settings = getSharedPreferences("Prefs", 0); - settings.edit().putBoolean(INIIALIZED_TAG, true).commit(); - settings.edit().putString(VERSION_TAG, currentVersionValue).commit(); + settings.edit().putBoolean(INITIALIZED_TAG, true).commit(); + settings.edit().putString(VERSION_TAG, currentVersionName).commit(); Log.d(LOG_TAG, "Assets completely copied"); } diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/SudokuLoadingActivity.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/SudokuLoadingActivity.java index f4849ec4..a35335f6 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/SudokuLoadingActivity.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/SudokuLoadingActivity.java @@ -56,11 +56,11 @@ public class SudokuLoadingActivity extends SudoqListActivity implements OnItemCl private List games; - protected static MenuItem menuDeleteFinished; +/* protected static MenuItem menuDeleteFinished; private static final int MENU_DELETE_FINISHED = 0; protected static MenuItem menuDeleteSpecific; - private static final int MENU_DELETE_SPECIFIC = 1; + private static final int MENU_DELETE_SPECIFIC = 1; commented out to make sure it's not needed*/ private enum FAB_STATES { DELETE, INACTIVE, GO_BACK}; @@ -185,6 +185,8 @@ public void onConfigurationChanged(Configuration newConfig) { public void onContentChanged() { super.onContentChanged(); initialiseGames(); + Profile.getInstance().setCurrentGame(adapter.isEmpty() ? -1 + : adapter.getItem(0).getId()); } diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/AdvancedPreferencesActivity.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/AdvancedPreferencesActivity.java index 4614d301..6f358b9a 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/AdvancedPreferencesActivity.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/AdvancedPreferencesActivity.java @@ -13,7 +13,6 @@ import android.os.Bundle; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; -import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -22,9 +21,13 @@ import android.widget.CheckBox; import de.sudoq.R; +import de.sudoq.controller.menus.NewSudokuActivity; +import de.sudoq.model.game.Assistances; import de.sudoq.model.game.GameSettings; import de.sudoq.model.profile.Profile; +import static de.sudoq.controller.menus.preferences.AdvancedPreferencesActivity.ParentActivity.NOT_SPECIFIED; + /** * Activity um Profile zu bearbeiten und zu verwalten * @@ -32,11 +35,18 @@ public class AdvancedPreferencesActivity extends PreferencesActivity { /** Attributes */ private static final String LOG_TAG = AdvancedPreferencesActivity.class.getSimpleName(); - - /*this is a hack! activity can be called in sudoku-pref and in profile, but has different behaviours*/ - public static PreferencesActivity myCaller; - //public static GameSettings gameSettings; - + + public enum ParentActivity{PROFILE,NEW_SUDOKU,NOT_SPECIFIED}; + + /*this is still a hack! this activity can be called in newSudoku-pref and in player(profile)Pref, but has different behaviours*/ + public static ParentActivity caller= NOT_SPECIFIED; + + public static GameSettings gameSettings; + + CheckBox helper; + CheckBox lefthand; + Button restricttypes; + /** * Wird aufgerufen, falls die Activity zum ersten Mal gestartet wird. Läd * die Preferences anhand der zur Zeit aktiven Profil-ID. @@ -54,13 +64,22 @@ public void onCreate(Bundle savedInstanceState) { ab.setDisplayShowTitleEnabled(true); - myCaller.helper = (CheckBox) findViewById(R.id.checkbox_hints_provider); - myCaller.lefthand = (CheckBox) findViewById(R.id.checkbox_lefthand_mode); - myCaller.restricttypes = (Button) findViewById(R.id.button_provide_restricted_set_of_types); - - GameSettings a = Profile.getInstance().getAssistances(); - myCaller.helper. setChecked(a.isHelperSet()); - myCaller.lefthand. setChecked(a.isLefthandModeSet()); + helper = (CheckBox) findViewById(R.id.checkbox_hints_provider); + lefthand = (CheckBox) findViewById(R.id.checkbox_lefthand_mode); + restricttypes = (Button) findViewById(R.id.button_provide_restricted_set_of_types); + gameSettings = NewSudokuActivity.gameSettings; + GameSettings profileGameSettings = Profile.getInstance().getAssistances(); + + switch (caller){ + case NEW_SUDOKU: + helper. setChecked(gameSettings.isHelperSet()); + lefthand.setChecked(gameSettings.isLefthandModeSet()); + break; + case PROFILE: + case NOT_SPECIFIED://not specified souldn't happen, but you never know + helper. setChecked(profileGameSettings.isHelperSet()); + lefthand.setChecked(profileGameSettings.isLefthandModeSet()); + } //myCaller.restricttypes.setChecked(a.isreHelperSet()); Profile.getInstance().registerListener(this); @@ -78,8 +97,9 @@ protected void refreshValues() { } /** - * Wird beim Buttonklick aufgerufen und erstellt ein neues Profil - * + * Selected by click on button (specified in layout file) + * Starts new activity that lets user choose which types are offered in 'new sudoku' menu + * * @param view * von android xml übergebene View */ @@ -117,8 +137,37 @@ public void onClick(DialogInterface dialog, int which) { alertDialog.show(); } + @Override + protected void adjustValuesAndSave() { + switch(caller){ + case NEW_SUDOKU://TODO just have 2 subclasses, one to be called from playerpref, one from newSudokuPref + saveToGameSettings(); + break; + case PROFILE: + saveToProfile(); + break; + } + } + + private void saveToGameSettings(){ + if(lefthand != null && helper != null){ + gameSettings.setLefthandMode(lefthand.isChecked()); + gameSettings.setHelper(helper.isChecked()); + } + } + + protected void saveToProfile() { + Profile p = Profile.getInstance(); + if(helper != null) + p.setHelperActive(helper.isChecked()); + if(lefthand != null) + p.setLefthandActive(lefthand.isChecked()); + //restrict types is automatically saved to profile... + Profile.getInstance().saveChanges(); + } - // ///////////////////////////////////////optionsMenue + + // ///////////////////////////////////////optionsMenue @Override public boolean onCreateOptionsMenu(Menu menu) { @@ -145,6 +194,5 @@ public boolean onPrepareOptionsMenu(Menu menu) { return true; } - @Override - protected void adjustValuesAndSave() {} + } \ No newline at end of file diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/NewSudokuPreferencesActivity.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/NewSudokuPreferencesActivity.java index 724dd881..5b97d84b 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/NewSudokuPreferencesActivity.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/NewSudokuPreferencesActivity.java @@ -15,7 +15,7 @@ import android.widget.CheckBox; import de.sudoq.R; -import de.sudoq.controller.menus.NewSudokuConfigurationActivity; +import de.sudoq.controller.menus.NewSudokuActivity; import de.sudoq.model.game.Assistances; import de.sudoq.model.game.GameSettings; import de.sudoq.model.profile.Profile; @@ -25,7 +25,7 @@ */ public class NewSudokuPreferencesActivity extends PreferencesActivity { - /* shortcut for NewSudokuConfigurationActivity.gameSettings */ + /* shortcut for NewSudokuActivity.gameSettings */ GameSettings confSettings; /** @@ -51,8 +51,8 @@ public void onCreate(Bundle savedInstanceState) { markWrongSymbol = (CheckBox) findViewById(R.id.checkbox_markWrongSymbol); restrictCandidates = (CheckBox) findViewById(R.id.checkbox_restrictCandidates); - confSettings = NewSudokuConfigurationActivity.gameSettings; - gesture. setChecked(confSettings.isGesturesSet()); + confSettings = NewSudokuActivity.gameSettings; + gesture. setChecked(confSettings.isGesturesSet()); autoAdjustNotes. setChecked(confSettings.getAssistance(Assistances.autoAdjustNotes)); markRowColumn. setChecked(confSettings.getAssistance(Assistances.markRowColumn)); markWrongSymbol. setChecked(confSettings.getAssistance(Assistances.markWrongSymbol)); @@ -77,32 +77,22 @@ protected void refreshValues() { /** - * Speichert die Werte der Views in gameSettings + * Saves currend state of buttons/checkboxes to gameSettings */ protected void adjustValuesAndSave() { - NewSudokuConfigurationActivity.gameSettings.setGestures(gesture.isChecked()); - saveCheckbox(autoAdjustNotes, Assistances.autoAdjustNotes); - saveCheckbox(markRowColumn, Assistances.markRowColumn); - saveCheckbox(markWrongSymbol, Assistances.markWrongSymbol); - saveCheckbox(restrictCandidates, Assistances.restrictCandidates); - if(lefthand != null && helper != null){ - confSettings.setLefthandMode(lefthand.isChecked()); - confSettings.setHelper(helper.isChecked()); - } + confSettings.setGestures(gesture.isChecked()); + saveCheckbox(autoAdjustNotes, Assistances.autoAdjustNotes, confSettings); + saveCheckbox(markRowColumn, Assistances.markRowColumn, confSettings); + saveCheckbox(markWrongSymbol, Assistances.markWrongSymbol, confSettings); + saveCheckbox(restrictCandidates, Assistances.restrictCandidates, confSettings); Profile.getInstance().saveChanges(); } - private void saveCheckbox(CheckBox cb, Assistances a){ - if(cb.isChecked()) - confSettings.setAssistance(a); - else - confSettings.clearAssistance(a); - } + /** - * Speichert die Profiländerungen. - * TODO make it so: save it in the profile + * Speichert die Profiländerungen * @param view * unbenutzt */ @@ -111,12 +101,27 @@ public void saveChanges(View view) { onBackPressed();//go back to parent activity } + protected void saveToProfile() { + Profile p = Profile.getInstance(); + + p.setGestureActive(gesture.isChecked()); + saveAssistance(Assistances.autoAdjustNotes, autoAdjustNotes); + saveAssistance(Assistances.markRowColumn, markRowColumn ); + saveAssistance(Assistances.markWrongSymbol, markWrongSymbol); + saveAssistance(Assistances.restrictCandidates, restrictCandidates); + + p.setHelperActive(confSettings.isHelperSet()); + p.setLefthandActive(confSettings.isLefthandModeSet()); + + //restrict types is automatically saved to profile... + Profile.getInstance().saveChanges(); + } /* parameter View only needed to be foud by xml who clicks this*/ public void switchToAdvancedPreferences(View view){ Intent advIntent = new Intent(this, AdvancedPreferencesActivity.class); - AdvancedPreferencesActivity.myCaller=this; + AdvancedPreferencesActivity.caller= AdvancedPreferencesActivity.ParentActivity.NEW_SUDOKU; startActivity(advIntent); } diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/PlayerPreferencesActivity.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/PlayerPreferencesActivity.java index 70396569..6e54b634 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/PlayerPreferencesActivity.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/PlayerPreferencesActivity.java @@ -157,11 +157,21 @@ protected void adjustValuesAndSave() { saveToProfile(); } + protected void saveToProfile() { + Profile p = Profile.getInstance(); + p.setGestureActive(gesture.isChecked()); + saveAssistance(Assistances.autoAdjustNotes, autoAdjustNotes); + saveAssistance(Assistances.markRowColumn, markRowColumn ); + saveAssistance(Assistances.markWrongSymbol, markWrongSymbol); + saveAssistance(Assistances.restrictCandidates, restrictCandidates); + Profile.getInstance().saveChanges(); + } + /* parameter View only needed to be found by xml who clicks this */ public void switchToAdvancedPreferences(View view){ Intent advIntent = new Intent(this, AdvancedPreferencesActivity.class); - AdvancedPreferencesActivity.myCaller=this; + AdvancedPreferencesActivity.caller= AdvancedPreferencesActivity.ParentActivity.PROFILE; //AdvancedPreferencesActivity.gameSettings = this.gameSettings; startActivity(advIntent); diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/PreferencesActivity.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/PreferencesActivity.java index 8af2c10b..5b3dbeb9 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/PreferencesActivity.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/menus/preferences/PreferencesActivity.java @@ -9,6 +9,7 @@ import de.sudoq.controller.menus.GestureBuilder; import de.sudoq.model.ModelChangeListener; import de.sudoq.model.game.Assistances; +import de.sudoq.model.game.GameSettings; import de.sudoq.model.profile.Profile; public abstract class PreferencesActivity extends SudoqCompatActivity implements ModelChangeListener { @@ -19,8 +20,8 @@ public abstract class PreferencesActivity extends SudoqCompatActivity implements CheckBox markWrongSymbol; CheckBox restrictCandidates; - CheckBox helper; - CheckBox lefthand; + //CheckBox helper; + //CheckBox lefthand; Button restricttypes; @@ -64,31 +65,17 @@ public void onModelChanged(Profile obj) { this.refreshValues(); } - protected void saveToProfile() { - Profile p = Profile.getInstance(); - p.setGestureActive(gesture.isChecked()); - if(helper != null) - p.setHelperActive(helper.isChecked()); - if(lefthand != null) - p.setLefthandActive(lefthand.isChecked()); - saveAssistance(Assistances.autoAdjustNotes, autoAdjustNotes); - saveAssistance(Assistances.markRowColumn, markRowColumn ); - saveAssistance(Assistances.markWrongSymbol, markWrongSymbol); - saveAssistance(Assistances.restrictCandidates, restrictCandidates); - Profile.getInstance().saveChanges(); - } + abstract protected void saveToProfile(); - private void saveAssistance(Assistances a, CheckBox c){ + protected void saveAssistance(Assistances a, CheckBox c){ Profile.getInstance().setAssistance(a, c.isChecked()); } - /* parameter View only needed to be foud by xml who clicks this*/ - public void switchToAdvancedPreferences(View view){ - - Intent advIntent = new Intent(this, AdvancedPreferencesActivity.class); - AdvancedPreferencesActivity.myCaller=this; - startActivity(advIntent); + protected void saveCheckbox(CheckBox cb, Assistances a, GameSettings gs){ + if(cb.isChecked()) + gs.setAssistance(a); + else + gs.clearAssistance(a); } - } \ No newline at end of file diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/sudoku/board/FieldViewPainter.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/sudoku/board/FieldViewPainter.java index 28ba7b48..7f334fe9 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/sudoku/board/FieldViewPainter.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/sudoku/board/FieldViewPainter.java @@ -179,8 +179,29 @@ public void markField(Canvas canvas, View field, String symbol, boolean justText } } //Log.d("FieldPainter", "Field drawn"); - sl.getHintPainter().invalidateAll();//invalidate(); + try { + sl.getHintPainter().invalidateAll();//invalidate(); + }catch(NullPointerException e){ + /* + I don't see how this happens but a nullpointer exception was reported, so I made a try-catch-block here: + reported at version 20 + This happens when 'gesture' is clicked in profile without playing a game first. sl is then null + java.lang.NullPointerException: + at de.sudoq.controller.sudoku.board.FieldViewPainter.markField (FieldViewPainter.java:182) + at de.sudoq.view.VirtualKeyboardButtonView.onDraw (VirtualKeyboardButtonView.java:104) + at android.view.View.draw (View.java:17469) + at android.view.View.updateDisplayListIfDirty (View.java:16464) + at android.view.View.draw (View.java:17238) + at android.view.ViewGroup.drawChild (ViewGroup.java:3921) + at android.view.ViewGroup.dispatchDraw (ViewGroup.java:3711) + at android.view.View.updateDisplayListIfDirty (View.java:16459) + at android.view.View.draw (View.java:17238) + at android.view.ViewGroup.drawChild (ViewGroup.java:3921) + at android.view.ViewGroup.dispatchDraw (ViewGroup.java:3711) + ... + */ + } } diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/sudoku/hints/HintFormulator.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/sudoku/hints/HintFormulator.java index 84872ccf..873f3502 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/sudoku/hints/HintFormulator.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/controller/sudoku/hints/HintFormulator.java @@ -71,12 +71,9 @@ public static String getText(Context context, SolveDerivation sd){ case Backtracking: text = context.getString(R.string.hint_backtracking); - Sudoku sudoku = ((SudokuActivity) context).getGame().getSudoku(); - for (Field f : sudoku) - if (f.isCompletelyEmpty()){ - text += context.getString(R.string.hint_fill_out_notes); - break; - } + if(aFieldIsEmpty((SudokuActivity) context)) + text += context.getString(R.string.hint_fill_out_notes); + break; default: @@ -85,6 +82,17 @@ public static String getText(Context context, SolveDerivation sd){ return text; } + private static boolean aFieldIsEmpty(SudokuActivity sActivity){ + Sudoku sudoku = sActivity.getGame().getSudoku(); + for (Field f : sudoku) + if (f.isCompletelyEmpty()){ + return true; + } + return false; + } + + + private static String lastDigitText(Context context, SolveDerivation sd){ LastDigitDerivation d = (LastDigitDerivation) sd; String shapeString = Utility.constraintShapeAccDet2string(context, d.getConstraintShape()); diff --git a/sudoq-app/sudoqapp/src/main/java/de/sudoq/view/SudokuFieldView.java b/sudoq-app/sudoqapp/src/main/java/de/sudoq/view/SudokuFieldView.java index c17a353f..cd49d28c 100644 --- a/sudoq-app/sudoqapp/src/main/java/de/sudoq/view/SudokuFieldView.java +++ b/sudoq-app/sudoqapp/src/main/java/de/sudoq/view/SudokuFieldView.java @@ -179,7 +179,10 @@ private void drawNotes(Canvas canvas) { for (int i = 0; i < Symbol.getInstance().getNumberOfSymbols(); i++) { if (this.field.isNoteSet(i)) { String note = Symbol.getInstance().getMapping(i); - canvas.drawText(note + "", (i % Symbol.getInstance().getRasterSize()) * noteTextSize + noteTextSize / 2, (i / Symbol.getInstance().getRasterSize()) * noteTextSize + noteTextSize, notePaint); + canvas.drawText(note + "", + (i % Symbol.getInstance().getRasterSize()) * noteTextSize + noteTextSize / 2, + (i / Symbol.getInstance().getRasterSize()) * noteTextSize + noteTextSize, + notePaint); } } } diff --git a/sudoq-app/sudoqapp/src/tests/java/de/sudoq/controller/menu/SplashUnitTests.java b/sudoq-app/sudoqapp/src/tests/java/de/sudoq/controller/menu/SplashUnitTests.java new file mode 100644 index 00000000..13fa180a --- /dev/null +++ b/sudoq-app/sudoqapp/src/tests/java/de/sudoq/controller/menu/SplashUnitTests.java @@ -0,0 +1,21 @@ +package de.sudoq.test; + +/** + * Created by timo on 11.05.17. + */ + +import org.junit.Test; + +import de.sudoq.controller.menus.SplashActivity; + +import static org.junit.Assert.assertTrue; + + +public class SplashUnitTests extends SplashActivity { + + @Test + public void testInit() { + assertTrue(updateSituation("dummy")); + + } +} diff --git a/sudoq-app/sudoqapp/src/test/java/de/sudoq/controller/sudoku/SudokuActivityTests.java b/sudoq-app/sudoqapp/src/tests/java/de/sudoq/controller/sudoku/SudokuActivityTests.java similarity index 100% rename from sudoq-app/sudoqapp/src/test/java/de/sudoq/controller/sudoku/SudokuActivityTests.java rename to sudoq-app/sudoqapp/src/tests/java/de/sudoq/controller/sudoku/SudokuActivityTests.java diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/Action.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/Action.java index 61bea68a..d3427a91 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/Action.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/Action.java @@ -68,6 +68,9 @@ protected Action(int diff, Field field) { public int getFieldId() { return field.getId(); } + public Field getField() { + return field; + } /** * {@inheritDoc} @@ -83,5 +86,4 @@ public boolean equals(Object o) { public abstract boolean inverse(Action a); - } diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/ActionTree.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/ActionTree.java index 88c03997..a9ebfe82 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/ActionTree.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/ActionTree.java @@ -15,6 +15,7 @@ import de.sudoq.model.ModelChangeListener; import de.sudoq.model.ObservableModelImpl; +import de.sudoq.model.sudoku.Field; /** * Diese Klasse repräsentiert die Menge aller Züge auf einem Sudoku. Sie erlaubt @@ -33,6 +34,10 @@ public class ActionTree extends ObservableModelImpl implement */ private int idCounter; + public enum InsertStrategy {redundant, undo, upwards, regular, none}; + private InsertStrategy lastStrategy = InsertStrategy.none; + public InsertStrategy getLastInsertStrategy(){return lastStrategy;} + private List actionSequence = new ArrayList<>(); /** Constructors */ /** @@ -40,7 +45,12 @@ public class ActionTree extends ObservableModelImpl implement */ public ActionTree() { idCounter = 1; - rootElement = null; + Action mockAction = new Action(0, new Field(-1, 1)) { + public void undo() { } + public void execute() { } + public boolean inverse(Action a){ return false; } + }; + rootElement = new ActionTreeElement(idCounter++, mockAction, rootElement); } /** Methods */ @@ -65,60 +75,26 @@ public ActionTreeElement add(Action action, ActionTreeElement mountingElement) { if (rootElement != null && mountingElement == null) { throw new IllegalArgumentException(); //There'a a root but no mounting el? -> throw exception } + ActionTreeElement ate; /* */ - if(isActionRedundant(mountingElement, action)) - { - ate = findExistingChildren(mountingElement, action).get(0); - }else if(isActionAStepBack(mountingElement, action)){ - ate = mountingElement; - }else if(isActionOnSameField(mountingElement, action)){ - ate = new ActionTreeElement(idCounter, action, mountingElement.getParent()); - idCounter++; - }else{ - ate = new ActionTreeElement(idCounter, action, mountingElement); - idCounter++; - } - + ate = new ActionTreeElement(idCounter, action, mountingElement); + idCounter++; + if (rootElement==null) { - rootElement = ate; //if there's no root, ate is root + rootElement = ate; //if there's no root, ate is root TODO as of now theres never a null root right? } notifyListeners(ate); - + //actionSequence.clear(); return ate; } - /* check if action already in Tree, - i.e. we went back in actionTree but are doing same steps again */ - private boolean isActionRedundant(ActionTreeElement mountingElement, Action action){ - - return !findExistingChildren(mountingElement, action).isEmpty(); - } - - private List findExistingChildren(ActionTreeElement mountingElement, Action action){ - List l = new Stack<>(); - if (mountingElement != null) { - for(ActionTreeElement ateI : mountingElement.getChildrenList()) - if(ateI.actionEquals(action)) - l.add(ateI); - - } - return l; - } - - private boolean isActionAStepBack(ActionTreeElement mountingElement, Action action) { - return mountingElement.getAction().inverse(action); - } - - private boolean isActionOnSameField(ActionTreeElement mountingElement, Action action) { - return mountingElement.getAction().field.equals(action.field); - } /** @@ -152,14 +128,6 @@ public int getSize() { return idCounter - 1; } - /** - * Gibt zurück ob der Baum leer ist - * - * @return true falls er leer ist, false falls Elemente enthalten sind - */ - public boolean isEmpty() { - return idCounter == 1; - } /** * Gibt das Wurzelelemtn dieses Baums zurueck @@ -207,6 +175,8 @@ static public List findPath(ActionTreeElement start, ActionTr return new LinkedList(); } + + // Ways from Start or End Element to the tree root LinkedList startToRoot = new LinkedList(); LinkedList endToRoot = new LinkedList(); @@ -223,12 +193,9 @@ static public List findPath(ActionTreeElement start, ActionTr path = false; } - while (startToRoot.isEmpty() || endToRoot.isEmpty() - || (startToRoot.getLast() != endToRoot.getLast() - && (startToRoot.getLast().getParent() != null - || endToRoot.getLast().getParent() != null))) { + while (conditionA(startToRoot, endToRoot)) {//I wish I knew what they do - while (current != null && (other == null || current.getId() >= other.getId())) { + while (conditionB(current,other)) { (path ? startToRoot : endToRoot).addLast(current); current = current.getParent(); } @@ -265,6 +232,24 @@ static public List findPath(ActionTreeElement start, ActionTr return startToRoot; } + private static boolean conditionA(LinkedList startToRoot, LinkedList endToRoot){ + boolean eitherListEmpty = startToRoot.isEmpty() || endToRoot.isEmpty(); + + return eitherListEmpty || ( + startToRoot.getLast() != endToRoot.getLast() //last elements differ + && + startToRoot.getLast().getParent() != null || endToRoot.getLast().getParent() != null + ); + /* mangels laziness kann ich leider nicht alles abkürzen*/ + } + + private static boolean conditionB(ActionTreeElement current, ActionTreeElement other){ + + return current != null && (other == null || current.getId() >= other.getId()); + } + + + /** * Gibt einen Iterator für die ActionTreeElemente zurück. * diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/ActionTreeElement.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/ActionTreeElement.java index 57f67cfc..a220af32 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/ActionTreeElement.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/ActionTreeElement.java @@ -117,7 +117,7 @@ public ActionTreeElement(int id, Action action, ActionTreeElement parent) { parent.addChild(this); } - following = new ArrayList(); + following = new ArrayList<>(); } } @@ -125,6 +125,7 @@ public Action getAction() { return action; } + /** * Diese Methode führt die Aktion dieses Elementes aus. * @@ -189,8 +190,8 @@ public ActionTreeElement getParent() { * * @return Die Liste aller Kindelemente. */ - // ja, package scope - ArrayList getChildrenList() { + // ja, package scope TODO refactor and make package scope again + public ArrayList getChildrenList() { return following; } diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/SolveAction.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/SolveAction.java index dae0b164..f274cc95 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/SolveAction.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/actionTree/SolveAction.java @@ -53,4 +53,12 @@ public boolean inverse(Action a){ return field.equals(a.field) && diff+a.diff == 0; return false; } + + /** in case we want to move an action up one level (field stays the same) we need to add the diffs + * TODO refactor this, break with diffs entirely maybe? + * */ + public SolveAction add(SolveAction action){ + + return new SolveAction(diff+action.diff,field); + } } diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/Game.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/Game.java index 5b4dc3c3..2d78d148 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/Game.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/Game.java @@ -275,6 +275,8 @@ private void updateNotes(Field field) { * Wird geworfen, falls das übergebene ActionTreeElement null ist */ public void goToState(ActionTreeElement ate) { + if(ate == null) + throw new IllegalArgumentException(); stateHandler.goToState(ate); } @@ -525,8 +527,8 @@ public void fillFromXml(XmlTree xmlTreeRepresentation) { sudoku = SudokuManager.getEmptySudokuToFillWithXml(); sudoku.fillFromXml(sub); }else if(sub.getName().equals("gameSettings")){ - gameSettings = new GameSettings(); - gameSettings.fillFromXml(sub); + gameSettings = new GameSettings(); + gameSettings.fillFromXml(sub); } } stateHandler = new GameStateHandler(); @@ -536,20 +538,22 @@ public void fillFromXml(XmlTree xmlTreeRepresentation) { int diff = Integer.parseInt(sub.getAttributeValue(ActionTreeElement.DIFF)); // put the action to the parent action - goToState(stateHandler.getActionTree().getElement( - Integer.parseInt(sub.getAttributeValue(ActionTreeElement.PARENT)))); + String attributeValue = sub.getAttributeValue(ActionTreeElement.PARENT); + int parentID = Integer.parseInt(attributeValue); + ActionTreeElement parent = stateHandler.getActionTree().getElement(parentID); + goToState(parent); // if(!sub.getAttributeValue(ActionTreeElement.PARENT).equals("")) // is not necessary since the root action comes from the gsh so + // every element has e parent int field_id = Integer.parseInt(sub.getAttributeValue(ActionTreeElement.FIELD_ID)); - + Field f = sudoku.getField(field_id); if (sub.getAttributeValue(ActionTreeElement.ACTION_TYPE).equals(SolveAction.class.getSimpleName())) { - this.stateHandler.addAndExecute(new SolveActionFactory().createAction(sudoku.getField(field_id) - .getCurrentValue() + diff, sudoku.getField(field_id))); + this.stateHandler.addAndExecute(new SolveActionFactory().createAction(f.getCurrentValue() + diff, + f)); } else { // if(sub.getAttributeValue(ActionTreeElement.ACTION_TYPE).equals(NoteAction.class.getSimpleName())) - this.stateHandler.addAndExecute(new NoteActionFactory().createAction(diff, - sudoku.getField(field_id))); + this.stateHandler.addAndExecute(new NoteActionFactory().createAction(diff, f)); } if (Boolean.parseBoolean(sub.getAttributeValue(ActionTreeElement.MARKED))) { diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/GameManager.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/GameManager.java index f6eee26a..fe85dcef 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/GameManager.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/GameManager.java @@ -120,7 +120,7 @@ public Game newGame(SudokuTypes type, Complexity complexity, GameSettings assist * falls keine Spiel mit der entsprechenden id existiert */ public Game load(int id) { - if (id <= 0) throw new IllegalArgumentException("unvalid id"); + if (id <= 0) throw new IllegalArgumentException("invalid id"); Game game = new Game(); // throws IllegalArgumentException new GameXmlHandler(id).createObjectFromXml(game); diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/GameStateHandler.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/GameStateHandler.java index f4166919..56aad0a8 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/GameStateHandler.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/game/GameStateHandler.java @@ -14,6 +14,7 @@ import de.sudoq.model.actionTree.Action; import de.sudoq.model.actionTree.ActionTree; import de.sudoq.model.actionTree.ActionTreeElement; +import de.sudoq.model.actionTree.SolveAction; import de.sudoq.model.sudoku.Field; /** @@ -51,23 +52,14 @@ public GameStateHandler() { actionTree = new ActionTree(); undoStack = new Stack(); - currentState = actionTree.add(new Action(0, new Field(-1, 1)) { - // Empty Action - do nothing - @Override - public void undo() { - } - - @Override - public void execute() { - } - }, currentState); + currentState = actionTree.getRoot(); locked = false; } /** * Die Methode gibt den ActionTree zurück. - * + * * @return Der ActionTree */ public ActionTree getActionTree() { @@ -76,7 +68,7 @@ public ActionTree getActionTree() { /** * Die Methode gibt den aktuellen Zustand zurück. - * + * * @return Das ActionTreeElement mit dem aktuellen Zustand */ public ActionTreeElement getCurrentState() { @@ -85,25 +77,90 @@ public ActionTreeElement getCurrentState() { /** * Fügt die gegebene Aktion dem ActionTree hinzu und führt sie aus. - * - * @param action - * Die auszuführende Aktion - * @throws IllegalArgumentException - * falls Action null ist + * + * @param action Die auszuführende Aktion + * @throws IllegalArgumentException falls Action null ist */ public void addAndExecute(Action action) { // if another change is in progress dont execute! if (!locked) { locked = true; - currentState = actionTree.add(action, currentState); - currentState.execute(); + addStrategic(action); + notifyListeners(currentState); locked = false; } } + //private + private void addStrategic(Action action){ + if(isActionRedundant(currentState, action)) { + currentState = findExistingChildren(currentState, action).get(0); + action.execute(); + + }else if(isActionAStepBack(currentState, action)) { + currentState = currentState.getParent(); + action.execute(); + + }else if(isSolveOnSameField(action)) { + + SolveAction intended = (SolveAction) action; + SolveAction above = (SolveAction) currentState.getAction(); + SolveAction liftedAction = intended.add(above); + currentState.undo(); + currentState = currentState.getParent(); + addStrategic(liftedAction); + return; + } else { + currentState = actionTree.add(action, currentState); + currentState.execute(); + } + + } + + + + /* check if action already in Tree, + i.e. we went back in actionTree but are doing same steps again */ + public boolean isActionRedundant(ActionTreeElement mountingElement, Action action){ + + return !findExistingChildren(mountingElement, action).isEmpty(); + } + + private List findExistingChildren(ActionTreeElement mountingElement, Action action){ + List l = new Stack<>(); + + if (mountingElement != null) { + for(ActionTreeElement ateI : mountingElement.getChildrenList()) + if(ateI.actionEquals(action)) + l.add(ateI); + } + return l; + } + + private boolean isActionAStepBack(ActionTreeElement mountingElement, Action action) { + return mountingElement.getAction().inverse(action); + } + + private boolean isSolveOnSameField(Action action){ + return currentState != actionTree.getRoot() && bothSolveActions(currentState, action) && isActionOnSameField(currentState, action); + } + + private boolean bothSolveActions(ActionTreeElement mountingElement, Action action) { + Action actionAbove = mountingElement.getAction(); + return (action instanceof SolveAction) && (actionAbove instanceof SolveAction); + } + + private boolean isActionOnSameField(ActionTreeElement mountingElement, Action action) { + + boolean sameField = mountingElement.getAction().getField().equals(action.getField()); + return (action instanceof SolveAction) && sameField; + } + + + /** * Führt alle nötigen Aktionen aus, damit das Sudoku nach Ausführung dieser Methode wieder im gleichen Zustand wie * nach der ersten Ausführung der gegebenen Aktion ist. @@ -122,7 +179,7 @@ public void goToState(ActionTreeElement target) { listWay.toArray(way); for (int i = 1; i < way.length; i++) { - if (way[i - 1].getParent() == way[i]) { + if (way[i - 1].getParent() == way[i]) {//are we going backwards? way[i - 1].undo(); if (way[i].isSplitUp()) { undoStack.push(way[i - 1]); diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/profile/Profile.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/profile/Profile.java index fb5272e4..dbca0c44 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/profile/Profile.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/profile/Profile.java @@ -22,7 +22,7 @@ import de.sudoq.model.xml.Xmlable; /** - * Diese statische Klasse ist ein Wrapper für das aktuell geladene und durch + * Diese statische Klasse ist ein Wrapper für das aktuell geladene und durch TODO splitt into profile handler and profile * SharedPreferences von der Android-API verwaltete Spielerprofil. * */ diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/Field.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/Field.java index 078a9760..3b1f7e1f 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/Field.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/Field.java @@ -137,7 +137,7 @@ public int getCurrentValue() { public void setCurrentValue(int value) { if (isEditable()) { if ((value < 0 && value != EMPTYVAL) || value > maxValue) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("value is "+value); } this.currentVal = value; diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/PositionMap.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/PositionMap.java index c9cc0cfe..73a643cf 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/PositionMap.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/PositionMap.java @@ -72,12 +72,12 @@ public T put(Position pos, T object) { * @return Das BitSet, welches der spezifizierten Position zugeordnet wurde oder null, falls keines zugewiesen wurde */ public T get(Position pos) { - /*if (pos == null) + if (pos == null) throw new IllegalArgumentException("pos was null"); if (pos.getX() > this.dimension.getX()) throw new IllegalArgumentException("x coordinate of pos was > " + this.dimension.getX() + ": " + pos.getX()); if (pos.getY() > this.dimension.getY()) - throw new IllegalArgumentException("y coordinate of pos was > " + this.dimension.getY() + ": " + pos.getY());*/ + throw new IllegalArgumentException("y coordinate of pos was > " + this.dimension.getY() + ": " + pos.getY()); assert pos != null; assert pos.getX() < this.dimension.getX(); assert pos.getY() < this.dimension.getY(); diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/SudokuBuilder.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/SudokuBuilder.java index 5647eadb..bd810de5 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/SudokuBuilder.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/sudoku/SudokuBuilder.java @@ -73,7 +73,7 @@ public Sudoku createSudoku() { */ public void addSolution(Position pos, int value) { if (value < 0 || value >= type.getNumberOfSymbols()) { - throw new IllegalArgumentException("Unvalid value for given Sudoku Type"); + throw new IllegalArgumentException("Invalid value for given Sudoku Type"); } solutions.put(pos, value); } diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/xml/XmlAttribute.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/xml/XmlAttribute.java index fc0bd460..4c2eaddb 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/xml/XmlAttribute.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/xml/XmlAttribute.java @@ -73,6 +73,8 @@ public String getValue() { return value; } + public String toString() { return name+": "+value; } + /** * Setzt falls der Parameter nicht null ist value auf diesen * diff --git a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/xml/XmlHandler.java b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/xml/XmlHandler.java index ca625580..1630a822 100644 --- a/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/xml/XmlHandler.java +++ b/sudoq-app/sudoqmodel/src/main/java/de/sudoq/model/xml/XmlHandler.java @@ -73,6 +73,8 @@ public T createObjectFromXml(T obj) { obj.fillFromXml(helper.loadXml(getFileFor(obj))); } catch (IOException e) { throw new IllegalArgumentException("Something went wrong when reading xml " + getFileFor(obj), e); + } catch (IllegalArgumentException e){ + throw new IllegalArgumentException("Something went wrong when filling obj from xml ", e); } return obj; } diff --git a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeAddElementsTests.java b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeAddElementsTests.java new file mode 100644 index 00000000..e5e82f9d --- /dev/null +++ b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeAddElementsTests.java @@ -0,0 +1,65 @@ +package de.sudoq.model.actionTree; + +import org.junit.Test; + +import java.util.List; + +import de.sudoq.model.game.GameStateHandler; +import de.sudoq.model.sudoku.Field; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +public class ActionTreeAddElementsTests { + + @Test + public void testAddingRedundantElement() { + GameStateHandler stateHandler = new GameStateHandler(); + ActionFactory af = new SolveActionFactory(); + //ActionTree at = new ActionTree(); + ActionFactory factory = new SolveActionFactory(); + + Field field = new Field(1, 9); + + ActionTreeElement root = stateHandler.getActionTree().getRoot(); + + stateHandler.addAndExecute(factory.createAction(1, field)); + stateHandler.undo(); + stateHandler.addAndExecute(factory.createAction(1, field));//should be ignored by at + + assertEquals(1, root.getChildrenList().size()); + assertTrue(root.getChildrenList().get(0).getChildrenList().isEmpty()); + } + + @Test + public void testAddingRedundantElementBelow() { + /* r intended values, not diffs + * / \ + * 1 2 + * | + * 2 + */ + GameStateHandler sh = new GameStateHandler(); + ActionFactory af = new SolveActionFactory(); + + Field field = new Field(1, 9); + + ActionTreeElement root = sh.getActionTree().getRoot(); + + sh.addAndExecute(af.createAction(2, field)); + sh.addAndExecute(af.createAction(1, field)); + + sh.addAndExecute(af.createAction(2, field)); + + assertEquals(2, root.getChildrenList().size()); + for(ActionTreeElement child: root.getChildrenList()) + assertTrue(child.getChildrenList().isEmpty()); + } + + +} diff --git a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeIteratorTests.java b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeIteratorTests.java index e388af29..e83f802c 100644 --- a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeIteratorTests.java +++ b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeIteratorTests.java @@ -24,11 +24,15 @@ public void testCompleteness() { ActionFactory factory = new SolveActionFactory(); Field field = new Field(-1, 1); - ActionTreeElement ate1 = at.add(factory.createAction(1, field), null); //root element - ActionTreeElement ate2 = at.add(factory.createAction(1, field), ate1); //one child - at.add(factory.createAction(1, field), ate2); - at.add(factory.createAction(1, field), ate2);//this should not be ignored by the actionTree, cause we've been there already - at.add(factory.createAction(2, field), ate2); + Action a2 = new SolveAction(1, field); // -> value 1 + Action a3 = new SolveAction(0, field); // -> value 1 + Action a4 = new SolveAction(0, field); // -> value 1 + Action a5 = new SolveAction(1, field); // -> value 2 + + ActionTreeElement ate2 = at.add(a2, at.getRoot()); //one child + at.add(a3, ate2);//this should be ignored by the actionTree, cause redundant to parent TODO no ot shouldnd, only in gamestatehandler scenario. make that scenario!!! + at.add(a4, ate2);//this should be ignored by the actionTree, cause we've been there already + at.add(a5, ate2); int i = 0; ArrayList ids = new ArrayList(); @@ -38,15 +42,42 @@ public void testCompleteness() { i++; } - assertEquals(i, 4); + assertEquals(5, i); + } + @Test + public void testCompleteness2() { + ActionTree at = new ActionTree(); + ActionFactory factory = new SolveActionFactory(); + Field field = new Field(-1, 1); + + Action a2 = factory.createAction(1, field);//actions are created by factory in relation to current field + Action a3 = factory.createAction(3, field);//creating them as needed makes it hard to see what is what + Action a4 = factory.createAction(3, field); + Action a5 = factory.createAction(2, field); + + ActionTreeElement ate2 = at.add(a2, at.getRoot()); //one child + ActionTreeElement ate3 = at.add(a3, ate2); + ActionTreeElement ate4 = at.add(a4, ate2); + ActionTreeElement ate5 = at.add(a5, ate2);//this should be ignored by the actionTree, cause we've been there already + + int i = 0; + ArrayList ids = new ArrayList(); + for (ActionTreeElement ate : at) { + assertFalse(ids.contains(new Integer(ate.getId()))); + ids.add(ate.getId()); + i++; + } + + assertEquals(5, i); } @Test public void testExceptions() { - ActionTree at = new ActionTree(); + ActionTree at = new ActionTree();//has automatic root element Iterator iterator = at.iterator(); try { + iterator.next(); iterator.next(); fail("No Exception thrown"); } catch (NoSuchElementException e) { diff --git a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeTests.java b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeTests.java index 70eac1dc..879a6daf 100644 --- a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeTests.java +++ b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/actionTree/ActionTreeTests.java @@ -3,6 +3,7 @@ import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -22,8 +23,7 @@ public class ActionTreeTests { @Test public void testConstruction() { ActionTree at = new ActionTree(); - assertTrue(at.isEmpty()); - assertNull(at.getRoot()); + assertNotNull(at.getRoot()); } @Test @@ -32,9 +32,8 @@ public void testAddingElements() { ActionFactory factory = new SolveActionFactory(); Field field = new Field(-1, 1); - ActionTreeElement ate = at.add(factory.createAction(1, field), null); + ActionTreeElement ate = at.getRoot();//add(factory.createAction(1, field), null); assertEquals(ate.getId(), 1); - assertFalse(at.isEmpty()); try { at.add(factory.createAction(2, field), null); @@ -52,10 +51,8 @@ public void testEquals() { assertFalse(new ActionTree().equals(new Object())); ActionTree at = new ActionTree(); - at.add(new SolveActionFactory().createAction(1, new Field(-1, 1)), null); - assertFalse(at.equals(new ActionTree())); ActionTree at2 = new ActionTree(); - at2.add(new SolveActionFactory().createAction(5, new Field(-1, 1)), null); + at2.add(new SolveActionFactory().createAction(5, new Field(-1, 1)), at2.getRoot()); assertFalse(at.equals(at2)); assertTrue(at.equals(at)); } @@ -65,11 +62,14 @@ public void testGettingElementsById() { ActionTree at = new ActionTree(); ActionFactory factory = new SolveActionFactory(); Field field = new Field(-1, 1); + Field field2 = new Field(0, 2); + Field field3 = new Field(1, 3); + Field field4 = new Field(2, 4); - ActionTreeElement ate1 = at.add(factory.createAction(1, field), null); - ActionTreeElement ate2 = at.add(factory.createAction(1, field), ate1); - ActionTreeElement ate3 = at.add(factory.createAction(1, field), ate2); - ActionTreeElement ate4 = at.add(factory.createAction(2, field), ate2); + ActionTreeElement ate1 = at.getRoot(); + ActionTreeElement ate2 = at.add(factory.createAction(1, field2), ate1); + ActionTreeElement ate3 = at.add(factory.createAction(1, field3), ate2); + ActionTreeElement ate4 = at.add(factory.createAction(2, field4), ate2); assertEquals(ate1, at.getElement(1)); assertEquals(ate2, at.getElement(2)); @@ -85,7 +85,7 @@ public void testSearchForInexistentId() { ActionFactory factory = new SolveActionFactory(); Field field = new Field(-1, 1); - ActionTreeElement ate1 = at.add(factory.createAction(1, field), null); + ActionTreeElement ate1 = at.getRoot(); ActionTreeElement ate2 = at.add(factory.createAction(1, field), ate1); at.add(factory.createAction(1, field), ate2); at.add(factory.createAction(1, field), ate2); @@ -101,14 +101,14 @@ public void testConsistencyCheck() { ActionFactory factory = new SolveActionFactory(); Field field = new Field(-1, 1); - ActionTreeElement ate1 = at.add(factory.createAction(1, field), null); + ActionTreeElement ate1 = at.getRoot(); ActionTreeElement ate2 = at.add(factory.createAction(1, field), ate1); ActionTreeElement ate3 = at.add(factory.createAction(1, field), ate2); at.add(factory.createAction(1, field), ate2); - assertTrue(at.isConsitent()); + assertTrue(at.isConsistent()); ate3.addChild(ate1); - assertFalse(at.isConsitent()); + assertFalse(at.isConsistent()); } // AT170 @@ -116,14 +116,18 @@ public void testConsistencyCheck() { public void testFindPath() { ActionTree at = new ActionTree(); ActionFactory factory = new SolveActionFactory(); - Field field = new Field(-1, 1); - - ActionTreeElement ate1 = at.add(factory.createAction(1, field), null); - ActionTreeElement ate2 = at.add(factory.createAction(1, field), ate1); - ActionTreeElement ate3 = at.add(factory.createAction(1, field), ate2); - ActionTreeElement ate4 = at.add(factory.createAction(1, field), ate3); - ActionTreeElement ate5 = at.add(factory.createAction(2, field), ate2); - ActionTreeElement ate6 = at.add(factory.createAction(1, field), ate5); + Field field0 = new Field( 4, 0); + Field field1 = new Field( 0, 2); + Field field2 = new Field( 1, 3); + Field field3 = new Field( 2, 4); + Field field4 = new Field( 3, 5); + + ActionTreeElement ate1 = at.getRoot();//at.add(factory.createAction(1, field), null); + ActionTreeElement ate2 = at.add(factory.createAction(1, field0), ate1); + ActionTreeElement ate3 = at.add(factory.createAction(3, field1), ate2); + ActionTreeElement ate4 = at.add(factory.createAction(1, field2), ate3); + ActionTreeElement ate5 = at.add(factory.createAction(2, field3), ate2); + ActionTreeElement ate6 = at.add(factory.createAction(1, field4), ate5); assertArrayEquals(new ActionTreeElement[] { ate4, ate3, ate2, ate5, ate6 }, ActionTree.findPath(ate4, ate6) .toArray()); @@ -148,12 +152,17 @@ public void testFindNonExistingPath() { ActionFactory factory = new SolveActionFactory(); Field field = new Field(-1, 1); - ActionTreeElement ate1 = at1.add(factory.createAction(1, field), null); + ActionTreeElement ate1 = at1.getRoot(); ActionTreeElement ate2 = at1.add(factory.createAction(4, field), ate1); - ActionTreeElement ate3 = at2.add(factory.createAction(3, field), null); + + ActionTreeElement ate3 = at2.getRoot(); ActionTreeElement ate4 = at2.add(factory.createAction(2, field), ate3); List a = ActionTree.findPath(ate2, ate4); assertNull(a); + /*List b = ActionTree.findPath(at1.getRoot() + ,at2.getRoot()); + assertNull(b); TODO vertagt, gibt bislang [] zurück. vielleicht sollte nie null zurückgegeben werden sondern immer [] wenns hakt*/ + } } diff --git a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/game/GameStateHandlerTests.java b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/game/GameStateHandlerTests.java index ea78cfbd..f7647fd8 100644 --- a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/game/GameStateHandlerTests.java +++ b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/game/GameStateHandlerTests.java @@ -29,7 +29,7 @@ public void testConstruction() { stateHandler.addAndExecute(af.createAction(5, field)); assertEquals(field.getCurrentValue(), 5); - assertTrue(!stateHandler.getActionTree().isEmpty()); + assertTrue(stateHandler.getActionTree().getSize() !=0); } @Test @@ -76,19 +76,45 @@ public void testUndoRedo() { assertEquals(7, field3.getCurrentValue()); } + @Test + public void testTapSameSymbol4Times() { + /* regression for: press three times '3' on same field. + * first 2 beheave as expected, 3rd does nothing and 4 crashes */ + GameStateHandler stateHandler = new GameStateHandler(); + ActionFactory af = new SolveActionFactory(); + Field field1 = new Field(-1, 9); + + stateHandler.addAndExecute(af.createAction(3, field1)); + assertEquals(3, field1.getCurrentValue()); + + stateHandler.addAndExecute(af.createAction(-1, field1)); + assertEquals(-1, field1.getCurrentValue()); + + stateHandler.addAndExecute(af.createAction(3, field1)); + assertEquals(3, field1.getCurrentValue()); + + stateHandler.addAndExecute(af.createAction(-1, field1)); + assertEquals(-1, field1.getCurrentValue()); + + } + + @Test public void testGoTo() { GameStateHandler stateHandler = new GameStateHandler(); ActionFactory af = new SolveActionFactory(); Field field = new Field(-1, 9); + //add 5, undo test if undo successful int value = field.getCurrentValue(); stateHandler.addAndExecute(af.createAction(5, field)); stateHandler.goToState(stateHandler.getCurrentState()); stateHandler.undo(); assertEquals(value, field.getCurrentValue()); + + //redo the 5, stateHandler.redo(); - ActionTreeElement first = stateHandler.getCurrentState(); + ActionTreeElement first = stateHandler.getCurrentState();// first <- 5 stateHandler.addAndExecute(af.createAction(7, field)); ActionTreeElement branch = stateHandler.getCurrentState(); stateHandler.goToState(first); @@ -114,22 +140,25 @@ public void testGoTo() { public void testEmptyUndoStack() { GameStateHandler stateHandler = new GameStateHandler(); ActionFactory af = new SolveActionFactory(); - Field field = new Field(-1, 9); + Field f_1 = new Field(-1, 9); + Field f_2 = new Field(-2, 9); + Field f_3 = new Field(-3, 9); + Field f_4 = new Field(-4, 9); - stateHandler.addAndExecute(af.createAction(1, field)); + stateHandler.addAndExecute(af.createAction(1, f_1)); ActionTreeElement b1 = stateHandler.getCurrentState(); stateHandler.redo(); assertTrue(b1.equals(stateHandler.getCurrentState())); stateHandler.undo(); ActionTreeElement start = stateHandler.getCurrentState(); assertNotNull(start); - stateHandler.addAndExecute(af.createAction(2, field)); + stateHandler.addAndExecute(af.createAction(2, f_2)); ActionTreeElement b2 = stateHandler.getCurrentState(); stateHandler.goToState(start); assertTrue(stateHandler.canRedo()); stateHandler.redo(); assertTrue(b2.equals(stateHandler.getCurrentState())); - stateHandler.addAndExecute(af.createAction(3, field)); + stateHandler.addAndExecute(af.createAction(3, f_3)); ActionTreeElement b3 = stateHandler.getCurrentState(); stateHandler.goToState(b1); stateHandler.goToState(b2); @@ -137,7 +166,7 @@ public void testEmptyUndoStack() { stateHandler.redo(); assertTrue(b3.equals(stateHandler.getCurrentState())); stateHandler.goToState(b2); - stateHandler.addAndExecute(af.createAction(4, field)); + stateHandler.addAndExecute(af.createAction(4, f_4)); stateHandler.goToState(b1); stateHandler.goToState(b2); assertFalse(stateHandler.canRedo()); diff --git a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/game/GameTests.java b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/game/GameTests.java index 8bb0262a..81d9e7d8 100644 --- a/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/game/GameTests.java +++ b/sudoq-app/sudoqmodel/src/test/java/de/sudoq/model/game/GameTests.java @@ -55,7 +55,7 @@ public void testInstanciation() { } @Test(expected = IllegalArgumentException.class) - public void testNullInstanciation() { + public void testNullInstantiation() { new Game(2, null); } @@ -65,24 +65,25 @@ public void testGameInteraction() { Position pos = Position.get(1, 1); ActionTreeElement start = game.getCurrentState(); - - game.addAndExecute(new SolveActionFactory().createAction(3, game.getSudoku().getField(pos))); - game.addAndExecute(new SolveActionFactory().createAction(4, game.getSudoku().getField(pos))); + Field f = game.getSudoku().getField(pos); + game.addAndExecute(new SolveActionFactory().createAction(3, f));//setze 3 + game.addAndExecute(new SolveActionFactory().createAction(4, f));//setze 4 assertFalse(game.isMarked(game.getCurrentState())); - game.addAndExecute(new SolveActionFactory().createAction(5, game.getSudoku().getField(pos))); - assertEquals(game.getSudoku().getField(pos).getCurrentValue(), 5); + game.addAndExecute(new SolveActionFactory().createAction(5, f));//setze 5 + assertEquals(5, game.getSudoku().getField(pos).getCurrentValue()); game.markCurrentState(); assertTrue(game.isMarked(game.getCurrentState())); game.goToState(start); - assertEquals(game.getSudoku().getField(pos).getCurrentValue(), Field.EMPTYVAL); + assertEquals(Field.EMPTYVAL, f.getCurrentValue()); assertFalse(game.isFinished()); game.redo(); game.redo(); - assertEquals(game.getSudoku().getField(pos).getCurrentValue(), 4); + assertEquals(5, f.getCurrentValue());//schlägt fehl game.undo(); - assertEquals(game.getSudoku().getField(pos).getCurrentValue(), 3); + assertEquals(Field.EMPTYVAL, f.getCurrentValue()); + game.redo(); assertFalse(game.checkSudoku()); game.addTime(23);