Passed
Push — main ( 19cade...5376e4 )
by Yume
01:03
created

pkg/queries/queries.go   A

Size/Duplication

Total Lines 309
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
cc 42
eloc 195
dl 0
loc 309
rs 9.0399
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A queries.PostMem 0 32 3
A queries.FetchMem 0 8 2
B queries.FetchNextCard 0 30 6
A queries.PopulateMemDate 0 22 3
A queries.FetchAnswers 0 9 2
A queries.GenerateAnswers 0 13 3
B queries.GenerateAccess 0 43 6
A queries.CheckAccess 0 11 2
A queries.GenerateMemDate 0 31 3
B queries.FetchNextCardByDeck 0 30 6
B queries.FetchNextTodayCard 0 33 6
1
package queries
2
3
import (
4
	"errors"
5
	"math/rand"
6
	"memnixrest/app/database"
7
	"memnixrest/app/models"
8
	"memnixrest/pkg/core"
9
	"time"
10
11
	"github.com/gofiber/fiber/v2"
12
	"gorm.io/gorm"
13
)
14
15
// GenerateAccess
16
func GenerateAccess(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
17
	db := database.DBConn
18
19
	if deck.Status != models.DeckPublic && user.Permissions != models.PermAdmin {
20
		return models.ResponseHTTP{
21
			Success: false,
22
			Message: "You don't have the permissions to subscribe to this deck!",
23
			Data:    nil,
24
			Count:   0,
25
		}
26
	}
27
28
	access := new(models.Access)
29
30
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id =?", user.ID, deck.ID).Find(&access).Error; err != nil {
31
		if errors.Is(err, gorm.ErrRecordNotFound) {
32
			access.DeckID = deck.ID
33
			access.UserID = user.ID
34
			access.Permission = 1
35
			db.Preload("User").Preload("Deck").Create(access)
36
		}
37
38
	} else {
39
		if access.Permission >= models.AccessStudent {
40
			return models.ResponseHTTP{
41
				Success: false,
42
				Message: "You are already subscribed to this deck",
43
				Data:    nil,
44
				Count:   0,
45
			}
46
		} else {
47
			access.DeckID = deck.ID
48
			access.UserID = user.ID
49
			access.Permission = 1
50
			db.Preload("User").Preload("Deck").Save(access)
51
		}
52
	}
53
54
	return models.ResponseHTTP{
55
		Success: true,
56
		Message: "Success register an access",
57
		Data:    *access,
58
		Count:   1,
59
	}
60
}
61
62
func CheckAccess(c *fiber.Ctx, user *models.User, card *models.Card) models.Access {
63
	db := database.DBConn // DB Conn
64
65
	access := new(models.Access)
66
67
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id = ?", user.ID, card.DeckID).First(&access).Error; err != nil {
68
		access.Permission = 0
69
		return *access
70
	}
71
72
	return *access
73
}
74
75
func PostMem(c *fiber.Ctx, user models.User, card models.Card, validation models.CardResponseValidation) models.ResponseHTTP {
76
	db := database.DBConn // DB Conn
77
78
	memDate := new(models.MemDate)
79
80
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.card_id = ?",
81
		&user.ID, card.ID).First(&memDate).Error; err != nil {
82
		return models.ResponseHTTP{
83
			Success: false,
84
			Message: "MemDate Not Found",
85
			Data:    nil,
86
		}
87
	}
88
89
	ex_mem := FetchMem(c, memDate, &user)
90
	if ex_mem.Efactor == 0 {
91
		ex_mem = models.Mem{
92
			UserID:     user.ID,
93
			CardID:     card.ID,
94
			Quality:    0,
95
			Repetition: 0,
96
			Efactor:    2.5,
97
			Interval:   0,
98
		}
99
	}
100
101
	core.UpdateMem(c, &ex_mem, validation)
102
103
	return models.ResponseHTTP{
104
		Success: true,
105
		Message: "Success Post Mem",
106
		Data:    nil,
107
	}
