pub mod node;
use std::cell::Cell;
use crate::snowman::snowball::binary;
#[derive(Clone, Debug)]
pub struct Snowflake {
beta: Cell<i64>,
confidence: Cell<i64>,
finalized: Cell<bool>,
}
impl Snowflake {
pub fn new(beta: i64) -> Self {
Self {
beta: Cell::new(beta),
confidence: Cell::new(0),
finalized: Cell::new(false),
}
}
pub fn beta(&self) -> i64 {
self.beta.get()
}
pub fn confidence(&self) -> i64 {
self.confidence.get()
}
pub fn finalized(&self) -> bool {
self.finalized.get()
}
pub fn record_successful_poll(&self) {
let confidence = self.confidence.get() + 1;
self.confidence.set(confidence);
if !self.finalized.get() {
self.finalized.set(confidence >= self.beta());
}
}
pub fn record_unsuccessful_poll(&self) {
self.confidence.set(0);
}
pub fn extend(&self, beta: i64, choice: i64) -> binary::Snowflake {
binary::Snowflake::new(beta, choice, self.confidence(), self.finalized())
}
}
impl std::fmt::Display for Snowflake {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"SF(Confidence = {}, Finalized = {})",
self.confidence(),
self.finalized()
)
}
}
#[test]
fn test_snowflake() {
let _ = env_logger::builder()
.filter_level(log::LevelFilter::Info)
.is_test(true)
.try_init();
let beta = 2_i64;
let snf = Snowflake::new(beta);
snf.record_successful_poll();
assert_eq!(snf.beta(), beta);
assert_eq!(snf.confidence(), 1);
assert_eq!(snf.finalized(), false);
snf.record_unsuccessful_poll();
assert_eq!(snf.beta(), beta);
assert_eq!(snf.confidence(), 0);
assert_eq!(snf.finalized(), false);
snf.record_successful_poll();
assert_eq!(snf.beta(), beta);
assert_eq!(snf.confidence(), 1);
assert_eq!(snf.finalized(), false);
snf.record_successful_poll();
assert_eq!(snf.beta(), beta);
assert_eq!(snf.confidence(), 2);
assert_eq!(snf.finalized(), true);
snf.record_unsuccessful_poll();
assert_eq!(snf.beta(), beta);
assert_eq!(snf.confidence(), 0);
assert_eq!(snf.finalized(), true);
snf.record_successful_poll();
assert_eq!(snf.beta(), beta);
assert_eq!(snf.confidence(), 1);
assert_eq!(snf.finalized(), true);
log::info!("{snf}");
}
#[test]
fn test_snowflake_extend() {
let _ = env_logger::builder()
.filter_level(log::LevelFilter::Info)
.is_test(true)
.try_init();
let beta = 2_i64;
let snf = Snowflake::new(beta);
assert_eq!(snf.beta(), beta);
snf.record_successful_poll();
assert_eq!(snf.confidence(), 1);
assert_eq!(snf.finalized(), false);
snf.record_unsuccessful_poll();
assert_eq!(snf.confidence(), 0);
assert_eq!(snf.finalized(), false);
snf.record_successful_poll();
assert_eq!(snf.confidence(), 1);
assert_eq!(snf.finalized(), false);
let snf_binary = snf.extend(beta, 0);
assert_eq!(snf_binary.beta(), beta);
snf_binary.record_unsuccessful_poll();
snf_binary.record_successful_poll(1);
assert_eq!(snf_binary.finalized(), false);
snf_binary.record_successful_poll(1);
assert_eq!(snf_binary.preference(), 1);
assert_eq!(snf_binary.finalized(), true);
log::info!("{snf_binary}");
snf.record_successful_poll();
assert_eq!(snf.confidence(), 2);
assert_eq!(snf.finalized(), true);
snf.record_unsuccessful_poll();
assert_eq!(snf.confidence(), 0);
assert_eq!(snf.finalized(), true);
snf.record_successful_poll();
assert_eq!(snf.confidence(), 1);
assert_eq!(snf.finalized(), true);
}
#[derive(Clone, Debug)]
pub struct Snowball {
snowflake: Snowflake,
num_successful_polls: Cell<i64>,
}
impl Snowball {
pub fn new(beta: i64) -> Self {
Self {
snowflake: Snowflake::new(beta),
num_successful_polls: Cell::new(0),
}
}
pub fn beta(&self) -> i64 {
self.snowflake.beta()
}
pub fn confidence(&self) -> i64 {
self.snowflake.confidence()
}
pub fn finalized(&self) -> bool {
self.snowflake.finalized()
}
pub fn num_successful_polls(&self) -> i64 {
self.num_successful_polls.get()
}
pub fn record_successful_poll(&self) {
let polls = self.num_successful_polls.get() + 1;
self.num_successful_polls.set(polls);
self.snowflake.record_successful_poll();
}
pub fn record_unsuccessful_poll(&self) {
self.snowflake.record_unsuccessful_poll()
}
pub fn extend(&self, beta: i64, choice: i64) -> binary::Snowball {
let mut polls = [0_i64, 0_i64];
polls[choice as usize] = self.num_successful_polls.get();
binary::Snowball::new(
binary::Snowflake::new(
beta,
choice,
self.snowflake.confidence(),
self.snowflake.finalized(),
),
choice,
polls,
)
}
}
impl std::fmt::Display for Snowball {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"SB(NumSuccessfulPolls = {}, {})",
self.num_successful_polls(),
self.snowflake
)
}
}
#[test]
fn test_snowball_unary() {
let _ = env_logger::builder()
.filter_level(log::LevelFilter::Info)
.is_test(true)
.try_init();
let beta = 2_i64;
let snb = Snowball::new(beta);
assert_eq!(snb.beta(), beta);
snb.record_successful_poll();
assert_eq!(snb.confidence(), 1);
assert_eq!(snb.finalized(), false);
assert_eq!(snb.num_successful_polls(), 1);
snb.record_unsuccessful_poll();
assert_eq!(snb.confidence(), 0);
assert_eq!(snb.finalized(), false);
assert_eq!(snb.num_successful_polls(), 1);
snb.record_successful_poll();
assert_eq!(snb.confidence(), 1);
assert_eq!(snb.finalized(), false);
assert_eq!(snb.num_successful_polls(), 2);
snb.record_successful_poll();
assert_eq!(snb.beta(), beta);
assert_eq!(snb.confidence(), 2);
assert_eq!(snb.finalized(), true);
assert_eq!(snb.num_successful_polls(), 3);
snb.record_unsuccessful_poll();
assert_eq!(snb.confidence(), 0);
assert_eq!(snb.finalized(), true);
snb.record_successful_poll();
assert_eq!(snb.confidence(), 1);
assert_eq!(snb.finalized(), true);
log::info!("{snb}");
}
#[test]
fn test_snowball_extend() {
let _ = env_logger::builder()
.filter_level(log::LevelFilter::Info)
.is_test(true)
.try_init();
let beta = 2_i64;
let snb = Snowball::new(beta);
assert_eq!(snb.beta(), beta);
snb.record_successful_poll();
assert_eq!(snb.confidence(), 1);
assert_eq!(snb.finalized(), false);
assert_eq!(snb.num_successful_polls(), 1);
snb.record_unsuccessful_poll();
assert_eq!(snb.confidence(), 0);
assert_eq!(snb.finalized(), false);
assert_eq!(snb.num_successful_polls(), 1);
snb.record_successful_poll();
assert_eq!(snb.confidence(), 1);
assert_eq!(snb.finalized(), false);
assert_eq!(snb.num_successful_polls(), 2);
let snb_binary = snb.extend(beta, 0);
log::info!("{snb_binary}");
assert_eq!(snb_binary.to_string(), "SB(Preference = 0, NumSuccessfulPolls[0] = 2, NumSuccessfulPolls[1] = 0, SF(Confidence = 1, Finalized = false, SL(Preference = 0)))");
assert_eq!(snb_binary.beta(), beta);
assert_eq!(snb_binary.confidence(), 1);
assert_eq!(snb_binary.finalized(), false);
assert_eq!(snb_binary.preference(), 0);
assert_eq!(snb_binary.num_successful_polls(0), 2);
assert_eq!(snb_binary.num_successful_polls(1), 0);
snb_binary.record_unsuccessful_poll();
for _ in 0..3 {
assert_eq!(snb_binary.preference(), 0);
assert_eq!(snb_binary.finalized(), false);
snb_binary.record_successful_poll(1);
snb_binary.record_unsuccessful_poll();
}
assert_eq!(snb_binary.confidence(), 0);
assert_eq!(snb_binary.finalized(), false);
assert_eq!(snb_binary.preference(), 1);
assert_eq!(snb_binary.num_successful_polls(0), 2);
assert_eq!(snb_binary.num_successful_polls(1), 3);
snb_binary.record_successful_poll(1);
assert_eq!(snb_binary.preference(), 1);
assert_eq!(snb_binary.confidence(), 1);
assert_eq!(snb_binary.finalized(), false);
snb_binary.record_successful_poll(1);
assert_eq!(snb_binary.preference(), 1);
assert_eq!(snb_binary.confidence(), 2);
assert_eq!(snb_binary.finalized(), true);
log::info!("{snb}");
assert_eq!(
snb.to_string(),
"SB(NumSuccessfulPolls = 2, SF(Confidence = 1, Finalized = false))"
);
}