Passed
Push — main ( 619ee7...6c7dd4 )
by Yume
01:38
created

queries.FetchNextCard   B

Complexity

Conditions 6

Size

Total Lines 32
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 23
nop 2
dl 0
loc 32
rs 8.3946
c 0
b 0
f 0
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
func DeleteRating(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
16
	db := database.DBConn
17
18
	rating := new(models.Rating)
19
20
	if err := db.Where("ratings.user_id = ? AND ratings.deck_id = ?", user.ID, deck.ID).Delete(&rating).Error; err != nil {
21
		return models.ResponseHTTP{
22
			Success: false,
23
			Message: err.Error(),
24
			Data:    nil,
25
			Count:   0,
26
		}
27
	}
28
	return models.ResponseHTTP{
29
		Success: true,
30
		Message: "Rating deleted",
31
		Data:    *rating,
32
		Count:   1,
33
	}
34
}
35
36
func GenerateRating(c *fiber.Ctx, rating *models.Rating) models.ResponseHTTP {
37
	db := database.DBConn
38
	deck := new(models.Deck)
39
40
	if err := db.First(&deck, rating.DeckID).Error; err != nil {
41
		return models.ResponseHTTP{
42
			Success: false,
43
			Message: "Can't find deck matching the ID provided",
44
			Data:    nil,
45
			Count:   0,
46
		}
47
	}
48
49
	access := new(models.Access)
50
51
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id =?", rating.UserID, rating.DeckID).First(&access).Error; err != nil {
52
		return models.ResponseHTTP{
53
			Success: false,
54
			Message: "You don't have the permissions to rate this deck",
55
			Data:    nil,
56
			Count:   0,
57
		}
58
	}
59
60
	if access.Permission < models.AccessStudent {
61
		return models.ResponseHTTP{
62
			Success: false,
63
			Message: "You are not subscribed to this deck",
64
			Data:    nil,
65
			Count:   0,
66
		}
67
	}
68
69
	oldRating := new(models.Rating)
70
71
	if err := db.Joins("User").Joins("Deck").Where("ratings.user_id = ? AND ratings.deck_id = ?", rating.UserID, rating.DeckID).First(&oldRating).Error; err != nil {
72
		if errors.Is(err, gorm.ErrRecordNotFound) {
73
			db.Preload("User").Preload("Deck").Create(rating)
74
			oldRating = rating
75
		}
76
	} else {
77
		oldRating.Value = rating.Value
78
		db.Preload("User").Preload("Deck").Save(oldRating)
79
	}
80
81
	return models.ResponseHTTP{
82
		Success: true,
83
		Message: "Success rate the deck",
84
		Data:    *oldRating,
85
		Count:   1,
86
	}
87
}
88
89
// GenerateAdminAccess
90
func GenerateCreatorAccess(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
91
	db := database.DBConn
92
93
	access := new(models.Access)
94
95
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id =?", user.ID, deck.ID).Find(&access).Error; err != nil {
96
		if errors.Is(err, gorm.ErrRecordNotFound) {
97
			access.DeckID = deck.ID
98
			access.UserID = user.ID
99
			access.Permission = models.AccessOwner
100
			db.Create(access)
101
		}
102
103
	} else {
104
		if access.Permission >= models.AccessStudent {
105
			return models.ResponseHTTP{
106
				Success: false,
107
				Message: "You are already subscribed to this deck. You can't become an owner...",
108
				Data:    nil,
109
				Count:   0,
110
			}
111
		} else {
112
			access.DeckID = deck.ID
113
			access.UserID = user.ID
114
			access.Permission = models.AccessOwner
115
			db.Preload("User").Preload("Deck").Save(access)
116
		}
117
	}
118
119
	log := CreateLog(models.LogSubscribe, user.Username+" subscribed to "+deck.DeckName)
120
	_ = CreateUserLog(user.ID, *log)
121
	_ = CreateDeckLog(deck.ID, *log)
122
123
	return models.ResponseHTTP{
124
		Success: true,
125
		Message: "Success register a creator access !",
126
		Data:    *access,
127
		Count:   1,
128
	}
129
}
130
131
// GenerateAccess
132
func GenerateAccess(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
133
	db := database.DBConn
134
135
	if deck.Status != models.DeckPublic && user.Permissions != models.PermAdmin {
136
		return models.ResponseHTTP{
137
			Success: false,
138
			Message: "You don't have the permissions to subscribe to this deck!",
139
			Data:    nil,
140
			Count:   0,
141
		}
142
	}
143
144
	access := new(models.Access)
145
146
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id =?", user.ID, deck.ID).Find(&access).Error; err != nil {
147
		if errors.Is(err, gorm.ErrRecordNotFound) {
148
			access.DeckID = deck.ID
149
			access.UserID = user.ID
150
			access.Permission = models.AccessStudent
151
			db.Preload("User").Preload("Deck").Create(access)
152
		}
153
154
	} else {
155
		if access.Permission >= models.AccessStudent {
156
			return models.ResponseHTTP{
157
				Success: false,
158
				Message: "You are already subscribed to this deck",
159
				Data:    nil,
160
				Count:   0,
161
			}
162
		} else {
163
			access.DeckID = deck.ID
164
			access.UserID = user.ID
165
			access.Permission = models.AccessStudent
166
			db.Preload("User").Preload("Deck").Save(access)
167
		}
168
	}
