diff --git a/client/src/views/Leaderboard.vue b/client/src/views/Leaderboard.vue index 1cfb226..cfaa30c 100644 --- a/client/src/views/Leaderboard.vue +++ b/client/src/views/Leaderboard.vue @@ -1,87 +1,213 @@ diff --git a/client/src/views/games/PlayerStats.vue b/client/src/views/games/PlayerStats.vue index 151b9c4..f12a635 100644 --- a/client/src/views/games/PlayerStats.vue +++ b/client/src/views/games/PlayerStats.vue @@ -53,6 +53,7 @@ Rol Tokens Evento + Round/Game Mensaje Sala @@ -61,6 +62,7 @@ {{ (m.role || '') || '—' }} 🦃 {{ m.pavoTokens ?? 0 }} · 🌽 {{ m.eloteTokens ?? 0 }} · 😶 {{ m.shameTokens }} {{ friendlyKind(m.kind) }} + R{{ m.round || '?' }}/{{ (m.gameVariant || m.variant || '?').replace('G', '') }} {{ m.text }} {{ (m.roomId || '').slice(0,8) }} @@ -218,7 +220,7 @@ function friendlyKind(kind: string): string { .history-loading, .history-empty { font-size:12px; color:#666; padding:6px; text-align:center; } .history-table {} .history-scroll { max-height: 60vh; overflow:auto; border:1px solid #e5e9f0; border-radius:8px; background:#fff; margin: 10px; } -.history-grid { display:grid; grid-template-columns: 82px 36px 160px 110px 2fr 70px; gap:6px; align-items:center; } +.history-grid { display:grid; grid-template-columns: 82px 36px 160px 110px 65px 2fr 70px; gap:6px; align-items:center; } .history-header { position: sticky; top: 0; z-index: 1; background:#667eea; border-bottom:1px solid #e5e9f0; padding:6px; box-shadow: 0 2px 6px rgba(0,0,0,0.08); } .history-header .th { font-size:11px; font-weight:800; color:#ffffff; text-transform: uppercase; } .history-row { padding:6px; border-bottom:1px solid #f1f5f9; } @@ -227,6 +229,7 @@ function friendlyKind(kind: string): string { .history-row .r { font-size:11px; font-weight:700; color:#555; text-transform: uppercase; } .history-row .tok { font-size:12px; color:#334155; } .history-row .k { font-size:12px; font-weight:700; color:#334155; } +.history-row .rnd { font-size:11px; font-weight:600; color:#667eea; font-family: monospace; } .history-row .x { font-size:12px; color:#475569; } .history-row .room { font-family: monospace; font-size:11px; color:#777; text-align:right; } .shame-badge { margin-left:8px; margin-right:0; background:#fee2e2; color:#b91c1c; border:1px solid #fecaca; border-radius:999px; padding:2px 8px; font-weight:800; font-size:12px; display:flex; align-items:center; gap:6px; } diff --git a/server/src/adminApi.ts b/server/src/adminApi.ts index d3d4628..4b8d44c 100644 --- a/server/src/adminApi.ts +++ b/server/src/adminApi.ts @@ -816,18 +816,28 @@ async function sendPlayersActionsUpdate(client?: Response) { const players = uuids.map((uuid: string) => { const history = nameManager.getSystemHistory(uuid) || []; const counts: any = Object.fromEntries(ACTION_EVENTS.map(k => [k, 0])); + const detailedHistory: any[] = []; + for (const entry of history) { const kind = (entry as any)?.kind || ''; if (!ACTION_EVENTS.includes(kind)) continue; if (!isActionMade(kind, (entry as any)?.role)) continue; counts[kind] = (counts[kind] || 0) + 1; + + // Include detailed event info + detailedHistory.push({ + kind, + round: (entry as any)?.round, + gameVariant: (entry as any)?.gameVariant || (entry as any)?.variant + }); } const total = ACTION_EVENTS.reduce((acc, k) => acc + (counts[k] || 0), 0); return { uuid, name: nameManager.getPlayerName(uuid) || null, counts, - total + total, + detailedHistory }; }).filter((p: any) => p.total > 0 || p.name); diff --git a/server/src/rooms/GameRoom.ts b/server/src/rooms/GameRoom.ts index 23405ec..a31a8c7 100644 --- a/server/src/rooms/GameRoom.ts +++ b/server/src/rooms/GameRoom.ts @@ -6,7 +6,7 @@ import { broadcastDashboardUpdate } from "../adminApi"; export class GameRoom extends Room { maxClients = 2; - private systemMessages: { text: string; kind: string; timestamp: number }[] = []; + private systemMessages: { text: string; kind: string; timestamp: number; round?: number; gameVariant?: string }[] = []; getFilterOptions() { // If waiting for shuffled players, report as available regardless of current client count @@ -46,8 +46,14 @@ export class GameRoom extends Room { if (kind !== 'round_advance') { this.recentSystemMessage = { text, kind, timestamp }; } - // Persist in per-room history (keep last 200) - this.systemMessages.push({ text, kind, timestamp }); + // Persist in per-room history (keep last 200) with round and game variant info + this.systemMessages.push({ + text, + kind, + timestamp, + round: this.state.currentRound, + gameVariant: this.state.currentVariant + }); if (this.systemMessages.length > 200) { this.systemMessages.splice(0, this.systemMessages.length - 200); } @@ -78,7 +84,7 @@ export class GameRoom extends Room { kind, text, roomId: this.roomId, - variant: this.state.currentVariant, + gameVariant: this.state.currentVariant, round: this.state.currentRound, role: (player as any)?.role || '', pavoTokens: (player as any)?.pavoTokens || 0, diff --git a/server/src/utils/nameManager.ts b/server/src/utils/nameManager.ts index 768800a..aad017b 100644 --- a/server/src/utils/nameManager.ts +++ b/server/src/utils/nameManager.ts @@ -9,6 +9,7 @@ export class NameManager { text: string; roomId?: string; variant?: string; + gameVariant?: string; round?: number; role?: 'P1' | 'P2' | ''; pavoTokens?: number; @@ -174,7 +175,7 @@ export class NameManager { // Per-UUID system message history (as seen while connected) appendSystemMessage(uuid: string, entry: { timestamp: number; kind: string; text: string; - roomId?: string; variant?: string; round?: number; + roomId?: string; variant?: string; gameVariant?: string; round?: number; role?: 'P1'|'P2'|''; pavoTokens?: number; eloteTokens?: number; shameTokens?: number; }): void { if (!uuid) return; @@ -184,7 +185,8 @@ export class NameManager { kind: (entry.kind || '').toString(), text: (entry.text || '').toString(), roomId: entry.roomId, - variant: entry.variant, + variant: entry.variant || entry.gameVariant, + gameVariant: entry.gameVariant || entry.variant, round: entry.round, role: entry.role || '', pavoTokens: Number(entry.pavoTokens ?? 0), @@ -197,7 +199,7 @@ export class NameManager { getSystemHistory(uuid: string): { timestamp: number; kind: string; text: string; - roomId?: string; variant?: string; round?: number; + roomId?: string; variant?: string; gameVariant?: string; round?: number; role?: 'P1'|'P2'|''; pavoTokens?: number; eloteTokens?: number; shameTokens?: number; }[] { return [...(this.uuidToSystemHistory.get(uuid) || [])];