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 lazy_static::*;
use crate::levels::Levels;
use crate::new_levels::Defense;
//use crate::new_levels::Levels;
// TODO move this into config parameter
// lazy_static! {
@ -22,27 +23,48 @@ struct DeleteVisitor;
#[derive(Builder)]
pub struct Counter {
visitor_count: usize,
levels: Levels,
#[builder(default = "0", setter(skip))]
visitor_count: u32,
defense: Defense,
duration: u64,
}
impl Default for Counter {
fn default() -> Self {
Counter {
visitor_count: 0,
levels: Levels::default(),
duration: 30,
// impl Default for Counter {
// fn default() -> Self {
// Counter {
// visitor_count: 0,
// levels: Levels::default(),
// 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 {
type Context = Context<Self>;
// fn started(&mut self, ctx: &mut Self::Context) {
// ctx.set_mailbox_capacity(usize::MAX / 2);
// }
}
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 {
use actix::clock::delay_for;
self.visitor_count += 1;
let addr = ctx.address();
let duration: Duration = Duration::new(self.duration.clone(), 0);
@ -62,97 +82,93 @@ impl Handler<Visitor> for Counter {
.into_actor(self);
ctx.spawn(wait_for);
if self.visitor_count > self.levels.threshold() {
self.levels.focus();
} else {
self.levels.relax();
}
self.levels.get_difficulty()
self.add_visitor();
self.get_difficulty()
}
}
impl Handler<DeleteVisitor> for Counter {
type Result = ();
fn handle(&mut self, _msg: DeleteVisitor, _ctx: &mut Self::Context) -> Self::Result {
if self.visitor_count > 0 {
self.visitor_count -= 1;
}
self.decrement_visiotr();
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::new_levels::*;
async fn race(addr: Addr<Counter>, count: Levels) {
for _ in 0..count as usize - 1 {
// constants foor testing
// (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();
}
}
#[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();
let mut difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, one);
let addr = Counter::default().start();
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);
fn get_counter() -> Counter {
CounterBuilder::default()
.defense(get_defense())
.duration(DURATION)
.build()
.unwrap()
}
#[actix_rt::test]
async fn counter_relax_works() {
use actix::clock::delay_for;
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();
async fn counter_defense_tightenup_works() {
let addr = get_counter().start();
let mut difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, LEVEL_1.0);
let addr = Counter::default().start();
race(addr.clone(), Levels::Four).await;
addr.send(Visitor).await.unwrap();
race(addr.clone(), LEVEL_2).await;
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
let duration = Duration::new(30, 0);
#[actix_rt::test]
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;
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, three);
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, two);
difficulty_factor = addr.send(Visitor).await.unwrap();
assert_eq!(difficulty_factor, one);
assert_eq!(difficulty_factor, LEVEL_1.1);
}
}

View File

@ -1,22 +1,25 @@
//! Error datatypes
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)]
#[cfg(not(tarpaulin_include))]
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
#[display(fmt = "LevelBuilder should have atleaset one level configured")]
LevelEmpty,
/// 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.
#[display(fmt = "difficulty factor must be greater than zero")]
DifficultyFactorZero,
/// Difficulty factor must be set
#[display(fmt = "Set difficulty factor")]
SetDifficultyFactor,
/// Visitor count must be set
#[display(fmt = "Set visitor count")]
SetVisitorCount,

View File

@ -1,4 +1,4 @@
pub mod counter;
pub mod errors;
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
/// when defense is at max level, calling this method will have no effect
pub fn tighten_up(&mut self) {
println!("{}", self.current_visitor_threshold);
if self.current_visitor_threshold != self.levels.len() - 1 {
self.current_visitor_threshold += 1;
println!("{}", self.current_visitor_threshold);
}
}
/// loosen up defense. Decreases defense level by a factor of one