godot-flashcards/scripts/models/progress.gd
2025-12-27 00:20:33 -05:00

116 lines
3.3 KiB
GDScript

class_name Progress
extends Resource
@export var deck_id: String = ""
@export var total_sessions: int = 0
@export var total_cards_studied: int = 0
@export var total_correct: int = 0
@export var total_incorrect: int = 0
@export var current_streak: int = 0
@export var best_streak: int = 0
@export var last_session_at: String = ""
@export var card_stats: Dictionary = {}
func to_dict() -> Dictionary:
return {
"deck_id": deck_id,
"stats": {
"total_sessions": total_sessions,
"total_cards_studied": total_cards_studied,
"total_correct": total_correct,
"total_incorrect": total_incorrect,
"current_streak": current_streak,
"best_streak": best_streak,
"last_session_at": last_session_at
},
"card_stats": card_stats.duplicate()
}
func from_dict(data: Dictionary) -> void:
deck_id = data.get("deck_id", "")
var stats = data.get("stats", {})
total_sessions = stats.get("total_sessions", 0)
total_cards_studied = stats.get("total_cards_studied", 0)
total_correct = stats.get("total_correct", 0)
total_incorrect = stats.get("total_incorrect", 0)
current_streak = stats.get("current_streak", 0)
best_streak = stats.get("best_streak", 0)
last_session_at = stats.get("last_session_at", "")
card_stats = data.get("card_stats", {}).duplicate()
func record_answer(card_id: String, is_correct: bool) -> void:
if not card_stats.has(card_id):
card_stats[card_id] = {
"correct": 0,
"incorrect": 0,
"last_seen_at": "",
"next_review_at": "",
"ease_factor": 2.5
}
if is_correct:
total_correct += 1
card_stats[card_id]["correct"] += 1
current_streak += 1
if current_streak > best_streak:
best_streak = current_streak
else:
total_incorrect += 1
card_stats[card_id]["incorrect"] += 1
current_streak = 0
total_cards_studied += 1
var now = Time.get_datetime_string_from_system(true, true) + "Z"
card_stats[card_id]["last_seen_at"] = now
last_session_at = now
_update_next_review(card_id, is_correct)
func get_accuracy() -> float:
var total = total_correct + total_incorrect
if total == 0:
return 0.0
return (float(total_correct) / float(total)) * 100.0
func get_card_stats(card_id: String) -> Dictionary:
return card_stats.get(card_id, {
"correct": 0,
"incorrect": 0,
"last_seen_at": "",
"next_review_at": "",
"ease_factor": 2.5
})
func _update_next_review(card_id: String, is_correct: bool) -> void:
var stats = card_stats[card_id]
var ease_factor: float = stats.get("ease_factor", 2.5)
if is_correct:
ease_factor = min(ease_factor + 0.1, 3.0)
else:
ease_factor = max(ease_factor - 0.2, 1.3)
stats["ease_factor"] = ease_factor
var review_interval_days: int = 1
if is_correct:
var correct_count = stats.get("correct", 0)
review_interval_days = int(correct_count * ease_factor)
else:
review_interval_days = 1
var now_unix = Time.get_unix_time_from_system()
#var now_unix = Time.get_time_dict_from_unix_time(Time.get_unix_time_from_system())
var next_review_unix = now_unix + (review_interval_days * 86400) # 86400 seconds in a day
var next_review_dict = Time.get_datetime_dict_from_unix_time(int(next_review_unix))
stats["next_review_at"] = "%04d-%02d-%02dT%02d:%02d:%02dZ" % [
next_review_dict.year, next_review_dict.month, next_review_dict.day,
next_review_dict.hour, next_review_dict.minute, next_review_dict.second
]
func start_session() -> void:
total_sessions += 1