Files
2026-10-11 22:49:01 +02:00

64 lines
2.5 KiB
GDScript

class_name ProgressReport
extends RefCounted
## Synthese de progression destinee a l'adulte, calculee a partir d'une
## sauvegarde. Code pur : aucun acces a l'arbre de scenes ni au disque. Les
## intitules viennent de l'appelant (UIText) : ici seulement des identifiants
## et des nombres. Une notion « a retravailler » n'est jamais un jugement sur
## l'enfant : c'est un signal pour l'adulte (cahier des charges §9).
## Nombre minimal de tentatives recentes avant de parler de difficulte.
const MIN_ATTEMPTS_FOR_DIFFICULTY := 3
## Taux de reussite recent en dessous duquel la notion est signalee.
const STRUGGLE_RATE := 0.6
## `missions_total` : nombre de missions du niveau de l'enfant ;
## `items_total` : taille du catalogue d'objets.
static func build(save: Dictionary, missions_total: int, items_total: int) -> Dictionary:
var results: Dictionary = save.get("mission_results", {})
var rewards: Dictionary = save.get("rewards", {"stars": 0, "items": []})
var skills: Array[Dictionary] = []
var skill_states: Dictionary = save.get("skills", {})
var skill_ids: Array = skill_states.keys()
skill_ids.sort()
for skill_id: String in skill_ids:
skills.append(_skill_row(skill_id, skill_states[skill_id]))
return {
"display_name": save.get("display_name", ""),
"school_level": save.get("school_level", ""),
"session_count": int(save.get("session_count", 0)),
"stars": int(rewards.get("stars", 0)),
"missions_done": results.size(),
"missions_total": missions_total,
"items_owned": rewards.get("items", []).size(),
"items_total": items_total,
"skills": skills,
}
static func _skill_row(skill_id: String, state: Dictionary) -> Dictionary:
var recent: Array = state.get("recent_results", [])
var hints: Array = state.get("recent_hint_used", [])
var successes := 0
for result: bool in recent:
if result:
successes += 1
var hint_count := 0
for used: bool in hints:
if used:
hint_count += 1
var attempts := recent.size()
var status: String = state.get("status", "decouverte")
var struggling := (
attempts >= MIN_ATTEMPTS_FOR_DIFFICULTY
and float(successes) / float(attempts) < STRUGGLE_RATE
)
return {
"skill_id": skill_id,
"status": status,
"attempts": attempts,
"successes": successes,
"hints_used": hint_count,
"needs_work": status == "a_reviser" or struggling,
}