Files
step3/scripts/autoload/dynamic_question_service.gd
T

109 lines
3.5 KiB
GDScript

extends Node
const EndpointConfig := preload("res://scripts/autoload/api_endpoint_config.gd")
const DEFAULT_API_URL := "https://us3q.ranaze.com/api/dynamic-questions"
signal status_loaded(status: Dictionary)
signal question_loaded(question: Dictionary)
signal attempt_completed(result: Dictionary)
signal report_submitted(question_id: String, report_id: String)
signal report_failed(question_id: String, message: String)
signal request_failed(message: String)
var api_url := DEFAULT_API_URL
var run_token := ""
var generation_token := ""
var current_envelope := {}
var _request: HTTPRequest
var _operation := ""
var _report_question_id := ""
func _ready() -> void:
api_url = EndpointConfig.resolve(
str(ProjectSettings.get_setting("step3/dynamic_questions_api_url", DEFAULT_API_URL)),
"/api/dynamic-questions")
_request = HTTPRequest.new()
_request.timeout = 30.0
_request.request_completed.connect(_on_completed)
add_child(_request)
func load_status() -> void:
_send("status", HTTPClient.METHOD_GET, "/status", {})
func load_next() -> void:
_send("next", HTTPClient.METHOD_POST, "/next", {"runToken": run_token})
func submit_attempt(choice_id: String, duration_seconds: int, is_skip := false) -> void:
_send("attempt", HTTPClient.METHOD_POST, "/attempt", {
"generationToken": generation_token,
"choiceId": choice_id,
"isSkip": is_skip,
"durationSeconds": duration_seconds
})
func submit_report(question_id: String, category: String, details: String) -> void:
_report_question_id = question_id
_send("report", HTTPClient.METHOD_POST, "/report", {
"generationToken": generation_token,
"category": category,
"details": details
})
func reset_run() -> void:
run_token = ""
generation_token = ""
current_envelope = {}
func _send(operation: String, method: int, suffix: String, payload: Dictionary) -> void:
if not AuthState.can_send_authenticated_request():
request_failed.emit("Log in to use Dynamic Questions.")
return
if _request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
return
_operation = operation
var headers := PackedStringArray([
"Content-Type: application/json",
"Authorization: Bearer %s" % AuthState.access_token
])
var body := "" if method == HTTPClient.METHOD_GET else JSON.stringify(payload)
var error := _request.request(api_url + suffix, headers, method, body)
if error != OK:
_operation = ""
request_failed.emit("Could not connect to Dynamic Questions.")
func _on_completed(_result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
var operation := _operation
_operation = ""
var parsed: Variant = JSON.parse_string(body.get_string_from_utf8())
if response_code < 200 or response_code >= 300 or typeof(parsed) != TYPE_DICTIONARY:
var message := str(parsed) if parsed != null else "Dynamic Questions request failed."
if operation == "report":
report_failed.emit(_report_question_id, message)
else:
request_failed.emit(message)
return
var data: Dictionary = parsed
match operation:
"status":
status_loaded.emit(data)
"next":
run_token = str(data.get("runToken", ""))
generation_token = str(data.get("generationToken", ""))
current_envelope = data
var question := QuestionBankService.normalize_api_question(data.get("question", {}))
question["_dynamic_objective_id"] = str(data.get("objectiveId", ""))
question["_dynamic_objective_title"] = str(data.get("objectiveTitle", ""))
question_loaded.emit(question)
"attempt":
attempt_completed.emit(data)
"report":
report_submitted.emit(_report_question_id, str(data.get("id", "")))