Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}