Reference implementation for the Phoenix Architecture. Work in progress. aicoding.leaflet.pub/
ai coding crazy
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 178 lines 4.7 kB view raw
1export interface ScoreboardEntry { 2 teamId: string; 3 teamName: string; 4 score: number; 5 isPlayer: boolean; 6} 7 8export interface LayoutConfig { 9 backgroundColor?: string; 10 gridWidth?: number; 11 gridHeight?: number; 12 showScoreboard?: boolean; 13} 14 15export interface LayoutState { 16 config: LayoutConfig; 17 scoreboard: ScoreboardEntry[]; 18 gridContent: string; 19} 20 21export class Layout { 22 private state: LayoutState; 23 24 constructor(config: LayoutConfig = {}) { 25 this.state = { 26 config: { 27 backgroundColor: '#1a1a2e', 28 gridWidth: 800, 29 gridHeight: 600, 30 showScoreboard: true, 31 ...config 32 }, 33 scoreboard: [], 34 gridContent: '' 35 }; 36 } 37 38 public setGridContent(content: string): void { 39 this.state.gridContent = content; 40 } 41 42 public updateScoreboard(entries: ScoreboardEntry[]): void { 43 this.state.scoreboard = [...entries]; 44 } 45 46 public setPlayerTeam(teamId: string): void { 47 this.state.scoreboard = this.state.scoreboard.map(entry => ({ 48 ...entry, 49 isPlayer: entry.teamId === teamId 50 })); 51 } 52 53 public render(): string { 54 const { config } = this.state; 55 56 return ` 57 <div class="layout-container" style=" 58 background-color: ${config.backgroundColor}; 59 min-height: 100vh; 60 display: flex; 61 flex-direction: column; 62 align-items: center; 63 justify-content: center; 64 padding: 20px; 65 box-sizing: border-box; 66 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; 67 "> 68 ${this.renderScoreboard()} 69 <div class="grid-container" style=" 70 width: ${config.gridWidth}px; 71 height: ${config.gridHeight}px; 72 border: 2px solid #333; 73 border-radius: 8px; 74 background-color: rgba(255, 255, 255, 0.05); 75 display: flex; 76 align-items: center; 77 justify-content: center; 78 margin: 20px 0; 79 "> 80 ${this.state.gridContent} 81 </div> 82 </div> 83 `; 84 } 85 86 private renderScoreboard(): string { 87 if (!this.state.config.showScoreboard || this.state.scoreboard.length === 0) { 88 return ''; 89 } 90 91 const scoreboardEntries = this.state.scoreboard 92 .sort((a, b) => b.score - a.score) 93 .map(entry => this.renderScoreboardEntry(entry)) 94 .join(''); 95 96 return ` 97 <div class="scoreboard" style=" 98 background-color: rgba(255, 255, 255, 0.1); 99 border-radius: 8px; 100 padding: 16px; 101 margin-bottom: 20px; 102 min-width: 300px; 103 "> 104 <h3 style=" 105 color: #fff; 106 margin: 0 0 12px 0; 107 font-size: 18px; 108 text-align: center; 109 ">Scoreboard</h3> 110 <div class="scoreboard-entries"> 111 ${scoreboardEntries} 112 </div> 113 </div> 114 `; 115 } 116 117 private renderScoreboardEntry(entry: ScoreboardEntry): string { 118 const isPlayerStyle = entry.isPlayer 119 ? 'background-color: rgba(74, 144, 226, 0.3); border-left: 4px solid #4a90e2;' 120 : 'background-color: rgba(255, 255, 255, 0.05);'; 121 122 return ` 123 <div class="scoreboard-entry" style=" 124 ${isPlayerStyle} 125 padding: 8px 12px; 126 margin: 4px 0; 127 border-radius: 4px; 128 display: flex; 129 justify-content: space-between; 130 align-items: center; 131 "> 132 <span style=" 133 color: ${entry.isPlayer ? '#4a90e2' : '#fff'}; 134 font-weight: ${entry.isPlayer ? 'bold' : 'normal'}; 135 ">${this.escapeHtml(entry.teamName)}</span> 136 <span style=" 137 color: ${entry.isPlayer ? '#4a90e2' : '#ccc'}; 138 font-weight: bold; 139 ">${entry.score}</span> 140 </div> 141 `; 142 } 143 144 private escapeHtml(text: string): string { 145 return text 146 .replace(/&/g, '&amp;') 147 .replace(/</g, '&lt;') 148 .replace(/>/g, '&gt;') 149 .replace(/"/g, '&quot;') 150 .replace(/'/g, '&#39;'); 151 } 152 153 public getState(): Readonly<LayoutState> { 154 return { ...this.state }; 155 } 156 157 public updateConfig(updates: Partial<LayoutConfig>): void { 158 this.state.config = { ...this.state.config, ...updates }; 159 } 160} 161 162export function createLayout(config?: LayoutConfig): Layout { 163 return new Layout(config); 164} 165 166export function renderCenteredGrid(content: string, width = 800, height = 600): string { 167 const layout = createLayout({ gridWidth: width, gridHeight: height }); 168 layout.setGridContent(content); 169 return layout.render(); 170} 171 172/** @internal Phoenix VCS traceability — do not remove. */ 173export const _phoenix = { 174 iu_id: '9a35a9f5ebc71f65e83ff408274437068be7102b862e2935ac1476754d238566', 175 name: 'Layout', 176 risk_tier: 'low', 177 canon_ids: [2 as const], 178} as const;