diff --git a/build.gradle b/build.gradle
index f9197b90a90f9f73ceb0fd3779e385ef5b03d0a6..1424a411d018a38906e5b6c427ffda1431f2a6a0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -26,6 +26,9 @@ final assetsGameGlobalDirectory = "_global"
 final assetsGameCommonDifficultyDirectory = "common"
 final assetsGameExcludedDirectory = "excluded"
 
+final String TABLEXIA_GIT_PATH  = './'
+final String MODEL_GIT_PATH     = 'core/external/'
+
 System.setProperty("javax.net.ssl.trustStore", new File("${project(":android").projectDir.absolutePath}/assets/keystore/tablexiaTrustKeystore").getAbsolutePath());
 System.setProperty("javax.net.ssl.trustStorePassword", "tablexia");
 
@@ -45,8 +48,10 @@ allprojects {
         masterBranch = 'master'
         applicationBaseId = 'cz.nic.tablexia'
         tablexiaAppName = getTablexiaAppName()
-        tablexiaVersionName = getVersionNameFromGit()
-        tablexiaVersionCode = getVersionCodeFromGit()
+        tablexiaVersionName = getVersionNameFromGit(TABLEXIA_GIT_PATH)
+        tablexiaVersionCode = getVersionCodeFromGit(TABLEXIA_GIT_PATH)
+        tablexiaModelVersionName = getVersionNameFromGit(MODEL_GIT_PATH)
+        tablexiaModelVersionCode = getVersionCodeFromGit(MODEL_GIT_PATH)
         applicationIdBranch = getTablexiaAppId()
         applicationIdRelease = applicationBaseId + applicationIdBranch
         applicationIdDebugSuffix = '.debug'
@@ -72,7 +77,7 @@ allprojects {
         ravenVersion = '7.5.0'
     }
 
-    version = getVersionNameFromGit()
+    version = getVersionNameFromGit(TABLEXIA_GIT_PATH)
 
     repositories {
         maven   { url "http://repo1.maven.org/maven2" }
@@ -270,12 +275,13 @@ def getTablexiaAppId() {
     }
 }
 
-def getVersionNameFromGit() {
+def getVersionNameFromGit(String relativePath) {
     def stdout = new ByteArrayOutputStream()
     String branchName = getBranchNameFromGit()
 
     // get last tag in current branch
     exec {
+        workingDir relativePath
         commandLine 'git', 'describe', '--abbrev=0', '--tags'
         standardOutput = stdout
     }
@@ -285,6 +291,7 @@ def getVersionNameFromGit() {
     if (!project.masterBranch.equals(branchName)) {
         stdout = new ByteArrayOutputStream()
         exec {
+            workingDir relativePath
             commandLine 'git', 'rev-list', "${result}..HEAD", '--count'
             standardOutput = stdout
         }
@@ -298,9 +305,10 @@ def getVersionNameFromGit() {
     return result
 }
 
-def getVersionCodeFromGit() {
+def getVersionCodeFromGit(String relativePath) {
     def stdout = new ByteArrayOutputStream()
     exec {
+        workingDir relativePath
         commandLine 'git', 'log', '-1', '--format=%at'
         standardOutput = stdout
     }
diff --git a/core/build.gradle b/core/build.gradle
index aae1780ed651c3e9f5e7fda601dcecba81074712..5258f8738f969d5fda2ac023c296c2d30fd30b8e 100644
--- a/core/build.gradle
+++ b/core/build.gradle
@@ -37,6 +37,8 @@ task writeTablexiaBuildConfig {
                 "    public final static String  APP_NAME = \"${tablexiaAppName}\";\n" +
                 "    public final static String  APPLICATION_VERSION_NAME = \"${tablexiaVersionName}\";\n" +
                 "    public final static Integer APPLICATION_VERSION_CODE = ${tablexiaVersionCode};\n" +
+                "    public final static String  MODEL_VERSION_NAME = \"${tablexiaModelVersionName}\";\n" +
+                "    public final static Integer MODEL_VERSION_CODE = ${tablexiaModelVersionCode};\n" +
                 "    public final static String  ASSETS_CHECKSUM = \"${getMapConvertedToString(rootProject.ext.assetsChecksum)}\";\n" +
                 "    public final static String  TABLEXIA_ASSETS_URL = ${project.hasProperty('TABLEXIA_ASSETS_DOWNLOAD_URL') ? "\"$TABLEXIA_ASSETS_DOWNLOAD_URL\"" : "null"};\n" +
                 "    public final static String  TABLEXIA_SERVER_PROTOCOL = ${project.hasProperty('TABLEXIA_SERVER_PROTOCOL') ? "\"$TABLEXIA_SERVER_PROTOCOL\"" : "null"};\n" +
diff --git a/core/src/cz/nic/tablexia/TablexiaSettings.java b/core/src/cz/nic/tablexia/TablexiaSettings.java
index 5b9d3c3599ab8eb7199d258557e25bf2c6086bf9..4360be8638086d72bff9256841d68eedc8e2c6bc 100644
--- a/core/src/cz/nic/tablexia/TablexiaSettings.java
+++ b/core/src/cz/nic/tablexia/TablexiaSettings.java
@@ -56,9 +56,12 @@ public class TablexiaSettings {
     private static final    String      APP_NAME                    = TablexiaBuildConfig.APP_NAME;
     private final           String      APPLICATION_VERSION_NAME    = TablexiaBuildConfig.APPLICATION_VERSION_NAME;
     private final           int         APPLICATION_VERSION_CODE    = TablexiaBuildConfig.APPLICATION_VERSION_CODE;
+    private final           String      MODEL_VERSION_NAME          = TablexiaBuildConfig.MODEL_VERSION_NAME;
+    private final           int         MODEL_VERSION_CODE          = TablexiaBuildConfig.MODEL_VERSION_CODE;
+    private                 Platform    PLATFORM;
     private final           BuildType   BUILD_TYPE;
     private final           boolean     HAS_SOFT_BACK_BUTTON;
-    private static          String      hwSerial;
+    private static          String      HW_SERIAL_NUMBER;
 
     private Preferences      preferences;
     private LocaleDefinition systemLocale;
@@ -69,15 +72,47 @@ public class TablexiaSettings {
     private boolean          soundMuted = false;
 
 
+    public enum Platform {
+
+        UNKNOWN (-1,    null),
+        DESKTOP (1,     Application.ApplicationType.Desktop),
+        ANDROID (2,     Application.ApplicationType.Android),
+        iOS     (3,     Application.ApplicationType.iOS);
+
+        private static Platform FALLBACK_PLATFORM = UNKNOWN;
+
+        private final int id;
+        private final Application.ApplicationType applicationType;
+
+        Platform(int id, Application.ApplicationType applicationType) {
+            this.id                 = id;
+            this.applicationType    = applicationType;
+        }
+
+        public int getId() {
+            return id;
+        }
+
+        public static Platform getPlatformForApplicationType(Application.ApplicationType applicationType) {
+            for (Platform platform : values()) {
+                if (platform.applicationType != null && platform.applicationType.equals(applicationType)) {
+                    return platform;
+                }
+            }
+            return FALLBACK_PLATFORM;
+        }
+    }
+
     public enum BuildType {
 
         //                  boxes   aInfo   sInfo   dMenu   btName  bReport  debugBtn
-        RELEASE ("release", false,  false,  false,  false,  false,  true,    false,   Log.TablexiaLogLevel.ERROR),
-        DEBUG   ("debug",   false,  true,   true,   true,   true,   true,    true,    Log.TablexiaLogLevel.DEBUG),
-        DEVEL   ("devel",   true,   true,   true,   true,   true,   false,   true,    Log.TablexiaLogLevel.DEBUG);
+        RELEASE (1, "release", false,  false,  false,  false,  false,  true,    false,   Log.TablexiaLogLevel.ERROR),
+        DEBUG   (2, "debug",   false,  true,   true,   true,   true,   true,    true,    Log.TablexiaLogLevel.DEBUG),
+        DEVEL   (3, "devel",   true,   true,   true,   true,   true,   false,   true,    Log.TablexiaLogLevel.DEBUG);
 
         private final static BuildType FALLBACK_VARIANT = BuildType.DEVEL;
 
+        private       int                  id;
         private final String               key;
         private       boolean              boundingBoxes;
         private       boolean              applicationInfo;
@@ -88,7 +123,8 @@ public class TablexiaSettings {
         private       boolean              showDebugButtons;
         private final Log.TablexiaLogLevel logLevel;
 
-        BuildType(String key, boolean boundingBoxes, boolean applicationInfo, boolean screenInfo, boolean debugMenu, boolean showBuildTypeInName, boolean bugReport, boolean showDebugButtons, Log.TablexiaLogLevel logLevel) {
+        BuildType(int id, String key, boolean boundingBoxes, boolean applicationInfo, boolean screenInfo, boolean debugMenu, boolean showBuildTypeInName, boolean bugReport, boolean showDebugButtons, Log.TablexiaLogLevel logLevel) {
+            this.id = id;
             this.key = key;
             this.boundingBoxes = boundingBoxes;
             this.applicationInfo = applicationInfo;
@@ -100,6 +136,10 @@ public class TablexiaSettings {
             this.logLevel = logLevel;
         }
 
+        public int getId() {
+            return id;
+        }
+
         public String getKey() {
             return key;
         }
@@ -170,7 +210,7 @@ public class TablexiaSettings {
         TablexiaSettings.init(BuildType.getBuildTypeForKey(buildTypeKey), systemLocale, hasSoftBackButton, hwSerial);
     }
 
-    static void init(BuildType buildType, Locale systemLocale, boolean hasSoftBackButton, String hwSerial) {
+    static void init(BuildType buildType, Locale systemLocale, boolean hasSoftBackButton, String hwSerialNumber) {
         if (instance != null) {
             String exceptionMessage = "Tablexia settings already initialized!";
             Log.err(TablexiaSettings.class, exceptionMessage);
@@ -178,7 +218,7 @@ public class TablexiaSettings {
         }
 
         instance = new TablexiaSettings(buildType, systemLocale, hasSoftBackButton);
-        TablexiaSettings.hwSerial = hwSerial;
+        TablexiaSettings.HW_SERIAL_NUMBER = hwSerialNumber;
     }
 
     void dispose() {
@@ -202,27 +242,42 @@ public class TablexiaSettings {
 //////////////////////////// SETTINGS ACCESS
 
     public String getFullName() {
-        return getAppName() + " " + getVersionName();
+        return getAppName() + " " + getApplicationVersionName();
     }
 
     public String getAppName() {
         return getBuildType().getAppName();
     }
 
-    public String getVersionName() {
+    public String getApplicationVersionName() {
         return APPLICATION_VERSION_NAME;
     }
 
-    public int getVersionCode() {
+    public int getApplicationVersionCode() {
         return APPLICATION_VERSION_CODE;
     }
 
+    public String getModelVersionName() {
+        return MODEL_VERSION_NAME;
+    }
+
+    public int getModelVersionCode() {
+        return MODEL_VERSION_CODE;
+    }
+
+    public Platform getPlatform() {
+        if (PLATFORM == null) {
+            PLATFORM = Platform.getPlatformForApplicationType(Gdx.app.getType());
+        }
+        return PLATFORM;
+    }
+
     public boolean hasSoftBackButton() {
         return HAS_SOFT_BACK_BUTTON;
     }
 
-    public String getHwSerial() {
-        return hwSerial;
+    public String getHwSerialNumber() {
+        return HW_SERIAL_NUMBER;
     }
 
     public boolean isWinterMode() { return winterMode; }
diff --git a/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java b/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java
index 834756e6fbd21cb2f8066509f8b92e2dc009ae18..4b4188519231a7e55e900e1762a370c942f86d75 100644
--- a/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java
+++ b/core/src/cz/nic/tablexia/game/AbstractTablexiaGame.java
@@ -430,7 +430,7 @@ public abstract class AbstractTablexiaGame<T> extends AbstractTablexiaScreen<T>
             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() && UserDAO.isTutorialForGameDefinition(gameDefinition, getSelectedUser()) ? GameDifficulty.TUTORIAL : getGameDifficulty();
-            game = GameDAO.createGame(getSelectedUser(), gameDifficulty, gameDefinition, random, TablexiaSettings.getInstance().getHwSerial(), TablexiaSettings.getInstance().getVersionName(), TablexiaSettings.getInstance().getVersionCode());
+            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);
diff --git a/core/src/cz/nic/tablexia/menu/AbstractMenu.java b/core/src/cz/nic/tablexia/menu/AbstractMenu.java
index 3c82418f808c58a239f6106e35d476dc33262262..ef157ea9bb1b864a0b6008a5cc0c7b2ed65faebc 100644
--- a/core/src/cz/nic/tablexia/menu/AbstractMenu.java
+++ b/core/src/cz/nic/tablexia/menu/AbstractMenu.java
@@ -42,7 +42,8 @@ import cz.nic.tablexia.util.ui.TablexiaNoBlendingImage;
  * @author Matyáš Latner
  */
 public abstract class AbstractMenu extends Stack implements Disposable {
-    private static final String VERSION_LINE_SEPARATOR = "\r\n";
+
+    private static final String TABLEXIA_VERSION_LABEL = "%s\r\n%s";
 
     protected enum MenuControlType {
 
@@ -314,7 +315,7 @@ public abstract class AbstractMenu extends Stack implements Disposable {
 
         //App name and version
         TablexiaLabel appName = new TablexiaLabel(
-        TablexiaSettings.getInstance().getAppName() + VERSION_LINE_SEPARATOR + TablexiaSettings.getInstance().getVersionName(),
+                String.format(TABLEXIA_VERSION_LABEL, TablexiaSettings.getInstance().getAppName(), TablexiaSettings.getInstance().getApplicationVersionName()),
                 new TablexiaLabel.TablexiaLabelStyle(APP_NAME_TEXT_FONT, Color.BLACK));
         appName.setAlignment(APP_NAME_TEXT_ALIGN);
         appName.setWrap(true);
diff --git a/core/src/cz/nic/tablexia/model/DatabaseManager.java b/core/src/cz/nic/tablexia/model/DatabaseManager.java
index f3f72a523f9d658efb33837637624c11cd747aee..26c1f46f5ef0ef9a3859fe3e7b1fac1d8e667c6e 100644
--- a/core/src/cz/nic/tablexia/model/DatabaseManager.java
+++ b/core/src/cz/nic/tablexia/model/DatabaseManager.java
@@ -32,9 +32,13 @@ public class DatabaseManager {
 
     private enum VersionScript {
         VERSION_01( 1, "ALTER TABLE game ADD locale INTEGER NOT NULL DEFAULT " + Game.DEFAULT_GAME_LOCALE),
-        VERSION_02( 2, "ALTER TABLE game ADD version_name TEXT NOT NULL DEFAULT '"  + Game.DEFAULT_GAME_VERSION_NAME + "'"),
-        VERSION_03( 3, "ALTER TABLE game ADD version_code INTEGER NOT NULL DEFAULT "  + Game.DEFAULT_GAME_VERSION_CODE),
-        VERSION_04( 4, "ALTER TABLE game ADD hw_serial_number TEXT");
+        VERSION_02( 2, "ALTER TABLE game ADD application_version_name TEXT NOT NULL DEFAULT '"  + Game.DEFAULT_APPLICATION_VERSION_NAME + "'"),
+        VERSION_03( 3, "ALTER TABLE game ADD application_version_code INTEGER NOT NULL DEFAULT "  + Game.DEFAULT_APPLICATION_VERSION_CODE),
+        VERSION_04( 4, "ALTER TABLE game ADD model_version_name TEXT NOT NULL DEFAULT '"  + Game.DEFAULT_MODEL_VERSION_NAME + "'"),
+        VERSION_05( 5, "ALTER TABLE game ADD model_version_code INTEGER NOT NULL DEFAULT "  + Game.DEFAULT_MODE_VERSION_CODE),
+        VERSION_06( 6, "ALTER TABLE game ADD build_type INTEGER NOT NULL DEFAULT " + Game.DEFAULT_BUILD_TYPE),
+        VERSION_07( 7, "ALTER TABLE game ADD platform INTEGER NOT NULL DEFAULT " + Game.DEFAULT_PLATFORM),
+        VERSION_08( 7, "ALTER TABLE game ADD hw_serial_number TEXT");
 
         private int version;
         private String sqlStatement;
diff --git a/core/src/cz/nic/tablexia/model/UserDAO.java b/core/src/cz/nic/tablexia/model/UserDAO.java
index 2d309f29997d0521858d7fffd590e8ad40394a83..b3c91a7cf52f909273a9244ca415dd09d7cf0a0e 100644
--- a/core/src/cz/nic/tablexia/model/UserDAO.java
+++ b/core/src/cz/nic/tablexia/model/UserDAO.java
@@ -240,7 +240,7 @@ public class UserDAO {
                         continue;
                     }
 
-                    Long gameId = GameDAO.importGame(dbUser, game.getGameDifficulty(), game.getGameNumber(), game.getGameLocale(), game.getGameVersionName(), game.getRandomSeed(), game.getStartTime(), game.getEndTime());
+                    Long gameId = GameDAO.importGame(dbUser, game);
 
                     if (gameId == null) {
                         continue;
diff --git a/core/src/cz/nic/tablexia/model/game/GameDAO.java b/core/src/cz/nic/tablexia/model/game/GameDAO.java
index f998d1cca9bc3076f4a60532323ae1d346699394..ff60700bdd48ae68ec0eef905d743ba2af3b3668 100644
--- a/core/src/cz/nic/tablexia/model/game/GameDAO.java
+++ b/core/src/cz/nic/tablexia/model/game/GameDAO.java
@@ -34,13 +34,10 @@ public class GameDAO {
 //////////////////////////// Game API
 
     public static Game createGame(User user, GameDifficulty difficulty, GameDefinition gameDefinition, TablexiaRandom random) {
-        String versionName = TablexiaSettings.getInstance().getVersionName();
-        TablexiaSettings.LocaleDefinition localeDefinition = TablexiaSettings.getInstance().getLocaleDefinition();
-
         Game game = null;
-        Long id = insertNewGame(user, difficulty, gameDefinition, localeDefinition, versionName, random);
+        Long id = insertNewGame(user, difficulty, gameDefinition, random);
         if (id != null) {
-            game = new Game(id, user, difficulty.getDifficultyNumber(), gameDefinition.getGameNumber(), localeDefinition.getLocaleNumber(), versionName, random.getSeed());
+            game = GameDAO.selectGameForId(id);
             game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game));
         }
         return game;
@@ -148,38 +145,71 @@ public class GameDAO {
 
 //////////////////////////// DB ACCESS
 
+    public static final String GAME_SELECT_COLUMNS = "id, user_id, difficulty_number, game_number, random_seed, start_time, end_time, locale, application_version_name, application_version_code, model_version_name, model_version_code, build_type, platform, hw_serial_number";
+
+    public static Game prepareGameObject(ResultSet resultSet) throws SQLException {
+        String startTimeStr = resultSet.getString(6);
+        String endTimeStr = resultSet.getString(7);
+        Game game = new Game(
+                resultSet.getLong(1),                                       //gameId
+                UserDAO.selectUser(resultSet.getLong(2)),                   //user
+                resultSet.getInt(3),                                        //difficultyNumber
+                resultSet.getInt(4),                                        //gameNumber
+                resultSet.getLong(5),                                       //randomSeed
+                startTimeStr != null ? Long.valueOf(startTimeStr) : null,   //startTime
+                endTimeStr != null ? Long.valueOf(endTimeStr) : null,       //endTime
+                resultSet.getInt(8),                                        //locale
+                resultSet.getString(9),                                     //applicationVersionName
+                resultSet.getInt(10),                                       //applicationVersionCode
+                resultSet.getString(11),                                    //modelVersionName
+                resultSet.getInt(12),                                       //modelVersionCode
+                resultSet.getInt(13),                                       //buildType
+                resultSet.getInt(14),                                       //platform
+                resultSet.getString(15)                                     //hwSerialNumber
+        );
+        game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game));
+        game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId()));
+        return game;
+    }
+
     // 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, locale, version_name, version_code, hw_serial_number) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
+    public static final String NEW_GAME_INSERT = "INSERT INTO game (user_id, difficulty_number, game_number, random_seed, locale, application_version_name, application_version_code, model_version_name, model_version_code, build_type, platform, hw_serial_number) 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, locale, version_name, version_code, hw_serial_number FROM game WHERE id = ?";
+    public static final String GAME_SELECT_FOR_ID = "SELECT " + GAME_SELECT_COLUMNS + " 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, locale, version_name, version_code, hw_serial_number FROM game WHERE user_id = ? AND game_number = ? AND end_time IS NOT NULL AND end_time != 0 ORDER BY start_time ASC";
+    public static final String GAME_SELECT_FOR_USER_AND_DEFINITION = "SELECT " + GAME_SELECT_COLUMNS + " FROM game WHERE user_id = ? AND game_number = ? AND end_time IS NOT NULL AND end_time != 0 ORDER BY start_time ASC";
     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_ALL_FOR_USER_SYNC = "SELECT id, user_id, difficulty_number, game_number, version, random_seed, start_time, end_time, locale, version_name, version_code, hw_serial_number FROM game where user_id = ? AND sync_at is null";
+    public static final String GAME_SELECT_ALL_FOR_USER_SYNC = "SELECT " + GAME_SELECT_COLUMNS + " 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_BY_START_AND_NULL_END = "SELECT id FROM game WHERE user_id = ? AND start_time = ? AND end_time IS NULL";
 
 
     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_FOR_RANK_MANAGER = "SELECT id, difficulty_number, game_number, version, start_time, end_time FROM game WHERE user_id = ? AND start_time IS NOT NULL AND start_time != 0 AND end_time IS NOT NULL AND end_time != 0 ORDER BY end_time ASC";
+    public static final String GAME_SELECT_FOR_RANK_MANAGER = "SELECT " + GAME_SELECT_COLUMNS + " FROM game WHERE user_id = ? AND start_time IS NOT NULL AND start_time != 0 AND end_time IS NOT NULL AND end_time != 0 ORDER BY end_time ASC";
 
     // classic statements
-    public static final String IMPORT_GAME_INSERT = "INSERT INTO game (user_id, difficulty_number, game_number, random_seed, start_time, end_time, locale, version_name, version_code, hw_serial_number, sync_at) VALUES (%d, %d, %d, %d, %d, %d, %d, %s, %d, %s, %d)";
+    public static final String IMPORT_GAME_INSERT = "INSERT INTO game (user_id, difficulty_number, game_number, random_seed, start_time, end_time, locale, application_version_name, application_version_code, model_version_name, model_version_code, build_type, platform, hw_serial_number, sync_at) VALUES (%d, %d, %d, %d, '%s', '%s', %d, '%s', %d, '%s', %d, %d, %d, '%s', %d)";
 
 
-    private static Long insertNewGame(User user, GameDifficulty difficulty, GameDefinition gameDefinition, TablexiaSettings.LocaleDefinition localeDefinition, String versionName, TablexiaRandom random) {
+    private static Long insertNewGame(User user, GameDifficulty difficulty, GameDefinition gameDefinition, TablexiaRandom random) {
         try {
             PreparedStatement insertStatement = TablexiaStorage.getInstance().prepareStatement(NEW_GAME_INSERT);
             insertStatement.setLong(1, user.getId());
             insertStatement.setInt(2, difficulty.getDifficultyNumber());
             insertStatement.setInt(3, gameDefinition.getGameNumber());
-            insertStatement.setInt(4, localeDefinition.getLocaleNumber());
-            insertStatement.setString(5, versionName);
-            insertStatement.setLong(6, random.getSeed());
+            insertStatement.setLong(4, random.getSeed());
+            insertStatement.setInt(5, TablexiaSettings.getInstance().getLocaleDefinition().getLocaleNumber());
+            insertStatement.setString(6, TablexiaSettings.getInstance().getApplicationVersionName());
+            insertStatement.setInt(7, TablexiaSettings.getInstance().getApplicationVersionCode());
+            insertStatement.setString(8, TablexiaSettings.getInstance().getModelVersionName());
+            insertStatement.setInt(9, TablexiaSettings.getInstance().getModelVersionCode());
+            insertStatement.setInt(10, TablexiaSettings.getInstance().getBuildType().getId());
+            insertStatement.setInt(11, TablexiaSettings.getInstance().getPlatform().getId());
+            insertStatement.setString(12, TablexiaSettings.getInstance().getHwSerialNumber());
             insertStatement.executeUpdate();
             insertStatement.close();
             // insertStatement.getGeneratedKeys().getLong(1) cannot be used -> getGeneratedKeys() is not implemented in SQLDroid
@@ -212,13 +242,29 @@ public class GameDAO {
 		return result;
 	}
 
-    public static Long importGame(User user, int difficulty, int gameNumber, int gameLocale, String version, long randomSeed, long startTime, long endTime) {
+    public static Long importGame(User user, Game game) {
         try {
             Long gameId = null;
             Statement st = TablexiaStorage.getInstance().createStatement();
+            Long startTime = game.getStartTime();
+            Long endTime = game.getEndTime();
             // workaround for sync error -> serialized JSON from server contains 0 instead of NULL
-//            String sql = String.format(IMPORT_GAME_INSERT, user.getId(), difficulty, gameNumber, randomSeed, startTime, endTime, System.currentTimeMillis());
-            String sql = String.format(IMPORT_GAME_INSERT, user.getId(), difficulty, gameNumber, gameLocale, version, randomSeed, startTime, endTime != 0 ? String.valueOf(endTime) : "NULL", System.currentTimeMillis());
+            String sql = String.format(IMPORT_GAME_INSERT,
+                    user.getId(),
+                    game.getGameDifficulty(),
+                    game.getGameNumber(),
+                    game.getRandomSeed(),
+                    startTime != 0L ? String.valueOf(startTime) : "NULL",
+                    endTime != 0L ? String.valueOf(endTime) : "NULL",
+                    game.getGameLocale(),
+                    game.getApplicationVersionName(),
+                    game.getApplicationVersionCode(),
+                    game.getModelVersionName(),
+                    game.getModelVersionCode(),
+                    game.getBuildType(),
+                    game.getPlatform(),
+                    game.getHwSerialNumber(),
+                    System.currentTimeMillis());
             st.executeUpdate(sql);
             gameId = selectLastGameId();
             st.close();
@@ -263,23 +309,7 @@ public class GameDAO {
             try {
                 ResultSet resultSet = statement.executeQuery();
                 if (resultSet.next()) {
-                    String startTimeStr = resultSet.getString(8);
-                    String endTimeStr = resultSet.getString(9);
-                    selectedGame = new Game(resultSet.getLong(1),
-                            UserDAO.selectUser(resultSet.getLong(2)),
-                            resultSet.getInt(3),
-                            resultSet.getInt(4),
-                            resultSet.getInt(5),
-                            resultSet.getString(6),
-                            resultSet.getLong(7),
-                            startTimeStr != null ? Long.valueOf(startTimeStr) : null,
-                            endTimeStr != null ? Long.valueOf(endTimeStr) : null,
-                            resultSet.getString(8),
-                            resultSet.getString(9),
-                            resultSet.getInt(10));
-
-                    selectedGame.setGamePauses(GamePauseDAO.selectGamePausesForGame(selectedGame));
-                    selectedGame.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(selectedGame.getId()));
+                    selectedGame = prepareGameObject(resultSet);
                 }
                 resultSet.close();
             } catch (SQLException e) {
@@ -300,24 +330,7 @@ public class GameDAO {
             try {
                 ResultSet resultSet = statement.executeQuery();
                 while (resultSet.next()) {
-                    String startTimeStr = resultSet.getString(8);
-                    String endTimeStr = resultSet.getString(9);
-                    Game game = new Game(resultSet.getLong(1),
-                            UserDAO.selectUser(resultSet.getLong(2)),
-                            resultSet.getInt(3),
-                            resultSet.getInt(4),
-                            resultSet.getInt(5),
-                            resultSet.getString(6),
-                            resultSet.getLong(7),
-                            startTimeStr != null ? Long.valueOf(startTimeStr) : null,
-                            endTimeStr != null ? Long.valueOf(endTimeStr) : null,
-                            resultSet.getString(8),
-                            resultSet.getString(9),
-                            resultSet.getInt(10));
-
-                    game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game));
-                    game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId()));
-                    games.add(game);
+                    games.add(prepareGameObject(resultSet));
                 }
                 resultSet.close();
             } catch (SQLException e) {
@@ -339,36 +352,8 @@ public class GameDAO {
 
                 ResultSet resultSet = statement.executeQuery();
                 while (resultSet.next()) {
-                    long id  = resultSet.getLong(1);
-                    int diff = resultSet.getInt(2);
-                    int gameNum = resultSet.getInt(3);
-                    String version = resultSet.getString(4);
-
-                    String startTime = resultSet.getString(5);
-                    String endTime   = resultSet.getString(6);
-
-                    Long startTimeLong = startTime != null ? Long.valueOf(startTime) : null;
-                    Long endTimeLong   = endTime   != null ? Long.valueOf(endTime)   : null;
-
-                    if(startTime == null || endTime == null) continue; //only games that were finished
-
-                    Game game = new Game(
-                        id,
-                        UserDAO.selectUser(userId),
-                        diff,
-                        gameNum,
-                        Game.DEFAULT_GAME_LOCALE,
-                        version,
-                        0L, //Don't need seed
-                        startTimeLong,
-                        endTimeLong,
-                        hwSerial,
-                        applicationVersionName,
-                        applicationVersionCode
-                    );
-
-                    game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game));
-                    game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId()));
+                    Game game = prepareGameObject(resultSet);
+                    if(game.getStartTime() == null || game.getEndTime() == null) continue; //only games that were finished
                     games.add(game);
                 }
                 resultSet.close();
@@ -397,26 +382,7 @@ public class GameDAO {
 
                 while (hasNextGames) {
                     if (resultSet.next()) {
-                        Game game;
-
-                        String startTimeStr = resultSet.getString(7);
-                        String endTimeStr = resultSet.getString(8);
-                        game = new Game(resultSet.getLong(1),
-                                UserDAO.selectUser(resultSet.getLong(2)),
-                                resultSet.getInt(3),
-                                resultSet.getInt(4),
-                                resultSet.getInt(5),
-                                resultSet.getLong(6),
-                                startTimeStr != null ? Long.valueOf(startTimeStr) : null,
-                                endTimeStr != null ? Long.valueOf(endTimeStr) : null,
-                                resultSet.getString(8),
-                                resultSet.getString(9),
-                                resultSet.getInt(10));
-
-                        game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game));
-                        game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId()));
-                        selectedGames.add(game);
-
+                        selectedGames.add(prepareGameObject(resultSet));
                     } else {
                         hasNextGames = false;
                     }
diff --git a/core/src/cz/nic/tablexia/model/game/GameTrophy.java b/core/src/cz/nic/tablexia/model/game/GameTrophy.java
index ae9b54b2002a39b61c3a58f77301e5bdd796a678..0c3925b3c594d4b1a6830ea8f2e0d5a960248dd6 100644
--- a/core/src/cz/nic/tablexia/model/game/GameTrophy.java
+++ b/core/src/cz/nic/tablexia/model/game/GameTrophy.java
@@ -10,7 +10,6 @@ import cz.nic.tablexia.TablexiaStorage;
 import cz.nic.tablexia.game.AbstractTablexiaGame;
 import cz.nic.tablexia.game.difficulty.GameDifficulty;
 import cz.nic.tablexia.game.trophy.GameTrophyDefinition;
-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;
@@ -55,7 +54,7 @@ public class GameTrophy {
 
     public static class ThreeStarsReceived implements GameTrophyResolver {
 
-        public static final String GAME_SELECT_FOR_GAME_AND_DIFFICULTY = "SELECT id, user_id, difficulty_number, game_number, random_seed, start_time, end_time, hw_serial_number, application_version_name, application_version_code FROM game WHERE game_number = ? AND difficulty_number = ? AND user_id = ? AND end_time IS NOT NULL";
+    public static final String GAME_SELECT_FOR_GAME_AND_DIFFICULTY = "SELECT " + GameDAO.GAME_SELECT_COLUMNS + " FROM game WHERE game_number = ? AND difficulty_number = ? AND user_id = ? AND end_time IS NOT NULL";
 
         private static List<Game> getGamesForGameAndDifficulty(User user, GameTrophyDefinition trophyDef) {
             List<Game> games = new ArrayList<Game>();
@@ -67,21 +66,7 @@ public class GameTrophy {
                 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,
-                                resultSet.getString(8),
-                                resultSet.getString(9),
-                                resultSet.getInt(10));
-                        game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game));
-                        game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId()));
-                        games.add(game);
+                        games.add(GameDAO.prepareGameObject(resultSet));
                     }
                     resultSet.close();
                 } catch (SQLException e) {
diff --git a/core/src/cz/nic/tablexia/model/game/UserTrophy.java b/core/src/cz/nic/tablexia/model/game/UserTrophy.java
index fe5af83240ce865edb065de87d2a81b05e472484..1db6c09b0eae4a227923f2629ec6a89604854c22 100644
--- a/core/src/cz/nic/tablexia/model/game/UserTrophy.java
+++ b/core/src/cz/nic/tablexia/model/game/UserTrophy.java
@@ -20,9 +20,8 @@ import cz.nic.tablexia.game.AbstractTablexiaGame;
 import cz.nic.tablexia.game.GameDefinition;
 import cz.nic.tablexia.game.difficulty.GameDifficulty;
 import cz.nic.tablexia.game.trophy.UserTrophyDefinition;
-import cz.nic.tablexia.model.UserDAO;
-import cz.nic.tablexia.shared.model.User;
 import cz.nic.tablexia.shared.model.Game;
+import cz.nic.tablexia.shared.model.User;
 import cz.nic.tablexia.util.Log;
 
 /**
@@ -155,8 +154,8 @@ public class UserTrophy {
 
     public static class AllStarsGame implements UserTrophyResolver {
 
-        public static final String GAME_SELECT_FOR_USER_AND_DIFFICULTY = "SELECT id, user_id, difficulty_number, game_number, random_seed, start_time, end_time, hw_serial_number, application_version_name, application_version_code FROM game WHERE difficulty_number = ? AND user_id = ? AND end_time IS NOT NULL";
-        public static final String GAME_SELECT_FOR_USER = "SELECT id, user_id, difficulty_number, game_number, random_seed, start_time, end_time, hw_serial_number, application_version_name, application_version_code FROM game WHERE user_id = ? AND difficulty_number != ? AND start_time IS NOT NULL AND start_time != 0 AND end_time IS NOT NULL AND end_time != 0";
+        public static final String GAME_SELECT_FOR_USER_AND_DIFFICULTY = "SELECT " + GameDAO.GAME_SELECT_COLUMNS + " FROM game WHERE difficulty_number = ? AND user_id = ? AND end_time IS NOT NULL";
+        public static final String GAME_SELECT_FOR_USER = "SELECT " + GameDAO.GAME_SELECT_COLUMNS + " FROM game WHERE user_id = ? AND difficulty_number != ? AND start_time IS NOT NULL AND start_time != 0 AND end_time IS NOT NULL AND end_time != 0";
 
         private static List<Game> getGamesForUserAndDifficulty(User user, UserTrophyDefinition trophyDef) throws SQLException {
             PreparedStatement statement = TablexiaStorage.getInstance().prepareStatement(GAME_SELECT_FOR_USER_AND_DIFFICULTY);
@@ -180,22 +179,7 @@ public class UserTrophy {
                 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,
-                                resultSet.getString(8),
-                                resultSet.getString(9),
-                                resultSet.getInt(10));
-
-                        game.setGamePauses(GamePauseDAO.selectGamePausesForGame(game));
-                        game.getGameScoreMap().addAll(GameScoreDAO.selectGameScores(game.getId()));
-                        games.add(game);
+                        games.add(GameDAO.prepareGameObject(resultSet));
                     }
                     resultSet.close();
                 } catch (SQLException e) {