109 lines
3.5 KiB
GDScript
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", "")))
|