2025-04-07 15:05:42 -06:00

268 lines
9.1 KiB
JavaScript

class WompumGrid {
constructor(element) {
this.gridElement = element;
this.gridSize = {
columns: parseInt(element.dataset.columns) || 7,
rows: parseInt(element.dataset.rows) || 5
};
// Set grid template columns based on data attribute or default
this.gridElement.style.gridTemplateColumns = `repeat(${this.gridSize.columns}, 1fr)`;
// Initialize color calculator
this.colorCalculator = new ColorCalculator();
// Generate sigil from text content if provided
const text = element.dataset.text || '';
this.sigil = Sigil.generate(text);
this.gridElement.dataset.sigil = JSON.stringify(this.sigil);
}
// Get sigil digit for a cell based on its position
getSigilDigit(position) {
if (!this.sigil || !this.sigil.length) return 0;
return this.sigil[position % this.sigil.length];
}
// Get influences from adjacent cells
getInfluences(column, row) {
const influences = [];
// Check adjacent cells (up, down, left, right)
const adjacentPositions = [
[column, row - 1], // up
[column, row + 1], // down
[column - 1, row], // left
[column + 1, row] // right
];
for (const [adjCol, adjRow] of adjacentPositions) {
if (adjCol >= 0 && adjCol < this.gridSize.columns &&
adjRow >= 0 && adjRow < this.gridSize.rows) {
const cell = this.gridElement.querySelector(
`[data-column="${adjCol}"][data-row="${adjRow}"]`
);
if (cell && cell.dataset.sigilDigit) {
influences.push(parseInt(cell.dataset.sigilDigit));
}
}
}
return influences;
}
// Create basic grid cells
createGrid() {
const totalCells = this.gridSize.columns * this.gridSize.rows;
for (let i = 0; i < totalCells; i++) {
const cell = document.createElement('div');
const column = i % this.gridSize.columns;
const row = Math.floor(i / this.gridSize.columns);
cell.className = 'wompum-cell';
cell.setAttribute('data-cell-index', i);
cell.setAttribute('data-column', column);
cell.setAttribute('data-row', row);
// Set sigil digit based on cell position
const sigilDigit = this.getSigilDigit(i);
cell.setAttribute('data-sigil-digit', sigilDigit);
this.gridElement.appendChild(cell);
}
}
applyMetadataDesign() {
const cells = this.gridElement.querySelectorAll('.wompum-cell');
cells.forEach(cell => {
const column = parseInt(cell.dataset.column);
const row = parseInt(cell.dataset.row);
const sigilDigit = parseInt(cell.dataset.sigilDigit);
// Get influences from adjacent cells
const influences = this.getInfluences(column, row);
// Calculate and apply color
const color = this.colorCalculator.getColor(sigilDigit, influences);
cell.style.backgroundColor = color;
});
}
init() {
if (!this.gridElement) return;
this.createGrid();
this.applyMetadataDesign();
}
}
class ArticleGrid extends WompumGrid {
constructor(element, metadata) {
super(element);
this.metadata = metadata;
// Generate sigils for each metadata component
this.sigils = {
narrator: Sigil.generate(metadata.narrator),
subject: Sigil.generate(metadata.subject),
facilitator: Sigil.generate(metadata.facilitator)
};
// Store sigils as data attributes
Object.entries(this.sigils).forEach(([key, value]) => {
this.gridElement.dataset[`${key}Sigil`] = JSON.stringify(value);
});
}
getSigilDigit(position, section) {
const sigil = this.sigils[section];
if (!sigil || !sigil.length) return 0;
return sigil[position % sigil.length];
}
createGrid() {
const totalCells = this.gridSize.columns * this.gridSize.rows;
const narratorColumns = 2;
const facilitatorColumns = 2;
for (let i = 0; i < totalCells; i++) {
const cell = document.createElement('div');
const column = i % this.gridSize.columns;
const row = Math.floor(i / this.gridSize.columns);
// Determine section based on column position
let section;
if (column < narratorColumns) section = 'narrator';
else if (column >= this.gridSize.columns - facilitatorColumns) section = 'facilitator';
else section = 'subject';
cell.className = 'wompum-cell';
cell.setAttribute('data-cell-index', i);
cell.setAttribute('data-section', section);
cell.setAttribute('data-column', column);
cell.setAttribute('data-row', row);
// Set sigil digit based on section and position
const sigilDigit = this.getSigilDigit(row, section);
cell.setAttribute('data-sigil-digit', sigilDigit);
this.gridElement.appendChild(cell);
}
}
}
class RadialWompumGrid {
constructor(element, size = 10) {
this.element = element; // Remove .parentElement
this.segments = size;
this.colorCalculator = new ColorCalculator();
this.sigil = Sigil.generate(this.element.dataset.text || '');
}
createSegment(index) {
const angle = (360 / this.segments);
// Add a small gap by reducing the arc angle
const gap = 2; // degrees of gap
const startAngle = (index * angle) + (gap / 2);
const endAngle = ((index + 1) * angle) - (gap / 2);
const outerRadius = 50;
const innerRadius = 0;
const start = this.polarToCartesian(startAngle, outerRadius);
const end = this.polarToCartesian(endAngle, outerRadius);
const innerStart = this.polarToCartesian(startAngle, innerRadius);
const innerEnd = this.polarToCartesian(endAngle, innerRadius);
const largeArcFlag = (angle - gap) > 180 ? 1 : 0;
const d = [
`M ${start.x} ${start.y}`,
`A ${outerRadius} ${outerRadius} 0 ${largeArcFlag} 1 ${end.x} ${end.y}`,
`L ${innerEnd.x} ${innerEnd.y}`,
`A ${innerRadius} ${innerRadius} 0 ${largeArcFlag} 0 ${innerStart.x} ${innerStart.y}`,
'Z'
].join(' ');
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
path.setAttribute('d', d);
const sigilDigit = this.getSigilDigit(index);
// Pass empty array for influences since we don't need adjacent segments
const color = this.colorCalculator.getColor(sigilDigit, []);
path.setAttribute('fill', color);
return path;
}
polarToCartesian(angle, radius) {
const radian = (angle - 90) * Math.PI / 180.0;
return {
x: 50 + (radius * Math.cos(radian)),
y: 50 + (radius * Math.sin(radian))
};
}
getSigilDigit(position) {
if (!this.sigil || !this.sigil.length) return 0;
return this.sigil[position % this.sigil.length];
}
getInfluences(index) {
const prev = (index - 1 + this.segments) % this.segments;
const next = (index + 1) % this.segments;
return [
this.getSigilDigit(prev),
this.getSigilDigit(next)
];
}
createSVG() {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.setAttribute('viewBox', '0 0 100 100');
svg.setAttribute('class', 'wompum-radial-grid');
for (let i = 0; i < this.segments; i++) {
svg.appendChild(this.createSegment(i));
}
return svg;
}
init() {
if (!this.sigil || !this.sigil.length) {
console.error('No sigil generated from text:', this.element.getAttribute('data-text'));
return;
}
const svg = this.createSVG();
this.element.insertBefore(svg, this.element.firstChild);
}
}
// Initialize grids
document.addEventListener('DOMContentLoaded', () => {
// Initialize basic grids
document.querySelectorAll('.wompum-grid').forEach(element => {
const grid = new WompumGrid(element);
grid.init();
});
// Initialize article grids
document.querySelectorAll('.wompum-article-grid').forEach(element => {
let metadata = {};
try {
metadata = JSON.parse(element.dataset.metadata || '{}');
} catch (e) {
console.error('Error parsing metadata for article grid:', e);
}
const grid = new ArticleGrid(element, metadata);
grid.init();
});
// Initialize radial grids for profile images
document.querySelectorAll('.narrator__container').forEach(element => {
const grid = new RadialWompumGrid(element);
grid.init();
});
});