Passed
Pull Request — main (#42)
by Yume
01:17
created

models.*Card.NotValidate   C

Complexity

Conditions 10

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 5
nop 0
dl 0
loc 5
rs 5.9999
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like models.*Card.NotValidate often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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          `swaggerignore:"true" json:"-"`
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
	Explication      string        `json:"card_explication"`
26
	ExplicationImage string        `json:"card_explication_image"`
27
	McqID            sql.NullInt32 `json:"mcq_id" swaggerignore:"true"`
28
	Mcq              Mcq           `swaggerignore:"true" json:"-"`
29
}
30
31
// CardType enum type
32
type CardType int64
33
34
const (
35
	CardString CardType = iota
36
	CardInt
37
	CardMCQ
38
)
39
40
// NotValidate performs validation of the Card
41
func (card *Card) NotValidate() bool {
42
	return len(card.Question) < utils.MinCardQuestionLen || card.Answer == "" || (card.Type == CardMCQ && card.McqID.Int32 == 0) || len(
43
		card.Format) > utils.MaxCardFormatLen || len(
44
		card.Question) > utils.MaxDefaultLen || len(card.Answer) > utils.MaxDefaultLen || len(card.Image) > utils.MaxImageURLLen || len(
45
		card.ExplicationImage) > utils.MaxImageURLLen || len(card.Explication) > utils.MaxCardExplicationLen
46
}
47
48
// ValidateMCQ makes sure that the mcq attached to a card is correct
49
func (card *Card) ValidateMCQ(user *User) (*Mcq, bool) {
50
	db := database.DBConn // DB Conn
51
	mcq := new(Mcq)
52
53
	if card.McqID.Int32 != 0 {
54
		if err := db.First(&mcq, card.McqID).Error; err != nil {
55
			log := CreateLog(fmt.Sprintf("Error on CreateNewCard: %s from %s", err.Error(), user.Email), LogQueryGetError).SetType(LogTypeError).AttachIDs(user.ID, card.DeckID, 0)
56
			_ = log.SendLog()
57
			return nil, false
58
		}
59
		if mcq.DeckID != card.DeckID {
60
			log := CreateLog(fmt.Sprintf("Error on CreateNewCard: card.DeckID != mcq.DeckID from %s", user.Email), LogBadRequest).SetType(LogTypeError).AttachIDs(user.ID, card.DeckID, 0)
61
			_ = log.SendLog()
62
			return nil, false
63
		}
64
65
		if mcq.Type == McqLinked {
66
			return mcq, true
67
		}
68
	}
69
	return nil, true
70
}
71
72
// ToString returns CardType value as a string
73
func (s CardType) ToString() string {
74
	switch s {
75
	case CardString:
76
		return "Card String"
77
	case CardInt:
78
		return "Card Int"
79
	case CardMCQ:
80
		return "Card MCQ"
81
	default:
82
		return utils.UNKNOWN
83
	}
84
}
85
86
// GetMCQAnswers returns mcq's answers
87
func (card *Card) GetMCQAnswers() []string {
88
	db := database.DBConn // DB Conn
89
90
	var answers []string
91
92
	mcq := new(Mcq)
93
94
	if err := db.First(&mcq, card.McqID).Error; err != nil {
95
		return answers
96
	}
97
98
	answersList := mcq.GetAnswers()
99
100
	for i := range answersList {
101
		if i >= len(answersList) {
102
			break
103
		}
104
		if answersList[i] == card.Answer {
105
			answersList[i] = answersList[len(answersList)-1]
106
			answersList = answersList[:len(answersList)-1]
107
		}
108
	}
109
110
	if len(answersList) < 3 {
111
		return make([]string, 0)
112
	}
113
114
	rand.Seed(time.Now().UnixNano())
115
	rand.Shuffle(len(answersList), func(i, j int) { answersList[i], answersList[j] = answersList[j], answersList[i] })
116
117
	i, c := 0, 0
118
	for i < 3 {
119
		if answersList[c] != card.Answer {
120
			answers = append(answers, answersList[c])
121
			i++
122
		}
123
		c++
124
	}
125
126
	answers = append(answers, card.Answer)
127
128
	rand.Seed(time.Now().UnixNano())
129
	rand.Shuffle(len(answers), func(i, j int) { answers[i], answers[j] = answers[j], answers[i] })
130
131
	return answers
132
}
133