Add integrity check to progression data
This commit is contained in:
@@ -10,7 +10,9 @@ enum Status{
|
||||
}
|
||||
|
||||
@export var version: String = ProjectSettings.get_setting("application/config/version")
|
||||
@export var unlocks: Dictionary = {}
|
||||
@export var unlocks: Dictionary = {}:
|
||||
set(value):
|
||||
unlocks = check_data_integrity(value)
|
||||
@export var level_times: Dictionary[int, PackedInt32Array] = {} # Level ID, Last number of seconds for minigames 0, 1 and 2
|
||||
@export var level_total_times: Dictionary[int, PackedInt32Array] = {} # Level ID, Total number of seconds for minigames 0, 1 and 2
|
||||
@export var last_modified: String
|
||||
@@ -47,6 +49,98 @@ func init_unlocks() -> void:
|
||||
unlocks[1]["look_and_learn"] = Status.Unlocked
|
||||
|
||||
|
||||
func check_data_integrity(data: Dictionary) -> Dictionary:
|
||||
var result: Dictionary = data.duplicate(true)
|
||||
|
||||
# Check missin keys
|
||||
var min_key: int = 1
|
||||
var max_key: int = 1
|
||||
if result.size() > 0:
|
||||
if result.keys()[0] is int:
|
||||
min_key = result.keys().min() as int
|
||||
max_key = result.keys().max() as int
|
||||
else:
|
||||
Log.error("StudentProgression: Received keys with wrong datatype")
|
||||
|
||||
for index: int in range(min_key, max_key + 1):
|
||||
if not result.has(index):
|
||||
Log.warn("StudentProgression: Garden %d missing → added with default values." % index)
|
||||
result[index] = {
|
||||
"games": [0, 0, 0],
|
||||
"look_and_learn": 0,
|
||||
"last_duration": 0.0,
|
||||
"total_duration": 0.0
|
||||
}
|
||||
|
||||
# Check internal structure
|
||||
for index: int in result.keys():
|
||||
var garden: Dictionary = result[index]
|
||||
|
||||
# Check missing keys
|
||||
if not garden.has("games"):
|
||||
Log.warn("Garden %d : Add missing key 'games'." % index)
|
||||
garden["games"] = [0, 0, 0]
|
||||
if not garden.has("look_and_learn"):
|
||||
Log.warn("Garden %d : Add missing key 'look_and_learn'." % index)
|
||||
garden["look_and_learn"] = 0
|
||||
if not garden.has("last_duration"):
|
||||
garden["last_duration"] = 0.0
|
||||
if not garden.has("total_duration"):
|
||||
garden["total_duration"] = 0.0
|
||||
|
||||
# Check array "games"
|
||||
if typeof(garden["games"]) != TYPE_ARRAY or (garden["games"] as Array).size() != 3:
|
||||
Log.warn("Garden %d : invalid format for 'games' → reset." % index)
|
||||
garden["games"] = [0, 0, 0]
|
||||
|
||||
# Check value outside of 0/1/2
|
||||
for game_index: int in range(3):
|
||||
if garden["games"][game_index] not in [0, 1, 2]:
|
||||
garden["games"][game_index] = 0
|
||||
if garden["look_and_learn"] not in [0, 1, 2]:
|
||||
garden["look_and_learn"] = 0
|
||||
|
||||
# Check progression rules
|
||||
for index: int in range(min_key, max_key + 1):
|
||||
var garden: Dictionary = result[index]
|
||||
var prev_completed: bool = false
|
||||
|
||||
# Check previous garden is completed
|
||||
if result.has(index - 1):
|
||||
var prev: Dictionary = result[index - 1]
|
||||
prev_completed = (
|
||||
prev["look_and_learn"] == 2 and
|
||||
(prev["games"] as Array).all(func(x: int) -> bool: return x == 2)
|
||||
)
|
||||
else:
|
||||
# First garden (key 1) is always unlocked
|
||||
prev_completed = true
|
||||
|
||||
# Case : previous garden not completed
|
||||
if not prev_completed:
|
||||
for game_index: int in range(3):
|
||||
if garden["games"][game_index] != 0 or garden["look_and_learn"] != 0:
|
||||
Log.warn("Garden %d : invalid progression (previous not finished) → reset." % index)
|
||||
garden["games"] = [0, 0, 0]
|
||||
garden["look_and_learn"] = 0
|
||||
break
|
||||
continue
|
||||
|
||||
# Case : lesson completed → games unlocked if needed
|
||||
if garden["look_and_learn"] == 2:
|
||||
for game_index: int in range(3):
|
||||
if garden["games"][game_index] == 0:
|
||||
garden["games"][game_index] = 1
|
||||
Log.warn("Garden %d : game %d unlocked because lesson is completed" % [index, game_index + 1])
|
||||
|
||||
# Case : previous garden completed → lesson unlocked if needed
|
||||
elif garden["look_and_learn"] == 0:
|
||||
garden["look_and_learn"] = 1
|
||||
Log.warn("Garden %d : lesson unlocked because previous garden is completed" % index)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
func get_max_unlocked_lesson_index() -> int:
|
||||
var max_unlocked_level: int = 1
|
||||
for index: int in range(unlocks.size()):
|
||||
|
||||
Reference in New Issue
Block a user