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
@@ -43,7 +43,7 @@ func validate() -> bool:
continue
var control: Control = info.control as Control
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
var passed = info.validator.validate(control)
var messages = info.validator.get_messages()
@@ -62,7 +62,7 @@ func _get_validator_info_list() -> Array[ValidatorInfo]:
for controlKey in _control_validator_map.keys():
var control: Control = controlKey as Control
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
var validator = _control_validator_map[control]
if not validator:
@@ -5,7 +5,7 @@ class_name ValidatorFunctions
static func matches(pattern: String, text: String) -> bool:
var regex = RegEx.create_from_string(pattern)
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
var result = regex.search(text)
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:
var regex = RegEx.create_from_string(pattern)
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
var result = regex.search(text)
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:
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)
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()
return ""
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()
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 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 error: Error = FileAccess.get_open_error()
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()
return first_folder
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()
return first_folder
if file != null:
file.store_buffer(read_file(sub_path))
file.close()
Logger.trace("FolderUnzipper: Copied %s" % file_name)
Log.trace("FolderUnzipper: Copied %s" % file_name)
copied_file += 1
file_copied.emit(copied_file, file_name)
close()
finished.emit()
Logger.trace("FolderUnzipper: Extraction finished in %s" % extract_folder)
Log.trace("FolderUnzipper: Extraction finished in %s" % extract_folder)
return first_folder
+6 -6
View File
@@ -23,7 +23,7 @@ func write_folder_recursive(abs_path: String, rel_path: String) -> Error:
close()
return error
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)
if error != OK:
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)
error = FileAccess.get_open_error()
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()
return error
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:
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)
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()
return
path = path.simplify_path()
err = write_folder_recursive(path.get_base_dir(), path.get_file())
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()
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/version="2.1.6"
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)
config/icon="res://assets/kalulu_icon.png"
custom/unlock_everything=false
@@ -25,7 +25,7 @@ buses/default_bus_layout="res://resources/audio_buses/main_audio_bus_layout.tres
[autoload]
Logger="*res://sources/utils/autoloads/logger.gd"
Log="*res://sources/utils/autoloads/logger.gd"
LessonLogger="*res://sources/utils/autoloads/lesson_logger.gd"
ServerManager="*res://sources/utils/autoloads/server_manager.tscn"
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:
if student_data.code == student_code:
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)
UserDataManager.save_all()
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:
@@ -74,18 +74,18 @@ func update_student_device(student_code: int, new_student_device: int) -> void:
for student_data: StudentData in students_data:
if student_data.code == student_code:
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
students_data.erase(student_data)
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].append(student_data)
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)
UserDataManager.save_all()
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:
@@ -148,7 +148,7 @@ func delete_student(student_code: int) -> void:
if students[device].is_empty():
students.erase(device)
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:
@@ -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.last_modified = new_last_modified
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:
if not minigame_scores or minigame_scores.is_empty():
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():
var given_list: PackedInt32Array = minigame_scores[expected_id]
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:
if not minigame_scores:
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():
var new_gp_score: int = get_gp_score(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:
if not minigame_scores:
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():
var new_syllable_score: int = get_syllable_score(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:
if not minigame_scores:
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():
var new_word_score: int = get_word_score(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"):
starting_garden = transition_data.current_garden_index
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
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]:
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 lessons_left: int = total_lessons
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 error: Error = FileAccess.get_open_error()
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
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
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":
+1 -1
View File
@@ -108,7 +108,7 @@ func insert_in_database() -> void:
if not Database.db.query_result.is_empty():
var element: Dictionary = Database.db.query_result[0]
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})
return
@@ -51,10 +51,10 @@ func set_sound_preview(sound_path: String) -> void:
var file: FileAccess = FileAccess.open(sound_path, FileAccess.READ)
var error: Error = FileAccess.get_open_error()
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
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
var sound: AudioStreamMP3 = AudioStreamMP3.new()
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:
return (data as Dictionary).has("gp_id")
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
func _drop_data_in_gp_container(_at_position: Vector2, data: Variant) -> void:
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
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
var new_gp_label: LessonGPLabel = gp_label_scene.instantiate()
new_gp_label.grapheme = data.grapheme
@@ -80,13 +80,13 @@ func _can_drop_data(at_position: Vector2, data: Variant) -> bool:
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)
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
func _drop_data(at_position: Vector2, data: Variant) -> void:
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
if not (data as Dictionary).has("number") or (data as Dictionary).has("gp_id"):
return
+2 -2
View File
@@ -35,13 +35,13 @@ func _can_drop_data(_at_position: Vector2, data: Variant) -> bool:
if data is Dictionary:
return (data as Dictionary).has("gp_id") and data.gp_id != gp_id
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
func _drop_data(at_position: Vector2, data: Variant) -> void:
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"):
return
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
error_label.text = "Database integrity checks lesson " + str(lesson_id)
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)
for new_gp: Dictionary in new_gps_for_lesson:
@@ -264,7 +264,7 @@ func _check_db_integrity() -> void:
integrity_checking = false
if check_box_log.button_pressed:
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)
#endregion
@@ -283,7 +283,7 @@ func log_message(message: String) -> bool:
file.store_line(message)
file.close()
else:
Logger.warn("ProfToolMenu: Integrity log file not found")
Log.warn("ProfToolMenu: Integrity log file not found")
return true
else:
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: FileAccess = FileAccess.open(file_path, FileAccess.READ)
if file == null:
Logger.error("ProfToolMenu: Error opening file: " + file_path)
Log.error("ProfToolMenu: Error opening file: " + file_path)
continue
if file.eof_reached():
@@ -590,7 +590,7 @@ func create_book() -> void:
var values: PackedStringArray = parse_csv_line(line)
if values.size() != raw_headers.size():
Logger.warn("ProfToolMenu: Malformed line ignored: %s" % values)
Log.warn("ProfToolMenu: Malformed line ignored: %s" % values)
continue
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_file: FileAccess = FileAccess.open(output_path, FileAccess.WRITE)
if output_file == null:
Logger.error("ProfToolMenu: Impossible to write: " + output_path)
Log.error("ProfToolMenu: Impossible to write: " + output_path)
return
output_file.store_line(escape_csv_line(PackedStringArray(ordered_headers)))
@@ -638,7 +638,7 @@ func create_book() -> void:
output_file.close()
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
+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 error: Error = FileAccess.get_open_error()
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
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
while not file.eof_reached():
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 error: Error = FileAccess.get_open_error()
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
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
for segment: SegmentBuild in segments:
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 result: bool = Database.db.query(alter_sql)
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:
@@ -136,7 +136,7 @@ func _on_element_new_gp_asked(ind: int, element: WordListElement) -> void:
elif new_gp is GPListElement:
(new_gp as GPListElement).edit_mode()
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:
@@ -150,7 +150,7 @@ func _on_gp_list_element_validated() -> void:
elif new_gp is GPListElement:
(new_gp as GPListElement).insert_in_database()
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 as Object).has_method("update_lesson"):
if new_gp is WordListElement:
@@ -158,9 +158,9 @@ func _on_gp_list_element_validated() -> void:
elif new_gp is SentenceListElement:
(new_gp as SentenceListElement).update_lesson()
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:
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
create_sub_elements_list()
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:
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"
return
var file: FileAccess = FileAccess.open(path, FileAccess.READ)
var error: Error = FileAccess.get_open_error()
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
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
var line: PackedStringArray = file.get_csv_line()
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]
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():
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:
@@ -327,7 +327,7 @@ func _add_from_additional_word_list(new_text: String) -> int:
func _try_to_complete_from_word(new_text: String) -> int:
var index: int = _already_in_database(new_text)
if index >= 0:
Logger.trace("WordListElement: Already in DB " + new_text)
Log.trace("WordListElement: Already in DB " + new_text)
return index
index = _add_from_additional_word_list(new_text)
+4 -4
View File
@@ -30,7 +30,7 @@ func _ready() -> void:
gardens_data = transition_data
transition_data = {}
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()
await OpeningCurtain.open()
@@ -39,7 +39,7 @@ func setup() -> void:
gp_list = Database.get_gps_for_lesson(lesson_nb, true, true)
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()
_on_tracing_manager_finished()
return
@@ -114,14 +114,14 @@ func _on_grapheme_button_pressed() -> void:
0:
current_button_pressed += 1
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
animation_player.play("to_videos")
loop = false
1:
current_button_pressed += 1
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
animation_player.play("to_images_and_sounds")
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 error: Error = FileAccess.get_open_error()
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
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
while not file.eof_reached():
var points: Array[Vector2] = []
@@ -46,7 +46,7 @@ func _draw_password() -> void:
var index: int = 0
for value: String in password.split(""):
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
if value in ICONS_TEXTURES:
@@ -27,6 +27,6 @@ func _refresh() -> 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):
get_tree().change_scene_to_file(LOGIN_SCENE_PATH)
@@ -34,7 +34,7 @@ var current_language_version: Dictionary = {}
func _ready() -> void:
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)
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_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():
# Offline mode, if a pack is already downloaded, go to next scene
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
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:
server_language_version = Time.get_datetime_dict_from_datetime_string(res.body.last_modified as String, false)
# 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 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()
download_label.show()
@@ -95,7 +95,7 @@ func _ready() -> void:
# Download the pack
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)
else:
download_bar.value = 1
@@ -108,10 +108,10 @@ func is_language_directory_valid(path: String) -> bool:
var dir: DirAccess = DirAccess.open(path)
var error: Error = DirAccess.get_open_error()
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
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
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")):
return
Logger.trace("PackageDownloader: Extracting downloaded package")
Log.trace("PackageDownloader: Extracting downloaded package")
var language_zip: String = device_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
var subfolder: String = unzipper.extract(language_zip_path, USER_LANGUAGE_RESOURCES_PATH, false)
if subfolder == "":
Logger.error("PackageDownloader: Extraction failed for %s" % language_zip_path)
Log.error("PackageDownloader: Extraction failed for %s" % language_zip_path)
return
# 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)
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:
Logger.trace("PackageDownloader: Package extracted to %s" % current_language_path)
Log.trace("PackageDownloader: Package extracted to %s" % current_language_path)
# Cleanup unnecessary files
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
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:
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:
mutex = Mutex.new()
thread = Thread.new()
+1 -1
View File
@@ -35,7 +35,7 @@ func _process(delta: float) -> void:
func _play_speech(speech: AudioStream) -> void:
if not speech:
Logger.warn("Kalulu: Speech not found")
Log.warn("Kalulu: Speech not found")
is_speaking = false
return
is_speaking = true
+3 -10
View File
@@ -33,9 +33,7 @@ fail_message = "A value is required."
[sub_resource type="Resource" id="Resource_owox8"]
script = ExtResource("20_6xsd1")
validation_order = 1
validation_method = 1
skip_validation = false
rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_mh75v")])
[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"]
script = ExtResource("21_1bl4i")
validation_order = 1
validation_method = 1
skip_validation = false
rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_j516d"), SubResource("Resource_ayewh")])
[sub_resource type="Resource" id="Resource_b08p8"]
@@ -59,9 +55,7 @@ fail_message = "A value is required."
[sub_resource type="Resource" id="Resource_k2y4u"]
script = ExtResource("21_1bl4i")
validation_order = 1
validation_method = 1
skip_validation = false
rules = Array[ExtResource("18_5m8xx")]([SubResource("Resource_b08p8")])
[sub_resource type="Gradient" id="Gradient_22q4u"]
@@ -123,7 +117,7 @@ grow_vertical = 2
script = ExtResource("8_cxg8l")
[node name="Title" type="TextureRect" parent="Kalulu"]
layout_mode = 2
layout_mode = 0
offset_left = -324.0
offset_top = -644.0
offset_right = 323.0
@@ -135,7 +129,7 @@ texture = ExtResource("7_ftt26")
[node name="Background" type="TextureRect" parent="Kalulu"]
custom_minimum_size = Vector2(868, 868)
layout_mode = 2
layout_mode = 0
offset_left = -434.0
offset_top = -250.0
offset_right = 434.0
@@ -376,7 +370,7 @@ grow_vertical = 0
[node name="BuildVersionTitle" type="Label" parent="Informations"]
custom_minimum_size = Vector2(400, 0)
layout_mode = 2
layout_mode = 0
offset_left = 10.0
offset_right = 261.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="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="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"]
+2 -2
View File
@@ -56,12 +56,12 @@ func _on_back_button_pressed() -> void:
func _on_validate_button_pressed() -> void:
# Validate the fields
if not form_validator.validate():
Logger.warn("BaseStep: Validation failed (" + str(self) + ")")
Log.warn("BaseStep: Validation failed (" + str(self) + ")")
return
# Writes data in object
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
if _on_next():
@@ -9,12 +9,12 @@ func _on_validate_button_pressed() -> void:
# Validate the fields
if not form_validator.validate():
Logger.warn("CredentialsStep: Validation failed (" + str(self) + ")")
Log.warn("CredentialsStep: Validation failed (" + str(self) + ")")
return
# Writes data in object
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
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_number = element.LessonNb
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
student_unlock.unlocks = progression.unlocks
lesson_container.add_child(student_unlock)
@@ -105,4 +105,4 @@ func _device_button_pressed(device_id: int) -> void:
device = device_id
var res_set: Dictionary = await ServerManager.set_student_data(student, {"device_id": device_id})
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.save_teacher_settings()
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:
@@ -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.save_teacher_settings()
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:
@@ -69,7 +69,7 @@ func refresh_devices_tabs() -> void:
child.queue_free()
if not UserDataManager.teacher_settings:
Logger.error("SettingsTeacherSettings: Teacher settings not found")
Log.error("SettingsTeacherSettings: Teacher settings not found")
return
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:
var current_tab: DeviceTab = devices_tab_container.get_current_tab_control() as DeviceTab
if not current_tab:
Logger.error("SettingsTeacherSettings: DeviceTab not found")
Log.error("SettingsTeacherSettings: DeviceTab not found")
return
var res: Dictionary = await ServerManager.add_student({"device": current_tab.device_id})
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.refresh()
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:
@@ -179,7 +179,7 @@ func update_student_name(student_code: int, student_name: String) -> void:
if student_panel.student_data.code == student_code:
student_panel.name_label.text = student_name
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
@@ -190,9 +190,9 @@ func _on_dashboard_button_pressed() -> void:
if (res.body as Dictionary).has("url"):
OS.shell_open(res.body.url as String)
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:
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:
@@ -204,6 +204,6 @@ func _on_loading_popup_ok() -> 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
+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:
var err: Error = get_tree().change_scene_to_file(MAIN_MENU_SCENE_PATH)
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:
+1 -1
View File
@@ -78,7 +78,7 @@ func _find_stimuli_and_distractions() -> void:
# Shuffle the stimuli
stimuli.shuffle()
Logger.trace("AntsMinigame: stimuli = " + str(stimuli))
Log.trace("AntsMinigame: stimuli = " + str(stimuli))
func _start() -> void:
+2 -2
View File
@@ -137,7 +137,7 @@ func _setup_minigame() -> void:
# Find the stimuli and distractions of the minigame.
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
@@ -272,7 +272,7 @@ func _submit_student_level_time() -> void:
#region Logs
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()
@@ -22,7 +22,7 @@ var is_stimulus_heard: bool = false:
func _start() -> void:
super()
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()
return
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"):
_update_remediation_syllable_score(_get_current_stimulus().ID as int, -1)
else:
Logger.error("SyllablesMinigame: current stimulus has no ID")
Log.error("SyllablesMinigame: current stimulus has no ID")
# Handles the pressed stimulus Gps
if stimulus.has("ID"):
_update_remediation_syllable_score(stimulus.ID as int, -1)
else:
Logger.warn("SyllablesMinigame: stimulus has no ID")
Log.warn("SyllablesMinigame: stimulus has no ID")
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()
await audio_player.finished
else:
Logger.warn("Kalulu: Speech not found")
Log.warn("Kalulu: Speech not found")
if hide_animation:
audio_player.stream = HIDE_SOUND
@@ -3,38 +3,38 @@ extends AudioStreamPlayer
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():
return
var phoneme_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_gp_sound_path(gp)) as 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
await play_audio_stream(phoneme_audiostream)
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():
return
var syllable_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_syllable_sound_path(syllable))
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
await play_audio_stream(syllable_audiostream)
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():
return
var word_audiostream: AudioStreamMP3 = Database.load_external_sound(Database.get_word_sound_path({Word = word}))
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
await play_audio_stream(word_audiostream)
@@ -92,7 +92,7 @@ func _find_stimuli_and_distractions() -> void:
func _start() -> void:
super()
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()
return
_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)
_update_confusion_matrix_gp_score(self._get_gp().ID as int, gp.ID as int)
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
if self._is_gp_right(gp):
+1 -1
View File
@@ -58,7 +58,7 @@ func _ready() -> void:
func _find_stimuli_and_distractions() -> void:
var data_array: Array[Dictionary] = Database.get_pseudowords_for_lesson(lesson_nb)
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
data_array.shuffle()
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"]
width = 128
height = 128
seamless_blend_skirt = 0.0
color_ramp = SubResource("Gradient_s16dt")
noise = SubResource("FastNoiseLite_c8rmy")
color_ramp = SubResource("Gradient_s16dt")
seamless_blend_skirt = 0.0
[resource]
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"]
width = 128
height = 128
seamless_blend_skirt = 0.0
color_ramp = SubResource("Gradient_q5on4")
noise = SubResource("FastNoiseLite_6xjnx")
color_ramp = SubResource("Gradient_q5on4")
seamless_blend_skirt = 0.0
[resource]
resource_local_to_scene = true
+2 -2
View File
@@ -29,11 +29,11 @@ const SCALE_FACTOR: float = 0.2
if animated_sprite_body:
animated_sprite_body.sprite_frames = ANIMATIONS_BODY[color]
else:
Logger.error("Jellyfish: no animated sprite body")
Log.error("Jellyfish: no animated sprite body")
if animated_sprite_arms:
animated_sprite_arms.sprite_frames = ANIMATIONS_ARMS[color]
else:
Logger.error("Jellyfish: no animated sprite arms")
Log.error("Jellyfish: no animated sprite arms")
scale = SCALES[color] * (1. + randf() * SCALE_FACTOR)
# Handles sprite size
@@ -69,14 +69,14 @@ func _find_stimuli_and_distractions() -> void:
for sentence: Dictionary in stimuli:
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
func _start() -> void:
super()
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()
return
_setup_word_progression()
@@ -161,7 +161,7 @@ func _on_snowball_thrown(pos: Vector2, label: PenguinLabel) -> void:
if label.gp.has("WordID"):
_update_remediation_word_score(label.gp.WordID as int, 1 if correct_answer else -1)
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:
penguin.happy()
@@ -46,7 +46,7 @@ func _setup_minigame() -> void:
spawn_timer.wait_time = settings.spawn_rate
for stimulus: Dictionary in stimuli:
Logger.trace("TurtleMinigame: %s" % stimulus.Word)
Log.trace("TurtleMinigame: %s" % stimulus.Word)
func _highlight() -> void:
+15 -15
View File
@@ -50,7 +50,7 @@ func connect_to_db() -> void:
if FileAccess.file_exists(db.path):
is_open = db.open_db()
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:
@@ -64,15 +64,15 @@ func load_additional_word_list() -> String:
var file: FileAccess = FileAccess.open(word_list_path, FileAccess.READ)
var error: Error = FileAccess.get_open_error()
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 ""
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 ""
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):
var msg: String = "word list should have columns ORTHO, PHON and GPMATCH"
Logger.error("Database: " + msg)
Log.error("Database: " + msg)
return msg
var ortho_index: int = title_line.find("ORTHO")
while not file.eof_reached():
@@ -85,7 +85,7 @@ func load_additional_word_list() -> String:
additional_word_list[line[ortho_index]] = data
file.close()
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 ""
@@ -181,7 +181,7 @@ func get_word_id_from_text(text: String) -> int:
if db.query_result.size() > 0:
if db.query_result[0].has("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
@@ -497,7 +497,7 @@ func get_audio_stream_for_phoneme(phoneme: String) -> AudioStream:
if FileAccess.file_exists(path) and ResourceLoader.exists(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
@@ -511,7 +511,7 @@ func get_gp_look_and_learn_image(gp: Dictionary) -> Texture:
var texture: ImageTexture = ImageTexture.create_from_image(image)
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
@@ -524,16 +524,16 @@ func get_gp_look_and_learn_sound(gp: Dictionary) -> AudioStream:
var file: FileAccess = FileAccess.open(path, FileAccess.READ)
var error: Error = FileAccess.get_open_error()
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
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
var sound: AudioStreamMP3 = AudioStreamMP3.new()
sound.data = file.get_buffer(file.get_length())
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
@@ -543,7 +543,7 @@ func get_gp_look_and_learn_video(gp: Dictionary) -> VideoStream:
var video: VideoStream = load(path)
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
@@ -588,16 +588,16 @@ func get_kalulu_speech_path(speech_category: String, speech_name: String) -> Str
func load_external_sound(path: String) -> AudioStreamMP3:
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
var file: FileAccess = FileAccess.open(path, FileAccess.READ)
var error: Error = FileAccess.get_open_error()
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
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
var audio_stream: AudioStreamMP3 = AudioStreamMP3.new()
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/"
1: environment_url = "https://uqkpbayw1k.execute-api.eu-west-3.amazonaws.com/prod/"
_: 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:
@@ -98,7 +98,7 @@ func get_user_data() -> Dictionary:
func update_student_remediation_data(student_code: int, student_remediation: UserRemediation) -> Dictionary:
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
code = -1
json = {}
@@ -134,7 +134,7 @@ func set_student_data(student_code: int, data: Dictionary) -> Dictionary:
#region Sender functions
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)
if res == OK:
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)
if content_type_json:
headers.append("Content-Type: application/json")
Logger.trace("ServerManager Create Header: " + str(headers))
Log.trace("ServerManager Create Header: " + str(headers))
return headers
@@ -177,13 +177,13 @@ func _get_request(uri: String, params: Dictionary) -> void:
reset_result()
var headers: PackedStringArray = _create_request_headers()
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:
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:
await request_completed
else:
Logger.error("ServerManager Error sending GET request")
Log.error("ServerManager Error sending GET request")
code = 500
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 headers: PackedStringArray = _create_request_headers()
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:
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:
await request_completed
else:
Logger.error("ServerManager Error sending POST request")
Log.error("ServerManager Error sending POST request")
code = 500
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 headers: PackedStringArray = _create_request_headers(true)
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:
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:
await request_completed
else:
Logger.error("ServerManager Error sending POST JSON request")
Log.error("ServerManager Error sending POST JSON request")
code = 500
json = {message = "Internal Server Error"}
@@ -224,11 +224,11 @@ func _delete_request(uri: String, params: Dictionary = {}) -> void:
reset_result()
var req: String = _create_uri_with_parameters(environment_url + uri, params)
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:
await request_completed
else:
Logger.error("ServerManager Error sending DELETE request")
Log.error("ServerManager Error sending DELETE request")
code = 500
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:
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:
code = response_code
if code == 200:
Logger.trace("ServerManager Request Completed. Response code = %d" % response_code)
Log.trace("ServerManager Request Completed. Response code = %d" % response_code)
else:
Logger.warn("ServerManager Request Completed. Response code = %d" % response_code)
Log.warn("ServerManager Request Completed. Response code = %d" % response_code)
if body:
var str_body: String = body.get_string_from_utf8()
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:
var pretty: String = JSON.stringify(result, "\t")
if code == 200:
Logger.trace("ServerManager Prettyfied Body received :\n%s" % pretty)
Log.trace("ServerManager Prettyfied Body received :\n%s" % pretty)
else:
Logger.warn("ServerManager Prettyfied Body received :\n%s" % pretty)
Log.warn("ServerManager Prettyfied Body received :\n%s" % pretty)
else:
if code == 200:
Logger.trace("ServerManager Body received = %s" % str_body)
Log.trace("ServerManager Body received = %s" % str_body)
else:
Logger.warn("ServerManager Body received = %s" % str_body)
Log.warn("ServerManager Body received = %s" % str_body)
if result != null:
json = result
else:
if code == 200:
Logger.trace("ServerManager: result null after parsing String to JSON")
Log.trace("ServerManager: result null after parsing String to JSON")
else:
Logger.warn("ServerManager: result null after parsing String to JSON")
Log.warn("ServerManager: result null after parsing String to JSON")
else:
if code == 200:
Logger.trace("ServerManager Body received is empty")
Log.trace("ServerManager Body received is empty")
else:
Logger.warn("ServerManager Body received is empty")
Log.warn("ServerManager Body received is empty")
success = result_code == OK and response_code == 200
request_completed.emit(success, response_code, json)
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:
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:
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
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
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 error: Error = DirAccess.get_open_error()
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
if not dir:
Logger.warn("UserDataManager: Could not open user:// directory for cleanup.")
Log.warn("UserDataManager: Could not open user:// directory for cleanup.")
return
dir.list_dir_begin()
var file_name: String = dir.get_next()
@@ -64,7 +64,7 @@ func purge_user_folders_if_needed() -> void:
file_name = dir.get_next()
dir.list_dir_end()
Logger.trace("UserDataManager: Purge completed")
Log.trace("UserDataManager: Purge completed")
_device_settings.game_version = current_version
ResourceSaver.save(_device_settings, "user://device_settings.tres")
@@ -98,7 +98,7 @@ func stop_synchronization_timer() -> void:
func register(register_settings: TeacherSettings) -> bool:
if not register_settings:
Logger.warn("UserDataManager: register called with invalid register_settings")
Log.warn("UserDataManager: register called with invalid register_settings")
return false
# Handles device settings
@@ -118,27 +118,27 @@ func register(register_settings: TeacherSettings) -> bool:
# Allow the user to log-in from the server
func login(infos: Dictionary) -> bool:
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
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
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
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
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
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
# 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:
if not FileAccess.file_exists(path):
Logger.error("UserDataManager: File not found: " + path)
Log.error("UserDataManager: File not found: " + path)
return null
var content: String = FileAccess.get_file_as_string(path)
for index: int in range(old_texts.size()):
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])
var file: FileAccess = FileAccess.open(path, FileAccess.WRITE)
var error: Error = FileAccess.get_open_error()
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
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
file.store_string(content)
file.close()
var resource: Resource = ResourceLoader.load(path)
if resource == null:
Logger.error("UserDataManager: Loading failed after correction: " + path)
Log.error("UserDataManager: Loading failed after correction: " + path)
else:
Logger.trace("UserDataManager: Loading success: " + path)
Log.trace("UserDataManager: Loading success: " + path)
return resource
func set_device_id(device: int) -> bool:
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
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
_device_settings.device_id = device
@@ -231,10 +231,10 @@ func delete_teacher_data() -> void:
func student_exists(code: String) -> bool:
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
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
var students: Array[StudentData] = teacher_settings.students[_device_settings.device_id] as Array[StudentData]
if students:
@@ -246,10 +246,10 @@ func student_exists(code: String) -> bool:
func login_student(code: String) -> bool:
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
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
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()
return true
Logger.warn("UserDataManager: login_student failed, code not found: " + code)
Log.warn("UserDataManager: login_student failed, code not found: " + code)
return false
func logout_student() -> bool:
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
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
student = ""
@@ -301,7 +301,7 @@ func _load_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())
@@ -415,7 +415,7 @@ func _load_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())
@@ -524,7 +524,7 @@ func _load_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())
@@ -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 error: Error = ResourceSaver.save(progression, progression_path)
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:
@@ -578,7 +578,7 @@ func set_student_progression_data(student_code: int, version: String, new_data:
current_data.last_modified = updated_at
var err: Error = ResourceSaver.save(current_data, get_student_progression_path(0, student_code))
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
@@ -613,7 +613,7 @@ func get_student_remediation_data(student_code: int) -> UserRemediation:
var student_remediation: UserRemediation
student_remediation = load(remediation_data_path)
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
@@ -654,7 +654,7 @@ func set_student_remediation_words_data(student_code: int, new_scores: Dictionar
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())
@@ -666,7 +666,7 @@ func get_gp_remediation_score(gp_id: int) -> int:
func update_remediation_gp_scores(remediation_gp_scores: Dictionary) -> void:
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
if 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:
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
if 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:
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
if 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
student_confusion_matrix = load(confusion_matrix_data_path)
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
@@ -737,7 +737,7 @@ func set_student_confusion_matrix_gp_data(student_code: int, new_scores: Diction
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())
@@ -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:
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
if 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:
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())
func get_difficulty_for_minigame(minigame_name: String) -> int:
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 _student_difficulty.get_difficulty(minigame_name)
func update_difficulty_for_minigame(minigame_name: String, minigame_won: bool) -> void:
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
_student_difficulty.add_game(minigame_name, minigame_won)
@@ -812,14 +812,14 @@ func _load_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())
func mark_speech_as_played(speech: String) -> void:
if not _student_speeches:
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
_student_speeches.add_speech(speech)
@@ -827,7 +827,7 @@ func mark_speech_as_played(speech: String) -> void:
func is_speech_played(speech: String) -> bool:
if not _student_speeches:
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 _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)):
var err: Error = parent_dir.rename(old_child_dir, new_child_dir)
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:
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
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 dir: DirAccess = DirAccess.open(teacher_path)
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 ""
var language: String = _device_settings.language
@@ -899,7 +899,7 @@ func _scan_teacher_devices(match_callback: Callable) -> String:
sub_file = lang_subdir.get_next()
lang_subdir.list_dir_end()
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()
dir.list_dir_end()
@@ -47,7 +47,7 @@ func _pull_timestamps() -> Dictionary:
set_loading_bar_text("SYNCHRONIZATION_ASK_SERVER_TIMESTAMP")
var res: Dictionary = await (ServerManager as ServerManagerClass).pull_timestamps()
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")
stop_sync()
return {}
@@ -58,13 +58,13 @@ func _pull_timestamps() -> Dictionary:
func _determine_user_update(response_body: Dictionary) -> UpdateNeeded:
set_loading_bar_text("SYNCHRONIZATION_COMPARE_SERVER_TIMESTAMP")
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")
stop_sync()
return UpdateNeeded.Nothing
var user: Dictionary = response_body.user
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")
stop_sync()
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)
var need_update_user: UpdateNeeded = UpdateNeeded.Nothing
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:
need_update_user = UpdateNeeded.FromLocal
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:
var need_update_students: Dictionary[int, Dictionary] = {}
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")
stop_sync()
return {}
@@ -101,7 +101,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
if student_dic.has("updated_at"):
server_student_unix_time = Time.get_unix_time_from_datetime_string(student_dic.updated_at as String)
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
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
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:
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})
elif local_student_unix_time > server_student_unix_time:
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 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:
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})
elif local_student_progression_unix_time > server_student_progression_unix_time:
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:
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:
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})
elif local_student_gp_remediation_unix_time > server_student_remediation_gp_unix_time:
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)
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})
elif local_student_syllables_remediation_unix_time > server_student_remediation_syllables_unix_time:
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)
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})
elif local_student_words_remediation_unix_time > server_student_remediation_words_unix_time:
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:
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:
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})
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})
@@ -219,7 +219,7 @@ func _determine_students_update(response_body: Dictionary, need_update_user: Upd
elif need_update_user == UpdateNeeded.FromLocal:
need_update_students[code_to_check]["data"] = UpdateNeeded.DeleteServer
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():
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]["data"] = UpdateNeeded.FromLocal
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
@@ -269,11 +269,11 @@ func _build_message_to_server(need_update_user: UpdateNeeded, need_update_studen
elif student_update == UpdateNeeded.FromLocal:
var device_id: int = UserDataManager.teacher_settings.get_student_device(student_code)
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
var student_data: StudentData = UserDataManager.teacher_settings.get_student_with_code(student_code)
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
student_block.merge({
"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
var student_progression: StudentProgression = UserDataManager.get_student_progression_for_code(0, student_code)
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"):
var progression_block: Dictionary = {}
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)
set_loading_bar_text("SYNCHRONIZATION_SEND_SERVER_INSTRUCTIONS")
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 {}
var res_get_server_instructions: Dictionary = await (ServerManager as ServerManagerClass).send_server_synchronization_instructions(message_to_server)
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")
stop_sync()
return {}
@@ -397,21 +397,21 @@ func _send_instructions(message_to_server: Dictionary) -> Dictionary:
func _apply_server_response(response_body: Dictionary) -> void:
if response_body.has("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"):
Logger.warn("UserDatabaseSynchronizer: While updating user, no account_type found")
Log.warn("UserDatabaseSynchronizer: While updating user, no account_type found")
else:
UserDataManager.teacher_settings.account_type = response_user.account_type
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:
UserDataManager.teacher_settings.education_method = response_user.education_method
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:
UserDataManager.teacher_settings.last_modified = response_user.last_modified
if response_body.has("students"):
Logger.trace("UserDatabaseSynchronizer: Updating students")
Log.trace("UserDatabaseSynchronizer: Updating students")
var response_students: Dictionary = response_body.students
for response_student_code: String in response_students.keys():
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:
Logger.trace("UserDatabaseSynchronizer: Start synchronizing user data.")
Log.trace("UserDatabaseSynchronizer: Start synchronizing user data.")
if synchronizing:
Logger.trace("UserDatabaseSynchronizer: User synchronization already started, cancel double-call.")
Log.trace("UserDatabaseSynchronizer: User synchronization already started, cancel double-call.")
return
await start_sync()
@@ -513,7 +513,7 @@ func validate_student_data(data: Dictionary) -> bool:
if missing.is_empty():
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
+3 -3
View File
@@ -39,13 +39,13 @@ func clean_dir(path: String) -> Error:
func delete_directory_recursive(path: String) -> void:
var err: Error = clean_dir(path)
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
err = DirAccess.remove_absolute(path)
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:
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
+2 -2
View File
@@ -35,7 +35,7 @@ func read(resource: Resource) -> void:
var property_value: Variant = data.get(binder.property_name)
binder.set_value(property_value)
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:
@@ -47,6 +47,6 @@ func write() -> bool:
if binder.property_name in data:
data.set(binder.property_name as StringName, binder.get_value())
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