#![allow(dead_code)]
use rand::{self, seq::SliceRandom, Rng, RngCore};
use sp_npos_elections::{phragmms, seq_phragmen, BalancingConfig, ElectionResult, VoteWeight};
use sp_runtime::Perbill;
use std::collections::{BTreeMap, HashSet};
pub fn to_range(x: usize, a: usize, b: usize) -> usize {
assert!(b >= 2 * a);
let collapsed = x % b;
if collapsed >= a {
collapsed
} else {
collapsed + a
}
}
pub enum ElectionType {
Phragmen(Option<BalancingConfig>),
Phragmms(Option<BalancingConfig>),
}
pub type AccountId = u64;
pub fn generate_random_npos_inputs(
candidate_count: usize,
voter_count: usize,
mut rng: impl Rng,
) -> (usize, Vec<AccountId>, Vec<(AccountId, VoteWeight, Vec<AccountId>)>) {
let mut used_ids = HashSet::with_capacity(candidate_count + voter_count);
let rounds = rng.gen_range(1..candidate_count);
let mut candidates: Vec<AccountId> = Vec::with_capacity(candidate_count);
for _ in 0..candidate_count {
let mut id = rng.gen();
while !used_ids.insert(id) {
id = rng.gen();
}
candidates.push(id);
}
candidates.sort();
candidates.dedup();
assert_eq!(candidates.len(), candidate_count);
let mut voters = Vec::with_capacity(voter_count);
for _ in 0..voter_count {
let mut id = rng.gen();
while !used_ids.insert(id) {
id = rng.gen();
}
let vote_weight = rng.gen();
let n_candidates_chosen = rng.gen_range(1..candidates.len());
let mut chosen_candidates = Vec::with_capacity(n_candidates_chosen);
chosen_candidates.extend(candidates.choose_multiple(&mut rng, n_candidates_chosen));
chosen_candidates.sort();
voters.push((id, vote_weight, chosen_candidates));
}
voters.sort();
voters.dedup_by_key(|(id, _weight, _chosen_candidates)| *id);
assert_eq!(voters.len(), voter_count);
(rounds, candidates, voters)
}
pub fn generate_random_npos_result(
voter_count: u64,
target_count: u64,
to_elect: usize,
mut rng: impl RngCore,
election_type: ElectionType,
) -> (
ElectionResult<AccountId, Perbill>,
Vec<AccountId>,
Vec<(AccountId, VoteWeight, Vec<AccountId>)>,
BTreeMap<AccountId, VoteWeight>,
) {
let prefix = 100_000;
let base_stake: u64 = 1_000_000_000_000;
let ed: u64 = base_stake;
let mut candidates = Vec::with_capacity(target_count as usize);
let mut stake_of: BTreeMap<AccountId, VoteWeight> = BTreeMap::new();
(1..=target_count).for_each(|acc| {
candidates.push(acc);
let stake_var = rng.gen_range(ed..100 * ed);
stake_of.insert(acc, base_stake + stake_var);
});
let mut voters = Vec::with_capacity(voter_count as usize);
(prefix..=(prefix + voter_count)).for_each(|acc| {
let edge_per_this_voter = rng.gen_range(1..candidates.len());
let mut all_targets = candidates.clone();
let targets = (0..edge_per_this_voter)
.map(|_| {
let upper = all_targets.len() - 1;
let idx = rng.gen_range(0..upper);
all_targets.remove(idx)
})
.collect::<Vec<AccountId>>();
let stake_var = rng.gen_range(ed..100 * ed);
let stake = base_stake + stake_var;
stake_of.insert(acc, stake);
voters.push((acc, stake, targets));
});
(
match election_type {
ElectionType::Phragmen(conf) =>
seq_phragmen(to_elect, candidates.clone(), voters.clone(), conf).unwrap(),
ElectionType::Phragmms(conf) =>
phragmms(to_elect, candidates.clone(), voters.clone(), conf).unwrap(),
},
candidates,
voters,
stake_of,
)
}