Refactor into different crates

This commit is contained in:
hal8174 2025-01-18 17:30:55 +01:00
parent 94473c64e0
commit dfdeae5638
82 changed files with 624 additions and 647 deletions

592
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,31 +1,8 @@
[package] [workspace]
name = "factorio_blueprint" members = [ "factorio-blueprint", "factorio-blueprint-generator", "factorio-core",
version = "0.1.0" "factorio-pathfinding"
edition = "2021" ]
resolver = "2"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release] [profile.release]
debug = true debug = true
[dev-dependencies]
criterion = "0.3"
[[bench]]
name = "bruteforce"
harness = false
[dependencies]
base64 = "0.21.5"
bon = "3.0.2"
clap = { version = "4.4.8", features = ["derive"] }
flate2 = "1.0.28"
image = "0.25.2"
miette = { version = "7.2.0", features = ["fancy"] }
proptest = "1.5.0"
proptest-derive = "0.5.0"
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"

View file

@ -0,0 +1,11 @@
[package]
name = "factorio-blueprint-generator"
version = "0.1.0"
edition = "2024"
[dependencies]
factorio-pathfinding = { path = "../factorio-pathfinding" }
factorio-core = { path = "../factorio-core" }
factorio-blueprint = { path = "../factorio-blueprint" }
serde_json = "1.0.135"
clap = { version = "4.5.26", features = ["derive"] }

View file

@ -1,9 +1,7 @@
use crate::{belt_finding::common::PathField, prelude::*}; use factorio_blueprint::{
Blueprint, BlueprintEntity, BlueprintPosition, belt::convert_to_blueprint, misc::Beltspeed,
use super::{
belt::{convert_to_blueprint, Beltspeed},
Blueprint, BlueprintEntity, BlueprintPosition,
}; };
use factorio_core::{pathfield::PathField, prelude::*};
pub fn generate_4_lane_balancer() -> Blueprint { pub fn generate_4_lane_balancer() -> Blueprint {
let mut e = vec![ let mut e = vec![

View file

@ -0,0 +1,10 @@
use factorio_blueprint::{BlueprintString, encode};
use factorio_blueprint_generator::balancer::generate_4_lane_balancer;
fn main() {
let b = BlueprintString::Blueprint(generate_4_lane_balancer());
println!("{}", serde_json::to_string_pretty(&b).unwrap());
println!("{}", encode(&serde_json::to_string(&b).unwrap()));
}

View file

@ -1,9 +1,9 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use factorio_blueprint::blueprint::{ use factorio_blueprint::{
belt::{Beltspeed, Belttype}, BlueprintBook, BlueprintBookEntry, BlueprintString, encode,
station::{basic_unload_station, station_unload}, misc::{Beltspeed, Belttype},
BlueprintBook, BlueprintBookEntry, BlueprintString,
}; };
use factorio_blueprint_generator::station::basic_unload_station;
#[derive(Parser)] #[derive(Parser)]
struct Args { struct Args {
@ -104,10 +104,7 @@ fn main() {
.build(), .build(),
); );
println!( println!("{}", encode(&serde_json::to_string(&b).unwrap()));
"{}",
factorio_blueprint::blueprint::encode(&serde_json::to_string(&b).unwrap())
);
} }
Command::Single { Command::Single {
locomotives, locomotives,
@ -126,10 +123,7 @@ fn main() {
// println!("{}", serde_json::to_string_pretty(&b).unwrap()); // println!("{}", serde_json::to_string_pretty(&b).unwrap());
println!( println!("{}", encode(&serde_json::to_string(&b).unwrap()));
"{}",
factorio_blueprint::blueprint::encode(&serde_json::to_string(&b).unwrap())
);
} }
} }
} }

View file

