Passed
Push — main ( 4bc251...964038 )
by Yume
01:06
created

queries.GetSubUsers   A

Complexity

Conditions 2

Size

Total Lines 10
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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