1use std::fs;
2use std::fs::File;
3use std::io::{BufReader, BufWriter};
4use std::path::Path;
5
6use crate::EPOCH;
7use log::{Level, LevelFilter, info, log};
8use serde::Serialize;
9use svg::Document;
10
11use anyhow::{Context, Result};
12use jagua_rs::probs::bpp::io::ext_repr::ExtBPInstance;
13use jagua_rs::probs::spp::io::ext_repr::ExtSPInstance;
14
15pub mod cli;
16pub mod output;
17
18pub fn read_spp_instance(path: &Path) -> Result<ExtSPInstance> {
19 let file = File::open(path).context("could not open instance file")?;
20 serde_json::from_reader(BufReader::new(file))
21 .context("not a valid strip packing instance (ExtSPInstance)")
22}
23
24pub fn read_bpp_instance(path: &Path) -> Result<ExtBPInstance> {
25 let file = File::open(path).context("could not open instance file")?;
26 serde_json::from_reader(BufReader::new(file))
27 .context("not a valid bin packing instance (ExtBPInstance)")
28}
29
30pub fn write_json(json: &impl Serialize, path: &Path) -> Result<()> {
31 let file = File::create(path)?;
32 let writer = BufWriter::new(file);
33
34 serde_json::to_writer_pretty(writer, &json)?;
35
36 info!(
37 "Solution JSON written to file://{}",
38 fs::canonicalize(path)?.to_str().unwrap()
39 );
40 Ok(())
41}
42
43pub fn write_svg(document: &Document, path: &Path) -> Result<()> {
44 svg::save(path, document)?;
45 info!(
46 "Solution SVG written to file://{}",
47 fs::canonicalize(path)
48 .expect("could not canonicalize path")
49 .to_str()
50 .unwrap()
51 );
52 Ok(())
53}
54
55pub fn init_logger(level_filter: LevelFilter) -> Result<()> {
56 fern::Dispatch::new()
57 .format(|out, message, record| {
59 let handle = std::thread::current();
60 let thread_name = handle.name().unwrap_or("-");
61
62 let duration = EPOCH.elapsed();
63 let sec = duration.as_secs() % 60;
64 let min = (duration.as_secs() / 60) % 60;
65 let hours = (duration.as_secs() / 60) / 60;
66
67 let prefix = format!(
68 "[{}] [{:0>2}:{:0>2}:{:0>2}] <{}>",
69 record.level(),
70 hours,
71 min,
72 sec,
73 thread_name,
74 );
75
76 out.finish(format_args!("{prefix:<27}{message}"))
77 })
78 .level(level_filter)
80 .chain(std::io::stdout())
81 .apply()?;
82 log!(Level::Info, "Epoch: {}", jiff::Timestamp::now());
83 Ok(())
84}