sp_npos_elections/
helpers.rs1use crate::{
21 Assignment, Error, ExtendedBalance, IdentifierT, PerThing128, StakedAssignment, Supports,
22 VoteWeight,
23};
24use alloc::{collections::BTreeMap, vec::Vec};
25use sp_arithmetic::PerThing;
26
27pub fn assignment_ratio_to_staked<A: IdentifierT, P: PerThing128, FS>(
31 ratios: Vec<Assignment<A, P>>,
32 stake_of: FS,
33) -> Vec<StakedAssignment<A>>
34where
35 for<'r> FS: Fn(&'r A) -> VoteWeight,
36{
37 ratios
38 .into_iter()
39 .map(|a| {
40 let stake = stake_of(&a.who);
41 a.into_staked(stake.into())
42 })
43 .collect()
44}
45
46pub fn assignment_ratio_to_staked_normalized<A: IdentifierT, P: PerThing128, FS>(
48 ratio: Vec<Assignment<A, P>>,
49 stake_of: FS,
50) -> Result<Vec<StakedAssignment<A>>, Error>
51where
52 for<'r> FS: Fn(&'r A) -> VoteWeight,
53{
54 let mut staked = assignment_ratio_to_staked(ratio, &stake_of);
55 staked.iter_mut().try_for_each(|a| {
56 a.try_normalize(stake_of(&a.who).into()).map_err(|_| Error::ArithmeticError)
57 })?;
58 Ok(staked)
59}
60
61pub fn assignment_staked_to_ratio<A: IdentifierT, P: PerThing>(
65 staked: Vec<StakedAssignment<A>>,
66) -> Vec<Assignment<A, P>> {
67 staked.into_iter().map(|a| a.into_assignment()).collect()
68}
69
70pub fn assignment_staked_to_ratio_normalized<A: IdentifierT, P: PerThing128>(
72 staked: Vec<StakedAssignment<A>>,
73) -> Result<Vec<Assignment<A, P>>, Error> {
74 let mut ratio = staked.into_iter().map(|a| a.into_assignment()).collect::<Vec<_>>();
75 for assignment in ratio.iter_mut() {
76 assignment.try_normalize().map_err(|_| Error::ArithmeticError)?;
77 }
78 Ok(ratio)
79}
80
81pub fn supports_to_staked_assignment<A: IdentifierT>(
83 supports: Supports<A>,
84) -> Vec<StakedAssignment<A>> {
85 let mut staked: BTreeMap<A, Vec<(A, ExtendedBalance)>> = BTreeMap::new();
86 for (target, support) in supports {
87 for (voter, amount) in support.voters {
88 staked.entry(voter).or_default().push((target.clone(), amount))
89 }
90 }
91
92 staked
93 .into_iter()
94 .map(|(who, distribution)| StakedAssignment { who, distribution })
95 .collect::<Vec<_>>()
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101 use sp_arithmetic::Perbill;
102
103 #[test]
104 fn into_staked_works() {
105 let assignments = vec![
106 Assignment {
107 who: 1u32,
108 distribution: vec![
109 (10u32, Perbill::from_float(0.5)),
110 (20, Perbill::from_float(0.5)),
111 ],
112 },
113 Assignment {
114 who: 2u32,
115 distribution: vec![
116 (10, Perbill::from_float(0.33)),
117 (20, Perbill::from_float(0.67)),
118 ],
119 },
120 ];
121
122 let stake_of = |_: &u32| -> VoteWeight { 100 };
123 let staked = assignment_ratio_to_staked(assignments, stake_of);
124
125 assert_eq!(
126 staked,
127 vec![
128 StakedAssignment { who: 1u32, distribution: vec![(10u32, 50), (20, 50),] },
129 StakedAssignment { who: 2u32, distribution: vec![(10u32, 33), (20, 67),] }
130 ]
131 );
132 }
133}