Refactor into different crates
This commit is contained in:
parent
94473c64e0
commit
dfdeae5638
82 changed files with 624 additions and 647 deletions
592
Cargo.lock
generated
592
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
33
Cargo.toml
33
Cargo.toml
|
|
@ -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"
|
|
||||||
|
|
|
||||||
11
factorio-blueprint-generator/Cargo.toml
Normal file
11
factorio-blueprint-generator/Cargo.toml
Normal 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"] }
|
||||||
|
|
@ -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![
|
||||||
10
factorio-blueprint-generator/src/bin/balancer_blueprint.rs
Normal file
10
factorio-blueprint-generator/src/bin/balancer_blueprint.rs
Normal 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()));
|
||||||
|
}
|
||||||
|
|
@ -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())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
3
factorio-blueprint-generator/src/lib.rs
Normal file
3
factorio-blueprint-generator/src/lib.rs
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod balancer;
|
||||||
|
pub mod station;
|
||||||
|
pub mod train;
|
||||||
|
|
@ -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![
|
||||||
"fast-transport-belt".to_owned(),
|
BlueprintEntity::builder(
|
||||||
0,
|
"fast-transport-belt".to_owned(),
|
||||||
BlueprintPosition::new(3.5, -1.5),
|
0,
|
||||||
)
|
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![
|
||||||
"fast-transport-belt".to_owned(),
|
BlueprintEntity::builder(
|
||||||
0,
|
"fast-transport-belt".to_owned(),
|
||||||
BlueprintPosition::new(3.5, -3.5),
|
0,
|
||||||
)
|
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![
|
||||||
"express-transport-belt".to_owned(),
|
BlueprintEntity::builder(
|
||||||
0,
|
"express-transport-belt".to_owned(),
|
||||||
BlueprintPosition::new(3.5, -3.5),
|
0,
|
||||||
)
|
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;
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{
|
use factorio_blueprint::{
|
||||||
Blueprint, BlueprintEntity, BlueprintInventoryLocation, BlueprintItemID, BlueprintItemRequest,
|
Blueprint, BlueprintEntity, BlueprintInventoryLocation, BlueprintItemID, BlueprintItemRequest,
|
||||||
BlueprintPosition, BlueprintStockConnection,
|
BlueprintPosition, BlueprintStockConnection,
|
||||||
};
|
};
|
||||||
13
factorio-blueprint/Cargo.toml
Normal file
13
factorio-blueprint/Cargo.toml
Normal 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"
|
||||||
1
factorio-blueprint/blueprints/chests.bp
Normal file
1
factorio-blueprint/blueprints/chests.bp
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0eNqVkN0OgjAMRt+l14XwVw28ijFmYKNNYCAbRkL27o55oVET42Wbfue0XaBuJx5G0RaqBaTptYFqt4CRk1bt2tOqY6jAWOY2as5sLDgE0Ue+QZU6/DGLcJlUK3b2fR6keQlnbo/A2ooVflhDMR/01NU8ejp+Jw698Zler0rPIaKYELwhKmJyH0aEWnnaNlmXfVNkfysoKAIxT9YLxHLn889HIlx5NCFMm6wsypKooKzMU+fu/rR3Gg==
|
||||||
1
factorio-blueprint/blueprints/train-signals-param.bp
Normal file
1
factorio-blueprint/blueprints/train-signals-param.bp
Normal 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=
|
||||||
1
factorio-blueprint/blueprints/train-signals.bp
Normal file
1
factorio-blueprint/blueprints/train-signals.bp
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
0eNrFlM9unDAQxt9lziZaYIHAoU/QY2+rFeLPbGPV2JY9bLNa8e4ZA9msIppWOTRCQuOx/fM33xiu0KoRrZOaoLqC7Iz2UB2u4OVP3aiQ082AUEGPnezRRZ0ZWqkbMg4mAVL3+AxVPImNLeQaqSNPxt4tTaajANQkSeJy1Dy41HocWnTMEhv7BVjjeYvRgc+YPOV1F6iiMmU2yyZnVN3iU3OWLI0XedR9TaaeKVCdGuVRLMw6MC329Ztkuthw5Fk6Gjlz07CsiH6ECjzSQvO1koNkx8iNr8w19+/I7zAFJjVLVQDBw3deJOID+//syePjQ8bsXjrslvk42TZpxdY8188oH7L3I27QSTp/X9gqSTqjI6saQlhawLWEa5TsdrvQZDOSHen9dfq7K4FlLyxp1FSfnBlqqRm0tnA6TtOGU+knnSq+0qmYnQrjwTZuFlrBN/jv1u1voAF7OQ4RKjbDyS6yRuGmeQ/Zal/O9m0gsxuyHdWviL8OdISbjdi9soqNS7uBzt/KJkQVdU/o6UORM3iDVHy+7qIMSG7Ub1Yb2nSIRSwSkR7FIeEoFfEcpeHhiMdiP+f4LYo1yjjKOMrXHPMk4RBcu/2UBZzR+VlEliflviyzbJ8lZRpP0wudqOug
|
||||||
59
factorio-blueprint/src/belt.rs
Normal file
59
factorio-blueprint/src/belt.rs
Normal 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))
|
||||||
|
}
|
||||||
|
|
@ -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)]
|
||||||
|
|
@ -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');
|
||||||
|
|
@ -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
16
factorio-core/Cargo.toml
Normal 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"
|
||||||
|
|
@ -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,
|
||||||
|
|
@ -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) {
|
||||||
31
factorio-pathfinding/Cargo.toml
Normal file
31
factorio-pathfinding/Cargo.toml
Normal 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"
|
||||||
|
|
@ -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) => {
|
||||||
|
|
@ -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 {
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
@ -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>()
|
||||||
|
|
@ -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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -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)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -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() {
|
||||||
|
|
@ -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)]
|
||||||
98
factorio-pathfinding/src/bin/layout.rs
Normal file
98
factorio-pathfinding/src/bin/layout.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
5
factorio-pathfinding/src/lib.rs
Normal file
5
factorio-pathfinding/src/lib.rs
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
pub mod belt_finding;
|
||||||
|
pub mod graph;
|
||||||
|
pub mod layout;
|
||||||
|
pub mod misc;
|
||||||
|
pub mod priority_queue;
|
||||||
|
|
@ -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())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -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(())
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue