import { Tool } from '../Tool'; import { YjsDocument } from '../../crdt/YjsDocument'; type SeatingTemplate = 'bankett' | 'gala' | 'stehempfang' | 'parlament' | 'klasse'; class SeatingTemplateTool extends Tool { private template: SeatingTemplate = 'bankett'; private tableSpacing: number = 150; // Spacing between tables private chairSpacing: number = 60; // Spacing between chairs constructor(yjsDoc: YjsDocument, template: SeatingTemplate = 'bankett') { super(yjsDoc); this.name = 'SeatingTemplateTool'; this.template = template; } onMouseDown(event: MouseEvent): void { // This tool creates templates at the click position const x = event.clientX; const y = event.clientY; switch (this.template) { case 'bankett': this.createBankettTemplate(x, y); break; case 'gala': this.createGalaTemplate(x, y); break; case 'stehempfang': this.createStehempfangTemplate(x, y); break; case 'parlament': this.createParlamentTemplate(x, y); break; case 'klasse': this.createKlasseTemplate(x, y); break; } } onMouseMove(event: MouseEvent): void { // Preview template at cursor position } onMouseUp(event: MouseEvent): void { // Handle mouse up if needed } onKeyUp(event: KeyboardEvent): void { // Handle key up events if (event.key === 'Escape') { this.reset(); } } reset(): void { // Reset any state if needed } // Create Bankett template (long tables with chairs on both sides) private createBankettTemplate(x: number, y: number): void { const tableWidth = 240; const tableHeight = 100; const chairWidth = 45; const chairHeight = 45; const tablesCount = 3; for (let i = 0; i < tablesCount; i++) { const tableX = x + i * (tableWidth + this.tableSpacing); const tableY = y; // Create table this.yjsDoc.createElement({ id: crypto.randomUUID() + '_table_' + i, type: 'rectangular_table', layerId: 'default', x: tableX, y: tableY, width: tableWidth, height: tableHeight, properties: {} }); // Create chairs on both sides const chairsPerSide = 4; for (let j = 0; j < chairsPerSide; j++) { const positionRatio = (j + 1) / (chairsPerSide + 1); // Top side chairs this.yjsDoc.createElement({ id: crypto.randomUUID() + '_chair_top_' + i + '_' + j, type: 'chair', layerId: 'default', x: tableX + positionRatio * tableWidth - chairWidth / 2, y: tableY - this.chairSpacing - chairHeight, width: chairWidth, height: chairHeight, properties: {} }); // Bottom side chairs this.yjsDoc.createElement({ id: crypto.randomUUID() + '_chair_bottom_' + i + '_' + j, type: 'chair', layerId: 'default', x: tableX + positionRatio * tableWidth - chairWidth / 2, y: tableY + tableHeight + this.chairSpacing, width: chairWidth, height: chairHeight, properties: {} }); } } } // Create Gala template (round tables with chairs around) private createGalaTemplate(x: number, y: number): void { const tableRadius = 50; const tablesPerRow = 3; const tablesRows = 2; for (let i = 0; i < tablesRows; i++) { for (let j = 0; j < tablesPerRow; j++) { const tableX = x + j * (tableRadius * 2 + this.tableSpacing); const tableY = y + i * (tableRadius * 2 + this.tableSpacing); // Create round table this.yjsDoc.createElement({ id: crypto.randomUUID() + '_table_' + i + '_' + j, type: 'round_table', layerId: 'default', x: tableX - tableRadius, y: tableY - tableRadius, width: tableRadius * 2, height: tableRadius * 2, properties: { radius: tableRadius, centerX: tableX, centerY: tableY } }); // Create chairs around table const chairsAround = 8; for (let k = 0; k < chairsAround; k++) { const angle = (2 * Math.PI * k) / chairsAround; const chairX = tableX + (tableRadius + this.chairSpacing) * Math.cos(angle) - 22.5; const chairY = tableY + (tableRadius + this.chairSpacing) * Math.sin(angle) - 22.5; this.yjsDoc.createElement({ id: crypto.randomUUID() + '_chair_' + i + '_' + j + '_' + k, type: 'chair', layerId: 'default', x: chairX, y: chairY, width: 45, height: 45, properties: {} }); } } } } // Create Stehempfang template (no chairs, just tables for drinks/food) private createStehempfangTemplate(x: number, y: number): void { const tableWidth = 120; const tableHeight = 60; const tablesPerRow = 4; const tablesRows = 2; for (let i = 0; i < tablesRows; i++) { for (let j = 0; j < tablesPerRow; j++) { const tableX = x + j * (tableWidth + this.tableSpacing); const tableY = y + i * (tableHeight + this.tableSpacing); // Create table this.yjsDoc.createElement({ id: crypto.randomUUID() + '_table_' + i + '_' + j, type: 'rectangular_table', layerId: 'default', x: tableX, y: tableY, width: tableWidth, height: tableHeight, properties: {} }); } } } // Create Parlament template (U-shape with chairs) private createParlamentTemplate(x: number, y: number): void { const tableWidth = 200; const tableHeight = 60; const chairWidth = 45; const chairHeight = 45; // Create main table (president's table) this.yjsDoc.createElement({ id: crypto.randomUUID() + '_main_table', type: 'rectangular_table', layerId: 'default', x: x + tableWidth / 2, y: y, width: tableWidth, height: tableHeight, properties: {} }); // Create side tables (delegates' tables) const sideTablesCount = 4; for (let i = 0; i < sideTablesCount; i++) { // Left side table this.yjsDoc.createElement({ id: crypto.randomUUID() + '_left_table_' + i, type: 'rectangular_table', layerId: 'default', x: x, y: y + (i + 1) * (tableHeight + this.tableSpacing), width: tableWidth / 2, height: tableHeight, properties: {} }); // Right side table this.yjsDoc.createElement({ id: crypto.randomUUID() + '_right_table_' + i, type: 'rectangular_table', layerId: 'default', x: x + tableWidth + tableWidth / 2, y: y + (i + 1) * (tableHeight + this.tableSpacing), width: tableWidth / 2, height: tableHeight, properties: {} }); // Create chairs for side tables // Left side chairs this.yjsDoc.createElement({ id: crypto.randomUUID() + '_left_chair_' + i, type: 'chair', layerId: 'default', x: x - this.chairSpacing - chairWidth, y: y + (i + 1) * (tableHeight + this.tableSpacing) + tableHeight / 2 - chairHeight / 2, width: chairWidth, height: chairHeight, properties: {} }); // Right side chairs this.yjsDoc.createElement({ id: crypto.randomUUID() + '_right_chair_' + i, type: 'chair', layerId: 'default', x: x + tableWidth + tableWidth / 2 + tableWidth / 2 + this.chairSpacing, y: y + (i + 1) * (tableHeight + this.tableSpacing) + tableHeight / 2 - chairHeight / 2, width: chairWidth, height: chairHeight, properties: {} }); } } // Create Klasse template (U-shape classroom layout open at bottom) private createKlasseTemplate(x: number, y: number): void { const tableWidth = 120; const tableHeight = 60; const chairWidth = 45; const chairHeight = 45; // Create teacher's table this.yjsDoc.createElement({ id: crypto.randomUUID() + '_teacher_table', type: 'rectangular_table', layerId: 'default', x: x + tableWidth, y: y, width: tableWidth, height: tableHeight, properties: {} }); // Create student tables in U-shape (open at bottom) const rows = 4; const cols = 5; for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { // Create U-shape that is open at the bottom // Skip inner tables but keep the bottom row if (i > 0 && i < rows - 1 && j > 0 && j < cols - 1) continue; const tableX = x + j * (tableWidth + this.tableSpacing); const tableY = y + (i + 1) * (tableHeight + this.tableSpacing); // Create table this.yjsDoc.createElement({ id: crypto.randomUUID() + '_student_table_' + i + '_' + j, type: 'rectangular_table', layerId: 'default', x: tableX, y: tableY, width: tableWidth, height: tableHeight, properties: {} }); // Create chair behind each table this.yjsDoc.createElement({ id: crypto.randomUUID() + '_student_chair_' + i + '_' + j, type: 'chair', layerId: 'default', x: tableX + tableWidth / 2 - chairWidth / 2, y: tableY + tableHeight + this.chairSpacing, width: chairWidth, height: chairHeight, properties: {} }); } } } // Set template setTemplate(template: SeatingTemplate): void { this.template = template; } // Set table spacing setTableSpacing(spacing: number): void { this.tableSpacing = spacing; } // Set chair spacing setChairSpacing(spacing: number): void { this.chairSpacing = spacing; } } export { SeatingTemplateTool };