use std::cmp::Ordering;
use std::fmt;
use std::i32;
use std::ops::{Add, Deref, Sub};
#[derive(Debug, PartialEq, Eq, Clone, Ord, PartialOrd)]
pub enum Version {
Across,
Elma,
}
impl Default for Version {
fn default() -> Version {
Version::Elma
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
pub enum Clip {
Unclipped = 0,
Ground = 1,
Sky = 2,
}
impl Default for Clip {
fn default() -> Clip {
Clip::Sky
}
}
#[derive(Debug, Default, PartialEq, Eq, Clone)]
pub struct BestTimes {
pub single: Vec<TimeEntry>,
pub multi: Vec<TimeEntry>,
}
impl BestTimes {
pub fn new() -> Self {
Self::default()
}
}
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct Time(pub i32);
impl Time {
pub fn to_parts(self) -> (bool, i32, i32, i32, i32) {
let h = self.0 % 100;
let s = (self.0 / 100) % 60;
let m = (self.0 / (100 * 60)) % 60;
let hr = self.0 / (100 * 60 * 60);
let neg = self.0 < 0;
(neg, hr.abs(), m.abs(), s.abs(), h.abs())
}
pub fn from(s: &str) -> Self {
let parts: Vec<_> = s.split(|c: char| !c.is_numeric())
.filter(|s| !s.is_empty())
.map(|s| s.parse::<i32>().unwrap())
.collect();
let mut time = 0;
for (n, val) in parts.iter().rev().enumerate() {
match n {
n if n == 0 => time += val,
n if n == 1 => time += val * 100,
n if n == 2 => time += val * 6000,
n if n == 3 => time += val * 360_000,
n if n == 4 => time += val * 8_640_000,
_ => time = time.saturating_add(i32::MAX),
}
}
if s.starts_with('-') {
time *= -1
}
Time(time)
}
}
impl From<i32> for Time {
fn from(i: i32) -> Self {
Time(i)
}
}
impl Add for Time {
type Output = Time;
fn add(self, other: Self) -> Self {
Time(self.0 + other.0)
}
}
impl Sub for Time {
type Output = Time;
fn sub(self, other: Self) -> Self {
Time(self.0 - other.0)
}
}
impl From<Time> for i32 {
fn from(t: Time) -> Self {
t.0
}
}
impl Deref for Time {
type Target = i32;
fn deref(&self) -> &i32 {
&self.0
}
}
impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let h = self.0 % 100;
let s = (self.0 / 100) % 60;
let m = (self.0 / (100 * 60)) % 60;
let hr = self.0 / (100 * 60 * 60);
write!(
f,
"{}{}{:02}:{:02},{:02}",
if self.0 < 0 { "-" } else { "" },
if hr > 0 {
format!("{:02}:", hr)
} else {
"".into()
},
m,
s,
h
)
}
}
#[derive(Debug, Default, PartialEq, Clone)]
pub struct Position<T> {
pub x: T,
pub y: T,
}
impl<T> Position<T> {
pub fn new(x: T, y: T) -> Self {
Position { x, y }
}
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct TimeEntry {
pub names: (String, String),
pub time: Time,
}
impl Ord for TimeEntry {
fn cmp(&self, other: &Self) -> Ordering {
self.time.cmp(&other.time)
}
}
impl PartialOrd for TimeEntry {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl TimeEntry {
pub fn new<T: Into<Time>, S: Into<String>>(names: (S, S), time: T) -> Self {
TimeEntry {
names: (names.0.into(), names.1.into()),
time: time.into(),
}
}
}