108
}
109
110
func PopulateMemDate(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
111
	db := database.DBConn // DB Conn
112
	var cards []models.Card
113
114
	if err := db.Joins("Deck").Where("cards.deck_id = ?", deck.ID).Find(&cards).Error; err != nil {
115
		return models.ResponseHTTP{
116
			Success: false,
117
			Message: err.Error(),
118
			Data:    nil,
119
			Count:   0,
120
		}
121
	}
122
123
	for _, s := range cards {
124
		_ = GenerateMemDate(c, user, &s)
125
	} // TODO: Handle errors
126
127
	return models.ResponseHTTP{
128
		Success: true,
129
		Message: "Success generated mem_date",
130
		Data:    nil,
131
		Count:   0,
132
	}
133
134
}
135
136
func GenerateMemDate(c *fiber.Ctx, user *models.User, card *models.Card) models.ResponseHTTP {
137
	db := database.DBConn // DB Conn
138
139
	memDate := new(models.MemDate)
140
141
	if err := db.Joins("User").Joins("Card").Where("mem_dates.user_id = ? AND mem_dates.card_id = ?", user.ID, card.ID).First(&memDate).Error; err != nil {
142
		if errors.Is(err, gorm.ErrRecordNotFound) {
143
144
			memDate = &models.MemDate{
145
				UserID:   user.ID,
146
				CardID:   card.ID,
147
				DeckID:   card.DeckID,
148
				NextDate: time.Now(),
149
			}
150
151
			db.Preload("User").Preload("Card").Create(memDate)
152
		} else {
153
			return models.ResponseHTTP{
154
				Success: false,
155
				Message: err.Error(),
156
				Data:    nil,
157
				Count:   0,
158
			}
159
		}
160
	}
161
162
	return models.ResponseHTTP{
163
		Success: true,
164
		Message: "Success generate MemDate",
165
		Data:    *memDate,
166
		Count:   1,
167
	}
168
}
169
170
// FetchAnswers
171
func FetchAnswers(c *fiber.Ctx, card *models.Card) []models.Answer {
172
	var answers []models.Answer
173
	db := database.DBConn // DB Conn
174
175
	if err := db.Joins("Card").Where("answers.card_id = ?", card.ID).Limit(3).Order("random()").Find(&answers).Error; err != nil {
176
		return nil
177
	}
178
179
	return answers
180
}
181
182
func FetchMem(c *fiber.Ctx, memDate *models.MemDate, user *models.User) models.Mem {
183
	db := database.DBConn // DB Conn
184
185
	mem := new(models.Mem)
186
	if err := db.Joins("Card").Where("mems.card_id = ? AND mems.user_id = ?", memDate.CardID, user.ID).Order("id desc").First(&mem).Error; err != nil {
187
		mem.Efactor = 0
188
	}
189
	return *mem
190
}
191
192
func GenerateAnswers(c *fiber.Ctx, memDate *models.MemDate) []string {
193
	var answersList []string
194
195
	res := FetchAnswers(c, &memDate.Card)
196
197
	if len(res) >= 3 {
198
		answersList = append(answersList, res[0].Answer, res[1].Answer, res[2].Answer, memDate.Card.Answer)
199
200
		rand.Seed(time.Now().UnixNano())
201
		rand.Shuffle(len(answersList), func(i, j int) { answersList[i], answersList[j] = answersList[j], answersList[i] })
202
	}
203
204
	return answersList
205
206
}
207
208
func FetchNextCard(c *fiber.Ctx, user *models.User) models.ResponseHTTP {
209
	db := database.DBConn // DB Conn
210
211
	memDate := new(models.MemDate)
212
	var answersList []string
213
214
	// Get next card
215
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ?",
216
		&user.ID).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
217
		return models.ResponseHTTP{
218
			Success: false,
219
			Message: "Next card not found",
220
			Data:    nil,
221
		}
222
	}
223
224
	mem := FetchMem(c, memDate, user)
225
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 {
226
		answersList = GenerateAnswers(c, memDate)
227
		if len(answersList) == 4 {
228
			memDate.Card.Type = 2 // MCQ
229
		}
230
	}
231
232
	return models.ResponseHTTP{
233
		Success: true,
234
		Message: "Get Next Card",
235
		Data: models.ResponseCard{
236
			Card:    memDate.Card,
237
			Answers: answersList,
238
		},
239
	}
240
}
241
242
func FetchNextCardByDeck(c *fiber.Ctx, user *models.User, deckID string) models.ResponseHTTP {
243
	db := database.DBConn // DB Conn
244
245
	memDate := new(models.MemDate)
246
	var answersList []string
247
248
	// Get next card
249
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.deck_id = ?",
250
		&user.ID, deckID).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
251
		return models.ResponseHTTP{
252
			Success: false,
253
			Message: "Next card by deck not found",
254
			Data:    nil,
255
		}
256
	}
257
258
	mem := FetchMem(c, memDate, user)
259
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 {
260
		answersList = GenerateAnswers(c, memDate)
261
		if len(answersList) == 4 {
262
			memDate.Card.Type = 2 // MCQ
263
		}
264
	}
265
266
	return models.ResponseHTTP{
267
		Success: true,
268
		Message: "Get Next Card By Deck",
269
		Data: models.ResponseCard{
270
			Card:    memDate.Card,
271
			Answers: answersList,
272
		},
273
	}
274
}
275
276
// FetchNextTodayCard
277
func FetchNextTodayCard(c *fiber.Ctx, user *models.User) models.ResponseHTTP {
278
	db := database.DBConn // DB Conn
279
	memDate := new(models.MemDate)
280
281
	var answersList []string
282
283
	// Get next card with date condition
284
	t := time.Now()
285
286
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.next_date < ?",
287
		&user.ID, t.AddDate(0, 0, 1).Add(
288
			time.Duration(-t.Hour())*time.Hour)).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
289
		return models.ResponseHTTP{
290
			Success: false,
291
			Message: "Next today card not found",
292
			Data:    nil,
293
		}
294
	}
295
296
	mem := FetchMem(c, memDate, user)
297
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 {
298
		answersList = GenerateAnswers(c, memDate)
299
		if len(answersList) == 4 {
300
			memDate.Card.Type = 2 // MCQ
301
		}
302
	}
303
304
	return models.ResponseHTTP{
305
		Success: true,
306
		Message: "Get Next Today Card",
307
		Data: models.ResponseCard{
308
			Card:    memDate.Card,
309
			Answers: answersList,
310
		},
311
	}
312
}
313