use std::cmp::Ordering;
use std::fmt::{Debug, Display};
use std::ops::{Add, Neg, Sub};
use super::ScoreLevel;
pub trait Score:
Copy
+ Debug
+ Display
+ Default
+ Send
+ Sync
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ Add<Output = Self>
+ Sub<Output = Self>
+ Neg<Output = Self>
+ 'static
{
fn is_feasible(&self) -> bool;
fn zero() -> Self;
fn levels_count() -> usize;
fn to_level_numbers(&self) -> Vec<i64>;
fn from_level_numbers(levels: &[i64]) -> Self;
fn multiply(&self, multiplicand: f64) -> Self;
fn divide(&self, divisor: f64) -> Self;
fn abs(&self) -> Self;
fn to_scalar(&self) -> f64;
fn level_label(index: usize) -> ScoreLevel;
fn compare(&self, other: &Self) -> Ordering {
self.cmp(other)
}
fn is_better_than(&self, other: &Self) -> bool {
self > other
}
fn is_worse_than(&self, other: &Self) -> bool {
self < other
}
fn is_equal_to(&self, other: &Self) -> bool {
self == other
}
fn one_hard() -> Self {
let mut levels = vec![0i64; Self::levels_count()];
if let Some(i) =
(0..Self::levels_count()).find(|&i| Self::level_label(i) == ScoreLevel::Hard)
{
levels[i] = 1;
}
Self::from_level_numbers(&levels)
}
fn one_soft() -> Self {
let mut levels = vec![0i64; Self::levels_count()];
if let Some(i) = (0..Self::levels_count())
.rev()
.find(|&i| Self::level_label(i) == ScoreLevel::Soft)
{
levels[i] = 1;
}
Self::from_level_numbers(&levels)
}
fn one_medium() -> Self {
let mut levels = vec![0i64; Self::levels_count()];
if let Some(i) =
(0..Self::levels_count()).find(|&i| Self::level_label(i) == ScoreLevel::Medium)
{
levels[i] = 1;
}
Self::from_level_numbers(&levels)
}
}
pub trait ParseableScore: Score {
fn parse(s: &str) -> Result<Self, ScoreParseError>;
fn to_string_repr(&self) -> String;
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScoreParseError {
pub message: String,
}
impl std::fmt::Display for ScoreParseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "Score parse error: {}", self.message)
}
}
impl std::error::Error for ScoreParseError {}