Passed
Branch main (df988b)
by Yume
01:16
created

queries.GenerateAnswers   A

Complexity

Conditions 3

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 8
nop 2
dl 0
loc 13
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 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
// GenerateAccess
90
func GenerateAccess(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
91
	db := database.DBConn
92
93
	if deck.Status != models.DeckPublic && user.Permissions != models.PermAdmin {
94
		return models.ResponseHTTP{
95
			Success: false,
96
			Message: "You don't have the permissions to subscribe to this deck!",
97
			Data:    nil,
98
			Count:   0,
99
		}
100
	}
101
102
	access := new(models.Access)
103
104
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id =?", user.ID, deck.ID).Find(&access).Error; err != nil {
105
		if errors.Is(err, gorm.ErrRecordNotFound) {
106
			access.DeckID = deck.ID
107
			access.UserID = user.ID
108
			access.Permission = 1
109
			db.Preload("User").Preload("Deck").Create(access)
110
		}
111
112
	} else {
113
		if access.Permission >= models.AccessStudent {
114
			return models.ResponseHTTP{
115
				Success: false,
116
				Message: "You are already subscribed to this deck",
117
				Data:    nil,
118
				Count:   0,
119
			}
120
		} else {
121
			access.DeckID = deck.ID
122
			access.UserID = user.ID
123
			access.Permission = 1
124
			db.Preload("User").Preload("Deck").Save(access)
125
		}
126
	}
127
128
	return models.ResponseHTTP{
129
		Success: true,
130
		Message: "Success register an access",
131
		Data:    *access,
132
		Count:   1,
133
	}
134
}
135
136
func CheckAccess(c *fiber.Ctx, user *models.User, card *models.Card) models.Access {
137
	db := database.DBConn // DB Conn
138
139
	access := new(models.Access)
140
141
	if err := db.Joins("User").Joins("Deck").Where("accesses.user_id = ? AND accesses.deck_id = ?", user.ID, card.DeckID).First(&access).Error; err != nil {
142
		access.Permission = 0
143
		return *access
144
	}
145
146
	return *access
147
}
148
149
func PostMem(c *fiber.Ctx, user models.User, card models.Card, validation models.CardResponseValidation) models.ResponseHTTP {
150
	db := database.DBConn // DB Conn
151
152
	memDate := new(models.MemDate)
153
154
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.card_id = ?",
155
		&user.ID, card.ID).First(&memDate).Error; err != nil {
156
		return models.ResponseHTTP{
157
			Success: false,
158
			Message: "MemDate Not Found",
159
			Data:    nil,
160
		}
161
	}
162
163
	ex_mem := FetchMem(c, memDate, &user)
164
	if ex_mem.Efactor == 0 {
165
		ex_mem = models.Mem{
166
			UserID:     user.ID,
167
			CardID:     card.ID,
168
			Quality:    0,
169
			Repetition: 0,
170
			Efactor:    2.5,
171
			Interval:   0,
172
		}
173
	}
174
175
	core.UpdateMem(c, &ex_mem, validation)
176
177
	return models.ResponseHTTP{
178
		Success: true,
179
		Message: "Success Post Mem",
180
		Data:    nil,
181
	}
182
}
183
184
func PopulateMemDate(c *fiber.Ctx, user *models.User, deck *models.Deck) models.ResponseHTTP {
185
	db := database.DBConn // DB Conn
186
	var cards []models.Card
187
188
	if err := db.Joins("Deck").Where("cards.deck_id = ?", deck.ID).Find(&cards).Error; err != nil {
189
		return models.ResponseHTTP{
190
			Success: false,
191
			Message: err.Error(),
192
			Data:    nil,
193
			Count:   0,
194
		}
195
	}
196
197
	for _, s := range cards {
198
		_ = GenerateMemDate(c, user, &s)
199
	} // TODO: Handle errors
200
201
	return models.ResponseHTTP{
202
		Success: true,
203
		Message: "Success generated mem_date",
204
		Data:    nil,
205
		Count:   0,
206
	}
207
208
}
209
210
func GenerateMemDate(c *fiber.Ctx, user *models.User, card *models.Card) models.ResponseHTTP {
211
	db := database.DBConn // DB Conn
212
213
	memDate := new(models.MemDate)
214
215
	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 {
216
		if errors.Is(err, gorm.ErrRecordNotFound) {
217
218
			memDate = &models.MemDate{
219
				UserID:   user.ID,
220
				CardID:   card.ID,
221
				DeckID:   card.DeckID,
222
				NextDate: time.Now(),
223
			}
224
225
			db.Preload("User").Preload("Card").Create(memDate)
226
		} else {
227
			return models.ResponseHTTP{
228
				Success: false,
229
				Message: err.Error(),
230
				Data:    nil,
231
				Count:   0,
232
			}
233
		}
234
	}
235
236
	return models.ResponseHTTP{
237
		Success: true,
238
		Message: "Success generate MemDate",
239
		Data:    *memDate,
240
		Count:   1,
241
	}
242
}
243
244
// FetchAnswers
245
func FetchAnswers(c *fiber.Ctx, card *models.Card) []models.Answer {
246
	var answers []models.Answer
247
	db := database.DBConn // DB Conn
248
249
	if err := db.Joins("Card").Where("answers.card_id = ?", card.ID).Limit(3).Order("random()").Find(&answers).Error; err != nil {
250
		return nil
251
	}
252
253
	return answers
254
}
255
256
func FetchMem(c *fiber.Ctx, memDate *models.MemDate, user *models.User) models.Mem {
257
	db := database.DBConn // DB Conn
258
259
	mem := new(models.Mem)
260
	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 {
261
		mem.Efactor = 0
262
	}
263
	return *mem
264
}
265
266
func GenerateAnswers(c *fiber.Ctx, memDate *models.MemDate) []string {
267
	var answersList []string
268
269
	res := FetchAnswers(c, &memDate.Card)
270
271
	if len(res) >= 3 {
272
		answersList = append(answersList, res[0].Answer, res[1].Answer, res[2].Answer, memDate.Card.Answer)
273
274
		rand.Seed(time.Now().UnixNano())
275
		rand.Shuffle(len(answersList), func(i, j int) { answersList[i], answersList[j] = answersList[j], answersList[i] })
276
	}
277
278
	return answersList
279
280
}
281
282
func FetchNextCard(c *fiber.Ctx, user *models.User) models.ResponseHTTP {
283
	db := database.DBConn // DB Conn
284
285
	memDate := new(models.MemDate)
286
	var answersList []string
287
288
	// Get next card
289
	if err := db.Joins(
290
		"left join accesses ON mem_dates.deck_id = accesses.deck_id AND accesses.user_id = ?",
291
		user.ID).Joins("Card").Joins("Deck").Where("mem_dates.user_id = ? AND accesses.permission >= ?",
292
		&user.ID, models.AccessStudent).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
293
		return models.ResponseHTTP{
294
			Success: false,
295
			Message: "Next card not found",
296
			Data:    nil,
297
		}
298
	}
