Добавить испытания и прогрессию по LevelID

This commit is contained in:
2026-08-19 09:25:32 +03:00
parent 259fcd316b
commit 3de8d45039
37 changed files with 968 additions and 63 deletions
@@ -5,7 +5,7 @@ import android.content.SharedPreferences;
public final class ProgressStore {
private static final String FILE = "project_sacrifice_progress_v1";
public static final int CURRENT_SAVE_VERSION = 2;
public static final int CURRENT_SAVE_VERSION = 3;
private final SharedPreferences preferences;
public ProgressStore(Context context) {
@@ -18,26 +18,60 @@ public final class ProgressStore {
}
public boolean isCompleted(int levelNumber) {
return preferences.getBoolean(key(levelNumber, "completed"), false);
return isCompleted(levelId(levelNumber));
}
public boolean isCompleted(String levelId) {
return preferences.getBoolean(idKey(levelId, "completed"), false);
}
public int bestDeaths(int levelNumber) {
return preferences.getInt(key(levelNumber, "deaths"), Integer.MAX_VALUE);
return bestDeaths(levelId(levelNumber));
}
public int bestDeaths(String levelId) {
return preferences.getInt(idKey(levelId, "deaths"), Integer.MAX_VALUE);
}
public long bestTimeMs(int levelNumber) {
return preferences.getLong(key(levelNumber, "time"), Long.MAX_VALUE);
return bestTimeMs(levelId(levelNumber));
}
public long bestTimeMs(String levelId) {
return preferences.getLong(idKey(levelId, "time"), Long.MAX_VALUE);
}
public boolean collectibleFound(String levelId) {
return preferences.getBoolean(idKey(levelId, "collectible"), false);
}
public void recordCompletion(int levelNumber, int deaths, long elapsedMs) {
recordCompletion(LevelCatalog.get(levelNumber - 1), deaths, elapsedMs, false);
}
public void recordCompletion(LevelDefinition level, int deaths, long elapsedMs,
boolean collectibleFound) {
if (level == null) throw new IllegalArgumentException("level is required");
SharedPreferences.Editor editor = preferences.edit();
editor.putBoolean(key(levelNumber, "completed"), true);
editor.putInt(key(levelNumber, "deaths"), Math.min(deaths, bestDeaths(levelNumber)));
editor.putLong(key(levelNumber, "time"), Math.min(elapsedMs, bestTimeMs(levelNumber)));
editor.putInt("unlocked", Math.min(LevelCatalog.all().size(), Math.max(unlockedCount(), levelNumber + 1)));
editor.putBoolean(idKey(level.levelId, "completed"), true);
editor.putInt(idKey(level.levelId, "deaths"),
Math.min(Math.max(0, deaths), bestDeaths(level.levelId)));
editor.putLong(idKey(level.levelId, "time"),
Math.min(Math.max(0L, elapsedMs), bestTimeMs(level.levelId)));
if (collectibleFound || collectibleFound(level.levelId)) {
editor.putBoolean(idKey(level.levelId, "collectible"), true);
}
editor.putInt("unlocked", Math.min(LevelCatalog.all().size(),
Math.max(unlockedCount(), level.number + 1)));
editor.apply();
}
public int earnedStars(LevelDefinition level) {
if (level == null || !isCompleted(level.levelId)) return 0;
return ChallengeResult.evaluate(level, bestDeaths(level.levelId),
bestTimeMs(level.levelId), collectibleFound(level.levelId)).stars();
}
public int saveVersion() {
return preferences.getInt("save_version", 1);
}
@@ -45,11 +79,56 @@ public final class ProgressStore {
private void migrateIfSupported() {
int version = preferences.getInt("save_version", 1);
if (version >= 1 && version < CURRENT_SAVE_VERSION) {
preferences.edit().putInt("save_version", CURRENT_SAVE_VERSION).apply();
SharedPreferences.Editor editor = preferences.edit();
if (version < 3) migrateNumericKeys(editor);
editor.putInt("save_version", CURRENT_SAVE_VERSION).apply();
}
}
private void migrateNumericKeys(SharedPreferences.Editor editor) {
for (LevelDefinition level : LevelCatalog.all()) {
copyBooleanIfPresent(editor, key(level.number, "completed"),
idKey(level.levelId, "completed"));
copyIntIfPresent(editor, key(level.number, "deaths"),
idKey(level.levelId, "deaths"));
copyLongIfPresent(editor, key(level.number, "time"),
idKey(level.levelId, "time"));
}
}
private void copyBooleanIfPresent(SharedPreferences.Editor editor,
String oldKey, String newKey) {
if (preferences.contains(oldKey) && !preferences.contains(newKey)) {
editor.putBoolean(newKey, preferences.getBoolean(oldKey, false));
}
}
private void copyIntIfPresent(SharedPreferences.Editor editor,
String oldKey, String newKey) {
if (preferences.contains(oldKey) && !preferences.contains(newKey)) {
editor.putInt(newKey, preferences.getInt(oldKey, Integer.MAX_VALUE));
}
}
private void copyLongIfPresent(SharedPreferences.Editor editor,
String oldKey, String newKey) {
if (preferences.contains(oldKey) && !preferences.contains(newKey)) {
editor.putLong(newKey, preferences.getLong(oldKey, Long.MAX_VALUE));
}
}
private static String levelId(int levelNumber) {
if (levelNumber >= 1 && levelNumber <= LevelCatalog.all().size()) {
return LevelCatalog.get(levelNumber - 1).levelId;
}
return LevelDefinition.defaultLevelId(levelNumber);
}
private static String key(int levelNumber, String suffix) {
return "level_" + levelNumber + "_" + suffix;
}
private static String idKey(String levelId, String suffix) {
return "level_id_" + levelId + "_" + suffix;
}
}