use super::{ExtendedBalance, IdentifierT, PerThing128};
use crate::arithmetic::{
traits::{Bounded, Zero},
Normalizable, PerThing,
};
use alloc::vec::Vec;
#[cfg(feature = "serde")]
use codec::{Decode, Encode};
use core::fmt::Debug;
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(PartialEq, Eq, Encode, Decode))]
pub struct Assignment<AccountId, P: PerThing> {
pub who: AccountId,
pub distribution: Vec<(AccountId, P)>,
}
impl<AccountId: IdentifierT, P: PerThing128> Assignment<AccountId, P> {
pub fn into_staked(self, stake: ExtendedBalance) -> StakedAssignment<AccountId> {
let distribution = self
.distribution
.into_iter()
.filter_map(|(target, p)| {
if p.is_zero() {
None
} else {
let distribution_stake = p * stake;
Some((target, distribution_stake))
}
})
.collect::<Vec<(AccountId, ExtendedBalance)>>();
StakedAssignment { who: self.who, distribution }
}
pub fn try_normalize(&mut self) -> Result<(), &'static str> {
self.distribution
.iter()
.map(|(_, p)| *p)
.collect::<Vec<_>>()
.normalize(P::one())
.map(|normalized_ratios| {
self.distribution.iter_mut().zip(normalized_ratios).for_each(
|((_, old), corrected)| {
*old = corrected;
},
)
})
}
}
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(PartialEq, Eq, Encode, Decode))]
pub struct StakedAssignment<AccountId> {
pub who: AccountId,
pub distribution: Vec<(AccountId, ExtendedBalance)>,
}
impl<AccountId> StakedAssignment<AccountId> {
pub fn into_assignment<P: PerThing>(self) -> Assignment<AccountId, P>
where
AccountId: IdentifierT,
{
let stake = self.total();
let mut distribution = Vec::<(AccountId, P)>::with_capacity(self.distribution.len());
self.distribution.into_iter().for_each(|(target, w)| {
let per_thing = P::from_rational(w, stake);
if per_thing != Bounded::min_value() {
distribution.push((target, per_thing));
}
});
Assignment { who: self.who, distribution }
}
pub fn try_normalize(&mut self, stake: ExtendedBalance) -> Result<(), &'static str> {
self.distribution
.iter()
.map(|(_, ref weight)| *weight)
.collect::<Vec<_>>()
.normalize(stake)
.map(|normalized_weights| {
self.distribution.iter_mut().zip(normalized_weights.into_iter()).for_each(
|((_, weight), corrected)| {
*weight = corrected;
},
)
})
}
pub fn total(&self) -> ExtendedBalance {
self.distribution.iter().fold(Zero::zero(), |a, b| a.saturating_add(b.1))
}
}