#[allow(unused_imports)]
use crate::mwpf::shim::prelude::*;
use super::interface::*;
use crate::mwpf::util::*;
use prettytable::format::TableFormat;
use prettytable::*;
#[derive(Clone)]
pub struct VizTable {
pub title: Row,
pub rows: Vec<Row>,
pub edges: Vec<EdgeIndex>,
}
impl VizTable {
pub fn force_single_column(long_str: &str) -> String {
long_str
.chars()
.enumerate()
.flat_map(|(idx, c)| if idx == 0 { vec![c] } else { vec!['\n', c] })
.collect()
}
}
pub static DEFAULT_TABLE_FORMAT: std::sync::LazyLock<TableFormat> = std::sync::LazyLock::new(|| {
let mut format = TableFormat::new();
format.padding(0, 0);
format.column_separator('\u{250A}');
format.borders('\u{250A}');
use format::LinePosition::*;
let separators = [
(Intern, ['\u{2500}', '\u{253C}', '\u{251C}', '\u{2524}']),
(Top, ['\u{2500}', '\u{252C}', '\u{250C}', '\u{2510}']),
(Bottom, ['\u{2500}', '\u{2534}', '\u{2514}', '\u{2518}']),
(Title, ['\u{2550}', '\u{256A}', '\u{255E}', '\u{2561}']),
];
for (position, s) in separators {
format.separators(&[position], format::LineSeparator::new(s[0], s[1], s[2], s[3]))
}
format
});
impl<M: MatrixView> From<&mut M> for VizTable {
fn from(matrix: &mut M) -> VizTable {
let mut title = Row::empty();
title.add_cell(Cell::new(""));
let mut edges = vec![];
for column in 0..matrix.columns() {
let var_index = matrix.column_to_var_index(column);
let edge_index = matrix.var_to_edge_index(var_index);
edges.push(edge_index);
let edge_index_str = Self::force_single_column(edge_index.to_string().as_str());
title.add_cell(Cell::new(edge_index_str.as_str()).style_spec("brFm"));
}
title.add_cell(Cell::new(" = "));
let mut rows: Vec<Row> = vec![];
for row in 0..matrix.rows() {
let mut table_row = Row::empty();
table_row.add_cell(Cell::new(row.to_string().as_str()).style_spec("brFb"));
for column in 0..matrix.columns() {
let var_index = matrix.column_to_var_index(column);
table_row.add_cell(Cell::new(if matrix.get_lhs(row, var_index) { "1" } else { " " }));
}
table_row.add_cell(Cell::new(if matrix.get_rhs(row) { " 1 " } else { " " }));
rows.push(table_row);
}
VizTable { title, rows, edges }
}
}
impl From<VizTable> for Table {
fn from(viz_table: VizTable) -> Table {
let mut table = Table::new();
table.set_format(*DEFAULT_TABLE_FORMAT);
table.set_titles(viz_table.title.clone());
for row in viz_table.rows.iter() {
table.add_row(row.clone());
}
table
}
}
impl From<VizTable> for serde_json::Value {
fn from(viz_table: VizTable) -> serde_json::Value {
let mut table_json = vec![];
let mut title_json = vec![];
for cell in viz_table.title.iter() {
title_json.push(cell.get_content());
}
table_json.push(title_json);
for row in viz_table.rows.iter() {
let mut row_json = vec![];
for cell in row {
row_json.push(cell.get_content());
}
table_json.push(row_json);
}
json!(table_json)
}
}
pub trait VizTrait {
fn viz_table(&mut self) -> VizTable;
fn printstd_str(&mut self) -> String {
Table::from(self.viz_table()).to_string().replace("\r", "")
}
fn printstd(&mut self) {
println!("{}", Table::from(self.viz_table()));
}
}
impl VizTrait for VizTable {
fn viz_table(&mut self) -> VizTable {
self.clone()
}
}
impl VizTable {
pub fn snapshot(&self) -> serde_json::Value {
json!({
"version": crate::mwpf::MWPF_VERSION,
"table": serde_json::Value::from(self.clone()),
"edges": self.edges,
})
}
}
#[cfg(test)]
pub mod tests {
use super::super::*;
use crate::mwpf::json;
use crate::mwpf::shim::prelude::serde_json;
#[test]
fn viz_table_1() {
let mut matrix = BasicMatrix::new();
matrix.add_constraint(0, &[1, 4, 16], true);
matrix.add_constraint(1, &[4, 23], false);
matrix.add_constraint(2, &[1, 23], true);
matrix.printstd();
assert_eq!(
matrix.clone().printstd_str(),
"\
┌─┬─┬─┬─┬─┬───┐
┊ ┊1┊4┊1┊2┊ = ┊
┊ ┊ ┊ ┊6┊3┊ ┊
╞═╪═╪═╪═╪═╪═══╡
┊0┊1┊1┊1┊ ┊ 1 ┊
├─┼─┼─┼─┼─┼───┤
┊1┊ ┊1┊ ┊1┊ ┊
├─┼─┼─┼─┼─┼───┤
┊2┊1┊ ┊ ┊1┊ 1 ┊
└─┴─┴─┴─┴─┴───┘
"
);
let mut viz_table = matrix.viz_table();
assert_eq!(
serde_json::Value::from(viz_table.viz_table()),
json!([
["", "1", "4", "1\n6", "2\n3", " = "],
["0", "1", "1", "1", " ", " 1 "],
["1", " ", "1", " ", "1", " "],
["2", "1", " ", " ", "1", " 1 "]
])
)
}
}