Skip to content

Commit 578e85d

Browse files
committed
Add database
1 parent a517670 commit 578e85d

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

db.go

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"os"
7+
"path/filepath"
8+
9+
"github.com/adrg/xdg"
10+
"github.com/google/renameio/maybe"
11+
"github.com/pkg/errors"
12+
)
13+
14+
// dbPath is the path to the database file.
15+
// This is usually set to ~/.local/share/clidle/db.json on most UNIX systems.
16+
var dbPath = filepath.Join(xdg.DataHome, "clidle", "db.json")
17+
18+
// db is the file where the game statistics are stored.
19+
type db struct {
20+
// Guesses stores the win statistics of each game. Guesses[0] is the number
21+
// of games that were lost, Guesses[1] is the number of games that were won
22+
// with 1 guess, etc.
23+
Guesses [numGuesses + 1]int `json:"guesses"`
24+
}
25+
26+
// loadDb reads the database from dbPath.
27+
func loadDb() (*db, error) {
28+
file, err := os.Open(dbPath)
29+
if err != nil {
30+
if os.IsNotExist(err) {
31+
return &db{}, nil
32+
}
33+
return nil, errors.Wrap(err, "could not find database")
34+
}
35+
var db db
36+
if err := json.NewDecoder(file).Decode(&db); err != nil {
37+
return nil, errors.Wrap(err, "could not read from database")
38+
}
39+
return &db, nil
40+
}
41+
42+
// save atomically (best effort) writes the database to dbPath.
43+
func (db *db) save() error {
44+
dir := filepath.Dir(dbPath)
45+
if err := os.MkdirAll(dir, 0755); err != nil {
46+
return errors.Wrapf(err, "could not create data directory: %s", dir)
47+
}
48+
data, err := json.MarshalIndent(&db, "", " ")
49+
if err != nil {
50+
return errors.Wrap(err, "could not serialize database")
51+
}
52+
if err := maybe.WriteFile(dbPath, data, 0o644); err != nil {
53+
return errors.Wrapf(err, "could not write to database: %s", dbPath)
54+
}
55+
return nil
56+
}
57+
58+
// addWin adds a win to the game statistics. It also stores the number of
59+
// guesses it took, in the range [1,numGuesses].
60+
func (db *db) addWin(guesses int) {
61+
if !(1 <= guesses && guesses <= numGuesses) {
62+
panic(fmt.Sprintf("guesses out of range: %d", guesses))
63+
}
64+
db.Guesses[guesses]++
65+
}
66+
67+
// addLoss adds a loss to the game statistics.
68+
func (db *db) addLoss() {
69+
db.Guesses[0]++
70+
}
71+
72+
// score returns the current total score based on the statistics.
73+
//
74+
// A game that was lost provides 0 points. A game that was won provides 50
75+
// points, plus an extra 10 points for each remaining guess.
76+
func (db *db) score() int {
77+
score := 0
78+
for i, guess := range db.Guesses[1:] {
79+
score += (100 - 10*i) * guess
80+
}
81+
return score
82+
}

0 commit comments

Comments
 (0)