use std::{cmp::Ordering, fmt};
pub struct Wheel<T, const N0: usize, const N: usize, const L: usize> {
layer0: [Vec<TimeoutItem<T>>; N0],
layers: [[Vec<TimeoutItem<T>>; N]; L],
index: usize,
indexs: [usize; L],
}
impl<T, const N0: usize, const N: usize, const L: usize> Default for Wheel<T, N0, N, L> {
fn default() -> Self {
Wheel {
layer0: std::array::from_fn(|_| Vec::new()),
layers: std::array::from_fn(|_| std::array::from_fn(|_| Vec::new())),
index: 0,
indexs: [0; L],
}
}
}
impl<T: fmt::Debug, const N0: usize, const N: usize, const L: usize> fmt::Debug
for Wheel<T, N0, N, L>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Wheel")
.field("layer0", &self.layer0)
.field("layers", &self.layers)
.field("index", &self.index)
.field("indexs", &self.indexs)
.finish()
}
}
impl<T, const N0: usize, const N: usize, const L: usize> Wheel<T, N0, N, L> {
pub fn roll_count(&self) -> usize {
let mut c = self.index;
for i in 0..L {
c += self.indexs[i] * (N0 * N.pow(i as u32));
}
c
}
pub fn is_cur_over(&self) -> bool {
self.layer0[self.index].is_empty()
}
pub fn push(&mut self, mut it: TimeoutItem<T>) -> Option<TimeoutItem<T>> {
if it.timeout < N0 {
self.layer0[(it.timeout + self.index) % N0].push(it);
return None;
}
let mut fix = self.index;
for i in 0..L {
let t = N0 * N.pow(i as u32);
if it.timeout < t * N {
it.timeout = (it.timeout + fix + self.indexs[i] * t) % (t * N);
self.layers[i][it.timeout / t].push(it);
return None;
}
fix += self.indexs[i] * t;
}
it.timeout += fix;
Some(it)
}
pub fn max_time(&self) -> usize {
N0 * N.pow(L as u32)
}
pub fn pop(&mut self) -> Option<TimeoutItem<T>> {
self.layer0[self.index].pop()
}
pub fn roll(&mut self) -> bool {
if self.index < N0 - 1 {
self.index += 1;
return false;
}
self.index = 0;
self.indexs[0] = (self.indexs[0] + 1) % N;
while let Some(mut it) = self.layers[0][self.indexs[0]].pop() {
it.timeout -= N0 * self.indexs[0];
self.layer0[it.timeout].push(it);
}
if self.indexs[0] > 0 {
return false;
}
for i in 1..L {
self.indexs[i] = (self.indexs[i] + 1) % N;
while let Some(mut it) = self.layers[i][self.indexs[i]].pop() {
it.timeout -= N0 * N.pow(i as u32) * self.indexs[i];
self.push(it);
}
if self.indexs[i] > 0 {
return false;
}
}
true
}
}
pub struct TimeoutItem<T> {
pub timeout: usize,
pub el: T,
}
impl<T> TimeoutItem<T> {
pub fn new(timeout: usize, el: T) -> Self {
TimeoutItem { timeout, el }
}
pub fn timeout(&self) -> usize {
self.timeout
}
}
impl<T: fmt::Debug> fmt::Debug for TimeoutItem<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("TimeoutItem")
.field("timeout", &self.timeout)
.field("el", &self.el)
.finish()
}
}
impl<T> Eq for TimeoutItem<T> {}
impl<T> Ord for TimeoutItem<T> {
fn cmp(&self, other: &TimeoutItem<T>) -> Ordering {
self.timeout.cmp(&other.timeout)
}
}
impl<T> PartialOrd for TimeoutItem<T> {
fn partial_cmp(&self, other: &TimeoutItem<T>) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl<T> PartialEq for TimeoutItem<T> {
fn eq(&self, other: &TimeoutItem<T>) -> bool {
self.timeout == other.timeout
}
}
#[test]
fn test() {
use crate::*;
let vec = vec![
0, 1, 10, 6, 4, 4, 4, 5, 3, 7, 2, 15, 18, 21, 26, 31, 39, 41, 8, 79, 89,
]; let mut wheel: Wheel<usize, 10, 3, 2> = Wheel::default();
println!("max_time:{:?}", wheel.max_time());
for i in vec.clone() {
wheel.push(TimeoutItem::new(i, i));
}
println!("{:?}", wheel);
let mut sorted = vec.clone();
sorted.sort();
sorted.reverse();
let mut c = 0;
while sorted.len() > 0 {
if let Some(r) = wheel.pop() {
println!("r:{:?}, c:{}", r, c);
assert_eq!(r.el, sorted.pop().unwrap());
assert_eq!(r.el, c);
if r.el == 18 {
sorted.push(32);
sorted.push(47);
sorted.sort();
sorted.reverse();
wheel.push(TimeoutItem::new(14, 32));
wheel.push(TimeoutItem::new(29, 47));
println!("---{:?}", wheel);
}
} else {
let r = wheel.roll();
c += 1;
if c % 10 == 0 {
if c < 60 {
sorted.push(c * 2 + 2);
sorted.sort();
sorted.reverse();
wheel.push(TimeoutItem::new(c + 2, c * 2 + 2));
}
}
println!("roll:: {:?} {:?}", r, wheel.roll_count());
}
}
}