(Feat): Initial Commit, Termdoku
This commit is contained in:
91
internal/savegame/persistence.go
Normal file
91
internal/savegame/persistence.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package savegame
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"termdoku/internal/game"
|
||||
)
|
||||
|
||||
// SavedGame represents a saved game state
|
||||
type SavedGame struct {
|
||||
Board game.Grid `json:"board"`
|
||||
Solution game.Grid `json:"solution"`
|
||||
Given [9][9]bool `json:"given"`
|
||||
Difficulty string `json:"difficulty"`
|
||||
Elapsed int64 `json:"elapsed"` // seconds
|
||||
StartTime time.Time `json:"startTime"`
|
||||
HintsUsed int `json:"hintsUsed"`
|
||||
Notes map[string][]uint8 `json:"notes"` // JSON keys must be strings
|
||||
SavedAt time.Time `json:"savedAt"`
|
||||
AutoCheck bool `json:"autoCheck"`
|
||||
TimerEnabled bool `json:"timerEnabled"`
|
||||
}
|
||||
|
||||
// path returns the save file path
|
||||
func path() (string, error) {
|
||||
h, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return filepath.Join(h, ".termdoku", "savegame.json"), nil
|
||||
}
|
||||
|
||||
// Save writes a game state to disk
|
||||
func Save(sg SavedGame) error {
|
||||
p, err := path()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
|
||||
return err
|
||||
}
|
||||
data, err := json.MarshalIndent(sg, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile(p, data, 0o644)
|
||||
}
|
||||
|
||||
// Load reads a game state from disk
|
||||
func Load() (SavedGame, error) {
|
||||
var sg SavedGame
|
||||
p, err := path()
|
||||
if err != nil {
|
||||
return sg, err
|
||||
}
|
||||
b, err := os.ReadFile(p)
|
||||
if err != nil {
|
||||
if errors.Is(err, fs.ErrNotExist) {
|
||||
return sg, errors.New("no saved game found")
|
||||
}
|
||||
return sg, err
|
||||
}
|
||||
if err := json.Unmarshal(b, &sg); err != nil {
|
||||
return sg, err
|
||||
}
|
||||
return sg, nil
|
||||
}
|
||||
|
||||
// Exists checks if a saved game exists
|
||||
func Exists() bool {
|
||||
p, err := path()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
_, err = os.Stat(p)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// Delete removes the saved game
|
||||
func Delete() error {
|
||||
p, err := path()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Remove(p)
|
||||
}
|
||||
Reference in New Issue
Block a user