Add flashcards feature with spaced repetition scheduling
Adds a full flashcards system: FSRS-based scheduling, cloze/basic card types, CSV import/export, media storage, and study UI, wired into navigation and the dashboard alongside existing question flows.
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
extends SceneTree
|
||||
|
||||
# Exercises FlashcardService's offline-review-queue bookkeeping without touching the network
|
||||
# or user:// disk (mirrors the load(...).new() pattern used by review_queue_session_test.gd -
|
||||
# the instance is never added to the tree, so _ready() never runs and the real HTTPRequest
|
||||
# nodes/autoload wiring are never touched).
|
||||
|
||||
var failures := 0
|
||||
|
||||
|
||||
func _initialize() -> void:
|
||||
var service = load("res://scripts/autoload/flashcard_service.gd").new()
|
||||
|
||||
var uuid: String = service._new_uuid()
|
||||
_assert(uuid.length() == 36, "a client review id should be a standard 36-character UUID")
|
||||
var segments := uuid.split("-")
|
||||
_assert(segments.size() == 5, "a UUID should have five dash-separated segments")
|
||||
_assert(segments[2].begins_with("4"), "the generated UUID should be version 4")
|
||||
_assert("89ab".contains(segments[3][0]), "the generated UUID should have a valid RFC 4122 variant nibble")
|
||||
|
||||
service.active_account_key = "account-a"
|
||||
service.outbox = [
|
||||
{"account": "account-b", "payload": {"cardId": "other-account-card"}, "retry_count": 0},
|
||||
{"account": "account-a", "payload": {"cardId": "card-1"}, "retry_count": 0}
|
||||
]
|
||||
_assert(service.has_pending_reviews(), "a queued review for the active account should be reported as pending")
|
||||
_assert(service._next_account_item_index() == 1,
|
||||
"outbox lookup should skip items queued under a different account (offline queue recovery must not leak across accounts)")
|
||||
|
||||
service.active_account_key = "account-c"
|
||||
_assert(not service.has_pending_reviews(),
|
||||
"switching to an account with no queued reviews should report nothing pending")
|
||||
|
||||
service.active_account_key = "account-a"
|
||||
service.outbox[1]["active"] = true
|
||||
_assert(service._active_item_index() == 1, "the in-flight retry item should be discoverable while marked active")
|
||||
|
||||
var iso: String = service.current_study_day_start_utc()
|
||||
_assert(iso.ends_with("Z"), "the study day boundary must be expressed as a UTC instant")
|
||||
_assert(Time.get_unix_time_from_datetime_string(iso.trim_suffix("Z")) > 0,
|
||||
"the study day boundary string should parse back into a valid datetime")
|
||||
|
||||
service.free()
|
||||
quit(1 if failures > 0 else 0)
|
||||
|
||||
|
||||
func _assert(condition: bool, message: String) -> void:
|
||||
if condition:
|
||||
return
|
||||
failures += 1
|
||||
push_error(message)
|
||||
Reference in New Issue
Block a user