This commit is contained in:
Adrien Ufferte
2026-04-17 10:06:46 +02:00
parent e169f066ac
commit c6f7ef833d
29 changed files with 361 additions and 275 deletions
+81 -13
View File
@@ -136,7 +136,11 @@ def _to_snake_case(name: str) -> str:
def _to_pascal_case(name: str) -> str:
prefix = '_' if name.startswith('_') else ''
core = name.lstrip('_')
return prefix + ''.join(w.capitalize() for w in re.split(r'[_\s]+', core) if w)
# Split on camelCase boundaries first, then on underscores/spaces
# e.g. 'myBadEnum' → 'my_Bad_Enum' → 'MyBadEnum'
snake = re.sub(r'([a-z0-9])([A-Z])', r'\1_\2', core)
snake = re.sub(r'([A-Z]+)([A-Z][a-z])', r'\1_\2', snake)
return prefix + ''.join(w.capitalize() for w in re.split(r'[_\s]+', snake) if w)
def _to_upper_snake_case(name: str) -> str:
@@ -148,31 +152,63 @@ def _to_upper_snake_case(name: str) -> str:
CONVENTION_NAMES: dict[str, str] = {
'class': 'PascalCase',
'function': 'snake_case',
'variable': 'snake_case',
'constant': 'UPPER_SNAKE_CASE',
'signal': 'snake_case',
'class': 'PascalCase',
'enum_name': 'PascalCase',
'enum_member': 'UPPER_SNAKE_CASE',
'function': 'snake_case',
'variable': 'snake_case',
'constant': 'UPPER_SNAKE_CASE',
'signal': 'snake_case',
}
SUGGESTION_FN: dict = {
'class': _to_pascal_case,
'function': _to_snake_case,
'variable': _to_snake_case,
'constant': _to_upper_snake_case,
'signal': _to_snake_case,
'class': _to_pascal_case,
'enum_name': _to_pascal_case,
'enum_member': _to_upper_snake_case,
'function': _to_snake_case,
'variable': _to_snake_case,
'constant': _to_upper_snake_case,
'signal': _to_snake_case,
}
NAMING_KINDS = frozenset({'class', 'function', 'variable', 'constant', 'signal'})
NAMING_KINDS = frozenset({'class', 'enum_name', 'enum_member', 'function', 'variable', 'constant', 'signal'})
# ─── Naming check ─────────────────────────────────────────────────────────────
def _check_enum_member(path: str, idx: int, name: str) -> None:
"""Flag a single enum member name if it is not UPPER_SNAKE_CASE."""
if name and not UPPER_SNAKE_CASE.match(name):
issues.append((path, idx, 'enum_member', name))
def check_naming(path: str, lines: list[str]):
in_enum = False # True while scanning the body of a multi-line enum
for idx, line in enumerate(lines, 1):
stripped = line.strip()
if stripped.startswith('#') or stripped.startswith('@warning_ignore(') or not stripped:
continue
# ── Enum-body lines ────────────────────────────────────────────────────
if in_enum:
close = stripped.find('}')
if close != -1:
in_enum = False
# Any identifiers before the closing brace on this line
before = stripped[:close]
for part in before.split(','):
m = re.match(r"\s*([A-Za-z0-9_]+)", part)
if m:
_check_enum_member(path, idx, m.group(1))
else:
# One (or more) members on this line: "NAME," or "NAME = val,"
for part in stripped.split(','):
m = re.match(r"\s*([A-Za-z0-9_]+)", part)
if m:
_check_enum_member(path, idx, m.group(1))
continue
# ── End enum-body ──────────────────────────────────────────────────────
match_class = re.match(r"class_name\s+([A-Za-z0-9_]+)", stripped)
if match_class:
name = match_class.group(1)
@@ -208,6 +244,26 @@ def check_naming(path: str, lines: list[str]):
if not UPPER_SNAKE_CASE.match(name):
issues.append((path, idx, 'constant', name))
match_enum = re.match(r"enum\s+([A-Za-z0-9_]+)", stripped)
if match_enum:
name = match_enum.group(1)
if not PASCAL_CASE.match(name):
issues.append((path, idx, 'enum_name', name))
# Determine whether the enum body is inline or multi-line
brace = stripped.find('{')
if brace != -1:
rest = stripped[brace + 1:]
close = rest.find('}')
if close != -1:
# Inline enum — check members immediately
for part in rest[:close].split(','):
m = re.match(r"\s*([A-Za-z0-9_]+)", part)
if m:
_check_enum_member(path, idx, m.group(1))
else:
# Body continues on following lines
in_enum = True
match_signal = re.match(r"signal\s+([A-Za-z0-9_]+)", stripped)
if match_signal:
name = match_signal.group(1)
@@ -499,11 +555,23 @@ def categorize(kind: str) -> str:
return 'other'
_KIND_LABEL: dict[str, str] = {
'class': 'class names',
'enum_name': 'enum names',
'enum_member': 'enum member names',
'function': 'function names',
'variable': 'variable names',
'constant': 'constant names',
'signal': 'signal names',
}
def format_message(kind: str, data) -> str:
if kind in NAMING_KINDS:
suggestion = SUGGESTION_FN[kind](data)
conv = CONVENTION_NAMES[kind]
return f"'{data}' should be '{suggestion}' ({kind}s must be {conv})"
label = _KIND_LABEL.get(kind, f"{kind}s")
return f"'{data}' should be '{suggestion}' ({label} must be {conv})"
if kind == 'error':
return str(data)
template = MESSAGES.get(kind, kind)
+1 -1
View File
@@ -404,7 +404,7 @@ VALIDATE,Confirmer,Confirmar,Confirmar,Conferma
SUMMARY_EMAIL,Adresse email : {mail},Correo electrónico: {mail},Endereço de e-mail : {mail},Indirizzo email: {mail}
SUMMARY_TYPE,Type de compte : {type},Tipo de cuenta: {type},Tipo de conta : {type},Tipo di account: {type}
SUMMARY_METHOD,Méthode d'éducation : {method},Método de enseñanza: {method},Método educacional : {method},Metodo educativo: {method}
APPONLY,Application uniquement,Solo aplicación,Somente aplicativo,Solo applicazione
APP_ONLY,Application uniquement,Solo aplicación,Somente aplicativo,Solo applicazione
COMPLETE,Complète (livrets et jeux papiers),Completo (cuaderno y juegos en papel),Completo (livretos e jogos de papel),Completo (libretti e giochi cartacei)
SUMMARY_NUMBER_OF_DEVICES,Nombre d'appareils : {number},Cantidad de dispositivos: {number},Número de dispositivos : {number},Numero di dispositivi: {number}
SUMMARY_NUMBER_OF_STUDENTS,Nombre d'élèves : {number},Cantidad de estudiantes: {number},Número de alunos : {number},Numero di studenti: {number}
Can't render this file because it contains an unexpected character in line 41 and column 273.
+1 -1
View File
@@ -2,7 +2,7 @@
class_name Garden
extends Control
const BACKGROUND_PATH_MODEL: String = "res://assets/gardens/gardens/Garden_%02d.png"
const BACKGROUND_PATH_MODEL: String = "res://assets/gardens/gardens/garden_%02d.png"
const MAX_LESSONS: int = 5
const PLANT_COUNT: int = 8
# Maps lesson count → which slot indices to use
+4 -4
View File
@@ -3,15 +3,15 @@ class_name GardenLayout
extends Resource
enum FirstOrLast {
First,
Neither,
Last
FIRST,
NEITHER,
LAST
}
@export var color: int = 0
@export var lesson_buttons_export: Array[Dictionary] = []:
set = set_lesson_buttons_export
@export var is_first_or_last: FirstOrLast = FirstOrLast.Neither
@export var is_first_or_last: FirstOrLast = FirstOrLast.NEITHER
var lesson_buttons: Array[GardenLayoutLessonButton] = []:
set = set_lesson_buttons
+4 -4
View File
@@ -2,14 +2,14 @@ class_name StudentData
extends Resource
enum Level {
Beginner,
Reviewer,
Adult
BEGINNER,
REVIEWER,
ADULT
}
@export var code: int = 0
@export var name: String = ""
@export var level: Level = Level.Beginner
@export var level: Level = Level.BEGINNER
@export var age: int = 0
@export var last_modified: String = ""
+37 -37
View File
@@ -4,9 +4,9 @@ extends Resource
signal progression_changed()
enum Status{
Locked,
Unlocked,
Completed,
LOCKED,
UNLOCKED,
COMPLETED,
}
static var cached_boss_gate_lessons: Array[int] = []
@@ -42,11 +42,11 @@ func init_unlocks() -> void:
for index: int in range(number_of_lessons):
if not unlocks.has(index+1):
unlocks[index + 1] = {
"look_and_learn": Status.Locked,
"look_and_learn": Status.LOCKED,
"games": [
Status.Locked,
Status.Locked,
Status.Locked,
Status.LOCKED,
Status.LOCKED,
Status.LOCKED,
],
"last_duration": PackedInt32Array([0, 0, 0]),
"total_duration": PackedInt32Array([0, 0, 0])
@@ -54,8 +54,8 @@ func init_unlocks() -> void:
# Make sure that the first garden is always accessible
if unlocks.has(1):
if unlocks[1]["look_and_learn"] == Status.Locked:
unlocks[1]["look_and_learn"] = Status.Unlocked
if unlocks[1]["look_and_learn"] == Status.LOCKED:
unlocks[1]["look_and_learn"] = Status.UNLOCKED
_sanitize_boss_progression()
@@ -75,8 +75,8 @@ func ensure_data_integrity(data: Dictionary[int, Dictionary]) -> Dictionary:
if not is_init:
Log.warn("StudentProgression: Garden %d missing → added with default values." % index)
result[index] = {
"games": [Status.Locked, Status.Locked, Status.Locked],
"look_and_learn": Status.Locked,
"games": [Status.LOCKED, Status.LOCKED, Status.LOCKED],
"look_and_learn": Status.LOCKED,
"last_duration": PackedInt32Array([0, 0, 0]),
"total_duration": PackedInt32Array([0, 0, 0])
}
@@ -87,11 +87,11 @@ func ensure_data_integrity(data: Dictionary[int, Dictionary]) -> Dictionary:
if not garden.has("games"):
if not is_init:
Log.warn("StudentProgression: Garden %d: Add missing key 'games'." % index)
garden["games"] = [Status.Locked, Status.Locked, Status.Locked]
garden["games"] = [Status.LOCKED, Status.LOCKED, Status.LOCKED]
if not garden.has("look_and_learn"):
if not is_init:
Log.warn("StudentProgression: Garden %d: Add missing key 'look_and_learn'." % index)
garden["look_and_learn"] = Status.Locked
garden["look_and_learn"] = Status.LOCKED
if not garden.has("last_duration"):
garden["last_duration"] = PackedInt32Array([0, 0, 0])
if not garden.has("total_duration"):
@@ -101,14 +101,14 @@ func ensure_data_integrity(data: Dictionary[int, Dictionary]) -> Dictionary:
if typeof(garden["games"]) != TYPE_ARRAY or (garden["games"] as Array).size() != 3:
if not is_init:
Log.warn("StudentProgression: Garden %d: invalid format for 'games' → reset." % index)
garden["games"] = [Status.Locked, Status.Locked, Status.Locked]
garden["games"] = [Status.LOCKED, Status.LOCKED, Status.LOCKED]
# Check value outside of possible enum values
for game_index: int in range(3):
if garden["games"][game_index] not in [Status.Locked, Status.Unlocked, Status.Completed]:
garden["games"][game_index] = Status.Locked
if garden["look_and_learn"] not in [Status.Locked, Status.Unlocked, Status.Completed]:
garden["look_and_learn"] = Status.Locked
if garden["games"][game_index] not in [Status.LOCKED, Status.UNLOCKED, Status.COMPLETED]:
garden["games"][game_index] = Status.LOCKED
if garden["look_and_learn"] not in [Status.LOCKED, Status.UNLOCKED, Status.COMPLETED]:
garden["look_and_learn"] = Status.LOCKED
# Check progression rules
for index: int in range(min_key, max_key + 1):
@@ -119,8 +119,8 @@ func ensure_data_integrity(data: Dictionary[int, Dictionary]) -> Dictionary:
if result.has(index - 1):
var prev: Dictionary = result[index - 1]
prev_completed = (
prev["look_and_learn"] == Status.Completed and
(prev["games"] as Array).all(func(x: int) -> bool: return x == Status.Completed)
prev["look_and_learn"] == Status.COMPLETED and
(prev["games"] as Array).all(func(x: int) -> bool: return x == Status.COMPLETED)
)
else:
# First garden (key 1) is always unlocked
@@ -129,25 +129,25 @@ func ensure_data_integrity(data: Dictionary[int, Dictionary]) -> Dictionary:
# Case: previous garden not completed
if not prev_completed:
for game_index: int in range(3):
if garden["games"][game_index] != Status.Locked or garden["look_and_learn"] != Status.Locked:
if garden["games"][game_index] != Status.LOCKED or garden["look_and_learn"] != Status.LOCKED:
if not is_init:
Log.warn("StudentProgression: Garden %d: invalid progression (previous not finished) → reset." % index)
garden["games"] = [Status.Locked, Status.Locked, Status.Locked]
garden["look_and_learn"] = Status.Locked
garden["games"] = [Status.LOCKED, Status.LOCKED, Status.LOCKED]
garden["look_and_learn"] = Status.LOCKED
break
continue
# Case: lesson completed → unlock games if needed
if garden["look_and_learn"] == Status.Completed:
if garden["look_and_learn"] == Status.COMPLETED:
for game_index: int in range(3):
if garden["games"][game_index] == Status.Locked:
garden["games"][game_index] = Status.Unlocked
if garden["games"][game_index] == Status.LOCKED:
garden["games"][game_index] = Status.UNLOCKED
if not is_init:
Log.warn("StudentProgression: Garden %d: game %d unlocked because lesson is completed" % [index, game_index + 1])
# Case: previous garden completed → unlock lesson if needed
elif garden["look_and_learn"] == Status.Locked:
garden["look_and_learn"] = Status.Unlocked
elif garden["look_and_learn"] == Status.LOCKED:
garden["look_and_learn"] = Status.UNLOCKED
if not is_init:
Log.warn("StudentProgression: Garden %d: lesson unlocked because previous garden is completed" % index)
@@ -229,7 +229,7 @@ func get_max_unlocked_lesson_index() -> int:
for index: int in range(unlocks.size()):
if is_lesson_blocked_by_boss(index + 1):
break
if unlocks[index + 1]["look_and_learn"] >= Status.Unlocked:
if unlocks[index + 1]["look_and_learn"] >= Status.UNLOCKED:
max_unlocked_level = index
else:
break
@@ -238,18 +238,18 @@ func get_max_unlocked_lesson_index() -> int:
func is_lesson_completed(lesson_number: int) -> bool:
return unlocks[lesson_number]["look_and_learn"] == Status.Completed and unlocks[lesson_number]["games"][0] == Status.Completed and unlocks[lesson_number]["games"][1] == Status.Completed and unlocks[lesson_number]["games"][2] == Status.Completed
return unlocks[lesson_number]["look_and_learn"] == Status.COMPLETED and unlocks[lesson_number]["games"][0] == Status.COMPLETED and unlocks[lesson_number]["games"][1] == Status.COMPLETED and unlocks[lesson_number]["games"][2] == Status.COMPLETED
# Return true if the progression is saved or false if the look and learn was already completed
func look_and_learn_completed(lesson_number: int) -> bool:
if unlocks[lesson_number]["look_and_learn"] == Status.Completed:
if unlocks[lesson_number]["look_and_learn"] == Status.COMPLETED:
return false
unlocks[lesson_number]["look_and_learn"] = Status.Completed
unlocks[lesson_number]["look_and_learn"] = Status.COMPLETED
for index: int in range(3):
unlocks[lesson_number]["games"][index] = Status.Unlocked
unlocks[lesson_number]["games"][index] = Status.UNLOCKED
last_modified = Time.get_datetime_string_from_system(true)
progression_changed.emit()
@@ -259,18 +259,18 @@ func look_and_learn_completed(lesson_number: int) -> bool:
# Return true if the progression is saved or false if the game was already completed
func game_completed(lesson_number: int, game_number: int) -> bool:
# If the game is already completed, do nothing
if unlocks[lesson_number]["games"][game_number] == Status.Completed:
if unlocks[lesson_number]["games"][game_number] == Status.COMPLETED:
return false
unlocks[lesson_number]["games"][game_number] = Status.Completed
unlocks[lesson_number]["games"][game_number] = Status.COMPLETED
var all_completed: bool = true
for index: int in range(3):
all_completed = all_completed and unlocks[lesson_number]["games"][index] == Status.Completed
all_completed = all_completed and unlocks[lesson_number]["games"][index] == Status.COMPLETED
if all_completed:
if unlocks.has(lesson_number + 1):
unlocks[lesson_number + 1]["look_and_learn"] = Status.Unlocked
unlocks[lesson_number + 1]["look_and_learn"] = Status.UNLOCKED
last_modified = Time.get_datetime_string_from_system(true)
progression_changed.emit()
+4 -4
View File
@@ -2,12 +2,12 @@ class_name TeacherSettings
extends Resource
enum AccountType {
Teacher,
Parent
TEACHER,
PARENT
}
enum EducationMethod {
AppOnly,
Complete
APP_ONLY,
COMPLETE
}
const AVAILABLE_CODES: Array[int] = [123, 124, 125, 126, 132, 134, 135, 136, 142, 143, 145, 146, 152, 153, 154, 213, 214, 215, 216, 231, 234, 235, 236, 241, 243, 245, 246, 251, 253, 254, 321, 324, 325, 326, 312, 314, 315, 316, 342, 341, 345, 346, 352, 351, 354, 423, 421, 425, 426, 432, 431, 435, 436, 412, 413, 415, 416, 452, 453, 451, 523, 524, 521, 526, 532, 534, 531, 536, 542, 543, 541, 546, 512, 513, 514, 623, 624, 625, 621, 632, 634, 635, 631, 642, 643, 645, 641, 652, 653, 654]
+11 -11
View File
@@ -178,7 +178,7 @@ func _apply_progression_to_gardens(transition_context: Dictionary) -> void:
var lesson_unlocks: Dictionary = UserDataManager.student_progression.unlocks[lesson_index]
var is_blocked_by_boss: bool = UserDataManager.student_progression.is_lesson_blocked_by_boss(lesson_index)
var is_lesson_unlocked: bool = lesson_unlocks["look_and_learn"] != StudentProgression.Status.Locked and not is_blocked_by_boss
var is_lesson_unlocked: bool = lesson_unlocks["look_and_learn"] != StudentProgression.Status.LOCKED and not is_blocked_by_boss
button.set_button_disabled(not is_lesson_unlocked)
if transition_context.new_lesson_unlocked and lesson_index == transition_context.newly_unlocked_lesson_number:
@@ -352,7 +352,7 @@ func _ready() -> void:
_scroll_to_starting_garden(transition_context)
await (OpeningCurtain as OpeningCurtainClass).open()
(MusicManager as MusicManagerClass).play((MusicManager as MusicManagerClass).Track.Garden)
(MusicManager as MusicManagerClass).play((MusicManager as MusicManagerClass).Track.GARDEN)
# Handles all the animation played when entering the gardens
if transition_data:
@@ -674,7 +674,7 @@ func _open_minigames_layout(button: LessonButton, lesson_number: int) -> void:
current_button_global_position = button.global_position
# Gets the current lesson unlocks
var lesson_unlocks: Dictionary = UserDataManager.student_progression.unlocks[current_lesson_number]
var are_minigames_locked: bool = lesson_unlocks["games"][0] == StudentProgression.Status.Locked and lesson_unlocks["games"][1] == StudentProgression.Status.Locked and lesson_unlocks["games"][2] == StudentProgression.Status.Locked
var are_minigames_locked: bool = lesson_unlocks["games"][0] == StudentProgression.Status.LOCKED and lesson_unlocks["games"][1] == StudentProgression.Status.LOCKED and lesson_unlocks["games"][2] == StudentProgression.Status.LOCKED
# Deactivate the mouse filters on the buttons behind the layout
for lesson_button_item: LessonButton in current_garden.get_lesson_buttons():
lesson_button_item.mouse_filter = Control.MOUSE_FILTER_IGNORE
@@ -712,10 +712,10 @@ func _open_minigames_layout(button: LessonButton, lesson_number: int) -> void:
func _handle_lesson_button(lesson_number: int, status: StudentProgression.Status) -> void:
lesson_button.text = lessons[lesson_number][0].grapheme
lesson_button.set_button_disabled(status == StudentProgression.Status.Locked)
lesson_button.completed = status == StudentProgression.Status.Completed
lesson_button_particles.emitting = status == StudentProgression.Status.Unlocked
if status == StudentProgression.Status.Completed:
lesson_button.set_button_disabled(status == StudentProgression.Status.LOCKED)
lesson_button.completed = status == StudentProgression.Status.COMPLETED
lesson_button_particles.emitting = status == StudentProgression.Status.UNLOCKED
if status == StudentProgression.Status.COMPLETED:
if transition_data and transition_data.has("look_and_learn_completed") and transition_data.look_and_learn_completed:
await minigame_layout_opened
lesson_button.right()
@@ -723,8 +723,8 @@ func _handle_lesson_button(lesson_number: int, status: StudentProgression.Status
func _fill_minigame_choice(minigame_layout: MinigameLayout, exercise_type: int, status: StudentProgression.Status, minigame_number: int) -> void:
minigame_layout.icon.texture = minigames_icons[exercise_type-1]
minigame_layout.is_disabled = status == StudentProgression.Status.Locked
if status == StudentProgression.Status.Completed:
minigame_layout.is_disabled = status == StudentProgression.Status.LOCKED
if status == StudentProgression.Status.COMPLETED:
if transition_data and transition_data.has("minigame_completed") and transition_data.minigame_completed and transition_data.has("minigame_number") and transition_data.minigame_number == minigame_number and transition_data.has("first_clear") and transition_data.first_clear:
minigame_layout.self_modulate = unlocked_color
await minigame_layout_opened
@@ -732,7 +732,7 @@ func _fill_minigame_choice(minigame_layout: MinigameLayout, exercise_type: int,
minigame_layout.right()
else:
minigame_layout.self_modulate.a = 0
elif status == StudentProgression.Status.Locked:
elif status == StudentProgression.Status.LOCKED:
minigame_layout.self_modulate = locked_color
else:
minigame_layout.self_modulate = unlocked_color
@@ -760,7 +760,7 @@ func _count_completed_minigames(lesson_number: int) -> int:
return 0
var completed: int = 0
for game_status: int in UserDataManager.student_progression.unlocks[lesson_number]["games"]:
if game_status == StudentProgression.Status.Completed:
if game_status == StudentProgression.Status.COMPLETED:
completed += 1
return completed
+7 -5
View File
@@ -5,16 +5,18 @@ signal delete_pressed()
signal validated()
enum Type {
Silent,
Vowel,
Consonant,
SILENT,
VOWEL,
CONSONANT,
}
const TYPE_LABELS: Array[String] = ["Silent", "Vowel", "Consonant"]
var grapheme: String = "":
set = set_grapheme
var phoneme: String = "":
set = set_phoneme
var type: GPListElement.Type = Type.Silent:
var type: GPListElement.Type = Type.SILENT:
set = set_type
var exception: bool = false:
set = set_exception
@@ -55,7 +57,7 @@ func set_phoneme(p_phoneme: String) -> void:
func set_type(p_type: Type) -> void:
type = p_type
if type_label:
type_label.text = Type.keys()[type]
type_label.text = TYPE_LABELS[type]
if type_edit:
type_edit.selected = type
+1 -1
View File
@@ -15,7 +15,7 @@ func _ready() -> void:
Database.db.query(query)
if Database.db.query_result.is_empty():
Database.db.query("CREATE TABLE ExerciseTypes (ID INTEGER PRIMARY KEY ASC AUTOINCREMENT UNIQUE NOT NULL, Type TEXT NOT NULL)")
for exercise_name: String in Minigame.Type.keys():
for exercise_name: String in Minigame.TYPE_NAMES:
Database.db.query("SELECT * FROM ExerciseTypes WHERE Type = '%s'" % exercise_name)
if Database.db.query_result.is_empty():
Database.db.insert_row("ExerciseTypes",
+2 -2
View File
@@ -74,10 +74,10 @@ func _on_step_completed(step: Step) -> void:
"type":
# Adds teacher or parent steps
_remove_future_steps()
if register_data.account_type == TeacherSettings.AccountType.Teacher:
if register_data.account_type == TeacherSettings.AccountType.TEACHER:
for scene: PackedScene in teacher_steps:
current_steps.append(scene.instantiate())
elif register_data.account_type == TeacherSettings.AccountType.Parent:
elif register_data.account_type == TeacherSettings.AccountType.PARENT:
for scene: PackedScene in parent_steps:
current_steps.append(scene.instantiate())
progress_bar.max_value = current_steps.size() + 3
@@ -14,8 +14,8 @@ func _ready() -> void:
func _on_next() -> bool:
var register_data: TeacherSettings = data as TeacherSettings
if register_data:
if register_data.account_type == TeacherSettings.AccountType.Parent:
register_data.education_method = TeacherSettings.EducationMethod.AppOnly
if register_data.account_type == TeacherSettings.AccountType.PARENT:
register_data.education_method = TeacherSettings.EducationMethod.APP_ONLY
Log.info("Register/AccountTypeStep: selected account type = %s" % TeacherSettings.AccountType.keys()[register_data.account_type])
else:
Log.warn("Register/AccountTypeStep: cannot continue because TeacherSettings data is missing")
+2 -2
View File
@@ -22,7 +22,7 @@ func on_enter() -> void:
email.text = tr("SUMMARY_EMAIL").format({"mail": teacher_settings.email})
account_type.text = tr("SUMMARY_TYPE").format({"type": tr((TeacherSettings.AccountType.keys()[teacher_settings.account_type] as String).to_upper())})
if teacher_settings.account_type == TeacherSettings.AccountType.Teacher:
if teacher_settings.account_type == TeacherSettings.AccountType.TEACHER:
education_method.text = tr("SUMMARY_METHOD").format({"method": tr((TeacherSettings.EducationMethod.keys()[teacher_settings.education_method] as String).to_upper())})
education_method.show()
@@ -41,7 +41,7 @@ func on_enter() -> void:
for device: int in teacher_settings.students.keys():
var device_recap: DeviceRecap = DEVICE_RECAP_SCENE.instantiate()
if teacher_settings.account_type == TeacherSettings.AccountType.Teacher:
if teacher_settings.account_type == TeacherSettings.AccountType.TEACHER:
device_recap.title = tr("DEVICE_NUMBER").format({"number": device})
else:
device_recap.title = tr("PLAYERS")
@@ -13,8 +13,8 @@ func _ready() -> void:
func _on_next() -> bool:
var register_data: TeacherSettings = data as TeacherSettings
if register_data:
if register_data.account_type == TeacherSettings.AccountType.Parent:
register_data.education_method = TeacherSettings.EducationMethod.AppOnly
if register_data.account_type == TeacherSettings.AccountType.PARENT:
register_data.education_method = TeacherSettings.EducationMethod.APP_ONLY
else:
return false
return true
@@ -1,13 +1,13 @@
[gd_scene format=3 uid="uid://buhnx0oblueuq"]
[ext_resource type="PackedScene" uid="uid://bxd3i06rqpxf0" path="res://sources/menus/register/steps/base_step.tscn" id="1_ksrhk"]
[ext_resource type="Script" uid="uid://dg4qit8mffvjh" path="res://addons/godot-form-validator/control_validator.gd" id="2_03dua"]
[ext_resource type="Script" uid="uid://ctfu2lhk6xaad" path="res://addons/godot-form-validator/control_validator.gd" id="2_03dua"]
[ext_resource type="Script" uid="uid://ugsjyxqh1s5h" path="res://sources/menus/register/steps/teacher/method_step.gd" id="2_onyn6"]
[ext_resource type="Script" uid="uid://dv82313fptjgb" path="res://sources/ui/tr_item_list.gd" id="2_qrbn1"]
[ext_resource type="Script" uid="uid://dw5aercmfe4" path="res://addons/godot-form-validator/rules/required_rule.gd" id="3_qewnl"]
[ext_resource type="Script" uid="uid://btw6a2qw2xnje" path="res://addons/godot-form-validator/rules/required_rule.gd" id="3_qewnl"]
[ext_resource type="Script" uid="uid://7uwoocpe7ieu" path="res://sources/utils/binder/control_binder.gd" id="4_1k1yt"]
[ext_resource type="Script" uid="uid://83q48kwp3p6p" path="res://sources/menus/register/steps/validation/item_list_validator.gd" id="4_rimto"]
[ext_resource type="Script" uid="uid://dg17cfvs2w257" path="res://addons/godot-form-validator/rules/validator_rule.gd" id="4_wmpac"]
[ext_resource type="Script" uid="uid://dlg1muqj8qwau" path="res://addons/godot-form-validator/rules/validator_rule.gd" id="4_wmpac"]
[ext_resource type="LabelSettings" uid="uid://ohvlqccl2oog" path="res://resources/themes/error_label_settings.tres" id="6_sf33v"]
[sub_resource type="Resource" id="Resource_kw8sn"]
@@ -16,7 +16,9 @@ fail_message = "A value is required."
[sub_resource type="Resource" id="Resource_ar6ux"]
script = ExtResource("4_rimto")
validation_order = 1
validation_method = 1
skip_validation = false
rules = Array[ExtResource("4_wmpac")]([SubResource("Resource_kw8sn")])
[node name="MethodStep" unique_id=304348596 instance=ExtResource("1_ksrhk")]
+37 -37
View File
@@ -68,54 +68,54 @@ func _set_lesson_gps(value: String) -> void:
func _on_look_and_learn_option_button_item_selected(index: int) -> void:
unlocks[lesson_number]["look_and_learn"] = index
if index == StudentProgression.Status.Locked:
if index == StudentProgression.Status.LOCKED:
if lesson_number == 1:
unlocks[lesson_number]["look_and_learn"] = StudentProgression.Status.Unlocked
unlocks[lesson_number]["look_and_learn"] = StudentProgression.Status.UNLOCKED
else:
unlocks[lesson_number - 1]["look_and_learn"] = StudentProgression.Status.Unlocked
unlocks[lesson_number - 1]["games"][0] = StudentProgression.Status.Locked
unlocks[lesson_number - 1]["games"][1] = StudentProgression.Status.Locked
unlocks[lesson_number - 1]["games"][2] = StudentProgression.Status.Locked
unlocks[lesson_number - 1]["look_and_learn"] = StudentProgression.Status.UNLOCKED
unlocks[lesson_number - 1]["games"][0] = StudentProgression.Status.LOCKED
unlocks[lesson_number - 1]["games"][1] = StudentProgression.Status.LOCKED
unlocks[lesson_number - 1]["games"][2] = StudentProgression.Status.LOCKED
unlocks[lesson_number]["games"][0] = StudentProgression.Status.Locked
unlocks[lesson_number]["games"][1] = StudentProgression.Status.Locked
unlocks[lesson_number]["games"][2] = StudentProgression.Status.Locked
unlocks[lesson_number]["games"][0] = StudentProgression.Status.LOCKED
unlocks[lesson_number]["games"][1] = StudentProgression.Status.LOCKED
unlocks[lesson_number]["games"][2] = StudentProgression.Status.LOCKED
for lesson: int in unlocks.keys():
if lesson > lesson_number:
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.Locked
unlocks[lesson]["games"][0] = StudentProgression.Status.Locked
unlocks[lesson]["games"][1] = StudentProgression.Status.Locked
unlocks[lesson]["games"][2] = StudentProgression.Status.Locked
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][0] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][1] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][2] = StudentProgression.Status.LOCKED
elif index == StudentProgression.Status.Unlocked:
unlocks[lesson_number]["games"][0] = StudentProgression.Status.Locked
unlocks[lesson_number]["games"][1] = StudentProgression.Status.Locked
unlocks[lesson_number]["games"][2] = StudentProgression.Status.Locked
elif index == StudentProgression.Status.UNLOCKED:
unlocks[lesson_number]["games"][0] = StudentProgression.Status.LOCKED
unlocks[lesson_number]["games"][1] = StudentProgression.Status.LOCKED
unlocks[lesson_number]["games"][2] = StudentProgression.Status.LOCKED
for lesson: int in unlocks.keys():
if lesson < lesson_number:
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.Completed
unlocks[lesson]["games"][0] = StudentProgression.Status.Completed
unlocks[lesson]["games"][1] = StudentProgression.Status.Completed
unlocks[lesson]["games"][2] = StudentProgression.Status.Completed
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.COMPLETED
unlocks[lesson]["games"][0] = StudentProgression.Status.COMPLETED
unlocks[lesson]["games"][1] = StudentProgression.Status.COMPLETED
unlocks[lesson]["games"][2] = StudentProgression.Status.COMPLETED
elif lesson > lesson_number:
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.Locked
unlocks[lesson]["games"][0] = StudentProgression.Status.Locked
unlocks[lesson]["games"][1] = StudentProgression.Status.Locked
unlocks[lesson]["games"][2] = StudentProgression.Status.Locked
elif index == StudentProgression.Status.Completed:
unlocks[lesson_number]["games"][0] = StudentProgression.Status.Unlocked
unlocks[lesson_number]["games"][1] = StudentProgression.Status.Unlocked
unlocks[lesson_number]["games"][2] = StudentProgression.Status.Unlocked
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][0] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][1] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][2] = StudentProgression.Status.LOCKED
elif index == StudentProgression.Status.COMPLETED:
unlocks[lesson_number]["games"][0] = StudentProgression.Status.UNLOCKED
unlocks[lesson_number]["games"][1] = StudentProgression.Status.UNLOCKED
unlocks[lesson_number]["games"][2] = StudentProgression.Status.UNLOCKED
for lesson: int in unlocks.keys():
if lesson < lesson_number:
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.Completed
unlocks[lesson]["games"][0] = StudentProgression.Status.Completed
unlocks[lesson]["games"][1] = StudentProgression.Status.Completed
unlocks[lesson]["games"][2] = StudentProgression.Status.Completed
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.COMPLETED
unlocks[lesson]["games"][0] = StudentProgression.Status.COMPLETED
unlocks[lesson]["games"][1] = StudentProgression.Status.COMPLETED
unlocks[lesson]["games"][2] = StudentProgression.Status.COMPLETED
elif lesson > lesson_number:
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.Locked
unlocks[lesson]["games"][0] = StudentProgression.Status.Locked
unlocks[lesson]["games"][1] = StudentProgression.Status.Locked
unlocks[lesson]["games"][2] = StudentProgression.Status.Locked
unlocks[lesson]["look_and_learn"] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][0] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][1] = StudentProgression.Status.LOCKED
unlocks[lesson]["games"][2] = StudentProgression.Status.LOCKED
unlocks_changed.emit()
+1 -1
View File
@@ -90,7 +90,7 @@ func _on_back_button_pressed() -> void:
func _get_highest_unlocked_lesson() -> int:
var highest_unlocked_lesson: int = 0
for lesson_number: int in progression.unlocks.keys():
if progression.unlocks[lesson_number]["look_and_learn"] >= StudentProgression.Status.Unlocked:
if progression.unlocks[lesson_number]["look_and_learn"] >= StudentProgression.Status.UNLOCKED:
highest_unlocked_lesson = max(highest_unlocked_lesson, lesson_number)
return highest_unlocked_lesson
+44 -30
View File
@@ -2,18 +2,32 @@ class_name Minigame
extends Control
enum Type {
jellyfish,
crabs,
parakeets,
monkey,
caterpillar,
frog,
turtles,
ants,
penguin,
fish
JELLYFISH,
CRABS,
PARAKEETS,
MONKEY,
CATERPILLAR,
FROG,
TURTLES,
ANTS,
PENGUIN,
FISH,
}
# String names used for file paths, database keys, and speech lookups.
# Kept separate from enum member names so renaming members doesn't affect runtime behaviour.
const TYPE_NAMES: Array[String] = [
"jellyfish",
"crabs",
"parakeets",
"monkey",
"caterpillar",
"frog",
"turtles",
"ants",
"penguin",
"fish",
]
const WIN_SOUND_FX: AudioStreamMP3 = preload("res://assets/sfx/sfx_game_over_win.mp3")
const LOSE_SOUND_FX: AudioStreamMP3 = preload("res://assets/sfx/sfx_game_over_lose.mp3")
const LABEL_COLOR_NEUTRAL: Color = Color("#e6f3e0")
@@ -59,7 +73,7 @@ var current_lives: int = 0:
var previous_lives: int = current_lives
current_lives = value
if current_lives != previous_lives:
Log.trace("BaseMinigame: Lives changed from %d to %d (max %d) for %s" % [previous_lives, current_lives, max_number_of_lives, Type.keys()[minigame_name]])
Log.trace("BaseMinigame: Lives changed from %d to %d (max %d) for %s" % [previous_lives, current_lives, max_number_of_lives, TYPE_NAMES[minigame_name]])
if current_lives < previous_lives:
consecutive_errors += previous_lives - current_lives
if current_lives <= max_number_of_lives - errors_before_help_speech:
@@ -104,11 +118,11 @@ func _ready() -> void:
# Difficulty
if (UserDataManager as UserDataManagerClass)._student_difficulty:
difficulty = UserDataManager.get_difficulty_for_minigame(Type.keys()[minigame_name] as String)
difficulty = UserDataManager.get_difficulty_for_minigame(TYPE_NAMES[minigame_name] as String)
intro_kalulu_speech = Database.load_external_sound(Database.get_kalulu_speech_path(Type.keys()[minigame_name] as String, "intro"))
help_kalulu_speech = Database.load_external_sound(Database.get_kalulu_speech_path(Type.keys()[minigame_name] as String, "help"))
win_kalulu_speech = Database.load_external_sound(Database.get_kalulu_speech_path(Type.keys()[minigame_name] as String, "end"))
intro_kalulu_speech = Database.load_external_sound(Database.get_kalulu_speech_path(TYPE_NAMES[minigame_name] as String, "intro"))
help_kalulu_speech = Database.load_external_sound(Database.get_kalulu_speech_path(TYPE_NAMES[minigame_name] as String, "help"))
win_kalulu_speech = Database.load_external_sound(Database.get_kalulu_speech_path(TYPE_NAMES[minigame_name] as String, "end"))
lose_kalulu_speech = Database.load_external_sound(Database.get_kalulu_speech_path("minigame", "lose"))
if not Engine.is_editor_hint():
@@ -125,7 +139,7 @@ func _initialize() -> void:
_setup_minigame()
Log.info("BaseMinigame: Initialize %s (lesson %d, minigame #%d, difficulty %d)" % [Type.keys()[minigame_name], lesson_nb, minigame_number, difficulty])
Log.info("BaseMinigame: Initialize %s (lesson %d, minigame #%d, difficulty %d)" % [TYPE_NAMES[minigame_name], lesson_nb, minigame_number, difficulty])
if not Engine.is_editor_hint():
await _curtains_and_kalulu()
@@ -151,10 +165,10 @@ func _curtains_and_kalulu() -> void:
await (OpeningCurtain as OpeningCurtainClass).open()
# Checks if intro needs to be played
if not UserDataManager.is_speech_played(Type.keys()[minigame_name] as String):
if not UserDataManager.is_speech_played(TYPE_NAMES[minigame_name] as String):
minigame_ui.play_kalulu_speech(intro_kalulu_speech)
await minigame_ui.kalulu_speech_ended
UserDataManager.mark_speech_as_played(Type.keys()[minigame_name] as String)
UserDataManager.mark_speech_as_played(TYPE_NAMES[minigame_name] as String)
#endregion
#region Timer
@@ -166,7 +180,7 @@ var _is_paused: bool = false
# Launch the minigame
func _start() -> void:
Log.info("BaseMinigame: Start minigame=%s lesson=%d difficulty=%d" % [Type.keys()[minigame_name], lesson_nb, difficulty])
Log.info("BaseMinigame: Start minigame=%s lesson=%d difficulty=%d" % [TYPE_NAMES[minigame_name], lesson_nb, difficulty])
_start_time = Time.get_ticks_msec() / 1000.0
_elapsed_paused = 0.0
_is_paused = false
@@ -218,13 +232,13 @@ func _win() -> void:
update_scores()
Log.info("BaseMinigame: %s won in %d seconds with progression %d/%d and %d/%d lives" % [Type.keys()[minigame_name], _get_elapsed_time_seconds(), current_progression, max_progression, current_lives, max_number_of_lives])
Log.info("BaseMinigame: %s won in %d seconds with progression %d/%d and %d/%d lives" % [TYPE_NAMES[minigame_name], _get_elapsed_time_seconds(), current_progression, max_progression, current_lives, max_number_of_lives])
# Difficulty
if current_lives <= 0:
UserDataManager.update_difficulty_for_minigame(Type.keys()[minigame_name] as String, false)
UserDataManager.update_difficulty_for_minigame(TYPE_NAMES[minigame_name] as String, false)
else:
UserDataManager.update_difficulty_for_minigame(Type.keys()[minigame_name] as String, true)
UserDataManager.update_difficulty_for_minigame(TYPE_NAMES[minigame_name] as String, true)
audio_player.stream = WIN_SOUND_FX
audio_player.play()
@@ -263,10 +277,10 @@ func _lose() -> void:
update_scores()
Log.info("BaseMinigame: %s Lose in %d seconds with progression %d/%d and %d/%d lives" % [Type.keys()[minigame_name], _get_elapsed_time_seconds(), current_progression, max_progression, current_lives, max_number_of_lives])
Log.info("BaseMinigame: %s Lose in %d seconds with progression %d/%d and %d/%d lives" % [TYPE_NAMES[minigame_name], _get_elapsed_time_seconds(), current_progression, max_progression, current_lives, max_number_of_lives])
# Difficulty
UserDataManager.update_difficulty_for_minigame(Type.keys()[minigame_name] as String, false)
UserDataManager.update_difficulty_for_minigame(TYPE_NAMES[minigame_name] as String, false)
audio_player.stream = LOSE_SOUND_FX
audio_player.play()
@@ -280,7 +294,7 @@ func _lose() -> void:
if has_method("show_adult_block"):
call("show_adult_block")
else:
Log.error("BaseMinigame: Adult block requested but no handler exists for %s" % Type.keys()[minigame_name])
Log.error("BaseMinigame: Adult block requested but no handler exists for %s" % TYPE_NAMES[minigame_name])
return
_reset()
@@ -303,8 +317,8 @@ func _save_logs() -> void:
var logs_size: int = -1
if logs.has("answers") and logs.get("answers", []) is Array:
logs_size = (logs.get("answers", []) as Array).size()
Log.info("BaseMinigame: Saving logs for %s with %d answer(s)" % [Type.keys()[minigame_name], logs_size])
LessonLogger.save_logs(logs, UserDataManager.get_student_folder(), Type.keys()[minigame_name] as String, lesson_nb, Time.get_time_string_from_system())
Log.info("BaseMinigame: Saving logs for %s with %d answer(s)" % [TYPE_NAMES[minigame_name], logs_size])
LessonLogger.save_logs(logs, UserDataManager.get_student_folder(), TYPE_NAMES[minigame_name] as String, lesson_nb, Time.get_time_string_from_system())
_reset_logs()
@@ -317,7 +331,7 @@ func _log_new_response(response: Dictionary, current_stimulus: Dictionary) -> vo
"reponse": response,
"awaited_response": current_stimulus,
"is_right": response == current_stimulus,
"minigame": Type.keys()[minigame_name],
"minigame": TYPE_NAMES[minigame_name],
"number_of_hints": current_number_of_hints,
"current_progression": current_progression,
"max_progression": max_progression,
@@ -325,7 +339,7 @@ func _log_new_response(response: Dictionary, current_stimulus: Dictionary) -> vo
"max_number_of_lives": max_number_of_lives,
}
Log.trace("BaseMinigame: Log new response minigame=%s response=%s expected=%s right=%s progression=%d/%d lives=%d/%d" % [
Type.keys()[minigame_name],
TYPE_NAMES[minigame_name],
str(response),
str(current_stimulus),
str(response_log.is_right),
@@ -437,7 +451,7 @@ func _play_kalulu_help_speech() -> void:
func set_current_progression(p_current_progression: int) -> void:
var previous_progression: int = current_progression
current_progression = p_current_progression
Log.trace("BaseMinigame: Progression changed from %d to %d/%d for %s" % [previous_progression, current_progression, max_progression, Type.keys()[minigame_name]])
Log.trace("BaseMinigame: Progression changed from %d to %d/%d for %s" % [previous_progression, current_progression, max_progression, TYPE_NAMES[minigame_name]])
consecutive_errors = 0
is_highlighting = false
+6 -6
View File
@@ -65,7 +65,7 @@ func _ready() -> void:
default_label_background_color = texture_rect_text_box.self_modulate
# Skips the whole tutorial
if UserDataManager.is_speech_played(Type.keys()[minigame_name] as String):
if UserDataManager.is_speech_played(TYPE_NAMES[minigame_name]):
tutorial_count = 2
@@ -158,7 +158,7 @@ func _present_next_word() -> void:
if _is_boss_session():
_boss_answer_start_ms = Time.get_ticks_msec()
if tutorial_count == 0:
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(Type.keys()[minigame_name] as String, "intro_test_game_first_word"))
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(TYPE_NAMES[minigame_name], "intro_test_game_first_word"))
minigame_ui.play_kalulu_speech(speech)
await minigame_ui.kalulu_speech_ended
@@ -224,12 +224,12 @@ func _on_answer_dropped(is_answered_real: bool) -> void:
words_to_present.pop_front()
await _play_correct_answer_animation(target_button)
if tutorial_count == 0:
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(Type.keys()[minigame_name] as String, "win_test_game_first_word"))
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(TYPE_NAMES[minigame_name], "win_test_game_first_word"))
minigame_ui.play_kalulu_speech(speech)
await minigame_ui.kalulu_speech_ended
tutorial_count += 1
elif tutorial_count == 1:
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(Type.keys()[minigame_name] as String, "win_test_game_second_word"))
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(TYPE_NAMES[minigame_name], "win_test_game_second_word"))
minigame_ui.play_kalulu_speech(speech)
await minigame_ui.kalulu_speech_ended
tutorial_count += 1
@@ -245,12 +245,12 @@ func _on_answer_dropped(is_answered_real: bool) -> void:
wrong_fx.play()
words_to_present_next.append(words_to_present.pop_front())
if tutorial_count == 0:
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(Type.keys()[minigame_name] as String, "lose_test_game_first_word"))
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(TYPE_NAMES[minigame_name], "lose_test_game_first_word"))
minigame_ui.play_kalulu_speech(speech)
await minigame_ui.kalulu_speech_ended
tutorial_count += 1
elif tutorial_count == 1:
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(Type.keys()[minigame_name] as String, "lose_test_game_second_word"))
var speech: AudioStreamMP3 = Database.load_external_sound(Database.get_kalulu_speech_path(TYPE_NAMES[minigame_name], "lose_test_game_second_word"))
minigame_ui.play_kalulu_speech(speech)
await minigame_ui.kalulu_speech_ended
tutorial_count += 1
+1 -1
View File
@@ -162,7 +162,7 @@ func _on_current_progression_changed() -> void:
func set_current_progression(p_current_progression: int) -> void:
var previous_progression: int = current_progression
current_progression = p_current_progression
Log.debug("BaseMinigame: Progression changed from %d to %d/%d for %s" % [previous_progression, current_progression, max_progression, Type.keys()[minigame_name]])
Log.debug("BaseMinigame: Progression changed from %d to %d/%d for %s" % [previous_progression, current_progression, max_progression, TYPE_NAMES[minigame_name]])
consecutive_errors = 0
is_highlighting = false
+6 -6
View File
@@ -4,8 +4,8 @@ extends Control
signal pressed(stimulus: Dictionary)
enum Colors {
Blue,
Pink,
BLUE,
PINK,
}
const ANIMATIONS_BODY: Array[SpriteFrames] = [
@@ -28,7 +28,7 @@ const SCALE_FACTOR: float = 0.2
if is_node_ready():
_apply_visuals()
var _color: int = Colors.Blue
var _color: int = Colors.BLUE
var color: int:
get: return _color
set(value):
@@ -62,7 +62,7 @@ func _ready() -> void:
return
var rand: float = randf()
color = Colors.Blue if rand < 0.7 else Colors.Pink
color = Colors.BLUE if rand < 0.7 else Colors.PINK
var rand_frame: int = randi_range(0, animated_sprite_body.sprite_frames.get_frame_count("idle") - 1)
animated_sprite_body.frame = rand_frame
animated_sprite_arms.frame = rand_frame
@@ -71,7 +71,7 @@ func _ready() -> void:
func _apply_visuals() -> void:
if boss:
animated_sprite_body.sprite_frames = ANIMATIONS_BODY[Colors.Pink]
animated_sprite_body.sprite_frames = ANIMATIONS_BODY[Colors.PINK]
animated_sprite_arms.hide()
return
else:
@@ -147,7 +147,7 @@ func delete() -> void:
func idle_boss() -> void:
text_box_sprite_2d.hide()
color = Colors.Pink
color = Colors.PINK
scale = Vector2(0.45, 0.45)
animated_sprite_body.stop()
animated_sprite_arms.stop()
@@ -1,9 +1,9 @@
extends WordsMinigame
enum Audio {
SendToKing,
SendToPlank,
SendToMonkey,
SEND_TO_KING,
SEND_TO_PLANK,
SEND_TO_MONKEY,
}
const MONKEY_SCENE: PackedScene = preload("res://sources/minigames/monkeys/monkey.tscn")
@@ -123,7 +123,7 @@ func _get_coconut_from_monkey_to_king(monkey: Monkey) -> Node2D:
await monkey.play("start_throw")
monkey.play("finish_throw")
audio_player.stream = AUDIO_STREAMS[Audio.SendToKing]
audio_player.stream = AUDIO_STREAMS[Audio.SEND_TO_KING]
audio_player.play()
var coconut: Coconut = monkey.coconut.duplicate()
@@ -167,7 +167,7 @@ func _on_coconut_thrown(monkey: Monkey) -> void:
if _is_gp_right(monkey.stimulus):
await king.play("start_right")
audio_player.stream = AUDIO_STREAMS[Audio.SendToPlank]
audio_player.stream = AUDIO_STREAMS[Audio.SEND_TO_PLANK]
audio_player.play()
king.play("finish_right")
var tween: Tween = create_tween()
@@ -179,7 +179,7 @@ func _on_coconut_thrown(monkey: Monkey) -> void:
current_word_progression += 1
else:
await king.play("start_wrong")
audio_player.stream = AUDIO_STREAMS[Audio.SendToMonkey]
audio_player.stream = AUDIO_STREAMS[Audio.SEND_TO_MONKEY]
audio_player.play()
king.play("finish_wrong")
var tween: Tween = create_tween()
+5 -5
View File
@@ -4,9 +4,9 @@ extends Node2D
signal pressed()
enum Colors {
Red,
Green,
Yellow,
RED,
GREEN,
YELLOW,
}
const ANIMATIONS: Array[SpriteFrames] = [
@@ -21,7 +21,7 @@ const FEATHERS_ANIMATIONS: Array[SpriteFrames] = [
]
@export var sad_duration: float = 2.0
@export var color: Colors = Colors.Red:
@export var color: Colors = Colors.RED:
set(value):
color = value
if animated_sprite:
@@ -141,7 +141,7 @@ func wrong() -> void:
func idle_boss() -> void:
text_box_sprite_2d.hide()
color = Colors.Green
color = Colors.GREEN
animated_sprite.play("idle_front")
animated_sprite.stop()
@@ -1,16 +1,16 @@
extends Minigame
enum State {
Locked,
Idle,
Selected1,
Selected2,
LOCKED,
IDLE,
SELECTED_1,
SELECTED_2,
}
enum Audio {
Fly,
Happy,
Turn,
Win,
FLY,
HAPPY,
TURN,
WIN,
}
const AUDIO_STREAMS: Array[AudioStreamMP3] = [
@@ -32,7 +32,7 @@ const PARAKEET_SCENE: PackedScene = preload("res://sources/minigames/parakeets/p
var parakeets: Array[Parakeet] = []
var selected: Array[Parakeet] = []
var state: State = State.Locked
var state: State = State.LOCKED
@onready var branches: Node2D = $GameRoot/TreeTrunk/Branches
@onready var possible_start_positions_parent: Control = $GameRoot/FlyFrom
@@ -114,30 +114,30 @@ func _start() -> void:
func _on_parakeet_pressed(parakeet: Parakeet) -> void:
match state:
State.Selected2, State.Locked:
State.SELECTED_2, State.LOCKED:
return
State.Selected1:
state = State.Locked
State.SELECTED_1:
state = State.LOCKED
if parakeet in selected:
selected.erase(parakeet)
await _turn(parakeet, true)
state = State.Idle
state = State.IDLE
else:
selected.append(parakeet)
await _turn(parakeet, false)
state = State.Selected2
state = State.SELECTED_2
_log_new_response({"pair": [selected[0].stimulus, selected[1].stimulus]}, {"pair": [selected[0].stimulus, selected[0].stimulus]})
if selected[0].stimulus.Grapheme == selected[1].stimulus.Grapheme:
_correct()
else:
_wrong()
State.Idle:
state = State.Locked
State.IDLE:
state = State.LOCKED
selected.append(parakeet)
await _turn(parakeet, false)
state = State.Selected1
state = State.SELECTED_1
func _correct() -> void:
@@ -151,7 +151,7 @@ func _correct() -> void:
await _fly_to(nest_positions)
await _make_selected_coo()
_fly_to(fly_away_positions)
state = State.Idle
state = State.IDLE
selected.clear()
@@ -183,14 +183,14 @@ func _present_parakeets() -> void:
for parakeet: Parakeet in parakeets:
coroutine.add_future(_turn.bind(parakeet, true))
await coroutine.join_all()
state = State.Idle
state = State.IDLE
func _make_selected_happy() -> void:
for parakeet: Parakeet in selected:
parakeet.right()
parakeet.happy()
audio_player.stream = AUDIO_STREAMS[Audio.Happy]
audio_player.stream = AUDIO_STREAMS[Audio.HAPPY]
audio_player.play()
await audio_player.finished
@@ -206,7 +206,7 @@ func _make_selected_sad() -> void:
func _make_selected_coo() -> void:
for parakeet: Parakeet in selected:
parakeet.idle()
audio_player.stream = AUDIO_STREAMS[Audio.Win]
audio_player.stream = AUDIO_STREAMS[Audio.WIN]
audio_player.play()
await audio_player.finished
@@ -216,7 +216,7 @@ func _fly_to(targets: Array[Vector2]) -> void:
parent.move_child(selected[0], parent.get_child_count() - 1)
parent.move_child(selected[1], parent.get_child_count() - 1)
var coroutine: Coroutine = Coroutine.new()
audio_player.stream = AUDIO_STREAMS[Audio.Fly]
audio_player.stream = AUDIO_STREAMS[Audio.FLY]
audio_player.play()
coroutine.add_future(audio_player.finished)
coroutine.add_future(selected[0].fly_to.bind(targets[0], fly_duration))
@@ -226,7 +226,7 @@ func _fly_to(targets: Array[Vector2]) -> void:
func _turn(parakeet: Parakeet, to_back: bool) -> void:
if not audio_player.playing:
audio_player.stream = AUDIO_STREAMS[Audio.Turn]
audio_player.stream = AUDIO_STREAMS[Audio.TURN]
audio_player.play()
if to_back:
await parakeet.turn_to_back()
@@ -237,7 +237,7 @@ func _turn(parakeet: Parakeet, to_back: bool) -> void:
func _flying_arrival(to: Array[Vector2]) -> void:
assert(parakeets.size() <= to.size(), "Some parakeets don't have a destination")
var coroutine: Coroutine = Coroutine.new()
audio_player.stream = AUDIO_STREAMS[Audio.Fly]
audio_player.stream = AUDIO_STREAMS[Audio.FLY]
audio_player.play()
coroutine.add_future(audio_player.finished)
for index: int in range(parakeets.size()):
+4 -4
View File
@@ -5,9 +5,9 @@ signal pressed(gp: Dictionary)
signal animation_changed(position: Vector2)
enum Colors {
Green,
Khaki,
Purple,
GREEN,
KHAKI,
PURPLE,
}
const ANIMATIONS: Array[SpriteFrames] = [
@@ -18,7 +18,7 @@ const ANIMATIONS: Array[SpriteFrames] = [
const TURTLE_BACK_RIGHT: CompressedTexture2D = preload("res://assets/minigames/turtles/graphic/turtle_back_right.png")
const TURTLE_BACK_WRONG: CompressedTexture2D = preload("res://assets/minigames/turtles/graphic/turtle_back_wrong.png")
@export var color: Colors = Colors.Purple:
@export var color: Colors = Colors.PURPLE:
set(value):
color = value
if sprite:
+3 -3
View File
@@ -2,8 +2,8 @@ class_name MusicManagerClass
extends Node
enum Track {
Title,
Garden
TITLE,
GARDEN
}
const TRACKS: Array = [
@@ -16,7 +16,7 @@ const TRACKS: Array = [
func _ready() -> void:
Log.trace("MusicManager: Ready - starting title track")
play(Track.Title)
play(Track.TITLE)
func _on_music_player_finished() -> void:
@@ -2,11 +2,11 @@ class_name UserDatabaseSynchronizer
extends Node
enum UpdateNeeded {
Nothing,
FromLocal,
FromServer,
DeleteLocal,
DeleteServer
NOTHING,
FROM_LOCAL,
FROM_SERVER,
DELETE_LOCAL,
DELETE_SERVER
}
var synchronizing: bool = false
@@ -62,13 +62,13 @@ func _determine_user_update(response_body: Dictionary) -> UpdateNeeded:
Log.trace("UserDatabaseSynchronizer: Cannot get user from body. Canceling synchronization.")
set_loading_bar_text("SYNCHRONIZATION_ERROR_NO_BODY_FROM_SERVER")
stop_sync()
return UpdateNeeded.Nothing
return UpdateNeeded.NOTHING
var user: Dictionary = response_body.user
if not user.has("last_modified"):
Log.trace("UserDatabaseSynchronizer: Cannot get last_modified from user. Canceling synchronization.")
set_loading_bar_text("SYNCHRONIZATION_ERROR")
stop_sync()
return UpdateNeeded.Nothing
return UpdateNeeded.NOTHING
var server_unix_time_user: int = Time.get_unix_time_from_datetime_string(user.last_modified as String)
var local_user_string_time: String = UserDataManager.teacher_settings.last_modified
var local_unix_time_user: int = 0
@@ -79,10 +79,10 @@ func _determine_user_update(response_body: Dictionary) -> UpdateNeeded:
func _compute_update_needed(local_unix_time: int, server_unix_time: int) -> UpdateNeeded:
if local_unix_time == server_unix_time:
return UpdateNeeded.Nothing
return UpdateNeeded.NOTHING
if local_unix_time > server_unix_time:
return UpdateNeeded.FromLocal
return UpdateNeeded.FromServer
return UpdateNeeded.FROM_LOCAL
return UpdateNeeded.FROM_SERVER
func _determine_students_update(response_body: Dictionary, need_update_user: UpdateNeeded) -> Dictionary:
@@ -150,7 +150,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
# Synchronize student data
var local_student_unix_time: int = Time.get_unix_time_from_datetime_string(student_data.last_modified)
student_updates["data"] = _compute_update_needed(local_student_unix_time, server_student_unix_time)
if student_updates["data"] == UpdateNeeded.Nothing:
if student_updates["data"] == UpdateNeeded.NOTHING:
Log.trace("UserDatabaseSynchronizer: Student %d data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
# Synchronize student progression
@@ -162,7 +162,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
return {}
var local_student_progression_unix_time: int = Time.get_unix_time_from_datetime_string(student_progression.last_modified)
student_updates["progression"] = _compute_update_needed(local_student_progression_unix_time, server_student_progression_unix_time)
if student_updates["progression"] == UpdateNeeded.Nothing:
if student_updates["progression"] == UpdateNeeded.NOTHING:
Log.trace("UserDatabaseSynchronizer: Student %d progression data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
# Synchronize student remediation
@@ -170,17 +170,17 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
if student_remediation != null:
var local_student_gp_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.gp_last_modified)
student_updates["remediation_gp"] = _compute_update_needed(local_student_gp_remediation_unix_time, server_student_remediation_gp_unix_time)
if student_updates["remediation_gp"] == UpdateNeeded.Nothing:
if student_updates["remediation_gp"] == UpdateNeeded.NOTHING:
Log.trace("UserDatabaseSynchronizer: Student %d GP remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
var local_student_syllables_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.syllables_last_modified)
student_updates["remediation_syllables"] = _compute_update_needed(local_student_syllables_remediation_unix_time, server_student_remediation_syllables_unix_time)
if student_updates["remediation_syllables"] == UpdateNeeded.Nothing:
if student_updates["remediation_syllables"] == UpdateNeeded.NOTHING:
Log.trace("UserDatabaseSynchronizer: Student %d syllables remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
var local_student_words_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.words_last_modified)
student_updates["remediation_words"] = _compute_update_needed(local_student_words_remediation_unix_time, server_student_remediation_words_unix_time)
if student_updates["remediation_words"] == UpdateNeeded.Nothing:
if student_updates["remediation_words"] == UpdateNeeded.NOTHING:
Log.trace("UserDatabaseSynchronizer: Student %d words remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
# Synchronize student confusion matrix
@@ -188,20 +188,20 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
if student_confusion_matrix != null:
var local_student_gp_confusion_matrix_unix_time: int = Time.get_unix_time_from_datetime_string(student_confusion_matrix.gp_last_modified)
student_updates["confusion_matrix_gp"] = _compute_update_needed(local_student_gp_confusion_matrix_unix_time, server_student_confusion_matrix_gp_unix_time)
if student_updates["confusion_matrix_gp"] == UpdateNeeded.Nothing:
if student_updates["confusion_matrix_gp"] == UpdateNeeded.NOTHING:
Log.trace("UserDatabaseSynchronizer: Student %d GP confusion matrix data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
else:
if server_student_confusion_matrix_gp_unix_time > 0:
student_updates["confusion_matrix_gp"] = UpdateNeeded.FromServer
student_updates["confusion_matrix_gp"] = UpdateNeeded.FROM_SERVER
break
if found:
break
if not found:
if need_update_user == UpdateNeeded.FromServer:
need_update_students[code_to_check]["data"] = UpdateNeeded.FromServer
elif need_update_user == UpdateNeeded.FromLocal:
need_update_students[code_to_check]["data"] = UpdateNeeded.DeleteServer
if need_update_user == UpdateNeeded.FROM_SERVER:
need_update_students[code_to_check]["data"] = UpdateNeeded.FROM_SERVER
elif need_update_user == UpdateNeeded.FROM_LOCAL:
need_update_students[code_to_check]["data"] = UpdateNeeded.DELETE_SERVER
else:
Log.warn("UserDatabaseSynchronizer: Student %d not found in local, but user doesn't need to be updated...this is theoretically not possible" % code_to_check)
@@ -209,12 +209,12 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
var students_in_device: Array[StudentData] = UserDataManager.teacher_settings.students[device]
for student_data: StudentData in students_in_device:
if not need_update_students.has(student_data.code):
if need_update_user == UpdateNeeded.FromServer:
if need_update_user == UpdateNeeded.FROM_SERVER:
need_update_students[student_data.code] = {}
need_update_students[student_data.code]["data"] = UpdateNeeded.DeleteLocal
elif need_update_user == UpdateNeeded.FromLocal:
need_update_students[student_data.code]["data"] = UpdateNeeded.DELETE_LOCAL
elif need_update_user == UpdateNeeded.FROM_LOCAL:
need_update_students[student_data.code] = {}
need_update_students[student_data.code]["data"] = UpdateNeeded.FromLocal
need_update_students[student_data.code]["data"] = UpdateNeeded.FROM_LOCAL
else:
Log.warn("UserDatabaseSynchronizer: Student %d not found in server, but user doesn't need to be updated...this is theoretically not possible" % student_data.code)
return need_update_students
@@ -223,13 +223,13 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
func _build_message_to_server(need_update_user: UpdateNeeded, need_update_students: Dictionary[int, Dictionary]) -> Dictionary:
var message_to_server: Dictionary = {}
if need_update_user == UpdateNeeded.FromLocal:
if need_update_user == UpdateNeeded.FROM_LOCAL:
message_to_server["user"] = {
"account_type": UserDataManager.teacher_settings.account_type,
"education_method": UserDataManager.teacher_settings.education_method,
"last_modified": UserDataManager.teacher_settings.last_modified
}
elif need_update_user == UpdateNeeded.FromServer:
elif need_update_user == UpdateNeeded.FROM_SERVER:
message_to_server["user"] = {"need_update": true}
message_to_server["students"] = {}
@@ -241,14 +241,14 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
if student_entry.has("data"):
var student_update: UpdateNeeded = student_entry["data"]
if student_update == UpdateNeeded.DeleteLocal:
if student_update == UpdateNeeded.DELETE_LOCAL:
UserDataManager.delete_student(student_code)
continue
elif student_update == UpdateNeeded.DeleteServer:
elif student_update == UpdateNeeded.DELETE_SERVER:
student_block["delete"] = true
elif student_update == UpdateNeeded.FromLocal:
elif student_update == UpdateNeeded.FROM_LOCAL:
var device_id: int = UserDataManager.teacher_settings.get_student_device(student_code)
if device_id == -1:
Log.error("UserDatabaseSynchronizer: Student code %s has no device ID" % student_code)
@@ -264,7 +264,7 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
"updated_at": student_data.last_modified
})
elif student_update == UpdateNeeded.FromServer:
elif student_update == UpdateNeeded.FROM_SERVER:
student_block["need_update"] = true
var student_progression: StudentProgression = UserDataManager.get_student_progression_for_code(0, student_code)
@@ -272,16 +272,16 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
Log.trace("Cannot find progression data for student %s" % str(student_code))
elif student_entry.has("progression"):
var progression_block: Dictionary = {}
if student_entry.progression == UpdateNeeded.FromLocal:
if student_entry.progression == UpdateNeeded.FROM_LOCAL:
progression_block = {
"version": student_progression.version,
"unlocked": student_progression.unlocks,
"highest_boss_defeated": student_progression.highest_boss_defeated,
"updated_at": student_progression.last_modified
}
elif student_entry.progression == UpdateNeeded.FromServer:
elif student_entry.progression == UpdateNeeded.FROM_SERVER:
progression_block = {"need_update": true}
elif student_entry.progression == UpdateNeeded.DeleteServer:
elif student_entry.progression == UpdateNeeded.DELETE_SERVER:
progression_block = {"delete": true}
if progression_block.size() > 0:
@@ -290,14 +290,14 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
var student_remediation: UserRemediation = UserDataManager.get_student_remediation_data(student_code)
if student_entry.has("remediation_gp"):
var gp_remediation_block: Dictionary = {}
if student_entry.remediation_gp == UpdateNeeded.FromLocal:
if student_entry.remediation_gp == UpdateNeeded.FROM_LOCAL:
var tuple_list: Array = []
for key: int in student_remediation.gps_scores.keys():
tuple_list.append([key, student_remediation.gps_scores[key]])
gp_remediation_block = {"score_remediation": tuple_list, "updated_at": student_remediation.gp_last_modified}
elif student_entry.remediation_gp == UpdateNeeded.FromServer:
elif student_entry.remediation_gp == UpdateNeeded.FROM_SERVER:
gp_remediation_block = {"need_update": true}
elif student_entry.remediation_gp == UpdateNeeded.DeleteServer:
elif student_entry.remediation_gp == UpdateNeeded.DELETE_SERVER:
gp_remediation_block = {"delete": true}
if gp_remediation_block.size() > 0:
@@ -305,14 +305,14 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
if student_entry.has("remediation_syllables"):
var syllables_remediation_block: Dictionary = {}
if student_entry.remediation_syllables == UpdateNeeded.FromLocal:
if student_entry.remediation_syllables == UpdateNeeded.FROM_LOCAL:
var tuple_list: Array = []
for key: int in student_remediation.syllables_scores.keys():
tuple_list.append([key, student_remediation.syllables_scores[key]])
syllables_remediation_block = {"score_remediation": tuple_list, "updated_at": student_remediation.syllables_last_modified}
elif student_entry.remediation_syllables == UpdateNeeded.FromServer:
elif student_entry.remediation_syllables == UpdateNeeded.FROM_SERVER:
syllables_remediation_block = {"need_update": true}
elif student_entry.remediation_syllables == UpdateNeeded.DeleteServer:
elif student_entry.remediation_syllables == UpdateNeeded.DELETE_SERVER:
syllables_remediation_block = {"delete": true}
if syllables_remediation_block.size() > 0:
@@ -320,14 +320,14 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
if student_entry.has("remediation_words"):
var words_remediation_block: Dictionary = {}
if student_entry.remediation_words == UpdateNeeded.FromLocal:
if student_entry.remediation_words == UpdateNeeded.FROM_LOCAL:
var tuple_list: Array = []
for key: int in student_remediation.words_scores.keys():
tuple_list.append([key, student_remediation.words_scores[key]])
words_remediation_block = {"score_remediation": tuple_list, "updated_at": student_remediation.words_last_modified}
elif student_entry.remediation_words == UpdateNeeded.FromServer:
elif student_entry.remediation_words == UpdateNeeded.FROM_SERVER:
words_remediation_block = {"need_update": true}
elif student_entry.remediation_words == UpdateNeeded.DeleteServer:
elif student_entry.remediation_words == UpdateNeeded.DELETE_SERVER:
words_remediation_block = {"delete": true}
if words_remediation_block.size() > 0:
@@ -336,14 +336,14 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
var student_confusion_matrix: UserConfusionMatrix = UserDataManager.get_student_confusion_matrix_data(student_code)
if student_entry.has("confusion_matrix_gp"):
var gp_confusion_matrix_block: Dictionary = {}
if student_entry.confusion_matrix_gp == UpdateNeeded.FromLocal:
if student_entry.confusion_matrix_gp == UpdateNeeded.FROM_LOCAL:
var tuple_list: Array = []
for key: int in student_confusion_matrix.gp_scores.keys():
tuple_list.append([key, student_confusion_matrix.gp_scores[key]])
gp_confusion_matrix_block = {"confusion_matrix": tuple_list, "updated_at": student_confusion_matrix.gp_last_modified}
elif student_entry.confusion_matrix_gp == UpdateNeeded.FromServer:
elif student_entry.confusion_matrix_gp == UpdateNeeded.FROM_SERVER:
gp_confusion_matrix_block = {"need_update": true}
elif student_entry.confusion_matrix_gp == UpdateNeeded.DeleteServer:
elif student_entry.confusion_matrix_gp == UpdateNeeded.DELETE_SERVER:
gp_confusion_matrix_block = {"delete": true}
if gp_confusion_matrix_block.size() > 0:
@@ -474,7 +474,7 @@ func synchronize() -> void:
return
var need_update_user: UpdateNeeded = _determine_user_update(response_body)
if need_update_user == UpdateNeeded.Nothing:
if need_update_user == UpdateNeeded.NOTHING:
Log.trace("UserDatabaseSynchronizer: User data timestamp is the same in local and on server. No synchronization necessary")
if not synchronizing:
return
@@ -84,8 +84,8 @@ func test_full_account_creation_login_and_deletion() -> void:
gut.p("Step 2: Building registration payload…")
var register_data: TeacherSettings = TeacherSettings.new()
register_data.account_type = TeacherSettings.AccountType.Teacher
register_data.education_method = TeacherSettings.EducationMethod.Complete
register_data.account_type = TeacherSettings.AccountType.TEACHER
register_data.education_method = TeacherSettings.EducationMethod.COMPLETE
register_data.email = _test_email
register_data.password = TEST_PASSWORD
register_data.language = "fr_FR"
@@ -94,20 +94,20 @@ func test_full_account_creation_login_and_deletion() -> void:
var student_alice: StudentData = StudentData.new()
student_alice.code = 123
student_alice.name = "Alice"
student_alice.level = StudentData.Level.Beginner
student_alice.level = StudentData.Level.BEGINNER
student_alice.age = 7
var student_bob: StudentData = StudentData.new()
student_bob.code = 124
student_bob.name = "Bob"
student_bob.level = StudentData.Level.Reviewer
student_bob.level = StudentData.Level.REVIEWER
student_bob.age = 8
# Device 2 — one student
var student_charlie: StudentData = StudentData.new()
student_charlie.code = 321
student_charlie.name = "Charlie"
student_charlie.level = StudentData.Level.Adult
student_charlie.level = StudentData.Level.ADULT
student_charlie.age = 10
register_data.students[1] = [student_alice, student_bob]
@@ -166,9 +166,9 @@ func test_full_account_creation_login_and_deletion() -> void:
# --- Basic fields ---
assert_eq(str(login_body.email), _test_email, "Returned email should match")
assert_eq(login_body.account_type as int, TeacherSettings.AccountType.Teacher,
assert_eq(login_body.account_type as int, TeacherSettings.AccountType.TEACHER,
"Account type should be Teacher (0)")
assert_eq(login_body.education_method as int, TeacherSettings.EducationMethod.Complete,
assert_eq(login_body.education_method as int, TeacherSettings.EducationMethod.COMPLETE,
"Education method should be Complete (1)")
assert_eq(str(login_body.language), "fr_FR", "Language should be 'fr'")
assert_true(login_body.has("token"), "Login response must include token")
@@ -198,13 +198,13 @@ func test_full_account_creation_login_and_deletion() -> void:
found_alice = true
assert_eq(str(student.name), "Alice", "Student 123 should be Alice")
assert_eq(student.age as int, 7, "Alice should be age 7")
assert_eq(student.level as int, StudentData.Level.Beginner,
assert_eq(student.level as int, StudentData.Level.BEGINNER,
"Alice should be Beginner (0)")
124:
found_bob = true
assert_eq(str(student.name), "Bob", "Student 124 should be Bob")
assert_eq(student.age as int, 8, "Bob should be age 8")
assert_eq(student.level as int, StudentData.Level.Reviewer,
assert_eq(student.level as int, StudentData.Level.REVIEWER,
"Bob should be Reviewer (1)")
assert_true(found_alice, "Alice (code 123) should be present on device 1")
assert_true(found_bob, "Bob (code 124) should be present on device 1")
@@ -215,7 +215,7 @@ func test_full_account_creation_login_and_deletion() -> void:
assert_eq(charlie.code as int, 321, "Device 2 student should have code 321")
assert_eq(str(charlie.name), "Charlie", "Student 321 should be Charlie")
assert_eq(charlie.age as int, 10, "Charlie should be age 10")
assert_eq(charlie.level as int, StudentData.Level.Adult,
assert_eq(charlie.level as int, StudentData.Level.ADULT,
"Charlie should be Adult (2)")
# ------------------------------------------------------------------
+3 -3
View File
@@ -3,14 +3,14 @@ extends GutTest
var default_student_data_dict: Dictionary = {
"code": 0,
"name": "",
"level": StudentData.Level.Beginner,
"level": StudentData.Level.BEGINNER,
"age": 0,
"last_modified": ""
}
var modified_student_data_dict: Dictionary = {
"code": 123,
"name": "Alice",
"level": StudentData.Level.Adult,
"level": StudentData.Level.ADULT,
"age": 7,
"last_modified": Time.get_datetime_string_from_unix_time(12345)
}
@@ -21,7 +21,7 @@ func test_to_dict() -> void:
assert_eq_deep(default_student.to_dict(), default_student_data_dict)
default_student.code = 123
default_student.name = "Alice"
default_student.level = StudentData.Level.Adult
default_student.level = StudentData.Level.ADULT
default_student.age = 7
default_student.last_modified = Time.get_datetime_string_from_unix_time(12345)
assert_eq_deep(default_student.to_dict(), modified_student_data_dict)