use std::fmt::{Debug};
use std::ops::{Add, AddAssign};
use super::{Resources, BUDGET};
use crate::util::{AsUsize};
array_index! {
#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct Time(std::num::NonZeroUsize) {
debug_name: "Time",
UInt: usize,
}
}
impl Time {
pub fn max_with(&mut self, other: Time) {
*self = std::cmp::max(*self, other);
}
}
pub const LEAST: Time = unsafe {Time::new_unchecked(0)};
impl Default for Time {
fn default() -> Self { LEAST }
}
impl Add<usize> for Time {
type Output = Self;
fn add(self, rhs: usize) -> Self::Output {
Time::new(self.as_usize() + rhs).expect("Overflow")
}
}
impl AddAssign<usize> for Time {
fn add_assign(&mut self, other: usize) {
*self = self.add(other);
}
}
const MAX_ITEMS: usize = 8;
#[derive(Debug)]
struct Cycle<T> {
remaining: Resources,
num_items: usize,
items: [Option<T>; MAX_ITEMS],
}
impl<T> Cycle<T> {
pub fn new() -> Self {
Cycle {
remaining: BUDGET,
num_items: 0,
items: Default::default(),
}
}
pub fn push(&mut self, item: T) {
self.items[self.num_items] = Some(item);
self.num_items += 1;
}
pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a T> {
self.items[0..self.num_items].iter().map(Option::as_ref).map(Option::unwrap)
}
}
#[derive(Debug)]
pub struct Placer<T: Debug> {
cycles: Vec<Cycle<T>>,
}
impl<T: Debug> Default for Placer<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Debug> Placer<T> {
pub fn new() -> Self {
Placer {
cycles: Vec::new(),
}
}
fn len(&self) -> Time {
Time::new(self.cycles.len()).expect("Overflow")
}
fn at(&mut self, time: Time) -> &mut Cycle<T> {
&mut self.cycles[time.as_usize()]
}
pub fn add_item(&mut self, item: T, cost: Resources, time: &mut Time) {
while self.len() <= *time {
self.cycles.push(Cycle::new());
}
#[allow(clippy::neg_cmp_op_on_partial_ord)]
while !(cost <= self.at(*time).remaining) {
*time += 1;
}
self.at(*time).remaining -= cost;
self.at(*time).push(item);
}
pub fn iter(&self) -> impl Iterator<Item=&T> {
self.cycles.iter().flat_map(|c| c.iter())
}
}