213 lines
6.4 KiB
GDScript
213 lines
6.4 KiB
GDScript
extends Minigame
|
|
|
|
const LABEL_SCENE: PackedScene = preload("res://sources/minigames/penguin/penguin_label.tscn")
|
|
|
|
var current_word_progression: int = 0: set = _set_current_word_progression
|
|
var max_word_progression: int = 0
|
|
var labels: Array[PenguinLabel] = []
|
|
|
|
@onready var penguin: Penguin = $GameRoot/Penguin
|
|
@onready var sentence_background: HFlowContainer = %SentenceBackground
|
|
@onready var sentence_container: HFlowContainer = %Sentence
|
|
|
|
|
|
# Find words with silent GPs
|
|
func _find_stimuli_and_distractions() -> void:
|
|
var sentences_list: Array = Database.get_sentences_for_lesson_with_silent_gps(lesson_nb)
|
|
|
|
if sentences_list.is_empty():
|
|
return
|
|
var current_lesson_sentences: Array[Dictionary] = []
|
|
var previous_lesson_sentences: Array[Dictionary] = []
|
|
|
|
for sentence: Dictionary in sentences_list:
|
|
if sentence.LessonNb == lesson_nb:
|
|
current_lesson_sentences.append(sentence)
|
|
else:
|
|
previous_lesson_sentences.append(sentence)
|
|
|
|
# Shuffle everything
|
|
current_lesson_sentences.shuffle()
|
|
previous_lesson_sentences.shuffle()
|
|
|
|
# If there is no previous stimuli, only adds from current lesson
|
|
if previous_lesson_sentences.is_empty():
|
|
while stimuli.size() < max_progression:
|
|
stimuli.append(current_lesson_sentences.pick_random())
|
|
else:
|
|
if not current_lesson_sentences.is_empty():
|
|
# If there are more stimuli in current lesson than needed
|
|
if current_lesson_sentences.size() >= current_lesson_stimuli_number:
|
|
for index: int in range(current_lesson_stimuli_number):
|
|
stimuli.append(current_lesson_sentences[index])
|
|
else:
|
|
stimuli.append_array(current_lesson_sentences)
|
|
|
|
# If there are not enough stimuli from current lesson, we want at least half the target number of stimuli
|
|
var minimal_stimuli: int = floori(current_lesson_stimuli_number/2.0)
|
|
if stimuli.size() < minimal_stimuli:
|
|
while stimuli.size() < minimal_stimuli:
|
|
stimuli.append(current_lesson_sentences.pick_random())
|
|
|
|
# Gets other stimuli from previous errors or lessons
|
|
var spaces_left: int = max_progression - stimuli.size()
|
|
if previous_lesson_sentences.size() >= spaces_left:
|
|
for index: int in range(spaces_left):
|
|
stimuli.append(previous_lesson_sentences[index])
|
|
else:
|
|
stimuli.append_array(previous_lesson_sentences)
|
|
|
|
# If there are not enough stimuli, fill the rest with current lesson
|
|
if current_lesson_sentences:
|
|
while stimuli.size() < max_progression:
|
|
stimuli.append(current_lesson_sentences.pick_random())
|
|
|
|
# Shuffle the stimuli
|
|
stimuli.shuffle()
|
|
|
|
# Find the GPs and distractors for each word
|
|
for sentence: Dictionary in stimuli:
|
|
sentence.GPs = Database.get_gps_from_sentence(sentence.ID as int)
|
|
|
|
Log.trace("PenguinMinigame: Stimuli: %s" % str(stimuli))
|
|
|
|
|
|
# Launch the minigame
|
|
func _start() -> void:
|
|
super()
|
|
fireworks.set_colors([Color("#bca4ff"), Color("#f5a8c8"), Color("#7fc8ff")])
|
|
if stimuli.is_empty():
|
|
Log.error("PenguinMinigame: Cannot start game because stimuli is empty")
|
|
_win()
|
|
return
|
|
_setup_word_progression()
|
|
sentence_background.show()
|
|
|
|
|
|
# Sets up the word progression for the current progression
|
|
func _setup_word_progression() -> void:
|
|
max_word_progression = 0
|
|
|
|
for node: Node in sentence_container.get_children():
|
|
node.queue_free()
|
|
labels.clear()
|
|
|
|
var stimulus: Dictionary = _get_current_stimulus()
|
|
|
|
var first_gp: bool = true
|
|
var last_word_id: int
|
|
var word_container: HBoxContainer
|
|
|
|
for gp: Dictionary in stimulus.GPs:
|
|
if gp.WordID != last_word_id:
|
|
last_word_id = gp.WordID
|
|
word_container = HBoxContainer.new()
|
|
sentence_container.add_child(word_container)
|
|
|
|
var label: PenguinLabel = LABEL_SCENE.instantiate()
|
|
if first_gp:
|
|
label.capitalized = true
|
|
first_gp = false
|
|
label.gp = gp
|
|
word_container.add_child(label)
|
|
label.pressed.connect(_on_snowball_thrown.bind(label))
|
|
labels.append(label)
|
|
|
|
if gp.Type == 0:
|
|
max_word_progression += 1
|
|
|
|
setup_sentence_background()
|
|
current_word_progression = 0
|
|
|
|
|
|
func setup_sentence_background() -> void:
|
|
await get_tree().process_frame
|
|
var number_of_lines: int = sentence_container.get_line_count()
|
|
var children: Array[Node] = sentence_background.get_children()
|
|
if children.is_empty():
|
|
Log.error("Ants Minigame: sentence_background has no child, but it should always at least keep 1")
|
|
return
|
|
if number_of_lines == children.size():
|
|
return
|
|
while number_of_lines < sentence_background.get_children().size():
|
|
var child: Node = sentence_background.get_child(-1) # Get last child
|
|
child.queue_free()
|
|
await get_tree().process_frame
|
|
if number_of_lines == children.size():
|
|
return
|
|
var template: Node = children[0]
|
|
while number_of_lines > sentence_background.get_children().size():
|
|
var new_child: Node = template.duplicate()
|
|
sentence_background.add_child(new_child)
|
|
await get_tree().process_frame
|
|
|
|
|
|
func _highlight() -> void:
|
|
for label: PenguinLabel in labels:
|
|
if self._is_silent(label.gp) and not label.is_pressed:
|
|
label.highlight()
|
|
|
|
|
|
func _stop_highlight() -> void:
|
|
for label: PenguinLabel in labels:
|
|
label.highlight(false)
|
|
|
|
|
|
# Get the current stimulus which needs to be found to increase progression
|
|
func _get_current_stimulus() -> Dictionary:
|
|
if stimuli.size() == 0:
|
|
return {}
|
|
return stimuli[current_progression % stimuli.size()]
|
|
|
|
|
|
func _is_silent(gp: Dictionary) -> bool:
|
|
return gp.Type == 0
|
|
|
|
|
|
func _set_current_word_progression(p_current_word_progression: int) -> void:
|
|
current_word_progression = p_current_word_progression
|
|
if current_word_progression == max_word_progression:
|
|
current_progression += 1
|
|
|
|
#region Connections
|
|
|
|
func _on_snowball_thrown(pos: Vector2, label: PenguinLabel) -> void:
|
|
# Disables all labels
|
|
for p_label: PenguinLabel in labels:
|
|
p_label.set_button_enabled(false)
|
|
|
|
# Throw the snowball
|
|
await penguin.throw(pos)
|
|
|
|
var correct_answer: bool = _is_silent(label.gp)
|
|
|
|
_log_new_response({"gp": label.gp, "is_silent": correct_answer}, {"gp": label.gp, "is_silent": true})
|
|
|
|
if label.gp.has("WordID"):
|
|
_update_remediation_word_score(label.gp.WordID as int, 1 if correct_answer else -1)
|
|
else:
|
|
Log.error("PenguinMinigame: Cannot update remediation score because label GP has no WordID")
|
|
|
|
if correct_answer:
|
|
label.right()
|
|
await penguin.happy()
|
|
current_word_progression += 1
|
|
else:
|
|
label.wrong()
|
|
await penguin.sad()
|
|
current_lives -= 1
|
|
|
|
# Re-enables all labels
|
|
for p_label: PenguinLabel in labels:
|
|
p_label.set_button_enabled(true)
|
|
|
|
penguin.idle()
|
|
|
|
|
|
func _on_current_progression_changed() -> void:
|
|
if current_progression >= max_progression:
|
|
return
|
|
_setup_word_progression()
|
|
|
|
#endregion
|