reworked counter

This commit is contained in:
Aravinth Manivannan 2021-02-28 23:26:32 +05:30
parent 890fe56a16
commit f5a16766d6
Signed by: realaravinth
GPG Key ID: AD9F0F08E855ED88
4 changed files with 101 additions and 84 deletions

View File

@ -4,7 +4,8 @@ use actix::prelude::*;
use derive_builder::Builder; use derive_builder::Builder;
//use lazy_static::*; //use lazy_static::*;
use crate::levels::Levels; use crate::new_levels::Defense;
//use crate::new_levels::Levels;
// TODO move this into config parameter // TODO move this into config parameter
// lazy_static! { // lazy_static! {
@ -22,27 +23,48 @@ struct DeleteVisitor;
#[derive(Builder)] #[derive(Builder)]
pub struct Counter { pub struct Counter {
visitor_count: usize, #[builder(default = "0", setter(skip))]
levels: Levels, visitor_count: u32,
defense: Defense,
duration: u64, duration: u64,
} }
impl Default for Counter { // impl Default for Counter {
fn default() -> Self { // fn default() -> Self {
Counter { // Counter {
visitor_count: 0, // visitor_count: 0,
levels: Levels::default(), // levels: Levels::default(),
duration: 30, // duration: 30,
// }
// }
// }
impl Counter {
/// incerment visiotr count by one
pub fn add_visitor(&mut self) {
self.visitor_count += 1;
if self.visitor_count > self.defense.visitor_threshold() {
self.defense.tighten_up();
} else {
self.defense.loosen_up();
} }
} }
/// deccerment visiotr count by one
pub fn decrement_visiotr(&mut self) {
if self.visitor_count > 0 {
self.visitor_count -= 1;
}
}
/// get current difficulty factor
pub fn get_difficulty(&self) -> u32 {
self.defense.get_difficulty()
}
} }
impl Actor for Counter { impl Actor for Counter {
type Context = Context<Self>; type Context = Context<Self>;
// fn started(&mut self, ctx: &mut Self::Context) {
// ctx.set_mailbox_capacity(usize::MAX / 2);
// }
} }
impl Handler<Visitor> for Counter { impl Handler<Visitor> for Counter {
@ -50,8 +72,6 @@ impl Handler<Visitor> for Counter {
fn handle(&mut self, _: Visitor, ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, _: Visitor, ctx: &mut Self::Context) -> Self::Result {
use actix::clock::delay_for; use actix::clock::delay_for;
self.visitor_count += 1;
let addr = ctx.address(); let addr = ctx.address();
let duration: Duration = Duration::new(self.duration.clone(), 0); let duration: Duration = Duration::new(self.duration.clone(), 0);
@ -62,97 +82,93 @@ impl Handler<Visitor> for Counter {
.into_actor(self); .into_actor(self);
ctx.spawn(wait_for); ctx.spawn(wait_for);
if self.visitor_count > self.levels.threshold() { self.add_visitor();
self.levels.focus(); self.get_difficulty()
} else {
self.levels.relax();
}
self.levels.get_difficulty()
} }
} }
impl Handler<DeleteVisitor> for Counter { impl Handler<DeleteVisitor> for Counter {
type Result = (); type Result = ();
fn handle(&mut self, _msg: DeleteVisitor, _ctx: &mut Self::Context) -> Self::Result { fn handle(&mut self, _msg: DeleteVisitor, _ctx: &mut Self::Context) -> Self::Result {
if self.visitor_count > 0 { self.decrement_visiotr();
self.visitor_count -= 1;
}
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::new_levels::*;
async fn race(addr: Addr<Counter>, count: Levels) { // constants foor testing
for _ in 0..count as usize - 1 { // (visitor count, level)
const LEVEL_1: (u32, u32) = (50, 50);
const LEVEL_2: (u32, u32) = (500, 500);
const DURATION: u64 = 10;
fn get_defense() -> Defense {
DefenseBuilder::default()
.add_level(
LevelBuilder::default()
.visitor_count(LEVEL_1.0)
.difficulty_factor(LEVEL_1.1)
.unwrap()
.build()
.unwrap(),
)
.unwrap()
.add_level(
LevelBuilder::default()
.visitor_count(LEVEL_2.0)
.difficulty_factor(LEVEL_2.1)
.unwrap()
.build()
.unwrap(),
)
.unwrap()
.build()
.unwrap()
}
async fn race(addr: Addr<Counter>, count: (u32, u32)) {
for _ in 0..count.0 as usize - 1 {
let _ = addr.send(Visitor).await.unwrap(); let _ = addr.send(Visitor).await.unwrap();
} }
} }
#[actix_rt::test]
async fn counter_focus_works() {
let four = Levels::Four.get_difficulty();
let three = Levels::Three.get_difficulty();
let two = Levels::Two.get_difficulty();
let one = Levels::One.get_difficulty();
let addr = Counter::default().start(); fn get_counter() -> Counter {
CounterBuilder::default()
let mut difficulty_factor = addr.send(Visitor).await.unwrap(); .defense(get_defense())
assert_eq!(difficulty_factor, one); .duration(DURATION)
.build()
let addr = Counter::default().start(); .unwrap()
race(addr.clone(), Levels::One).await;
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, one);
let addr = Counter::default().start();
race(addr.clone(), Levels::Two).await;
addr.send(Visitor).await.unwrap();
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, two);
let addr = Counter::default().start();
race(addr.clone(), Levels::Three).await;
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, three);
let addr = Counter::default().start();
race(addr.clone(), Levels::Four).await;
addr.send(Visitor).await.unwrap();
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, four);
} }
#[actix_rt::test] #[actix_rt::test]
async fn counter_relax_works() { async fn counter_defense_tightenup_works() {
use actix::clock::delay_for; let addr = get_counter().start();
let four = Levels::Four.get_difficulty();
let three = Levels::Three.get_difficulty();
let two = Levels::Two.get_difficulty();
let one = Levels::One.get_difficulty();
let addr = Counter::default().start();
let mut difficulty_factor = addr.send(Visitor).await.unwrap(); let mut difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, LEVEL_1.0);
let addr = Counter::default().start(); race(addr.clone(), LEVEL_2).await;
race(addr.clone(), Levels::Four).await;
addr.send(Visitor).await.unwrap();
difficulty_factor = addr.send(Visitor).await.unwrap(); difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, four); assert_eq!(difficulty_factor, LEVEL_2.1);
}
// could break when default duration for counter actor changes #[actix_rt::test]
let duration = Duration::new(30, 0); async fn counter_defense_loosenup_works() {
use actix::clock::delay_for;
let addr = get_counter().start();
race(addr.clone(), LEVEL_2).await;
race(addr.clone(), LEVEL_2).await;
let mut difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, LEVEL_2.1);
let duration = Duration::new(DURATION, 0);
delay_for(duration).await; delay_for(duration).await;
difficulty_factor = addr.send(Visitor).await.unwrap(); difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, three); assert_eq!(difficulty_factor, LEVEL_1.1);
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, two);
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, one);
} }
} }