@ -1,6 +1,5 @@
use factorio_blueprint::blueprint::{ use factorio_blueprint::{BlueprintBook, BlueprintBookEntry, BlueprintString, encode};
train::generate_train, BlueprintBook, BlueprintBookEntry, BlueprintString, use factorio_blueprint_generator::train::generate_train;
};
fn main() { fn main() {
let layouts = [ let layouts = [
@ -38,8 +37,5 @@ fn main() {
println!("{}", serde_json::to_string_pretty(&b).unwrap()); println!("{}", serde_json::to_string_pretty(&b).unwrap());
println!( println!("{}", encode(&serde_json::to_string(&b).unwrap()));
"{}",
factorio_blueprint::blueprint::encode(&serde_json::to_string(&b).unwrap())
);
} }

View file

@ -0,0 +1,3 @@
pub mod balancer;
pub mod station;
pub mod train;

View file

@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use super::{ use factorio_blueprint::{
belt::{Beltspeed, Belttype},
Blueprint, BlueprintEntity, BlueprintPosition, Blueprint, BlueprintEntity, BlueprintPosition,
misc::{Beltspeed, Belttype},
}; };
pub fn station_unload( pub fn station_unload(
@ -177,12 +177,14 @@ pub fn station_unload(
pub fn unloader(beltspeed: Beltspeed, belttype: Belttype) -> (Vec<BlueprintEntity>, f64) { pub fn unloader(beltspeed: Beltspeed, belttype: Belttype) -> (Vec<BlueprintEntity>, f64) {
match beltspeed { match beltspeed {
Beltspeed::Normal => { Beltspeed::Normal => {
let mut e = vec![BlueprintEntity::builder( let mut e = vec![
BlueprintEntity::builder(
"fast-transport-belt".to_owned(), "fast-transport-belt".to_owned(),
0, 0,
BlueprintPosition::new(3.5, -1.5), BlueprintPosition::new(3.5, -1.5),
) )
.build()]; .build(),
];
if belttype.contains_left() { if belttype.contains_left() {
let offset = e.len() as u32; let offset = e.len() as u32;
@ -239,12 +241,14 @@ pub fn unloader(beltspeed: Beltspeed, belttype: Belttype) -> (Vec<BlueprintEntit
(e, -2.5) (e, -2.5)
} }
Beltspeed::Fast => { Beltspeed::Fast => {
let mut e = vec![BlueprintEntity::builder( let mut e = vec![
BlueprintEntity::builder(
"fast-transport-belt".to_owned(), "fast-transport-belt".to_owned(),
0, 0,
BlueprintPosition::new(3.5, -3.5), BlueprintPosition::new(3.5, -3.5),
) )
.build()]; .build(),
];
if belttype.contains_left() { if belttype.contains_left() {
let offset = e.len() as u32; let offset = e.len() as u32;
@ -369,12 +373,14 @@ pub fn unloader(beltspeed: Beltspeed, belttype: Belttype) -> (Vec<BlueprintEntit
(e, -4.5) (e, -4.5)
} }
Beltspeed::Express => { Beltspeed::Express => {
let mut e = vec![BlueprintEntity::builder( let mut e = vec![
BlueprintEntity::builder(
"express-transport-belt".to_owned(), "express-transport-belt".to_owned(),
0, 0,
BlueprintPosition::new(3.5, -3.5), BlueprintPosition::new(3.5, -3.5),
) )
.build()]; .build(),
];
if belttype.contains_left() { if belttype.contains_left() {
let offset = e.len() as u32; let offset = e.len() as u32;

View file

@ -1,4 +1,4 @@
use super::{ use factorio_blueprint::{
Blueprint, BlueprintEntity, BlueprintInventoryLocation, BlueprintItemID, BlueprintItemRequest, Blueprint, BlueprintEntity, BlueprintInventoryLocation, BlueprintItemID, BlueprintItemRequest,
BlueprintPosition, BlueprintStockConnection, BlueprintPosition, BlueprintStockConnection,
}; };

View file

@ -0,0 +1,13 @@
[package]
name = "factorio-blueprint"
version = "0.1.0"
edition = "2024"
[dependencies]
factorio-core = { path = "../factorio-core" }
base64 = "0.22.1"
bon = "3.3.2"
clap = { version = "4.5.26", features = ["derive"] }
serde = "1.0.217"
serde_json = "1.0.135"
flate2 = "1.0.35"

View file

@ -0,0 +1 @@
0eNqVkN0OgjAMRt+l14XwVw28ijFmYKNNYCAbRkL27o55oVET42Wbfue0XaBuJx5G0RaqBaTptYFqt4CRk1bt2tOqY6jAWOY2as5sLDgE0Ue+QZU6/DGLcJlUK3b2fR6keQlnbo/A2ooVflhDMR/01NU8ejp+Jw698Zler0rPIaKYELwhKmJyH0aEWnnaNlmXfVNkfysoKAIxT9YLxHLn889HIlx5NCFMm6wsypKooKzMU+fu/rR3Gg==

View file

@ -0,0 +1 @@
0eNrFld2OmzAQhV9lNZeVWfETkgWpfYJe9i6KLAKTrlWwqW3SRhHv3jE4JLv1ptVetIqExoP9cebMQM6wbwfstZAWyjOIWkkD5fYMRnyVVetysuoQSmiwFg3qqFbdXsjKKg0jAyEb/AllMrLAEasrISNjVX+zNR13DFBaYQXOj5oWJy6Hbo+aWCxwnkGvDB1R0vEJs85o3wnKqMiITbKtVi3f43N1FCSNNhmUDbeKTxQoD1VrkM1M7pg9Nvwq2Z5698ij0HagzKJh3hF9cRUYtDPN8FZ0ghyzergwfe7vkZ9hdExbzVUBOA9feZGyO/a/7cnT02NO7EZorOf7SRo2yWM53WsmlHHZ2xU16CC0uS3MS+orTYElUTHMPaBi3BylcRy7LqvB9oN9PU9/tsWx+hNpGqTlB606LiSBfA/H3TgGrMreadXmv1qVkFVu3bkdTmkJn+Cfe7daQB02YugibMkNLeqoVy0G3XvMvX9r8i+AzBfkfmi/RfR+oKb6Q6z4wtoExjaAXl/LtohtVD+jsXdFTuAAafP+ujeFQ1KjfpBa16ZtwhKWsmzHtilFGUumKHM/imjNVlOOrmzjo5yinKK1zxFvGZW5977joiE1dHk5Sgy+0xhQRdEyhk6pT9JmqXQ3zcmLCfsIkxke7c1gl6AE9/5eZyul8ECcoa3c42NuKNFgT59XlP4beBeXvMAlv+EePjykASR5ISx2boKWvygGRzJmKjNfp8WqKPJ8ladFlozjL1XOQeE=

View file

@ -0,0 +1 @@
0eNrFlM9unDAQxt9lziZaYIHAoU/QY2+rFeLPbGPV2JY9bLNa8e4ZA9msIppWOTRCQuOx/fM33xiu0KoRrZOaoLqC7Iz2UB2u4OVP3aiQ082AUEGPnezRRZ0ZWqkbMg4mAVL3+AxVPImNLeQaqSNPxt4tTaajANQkSeJy1Dy41HocWnTMEhv7BVjjeYvRgc+YPOV1F6iiMmU2yyZnVN3iU3OWLI0XedR9TaaeKVCdGuVRLMw6MC329Ztkuthw5Fk6Gjlz07CsiH6ECjzSQvO1koNkx8iNr8w19+/I7zAFJjVLVQDBw3deJOID+//syePjQ8bsXjrslvk42TZpxdY8188oH7L3I27QSTp/X9gqSTqjI6saQlhawLWEa5TsdrvQZDOSHen9dfq7K4FlLyxp1FSfnBlqqRm0tnA6TtOGU+knnSq+0qmYnQrjwTZuFlrBN/jv1u1voAF7OQ4RKjbDyS6yRuGmeQ/Zal/O9m0gsxuyHdWviL8OdISbjdi9soqNS7uBzt/KJkQVdU/o6UORM3iDVHy+7qIMSG7Ub1Yb2nSIRSwSkR7FIeEoFfEcpeHhiMdiP+f4LYo1yjjKOMrXHPMk4RBcu/2UBZzR+VlEliflviyzbJ8lZRpP0wudqOug

View file

@ -0,0 +1,59 @@
use factorio_core::{pathfield::PathField, prelude::*};
use crate::misc::Beltspeed;
use super::{BlueprintEntity, BlueprintPosition};
pub fn convert_belt_to_blueprint(
belt: &PathField,
speed: &Beltspeed,
nextfree: &mut u32,
) -> impl Iterator<Item = BlueprintEntity> + use<> {
match belt {
PathField::Belt { pos, dir } => {
*nextfree += 1;
vec![
BlueprintEntity::builder(
speed.string(),
*nextfree - 1,
BlueprintPosition::new(pos.x as f64 + 0.5, pos.y as f64 + 0.5),
)
.direction(dir.get_index() * 4)
.build(),
]
.into_iter()
}
PathField::Underground { pos, dir, len } => {
*nextfree += 2;
let endpos = pos.in_direction(dir, *len as PositionType);
vec![
BlueprintEntity::builder(
speed.string_underground(),
*nextfree - 2,
BlueprintPosition::new(pos.x as f64 + 0.5, pos.y as f64 + 0.5),
)
.underground_type("input".to_string())
.direction(dir.get_index() * 4)
.build(),
BlueprintEntity::builder(
speed.string_underground(),
*nextfree - 1,
BlueprintPosition::new(endpos.x as f64 + 0.5, endpos.y as f64 + 0.5),
)
.underground_type("output".to_string())
.direction(dir.get_index() * 4)
.build(),
]
.into_iter()
}
}
}
pub fn convert_to_blueprint<'p, 's, 'n>(
path: &'p [PathField],
speed: &'s Beltspeed,
nextfree: &'n mut u32,
) -> impl Iterator<Item = BlueprintEntity> + use<'p, 's, 'n> {
path.iter()
.flat_map(|b| convert_belt_to_blueprint(b, speed, nextfree))
}

View file

@ -1,6 +1,5 @@
use base64::prelude::*;
use clap::Parser; use clap::Parser;
use factorio_blueprint::blueprint::{decode, encode}; use factorio_blueprint::{decode, encode};
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]

View file

@ -1,18 +1,16 @@
use base64::Engine;
use base64::engine::general_purpose::STANDARD; use base64::engine::general_purpose::STANDARD;
use base64::prelude::BASE64_STANDARD; use base64::prelude::BASE64_STANDARD;
use base64::Engine;
use std::io::Cursor; use std::io::Cursor;
use std::io::Read; use std::io::Read;
pub mod misc;
pub mod structs; pub mod structs;
pub mod belt;
pub use structs::*; pub use structs::*;
pub mod balancer;
pub mod belt;
pub mod station;
pub mod train;
pub fn decode(s: &str) -> String { pub fn decode(s: &str) -> String {
let raw = s.trim().as_bytes(); let raw = s.trim().as_bytes();
assert!(raw[0] == b'0'); assert!(raw[0] == b'0');

View file

@ -1,9 +1,5 @@
use clap::ValueEnum; use clap::ValueEnum;
use crate::{belt_finding::common::PathField, prelude::PositionType};
use super::{Blueprint, BlueprintEntity, BlueprintPosition};
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)] #[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
pub enum Beltspeed { pub enum Beltspeed {
Normal, Normal,
@ -84,55 +80,3 @@ impl Belttype {
} }
} }
} }
pub fn convert_belt_to_blueprint(
belt: &PathField,
speed: &Beltspeed,
nextfree: &mut u32,
) -> impl Iterator<Item = BlueprintEntity> {
match belt {
PathField::Belt { pos, dir } => {
*nextfree += 1;
vec![BlueprintEntity::builder(
speed.string(),
*nextfree - 1,
BlueprintPosition::new(pos.x as f64 + 0.5, pos.y as f64 + 0.5),
)
.direction(dir.get_index() * 4)
.build()]
.into_iter()
}
PathField::Underground { pos, dir, len } => {
*nextfree += 2;
let endpos = pos.in_direction(dir, *len as PositionType);
vec![
BlueprintEntity::builder(
speed.string_underground(),
*nextfree - 2,
BlueprintPosition::new(pos.x as f64 + 0.5, pos.y as f64 + 0.5),
)
.underground_type("input".to_string())
.direction(dir.get_index() * 4)
.build(),
BlueprintEntity::builder(
speed.string_underground(),
*nextfree - 1,
BlueprintPosition::new(endpos.x as f64 + 0.5, endpos.y as f64 + 0.5),
)
.underground_type("output".to_string())
.direction(dir.get_index() * 4)
.build(),
]
.into_iter()
}
}
}
pub fn convert_to_blueprint<'p, 's, 'n>(
path: &'p [PathField],
speed: &'s Beltspeed,
nextfree: &'n mut u32,
) -> impl Iterator<Item = BlueprintEntity> + use<'p, 's, 'n> {
path.iter()
.flat_map(|b| convert_belt_to_blueprint(b, speed, nextfree))
}

16
factorio-core/Cargo.toml Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "factorio-core"
version = "0.1.0"
edition = "2024"
[dev-dependencies]
criterion = "0.3"
[dependencies]
image = "0.25.5"
proptest = "1.5.0"
proptest-derive = "0.5.0"
rand = "0.8.5"
serde = { version = "1.0.217", features = ["derive"] }
termcolor = "1.4.1"

View file

@ -1,13 +1,14 @@
pub mod belt_finding; pub mod aabb;
pub mod blueprint; pub mod block;
pub mod common; pub mod color;
pub mod graph; pub mod direction;
pub mod layout; pub mod pathfield;
pub mod misc; pub mod position;
pub mod priority_queue; pub mod transformation;
pub mod visualize;
pub mod prelude { pub mod prelude {
pub use crate::common::{ pub use crate::{
aabb::AABB, aabb::AABB,
block::Block, block::Block,
direction::Direction, direction::Direction,

View file

@ -1,5 +1,5 @@
use super::Visualization; use super::Visualization;
use crate::{common::visualize::Symbol, prelude::Direction}; use crate::{prelude::Direction, visualize::Symbol};
use image::{GenericImage, Rgba, RgbaImage}; use image::{GenericImage, Rgba, RgbaImage};
pub(super) fn draw<I: GenericImage<Pixel = Rgba<u8>>>(v: &Visualization, image: &mut I) { pub(super) fn draw<I: GenericImage<Pixel = Rgba<u8>>>(v: &Visualization, image: &mut I) {

View file

@ -0,0 +1,31 @@
[package]
name = "factorio-pathfinding"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dev-dependencies]
criterion = "0.3"
[[bench]]
name = "bruteforce"
harness = false
[dependencies]
factorio-core = { path = "../factorio-core" }
factorio-blueprint = { path = "../factorio-blueprint" }
base64 = "0.21.5"
bon = "3.0.2"
clap = { version = "4.4.8", features = ["derive"] }
flate2 = "1.0.28"
image = "0.25.2"
miette = { version = "7.2.0", features = ["fancy"] }
proptest = "1.5.0"
proptest-derive = "0.5.0"
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"

View file

@ -1,6 +1,6 @@
use criterion::{criterion_group, criterion_main, Criterion}; use criterion::{criterion_group, criterion_main, Criterion};
use factorio_blueprint::belt_finding::brute_force::problems::{mid, simple, snake}; use factorio_pathfinding::belt_finding::brute_force::problems::{mid, simple, snake};
macro_rules! bench_bruteforce { macro_rules! bench_bruteforce {
($b:ident; $i:ident) => { ($b:ident; $i:ident) => {

View file

@ -1,10 +1,7 @@
use std::io;
use clap::{Parser, ValueEnum}; use clap::{Parser, ValueEnum};
use factorio_blueprint::{ use factorio_core::visualize::Visualize;
belt_finding::brute_force::{problems, Bruteforce}, use factorio_pathfinding::belt_finding::brute_force::{problems, Bruteforce};
common::visualize::Visualize, use std::io;
};
#[derive(ValueEnum, Clone)] #[derive(ValueEnum, Clone)]
enum Mode { enum Mode {

View file

@ -1,5 +1,5 @@
use clap::Parser; use clap::Parser;
use factorio_blueprint::blueprint; use factorio_blueprint::{decode, BlueprintString};
use std::path::PathBuf; use std::path::PathBuf;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
@ -12,10 +12,10 @@ fn main() {
let s = std::fs::read_to_string(args.blueprint).unwrap(); let s = std::fs::read_to_string(args.blueprint).unwrap();
let raw = blueprint::decode(s.trim_end()); let raw = decode(s.trim_end());
// println!("{}", &raw); // println!("{}", &raw);
let bp = serde_json::from_str::<blueprint::structs::BlueprintString>(&raw).unwrap(); let bp = serde_json::from_str::<BlueprintString>(&raw).unwrap();
dbg!(&bp); dbg!(&bp);

View file

@ -1,4 +1,4 @@
use factorio_blueprint::priority_queue::{fibonacci_heap::FibonacciHeap, PriorityQueue}; use factorio_pathfinding::priority_queue::{fibonacci_heap::FibonacciHeap, PriorityQueue};
use std::fmt::Debug; use std::fmt::Debug;
fn test_loop<P>() fn test_loop<P>()

View file

@ -1,8 +1,8 @@
use super::{common::PathField, Position}; use factorio_core::{pathfield::PathField, prelude::*, visualize::Visualize};
use crate::prelude::*;
use crate::{common::visualize::Visualize, misc::Map};
use std::time::Instant; use std::time::Instant;
use crate::misc::Map;
#[derive(Default, Debug, Clone)] #[derive(Default, Debug, Clone)]
pub struct BruteforceField { pub struct BruteforceField {
pub blocked: bool, pub blocked: bool,
@ -590,8 +590,8 @@ impl Bruteforce {
} }
impl Visualize for Bruteforce { impl Visualize for Bruteforce {
fn visualize(&self) -> crate::common::visualize::Visualization { fn visualize(&self) -> factorio_core::visualize::Visualization {
let mut v = crate::common::visualize::Visualization::new(Position::new( let mut v = factorio_core::visualize::Visualization::new(Position::new(
self.map.width as i32, self.map.width as i32,
self.map.height as i32, self.map.height as i32,
)); ));
@ -601,8 +601,8 @@ impl Visualize for Bruteforce {
if self.map.get(x, y).blocked { if self.map.get(x, y).blocked {
v.add_symbol( v.add_symbol(
Position::new(x as i32, y as i32), Position::new(x as i32, y as i32),
crate::common::visualize::Symbol::Block, factorio_core::visualize::Symbol::Block,
Some(crate::common::visualize::Color::white()), Some(factorio_core::visualize::Color::white()),
None, None,
); );
} }
@ -615,22 +615,22 @@ impl Visualize for Bruteforce {
PathField::Belt { pos, dir } => { PathField::Belt { pos, dir } => {
v.add_symbol( v.add_symbol(
*pos, *pos,
crate::common::visualize::Symbol::Arrow(*dir), factorio_core::visualize::Symbol::Arrow(*dir),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
); );
} }
PathField::Underground { pos, dir, len } => { PathField::Underground { pos, dir, len } => {
v.add_symbol( v.add_symbol(
*pos, *pos,
crate::common::visualize::Symbol::ArrowEnter(*dir), factorio_core::visualize::Symbol::ArrowEnter(*dir),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
); );
v.add_symbol( v.add_symbol(
pos.in_direction(dir, *len as i32), pos.in_direction(dir, *len as i32),
crate::common::visualize::Symbol::ArrowExit(*dir), factorio_core::visualize::Symbol::ArrowExit(*dir),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
); );
} }
@ -638,11 +638,11 @@ impl Visualize for Bruteforce {
} }
v.add_symbol( v.add_symbol(
problem.end_pos, problem.end_pos,
crate::common::visualize::Symbol::Char(match problem.finished { factorio_core::visualize::Symbol::Char(match problem.finished {
true => 'T', true => 'T',
false => 't', false => 't',
}), }),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
); );
} }

View file

@ -1,13 +1,13 @@
use super::{common::PathField, Problem};
use crate::blueprint::belt::{convert_to_blueprint, Beltspeed};
use crate::blueprint::BlueprintEntity;
use crate::{belt_finding::brute_force::BruteforceBuilder, misc::Map}; use crate::{belt_finding::brute_force::BruteforceBuilder, misc::Map};
use crate::{common::visualize::Visualize, prelude::*}; use factorio_blueprint::{belt::convert_to_blueprint, misc::Beltspeed, BlueprintEntity};
use factorio_core::{pathfield::PathField, prelude::*, visualize::Visualize};
use std::{ use std::{
ops::RangeInclusive, ops::RangeInclusive,
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use super::Problem;
#[derive(Default)] #[derive(Default)]
struct Field { struct Field {
blocked: bool, blocked: bool,
@ -510,8 +510,8 @@ impl ConflictAvoidance {
} }
impl Visualize for ConflictAvoidance { impl Visualize for ConflictAvoidance {
fn visualize(&self) -> crate::common::visualize::Visualization { fn visualize(&self) -> factorio_core::visualize::Visualization {
let mut v = crate::common::visualize::Visualization::new(Position::new( let mut v = factorio_core::visualize::Visualization::new(Position::new(
self.map.width as i32, self.map.width as i32,
self.map.height as i32, self.map.height as i32,
)); ));
@ -526,8 +526,8 @@ impl Visualize for ConflictAvoidance {
v.add_symbol( v.add_symbol(
Position::new(x as i32, y as i32), Position::new(x as i32, y as i32),
crate::common::visualize::Symbol::Block, factorio_core::visualize::Symbol::Block,
Some(crate::common::visualize::Color::white()), Some(factorio_core::visualize::Color::white()),
None, None,
); );
} }
@ -555,22 +555,22 @@ impl Visualize for ConflictAvoidance {
PathField::Belt { pos, dir } => { PathField::Belt { pos, dir } => {
v.add_symbol( v.add_symbol(
*pos, *pos,
crate::common::visualize::Symbol::Arrow(*dir), factorio_core::visualize::Symbol::Arrow(*dir),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
); );
} }
PathField::Underground { pos, dir, len } => { PathField::Underground { pos, dir, len } => {
v.add_symbol( v.add_symbol(
*pos, *pos,
crate::common::visualize::Symbol::ArrowEnter(*dir), factorio_core::visualize::Symbol::ArrowEnter(*dir),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
); );
v.add_symbol( v.add_symbol(
pos.in_direction(dir, *len as i32), pos.in_direction(dir, *len as i32),
crate::common::visualize::Symbol::ArrowExit(*dir), factorio_core::visualize::Symbol::ArrowExit(*dir),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
); );
} }
@ -583,7 +583,7 @@ impl Visualize for ConflictAvoidance {
for y in yrange.clone() { for y in yrange.clone() {
v.overwrite_background( v.overwrite_background(
Position::new(x, y), Position::new(x, y),
Some(crate::common::visualize::Color::new(150, 150, 0)), Some(factorio_core::visualize::Color::new(150, 150, 0)),
); );
} }
} }
@ -594,7 +594,7 @@ impl Visualize for ConflictAvoidance {
if conflicts.get(x, y) > &1 { if conflicts.get(x, y) > &1 {
v.overwrite_background( v.overwrite_background(
Position::new(x as i32, y as i32), Position::new(x as i32, y as i32),
Some(crate::common::visualize::Color::new(100, 80, 80)), Some(factorio_core::visualize::Color::new(100, 80, 80)),
); );
} }
} }

View file

@ -1,14 +1,13 @@
use crate::common::visualize::Visualize;
use crate::graph::wheighted_graph::shortest_path::dijkstra; use crate::graph::wheighted_graph::shortest_path::dijkstra;
use crate::graph::wheighted_graph::WheightedGraph; use crate::graph::wheighted_graph::WheightedGraph;
use crate::layout::Layout; use crate::layout::Layout;
use crate::misc::Map; use crate::misc::Map;
use crate::prelude::*;
use crate::priority_queue::BinaryHeap; use crate::priority_queue::BinaryHeap;
use factorio_core::{prelude::*, visualize::Visualize};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
pub mod brute_force; pub mod brute_force;
pub mod common;
pub mod conflict_avoidance; pub mod conflict_avoidance;
#[derive(Debug, Default, Serialize, Deserialize, Clone, Copy)] #[derive(Debug, Default, Serialize, Deserialize, Clone, Copy)]
@ -128,8 +127,8 @@ impl Problem {
} }
impl Visualize for Problem { impl Visualize for Problem {
fn visualize(&self) -> crate::common::visualize::Visualization { fn visualize(&self) -> factorio_core::visualize::Visualization {
let mut v = crate::common::visualize::Visualization::new(Position::new( let mut v = factorio_core::visualize::Visualization::new(Position::new(
self.map.width as i32, self.map.width as i32,
self.map.height as i32, self.map.height as i32,
)); ));
@ -139,8 +138,8 @@ impl Visualize for Problem {
if self.map.get(x, y).blocked { if self.map.get(x, y).blocked {
v.add_symbol( v.add_symbol(
Position::new(x as i32, y as i32), Position::new(x as i32, y as i32),
crate::common::visualize::Symbol::Block, factorio_core::visualize::Symbol::Block,
Some(crate::common::visualize::Color::white()), Some(factorio_core::visualize::Color::white()),
None, None,
) )
} }
@ -150,8 +149,8 @@ impl Visualize for Problem {
for (i, (p, _d)) in self.start.iter().enumerate() { for (i, (p, _d)) in self.start.iter().enumerate() {
v.add_symbol( v.add_symbol(
*p, *p,
crate::common::visualize::Symbol::Char('S'), factorio_core::visualize::Symbol::Char('S'),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
) )
} }
@ -159,8 +158,8 @@ impl Visualize for Problem {
for (i, (p, _d)) in self.end.iter().enumerate() { for (i, (p, _d)) in self.end.iter().enumerate() {
v.add_symbol( v.add_symbol(
*p, *p,
crate::common::visualize::Symbol::Char('T'), factorio_core::visualize::Symbol::Char('T'),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
) )
} }
@ -169,8 +168,8 @@ impl Visualize for Problem {
for (pos, dir) in p { for (pos, dir) in p {
v.add_symbol( v.add_symbol(
*pos, *pos,
crate::common::visualize::Symbol::Arrow(*dir), factorio_core::visualize::Symbol::Arrow(*dir),
Some(crate::common::visualize::Color::index(i)), Some(factorio_core::visualize::Color::index(i)),
None, None,
) )
} }
@ -252,7 +251,7 @@ impl Problem {
pub mod problems { pub mod problems {
use super::Problem; use super::Problem;
use crate::prelude::*; use factorio_core::prelude::*;
pub fn simple() -> Problem { pub fn simple() -> Problem {
let mut p = Problem::new(5, 3); let mut p = Problem::new(5, 3);

View file

@ -1,8 +1,8 @@
use clap::{Parser, Subcommand, ValueEnum}; use clap::{Parser, Subcommand, ValueEnum};
use factorio_blueprint::{ use factorio_blueprint::{encode, misc::Beltspeed, Blueprint, BlueprintString};
belt_finding::{conflict_avoidance::ConflictAvoidance, problems, Problem}, use factorio_core::visualize::Visualize;
blueprint::{Blueprint, BlueprintString}, use factorio_pathfinding::belt_finding::{
common::visualize::Visualize, conflict_avoidance::ConflictAvoidance, problems, Problem,
}; };
use std::{io, path::PathBuf}; use std::{io, path::PathBuf};
@ -49,10 +49,7 @@ struct Args {
fn output_blueprint(conflict: &ConflictAvoidance) { fn output_blueprint(conflict: &ConflictAvoidance) {
let mut offset = 0; let mut offset = 0;
let belts = conflict.belt_blueprint( let belts = conflict.belt_blueprint(&Beltspeed::Normal, &mut offset);
&factorio_blueprint::blueprint::belt::Beltspeed::Normal,
&mut offset,
);
let bp = BlueprintString::Blueprint( let bp = BlueprintString::Blueprint(
Blueprint::builder() Blueprint::builder()
@ -61,10 +58,7 @@ fn output_blueprint(conflict: &ConflictAvoidance) {
.build(), .build(),
); );
println!( println!("{}", encode(&serde_json::to_string(&bp).unwrap()));
"{}",
factorio_blueprint::blueprint::encode(&serde_json::to_string(&bp).unwrap())
);
} }
fn main() { fn main() {

View file

@ -1,8 +1,7 @@
use clap::Parser; use clap::Parser;
use factorio_blueprint::{ use factorio_core::visualize::image_grid;
belt_finding::{conflict_avoidance::ConflictAvoidance, Problem}, use factorio_core::visualize::Visualize;
common::visualize::{image_grid, Visualize}, use factorio_pathfinding::belt_finding::{conflict_avoidance::ConflictAvoidance, Problem};
};
use std::{fs::File, path::PathBuf}; use std::{fs::File, path::PathBuf};
#[derive(Parser)] #[derive(Parser)]

View file

@ -0,0 +1,98 @@
use clap::{Parser, Subcommand};
use factorio_core::visualize::Visualize;
use factorio_pathfinding::layout::{genetic_algorithm2, GeneticAlgorithm, PathLayout};
use miette::{Context, IntoDiagnostic, Result};
use rand::{rngs::SmallRng, SeedableRng};
use std::path::PathBuf;
#[derive(Debug, Parser)]
struct Args {
#[clap(short, long, default_value_t = 0)]
seed: u64,
problem: PathBuf,
#[command(subcommand)]
subcommand: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
V1,
V2,
Bench {
#[clap(short, long, default_value_t = 100)]
runs: usize,
#[clap(short, long, default_value_t = 100)]
mutations: usize,
},
}
fn main() -> Result<()> {
let args = Args::parse();
let mut rng = SmallRng::seed_from_u64(args.seed);
let file = std::fs::File::open(args.problem)
.into_diagnostic()
.context("Failed to open problem file.")?;
let p = serde_yaml::from_reader(file)
.into_diagnostic()
.context("Failed to parse yaml.")?;
match args.subcommand {
Commands::V1 => {
let mut g = GeneticAlgorithm::new(&p, 20, 2, 0, &mut rng);
for i in 0..100 {
println!("Generatrion {i}");
g.generation(&mut rng);
}
g.output_population();
}
Commands::V2 => {
let mut m: Option<PathLayout> = None;
for _ in 0..20 {
let g = genetic_algorithm2(&p, 10, 320, 10000, &mut rng);
g.print_visualization();
if m.as_ref().is_none_or(|m| g.score() < m.score()) {
m = Some(g);
}
}
m.unwrap().print_visualization();
}
Commands::Bench { runs, mutations } => {
let mut map = Vec::new();
let mut m: Option<PathLayout> = None;
let start = std::time::Instant::now();
for _ in 0..runs {
let g = genetic_algorithm2(&p, 1, mutations, mutations, &mut rng);
map.push(g.score());
if m.as_ref().is_none_or(|m| g.score() < m.score()) {
m = Some(g);
}
}
println!("Time: {:.2}", start.elapsed().as_secs_f32());
let mean = map.iter().sum::<usize>() / runs;
println!("Mean: {}", mean);
let min = map.iter().min().unwrap();
println!("Min: {}", min);
let max = map.iter().max().unwrap();
println!("Max: {}", max);
let stddev =
((map.iter().map(|v| (v - mean) * (v - mean)).sum::<usize>() / runs) as f64).sqrt();
println!("Stddev: {:.1}", stddev);
m.unwrap().print_visualization();
}
}
Ok(())
}

View file

@ -1,7 +1,7 @@
use crate::belt_finding::common::PathField;
use crate::belt_finding::conflict_avoidance::ConflictAvoidance; use crate::belt_finding::conflict_avoidance::ConflictAvoidance;
use crate::common::visualize::{image_grid, Color, Symbol, Visualization, Visualize}; use factorio_core::pathfield::PathField;
use crate::prelude::*; use factorio_core::prelude::*;
use factorio_core::visualize::{image_grid, Color, Symbol, Visualization, Visualize};
use rand::{seq::SliceRandom, Rng}; use rand::{seq::SliceRandom, Rng};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::atomic::AtomicU32; use std::sync::atomic::AtomicU32;
@ -241,7 +241,7 @@ impl<'a> PathLayout<'a> {
} }
impl<'a> Visualize for PathLayout<'a> { impl<'a> Visualize for PathLayout<'a> {
fn visualize(&self) -> Visualization { fn visualize(&self) -> factorio_core::visualize::Visualization {
let mut v = self.layout.visualize(); let mut v = self.layout.visualize();
let offset = self.layout.blocks.len(); let offset = self.layout.blocks.len();

View file

@ -0,0 +1,5 @@
pub mod belt_finding;
pub mod graph;
pub mod layout;
pub mod misc;
pub mod priority_queue;

View file

@ -1,12 +0,0 @@
use factorio_blueprint::blueprint::{balancer::generate_4_lane_balancer, BlueprintString};
fn main() {
let b = BlueprintString::Blueprint(generate_4_lane_balancer());
println!("{}", serde_json::to_string_pretty(&b).unwrap());
println!(
"{}",
factorio_blueprint::blueprint::encode(&serde_json::to_string(&b).unwrap())
);
}

View file

@ -1,65 +0,0 @@
use clap::{Parser, Subcommand};
use factorio_blueprint::{
common::visualize::Visualize,
layout::{genetic_algorithm2, GeneticAlgorithm, PathLayout},
};
use miette::{Context, IntoDiagnostic, Result};
use rand::{rngs::SmallRng, SeedableRng};
use std::path::PathBuf;
#[derive(Debug, Parser)]
struct Args {
#[clap(short, long, default_value_t = 0)]
seed: u64,
problem: PathBuf,
#[command(subcommand)]
subcommand: Commands,
}
#[derive(Debug, Subcommand)]
enum Commands {
V1,
V2,
}
fn main() -> Result<()> {
let args = Args::parse();
let mut rng = SmallRng::seed_from_u64(args.seed);
let file = std::fs::File::open(args.problem)
.into_diagnostic()
.context("Failed to open problem file.")?;
let p = serde_yaml::from_reader(file)
.into_diagnostic()
.context("Failed to parse yaml.")?;
match args.subcommand {
Commands::V1 => {
let mut g = GeneticAlgorithm::new(&p, 20, 2, 0, &mut rng);
for i in 0..100 {
println!("Generatrion {i}");
g.generation(&mut rng);
}
g.output_population();
}
Commands::V2 => {
let mut m: Option<PathLayout> = None;
for _ in 0..20 {
let g = genetic_algorithm2(&p, 10, 320, &mut rng);
g.print_visualization();
if m.as_ref().is_none_or(|m| g.score() < m.score()) {
m = Some(g);
}
}
m.unwrap().print_visualization();
}
}
Ok(())
}

View file

@ -1,7 +0,0 @@
pub mod aabb;
pub mod block;
pub mod color;
pub mod direction;
pub mod position;
pub mod transformation;
pub mod visualize;