-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdata_base.py
129 lines (111 loc) · 5.79 KB
/
data_base.py
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
from pymongo import MongoClient
# This is the number of times a user sees a flashcard.
# 0 means they haven't studied it yet, 1 means it is their first time, and so on.
# It is also referred to as n in some of the documentation.
REPETITIONS_DEFAULT: int = 0
# This is also referred to as the easiness factor or EFactor or EF.
# It is multiplier used to increase the "space" in spaced repetition.
# The range is from 1.3 to 2.5
EASINESS_DEFAULT: float = 2.5
# This is the length of time (in days) between repetitions.
# It is the "space" of spaced repetition
INTERVAL_DEFAULT: int = 1
class DataBase:
def __init__(self):
self.client = MongoClient(authenticate_connection())
self.db = self.client['users']
def add(self, user, question: str, answer: str) -> bool:
if self.db[str(user)].find_one( {'question': question} ) == None:
self.db[str(user)].insert_one({
'question': question,
'answer': answer,
'repetitions': REPETITIONS_DEFAULT,
'easiness': EASINESS_DEFAULT,
'interval': INTERVAL_DEFAULT
})
return True
return False
def get(self, user: int):
self.db[str(user)].update_one({
'type': 'information'
},
{
'$inc': {'cards_received': 1}
}, upsert=True)
return self.db[str(user)].find_one({
'question': {'$exists':True},
'answer': {'$exists':True},
'interval': {'$exists':True},
},
sort=[("interval", 1)])
def get_all(self, user: int):
return self.db[str(user)].find({
'question': {'$exists': True}
})
def delete(self, user: int, questions: list[str]):
for question in questions:
self.db[str(user)].delete_one( {'question': question} )
def update(self, user: int, card, quality: int):
new_easiness, new_interval, new_repetitions = update_card_values(card['interval'], card['easiness'], card['repetitions'], quality)
self.db[str(user)].update_one({
'_id': card['_id']
},
{
'$set': {
'easiness': new_easiness,
'interval': new_interval,
'repetitions': new_repetitions,
}
})
def reset(self, user: int):
self.db[str(user)].update_many({
'question': {'$exists':True},
'answer': {'$exists':True}
},
{
'$set': {
"interval": INTERVAL_DEFAULT,
"easiness": EASINESS_DEFAULT,
"repetitions": REPETITIONS_DEFAULT
}
})
self.db[str(user)].update_one({
'type': 'information'
},
{
'$set': {
'cards_received':0
}
})
def info(self, user: int):
cards_received = self.db[str(user)].find_one({
'type': 'information'
},
{
'_id': False,
'cards_received':True
})
return {
'number_cards': self.db[str(user)].count_documents({
'question': {'$exists':True},
'answer': {'$exists':True}
}
),
'cards_received': cards_received['cards_received'] if cards_received != None else 0
}
def isEmpty(self, user: int) -> bool:
return self.db[str(user)].find_one() == None
def update_card_values(interval, easiness, repetitions, quality):
assert quality >= 0 and quality <= 5
easiness = max(1.3, easiness + 0.1 - (5.0 - quality) * (0.08 + (5.0 - quality) * 0.02))
if quality < 3: repetitions = 0
else: repetitions += 1
if repetitions == 1: interval = 2
elif repetitions == 2: interval = 6
else: interval = round(interval * easiness)
return [easiness, interval, repetitions]
def authenticate_connection() -> str:
with open("./database_credentials.txt", "r") as f:
lines = f.readlines()
return lines[0].strip()
data_base = DataBase()