94 lines
2.5 KiB
Rust
94 lines
2.5 KiB
Rust
use petgraph::dot::{Dot, Config};
|
|
use petgraph::{Graph, graph::NodeIndex};
|
|
use anyhow::Context;
|
|
use std::{collections::HashMap, str::FromStr};
|
|
use std::env;
|
|
|
|
fn main() -> anyhow::Result<()> {
|
|
let g = include_str!("../assets/combinations.txt").parse::<GraphGen>()?;
|
|
let searched = env::args().nth(1).context("Supply argument for searched element")?;
|
|
let graph = g.create_graph(&searched);
|
|
let dot = Dot::with_config(&graph, &[Config::EdgeNoLabel]);
|
|
println!("{}", dot);
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Debug, Default)]
|
|
struct GraphGen {
|
|
map: HashMap<String, (String, String)>,
|
|
graph: Graph<String, String>,
|
|
}
|
|
|
|
impl GraphGen {
|
|
fn try_parse_comb(&mut self, c: &str) -> anyhow::Result<()> {
|
|
let err = "Failed to Parse combination";
|
|
let mut split = c.splitn(2, '=');
|
|
let name = split.next().context(err)?.trim().to_owned();
|
|
let rest = split.next().context(err)?;
|
|
|
|
let mut split = rest.splitn(2, '+');
|
|
let ing_a = split.next().context(err)?.trim().to_owned();
|
|
let ing_b = split.next().context(err)?.trim().to_owned();
|
|
|
|
self.map.insert(name, (ing_a, ing_b));
|
|
Ok(())
|
|
}
|
|
|
|
fn populate(&mut self, elem: String) {
|
|
let ab = self.map.get(&elem);
|
|
|
|
if !self.graph.node_indices().any(|n| self.graph.node_weight(n).unwrap() == &elem) {
|
|
self.graph.add_node(elem);
|
|
}
|
|
|
|
if let Some((a, b)) = ab {
|
|
let a = a.clone();
|
|
let b = b.clone();
|
|
|
|
self.populate(a);
|
|
self.populate(b);
|
|
}
|
|
}
|
|
|
|
fn link(&mut self) {
|
|
for n in self.graph.node_indices() {
|
|
let w = self.graph.node_weight(n).unwrap();
|
|
if let Some((a, b)) = self.map.get(w) {
|
|
if let Some(i) = self.find_node(a) {
|
|
self.graph.add_edge(i, n, String::new());
|
|
}
|
|
|
|
if let Some(i) = self.find_node(b) {
|
|
self.graph.add_edge(i, n, String::new());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn find_node(&self, w: &str) -> Option<NodeIndex>{
|
|
self.graph.node_indices().find(|g| &self.graph[*g] == w)
|
|
}
|
|
|
|
fn create_graph(mut self, node: &str) -> Graph<String, String> {
|
|
self.populate(node.to_owned());
|
|
self.link();
|
|
self.graph
|
|
}
|
|
}
|
|
|
|
impl FromStr for GraphGen {
|
|
type Err = anyhow::Error;
|
|
|
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
let mut this = Self::default();
|
|
|
|
for l in s.lines() {
|
|
this.try_parse_comb(l)?;
|
|
}
|
|
|
|
Ok(this)
|
|
}
|
|
}
|
|
|