169
170
	return models.ResponseHTTP{
171
		Success: true,
172
		Message: "Success register an access",
173
		Data:    *access,
174
		Count:   1,
175
	}
176
}
177
178
func CheckAccess(c *fiber.Ctx, userID uint, deckID uint, perm models.AccessPermission) models.ResponseHTTP {
179
	db := database.DBConn // DB Conn
180
181
	access := new(models.Access)
182
183
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id = ?", userID, deckID).First(&access).Error; err != nil {
184
		access.Permission = models.AccessNone
185
	}
186
187
	if access.Permission < perm {
188
		return models.ResponseHTTP{
189
			Success: false,
190
			Message: "You don't have the permission to access this deck!",
191
			Data:    *access,
192
			Count:   1,
193
		}
194
	}
195
196
	return models.ResponseHTTP{
197
		Success: true,
198
		Message: "Success checking access permissions",
199
		Data:    *access,
200
		Count:   1,
201
	}
202
}
203
204
func PostMem(c *fiber.Ctx, user models.User, card models.Card, validation models.CardResponseValidation) models.ResponseHTTP {
205
	db := database.DBConn // DB Conn
206
207
	memDate := new(models.MemDate)
208
209
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.card_id = ?",
210
		&user.ID, card.ID).First(&memDate).Error; err != nil {
211
		return models.ResponseHTTP{
212
			Success: false,
213
			Message: "MemDate Not Found",
214
			Data:    nil,
215
		}
216
	}
217
218
	ex_mem := FetchMem(c, memDate, &user)
219
	if ex_mem.Efactor == 0 {
220
		ex_mem = models.Mem{
221
			UserID:     user.ID,
222
			CardID:     card.ID,
223
			Quality:    0,
224
			Repetition: 0,
225
			Efactor:    2.5,
226
			Interval:   0,
227
		}
228
	}
229
230
	core.UpdateMem(c, &ex_mem, validation)
231
232
	return models.ResponseHTTP{
233
		Success: true,
234
		Message: "Success Post Mem",
235
		Data:    nil,
236
	}
237
}
238
239
func PopulateMemDate(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
240
	db := database.DBConn // DB Conn
241
	var cards []models.Card
242
243
	if err := db.Joins("Deck").Where("cards.deck_id = ?", deck.ID).Find(&cards).Error; err != nil {
244
		return models.ResponseHTTP{
245
			Success: false,
246
			Message: err.Error(),
247
			Data:    nil,
248
			Count:   0,
249
		}
250
	}
251
252
	ch := make(chan models.ResponseHTTP)
253
254
	for _, s := range cards {
255
		go func(c *fiber.Ctx, user *models.User, card models.Card) {
256
			res := GenerateMemDate(c, user, &card)
257
			ch <- res
258
		}(c, user, s)
259
	}
260
261
	return models.ResponseHTTP{
262
		Success: true,
263
		Message: "Success generated mem_date",
264
		Data:    nil,
265
		Count:   0,
266
	}
267
}
268
269
func GetSubUsers(c *fiber.Ctx, deckID uint) []models.User {
270
	db := database.DBConn // DB Conn
271
272
	var users []models.User
273
274
	if err := db.Joins("left join accesses ON users.id = accesses.user_id AND accesses.deck_id = ?", deckID).Where("accesses.permission > ?", models.AccessNone).Find(&users).Error; err != nil {
275
		return nil
276
	}
277
278
	return users
279
280
}
281
282
func GenerateMemDate(c *fiber.Ctx, user *models.User, card *models.Card) models.ResponseHTTP {
283
	db := database.DBConn // DB Conn
284
285
	memDate := new(models.MemDate)
286
287
	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 {
288
		if errors.Is(err, gorm.ErrRecordNotFound) {
289
290
			memDate = &models.MemDate{
291
				UserID:   user.ID,
292
				CardID:   card.ID,
293
				DeckID:   card.DeckID,
294
				NextDate: time.Now(),
295
			}
296
297
			db.Preload("User").Preload("Card").Create(memDate)
298
		} else {
299
			return models.ResponseHTTP{
300
				Success: false,
301
				Message: err.Error(),
302
				Data:    nil,
303
				Count:   0,
304
			}
305
		}
306
	}
307
308
	return models.ResponseHTTP{
309
		Success: true,
310
		Message: "Success generate MemDate",
311
		Data:    *memDate,
312
		Count:   1,
313
	}
314
}
315
316
// FetchAnswers
317
func FetchAnswers(c *fiber.Ctx, card *models.Card) []models.Answer {
318
	var answers []models.Answer
319
	db := database.DBConn // DB Conn
320
321
	if err := db.Joins("Card").Where("answers.card_id = ?", card.ID).Limit(3).Order("random()").Find(&answers).Error; err != nil {
322
		return nil
323
	}
324
325
	return answers
326
}
327
328
func FetchMem(c *fiber.Ctx, memDate *models.MemDate, user *models.User) models.Mem {
329
	db := database.DBConn // DB Conn
330
331
	mem := new(models.Mem)
332
	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 {
333
		mem.Efactor = 0
334
	}
335
	return *mem
336
}
337
338
func GenerateAnswers(c *fiber.Ctx, memDate *models.MemDate) []string {
339
	var answersList []string
340
341
	res := FetchAnswers(c, &memDate.Card)
342
343
	if len(res) >= 3 {
344
		answersList = append(answersList, res[0].Answer, res[1].Answer, res[2].Answer, memDate.Card.Answer)
345
346
		rand.Seed(time.Now().UnixNano())
347
		rand.Shuffle(len(answersList), func(i, j int) { answersList[i], answersList[j] = answersList[j], answersList[i] })
348
	}
349
350
	return answersList
351
352
}
353
354
func FetchNextCard(c *fiber.Ctx, user *models.User) models.ResponseHTTP {
355
	db := database.DBConn // DB Conn
356
357
	memDate := new(models.MemDate)
358
	var answersList []string
359
360
	// Get next card
361
	if err := db.Joins(
362
		"left join accesses ON mem_dates.deck_id = accesses.deck_id AND accesses.user_id = ?",
363
		user.ID).Joins("Card").Joins("Deck").Where("mem_dates.user_id = ? AND accesses.permission >= ?",
364
		&user.ID, models.AccessStudent).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
365
		return models.ResponseHTTP{
366
			Success: false,
367
			Message: "Next card not found",
368
			Data:    nil,
369
		}
370
	}
