diff --git a/client/src/components/EventChart.vue b/client/src/components/EventChart.vue
index 53a24ed..567896e 100644
--- a/client/src/components/EventChart.vue
+++ b/client/src/components/EventChart.vue
@@ -43,7 +43,7 @@
class="bar-fill global shimmer"
:style="{
width: globalBarWidth(eventType) + '%',
- background: eventStyles[eventType]?.gradient || 'linear-gradient(90deg, #94a3b8, #64748b)'
+ background: EVENT_STYLES[eventType]?.gradient || 'linear-gradient(90deg, #94a3b8, #64748b)'
}"
>
-
{{ eventStyles[eventType]?.icon || 'π' }}
+
{{ EVENT_STYLES[eventType]?.icon || 'π' }}
{{ friendlyEventName(eventType) }}
{{ globalValueLabel(eventType) }}
{{ playerValueLabel(eventType) }}
@@ -94,7 +94,7 @@
class="ratio-segment"
:style="{
width: group.percentages[actionIndex] + '%',
- background: eventStyles[action]?.gradient || 'linear-gradient(90deg, #94a3b8, #64748b)'
+ background: EVENT_STYLES[action]?.gradient || 'linear-gradient(90deg, #94a3b8, #64748b)'
}"
>
- {{ eventStyles[action]?.icon || 'π' }}
+ {{ EVENT_STYLES[action]?.icon || 'π' }}
{{ group.labels[actionIndex] }}
{{ group.values[actionIndex] }} ({{ Math.round(group.percentages[actionIndex]) }}%)
@@ -123,12 +123,14 @@
import { ref, computed } from 'vue';
interface Props {
- eventTypes: string[];
- eventStyles: Record
;
- globalEventCounts: Record;
- playerEventCounts: Record;
+ filteredData?: {
+ events: any[];
+ players: any[];
+ metrics: Record;
+ aggregatedCounts: Record;
+ sourceData: string;
+ };
selectedPlayerUuid?: string;
- playerBarGradient: string;
viewMode: 'count' | 'percent' | 'ratio';
loading?: boolean;
filtersCollapsed?: boolean;
@@ -140,15 +142,6 @@ interface Props {
selectedPlayer?: string;
selectedRoom?: string;
};
- groupTotals?: {
- offers: number;
- responses: number;
- force: number;
- shame: number;
- report: number;
- averageScore: number;
- totalPlayers: number;
- };
}
const props = withDefaults(defineProps(), {
@@ -156,51 +149,174 @@ const props = withDefaults(defineProps(), {
loading: false
});
+// Event types and styles
+const EVENTS = [
+ 'p1_propose', 'p1_no_offer',
+ 'p2_snatch', 'p2_accept', 'p2_force', 'p2_no_force', 'p2_reject',
+ 'p1_shame', 'p1_no_shame', 'p1_report', 'p1_no_report'
+];
+
+const METRICS = [
+ 'players_seated', 'score_p1', 'score_p2', 'players_with_shame', 'players_without_shame'
+];
+
+const ALL_CHART_TYPES = [...EVENTS, ...METRICS];
+
+const EVENT_STYLES: Record = {
+ 'p1_propose': { icon: 'β¨', color: '#667eea', gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' },
+ 'p1_no_offer': { icon: 'β', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
+ 'p2_accept': { icon: 'β', color: '#10b981', gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)' },
+ 'p2_reject': { icon: 'β', color: '#f59e0b', gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)' },
+ 'p2_snatch': { icon: 'πΉ', color: '#ef4444', gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)' },
+ 'p2_force': { icon: 'β‘', color: '#667eea', gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' },
+ 'p2_no_force': { icon: 'π«', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
+ 'p1_shame': { icon: 'πΆ', color: '#fbbf24', gradient: 'linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%)' },
+ 'p1_no_shame': { icon: 'π', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
+ 'p1_report': { icon: 'βοΈ', color: '#8b5cf6', gradient: 'linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%)' },
+ 'p1_no_report': { icon: 'π€', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
+ 'players_seated': { icon: 'π₯', color: '#06b6d4', gradient: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)' },
+ 'score_p1': { icon: 'π¦', color: '#16a34a', gradient: 'linear-gradient(135deg, #16a34a 0%, #15803d 100%)' },
+ 'score_p2': { icon: 'π½', color: '#d97706', gradient: 'linear-gradient(135deg, #d97706 0%, #b45309 100%)' },
+ 'players_with_shame': { icon: 'πΆ', color: '#dc2626', gradient: 'linear-gradient(135deg, #dc2626 0%, #b91c1c 100%)' },
+ 'players_without_shame': { icon: 'π₯', color: '#06b6d4', gradient: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)' }
+};
+
const highlighted = ref('');
+// Main data computations
+const eventTypes = computed(() => ALL_CHART_TYPES);
+
+const globalEventCounts = computed(() => {
+ if (!props.filteredData) return {};
+ return {
+ ...props.filteredData.aggregatedCounts,
+ ...props.filteredData.metrics
+ };
+});
+
+const playerEventCounts = computed(() => {
+ if (!props.selectedPlayerUuid || !props.filteredData) return {};
+
+ // Calculate player-specific counts from filtered events
+ const playerCounts: Record = {};
+ EVENTS.forEach(eventType => {
+ playerCounts[eventType] = props.filteredData!.events.filter(
+ (e: any) => e.kind === eventType && e.playerUuid === props.selectedPlayerUuid
+ ).length;
+ });
+
+ // Calculate player-specific metrics
+ const selectedPlayer = props.filteredData.players.find((p: any) => p.uuid === props.selectedPlayerUuid);
+ if (selectedPlayer) {
+ let totalP1Scores = 0;
+ let totalP2Scores = 0;
+ let p1Count = 0;
+ let p2Count = 0;
+ let playersWithShame = selectedPlayer.shameTokens > 0 ? 1 : 0;
+
+ if (selectedPlayer.roomScoreHistory) {
+ selectedPlayer.roomScoreHistory.forEach((roomScore: any) => {
+ roomScore.scores.forEach((score: any) => {
+ if (score.role === 'P1') {
+ totalP1Scores += score.score;
+ p1Count++;
+ } else if (score.role === 'P2') {
+ totalP2Scores += score.score;
+ p2Count++;
+ }
+ });
+ });
+ }
+
+ playerCounts.players_seated = 1;
+ playerCounts.score_p1 = p1Count > 0 ? Math.round((totalP1Scores / p1Count) * 10) / 10 : 0;
+ playerCounts.score_p2 = p2Count > 0 ? Math.round((totalP2Scores / p2Count) * 10) / 10 : 0;
+ playerCounts.players_with_shame = playersWithShame;
+ playerCounts.players_without_shame = 1 - playersWithShame;
+ }
+
+ return playerCounts;
+});
+
+const playerBarGradient = computed(() => '#8b5cf6');
+
+// Group totals computation
+const groupTotals = computed(() => {
+ const counts = globalEventCounts.value;
+ return {
+ offers: (counts.p1_propose || 0) + (counts.p1_no_offer || 0),
+ responses: (counts.p2_accept || 0) + (counts.p2_reject || 0) + (counts.p2_snatch || 0),
+ force: (counts.p2_force || 0) + (counts.p2_no_force || 0),
+ shame: (counts.p1_shame || 0) + (counts.p1_no_shame || 0),
+ report: (counts.p1_report || 0) + (counts.p1_no_report || 0),
+ averageScore: calculateAverageScore(),
+ totalPlayers: counts.players_seated || 0
+ };
+});
+
+function calculateAverageScore(): number {
+ if (!props.filteredData?.players.length) return 0;
+
+ let totalScores = 0;
+ let totalScoreCount = 0;
+
+ props.filteredData.players.forEach((player: any) => {
+ if (player.roomScoreHistory) {
+ player.roomScoreHistory.forEach((roomScore: any) => {
+ roomScore.scores.forEach((score: any) => {
+ totalScores += score.score;
+ totalScoreCount++;
+ });
+ });
+ }
+ });
+
+ return totalScoreCount > 0 ? Math.round((totalScores / totalScoreCount) * 10) / 10 : 0;
+}
+
// Define ratio groups for superposed view
const ratioGroups = computed(() => [
{
name: 'Ofertas',
actions: ['p1_propose', 'p1_no_offer'],
labels: ['Ofrecer', 'No Ofrecer'],
- total: props.groupTotals?.offers || 0
+ total: groupTotals.value.offers
},
{
name: 'Respuestas',
actions: ['p2_accept', 'p2_reject', 'p2_snatch'],
labels: ['Aceptar', 'Rechazar', 'Robar'],
- total: props.groupTotals?.responses || 0
+ total: groupTotals.value.responses
},
{
name: 'Forzar',
actions: ['p2_force', 'p2_no_force'],
labels: ['Forzar', 'No Forzar'],
- total: props.groupTotals?.force || 0
+ total: groupTotals.value.force
},
{
name: 'Avergonzar',
actions: ['p1_shame', 'p1_no_shame'],
labels: ['Asignar', 'No Asignar'],
- total: props.groupTotals?.shame || 0
+ total: groupTotals.value.shame
},
{
name: 'Denunciar',
actions: ['p1_report', 'p1_no_report'],
labels: ['Denunciar', 'No Denunciar'],
- total: props.groupTotals?.report || 0
+ total: groupTotals.value.report
},
{
name: 'Puntaje Promedio',
actions: ['score_p1', 'score_p2'],
labels: ['P1', 'P2'],
- total: props.groupTotals?.averageScore ? props.groupTotals.averageScore.toFixed(1) : '0.0'
+ total: groupTotals.value.averageScore.toFixed(1)
},
{
name: 'Total Jugadores',
actions: ['players_with_shame', 'players_without_shame'],
labels: ['Con vergΓΌenza', 'Sin vergΓΌenza'],
- total: props.groupTotals?.totalPlayers || 0,
+ total: groupTotals.value.totalPlayers,
isCustomRatio: true // Special handling needed
}
]);
@@ -209,8 +325,8 @@ const ratioGroups = computed(() => [
const ratioData = computed(() => {
return ratioGroups.value.map(group => {
const counts = props.selectedPlayerUuid
- ? props.playerEventCounts
- : props.globalEventCounts;
+ ? playerEventCounts.value
+ : globalEventCounts.value;
let values = group.actions.map(action => counts[action] || 0);
@@ -234,55 +350,55 @@ const ratioData = computed(() => {
// Global calculations
const globalMax = computed(() => {
- const vals = props.eventTypes.map(k => props.globalEventCounts[k] || 0);
+ const vals = eventTypes.value.map(k => globalEventCounts.value[k] || 0);
const m = Math.max(0, ...vals);
return m || 1;
});
const globalTotal = computed(() =>
- props.eventTypes.reduce((acc, k) => acc + (props.globalEventCounts[k] || 0), 0) || 1
+ eventTypes.value.reduce((acc, k) => acc + (globalEventCounts.value[k] || 0), 0) || 1
);
function globalBarWidth(eventType: string) {
- const v = props.globalEventCounts[eventType] || 0;
+ const v = globalEventCounts.value[eventType] || 0;
return Math.round((v / (props.viewMode === 'percent' ? globalTotal.value : globalMax.value)) * 100);
}
function globalValueLabel(eventType: string) {
- const v = props.globalEventCounts[eventType] || 0;
+ const v = globalEventCounts.value[eventType] || 0;
return props.viewMode === 'percent' ? `${Math.round((v / globalTotal.value) * 100)}%` : String(v);
}
// Player calculations
const playerMax = computed(() => {
- const vals = props.eventTypes.map(k => props.playerEventCounts[k] || 0);
+ const vals = eventTypes.value.map(k => playerEventCounts.value[k] || 0);
const m = Math.max(0, ...vals);
return m || 1;
});
const playerTotal = computed(() =>
- props.eventTypes.reduce((acc, k) => acc + (props.playerEventCounts[k] || 0), 0) || 1
+ eventTypes.value.reduce((acc, k) => acc + (playerEventCounts.value[k] || 0), 0) || 1
);
function playerBarWidth(eventType: string) {
- const v = props.playerEventCounts[eventType] || 0;
+ const v = playerEventCounts.value[eventType] || 0;
return Math.round((v / (props.viewMode === 'percent' ? playerTotal.value : playerMax.value)) * 100);
}
function playerValueLabel(eventType: string) {
- const v = props.playerEventCounts[eventType] || 0;
+ const v = playerEventCounts.value[eventType] || 0;
return props.viewMode === 'percent' ? `${Math.round((v / playerTotal.value) * 100)}%` : String(v);
}
// Styling helpers
function getEventChipBg(eventType: string): string {
- const style = props.eventStyles[eventType];
+ const style = EVENT_STYLES[eventType];
if (!style) return 'rgba(255,255,255,0.82)';
return `linear-gradient(135deg, ${style.color}15 0%, rgba(255,255,255,0.9) 100%)`;
}
function getEventBorderColor(eventType: string): string {
- const style = props.eventStyles[eventType];
+ const style = EVENT_STYLES[eventType];
if (!style) return 'rgba(229,231,235,0.9)';
return `${style.color}40`;
}
diff --git a/client/src/views/Leaderboard.vue b/client/src/views/Leaderboard.vue
index ac0d923..ecbae27 100644
--- a/client/src/views/Leaderboard.vue
+++ b/client/src/views/Leaderboard.vue
@@ -64,25 +64,12 @@
@@ -104,12 +91,10 @@ import EventFilters from '../components/EventFilters.vue';
import FilterDataViewer from '../components/FilterDataViewer.vue';
import GameLogo from '../components/GameLogo.vue';
import AppCredits from '../components/AppCredits.vue';
-import { useEventFilters } from '../composables/useEventFilters';
const router = useRouter();
const loading = ref(false);
-const eventFilters = useEventFilters();
const filtersCollapsed = ref(false);
// Filter state using new EventFilters approach
@@ -135,263 +120,15 @@ function clearTimeFilter() {
// Handle filtered data from EventFilters component
function onFiltered(data: any) {
filteredData.value = data;
- if (data) {
- // Update global counts from filtered data
- eventFilters.globalEventCounts.value = data.aggregatedCounts || {};
- // Update metrics
- additionalMetrics.value = data.metrics || {};
- // Recompute selected player metrics
- computeSelectedPlayersMetrics();
- }
}
-const EVENTS = [
- 'p1_propose', 'p1_no_offer',
- 'p2_snatch', 'p2_accept', 'p2_force', 'p2_no_force', 'p2_reject',
- 'p1_shame', 'p1_no_shame', 'p1_report', 'p1_no_report'
-];
-// New metric types for additional charts
-const METRICS = [
- 'players_seated', 'score_p1', 'score_p2', 'players_with_shame', 'players_without_shame'
-];
-
-const ALL_CHART_TYPES = [...EVENTS, ...METRICS];
-
-// Event and metric styles matching OfferActions and OfferControls components
-const EVENT_STYLES: Record = {
- // Event types
- 'p1_propose': { icon: 'β¨', color: '#667eea', gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' },
- 'p1_no_offer': { icon: 'β', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
- 'p2_accept': { icon: 'β', color: '#10b981', gradient: 'linear-gradient(135deg, #10b981 0%, #059669 100%)' },
- 'p2_reject': { icon: 'β', color: '#f59e0b', gradient: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)' },
- 'p2_snatch': { icon: 'πΉ', color: '#ef4444', gradient: 'linear-gradient(135deg, #ef4444 0%, #dc2626 100%)' },
- 'p2_force': { icon: 'β‘', color: '#667eea', gradient: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' },
- 'p2_no_force': { icon: 'π«', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
- 'p1_shame': { icon: 'πΆ', color: '#fbbf24', gradient: 'linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%)' },
- 'p1_no_shame': { icon: 'π', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
- 'p1_report': { icon: 'βοΈ', color: '#8b5cf6', gradient: 'linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%)' },
- 'p1_no_report': { icon: 'π€', color: '#6b7280', gradient: 'linear-gradient(135deg, #94a3b8 0%, #64748b 100%)' },
-
- // Metric types
- 'players_seated': { icon: 'π₯', color: '#06b6d4', gradient: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)' },
- 'score_p1': { icon: 'π¦', color: '#16a34a', gradient: 'linear-gradient(135deg, #16a34a 0%, #15803d 100%)' },
- 'score_p2': { icon: 'π½', color: '#d97706', gradient: 'linear-gradient(135deg, #d97706 0%, #b45309 100%)' },
- 'players_with_shame': { icon: 'πΆ', color: '#dc2626', gradient: 'linear-gradient(135deg, #dc2626 0%, #b91c1c 100%)' },
- 'players_without_shame': { icon: 'π₯', color: '#06b6d4', gradient: 'linear-gradient(135deg, #06b6d4 0%, #0891b2 100%)' }
-};
-
-
-// Additional metrics computation
-const additionalMetrics = ref>({
- players_seated: 0,
- score_p1: 0,
- score_p2: 0,
- players_with_shame: 0,
- players_without_shame: 0
-});
-
-const selectedPlayerMetrics = ref>({
- players_seated: 0,
- score_p1: 0,
- score_p2: 0,
- players_with_shame: 0,
- players_without_shame: 0
-});
// Store room score history from players
const allPlayersWithScores = ref([]);
-// Function to check if a score passes the current filters
-function scorePassesFilters(score: any, roomId: string) {
- // Room filter (array): empty means all
- const rf = filterState.value.rooms;
- if (rf.length && !rf.includes(String(roomId))) return false;
- // Round filter (array)
- const rds = filterState.value.rounds;
- if (rds.length && !rds.includes(Number(score.round))) return false;
-
- // Game variant filter (array)
- const gfs = filterState.value.games;
- if (gfs.length && !gfs.includes(String(score.variant))) return false;
-
- return true;
-}
-
-// Function to compute additional metrics from players' score history
-function computeMetricsFromScores() {
- if (!allPlayersWithScores.value.length) return;
-
- let totalP1Scores = 0;
- let totalP2Scores = 0;
- let p1Count = 0;
- let p2Count = 0;
- let playersWithShame = 0;
- let totalPlayersWithNames = 0;
-
- // Get score data from players with room score history
- allPlayersWithScores.value.forEach((player: any) => {
- if (player.name) {
- totalPlayersWithNames++;
-
- // Count players with shame tokens
- if (player.shameTokens && player.shameTokens > 0) {
- playersWithShame++;
- }
-
- // Extract scores from roomScoreHistory if available
- if (player.roomScoreHistory) {
- player.roomScoreHistory.forEach((roomScore: any) => {
- roomScore.scores.forEach((score: any) => {
- // Apply filters to scores
- if (!scorePassesFilters(score, roomScore.roomId)) {
- return;
- }
-
- if (score.role === 'P1') {
- totalP1Scores += score.score;
- p1Count++;
- } else if (score.role === 'P2') {
- totalP2Scores += score.score;
- p2Count++;
- }
- });
- });
- }
- }
- });
-
- const avgP1Score = p1Count > 0 ? totalP1Scores / p1Count : 0;
- const avgP2Score = p2Count > 0 ? totalP2Scores / p2Count : 0;
-
- additionalMetrics.value = {
- players_seated: totalPlayersWithNames,
- score_p1: Math.round(avgP1Score * 10) / 10, // Round to 1 decimal
- score_p2: Math.round(avgP2Score * 10) / 10,
- players_with_shame: playersWithShame,
- players_without_shame: totalPlayersWithNames - playersWithShame
- };
-}
-
-// Function to compute metrics for selected players (multi-select)
-function computeSelectedPlayersMetrics() {
- const uuids = filterState.value.playerUuids;
- if (!uuids.length) {
- selectedPlayerMetrics.value = {
- players_seated: 0,
- score_p1: 0,
- score_p2: 0,
- players_with_shame: 0,
- players_without_shame: 0
- };
- return;
- }
-
- let totalP1Scores = 0;
- let totalP2Scores = 0;
- let p1Count = 0;
- let p2Count = 0;
- let playersWithShame = 0;
-
- uuids.forEach(uuid => {
- const playerData = allPlayersWithScores.value.find(p => p.uuid === uuid);
- if (!playerData) return;
- if (playerData.shameTokens && playerData.shameTokens > 0) playersWithShame++;
- if (playerData.roomScoreHistory) {
- playerData.roomScoreHistory.forEach((roomScore: any) => {
- roomScore.scores.forEach((score: any) => {
- if (!scorePassesFilters(score, roomScore.roomId)) return;
- if (score.role === 'P1') { totalP1Scores += score.score; p1Count++; }
- else if (score.role === 'P2') { totalP2Scores += score.score; p2Count++; }
- });
- });
- }
- });
-
- selectedPlayerMetrics.value = {
- players_seated: uuids.length,
- score_p1: p1Count > 0 ? Math.round((totalP1Scores / p1Count) * 10) / 10 : 0,
- score_p2: p2Count > 0 ? Math.round((totalP2Scores / p2Count) * 10) / 10 : 0,
- players_with_shame: playersWithShame,
- players_without_shame: uuids.length - playersWithShame
- };
-}
-
-// Combined counts for charts (events + metrics)
-const combinedGlobalCounts = computed(() => ({
- ...eventFilters.globalEventCounts.value,
- ...additionalMetrics.value
-}));
-
-const combinedPlayerCounts = computed(() => ({
- ...playerEventCounts.value,
- ...selectedPlayerMetrics.value
-}));
-
-
-// Chart group totals
-const offersTotal = computed(() => {
- const propose = eventFilters.globalEventCounts.value.p1_propose || 0;
- const noOffer = eventFilters.globalEventCounts.value.p1_no_offer || 0;
- return propose + noOffer;
-});
-
-const responsesTotal = computed(() => {
- const accept = eventFilters.globalEventCounts.value.p2_accept || 0;
- const reject = eventFilters.globalEventCounts.value.p2_reject || 0;
- const snatch = eventFilters.globalEventCounts.value.p2_snatch || 0;
- return accept + reject + snatch;
-});
-
-const forceTotal = computed(() => {
- const force = eventFilters.globalEventCounts.value.p2_force || 0;
- const noForce = eventFilters.globalEventCounts.value.p2_no_force || 0;
- return force + noForce;
-});
-
-const shameTotal = computed(() => {
- const shame = eventFilters.globalEventCounts.value.p1_shame || 0;
- const noShame = eventFilters.globalEventCounts.value.p1_no_shame || 0;
- return shame + noShame;
-});
-
-const reportTotal = computed(() => {
- const report = eventFilters.globalEventCounts.value.p1_report || 0;
- const noReport = eventFilters.globalEventCounts.value.p1_no_report || 0;
- return report + noReport;
-});
-
-const averageScoreTotal = computed(() => {
- if (!allPlayersWithScores.value.length) return 0;
-
- let totalScores = 0;
- let totalScoreCount = 0;
-
- // Sum all individual scores from all players regardless of role, applying filters
- allPlayersWithScores.value.forEach((player: any) => {
- if (player.roomScoreHistory) {
- player.roomScoreHistory.forEach((roomScore: any) => {
- roomScore.scores.forEach((score: any) => {
- // Apply filters to scores
- if (!scorePassesFilters(score, roomScore.roomId)) {
- return;
- }
-
- totalScores += score.score;
- totalScoreCount++;
- });
- });
- }
- });
-
- return totalScoreCount > 0 ? Math.round((totalScores / totalScoreCount) * 10) / 10 : 0;
-});
-
-const totalPlayersCount = computed(() => {
- return additionalMetrics.value.players_seated || 0;
-});
// Active filters object
const activeFilters = computed(() => ({
@@ -403,15 +140,8 @@ const activeFilters = computed(() => ({
selectedRoom: filterState.value.rooms.length ? `${filterState.value.rooms.length} salas` : undefined
}));
-// Watch for changes in filter state to update selected player metrics
-watch(filterState, () => {
- computeSelectedPlayersMetrics();
-}, { deep: true });
const availableRooms = ref<{ roomId: string; name: string; playerCount?: number }[]>([]);
-const playerLoading = ref(false);
-const playerEventCounts = ref>((Object.fromEntries(EVENTS.map(k => [k, 0])) as Record));
-const playersActionsByUuid = ref>>({});
@@ -421,8 +151,6 @@ function goHome() {
}
-// Dynamic per-player overlay bar gradient and label color
-const playerBarGradient = computed(() => '#8b5cf6');
@@ -472,17 +200,6 @@ function setupStreams() {
});
- // Mapear counts por jugador
- const byUuid: Record> = {};
- list.forEach((p: any) => {
- const uuid = String(p?.uuid || '');
- if (!uuid) return;
- const src = p?.counts || {};
- const normalized: Record = Object.fromEntries(EVENTS.map(k => [k, 0])) as any;
- EVENTS.forEach(k => { normalized[k] = Number(src[k] || 0); });
- byUuid[uuid] = normalized;
- });
- playersActionsByUuid.value = byUuid;
// Store aggregated events for the EventFilters component
const aggEvents = Array.isArray(data?.aggregated?.detailedEvents) ? data.aggregated.detailedEvents : [];
@@ -518,11 +235,6 @@ function setupStreams() {
})).sort((a: any, b: any) => (a._lastSeen - b._lastSeen)).map(({ _lastSeen, ...rest }: any) => rest);
}
- // Recalculate metrics from score history
- computeMetricsFromScores();
-
- // Actualizar conteos del/los jugador(es) seleccionado(s)
- updateSelectedPlayersCounts();
} finally {
loading.value = false;
@@ -535,23 +247,10 @@ function setupStreams() {
-function updateSelectedPlayersCounts() {
- playerLoading.value = true;
- const next: Record = Object.fromEntries(EVENTS.map(k => [k, 0])) as any;
- const byUuid = playersActionsByUuid.value;
- filterState.value.playerUuids.forEach(uuid => {
- const counts = byUuid[uuid] || {};
- EVENTS.forEach(k => { next[k] = (next[k] || 0) + Number(counts[k] || 0); });
- });
- playerEventCounts.value = next as any;
- playerLoading.value = false;
-}
onMounted(() => {
setupStreams();
- // Initialize with aggregated data as default
- eventFilters.globalEventCounts.value = { ...eventFilters.globalEventCountsAggregated.value };
// Initialize default time range for filter state
const now = new Date();