Save best scores and last difficulty to a JSON profile

- profile package: best moves, best time and games played per
  deck/difficulty, stored in the user data folder
- Win panel shows the best (or New best!), language menu shows bests
- Profile memory always comes from the heap allocator (it outlives callers)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
SansanandClaude Opus 5.5 committed 2026-10-01 21:35:43 +02:00
1 parent 685182b25d
commit 83ff9511ec
5 files changed
+225 -6

No files matched your search

+11 -3
View File
@@ -1,10 +1,13 @@
package screens
import "core:fmt"
import "core:math"
import "core:strings"
import raylib "vendor:raylib"
import card "../card"
import decks "../decks"
import memory "../memory"
import profile "../profile"
import themes "../themes"
import ui "../ui"
@@ -100,21 +103,26 @@ language_menu :: proc(language: decks.Language, difficulty: ^memory.Difficulty)
if ui.button(rect, decks.DECKS[deck].name, theme.primary, hotkey = keys[i]) {
result = deck
}
ui.draw_text_centered(decks.DECKS[deck].native, x + button_w / 2, 450, 22, theme.ink, info.symbol_style)
ui.draw_text_centered(decks.DECKS[deck].native, x + button_w / 2, 448, 22, theme.ink, info.symbol_style)
best_text := cstring("No games yet")
if record, ok := profile.get(memory.score_key(deck, difficulty^)); ok {
best_text = strings.clone_to_cstring(fmt.tprintf("Best %d moves · %s", record.best_moves, profile.format_time(record.best_seconds)), context.temp_allocator)
}
ui.draw_text_centered(best_text, x + button_w / 2, 476, 17, raylib.Fade(theme.ink, 0.65))
x += button_w + gap
}
// Difficulty selector
names := memory.DIFFICULTY_NAMES
layouts := memory.LAYOUTS
ui.draw_text_centered("Difficulty (Left / Right)", themes.SCREEN_WIDTH / 2, 500, 20, raylib.Fade(theme.ink, 0.7))
ui.draw_text_centered("Difficulty (Left / Right)", themes.SCREEN_WIDTH / 2, 512, 20, raylib.Fade(theme.ink, 0.7))
seg_w: f32 = 150
seg_x := (themes.SCREEN_WIDTH - 3 * seg_w - 2 * 12) / 2
for level in memory.Difficulty {
selected := difficulty^ == level
color := selected ? theme.primary : raylib.ColorLerp(theme.primary, themes.WHITE, 0.55)
label := raylib.TextFormat("%s %d", names[level], layouts[level].rows * layouts[level].cols / 2)
if ui.button({seg_x, 530, seg_w, 48}, label, color, font_size = 22, selected = selected) {
if ui.button({seg_x, 542, seg_w, 48}, label, color, font_size = 22, selected = selected) {
difficulty^ = level
}
seg_x += seg_w + 12