161 lines
5.4 KiB
GDScript
161 lines
5.4 KiB
GDScript
extends VBoxContainer
|
|
|
|
const Style := preload("res://scripts/ui/ui_style.gd")
|
|
|
|
var main: Control
|
|
var status_label: Label
|
|
var daily_label: Label
|
|
var elo_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 QuestionBankService.ratings_changed.is_connected(_refresh):
|
|
QuestionBankService.ratings_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")
|
|
elo_label = _add_metric(summary, "ELO")
|
|
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]
|
|
elo_label.text = "ELO\n%d overall\n%d rated" % [
|
|
QuestionBankService.overall_elo,
|
|
QuestionBankService.rated_question_count
|
|
]
|
|
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()
|