View File

@ -1,22 +1,25 @@
//! Error datatypes //! Error datatypes
use derive_more::{Display, Error}; use derive_more::{Display, Error};
/// Errors that can occur when interacting with the blockchain /// Errors that can occur when using
#[derive(Debug, PartialEq, Display, Clone, Error)] #[derive(Debug, PartialEq, Display, Clone, Error)]
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
pub enum CaptchaError { pub enum CaptchaError {
/// when configuring m_captcha, `DefenseBuilder` must be passed atleast /// when configuring m_captcha, [DefenseBuilder][crate::new_levels::DefenseBuilder] must be passed atleast
/// one `LevelConfig` if not this error will arise /// one `LevelConfig` if not this error will arise
#[display(fmt = "LevelBuilder should have atleaset one level configured")] #[display(fmt = "LevelBuilder should have atleaset one level configured")]
LevelEmpty, LevelEmpty,
/// Visitor count must be an integer /// Visitor count must be an integer
/// when configuring m_captcha, `LevelBuilder` difficulty_factor /// when configuring m_captcha, [LevelBuilder][crate::new_levels::LevelBuilder] difficulty_factor
/// must be set to greater than zero. /// must be set to greater than zero.
#[display(fmt = "difficulty factor must be greater than zero")] #[display(fmt = "difficulty factor must be greater than zero")]
DifficultyFactorZero, DifficultyFactorZero,
/// Difficulty factor must be set /// Difficulty factor must be set
#[display(fmt = "Set difficulty factor")] #[display(fmt = "Set difficulty factor")]
SetDifficultyFactor, SetDifficultyFactor,
/// Visitor count must be set /// Visitor count must be set
#[display(fmt = "Set visitor count")] #[display(fmt = "Set visitor count")]
SetVisitorCount, SetVisitorCount,

View File

@ -1,4 +1,4 @@
pub mod counter; pub mod counter;
pub mod errors; pub mod errors;
mod levels; mod levels;
mod new_levels; pub mod new_levels;

View File

@ -177,10 +177,8 @@ impl Defense {
/// tighten up defense. Increases defense level by a factor of one /// tighten up defense. Increases defense level by a factor of one
/// when defense is at max level, calling this method will have no effect /// when defense is at max level, calling this method will have no effect
pub fn tighten_up(&mut self) { pub fn tighten_up(&mut self) {
println!("{}", self.current_visitor_threshold);
if self.current_visitor_threshold != self.levels.len() - 1 { if self.current_visitor_threshold != self.levels.len() - 1 {
self.current_visitor_threshold += 1; self.current_visitor_threshold += 1;
println!("{}", self.current_visitor_threshold);
} }
} }
/// loosen up defense. Decreases defense level by a factor of one /// loosen up defense. Decreases defense level by a factor of one