Passed
Pull Request — main (#71)
by Yume
01:15
created

models.*Card.GetMCQAnswers   C

Complexity

Conditions 10

Size

Total Lines 45
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

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

How to fix   Complexity   

Complexity

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