1 line
No EOL
71 KiB
JSON
1 line
No EOL
71 KiB
JSON
{"ast":null,"code":"var _jsxFileName = \"/Users/davidl/Nextcloud/Uni/Swinburne/ICT30016 - ICT Project/Assignment 3/incident-response-game/src/App.jsx\",\n _s = $RefreshSig$();\nimport React, { useMemo, useState, useEffect } from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport { Shield, Skull, RefreshCw, HelpCircle, Info, Sparkles } from \"lucide-react\";\n\n/**\n * Cybersecurity Incident Response – Card Game (Web App Prototype)\n * Single-file React prototype. Tailwind CSS assumed available by host.\n *\n * Core features:\n * - AI plays Attack cards; player responds with Defence cards.\n * - Action Point (AP) pool per round (default: 10) with varied defence costs.\n * - Ensures at least one viable counter is in the player's hand each attack.\n * - MITRE ATT&CK tagging on cards + quick definitions.\n * - Iterative-friendly architecture (pure data decks + simple rule engine).\n */\n\n// --- Types ---\nimport { jsxDEV as _jsxDEV } from \"react/jsx-dev-runtime\";\nconst MITRE = {\n phishing: {\n name: \"Phishing\",\n tactic: \"Initial Access\",\n id: \"T1566\"\n },\n malware: {\n name: \"Malware\",\n tactic: \"Execution\",\n id: \"T1204\"\n },\n privEsc: {\n name: \"Privilege Escalation\",\n tactic: \"Privilege Escalation\",\n id: \"TA0004\"\n },\n lateral: {\n name: \"Lateral Movement\",\n tactic: \"Lateral Movement\",\n id: \"TA0008\"\n },\n exfil: {\n name: \"Data Exfiltration\",\n tactic: \"Exfiltration\",\n id: \"TA0010\"\n }\n};\n\n/** Attack card model\n * id, title, description, mitreTag, difficulty(1-3), counterTags: string[] keys that match defence tags\n */\nconst ATTACK_DECK = [{\n id: \"A1\",\n title: \"Phishing Email\",\n description: \"A convincing email attempts to trick a user into entering credentials.\",\n mitreTag: \"phishing\",\n difficulty: 1,\n counterTags: [\"report\", \"mfa\", \"blockSender\", \"awareness\"]\n}, {\n id: \"A2\",\n title: \"Malware Dropper\",\n description: \"A user executes a downloaded attachment that launches a dropper.\",\n mitreTag: \"malware\",\n difficulty: 2,\n counterTags: [\"edr\", \"isolateHost\", \"patch\"]\n}, {\n id: \"A3\",\n title: \"Privilege Escalation\",\n description: \"Attacker abuses a vulnerable service to gain admin rights.\",\n mitreTag: \"privEsc\",\n difficulty: 2,\n counterTags: [\"patch\", \"leastPrivilege\", \"audit\"]\n}, {\n id: \"A4\",\n title: \"Lateral Movement\",\n description: \"Compromised account used to pivot through the network.\",\n mitreTag: \"lateral\",\n difficulty: 3,\n counterTags: [\"networkSeg\", \"isolateHost\", \"resetCreds\", \"monitor\"]\n}, {\n id: \"A5\",\n title: \"Data Exfiltration\",\n description: \"Sensitive data is staged and sent out of the organisation.\",\n mitreTag: \"exfil\",\n difficulty: 3,\n counterTags: [\"dlp\", \"isolateHost\", \"blockEgress\", \"monitor\"]\n}];\n\n/** Defence card model\n * id, title, cost, description, tags: string[] (must overlap attack.counterTags to fully mitigate)\n * effect: \"mitigate\" | \"reduce\" | \"fail\" is computed at play-time from tag overlap.\n */\nconst DEFENCE_POOL = [{\n id: \"D1\",\n title: \"Report to IT\",\n cost: 2,\n tags: [\"report\", \"awareness\"],\n description: \"Escalate suspicious activity to IT/security.\"\n}, {\n id: \"D2\",\n title: \"Enable MFA\",\n cost: 3,\n tags: [\"mfa\"],\n description: \"Require multi-factor authentication for access.\"\n}, {\n id: \"D3\",\n title: \"Patch Systems\",\n cost: 4,\n tags: [\"patch\"],\n description: \"Apply vendor patches to remediate vulnerabilities.\"\n}, {\n id: \"D4\",\n title: \"Endpoint Detection & Response\",\n cost: 5,\n tags: [\"edr\", \"monitor\"],\n description: \"Detect, contain, and remediate malicious processes.\"\n}, {\n id: \"D5\",\n title: \"Isolate Host\",\n cost: 6,\n tags: [\"isolateHost\"],\n description: \"Remove a device from the network to stop spread.\"\n}, {\n id: \"D6\",\n title: \"Network Segmentation\",\n cost: 5,\n tags: [\"networkSeg\"],\n description: \"Restrict lateral movement with segmented zones.\"\n}, {\n id: \"D7\",\n title: \"Reset Credentials\",\n cost: 3,\n tags: [\"resetCreds\"],\n description: \"Force password reset and revoke sessions.\"\n}, {\n id: \"D8\",\n title: \"DLP Policy\",\n cost: 5,\n tags: [\"dlp\"],\n description: \"Detect and prevent exfiltration of sensitive data.\"\n}, {\n id: \"D9\",\n title: \"Block Egress Rule\",\n cost: 4,\n tags: [\"blockEgress\"],\n description: \"Block suspicious outbound connections at firewall.\"\n}, {\n id: \"D10\",\n title: \"Block Sender/Domain\",\n cost: 2,\n tags: [\"blockSender\"],\n description: \"Block malicious sender to prevent recurrences.\"\n}, {\n id: \"D11\",\n title: \"Audit & Logging\",\n cost: 2,\n tags: [\"audit\", \"monitor\"],\n description: \"Increase logging and review to detect anomalies.\"\n}, {\n id: \"D12\",\n title: \"Reimage & Network Scan\",\n cost: 6,\n tags: [\"isolateHost\", \"monitor\"],\n description: \"Rebuild host and scan for indicators of compromise.\"\n}, {\n id: \"D13\",\n title: \"Least Privilege\",\n cost: 3,\n tags: [\"leastPrivilege\"],\n description: \"Reduce account/device permissions to minimum.\"\n}];\n\n// Utility to pick N distinct random items\nfunction pickN(arr, n) {\n const copy = [...arr];\n const out = [];\n while (out.length < n && copy.length) {\n const idx = Math.floor(Math.random() * copy.length);\n out.push(copy.splice(idx, 1)[0]);\n }\n return out;\n}\nfunction defenceEffect(attack, defence) {\n const overlap = defence.tags.some(t => attack.counterTags.includes(t));\n if (overlap) return {\n result: \"mitigate\",\n score: 2\n };\n // Non-overlap but helpful generic controls can reduce impact\n if (defence.tags.includes(\"monitor\") || defence.tags.includes(\"audit\")) {\n return {\n result: \"reduce\",\n score: 1\n };\n }\n return {\n result: \"fail\",\n score: 0\n };\n}\nfunction mitreBadge(tagKey) {\n const tag = MITRE[tagKey];\n if (!tag) return null;\n return /*#__PURE__*/_jsxDEV(\"span\", {\n className: \"text-xs px-2 py-1 rounded-full bg-slate-100 border font-medium\",\n children: [tag.name, \" \\u2022 \", tag.tactic, \" (\", tag.id, \")\"]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 117,\n columnNumber: 5\n }, this);\n}\nfunction Card({\n title,\n children,\n icon,\n accent = \"\",\n onClick,\n disabled\n}) {\n return /*#__PURE__*/_jsxDEV(\"button\", {\n onClick: onClick,\n disabled: disabled,\n className: `group relative text-left w-full ${onClick ? \"hover:-translate-y-0.5 active:translate-y-0\" : \"\"} transition disabled:opacity-50`,\n children: /*#__PURE__*/_jsxDEV(\"div\", {\n className: `rounded-2xl shadow p-4 border ${accent} bg-white`,\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center gap-2 mb-2\",\n children: [icon, /*#__PURE__*/_jsxDEV(\"h3\", {\n className: \"font-semibold text-slate-800\",\n children: title\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 133,\n columnNumber: 11\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 131,\n columnNumber: 9\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-sm text-slate-600\",\n children: children\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 135,\n columnNumber: 9\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 130,\n columnNumber: 7\n }, this)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 125,\n columnNumber: 5\n }, this);\n}\n_c = Card;\nexport default function App() {\n _s();\n const [round, setRound] = useState(1);\n const [ap, setAp] = useState(10);\n const [score, setScore] = useState(0);\n const [attacksLeft, setAttacksLeft] = useState(5); // number of attacks per round\n const [currentAttack, setCurrentAttack] = useState(null);\n const [hand, setHand] = useState([]);\n const [log, setLog] = useState([]);\n const [showHelp, setShowHelp] = useState(false);\n\n // Draw a new attack\n const drawAttack = () => ATTACK_DECK[Math.floor(Math.random() * ATTACK_DECK.length)];\n\n // Draw a hand that guarantees at least one viable counter for the current attack\n function drawHandForAttack(attack, size = 5) {\n for (let i = 0; i < 25; i++) {\n const h = pickN(DEFENCE_POOL, size);\n const viable = h.some(d => d.tags.some(t => attack.counterTags.includes(t)));\n if (viable) return h;\n }\n // Fallback: force-insert a matching defence if random failed\n const forced = pickN(DEFENCE_POOL, size - 1);\n const must = DEFENCE_POOL.find(d => d.tags.some(t => attack.counterTags.includes(t)));\n return [must, ...forced].slice(0, size);\n }\n\n // Start or advance state\n useEffect(() => {\n if (!currentAttack) {\n const atk = drawAttack();\n setCurrentAttack(atk);\n setHand(drawHandForAttack(atk));\n }\n }, [currentAttack]);\n function playDefence(card) {\n if (card.cost > ap) return; // not enough AP\n setAp(v => v - card.cost);\n const outcome = defenceEffect(currentAttack, card);\n setScore(s => s + outcome.score);\n setLog(l => [{\n ts: Date.now(),\n text: `${card.title} (${card.cost} AP) → ${outcome.result.toUpperCase()} (+${outcome.score})`\n }, ...l]);\n\n // If fully mitigated, move to next attack immediately\n const nextAttacks = attacksLeft - (outcome.result === \"mitigate\" ? 1 : 0);\n setAttacksLeft(nextAttacks);\n if (nextAttacks <= 0 || ap - card.cost <= 0) {\n // Round ends\n return;\n }\n\n // New attack + guaranteed-counter hand\n const atk = drawAttack();\n setCurrentAttack(atk);\n setHand(drawHandForAttack(atk));\n }\n function newRound() {\n setRound(r => r + 1);\n setAp(10);\n setAttacksLeft(5);\n setCurrentAttack(null);\n setHand([]);\n setLog([]);\n }\n const roundEnded = attacksLeft <= 0 || ap <= 0;\n return /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"min-h-screen bg-slate-50 p-6\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"max-w-6xl mx-auto space-y-6\",\n children: [/*#__PURE__*/_jsxDEV(\"header\", {\n className: \"flex items-center justify-between\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center gap-3\",\n children: [/*#__PURE__*/_jsxDEV(Shield, {\n className: \"w-6 h-6\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 218,\n columnNumber: 13\n }, this), /*#__PURE__*/_jsxDEV(\"h1\", {\n className: \"text-2xl font-bold\",\n children: \"Incident Response \\u2013 Card Game\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 219,\n columnNumber: 13\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 217,\n columnNumber: 11\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center gap-2\",\n children: [/*#__PURE__*/_jsxDEV(\"button\", {\n onClick: () => setShowHelp(true),\n className: \"inline-flex items-center gap-1 text-sm px-3 py-2 rounded-xl bg-white border shadow-sm hover:bg-slate-50\",\n children: [/*#__PURE__*/_jsxDEV(HelpCircle, {\n className: \"w-4 h-4\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 223,\n columnNumber: 15\n }, this), \" How to Play\"]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 222,\n columnNumber: 13\n }, this), /*#__PURE__*/_jsxDEV(\"button\", {\n onClick: newRound,\n className: \"inline-flex items-center gap-1 text-sm px-3 py-2 rounded-xl bg-white border shadow-sm hover:bg-slate-50\",\n children: [/*#__PURE__*/_jsxDEV(RefreshCw, {\n className: \"w-4 h-4\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 226,\n columnNumber: 15\n }, this), \" New Round\"]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 225,\n columnNumber: 13\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 221,\n columnNumber: 11\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 216,\n columnNumber: 9\n }, this), /*#__PURE__*/_jsxDEV(\"section\", {\n className: \"grid grid-cols-1 md:grid-cols-3 gap-4\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"md:col-span-2 space-y-4\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"grid grid-cols-3 gap-3\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"rounded-2xl bg-white border p-4 shadow-sm\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-xs text-slate-500\",\n children: \"Round\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 236,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-2xl font-semibold\",\n children: round\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 237,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 235,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"rounded-2xl bg-white border p-4 shadow-sm\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-xs text-slate-500\",\n children: \"Action Points\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 240,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-2xl font-semibold\",\n children: ap\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 241,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 239,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"rounded-2xl bg-white border p-4 shadow-sm\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-xs text-slate-500\",\n children: \"Score\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 244,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-2xl font-semibold\",\n children: score\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 245,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 243,\n columnNumber: 15\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 234,\n columnNumber: 13\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"rounded-2xl bg-white border p-5 shadow-sm\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center justify-between mb-3\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center gap-2\",\n children: [/*#__PURE__*/_jsxDEV(Skull, {\n className: \"w-5 h-5\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 253,\n columnNumber: 19\n }, this), /*#__PURE__*/_jsxDEV(\"h2\", {\n className: \"font-semibold\",\n children: \"Current Attack\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 254,\n columnNumber: 19\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 252,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"span\", {\n className: \"text-xs text-slate-500\",\n children: [\"Attacks remaining this round: \", attacksLeft]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 256,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 251,\n columnNumber: 15\n }, this), currentAttack && /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"space-y-3\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex flex-wrap items-center gap-2\",\n children: [mitreBadge(currentAttack.mitreTag), /*#__PURE__*/_jsxDEV(\"span\", {\n className: \"text-xs px-2 py-1 rounded-full bg-amber-100 text-amber-800\",\n children: [\"Difficulty \", currentAttack.difficulty]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 263,\n columnNumber: 21\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 261,\n columnNumber: 19\n }, this), /*#__PURE__*/_jsxDEV(\"h3\", {\n className: \"text-lg font-semibold\",\n children: currentAttack.title\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 265,\n columnNumber: 19\n }, this), /*#__PURE__*/_jsxDEV(\"p\", {\n className: \"text-sm text-slate-600\",\n children: currentAttack.description\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 266,\n columnNumber: 19\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 260,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 250,\n columnNumber: 13\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"space-y-2\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center gap-2\",\n children: [/*#__PURE__*/_jsxDEV(Shield, {\n className: \"w-4 h-4\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 274,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"h2\", {\n className: \"font-semibold\",\n children: \"Your Defence Hand\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 275,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 273,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\",\n children: hand.map(card => /*#__PURE__*/_jsxDEV(Card, {\n title: `${card.title} • ${card.cost} AP`,\n icon: /*#__PURE__*/_jsxDEV(Shield, {\n className: \"w-4 h-4\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 282,\n columnNumber: 27\n }, this),\n onClick: !roundEnded ? () => playDefence(card) : undefined,\n disabled: roundEnded || card.cost > ap,\n accent: card.cost > ap ? \"border-slate-200\" : \"border-slate-200 hover:border-emerald-300\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-xs mb-2\",\n children: card.description\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 287,\n columnNumber: 21\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex flex-wrap gap-1\",\n children: card.tags.map(t => /*#__PURE__*/_jsxDEV(\"span\", {\n className: \"text-[10px] px-2 py-0.5 rounded-full bg-slate-100 border\",\n children: t\n }, t, false, {\n fileName: _jsxFileName,\n lineNumber: 290,\n columnNumber: 25\n }, this))\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 288,\n columnNumber: 21\n }, this)]\n }, card.id, true, {\n fileName: _jsxFileName,\n lineNumber: 279,\n columnNumber: 19\n }, this))\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 277,\n columnNumber: 15\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 272,\n columnNumber: 13\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 232,\n columnNumber: 11\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"space-y-3\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"rounded-2xl bg-white border p-4 shadow-sm\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center gap-2 mb-2\",\n children: [/*#__PURE__*/_jsxDEV(Info, {\n className: \"w-4 h-4\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 302,\n columnNumber: 61\n }, this), /*#__PURE__*/_jsxDEV(\"h3\", {\n className: \"font-semibold\",\n children: \"Event Log\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 302,\n columnNumber: 88\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 302,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"space-y-2 max-h-80 overflow-auto pr-2\",\n children: [log.length === 0 && /*#__PURE__*/_jsxDEV(\"p\", {\n className: \"text-sm text-slate-500\",\n children: \"No actions yet. Play a defence card to respond.\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 304,\n columnNumber: 38\n }, this), log.map(e => /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-sm text-slate-700\",\n children: [new Date(e.ts).toLocaleTimeString(), \" \\u2014 \", e.text]\n }, e.ts, true, {\n fileName: _jsxFileName,\n lineNumber: 306,\n columnNumber: 19\n }, this))]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 303,\n columnNumber: 15\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 301,\n columnNumber: 13\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"rounded-2xl bg-gradient-to-br from-emerald-50 to-slate-50 border p-4 shadow-sm text-center\",\n children: roundEnded ? /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"space-y-2\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"inline-flex items-center gap-2 text-emerald-700\",\n children: [/*#__PURE__*/_jsxDEV(Sparkles, {\n className: \"w-4 h-4\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 315,\n columnNumber: 84\n }, this), \" \", /*#__PURE__*/_jsxDEV(\"b\", {\n children: \"Round Complete\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 315,\n columnNumber: 116\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 315,\n columnNumber: 19\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-sm text-slate-600\",\n children: [\"Score this round: \", /*#__PURE__*/_jsxDEV(\"b\", {\n children: score\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 316,\n columnNumber: 77\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 316,\n columnNumber: 19\n }, this), /*#__PURE__*/_jsxDEV(\"button\", {\n onClick: newRound,\n className: \"mt-2 inline-flex items-center gap-1 text-sm px-3 py-2 rounded-xl bg-emerald-600 text-white hover:bg-emerald-700\",\n children: \"Start Next Round\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 317,\n columnNumber: 19\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 314,\n columnNumber: 17\n }, this) : /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-sm text-slate-600\",\n children: \"Mitigate attacks efficiently and conserve AP for tougher threats.\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 320,\n columnNumber: 17\n }, this)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 312,\n columnNumber: 13\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 300,\n columnNumber: 11\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 231,\n columnNumber: 9\n }, this), /*#__PURE__*/_jsxDEV(\"footer\", {\n className: \"text-xs text-slate-500 pt-4\",\n children: /*#__PURE__*/_jsxDEV(\"p\", {\n children: \"MITRE ATT&CK tags are indicative and simplified for learning. This prototype focuses on accessibility across skill levels and resource-based decision making.\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 327,\n columnNumber: 11\n }, this)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 326,\n columnNumber: 9\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 215,\n columnNumber: 7\n }, this), /*#__PURE__*/_jsxDEV(AnimatePresence, {\n children: showHelp && /*#__PURE__*/_jsxDEV(motion.div, {\n initial: {\n opacity: 0\n },\n animate: {\n opacity: 1\n },\n exit: {\n opacity: 0\n },\n className: \"fixed inset-0 bg-black/30 backdrop-blur-sm flex items-center justify-center p-4 z-50\",\n children: /*#__PURE__*/_jsxDEV(motion.div, {\n initial: {\n scale: 0.95,\n opacity: 0\n },\n animate: {\n scale: 1,\n opacity: 1\n },\n exit: {\n scale: 0.95,\n opacity: 0\n },\n className: \"max-w-xl w-full bg-white rounded-2xl shadow-2xl border p-6 space-y-3\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center justify-between\",\n children: [/*#__PURE__*/_jsxDEV(\"div\", {\n className: \"flex items-center gap-2\",\n children: [/*#__PURE__*/_jsxDEV(HelpCircle, {\n className: \"w-5 h-5\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 339,\n columnNumber: 58\n }, this), /*#__PURE__*/_jsxDEV(\"h3\", {\n className: \"font-semibold\",\n children: \"How to Play\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 339,\n columnNumber: 91\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 339,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"button\", {\n onClick: () => setShowHelp(false),\n className: \"text-slate-500 hover:text-slate-700\",\n children: \"Close\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 340,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 338,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"ol\", {\n className: \"list-decimal pl-5 text-sm space-y-2 text-slate-700\",\n children: [/*#__PURE__*/_jsxDEV(\"li\", {\n children: [\"The computer plays an \", /*#__PURE__*/_jsxDEV(\"b\", {\n children: \"Attack\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 343,\n columnNumber: 43\n }, this), \". Review its MITRE tag and description.\"]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 343,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"li\", {\n children: [\"You have \", /*#__PURE__*/_jsxDEV(\"b\", {\n children: \"10 Action Points\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 344,\n columnNumber: 30\n }, this), \" (AP) to spend each round. Each defence costs AP.\"]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 344,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"li\", {\n children: [\"Play a \", /*#__PURE__*/_jsxDEV(\"b\", {\n children: \"Defence\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 345,\n columnNumber: 28\n }, this), \" from your hand. If its tags match the attack\\u2019s counters, you \", /*#__PURE__*/_jsxDEV(\"b\", {\n children: \"mitigate\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 345,\n columnNumber: 104\n }, this), \" it (+2 points). Generic controls may \", /*#__PURE__*/_jsxDEV(\"b\", {\n children: \"reduce\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 345,\n columnNumber: 157\n }, this), \" impact (+1). Otherwise it \", /*#__PURE__*/_jsxDEV(\"b\", {\n children: \"fails\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 345,\n columnNumber: 197\n }, this), \" (0).\"]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 345,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"li\", {\n children: \"Mitigated attacks advance the round. When AP hits 0 or you clear all attacks, the round ends. Start a new round anytime.\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 346,\n columnNumber: 17\n }, this), /*#__PURE__*/_jsxDEV(\"li\", {\n children: \"Learn strategically: conserve AP for harder threats and combine monitoring with containment.\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 347,\n columnNumber: 17\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 342,\n columnNumber: 15\n }, this), /*#__PURE__*/_jsxDEV(\"div\", {\n className: \"text-xs text-slate-500\",\n children: \"Designed for classrooms/workshops; quick rounds target 15\\u201320 minutes with discussion.\"\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 349,\n columnNumber: 15\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 337,\n columnNumber: 13\n }, this)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 336,\n columnNumber: 11\n }, this)\n }, void 0, false, {\n fileName: _jsxFileName,\n lineNumber: 334,\n columnNumber: 7\n }, this)]\n }, void 0, true, {\n fileName: _jsxFileName,\n lineNumber: 214,\n columnNumber: 5\n }, this);\n}\n_s(App, \"9/DowfyYaAy9fzb8ESi04nHjjD0=\");\n_c2 = App;\nvar _c, _c2;\n$RefreshReg$(_c, \"Card\");\n$RefreshReg$(_c2, \"App\");","map":{"version":3,"names":["React","useMemo","useState","useEffect","motion","AnimatePresence","Shield","Skull","RefreshCw","HelpCircle","Info","Sparkles","jsxDEV","_jsxDEV","MITRE","phishing","name","tactic","id","malware","privEsc","lateral","exfil","ATTACK_DECK","title","description","mitreTag","difficulty","counterTags","DEFENCE_POOL","cost","tags","pickN","arr","n","copy","out","length","idx","Math","floor","random","push","splice","defenceEffect","attack","defence","overlap","some","t","includes","result","score","mitreBadge","tagKey","tag","className","children","fileName","_jsxFileName","lineNumber","columnNumber","Card","icon","accent","onClick","disabled","_c","App","_s","round","setRound","ap","setAp","setScore","attacksLeft","setAttacksLeft","currentAttack","setCurrentAttack","hand","setHand","log","setLog","showHelp","setShowHelp","drawAttack","drawHandForAttack","size","i","h","viable","d","forced","must","find","slice","atk","playDefence","card","v","outcome","s","l","ts","Date","now","text","toUpperCase","nextAttacks","newRound","r","roundEnded","map","undefined","e","toLocaleTimeString","div","initial","opacity","animate","exit","scale","_c2","$RefreshReg$"],"sources":["/Users/davidl/Nextcloud/Uni/Swinburne/ICT30016 - ICT Project/Assignment 3/incident-response-game/src/App.jsx"],"sourcesContent":["import React, { useMemo, useState, useEffect } from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport { Shield, Skull, RefreshCw, HelpCircle, Info, Sparkles } from \"lucide-react\";\n\n/**\n * Cybersecurity Incident Response – Card Game (Web App Prototype)\n * Single-file React prototype. Tailwind CSS assumed available by host.\n *\n * Core features:\n * - AI plays Attack cards; player responds with Defence cards.\n * - Action Point (AP) pool per round (default: 10) with varied defence costs.\n * - Ensures at least one viable counter is in the player's hand each attack.\n * - MITRE ATT&CK tagging on cards + quick definitions.\n * - Iterative-friendly architecture (pure data decks + simple rule engine).\n */\n\n// --- Types ---\nconst MITRE = {\n phishing: { name: \"Phishing\", tactic: \"Initial Access\", id: \"T1566\" },\n malware: { name: \"Malware\", tactic: \"Execution\", id: \"T1204\" },\n privEsc: { name: \"Privilege Escalation\", tactic: \"Privilege Escalation\", id: \"TA0004\" },\n lateral: { name: \"Lateral Movement\", tactic: \"Lateral Movement\", id: \"TA0008\" },\n exfil: { name: \"Data Exfiltration\", tactic: \"Exfiltration\", id: \"TA0010\" },\n};\n\n/** Attack card model\n * id, title, description, mitreTag, difficulty(1-3), counterTags: string[] keys that match defence tags\n */\nconst ATTACK_DECK = [\n {\n id: \"A1\",\n title: \"Phishing Email\",\n description: \"A convincing email attempts to trick a user into entering credentials.\",\n mitreTag: \"phishing\",\n difficulty: 1,\n counterTags: [\"report\", \"mfa\", \"blockSender\", \"awareness\"],\n },\n {\n id: \"A2\",\n title: \"Malware Dropper\",\n description: \"A user executes a downloaded attachment that launches a dropper.\",\n mitreTag: \"malware\",\n difficulty: 2,\n counterTags: [\"edr\", \"isolateHost\", \"patch\"],\n },\n {\n id: \"A3\",\n title: \"Privilege Escalation\",\n description: \"Attacker abuses a vulnerable service to gain admin rights.\",\n mitreTag: \"privEsc\",\n difficulty: 2,\n counterTags: [\"patch\", \"leastPrivilege\", \"audit\"],\n },\n {\n id: \"A4\",\n title: \"Lateral Movement\",\n description: \"Compromised account used to pivot through the network.\",\n mitreTag: \"lateral\",\n difficulty: 3,\n counterTags: [\"networkSeg\", \"isolateHost\", \"resetCreds\", \"monitor\"],\n },\n {\n id: \"A5\",\n title: \"Data Exfiltration\",\n description: \"Sensitive data is staged and sent out of the organisation.\",\n mitreTag: \"exfil\",\n difficulty: 3,\n counterTags: [\"dlp\", \"isolateHost\", \"blockEgress\", \"monitor\"],\n },\n];\n\n/** Defence card model\n * id, title, cost, description, tags: string[] (must overlap attack.counterTags to fully mitigate)\n * effect: \"mitigate\" | \"reduce\" | \"fail\" is computed at play-time from tag overlap.\n */\nconst DEFENCE_POOL = [\n { id: \"D1\", title: \"Report to IT\", cost: 2, tags: [\"report\", \"awareness\"], description: \"Escalate suspicious activity to IT/security.\" },\n { id: \"D2\", title: \"Enable MFA\", cost: 3, tags: [\"mfa\"], description: \"Require multi-factor authentication for access.\" },\n { id: \"D3\", title: \"Patch Systems\", cost: 4, tags: [\"patch\"], description: \"Apply vendor patches to remediate vulnerabilities.\" },\n { id: \"D4\", title: \"Endpoint Detection & Response\", cost: 5, tags: [\"edr\", \"monitor\"], description: \"Detect, contain, and remediate malicious processes.\" },\n { id: \"D5\", title: \"Isolate Host\", cost: 6, tags: [\"isolateHost\"], description: \"Remove a device from the network to stop spread.\" },\n { id: \"D6\", title: \"Network Segmentation\", cost: 5, tags: [\"networkSeg\"], description: \"Restrict lateral movement with segmented zones.\" },\n { id: \"D7\", title: \"Reset Credentials\", cost: 3, tags: [\"resetCreds\"], description: \"Force password reset and revoke sessions.\" },\n { id: \"D8\", title: \"DLP Policy\", cost: 5, tags: [\"dlp\"], description: \"Detect and prevent exfiltration of sensitive data.\" },\n { id: \"D9\", title: \"Block Egress Rule\", cost: 4, tags: [\"blockEgress\"], description: \"Block suspicious outbound connections at firewall.\" },\n { id: \"D10\", title: \"Block Sender/Domain\", cost: 2, tags: [\"blockSender\"], description: \"Block malicious sender to prevent recurrences.\" },\n { id: \"D11\", title: \"Audit & Logging\", cost: 2, tags: [\"audit\", \"monitor\"], description: \"Increase logging and review to detect anomalies.\" },\n { id: \"D12\", title: \"Reimage & Network Scan\", cost: 6, tags: [\"isolateHost\", \"monitor\"], description: \"Rebuild host and scan for indicators of compromise.\" },\n { id: \"D13\", title: \"Least Privilege\", cost: 3, tags: [\"leastPrivilege\"], description: \"Reduce account/device permissions to minimum.\" },\n];\n\n// Utility to pick N distinct random items\nfunction pickN(arr, n) {\n const copy = [...arr];\n const out = [];\n while (out.length < n && copy.length) {\n const idx = Math.floor(Math.random() * copy.length);\n out.push(copy.splice(idx, 1)[0]);\n }\n return out;\n}\n\nfunction defenceEffect(attack, defence) {\n const overlap = defence.tags.some((t) => attack.counterTags.includes(t));\n if (overlap) return { result: \"mitigate\", score: 2 };\n // Non-overlap but helpful generic controls can reduce impact\n if (defence.tags.includes(\"monitor\") || defence.tags.includes(\"audit\")) {\n return { result: \"reduce\", score: 1 };\n }\n return { result: \"fail\", score: 0 };\n}\n\nfunction mitreBadge(tagKey) {\n const tag = MITRE[tagKey];\n if (!tag) return null;\n return (\n <span className=\"text-xs px-2 py-1 rounded-full bg-slate-100 border font-medium\">\n {tag.name} • {tag.tactic} ({tag.id})\n </span>\n );\n}\n\nfunction Card({ title, children, icon, accent = \"\", onClick, disabled }) {\n return (\n <button\n onClick={onClick}\n disabled={disabled}\n className={`group relative text-left w-full ${onClick ? \"hover:-translate-y-0.5 active:translate-y-0\" : \"\"} transition disabled:opacity-50`}\n >\n <div className={`rounded-2xl shadow p-4 border ${accent} bg-white`}>\n <div className=\"flex items-center gap-2 mb-2\">\n {icon}\n <h3 className=\"font-semibold text-slate-800\">{title}</h3>\n </div>\n <div className=\"text-sm text-slate-600\">{children}</div>\n </div>\n </button>\n );\n}\n\nexport default function App() {\n const [round, setRound] = useState(1);\n const [ap, setAp] = useState(10);\n const [score, setScore] = useState(0);\n const [attacksLeft, setAttacksLeft] = useState(5); // number of attacks per round\n const [currentAttack, setCurrentAttack] = useState(null);\n const [hand, setHand] = useState([]);\n const [log, setLog] = useState([]);\n const [showHelp, setShowHelp] = useState(false);\n\n // Draw a new attack\n const drawAttack = () => ATTACK_DECK[Math.floor(Math.random() * ATTACK_DECK.length)];\n\n // Draw a hand that guarantees at least one viable counter for the current attack\n function drawHandForAttack(attack, size = 5) {\n for (let i = 0; i < 25; i++) {\n const h = pickN(DEFENCE_POOL, size);\n const viable = h.some((d) => d.tags.some((t) => attack.counterTags.includes(t)));\n if (viable) return h;\n }\n // Fallback: force-insert a matching defence if random failed\n const forced = pickN(DEFENCE_POOL, size - 1);\n const must = DEFENCE_POOL.find((d) => d.tags.some((t) => attack.counterTags.includes(t)));\n return [must, ...forced].slice(0, size);\n }\n\n // Start or advance state\n useEffect(() => {\n if (!currentAttack) {\n const atk = drawAttack();\n setCurrentAttack(atk);\n setHand(drawHandForAttack(atk));\n }\n }, [currentAttack]);\n\n function playDefence(card) {\n if (card.cost > ap) return; // not enough AP\n setAp((v) => v - card.cost);\n\n const outcome = defenceEffect(currentAttack, card);\n setScore((s) => s + outcome.score);\n setLog((l) => [\n { ts: Date.now(), text: `${card.title} (${card.cost} AP) → ${outcome.result.toUpperCase()} (+${outcome.score})` },\n ...l,\n ]);\n\n // If fully mitigated, move to next attack immediately\n const nextAttacks = attacksLeft - (outcome.result === \"mitigate\" ? 1 : 0);\n setAttacksLeft(nextAttacks);\n\n if (nextAttacks <= 0 || ap - card.cost <= 0) {\n // Round ends\n return;\n }\n\n // New attack + guaranteed-counter hand\n const atk = drawAttack();\n setCurrentAttack(atk);\n setHand(drawHandForAttack(atk));\n }\n\n function newRound() {\n setRound((r) => r + 1);\n setAp(10);\n setAttacksLeft(5);\n setCurrentAttack(null);\n setHand([]);\n setLog([]);\n }\n\n const roundEnded = attacksLeft <= 0 || ap <= 0;\n\n return (\n <div className=\"min-h-screen bg-slate-50 p-6\">\n <div className=\"max-w-6xl mx-auto space-y-6\">\n <header className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n <Shield className=\"w-6 h-6\" />\n <h1 className=\"text-2xl font-bold\">Incident Response – Card Game</h1>\n </div>\n <div className=\"flex items-center gap-2\">\n <button onClick={() => setShowHelp(true)} className=\"inline-flex items-center gap-1 text-sm px-3 py-2 rounded-xl bg-white border shadow-sm hover:bg-slate-50\">\n <HelpCircle className=\"w-4 h-4\"/> How to Play\n </button>\n <button onClick={newRound} className=\"inline-flex items-center gap-1 text-sm px-3 py-2 rounded-xl bg-white border shadow-sm hover:bg-slate-50\">\n <RefreshCw className=\"w-4 h-4\"/> New Round\n </button>\n </div>\n </header>\n\n <section className=\"grid grid-cols-1 md:grid-cols-3 gap-4\">\n <div className=\"md:col-span-2 space-y-4\">\n {/* Status */}\n <div className=\"grid grid-cols-3 gap-3\">\n <div className=\"rounded-2xl bg-white border p-4 shadow-sm\">\n <div className=\"text-xs text-slate-500\">Round</div>\n <div className=\"text-2xl font-semibold\">{round}</div>\n </div>\n <div className=\"rounded-2xl bg-white border p-4 shadow-sm\">\n <div className=\"text-xs text-slate-500\">Action Points</div>\n <div className=\"text-2xl font-semibold\">{ap}</div>\n </div>\n <div className=\"rounded-2xl bg-white border p-4 shadow-sm\">\n <div className=\"text-xs text-slate-500\">Score</div>\n <div className=\"text-2xl font-semibold\">{score}</div>\n </div>\n </div>\n\n {/* Current Attack */}\n <div className=\"rounded-2xl bg-white border p-5 shadow-sm\">\n <div className=\"flex items-center justify-between mb-3\">\n <div className=\"flex items-center gap-2\">\n <Skull className=\"w-5 h-5\"/>\n <h2 className=\"font-semibold\">Current Attack</h2>\n </div>\n <span className=\"text-xs text-slate-500\">Attacks remaining this round: {attacksLeft}</span>\n </div>\n\n {currentAttack && (\n <div className=\"space-y-3\">\n <div className=\"flex flex-wrap items-center gap-2\">\n {mitreBadge(currentAttack.mitreTag)}\n <span className=\"text-xs px-2 py-1 rounded-full bg-amber-100 text-amber-800\">Difficulty {currentAttack.difficulty}</span>\n </div>\n <h3 className=\"text-lg font-semibold\">{currentAttack.title}</h3>\n <p className=\"text-sm text-slate-600\">{currentAttack.description}</p>\n </div>\n )}\n </div>\n\n {/* Defence Hand */}\n <div className=\"space-y-2\">\n <div className=\"flex items-center gap-2\">\n <Shield className=\"w-4 h-4\"/>\n <h2 className=\"font-semibold\">Your Defence Hand</h2>\n </div>\n <div className=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3\">\n {hand.map((card) => (\n <Card\n key={card.id}\n title={`${card.title} • ${card.cost} AP`}\n icon={<Shield className=\"w-4 h-4\"/>}\n onClick={!roundEnded ? () => playDefence(card) : undefined}\n disabled={roundEnded || card.cost > ap}\n accent={card.cost > ap ? \"border-slate-200\" : \"border-slate-200 hover:border-emerald-300\"}\n >\n <div className=\"text-xs mb-2\">{card.description}</div>\n <div className=\"flex flex-wrap gap-1\">\n {card.tags.map((t) => (\n <span key={t} className=\"text-[10px] px-2 py-0.5 rounded-full bg-slate-100 border\">{t}</span>\n ))}\n </div>\n </Card>\n ))}\n </div>\n </div>\n </div>\n\n {/* Event Log */}\n <div className=\"space-y-3\">\n <div className=\"rounded-2xl bg-white border p-4 shadow-sm\">\n <div className=\"flex items-center gap-2 mb-2\"><Info className=\"w-4 h-4\"/><h3 className=\"font-semibold\">Event Log</h3></div>\n <div className=\"space-y-2 max-h-80 overflow-auto pr-2\">\n {log.length === 0 && <p className=\"text-sm text-slate-500\">No actions yet. Play a defence card to respond.</p>}\n {log.map((e) => (\n <div key={e.ts} className=\"text-sm text-slate-700\">{new Date(e.ts).toLocaleTimeString()} — {e.text}</div>\n ))}\n </div>\n </div>\n\n {/* Round Summary / CTA */}\n <div className=\"rounded-2xl bg-gradient-to-br from-emerald-50 to-slate-50 border p-4 shadow-sm text-center\">\n {roundEnded ? (\n <div className=\"space-y-2\">\n <div className=\"inline-flex items-center gap-2 text-emerald-700\"><Sparkles className=\"w-4 h-4\"/> <b>Round Complete</b></div>\n <div className=\"text-sm text-slate-600\">Score this round: <b>{score}</b></div>\n <button onClick={newRound} className=\"mt-2 inline-flex items-center gap-1 text-sm px-3 py-2 rounded-xl bg-emerald-600 text-white hover:bg-emerald-700\">Start Next Round</button>\n </div>\n ) : (\n <div className=\"text-sm text-slate-600\">Mitigate attacks efficiently and conserve AP for tougher threats.</div>\n )}\n </div>\n </div>\n </section>\n\n <footer className=\"text-xs text-slate-500 pt-4\">\n <p>\n MITRE ATT&CK tags are indicative and simplified for learning. This prototype focuses on accessibility across skill levels and resource-based decision making.\n </p>\n </footer>\n </div>\n\n {/* Help Modal */}\n <AnimatePresence>\n {showHelp && (\n <motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} exit={{ opacity: 0 }} className=\"fixed inset-0 bg-black/30 backdrop-blur-sm flex items-center justify-center p-4 z-50\">\n <motion.div initial={{ scale: 0.95, opacity: 0 }} animate={{ scale: 1, opacity: 1 }} exit={{ scale: 0.95, opacity: 0 }} className=\"max-w-xl w-full bg-white rounded-2xl shadow-2xl border p-6 space-y-3\">\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\"><HelpCircle className=\"w-5 h-5\"/><h3 className=\"font-semibold\">How to Play</h3></div>\n <button onClick={() => setShowHelp(false)} className=\"text-slate-500 hover:text-slate-700\">Close</button>\n </div>\n <ol className=\"list-decimal pl-5 text-sm space-y-2 text-slate-700\">\n <li>The computer plays an <b>Attack</b>. Review its MITRE tag and description.</li>\n <li>You have <b>10 Action Points</b> (AP) to spend each round. Each defence costs AP.</li>\n <li>Play a <b>Defence</b> from your hand. If its tags match the attack’s counters, you <b>mitigate</b> it (+2 points). Generic controls may <b>reduce</b> impact (+1). Otherwise it <b>fails</b> (0).</li>\n <li>Mitigated attacks advance the round. When AP hits 0 or you clear all attacks, the round ends. Start a new round anytime.</li>\n <li>Learn strategically: conserve AP for harder threats and combine monitoring with containment.</li>\n </ol>\n <div className=\"text-xs text-slate-500\">Designed for classrooms/workshops; quick rounds target 15–20 minutes with discussion.</div>\n </motion.div>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n );\n}\n\n"],"mappings":"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","ignoreList":[]},"metadata":{},"sourceType":"module","externalDependencies":[]} |