extern crate rand;
extern crate serde_json;
extern crate termcolor2rgb;
extern crate wasm_bindgen;
#[cfg(feature = "wasm_debug")]
extern crate web_sys;
use self::rand::rngs;
use crate::board;
use crate::gen::{RandomBoardGen, Resolution};
use crate::land::LandKind;
use cfg_if::cfg_if;
use wasm_bindgen::prelude::*;
cfg_if! {
if #[cfg(feature = "console_error_panic_hook")] {
extern crate console_error_panic_hook;
use self::console_error_panic_hook::set_once as set_panic_hook;
} else {
#[inline]
fn set_panic_hook() {}
}
}
cfg_if! {
if #[cfg(feature = "wasm_debug")] {
macro_rules! log {
($($t:tt)*) => {
web_sys::console::log_1(&format!($($t)*).into());
}
}
} else {
macro_rules! log {
($($t:tt)*) => {}
}
}
}
#[wasm_bindgen]
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Cell {
pub kind: LandKind,
pub altitude: u8,
}
impl Cell {
#[inline]
fn land_color(&self) -> Option<(u8, u8, u8)> {
use termcolor2rgb::ColorExt;
self.kind.preset_ref().color.fg().map(|c| c.to_rgb())
}
}
#[wasm_bindgen]
impl Cell {
pub fn color_code(&self) -> Option<String> {
self.land_color()
.map(|(r, g, b)| format!("#{:02x}{:02x}{:02x}", r, g, b))
}
pub fn rgb_color(&self) -> Option<u32> {
self.land_color()
.map(|(r, g, b)| (u32::from(r) << 16) + (u32::from(g) << 8) + u32::from(b))
}
pub fn legend(&self) -> String {
self.kind.legend().to_string()
}
}
#[wasm_bindgen]
pub struct Board {
inner: board::Board<'static>,
}
#[wasm_bindgen]
impl Board {
pub fn width(&self) -> usize {
self.inner.width()
}
pub fn height(&self) -> usize {
self.inner.height()
}
pub fn at(&self, x: usize, y: usize) -> Cell {
let c = self.inner.at(x, y);
Cell {
kind: c.kind,
altitude: c.altitude,
}
}
pub fn as_json(&self) -> Option<String> {
serde_json::to_string_pretty(&self.inner).ok()
}
}
#[wasm_bindgen]
pub struct Generator {
inner: RandomBoardGen<rngs::ThreadRng>,
}
#[allow(clippy::new_without_default_derive)]
#[wasm_bindgen]
impl Generator {
pub fn new() -> Generator {
set_panic_hook();
Generator {
inner: RandomBoardGen::default(),
}
}
pub fn gen_auto(&mut self, width: usize, height: usize) -> Board {
log!("Generate board: width={}, height={}", width, height);
let inner = self.inner.gen_auto(width, height);
#[cfg(feature = "wasm_debug")]
{
for (y, row) in inner.rows().enumerate() {
for (x, cell) in row.iter().enumerate() {
log!("At ({}, {}): {:?}", x, y, cell);
}
}
}
Board { inner }
}
pub fn gen(&mut self, res: Resolution, width: usize, height: usize) -> Board {
log!(
"Generate board with resolution={:?}: width={}, height={}",
res,
width,
height,
);
let inner = match res {
Resolution::Low => self.inner.gen_small(width, height),
Resolution::Middle => self.inner.gen_middle(width, height),
Resolution::High => self.inner.gen_large(width, height),
};
Board { inner }
}
}
#[cfg(test)]
mod tests {
use super::*;
extern crate wasm_bindgen_test;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
pub fn test_generate_board() {
let mut gen = Generator::new();
let board = gen.gen_auto(10, 20);
let width = board.width();
let height = board.height();
assert_eq!(width, 10);
assert_eq!(height, 20);
for x in 0..width {
for y in 0..height {
let cell = board.at(x, y);
let color_code = cell.color_code().unwrap();
assert!(color_code.len() > 0, "{}", color_code);
assert!(
color_code.chars().skip(1).all(|c| c.is_ascii_hexdigit()),
"{}",
color_code
);
let rgb_color = cell.rgb_color();
assert!(rgb_color.is_some(), "{:?}", rgb_color);
let altitude = cell.altitude;
assert!(altitude < 100, "{}", altitude);
let legend = cell.legend();
let kind = format!("{:?}", cell.kind);
assert!(
legend.contains(&kind),
"Legend '{}' does not contain kind '{}'",
legend,
kind
);
}
}
}
}