Passed
Push — main ( 4b841f...20b475 )
by Yume
01:25 queued 12s
created

queries.DeleteRating   A

Complexity

Conditions 2

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

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