Passed
Push — main ( 7c64d9...5da60f )
by Yume
01:20
created

models.*Card.ValidateMCQ   A

Complexity

Conditions 5

Size

Total Lines 21
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 15
nop 1
dl 0
loc 21
rs 9.1832
c 0
b 0
f 0
1
package models
2
3
import (
4
	"database/sql"
5
	"fmt"
6
	"github.com/memnix/memnixrest/pkg/database"
7
	"github.com/memnix/memnixrest/pkg/utils"
8
	"gorm.io/gorm"
9
	"math/rand"
10
	"time"
11
)
12
13
// Card structure
14
type Card struct {
15
	gorm.Model `swaggerignore:"true"`
16
	Question   string `json:"card_question" example:"What's the answer to life ?"`
17
	Answer     string `json:"card_answer" example:"42"`
18
	DeckID     uint   `json:"deck_id" example:"1"`
19
	Deck       Deck
20
	Type       CardType      `json:"card_type" example:"0" gorm:"type:Int"`
21
	Format     string        `json:"card_format" example:"Date / Name / Country"`
22
	Image      string        `json:"card_image"` // Should be an url
23
	Case       bool          `json:"card_case" gorm:"default:false"`
24
	Spaces     bool          `json:"card_spaces" gorm:"default:false"`
25
	McqID      sql.NullInt32 `json:"mcq_id" swaggerignore:"true"`
26
	Mcq        Mcq
27
}
28
29
// CardType enum type
30
type CardType int64
31
32
const (
33
	CardString CardType = iota
34
	CardInt
35
	CardMCQ
36
)
37
38
// NotValidate performs validation of the Card
39
func (card *Card) NotValidate() bool {
40
	return len(card.Question) < utils.MinCardQuestionLen || card.Answer == "" || (card.Type == CardMCQ && card.McqID.Int32 == 0) || len(
41
		card.Format) > utils.MaxCardFormatLen || len(
42
		card.Question) > utils.MaxDefaultLen || len(card.Answer) > utils.MaxDefaultLen || len(card.Image) > utils.MaxImageUrlLen
43
}
44
45
// ValidateMCQ makes sure that the mcq attached to a card is correct
46
func (card *Card) ValidateMCQ(user *User) (*Mcq, bool) {
47
	db := database.DBConn // DB Conn
48
	mcq := new(Mcq)
49
50
	if card.McqID.Int32 != 0 {
51
		if err := db.First(&mcq, card.McqID).Error; err != nil {
52
			log := CreateLog(fmt.Sprintf("Error on CreateNewCard: %s from %s", err.Error(), user.Email), LogQueryGetError).SetType(LogTypeError).AttachIDs(user.ID, card.DeckID, 0)
53
			_ = log.SendLog()
54
			return nil, false
55
		}
56
		if mcq.DeckID != card.DeckID {
57
			log := CreateLog(fmt.Sprintf("Error on CreateNewCard: card.DeckID != mcq.DeckID from %s", user.Email), LogBadRequest).SetType(LogTypeError).AttachIDs(user.ID, card.DeckID, 0)
58
			_ = log.SendLog()
59
			return nil, false
60
		}
61
62
		if mcq.Type == McqLinked {
63
			return mcq, true
64
		}
65
	}
66
	return nil, true
67
}
68
69
// ToString returns CardType value as a string
70
func (s CardType) ToString() string {
71
	switch s {
72
	case CardString:
73
		return "Card String"
74
	case CardInt:
75
		return "Card Int"
76
	case CardMCQ:
77
		return "Card MCQ"
78
	default:
79
		return "Unknown"
80
	}
81
}
82
83
// GetMCQAnswers returns mcq's answers
84
func (card *Card) GetMCQAnswers() []string {
85
	db := database.DBConn // DB Conn
86
87
	var answers []string
88
89
	mcq := new(Mcq)
90
91
	if err := db.First(&mcq, card.McqID).Error; err != nil {
92
		return answers
93
	}
94
95
	answersList := mcq.GetAnswers()
96
97
	for i := range answersList {
98
		if i >= len(answersList) {
99
			break
100
		}
101
		if answersList[i] == card.Answer {
102
			answersList[i] = answersList[len(answersList)-1]
103
			answersList = answersList[:len(answersList)-1]
104
		}
105
	}
106
107
	if len(answersList) < 3 {
108
		return answers
109
	}
110
111
	rand.Seed(time.Now().UnixNano())
112
	rand.Shuffle(len(answersList), func(i, j int) { answersList[i], answersList[j] = answersList[j], answersList[i] })
113
114
	i, c := 0, 0
115
	for i < 3 {
116
		if answersList[c] != card.Answer {
117
			answers = append(answers, answersList[c])
118
			i++
119
		}
120
		c++
121
	}
122
123
	answers = append(answers, card.Answer)
124
125
	rand.Seed(time.Now().UnixNano())
126
	rand.Shuffle(len(answers), func(i, j int) { answers[i], answers[j] = answers[j], answers[i] })
127
128
	return answers
129
}
130