use std::fmt::Write;
use crate::{
MatrixCoordinate, ROW_MATRIX_SIZE, RowLabelConvention, RowMatrix, RowMatrixCell,
RowMatrixEdgeLabels, RowOperation, ToneRow,
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RowMatrixData {
source: ToneRow,
convention: RowLabelConvention,
cells: Vec<RowMatrixCell>,
row_operations: [RowOperation; ROW_MATRIX_SIZE],
column_operations: [RowOperation; ROW_MATRIX_SIZE],
edge_labels: RowMatrixEdgeLabels,
}
impl RowMatrixData {
pub const fn source(&self) -> &ToneRow {
&self.source
}
pub const fn convention(&self) -> RowLabelConvention {
self.convention
}
pub fn cells(&self) -> &[RowMatrixCell] {
&self.cells
}
pub fn cell(&self, coordinate: MatrixCoordinate) -> &RowMatrixCell {
&self.cells[coordinate.row() * ROW_MATRIX_SIZE + coordinate.column()]
}
pub const fn row_operations(&self) -> &[RowOperation; ROW_MATRIX_SIZE] {
&self.row_operations
}
pub const fn column_operations(&self) -> &[RowOperation; ROW_MATRIX_SIZE] {
&self.column_operations
}
pub const fn edge_labels(&self) -> &RowMatrixEdgeLabels {
&self.edge_labels
}
}
impl RowMatrix {
pub fn render_data(&self) -> RowMatrixData {
let cells = (0..ROW_MATRIX_SIZE)
.flat_map(|row| {
(0..ROW_MATRIX_SIZE).map(move |column| {
let coordinate = MatrixCoordinate::new(row, column)
.expect("fixed matrix iteration always yields a valid coordinate");
self.cell(coordinate)
})
})
.collect();
let row_operations = std::array::from_fn(|row| {
self.row_operation(row)
.expect("fixed matrix iteration always yields a row operation")
});
let column_operations = std::array::from_fn(|column| {
self.column_operation(column)
.expect("fixed matrix iteration always yields a column operation")
});
RowMatrixData {
source: self.source().clone(),
convention: self.convention(),
cells,
row_operations,
column_operations,
edge_labels: *self.edge_labels(),
}
}
pub fn render_ascii(&self) -> String {
let data = self.render_data();
let mut output = String::new();
writeln!(output, "label-convention: {}", data.convention().as_str())
.expect("writing to a String cannot fail");
write!(output, "source:").expect("writing to a String cannot fail");
for class in data.source().classes() {
write!(output, " {:>2}", class.value()).expect("writing to a String cannot fail");
}
output.push('\n');
output.push_str(" ");
for label in data.edge_labels().top() {
write!(output, " {:>4}", label).expect("writing to a String cannot fail");
}
output.push('\n');
for row in 0..ROW_MATRIX_SIZE {
write!(output, "{:>4} |", data.edge_labels().left()[row])
.expect("writing to a String cannot fail");
for column in 0..ROW_MATRIX_SIZE {
let coordinate = MatrixCoordinate::new(row, column)
.expect("fixed matrix iteration always yields a valid coordinate");
write!(output, " {:>4}", data.cell(coordinate).class().value())
.expect("writing to a String cannot fail");
}
writeln!(output, " | {:<4}", data.edge_labels().right()[row])
.expect("writing to a String cannot fail");
}
output.push_str(" ");
for label in data.edge_labels().bottom() {
write!(output, " {:>4}", label).expect("writing to a String cannot fail");
}
output.push('\n');
output
}
}