299
300
	mem := FetchMem(c, memDate, user)
301
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 {
302
		answersList = GenerateAnswers(c, memDate)
303
		if len(answersList) == 4 {
304
			memDate.Card.Type = 2 // MCQ
305
		}
306
	}
307
308
	return models.ResponseHTTP{
309
		Success: true,
310
		Message: "Get Next Card",
311
		Data: models.ResponseCard{
312
			Card:    memDate.Card,
313
			Answers: answersList,
314
		},
315
	}
316
}
317
318
func FetchNextCardByDeck(c *fiber.Ctx, user *models.User, deckID string) models.ResponseHTTP {
319
	db := database.DBConn // DB Conn
320
321
	memDate := new(models.MemDate)
322
	var answersList []string
323
324
	// Get next card
325
	if err := db.Joins("Card").Joins("User").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.deck_id = ?",
326
		&user.ID, deckID).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
327
		return models.ResponseHTTP{
328
			Success: false,
329
			Message: "Next card by deck not found",
330
			Data:    nil,
331
		}
332
	}
333
334
	mem := FetchMem(c, memDate, user)
335
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 {
336
		answersList = GenerateAnswers(c, memDate)
337
		if len(answersList) == 4 {
338
			memDate.Card.Type = 2 // MCQ
339
		}
340
	}
341
342
	return models.ResponseHTTP{
343
		Success: true,
344
		Message: "Get Next Card By Deck",
345
		Data: models.ResponseCard{
346
			Card:    memDate.Card,
347
			Answers: answersList,
348
		},
349
	}
350
}
351
352
// FetchNextTodayCard
353
func FetchNextTodayCard(c *fiber.Ctx, user *models.User) models.ResponseHTTP {
354
	db := database.DBConn // DB Conn
355
	memDate := new(models.MemDate)
356
357
	var answersList []string
358
359
	// Get next card with date condition
360
	t := time.Now()
361
362
	if err := db.Joins(
363
		"left join accesses ON mem_dates.deck_id = accesses.deck_id AND accesses.user_id = ?",
364
		user.ID).Joins("Card").Joins("Deck").Where("mem_dates.user_id = ? AND mem_dates.next_date < ? AND accesses.permission >= ?",
365
		&user.ID, t.AddDate(0, 0, 1).Add(
366
			time.Duration(-t.Hour())*time.Hour), models.AccessStudent).Limit(1).Order("next_date asc").Find(&memDate).Error; err != nil {
367
		return models.ResponseHTTP{
368
			Success: false,
369
			Message: "Next today card not found",
370
			Data:    nil,
371
		}
372
	}
373
	mem := FetchMem(c, memDate, user)
374
	if mem.Efactor <= 1.4 || mem.Quality <= 1 || mem.Repetition < 2 {
375
		answersList = GenerateAnswers(c, memDate)
376
		if len(answersList) == 4 {
377
			memDate.Card.Type = 2 // MCQ
378
		}
379
	}
380
381
	return models.ResponseHTTP{
382
		Success: true,
383
		Message: "Get Next Today Card",
384
		Data: models.ResponseCard{
385
			Card:    memDate.Card,
386
			Answers: answersList,
387
		},
388
	}
389
}
390