Add data-driven dynamic question mode
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
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", "")))
|
||||
Reference in New Issue
Block a user