Add core game retry flow and question stats

This commit is contained in:
hz
2026-07-10 14:05:57 -05:00
parent 1822c00a3b
commit e991dccbb2
17 changed files with 1036 additions and 80 deletions
+110 -7
View File
@@ -11,8 +11,15 @@ var profile: Dictionary = {
"best_streak": 0,
"badges": [],
"completed_question_ids": [],
"correct_question_ids": [],
"question_wrong_counts": {},
"missed_question_ids": [],
"system_stats": {},
"block_history": []
"block_history": [],
"daily_date": "",
"daily_questions_answered": 0,
"daily_xp_earned": 0,
"daily_goal_questions": 10
}
func _ready() -> void:
@@ -21,6 +28,7 @@ func _ready() -> void:
func load_profile() -> void:
if not FileAccess.file_exists(SAVE_PATH):
_ensure_daily_current()
save_profile()
return
@@ -34,6 +42,8 @@ func load_profile() -> void:
for key in profile.keys():
if parsed.has(key):
profile[key] = parsed[key]
_ensure_tracking_fields()
_ensure_daily_current()
profile_changed.emit()
@@ -46,14 +56,18 @@ func save_profile() -> void:
func get_profile() -> Dictionary:
_ensure_daily_current()
return profile.duplicate(true)
func apply_block_results(results: Dictionary) -> void:
_ensure_daily_current()
profile["xp"] = int(profile["xp"]) + int(results.get("xp_earned", 0))
profile["level"] = ProgressionService.level_for_xp(int(profile["xp"]))
profile["current_streak"] = int(results.get("ending_streak", profile["current_streak"]))
profile["best_streak"] = max(int(profile["best_streak"]), int(profile["current_streak"]))
profile["daily_questions_answered"] = int(profile["daily_questions_answered"]) + int(results.get("total", 0))
profile["daily_xp_earned"] = int(profile["daily_xp_earned"]) + int(results.get("xp_earned", 0))
var unlocked_badges: Array = results.get("badges_unlocked", [])
for badge in unlocked_badges:
@@ -66,13 +80,10 @@ func apply_block_results(results: Dictionary) -> void:
var question_id := str(question.get("id", ""))
if question_id != "" and not profile["completed_question_ids"].has(question_id):
profile["completed_question_ids"].append(question_id)
_apply_question_tracking(question_id, bool(answer.get("is_correct", false)))
var system_name := str(question.get("system", "General"))
if not profile["system_stats"].has(system_name):
profile["system_stats"][system_name] = {"seen": 0, "correct": 0}
profile["system_stats"][system_name]["seen"] = int(profile["system_stats"][system_name]["seen"]) + 1
if bool(answer.get("is_correct", false)):
profile["system_stats"][system_name]["correct"] = int(profile["system_stats"][system_name]["correct"]) + 1
_apply_system_result(system_name, bool(answer.get("is_correct", false)))
var summary: Dictionary = {
"timestamp": Time.get_datetime_string_from_system(),
@@ -98,8 +109,100 @@ func reset_profile() -> void:
"best_streak": 0,
"badges": [],
"completed_question_ids": [],
"correct_question_ids": [],
"question_wrong_counts": {},
"missed_question_ids": [],
"system_stats": {},
"block_history": []
"block_history": [],
"daily_date": _today_string(),
"daily_questions_answered": 0,
"daily_xp_earned": 0,
"daily_goal_questions": 10
}
save_profile()
profile_changed.emit()
func apply_question_results(results: Dictionary) -> void:
_ensure_daily_current()
profile["xp"] = int(profile["xp"]) + int(results.get("xp_earned", 0))
profile["level"] = ProgressionService.level_for_xp(int(profile["xp"]))
profile["current_streak"] = int(results.get("ending_streak", profile["current_streak"]))
profile["best_streak"] = max(int(profile["best_streak"]), int(profile["current_streak"]))
profile["daily_questions_answered"] = int(profile["daily_questions_answered"]) + int(results.get("total", 0))
profile["daily_xp_earned"] = int(profile["daily_xp_earned"]) + int(results.get("xp_earned", 0))
var unlocked_badges: Array = results.get("badges_unlocked", [])
for badge in unlocked_badges:
if not profile["badges"].has(badge):
profile["badges"].append(badge)
var answers: Array = results.get("answers", [])
for answer in answers:
var question: Dictionary = answer.get("question", {})
var question_id := str(question.get("id", ""))
if question_id != "" and not profile["completed_question_ids"].has(question_id):
profile["completed_question_ids"].append(question_id)
_apply_question_tracking(question_id, bool(answer.get("is_correct", false)), bool(results.get("mastered", true)))
_apply_system_result(str(question.get("system", "General")), bool(answer.get("is_correct", false)))
save_profile()
profile_changed.emit()
func record_wrong_attempt(question: Dictionary) -> void:
_ensure_daily_current()
var question_id := str(question.get("id", ""))
_apply_question_tracking(question_id, false, false)
save_profile()
profile_changed.emit()
func _ensure_daily_current() -> void:
_ensure_tracking_fields()
var today := _today_string()
var changed := false
if not profile.has("daily_goal_questions"):
profile["daily_goal_questions"] = 10
changed = true
if str(profile.get("daily_date", "")) != today:
profile["daily_date"] = today
profile["daily_questions_answered"] = 0
profile["daily_xp_earned"] = 0
changed = true
if changed:
save_profile()
func _ensure_tracking_fields() -> void:
if not profile.has("correct_question_ids"):
profile["correct_question_ids"] = []
if not profile.has("question_wrong_counts"):
profile["question_wrong_counts"] = {}
if not profile.has("missed_question_ids"):
profile["missed_question_ids"] = []
func _apply_question_tracking(question_id: String, is_correct: bool, mastered: bool = true) -> void:
if question_id == "":
return
if is_correct and mastered:
if not profile["correct_question_ids"].has(question_id):
profile["correct_question_ids"].append(question_id)
elif not is_correct:
if not profile["missed_question_ids"].has(question_id):
profile["missed_question_ids"].append(question_id)
profile["question_wrong_counts"][question_id] = int(profile["question_wrong_counts"].get(question_id, 0)) + 1
func _apply_system_result(system_name: String, is_correct: bool) -> void:
if not profile["system_stats"].has(system_name):
profile["system_stats"][system_name] = {"seen": 0, "correct": 0}
profile["system_stats"][system_name]["seen"] = int(profile["system_stats"][system_name]["seen"]) + 1
if is_correct:
profile["system_stats"][system_name]["correct"] = int(profile["system_stats"][system_name]["correct"]) + 1
func _today_string() -> String:
var date := Time.get_datetime_dict_from_system()
return "%04d-%02d-%02d" % [int(date["year"]), int(date["month"]), int(date["day"])]