Add core game retry flow and question stats
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
extends VBoxContainer
|
||||
|
||||
const Style := preload("res://scripts/ui/ui_style.gd")
|
||||
|
||||
var main: Control
|
||||
var status_label: Label
|
||||
var daily_label: Label
|
||||
var xp_label: Label
|
||||
var streak_label: Label
|
||||
var bank_label: Label
|
||||
var error_label: Label
|
||||
var begin_button: Button
|
||||
var retry_button: Button
|
||||
|
||||
func _ready() -> void:
|
||||
set_anchors_preset(Control.PRESET_FULL_RECT)
|
||||
add_theme_constant_override("separation", 18)
|
||||
if not QuestionBankService.questions_changed.is_connected(_refresh):
|
||||
QuestionBankService.questions_changed.connect(_refresh)
|
||||
if not ProfileService.profile_changed.is_connected(_refresh):
|
||||
ProfileService.profile_changed.connect(_refresh)
|
||||
|
||||
var title := Label.new()
|
||||
title.text = "Core Mode"
|
||||
Style.set_label(title, 36, Style.TEXT)
|
||||
add_child(title)
|
||||
|
||||
var subtitle := Label.new()
|
||||
subtitle.text = "Begin a continuous STEP 3 question run. Keep your energy up, build score, and stay on pace."
|
||||
subtitle.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
Style.set_label(subtitle, 17, Style.MUTED)
|
||||
add_child(subtitle)
|
||||
|
||||
var summary := HBoxContainer.new()
|
||||
summary.add_theme_constant_override("separation", 14)
|
||||
add_child(summary)
|
||||
|
||||
daily_label = _add_metric(summary, "Today")
|
||||
xp_label = _add_metric(summary, "Daily XP")
|
||||
streak_label = _add_metric(summary, "Streak")
|
||||
bank_label = _add_metric(summary, "Question Bank")
|
||||
|
||||
var action_panel := PanelContainer.new()
|
||||
action_panel.add_theme_stylebox_override("panel", Style.panel_box(Color("172337"), Color("405475")))
|
||||
action_panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
add_child(action_panel)
|
||||
|
||||
var actions := VBoxContainer.new()
|
||||
actions.add_theme_constant_override("separation", 12)
|
||||
action_panel.add_child(actions)
|
||||
|
||||
status_label = Label.new()
|
||||
status_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
Style.set_label(status_label, 22, Style.CYAN)
|
||||
actions.add_child(status_label)
|
||||
|
||||
error_label = Label.new()
|
||||
error_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
Style.set_label(error_label, 15, Style.RED)
|
||||
actions.add_child(error_label)
|
||||
|
||||
var button_row := HBoxContainer.new()
|
||||
button_row.add_theme_constant_override("separation", 12)
|
||||
actions.add_child(button_row)
|
||||
|
||||
begin_button = Button.new()
|
||||
begin_button.text = "Begin"
|
||||
begin_button.custom_minimum_size = Vector2(260, 60)
|
||||
Style.style_primary_button(begin_button)
|
||||
begin_button.pressed.connect(_begin_core_mode)
|
||||
button_row.add_child(begin_button)
|
||||
|
||||
retry_button = Button.new()
|
||||
retry_button.text = "Retry Questions"
|
||||
retry_button.custom_minimum_size = Vector2(170, 54)
|
||||
Style.style_chip(retry_button, Style.AMBER)
|
||||
retry_button.pressed.connect(QuestionBankService.retry_now)
|
||||
button_row.add_child(retry_button)
|
||||
|
||||
var spacer := Control.new()
|
||||
spacer.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
add_child(spacer)
|
||||
|
||||
|
||||
func on_show(_payload: Variant = null) -> void:
|
||||
if QuestionBankService.load_state == "idle" and AuthState.is_logged_in:
|
||||
QuestionBankService.load_questions_from_api()
|
||||
_refresh()
|
||||
|
||||
|
||||
func _add_metric(parent: HBoxContainer, metric_name: String) -> Label:
|
||||
var panel := PanelContainer.new()
|
||||
panel.add_theme_stylebox_override("panel", Style.panel_box(Style.SURFACE, Color("33415c")))
|
||||
panel.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
parent.add_child(panel)
|
||||
|
||||
var label := Label.new()
|
||||
label.text = metric_name
|
||||
label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
|
||||
Style.set_label(label, 18, Style.TEXT)
|
||||
panel.add_child(label)
|
||||
return label
|
||||
|
||||
|
||||
func _refresh() -> void:
|
||||
if daily_label == null:
|
||||
return
|
||||
|
||||
var profile := ProfileService.get_profile()
|
||||
var answered := int(profile.get("daily_questions_answered", 0))
|
||||
var goal := int(profile.get("daily_goal_questions", 10))
|
||||
if goal < 1:
|
||||
goal = 1
|
||||
var progress := int(round(float(answered) / float(goal) * 100.0))
|
||||
if progress > 100:
|
||||
progress = 100
|
||||
daily_label.text = "Today\n%d/%d questions\n%d%% complete" % [answered, goal, progress]
|
||||
xp_label.text = "Daily XP\n%d XP earned" % int(profile.get("daily_xp_earned", 0))
|
||||
streak_label.text = "Streak\n%d current\n%d best" % [
|
||||
int(profile.get("current_streak", 0)),
|
||||
int(profile.get("best_streak", 0))
|
||||
]
|
||||
bank_label.text = "Question Bank\n%d available\n%s" % [
|
||||
QuestionBankService.get_all_questions().size(),
|
||||
QuestionBankService.load_state.capitalize()
|
||||
]
|
||||
|
||||
var state := QuestionBankService.load_state
|
||||
var has_questions := QuestionBankService.has_questions()
|
||||
begin_button.disabled = not has_questions
|
||||
retry_button.disabled = state == "loading"
|
||||
retry_button.visible = state != "ready"
|
||||
error_label.text = ""
|
||||
|
||||
if state == "ready":
|
||||
status_label.text = BlockSessionService.core_status_message if BlockSessionService.core_status_message != "" else "Question bank ready. Begin core mode when you are ready."
|
||||
elif state == "loading":
|
||||
status_label.text = "Loading question bank..."
|
||||
elif state == "retrying":
|
||||
status_label.text = "Question API unavailable. Retrying in %d seconds." % QuestionBankService.next_retry_seconds
|
||||
error_label.text = QuestionBankService.last_error
|
||||
elif state == "failed":
|
||||
status_label.text = "Question bank is not available."
|
||||
error_label.text = QuestionBankService.last_error
|
||||
else:
|
||||
status_label.text = "Question bank has not loaded yet."
|
||||
|
||||
|
||||
func _begin_core_mode() -> void:
|
||||
if not QuestionBankService.has_questions():
|
||||
return
|
||||
if BlockSessionService.start_core_run():
|
||||
main.show_screen("player")
|
||||
else:
|
||||
_refresh()
|
||||
Reference in New Issue
Block a user