5-tier card progression engine for the Royal Flush Network (RFN).
Accounts enter at the lowest tier (Ten) and earn points. When an account accumulates enough points to fill its tier's quota, it cycles up to the next tier. An account that cycles past Ace graduates.
This crate is pure domain logic — no database, no async runtime, no network. It's a library you embed in a service.
| Tier | Points to cycle out |
|---|---|
| Ten | 1 |
| Jack | 2 |
| Queen | 3 |
| King | 4 |
| Ace | 5 |
Thresholds ascend with the tier. Total points to graduate a fresh account
from Ten: 1 + 2 + 3 + 4 + 5 = 15.
| Method | What it does |
|---|---|
add_account |
The signup entry point. Inserts at Ten, then force-cycles with 5 points → lands in Queen, 2 pts, 2 cycles. |
distribute_points |
System-wide distribution. Always feeds the lowest non-empty tier's front account, cascading it up before spilling to the next. |
force_cycle |
Drive a single account up the ladder as far as pts allow, then spread leftover points to other accounts via a DistributionStrategy. |
reset_to_king |
Recreate a graduated account at King (used during the weekly pot-bonus reset). |
For leftover points after a force_cycle:
| Strategy | Behavior |
|---|---|
TierCascade |
Fill tiers bottom-up (Ten first). Default. |
AllCardlines |
Round-robin across all non-empty tiers. |
JackAndQueenOnly |
Round-robin across Jack and Queen only. |
Graduation is surfaced via the outbox pattern — mutating operations that
can graduate an account return a Vec<FlushlineGraduated>. There is no
async runtime dependency; the caller decides what to do with the events
(push to a channel, persist, log, ignore).
use flushline::{Account, CardlineType, Flushline};
let mut fl = Flushline::new();
let alice = Account::generate_id();
// Signup drives alice to Queen (2 pts, 2 cycles) — no graduation yet.
let events = fl.add_account(Account::new(alice, "alice")).unwrap();
assert!(events.is_empty());
// Graduate alice: finish Queen (1pt) + King (4) + Ace (5) = 10 more points.
let rest = CardlineType::Queen.threshold_points() - fl.account(&alice).unwrap().current_pts
+ CardlineType::King.threshold_points()
+ CardlineType::Ace.threshold_points();
let events = fl.force_cycle(&alice, rest).unwrap();
assert!(fl.is_graduated(&alice));
assert_eq!(events.len(), 1); // one FlushlineGraduated emitted[dependencies]
flushline = "0.1"cargo run --example demo # the 7-signup walkthrough
cargo doc --no-deps --open # browse the rustdoccargo fmt --all --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test # 30 testsflushline is fully compatible with WebAssembly out of the box. It supports compilation for both browser environments (Leptos frontend clients) and server-side WASM sandboxes (such as Leptos Spin or Leptos Wasmtime).
Pre-configured with uuid/js feature enabled, so generating secure v7 UUIDs requests secure entropy from browser-native JavaScript APIs (window.crypto.getRandomValues).
cargo check --target wasm32-unknown-unknownCompiles seamlessly to WASI for deployments like Spin and Wasmtime. WASI system calls provide entropy natively.
cargo check --target wasm32-wasip1MIT.