import { PropositionalFormula } from '../../../types.js';
import { TruthTableFormatter } from './TruthTableFormatter.js';
/**
* Text renderer for truth tables
* Handles plain text formatting with proper alignment
*/
export class TruthTableTextRenderer {
private formatter: TruthTableFormatter;
constructor() {
this.formatter = new TruthTableFormatter();
}
/**
* Render a truth table as plain text
* @param variables Variable names
* @param formulas Propositional formulas
* @param assignments Variable assignments
* @param results Evaluation results
* @param isArgument Whether this is an argument
* @param isArgumentValid Whether the argument is valid (if applicable)
* @returns Plain text string
*/
render(
variables: string[],
formulas: PropositionalFormula[],
assignments: Map<string, boolean>[],
results: boolean[][],
isArgument: boolean,
isArgumentValid?: boolean
): string {
// Calculate column widths
const colWidths = this.formatter.calculateColumnWidths(variables, formulas, isArgument);
// Build the table
let text = '';
// Header
const { headerLine, separatorLine } = this.buildHeader(variables, formulas, colWidths, isArgument);
text += headerLine + '\n';
text += separatorLine + '\n';
// Body
text += this.buildBody(variables, assignments, results, colWidths, isArgument);
// Footer for arguments
if (isArgument && isArgumentValid !== undefined) {
text += separatorLine + '\n';
text += `ANALYSIS: This argument is ${isArgumentValid ? 'VALID' : 'INVALID'}\n`;
}
return text;
}
private buildHeader(
variables: string[],
formulas: PropositionalFormula[],
colWidths: number[],
isArgument: boolean
): { headerLine: string; separatorLine: string } {
let headerLine = '';
let separatorLine = '';
// Variable headers
variables.forEach((variable, index) => {
headerLine += variable.padEnd(colWidths[index]) + ' | ';
separatorLine += '-'.repeat(colWidths[index]) + '-+-';
});
// Formula headers
formulas.forEach((formula, index) => {
const colIndex = variables.length + index;
const formatted = this.formatter.formatFormula(formula);
headerLine += formatted.padEnd(colWidths[colIndex]) + ' | ';
separatorLine += '-'.repeat(colWidths[colIndex]) + '-+-';
});
// Validity header
if (isArgument) {
const colIndex = variables.length + formulas.length;
headerLine += 'Valid?'.padEnd(colWidths[colIndex]);
separatorLine += '-'.repeat(colWidths[colIndex]);
} else {
// Remove trailing separator
headerLine = headerLine.slice(0, -3);
separatorLine = separatorLine.slice(0, -3);
}
return { headerLine, separatorLine };
}
private buildBody(
variables: string[],
assignments: Map<string, boolean>[],
results: boolean[][],
colWidths: number[],
isArgument: boolean
): string {
let body = '';
assignments.forEach((assignment, rowIndex) => {
let rowLine = '';
// Variable values
variables.forEach((variable, colIndex) => {
const value = assignment.get(variable)!;
rowLine += this.formatter.formatBoolean(value).padEnd(colWidths[colIndex]) + ' | ';
});
// Formula results
const rowResults = results[rowIndex];
rowResults.forEach((result, formulaIndex) => {
const colIndex = variables.length + formulaIndex;
rowLine += this.formatter.formatBoolean(result).padEnd(colWidths[colIndex]) + ' | ';
});
// Validity cell
if (isArgument) {
const allPremisesTrue = rowResults.slice(0, -1).every(result => result);
const conclusionFalse = !rowResults[rowResults.length - 1];
const isCounterexample = allPremisesTrue && conclusionFalse;
const colIndex = variables.length + rowResults.length;
const validityText = this.formatter.formatValidity(!isCounterexample, 'text');
rowLine += validityText.padEnd(colWidths[colIndex]);
} else {
// Remove trailing separator
rowLine = rowLine.slice(0, -3);
}
body += rowLine + '\n';
});
return body;
}
}