Passed
Push — main ( 161ef3...619ee7 )
by Yume
01:02
created

queries.PopulateMemDate   A

Complexity

Conditions 4

Size

Total Lines 27
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 20
nop 3
dl 0
loc 27
rs 9.4
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, *log)
121
	_ = CreateDeckLog(*deck, *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, user *models.User, card *models.Card) models.Access {
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 = ?", user.ID, card.DeckID).First(&access).Error; err != nil {
184
		access.Permission = models.AccessNone
185
		return *access
186
	}
187
188
	return *access
189
}
190
191
func PostMem(c *fiber.Ctx, user models.User, card models.Card, validation models.CardResponseValidation) models.ResponseHTTP {
192
	db := database.DBConn // DB Conn
193
194
	memDate := new(models.MemDate)
195
196
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.card_id = ?",
197
		&user.ID, card.ID).First(&memDate).Error; err != nil {
198
		return models.ResponseHTTP{
199
			Success: false,
200
			Message: "MemDate Not Found",
201
			Data:    nil,
202
		}
203
	}
204
205
	ex_mem := FetchMem(c, memDate, &user)
206
	if ex_mem.Efactor == 0 {
207
		ex_mem = models.Mem{
208
			UserID:     user.ID,
209
			CardID:     card.ID,
210
			Quality:    0,
211
			Repetition: 0,
212
			Efactor:    2.5,
213
			Interval:   0,
214
		}
215
	}
216
217
	core.UpdateMem(c, &ex_mem, validation)
218
219
	return models.ResponseHTTP{
220
		Success: true,
221
		Message: "Success Post Mem",
222
		Data:    nil,
223
	}
224
}
225
226
func PopulateMemDate(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
227
	db := database.DBConn // DB Conn
228
	var cards []models.Card
229
230
	if err := db.Joins("Deck").Where("cards.deck_id = ?", deck.ID).Find(&cards).Error; err != nil {
231
		return models.ResponseHTTP{
232
			Success: false,
233
			Message: err.Error(),
234
			Data:    nil,
235
			Count:   0,
236
		}
237
	}
238
239
	ch := make(chan models.ResponseHTTP)
240
241
	for _, s := range cards {
242
		go func(c *fiber.Ctx, user *models.User, card models.Card) {
243
			res := GenerateMemDate(c, user, &card)
244
			ch <- res
245
		}(c, user, s)
246
	}
247
248
	return models.ResponseHTTP{
249
		Success: true,
250
		Message: "Success generated mem_date",
251
		Data:    nil,
252
		Count:   0,
253
	}
254
255
}
256
257
func GenerateMemDate(c *fiber.Ctx, user *models.User, card *models.Card) models.ResponseHTTP {
258
	db := database.DBConn // DB Conn
259
260
	memDate := new(models.MemDate)
261
262
	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 {
263
		if errors.Is(err, gorm.ErrRecordNotFound) {
264
265
			memDate = &models.MemDate{
266
				UserID:   user.ID,
267
				CardID:   card.ID,
268
				DeckID:   card.DeckID,
269
				NextDate: time.Now(),
270
			}
271
272
			db.Preload("User").Preload("Card").Create(memDate)
273
		} else {
274
			return models.ResponseHTTP{
275
				Success: false,
276
				Message: err.Error(),
277
				Data:    nil,
278
				Count:   0,
279
			}
280
		}
281
	}
282
283
	return models.ResponseHTTP{
284
		Success: true,
285
		Message: "Success generate MemDate",
286
		Data:    *memDate,
287
		Count:   1,
288
	}
289
}
290
291
// FetchAnswers
292
func FetchAnswers(c *fiber.Ctx, card *models.Card) []models.Answer {
293
	var answers []models.Answer
294
	db := database.DBConn // DB Conn
295
296
	if err := db.Joins("Card").Where("answers.card_id = ?", card.ID).Limit(3).Order("random()").Find(&answers).Error; err != nil {
297
		return nil
298
	}
299
300
	return answers
301
}
302
303
func FetchMem(c *fiber.Ctx, memDate *models.MemDate, user *models.User) models.Mem {
304
	db := database.DBConn // DB Conn
305
306
	mem := new(models.Mem)
307
	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 {
308
		mem.Efactor = 0
309
	}
310
	return *mem
311
}
312
313
func GenerateAnswers(c *fiber.Ctx, memDate *models.MemDate) []string {
314
	var answersList []string
315
316
	res := FetchAnswers(c, &memDate.Card)
317
318
	if len(res) >= 3 {
319
		answersList = append(answersList, res[0].Answer, res[1].Answer, res[2].Answer, memDate.Card.Answer)
320
321
		rand.Seed(time.Now().UnixNano())
322
		rand.Shuffle(len(answersList), func(i, j int) { answersList[i], answersList[j] = answersList[j], answersList[i] })
323
	}
324
325
	return answersList
326
327
}
328
329
func FetchNextCard(c *fiber.Ctx, user *models.User) models.ResponseHTTP {
330
	db := database.DBConn // DB Conn
331
332
	memDate := new(models.MemDate)
333
	var answersList []string
334
335
	// Get next card
336
	if err := db.Joins(
337
		"left join accesses ON mem_dates.deck_id = accesses.deck_id AND accesses.user_id = ?",
338
		user.ID).Joins("Card").Joins("Deck").Where("mem_dates.user_id = ? AND accesses.permission >= ?",
339
		&user.ID, models.AccessStudent).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
340
		return models.ResponseHTTP{
341
			Success: false,
342
			Message: "Next card not found",
343
			Data:    nil,
344
		}
345
	}
