use core::cmp::Ordering;
use core::fmt::Debug;
use core::hash::Hash;
#[cfg(feature = "dev")]
use arbitrary::Arbitrary;
use order_theory::{
GreatestElement, LowerSemilattice, PredecessorExceptForLeast, SuccessorExceptForGreatest,
};
use crate::prelude::*;
pub use core::num::NonZeroU64;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "dev", derive(Arbitrary))]
pub struct AreaOfInterest<const MCL: usize, const MCC: usize, const MPL: usize, S> {
area: Area<MCL, MCC, MPL, S>,
max_count: NonZeroU64,
max_size: u64,
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> AreaOfInterest<MCL, MCC, MPL, S> {
pub fn new(area: Area<MCL, MCC, MPL, S>, max_count: NonZeroU64, max_size: u64) -> Self {
Self {
area,
max_count,
max_size,
}
}
pub fn area(&self) -> &Area<MCL, MCC, MPL, S> {
&self.area
}
pub fn max_count(&self) -> NonZeroU64 {
self.max_count
}
pub fn max_size(&self) -> u64 {
self.max_size
}
pub fn set_area(&mut self, new_area: Area<MCL, MCC, MPL, S>) {
self.area = new_area;
}
pub fn set_max_count(&mut self, new_max_count: NonZeroU64) {
self.max_count = new_max_count;
}
pub fn set_max_size(&mut self, new_max_size: u64) {
self.max_size = new_max_size;
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> AreaOfInterest<MCL, MCC, MPL, S>
where
S: PartialEq + Clone,
{
pub fn intersection(&self, other: &Self) -> Result<Self, EmptyGrouping> {
Ok(Self::new(
self.area().wdm_intersection(other.area())?,
core::cmp::min(self.max_count(), other.max_count()),
self.max_size().greatest_lower_bound(&other.max_size()),
))
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> PartialOrd<Self>
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (
self.area().partial_cmp(other.area())?,
self.max_count().cmp(&other.max_count()),
self.max_size().cmp(&other.max_size()),
) {
(Ordering::Equal, Ordering::Equal, Ordering::Equal) => Some(Ordering::Equal),
(area_cmp, count_cmp, size_cmp) => {
if area_cmp.is_le() && count_cmp.is_le() && size_cmp.is_le() {
Some(Ordering::Less)
} else if area_cmp.is_ge() && count_cmp.is_ge() && size_cmp.is_ge() {
Some(Ordering::Greater)
} else {
None
}
}
}
}
}
impl<const MCL: usize, const MCC: usize, const MPL: usize, S> GreatestElement
for AreaOfInterest<MCL, MCC, MPL, S>
where
S: Clone + Ord + PredecessorExceptForLeast + SuccessorExceptForGreatest,
{
fn greatest() -> Self {
Self::new(Area::greatest(), NonZeroU64::MAX, u64::MAX)
}
fn is_greatest(&self) -> bool {
self.area().is_greatest()
&& self.max_count() == NonZeroU64::MAX
&& self.max_size() == u64::MAX
}
}