Upgrade godot from 4.4.1 to 4.5

This commit is contained in:
Adrien Ufferte
2025-09-18 15:26:44 +02:00
parent b7f9e6220e
commit ee35e352b6
49 changed files with 257 additions and 264 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
![Godot Version](https://img.shields.io/badge/Godot-4.4.1+-blue) ![Godot Version](https://img.shields.io/badge/Godot-4.5+-blue)
# 📖 Kalulu — Learn to Read, the Smart Way # 📖 Kalulu — Learn to Read, the Smart Way
@@ -43,7 +43,7 @@ func validate() -> bool:
continue continue
var control: Control = info.control as Control var control: Control = info.control as Control
if control == null: if control == null:
Logger.error("FormValidator: ValidatorInfo.control is not a Control: %s" % [info.control]) Log.error("FormValidator: ValidatorInfo.control is not a Control: %s" % [info.control])
continue continue
var passed = info.validator.validate(control) var passed = info.validator.validate(control)
var messages = info.validator.get_messages() var messages = info.validator.get_messages()
@@ -62,7 +62,7 @@ func _get_validator_info_list() -> Array[ValidatorInfo]:
for controlKey in _control_validator_map.keys(): for controlKey in _control_validator_map.keys():
var control: Control = controlKey as Control var control: Control = controlKey as Control
if control == null: if control == null:
Logger.error("FormValidator: _control_validator_map key is not a Control") Log.error("FormValidator: _control_validator_map key is not a Control")
continue continue
var validator = _control_validator_map[control] var validator = _control_validator_map[control]
if not validator: if not validator:
@@ -5,7 +5,7 @@ class_name ValidatorFunctions
static func matches(pattern: String, text: String) -> bool: static func matches(pattern: String, text: String) -> bool:
var regex = RegEx.create_from_string(pattern) var regex = RegEx.create_from_string(pattern)
if not regex.is_valid(): if not regex.is_valid():
Logger.error("ValidatorFunctions: Invalid RegEx pattern supplied to matches function: %s" % pattern) Log.error("ValidatorFunctions: Invalid RegEx pattern supplied to matches function: %s" % pattern)
return false return false
var result = regex.search(text) var result = regex.search(text)
return result != null and result.strings.size() > 0 return result != null and result.strings.size() > 0
@@ -14,7 +14,7 @@ static func matches(pattern: String, text: String) -> bool:
static func does_not_match(pattern: String, text: String) -> bool: static func does_not_match(pattern: String, text: String) -> bool:
var regex = RegEx.create_from_string(pattern) var regex = RegEx.create_from_string(pattern)
if not regex.is_valid(): if not regex.is_valid():
Logger.error("ValidatorFunctions: Invalid RegEx pattern supplied to does_not_match function: %s" % pattern) Log.error("ValidatorFunctions: Invalid RegEx pattern supplied to does_not_match function: %s" % pattern)
return false return false
var result = regex.search(text) var result = regex.search(text)
return result == null return result == null
+7 -7
View File
@@ -16,17 +16,17 @@ func guess_path_type(path: String) -> String:
func extract(zip_path: String, extract_path: String, extract_in_subfolder: bool = true) -> String: func extract(zip_path: String, extract_path: String, extract_in_subfolder: bool = true) -> String:
Logger.trace("FolderUnzipper: Extracting %s to %s" % [zip_path, extract_path]) Log.trace("FolderUnzipper: Extracting %s to %s" % [zip_path, extract_path])
var err: Error = open(zip_path) var err: Error = open(zip_path)
if err != OK: if err != OK:
Logger.error("FolderUnzipper: Error " + error_string(err) + " while opening file: %s" % zip_path) Log.error("FolderUnzipper: Error " + error_string(err) + " while opening file: %s" % zip_path)
close() close()
return "" return ""
var extract_folder: String = extract_path.path_join(zip_path.get_file().get_basename()) if extract_in_subfolder else extract_path var extract_folder: String = extract_path.path_join(zip_path.get_file().get_basename()) if extract_in_subfolder else extract_path
var all_files: PackedStringArray = get_files() var all_files: PackedStringArray = get_files()
file_count.emit(all_files.size()) file_count.emit(all_files.size())
Logger.trace("FolderUnzipper: %d files found" % all_files.size()) Log.trace("FolderUnzipper: %d files found" % all_files.size())
var copied_file: int = 0 var copied_file: int = 0
var first_folder: String = "" var first_folder: String = ""
@@ -42,21 +42,21 @@ func extract(zip_path: String, extract_path: String, extract_in_subfolder: bool
var file: FileAccess = FileAccess.open(file_name, FileAccess.WRITE) var file: FileAccess = FileAccess.open(file_name, FileAccess.WRITE)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("FolderUnzipper: Extract: Cannot open file %s. Error: %s" % [file_name, error_string(error)]) Log.error("FolderUnzipper: Extract: Cannot open file %s. Error: %s" % [file_name, error_string(error)])
close() close()
return first_folder return first_folder
if file == null: if file == null:
Logger.error("FolderUnzipper: Extract: Cannot open file %s. File is null" % file_name) Log.error("FolderUnzipper: Extract: Cannot open file %s. File is null" % file_name)
close() close()
return first_folder return first_folder
if file != null: if file != null:
file.store_buffer(read_file(sub_path)) file.store_buffer(read_file(sub_path))
file.close() file.close()
Logger.trace("FolderUnzipper: Copied %s" % file_name) Log.trace("FolderUnzipper: Copied %s" % file_name)
copied_file += 1 copied_file += 1
file_copied.emit(copied_file, file_name) file_copied.emit(copied_file, file_name)
close() close()
finished.emit() finished.emit()
Logger.trace("FolderUnzipper: Extraction finished in %s" % extract_folder) Log.trace("FolderUnzipper: Extraction finished in %s" % extract_folder)
return first_folder return first_folder
+6 -6
View File
@@ -23,7 +23,7 @@ func write_folder_recursive(abs_path: String, rel_path: String) -> Error:
close() close()
return error return error
else: else:
Logger.trace("FolderZipper: Adding %s" % current_rel_path) Log.trace("FolderZipper: Adding %s" % current_rel_path)
var error: Error = start_file(current_rel_path) var error: Error = start_file(current_rel_path)
if error != OK: if error != OK:
close() close()
@@ -32,7 +32,7 @@ func write_folder_recursive(abs_path: String, rel_path: String) -> Error:
var file: FileAccess = FileAccess.open(current_full_path, FileAccess.READ) var file: FileAccess = FileAccess.open(current_full_path, FileAccess.READ)
error = FileAccess.get_open_error() error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("FolderZipper: Extract: Cannot open file %s. Error: %s" % [current_full_path, error_string(error)]) Log.error("FolderZipper: Extract: Cannot open file %s. Error: %s" % [current_full_path, error_string(error)])
close() close()
return error return error
if file: if file:
@@ -50,15 +50,15 @@ func write_folder_recursive(abs_path: String, rel_path: String) -> Error:
func compress(path: String, output_name: String) -> void: func compress(path: String, output_name: String) -> void:
Logger.trace("FolderZipper: Compressing %s into %s" % [path, output_name]) Log.trace("FolderZipper: Compressing %s into %s" % [path, output_name])
var err: Error = open(output_name, ZIPPacker.APPEND_CREATE) var err: Error = open(output_name, ZIPPacker.APPEND_CREATE)
if err != OK: if err != OK:
Logger.error("FolderZipper: Error " + error_string(err) + " while opening archive: %s" % output_name) Log.error("FolderZipper: Error " + error_string(err) + " while opening archive: %s" % output_name)
close() close()
return return
path = path.simplify_path() path = path.simplify_path()
err = write_folder_recursive(path.get_base_dir(), path.get_file()) err = write_folder_recursive(path.get_base_dir(), path.get_file())
if err != OK: if err != OK:
Logger.error("FolderZipper: Error " + error_string(err) + " while compressing folder: %s" % path) Log.error("FolderZipper: Error " + error_string(err) + " while compressing folder: %s" % path)
close() close()
Logger.trace("FolderZipper: Compression completed -> %s" % output_name) Log.trace("FolderZipper: Compression completed -> %s" % output_name)
+2 -2
View File
@@ -13,7 +13,7 @@ config_version=5
config/name="Kalulu" config/name="Kalulu"
config/version="2.1.6" config/version="2.1.6"
run/main_scene="res://sources/menus/splash_screen/splash_screen.tscn" run/main_scene="res://sources/menus/splash_screen/splash_screen.tscn"
config/features=PackedStringArray("4.4", "Forward Plus") config/features=PackedStringArray("4.5", "Forward Plus")
boot_splash/bg_color=Color(0.141176, 0.141176, 0.141176, 1) boot_splash/bg_color=Color(0.141176, 0.141176, 0.141176, 1)
config/icon="res://assets/kalulu_icon.png" config/icon="res://assets/kalulu_icon.png"
custom/unlock_everything=false custom/unlock_everything=false
@@ -25,7 +25,7 @@ buses/default_bus_layout="res://resources/audio_buses/main_audio_bus_layout.tres
[autoload] [autoload]
Logger="*res://sources/utils/autoloads/logger.gd" Log="*res://sources/utils/autoloads/logger.gd"
LessonLogger="*res://sources/utils/autoloads/lesson_logger.gd" LessonLogger="*res://sources/utils/autoloads/lesson_logger.gd"
ServerManager="*res://sources/utils/autoloads/server_manager.tscn" ServerManager="*res://sources/utils/autoloads/server_manager.tscn"
Database="*res://sources/utils/autoloads/database.gd" Database="*res://sources/utils/autoloads/database.gd"
+7 -7
View File
@@ -61,11 +61,11 @@ func update_student_name(student_code: int, student_name: String) -> void:
for student_data: StudentData in device_students: for student_data: StudentData in device_students:
if student_data.code == student_code: if student_data.code == student_code:
student_data.name = student_name student_data.name = student_name
Logger.trace("TeacherSettings: Updated student code " + str(student_code) + ": new name is " + student_name) Log.trace("TeacherSettings: Updated student code " + str(student_code) + ": new name is " + student_name)
student_data.last_modified = Time.get_datetime_string_from_system(true) student_data.last_modified = Time.get_datetime_string_from_system(true)
UserDataManager.save_all() UserDataManager.save_all()
return return
Logger.warn("TeacherSettings: update_student_name: student not found with code " + str(student_code)) Log.warn("TeacherSettings: update_student_name: student not found with code " + str(student_code))
func update_student_device(student_code: int, new_student_device: int) -> void: func update_student_device(student_code: int, new_student_device: int) -> void:
@@ -74,18 +74,18 @@ func update_student_device(student_code: int, new_student_device: int) -> void:
for student_data: StudentData in students_data: for student_data: StudentData in students_data:
if student_data.code == student_code: if student_data.code == student_code:
if current_student_device == new_student_device: if current_student_device == new_student_device:
Logger.trace("TeacherSettings: update_student_device: student %d new device is already current student device, no update necessary" % student_code) Log.trace("TeacherSettings: update_student_device: student %d new device is already current student device, no update necessary" % student_code)
return return
students_data.erase(student_data) students_data.erase(student_data)
if not students.has(new_student_device): if not students.has(new_student_device):
Logger.warn("TeacherSettings: update_student_device: student %d new device does not exists, it should not be possible. Update will still work anyway." % student_code) Log.warn("TeacherSettings: update_student_device: student %d new device does not exists, it should not be possible. Update will still work anyway." % student_code)
students[new_student_device] = [] students[new_student_device] = []
students[new_student_device].append(student_data) students[new_student_device].append(student_data)
UserDataManager.move_user_device_folder(str(current_student_device), str(new_student_device), student_code) UserDataManager.move_user_device_folder(str(current_student_device), str(new_student_device), student_code)
student_data.last_modified = Time.get_datetime_string_from_system(true) student_data.last_modified = Time.get_datetime_string_from_system(true)
UserDataManager.save_all() UserDataManager.save_all()
return return
Logger.warn("TeacherSettings: update_student_device: student not found with code " + str(student_code)) Log.warn("TeacherSettings: update_student_device: student not found with code " + str(student_code))
func get_new_code() -> int: func get_new_code() -> int:
@@ -148,7 +148,7 @@ func delete_student(student_code: int) -> void:
if students[device].is_empty(): if students[device].is_empty():
students.erase(device) students.erase(device)
return return
Logger.warn("TeacherSettings: Trying to delete student, but code %d not found" % student_code) Log.warn("TeacherSettings: Trying to delete student, but code %d not found" % student_code)
func get_student_with_code(student_code: int) -> StudentData: func get_student_with_code(student_code: int) -> StudentData:
@@ -174,4 +174,4 @@ func set_data_student_with_code(student_code: int, new_device_id: int, new_name:
student_data.age = new_age student_data.age = new_age
student_data.last_modified = new_last_modified student_data.last_modified = new_last_modified
return return
Logger.error("TeacherSettings: Student %d not found to set data on it" % student_code) Log.error("TeacherSettings: Student %d not found to set data on it" % student_code)
+1 -1
View File
@@ -55,7 +55,7 @@ func get_gp_scores(id: int) -> PackedInt32Array:
func update_gp_scores(minigame_scores: Dictionary[int, PackedInt32Array]) -> void: func update_gp_scores(minigame_scores: Dictionary[int, PackedInt32Array]) -> void:
if not minigame_scores or minigame_scores.is_empty(): if not minigame_scores or minigame_scores.is_empty():
return return
Logger.trace("UserConfusionMatrix: Update GP scores: %s" % [str(minigame_scores)]) Log.trace("UserConfusionMatrix: Update GP scores: %s" % [str(minigame_scores)])
for expected_id: int in minigame_scores.keys(): for expected_id: int in minigame_scores.keys():
var given_list: PackedInt32Array = minigame_scores[expected_id] var given_list: PackedInt32Array = minigame_scores[expected_id]
append_and_trim(gp_scores, expected_id, given_list) append_and_trim(gp_scores, expected_id, given_list)
+3 -3
View File
@@ -33,7 +33,7 @@ func get_gp_score(id: int) -> int:
func update_gp_scores(minigame_scores: Dictionary) -> void: func update_gp_scores(minigame_scores: Dictionary) -> void:
if not minigame_scores: if not minigame_scores:
return return
Logger.trace("UserRemediation: Update GP Scores: " + str(minigame_scores)) Log.trace("UserRemediation: Update GP Scores: " + str(minigame_scores))
for id: int in minigame_scores.keys(): for id: int in minigame_scores.keys():
var new_gp_score: int = get_gp_score(id) var new_gp_score: int = get_gp_score(id)
new_gp_score += minigame_scores[id] new_gp_score += minigame_scores[id]
@@ -74,7 +74,7 @@ func get_syllable_score(id: int) -> int:
func update_syllables_scores(minigame_scores: Dictionary) -> void: func update_syllables_scores(minigame_scores: Dictionary) -> void:
if not minigame_scores: if not minigame_scores:
return return
Logger.trace("UserRemediation: Update Syllable Scores: " + str(minigame_scores)) Log.trace("UserRemediation: Update Syllable Scores: " + str(minigame_scores))
for id: int in minigame_scores.keys(): for id: int in minigame_scores.keys():
var new_syllable_score: int = get_syllable_score(id) var new_syllable_score: int = get_syllable_score(id)
new_syllable_score += minigame_scores[id] new_syllable_score += minigame_scores[id]
@@ -115,7 +115,7 @@ func get_word_score(id: int) -> int:
func update_words_scores(minigame_scores: Dictionary) -> void: func update_words_scores(minigame_scores: Dictionary) -> void:
if not minigame_scores: if not minigame_scores:
return return
Logger.trace("UserRemediation: Update Syllable Scores: " + str(minigame_scores)) Log.trace("UserRemediation: Update Syllable Scores: " + str(minigame_scores))
for id: int in minigame_scores.keys(): for id: int in minigame_scores.keys():
var new_word_score: int = get_word_score(id) var new_word_score: int = get_word_score(id)
new_word_score += minigame_scores[id] new_word_score += minigame_scores[id]
+2 -2
View File
@@ -228,7 +228,7 @@ func _ready() -> void:
if transition_data.has("current_garden_index"): if transition_data.has("current_garden_index"):
starting_garden = transition_data.current_garden_index starting_garden = transition_data.current_garden_index
else: else:
Logger.error("Gardens: initialisation: transition_data exists but does not contains the needed current_garden_index") Log.error("Gardens: initialisation: transition_data exists but does not contains the needed current_garden_index")
starting_garden = 0 starting_garden = 0
scroll_container.scroll_horizontal = GARDEN_SIZE * starting_garden scroll_container.scroll_horizontal = GARDEN_SIZE * starting_garden
@@ -378,7 +378,7 @@ func _ready() -> void:
static func compute_lessons_distribution(total_lessons: int, garden_layouts: Array[GardenLayout]) -> Array[int]: static func compute_lessons_distribution(total_lessons: int, garden_layouts: Array[GardenLayout]) -> Array[int]:
Logger.trace("Gardens: compute_lessons_distribution: total_lessons = %s, garden_layouts count = %s" % [str(total_lessons), str(garden_layouts.size())]) Log.trace("Gardens: compute_lessons_distribution: total_lessons = %s, garden_layouts count = %s" % [str(total_lessons), str(garden_layouts.size())])
var distribution: Array[int] = [] var distribution: Array[int] = []
var lessons_left: int = total_lessons var lessons_left: int = total_lessons
var gardens_left: int = garden_layouts.size() var gardens_left: int = garden_layouts.size()
+2 -2
View File
@@ -122,10 +122,10 @@ func _on_list_title_import_path_selected(path: String, match_to_file: bool) -> v
var file: FileAccess = FileAccess.open(path, FileAccess.READ) var file: FileAccess = FileAccess.open(path, FileAccess.READ)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("GPList: Cannot open file %s. Error: %s" % [path, error_string(error)]) Log.error("GPList: Cannot open file %s. Error: %s" % [path, error_string(error)])
return return
if file == null: if file == null:
Logger.error("GPList: Cannot open file %s. File is null" % path) Log.error("GPList: Cannot open file %s. File is null" % path)
return return
var line: PackedStringArray = file.get_csv_line() var line: PackedStringArray = file.get_csv_line()
if line.size() < 4 or line[0] != "Grapheme" or line[1] != "Phoneme" or line[2] != "Type" or line[3] != "Exception": if line.size() < 4 or line[0] != "Grapheme" or line[1] != "Phoneme" or line[2] != "Type" or line[3] != "Exception":
+1 -1
View File
@@ -108,7 +108,7 @@ func insert_in_database() -> void:
if not Database.db.query_result.is_empty(): if not Database.db.query_result.is_empty():
var element: Dictionary = Database.db.query_result[0] var element: Dictionary = Database.db.query_result[0]
if grapheme != element.Grapheme or phoneme != element.Phoneme or type != element.Type or exception != element.Exception: if grapheme != element.Grapheme or phoneme != element.Phoneme or type != element.Type or exception != element.Exception:
Logger.trace("GPListElement: UPDATING %s" % element.Grapheme) Log.trace("GPListElement: UPDATING %s" % element.Grapheme)
Database.db.update_rows("GPs", "ID=%s" % id, {Grapheme=grapheme, Phoneme=phoneme, Type=type, Exception=exception}) Database.db.update_rows("GPs", "ID=%s" % id, {Grapheme=grapheme, Phoneme=phoneme, Type=type, Exception=exception})
return return
@@ -51,10 +51,10 @@ func set_sound_preview(sound_path: String) -> void:
var file: FileAccess = FileAccess.open(sound_path, FileAccess.READ) var file: FileAccess = FileAccess.open(sound_path, FileAccess.READ)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("ImageAndSoundGPDescription: Cannot open file %s. Error: %s" % [sound_path, error_string(error)]) Log.error("ImageAndSoundGPDescription: Cannot open file %s. Error: %s" % [sound_path, error_string(error)])
return return
if file == null: if file == null:
Logger.error("ImageAndSoundGPDescription: Cannot open file %s. File is null" % sound_path) Log.error("ImageAndSoundGPDescription: Cannot open file %s. File is null" % sound_path)
return return
var sound: AudioStreamMP3 = AudioStreamMP3.new() var sound: AudioStreamMP3 = AudioStreamMP3.new()
sound.data = file.get_buffer(file.get_length()) sound.data = file.get_buffer(file.get_length())
+5 -5
View File
@@ -47,16 +47,16 @@ func _can_drop_in_gp_container(_at_position: Vector2, data: Variant) -> bool:
if data is Dictionary: if data is Dictionary:
return (data as Dictionary).has("gp_id") return (data as Dictionary).has("gp_id")
else: else:
Logger.error("LessonContainer: Can not drop data (that is not of type Dictionary) in GP Container") Log.error("LessonContainer: Can not drop data (that is not of type Dictionary) in GP Container")
return false return false
func _drop_data_in_gp_container(_at_position: Vector2, data: Variant) -> void: func _drop_data_in_gp_container(_at_position: Vector2, data: Variant) -> void:
if not data is Dictionary: if not data is Dictionary:
Logger.error("LessonContainer: Cancel drop data in GP container because data is not of type Dictionary") Log.error("LessonContainer: Cancel drop data in GP container because data is not of type Dictionary")
return return
if not (data as Dictionary).has("gp_id"): if not (data as Dictionary).has("gp_id"):
Logger.trace("LessonContainer: Cancel drop data in GP container because data has no key gp_id") Log.trace("LessonContainer: Cancel drop data in GP container because data has no key gp_id")
return return
var new_gp_label: LessonGPLabel = gp_label_scene.instantiate() var new_gp_label: LessonGPLabel = gp_label_scene.instantiate()
new_gp_label.grapheme = data.grapheme new_gp_label.grapheme = data.grapheme
@@ -80,13 +80,13 @@ func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
if data is Dictionary: if data is Dictionary:
return ((data as Dictionary).has("number") and number != (data as Dictionary).number) or _can_drop_in_gp_container(at_position, data) return ((data as Dictionary).has("number") and number != (data as Dictionary).number) or _can_drop_in_gp_container(at_position, data)
else: else:
Logger.error("LessonContainer: Can not drop data that is not of type Dictionary") Log.error("LessonContainer: Can not drop data that is not of type Dictionary")
return false return false
func _drop_data(at_position: Vector2, data: Variant) -> void: func _drop_data(at_position: Vector2, data: Variant) -> void:
if not data is Dictionary: if not data is Dictionary:
Logger.error("LessonContainer: drop data failed because data is not of type Dictionary") Log.error("LessonContainer: drop data failed because data is not of type Dictionary")
return return
if not (data as Dictionary).has("number") or (data as Dictionary).has("gp_id"): if not (data as Dictionary).has("number") or (data as Dictionary).has("gp_id"):
return return
+2 -2
View File
@@ -35,13 +35,13 @@ func _can_drop_data(_at_position: Vector2, data: Variant) -> bool:
if data is Dictionary: if data is Dictionary:
return (data as Dictionary).has("gp_id") and data.gp_id != gp_id return (data as Dictionary).has("gp_id") and data.gp_id != gp_id
else: else:
Logger.error("LessonGPLabel: Can not drop data that is not of type Dictionary") Log.error("LessonGPLabel: Can not drop data that is not of type Dictionary")
return false return false
func _drop_data(at_position: Vector2, data: Variant) -> void: func _drop_data(at_position: Vector2, data: Variant) -> void:
if not data is Dictionary: if not data is Dictionary:
Logger.error("LessonGPLabel: drop data failed because data is not of type Dictionary") Log.error("LessonGPLabel: drop data failed because data is not of type Dictionary")
if not (data as Dictionary).has("gp_id"): if not (data as Dictionary).has("gp_id"):
return return
var before: bool = at_position.x < size.x / 2 var before: bool = at_position.x < size.x / 2
+7 -7
View File
@@ -171,7 +171,7 @@ func _check_db_integrity() -> void:
lesson_id = index +1 lesson_id = index +1
error_label.text = "Database integrity checks lesson " + str(lesson_id) error_label.text = "Database integrity checks lesson " + str(lesson_id)
await get_tree().process_frame await get_tree().process_frame
Logger.trace("ProfToolMenu: Lesson_id = " + str(lesson_id)) Log.trace("ProfToolMenu: Lesson_id = " + str(lesson_id))
var new_gps_for_lesson: Array = Database.get_gps_for_lesson(lesson_id, false, true, false, false, true) var new_gps_for_lesson: Array = Database.get_gps_for_lesson(lesson_id, false, true, false, false, true)
for new_gp: Dictionary in new_gps_for_lesson: for new_gp: Dictionary in new_gps_for_lesson:
@@ -264,7 +264,7 @@ func _check_db_integrity() -> void:
integrity_checking = false integrity_checking = false
if check_box_log.button_pressed: if check_box_log.button_pressed:
var file_path: String = ProjectSettings.globalize_path(integrity_log_path) var file_path: String = ProjectSettings.globalize_path(integrity_log_path)
Logger.trace("ProfToolMenu: Logs saved at " + file_path) Log.trace("ProfToolMenu: Logs saved at " + file_path)
OS.shell_open(file_path) OS.shell_open(file_path)
#endregion #endregion
@@ -283,7 +283,7 @@ func log_message(message: String) -> bool:
file.store_line(message) file.store_line(message)
file.close() file.close()
else: else:
Logger.warn("ProfToolMenu: Integrity log file not found") Log.warn("ProfToolMenu: Integrity log file not found")
return true return true
else: else:
error_label.text = message error_label.text = message
@@ -546,7 +546,7 @@ func create_book() -> void:
var file_path: String = lang_path.path_join(file_names[category]) var file_path: String = lang_path.path_join(file_names[category])
var file: FileAccess = FileAccess.open(file_path, FileAccess.READ) var file: FileAccess = FileAccess.open(file_path, FileAccess.READ)
if file == null: if file == null:
Logger.error("ProfToolMenu: Error opening file: " + file_path) Log.error("ProfToolMenu: Error opening file: " + file_path)
continue continue
if file.eof_reached(): if file.eof_reached():
@@ -590,7 +590,7 @@ func create_book() -> void:
var values: PackedStringArray = parse_csv_line(line) var values: PackedStringArray = parse_csv_line(line)
if values.size() != raw_headers.size(): if values.size() != raw_headers.size():
Logger.warn("ProfToolMenu: Malformed line ignored: %s" % values) Log.warn("ProfToolMenu: Malformed line ignored: %s" % values)
continue continue
var row_dict: Dictionary[String, String] = {} var row_dict: Dictionary[String, String] = {}
@@ -623,7 +623,7 @@ func create_book() -> void:
var output_path: String = lang_path.path_join("booklet.csv") var output_path: String = lang_path.path_join("booklet.csv")
var output_file: FileAccess = FileAccess.open(output_path, FileAccess.WRITE) var output_file: FileAccess = FileAccess.open(output_path, FileAccess.WRITE)
if output_file == null: if output_file == null:
Logger.error("ProfToolMenu: Impossible to write: " + output_path) Log.error("ProfToolMenu: Impossible to write: " + output_path)
return return
output_file.store_line(escape_csv_line(PackedStringArray(ordered_headers))) output_file.store_line(escape_csv_line(PackedStringArray(ordered_headers)))
@@ -638,7 +638,7 @@ func create_book() -> void:
output_file.close() output_file.close()
error_label.text = "📘 Export data of the booklet finished to path: " + output_path error_label.text = "📘 Export data of the booklet finished to path: " + output_path
Logger.trace("ProfToolMenu: " + error_label.text) Log.trace("ProfToolMenu: " + error_label.text)
# Fonction qui ajoute une ligne au dictionnaire # Fonction qui ajoute une ligne au dictionnaire
+4 -4
View File
@@ -61,10 +61,10 @@ func _load_segments(segment_container: SegmentContainer, path: String) -> void:
var file: FileAccess = FileAccess.open(real_path(path), FileAccess.READ) var file: FileAccess = FileAccess.open(real_path(path), FileAccess.READ)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("TracingBuilder: Load segment: Cannot open file %s. Error: %s" % [real_path(path), error_string(error)]) Log.error("TracingBuilder: Load segment: Cannot open file %s. Error: %s" % [real_path(path), error_string(error)])
return return
if file == null: if file == null:
Logger.error("TracingBuilder: Load segment: Cannot open file %s. File is null" % real_path(path)) Log.error("TracingBuilder: Load segment: Cannot open file %s. File is null" % real_path(path))
return return
while not file.eof_reached(): while not file.eof_reached():
var line: PackedStringArray = file.get_csv_line() var line: PackedStringArray = file.get_csv_line()
@@ -84,10 +84,10 @@ func _save_segments(segments: Array[SegmentBuild], path: String) -> void:
var file: FileAccess = FileAccess.open(real_path(path), FileAccess.WRITE) var file: FileAccess = FileAccess.open(real_path(path), FileAccess.WRITE)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("TracingBuilder: Save segment: Cannot open file %s. Error: %s" % [real_path(path), error_string(error)]) Log.error("TracingBuilder: Save segment: Cannot open file %s. Error: %s" % [real_path(path), error_string(error)])
return return
if file == null: if file == null:
Logger.error("TracingBuilder: Save segment: Cannot open file %s. File is null" % real_path(path)) Log.error("TracingBuilder: Save segment: Cannot open file %s. File is null" % real_path(path))
return return
for segment: SegmentBuild in segments: for segment: SegmentBuild in segments:
var values: PackedStringArray = [] var values: PackedStringArray = []
+8 -8
View File
@@ -93,7 +93,7 @@ func ensure_column_exists(table_name: String, column_name: String, default_value
var alter_sql: String = "ALTER TABLE %s ADD COLUMN %s INTEGER DEFAULT %s;" % [table_name, column_name, default_value] var alter_sql: String = "ALTER TABLE %s ADD COLUMN %s INTEGER DEFAULT %s;" % [table_name, column_name, default_value]
var result: bool = Database.db.query(alter_sql) var result: bool = Database.db.query(alter_sql)
if not result: if not result:
Logger.error("WordList: Failed to add column '%s' to table '%s'" % [column_name, table_name]) Log.error("WordList: Failed to add column '%s' to table '%s'" % [column_name, table_name])
func _input(event: InputEvent) -> void: func _input(event: InputEvent) -> void:
@@ -136,7 +136,7 @@ func _on_element_new_gp_asked(ind: int, element: WordListElement) -> void:
elif new_gp is GPListElement: elif new_gp is GPListElement:
(new_gp as GPListElement).edit_mode() (new_gp as GPListElement).edit_mode()
else: else:
Logger.error("WordList: Variable new_gp is of unknown type %s" % type_string(typeof(new_gp))) Log.error("WordList: Variable new_gp is of unknown type %s" % type_string(typeof(new_gp)))
func set_in_new_gp_mode(p_in_new_gp_mode: bool) -> void: func set_in_new_gp_mode(p_in_new_gp_mode: bool) -> void:
@@ -150,7 +150,7 @@ func _on_gp_list_element_validated() -> void:
elif new_gp is GPListElement: elif new_gp is GPListElement:
(new_gp as GPListElement).insert_in_database() (new_gp as GPListElement).insert_in_database()
else: else:
Logger.error("WordList: Variable new_gp is of unknown type %s" % type_string(typeof(new_gp))) Log.error("WordList: Variable new_gp is of unknown type %s" % type_string(typeof(new_gp)))
if new_gp is Object: if new_gp is Object:
if (new_gp as Object).has_method("update_lesson"): if (new_gp as Object).has_method("update_lesson"):
if new_gp is WordListElement: if new_gp is WordListElement:
@@ -158,9 +158,9 @@ func _on_gp_list_element_validated() -> void:
elif new_gp is SentenceListElement: elif new_gp is SentenceListElement:
(new_gp as SentenceListElement).update_lesson() (new_gp as SentenceListElement).update_lesson()
else: else:
Logger.error("WordList: Variable new_gp is of unknown type %s" % type_string(typeof(new_gp))) Log.error("WordList: Variable new_gp is of unknown type %s" % type_string(typeof(new_gp)))
else: else:
Logger.error("WordList: Variable new_gp is of unknown type %s" % type_string(typeof(new_gp))) Log.error("WordList: Variable new_gp is of unknown type %s" % type_string(typeof(new_gp)))
in_new_gp_mode = false in_new_gp_mode = false
create_sub_elements_list() create_sub_elements_list()
for element: WordListElement in elements_container.get_children(): for element: WordListElement in elements_container.get_children():
@@ -227,16 +227,16 @@ func _on_word_gui_input(event: InputEvent) -> void:
func _on_list_title_import_path_selected(path: String, match_to_file: bool) -> void: func _on_list_title_import_path_selected(path: String, match_to_file: bool) -> void:
if not FileAccess.file_exists(path): if not FileAccess.file_exists(path):
Logger.error("WordList: File not found %s" % path) Log.error("WordList: File not found %s" % path)
error_label.text = "File not found" error_label.text = "File not found"
return return
var file: FileAccess = FileAccess.open(path, FileAccess.READ) var file: FileAccess = FileAccess.open(path, FileAccess.READ)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("WordList: Cannot open file %s. Error: %s" % [path, error_string(error)]) Log.error("WordList: Cannot open file %s. Error: %s" % [path, error_string(error)])
return return
if file == null: if file == null:
Logger.error("WordList: Cannot open file %s. File is null" % path) Log.error("WordList: Cannot open file %s. File is null" % path)
return return
var line: PackedStringArray = file.get_csv_line() var line: PackedStringArray = file.get_csv_line()
if line.size() < 2 or line[0] != "ORTHO" or line[1] != "GPMATCH": if line.size() < 2 or line[0] != "ORTHO" or line[1] != "GPMATCH":
+2 -2
View File
@@ -240,7 +240,7 @@ func insert_in_database() -> void:
table, table,
table] table]
Database.db.query_with_bindings(query, [id]) Database.db.query_with_bindings(query, [id])
Logger.trace("WordListElement: Sending query to insert in database: %s" % query) Log.trace("WordListElement: Sending query to insert in database: %s" % query)
if not Database.db.query_result.is_empty(): if not Database.db.query_result.is_empty():
var element: Dictionary = Database.db.query_result[0] var element: Dictionary = Database.db.query_result[0]
if word != element[table_graph_column] or exception != element.Exception or reading != element.Reading or writing != element.Writing: if word != element[table_graph_column] or exception != element.Exception or reading != element.Reading or writing != element.Writing:
@@ -327,7 +327,7 @@ func _add_from_additional_word_list(new_text: String) -> int:
func _try_to_complete_from_word(new_text: String) -> int: func _try_to_complete_from_word(new_text: String) -> int:
var index: int = _already_in_database(new_text) var index: int = _already_in_database(new_text)
if index >= 0: if index >= 0:
Logger.trace("WordListElement: Already in DB " + new_text) Log.trace("WordListElement: Already in DB " + new_text)
return index return index
index = _add_from_additional_word_list(new_text) index = _add_from_additional_word_list(new_text)
+4 -4
View File
@@ -30,7 +30,7 @@ func _ready() -> void:
gardens_data = transition_data gardens_data = transition_data
transition_data = {} transition_data = {}
lesson_nb = gardens_data.get("current_lesson_number", lesson_nb) lesson_nb = gardens_data.get("current_lesson_number", lesson_nb)
Logger.trace("LookAndLearn: Starting lesson %d" % lesson_nb) Log.trace("LookAndLearn: Starting lesson %d" % lesson_nb)
setup() setup()
await OpeningCurtain.open() await OpeningCurtain.open()
@@ -39,7 +39,7 @@ func setup() -> void:
gp_list = Database.get_gps_for_lesson(lesson_nb, true, true) gp_list = Database.get_gps_for_lesson(lesson_nb, true, true)
if gp_list.size() <= 0: if gp_list.size() <= 0:
Logger.error("LookAndLearn: setup() did not found any GP for lesson " + str(lesson_nb)) Log.error("LookAndLearn: setup() did not found any GP for lesson " + str(lesson_nb))
await OpeningCurtain.open() await OpeningCurtain.open()
_on_tracing_manager_finished() _on_tracing_manager_finished()
return return
@@ -114,14 +114,14 @@ func _on_grapheme_button_pressed() -> void:
0: 0:
current_button_pressed += 1 current_button_pressed += 1
if videos.is_empty(): if videos.is_empty():
Logger.warn("LookAndLearn: Skipping video because empty in lesson %d" % lesson_nb) Log.warn("LookAndLearn: Skipping video because empty in lesson %d" % lesson_nb)
continue continue
animation_player.play("to_videos") animation_player.play("to_videos")
loop = false loop = false
1: 1:
current_button_pressed += 1 current_button_pressed += 1
if images.is_empty() or sounds.is_empty(): if images.is_empty() or sounds.is_empty():
Logger.warn("LookAndLearn: Skipping image&sound because empty in lesson %d" % lesson_nb) Log.warn("LookAndLearn: Skipping image&sound because empty in lesson %d" % lesson_nb)
continue continue
animation_player.play("to_images_and_sounds") animation_player.play("to_images_and_sounds")
loop = false loop = false
+2 -2
View File
@@ -83,10 +83,10 @@ func _load_tracing(path: String) -> Array:
var file: FileAccess = FileAccess.open(_real_path(path), FileAccess.READ) var file: FileAccess = FileAccess.open(_real_path(path), FileAccess.READ)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("TracingManager: Load tracing: Cannot open file %s. Error: %s" % [_real_path(path), error_string(error)]) Log.error("TracingManager: Load tracing: Cannot open file %s. Error: %s" % [_real_path(path), error_string(error)])
return segments return segments
if file == null: if file == null:
Logger.error("TracingManager: Load tracing: Cannot open file %s. File is null" % _real_path(path)) Log.error("TracingManager: Load tracing: Cannot open file %s. File is null" % _real_path(path))
return segments return segments
while not file.eof_reached(): while not file.eof_reached():
var points: Array[Vector2] = [] var points: Array[Vector2] = []
@@ -46,7 +46,7 @@ func _draw_password() -> void:
var index: int = 0 var index: int = 0
for value: String in password.split(""): for value: String in password.split(""):
if index >= 3: if index >= 3:
Logger.error("PasswordVisualizer: A password cannot be more than 3 characters long") Log.error("PasswordVisualizer: A password cannot be more than 3 characters long")
return return
if value in ICONS_TEXTURES: if value in ICONS_TEXTURES:
@@ -27,6 +27,6 @@ func _refresh() -> void:
func _device_button_pressed(device: int) -> void: func _device_button_pressed(device: int) -> void:
Logger.trace("DeviceSelection: User selected device %d" % device) Log.trace("DeviceSelection: User selected device %d" % device)
if UserDataManager.set_device_id(device): if UserDataManager.set_device_id(device):
get_tree().change_scene_to_file(LOGIN_SCENE_PATH) get_tree().change_scene_to_file(LOGIN_SCENE_PATH)
@@ -34,7 +34,7 @@ var current_language_version: Dictionary = {}
func _ready() -> void: func _ready() -> void:
await get_tree().process_frame await get_tree().process_frame
Logger.trace("PackageDownloader: Starting with device language %s" % UserDataManager.get_device_settings().language) Log.trace("PackageDownloader: Starting with device language %s" % UserDataManager.get_device_settings().language)
# Check the teacher settings, if we are logged in (this scene should not be accessible otherwise) # Check the teacher settings, if we are logged in (this scene should not be accessible otherwise)
var teacher_settings: TeacherSettings = UserDataManager.teacher_settings var teacher_settings: TeacherSettings = UserDataManager.teacher_settings
@@ -47,7 +47,7 @@ func _ready() -> void:
current_language_path = USER_LANGUAGE_RESOURCES_PATH.path_join(device_language) current_language_path = USER_LANGUAGE_RESOURCES_PATH.path_join(device_language)
current_language_version = UserDataManager.get_device_settings().language_versions.get(device_language, {}) current_language_version = UserDataManager.get_device_settings().language_versions.get(device_language, {})
Logger.trace("PackageDownloader: Checking internet access") Log.trace("PackageDownloader: Checking internet access")
if not await ServerManager.check_internet_access(): if not await ServerManager.check_internet_access():
# Offline mode, if a pack is already downloaded, go to next scene # Offline mode, if a pack is already downloaded, go to next scene
if DirAccess.dir_exists_absolute(current_language_path): if DirAccess.dir_exists_absolute(current_language_path):
@@ -61,7 +61,7 @@ func _ready() -> void:
# Gets the info of the language pack on the server # Gets the info of the language pack on the server
var res: Dictionary = await ServerManager.get_language_pack_url(device_language) var res: Dictionary = await ServerManager.get_language_pack_url(device_language)
Logger.trace("PackageDownloader: Language pack info received with code %d" % res.code) Log.trace("PackageDownloader: Language pack info received with code %d" % res.code)
if res.code == 200: if res.code == 200:
server_language_version = Time.get_datetime_dict_from_datetime_string(res.body.last_modified as String, false) server_language_version = Time.get_datetime_dict_from_datetime_string(res.body.last_modified as String, false)
# Authentication failed, disconnect the user # Authentication failed, disconnect the user
@@ -76,7 +76,7 @@ func _ready() -> void:
# If the language pack is not already downloaded or an update is needed # If the language pack is not already downloaded or an update is needed
if not DirAccess.dir_exists_absolute(current_language_path) or current_language_version != server_language_version: if not DirAccess.dir_exists_absolute(current_language_path) or current_language_version != server_language_version:
Logger.trace("A new version of the language pack has been detected.\n Current version = " + str(current_language_version) + "\n Server version = " + str(server_language_version)) Log.trace("A new version of the language pack has been detected.\n Current version = " + str(current_language_version) + "\n Server version = " + str(server_language_version))
checking_label.hide() checking_label.hide()
download_label.show() download_label.show()
@@ -95,7 +95,7 @@ func _ready() -> void:
# Download the pack # Download the pack
http_request.set_download_file(USER_LANGUAGE_RESOURCES_PATH.path_join(device_language + ".zip")) http_request.set_download_file(USER_LANGUAGE_RESOURCES_PATH.path_join(device_language + ".zip"))
Logger.trace("PackageDownloader: Downloading pack from %s" % res.body.url) Log.trace("PackageDownloader: Downloading pack from %s" % res.body.url)
http_request.request(res.body.url as String) http_request.request(res.body.url as String)
else: else:
download_bar.value = 1 download_bar.value = 1
@@ -108,10 +108,10 @@ func is_language_directory_valid(path: String) -> bool:
var dir: DirAccess = DirAccess.open(path) var dir: DirAccess = DirAccess.open(path)
var error: Error = DirAccess.get_open_error() var error: Error = DirAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("PackageDownloader: Is language directory valid: Cannot open directory %s. Error: %s" % [path, error_string(error)]) Log.error("PackageDownloader: Is language directory valid: Cannot open directory %s. Error: %s" % [path, error_string(error)])
return false return false
if not dir: if not dir:
Logger.error("PackageDownloader: Is language directory valid: Cannot open directory %s. dir is null" % path) Log.error("PackageDownloader: Is language directory valid: Cannot open directory %s. dir is null" % path)
return false return false
if dir.list_dir_begin() != OK: if dir.list_dir_begin() != OK:
@@ -142,7 +142,7 @@ func _copy_data(this: PackageDownloader) -> void:
if not FileAccess.file_exists(USER_LANGUAGE_RESOURCES_PATH.path_join(device_language + ".zip")): if not FileAccess.file_exists(USER_LANGUAGE_RESOURCES_PATH.path_join(device_language + ".zip")):
return return
Logger.trace("PackageDownloader: Extracting downloaded package") Log.trace("PackageDownloader: Extracting downloaded package")
var language_zip: String = device_language + ".zip" var language_zip: String = device_language + ".zip"
var language_zip_path: String = USER_LANGUAGE_RESOURCES_PATH.path_join(language_zip) var language_zip_path: String = USER_LANGUAGE_RESOURCES_PATH.path_join(language_zip)
@@ -169,19 +169,19 @@ func _copy_data(this: PackageDownloader) -> void:
# Extract the archive # Extract the archive
var subfolder: String = unzipper.extract(language_zip_path, USER_LANGUAGE_RESOURCES_PATH, false) var subfolder: String = unzipper.extract(language_zip_path, USER_LANGUAGE_RESOURCES_PATH, false)
if subfolder == "": if subfolder == "":
Logger.error("PackageDownloader: Extraction failed for %s" % language_zip_path) Log.error("PackageDownloader: Extraction failed for %s" % language_zip_path)
return return
# Move the data to the locale folder of the user # Move the data to the locale folder of the user
var error: Error = DirAccess.rename_absolute(USER_LANGUAGE_RESOURCES_PATH.path_join(subfolder), current_language_path) var error: Error = DirAccess.rename_absolute(USER_LANGUAGE_RESOURCES_PATH.path_join(subfolder), current_language_path)
if error != OK: if error != OK:
Logger.error("PackageDownloader: Error " + error_string(error) + " while renaming folder from %s to %s" % [USER_LANGUAGE_RESOURCES_PATH.path_join(subfolder), current_language_path]) Log.error("PackageDownloader: Error " + error_string(error) + " while renaming folder from %s to %s" % [USER_LANGUAGE_RESOURCES_PATH.path_join(subfolder), current_language_path])
else: else:
Logger.trace("PackageDownloader: Package extracted to %s" % current_language_path) Log.trace("PackageDownloader: Package extracted to %s" % current_language_path)
# Cleanup unnecessary files # Cleanup unnecessary files
DirAccess.remove_absolute(language_zip_path) DirAccess.remove_absolute(language_zip_path)
Logger.trace("PackageDownloader: Removed temporary archive %s" % language_zip_path) Log.trace("PackageDownloader: Removed temporary archive %s" % language_zip_path)
# Go to main menu # Go to main menu
this.call_thread_safe("_go_to_next_scene") this.call_thread_safe("_go_to_next_scene")
@@ -212,7 +212,7 @@ func _go_to_next_scene() -> void:
func _on_http_request_request_completed(_result: int, response_code: int, _headers: PackedStringArray, _body: PackedByteArray) -> void: func _on_http_request_request_completed(_result: int, response_code: int, _headers: PackedStringArray, _body: PackedByteArray) -> void:
Logger.trace("PackageDownloader: Download completed with HTTP code %d" % response_code) Log.trace("PackageDownloader: Download completed with HTTP code %d" % response_code)
if response_code == 200: if response_code == 200:
mutex = Mutex.new() mutex = Mutex.new()
thread = Thread.new() thread = Thread.new()
+1 -1
View File
@@ -35,7 +35,7 @@ func _process(delta: float) -> void:
func _play_speech(speech: AudioStream) -> void: func _play_speech(speech: AudioStream) -> void:
if not speech: if not speech:
Logger.warn("Kalulu: Speech not found") Log.warn("Kalulu: Speech not found")
is_speaking = false is_speaking = false
return return
is_speaking = true is_speaking = true
+3 -10
View File
@@ -33,9 +33,7 @@ fail_message = "A value is required."
[sub_resource type="Resource" id="Resource_owox8"] [sub_resource type="Resource" id="Resource_owox8"]
script = ExtResource("20_6xsd1") script = ExtResource("20_6xsd1")
validation_order = 1
validation_method = 1 validation_method = 1
skip_validation = false
rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_mh75v")]) rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_mh75v")])
[sub_resource type="Resource" id="Resource_j516d"] [sub_resource type="Resource" id="Resource_j516d"]
@@ -48,9 +46,7 @@ fail_message = "Value must be a valid email address."
[sub_resource type="Resource" id="Resource_hxkvx"] [sub_resource type="Resource" id="Resource_hxkvx"]
script = ExtResource("21_1bl4i") script = ExtResource("21_1bl4i")
validation_order = 1
validation_method = 1 validation_method = 1
skip_validation = false
rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_j516d"), SubResource("Resource_ayewh")]) rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_j516d"), SubResource("Resource_ayewh")])
[sub_resource type="Resource" id="Resource_b08p8"] [sub_resource type="Resource" id="Resource_b08p8"]
@@ -59,9 +55,7 @@ fail_message = "A value is required."
[sub_resource type="Resource" id="Resource_k2y4u"] [sub_resource type="Resource" id="Resource_k2y4u"]
script = ExtResource("21_1bl4i") script = ExtResource("21_1bl4i")
validation_order = 1
validation_method = 1 validation_method = 1
skip_validation = false
rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_b08p8")]) rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_b08p8")])
[sub_resource type="Gradient" id="Gradient_22q4u"] [sub_resource type="Gradient" id="Gradient_22q4u"]
@@ -123,7 +117,7 @@ grow_vertical = 2
script = ExtResource("8_cxg8l") script = ExtResource("8_cxg8l")
[node name="Title" type="TextureRect" parent="Kalulu"] [node name="Title" type="TextureRect" parent="Kalulu"]
layout_mode = 2 layout_mode = 0
offset_left = -324.0 offset_left = -324.0
offset_top = -644.0 offset_top = -644.0
offset_right = 323.0 offset_right = 323.0
@@ -135,7 +129,7 @@ texture = ExtResource("7_ftt26")
[node name="Background" type="TextureRect" parent="Kalulu"] [node name="Background" type="TextureRect" parent="Kalulu"]
custom_minimum_size = Vector2(868, 868) custom_minimum_size = Vector2(868, 868)
layout_mode = 2 layout_mode = 0
offset_left = -434.0 offset_left = -434.0
offset_top = -250.0 offset_top = -250.0
offset_right = 434.0 offset_right = 434.0
@@ -376,7 +370,7 @@ grow_vertical = 0
[node name="BuildVersionTitle" type="Label" parent="Informations"] [node name="BuildVersionTitle" type="Label" parent="Informations"]
custom_minimum_size = Vector2(400, 0) custom_minimum_size = Vector2(400, 0)
layout_mode = 2 layout_mode = 0
offset_left = 10.0 offset_left = 10.0
offset_right = 261.0 offset_right = 261.0
offset_bottom = 56.0 offset_bottom = 56.0
@@ -510,7 +504,6 @@ text = "CANCEL"
[connection signal="pressed" from="Kalulu/PlayButton" to="." method="_on_main_button_pressed"] [connection signal="pressed" from="Kalulu/PlayButton" to="." method="_on_main_button_pressed"]
[connection signal="logged_in" from="KeyboardSpacer/LoginForm" to="." method="_on_login_in"] [connection signal="logged_in" from="KeyboardSpacer/LoginForm" to="." method="_on_login_in"]
[connection signal="control_validated" from="KeyboardSpacer/LoginForm/LoginFormValidator" to="KeyboardSpacer/LoginForm" method="_on_login_form_validator_control_validated"]
[connection signal="item_selected" from="KeyboardSpacer/LoginForm/LoginFormValidator/FormContainer/LanguageContainer/LanguageField" to="KeyboardSpacer/LoginForm/LoginFormValidator/FormContainer/LanguageContainer/LanguageField" method="_on_item_selected"] [connection signal="item_selected" from="KeyboardSpacer/LoginForm/LoginFormValidator/FormContainer/LanguageContainer/LanguageField" to="KeyboardSpacer/LoginForm/LoginFormValidator/FormContainer/LanguageContainer/LanguageField" method="_on_item_selected"]
[connection signal="pressed" from="KeyboardSpacer/LoginForm/LoginFormValidator/FormContainer/ValidateButton" to="KeyboardSpacer/LoginForm" method="_on_validate_button_pressed"] [connection signal="pressed" from="KeyboardSpacer/LoginForm/LoginFormValidator/FormContainer/ValidateButton" to="KeyboardSpacer/LoginForm" method="_on_validate_button_pressed"]
[connection signal="pressed" from="KeyboardSpacer/LoginForm/LoginFormValidator/FormContainer/Register" to="." method="_on_register_pressed"] [connection signal="pressed" from="KeyboardSpacer/LoginForm/LoginFormValidator/FormContainer/Register" to="." method="_on_register_pressed"]
+2 -2
View File
@@ -56,12 +56,12 @@ func _on_back_button_pressed() -> void:
func _on_validate_button_pressed() -> void: func _on_validate_button_pressed() -> void:
# Validate the fields # Validate the fields
if not form_validator.validate(): if not form_validator.validate():
Logger.warn("BaseStep: Validation failed (" + str(self) + ")") Log.warn("BaseStep: Validation failed (" + str(self) + ")")
return return
# Writes data in object # Writes data in object
if not form_binder.write(): if not form_binder.write():
Logger.warn("BaseStep: Impossible to write data in object (" + str(self) + ")") Log.warn("BaseStep: Impossible to write data in object (" + str(self) + ")")
return return
if _on_next(): if _on_next():
@@ -9,12 +9,12 @@ func _on_validate_button_pressed() -> void:
# Validate the fields # Validate the fields
if not form_validator.validate(): if not form_validator.validate():
Logger.warn("CredentialsStep: Validation failed (" + str(self) + ")") Log.warn("CredentialsStep: Validation failed (" + str(self) + ")")
return return
# Writes data in object # Writes data in object
if not form_binder.write(): if not form_binder.write():
Logger.warn("CredentialsStep: Impossible to write data in object (" + str(self) + ")") Log.warn("CredentialsStep: Impossible to write data in object (" + str(self) + ")")
return return
var res: Dictionary = await ServerManager.check_email((data as TeacherSettings).email as String) var res: Dictionary = await ServerManager.check_email((data as TeacherSettings).email as String)
+2 -2
View File
@@ -39,7 +39,7 @@ ORDER BY LessonNb")
student_unlock.lesson_gps = element.GPs student_unlock.lesson_gps = element.GPs
student_unlock.lesson_number = element.LessonNb student_unlock.lesson_number = element.LessonNb
if not progression: if not progression:
Logger.trace("LessonUnlocks: User selected a student with no progression data") Log.trace("LessonUnlocks: User selected a student with no progression data")
return return
student_unlock.unlocks = progression.unlocks student_unlock.unlocks = progression.unlocks
lesson_container.add_child(student_unlock) lesson_container.add_child(student_unlock)
@@ -105,4 +105,4 @@ func _device_button_pressed(device_id: int) -> void:
device = device_id device = device_id
var res_set: Dictionary = await ServerManager.set_student_data(student, {"device_id": device_id}) var res_set: Dictionary = await ServerManager.set_student_data(student, {"device_id": device_id})
if not res_set.success: if not res_set.success:
Logger.trace("LessonUnlocks: Device was updated locally for the student, but the network update failed.") Log.trace("LessonUnlocks: Device was updated locally for the student, but the network update failed.")
+9 -9
View File
@@ -52,7 +52,7 @@ func _on_account_type_option_button_item_selected(index: int) -> void:
UserDataManager.teacher_settings.last_modified = Time.get_datetime_string_from_system(true) UserDataManager.teacher_settings.last_modified = Time.get_datetime_string_from_system(true)
UserDataManager.save_teacher_settings() UserDataManager.save_teacher_settings()
else: else:
Logger.warn("SettingsTeacherSettings: Cannot assign index %d to AccountType" % index) Log.warn("SettingsTeacherSettings: Cannot assign index %d to AccountType" % index)
func _on_education_method_option_button_item_selected(index: int) -> void: func _on_education_method_option_button_item_selected(index: int) -> void:
@@ -61,7 +61,7 @@ func _on_education_method_option_button_item_selected(index: int) -> void:
UserDataManager.teacher_settings.last_modified = Time.get_datetime_string_from_system(true) UserDataManager.teacher_settings.last_modified = Time.get_datetime_string_from_system(true)
UserDataManager.save_teacher_settings() UserDataManager.save_teacher_settings()
else: else:
Logger.warn("SettingsTeacherSettings: Cannot assign index %d to EducationMethod" % index) Log.warn("SettingsTeacherSettings: Cannot assign index %d to EducationMethod" % index)
func refresh_devices_tabs() -> void: func refresh_devices_tabs() -> void:
@@ -69,7 +69,7 @@ func refresh_devices_tabs() -> void:
child.queue_free() child.queue_free()
if not UserDataManager.teacher_settings: if not UserDataManager.teacher_settings:
Logger.error("SettingsTeacherSettings: Teacher settings not found") Log.error("SettingsTeacherSettings: Teacher settings not found")
return return
for device: int in UserDataManager.teacher_settings.students.keys(): for device: int in UserDataManager.teacher_settings.students.keys():
@@ -128,7 +128,7 @@ func _on_add_student_button_pressed() -> void:
func _on_add_student_popup_accepted() -> void: func _on_add_student_popup_accepted() -> void:
var current_tab: DeviceTab = devices_tab_container.get_current_tab_control() as DeviceTab var current_tab: DeviceTab = devices_tab_container.get_current_tab_control() as DeviceTab
if not current_tab: if not current_tab:
Logger.error("SettingsTeacherSettings: DeviceTab not found") Log.error("SettingsTeacherSettings: DeviceTab not found")
return return
var res: Dictionary = await ServerManager.add_student({"device": current_tab.device_id}) var res: Dictionary = await ServerManager.add_student({"device": current_tab.device_id})
if res.code == 200: if res.code == 200:
@@ -136,7 +136,7 @@ func _on_add_student_popup_accepted() -> void:
current_tab.students = UserDataManager.teacher_settings.students[current_tab.device_id] current_tab.students = UserDataManager.teacher_settings.students[current_tab.device_id]
current_tab.refresh() current_tab.refresh()
else: else:
Logger.error("SettingsTeacherSettings: Request to add student failed. Error code " + str(res.code)) Log.error("SettingsTeacherSettings: Request to add student failed. Error code " + str(res.code))
func _on_add_device_button_pressed() -> void: func _on_add_device_button_pressed() -> void:
@@ -179,7 +179,7 @@ func update_student_name(student_code: int, student_name: String) -> void:
if student_panel.student_data.code == student_code: if student_panel.student_data.code == student_code:
student_panel.name_label.text = student_name student_panel.name_label.text = student_name
return return
Logger.warn("SettingsTeacherSettings: update_student_name: student not found with code " + str(student_code)) Log.warn("SettingsTeacherSettings: update_student_name: student not found with code " + str(student_code))
#region Synchronization #region Synchronization
@@ -190,9 +190,9 @@ func _on_dashboard_button_pressed() -> void:
if (res.body as Dictionary).has("url"): if (res.body as Dictionary).has("url"):
OS.shell_open(res.body.url as String) OS.shell_open(res.body.url as String)
return return
Logger.error("SettingsTeacherSettings: Request to get Dashboard link has an invalid content") Log.error("SettingsTeacherSettings: Request to get Dashboard link has an invalid content")
else: else:
Logger.error("SettingsTeacherSettings: Request to get Dashboard link failed. Error code " + str(res.code)) Log.error("SettingsTeacherSettings: Request to get Dashboard link failed. Error code " + str(res.code))
func _on_synchronize_button_pressed() -> void: func _on_synchronize_button_pressed() -> void:
@@ -204,6 +204,6 @@ func _on_loading_popup_ok() -> void:
func _on_loading_popup_cancel() -> void: func _on_loading_popup_cancel() -> void:
Logger.warn("SettingsTeacherSettings: User wanted to cancel synchronization but it is impossible to interrupt.") Log.warn("SettingsTeacherSettings: User wanted to cancel synchronization but it is impossible to interrupt.")
#endregion #endregion
+1 -1
View File
@@ -6,7 +6,7 @@ const MAIN_MENU_SCENE_PATH: String = "res://sources/menus/main/main_menu.tscn"
func _go_to_main_menu() -> void: func _go_to_main_menu() -> void:
var err: Error = get_tree().change_scene_to_file(MAIN_MENU_SCENE_PATH) var err: Error = get_tree().change_scene_to_file(MAIN_MENU_SCENE_PATH)
if err != 0: if err != 0:
Logger.error("SplashScreen: Error while going to main menu: " + str(err)) Log.error("SplashScreen: Error while going to main menu: " + str(err))
func _on_timer_timeout() -> void: func _on_timer_timeout() -> void:
+1 -1
View File
@@ -78,7 +78,7 @@ func _find_stimuli_and_distractions() -> void:
# Shuffle the stimuli # Shuffle the stimuli
stimuli.shuffle() stimuli.shuffle()
Logger.trace("AntsMinigame: stimuli = " + str(stimuli)) Log.trace("AntsMinigame: stimuli = " + str(stimuli))
func _start() -> void: func _start() -> void:
+2 -2
View File
@@ -137,7 +137,7 @@ func _setup_minigame() -> void:
# Find the stimuli and distractions of the minigame. # Find the stimuli and distractions of the minigame.
func _find_stimuli_and_distractions() -> void: func _find_stimuli_and_distractions() -> void:
Logger.error("Minigame type " + str(minigame_name) + " has not implemented the function _find_stimuli_and_distractions()") Log.error("Minigame type " + str(minigame_name) + " has not implemented the function _find_stimuli_and_distractions()")
return return
@@ -272,7 +272,7 @@ func _submit_student_level_time() -> void:
#region Logs #region Logs
func _save_logs() -> void: func _save_logs() -> void:
LessonLogger.save_logs(logs, UserDataManager.get_student_folder(), Type.keys()[minigame_name] as String, lesson_nb, Time.get_time_string_from_system()) LessonLog.save_logs(logs, UserDataManager.get_student_folder(), Type.keys()[minigame_name] as String, lesson_nb, Time.get_time_string_from_system())
_reset_logs() _reset_logs()
@@ -22,7 +22,7 @@ var is_stimulus_heard: bool = false:
func _start() -> void: func _start() -> void:
super() super()
if stimuli.is_empty(): if stimuli.is_empty():
Logger.error("SyllablesMinigame: Cannot start game because stimuli is empty") Log.error("SyllablesMinigame: Cannot start game because stimuli is empty")
_win() _win()
return return
stimulus_timer.wait_time = stimulus_repeat_time stimulus_timer.wait_time = stimulus_repeat_time
@@ -204,13 +204,13 @@ func _on_stimulus_pressed(stimulus: Dictionary, _node: Node) -> bool:
if _get_current_stimulus().has("ID"): if _get_current_stimulus().has("ID"):
_update_remediation_syllable_score(_get_current_stimulus().ID as int, -1) _update_remediation_syllable_score(_get_current_stimulus().ID as int, -1)
else: else:
Logger.error("SyllablesMinigame: current stimulus has no ID") Log.error("SyllablesMinigame: current stimulus has no ID")
# Handles the pressed stimulus Gps # Handles the pressed stimulus Gps
if stimulus.has("ID"): if stimulus.has("ID"):
_update_remediation_syllable_score(stimulus.ID as int, -1) _update_remediation_syllable_score(stimulus.ID as int, -1)
else: else:
Logger.warn("SyllablesMinigame: stimulus has no ID") Log.warn("SyllablesMinigame: stimulus has no ID")
return true return true
+1 -1
View File
@@ -33,7 +33,7 @@ func play_kalulu_speech(speech: AudioStream, show_animation: bool = true, hide_a
audio_player.play() audio_player.play()
await audio_player.finished await audio_player.finished
else: else:
Logger.warn("Kalulu: Speech not found") Log.warn("Kalulu: Speech not found")
if hide_animation: if hide_animation:
audio_player.stream = HIDE_SOUND audio_player.stream = HIDE_SOUND
@@ -3,38 +3,38 @@ extends AudioStreamPlayer
func play_gp(gp: Dictionary) -> void: func play_gp(gp: Dictionary) -> void:
Logger.trace("Minigame Audio Stream Player: Playing GP " + str(gp)) Log.trace("Minigame Audio Stream Player: Playing GP " + str(gp))
if not gp or gp.is_empty(): if not gp or gp.is_empty():
return return
var phoneme_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_gp_sound_path(gp)) as AudioStream var phoneme_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_gp_sound_path(gp)) as AudioStream
if not phoneme_audiostream: if not phoneme_audiostream:
Logger.warn("MinigameAudioStreamPlayer: AudioStream not found for gp %s " % gp) Log.warn("MinigameAudioStreamPlayer: AudioStream not found for gp %s " % gp)
return return
await play_audio_stream(phoneme_audiostream) await play_audio_stream(phoneme_audiostream)
func play_syllable(syllable: Dictionary) -> void: func play_syllable(syllable: Dictionary) -> void:
Logger.trace("Minigame Audio Stream Player: Playing Syllable " + str(syllable)) Log.trace("Minigame Audio Stream Player: Playing Syllable " + str(syllable))
if not syllable or syllable.is_empty(): if not syllable or syllable.is_empty():
return return
var syllable_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_syllable_sound_path(syllable)) var syllable_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_syllable_sound_path(syllable))
if not syllable_audiostream: if not syllable_audiostream:
Logger.warn("MinigameAudioStreamPlayer: AudioStream not found for syllable %s " % syllable) Log.warn("MinigameAudioStreamPlayer: AudioStream not found for syllable %s " % syllable)
return return
await play_audio_stream(syllable_audiostream) await play_audio_stream(syllable_audiostream)
func play_word(word: String) -> void: func play_word(word: String) -> void:
Logger.trace("Minigame Audio Stream Player: Playing Word " + str(word)) Log.trace("Minigame Audio Stream Player: Playing Word " + str(word))
if not word or word.is_empty(): if not word or word.is_empty():
return return
var word_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_word_sound_path({Word = word})) var word_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_word_sound_path({Word = word}))
if not word_audiostream: if not word_audiostream:
Logger.warn("MinigameAudioStreamPlayer: AudioStream not found for word %s " % word) Log.warn("MinigameAudioStreamPlayer: AudioStream not found for word %s " % word)
return return
await play_audio_stream(word_audiostream) await play_audio_stream(word_audiostream)
@@ -92,7 +92,7 @@ func _find_stimuli_and_distractions() -> void:
func _start() -> void: func _start() -> void:
super() super()
if stimuli.is_empty(): if stimuli.is_empty():
Logger.error("WordsMinigame: Cannot start game because stimuli is empty") Log.error("WordsMinigame: Cannot start game because stimuli is empty")
_win() _win()
return return
_setup_word_progression() _setup_word_progression()
@@ -186,7 +186,7 @@ func _log_new_response_and_score(gp: Dictionary) -> void:
if gp.has("ID"): # GP can be an empty dictionary (empty word) if gp.has("ID"): # GP can be an empty dictionary (empty word)
_update_confusion_matrix_gp_score(self._get_gp().ID as int, gp.ID as int) _update_confusion_matrix_gp_score(self._get_gp().ID as int, gp.ID as int)
else: else:
Logger.trace("WordsMinigame: Confusion matrix cannot be updated because word is empty") # Empty word is normal, it just does not update the confusion matrix Log.trace("WordsMinigame: Confusion matrix cannot be updated because word is empty") # Empty word is normal, it just does not update the confusion matrix
# Handles Remediation GP scoring # Handles Remediation GP scoring
if self._is_gp_right(gp): if self._is_gp_right(gp):
+1 -1
View File
@@ -58,7 +58,7 @@ func _ready() -> void:
func _find_stimuli_and_distractions() -> void: func _find_stimuli_and_distractions() -> void:
var data_array: Array[Dictionary] = Database.get_pseudowords_for_lesson(lesson_nb) var data_array: Array[Dictionary] = Database.get_pseudowords_for_lesson(lesson_nb)
if data_array.size() <= 0: if data_array.size() <= 0:
Logger.error("FishMinigame: Cannot start fish minigame since data is empty for lesson %d" % lesson_nb) Log.error("FishMinigame: Cannot start fish minigame since data is empty for lesson %d" % lesson_nb)
return return
data_array.shuffle() data_array.shuffle()
words_to_present.clear() words_to_present.clear()
+2 -2
View File
@@ -20,9 +20,9 @@ domain_warp_fractal_gain = 0.1
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_5gfk0"] [sub_resource type="NoiseTexture2D" id="NoiseTexture2D_5gfk0"]
width = 128 width = 128
height = 128 height = 128
seamless_blend_skirt = 0.0
color_ramp = SubResource("Gradient_s16dt")
noise = SubResource("FastNoiseLite_c8rmy") noise = SubResource("FastNoiseLite_c8rmy")
color_ramp = SubResource("Gradient_s16dt")
seamless_blend_skirt = 0.0
[resource] [resource]
shader = ExtResource("1_obtft") shader = ExtResource("1_obtft")
+2 -2
View File
@@ -20,9 +20,9 @@ domain_warp_fractal_gain = 0.1
[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_noqed"] [sub_resource type="NoiseTexture2D" id="NoiseTexture2D_noqed"]
width = 128 width = 128
height = 128 height = 128
seamless_blend_skirt = 0.0
color_ramp = SubResource("Gradient_q5on4")
noise = SubResource("FastNoiseLite_6xjnx") noise = SubResource("FastNoiseLite_6xjnx")
color_ramp = SubResource("Gradient_q5on4")
seamless_blend_skirt = 0.0
[resource] [resource]
resource_local_to_scene = true resource_local_to_scene = true
+2 -2
View File
@@ -29,11 +29,11 @@ const SCALE_FACTOR: float = 0.2
if animated_sprite_body: if animated_sprite_body:
animated_sprite_body.sprite_frames = ANIMATIONS_BODY[color] animated_sprite_body.sprite_frames = ANIMATIONS_BODY[color]
else: else:
Logger.error("Jellyfish: no animated sprite body") Log.error("Jellyfish: no animated sprite body")
if animated_sprite_arms: if animated_sprite_arms:
animated_sprite_arms.sprite_frames = ANIMATIONS_ARMS[color] animated_sprite_arms.sprite_frames = ANIMATIONS_ARMS[color]
else: else:
Logger.error("Jellyfish: no animated sprite arms") Log.error("Jellyfish: no animated sprite arms")
scale = SCALES[color] * (1. + randf() * SCALE_FACTOR) scale = SCALES[color] * (1. + randf() * SCALE_FACTOR)
# Handles sprite size # Handles sprite size
@@ -69,14 +69,14 @@ func _find_stimuli_and_distractions() -> void:
for sentence: Dictionary in stimuli: for sentence: Dictionary in stimuli:
sentence.GPs = Database.get_gps_from_sentence(sentence.ID as int) sentence.GPs = Database.get_gps_from_sentence(sentence.ID as int)
Logger.trace("PenguinMinigame: Stimuli: %s" % str(stimuli)) Log.trace("PenguinMinigame: Stimuli: %s" % str(stimuli))
# Launch the minigame # Launch the minigame
func _start() -> void: func _start() -> void:
super() super()
if stimuli.is_empty(): if stimuli.is_empty():
Logger.error("PenguinMinigame: Cannot start game because stimuli is empty") Log.error("PenguinMinigame: Cannot start game because stimuli is empty")
_win() _win()
return return
_setup_word_progression() _setup_word_progression()
@@ -161,7 +161,7 @@ func _on_snowball_thrown(pos: Vector2, label: PenguinLabel) -> void:
if label.gp.has("WordID"): if label.gp.has("WordID"):
_update_remediation_word_score(label.gp.WordID as int, 1 if correct_answer else -1) _update_remediation_word_score(label.gp.WordID as int, 1 if correct_answer else -1)
else: else:
Logger.error("PenguinMinigame: Cannot update remediation score because label GP has no WordID") Log.error("PenguinMinigame: Cannot update remediation score because label GP has no WordID")
if correct_answer: if correct_answer:
penguin.happy() penguin.happy()
@@ -46,7 +46,7 @@ func _setup_minigame() -> void:
spawn_timer.wait_time = settings.spawn_rate spawn_timer.wait_time = settings.spawn_rate
for stimulus: Dictionary in stimuli: for stimulus: Dictionary in stimuli:
Logger.trace("TurtleMinigame: %s" % stimulus.Word) Log.trace("TurtleMinigame: %s" % stimulus.Word)
func _highlight() -> void: func _highlight() -> void:
+15 -15
View File
@@ -50,7 +50,7 @@ func connect_to_db() -> void:
if FileAccess.file_exists(db.path): if FileAccess.file_exists(db.path):
is_open = db.open_db() is_open = db.open_db()
else: else:
Logger.warn("Database: DB file not found at %s" % db.path) Log.warn("Database: DB file not found at %s" % db.path)
func get_additional_word_list_path() -> String: func get_additional_word_list_path() -> String:
@@ -64,15 +64,15 @@ func load_additional_word_list() -> String:
var file: FileAccess = FileAccess.open(word_list_path, FileAccess.READ) var file: FileAccess = FileAccess.open(word_list_path, FileAccess.READ)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("Database: Load additional word list: Cannot open file %s. Error: %s" % [word_list_path, error_string(error)]) Log.error("Database: Load additional word list: Cannot open file %s. Error: %s" % [word_list_path, error_string(error)])
return "" return ""
if file == null: if file == null:
Logger.error("Database: Load additional word list: Cannot open file %s. File is null" % word_list_path) Log.error("Database: Load additional word list: Cannot open file %s. File is null" % word_list_path)
return "" return ""
var title_line: PackedStringArray = file.get_csv_line() var title_line: PackedStringArray = file.get_csv_line()
if (not "ORTHO" in title_line) or (not "PHON" in title_line) or (not "GPMATCH" in title_line): if (not "ORTHO" in title_line) or (not "PHON" in title_line) or (not "GPMATCH" in title_line):
var msg: String = "word list should have columns ORTHO, PHON and GPMATCH" var msg: String = "word list should have columns ORTHO, PHON and GPMATCH"
Logger.error("Database: " + msg) Log.error("Database: " + msg)
return msg return msg
var ortho_index: int = title_line.find("ORTHO") var ortho_index: int = title_line.find("ORTHO")
while not file.eof_reached(): while not file.eof_reached():
@@ -85,7 +85,7 @@ func load_additional_word_list() -> String:
additional_word_list[line[ortho_index]] = data additional_word_list[line[ortho_index]] = data
file.close() file.close()
else: else:
Logger.warn("Database: Additional word list file not found: %s" % word_list_path) Log.warn("Database: Additional word list file not found: %s" % word_list_path)
return "" return ""
@@ -181,7 +181,7 @@ func get_word_id_from_text(text: String) -> int:
if db.query_result.size() > 0: if db.query_result.size() > 0:
if db.query_result[0].has("ID"): if db.query_result[0].has("ID"):
return db.query_result[0].ID return db.query_result[0].ID
Logger.trace("Database: Word " + text + " ID not found") Log.trace("Database: Word " + text + " ID not found")
return -1 return -1
@@ -497,7 +497,7 @@ func get_audio_stream_for_phoneme(phoneme: String) -> AudioStream:
if FileAccess.file_exists(path) and ResourceLoader.exists(path): if FileAccess.file_exists(path) and ResourceLoader.exists(path):
return load(path) return load(path)
Logger.trace("Database: Audio stream not found for phoneme %s" % phoneme) Log.trace("Database: Audio stream not found for phoneme %s" % phoneme)
return null return null
@@ -511,7 +511,7 @@ func get_gp_look_and_learn_image(gp: Dictionary) -> Texture:
var texture: ImageTexture = ImageTexture.create_from_image(image) var texture: ImageTexture = ImageTexture.create_from_image(image)
return texture return texture
Logger.trace("Database: Look & Learn image not found for GP %s" % str(gp)) Log.trace("Database: Look & Learn image not found for GP %s" % str(gp))
return null return null
@@ -524,16 +524,16 @@ func get_gp_look_and_learn_sound(gp: Dictionary) -> AudioStream:
var file: FileAccess = FileAccess.open(path, FileAccess.READ) var file: FileAccess = FileAccess.open(path, FileAccess.READ)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("Database: Get GP look and learn sound: Cannot open file %s. Error: %s" % [path, error_string(error)]) Log.error("Database: Get GP look and learn sound: Cannot open file %s. Error: %s" % [path, error_string(error)])
return null return null
if file == null: if file == null:
Logger.error("Database: Get GP look and learn sound: Cannot open file %s. File is null" % path) Log.error("Database: Get GP look and learn sound: Cannot open file %s. File is null" % path)
return null return null
var sound: AudioStreamMP3 = AudioStreamMP3.new() var sound: AudioStreamMP3 = AudioStreamMP3.new()
sound.data = file.get_buffer(file.get_length()) sound.data = file.get_buffer(file.get_length())
return sound return sound
Logger.trace("Database: Look & Learn sound not found for GP %s" % str(gp)) Log.trace("Database: Look & Learn sound not found for GP %s" % str(gp))
return null return null
@@ -543,7 +543,7 @@ func get_gp_look_and_learn_video(gp: Dictionary) -> VideoStream:
var video: VideoStream = load(path) var video: VideoStream = load(path)
return video return video
Logger.trace("Database: Look & Learn video not found for GP %s" % gp) Log.trace("Database: Look & Learn video not found for GP %s" % gp)
return null return null
@@ -588,16 +588,16 @@ func get_kalulu_speech_path(speech_category: String, speech_name: String) -> Str
func load_external_sound(path: String) -> AudioStreamMP3: func load_external_sound(path: String) -> AudioStreamMP3:
if not FileAccess.file_exists(path): if not FileAccess.file_exists(path):
Logger.trace("Database: External sound file not found: %s" % path) Log.trace("Database: External sound file not found: %s" % path)
return null return null
var file: FileAccess = FileAccess.open(path, FileAccess.READ) var file: FileAccess = FileAccess.open(path, FileAccess.READ)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("Database: Load external sound: Cannot open file %s. Error: %s" % [path, error_string(error)]) Log.error("Database: Load external sound: Cannot open file %s. Error: %s" % [path, error_string(error)])
return null return null
if file == null: if file == null:
Logger.error("Database: Load external sound: Cannot open file %s. File is null" % path) Log.error("Database: Load external sound: Cannot open file %s. File is null" % path)
return null return null
var audio_stream: AudioStreamMP3 = AudioStreamMP3.new() var audio_stream: AudioStreamMP3 = AudioStreamMP3.new()
audio_stream.data = file.get_buffer(file.get_length()) audio_stream.data = file.get_buffer(file.get_length())
+28 -28
View File
@@ -31,7 +31,7 @@ func set_environment(env: int) -> void:
0: environment_url = "https://iu695b0nk5.execute-api.eu-west-3.amazonaws.com/dev/" 0: environment_url = "https://iu695b0nk5.execute-api.eu-west-3.amazonaws.com/dev/"
1: environment_url = "https://uqkpbayw1k.execute-api.eu-west-3.amazonaws.com/prod/" 1: environment_url = "https://uqkpbayw1k.execute-api.eu-west-3.amazonaws.com/prod/"
_: environment_url = "" _: environment_url = ""
Logger.info("Environment URL set to " + environment_url) Log.info("Environment URL set to " + environment_url)
func submit_student_level_time(level: int, elapsed_time: int) -> void: func submit_student_level_time(level: int, elapsed_time: int) -> void:
@@ -98,7 +98,7 @@ func get_user_data() -> Dictionary:
func update_student_remediation_data(student_code: int, student_remediation: UserRemediation) -> Dictionary: func update_student_remediation_data(student_code: int, student_remediation: UserRemediation) -> Dictionary:
if not student_remediation: if not student_remediation:
Logger.trace("ServerManager: Cannot update student remediation data because data does not exists") Log.trace("ServerManager: Cannot update student remediation data because data does not exists")
success = true success = true
code = -1 code = -1
json = {} json = {}
@@ -134,7 +134,7 @@ func set_student_data(student_code: int, data: Dictionary) -> Dictionary:
#region Sender functions #region Sender functions
func check_internet_access() -> bool: func check_internet_access() -> bool:
Logger.trace("ServerManager Sending simple request to " + INTERNET_CHECK_URL + " to check if internet is available") Log.trace("ServerManager Sending simple request to " + INTERNET_CHECK_URL + " to check if internet is available")
var res: Error = internet_check.request(INTERNET_CHECK_URL) var res: Error = internet_check.request(INTERNET_CHECK_URL)
if res == OK: if res == OK:
return await internet_check_completed return await internet_check_completed
@@ -160,7 +160,7 @@ func _create_request_headers(content_type_json: bool = false) -> PackedStringArr
headers.append("Authorization: Bearer " + teacher_settings.token) headers.append("Authorization: Bearer " + teacher_settings.token)
if content_type_json: if content_type_json:
headers.append("Content-Type: application/json") headers.append("Content-Type: application/json")
Logger.trace("ServerManager Create Header: " + str(headers)) Log.trace("ServerManager Create Header: " + str(headers))
return headers return headers
@@ -177,13 +177,13 @@ func _get_request(uri: String, params: Dictionary) -> void:
reset_result() reset_result()
var headers: PackedStringArray = _create_request_headers() var headers: PackedStringArray = _create_request_headers()
if params.has("password"): if params.has("password"):
Logger.trace("ServerManager Sending GET request.\n URI = %s\n Parameters not logged because it contains a password." % uri) Log.trace("ServerManager Sending GET request.\n URI = %s\n Parameters not logged because it contains a password." % uri)
else: else:
Logger.trace("ServerManager Sending GET request.\n URI = %s\n Parameters = %s" % [uri, params]) Log.trace("ServerManager Sending GET request.\n URI = %s\n Parameters = %s" % [uri, params])
if http_request.request(_create_uri_with_parameters(environment_url + uri, params), headers) == OK: if http_request.request(_create_uri_with_parameters(environment_url + uri, params), headers) == OK:
await request_completed await request_completed
else: else:
Logger.error("ServerManager Error sending GET request") Log.error("ServerManager Error sending GET request")
code = 500 code = 500
json = {message = "Internal Server Error"} json = {message = "Internal Server Error"}
@@ -193,13 +193,13 @@ func _post_request(uri: String, params: Dictionary) -> void:
var url: String = _create_uri_with_parameters(environment_url + uri, params) var url: String = _create_uri_with_parameters(environment_url + uri, params)
var headers: PackedStringArray = _create_request_headers() var headers: PackedStringArray = _create_request_headers()
if params.has("password"): if params.has("password"):
Logger.trace("ServerManager Sending POST request.\n URI = %s\n Parameters not logged because it contains a password." % uri) Log.trace("ServerManager Sending POST request.\n URI = %s\n Parameters not logged because it contains a password." % uri)
else: else:
Logger.trace("ServerManager Sending POST request.\n URI = %s\n Parameters = %s" % [uri, params]) Log.trace("ServerManager Sending POST request.\n URI = %s\n Parameters = %s" % [uri, params])
if http_request.request(url, headers, HTTPClient.METHOD_POST, "") == OK: if http_request.request(url, headers, HTTPClient.METHOD_POST, "") == OK:
await request_completed await request_completed
else: else:
Logger.error("ServerManager Error sending POST request") Log.error("ServerManager Error sending POST request")
code = 500 code = 500
json = {message = "Internal Server Error"} json = {message = "Internal Server Error"}
@@ -209,13 +209,13 @@ func _post_json_request(uri: String, data: Dictionary) -> void:
var req: String = environment_url + uri var req: String = environment_url + uri
var headers: PackedStringArray = _create_request_headers(true) var headers: PackedStringArray = _create_request_headers(true)
if data.has("password"): if data.has("password"):
Logger.trace("ServerManager sending POST JSON request.\n URI = %s\n Data not logged because it contains a password." % uri) Log.trace("ServerManager sending POST JSON request.\n URI = %s\n Data not logged because it contains a password." % uri)
else: else:
Logger.trace("ServerManager Sending POST JSON request.\n URI = %s\n Data = %s" % [uri, data]) Log.trace("ServerManager Sending POST JSON request.\n URI = %s\n Data = %s" % [uri, data])
if http_request.request(req, headers, HTTPClient.METHOD_POST, JSON.stringify(data)) == OK: if http_request.request(req, headers, HTTPClient.METHOD_POST, JSON.stringify(data)) == OK:
await request_completed await request_completed
else: else:
Logger.error("ServerManager Error sending POST JSON request") Log.error("ServerManager Error sending POST JSON request")
code = 500 code = 500
json = {message = "Internal Server Error"} json = {message = "Internal Server Error"}
@@ -224,11 +224,11 @@ func _delete_request(uri: String, params: Dictionary = {}) -> void:
reset_result() reset_result()
var req: String = _create_uri_with_parameters(environment_url + uri, params) var req: String = _create_uri_with_parameters(environment_url + uri, params)
var headers: PackedStringArray = _create_request_headers() var headers: PackedStringArray = _create_request_headers()
Logger.trace("ServerManager Sending DELETE request.\n URI = %s\n Parameters = %s" % [uri, params]) Log.trace("ServerManager Sending DELETE request.\n URI = %s\n Parameters = %s" % [uri, params])
if http_request.request(req, headers, HTTPClient.METHOD_DELETE, "") == OK: if http_request.request(req, headers, HTTPClient.METHOD_DELETE, "") == OK:
await request_completed await request_completed
else: else:
Logger.error("ServerManager Error sending DELETE request") Log.error("ServerManager Error sending DELETE request")
code = 500 code = 500
json = {message = "Internal Server Error"} json = {message = "Internal Server Error"}
@@ -236,13 +236,13 @@ func _delete_request(uri: String, params: Dictionary = {}) -> void:
func _on_http_request_request_completed(result_code: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: func _on_http_request_request_completed(result_code: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
if result_code != OK: if result_code != OK:
Logger.warn("Cannot complete http request. Error code %d = %s" % [result_code, error_string(result_code)]) Log.warn("Cannot complete http request. Error code %d = %s" % [result_code, error_string(result_code)])
else: else:
code = response_code code = response_code
if code == 200: if code == 200:
Logger.trace("ServerManager Request Completed. Response code = %d" % response_code) Log.trace("ServerManager Request Completed. Response code = %d" % response_code)
else: else:
Logger.warn("ServerManager Request Completed. Response code = %d" % response_code) Log.warn("ServerManager Request Completed. Response code = %d" % response_code)
if body: if body:
var str_body: String = body.get_string_from_utf8() var str_body: String = body.get_string_from_utf8()
var result: Variant = JSON.parse_string(str_body) var result: Variant = JSON.parse_string(str_body)
@@ -250,26 +250,26 @@ func _on_http_request_request_completed(result_code: int, response_code: int, _h
if result is Dictionary or result is Array: if result is Dictionary or result is Array:
var pretty: String = JSON.stringify(result, "\t") var pretty: String = JSON.stringify(result, "\t")
if code == 200: if code == 200:
Logger.trace("ServerManager Prettyfied Body received :\n%s" % pretty) Log.trace("ServerManager Prettyfied Body received :\n%s" % pretty)
else: else:
Logger.warn("ServerManager Prettyfied Body received :\n%s" % pretty) Log.warn("ServerManager Prettyfied Body received :\n%s" % pretty)
else: else:
if code == 200: if code == 200:
Logger.trace("ServerManager Body received = %s" % str_body) Log.trace("ServerManager Body received = %s" % str_body)
else: else:
Logger.warn("ServerManager Body received = %s" % str_body) Log.warn("ServerManager Body received = %s" % str_body)
if result != null: if result != null:
json = result json = result
else: else:
if code == 200: if code == 200:
Logger.trace("ServerManager: result null after parsing String to JSON") Log.trace("ServerManager: result null after parsing String to JSON")
else: else:
Logger.warn("ServerManager: result null after parsing String to JSON") Log.warn("ServerManager: result null after parsing String to JSON")
else: else:
if code == 200: if code == 200:
Logger.trace("ServerManager Body received is empty") Log.trace("ServerManager Body received is empty")
else: else:
Logger.warn("ServerManager Body received is empty") Log.warn("ServerManager Body received is empty")
success = result_code == OK and response_code == 200 success = result_code == OK and response_code == 200
request_completed.emit(success, response_code, json) request_completed.emit(success, response_code, json)
loading_rect.hide() loading_rect.hide()
@@ -277,9 +277,9 @@ func _on_http_request_request_completed(result_code: int, response_code: int, _h
func _on_internet_check_request_completed(result_code: int, response_code: int, _headers: PackedStringArray, _body: PackedByteArray) -> void: func _on_internet_check_request_completed(result_code: int, response_code: int, _headers: PackedStringArray, _body: PackedByteArray) -> void:
if result_code != OK: if result_code != OK:
Logger.warn("Cannot check internet request. Error code %d = %s" % [result_code, error_string(result_code)]) Log.warn("Cannot check internet request. Error code %d = %s" % [result_code, error_string(result_code)])
else: else:
Logger.trace("ServerManager Internet check completed.\n Response code = %s. (200 = OK)" % str(response_code)) Log.trace("ServerManager Internet check completed.\n Response code = %s. (200 = OK)" % str(response_code))
success = result_code == OK and response_code == 200 success = result_code == OK and response_code == 200
internet_check_completed.emit(success) internet_check_completed.emit(success)
+49 -49
View File
@@ -47,14 +47,14 @@ func purge_user_folders_if_needed() -> void:
var previous_version: String = _device_settings.game_version var previous_version: String = _device_settings.game_version
if previous_version == "" or Utils.compare_versions(previous_version, "2.1.3") < 0: if previous_version == "" or Utils.compare_versions(previous_version, "2.1.3") < 0:
Logger.trace("UserDataManager: Version difference detected, need to purge user folder to avoid data incompatibility") Log.trace("UserDataManager: Version difference detected, need to purge user folder to avoid data incompatibility")
var dir: DirAccess = DirAccess.open("user://") var dir: DirAccess = DirAccess.open("user://")
var error: Error = DirAccess.get_open_error() var error: Error = DirAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("UserDataManager: Could not open user:// directory for cleanup. Error: %s" % error_string(error)) Log.error("UserDataManager: Could not open user:// directory for cleanup. Error: %s" % error_string(error))
return return
if not dir: if not dir:
Logger.warn("UserDataManager: Could not open user:// directory for cleanup.") Log.warn("UserDataManager: Could not open user:// directory for cleanup.")
return return
dir.list_dir_begin() dir.list_dir_begin()
var file_name: String = dir.get_next() var file_name: String = dir.get_next()
@@ -64,7 +64,7 @@ func purge_user_folders_if_needed() -> void:
file_name = dir.get_next() file_name = dir.get_next()
dir.list_dir_end() dir.list_dir_end()
Logger.trace("UserDataManager: Purge completed") Log.trace("UserDataManager: Purge completed")
_device_settings.game_version = current_version _device_settings.game_version = current_version
ResourceSaver.save(_device_settings, "user://device_settings.tres") ResourceSaver.save(_device_settings, "user://device_settings.tres")
@@ -98,7 +98,7 @@ func stop_synchronization_timer() -> void:
func register(register_settings: TeacherSettings) -> bool: func register(register_settings: TeacherSettings) -> bool:
if not register_settings: if not register_settings:
Logger.warn("UserDataManager: register called with invalid register_settings") Log.warn("UserDataManager: register called with invalid register_settings")
return false return false
# Handles device settings # Handles device settings
@@ -118,27 +118,27 @@ func register(register_settings: TeacherSettings) -> bool:
# Allow the user to log-in from the server # Allow the user to log-in from the server
func login(infos: Dictionary) -> bool: func login(infos: Dictionary) -> bool:
if not _device_settings: if not _device_settings:
Logger.error("UserDataManager: User cannot login because they have no _device_settings.") Log.error("UserDataManager: User cannot login because they have no _device_settings.")
return false return false
if not infos: if not infos:
Logger.error("UserDataManager: User cannot login because they have no _device_settings.") Log.error("UserDataManager: User cannot login because they have no _device_settings.")
return false return false
if not infos.has("email") or not infos.email: if not infos.has("email") or not infos.email:
Logger.error("UserDataManager: User cannot login because they have no infos.") Log.error("UserDataManager: User cannot login because they have no infos.")
return false return false
if not infos.has("account_type"): if not infos.has("account_type"):
Logger.error("UserDataManager: User cannot login because they have no account_type.") Log.error("UserDataManager: User cannot login because they have no account_type.")
return false return false
if infos.account_type < 0 or infos.account_type > 1: if infos.account_type < 0 or infos.account_type > 1:
Logger.error("UserDataManager: User cannot login because they have invalid account_type: " + str(infos.account_type)) Log.error("UserDataManager: User cannot login because they have invalid account_type: " + str(infos.account_type))
return false return false
if not infos.has("token") or not infos.token: if not infos.has("token") or not infos.token:
Logger.error("UserDataManager: User cannot login because they have no token.") Log.error("UserDataManager: User cannot login because they have no token.")
return false return false
# Handles device settings # Handles device settings
@@ -167,41 +167,41 @@ func login(infos: Dictionary) -> bool:
func safe_load_and_fix_resource(path: String, old_texts: Array[String], new_texts: Array[String]) -> Resource: func safe_load_and_fix_resource(path: String, old_texts: Array[String], new_texts: Array[String]) -> Resource:
if not FileAccess.file_exists(path): if not FileAccess.file_exists(path):
Logger.error("UserDataManager: File not found: " + path) Log.error("UserDataManager: File not found: " + path)
return null return null
var content: String = FileAccess.get_file_as_string(path) var content: String = FileAccess.get_file_as_string(path)
for index: int in range(old_texts.size()): for index: int in range(old_texts.size()):
if content.find(old_texts[index]) != -1: if content.find(old_texts[index]) != -1:
Logger.trace("UserDataManager: Fix resource:" + path) Log.trace("UserDataManager: Fix resource:" + path)
content = content.replace(old_texts[index], new_texts[index]) content = content.replace(old_texts[index], new_texts[index])
var file: FileAccess = FileAccess.open(path, FileAccess.WRITE) var file: FileAccess = FileAccess.open(path, FileAccess.WRITE)
var error: Error = FileAccess.get_open_error() var error: Error = FileAccess.get_open_error()
if error != OK: if error != OK:
Logger.error("UserDataManager: Safe load and fix resource: Cannot open file %s. Error: %s" % [path, error_string(error)]) Log.error("UserDataManager: Safe load and fix resource: Cannot open file %s. Error: %s" % [path, error_string(error)])
return null return null
if file == null: if file == null:
Logger.error("UserDataManager: Safe load and fix resource: Cannot open file %s. File is null" % path) Log.error("UserDataManager: Safe load and fix resource: Cannot open file %s. File is null" % path)
return null return null
file.store_string(content) file.store_string(content)
file.close() file.close()
var resource: Resource = ResourceLoader.load(path) var resource: Resource = ResourceLoader.load(path)
if resource == null: if resource == null:
Logger.error("UserDataManager: Loading failed after correction: " + path) Log.error("UserDataManager: Loading failed after correction: " + path)
else: else:
Logger.trace("UserDataManager: Loading success: " + path) Log.trace("UserDataManager: Loading success: " + path)
return resource return resource
func set_device_id(device: int) -> bool: func set_device_id(device: int) -> bool:
if not _device_settings: if not _device_settings:
Logger.warn("UserDataManager: set_device_id called with no device settings loaded") Log.warn("UserDataManager: set_device_id called with no device settings loaded")
return false return false
if not device: if not device:
Logger.warn("UserDataManager: set_device_id called with invalid device") Log.warn("UserDataManager: set_device_id called with invalid device")
return false return false
_device_settings.device_id = device _device_settings.device_id = device
@@ -231,10 +231,10 @@ func delete_teacher_data() -> void:
func student_exists(code: String) -> bool: func student_exists(code: String) -> bool:
if not _device_settings: if not _device_settings:
Logger.trace("UserDataManager: student_exists called with invalid _device_settings") Log.trace("UserDataManager: student_exists called with invalid _device_settings")
return false return false
if not teacher_settings: if not teacher_settings:
Logger.trace("UserDataManager: student_exists called with invalid teacher_settings") Log.trace("UserDataManager: student_exists called with invalid teacher_settings")
return false return false
var students: Array[StudentData] = teacher_settings.students[_device_settings.device_id] as Array[StudentData] var students: Array[StudentData] = teacher_settings.students[_device_settings.device_id] as Array[StudentData]
if students: if students:
@@ -246,10 +246,10 @@ func student_exists(code: String) -> bool:
func login_student(code: String) -> bool: func login_student(code: String) -> bool:
if not _device_settings: if not _device_settings:
Logger.warn("UserDataManager: login_student failed because of invalid _device_settings") Log.warn("UserDataManager: login_student failed because of invalid _device_settings")
return false return false
if not teacher_settings: if not teacher_settings:
Logger.warn("UserDataManager: login_student failed because of invalid teacher_settings") Log.warn("UserDataManager: login_student failed because of invalid teacher_settings")
return false return false
var students: Array[StudentData] = teacher_settings.students[_device_settings.device_id] as Array[StudentData] var students: Array[StudentData] = teacher_settings.students[_device_settings.device_id] as Array[StudentData]
@@ -260,16 +260,16 @@ func login_student(code: String) -> bool:
(ServerManager as ServerManagerClass).first_login_student() (ServerManager as ServerManagerClass).first_login_student()
return true return true
Logger.warn("UserDataManager: login_student failed, code not found: " + code) Log.warn("UserDataManager: login_student failed, code not found: " + code)
return false return false
func logout_student() -> bool: func logout_student() -> bool:
if not _device_settings: if not _device_settings:
Logger.warn("UserDataManager: logout_student failed because of invalid _device_settings") Log.warn("UserDataManager: logout_student failed because of invalid _device_settings")
return false return false
if not teacher_settings: if not teacher_settings:
Logger.warn("UserDataManager: logout_student failed because of invalid teacher_settings") Log.warn("UserDataManager: logout_student failed because of invalid teacher_settings")
return false return false
student = "" student = ""
@@ -301,7 +301,7 @@ func _load_device_settings() -> void:
func _save_device_settings() -> void: func _save_device_settings() -> void:
Logger.trace("UserDataManager: Saving device settings in " + ProjectSettings.globalize_path(get_device_settings_path())) Log.trace("UserDataManager: Saving device settings in " + ProjectSettings.globalize_path(get_device_settings_path()))
ResourceSaver.save(_device_settings, get_device_settings_path()) ResourceSaver.save(_device_settings, get_device_settings_path())
@@ -415,7 +415,7 @@ func _load_teacher_settings() -> void:
func save_teacher_settings() -> void: func save_teacher_settings() -> void:
Logger.trace("UserDataManager: Saving teacher settings in " + ProjectSettings.globalize_path(get_teacher_settings_path())) Log.trace("UserDataManager: Saving teacher settings in " + ProjectSettings.globalize_path(get_teacher_settings_path()))
ResourceSaver.save(teacher_settings, get_teacher_settings_path()) ResourceSaver.save(teacher_settings, get_teacher_settings_path())
@@ -524,7 +524,7 @@ func _load_student_progression() -> void:
func _save_student_progression() -> void: func _save_student_progression() -> void:
Logger.trace("UserDataManager: Saving student progression in " + ProjectSettings.globalize_path(get_student_progression_path())) Log.trace("UserDataManager: Saving student progression in " + ProjectSettings.globalize_path(get_student_progression_path()))
ResourceSaver.save(student_progression, get_student_progression_path()) ResourceSaver.save(student_progression, get_student_progression_path())
@@ -566,7 +566,7 @@ func save_student_progression_for_code(device: int, code: int, progression: Stud
var progression_path: String = "user://".path_join(_device_settings.teacher).path_join(str(device)).path_join(_device_settings.language).path_join(str(code)).path_join("progression.tres") var progression_path: String = "user://".path_join(_device_settings.teacher).path_join(str(device)).path_join(_device_settings.language).path_join(str(code)).path_join("progression.tres")
var error: Error = ResourceSaver.save(progression, progression_path) var error: Error = ResourceSaver.save(progression, progression_path)
if error != OK: if error != OK:
Logger.error("UserDataManager: save_student_progression_for_code(device = %s, code = %s): error %s" % [str(device), str(code), error_string(error)]) Log.error("UserDataManager: save_student_progression_for_code(device = %s, code = %s): error %s" % [str(device), str(code), error_string(error)])
func set_student_progression_data(student_code: int, version: String, new_data: Dictionary, updated_at: String) -> void: func set_student_progression_data(student_code: int, version: String, new_data: Dictionary, updated_at: String) -> void:
@@ -578,7 +578,7 @@ func set_student_progression_data(student_code: int, version: String, new_data:
current_data.last_modified = updated_at current_data.last_modified = updated_at
var err: Error = ResourceSaver.save(current_data, get_student_progression_path(0, student_code)) var err: Error = ResourceSaver.save(current_data, get_student_progression_path(0, student_code))
if err != OK: if err != OK:
Logger.error("UserDataManager: Error while saving student progression: %s" % error_string(err)) Log.error("UserDataManager: Error while saving student progression: %s" % error_string(err))
#endregion #endregion
@@ -613,7 +613,7 @@ func get_student_remediation_data(student_code: int) -> UserRemediation:
var student_remediation: UserRemediation var student_remediation: UserRemediation
student_remediation = load(remediation_data_path) student_remediation = load(remediation_data_path)
return student_remediation return student_remediation
Logger.trace("UserDataManager: Remediation data of student code %d not found" % student_code) Log.trace("UserDataManager: Remediation data of student code %d not found" % student_code)
return null return null
@@ -654,7 +654,7 @@ func set_student_remediation_words_data(student_code: int, new_scores: Dictionar
func _save_student_remediation() -> void: func _save_student_remediation() -> void:
Logger.trace("UserDataManager: Saving student remediation in " + ProjectSettings.globalize_path(_get_student_remediation_path())) Log.trace("UserDataManager: Saving student remediation in " + ProjectSettings.globalize_path(_get_student_remediation_path()))
ResourceSaver.save(_student_remediation, _get_student_remediation_path()) ResourceSaver.save(_student_remediation, _get_student_remediation_path())
@@ -666,7 +666,7 @@ func get_gp_remediation_score(gp_id: int) -> int:
func update_remediation_gp_scores(remediation_gp_scores: Dictionary) -> void: func update_remediation_gp_scores(remediation_gp_scores: Dictionary) -> void:
if not _student_remediation: if not _student_remediation:
Logger.warn("UserDataManager: No student remediation data for " + str(student)) Log.warn("UserDataManager: No student remediation data for " + str(student))
return return
if remediation_gp_scores: if remediation_gp_scores:
_student_remediation.update_gp_scores(remediation_gp_scores) _student_remediation.update_gp_scores(remediation_gp_scores)
@@ -674,7 +674,7 @@ func update_remediation_gp_scores(remediation_gp_scores: Dictionary) -> void:
func update_remediation_syllables_scores(remediation_syllables_scores: Dictionary) -> void: func update_remediation_syllables_scores(remediation_syllables_scores: Dictionary) -> void:
if not _student_remediation: if not _student_remediation:
Logger.warn("UserDataManager: No student remediation data for " + str(student)) Log.warn("UserDataManager: No student remediation data for " + str(student))
return return
if remediation_syllables_scores: if remediation_syllables_scores:
_student_remediation.update_syllables_scores(remediation_syllables_scores) _student_remediation.update_syllables_scores(remediation_syllables_scores)
@@ -682,7 +682,7 @@ func update_remediation_syllables_scores(remediation_syllables_scores: Dictionar
func update_remediation_words_scores(remediation_words_scores: Dictionary) -> void: func update_remediation_words_scores(remediation_words_scores: Dictionary) -> void:
if not _student_remediation: if not _student_remediation:
Logger.warn("UserDataManager: No student remediation data for " + str(student)) Log.warn("UserDataManager: No student remediation data for " + str(student))
return return
if remediation_words_scores: if remediation_words_scores:
_student_remediation.update_words_scores(remediation_words_scores) _student_remediation.update_words_scores(remediation_words_scores)
@@ -720,7 +720,7 @@ func get_student_confusion_matrix_data(student_code: int) -> UserConfusionMatrix
var student_confusion_matrix: UserConfusionMatrix var student_confusion_matrix: UserConfusionMatrix
student_confusion_matrix = load(confusion_matrix_data_path) student_confusion_matrix = load(confusion_matrix_data_path)
return student_confusion_matrix return student_confusion_matrix
Logger.trace("UserDataManager: Confusion matrix data of student code %d not found" % student_code) Log.trace("UserDataManager: Confusion matrix data of student code %d not found" % student_code)
return null return null
@@ -737,7 +737,7 @@ func set_student_confusion_matrix_gp_data(student_code: int, new_scores: Diction
func _save_student_confusion_matrix() -> void: func _save_student_confusion_matrix() -> void:
Logger.trace("UserDataManager: Saving student confusion_matrix in " + ProjectSettings.globalize_path(_get_student_confusion_matrix_path())) Log.trace("UserDataManager: Saving student confusion_matrix in " + ProjectSettings.globalize_path(_get_student_confusion_matrix_path()))
ResourceSaver.save(_student_confusion_matrix, _get_student_confusion_matrix_path()) ResourceSaver.save(_student_confusion_matrix, _get_student_confusion_matrix_path())
@@ -749,7 +749,7 @@ func get_gp_confusion_matrix_score(gp_id: int) -> PackedInt32Array:
func update_confusion_matrix_gp_scores(confusion_matrix_gp_scores: Dictionary) -> void: func update_confusion_matrix_gp_scores(confusion_matrix_gp_scores: Dictionary) -> void:
if not _student_confusion_matrix: if not _student_confusion_matrix:
Logger.warn("UserDataManager: No student confusion matrix data for " + str(student)) Log.warn("UserDataManager: No student confusion matrix data for " + str(student))
return return
if confusion_matrix_gp_scores: if confusion_matrix_gp_scores:
_student_confusion_matrix.update_gp_scores(confusion_matrix_gp_scores) _student_confusion_matrix.update_gp_scores(confusion_matrix_gp_scores)
@@ -775,20 +775,20 @@ func _load_student_difficulty() -> void:
func _save_student_difficulty() -> void: func _save_student_difficulty() -> void:
Logger.trace("UserDataManager: Saving student difficulty in " + ProjectSettings.globalize_path(_get_student_difficulty_path())) Log.trace("UserDataManager: Saving student difficulty in " + ProjectSettings.globalize_path(_get_student_difficulty_path()))
ResourceSaver.save(_student_difficulty, _get_student_difficulty_path()) ResourceSaver.save(_student_difficulty, _get_student_difficulty_path())
func get_difficulty_for_minigame(minigame_name: String) -> int: func get_difficulty_for_minigame(minigame_name: String) -> int:
if not _student_difficulty: if not _student_difficulty:
Logger.warn("UserDataManager: No student difficulty data for " + str(student)) Log.warn("UserDataManager: No student difficulty data for " + str(student))
return 0 return 0
return _student_difficulty.get_difficulty(minigame_name) return _student_difficulty.get_difficulty(minigame_name)
func update_difficulty_for_minigame(minigame_name: String, minigame_won: bool) -> void: func update_difficulty_for_minigame(minigame_name: String, minigame_won: bool) -> void:
if not _student_difficulty: if not _student_difficulty:
Logger.warn("UserDataManager: No student difficulty data for " + str(student)) Log.warn("UserDataManager: No student difficulty data for " + str(student))
return return
_student_difficulty.add_game(minigame_name, minigame_won) _student_difficulty.add_game(minigame_name, minigame_won)
@@ -812,14 +812,14 @@ func _load_student_speeches() -> void:
func _save_student_speeches() -> void: func _save_student_speeches() -> void:
Logger.trace("UserDataManager: Saving student speeches in " + ProjectSettings.globalize_path(_get_student_speeches_path())) Log.trace("UserDataManager: Saving student speeches in " + ProjectSettings.globalize_path(_get_student_speeches_path()))
ResourceSaver.save(_student_speeches, _get_student_speeches_path()) ResourceSaver.save(_student_speeches, _get_student_speeches_path())
func mark_speech_as_played(speech: String) -> void: func mark_speech_as_played(speech: String) -> void:
if not _student_speeches: if not _student_speeches:
if not Engine.is_editor_hint(): if not Engine.is_editor_hint():
Logger.warn("UserDataManager: No student speeches data for " + str(student)) Log.warn("UserDataManager: No student speeches data for " + str(student))
return return
_student_speeches.add_speech(speech) _student_speeches.add_speech(speech)
@@ -827,7 +827,7 @@ func mark_speech_as_played(speech: String) -> void:
func is_speech_played(speech: String) -> bool: func is_speech_played(speech: String) -> bool:
if not _student_speeches: if not _student_speeches:
if not Engine.is_editor_hint(): if not Engine.is_editor_hint():
Logger.warn("UserDataManager: No student speeches data for " + str(student)) Log.warn("UserDataManager: No student speeches data for " + str(student))
return false return false
return _student_speeches.is_speech_played(speech) return _student_speeches.is_speech_played(speech)
@@ -849,9 +849,9 @@ func move_user_device_folder(old_device: String, new_device: String, student_cod
if parent_dir.dir_exists(str(old_child_dir)): if parent_dir.dir_exists(str(old_child_dir)):
var err: Error = parent_dir.rename(old_child_dir, new_child_dir) var err: Error = parent_dir.rename(old_child_dir, new_child_dir)
if err != OK: if err != OK:
Logger.error("UserDataManager: Error while renaming folder: %s" % error_string(err)) Log.error("UserDataManager: Error while renaming folder: %s" % error_string(err))
else: else:
Logger.error("UserDataManager: The folder '%s' cannot be moved because it does no exists in %s." % [old_device, parent_dir_path]) Log.error("UserDataManager: The folder '%s' cannot be moved because it does no exists in %s." % [old_device, parent_dir_path])
return return
save_teacher_settings() save_teacher_settings()
@@ -874,7 +874,7 @@ func _scan_teacher_devices(match_callback: Callable) -> String:
var teacher_path: String = "user://".path_join(_device_settings.teacher) var teacher_path: String = "user://".path_join(_device_settings.teacher)
var dir: DirAccess = DirAccess.open(teacher_path) var dir: DirAccess = DirAccess.open(teacher_path)
if not dir: if not dir:
Logger.error("UserDataManager: Impossible to open teacher folder: %s" % teacher_path) Log.error("UserDataManager: Impossible to open teacher folder: %s" % teacher_path)
return "" return ""
var language: String = _device_settings.language var language: String = _device_settings.language
@@ -899,7 +899,7 @@ func _scan_teacher_devices(match_callback: Callable) -> String:
sub_file = lang_subdir.get_next() sub_file = lang_subdir.get_next()
lang_subdir.list_dir_end() lang_subdir.list_dir_end()
else: else:
Logger.warn("UserDataManager: Device folder %s has no language sub-folder" % device_dir) Log.warn("UserDataManager: Device folder %s has no language sub-folder" % device_dir)
file_name = dir.get_next() file_name = dir.get_next()
dir.list_dir_end() dir.list_dir_end()
@@ -47,7 +47,7 @@ func _pull_timestamps() -> Dictionary:
set_loading_bar_text("SYNCHRONIZATION_ASK_SERVER_TIMESTAMP") set_loading_bar_text("SYNCHRONIZATION_ASK_SERVER_TIMESTAMP")
var res: Dictionary = await (ServerManager as ServerManagerClass).pull_timestamps() var res: Dictionary = await (ServerManager as ServerManagerClass).pull_timestamps()
if not res.success: if not res.success:
Logger.trace("UserDatabaseSynchronizer: Cannot get all timestamps from server. Canceling synchronization.") Log.trace("UserDatabaseSynchronizer: Cannot get all timestamps from server. Canceling synchronization.")
set_loading_bar_text("SYNCHRONIZATION_ERROR_NO_SERVER") set_loading_bar_text("SYNCHRONIZATION_ERROR_NO_SERVER")
stop_sync() stop_sync()
return {} return {}
@@ -58,13 +58,13 @@ func _pull_timestamps() -> Dictionary:
func _determine_user_update(response_body: Dictionary) -> UpdateNeeded: func _determine_user_update(response_body: Dictionary) -> UpdateNeeded:
set_loading_bar_text("SYNCHRONIZATION_COMPARE_SERVER_TIMESTAMP") set_loading_bar_text("SYNCHRONIZATION_COMPARE_SERVER_TIMESTAMP")
if not response_body.has("user"): if not response_body.has("user"):
Logger.trace("UserDatabaseSynchronizer: Cannot get user from body. Canceling synchronization.") Log.trace("UserDatabaseSynchronizer: Cannot get user from body. Canceling synchronization.")
set_loading_bar_text("SYNCHRONIZATION_ERROR_NO_BODY_FROM_SERVER") set_loading_bar_text("SYNCHRONIZATION_ERROR_NO_BODY_FROM_SERVER")
stop_sync() stop_sync()
return UpdateNeeded.Nothing return UpdateNeeded.Nothing
var user: Dictionary = response_body.user var user: Dictionary = response_body.user
if not user.has("last_modified"): if not user.has("last_modified"):
Logger.trace("UserDatabaseSynchronizer: Cannot get last_modified from user. Canceling synchronization.") Log.trace("UserDatabaseSynchronizer: Cannot get last_modified from user. Canceling synchronization.")
set_loading_bar_text("SYNCHRONIZATION_ERROR") set_loading_bar_text("SYNCHRONIZATION_ERROR")
stop_sync() stop_sync()
return UpdateNeeded.Nothing return UpdateNeeded.Nothing
@@ -75,7 +75,7 @@ func _determine_user_update(response_body: Dictionary) -> UpdateNeeded:
local_unix_time_user = Time.get_unix_time_from_datetime_string(local_user_string_time) local_unix_time_user = Time.get_unix_time_from_datetime_string(local_user_string_time)
var need_update_user: UpdateNeeded = UpdateNeeded.Nothing var need_update_user: UpdateNeeded = UpdateNeeded.Nothing
if local_unix_time_user == server_unix_time_user: if local_unix_time_user == server_unix_time_user:
Logger.trace("UserDatabaseSynchronizer: User data timestamp is the same in local and on server. No synchronization necessary") Log.trace("UserDatabaseSynchronizer: User data timestamp is the same in local and on server. No synchronization necessary")
elif local_unix_time_user > server_unix_time_user: elif local_unix_time_user > server_unix_time_user:
need_update_user = UpdateNeeded.FromLocal need_update_user = UpdateNeeded.FromLocal
else: else:
@@ -86,7 +86,7 @@ func _determine_user_update(response_body: Dictionary) -> UpdateNeeded:
func _determine_students_update(response_body: Dictionary, need_update_user: UpdateNeeded) -> Dictionary: func _determine_students_update(response_body: Dictionary, need_update_user: UpdateNeeded) -> Dictionary:
var need_update_students: Dictionary[int, Dictionary] = {} var need_update_students: Dictionary[int, Dictionary] = {}
if not response_body.has("students"): if not response_body.has("students"):
Logger.trace("UserDatabaseSynchronizer: Cannot get last_modified from user. Canceling synchronization.") Log.trace("UserDatabaseSynchronizer: Cannot get last_modified from user. Canceling synchronization.")
set_loading_bar_text("SYNCHRONIZATION_ERROR") set_loading_bar_text("SYNCHRONIZATION_ERROR")
stop_sync() stop_sync()
return {} return {}
@@ -101,7 +101,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
if student_dic.has("updated_at"): if student_dic.has("updated_at"):
server_student_unix_time = Time.get_unix_time_from_datetime_string(student_dic.updated_at as String) server_student_unix_time = Time.get_unix_time_from_datetime_string(student_dic.updated_at as String)
else: else:
Logger.warn("UserDatabaseSynchronizer: Student %d received from server has no timestamp" % code_to_check) Log.warn("UserDatabaseSynchronizer: Student %d received from server has no timestamp" % code_to_check)
var server_student_progression_unix_time: int = -1 var server_student_progression_unix_time: int = -1
if student_dic.has("progression_last_modified"): if student_dic.has("progression_last_modified"):
@@ -147,7 +147,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
# Synchronize student data # Synchronize student data
var local_student_unix_time: int = Time.get_unix_time_from_datetime_string(student_data.last_modified) var local_student_unix_time: int = Time.get_unix_time_from_datetime_string(student_data.last_modified)
if local_student_unix_time == server_student_unix_time: if local_student_unix_time == server_student_unix_time:
Logger.trace("UserDatabaseSynchronizer: Student %d data timestamp is the same in local and on server. No synchronization necessary" % code_to_check) Log.trace("UserDatabaseSynchronizer: Student %d data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
need_update_students[code_to_check].merge({"data": UpdateNeeded.Nothing}) need_update_students[code_to_check].merge({"data": UpdateNeeded.Nothing})
elif local_student_unix_time > server_student_unix_time: elif local_student_unix_time > server_student_unix_time:
need_update_students[code_to_check].merge({"data": UpdateNeeded.FromLocal}) need_update_students[code_to_check].merge({"data": UpdateNeeded.FromLocal})
@@ -158,7 +158,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
var student_progression: StudentProgression = UserDataManager.get_student_progression_for_code(device, code_to_check) var student_progression: StudentProgression = UserDataManager.get_student_progression_for_code(device, code_to_check)
var local_student_progression_unix_time: int = Time.get_unix_time_from_datetime_string(student_progression.last_modified) var local_student_progression_unix_time: int = Time.get_unix_time_from_datetime_string(student_progression.last_modified)
if local_student_progression_unix_time == server_student_progression_unix_time: if local_student_progression_unix_time == server_student_progression_unix_time:
Logger.trace("UserDatabaseSynchronizer: Student %d progression data timestamp is the same in local and on server. No synchronization necessary" % code_to_check) Log.trace("UserDatabaseSynchronizer: Student %d progression data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
need_update_students[code_to_check].merge({"progression": UpdateNeeded.Nothing}) need_update_students[code_to_check].merge({"progression": UpdateNeeded.Nothing})
elif local_student_progression_unix_time > server_student_progression_unix_time: elif local_student_progression_unix_time > server_student_progression_unix_time:
need_update_students[code_to_check].merge({"progression": UpdateNeeded.FromLocal}) need_update_students[code_to_check].merge({"progression": UpdateNeeded.FromLocal})
@@ -170,7 +170,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
if student_remediation != null: if student_remediation != null:
var local_student_gp_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.gp_last_modified) var local_student_gp_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.gp_last_modified)
if local_student_gp_remediation_unix_time == server_student_remediation_gp_unix_time: if local_student_gp_remediation_unix_time == server_student_remediation_gp_unix_time:
Logger.trace("UserDatabaseSynchronizer: Student %d GP remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check) Log.trace("UserDatabaseSynchronizer: Student %d GP remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
need_update_students[code_to_check].merge({"remediation_gp": UpdateNeeded.Nothing}) need_update_students[code_to_check].merge({"remediation_gp": UpdateNeeded.Nothing})
elif local_student_gp_remediation_unix_time > server_student_remediation_gp_unix_time: elif local_student_gp_remediation_unix_time > server_student_remediation_gp_unix_time:
need_update_students[code_to_check].merge({"remediation_gp": UpdateNeeded.FromLocal}) need_update_students[code_to_check].merge({"remediation_gp": UpdateNeeded.FromLocal})
@@ -179,7 +179,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
var local_student_syllables_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.syllables_last_modified) var local_student_syllables_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.syllables_last_modified)
if local_student_syllables_remediation_unix_time == server_student_remediation_syllables_unix_time: if local_student_syllables_remediation_unix_time == server_student_remediation_syllables_unix_time:
Logger.trace("UserDatabaseSynchronizer: Student %d syllables remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check) Log.trace("UserDatabaseSynchronizer: Student %d syllables remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
need_update_students[code_to_check].merge({"remediation_syllables": UpdateNeeded.Nothing}) need_update_students[code_to_check].merge({"remediation_syllables": UpdateNeeded.Nothing})
elif local_student_syllables_remediation_unix_time > server_student_remediation_syllables_unix_time: elif local_student_syllables_remediation_unix_time > server_student_remediation_syllables_unix_time:
need_update_students[code_to_check].merge({"remediation_syllables": UpdateNeeded.FromLocal}) need_update_students[code_to_check].merge({"remediation_syllables": UpdateNeeded.FromLocal})
@@ -188,7 +188,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
var local_student_words_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.words_last_modified) var local_student_words_remediation_unix_time: int = Time.get_unix_time_from_datetime_string(student_remediation.words_last_modified)
if local_student_words_remediation_unix_time == server_student_remediation_words_unix_time: if local_student_words_remediation_unix_time == server_student_remediation_words_unix_time:
Logger.trace("UserDatabaseSynchronizer: Student %d words remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check) Log.trace("UserDatabaseSynchronizer: Student %d words remediation data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
need_update_students[code_to_check].merge({"remediation_words": UpdateNeeded.Nothing}) need_update_students[code_to_check].merge({"remediation_words": UpdateNeeded.Nothing})
elif local_student_words_remediation_unix_time > server_student_remediation_words_unix_time: elif local_student_words_remediation_unix_time > server_student_remediation_words_unix_time:
need_update_students[code_to_check].merge({"remediation_words": UpdateNeeded.FromLocal}) need_update_students[code_to_check].merge({"remediation_words": UpdateNeeded.FromLocal})
@@ -200,7 +200,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
if student_confusion_matrix != null: 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) var local_student_gp_confusion_matrix_unix_time: int = Time.get_unix_time_from_datetime_string(student_confusion_matrix.gp_last_modified)
if local_student_gp_confusion_matrix_unix_time == server_student_confusion_matrix_gp_unix_time: if local_student_gp_confusion_matrix_unix_time == server_student_confusion_matrix_gp_unix_time:
Logger.trace("UserDatabaseSynchronizer: Student %d GP confusion matrix data timestamp is the same in local and on server. No synchronization necessary" % code_to_check) Log.trace("UserDatabaseSynchronizer: Student %d GP confusion matrix data timestamp is the same in local and on server. No synchronization necessary" % code_to_check)
need_update_students[code_to_check].merge({"confusion_matrix_gp": UpdateNeeded.Nothing}) need_update_students[code_to_check].merge({"confusion_matrix_gp": UpdateNeeded.Nothing})
elif local_student_gp_confusion_matrix_unix_time > server_student_confusion_matrix_gp_unix_time: elif local_student_gp_confusion_matrix_unix_time > server_student_confusion_matrix_gp_unix_time:
need_update_students[code_to_check].merge({"confusion_matrix_gp": UpdateNeeded.FromLocal}) need_update_students[code_to_check].merge({"confusion_matrix_gp": UpdateNeeded.FromLocal})
@@ -219,7 +219,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
elif need_update_user == UpdateNeeded.FromLocal: elif need_update_user == UpdateNeeded.FromLocal:
need_update_students[code_to_check]["data"] = UpdateNeeded.DeleteServer need_update_students[code_to_check]["data"] = UpdateNeeded.DeleteServer
else: else:
Logger.warn("UserDatabaseSynchronizer: Student %d not found in local, but user doesn't need to be updated...this is theoretically not possible" % code_to_check) 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)
for device: int in UserDataManager.teacher_settings.students.keys(): for device: int in UserDataManager.teacher_settings.students.keys():
var students_in_device: Array[StudentData] = UserDataManager.teacher_settings.students[device] var students_in_device: Array[StudentData] = UserDataManager.teacher_settings.students[device]
@@ -232,7 +232,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
need_update_students[student_data.code] = {} need_update_students[student_data.code] = {}
need_update_students[student_data.code]["data"] = UpdateNeeded.FromLocal need_update_students[student_data.code]["data"] = UpdateNeeded.FromLocal
else: else:
Logger.warn("UserDatabaseSynchronizer: Student %d not found in server, but user doesn't need to be updated...this is theoretically not possible" % student_data.code) 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 return need_update_students
@@ -269,11 +269,11 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
elif student_update == UpdateNeeded.FromLocal: elif student_update == UpdateNeeded.FromLocal:
var device_id: int = UserDataManager.teacher_settings.get_student_device(student_code) var device_id: int = UserDataManager.teacher_settings.get_student_device(student_code)
if device_id == -1: if device_id == -1:
Logger.error("UserDatabaseSynchronizer: Student code %s has no device ID" % student_code) Log.error("UserDatabaseSynchronizer: Student code %s has no device ID" % student_code)
continue continue
var student_data: StudentData = UserDataManager.teacher_settings.get_student_with_code(student_code) var student_data: StudentData = UserDataManager.teacher_settings.get_student_with_code(student_code)
if not student_data: if not student_data:
Logger.warn("UserDatabaseSynchronizer: Cannot find student with code %d" % student_code) Log.warn("UserDatabaseSynchronizer: Cannot find student with code %d" % student_code)
continue continue
student_block.merge({ student_block.merge({
"device_id": device_id, "device_id": device_id,
@@ -288,7 +288,7 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
# Traitement des data de progression # Traitement des data de progression
var student_progression: StudentProgression = UserDataManager.get_student_progression_for_code(0, student_code) var student_progression: StudentProgression = UserDataManager.get_student_progression_for_code(0, student_code)
if student_progression == null: if student_progression == null:
Logger.trace("Cannot find progression data for student %s" % str(student_code)) Log.trace("Cannot find progression data for student %s" % str(student_code))
elif student_entry.has("progression"): elif student_entry.has("progression"):
var progression_block: Dictionary = {} var progression_block: Dictionary = {}
if student_entry.progression == UpdateNeeded.FromLocal: if student_entry.progression == UpdateNeeded.FromLocal:
@@ -381,11 +381,11 @@ func _send_instructions(message_to_server: Dictionary) -> Dictionary:
await set_loading_bar_progression(60.0) await set_loading_bar_progression(60.0)
set_loading_bar_text("SYNCHRONIZATION_SEND_SERVER_INSTRUCTIONS") set_loading_bar_text("SYNCHRONIZATION_SEND_SERVER_INSTRUCTIONS")
if message_to_server.keys().size() == 0: if message_to_server.keys().size() == 0:
Logger.trace("UserDatabaseSynchronizer: No instruction to send to server") Log.trace("UserDatabaseSynchronizer: No instruction to send to server")
return {} return {}
var res_get_server_instructions: Dictionary = await (ServerManager as ServerManagerClass).send_server_synchronization_instructions(message_to_server) var res_get_server_instructions: Dictionary = await (ServerManager as ServerManagerClass).send_server_synchronization_instructions(message_to_server)
if not res_get_server_instructions.success: if not res_get_server_instructions.success:
Logger.trace("UserDatabaseSynchronizer: Cannot send instructions to server. Canceling synchronization.") Log.trace("UserDatabaseSynchronizer: Cannot send instructions to server. Canceling synchronization.")
set_loading_bar_text("SYNCHRONIZATION_ERROR_NO_SERVER") set_loading_bar_text("SYNCHRONIZATION_ERROR_NO_SERVER")
stop_sync() stop_sync()
return {} return {}
@@ -397,21 +397,21 @@ func _send_instructions(message_to_server: Dictionary) -> Dictionary:
func _apply_server_response(response_body: Dictionary) -> void: func _apply_server_response(response_body: Dictionary) -> void:
if response_body.has("user"): if response_body.has("user"):
var response_user: Dictionary = response_body.user var response_user: Dictionary = response_body.user
Logger.trace("UserDatabaseSynchronizer: Updating user") Log.trace("UserDatabaseSynchronizer: Updating user")
if not response_user.has("account_type"): if not response_user.has("account_type"):
Logger.warn("UserDatabaseSynchronizer: While updating user, no account_type found") Log.warn("UserDatabaseSynchronizer: While updating user, no account_type found")
else: else:
UserDataManager.teacher_settings.account_type = response_user.account_type UserDataManager.teacher_settings.account_type = response_user.account_type
if not response_user.has("education_method"): if not response_user.has("education_method"):
Logger.warn("UserDatabaseSynchronizer: While updating user, no education_method found") Log.warn("UserDatabaseSynchronizer: While updating user, no education_method found")
else: else:
UserDataManager.teacher_settings.education_method = response_user.education_method UserDataManager.teacher_settings.education_method = response_user.education_method
if not response_user.has("last_modified"): if not response_user.has("last_modified"):
Logger.warn("UserDatabaseSynchronizer: While updating user, no last_modified found") Log.warn("UserDatabaseSynchronizer: While updating user, no last_modified found")
else: else:
UserDataManager.teacher_settings.last_modified = response_user.last_modified UserDataManager.teacher_settings.last_modified = response_user.last_modified
if response_body.has("students"): if response_body.has("students"):
Logger.trace("UserDatabaseSynchronizer: Updating students") Log.trace("UserDatabaseSynchronizer: Updating students")
var response_students: Dictionary = response_body.students var response_students: Dictionary = response_body.students
for response_student_code: String in response_students.keys(): for response_student_code: String in response_students.keys():
var response_student_data: Dictionary = response_students[response_student_code] var response_student_data: Dictionary = response_students[response_student_code]
@@ -466,9 +466,9 @@ func _apply_server_response(response_body: Dictionary) -> void:
func synchronize() -> void: func synchronize() -> void:
Logger.trace("UserDatabaseSynchronizer: Start synchronizing user data.") Log.trace("UserDatabaseSynchronizer: Start synchronizing user data.")
if synchronizing: if synchronizing:
Logger.trace("UserDatabaseSynchronizer: User synchronization already started, cancel double-call.") Log.trace("UserDatabaseSynchronizer: User synchronization already started, cancel double-call.")
return return
await start_sync() await start_sync()
@@ -513,7 +513,7 @@ func validate_student_data(data: Dictionary) -> bool:
if missing.is_empty(): if missing.is_empty():
return true return true
Logger.trace("UserDatabaseSynchronizer: Student data is incomplete. Missing keys: %s" % str(missing)) Log.trace("UserDatabaseSynchronizer: Student data is incomplete. Missing keys: %s" % str(missing))
return false return false
+3 -3
View File
@@ -39,13 +39,13 @@ func clean_dir(path: String) -> Error:
func delete_directory_recursive(path: String) -> void: func delete_directory_recursive(path: String) -> void:
var err: Error = clean_dir(path) var err: Error = clean_dir(path)
if err != OK: if err != OK:
Logger.error("Utils: Error " + error_string(err) + " while cleaning folder: %s" % path) Log.error("Utils: Error " + error_string(err) + " while cleaning folder: %s" % path)
return return
err = DirAccess.remove_absolute(path) err = DirAccess.remove_absolute(path)
if err != OK: if err != OK:
Logger.error("Utils: Error " + error_string(err) + " while deleting folder: %s" % path) Log.error("Utils: Error " + error_string(err) + " while deleting folder: %s" % path)
else: else:
Logger.info("Utils: Folder deleted: %s" % path) Log.info("Utils: Folder deleted: %s" % path)
## Returns -1 if version_a is lower than version_b, 0 if they are equals, and 1 if version_a is greater than version_b ## Returns -1 if version_a is lower than version_b, 0 if they are equals, and 1 if version_a is greater than version_b
+2 -2
View File
@@ -35,7 +35,7 @@ func read(resource: Resource) -> void:
var property_value: Variant = data.get(binder.property_name) var property_value: Variant = data.get(binder.property_name)
binder.set_value(property_value) binder.set_value(property_value)
else: else:
Logger.warn("FormBinder: Property " + binder.property_name + " not found in " + data.get_class()) Log.warn("FormBinder: Property " + binder.property_name + " not found in " + data.get_class())
func write() -> bool: func write() -> bool:
@@ -47,6 +47,6 @@ func write() -> bool:
if binder.property_name in data: if binder.property_name in data:
data.set(binder.property_name as StringName, binder.get_value()) data.set(binder.property_name as StringName, binder.get_value())
else: else:
Logger.warn("FormBinder: Property " + str(binder.property_name) + " not found in " + data.get_class()) Log.warn("FormBinder: Property " + str(binder.property_name) + " not found in " + data.get_class())
return true return true