use factorio_core::{beltoptions::Beltspeed, pathfield::PathField, prelude::*}; pub mod belt_finding; pub mod examples; pub mod graph; pub mod misc; pub mod priority_queue; pub struct PathInput<'c, M> { pub connections: &'c [Connection], pub map: M, } pub struct Connection { pub start_pos: Position, pub start_dir: Direction, pub end_pos: Position, pub end_dir: Direction, pub beltspeed: Beltspeed, pub lanes: usize, } pub trait Map { /// Returns true if the position is useable fn get_position(&self, pos: Position) -> bool; /// Returns the relevant area as (pos, size) fn area(&self) -> (Position, Position); } pub trait Pathfinder { fn find_paths(&self, input: PathInput<'_, M>) -> Option>>; } pub struct SinglePathInput<'c, M> { connections: &'c [SingleConnection], map: M, } struct SingleConnection { pub start_pos: Position, pub start_dir: Direction, pub end_pos: Position, pub end_dir: Direction, pub beltspeed: Beltspeed, } trait SinglePathfinder { fn find_paths(&self, input: SinglePathInput<'_, M>) -> Option>>; } impl

Pathfinder for P where P: SinglePathfinder, { fn find_paths(&self, input: PathInput<'_, M>) -> Option>> { let inner_input = input .connections .iter() .flat_map(|c| { (0..c.lanes).map(|i| SingleConnection { start_pos: c .start_pos .in_direction(&c.start_dir.clockwise(), i as PositionType), start_dir: c.start_dir, end_pos: c .end_pos .in_direction(&c.start_dir.clockwise(), i as PositionType), end_dir: c.end_dir, beltspeed: c.beltspeed, }) }) .collect::>(); let inner_result = self.find_paths(SinglePathInput { connections: &inner_input, map: input.map, })?; let mut inner_iterator = inner_result.into_iter(); Some( input .connections .iter() .map(|i| inner_iterator.by_ref().take(i.lanes).flatten().collect()) .collect(), ) } }