diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000000000000000000000000000000000..e9d50e4d375f95edb051438c118e29558c14e922 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "core/external"] + path = core/external + url = git@gitlab.labs.nic.cz:mlatner/Tablexia-Model.git diff --git a/core/build.gradle b/core/build.gradle index 38434a7d1c1f28224d5ccbb3d4b87605220754c0..67a96d51552be3af13dbc3d39ce3fff06c962a76 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -8,7 +8,7 @@ final String BUILD_CONFIG_FILE_ENCODING = "UTF-8" sourceCompatibility = 1.6 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' -sourceSets.main.java.srcDirs = ["src/", "gen/"] +sourceSets.main.java.srcDirs = ["src/", "gen/", "external/shared"] eclipse.project { diff --git a/core/external b/core/external new file mode 160000 index 0000000000000000000000000000000000000000..17f7d92b6b507736f75c8ba45498b08b24e7469c --- /dev/null +++ b/core/external @@ -0,0 +1 @@ +Subproject commit 17f7d92b6b507736f75c8ba45498b08b24e7469c diff --git a/core/src/cz/nic/tablexia/TablexiaApplication.java b/core/src/cz/nic/tablexia/TablexiaApplication.java index 3884c7a994fd255bfe88bac156ccca1d78c2f516..ac8229f91ea839bd3eb6feefb600cba60eb348db 100644 --- a/core/src/cz/nic/tablexia/TablexiaApplication.java +++ b/core/src/cz/nic/tablexia/TablexiaApplication.java @@ -29,7 +29,11 @@ import net.engio.mbassy.listener.Handler; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.bus.ApplicationBus.ApplicationEvent; +import cz.nic.tablexia.bus.event.DeleteUserSynchronizationEvent; import cz.nic.tablexia.bus.event.DimmerControlEvent; +import cz.nic.tablexia.bus.event.DownloadUserSynchronizationEvent; +import cz.nic.tablexia.bus.event.StartFullSynchronizationEvent; +import cz.nic.tablexia.bus.event.StartIncrementalSynchronizationEvent; import cz.nic.tablexia.debug.DebugInfo; import cz.nic.tablexia.loader.TablexiaAbstractFileManager; import cz.nic.tablexia.loader.TablexiaAtlasManager; @@ -37,8 +41,14 @@ import cz.nic.tablexia.loader.application.ApplicationAtlasManager; import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.loader.application.ApplicationTextManager; import cz.nic.tablexia.menu.MenuController; +import cz.nic.tablexia.model.UserDAO; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.screen.AbstractTablexiaScreen.ScreenLoadingListener; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.sync.RestSynchronizationService; +import cz.nic.tablexia.sync.work.DeleteUser; +import cz.nic.tablexia.sync.work.DownloadUser; +import cz.nic.tablexia.sync.work.PushDataToServer; import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.ui.TablexiaButton; import cz.nic.tablexia.util.ui.dialog.TablexiaDialog; @@ -136,6 +146,8 @@ public abstract class TablexiaApplication implements ApplicationListener { prepareMenuLayer(); prepareScreenDimmer(); prepareDebugInfo(); + + ApplicationBus.getInstance().subscribe(this); } @Override @@ -778,4 +790,41 @@ public abstract class TablexiaApplication implements ApplicationListener { ApplicationBus.getInstance().post(new DimmerControlEvent(false)).asynchronously(); } } + +//////////////////////////// SERVER SYNCHRONIZATION + + @Handler + public void handleSynchronizationEvent(StartFullSynchronizationEvent syncEvent) { + Log.debug(this.getClass(), "Full sync request"); + for (User user: syncEvent.getUsers()) { + RestSynchronizationService.doSyncWork(new PushDataToServer(user, syncEvent.getType())); + } + } + + @Handler + public void handleSynchronizationEvent(StartIncrementalSynchronizationEvent syncEvent) { + Log.debug(this.getClass(), "Sync request for userId: " + syncEvent.getUserId()); + User user = UserDAO.selectUser(syncEvent.getUserId()); + if (user != null) { + RestSynchronizationService.doSyncWork(new PushDataToServer(user, syncEvent.getType())); + } + } + + @Handler + public void handleSynchronizationEvent(DeleteUserSynchronizationEvent syncEvent) { + Log.debug(this.getClass(), "Delete user request for uuid: " + syncEvent.getUser().getUuid()); + if (syncEvent.getUser() != null && syncEvent.getUser().getUuid() != null) { + RestSynchronizationService.doSyncWork(new DeleteUser(syncEvent.getUser())); + } + } + + @Handler + public void handleSynchronizationEvent(DownloadUserSynchronizationEvent syncEvent) { + if (syncEvent.getUser().getUuid() == null || syncEvent.getUser().getUuid().isEmpty()) { + Log.err(this.getClass(), "Calling download user without uuid"); + return; + } + Log.debug(this.getClass(), "Download user request for uuid: " + syncEvent.getUser().getUuid()); + RestSynchronizationService.doSyncWork(new DownloadUser(syncEvent.getUser().getUuid())); + } } diff --git a/core/src/cz/nic/tablexia/TablexiaSettings.java b/core/src/cz/nic/tablexia/TablexiaSettings.java index 91b15050fec46c54873f2ac2efc02a1d445d79f8..4d61186a8873b6f3c1b80278d4244b96e41a61bf 100644 --- a/core/src/cz/nic/tablexia/TablexiaSettings.java +++ b/core/src/cz/nic/tablexia/TablexiaSettings.java @@ -13,10 +13,13 @@ import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.difficulty.GameDifficulty; import cz.nic.tablexia.loader.application.ApplicationTextManager; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.screen.gamemenu.GameMenuScreen; import cz.nic.tablexia.screen.loader.LoaderScreen; +import cz.nic.tablexia.sync.work.PushDataToServer; +import cz.nic.tablexia.sync.RestSynchronizationService; import cz.nic.tablexia.util.Log; public class TablexiaSettings { @@ -170,7 +173,7 @@ public class TablexiaSettings { public void loadPreferences(boolean reset) { preferences = Gdx.app.getPreferences(PREFERENCES_KEY + BUILD_TYPE.getKey()); selectedLocale = LocaleDefinition.getLocaleDefinitionForKey(preferences.getString(LOCALE_KEY)); - selectedUser = reset ? null : User.selectUser(preferences.getLong(SELECTED_USER)); + selectedUser = reset ? null : UserDAO.selectUser(preferences.getLong(SELECTED_USER)); Calendar calendar = GregorianCalendar.getInstance(); winterMode = (calendar.get(Calendar.MONTH) > WINTER_MODE_START_MONTH) || (calendar.get(Calendar.MONTH) < WINTER_MODE_END_MONTH); diff --git a/core/src/cz/nic/tablexia/TablexiaStorage.java b/core/src/cz/nic/tablexia/TablexiaStorage.java index f5573a642e14f34644178f93781047380630fd05..fba64117173e7b667ce8e1de5cbbabe547d7da7a 100644 --- a/core/src/cz/nic/tablexia/TablexiaStorage.java +++ b/core/src/cz/nic/tablexia/TablexiaStorage.java @@ -17,10 +17,11 @@ import java.util.Map; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.loader.TablexiaAbstractFileManager; -import cz.nic.tablexia.model.game.Game; -import cz.nic.tablexia.model.game.GamePause; -import cz.nic.tablexia.model.User; -import cz.nic.tablexia.model.game.GameScore; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.model.game.GameDAO; +import cz.nic.tablexia.model.game.GamePauseDAO; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.model.game.GameScoreDAO; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.Utility; @@ -121,11 +122,11 @@ public class TablexiaStorage { private void initTables() { try { Statement statement = createStatement(); - statement.execute(User.CREATE_TABLE); - statement.execute(Game.CREATE_TABLE); - statement.execute(GameScore.CREATE_TABLE); - statement.execute(GamePause.CREATE_TABLE); - statement.execute(GamePause.CREATE_CONNECTION_TABLE); + statement.execute(UserDAO.CREATE_TABLE); + statement.execute(GameDAO.CREATE_TABLE); + statement.execute(GameScoreDAO.CREATE_TABLE); + statement.execute(GamePauseDAO.CREATE_TABLE); + statement.execute(GamePauseDAO.CREATE_CONNECTION_TABLE); statement.execute(SCREEN_STATE_CREATE_TABLE); statement.close(); } catch (SQLException e) { @@ -134,7 +135,8 @@ public class TablexiaStorage { } private void MigrateData() { - User.migrateUserSignaturesData(); + UserDAO.migrateUserSignaturesData(); + UserDAO.migrateUserTableStructure(); } private void reset(boolean reset) { diff --git a/core/src/cz/nic/tablexia/bus/event/DeleteUserSynchronizationEvent.java b/core/src/cz/nic/tablexia/bus/event/DeleteUserSynchronizationEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..8cb9e93dfa6efc2d7cbfc3cab834b3d19788f568 --- /dev/null +++ b/core/src/cz/nic/tablexia/bus/event/DeleteUserSynchronizationEvent.java @@ -0,0 +1,20 @@ +package cz.nic.tablexia.bus.event; + +import cz.nic.tablexia.bus.ApplicationBus; +import cz.nic.tablexia.shared.model.User; + +/** + * Created by frantisek on 19.1.16. + */ +public class DeleteUserSynchronizationEvent implements ApplicationBus.ApplicationEvent { + + private final User user; + + public DeleteUserSynchronizationEvent(User user) { + this.user = user; + } + + public User getUser() { + return user; + } +} diff --git a/core/src/cz/nic/tablexia/bus/event/DownloadUserSynchronizationEvent.java b/core/src/cz/nic/tablexia/bus/event/DownloadUserSynchronizationEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..2bc0943859615c24cfd801b86d98f343d0e7f68f --- /dev/null +++ b/core/src/cz/nic/tablexia/bus/event/DownloadUserSynchronizationEvent.java @@ -0,0 +1,21 @@ +package cz.nic.tablexia.bus.event; + +import cz.nic.tablexia.bus.ApplicationBus; +import cz.nic.tablexia.shared.model.User; + +/** + * Created by frantisek on 22.1.16. + */ +public class DownloadUserSynchronizationEvent implements ApplicationBus.ApplicationEvent { + + private final User user; + + public DownloadUserSynchronizationEvent(User user) { + this.user = user; + } + + public User getUser() { + return user; + } + +} diff --git a/core/src/cz/nic/tablexia/bus/event/StartFullSynchronizationEvent.java b/core/src/cz/nic/tablexia/bus/event/StartFullSynchronizationEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..7720857f0ddc04bc733bedb1148bfa6198c4885f --- /dev/null +++ b/core/src/cz/nic/tablexia/bus/event/StartFullSynchronizationEvent.java @@ -0,0 +1,33 @@ +package cz.nic.tablexia.bus.event; + +import java.util.ArrayList; +import java.util.List; + +import cz.nic.tablexia.bus.ApplicationBus; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.sync.RestSynchronizationService; + +/** + * Created by frantisek on 18.1.16. + */ +public class StartFullSynchronizationEvent implements ApplicationBus.ApplicationEvent { + + private List<User> users; + + public StartFullSynchronizationEvent(List<User> users) { + this.users = users; + } + + public StartFullSynchronizationEvent(User user) { + users = new ArrayList<User>(); + users.add(user); + } + + public RestSynchronizationService.SynchronizationType getType() { + return RestSynchronizationService.SynchronizationType.FULL; + } + + public List<User> getUsers() { + return users; + } +} diff --git a/core/src/cz/nic/tablexia/bus/event/StartIncrementalSynchronizationEvent.java b/core/src/cz/nic/tablexia/bus/event/StartIncrementalSynchronizationEvent.java new file mode 100644 index 0000000000000000000000000000000000000000..ce2749196ef0acfd88387eeb661ae10b596448d1 --- /dev/null +++ b/core/src/cz/nic/tablexia/bus/event/StartIncrementalSynchronizationEvent.java @@ -0,0 +1,24 @@ +package cz.nic.tablexia.bus.event; + +import cz.nic.tablexia.bus.ApplicationBus; +import cz.nic.tablexia.sync.RestSynchronizationService; + +/** + * Created by frantisek on 18.1.16. + */ +public class StartIncrementalSynchronizationEvent implements ApplicationBus.ApplicationEvent { + + private final long userId; + + public StartIncrementalSynchronizationEvent(long userId) { + this.userId = userId; + } + + public long getUserId() { + return userId; + } + + public RestSynchronizationService.SynchronizationType getType() { + return RestSynchronizationService.SynchronizationType.INCREMENT; + } +} diff --git a/core/src/cz/nic/tablexia/debug/DebugInfo.java b/core/src/cz/nic/tablexia/debug/DebugInfo.java index a7f1435ebcf5e21b965156a47f40c5c263b37f6b..ef726f3f2746ec69853b97872c6a65360dcab43d 100644 --- a/core/src/cz/nic/tablexia/debug/DebugInfo.java +++ b/core/src/cz/nic/tablexia/debug/DebugInfo.java @@ -22,7 +22,7 @@ import cz.nic.tablexia.TablexiaApplication.ScreenChangedEvent; import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.loader.application.ApplicationAtlasManager; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.screen.AbstractTablexiaScreen.ScreenInfoEvent; import static com.badlogic.gdx.scenes.scene2d.actions.Actions.alpha; diff --git a/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java b/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java index cb5061b24b85828d84bbb4e7ce30f625f2212011..96b8f4956ca42c2720eb3cc6c069f5b37ec3dd57 100644 --- a/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java +++ b/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java @@ -33,6 +33,7 @@ import cz.nic.tablexia.TablexiaStorage; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.bus.event.DimmerControlEvent; import cz.nic.tablexia.bus.event.MenuControlEvent; +import cz.nic.tablexia.bus.event.StartIncrementalSynchronizationEvent; import cz.nic.tablexia.game.common.TablexiaRandom; import cz.nic.tablexia.game.difficulty.GameDifficulty; import cz.nic.tablexia.game.trophy.ITrophyDefinition; @@ -41,7 +42,9 @@ import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.loader.application.ApplicationTextManager; import cz.nic.tablexia.menu.AbstractMenu; import cz.nic.tablexia.menu.main.MainMenu; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.model.game.GameDAO; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.screen.gamemenu.GameMenuScreen; import cz.nic.tablexia.screen.halloffame.trophy.TrophyHelper; @@ -153,7 +156,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> @Override public boolean preloaderHasSpeech() { - return Game.getNumberOfIncompleteAndCompleteGamesForGameDefinition(GameDefinition.getGameDefinitionForClass(getClass()), getSelectedUser()) < TablexiaSettings.PRELOADER_SPEECH_PLAY_COUNT; + return GameDAO.getNumberOfIncompleteAndCompleteGamesForGameDefinition(GameDefinition.getGameDefinitionForClass(getClass()), getSelectedUser()) < TablexiaSettings.PRELOADER_SPEECH_PLAY_COUNT; } @@ -169,6 +172,11 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> return true; } + @Override + protected boolean canSyncOnResume() { + return false; + } + @Handler public void handleMenuPauseEvent(AbstractMenu.MenuPauseEvent menuPauseEvent) { if (menuPauseEvent.isPause()) { @@ -214,10 +222,10 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> protected final void screenResumed() { if (gamePhase == GamePhase.STARTED) { if (game.isStarted()) { - Long resumeTime = game.resumeGame(); + Long resumeTime = GameDAO.resumeGame(game); Log.info(getClass(), "[DB] GAME object resumed: " + resumeTime); } else { - game.startGame(); + GameDAO.startGame(game); Log.info(getClass(), "[DB] Started game: " + game); } performGameResumed(); @@ -241,7 +249,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> performGamePaused(screenState); screenState.put(GAME_STATE_GAME_ID, String.valueOf(game.getId())); Log.info(getClass(), "[DB] Stored game object to screen state: " + game); - Long endTime = game.pauseGame(); + Long endTime = GameDAO.pauseGame(game); Log.info(getClass(), "[DB] GAME object paused: " + endTime); } } @@ -274,14 +282,14 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> if (screenState.size() > 0) { // restore from game state String gameIdStr = screenState.get(GAME_STATE_GAME_ID); - game = gameIdStr != null ? Game.getGameForId(Long.valueOf(gameIdStr)) : null; + game = gameIdStr != null ? GameDAO.getGameForId(Long.valueOf(gameIdStr)) : null; } if (game == null) { // create new TablexiaRandom random = TablexiaSettings.GAMES_RANDOM_SEED == null ? new TablexiaRandom() : new TablexiaRandom(TablexiaSettings.GAMES_RANDOM_SEED); GameDefinition gameDefinition = GameDefinition.getGameDefinitionForClass(AbstractTablexiaGame.this.getClass()); - GameDifficulty gameDifficulty = gameDefinition.hasTutorial() && getSelectedUser().isTutorialForGameDefinition(gameDefinition) ? GameDifficulty.TUTORIAL : TablexiaSettings.getInstance().getGameDifficulty(gameDefinition); - game = Game.createGame(getSelectedUser(), gameDifficulty, gameDefinition, random); + GameDifficulty gameDifficulty = gameDefinition.hasTutorial() && UserDAO.isTutorialForGameDefinition(gameDefinition, getSelectedUser()) ? GameDifficulty.TUTORIAL : TablexiaSettings.getInstance().getGameDifficulty(gameDefinition); + game = GameDAO.createGame(getSelectedUser(), gameDifficulty, gameDefinition, random); Log.info(getClass(), "[DB] Created new GAME object: " + game); } else { Log.info(getClass(), "[DB] Restored last GAME object: " + game); @@ -346,7 +354,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> } private final void prepareGameTrophies() { - List<ITrophyDefinition> trophies = TrophyHelper.getPossibleTrophiesForGame(getGame().getGameDefinition()); + List<ITrophyDefinition> trophies = TrophyHelper.getPossibleTrophiesForGame(GameDefinition.getGameDefinitionForGameNumber(getGame().getGameNumber())); for (ITrophyDefinition trophy : trophies) { hasTrophies.put(trophy, trophy.hasTrophy(getSelectedUser())); } @@ -500,7 +508,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> if (getGameDifficulty() == GameDifficulty.TUTORIAL) { victoryDialogText = ApplicationTextManager.getInstance().getText(VICTORY_DIALOG_TUTORIAL_TEXT); } else { - String textKey = getTextKeyForGameResult(game.getGameResult()); + String textKey = getTextKeyForGameResult(GameDAO.getGameResult(game)); victoryDialogText = textKey != null ? getText(textKey) : ""; } getContentTable().row(); @@ -525,7 +533,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> } private void showTrophies() { - List<ITrophyDefinition> trophies = TrophyHelper.getPossibleTrophiesForGame(getGame().getGameDefinition()); + List<ITrophyDefinition> trophies = TrophyHelper.getPossibleTrophiesForGame(GameDefinition.getGameDefinitionForGameNumber(getGame().getGameNumber())); List<ITrophyDefinition> received = new ArrayList<ITrophyDefinition>(); for (ITrophyDefinition trophy : trophies) { @@ -582,7 +590,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> public Dialog show(Stage stage) { super.show(stage); - final GameResult gameResult = game.getGameResult(); + final GameResult gameResult = GameDAO.getGameResult(game); // victory dialog sound getSound(VICTORY_DIALOG_SHOW_SOUND, false).play(); @@ -653,11 +661,11 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> } public TablexiaRandom getRandom() { - return game.getRandom(); + return new TablexiaRandom(game.getRandomSeed()); } public GameDifficulty getGameDifficulty() { - return game.getDifficulty(); + return GameDifficulty.getGameDifficultyForDifficultyNumber(game.getGameDifficulty()); } protected Game getGame() { @@ -666,12 +674,13 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> public void gameComplete() { endGame(); + ApplicationBus.getInstance().publishAsync(new StartIncrementalSynchronizationEvent(getSelectedUser().getId())); showVictoryDialog(); } public void endGame() { gamePhase = GamePhase.FINISHED; - game.endGame(); + GameDAO.endGame(game); Log.info(getClass(), "[DB] Ended game: " + game); } @@ -755,13 +764,13 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> public <T> void setGameScore(String key, T value) { if (game != null) { - game.setGameScore(key, String.valueOf(value)); + GameDAO.setGameScore(game, key, String.valueOf(value)); } } public String getGameScoreString(String key, String nullValue) { if (game != null) { - String gameScoreStr = game.getGameScore(key); + String gameScoreStr = game.getGameScoreValue(key); return gameScoreStr != null ? gameScoreStr : nullValue; } return nullValue; @@ -769,7 +778,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> public Integer getGameScoreInteger(String key, Integer nullValue) { if (game != null) { - String gameScoreStr = game.getGameScore(key); + String gameScoreStr = game.getGameScoreValue(key); return gameScoreStr != null ? Integer.valueOf(gameScoreStr) : nullValue; } return nullValue; @@ -777,7 +786,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> public Float getGameScoreFloat(String key, Float nullValue) { if (game != null) { - String gameScoreStr = game.getGameScore(key); + String gameScoreStr = game.getGameScoreValue(key); return gameScoreStr != null ? Float.valueOf(gameScoreStr) : nullValue; } return nullValue; @@ -785,7 +794,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> public Double getGameScoreDouble(String key, Double nullValue) { if (game != null) { - String gameScoreStr = game.getGameScore(key); + String gameScoreStr = game.getGameScoreValue(key); return gameScoreStr != null ? Double.valueOf(gameScoreStr) : nullValue; } return nullValue; @@ -793,7 +802,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T> public Boolean getGameScoreBoolean(String key, Boolean nullValue) { if (game != null) { - String gameScoreStr = game.getGameScore(key); + String gameScoreStr = game.getGameScoreValue(key); return gameScoreStr != null ? Boolean.valueOf(gameScoreStr) : nullValue; } return nullValue; diff --git a/core/src/cz/nic/tablexia/game/GameDefinition.java b/core/src/cz/nic/tablexia/game/GameDefinition.java index 4813bcc105daf49828afac610c300d08e2527f8a..d2bcf71b6ceef7aa3fc51b878905422e16937fd1 100644 --- a/core/src/cz/nic/tablexia/game/GameDefinition.java +++ b/core/src/cz/nic/tablexia/game/GameDefinition.java @@ -17,7 +17,7 @@ import cz.nic.tablexia.game.games.shooting_range.tools.ShootingRangeResultResolv import cz.nic.tablexia.loader.application.ApplicationTextManager; import cz.nic.tablexia.menu.AbstractMenu; import cz.nic.tablexia.menu.IMenuItem; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.screen.gamemenu.GameMenuScreen; import cz.nic.tablexia.screen.gamemenu.event.ShowGameMenuPageEvent; diff --git a/core/src/cz/nic/tablexia/game/difficulty/GameDifficulty.java b/core/src/cz/nic/tablexia/game/difficulty/GameDifficulty.java index b7b7777238098dc28d8483ce99fa5f1b2962a8a3..6cc48acd9b37b7ab7483bdfbbe6592b37b070d70 100644 --- a/core/src/cz/nic/tablexia/game/difficulty/GameDifficulty.java +++ b/core/src/cz/nic/tablexia/game/difficulty/GameDifficulty.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.List; import cz.nic.tablexia.loader.application.ApplicationTextManager; +import cz.nic.tablexia.shared.model.Game; /** * Game difficulty types @@ -87,4 +88,8 @@ public enum GameDifficulty { } return null; } + + public static GameDifficulty getByGame(Game game) { + return getGameDifficultyForDifficultyNumber(game.getGameDifficulty()); + } } diff --git a/core/src/cz/nic/tablexia/game/games/in_the_darkness/InTheDarknessGame.java b/core/src/cz/nic/tablexia/game/games/in_the_darkness/InTheDarknessGame.java index 650a0022b96fb535a91c1f658c30ebe889256c7a..189654bcfb2c1b06ea8d0e289a4a9862f76e00d0 100644 --- a/core/src/cz/nic/tablexia/game/games/in_the_darkness/InTheDarknessGame.java +++ b/core/src/cz/nic/tablexia/game/games/in_the_darkness/InTheDarknessGame.java @@ -36,7 +36,7 @@ import cz.nic.tablexia.game.games.in_the_darkness.map.mapobject.MapObjectType; import cz.nic.tablexia.game.games.in_the_darkness.map.tile.Tile; import cz.nic.tablexia.game.games.in_the_darkness.map.widget.MapWidget; import cz.nic.tablexia.loader.application.ApplicationTextManager; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.ScaleUtil; import cz.nic.tablexia.util.ui.AnimatedImage; @@ -61,7 +61,7 @@ public class InTheDarknessGame extends AbstractTablexiaGame<List<MapWidget>> imp public static class GameResultResolver implements GameDefinition.GameResultResolver { @Override public AbstractTablexiaGame.GameResult getGameCupsResult(Game game) { - Integer errorsCount = Integer.valueOf(game.getGameScore(InTheDarknessGame.SCORE_KEY_ERRORS_COUNT)); + Integer errorsCount = Integer.valueOf(game.getGameScoreValue(InTheDarknessGame.SCORE_KEY_ERRORS_COUNT)); if (errorsCount < 2) { return AbstractTablexiaGame.GameResult.THREE_STAR; } else if (errorsCount < 4) { diff --git a/core/src/cz/nic/tablexia/game/games/kidnapping/KidnappingGame.java b/core/src/cz/nic/tablexia/game/games/kidnapping/KidnappingGame.java index 4f1e4ade40cc4b67bdc4c61b2277fabab06d534f..d2214b8ecaf84ff878f51773031b02b24d66a78c 100644 --- a/core/src/cz/nic/tablexia/game/games/kidnapping/KidnappingGame.java +++ b/core/src/cz/nic/tablexia/game/games/kidnapping/KidnappingGame.java @@ -47,7 +47,7 @@ import cz.nic.tablexia.game.games.kidnapping.util.DirectionsHelper; import cz.nic.tablexia.loader.application.ApplicationAtlasManager; import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.loader.application.ApplicationTextManager; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.MusicUtil; import cz.nic.tablexia.util.ScaleUtil; import cz.nic.tablexia.util.ui.AnimatedImage; @@ -89,7 +89,7 @@ public class KidnappingGame extends AbstractTablexiaGame<GameState> { @Override protected GameState prepareGameData(java.util.Map<String, String> gameState) { - GameState gs = GameState.GameStateFactory.createInstance(getGame(),getRandom(), getGameDifficulty(), Properties.MAP_WIDTH, Properties.MAP_HEIGHT, Properties.GAME_STOPS, Properties.MAP_WIDTH / 2, Properties.MAP_HEIGHT / 2); + GameState gs = GameState.GameStateFactory.createInstance(getGame(), getRandom(), getGameDifficulty(), Properties.MAP_WIDTH, Properties.MAP_HEIGHT, Properties.GAME_STOPS, Properties.MAP_WIDTH / 2, Properties.MAP_HEIGHT / 2); return gs; } diff --git a/core/src/cz/nic/tablexia/game/games/kidnapping/model/GameState.java b/core/src/cz/nic/tablexia/game/games/kidnapping/model/GameState.java index 4afbb63be32f3300e78d1fafa1ab25180a549903..e3a61e2a2e92d1d6afa1bb81aef1829c48b80caf 100644 --- a/core/src/cz/nic/tablexia/game/games/kidnapping/model/GameState.java +++ b/core/src/cz/nic/tablexia/game/games/kidnapping/model/GameState.java @@ -13,7 +13,8 @@ import cz.nic.tablexia.game.games.kidnapping.generator.TileMapGenerator; import cz.nic.tablexia.game.games.kidnapping.media.DirectionSounds; import cz.nic.tablexia.game.games.kidnapping.media.assets.TileType; import cz.nic.tablexia.game.games.kidnapping.util.DirectionsHelper; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.model.game.GameDAO; +import cz.nic.tablexia.shared.model.Game; /** * Created by lhoracek on 5/15/15. @@ -56,8 +57,8 @@ public class GameState { } public void setStep(int step) { - if(game!=null) { - game.setGameScore(GAME_STEP, String.valueOf(step)); + if (game != null) { + GameDAO.setGameScore(game, GAME_STEP, String.valueOf(step)); } this.step = step; } @@ -71,19 +72,19 @@ public class GameState { } public void addReplay() { - game.setGameScore(GAME_REPLAYS, String.valueOf(getReplays() + 1)); + GameDAO.setGameScore(game, GAME_REPLAYS, String.valueOf(getReplays() + 1)); } public void addMiss() { - game.setGameScore(GAME_MISSES, String.valueOf(getMisses() + 1)); + GameDAO.setGameScore(game, GAME_MISSES, String.valueOf(getMisses() + 1)); } public void resetMisses() { - game.setGameScore(GAME_MISSES, String.valueOf(0)); + GameDAO.setGameScore(game, GAME_MISSES, String.valueOf(0)); } public void resetReplays() { - game.setGameScore(GAME_REPLAYS, String.valueOf(0)); + GameDAO.setGameScore(game, GAME_REPLAYS, String.valueOf(0)); } public int getMisses() { diff --git a/core/src/cz/nic/tablexia/game/games/kidnapping/util/KidnappingResultResolver.java b/core/src/cz/nic/tablexia/game/games/kidnapping/util/KidnappingResultResolver.java index 6070d1a4cb5cb80b893d61a8b6694761555f9509..fde3a17ee663c84e11c71a07f6c9bc2896559009 100644 --- a/core/src/cz/nic/tablexia/game/games/kidnapping/util/KidnappingResultResolver.java +++ b/core/src/cz/nic/tablexia/game/games/kidnapping/util/KidnappingResultResolver.java @@ -4,7 +4,7 @@ import cz.nic.tablexia.game.AbstractTablexiaGame; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.games.kidnapping.Properties; import cz.nic.tablexia.game.games.kidnapping.model.GameState; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.Log; /** @@ -13,9 +13,9 @@ import cz.nic.tablexia.util.Log; public class KidnappingResultResolver implements GameDefinition.GameResultResolver { @Override public AbstractTablexiaGame.GameResult getGameCupsResult(Game game) { - int[] levels = Properties.GAMERULE_CUPS[game.getDifficulty().getDifficultyNumber() - 1]; - if (game.getGameScore(GameState.GAME_MISSES) != null) { - int misses = Integer.valueOf(game.getGameScore(GameState.GAME_MISSES)); + int[] levels = Properties.GAMERULE_CUPS[game.getGameDifficulty() - 1]; + if (game.getGameScoreValue(GameState.GAME_MISSES) != null) { + int misses = Integer.valueOf(game.getGameScoreValue(GameState.GAME_MISSES)); if (misses <= levels[0]) { return AbstractTablexiaGame.GameResult.THREE_STAR; } else if (misses <= levels[1]) { diff --git a/core/src/cz/nic/tablexia/game/games/night_watch/NightWatchGame.java b/core/src/cz/nic/tablexia/game/games/night_watch/NightWatchGame.java index 81b40f458aae4a95cc13eefd842d022c358b495d..7adc332fd8cca2770222695b518ab6351a628791 100644 --- a/core/src/cz/nic/tablexia/game/games/night_watch/NightWatchGame.java +++ b/core/src/cz/nic/tablexia/game/games/night_watch/NightWatchGame.java @@ -35,7 +35,7 @@ import cz.nic.tablexia.game.games.night_watch.solution.GameSolutionGenerator; import cz.nic.tablexia.game.games.night_watch.solution.Solution; import cz.nic.tablexia.game.games.night_watch.subscene.Watch; import cz.nic.tablexia.loader.application.ApplicationTextManager; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.ScaleUtil; import cz.nic.tablexia.util.Utility; @@ -49,8 +49,8 @@ public class NightWatchGame extends AbstractTablexiaGame<int[][]> { public static class GameResultResolver implements GameDefinition.GameResultResolver { @Override public GameResult getGameCupsResult(Game game) { - int correctWindows = LEVELS_COUNT - Integer.valueOf(game.getGameScore(SCORE_WRONG_WINDOWS)); - int correctTimeCount = LEVELS_COUNT - Integer.valueOf(game.getGameScore(SCORE_WRONG_TIME)); + int correctWindows = LEVELS_COUNT - Integer.valueOf(game.getGameScoreValue(SCORE_WRONG_WINDOWS)); + int correctTimeCount = LEVELS_COUNT - Integer.valueOf(game.getGameScoreValue(SCORE_WRONG_TIME)); return GameRulesHelper.getNumberOfStarsForResult(correctWindows + correctTimeCount); } diff --git a/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java b/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java index 2caad9f7ac8618489fbb5338d6a35886cdc45176..46b7f9ef895b284e386e6cfb77df94e6cfc3a327 100644 --- a/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java +++ b/core/src/cz/nic/tablexia/game/games/pursuit/PursuitGame.java @@ -21,6 +21,7 @@ import cz.nic.tablexia.TablexiaApplication; import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.game.AbstractTablexiaGame; import cz.nic.tablexia.game.GameDefinition; +import cz.nic.tablexia.game.difficulty.GameDifficulty; import cz.nic.tablexia.game.games.pursuit.action.RotateAndMovePieceInPosition; import cz.nic.tablexia.game.games.pursuit.action.RotatePieceToClosestAngle; import cz.nic.tablexia.game.games.pursuit.assets.PursuitAssets; @@ -34,7 +35,8 @@ import cz.nic.tablexia.game.games.pursuit.model.PuzzlePiece; import cz.nic.tablexia.game.games.pursuit.model.Vehicle; import cz.nic.tablexia.game.games.pursuit.model.VehicleType; import cz.nic.tablexia.loader.application.ApplicationTextManager; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.model.game.GameDAO; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.Point; import cz.nic.tablexia.util.ScaleUtil; @@ -51,7 +53,7 @@ public class PursuitGame extends AbstractTablexiaGame<int[][]> { public static class GameResultResolver implements GameDefinition.GameResultResolver { @Override public GameResult getGameCupsResult(Game game) { - return GameRulesHelper.getNumberOfStarsForTime(game.getDifficulty(), game.getGameDuration()); + return GameRulesHelper.getNumberOfStarsForTime(GameDifficulty.getGameDifficultyForDifficultyNumber(game.getGameDifficulty()), game.getGameDuration()); } @Override public float getGameScoreResult(Game game) { @@ -296,7 +298,7 @@ public class PursuitGame extends AbstractTablexiaGame<int[][]> { } private void updateMapIndex() { - String lastMap = getGame().getLastGameScoreValueForGameAndKey(GameDefinition.PURSUIT.getGameNumber(), SCORE_KEY_LAST_MAP); + String lastMap = GameDAO.getLastGameScoreValueForGameAndKey(GameDefinition.PURSUIT.getGameNumber(), SCORE_KEY_LAST_MAP); //couldn't find the last map if(lastMap == null) { diff --git a/core/src/cz/nic/tablexia/game/games/robbery/AbstractRobberyScreen.java b/core/src/cz/nic/tablexia/game/games/robbery/AbstractRobberyScreen.java index fa634d2185075718028d3ebb512cdb52fd9f0086..96dd3183bfa9c480c0b9a664cbd6ee74a4de3cea 100644 --- a/core/src/cz/nic/tablexia/game/games/robbery/AbstractRobberyScreen.java +++ b/core/src/cz/nic/tablexia/game/games/robbery/AbstractRobberyScreen.java @@ -41,6 +41,10 @@ public abstract class AbstractRobberyScreen extends AbstractTablexiaScreen<GameR return robberyGame.isScreenPaused(); } + @Override + protected boolean canSyncOnResume() { + return false; + } //////////////////////////// ASSETS ACCESS diff --git a/core/src/cz/nic/tablexia/game/games/robbery/RobberyGame.java b/core/src/cz/nic/tablexia/game/games/robbery/RobberyGame.java index 39d31cb47d3e6c4d48f07e5d31c66a56e8c484c9..147611be94e77c873930c93f941f9267cf45b4ba 100644 --- a/core/src/cz/nic/tablexia/game/games/robbery/RobberyGame.java +++ b/core/src/cz/nic/tablexia/game/games/robbery/RobberyGame.java @@ -19,8 +19,8 @@ import cz.nic.tablexia.game.games.robbery.creature.CreatureFactory; import cz.nic.tablexia.game.games.robbery.rules.GameRule; import cz.nic.tablexia.game.games.robbery.rules.GameRulesDefinition; import cz.nic.tablexia.loader.application.ApplicationTextManager; -import cz.nic.tablexia.model.User; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.util.ScaleUtil; import cz.nic.tablexia.util.ui.AnimatedImage; @@ -30,7 +30,7 @@ public class RobberyGame extends AbstractTablexiaGame<GameRule> { public static class GameResultResolver implements GameDefinition.GameResultResolver { @Override public GameResult getGameCupsResult(Game game) { - int creaturesCount = Integer.valueOf(game.getGameScore(RobberyGame.SCORE_KEY_PERSON_NUMBER)) + 1; + int creaturesCount = Integer.valueOf(game.getGameScore(RobberyGame.SCORE_KEY_PERSON_NUMBER, "0")) + 1; if (creaturesCount > 49) { return AbstractTablexiaGame.GameResult.THREE_STAR; } else if (creaturesCount > 29) { @@ -44,7 +44,7 @@ public class RobberyGame extends AbstractTablexiaGame<GameRule> { @Override public float getGameScoreResult(Game game) { - return Float.parseFloat(game.getGameScore(RobberyGame.SCORE_KEY_PERSON_NUMBER,"0")) + 1; + return Float.parseFloat(game.getGameScore(RobberyGame.SCORE_KEY_PERSON_NUMBER, "0")) + 1; } } @@ -211,7 +211,7 @@ public class RobberyGame extends AbstractTablexiaGame<GameRule> { @Override protected List<SummaryMessage> getSummaryMessageForGameResult(Game game) { String identification = game.getUser().getGender() == User.Gender.MALE ? getText(SUMMARY_IDENTIFICATION_MALE_TEXT_KEY) : getText(SUMMARY_IDENTIFICATION_FEMALE_TEXT_KEY); - return Arrays.asList(new SummaryMessage(SummaryImage.STATS, getFormattedText(SUMMARY_TEXT_KEY, identification, game.getGameScore(SCORE_KEY_PERSON_NUMBER, "0"), game.getGameScore(SCORE_KEY_PERSON_COUNT)))); + return Arrays.asList(new SummaryMessage(SummaryImage.STATS, getFormattedText(SUMMARY_TEXT_KEY, identification, game.getGameScore(SCORE_KEY_PERSON_NUMBER, "0"), game.getGameScoreValue(SCORE_KEY_PERSON_COUNT)))); } @Override diff --git a/core/src/cz/nic/tablexia/game/games/shooting_range/ShootingRangeGame.java b/core/src/cz/nic/tablexia/game/games/shooting_range/ShootingRangeGame.java index d30ac8d002b23af250659665b0ce73c077d84d36..538f97c5cca648bbbd52bbef45a2f399606c3c31 100644 --- a/core/src/cz/nic/tablexia/game/games/shooting_range/ShootingRangeGame.java +++ b/core/src/cz/nic/tablexia/game/games/shooting_range/ShootingRangeGame.java @@ -37,7 +37,7 @@ import cz.nic.tablexia.game.games.shooting_range.tools.TargetGenerator; import cz.nic.tablexia.game.games.shooting_range.tools.TargetPositionController; import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.loader.application.ApplicationTextManager; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.ScaleUtil; import cz.nic.tablexia.util.ui.AnimatedImage; diff --git a/core/src/cz/nic/tablexia/game/games/shooting_range/tools/ShootingRangeResultResolver.java b/core/src/cz/nic/tablexia/game/games/shooting_range/tools/ShootingRangeResultResolver.java index 0848b57819939a6e1d98cbf7837dd88cbfa1bec8..8ffe5eed85732b8668836477f9fff1a6de0f5882 100644 --- a/core/src/cz/nic/tablexia/game/games/shooting_range/tools/ShootingRangeResultResolver.java +++ b/core/src/cz/nic/tablexia/game/games/shooting_range/tools/ShootingRangeResultResolver.java @@ -3,7 +3,7 @@ package cz.nic.tablexia.game.games.shooting_range.tools; import cz.nic.tablexia.game.AbstractTablexiaGame; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.games.shooting_range.Properties; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; /** * Created by lhoracek on 10/6/15. @@ -13,7 +13,7 @@ public class ShootingRangeResultResolver implements GameDefinition.GameResultRes public AbstractTablexiaGame.GameResult getGameCupsResult(Game game) { int[][] CUPS = {Properties.CUPS_EASY, Properties.CUPS_MEDIUM, Properties.CUPS_HARD}; int gameScore = Integer.valueOf(game.getGameScore(Properties.SCORE_TOTAL, "0")); - int gameDificultyOrdinal = game.getDifficulty().getDifficultyNumber() -1; + int gameDificultyOrdinal = game.getGameDifficulty() - 1; if (gameScore > CUPS[gameDificultyOrdinal][2]) { return AbstractTablexiaGame.GameResult.THREE_STAR; diff --git a/core/src/cz/nic/tablexia/game/trophy/GameTrophyDefinition.java b/core/src/cz/nic/tablexia/game/trophy/GameTrophyDefinition.java index 5bd23ec312d85dfe1850bf98ba886d1487790918..60188ee5664f2d15438021a7dd851cb294d89d03 100644 --- a/core/src/cz/nic/tablexia/game/trophy/GameTrophyDefinition.java +++ b/core/src/cz/nic/tablexia/game/trophy/GameTrophyDefinition.java @@ -21,7 +21,7 @@ package cz.nic.tablexia.game.trophy; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.difficulty.GameDifficulty; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.model.game.GameTrophy; /** diff --git a/core/src/cz/nic/tablexia/game/trophy/ITrophyDefinition.java b/core/src/cz/nic/tablexia/game/trophy/ITrophyDefinition.java index cd368c8976b8d346e7224e1893de779eab4494e8..a73024f38a4877babdeb4e8f55e39abaa2daeccb 100644 --- a/core/src/cz/nic/tablexia/game/trophy/ITrophyDefinition.java +++ b/core/src/cz/nic/tablexia/game/trophy/ITrophyDefinition.java @@ -18,18 +18,13 @@ ******************************************************************************/ package cz.nic.tablexia.game.trophy; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; - -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.shared.model.User; public interface ITrophyDefinition { - public String getTrophyName(); - public String getTrophyDescription(); - public boolean hasTrophy(User user); - public String name(); + String getTrophyName(); + String getTrophyDescription(); + boolean hasTrophy(User user); + String name(); } diff --git a/core/src/cz/nic/tablexia/game/trophy/UserTrophyDefinition.java b/core/src/cz/nic/tablexia/game/trophy/UserTrophyDefinition.java index e0b1e1fa44c423789d8955a391230ffbc8b1228b..96cf927513b97cda95057e7a93afcbba88103859 100644 --- a/core/src/cz/nic/tablexia/game/trophy/UserTrophyDefinition.java +++ b/core/src/cz/nic/tablexia/game/trophy/UserTrophyDefinition.java @@ -23,7 +23,7 @@ import java.util.ArrayList; import java.util.List; import cz.nic.tablexia.game.difficulty.GameDifficulty; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.model.game.*; /** diff --git a/core/src/cz/nic/tablexia/menu/MenuController.java b/core/src/cz/nic/tablexia/menu/MenuController.java index f95944d1e1c28f244122a610c23ff6d112a41112..ec212154b033f4fd6abc2f4493136c9216afab42 100644 --- a/core/src/cz/nic/tablexia/menu/MenuController.java +++ b/core/src/cz/nic/tablexia/menu/MenuController.java @@ -19,8 +19,10 @@ import cz.nic.tablexia.TablexiaApplication; import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.bus.event.MenuControlEvent; +import cz.nic.tablexia.bus.event.StartFullSynchronizationEvent; import cz.nic.tablexia.menu.main.MainMenu; import cz.nic.tablexia.menu.user.UserMenu; +import cz.nic.tablexia.model.UserDAO; import cz.nic.tablexia.screen.AbstractTablexiaScreen; /** @@ -173,6 +175,7 @@ public class MenuController extends Group implements Disposable { public void screenVisibleEvent(AbstractTablexiaScreen.ScreenVisibleEvent screenVisibleEvent) { if (TablexiaSettings.LOADER_SCREEN.equals(TablexiaApplication.getActualScreenClass())) { if (loadingComplete && TablexiaSettings.getInstance().getSelectedUser() == null) { + ApplicationBus.getInstance().publish(new StartFullSynchronizationEvent(UserDAO.selectActiveUsers())); doMenuAction(UserMenu.class, AbstractMenu.MenuAction.OPEN, true, true); } } else { diff --git a/core/src/cz/nic/tablexia/menu/main/user/UserSelectBox.java b/core/src/cz/nic/tablexia/menu/main/user/UserSelectBox.java index b8f443ba4cc9c5dcabe839c6d65d706eafad07b2..fbc7bcd4e03379d65ba0c4aeabbe2f9b4d8c276e 100644 --- a/core/src/cz/nic/tablexia/menu/main/user/UserSelectBox.java +++ b/core/src/cz/nic/tablexia/menu/main/user/UserSelectBox.java @@ -16,9 +16,11 @@ import cz.nic.tablexia.TablexiaApplication; import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.loader.application.ApplicationAtlasManager; +import cz.nic.tablexia.menu.user.UserMenuItem; import cz.nic.tablexia.menu.user.UserMenuNewSelectBoxItemGroup; import cz.nic.tablexia.menu.user.UserMenuSelectBoxItemGroup; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.screen.createuser.PanoramaScreen; import cz.nic.tablexia.util.ui.AbstractTablexiaSelectBox; @@ -73,8 +75,8 @@ public class UserSelectBox extends AbstractTablexiaSelectBox<UserSelectBox.UserS removeCaptureListener(changeListener); UserMenuSelectBoxItemGroup selectedUserItem = null; List<UserSelectBoxItem> userItems = new ArrayList<UserSelectBoxItem>(); - for (User user: User.selectActiveUsers()) { - UserMenuSelectBoxItemGroup userItem = new UserMenuSelectBoxItemGroup(user, getWidth()); + for (User user: UserDAO.selectActiveUsers()) { + UserMenuSelectBoxItemGroup userItem = new UserMenuSelectBoxItemGroup(new UserMenuItem(user), getWidth()); userItems.add(userItem); if (user.equals(TablexiaSettings.getInstance().getSelectedUser())) { selectedUserItem = userItem; diff --git a/core/src/cz/nic/tablexia/menu/user/UserMenu.java b/core/src/cz/nic/tablexia/menu/user/UserMenu.java index 0ddbed2cfdd9b8754854f6a6cb849c072067d8a6..99f8ba2ce43c40230b21ed509d87772fcf08ffc8 100644 --- a/core/src/cz/nic/tablexia/menu/user/UserMenu.java +++ b/core/src/cz/nic/tablexia/menu/user/UserMenu.java @@ -1,32 +1,45 @@ package cz.nic.tablexia.menu.user; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.scenes.scene2d.Actor; import com.badlogic.gdx.scenes.scene2d.Group; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Container; +import com.badlogic.gdx.scenes.scene2d.ui.Image; import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane; +import com.badlogic.gdx.scenes.scene2d.ui.TextField; import com.badlogic.gdx.scenes.scene2d.ui.VerticalGroup; import com.badlogic.gdx.scenes.scene2d.utils.ActorGestureListener; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import net.engio.mbassy.listener.Handler; import cz.nic.tablexia.Tablexia; import cz.nic.tablexia.TablexiaApplication; +import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.bus.ApplicationBus; +import cz.nic.tablexia.bus.event.DeleteUserSynchronizationEvent; import cz.nic.tablexia.bus.event.MenuControlEvent; import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.loader.application.ApplicationInternalSoundManager; import cz.nic.tablexia.loader.application.ApplicationTextManager; import cz.nic.tablexia.menu.AbstractMenu; -import cz.nic.tablexia.menu.IMenuItem; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.screen.createuser.PanoramaScreen; +import cz.nic.tablexia.sync.RestSynchronizationService; +import cz.nic.tablexia.sync.work.DownloadUser; +import cz.nic.tablexia.sync.work.SyncWork; import cz.nic.tablexia.util.ui.ClickListenerWithSound; import cz.nic.tablexia.util.ui.TablexiaButton; import cz.nic.tablexia.util.ui.dialog.TablexiaDialog; +import cz.nic.tablexia.util.ui.dialog.TwoButtonDialog; +import cz.nic.tablexia.util.ui.dialog.text.DialogTextContent; /** * UserMenu container @@ -66,14 +79,15 @@ public class UserMenu extends AbstractMenu { final Container<ScrollPane> container = new Container<ScrollPane>(scrollPane); container.setFillParent(true); final float userMenuItemWidth = getBackground().getWidth(); - for (final IMenuItem menuItem : User.selectActiveUsers()) { + for (final User user : UserDAO.selectActiveUsers()) { + final UserMenuItem menuItem = new UserMenuItem(user); final Group userItemGroup = getGroupForMenuItem(menuItem, getWidth()); userItemGroup.setSize(userMenuItemWidth, USER_ITEM_HEIGHT); userItemGroup.addListener(new ActorGestureListener() { @Override public boolean longPress(Actor actor, float x, float y) { int index = menuItemsLayout.getChildren().indexOf(actor, false); - final User selected = User.selectActiveUsers().get(index); + final User selected = UserDAO.selectActiveUsers().get(index); // TODO: 12.1.16 rework dialog String dialogText = ApplicationTextManager.getInstance().getText(ApplicationTextManager.ApplicationTextsAssets.USERMENU_DELETE_USER) + " " + selected.getName() + "?"; Label dialogLabel = new Label(dialogText, new Label.LabelStyle(ApplicationFontManager.getInstance().getFont(ApplicationFontManager.FontType.ROBOTO_REGULAR_18), Color.BLACK)); @@ -91,8 +105,9 @@ public class UserMenu extends AbstractMenu { public void onClick(InputEvent event, float x, float y) { if (event.getListenerActor().getUserObject().equals(BUTTON_OK_ID)) { selected.setDeleted(true); - User.updateUser(selected); + UserDAO.updateUser(selected); menuItemsLayout.removeActor(userItemGroup); + ApplicationBus.getInstance().publishAsync(new DeleteUserSynchronizationEvent(selected)); } dialog.hide(); } @@ -131,6 +146,25 @@ public class UserMenu extends AbstractMenu { }); menuItemsLayout.addActor(userMenuNewSelectBoxItemGroup); + + final SyncDialog dialog = new SyncDialog(300, 300, 500, 300); + final UserMenuDownloadSelectBoxItemGroup userDownload = new UserMenuDownloadSelectBoxItemGroup() { + @Override + public void performAction() { + dialog.show(getStage()); + } + }; + + userDownload.setSize(userMenuItemWidth, USER_ITEM_HEIGHT); + userDownload.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + ApplicationInternalSoundManager.getInstance().getSound(ApplicationInternalSoundManager.BUTTON_CLICKED).play(); + userDownload.performAction(); + } + }); + menuItemsLayout.addActor(userDownload); + layoutContainer.setActor(container); } @@ -143,7 +177,77 @@ public class UserMenu extends AbstractMenu { //////////////////////////// CREATE USER EVENT HANDLING @Handler - public void handleCreatedUserEvent(User.CreatedUserEvent createdUserEvent) { + public void handleCreatedUserEvent(UserDAO.CreatedUserEvent createdUserEvent) { initMenuItems(); } + + @Handler + public void handleRefreshUserMenuEvent(RefreshUserMenu refreshEvent) { + Gdx.app.postRunnable(new Runnable() { + @Override + public void run() { + initMenuItems(); + } + }); + } + + public static class RefreshUserMenu implements ApplicationBus.ApplicationEvent { + + } + + private class SyncDialog extends TwoButtonDialog { + + private TextField textField; + + public SyncDialog(float x, float y, float width, float height) { + super(x, y, width, height, BackGroundType.DIALOG_RECTANGLE, new DialogTextContent("Download user"), TablexiaButton.ButtonType.GREEN, TablexiaButton.ButtonType.RED, "ok", "cancel"); + textField = new TextField("", new TextField.TextFieldStyle(ApplicationFontManager.getInstance().getFont(ApplicationFontManager.FontType.ROBOTO_BOLD_16), Color.BLACK, createCursorForTextField(), null, createBackground())); + textField.setWidth(250); + } + + @Override + protected void prepareContent() { + super.prepareContent(); + getContentTable().row(); + getContentTable().add(textField).fillX(); + } + + @Override + protected void leftButtonAction() { + DownloadUser syncWork = new DownloadUser(textField.getText()); + syncWork.registerListener(new SyncWork.RestSyncListener() { + @Override + public void onSuccess(User user) { + ApplicationBus.getInstance().post(new RefreshUserMenu()).asynchronously(); + } + }); + RestSynchronizationService.doSyncWork(syncWork); + hide(); + } + + @Override + protected void rightButtonAction() { + hide(); + } + + private Drawable createCursorForTextField() { + Pixmap pixmap = new Pixmap(1, 16, Pixmap.Format.RGBA8888); + pixmap.setColor(Color.WHITE); + pixmap.drawLine(0, 0, 0, 16); + Texture texture = new Texture(pixmap); + pixmap.dispose(); + Image img = new Image(texture); + return img.getDrawable(); + } + + private Drawable createBackground() { + Pixmap pixmap = new Pixmap(250, 16, Pixmap.Format.RGBA8888); + pixmap.setColor(Color.BLUE); + pixmap.drawRectangle(0, 0, 250, 16); + Texture texture = new Texture(pixmap); + pixmap.dispose(); + Image img = new Image(texture); + return img.getDrawable(); + } + } } diff --git a/core/src/cz/nic/tablexia/menu/user/UserMenuDownloadSelectBoxItemGroup.java b/core/src/cz/nic/tablexia/menu/user/UserMenuDownloadSelectBoxItemGroup.java new file mode 100644 index 0000000000000000000000000000000000000000..515feaeb9ea1ad9ef228796b695b5b783938f836 --- /dev/null +++ b/core/src/cz/nic/tablexia/menu/user/UserMenuDownloadSelectBoxItemGroup.java @@ -0,0 +1,48 @@ +package cz.nic.tablexia.menu.user; + +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.GlyphLayout; +import com.badlogic.gdx.graphics.g2d.NinePatch; +import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.utils.Align; + +import cz.nic.tablexia.loader.application.ApplicationAtlasManager; +import cz.nic.tablexia.loader.application.ApplicationFontManager; +import cz.nic.tablexia.menu.main.user.UserSelectBox; + +/** + * Created by frantisek on 20.1.16. + */ +public abstract class UserMenuDownloadSelectBoxItemGroup extends Actor implements UserSelectBox.UserSelectBoxItem { + + private static final ApplicationFontManager.FontType NEWUSER_TEXT_FONT = ApplicationFontManager.FontType.ROBOTO_BOLD_20_NOFILTER; + private static final Color NEWUSER_TEXT_COLOR = new Color(0.098f, 0.086f, 0.075f, 1f); + private static final int NEWUSER_TEXT_ALIGN = Align.center; + + private final NinePatch background; + private final BitmapFont font; + private final String text; + private final GlyphLayout glyphLayout; + + public UserMenuDownloadSelectBoxItemGroup() { + background = ApplicationAtlasManager.getInstance().getPatch(ApplicationAtlasManager.USERMENU_MENUBUTTON_BACKGROUND); + font = ApplicationFontManager.getInstance().getFont(NEWUSER_TEXT_FONT); + text = "Download user"; + glyphLayout = new GlyphLayout(); + } + + public abstract void performAction(); + + @Override + public void draw(Batch batch, float parentAlpha) { + NEWUSER_TEXT_COLOR.a = parentAlpha; + font.setColor(NEWUSER_TEXT_COLOR); + + background.draw(batch, getX(), getY(), getWidth(), getHeight()); + + glyphLayout.setText(font, text, NEWUSER_TEXT_COLOR, getWidth(), NEWUSER_TEXT_ALIGN, false); + font.draw(batch, glyphLayout, getX(), getY() + getHeight() / 2 + font.getLineHeight() / 3); + } +} diff --git a/core/src/cz/nic/tablexia/menu/user/UserMenuItem.java b/core/src/cz/nic/tablexia/menu/user/UserMenuItem.java new file mode 100644 index 0000000000000000000000000000000000000000..53604ee037dec422358e54eb3a062bdbe56e1215 --- /dev/null +++ b/core/src/cz/nic/tablexia/menu/user/UserMenuItem.java @@ -0,0 +1,63 @@ +package cz.nic.tablexia.menu.user; + +import com.badlogic.gdx.scenes.scene2d.Group; + +import cz.nic.tablexia.TablexiaSettings; +import cz.nic.tablexia.menu.AbstractMenu; +import cz.nic.tablexia.menu.IMenuItem; +import cz.nic.tablexia.shared.model.User; + +/** + * Created by frantisek on 11.1.16. + */ +public class UserMenuItem implements IMenuItem { + + private User user; + + private static final Class<UserMenuSelectBoxItemGroup> USER_ITEM_CLASS = UserMenuSelectBoxItemGroup.class; + + + public UserMenuItem(User user) { + this.user = user; + } + + public User getUser() { + return user; + } + + @Override + public String getTitle() { + return user.getName(); + } + + @Override + public String getDescription() { + return null; + } + + @Override + public String[] getIcons() { + // TODO return user avatar + return null; + } + + @Override + public Class<? extends Group> getItemGroupClass() { + return USER_ITEM_CLASS; + } + + @Override + public void performAction() { + TablexiaSettings.getInstance().setSelectedUser(this.user); + } + + @Override + public AbstractMenu.MenuAction getMenuAction() { + return AbstractMenu.MenuAction.HIDE; + } + + @Override + public IMenuItem[] getSubmenu() { + return null; + } +} diff --git a/core/src/cz/nic/tablexia/menu/user/UserMenuSelectBoxItemGroup.java b/core/src/cz/nic/tablexia/menu/user/UserMenuSelectBoxItemGroup.java index dbf03dbfa2cdd6625845854ac18b9fda67474b0d..3c94d5e7501f4288aaaea6c376030b92d38744a6 100644 --- a/core/src/cz/nic/tablexia/menu/user/UserMenuSelectBoxItemGroup.java +++ b/core/src/cz/nic/tablexia/menu/user/UserMenuSelectBoxItemGroup.java @@ -11,7 +11,7 @@ import cz.nic.tablexia.loader.application.ApplicationAtlasManager; import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.menu.IMenuItem; import cz.nic.tablexia.menu.main.user.UserSelectBox; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.shared.model.User; /** * Created by Matyáš Latner. @@ -27,21 +27,22 @@ public class UserMenuSelectBoxItemGroup extends Group implements UserSelectBox.U private final NinePatch background; private final BitmapFont font; private final TextureRegionDrawable image; - private final User user; + private final UserMenuItem userMenuItem; public UserMenuSelectBoxItemGroup(IMenuItem menuItem, float width) { - this.user = (User) menuItem; - background = ApplicationAtlasManager.getInstance().getPatch(ApplicationAtlasManager.USERMENU_MENUITEM_BACKGROUND); + this.userMenuItem = (UserMenuItem)menuItem; + + background = ApplicationAtlasManager.getInstance().getPatch(ApplicationAtlasManager.USERMENU_MENUITEM_BACKGROUND); font = ApplicationFontManager.getInstance().getFont(TEXT_FONT); - image = new TextureRegionDrawable(ApplicationAtlasManager.getInstance().getTextureRegion(UserAvatarDefinition.getAvatar(user.getAvatar()))); + image = new TextureRegionDrawable(ApplicationAtlasManager.getInstance().getTextureRegion(UserAvatarDefinition.getAvatar(userMenuItem.getUser().getAvatar()))); } public void performAction() { - user.performAction(); + userMenuItem.performAction(); } public User getUser() { - return user; + return userMenuItem.getUser(); } @Override @@ -56,6 +57,6 @@ public class UserMenuSelectBoxItemGroup extends Group implements UserSelectBox.U float textPositionX = getX() + imageWidth + TEXT_LEFT_OFFSET; float textPositionY = getY() + getHeight() / 2; - font.draw(batch, user.getName(), textPositionX, textPositionY + font.getLineHeight() / 3); + font.draw(batch, userMenuItem.getTitle(), textPositionX, textPositionY + font.getLineHeight() / 3); } } diff --git a/core/src/cz/nic/tablexia/model/User.java b/core/src/cz/nic/tablexia/model/UserDAO.java similarity index 51% rename from core/src/cz/nic/tablexia/model/User.java rename to core/src/cz/nic/tablexia/model/UserDAO.java index 3f1ca363b3cb4a7d610c1b3220e5315575731b0e..8d318873a94f9423feb1e324075410288891b4b9 100644 --- a/core/src/cz/nic/tablexia/model/User.java +++ b/core/src/cz/nic/tablexia/model/UserDAO.java @@ -1,189 +1,43 @@ package cz.nic.tablexia.model; -import com.badlogic.gdx.scenes.scene2d.Group; - import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.TablexiaStorage; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.difficulty.GameDifficulty; -import cz.nic.tablexia.menu.AbstractMenu; -import cz.nic.tablexia.menu.IMenuItem; -import cz.nic.tablexia.menu.user.UserMenuSelectBoxItemGroup; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.model.game.GameDAO; +import cz.nic.tablexia.model.game.GamePauseDAO; +import cz.nic.tablexia.model.game.GameScoreDAO; +import cz.nic.tablexia.shared.model.Game; +import cz.nic.tablexia.shared.model.GamePause; +import cz.nic.tablexia.shared.model.GameScore; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.util.Log; /** * Created by lhoracek, Matyáš Latner */ -public class User implements IMenuItem { - - private static final Class<UserMenuSelectBoxItemGroup> USER_ITEM_CLASS = UserMenuSelectBoxItemGroup.class; - - public enum Gender { - FEMALE(0), - MALE(1); - - private int genderId; - - Gender(int genderId) { - this.genderId = genderId; - } - - public static Gender getGenderForId(int genderId) { - for (Gender gender : Gender.values()) { - if (gender.genderId == genderId) { - return gender; - } - } - return null; - } - } - - private final Long id; - private final String name; - private final String avatar; - private final String signature; - private final int age; - private final Gender gender; - private boolean deleted; - private boolean help; - private boolean intro; - - //need to be pulic for testing purposes - public User(long id, String name, int age, Gender gender, String avatar, String signature, boolean deleted, boolean help, boolean intro) { - this.id = id; - this.name = name; - this.age = age; - this.gender = gender; - this.signature = signature; - this.avatar = avatar; - this.deleted = deleted; - this.help = help; - this.intro = intro; - } - - public Long getId() { - return id; - } - - public String getName() { - return name; - } - - public int getAge() { - return age; - } - - public Gender getGender() { - return gender; - } - - public boolean isDeleted() { - return deleted; - } - - public boolean isHelp() { - return help; - } - - public boolean isIntro() { - return intro; - } - - public String getAvatar() { - return avatar; - } - - public String getSignature() { - return signature; - } - - public void setIntro(boolean intro) { - this.intro = intro; - } - - public void setHelp(boolean help) { - this.help = help; - } - - public void setDeleted(boolean deleted) { - this.deleted = deleted; - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (!(obj instanceof User)) { - return false; - } - return ((User) obj).getId().equals(getId()); - } - - @Override - public String toString() { - return "USER[id: " + id + ", name: " + name + ", age: " + age + ", gen: " + gender.name() + ", del: " + deleted + ", help: " + help + ", intro: " + intro + "]"; - } - - -//////////////////////////// USER MENU ITEM - - @Override - public String getTitle() { - return getName(); - } - - @Override - public String getDescription() { - return null; - } - - @Override - public String[] getIcons() { - // TODO return user avatar - return null; - } - - @Override - public Class<? extends Group> getItemGroupClass() { - return USER_ITEM_CLASS; - } - - @Override - public void performAction() { - TablexiaSettings.getInstance().setSelectedUser(this); - } - - @Override - public AbstractMenu.MenuAction getMenuAction() { - return AbstractMenu.MenuAction.HIDE; - } - - @Override - public IMenuItem[] getSubmenu() { - return null; - } - +public class UserDAO { //////////////////////////// DB ACCESS - public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER NOT NULL, gender INTEGER NOT NULL, avatar TEXT NOT NULL, signature TEXT NOT NULL, deleted INTEGER NOT NULL DEFAULT 0, help INTEGER NOT NULL DEFAULT 1, intro INTEGER NOT NULL DEFAULT 1)"; + public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER NOT NULL, gender INTEGER NOT NULL, avatar TEXT NOT NULL, signature TEXT NOT NULL, deleted INTEGER NOT NULL DEFAULT 0, help INTEGER NOT NULL DEFAULT 1, intro INTEGER NOT NULL DEFAULT 1, uuid TEXT)"; public static final String UPDATE_USER = "UPDATE user SET help = ?, intro = ?, deleted = ? WHERE id = ?"; - public static final String INSERT_USER = "INSERT INTO user (name, age, gender, avatar, signature) VALUES (?, ?, ?, ?, ?)"; - public static final String SELECT_USER_FOR_ID = "SELECT id, name, age, gender, avatar, signature, deleted, help, intro FROM user WHERE id = ?"; - public static final String SELECT_LAST_USER = "SELECT id, name, age, gender, avatar, signature, deleted, help, intro FROM user WHERE id IN (SELECT max(id) FROM user)"; - public static final String SELECT_ACTIVE_USERS = "SELECT id, name, age, gender, avatar, signature, deleted, help, intro FROM user WHERE deleted = 0"; + public static final String INSERT_USER = "INSERT INTO user (name, age, gender, avatar, signature, uuid) VALUES (?, ?, ?, ?, ?, ?)"; + public static final String SELECT_USER_FOR_ID = "SELECT id, name, age, gender, avatar, signature, deleted, help, intro, uuid FROM user WHERE id = ?"; + public static final String SELECT_USER_FOR_UUID = "SELECT id, name, age, gender, avatar, signature, deleted, help, intro, uuid FROM user WHERE uuid = ?"; + public static final String SELECT_LAST_USER = "SELECT id, name, age, gender, avatar, signature, deleted, help, intro, uuid FROM user WHERE id IN (SELECT max(id) FROM user)"; + public static final String SELECT_ACTIVE_USERS = "SELECT id, name, age, gender, avatar, signature, deleted, help, intro, uuid FROM user WHERE deleted = 0"; public static final String SELECT_USER_ALREADY_EXISTS = "SELECT 1 FROM user WHERE name = ?"; + public static final String UPDATE_USER_UUID = "UPDATE user SET uuid = ? WHERE id = ?"; public static List<User> selectActiveUsers() { ArrayList<User> users = new ArrayList<User>(); @@ -192,16 +46,8 @@ public class User implements IMenuItem { try { ResultSet resultSet = statement.executeQuery(); while (resultSet.next()) { - long id = resultSet.getLong(1); - String name = resultSet.getString(2); - int age = resultSet.getInt(3); - Gender gender = Gender.getGenderForId(resultSet.getInt(4)); - String avatar = resultSet.getString(5); - String signature = resultSet.getString(6); - boolean deleted = resultSet.getInt(7) != 0; - boolean help = resultSet.getInt(8) != 0; - boolean intro = resultSet.getInt(9) != 0; - users.add(new User(id, name, age, gender, avatar, signature, deleted, help, intro)); + User user = fetchUser(resultSet); + users.add(user); } resultSet.close(); } catch (SQLException e) { @@ -214,15 +60,20 @@ public class User implements IMenuItem { return users; } - public static User createUser(String name, int age, Gender gender, String avatar, String signature) { + public static User createUser(String name, int age, User.Gender gender, String avatar, String signature) { + return createUser(name, age, gender, avatar, signature, null); + } + + public static User createUser(String name, int age, User.Gender gender, String avatar, String signature, String uuid) { User user = null; try { PreparedStatement insertStatement = TablexiaStorage.getInstance().prepareStatement(INSERT_USER); insertStatement.setString(1, name); insertStatement.setInt(2, age); - insertStatement.setInt(3, gender.genderId); + insertStatement.setInt(3, gender.getGenderId()); insertStatement.setString(4, avatar); insertStatement.setString(5, signature); + insertStatement.setString(6, uuid); insertStatement.executeUpdate(); insertStatement.close(); // insertStatement.getGeneratedKeys().getLong(1) cannot be used -> getGeneratedKeys() is not implemented in SQLDroid @@ -260,16 +111,7 @@ public class User implements IMenuItem { try { ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { - String name = resultSet.getString(2); - int age = resultSet.getInt(3); - Gender gender = Gender.getGenderForId(resultSet.getInt(4)); - String avatar = resultSet.getString(5); - String signature = resultSet.getString(6); - boolean deleted = resultSet.getInt(7) != 0; - boolean help = resultSet.getInt(8) != 0; - boolean intro = resultSet.getInt(9) != 0; - - selectedUser = new User(id, name, age, gender, avatar, signature, deleted, help, intro); + selectedUser = fetchUser(resultSet); } resultSet.close(); } catch (SQLException e) { @@ -282,6 +124,27 @@ public class User implements IMenuItem { return selectedUser; } + public static User selectUserByUuid(String uuid) { + User selectedUser = null; + try { + PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(SELECT_USER_FOR_UUID); + statement.setString(1, uuid); + try { + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + selectedUser = fetchUser(resultSet); + } + resultSet.close(); + } catch (SQLException e) { + Log.err(User.class, "Cannot select user with uuid: " + uuid, e); + } + statement.close(); + } catch (SQLException e) { + Log.err(User.class, "Cannot select user with uuid: " + uuid, e); + } + return selectedUser; + } + public static User selectLastUser() { User selectedUser = null; try { @@ -289,17 +152,7 @@ public class User implements IMenuItem { try { ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { - Long id = resultSet.getLong(1); - String name = resultSet.getString(2); - int age = resultSet.getInt(3); - Gender gender = Gender.getGenderForId(resultSet.getInt(4)); - String avatar = resultSet.getString(5); - String signature = resultSet.getString(6); - boolean deleted = resultSet.getInt(7) != 0; - boolean help = resultSet.getInt(8) != 0; - boolean intro = resultSet.getInt(9) != 0; - - selectedUser = new User(id, name, age, gender, avatar, signature, deleted, help, intro); + selectedUser = fetchUser(resultSet); } resultSet.close(); } catch (SQLException e) { @@ -312,8 +165,23 @@ public class User implements IMenuItem { return selectedUser; } - public boolean isTutorialForGameDefinition(GameDefinition gameDefinition) { - return Game.getNumberOfCompleteGamesForGameDefinitionAndDifficulty(gameDefinition, GameDifficulty.TUTORIAL, this) < 1; + public static boolean updateUserUuid(long userId, String userUuid) { + PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(UPDATE_USER_UUID); + try { + statement.setString(1, userUuid); + statement.setLong(2, userId); + int result = statement.executeUpdate(); + statement.close(); + return result == 1; + } catch (SQLException e) { + Log.err(UserDAO.class, "Failed to store user REST uuid", e); + } + + return false; + } + + public static boolean isTutorialForGameDefinition(GameDefinition gameDefinition, User user) { + return GameDAO.getNumberOfCompleteGamesForGameDefinitionAndDifficulty(gameDefinition, GameDifficulty.TUTORIAL, user) < 1; } public static boolean userNameExists(String name) { @@ -325,12 +193,91 @@ public class User implements IMenuItem { if (resultSet.next()) { exists = (resultSet.getInt(1) == 1); } + resultSet.close(); + statement.close(); } catch (SQLException e) { Log.err(User.class, "Cannot check if user with username exists", e); } return exists; } + private static User fetchUser(ResultSet resultSet) throws SQLException { + Long id = resultSet.getLong("id"); + String name = resultSet.getString("name"); + int age = resultSet.getInt("age"); + User.Gender gender = User.Gender.getGenderForId(resultSet.getInt("gender")); + String avatar = resultSet.getString("avatar"); + String signature = resultSet.getString("signature"); + boolean deleted = resultSet.getInt("deleted") != 0; + boolean help = resultSet.getInt("help") != 0; + boolean intro = resultSet.getInt("intro") != 0; + String uuid = resultSet.getString("uuid"); + + User user = new User(id, name, age, gender, avatar, signature, deleted, help, intro); + user.setUuid(uuid); + + return user; + } + + public static Long importUser(User user) { + try { + TablexiaStorage.getInstance().setAutoCommit(false); + + User dbUser = UserDAO.selectUserByUuid(user.getUuid()); + if (dbUser == null) { + dbUser = createUser(user.getName(), user.getAge(), user.getGender(), user.getAvatar(), user.getSignature(), user.getUuid()); + Log.debug(UserDAO.class, "Creating new user with id: " + dbUser.getId()); + } else { + Log.debug(UserDAO.class, "User already exists in tablexia with id: " + dbUser.getId()); + } + + // fill in tablexia DB id to originally received user + user.setId(dbUser.getId()); + + if (user.getGames() != null) { + for (Game game : user.getGames()) { + + if (game.getStartTime() == null || game.getGameStartTime() == 0 || GameDAO.selectGameByTimes(dbUser.getId(), game.getGameStartTime(), game.getEndTime()) != null) { + continue; + } + + Long gameId = GameDAO.importGame(dbUser, game.getGameDifficulty(), game.getGameNumber(), game.getRandomSeed(), game.getStartTime(), game.getEndTime()); + + if (gameId == null) { + continue; + } + + if (game.getGamePauses() != null) { + for (GamePause pause : game.getGamePauses()) { + GamePauseDAO.importPause(gameId, pause.getStartTime(), pause.getEndTime()); + } + } + + if (game.getGameScoreMap() != null) { + GameScoreDAO.batchInsertGameScore(gameId, game.getGameScoreMap()); + } + } + } + + TablexiaStorage.getInstance().commit(); + TablexiaStorage.getInstance().setAutoCommit(true); + + return dbUser.getId(); + + } catch (SQLException ex) { + Log.err(UserDAO.class, "Failed to import user", ex); + try { + TablexiaStorage.getInstance().rollback(); + } catch (SQLException rollEx) { + Log.err(UserDAO.class, "Failed to import user", rollEx); + } + } + + return null; + } + +//////////////////////////// DB MIGRATIONS + public static void migrateUserSignaturesData() { String replaceSql = "update user set signature = ? where id = ?"; String conditionSql = "select id, signature from user where signature like '%\"size\"%'"; @@ -366,6 +313,35 @@ public class User implements IMenuItem { } } + public static void migrateUserTableStructure() { + String addUuidColumn = "ALTER TABLE user ADD COLUMN uuid TEXT"; + String addSyncAtColumn = "ALTER TABLE game ADD COLUMN sync_at INTEGER"; + + PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(addUuidColumn); + if (statement == null) { + Log.info(UserDAO.class, "uuid column in user table is already there"); + } else { + try { + statement.executeUpdate(); + statement.close(); + } catch (SQLException e) { + Log.err(User.class, "Cannot migrate user structure: " + e.getMessage(), e); + } + } + + PreparedStatement syncAtStatement = TablexiaStorage.getInstance().prepareStatement(addSyncAtColumn); + if (syncAtStatement == null) { + Log.info(UserDAO.class, "sync_at column in game table is already there"); + } else { + try { + syncAtStatement.executeUpdate(); + syncAtStatement.close(); + } catch (SQLException e) { + Log.err(User.class, "Cannot migrate game structure: " + e.getMessage(), e); + } + } + } + //////////////////////////// EVENT diff --git a/core/src/cz/nic/tablexia/model/game/Game.java b/core/src/cz/nic/tablexia/model/game/GameDAO.java similarity index 60% rename from core/src/cz/nic/tablexia/model/game/Game.java rename to core/src/cz/nic/tablexia/model/game/GameDAO.java index f3a74b5d093acae6072f8a59067356bad8157073..f4ac00408f30ca1a5a99077505cfa03f9a9d53c9 100644 --- a/core/src/cz/nic/tablexia/model/game/Game.java +++ b/core/src/cz/nic/tablexia/model/game/GameDAO.java @@ -5,12 +5,9 @@ import com.badlogic.gdx.utils.TimeUtils; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.text.SimpleDateFormat; +import java.sql.Statement; import java.util.ArrayList; -import java.util.Calendar; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.TablexiaStorage; @@ -18,116 +15,18 @@ import cz.nic.tablexia.game.AbstractTablexiaGame; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.common.TablexiaRandom; import cz.nic.tablexia.game.difficulty.GameDifficulty; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.Game; +import cz.nic.tablexia.shared.model.GameScore; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.util.Log; /** * Created by Matyáš Latner */ -public class Game { - - private static final String DATE_AND_TIME_FORMAT = "d.M.yyyy HH:mm:ss", DATE_FORMAT = "d.M.yyyy"; - private static final Object ATOMIC_LOCK = new Object(); - - private long id; - private User user; - private GameDifficulty difficulty; - private GameDefinition gameDefinition; - private TablexiaRandom random; - private Long startTime; - private Long endTime; - - private Map<String, String> gameScoreMap; - - public Game(Long id, User user, GameDifficulty difficulty, GameDefinition gameDefinition, TablexiaRandom random) { - this(id, user, difficulty, gameDefinition, random, null, null); - } - - public Game(Long id, User user, GameDifficulty difficulty, GameDefinition gameDefinition, TablexiaRandom random, Long startTime, Long endTime) { - this(id, user, difficulty, gameDefinition, random, startTime, endTime, new ConcurrentHashMap<String, String>(GameScore.selectGameScores(id))); - } - - public Game(Long id, User user, GameDifficulty difficulty, GameDefinition gameDefinition, TablexiaRandom random, Long startTime, Long endTime, Map<String, String> scores) { - this.id = id; - this.user = user; - this.difficulty = difficulty; - this.gameDefinition = gameDefinition; - this.random = random; - this.startTime = startTime; - this.endTime = endTime; - - gameScoreMap = scores; - } - - public long getId() { - return id; - } - - public User getUser() { - return user; - } - - public GameDifficulty getDifficulty() { - return difficulty; - } - - public GameDefinition getGameDefinition() { - return gameDefinition; - } - - public TablexiaRandom getRandom() { - return random; - } - - public Long getAllPausesDuration() { - List<GamePause> gamePauses = GamePause.selectGamePausesForGame(this); - long pausesDuration = 0; - for (GamePause gamePause : gamePauses) { - if (gamePause.hasStartTime() && gamePause.hasEndTime()) { - pausesDuration = pausesDuration + (gamePause.getEndTime() - gamePause.getStartTime()); - } - } - return pausesDuration; - } - - public Long getGameDuration() { - if (endTime == null || startTime == null) { - return null; - } - return endTime - startTime - getAllPausesDuration(); - } - - public Long getGameStartTime() { - return startTime != null ? startTime : 0; - } - - /**if dateAndTime is true, return complete date and time, otherwise only a day*/ - public String getGameStartDate(boolean dateAndTime) { - - if (startTime == null) return ""; - - Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(startTime); - SimpleDateFormat sdf; - if (dateAndTime) { - sdf = new SimpleDateFormat(DATE_AND_TIME_FORMAT); - } else { - sdf = new SimpleDateFormat(DATE_FORMAT); - } - return sdf.format(cal.getTime()); - } - - @Override - public String toString() { - String output = "GAME[id: " + id + ", user: " + user.getName() + ", difficulty: " + difficulty.name() + ", game: " + gameDefinition.name() + ", random: " + random.getSeed() + ", start: " + startTime + ", end: " + endTime + "]"; - output = output + " SCORE: ["; - for (String gameScoreKey : gameScoreMap.keySet()) { - output = output + " " + gameScoreKey + " : " + gameScoreMap.get(gameScoreKey); - } - output = output + "]"; - return output; - } +public class GameDAO { + private static final Object ATOMIC_LOCK = new Object(); //////////////////////////// Game API @@ -135,7 +34,8 @@ public class Game { Game game = null; Long id = insertNewGame(user, difficulty, gameDefinition, random); if (id != null) { - game = new Game(id, user, difficulty, gameDefinition, random); + game = new Game(id, user, difficulty.getDifficultyNumber(), gameDefinition.getGameNumber(), random.getSeed()); + game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game)); } return game; } @@ -152,68 +52,50 @@ public class Game { return selectGamesForUserAndDefinition(userId, definition); } - public void startGame() { - startTime = gameUpdateStart(getId(), TimeUtils.millis()); + public static void startGame(Game game) { + game.setStartTime(gameUpdateStart(game.getId(), TimeUtils.millis())); } - public void endGame() { - endTime = gameUpdateEnd(getId(), TimeUtils.millis()); + public static void endGame(Game game) { + game.setEndTime(gameUpdateEnd(game.getId(), TimeUtils.millis())); } - public Long pauseGame() { - if (!isFinished()) { - return GamePause.createGamePause(this); + public static Long pauseGame(Game game) { + if (!game.isFinished()) { + return GamePauseDAO.createGamePause(game); } return null; } - public Long resumeGame() { - if (!isFinished()) { - return GamePause.updateGamePauseEnd(this); + public static Long resumeGame(Game game) { + if (!game.isFinished()) { + return GamePauseDAO.updateGamePauseEnd(game); } return null; } - public boolean isStarted() { - return startTime != null; - } - - public boolean isFinished() { - return endTime != null; - } - - public void setGameScore(final String key, final String value) { + public static void setGameScore(final Game game, final String key, final String value) { new Thread(new Runnable() { @Override public void run() { - synchronized (ATOMIC_LOCK) { - final String storedValue = gameScoreMap.get(key); - if (storedValue == null) { - if (GameScore.insertGameScore(Game.this.getId(), key, value)) { - gameScoreMap.put(key, value); - } - } - else { - if (!storedValue.equals(value) && GameScore.updateGameScore(Game.this.getId(), key, value)) { - gameScoreMap.put(key, value); - } - } - } + synchronized (ATOMIC_LOCK) { + final GameScore storedScore = game.getGameScore(key); + if (storedScore == null) { + if (GameScoreDAO.insertGameScore(game.getId(), key, value)) { + game.getGameScoreMap().add(new GameScore(key, value)); + } + } else { + if (!storedScore.getValue().equals(value) && GameScoreDAO.updateGameScore(game.getId(), key, value)) { + storedScore.setValue(value); + } + } + } } }).start(); } - public String getGameScore(String key, String defaultValue) { - String gameScore = getGameScore(key); - return gameScore != null ? gameScore : defaultValue; - } - - public String getGameScore(String key) { - return gameScoreMap.get(key); - } - - public AbstractTablexiaGame.GameResult getGameResult() { - return getGameDefinition().getGameResultResolver().getGameCupsResult(this); + public static AbstractTablexiaGame.GameResult getGameResult(Game game) { + return GameDefinition.getGameDefinitionForGameNumber(game.getGameNumber()).getGameResultResolver().getGameCupsResult(game); } public static Integer getNumberOfCompleteGamesForGameDefinitionAndDifficulty(GameDefinition gameDefinition, GameDifficulty gameDifficulty, User user) { @@ -227,16 +109,24 @@ public class Game { //////////////////////////// DB ACCESS - public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS game (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, start_time INTEGER, end_time INTEGER, difficulty_number INTEGER NOT NULL, game_number INTEGER NOT NULL, random_seed INTEGER NOT NULL, FOREIGN KEY(user_id) REFERENCES user(id))"; + // prepared statements + public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS game (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER NOT NULL, start_time INTEGER, end_time INTEGER, difficulty_number INTEGER NOT NULL, game_number INTEGER NOT NULL, random_seed INTEGER NOT NULL, sync_at INTEGER, FOREIGN KEY(user_id) REFERENCES user(id))"; public static final String NEW_GAME_INSERT = "INSERT INTO game (user_id, difficulty_number, game_number, random_seed) VALUES (?, ?, ?, ?)"; public static final String GAME_UPDATE_START = "UPDATE game SET start_time = ? WHERE id = ?"; public static final String GAME_UPDATE_END = "UPDATE game SET end_time = ? WHERE id = ?"; + public static final String GAME_UPDATE_SYNC_AT = "UPDATE game SET sync_at = ? WHERE id = ?"; public static final String GAME_SELECT_FOR_ID = "SELECT id, user_id, difficulty_number, game_number, random_seed, start_time, end_time FROM game WHERE id = ?"; public static final String GAME_SELECT_LAST_ID = "SELECT max(id) FROM game"; public static final String GAME_SELECT_COUNT_FOR_GAME_AND_DIFFICULTY = "SELECT count(id) FROM game WHERE game_number = ? AND difficulty_number = ? AND user_id = ? AND end_time IS NOT NULL"; public static final String GAME_SELECT_FOR_USER_AND_DEFINITION = "SELECT id, user_id, difficulty_number, game_number, random_seed, start_time, end_time FROM game WHERE user_id = ? AND game_number = ? AND end_time IS NOT NULL"; public static final String GAME_SELECT_COUNT_FOR_GAME = "SELECT count(id) FROM game WHERE game_number = ? AND user_id = ?"; - public static final String GAME_SELECT_LAST_SCORES_FOR_USER_AND_GAME = "SELECT value FROM game_score INNER JOIN game ON game_score.game_id=game.id AND game.user_id=? AND game.game_number=? WHERE game_score.key=? AND end_time IS NOT NULL ORDER BY game_id DESC LIMIT 1"; + public static final String GAME_SELECT_ALL_FOR_USER_SYNC = "SELECT id, user_id, difficulty_number, game_number, random_seed, start_time, end_time FROM game where user_id = ? AND sync_at is null"; + public static final String GAME_SELECT_BY_START_AND_END = "SELECT id FROM game WHERE user_id = ? AND start_time = ? AND end_time = ?"; + public static final String GAME_SELECT_LAST_SCORES_FOR_USER_AND_GAME = "SELECT value FROM game_score INNER JOIN game ON game_score.game_id=game.id AND game.user_id=? AND game.game_number=? WHERE game_score.key=? AND end_time IS NOT NULL ORDER BY game_id DESC LIMIT 1"; + + // classic statements + public static final String IMPORT_GAME_INSERT = "INSERT INTO game (user_id, difficulty_number, game_number, random_seed, start_time, end_time, sync_at) VALUES (%d, %d, %d, %d, %d, %d, %d)"; + private static Long insertNewGame(User user, GameDifficulty difficulty, GameDefinition gameDefinition, TablexiaRandom random) { try { @@ -277,6 +167,48 @@ public class Game { return result; } + public static Long importGame(User user, int difficulty, int gameNumber, long randomSeed, long startTime, long endTime) { + try { + Long gameId = null; + + Statement st = TablexiaStorage.getInstance().createStatement(); + String sql = String.format(IMPORT_GAME_INSERT, user.getId(), difficulty, gameNumber, randomSeed, startTime, endTime, System.currentTimeMillis()); + st.executeUpdate(sql); + + ResultSet res = st.getGeneratedKeys(); + if (res.next()) { + gameId = res.getLong(1); + Log.debug(UserDAO.class, "game id: " + gameId); + } + res.close(); + st.close(); + + return gameId; + + } catch (SQLException ex) { + Log.err(GameDAO.class, "Cannot import game record into DB!", ex); + } + + return null; + } + + public static Long selectGameByTimes(long userId, long startTime, long endTime) throws SQLException { + PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(GAME_SELECT_BY_START_AND_END); + statement.setLong(1, userId); + statement.setLong(2, startTime); + statement.setLong(3, endTime); + + Long gameId = null; + ResultSet resultSet = statement.executeQuery(); + if (resultSet.next()) { + gameId = resultSet.getLong("id"); + } + resultSet.close(); + statement.close(); + + return gameId; + } + private static Game selectGameForId(long id) { Game selectedGame = null; try { @@ -288,12 +220,15 @@ public class Game { String startTimeStr = resultSet.getString(6); String endTimeStr = resultSet.getString(7); selectedGame = new Game(resultSet.getLong(1), - User.selectUser(resultSet.getLong(2)), - GameDifficulty.getGameDifficultyForDifficultyNumber(resultSet.getInt(3)), - GameDefinition.getGameDefinitionForGameNumber(resultSet.getInt(4)), - new TablexiaRandom(resultSet.getLong(5)), + UserDAO.selectUser(resultSet.getLong(2)), + resultSet.getInt(3), + resultSet.getInt(4), + resultSet.getLong(5), startTimeStr != null ? Long.valueOf(startTimeStr) : null, endTimeStr != null ? Long.valueOf(endTimeStr) : null); + + selectedGame.setGamePauses(GamePauseDAO.selectGamePausesForGame(selectedGame)); + selectedGame.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(selectedGame.getId())); } resultSet.close(); } catch (SQLException e) { @@ -306,6 +241,39 @@ public class Game { return selectedGame; } + public static List<Game> selectUsersGamesForSync(long userId) { + List<Game> games = new ArrayList<Game>(); + try { + PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(GAME_SELECT_ALL_FOR_USER_SYNC); + statement.setLong(1, userId); + try { + ResultSet resultSet = statement.executeQuery(); + while (resultSet.next()) { + String startTimeStr = resultSet.getString(6); + String endTimeStr = resultSet.getString(7); + Game game = new Game(resultSet.getLong(1), + UserDAO.selectUser(resultSet.getLong(2)), + resultSet.getInt(3), + resultSet.getInt(4), + resultSet.getLong(5), + startTimeStr != null ? Long.valueOf(startTimeStr) : null, + endTimeStr != null ? Long.valueOf(endTimeStr) : null); + + game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game)); + game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId())); + games.add(game); + } + resultSet.close(); + } catch (SQLException e) { + Log.err(User.class, "Cannot select games for user_id: " + userId, e); + } + statement.close(); + } catch (SQLException e) { + Log.err(User.class, "Cannot select games for user_id: " + userId, e); + } + return games; + } + private static List<Game> selectGamesForUserAndDefinition(long userId, GameDefinition definition) { List<Game> selectedGames = new ArrayList<Game>(); @@ -326,13 +294,15 @@ public class Game { String startTimeStr = resultSet.getString(6); String endTimeStr = resultSet.getString(7); game = new Game(resultSet.getLong(1), - User.selectUser(resultSet.getLong(2)), - GameDifficulty.getGameDifficultyForDifficultyNumber(resultSet.getInt(3)), - GameDefinition.getGameDefinitionForGameNumber(resultSet.getInt(4)), - new TablexiaRandom(resultSet.getLong(5)), + UserDAO.selectUser(resultSet.getLong(2)), + resultSet.getInt(3), + resultSet.getInt(4), + resultSet.getLong(5), startTimeStr != null ? Long.valueOf(startTimeStr) : null, endTimeStr != null ? Long.valueOf(endTimeStr) : null); + game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game)); + game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId())); selectedGames.add(game); } else { @@ -350,10 +320,7 @@ public class Game { Log.err(User.class, "Cannot select game with user id : " + userId, e); } - return selectedGames; - - } private static Long selectLastGameId() { @@ -421,6 +388,35 @@ public class Game { return count; } + public static void markGamesAsSync(List<Game> games) { + if (games == null) { + return; + } + + PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(GAME_UPDATE_SYNC_AT); + try { + try { + TablexiaStorage.getInstance().setAutoCommit(false); + for (Game game : games) { + statement.setLong(1, System.currentTimeMillis()); + statement.setLong(2, game.getId()); + statement.addBatch(); + } + statement.executeBatch(); + statement.close(); + TablexiaStorage.getInstance().commit(); + } catch (SQLException ex) { + TablexiaStorage.getInstance().rollback(); + Log.err(GameDAO.class, "Can't mark games as synchronized: " + ex.getMessage(), ex); + } finally { + TablexiaStorage.getInstance().setAutoCommit(true); + } + + } catch (SQLException ex) { + Log.err(GameDAO.class, "Can't mark games as synchronized: " + ex.getMessage(), ex); + } + } + private static Long gameUpdateStart(long id, long startTime) { try { PreparedStatement updateStatement = TablexiaStorage.getInstance().prepareStatement(GAME_UPDATE_START); diff --git a/core/src/cz/nic/tablexia/model/game/GamePause.java b/core/src/cz/nic/tablexia/model/game/GamePauseDAO.java similarity index 69% rename from core/src/cz/nic/tablexia/model/game/GamePause.java rename to core/src/cz/nic/tablexia/model/game/GamePauseDAO.java index 7c092bc03d517c1a5224996b715d4694fcecda68..b2493baec319b3c2b2622f30b434f323d4392719 100644 --- a/core/src/cz/nic/tablexia/model/game/GamePause.java +++ b/core/src/cz/nic/tablexia/model/game/GamePauseDAO.java @@ -3,57 +3,19 @@ package cz.nic.tablexia.model.game; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Statement; import java.util.ArrayList; import java.util.List; import cz.nic.tablexia.TablexiaStorage; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.shared.model.Game; +import cz.nic.tablexia.shared.model.GamePause; import cz.nic.tablexia.util.Log; /** * Created by Matyáš Latner */ -public class GamePause { - - private long id; - private Long startTime; - private Long endTime; - - public GamePause(Long id, Long startTime) { - this(id, startTime, null); - } - - public GamePause(Long id, Long startTime, Long endTime) { - this.id = id; - this.startTime = startTime; - this.endTime = endTime; - } - - public long getId() { - return id; - } - - public Long getStartTime() { - return startTime; - } - - public Long getEndTime() { - return endTime; - } - - public boolean hasStartTime() { - return startTime != null; - } - - public boolean hasEndTime() { - return endTime != null; - } - - @Override - public String toString() { - return "GAME PAUSE[id: " + id + ", start: " + startTime + ", end: " + endTime + "]"; - } - +public class GamePauseDAO { //////////////////////////// Pause API @@ -80,18 +42,19 @@ public class GamePause { //////////////////////////// DB ACCESS + // prepared statements public static final String CREATE_TABLE = "CREATE TABLE IF NOT EXISTS game_pause (id INTEGER PRIMARY KEY AUTOINCREMENT, start_time INTEGER NOT NULL, end_time INTEGER)"; public static final String CREATE_CONNECTION_TABLE = "CREATE TABLE IF NOT EXISTS game_pauses (id INTEGER PRIMARY KEY AUTOINCREMENT, game_id INTEGER NOT NULL, game_pause_id INTEGER NOT NULL, FOREIGN KEY(game_id) REFERENCES game(id), FOREIGN KEY(game_pause_id) REFERENCES game_pause(id))"; public static final String PAUSE_INSERT = "INSERT INTO game_pause (start_time) VALUES (?)"; public static final String PAUSE_SELECT_LAST_ID = "SELECT max(id) FROM game_pause"; public static final String PAUSE_CONNECTION_INSERT = "INSERT INTO game_pauses (game_id, game_pause_id) VALUES (?, ?)"; - public static final String PAUSE_UPDATE_END_TIME = "UPDATE game_pause SET end_time = ? WHERE id IN (SELECT max(id) FROM game_pauses WHERE game_id = ?)"; - public static final String PAUSE_SELECT_FOR_ID = "SELECT id, start_time, end_time FROM game_pause WHERE id = ?"; - public static final String PAUSE_SELECT_FOR_GAME_ID = "SELECT id, start_time, end_time FROM game_pause WHERE id IN (SELECT game_pause_id FROM game_pauses WHERE game_id = ? ORDER BY id ASC)"; + // classic statements + public static final String PAUSE_IMPORT = "INSERT INTO game_pause (start_time, end_time) VALUES (%d, %d)"; + private static boolean insertGamePause(long gameId, long startTime) { boolean result = false; try { @@ -112,16 +75,51 @@ public class GamePause { TablexiaStorage.getInstance().commit(); TablexiaStorage.getInstance().setAutoCommit(true); } catch (SQLException e) { - Log.err(GamePause.class, "Cannot insert game pause into DB!", e); + Log.err(GamePauseDAO.class, "Cannot insert game pause into DB!", e); try { TablexiaStorage.getInstance().rollback(); } catch (SQLException e1) { - Log.err(GamePause.class, "Cannot rollback game pause!", e); + Log.err(GamePauseDAO.class, "Cannot rollback game pause!", e); } } return result; } + /** + * Game pause import for server synchronization - don't use transaction inside. It is already managed by caller method + * + * @param gameId + * @param startTime + * @param endTime + */ + public static void importPause(long gameId, long startTime, long endTime) { + try { + Long gamePauseId = null; + Statement insertStatementPause = TablexiaStorage.getInstance().createStatement(); + insertStatementPause.executeUpdate(String.format(PAUSE_IMPORT, startTime, endTime)); + ResultSet subRes = insertStatementPause.getGeneratedKeys(); + if (subRes.next()) { + gamePauseId = subRes.getLong(1); + Log.debug(GamePauseDAO.class, "game pause id: " + gamePauseId); + } + insertStatementPause.close(); + subRes.close(); + + PreparedStatement insertStatementPauseConnection = TablexiaStorage.getInstance().prepareStatement(PAUSE_CONNECTION_INSERT); + insertStatementPauseConnection.setLong(1, gameId); + insertStatementPauseConnection.setLong(2, gamePauseId); + insertStatementPauseConnection.executeUpdate(); + insertStatementPauseConnection.close(); + } catch (SQLException e) { + Log.err(GamePauseDAO.class, "Cannot insert game pause into DB!", e); + try { + TablexiaStorage.getInstance().rollback(); + } catch (SQLException e1) { + Log.err(GamePauseDAO.class, "Cannot rollback game pause!", e); + } + } + } + private static boolean updateGamePauseEnd(long gameId, long endTime) { boolean result = false; try { @@ -131,11 +129,11 @@ public class GamePause { result = updateStatementPause.executeUpdate() > 0; updateStatementPause.close(); } catch (SQLException e) { - Log.err(GamePause.class, "Cannot update game pause in DB!", e); + Log.err(GamePauseDAO.class, "Cannot update game pause in DB!", e); try { TablexiaStorage.getInstance().rollback(); } catch (SQLException e1) { - Log.err(GamePause.class, "Cannot update game pause in DB!", e); + Log.err(GamePauseDAO.class, "Cannot update game pause in DB!", e); } } return result; @@ -152,38 +150,15 @@ public class GamePause { } resultSet.close(); } catch (SQLException e) { - Log.err(User.class, "Cannot select game pause with id: " + id, e); + Log.err(GamePauseDAO.class, "Cannot select game pause with id: " + id, e); } statement.close(); } catch (SQLException e) { - Log.err(User.class, "Cannot select game pause with id: " + id, e); + Log.err(GamePauseDAO.class, "Cannot select game pause with id: " + id, e); } return id; } - private static GamePause selectGamePauseForId(long id) { - GamePause selectedGame = null; - try { - PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(PAUSE_SELECT_FOR_ID); - statement.setLong(1, id); - try { - ResultSet resultSet = statement.executeQuery(); - if (resultSet.next()) { - selectedGame = new GamePause(resultSet.getLong(1), - resultSet.getLong(2), - resultSet.getLong(3)); - } - resultSet.close(); - } catch (SQLException e) { - Log.err(User.class, "Cannot select game pause with id: " + id, e); - } - statement.close(); - } catch (SQLException e) { - Log.err(User.class, "Cannot select game pause with id: " + id, e); - } - return selectedGame; - } - private static List<GamePause> selectGamePausesForGameId(long gameId) { List<GamePause> gamePauses = new ArrayList<GamePause>(); try { @@ -200,11 +175,11 @@ public class GamePause { } resultSet.close(); } catch (SQLException e) { - Log.err(GameScore.class, "Cannot select game pauses from DB!", e); + Log.err(GameScoreDAO.class, "Cannot select game pauses from DB!", e); } statement.close(); } catch (SQLException e) { - Log.err(GameScore.class, "Cannot select game pauses from DB!", e); + Log.err(GameScoreDAO.class, "Cannot select game pauses from DB!", e); } return gamePauses; } diff --git a/core/src/cz/nic/tablexia/model/game/GameScore.java b/core/src/cz/nic/tablexia/model/game/GameScoreDAO.java similarity index 57% rename from core/src/cz/nic/tablexia/model/game/GameScore.java rename to core/src/cz/nic/tablexia/model/game/GameScoreDAO.java index 4daa33513f9646f82365a311848a924b2ecb92cf..5a211046e82a93468fae4b17910d7756b6820172 100644 --- a/core/src/cz/nic/tablexia/model/game/GameScore.java +++ b/core/src/cz/nic/tablexia/model/game/GameScoreDAO.java @@ -3,33 +3,35 @@ package cz.nic.tablexia.model.game; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.HashMap; -import java.util.Map; +import java.util.ArrayList; +import java.util.List; import cz.nic.tablexia.TablexiaStorage; +import cz.nic.tablexia.shared.model.Game; +import cz.nic.tablexia.shared.model.GameScore; import cz.nic.tablexia.util.Log; /** * Created by Matyáš Latner */ -public class GameScore { +public class GameScoreDAO { - private GameScore() {} + private GameScoreDAO() {} //////////////////////////// GAME SCORE API - public static boolean createGameScore(Game game, String key, String value) { - if (game != null && key != null && value != null) { - if (insertGameScore(game.getId(), key, value)) { + public static boolean createGameScore(Game game, GameScore score) { + if (game != null && score.getKey() != null && score.getValue() != null) { + if (insertGameScore(game.getId(), score.getKey(), score.getValue())) { return true; } } return false; } - public static boolean updateGameScore(Game game, String key, String value) { - if (game != null && key != null && value != null) { - if (updateGameScore(game.getId(), key, value)) { + public static boolean updateGameScore(Game game, GameScore score) { + if (game != null && score.getKey() != null && score.getValue() != null) { + if (updateGameScore(game.getId(), score.getKey(), score.getValue())) { return true; } } @@ -54,11 +56,28 @@ public class GameScore { insertStatement.close(); return rowCount > 0; } catch (SQLException e) { - Log.err(GameScore.class, "Cannot insert new game score record into DB!", e); + Log.err(GameScoreDAO.class, "Cannot insert new game score record into DB!", e); } return false; } + public static void batchInsertGameScore(long gameId, List<GameScore> scores) { + try { + PreparedStatement insertStatement = TablexiaStorage.getInstance().prepareStatement(GAME_SCORE_INSERT); + for (GameScore score : scores) { + insertStatement.setLong(1, gameId); + insertStatement.setString(2, score.getKey()); + insertStatement.setString(3, score.getValue()); + insertStatement.addBatch(); + Log.debug(GameScoreDAO.class, "importing game score for game id: " + gameId + ", " + score.getKey() + " - " + score.getValue()); + } + insertStatement.executeBatch(); + insertStatement.close(); + } catch (SQLException e) { + Log.err(GameScoreDAO.class, "Cannot insert new game score record into DB!", e); + } + } + public static boolean updateGameScore(long gameId, String key, String value) { try { PreparedStatement updateStatement = TablexiaStorage.getInstance().prepareStatement(GAME_SCORE_UPDATE); @@ -71,13 +90,13 @@ public class GameScore { return true; } } catch (SQLException e) { - Log.err(GameScore.class, "Cannot update game score in DB!", e); + Log.err(GameScoreDAO.class, "Cannot update game score in DB!", e); } return false; } - public static Map<String, String> selectGameScores(long gameId) { - Map<String, String> gameScores = new HashMap<String, String>(); + public static List<GameScore> selectGameScores(long gameId) { + List<GameScore> gameScores = new ArrayList<GameScore>(); try { PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(GAME_SCORE_SELECT); statement.setLong(1, gameId); @@ -87,15 +106,15 @@ public class GameScore { String key = resultSet.getString(1); String value = resultSet.getString(2); - gameScores.put(key, value); + gameScores.add(new GameScore(key, value)); } resultSet.close(); } catch (SQLException e) { - Log.err(GameScore.class, "Cannot select game scores from DB!", e); + Log.err(GameScoreDAO.class, "Cannot select game scores from DB!", e); } statement.close(); } catch (SQLException e) { - Log.err(GameScore.class, "Cannot select game scores from DB!", e); + Log.err(GameScoreDAO.class, "Cannot select game scores from DB!", e); } return gameScores; } diff --git a/core/src/cz/nic/tablexia/model/game/GameTrophy.java b/core/src/cz/nic/tablexia/model/game/GameTrophy.java index c01f6700976af31a77ecbb4e89ded79b3a460834..9980d2eb4d12ea549a1c6114282dd655040a25d7 100644 --- a/core/src/cz/nic/tablexia/model/game/GameTrophy.java +++ b/core/src/cz/nic/tablexia/model/game/GameTrophy.java @@ -8,11 +8,11 @@ import java.util.List; import cz.nic.tablexia.TablexiaStorage; import cz.nic.tablexia.game.AbstractTablexiaGame; -import cz.nic.tablexia.game.GameDefinition; -import cz.nic.tablexia.game.common.TablexiaRandom; import cz.nic.tablexia.game.difficulty.GameDifficulty; import cz.nic.tablexia.game.trophy.GameTrophyDefinition; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.Log; /** @@ -21,12 +21,9 @@ import cz.nic.tablexia.util.Log; public class GameTrophy { public interface GameTrophyResolver { - - public boolean hasGameTrophy(User user, GameTrophyDefinition trophyDef); - + boolean hasGameTrophy(User user, GameTrophyDefinition trophyDef); } - public static class NumberOfTimesFinished implements GameTrophyResolver { public static final String GAME_PLAYED_SELECT = "SELECT COUNT(*) FROM game WHERE user_id = ? AND game_number = ? AND difficulty_number != ? AND end_time IS NOT NULL GROUP BY user_id, game_number"; @@ -72,13 +69,16 @@ public class GameTrophy { while (resultSet.next()) { String startTimeStr = resultSet.getString(6); String endTimeStr = resultSet.getString(7); - games.add(new Game(resultSet.getLong(1), - User.selectUser(resultSet.getLong(2)), - GameDifficulty.getGameDifficultyForDifficultyNumber(resultSet.getInt(3)), - GameDefinition.getGameDefinitionForGameNumber(resultSet.getInt(4)), - new TablexiaRandom(resultSet.getLong(5)), + Game game = new Game(resultSet.getLong(1), + UserDAO.selectUser(resultSet.getLong(2)), + resultSet.getInt(3), + resultSet.getInt(4), + resultSet.getLong(5), startTimeStr != null ? Long.valueOf(startTimeStr) : null, - endTimeStr != null ? Long.valueOf(endTimeStr) : null)); + endTimeStr != null ? Long.valueOf(endTimeStr) : null); + game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game)); + game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId())); + games.add(game); } resultSet.close(); } catch (SQLException e) { @@ -100,7 +100,7 @@ public class GameTrophy { } for (Game game : games) { - if (game.getGameResult().getStarCount() == AbstractTablexiaGame.GameResult.THREE_STAR.getStarCount()) { + if (GameDAO.getGameResult(game).getStarCount() == AbstractTablexiaGame.GameResult.THREE_STAR.getStarCount()) { return true; } } diff --git a/core/src/cz/nic/tablexia/model/game/UserTrophy.java b/core/src/cz/nic/tablexia/model/game/UserTrophy.java index 12b7facddcfac5cf11131420ce5fa91425d6d3a1..a7f31383f3b8098c3305a1b93d183ff62025f58f 100644 --- a/core/src/cz/nic/tablexia/model/game/UserTrophy.java +++ b/core/src/cz/nic/tablexia/model/game/UserTrophy.java @@ -21,7 +21,9 @@ import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.common.TablexiaRandom; import cz.nic.tablexia.game.difficulty.GameDifficulty; import cz.nic.tablexia.game.trophy.UserTrophyDefinition; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.Log; /** @@ -165,13 +167,17 @@ public class UserTrophy { while (resultSet.next()) { String startTimeStr = resultSet.getString(6); String endTimeStr = resultSet.getString(7); - games.add(new Game(resultSet.getLong(1), - User.selectUser(resultSet.getLong(2)), - GameDifficulty.getGameDifficultyForDifficultyNumber(resultSet.getInt(3)), - GameDefinition.getGameDefinitionForGameNumber(resultSet.getInt(4)), - new TablexiaRandom(resultSet.getLong(5)), + Game game = new Game(resultSet.getLong(1), + UserDAO.selectUser(resultSet.getLong(2)), + resultSet.getInt(3), + resultSet.getInt(4), + resultSet.getLong(5), startTimeStr != null ? Long.valueOf(startTimeStr) : null, - endTimeStr != null ? Long.valueOf(endTimeStr) : null)); + endTimeStr != null ? Long.valueOf(endTimeStr) : null); + + game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game)); + game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId())); + games.add(game); } resultSet.close(); } catch (SQLException e) { @@ -195,9 +201,9 @@ public class UserTrophy { Set<Integer> gamesPlayed = new HashSet<Integer>(); for (Game game : games) { - if (game.getGameResult().getStarCount() == AbstractTablexiaGame.GameResult.THREE_STAR.getStarCount() - && !gamesPlayed.contains(game.getGameDefinition().getGameNumber())) { - gamesPlayed.add(game.getGameDefinition().getGameNumber()); + if (GameDAO.getGameResult(game).getStarCount() == AbstractTablexiaGame.GameResult.THREE_STAR.getStarCount() + && !gamesPlayed.contains(game.getGameNumber())) { + gamesPlayed.add(game.getGameNumber()); } else { gamesPlayed.clear(); } @@ -216,10 +222,11 @@ public class UserTrophy { } for (Game game : games) { - if (!results.containsKey(game.getGameDefinition())) { - results.put(game.getGameDefinition(), 0); + GameDefinition gameDef = GameDefinition.getGameDefinitionForGameNumber(game.getGameNumber()); + if (!results.containsKey(gameDef)) { + results.put(gameDef, 0); } - results.put(game.getGameDefinition(), results.get(game.getGameDefinition()) + game.getGameResult().getStarCount()); + results.put(gameDef, results.get(gameDef) + GameDAO.getGameResult(game).getStarCount()); } return results; } diff --git a/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java b/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java index 876d71f96af17938b33c70163f9a0145b0c7c12d..3d076dc26f185d5bb93c9ae39556eb72a64dbd09 100644 --- a/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java +++ b/core/src/cz/nic/tablexia/screen/AbstractTablexiaScreen.java @@ -36,13 +36,17 @@ import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.TablexiaStorage; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.bus.ApplicationBus.ApplicationEvent; +import cz.nic.tablexia.bus.event.DownloadUserSynchronizationEvent; +import cz.nic.tablexia.bus.event.StartFullSynchronizationEvent; +import cz.nic.tablexia.bus.event.StartIncrementalSynchronizationEvent; import cz.nic.tablexia.loader.TablexiaAbstractFileManager; import cz.nic.tablexia.loader.TablexiaAtlasManager; import cz.nic.tablexia.loader.TablexiaDataManager; import cz.nic.tablexia.loader.TablexiaSoundManager; import cz.nic.tablexia.loader.application.ApplicationAtlasManager; import cz.nic.tablexia.loader.application.ApplicationFontManager; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.util.Log; import cz.nic.tablexia.util.ScaleUtil; import cz.nic.tablexia.util.Utility; @@ -159,7 +163,16 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter { private DataManager dataManager; private ScreenLoadingListener screenLoadingListener; private Map<String, String> screenState; - private Set<Disposable> disposables = new HashSet<Disposable>(); + private Set<Disposable> disposables = new HashSet<Disposable>(); + + // synchronization helpers + private static Long lastPauseTimeForFullSync; + private static Long lastTimeForUserSync = System.currentTimeMillis(); + + // run full synchronization 1 hour after pause + private static final long FULL_SYNC_DELAY = 60 * 60 * 1000; + // synchronize actual user on every screen resume but not sooner than 30 sec from last sync + private static final long USER_SYNC_DELAY = 30 * 1000; private boolean loadingComplete; private boolean loadingStarted; @@ -300,6 +313,10 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter { return true; } + protected boolean canSyncOnResume() { + return true; + } + public boolean isScreenPaused() { return canBePaused() && isScreenPaused && canStopActions(); } @@ -440,6 +457,15 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter { } stage.draw(); } + + if (lastTimeForUserSync != null && hasSynchronizedUser() && canSyncOnResume() && System.currentTimeMillis() - lastTimeForUserSync > USER_SYNC_DELAY) { + lastTimeForUserSync = System.currentTimeMillis(); + ApplicationBus.getInstance().publishAsync(new DownloadUserSynchronizationEvent(getSelectedUser())); + } + } + + private boolean hasSynchronizedUser() { + return getSelectedUser() != null && getSelectedUser().getUuid() != null && !getSelectedUser().getUuid().isEmpty(); } public void addDisposable(Disposable disposable) { @@ -504,6 +530,7 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter { protected final void performScreenPaused() { if (!isScreenPaused) { isScreenPaused = true; + lastPauseTimeForFullSync = System.currentTimeMillis(); Log.info(getClass(), "[ ------- Screen Paused ------- ]"); // save screen state Map<String, String> screenState = new HashMap<String, String>(); @@ -514,6 +541,10 @@ public abstract class AbstractTablexiaScreen<T> extends ScreenAdapter { protected final void performScreenResumed() { if (isScreenPaused) { + if (lastPauseTimeForFullSync != null && canSyncOnResume() && System.currentTimeMillis() - lastPauseTimeForFullSync > FULL_SYNC_DELAY) { + lastPauseTimeForFullSync = null; + ApplicationBus.getInstance().publishAsync(new StartFullSynchronizationEvent(UserDAO.selectActiveUsers())); + } isScreenPaused = false; Log.info(getClass(), "[ ------- Screen Resumed ------- ]"); screenResumed(); diff --git a/core/src/cz/nic/tablexia/screen/createuser/FormScreen.java b/core/src/cz/nic/tablexia/screen/createuser/FormScreen.java index 4242f5c29e1cb4feae6788e8e4717b20a8453a31..379ab48579a24a63f8aaf86bbb9c951347306759 100644 --- a/core/src/cz/nic/tablexia/screen/createuser/FormScreen.java +++ b/core/src/cz/nic/tablexia/screen/createuser/FormScreen.java @@ -38,10 +38,12 @@ import cz.nic.tablexia.Tablexia; import cz.nic.tablexia.TablexiaApplication; import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.bus.ApplicationBus; +import cz.nic.tablexia.bus.event.StartFullSynchronizationEvent; import cz.nic.tablexia.loader.application.ApplicationAtlasManager; import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.menu.user.UserAvatarDefinition; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.screen.createuser.form.FormActorsLayout; import cz.nic.tablexia.screen.createuser.form.SignatureDialog; @@ -304,9 +306,10 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { clearValidations(); validations.put(VALIDATION_STAMP, true); stampIt(); - User user = User.createUser(nameField.getText(), FormScreen.this.age, FormScreen.this.gender, mugshot, signature); + User user = UserDAO.createUser(nameField.getText(), FormScreen.this.age, FormScreen.this.gender, mugshot, signature); TablexiaSettings.getInstance().setSelectedUser(user); ApplicationBus.getInstance().post(new Tablexia.ChangeScreenEvent(TablexiaSettings.INITIAL_SCREEN, TablexiaApplication.ScreenTransaction.FADE)).asynchronously(); + ApplicationBus.getInstance().publishAsync(new StartFullSynchronizationEvent(user)); } } @@ -349,7 +352,7 @@ public class FormScreen extends AbstractTablexiaScreen<Void> { return false; } - if (User.userNameExists(nameField.getText())) { + if (UserDAO.userNameExists(nameField.getText())) { displayHintDialog(VALIDATION_USERNAME_EXISTS, nameField); return false; } diff --git a/core/src/cz/nic/tablexia/screen/gamemenu/GameMenuScreen.java b/core/src/cz/nic/tablexia/screen/gamemenu/GameMenuScreen.java index 69423b4ad420ecf9aa4a5c24a780e1dcb9696122..eee83533c123049aa1d333de57f3e2071716df3f 100644 --- a/core/src/cz/nic/tablexia/screen/gamemenu/GameMenuScreen.java +++ b/core/src/cz/nic/tablexia/screen/gamemenu/GameMenuScreen.java @@ -16,7 +16,7 @@ import java.util.Map; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.menu.game.GameMenuDefinition; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.screen.gamemenu.actions.ScrollHomeAction; import cz.nic.tablexia.screen.gamemenu.event.ShowGameMenuPageEvent; @@ -149,7 +149,7 @@ public class GameMenuScreen extends AbstractTablexiaScreen<int[][]> { public void run() { pagedScrollPane.setTouchable(Touchable.enabled); getSelectedUser().setIntro(false); - User.updateUser(getSelectedUser()); + UserDAO.updateUser(getSelectedUser()); } }))); } diff --git a/core/src/cz/nic/tablexia/screen/gamemenu/pages/OfficeMenuPage.java b/core/src/cz/nic/tablexia/screen/gamemenu/pages/OfficeMenuPage.java index 29fe873dd8d4a3a4fac4f959f199c91910d852b7..f9409add8f7868f60d8b179cf56a61d512ae5838 100644 --- a/core/src/cz/nic/tablexia/screen/gamemenu/pages/OfficeMenuPage.java +++ b/core/src/cz/nic/tablexia/screen/gamemenu/pages/OfficeMenuPage.java @@ -17,7 +17,8 @@ import cz.nic.tablexia.TablexiaApplication; import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.bus.ApplicationBus; import cz.nic.tablexia.loader.application.ApplicationAtlasManager; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.screen.encyclopedia.EncyclopediaScreen; import cz.nic.tablexia.screen.gamemenu.GameMenuAssets; @@ -109,7 +110,7 @@ public class OfficeMenuPage extends MenuPage { //Have user seen the help overlay ? if(TablexiaSettings.getInstance().getSelectedUser().isHelp()) { TablexiaSettings.getInstance().getSelectedUser().setHelp(false); - User.updateUser(TablexiaSettings.getInstance().getSelectedUser()); + UserDAO.updateUser(TablexiaSettings.getInstance().getSelectedUser()); toggleHelpOverlay(); } diff --git a/core/src/cz/nic/tablexia/screen/profile/ProfileScreen.java b/core/src/cz/nic/tablexia/screen/profile/ProfileScreen.java index 34cd1645abcd7478ba8e9082ce5f08887be55c82..39200829e6bf1fde3973963902aa7db855451a94 100644 --- a/core/src/cz/nic/tablexia/screen/profile/ProfileScreen.java +++ b/core/src/cz/nic/tablexia/screen/profile/ProfileScreen.java @@ -1,8 +1,10 @@ package cz.nic.tablexia.screen.profile; +import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Button; +import com.badlogic.gdx.scenes.scene2d.ui.Label; import com.badlogic.gdx.scenes.scene2d.utils.Drawable; import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; @@ -12,8 +14,9 @@ import cz.nic.tablexia.Tablexia; import cz.nic.tablexia.TablexiaApplication; import cz.nic.tablexia.TablexiaSettings; import cz.nic.tablexia.bus.ApplicationBus; +import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.menu.user.UserAvatarDefinition; -import cz.nic.tablexia.model.User; +import cz.nic.tablexia.shared.model.User; import cz.nic.tablexia.screen.createuser.FormScreen; import cz.nic.tablexia.util.ui.ClickListenerWithSound; @@ -44,13 +47,16 @@ public class ProfileScreen extends FormScreen { imageFemale.setVisible(getSelectedUser().getGender().equals(User.Gender.FEMALE)); imageMale.setVisible(getSelectedUser().getGender().equals(User.Gender.MALE)); - float center = (imageMale.getX() + imageFemale.getX())/2; + float center = (imageMale.getX() + imageFemale.getX()) / 2; imageFemale.setX(center); imageMale.setX(center); signaturePane.setSignature(getSelectedUser().getSignature()); stampIt(); getStage().addActor(createCloseButton()); + if (getSelectedUser().getUuid() != null && !getSelectedUser().getUuid().isEmpty()) { + getStage().addActor(createUserUuidLabel()); + } } @Override @@ -77,6 +83,12 @@ public class ProfileScreen extends FormScreen { return closeButton; } + private Label createUserUuidLabel() { + Label label = new Label(getSelectedUser().getUuid(), new Label.LabelStyle(getFont(ApplicationFontManager.FontType.ROBOTO_BOLD_16), Color.BLACK)); + label.setPosition(getStage().getWidth() * 0.17f, getStage().getWidth() * 0.075f); + return label; + } + @Override public void backButtonPressed() { backToInitialScreen(); diff --git a/core/src/cz/nic/tablexia/screen/statistics/StatisticsGameScoreResolver.java b/core/src/cz/nic/tablexia/screen/statistics/StatisticsGameScoreResolver.java index e71846b21a859943ea5d45998d0a48f074fa743b..c1f3af4bdf59ae78979a2db45772c0cd20e9d72f 100644 --- a/core/src/cz/nic/tablexia/screen/statistics/StatisticsGameScoreResolver.java +++ b/core/src/cz/nic/tablexia/screen/statistics/StatisticsGameScoreResolver.java @@ -5,7 +5,7 @@ import java.util.Calendar; import java.util.List; import cz.nic.tablexia.game.GameDefinition; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; /** * Created by danilov on 11/12/15. diff --git a/core/src/cz/nic/tablexia/screen/statistics/StatisticsScreen.java b/core/src/cz/nic/tablexia/screen/statistics/StatisticsScreen.java index 4cbd19abb5f38c908dc107af7cb5d78e69276ea7..32fbc37d4c1d353511b4aebb2956d2599770dd35 100644 --- a/core/src/cz/nic/tablexia/screen/statistics/StatisticsScreen.java +++ b/core/src/cz/nic/tablexia/screen/statistics/StatisticsScreen.java @@ -35,7 +35,8 @@ import cz.nic.tablexia.game.difficulty.GameDifficulty; import cz.nic.tablexia.loader.application.ApplicationAtlasManager; import cz.nic.tablexia.loader.application.ApplicationFontManager; import cz.nic.tablexia.loader.application.ApplicationTextManager; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.model.game.GameDAO; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.menu.game.GameMenuDefinition; import cz.nic.tablexia.screen.AbstractTablexiaScreen; import cz.nic.tablexia.screen.statistics.enums.GraphStyle; @@ -201,7 +202,8 @@ public class StatisticsScreen extends AbstractTablexiaScreen<Void> { games = getGames(GameDefinition.getGameDefinitionForGameNumber(i)); if(games.size() > 0) { selectGame(GameDefinition.getGameDefinitionForGameNumber(i)); - setDifficultyButtonChecked(difficultyButtons.get(games.get(0).getDifficulty()), true, games.get(0).getDifficulty()); + GameDifficulty difficulty = GameDifficulty.getByGame(games.get(0)); + setDifficultyButtonChecked(difficultyButtons.get(difficulty), true, difficulty); break; } } @@ -381,7 +383,7 @@ public class StatisticsScreen extends AbstractTablexiaScreen<Void> { TextureRegion[] textures = new TextureRegion[3]; TextureRegion starAchievedTexture = getScreenTextureRegion(GFX_PATH + "ratingstar_achieved", false); TextureRegion starNotAchievedTexture = getScreenTextureRegion(GFX_PATH + "ratingstar_not_achieved", false); - int starsAchieved = game.getGameResult().getStarCount(); + int starsAchieved = GameDAO.getGameResult(game).getStarCount(); for(int i = 0; i < starsAchieved; i++) { textures[i] = starAchievedTexture; @@ -415,22 +417,22 @@ public class StatisticsScreen extends AbstractTablexiaScreen<Void> { private DialogTextContent getGameStatisticsDialogTextContentForGame(Game game) { - return new DialogTextContent((game.getGameDefinition().getTitle() + "\n") + + return new DialogTextContent((GameDefinition.getGameDefinitionForGameNumber(game.getGameNumber()).getTitle() + "\n") + ApplicationTextManager.getInstance().getText(ApplicationTextManager.ApplicationTextsAssets.GAME_DIFFICULTY_NAME) + " " + - game.getDifficulty().getTextDescription() + "\n" + + GameDifficulty.getByGame(game).getTextDescription() + "\n" + game.getGameStartDate(true) + "\n" + - ApplicationTextManager.getInstance().getText(game.getGameDefinition().getStatisticsScoreDialogText()) + " " + + ApplicationTextManager.getInstance().getText(GameDefinition.getGameDefinitionForGameNumber(game.getGameNumber()).getStatisticsScoreDialogText()) + " " + (getCorrectedScore(selectedGameDefinition, game))); } private DialogTextContent getGameStatisticsDialogTextContentForAverageGame(Game game, float averageScore, String date) { - return new DialogTextContent((game.getGameDefinition().getTitle() + "\n") + + return new DialogTextContent((GameDefinition.getGameDefinitionForGameNumber(game.getGameNumber()).getTitle() + "\n") + ApplicationTextManager.getInstance().getText(ApplicationTextManager.ApplicationTextsAssets.GAME_DIFFICULTY_NAME) + " " + - game.getDifficulty().getTextDescription() + "\n" + + GameDifficulty.getByGame(game).getTextDescription() + "\n" + date + "\n" + - ApplicationTextManager.getInstance().getText(game.getGameDefinition().getStatisticsAverageScoreDialogText()) + " " + - getCorrectedScore(selectedGameDefinition, averageScore)); + ApplicationTextManager.getInstance().getText(GameDefinition.getGameDefinitionForGameNumber(game.getGameNumber()).getStatisticsAverageScoreDialogText()) + " " + + getCorrectedScore(selectedGameDefinition, averageScore)); } /**In some games is time used as score (less means better). @@ -537,7 +539,7 @@ public class StatisticsScreen extends AbstractTablexiaScreen<Void> { } private List<Game> getGames(GameDefinition definition) { - return Game.getGamesForUserAndDefinition(getSelectedUser().getId(), definition); + return GameDAO.getGamesForUserAndDefinition(getSelectedUser().getId(), definition); } @Override diff --git a/core/src/cz/nic/tablexia/screen/statistics/interfaces/GameClickListener.java b/core/src/cz/nic/tablexia/screen/statistics/interfaces/GameClickListener.java index bafd2a375de59ecf0af360f69a291000ccf34c08..9cef1d9bd3bc03e89d1f7a4624e86e2b92fcff56 100644 --- a/core/src/cz/nic/tablexia/screen/statistics/interfaces/GameClickListener.java +++ b/core/src/cz/nic/tablexia/screen/statistics/interfaces/GameClickListener.java @@ -2,7 +2,7 @@ package cz.nic.tablexia.screen.statistics.interfaces; import com.badlogic.gdx.scenes.scene2d.InputEvent; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.Game; public interface GameClickListener { diff --git a/core/src/cz/nic/tablexia/screen/statistics/views/GraphPane.java b/core/src/cz/nic/tablexia/screen/statistics/views/GraphPane.java index a44bf6534febdd435cb515441d14847d35a2dc4f..d80b3d941b42ff648b39768723c521d7fccb66b5 100644 --- a/core/src/cz/nic/tablexia/screen/statistics/views/GraphPane.java +++ b/core/src/cz/nic/tablexia/screen/statistics/views/GraphPane.java @@ -14,11 +14,11 @@ import java.util.Set; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.difficulty.GameDifficulty; -import cz.nic.tablexia.model.game.Game; import cz.nic.tablexia.screen.statistics.StatisticsGameScoreResolver; import cz.nic.tablexia.screen.statistics.StatisticsScreen; import cz.nic.tablexia.screen.statistics.enums.GraphStyle; import cz.nic.tablexia.screen.statistics.interfaces.GameClickListener; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.util.ui.ClickListenerWithSound; import com.badlogic.gdx.graphics.Color; @@ -154,7 +154,7 @@ public class GraphPane extends WidgetGroup { private void createScorePoints(List<Game> games) { for (Game game : games) { float score = selectedGameDefinition.getGameResultResolver().getGameScoreResult(game); - createPoint(game, score, getGamesByDifficulty(game.getDifficulty()).size(), games.indexOf(game), -1, null); + createPoint(game, score, getGamesByDifficulty(GameDifficulty.getByGame(game)).size(), games.indexOf(game), -1, null); } } @@ -178,7 +178,7 @@ public class GraphPane extends WidgetGroup { setPropertiesToGraphPoint(graphPoint, score, numberOfGames, index, isFlipOfGraphNeeded(selectedGameDefinition)); clickAreas.add(createPointClickArea(clickArea)); - getPointsByDifficulty(game.getDifficulty()).add(graphPoint); + getPointsByDifficulty(GameDifficulty.getByGame(game)).add(graphPoint); clickArea.addListener(new ClickListener() { @Override @@ -311,7 +311,7 @@ public class GraphPane extends WidgetGroup { hardGames = new ArrayList<Game>(); for (Game game : allGames) { - switch (game.getDifficulty()) { + switch (GameDifficulty.getByGame(game)) { case EASY: easyGames.add(game); break; diff --git a/core/src/cz/nic/tablexia/sync/RestSynchronizationService.java b/core/src/cz/nic/tablexia/sync/RestSynchronizationService.java new file mode 100644 index 0000000000000000000000000000000000000000..105e8ddd9faa35faad08c7b85e711684ab8f301c --- /dev/null +++ b/core/src/cz/nic/tablexia/sync/RestSynchronizationService.java @@ -0,0 +1,75 @@ +package cz.nic.tablexia.sync; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Net; +import com.badlogic.gdx.net.HttpRequestBuilder; +import com.badlogic.gdx.utils.JsonWriter; + +import cz.nic.tablexia.Tablexia; +import cz.nic.tablexia.shared.rest.UserRestPath; +import cz.nic.tablexia.sync.work.SyncWork; +import cz.nic.tablexia.util.Log; + +/** + * Created by frantisek on 13.1.16. + */ +public class RestSynchronizationService { + + public enum SynchronizationType { + FULL, + INCREMENT, + } + + //public static String REST_URL = "http://10.0.2.2:8080"; // from android emulator - localhost + public static String REST_URL = "http://localhost:8080"; + + private HttpRequestBuilder builder; + private Net.HttpResponseListener listener; + + public RestSynchronizationService(String url, String httpMethod, Net.HttpResponseListener listener) { + builder = new HttpRequestBuilder(); + builder.newRequest(); + HttpRequestBuilder.json.setOutputType(JsonWriter.OutputType.json); + builder.method(httpMethod); + builder.url(url); + this.listener = listener; + } + + public void setJsonObject(Object obj) { + builder.jsonContent(obj); + } + + public void send() { + Net.HttpRequest request = builder.build(); + Log.debug(this.getClass(), "Calling remote url: " + request.getUrl()); + Gdx.net.sendHttpRequest(request, listener); + } + + public void setHeader(String key, String value) { + builder.header(key, value); + } + + public static void doSyncWork(SyncWork work) { + if (Tablexia.connectionManager.isUsingMobileData()) { + Log.debug(RestSynchronizationService.class, "Using mobile data connection - synchronization disabled"); + return; + } + work.send(new RestSynchronizationService(work.getUrl(), work.getHttpMethod(), work)); + } + + public static String getCreateUserUrl() { + return REST_URL + UserRestPath.USER_PATH + UserRestPath.USER_CREATE; + } + + public static String getConfirmUserUrl(String uuid) { + return REST_URL + UserRestPath.USER_PATH + UserRestPath.USER_CONFIRM.replace("{" + UserRestPath.USER_UUID + "}", uuid); + } + + public static String getDownloadUserUrl(String uuid) { + return REST_URL + UserRestPath.USER_PATH + UserRestPath.USER_GET.replace("{" + UserRestPath.USER_UUID + "}", uuid); + } + + public static String getDeleteUserUrl(String uuid) { + return REST_URL + UserRestPath.USER_PATH + UserRestPath.USER_DELETE.replace("{" + UserRestPath.USER_UUID + "}", uuid); + } +} diff --git a/core/src/cz/nic/tablexia/sync/work/ConfirmDataReceived.java b/core/src/cz/nic/tablexia/sync/work/ConfirmDataReceived.java new file mode 100644 index 0000000000000000000000000000000000000000..b25ce31f5cd74c948969222f9ff2ad9bd1360fc7 --- /dev/null +++ b/core/src/cz/nic/tablexia/sync/work/ConfirmDataReceived.java @@ -0,0 +1,37 @@ +package cz.nic.tablexia.sync.work; + +import com.badlogic.gdx.Net; +import com.badlogic.gdx.net.HttpRequestHeader; + +import cz.nic.tablexia.model.game.GameDAO; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.sync.RestSynchronizationService; +import cz.nic.tablexia.util.Log; + +/** + * Created by frantisek on 15.1.16. + */ +public class ConfirmDataReceived extends SyncWork { + + public ConfirmDataReceived(User user) { + setUser(user); + } + + @Override + public String getUrl() { + return RestSynchronizationService.getConfirmUserUrl(getUser().getUuid()); + } + + @Override + public void send(RestSynchronizationService sync) { + sync.setHeader(HttpRequestHeader.ContentType, "application/json"); + sync.send(); + } + + @Override + protected void onResponse(Net.HttpResponse httpResponse) { + GameDAO.markGamesAsSync(getUser().getGames()); + Log.debug(this.getClass(), String.format("Marking %d of games as synchronized", getUser().getGames() != null ? getUser().getGames().size() : 0)); + RestSynchronizationService.doSyncWork(new DownloadUser(getUser().getUuid())); + } +} diff --git a/core/src/cz/nic/tablexia/sync/work/DeleteUser.java b/core/src/cz/nic/tablexia/sync/work/DeleteUser.java new file mode 100644 index 0000000000000000000000000000000000000000..2e9e026e3c4741d64f7e84e830679fa97b2fbde5 --- /dev/null +++ b/core/src/cz/nic/tablexia/sync/work/DeleteUser.java @@ -0,0 +1,38 @@ +package cz.nic.tablexia.sync.work; + +import com.badlogic.gdx.Net; +import com.badlogic.gdx.net.HttpRequestHeader; + +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.sync.RestSynchronizationService; +import cz.nic.tablexia.util.Log; + +/** + * Created by frantisek on 19.1.16. + */ +public class DeleteUser extends SyncWork { + + public DeleteUser(User user) { + setUser(user); + } + + @Override + public String getUrl() { + return RestSynchronizationService.getDeleteUserUrl(getUser().getUuid()); + } + + @Override + public String getHttpMethod() { + return Net.HttpMethods.DELETE; + } + + @Override + public void send(RestSynchronizationService sync) { + if (getUser() == null || getUser().getUuid() == null || getUser().getUuid().isEmpty()) { + Log.err(this.getClass(), "Can't delete user from REST server without uuid"); + return; + } + sync.setHeader(HttpRequestHeader.ContentType, "application/json"); + sync.send(); + } +} diff --git a/core/src/cz/nic/tablexia/sync/work/DownloadUser.java b/core/src/cz/nic/tablexia/sync/work/DownloadUser.java new file mode 100644 index 0000000000000000000000000000000000000000..c070836e1d9a02b7f7394457d44a91de4e78c437 --- /dev/null +++ b/core/src/cz/nic/tablexia/sync/work/DownloadUser.java @@ -0,0 +1,54 @@ +package cz.nic.tablexia.sync.work; + +import com.badlogic.gdx.Net; +import com.badlogic.gdx.net.HttpRequestHeader; +import com.badlogic.gdx.utils.Json; + +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.sync.RestSynchronizationService; +import cz.nic.tablexia.util.Log; + +/** + * Created by frantisek on 18.1.16. + */ +public class DownloadUser extends SyncWork { + + private final String uuid; + + public DownloadUser(String uuid) { + this.uuid = uuid; + } + + @Override + public String getUrl() { + return RestSynchronizationService.getDownloadUserUrl(uuid); + } + + @Override + public void send(RestSynchronizationService sync) { + sync.setHeader(HttpRequestHeader.ContentType, "application/json"); + sync.send(); + } + + @Override + protected void onResponse(Net.HttpResponse httpResponse) { + String userJson = httpResponse.getResultAsString(); + Json json = new Json(); + json.setIgnoreUnknownFields(true); + User user = json.fromJson(User.class, userJson); + + if (user == null) { + Log.err(this.getClass(), "Failed to deserialize user from JSON"); + return; + } + + long start = System.currentTimeMillis(); + user.setId(UserDAO.importUser(user)); + long finish = System.currentTimeMillis(); + + setUser(user); + + Log.debug(this.getClass(), "Duration: " + getTime(start, finish)); + } +} diff --git a/core/src/cz/nic/tablexia/sync/work/PushDataToServer.java b/core/src/cz/nic/tablexia/sync/work/PushDataToServer.java new file mode 100644 index 0000000000000000000000000000000000000000..179e35aafce9d61f664a1faf5cc2a4d3ded90bfc --- /dev/null +++ b/core/src/cz/nic/tablexia/sync/work/PushDataToServer.java @@ -0,0 +1,59 @@ +package cz.nic.tablexia.sync.work; + +import com.badlogic.gdx.Net; + +import cz.nic.tablexia.model.UserDAO; +import cz.nic.tablexia.model.game.GameDAO; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.shared.rest.UserRestPath; +import cz.nic.tablexia.sync.RestSynchronizationService; +import cz.nic.tablexia.util.Log; + +/** + * Created by frantisek on 15.1.16. + */ +public class PushDataToServer extends SyncWork { + + private final RestSynchronizationService.SynchronizationType syncType; + + public PushDataToServer(User user, RestSynchronizationService.SynchronizationType syncType) { + setUser(user); + getUser().setGames(GameDAO.selectUsersGamesForSync(user.getId())); + this.syncType = syncType; + } + + @Override + public String getUrl() { + return RestSynchronizationService.getCreateUserUrl(); + } + + @Override + public void send(RestSynchronizationService sync) { + sync.setJsonObject(getUser()); + sync.send(); + + Log.debug(this.getClass(), String.format("sending user '%s' uuid: %s", getUser().getName(), getUser().getUuid())); + } + + @Override + protected void onResponse(Net.HttpResponse httpResponse) { + + Log.debug(this.getClass(), "received uuid: " + httpResponse.getHeader("uuid")); + + String uuid = httpResponse.getHeader(UserRestPath.USER_UUID); + if (uuid == null || uuid.isEmpty()) { + Log.err(this.getClass(), "Failed to receive uuid from REST server"); + return; + } + + if (syncType == RestSynchronizationService.SynchronizationType.FULL || getUser().getUuid() == null) { + if (UserDAO.updateUserUuid(getUser().getId(), uuid)) { + getUser().setUuid(uuid); + RestSynchronizationService.doSyncWork(new ConfirmDataReceived(getUser())); + } + } else { + GameDAO.markGamesAsSync(getUser().getGames()); + Log.debug(this.getClass(), String.format("Marking %d of games as synchronized", getUser().getGames() != null ? getUser().getGames().size() : 0)); + } + } +} diff --git a/core/src/cz/nic/tablexia/sync/work/SyncWork.java b/core/src/cz/nic/tablexia/sync/work/SyncWork.java new file mode 100644 index 0000000000000000000000000000000000000000..7b2a07a13c8f470f1b6fc87bfd8ab28d4ffda04a --- /dev/null +++ b/core/src/cz/nic/tablexia/sync/work/SyncWork.java @@ -0,0 +1,110 @@ +package cz.nic.tablexia.sync.work; + +import com.badlogic.gdx.Net; +import com.badlogic.gdx.utils.Timer; + +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.sync.RestSynchronizationService; +import cz.nic.tablexia.util.Log; + +/** + * Created by frantisek on 15.1.16. + */ +public abstract class SyncWork implements Net.HttpResponseListener { + + private static final int MAX_RETRY_COUNT = 3; + // delay in seconds + private static final int RETRY_DELAY = 1; + private int retryCount = 0; + + private RestSyncListener listener; + private User user; + + public String getHttpMethod() { + return Net.HttpMethods.POST; + } + + public void registerListener(RestSyncListener listener) { + this.listener = listener; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + @Override + public final void handleHttpResponse(Net.HttpResponse httpResponse) { + onResponse(httpResponse); + if (listener != null) { + listener.onSuccess(getUser()); + } + } + + // override this method to handle success response from server + protected void onResponse(Net.HttpResponse httpResponse) { + + } + + @Override + public void failed(Throwable t) { + Log.err(this.getClass(), "sync request failed: " + t.getMessage(), t); + // retry mechanism if request fails + if (retryCount < MAX_RETRY_COUNT) { + Timer.schedule(new Timer.Task() { + @Override + public void run() { + retryCount++; + Log.debug(SyncWork.this.getClass(), "another try for request: " + getUrl()); + send(new RestSynchronizationService(getUrl(), getHttpMethod(), SyncWork.this)); + } + }, RETRY_DELAY); + } else if (listener != null) { + listener.onFailure(t); + } + } + + @Override + public void cancelled() { + Log.info(this.getClass(), "sync request cancelled"); + if (listener != null) { + listener.onCancelled(); + } + } + + /** + * Helper method to print measured time + * + * @param start + * @param finish + * @return + */ + protected String getTime(long start, long finish) { + long result = finish - start; + long minutes = result / (60 * 1000); + float seconds = (result - minutes * 60 * 1000) / 1000.0f; + return minutes + " min " + seconds + " sec"; + } + + public abstract String getUrl(); + public abstract void send(RestSynchronizationService sync); + + +//////////// Response listener class + + public abstract static class RestSyncListener { + + public void onFailure(Throwable t) { + + } + + public void onCancelled() { + + } + + public abstract void onSuccess(User user); + } +} diff --git a/core/test/cz/nic/tablexia/test/games/AverageScoreTest.java b/core/test/cz/nic/tablexia/test/games/AverageScoreTest.java index 56143b98dfed6c64efa96da6d0fb4bc32a573f1a..8bc557203067246ffb891d54162109a14c19b363 100644 --- a/core/test/cz/nic/tablexia/test/games/AverageScoreTest.java +++ b/core/test/cz/nic/tablexia/test/games/AverageScoreTest.java @@ -7,15 +7,15 @@ import org.junit.Test; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; import cz.nic.tablexia.game.GameDefinition; import cz.nic.tablexia.game.common.TablexiaRandom; import cz.nic.tablexia.game.difficulty.GameDifficulty; import cz.nic.tablexia.game.games.robbery.RobberyGame; -import cz.nic.tablexia.model.User; -import cz.nic.tablexia.model.game.Game; +import cz.nic.tablexia.shared.model.GameScore; +import cz.nic.tablexia.shared.model.User; +import cz.nic.tablexia.shared.model.Game; import cz.nic.tablexia.screen.statistics.StatisticsGameScoreResolver; @@ -28,14 +28,16 @@ public class AverageScoreTest { @Before public void tearUp() { - User user = new User(1,"name", 15, User.Gender.MALE,"avatar","signature",false,false,false); + User user = new User(1, "name", 15, User.Gender.MALE, "avatar", "signature", false, false, false); List<Game> games = new ArrayList<Game>(); String key = RobberyGame.SCORE_KEY_PERSON_NUMBER; - for(int i = 0; i < 3; i++) { - Map<String,String> scores = new ConcurrentHashMap<String,String>(); - scores.put(key, (i*10) + ""); - Game game = new Game((long)i, user, GameDifficulty.EASY, GameDefinition.ROBBERY, new TablexiaRandom(),0l,1l,scores); + for (int i = 0; i < 3; i++) { + List<GameScore> scores = new CopyOnWriteArrayList<GameScore>(); + scores.add(new GameScore(key, (i * 10) + "")); + TablexiaRandom random = new TablexiaRandom(); + Game game = new Game((long)i, user, GameDifficulty.EASY.getDifficultyNumber(), GameDefinition.ROBBERY.getGameNumber(), random.getSeed(), 0l, 1l); + game.setGameScoreMap(scores); games.add(game); } @@ -45,12 +47,12 @@ public class AverageScoreTest { @Test public void getAverageScoreTest() { - Assert.assertEquals(10+1,averageScores.get(0),0); + Assert.assertEquals(10 + 1, averageScores.get(0), 0); } @Test public void getPointsSize() { - Assert.assertEquals(1,averageScores.size(),0); + Assert.assertEquals(1, averageScores.size(), 0); } @After diff --git a/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java b/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java index 5c402ce2a10af7f9558fbb203e191c8804d059c7..e451ddaffe3df82be1a5e39efbf0a8bd479ba817 100644 --- a/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java +++ b/desktop/src/cz/nic/tablexia/desktop/DesktopLauncher.java @@ -67,7 +67,7 @@ public class DesktopLauncher { @Override public boolean isUsingMobileData() { //TODO - return false.. its desktop ;) - return TablexiaSettings.getInstance().getBuildType() == TablexiaSettings.BuildType.DEVEL; + return false;//TablexiaSettings.getInstance().getBuildType() == TablexiaSettings.BuildType.DEVEL; } } }