Event Log
{topTeams.length > 0 && (
{topTeams.map((team, idx) => (
{idx + 1}
{team.name}
{team.score} PTS
))}
)}
{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.
);
})
)}