Add visualization interface
This commit is contained in:
parent
48419b4674
commit
c572fcb0e2
4 changed files with 202 additions and 23 deletions
|
|
@ -1,4 +1,4 @@
|
|||
use factorio_blueprint::layout::Layout;
|
||||
use factorio_blueprint::{common::visualize::Visualize, layout::Layout};
|
||||
use rand::SeedableRng;
|
||||
|
||||
fn main() {
|
||||
|
|
@ -15,14 +15,13 @@ fn main() {
|
|||
|
||||
let p = serde_yaml::from_reader(file).unwrap();
|
||||
|
||||
dbg!(&p);
|
||||
|
||||
for i in 0..1 {
|
||||
for i in 0..100 {
|
||||
let mut rng = rand::rngs::SmallRng::seed_from_u64(i);
|
||||
|
||||
let l = Layout::new(&p, &mut rng);
|
||||
|
||||
println!("Seed: {i}, Score {}", l.score());
|
||||
l.print();
|
||||
|
||||
l.print_visualization();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
pub mod color;
|
||||
pub mod direction;
|
||||
pub mod position;
|
||||
pub mod visualize;
|
||||
|
|
|
|||
181
src/common/visualize.rs
Normal file
181
src/common/visualize.rs
Normal file
|
|
@ -0,0 +1,181 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use std::io::Write;
|
||||
use termcolor::{ColorSpec, StandardStream, WriteColor};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
pub trait Visualize {
|
||||
fn visualize(&self) -> Visualization;
|
||||
|
||||
fn print_visualization(&self) {
|
||||
let v = self.visualize();
|
||||
|
||||
let stdout = &mut StandardStream::stdout(termcolor::ColorChoice::Always);
|
||||
|
||||
let width_digits = (v.size.x - 1).ilog10() + 1;
|
||||
let height_digits = (v.size.y - 1).ilog10() + 1;
|
||||
|
||||
// print header
|
||||
for i in 0..width_digits {
|
||||
let d = width_digits - i - 1;
|
||||
|
||||
//padding
|
||||
for _ in 0..height_digits {
|
||||
write!(stdout, " ").unwrap();
|
||||
}
|
||||
|
||||
for x in 0..v.size.x {
|
||||
let digits = x / (i32::pow(10, d));
|
||||
if digits == 0 && d > 0 {
|
||||
write!(stdout, " ").unwrap();
|
||||
} else {
|
||||
write!(
|
||||
stdout,
|
||||
"{}",
|
||||
char::from_u32((digits % 10) as u32 + 48).unwrap()
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
writeln!(stdout).unwrap();
|
||||
}
|
||||
|
||||
for y in 0..v.size.y {
|
||||
write!(stdout, "{:1$}", y, height_digits as usize).unwrap();
|
||||
|
||||
for x in 0..v.size.x {
|
||||
if let Some((s, fg, bg)) = v.symbols.get(&Position::new(x, y)) {
|
||||
let mut c = ColorSpec::new();
|
||||
c.set_fg(fg.as_ref().map(|c| termcolor::Color::Rgb(c.r, c.g, c.b)));
|
||||
c.set_bg(bg.as_ref().map(|c| termcolor::Color::Rgb(c.r, c.g, c.b)));
|
||||
stdout.set_color(&c).unwrap();
|
||||
write!(stdout, "{:1}", s.get_str()).unwrap();
|
||||
stdout.reset().unwrap();
|
||||
} else {
|
||||
write!(stdout, " ").unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(stdout, "{:1$}", y, height_digits as usize).unwrap();
|
||||
}
|
||||
|
||||
for i in 0..width_digits {
|
||||
let d = width_digits - i - 1;
|
||||
|
||||
//padding
|
||||
for _ in 0..height_digits {
|
||||
write!(stdout, " ").unwrap();
|
||||
}
|
||||
|
||||
for x in 0..v.size.x {
|
||||
let digits = x / (i32::pow(10, d));
|
||||
if digits == 0 && d > 0 {
|
||||
write!(stdout, " ").unwrap();
|
||||
} else {
|
||||
write!(
|
||||
stdout,
|
||||
"{}",
|
||||
char::from_u32((digits % 10) as u32 + 48).unwrap()
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
writeln!(stdout).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Symbol {
|
||||
Arrow(Direction),
|
||||
ArrowEnter(Direction),
|
||||
ArrowExit(Direction),
|
||||
Char(&'static str),
|
||||
Block,
|
||||
Space,
|
||||
}
|
||||
|
||||
impl Symbol {
|
||||
fn get_str(&self) -> &'static str {
|
||||
match self {
|
||||
Symbol::Arrow(dir) => match dir {
|
||||
Direction::Up => "↑",
|
||||
Direction::Right => "→",
|
||||
Direction::Down => "↓",
|
||||
Direction::Left => "←",
|
||||
},
|
||||
Symbol::ArrowEnter(dir) => match dir {
|
||||
Direction::Up => "↟",
|
||||
Direction::Right => "↠",
|
||||
Direction::Down => "↡",
|
||||
Direction::Left => "↞",
|
||||
},
|
||||
Symbol::ArrowExit(dir) => match dir {
|
||||
Direction::Up => "↥",
|
||||
Direction::Right => "↦",
|
||||
Direction::Down => "↧",
|
||||
Direction::Left => "↤",
|
||||
},
|
||||
Symbol::Char(c) => c.split_at(1).0,
|
||||
Symbol::Block => "#",
|
||||
Symbol::Space => " ",
|
||||
}
|
||||
}
|
||||
|
||||
fn get_char(&self) -> char {
|
||||
self.get_str().chars().next().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Visualization {
|
||||
size: Position,
|
||||
symbols: HashMap<Position, (Symbol, Option<Color>, Option<Color>)>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Color {
|
||||
r: u8,
|
||||
g: u8,
|
||||
b: u8,
|
||||
}
|
||||
|
||||
impl Color {
|
||||
pub fn new(r: u8, g: u8, b: u8) -> Self {
|
||||
Self { r, g, b }
|
||||
}
|
||||
|
||||
pub fn index(i: usize) -> Self {
|
||||
let c = [
|
||||
Color::new(0xe6, 0x00, 0x49),
|
||||
Color::new(0x0b, 0xb4, 0xff),
|
||||
Color::new(0x50, 0xe9, 0x91),
|
||||
Color::new(0xe6, 0xd8, 0x00),
|
||||
Color::new(0x9b, 0x19, 0xf5),
|
||||
Color::new(0xff, 0xa3, 0x00),
|
||||
Color::new(0xdc, 0x0a, 0xb4),
|
||||
Color::new(0xb3, 0xd4, 0xff),
|
||||
Color::new(0x00, 0xbf, 0xa0),
|
||||
];
|
||||
|
||||
c[i % c.len()]
|
||||
}
|
||||
}
|
||||
|
||||
impl Visualization {
|
||||
pub fn new(size: Position) -> Self {
|
||||
Self {
|
||||
size,
|
||||
symbols: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_symbol(
|
||||
&mut self,
|
||||
pos: Position,
|
||||
symbol: Symbol,
|
||||
fg: Option<Color>,
|
||||
bg: Option<Color>,
|
||||
) {
|
||||
self.symbols.insert(pos, (symbol, fg, bg));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::common::visualize::{Color, Symbol, Visualization, Visualize};
|
||||
use crate::prelude::*;
|
||||
use crate::{belt_finding::common::print_map, misc::Map};
|
||||
|
||||
|
|
@ -36,7 +37,7 @@ pub struct Problem {
|
|||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct BlockHandle(usize);
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Layout<'a> {
|
||||
problem: &'a Problem,
|
||||
blocks: Vec<(Position, Direction)>,
|
||||
|
|
@ -145,7 +146,9 @@ impl Layout<'_> {
|
|||
|
||||
/// Mutate existing layout, creating a valid layout
|
||||
pub fn mutate<R: Rng + ?Sized>(&self, rng: &mut R) -> Self {
|
||||
todo!()
|
||||
let s = self.clone();
|
||||
|
||||
s
|
||||
}
|
||||
|
||||
fn collision(
|
||||
|
|
@ -208,10 +211,11 @@ impl Layout<'_> {
|
|||
Direction::Left => pos + Position::new(offset.y, -offset.x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(&self) {
|
||||
let mut m: Map<Option<(usize, &str)>> =
|
||||
Map::new(self.problem.size.x as usize, self.problem.size.y as usize);
|
||||
impl<'a> Visualize for Layout<'a> {
|
||||
fn visualize(&self) -> Visualization {
|
||||
let mut v = Visualization::new(self.problem.size);
|
||||
|
||||
for (i, ((p, d), b)) in self
|
||||
.blocks
|
||||
|
|
@ -219,39 +223,33 @@ impl Layout<'_> {
|
|||
.zip(self.problem.blocks.iter())
|
||||
.enumerate()
|
||||
{
|
||||
let c = Color::index(i);
|
||||
|
||||
let (npos, nsize) = Self::normalize_pos((b, *p, *d));
|
||||
|
||||
for x in npos.x..(npos.x + nsize.x) {
|
||||
for y in npos.y..(npos.y + nsize.y) {
|
||||
m.set(x as usize, y as usize, Some((i, "#")));
|
||||
v.add_symbol(Position::new(x, y), Symbol::Block, Some(c), None);
|
||||
}
|
||||
}
|
||||
|
||||
let pos = Self::transform(*p, *d, Position::new(0, 0));
|
||||
|
||||
m.set(pos.x as usize, pos.y as usize, Some((i, "X")));
|
||||
v.add_symbol(pos, Symbol::Char("X"), Some(c), None);
|
||||
|
||||
for input in &b.input {
|
||||
let pos = Self::transform(*p, *d, input.offset);
|
||||
|
||||
m.set(pos.x as usize, pos.y as usize, Some((i, "i")));
|
||||
v.add_symbol(pos, Symbol::Char("i"), Some(c), None);
|
||||
}
|
||||
|
||||
for output in &b.output {
|
||||
let pos = Self::transform(*p, *d, output.offset);
|
||||
|
||||
m.set(pos.x as usize, pos.y as usize, Some((i, "o")));
|
||||
v.add_symbol(pos, Symbol::Char("o"), Some(c), None);
|
||||
}
|
||||
}
|
||||
|
||||
let _ = print_map(self.problem.size.x, self.problem.size.y, |x, y| {
|
||||
if let Some(i) = m.get(x as usize, y as usize) {
|
||||
let mut color = ColorSpec::new();
|
||||
color.set_fg(Some(crate::common::color::COLORS[i.0]));
|
||||
(color, i.1)
|
||||
} else {
|
||||
(ColorSpec::new(), " ")
|
||||
}
|
||||
});
|
||||
v
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue