-
Notifications
You must be signed in to change notification settings - Fork 44
/
polls.go
135 lines (109 loc) · 3.58 KB
/
polls.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
package types
import (
"fmt"
"strings"
"time"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// NewProvidedAnswer returns a new ProvidedAnswer object
func NewProvidedAnswer(id string, text string) ProvidedAnswer {
return ProvidedAnswer{
ID: id,
Text: text,
}
}
// Validate implements validator
func (answer ProvidedAnswer) Validate() error {
if strings.TrimSpace(answer.Text) == "" {
return fmt.Errorf("answer text must be specified and cannot be empty")
}
return nil
}
// ___________________________________________________________________________________________________________________
// ProvidedAnswers represent a slice of ProvidedAnswers objects
type ProvidedAnswers []ProvidedAnswer
// NewPollAnswers builds a new ProvidedAnswers object from the given answer
func NewPollAnswers(providedAnswers ...ProvidedAnswer) ProvidedAnswers {
return providedAnswers
}
// AppendIfMissing appends the given answer to the answers slice if it does not exist inside it yet.
// It returns a new slice of ProvidedAnswers containing such PollAnswer.
func (answers ProvidedAnswers) AppendIfMissing(answer ProvidedAnswer) ProvidedAnswers {
for _, existing := range answers {
if existing.Equal(answer) {
return answers
}
}
return append(answers, answer)
}
// ___________________________________________________________________________________________________________________
// NewPoll returns a new Poll object pointer containing the given poll
func NewPoll(
question string, endDate time.Time, providedAnswers []ProvidedAnswer, allowMultipleAnswers, allowsAnswerEdits bool,
) *Poll {
return &Poll{
Question: question,
EndDate: endDate,
ProvidedAnswers: providedAnswers,
AllowsMultipleAnswers: allowMultipleAnswers,
AllowsAnswerEdits: allowsAnswerEdits,
}
}
// Validate implements the validator interface
func (data Poll) Validate() error {
if strings.TrimSpace(data.Question) == "" {
return fmt.Errorf("missing poll question")
}
if data.EndDate.IsZero() {
return fmt.Errorf("invalid poll end date")
}
if len(data.ProvidedAnswers) < 2 {
return fmt.Errorf("poll answer must be at least two")
}
for _, answer := range data.ProvidedAnswers {
err := answer.Validate()
if err != nil {
return err
}
}
return nil
}
// ___________________________________________________________________________________________________________________
// NewUserAnswer returns a new UserAnswer object containing the given poll
func NewUserAnswer(postID, user string, answers []string) UserAnswer {
return UserAnswer{
PostID: postID,
User: user,
Answers: answers,
}
}
// Validate implements validator
func (ua UserAnswer) Validate() error {
if !IsValidPostID(ua.PostID) {
return fmt.Errorf("invalid post id: %s", ua.PostID)
}
if _, err := sdk.AccAddressFromBech32(ua.User); err != nil {
return fmt.Errorf("invalid user address: %s", ua.User)
}
if len(ua.Answers) == 0 {
return fmt.Errorf("answers cannot be empty")
}
for _, answer := range ua.Answers {
if strings.TrimSpace(answer) == "" {
return fmt.Errorf("invalid answer")
}
}
return nil
}
// MustMarshalUserAnswer serializes the given user answer using the provided BinaryCodec
func MustMarshalUserAnswer(cdc codec.BinaryCodec, answer UserAnswer) []byte {
return cdc.MustMarshal(&answer)
}
// MustUnmarshalUserAnswer deserializes the given byte array as a user answer using
// the provided BinaryCodec
func MustUnmarshalUserAnswer(cdc codec.BinaryCodec, bz []byte) UserAnswer {
var answer UserAnswer
cdc.MustUnmarshal(bz, &answer)
return answer
}