Add core game retry flow and question stats
This commit is contained in:
@@ -1,15 +1,20 @@
|
||||
extends Node
|
||||
|
||||
const DEFAULT_QUESTIONS_API_URL := "https://s3q.ranaze.com/api/questions/search"
|
||||
const RETRY_DELAYS := [2, 5, 10, 20, 30]
|
||||
|
||||
signal questions_changed
|
||||
signal questions_load_failed(message: String)
|
||||
|
||||
var questions: Array = []
|
||||
var request: HTTPRequest
|
||||
var retry_timer: Timer
|
||||
var questions_api_url := DEFAULT_QUESTIONS_API_URL
|
||||
var is_loading := false
|
||||
var last_error := ""
|
||||
var load_state := "idle"
|
||||
var retry_attempt := 0
|
||||
var next_retry_seconds := 0
|
||||
|
||||
func _ready() -> void:
|
||||
questions_api_url = str(ProjectSettings.get_setting("step3/questions_api_url", DEFAULT_QUESTIONS_API_URL))
|
||||
@@ -17,13 +22,24 @@ func _ready() -> void:
|
||||
request.request_completed.connect(_on_api_questions_loaded)
|
||||
add_child(request)
|
||||
|
||||
retry_timer = Timer.new()
|
||||
retry_timer.one_shot = true
|
||||
retry_timer.timeout.connect(_on_retry_timer_timeout)
|
||||
add_child(retry_timer)
|
||||
|
||||
func load_questions_from_api() -> void:
|
||||
|
||||
func load_questions_from_api(reset_retry: bool = true) -> void:
|
||||
if AuthState.access_token.is_empty():
|
||||
_set_load_error("Login required before loading questions.")
|
||||
_set_load_error("Login required before loading questions.", false)
|
||||
return
|
||||
|
||||
if reset_retry:
|
||||
retry_attempt = 0
|
||||
next_retry_seconds = 0
|
||||
retry_timer.stop()
|
||||
|
||||
is_loading = true
|
||||
load_state = "retrying" if retry_attempt > 0 else "loading"
|
||||
last_error = ""
|
||||
questions.clear()
|
||||
questions_changed.emit()
|
||||
@@ -63,6 +79,31 @@ func _on_api_questions_loaded(result: int, response_code: int, _headers: PackedS
|
||||
|
||||
questions = api_questions
|
||||
last_error = ""
|
||||
load_state = "ready"
|
||||
retry_attempt = 0
|
||||
next_retry_seconds = 0
|
||||
retry_timer.stop()
|
||||
questions_changed.emit()
|
||||
|
||||
|
||||
func retry_now() -> void:
|
||||
retry_attempt = 0
|
||||
next_retry_seconds = 0
|
||||
retry_timer.stop()
|
||||
load_questions_from_api(false)
|
||||
|
||||
|
||||
func clear_questions() -> void:
|
||||
if request != null:
|
||||
request.cancel_request()
|
||||
if retry_timer != null:
|
||||
retry_timer.stop()
|
||||
questions.clear()
|
||||
is_loading = false
|
||||
last_error = ""
|
||||
load_state = "idle"
|
||||
retry_attempt = 0
|
||||
next_retry_seconds = 0
|
||||
questions_changed.emit()
|
||||
|
||||
|
||||
@@ -101,14 +142,34 @@ func has_questions() -> bool:
|
||||
return not questions.is_empty()
|
||||
|
||||
|
||||
func _set_load_error(message: String) -> void:
|
||||
func _set_load_error(message: String, schedule_retry: bool = true) -> void:
|
||||
is_loading = false
|
||||
last_error = message
|
||||
push_warning(message)
|
||||
questions_load_failed.emit(message)
|
||||
if schedule_retry and not AuthState.access_token.is_empty():
|
||||
_schedule_retry()
|
||||
else:
|
||||
load_state = "failed"
|
||||
next_retry_seconds = 0
|
||||
questions_changed.emit()
|
||||
|
||||
|
||||
func _schedule_retry() -> void:
|
||||
var delay_index := retry_attempt
|
||||
if delay_index >= RETRY_DELAYS.size():
|
||||
delay_index = RETRY_DELAYS.size() - 1
|
||||
next_retry_seconds = int(RETRY_DELAYS[delay_index])
|
||||
retry_attempt += 1
|
||||
load_state = "retrying"
|
||||
retry_timer.start(float(next_retry_seconds))
|
||||
|
||||
|
||||
func _on_retry_timer_timeout() -> void:
|
||||
next_retry_seconds = 0
|
||||
load_questions_from_api(false)
|
||||
|
||||
|
||||
func _is_valid_question(item: Variant) -> bool:
|
||||
if typeof(item) != TYPE_DICTIONARY:
|
||||
return false
|
||||
@@ -132,6 +193,7 @@ func _normalize_api_question(item: Variant) -> Dictionary:
|
||||
"correct_choice_id": str(item.get("correctChoiceId", item.get("correct_choice_id", ""))),
|
||||
"explanation": str(item.get("explanation", "")),
|
||||
"choice_explanations": item.get("choiceExplanations", item.get("choice_explanations", {})),
|
||||
"choice_selection_percentages": item.get("choiceSelectionPercentages", item.get("choice_selection_percentages", {})),
|
||||
"discipline": str(item.get("discipline", "")),
|
||||
"system": str(item.get("system", "")),
|
||||
"difficulty": int(item.get("difficulty", 1)),
|
||||
|
||||
Reference in New Issue
Block a user