use crate::prelude::*;
pub const SVG_SCALE: f64 = 6.;
pub fn timestring_abbreviate<'x>(base: &str, this: &'x str)
-> (&'x str, bool)
{
fn split(s: &str) -> ArrayVec<&str, 3> {
s.splitn(3, ' ').collect()
}
let base3 = split(base);
let this3 = split(this);
let matches = |i| base3.get(i) == this3.get(i);
if_chain! {
if matches(0) && matches(2);
if let Some(abbrev) = this3.get(1);
then { (abbrev, true) }
else { (this, false) }
}
}
pub fn raw_angle_transform(compass: u8) -> String {
assert!(compass < 8);
if compass == 0 { default() }
else { format!("rotate({})", -45 * (compass as i16)) }
}
#[throws(fmt::Error)]
pub fn die_cooldown_path<W: fmt::Write>(mut w: W, r: f64, remprop: f64) {
write!(w, "M 0,-{r} A")?;
let mut arcto = move |proportion: f64| {
let angle = proportion * TAU;
let x = r * angle.sin();
let y = -r * angle.cos();
write!(w, " {r},{r} 0 0 1 {x},{y}")
};
for split in [0.49, 0.98] {
if split >= remprop { break }
arcto(split)?;
}
arcto(remprop)?;
}
#[test]
fn die_cooldown_path_test() {
let t80 = |remprop, exp: &str| {
let mut got = String::new();
die_cooldown_path(&mut got, 80., remprop).unwrap();
assert_eq!(&got, exp, "\nfor {remprop} {exp}");
};
t80(1./3., "M 0,-80 A 80,80 0 0 1 69.2820323027551,39.999999999999986");
t80(1. , "M 0,-80 A 80,80 0 0 1 5.023241562345087,79.84213827426173 80,80 0 0 1 -10.026658685144373,-79.36917610515822 80,80 0 0 1 -0.000000000000019594348786357652,-80");
t80(0.5 , "M 0,-80 A 80,80 0 0 1 5.023241562345087,79.84213827426173 80,80 0 0 1 0.000000000000009797174393178826,80");
t80(0.6 , "M 0,-80 A 80,80 0 0 1 5.023241562345087,79.84213827426173 80,80 0 0 1 -47.02282018339784,64.72135954999581");
t80(0.9 , "M 0,-80 A 80,80 0 0 1 5.023241562345087,79.84213827426173 80,80 0 0 1 -47.02282018339787,-64.72135954999578");
t80(0.99 , "M 0,-80 A 80,80 0 0 1 5.023241562345087,79.84213827426173 80,80 0 0 1 -10.026658685144373,-79.36917610515822 80,80 0 0 1 -5.023241562345061,-79.84213827426173");
}
pub fn default<T:Default>() -> T { Default::default() }
#[macro_export]
macro_rules! display_as_debug {
{$x:ty $( , $($gen_tt:tt)* )?} => {
impl $( $($gen_tt)* )? std::fmt::Display for $x {
#[throws(std::fmt::Error)]
fn fmt(&self, f: &mut std::fmt::Formatter) {
<Self as Debug>::fmt(self, f)?
}
}
}
}
pub use crate::display_as_debug;
pub type SvgAttrs = Vec<(HtmlLit,Html)>;
pub fn space_table_attrs(table_size: PosC<f64>) -> SvgAttrs {
let PosC { coords: [x, y] } = table_size;
vec![
(Html::lit("viewBox"), hformat!("0 0 {} {}", x, y) ),
(Html::lit("width" ), (SVG_SCALE * x).to_html() ),
(Html::lit("height" ), (SVG_SCALE * y).to_html() ),
]
}
pub fn space_rect_attrs(table_size: PosC<f64>) -> SvgAttrs {
vec![
(Html::lit("width" ), table_size.x().to_html() ),
(Html::lit("height"), table_size.y().to_html() ),
]
}
#[macro_export]
macro_rules! if_let {
{ $($variant:ident)::+ ($binding:pat) = $input:expr;
else $($otherwise:tt)*
} => {
let $binding = match $input {
$($variant)::+ (y) => y,
_ => { $($otherwise)* },
};
};
{ $($variant:ident)::+ ($binding:pat) = $input:expr;
$($otherwise:tt)*
} => {
let $binding = match $input {
$($variant)::+ (y) => y,
$($otherwise)*,
};
};
{ $($variant:ident)::+ {$binding:ident} = $input:expr;
else $($otherwise:tt)*
} => {
let $binding = match $input {
$($variant)::+ { $binding } => $binding,
_ => { $($otherwise)* },
};
};
{ $($variant:ident)::+ {$binding:ident} = $input:expr;
$($otherwise:tt)*
} => {
let $binding = match $input {
$($variant)::+ { $binding } => $binding,
$($otherwise)*,
};
};
}
#[ext(pub, name=DebugExt)]
impl<T:Debug> T {
fn to_debug(&self) -> String { format!("{:?}", self) }
}
pub fn dbgc_helper(file: &'static str, line: u32,
values: &[(&'static str, &dyn Debug)]) {
let buf = (||{
let mut buf = String::new();
write!(buf, "[{}:{}]", file, line)?;
for (s, v) in values.iter() {
write!(buf, " {}={:?}", s, v)?;
}
write!(buf, "\n")?;
Ok::<_,fmt::Error>(buf)
})();
let buf = buf.unwrap_or_else(
|e| format!("error formatting for dbgc! {}\n", e));
eprint!("{}", buf);
}
#[macro_export]
macro_rules! dbgc {
() => {
$crate::misc::dbgc_helper(std::file!(), std::line!(), &[])
};
($val:expr $(,)?) => {
match $val {
tmp => {
$crate::misc::dbgc_helper(std::file!(), std::line!(),
&[(std::stringify!($val), &tmp)]);
tmp
}
}
};
($($val:expr),+ $(,)?) => {
$crate::misc::dbgc_helper(std::file!(), std::line!(),
&[$((std::stringify!($val), &$val)),+])
};
}