use super::*;
const _2001_01_01: u64 = 978300000;
#[repr(u8)]
#[derive(PartialEq, Debug, Copy, Clone)]
pub enum MoonPosition {
NewMoon = 0,
WaxingCrescent = 1,
FirstQuarter = 2,
WaxingGibbous = 3,
FullMoon = 4,
WaningGibbous = 5,
LastQuarter = 6,
WaningCrescent = 7,
}
pub fn corner_fill() -> Image {
let mut ret = Image::new(
MOON_WIDTH,
MOON_WIDTH,
CAT_WIDTH / 2 + CAT_WIDTH / 5 + 2,
TAIL.y_offset - 4 * MOON_WIDTH,
);
ret.plot_line_width((2, 0), (0, 2), 0.0);
ret.flood_fill(0, 0);
ret.plot_line_width((0, ret.height as i64 - 3), (2, ret.height as i64 - 1), 0.0);
ret.flood_fill(0, ret.height as i64 - 1);
ret.plot_line_width(
(ret.width as i64 - 1, ret.height as i64 - 3),
(ret.width as i64 - 3, ret.height as i64 - 1),
0.0,
);
ret.flood_fill(ret.width as i64 - 1, ret.height as i64 - 1);
ret.plot_line_width((ret.width as i64 - 3, 0), (ret.width as i64 - 1, 2), 0.0);
ret.flood_fill(ret.width as i64 - 1, 0);
ret
}
const MOON_WIDTH: usize = 16;
impl From<MoonPosition> for Image {
fn from(val: MoonPosition) -> Image {
use MoonPosition::*;
let mut ret = Image::new(
MOON_WIDTH,
MOON_WIDTH,
CAT_WIDTH / 2 + CAT_WIDTH / 5 + 2,
TAIL.y_offset - 4 * MOON_WIDTH,
);
const CENTER: (i64, i64) = ((MOON_WIDTH / 2) as i64, (MOON_WIDTH / 2) as i64);
match val {
NewMoon => {
ret.plot_ellipse(CENTER, (6, 6), [true, true, true, true], 1.0);
}
WaxingCrescent => {
ret.plot_ellipse(CENTER, (6, 6), [true, false, false, true], 1.0);
ret.plot_ellipse(
(CENTER.0 - 2, CENTER.1),
(5, 6),
[true, false, false, true],
1.0,
);
ret.flood_fill(CENTER.0 + 5, CENTER.1);
}
FirstQuarter => {
ret.plot_ellipse(CENTER, (6, 6), [true, false, false, true], 1.0);
ret.plot_line_width((CENTER.0, CENTER.0 - 6), (CENTER.0, CENTER.0 + 6), 0.0);
ret.flood_fill(CENTER.0 + 1, CENTER.1);
}
WaxingGibbous => {
ret.plot_ellipse(CENTER, (6, 6), [true, false, false, true], 1.0);
ret.plot_ellipse(
(CENTER.0, CENTER.1),
(5, 6),
[false, true, true, false],
1.0,
);
ret.flood_fill(CENTER.0 + 1, CENTER.1);
}
FullMoon => {
ret.plot_ellipse(CENTER, (6, 6), [true, true, true, true], 1.0);
ret.flood_fill(CENTER.0, CENTER.1);
}
WaningGibbous => {
ret.plot_ellipse(CENTER, (6, 6), [false, true, true, false], 1.0);
ret.plot_ellipse(
(CENTER.0, CENTER.1),
(4, 6),
[true, false, false, true],
1.0,
);
ret.flood_fill(CENTER.0 + 1, CENTER.1);
}
LastQuarter => {
ret.plot_ellipse(CENTER, (6, 6), [false, true, true, false], 1.0);
ret.plot_line_width((CENTER.0, CENTER.0 - 6), (CENTER.0, CENTER.0 + 6), 0.0);
ret.flood_fill(CENTER.0 - 1, CENTER.1);
}
WaningCrescent => {
ret.plot_ellipse(CENTER, (6, 6), [false, true, true, false], 1.0);
ret.plot_ellipse(
(CENTER.0 + 2, CENTER.1),
(5, 6),
[false, true, true, false],
1.0,
);
ret.flood_fill(CENTER.0 - 5, CENTER.1);
}
}
ret
}
}
pub fn position(now: Option<u64>) -> f64 {
let now: u64 = now.unwrap_or(
std::time::SystemTime::now()
.duration_since(std::time::SystemTime::UNIX_EPOCH)
.unwrap_or_default()
.as_secs(),
);
let diff = now - _2001_01_01;
let days = diff / 86400;
let lunations: f64 = 0.20439731 + ((days as f64) * 0.03386319269);
lunations % 1.0
}
pub fn phase(pos: f64) -> MoonPosition {
let idx = (pos * 8.) + 0.5;
let idx = (idx as usize) & 7;
match idx {
0 => MoonPosition::NewMoon,
1 => MoonPosition::WaxingCrescent,
2 => MoonPosition::FirstQuarter,
3 => MoonPosition::WaxingGibbous,
4 => MoonPosition::FullMoon,
5 => MoonPosition::WaningGibbous,
6 => MoonPosition::LastQuarter,
7 => MoonPosition::WaningCrescent,
_ => unreachable!(),
}
}
#[test]
fn test_position() {
assert_eq!(position(Some(1637831210)), 0.6821471127699965);
assert_eq!(
phase(position(Some(1637831210))),
MoonPosition::WaningGibbous
);
}
pub fn sun() -> Image {
let mut ret = Image::new(
MOON_WIDTH,
MOON_WIDTH,
CAT_WIDTH / 2 + CAT_WIDTH / 5 + 2,
TAIL.y_offset - 4 * MOON_WIDTH,
);
const CENTER: (i64, i64) = ((MOON_WIDTH / 2) as i64, (MOON_WIDTH / 2) as i64);
ret.plot_ellipse(CENTER, (6, 6), [true, true, true, true], 1.0);
ret.plot_line_width((MOON_WIDTH as i64 / 2, 0), (MOON_WIDTH as i64 / 2, 2), 1.0);
ret.plot_line_width(
(MOON_WIDTH as i64 / 2, MOON_WIDTH as i64 - 2),
(MOON_WIDTH as i64 / 2, MOON_WIDTH as i64 - 1),
1.0,
);
ret.plot_line_width(
(1, MOON_WIDTH as i64 / 2 - 1),
(1, MOON_WIDTH as i64 / 2),
1.0,
);
ret.plot_line_width(
(MOON_WIDTH as i64 - 2, MOON_WIDTH as i64 / 2 - 1),
(MOON_WIDTH as i64 - 1, MOON_WIDTH as i64 / 2),
1.0,
);
ret
}
pub fn sun_background() -> Image {
let mut ret = Image::new(
MOON_WIDTH,
MOON_WIDTH,
CAT_WIDTH / 2 + CAT_WIDTH / 5 + 2,
TAIL.y_offset - 4 * MOON_WIDTH,
);
const CENTER: (i64, i64) = ((MOON_WIDTH / 2) as i64, (MOON_WIDTH / 2) as i64);
ret.plot_ellipse(CENTER, (6, 6), [true, true, true, true], 1.0);
ret.flood_fill(CENTER.0, CENTER.1);
ret
}