reworked counter
This commit is contained in:
parent
890fe56a16
commit
f5a16766d6
4 changed files with 101 additions and 84 deletions
172
src/counter.rs
172
src/counter.rs
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue