From 48419b46741f68235b4b9231332f4ca6bd782d2c Mon Sep 17 00:00:00 2001 From: hal8174 Date: Wed, 21 Aug 2024 20:56:03 +0200 Subject: [PATCH] Refactor common types. --- Cargo.lock | 42 +++++++ Cargo.toml | 1 + examples/layout.rs | 25 ++-- layout.yml | 40 ++++++ src/belt_finding/brute_force.rs | 7 +- src/belt_finding/common.rs | 164 +------------------------ src/belt_finding/conflict_avoidance.rs | 7 +- src/belt_finding/mod.rs | 32 +---- src/common/color.rs | 21 ++++ src/common/direction.rs | 99 +++++++++++++++ src/common/mod.rs | 3 + src/common/position.rs | 67 ++++++++++ src/layout/mod.rs | 112 ++++++++++------- src/lib.rs | 6 + 14 files changed, 376 insertions(+), 250 deletions(-) create mode 100644 layout.yml create mode 100644 src/common/color.rs create mode 100644 src/common/direction.rs create mode 100644 src/common/mod.rs create mode 100644 src/common/position.rs diff --git a/Cargo.lock b/Cargo.lock index 78a6dbc..13eb6a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -272,6 +272,12 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "factorio_blueprint" version = "0.1.0" @@ -283,6 +289,7 @@ dependencies = [ "rand", "serde", "serde_json", + "serde_yaml", "termcolor", ] @@ -313,6 +320,12 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + [[package]] name = "heck" version = "0.5.0" @@ -328,6 +341,16 @@ dependencies = [ "libc", ] +[[package]] +name = "indexmap" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93ead53efc7ea8ed3cfb0c79fc8023fbb782a5432b52830b6518941cebe6505c" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "itertools" version = "0.10.5" @@ -596,6 +619,19 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "strsim" version = "0.11.0" @@ -653,6 +689,12 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "utf8parse" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index d5f56d6..9fc7820 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,4 +22,5 @@ flate2 = "1.0.28" rand = { version = "0.8.5", features = ["small_rng"] } serde = { version = "1.0.192", features = ["derive"] } serde_json = "1.0.108" +serde_yaml = "0.9.34" termcolor = "1.4.1" diff --git a/examples/layout.rs b/examples/layout.rs index ddcbf3a..d16e88e 100644 --- a/examples/layout.rs +++ b/examples/layout.rs @@ -1,20 +1,23 @@ -use factorio_blueprint::{ - belt_finding::common::Position, - layout::{Layout, Problem}, -}; +use factorio_blueprint::layout::Layout; use rand::SeedableRng; fn main() { - let mut p = Problem::new(Position::new(10, 10)); + // let mut p = Problem::new(Position::new(10, 10)); - let b1 = p.add_block(Position::new(3, 2)); - let b2 = p.add_block(Position::new(5, 2)); - let b3 = p.add_block(Position::new(5, 7)); + // let b1 = p.add_block(Position::new(3, 2)); + // let b2 = p.add_block(Position::new(5, 2)); + // let b3 = p.add_block(Position::new(5, 7)); - p.add_connection(b1, Position::new(0, 0), b2, Position::new(0, 0)); - p.add_connection(b2, Position::new(3, 1), b3, Position::new(4, 6)); + // p.add_connection(b1, Position::new(1, 0), b2, Position::new(1, 0)); + // p.add_connection(b2, Position::new(3, 1), b3, Position::new(4, 6)); - for i in 0..10 { + let file = std::fs::File::open("layout.yml").unwrap(); + + let p = serde_yaml::from_reader(file).unwrap(); + + dbg!(&p); + + for i in 0..1 { let mut rng = rand::rngs::SmallRng::seed_from_u64(i); let l = Layout::new(&p, &mut rng); diff --git a/layout.yml b/layout.yml new file mode 100644 index 0000000..8b10714 --- /dev/null +++ b/layout.yml @@ -0,0 +1,40 @@ +size: + x: 10 + y: 10 +blocks: + - size: + x: 3 + y: 2 + input: + - offset: + x: 1 + y: 1 + dir: Down + output: + - offset: + x: 1 + y: 0 + dir: Up + - size: + x: 5 + y: 2 + input: + output: + - offset: + x: 1 + y: 1 + dir: Down + - size: + x: 5 + y: 7 + input: + - offset: + x: 0 + y: 1 + dir: Left + output: +connections: + - startblock: 1 + startpoint: 0 + endblock: 0 + endpoint: 0 diff --git a/src/belt_finding/brute_force.rs b/src/belt_finding/brute_force.rs index d0ecb19..176326b 100644 --- a/src/belt_finding/brute_force.rs +++ b/src/belt_finding/brute_force.rs @@ -1,8 +1,9 @@ use super::{ - common::{print_map, Direction, PathField, PositionType}, - Position, COLORS, + common::{print_map, PathField}, + Position, }; use crate::misc::Map; +use crate::prelude::*; use termcolor::ColorSpec; #[derive(Default, Debug, Clone)] @@ -651,7 +652,7 @@ impl Bruteforce { let _ = print_map(self.map.width as i32, self.map.height as i32, |x, y| { if let Some((i, c)) = m.get(x as usize, y as usize) { let mut color = ColorSpec::new(); - color.set_fg(Some(COLORS[*i])); + color.set_fg(Some(crate::common::color::COLORS[*i])); (color, *c) } else if self.map.get(x as usize, y as usize).blocked { (ColorSpec::new(), "#") diff --git a/src/belt_finding/common.rs b/src/belt_finding/common.rs index d496a1e..c58ed1d 100644 --- a/src/belt_finding/common.rs +++ b/src/belt_finding/common.rs @@ -1,170 +1,8 @@ -use core::panic; use std::io::{self, Write}; -use rand::prelude::Distribution; use termcolor::{ColorSpec, StandardStream, WriteColor}; -pub type PositionType = i32; - -#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] -pub enum Direction { - Up, - Right, - Down, - Left, -} - -impl Direction { - pub fn from_neighbors(pos: &Position, neighbor: &Position) -> Self { - let x_diff = pos.x as i64 - neighbor.x as i64; - let y_diff = pos.y as i64 - neighbor.y as i64; - - match (x_diff, y_diff) { - (1, 0) => Direction::Left, - (0, 1) => Direction::Up, - (-1, 0) => Direction::Right, - (0, -1) => Direction::Down, - _ => { - panic!("Positions are not neighbors.") - } - } - } - - pub fn vertical(&self) -> bool { - match self { - Direction::Up => true, - Direction::Right => false, - Direction::Down => true, - Direction::Left => false, - } - } - - pub fn horizontal(&self) -> bool { - !self.vertical() - } - - pub fn reverse(&self) -> Self { - match self { - Direction::Up => Direction::Down, - Direction::Right => Direction::Left, - Direction::Down => Direction::Up, - Direction::Left => Direction::Right, - } - } - - pub fn clockwise(&self) -> Self { - match self { - Direction::Up => Direction::Right, - Direction::Right => Direction::Down, - Direction::Down => Direction::Left, - Direction::Left => Direction::Up, - } - } - - pub fn counter_clockwise(&self) -> Self { - match self { - Direction::Up => Direction::Left, - Direction::Right => Direction::Up, - Direction::Down => Direction::Right, - Direction::Left => Direction::Down, - } - } - - pub fn get_index(&self) -> u8 { - match self { - Direction::Up => 0, - Direction::Right => 1, - Direction::Down => 2, - Direction::Left => 3, - } - } - - pub fn from_index(i: u8) -> Self { - match i { - 0 => Direction::Up, - 1 => Direction::Right, - 2 => Direction::Down, - 3 => Direction::Left, - _ => panic!(), - } - } -} - -impl Distribution for rand::distributions::Standard { - fn sample(&self, rng: &mut R) -> Direction { - let a = [ - Direction::Up, - Direction::Right, - Direction::Down, - Direction::Left, - ]; - let r = rng.gen_range(0..4); - a[r] - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct Position { - pub x: PositionType, - pub y: PositionType, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct Dimension { - pub width: usize, - pub height: usize, -} - -impl Position { - pub fn new(x: PositionType, y: PositionType) -> Self { - Self { x, y } - } - - pub fn in_direction(&self, dir: &Direction, len: PositionType) -> Position { - match dir { - Direction::Up => Position::new(self.x, self.y - len), - Direction::Right => Position::new(self.x + len, self.y), - Direction::Down => Position::new(self.x, self.y + len), - Direction::Left => Position::new(self.x - len, self.y), - } - } - - pub fn in_range(&self, min: &Position, max: &Position) -> Option<&Position> { - if self.x < min.x { - return None; - } - if self.x >= max.x { - return None; - } - if self.y < min.y { - return None; - } - if self.y >= max.y { - return None; - } - Some(self) - } -} - -impl std::ops::Add for Position { - type Output = Position; - - fn add(mut self, rhs: Self) -> Self::Output { - self.x += rhs.x; - self.y += rhs.y; - self - } -} - -impl std::ops::Sub for Position { - type Output = Position; - - fn sub(mut self, rhs: Self) -> Self::Output { - self.x -= rhs.x; - self.y -= rhs.y; - self - } -} +use crate::prelude::*; #[derive(Clone, Debug, Copy)] pub enum PathField { diff --git a/src/belt_finding/conflict_avoidance.rs b/src/belt_finding/conflict_avoidance.rs index 717643e..ebf44ea 100644 --- a/src/belt_finding/conflict_avoidance.rs +++ b/src/belt_finding/conflict_avoidance.rs @@ -1,7 +1,8 @@ use super::{ - common::{print_map, Direction, PathField, Position, PositionType}, - Problem, COLORS, + common::{print_map, PathField}, + Problem, }; +use crate::prelude::*; use crate::{belt_finding::brute_force::BruteforceBuilder, misc::Map}; use std::ops::RangeInclusive; use termcolor::ColorSpec; @@ -520,7 +521,7 @@ impl ConflictAvoidance { } if let Some((i, c)) = m.get(x as usize, y as usize) { - color.set_fg(Some(COLORS[*i])); + color.set_fg(Some(crate::common::color::COLORS[*i])); (color, c) } else if self.map.get(x as usize, y as usize).blocked { (color, "#") diff --git a/src/belt_finding/mod.rs b/src/belt_finding/mod.rs index 9015a1d..e8e6269 100644 --- a/src/belt_finding/mod.rs +++ b/src/belt_finding/mod.rs @@ -1,12 +1,13 @@ +use crate::common::color::COLORS; use crate::graph::wheighted_graph::WheightedGraph; use crate::misc::Map; use crate::{ graph::wheighted_graph::shortest_path::dijkstra, priority_queue::fibonacci_heap::FibonacciHeap, }; -use std::ops::Index; -use termcolor::{Color, ColorSpec}; +use termcolor::ColorSpec; -use self::common::{print_map, Direction, Position, PositionType}; +use self::common::print_map; +use crate::prelude::*; pub mod brute_force; pub mod common; @@ -128,25 +129,6 @@ impl Problem { } } -pub static COLORS: Cyclic = Cyclic([ - Color::Red, - Color::Green, - Color::Yellow, - Color::Blue, - Color::Magenta, - Color::Cyan, -]); - -pub struct Cyclic([T; N]); - -impl Index for Cyclic { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self.0[index % N] - } -} - struct MapInternal<'a> { map: &'a Map, end: (Position, Direction), @@ -215,10 +197,8 @@ impl Problem { } pub mod problems { - use super::{ - common::{Direction, Position}, - Problem, - }; + use super::Problem; + use crate::prelude::*; pub fn simple() -> Problem { let mut p = Problem::new(5, 3); diff --git a/src/common/color.rs b/src/common/color.rs new file mode 100644 index 0000000..bd1d131 --- /dev/null +++ b/src/common/color.rs @@ -0,0 +1,21 @@ +use std::ops::Index; +use termcolor::Color; + +pub static COLORS: Cyclic = Cyclic([ + Color::Red, + Color::Green, + Color::Yellow, + Color::Blue, + Color::Magenta, + Color::Cyan, +]); + +pub struct Cyclic([T; N]); + +impl Index for Cyclic { + type Output = T; + + fn index(&self, index: usize) -> &Self::Output { + &self.0[index % N] + } +} diff --git a/src/common/direction.rs b/src/common/direction.rs new file mode 100644 index 0000000..64bc546 --- /dev/null +++ b/src/common/direction.rs @@ -0,0 +1,99 @@ +use crate::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Deserialize, Serialize)] +pub enum Direction { + Up, + Right, + Down, + Left, +} + +impl Direction { + pub fn from_neighbors(pos: &Position, neighbor: &Position) -> Self { + let x_diff = pos.x as i64 - neighbor.x as i64; + let y_diff = pos.y as i64 - neighbor.y as i64; + + match (x_diff, y_diff) { + (1, 0) => Direction::Left, + (0, 1) => Direction::Up, + (-1, 0) => Direction::Right, + (0, -1) => Direction::Down, + _ => { + panic!("Positions are not neighbors.") + } + } + } + + pub fn vertical(&self) -> bool { + match self { + Direction::Up => true, + Direction::Right => false, + Direction::Down => true, + Direction::Left => false, + } + } + + pub fn horizontal(&self) -> bool { + !self.vertical() + } + + pub fn reverse(&self) -> Self { + match self { + Direction::Up => Direction::Down, + Direction::Right => Direction::Left, + Direction::Down => Direction::Up, + Direction::Left => Direction::Right, + } + } + + pub fn clockwise(&self) -> Self { + match self { + Direction::Up => Direction::Right, + Direction::Right => Direction::Down, + Direction::Down => Direction::Left, + Direction::Left => Direction::Up, + } + } + + pub fn counter_clockwise(&self) -> Self { + match self { + Direction::Up => Direction::Left, + Direction::Right => Direction::Up, + Direction::Down => Direction::Right, + Direction::Left => Direction::Down, + } + } + + pub fn get_index(&self) -> u8 { + match self { + Direction::Up => 0, + Direction::Right => 1, + Direction::Down => 2, + Direction::Left => 3, + } + } + + pub fn from_index(i: u8) -> Self { + match i { + 0 => Direction::Up, + 1 => Direction::Right, + 2 => Direction::Down, + 3 => Direction::Left, + _ => panic!(), + } + } +} + +impl rand::prelude::Distribution for rand::distributions::Standard { + fn sample(&self, rng: &mut R) -> Direction { + let a = [ + Direction::Up, + Direction::Right, + Direction::Down, + Direction::Left, + ]; + let r = rng.gen_range(0..4); + a[r] + } +} diff --git a/src/common/mod.rs b/src/common/mod.rs new file mode 100644 index 0000000..30537fe --- /dev/null +++ b/src/common/mod.rs @@ -0,0 +1,3 @@ +pub mod color; +pub mod direction; +pub mod position; diff --git a/src/common/position.rs b/src/common/position.rs new file mode 100644 index 0000000..66e7f7d --- /dev/null +++ b/src/common/position.rs @@ -0,0 +1,67 @@ +use crate::prelude::*; +use serde::{Deserialize, Serialize}; + +pub type PositionType = i32; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Deserialize, Serialize)] +pub struct Position { + pub x: PositionType, + pub y: PositionType, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct Dimension { + pub width: usize, + pub height: usize, +} + +impl Position { + pub fn new(x: PositionType, y: PositionType) -> Self { + Self { x, y } + } + + pub fn in_direction(&self, dir: &Direction, len: PositionType) -> Position { + match dir { + Direction::Up => Position::new(self.x, self.y - len), + Direction::Right => Position::new(self.x + len, self.y), + Direction::Down => Position::new(self.x, self.y + len), + Direction::Left => Position::new(self.x - len, self.y), + } + } + + pub fn in_range(&self, min: &Position, max: &Position) -> Option<&Position> { + if self.x < min.x { + return None; + } + if self.x >= max.x { + return None; + } + if self.y < min.y { + return None; + } + if self.y >= max.y { + return None; + } + Some(self) + } +} + +impl std::ops::Add for Position { + type Output = Position; + + fn add(mut self, rhs: Self) -> Self::Output { + self.x += rhs.x; + self.y += rhs.y; + self + } +} + +impl std::ops::Sub for Position { + type Output = Position; + + fn sub(mut self, rhs: Self) -> Self::Output { + self.x -= rhs.x; + self.y -= rhs.y; + self + } +} diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 19dcdc1..b3f1ae4 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -1,32 +1,36 @@ -use crate::{ - belt_finding::{ - common::{print_map, Direction, Position}, - COLORS, - }, - misc::Map, -}; +use crate::prelude::*; +use crate::{belt_finding::common::print_map, misc::Map}; use rand::Rng; +use serde::{Deserialize, Serialize}; use termcolor::ColorSpec; -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] struct Block { size: Position, input: Vec, output: Vec, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] struct Interface { offset: Position, - // dir: Direction, - target: (usize, usize), + dir: Direction, } -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] +struct Connection { + startblock: usize, + startpoint: usize, + endblock: usize, + endpoint: usize, +} + +#[derive(Debug, Serialize, Deserialize)] pub struct Problem { size: Position, blocks: Vec, + connections: Vec, } #[derive(Debug, Clone, Copy)] @@ -43,6 +47,7 @@ impl Problem { Self { size, blocks: Vec::new(), + connections: Vec::new(), } } @@ -56,26 +61,26 @@ impl Problem { BlockHandle(self.blocks.len() - 1) } - pub fn add_connection( - &mut self, - starthandle: BlockHandle, - startoffset: Position, - endhandle: BlockHandle, - endoffset: Position, - ) { - let startinterface = self.blocks[starthandle.0].output.len(); - let endinterface = self.blocks[endhandle.0].input.len(); + // pub fn add_connection( + // &mut self, + // starthandle: BlockHandle, + // startoffset: Position, + // endhandle: BlockHandle, + // endoffset: Position, + // ) { + // let startinterface = self.blocks[starthandle.0].output.len(); + // let endinterface = self.blocks[endhandle.0].input.len(); - self.blocks[starthandle.0].output.push(Interface { - offset: startoffset, - target: (endhandle.0, endinterface), - }); + // self.blocks[starthandle.0].output.push(Interface { + // offset: startoffset, + // target: (endhandle.0, endinterface), + // }); - self.blocks[endhandle.0].input.push(Interface { - offset: endoffset, - target: (starthandle.0, startinterface), - }) - } + // self.blocks[endhandle.0].input.push(Interface { + // offset: endoffset, + // target: (starthandle.0, startinterface), + // }) + // } } impl Layout<'_> { @@ -176,17 +181,20 @@ impl Layout<'_> { pub fn score(&self) -> i32 { let mut sum = 0; - for ((pos, dir), b) in self.blocks.iter().zip(self.problem.blocks.iter()) { - for i in &b.output { - let startpos = Self::transform(*pos, *dir, i.offset); - let endpos = Self::transform( - self.blocks[i.target.0].0, - self.blocks[i.target.0].1, - self.problem.blocks[i.target.0].input[i.target.1].offset, - ); - sum += (startpos.x - endpos.x).abs() + (startpos.y - endpos.y).abs(); - } + for c in &self.problem.connections { + let startpos = Self::transform( + self.blocks[c.startblock].0, + self.blocks[c.startblock].1, + self.problem.blocks[c.startblock].output[c.startpoint].offset, + ); + let endpos = Self::transform( + self.blocks[c.endblock].0, + self.blocks[c.endblock].1, + self.problem.blocks[c.endblock].input[c.endpoint].offset, + ); + + sum += (startpos.x - endpos.x).abs() + (startpos.y - endpos.y).abs(); } sum @@ -202,7 +210,7 @@ impl Layout<'_> { } pub fn print(&self) { - let mut m: Map> = + let mut m: Map> = Map::new(self.problem.size.x as usize, self.problem.size.y as usize); for (i, ((p, d), b)) in self @@ -215,16 +223,32 @@ impl Layout<'_> { 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)); + m.set(x as usize, y as usize, Some((i, "#"))); } } + + let pos = Self::transform(*p, *d, Position::new(0, 0)); + + m.set(pos.x as usize, pos.y as usize, Some((i, "X"))); + + 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"))); + } + + 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"))); + } } 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(COLORS[*i])); - (color, "#") + color.set_fg(Some(crate::common::color::COLORS[i.0])); + (color, i.1) } else { (ColorSpec::new(), " ") } diff --git a/src/lib.rs b/src/lib.rs index 9f3bbe5..b1f7039 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,12 @@ pub mod belt_finding; pub mod blueprint; +pub mod common; pub mod graph; pub mod layout; pub mod misc; pub mod priority_queue; + +pub mod prelude { + pub use crate::common::direction::Direction; + pub use crate::common::position::{Position, PositionType}; +}