cond_role_count.gno
1.54 Kb ยท 67 lines
1package daocond
2
3import (
4 "errors"
5 "math"
6
7 "gno.land/p/nt/ufmt"
8)
9
10type roleCountCond struct {
11 hasRoleFn func(memberId string, role string) bool
12 count uint64
13 role string
14}
15
16func RoleCount(count uint64, role string, hasRoleFn func(memberId string, role string) bool) Condition {
17 if count == 0 {
18 panic(errors.New("count must be greater than 0"))
19 }
20 if role == "" {
21 panic(errors.New("role must not be empty"))
22 }
23 if hasRoleFn == nil {
24 panic(errors.New("nil hasRoleFn"))
25 }
26 return &roleCountCond{
27 count: count,
28 hasRoleFn: hasRoleFn,
29 role: role,
30 }
31}
32
33// Eval implements Condition.
34func (c *roleCountCond) Eval(ballot Ballot) bool {
35 return c.totalYes(ballot) >= c.count
36}
37
38// Signal implements Condition.
39func (c *roleCountCond) Signal(ballot Ballot) float64 {
40 return math.Min(float64(c.totalYes(ballot))/float64(c.count), 1)
41}
42
43// Render implements Condition.
44func (c *roleCountCond) Render() string {
45 return ufmt.Sprintf("%d %s", c.count, c.role)
46}
47
48// RenderWithVotes implements Condition.
49func (c *roleCountCond) RenderWithVotes(ballot Ballot) string {
50 s := ""
51 s += ufmt.Sprintf("to meet the condition, %d members with role %s must vote yes\n\n", c.count, c.role)
52 s += ufmt.Sprintf("Yes: %d/%d\n\n", c.totalYes(ballot), c.count)
53 return s
54}
55
56var _ Condition = (*roleCountCond)(nil)
57
58func (c *roleCountCond) totalYes(ballot Ballot) uint64 {
59 totalYes := uint64(0)
60 ballot.Iterate(func(voter string, vote Vote) bool {
61 if vote == VoteYes && c.hasRoleFn(voter, c.role) {
62 totalYes += 1
63 }
64 return false
65 })
66 return totalYes
67}