use arco::rules::{NoContext, Rule, RuleContext};
use arco::state::State;
use rand::{Rng, RngExt, SeedableRng};
use std::fmt;
use std::hash::{Hash, Hasher};
#[derive(Clone)]
struct Counter {
value: u8,
max_value: u8,
}
impl Counter {
fn new(value: u8, max_value: u8) -> Self {
assert!(value <= max_value);
Self { value, max_value }
}
fn increment(&self) -> Self {
if self.value >= self.max_value {
Self { value: 0, ..*self }
} else {
Self {
value: self.value + 1,
..*self
}
}
}
fn reset(&self) -> Self {
Self { value: 0, ..*self }
}
}
impl State for Counter {
type Encoding = Vec<u8>;
fn canonical_encoding(&self) -> Self::Encoding {
vec![self.value, self.max_value]
}
fn distance(&self, other: &Self) -> u32 {
let mut diff = 0u32;
if self.value != other.value {
diff += 1;
}
if self.max_value != other.max_value {
diff += 1;
}
diff
}
}
impl PartialEq for Counter {
fn eq(&self, other: &Self) -> bool {
self.value == other.value && self.max_value == other.max_value
}
}
impl Eq for Counter {}
impl Hash for Counter {
fn hash<H: Hasher>(&self, state: &mut H) {
self.value.hash(state);
self.max_value.hash(state);
}
}
impl fmt::Debug for Counter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Counter({}/{})", self.value, self.max_value)
}
}
impl fmt::Display for Counter {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.value)
}
}
#[derive(Debug, Clone)]
struct IncrementRule;
impl Rule<Counter> for IncrementRule {
type Context = NoContext;
fn name(&self) -> &str {
"Increment"
}
fn apply(
&self,
state: &Counter,
_context: &NoContext,
_rng: &mut dyn Rng, ) -> Counter {
state.increment()
}
}
#[derive(Debug, Clone)]
struct SetValue {
target: u8,
}
impl RuleContext for SetValue {}
#[derive(Debug, Clone)]
struct SetRule;
impl Rule<Counter> for SetRule {
type Context = SetValue;
fn name(&self) -> &str {
"Set"
}
fn apply(&self, state: &Counter, context: &SetValue, _rng: &mut dyn Rng) -> Counter {
Counter::new(context.target.min(state.max_value), state.max_value)
}
}
#[derive(Debug, Clone)]
struct MaybeResetRule;
impl Rule<Counter> for MaybeResetRule {
type Context = NoContext;
fn name(&self) -> &str {
"MaybeReset"
}
fn apply(
&self,
state: &Counter,
_context: &NoContext,
rng: &mut dyn Rng, ) -> Counter {
if rng.random_bool(0.7) {
state.increment()
} else {
state.reset()
}
}
}
fn main() {
println!("=== Example 02: Custom Rules ===\n");
let state = Counter::new(0, 5);
let mut rng = rand::rngs::StdRng::seed_from_u64(42);
let inc = IncrementRule;
let ctx = NoContext;
let s1 = inc.apply(&state, &ctx, &mut rng);
println!("After Increment: {} (was {})", s1, state);
let set = SetRule;
let ctx = SetValue { target: 3 };
let s2 = set.apply(&state, &ctx, &mut rng);
println!("After Set(3): {} (was {})", s2, state);
let maybe = MaybeResetRule;
print!("\nMaybeReset 10 times: ");
let mut current = state.clone();
for _ in 0..10 {
current = maybe.apply(¤t, &NoContext, &mut rng);
print!("{} ", current);
}
println!();
println!("\nOriginal state unchanged: {}", state);
println!("\n✓ Three rules implemented:");
println!(" - IncrementRule: deterministic, NoContext");
println!(" - SetRule: deterministic, custom SetValue context");
println!(" - MaybeResetRule: stochastic, NoContext");
}