use crate::{
interface::{WithSeats, WithVotes},
utils::clear_results,
};
pub fn compute_divisor_method<'a, T>(
results: &'a mut Vec<T>,
seats: u16,
divisor: impl Fn(u16) -> f32,
) -> Result<(), &'a str>
where
T: WithSeats + WithVotes,
{
clear_results(results);
for _ in 0..seats {
let better_idx = results
.iter()
.map(|c| {
let votes = c.get_votes() as f32;
let seats = c.get_seats();
let div = divisor(seats);
votes / div
})
.enumerate()
.max_by(|(_, a), (_, b)| a.total_cmp(b));
match better_idx {
Some((idx, _)) => results[idx].increase_seats(1),
None => return Err("EMPTY_RESULTS"),
}
}
Ok(())
}
#[allow(dead_code)]
pub fn compute_dhondt<T>(results: &mut Vec<T>, seats: u16) -> Result<(), &str>
where
T: WithSeats + WithVotes,
{
compute_divisor_method(results, seats, |s| (s + 1) as f32)
}
#[allow(dead_code)]
pub fn compute_sainte_lague<T>(results: &mut Vec<T>, seats: u16) -> Result<(), &str>
where
T: WithSeats + WithVotes,
{
compute_divisor_method(results, seats, |s| (2 * s + 1) as f32)
}
#[allow(dead_code)]
pub fn compute_adams<T>(results: &mut Vec<T>, seats: u16) -> Result<(), &str>
where
T: WithSeats + WithVotes,
{
compute_divisor_method(results, seats, |s| s as f32)
}
#[allow(dead_code)]
pub fn compute_imperiali<T>(results: &mut Vec<T>, seats: u16) -> Result<(), &str>
where
T: WithSeats + WithVotes,
{
compute_divisor_method(results, seats, |s| (s + 2) as f32)
}
#[allow(dead_code)]
pub fn compute_huntington_hill<T>(results: &mut Vec<T>, seats: u16) -> Result<(), &str>
where
T: WithSeats + WithVotes,
{
compute_divisor_method(results, seats, |s| ((s * (s + 1)) as f32).sqrt())
}
#[allow(dead_code)]
pub fn compute_danish<T>(results: &mut Vec<T>, seats: u16) -> Result<(), &str>
where
T: WithSeats + WithVotes,
{
compute_divisor_method(results, seats, |s| (3 * s + 1) as f32)
}
#[allow(dead_code)]
pub fn compute_wta<T>(results: &mut Vec<T>, seats: u16) -> Result<(), &str>
where
T: WithSeats + WithVotes,
{
clear_results(results);
let better_idx = results
.iter()
.map(|c| c.get_votes())
.enumerate()
.max_by(|(_, a), (_, b)| a.cmp(b));
match better_idx {
Some((idx, _)) => results[idx].set_seats(seats),
None => return Err("EMPTY_RESULTS"),
}
Ok(())
}