346
347
	mem := FetchMem(c, memDate, user)
348
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 {
349
		answersList = GenerateAnswers(c, memDate)
350
		if len(answersList) == 4 {
351
			memDate.Card.Type = 2 // MCQ
352
		}
353
	}
354
355
	return models.ResponseHTTP{
356
		Success: true,
357
		Message: "Get Next Card",
358
		Data: models.ResponseCard{
359
			Card:    memDate.Card,
360
			Answers: answersList,
361
		},
362
	}
363
}
364
365
func FetchNextCardByDeck(c *fiber.Ctx, user *models.User, deckID string) models.ResponseHTTP {
366
	db := database.DBConn // DB Conn
367
368
	memDate := new(models.MemDate)
369
	var answersList []string
370
371
	// Get next card
372
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.deck_id = ?",
373
		&user.ID, deckID).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
374
		return models.ResponseHTTP{
375
			Success: false,
376
			Message: "Next card by deck not found",
377
			Data:    nil,
378
		}
379
	}
380
381
	mem := FetchMem(c, memDate, user)
382
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 || memDate.Card.Type == 2 {
383
		answersList = GenerateAnswers(c, memDate)
384
		if len(answersList) == 4 {
385
			memDate.Card.Type = 2 // MCQ
386
		}
387
	}
388
389
	return models.ResponseHTTP{
390
		Success: true,
391
		Message: "Get Next Card By Deck",
392
		Data: models.ResponseCard{
393
			Card:    memDate.Card,
394
			Answers: answersList,
395
		},
396
	}
397
}
398
399
// FetchNextTodayCard
400
func FetchNextTodayCard(c *fiber.Ctx, user *models.User) models.ResponseHTTP {
401
	db := database.DBConn // DB Conn
402
	memDate := new(models.MemDate)
403
404
	var answersList []string
405
406
	// Get next card with date condition
407
	t := time.Now()
408
409
	if err := db.Joins(
410
		"left join accesses ON mem_dates.deck_id = accesses.deck_id AND accesses.user_id = ?",
411
		user.ID).Joins("Card").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.next_date < ? AND accesses.permission >= ?",
412
		&user.ID, t.AddDate(0, 0, 1).Add(
413
			time.Duration(-t.Hour())*time.Hour), models.AccessStudent).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
414
		return models.ResponseHTTP{
415
			Success: false,
416
			Message: "Next today card not found",
417
			Data:    nil,
418
		}
419
	}
420
	mem := FetchMem(c, memDate, user)
421
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 || memDate.Card.Type == 2 {
422
		answersList = GenerateAnswers(c, memDate)
423
		if len(answersList) == 4 {
424
			memDate.Card.Type = 2 // MCQ
425
		}
426
	}
427
428
	return models.ResponseHTTP{
429
		Success: true,
430
		Message: "Get Next Today Card",
431
		Data: models.ResponseCard{
432
			Card:    memDate.Card,
433
			Answers: answersList,
434
		},
435
	}
436
}
437