import React, { useMemo } from 'react'; import { Medal, CheckCircle2, History } from 'lucide-react'; import { useCTF } from './CTFContext'; import { calculateChallengeValue, getFirstBloodBonusFactor } from './services/scoring'; export const Log: React.FC = () => { const { state } = useCTF(); const sortedSolves = useMemo(() => { return [...state.solves].sort((a, b) => b.timestamp - a.timestamp); }, [state.solves]); return (

Event Log

{sortedSolves.length === 0 ? (
No activities recorded yet.
) : ( sortedSolves.map((solve, idx) => { const team = state.teams.find(t => t.id === solve.teamId); const challenge = state.challenges.find(c => c.id === solve.challengeId); if (!team || !challenge) return null; const challengeSolves = state.solves .filter(s => s.challengeId === solve.challengeId) .sort((a, b) => a.timestamp - b.timestamp); const rank = challengeSolves.findIndex(s => s.teamId === solve.teamId); const bonusFactor = getFirstBloodBonusFactor(rank); const basePoints = calculateChallengeValue( challenge.initialPoints, challenge.minimumPoints || 0, challenge.decaySolves || 1, challengeSolves.length ); const bonus = Math.floor(challenge.initialPoints * bonusFactor); const pointsGained = basePoints + bonus; const getRankIcon = (rank: number) => { if (rank === 0) return ; // Gold if (rank === 1) return ; // Silver if (rank === 2) return ; // Bronze return ; // Checkmark }; const difficultyColor = challenge.difficulty === 'Low' ? 'text-[#00ff00]' : challenge.difficulty === 'Medium' ? 'text-[#ffaa00]' : 'text-[#ff0000]'; const dateStr = new Date(solve.timestamp).toLocaleString(); return (
{getRankIcon(rank)}
[{dateStr}] {team.name} solved {challenge.category} - {challenge.title} and gained {pointsGained} points.
); }) )}
); };