export interface ScoreboardEntry {
teamId: string;
teamName: string;
score: number;
isPlayer: boolean;
}
export interface LayoutConfig {
backgroundColor?: string;
gridWidth?: number;
gridHeight?: number;
showScoreboard?: boolean;
}
export interface LayoutState {
config: LayoutConfig;
scoreboard: ScoreboardEntry[];
gridContent: string;
}
export class Layout {
private state: LayoutState;
constructor(config: LayoutConfig = {}) {
this.state = {
config: {
backgroundColor: '#1a1a2e',
gridWidth: 800,
gridHeight: 600,
showScoreboard: true,
...config
},
scoreboard: [],
gridContent: ''
};
}
public setGridContent(content: string): void {
this.state.gridContent = content;
}
public updateScoreboard(entries: ScoreboardEntry[]): void {
this.state.scoreboard = [...entries];
}
public setPlayerTeam(teamId: string): void {
this.state.scoreboard = this.state.scoreboard.map(entry => ({
...entry,
isPlayer: entry.teamId === teamId
}));
}
public render(): string {
const { config } = this.state;
return `
${this.renderScoreboard()}
${this.state.gridContent}
`;
}
private renderScoreboard(): string {
if (!this.state.config.showScoreboard || this.state.scoreboard.length === 0) {
return '';
}
const scoreboardEntries = this.state.scoreboard
.sort((a, b) => b.score - a.score)
.map(entry => this.renderScoreboardEntry(entry))
.join('');
return `
Scoreboard
${scoreboardEntries}
`;
}
private renderScoreboardEntry(entry: ScoreboardEntry): string {
const isPlayerStyle = entry.isPlayer
? 'background-color: rgba(74, 144, 226, 0.3); border-left: 4px solid #4a90e2;'
: 'background-color: rgba(255, 255, 255, 0.05);';
return `
${this.escapeHtml(entry.teamName)}
${entry.score}
`;
}
private escapeHtml(text: string): string {
return text
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
public getState(): Readonly {
return { ...this.state };
}
public updateConfig(updates: Partial): void {
this.state.config = { ...this.state.config, ...updates };
}
}
export function createLayout(config?: LayoutConfig): Layout {
return new Layout(config);
}
export function renderCenteredGrid(content: string, width = 800, height = 600): string {
const layout = createLayout({ gridWidth: width, gridHeight: height });
layout.setGridContent(content);
return layout.render();
}
/** @internal Phoenix VCS traceability — do not remove. */
export const _phoenix = {
iu_id: '9a35a9f5ebc71f65e83ff408274437068be7102b862e2935ac1476754d238566',
name: 'Layout',
risk_tier: 'low',
canon_ids: [2 as const],
} as const;