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

models.*Mem.ComputeLearningStage   A

Complexity

Conditions 5

Size

Total Lines 8
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 8
nop 0
dl 0
loc 8
rs 9.3333
c 0
b 0
f 0
1
package models
2
3
import (
4
	"gorm.io/gorm"
5
)
6
7
// Mem structure
8
type Mem struct {
9
	gorm.Model    `swaggerignore:"true"`
10
	UserID        uint          `json:"user_id" example:"1"`
11
	User          User          `swaggerignore:"true"`
12
	CardID        uint          `json:"card_id" example:"1"`
13
	Card          Card          `swaggerignore:"true"`
14
	Quality       MemQuality    `json:"quality" example:"0"`
15
	Repetition    uint          `json:"repetition" example:"0" `
16
	Efactor       float32       `json:"e_factor" example:"2.5"`
17
	Interval      uint          `json:"interval" example:"0"`
18
	LearningStage LearningStage `json:"learning_stage"`
19
}
20
21
// MemQuality enum type
22
type MemQuality int64
23
24
const (
25
	MemQualityNone     MemQuality = -1
26
	MemQualityBlackout MemQuality = iota
27
	MemQualityErrorMCQ
28
	MemQualityErrorHints
29
	MemQualityError
30
	MemQualityGoodMCQ
31
	MemQualityPerfect
32
)
33
34
// FillDefaultValues to fill a Mem with default values for given UserID and CardID
35
func (mem *Mem) FillDefaultValues(userID, cardID uint) {
36
	mem.UserID = userID
37
	mem.CardID = cardID
38
	mem.Quality = MemQualityBlackout
39
	mem.Repetition = 0
40
	mem.Efactor = 2.5
41
	mem.Interval = 0
42
	mem.LearningStage = StageToLearn
43
}
44
45
// ComputeEfactor calculates and sets new efactor using oldEfactor and MemQuality
46
func (mem *Mem) ComputeEfactor(oldEfactor float32, quality MemQuality) {
47
	eFactor := oldEfactor + (0.1 - (5.0-float32(quality))*(0.08+(5-float32(quality)))*0.02)
48
49
	if eFactor < 1.3 {
50
		mem.Efactor = 1.3
51
	} else {
52
		mem.Efactor = eFactor
53
	}
54
}
55
56
// ComputeTrainingEfactor calculates and sets new efactor using oldEfactor and MemQuality
57
// TrainingEfactor is a median between oldEfactor and ComputeEfactor
58
func (mem *Mem) ComputeTrainingEfactor(oldEfactor float32, quality MemQuality) {
59
	mem.ComputeEfactor(oldEfactor, quality)
60
	computedTrainingEfactor := (oldEfactor + mem.Efactor) / 2
61
	if computedTrainingEfactor < 1.3 {
62
		mem.Efactor = 1.3
63
	} else {
64
		mem.Efactor = computedTrainingEfactor
65
	}
66
}
67
68
// GetCardType returns the current CardType
69
// The CardType is CardMCQ if internal conditions are matched.
70
// Otherwise, it's Card.Type
71
func (mem *Mem) GetCardType() CardType {
72
	if mem.IsMCQ() {
73
		return CardMCQ
74
	}
75
76
	return mem.Card.Type
77
}
78
79
// ComputeInterval calculates and sets the interval between reviews
80
func (mem *Mem) ComputeInterval(oldInterval uint, eFactor float32, repetition uint) {
81
	switch repetition {
82
	case 0:
83
		mem.Interval = 1
84
	case 1, 2:
85
		mem.Interval = 2
86
	case 3:
87
		mem.Interval = 3
88
	default:
89
		mem.Interval = uint(float32(oldInterval)*eFactor*0.75) + 1
90
	}
91
}
92
93
func (mem *Mem) ComputeLearningStage() {
94
	switch {
95
	case mem.Repetition > 3 && mem.Repetition < 7:
96
		mem.LearningStage = StageReviewing
97
	case mem.Repetition > 7:
98
		mem.LearningStage = StageKnown
99
	default:
100
		mem.LearningStage = StageLearning
101
	}
102
}
103
104
// ComputeQualitySuccess sets the answer Quality
105
func (mem *Mem) ComputeQualitySuccess() {
106
	switch {
107
	case mem.GetCardType() == CardMCQ || mem.LearningStage == StageToLearn:
108
		mem.Quality = MemQualityError
109
	case mem.LearningStage == StageKnown:
110
		mem.Quality = MemQualityPerfect
111
	default:
112
		mem.Quality = MemQualityGoodMCQ
113
	}
114
}
115
116
// ComputeQualityFail sets the answer Quality
117
func (mem *Mem) ComputeQualityFail() {
118
	switch {
119
	case mem.GetCardType() == CardMCQ:
120
		if mem.LearningStage == StageToLearn {
121
			mem.Quality = MemQualityBlackout
122
		} else {
123
			mem.Quality = MemQualityErrorMCQ
124
		}
125
	case mem.LearningStage == StageLearning:
126
		mem.Quality = MemQualityErrorMCQ
127
	default:
128
		mem.Quality = MemQualityErrorHints
129
	}
130
}
131
132
// IsMCQ returns if the Mem should be an MCQ or not.
133
// It doesn't include Card.Type checks
134
func (mem *Mem) IsMCQ() bool {
135
	return mem.LearningStage < StageReviewing || mem.Efactor <= 1.7 || mem.Repetition < 2 || (mem.Efactor <= 2.3 && mem.Repetition < 3)
136
}
137