-
Notifications
You must be signed in to change notification settings - Fork 10
/
store.go
157 lines (122 loc) · 3.79 KB
/
store.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Riff - Spaced repetition.
// Copyright (c) 2022-present, b3log.org
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package riff
import (
"math/rand"
"path/filepath"
"sync"
"time"
)
// Store 描述了闪卡存储。
type Store interface {
// AddCard 添加一张卡片。
AddCard(id, blockID string) Card
// GetCard 获取一张卡片。
GetCard(id string) Card
// SetCard 设置一张卡片。
SetCard(card Card)
// RemoveCard 移除一张卡片。
RemoveCard(id string) Card
// GetCardsByBlockID 获取指定内容块的所有卡片。
GetCardsByBlockID(blockID string) []Card
// GetCardsByBlockIDs 获取指定内容块的所有卡片。
GetCardsByBlockIDs(blockIDs []string) []Card
// GetNewCardsByBlockIDs 获取指定内容块的所有新的卡片(制卡后没有进行过复习的卡片)。
GetNewCardsByBlockIDs(blockIDs []string) []Card
// GetDueCardsByBlockIDs 获取指定内容块的所有到期的卡片。
GetDueCardsByBlockIDs(blockIDs []string) []Card
// GetBlockIDs 获取所有内容块 ID。
GetBlockIDs() []string
// CountCards 获取卡包中的闪卡数量。
CountCards() int
// Review 闪卡复习。
Review(id string, rating Rating) (ret *Log)
// Dues 获取所有到期的闪卡列表。
Dues() []Card
// ID 获取存储 ID。
ID() string
// Algo 返回算法名称,如:fsrs。
Algo() Algo
// Load 从持久化存储中加载全部闪卡到内存。
Load() (err error)
// Save 将全部闪卡从内存保存到持久化存储中。
Save() error
// SaveLog 保存复习日志。
SaveLog(log *Log) error
// GetSaveDir 获取数据文件夹路径。
GetSaveDir() string
}
// BaseStore 描述了基础的闪卡存储实现。
type BaseStore struct {
id string // 存储 ID,应该和卡包 ID 一致
algo Algo // 算法名称,如:fsrs
saveDir string // 数据文件夹路径,如:F:\\SiYuan\\data\\storage\\riff\\
lock *sync.Mutex // 操作时需要用到的锁
}
func NewBaseStore(id string, algo Algo, saveDir string) *BaseStore {
return &BaseStore{
id: id,
algo: algo,
saveDir: saveDir,
lock: &sync.Mutex{},
}
}
func (store *BaseStore) ID() string {
return store.id
}
func (store *BaseStore) Algo() Algo {
return store.algo
}
func (store *BaseStore) GetSaveDir() string {
return store.saveDir
}
func (store *BaseStore) getMsgPackPath() string {
return filepath.Join(store.saveDir, store.id+".cards")
}
// Rating 描述了闪卡复习的评分。
type Rating int8
const (
Again Rating = iota + 1 // 完全不会,必须再复习一遍
Hard // 有点难
Good // 一般
Easy // 很容易
)
// Algo 描述了闪卡复习算法的名称。
type Algo string
const (
AlgoFSRS Algo = "fsrs"
AlgoSM2 Algo = "sm2"
)
// State 描述了闪卡的状态。
type State int8
const (
New State = iota
Learning
Review
Relearning
)
func newID() string {
now := time.Now()
return now.Format("20060102150405") + "-" + randStr(7)
}
func randStr(length int) string {
letter := []rune("abcdefghijklmnopqrstuvwxyz0123456789")
b := make([]rune, length)
for i := range b {
b[i] = letter[rand.Intn(len(letter))]
}
return string(b)
}