init wompum header image

This commit is contained in:
Drew
2025-03-06 22:09:53 -07:00
parent 0be059b269
commit 1a7f4521f5
11 changed files with 358 additions and 15 deletions

30
static/css/wompum.css Normal file
View File

@ -0,0 +1,30 @@
.wompum-container {
width: 100%;
margin: 0 auto;
}
.wompum-grid {
display: grid;
gap: 0;
padding: 0;
width: 100%;
}
.wompum-cell {
width: 100%;
min-height: 30px; /* Minimum height for cells */
background-color: var(--sand-500);
}
/* Create pseudo-random pattern using prime numbers */
.wompum-cell:nth-child(7n+1) {
background-color: var(--sand-100);
}
.wompum-cell:nth-child(5n+2) {
background-color: var(--sand-900);
}
.wompum-cell:nth-child(11n+3) {
background-color: var(--sand-500);
}

View File

@ -0,0 +1,30 @@
class ColorCalculator {
constructor() {
// Available color families from our palette
this.colorFamilies = ['sand', 'pink', 'red', 'rust', 'clay', 'gold', 'moss', 'pine', 'cyan', 'blue'];
// Available shades for each color
this.shades = ['100', '500', '900'];
}
// Get color based on sigil digit and influences
getColor(sigilDigit, influences = []) {
// Map digit 0-9 to color family
const colorFamily = this.colorFamilies[sigilDigit];
// Calculate shade based on influences
const shade = this.calculateShade(influences);
return `var(--${colorFamily}-${shade})`;
}
// Calculate shade based on surrounding influences
calculateShade(influences) {
if (!influences.length) return '500';
// Average the influences and map to one of our three shades
const avg = influences.reduce((sum, val) => sum + val, 0) / influences.length;
if (avg < 3) return '100';
if (avg > 6) return '900';
return '500';
}
}

44
static/js/sigil.js Normal file
View File

@ -0,0 +1,44 @@
class Sigil {
// Convert string to sigil array
static generate(str) {
if (!str) return [];
// Convert to lowercase, remove non-word characters
const cleaned = str.toLowerCase().replace(/[^a-z]/g, '');
// Remove vowels
const noVowels = cleaned.replace(/[aeiou]/g, '');
// Remove duplicate characters
const deduped = [...new Set(noVowels)].join('');
// Convert to ASCII values and get digital roots
return [...deduped].map(char => {
const ascii = char.charCodeAt(0);
return Sigil.getDigitalRoot(ascii);
});
}
// Get digital root of a number (sum digits until single digit)
static getDigitalRoot(num) {
if (num < 10) return num;
return Sigil.getDigitalRoot([...num.toString()].reduce((sum, digit) => sum + parseInt(digit), 0));
}
// Helper to validate and debug sigil generation
static debug(str) {
console.log({
original: str,
lowercase: str.toLowerCase(),
cleaned: str.toLowerCase().replace(/[^a-z]/g, ''),
noVowels: str.toLowerCase().replace(/[^a-z]/g, '').replace(/[aeiou]/g, ''),
deduped: [...new Set(str.toLowerCase().replace(/[^a-z]/g, '').replace(/[aeiou]/g, ''))].join(''),
sigil: Sigil.generate(str)
});
}
}
// Export for use in other files
if (typeof module !== 'undefined' && module.exports) {
module.exports = Sigil;
}

149
static/js/wompum.js Normal file
View File

@ -0,0 +1,149 @@
class WompumGrid {
constructor(element, metadata) {
this.gridElement = element;
this.metadata = metadata;
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)`;
// Generate sigils for each metadata component
this.sigils = {
narrator: Sigil.generate(metadata.narrator),
subject: Sigil.generate(metadata.subject),
facilitator: Sigil.generate(metadata.facilitator)
};
// Initialize color calculator
this.colorCalculator = new ColorCalculator();
// Store sigils as data attributes for future use
this.gridElement.dataset.narratorSigil = JSON.stringify(this.sigils.narrator);
this.gridElement.dataset.subjectSigil = JSON.stringify(this.sigils.subject);
this.gridElement.dataset.facilitatorSigil = JSON.stringify(this.sigils.facilitator);
}
// Get sigil digit for a cell based on its section and position
getSigilDigit(section, position) {
const sigil = this.sigils[section];
if (!sigil || !sigil.length) return 0;
return sigil[position % 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;
}
// Apply metadata-based design to the grid
applyMetadataDesign() {
const cells = this.gridElement.querySelectorAll('.wompum-cell');
cells.forEach(cell => {
const section = cell.dataset.section;
const column = parseInt(cell.dataset.column);
const row = parseInt(cell.dataset.row);
// Get sigil digit for this cell
const sigilDigit = this.getSigilDigit(section, row);
cell.dataset.sigilDigit = 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;
});
}
// Initialize the grid
init() {
if (!this.gridElement) return;
this.createGrid();
this.applyMetadataDesign();
this.setGridAreas();
}
// Define grid areas for each section
setGridAreas() {
const totalColumns = this.gridSize.columns;
const narratorColumns = 2;
const facilitatorColumns = 2;
const subjectColumns = totalColumns - narratorColumns - facilitatorColumns;
this.gridElement.style.gridTemplateAreas = `
"narrator subject facilitator"
`;
// this.gridElement.style.gridTemplateColumns = `${narratorColumns}fr ${subjectColumns}fr ${facilitatorColumns}fr`;
}
// Create the grid cells with position awareness
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);
// Determine which section this cell belongs to
let section;
if (column < 2) section = 'narrator';
else if (column >= this.gridSize.columns - 2) 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);
this.gridElement.appendChild(cell);
}
}
}
// Wait for DOM to be ready
document.addEventListener('DOMContentLoaded', () => {
// Find all grid elements
const gridElements = document.querySelectorAll('.wompum-grid');
// Initialize a grid for each element found
gridElements.forEach(element => {
let metadata = {};
try {
metadata = JSON.parse(element.dataset.metadata || '{}');
} catch (e) {
console.error('Error parsing metadata for grid:', e);
}
const wompum = new WompumGrid(element, metadata);
wompum.init();
});
});