Search Apps Documentation Source Content File Folder Download Copy Actions Download

cond_role_count.gno

2.01 Kb ยท 75 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
16// Creates a condition requiring a specific number of role holders to vote yes.
17//
18// Example: RoleCount(2, "admin", hasRoleFn)
19// Requires 2 admin votes.
20func RoleCount(count uint64, role string, hasRoleFn func(memberId string, role string) bool) Condition {
21	if count == 0 {
22		panic(errors.New("count must be greater than 0"))
23	}
24	if role == "" {
25		panic(errors.New("role must not be empty"))
26	}
27	if hasRoleFn == nil {
28		panic(errors.New("nil hasRoleFn"))
29	}
30	return &roleCountCond{
31		count:     count,
32		hasRoleFn: hasRoleFn,
33		role:      role,
34	}
35}
36
37// Checks if enough role holders voted yes to meet the count.
38func (c *roleCountCond) Eval(ballot Ballot) bool {
39	return c.totalVote(ballot, VoteYes) >= c.count
40}
41
42// Returns progress toward meeting the required count between 0.0 and 1.0.
43func (c *roleCountCond) Signal(ballot Ballot) float64 {
44	return math.Min(float64(c.totalVote(ballot, VoteYes))/float64(c.count), 1)
45}
46
47// Displays the condition as text.
48// Example output: "2 admin"
49func (c *roleCountCond) Render() string {
50	return ufmt.Sprintf("%d %s", c.count, c.role)
51}
52
53// Displays the condition with current vote counts.
54// Example output: "2 admin must vote yes\n\nYes: 1/2"
55func (c *roleCountCond) RenderWithVotes(ballot Ballot) string {
56	s := ""
57	s += ufmt.Sprintf("%d members with role %s must vote yes\n\n", c.count, c.role)
58	s += ufmt.Sprintf("Yes: %d/%d\n\n", c.totalVote(ballot, VoteYes), c.count)
59	s += ufmt.Sprintf("No: %d/%d\n\n", c.totalVote(ballot, VoteNo), c.count)
60	s += ufmt.Sprintf("Abstain: %d/%d\n\n", c.totalVote(ballot, VoteAbstain), c.count)
61	return s
62}
63
64var _ Condition = (*roleCountCond)(nil)
65
66func (c *roleCountCond) totalVote(ballot Ballot, vote Vote) uint64 {
67	total := uint64(0)
68	ballot.Iterate(func(voter string, v Vote) bool {
69		if v == vote && c.hasRoleFn(voter, c.role) {
70			total += 1
71		}
72		return false
73	})
74	return total
75}