371
372
	mem := FetchMem(c, memDate, user)
373
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 {
374
		answersList = GenerateAnswers(c, memDate)
375
		if len(answersList) == 4 {
376
			memDate.Card.Type = 2 // MCQ
377
		}
378
	}
379
380
	return models.ResponseHTTP{
381
		Success: true,
382
		Message: "Get Next Card",
383
		Data: models.ResponseCard{
384
			Card:    memDate.Card,
385
			Answers: answersList,
386
		},
387
	}
388
}
389
390
func FetchNextCardByDeck(c *fiber.Ctx, user *models.User, deckID string) models.ResponseHTTP {
391
	db := database.DBConn // DB Conn
392
393
	memDate := new(models.MemDate)
394
	var answersList []string
395
396
	// Get next card
397
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.deck_id = ?",
398
		&user.ID, deckID).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
399
		return models.ResponseHTTP{
400
			Success: false,
401
			Message: "Next card by deck not found",
402
			Data:    nil,
403
		}
404
	}
405
406
	mem := FetchMem(c, memDate, user)
407
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 || memDate.Card.Type == 2 {
408
		answersList = GenerateAnswers(c, memDate)
409
		if len(answersList) == 4 {
410
			memDate.Card.Type = 2 // MCQ
411
		}
412
	}
413
414
	return models.ResponseHTTP{
415
		Success: true,
416
		Message: "Get Next Card By Deck",
417
		Data: models.ResponseCard{
418
			Card:    memDate.Card,
419
			Answers: answersList,
420
		},
421
	}
422
}
423
424
// FetchNextTodayCard
425
func FetchNextTodayCard(c *fiber.Ctx, user *models.User) models.ResponseHTTP {
426
	db := database.DBConn // DB Conn
427
	memDate := new(models.MemDate)
428
429
	var answersList []string
430
431
	// Get next card with date condition
432
	t := time.Now()
433
434
	if err := db.Joins(
435
		"left join accesses ON mem_dates.deck_id = accesses.deck_id AND accesses.user_id = ?",
436
		user.ID).Joins("Card").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.next_date < ? AND accesses.permission >= ?",
437
		&user.ID, t.AddDate(0, 0, 1).Add(
438
			time.Duration(-t.Hour())*time.Hour), models.AccessStudent).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
439
		return models.ResponseHTTP{
440
			Success: false,
441
			Message: "Next today card not found",
442
			Data:    nil,
443
		}
444
	}
445
	mem := FetchMem(c, memDate, user)
446
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 || memDate.Card.Type == 2 {
447
		answersList = GenerateAnswers(c, memDate)
448
		if len(answersList) == 4 {
449
			memDate.Card.Type = 2 // MCQ
450
		}
451
	}
452
453
	return models.ResponseHTTP{
454
		Success: true,
455
		Message: "Get Next Today Card",
456
		Data: models.ResponseCard{
457
			Card:    memDate.Card,
458
			Answers: answersList,
459
		},
460
	}
461
}
462