mirror of
https://github.com/cliffe/BreakEscape.git
synced 2026-02-20 13:50:46 +00:00
Remove old scenario selection HTML and testing guide files
This commit is contained in:
295
TESTING_GUIDE.md
295
TESTING_GUIDE.md
@@ -1,295 +0,0 @@
|
||||
# Global Ink Variables - Testing Guide
|
||||
|
||||
## Quick Start Test
|
||||
|
||||
### Prerequisites
|
||||
- Open the game with the `npc-sprite-test2.json` scenario
|
||||
- Browser console open (F12)
|
||||
|
||||
### Test 1: Basic Functionality
|
||||
|
||||
1. **Verify Initial State**
|
||||
```javascript
|
||||
console.log(window.gameState.globalVariables);
|
||||
// Should show: { player_joined_organization: false }
|
||||
```
|
||||
|
||||
2. **Start conversation with test_npc_back**
|
||||
- Click on the back NPC in test_room
|
||||
- Follow the conversation through to "player_closing"
|
||||
|
||||
3. **Make the Join Choice**
|
||||
- Select "I'd love to join your organization!"
|
||||
- Observe NPC response
|
||||
|
||||
4. **Check Global State**
|
||||
```javascript
|
||||
console.log(window.gameState.globalVariables.player_joined_organization);
|
||||
// Should now be: true
|
||||
```
|
||||
|
||||
### Test 2: Cross-NPC Syncing
|
||||
|
||||
1. **Start conversation with container_test_npc (Equipment Officer)**
|
||||
- Click on the equipment officer NPC
|
||||
- Start conversation
|
||||
|
||||
2. **Observe Menu Options**
|
||||
- If you joined in Test 1, you should see:
|
||||
- "Tell me about your equipment"
|
||||
- **"Show me what you have available"** ← This should appear!
|
||||
- "Show me your specialist items"
|
||||
- If you didn't join, only the specialist items option appears
|
||||
|
||||
3. **Verify Variable Synced**
|
||||
```javascript
|
||||
console.log(window.gameState.globalVariables.player_joined_organization);
|
||||
// Still true from previous conversation!
|
||||
```
|
||||
|
||||
### Test 3: Direct Phaser Access
|
||||
|
||||
1. **Open Console**
|
||||
|
||||
2. **Directly Set Variable**
|
||||
```javascript
|
||||
window.gameState.globalVariables.player_joined_organization = false;
|
||||
```
|
||||
|
||||
3. **Start new conversation with Equipment Officer**
|
||||
- Full inventory option should now be GONE
|
||||
- Only specialist items option appears
|
||||
|
||||
4. **Set Back to True**
|
||||
```javascript
|
||||
window.gameState.globalVariables.player_joined_organization = true;
|
||||
```
|
||||
|
||||
5. **Start conversation again**
|
||||
- Full inventory option should reappear
|
||||
|
||||
### Test 4: State Persistence
|
||||
|
||||
1. **Join organization** (if not already done)
|
||||
- Complete the test_npc_back conversation
|
||||
- Choose to join
|
||||
|
||||
2. **Talk to Equipment Officer**
|
||||
- Verify full inventory option is available
|
||||
|
||||
3. **End conversation**
|
||||
- Close the minigame
|
||||
|
||||
4. **Reload the page** (F5)
|
||||
- Wait for game to fully load
|
||||
|
||||
5. **Check Global State**
|
||||
```javascript
|
||||
console.log(window.gameState.globalVariables.player_joined_organization);
|
||||
// Should still be true!
|
||||
```
|
||||
|
||||
6. **Talk to Equipment Officer again**
|
||||
- Full inventory option should still appear
|
||||
|
||||
## Debugging Checks
|
||||
|
||||
### Verify Scenario Loaded
|
||||
|
||||
```javascript
|
||||
console.log(window.gameScenario.globalVariables);
|
||||
// Should show: { player_joined_organization: false }
|
||||
```
|
||||
|
||||
### Check All Global Variables
|
||||
|
||||
```javascript
|
||||
console.log('Global Variables:', window.gameState.globalVariables);
|
||||
console.log('NPC Cache:', Array.from(window.npcManager.inkEngineCache.keys()));
|
||||
console.log('Saved States:', window.npcConversationStateManager.getSavedNPCs());
|
||||
```
|
||||
|
||||
### Check Variable Change Events
|
||||
|
||||
Add this before starting a conversation:
|
||||
|
||||
```javascript
|
||||
// Temporarily enable verbose logging
|
||||
window.npcConversationStateManager._log = (level, msg, data) => {
|
||||
console.log(`[${level}]`, msg, data);
|
||||
};
|
||||
```
|
||||
|
||||
Then start a conversation and watch the console for variable sync messages.
|
||||
|
||||
### Verify Ink Variable Names
|
||||
|
||||
```javascript
|
||||
// Check what variables are in test2.ink story
|
||||
const test2Engine = window.npcManager.inkEngineCache.get('test_npc_back');
|
||||
if (test2Engine?.story?.variablesState?._defaultGlobalVariables) {
|
||||
console.log('test2.ink variables:',
|
||||
Array.from(test2Engine.story.variablesState._defaultGlobalVariables.keys()));
|
||||
}
|
||||
|
||||
// Check equipment officer
|
||||
const eqEngine = window.npcManager.inkEngineCache.get('container_test_npc');
|
||||
if (eqEngine?.story?.variablesState?._defaultGlobalVariables) {
|
||||
console.log('equipment-officer.ink variables:',
|
||||
Array.from(eqEngine.story.variablesState._defaultGlobalVariables.keys()));
|
||||
}
|
||||
```
|
||||
|
||||
## Expected Console Output
|
||||
|
||||
When everything is working correctly, you should see messages like:
|
||||
|
||||
```
|
||||
🌐 Initialized global variables: {player_joined_organization: false}
|
||||
✅ Synced player_joined_organization = false to story
|
||||
🔍 Auto-discovered global variable: player_joined_organization = false
|
||||
🌐 Global variable changed: player_joined_organization = true (from test_npc_back)
|
||||
📡 Broadcasted player_joined_organization = true to container_test_npc
|
||||
✅ Restored global variables: {player_joined_organization: true}
|
||||
```
|
||||
|
||||
## Common Issues & Solutions
|
||||
|
||||
### Issue: Full inventory option never appears
|
||||
|
||||
**Check:**
|
||||
1. Did you actually choose "Join organization"?
|
||||
```javascript
|
||||
console.log(window.gameState.globalVariables.player_joined_organization);
|
||||
```
|
||||
|
||||
2. Did the Equipment Officer conversation load?
|
||||
```javascript
|
||||
console.log(window.npcManager.inkEngineCache.has('container_test_npc'));
|
||||
```
|
||||
|
||||
3. Are the stories properly synced?
|
||||
```javascript
|
||||
const eqStory = window.npcManager.inkEngineCache.get('container_test_npc').story;
|
||||
console.log('Eq Officer has variable:', eqStory.variablesState.GlobalVariableExistsWithName('player_joined_organization'));
|
||||
console.log('Value:', eqStory.variablesState['player_joined_organization']);
|
||||
```
|
||||
|
||||
### Issue: Variable resets on page reload
|
||||
|
||||
**Check:**
|
||||
1. Was state actually saved?
|
||||
```javascript
|
||||
console.log(window.npcConversationStateManager.getNPCState('test_npc_back'));
|
||||
```
|
||||
|
||||
2. Does saved state have global snapshot?
|
||||
```javascript
|
||||
const state = window.npcConversationStateManager.getNPCState('test_npc_back');
|
||||
console.log('Global snapshot:', state?.globalVariablesSnapshot);
|
||||
```
|
||||
|
||||
### Issue: Changes not syncing to other NPCs
|
||||
|
||||
**Check:**
|
||||
1. Are multiple stories loaded?
|
||||
```javascript
|
||||
console.log('Loaded stories:', Array.from(window.npcManager.inkEngineCache.keys()));
|
||||
```
|
||||
|
||||
2. Does the variable exist in both stories?
|
||||
```javascript
|
||||
// Check each story's variables
|
||||
window.npcManager.inkEngineCache.forEach((engine, id) => {
|
||||
const exists = engine.story.variablesState.GlobalVariableExistsWithName('player_joined_organization');
|
||||
console.log(`${id}: has player_joined_organization =`, exists);
|
||||
});
|
||||
```
|
||||
|
||||
## Advanced Testing
|
||||
|
||||
### Test Auto-Discovery of global_* Variables
|
||||
|
||||
1. Create a new Ink file with:
|
||||
```ink
|
||||
VAR global_test_flag = false
|
||||
```
|
||||
|
||||
2. Add it to an NPC in scenario
|
||||
|
||||
3. Load that NPC's conversation
|
||||
|
||||
4. Check console:
|
||||
```javascript
|
||||
console.log(window.gameState.globalVariables);
|
||||
// Should auto-discover: { player_joined_organization: false, global_test_flag: false }
|
||||
```
|
||||
|
||||
### Test Modifying from Phaser Code
|
||||
|
||||
1. Get reference to game code:
|
||||
```javascript
|
||||
// In Phaser scene, emit an event
|
||||
window.dispatchEvent(new CustomEvent('player-achievement', {
|
||||
detail: { achievement: 'joined_org' }
|
||||
}));
|
||||
|
||||
// In listener code:
|
||||
window.addEventListener('player-achievement', (e) => {
|
||||
window.gameState.globalVariables.player_joined_organization = true;
|
||||
});
|
||||
```
|
||||
|
||||
2. Start new NPC conversation
|
||||
|
||||
3. Verify variable is synced
|
||||
|
||||
### Test Multiple Global Variables
|
||||
|
||||
1. Update `npc-sprite-test2.json`:
|
||||
```json
|
||||
"globalVariables": {
|
||||
"player_joined_organization": false,
|
||||
"reputation": 0,
|
||||
"quest_stage": 0
|
||||
}
|
||||
```
|
||||
|
||||
2. Add to Ink files:
|
||||
```ink
|
||||
VAR player_joined_organization = false
|
||||
VAR reputation = 0
|
||||
VAR quest_stage = 0
|
||||
```
|
||||
|
||||
3. Use in conditionals:
|
||||
```ink
|
||||
{reputation >= 5:
|
||||
You're well known around here
|
||||
}
|
||||
```
|
||||
|
||||
4. Test syncing multiple variables at once
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Initial state loads with correct defaults
|
||||
✅ Variable changes persist in window.gameState
|
||||
✅ Changes sync to other loaded stories in real-time
|
||||
✅ Menu options conditionally appear based on variables
|
||||
✅ State persists across page reloads
|
||||
✅ Console shows appropriate sync messages
|
||||
✅ No errors in browser console
|
||||
✅ Multiple variables can be managed simultaneously
|
||||
|
||||
## Performance Notes
|
||||
|
||||
The system is optimized for:
|
||||
- **Few global variables** (< 50 per scenario) ✅
|
||||
- **Multiple NPCs** (handles all loaded stories) ✅
|
||||
- **Event-driven syncing** (only syncs on change) ✅
|
||||
- **No circular loops** (prevents infinite propagation) ✅
|
||||
|
||||
If testing with > 100 global variables, monitor console for any performance impact.
|
||||
|
||||
|
||||
@@ -1,424 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Office Adventure Game - Scenario Selection</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
min-height: 100vh;
|
||||
background: #333;
|
||||
font-family: Arial, sans-serif;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.container {
|
||||
width: 80%;
|
||||
max-width: 800px;
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
border-radius: 10px;
|
||||
padding: 30px;
|
||||
box-shadow: 0 5px 20px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
.scenario-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.scenario-card {
|
||||
background: #444;
|
||||
border-radius: 5px;
|
||||
padding: 20px;
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
border: 1px solid #555;
|
||||
}
|
||||
|
||||
.scenario-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||
background: #4a4a4a;
|
||||
}
|
||||
|
||||
.scenario-title {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-bottom: 10px;
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
.scenario-description {
|
||||
font-size: 14px;
|
||||
color: #ccc;
|
||||
margin-bottom: 15px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.scenario-difficulty {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.difficulty-easy {
|
||||
background: #2ecc71;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.difficulty-medium {
|
||||
background: #f39c12;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.difficulty-hard {
|
||||
background: #e74c3c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.back-button {
|
||||
display: block;
|
||||
margin: 30px auto 0;
|
||||
padding: 10px 20px;
|
||||
background: #3498db;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
font-size: 16px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s;
|
||||
}
|
||||
|
||||
.back-button:hover {
|
||||
background: #2980b9;
|
||||
}
|
||||
|
||||
.scenario-cybok {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 15px;
|
||||
font-size: 12px;
|
||||
color: #aaa;
|
||||
}
|
||||
|
||||
.cybok-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
.cybok-list {
|
||||
margin: 0;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.cybok-list li {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.scenario-cybok-badges {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.cybok-badge {
|
||||
display: inline-block;
|
||||
padding: 3px 8px;
|
||||
border-radius: 3px;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
background: #2c3e50;
|
||||
color: #fff;
|
||||
cursor: help;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.cybok-badge:hover .cybok-tooltip {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.cybok-tooltip {
|
||||
display: none;
|
||||
position: absolute;
|
||||
bottom: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
width: 250px;
|
||||
z-index: 100;
|
||||
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
||||
font-weight: normal;
|
||||
font-size: 11px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.cybok-tooltip:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 50%;
|
||||
margin-left: -5px;
|
||||
border-width: 5px;
|
||||
border-style: solid;
|
||||
border-color: rgba(0, 0, 0, 0.9) transparent transparent transparent;
|
||||
}
|
||||
|
||||
.cybok-tooltip-title {
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
color: #3498db;
|
||||
}
|
||||
|
||||
.cybok-tooltip-list {
|
||||
margin: 0;
|
||||
padding-left: 15px;
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
.cybok-tooltip-list li {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Select a Scenario</h1>
|
||||
|
||||
<div class="scenario-list" id="scenario-list">
|
||||
<!-- Scenarios will be loaded here dynamically -->
|
||||
</div>
|
||||
|
||||
<button class="back-button" onclick="window.location.href='index.html'">Back to Main Game</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
// List of available scenarios
|
||||
const scenarios = [
|
||||
{
|
||||
id: "encoding_lab",
|
||||
title: "Encoding and Encryption Lab",
|
||||
description: "Recover your legendary cookie recipe from mischievous squirrels by solving various encoding and encryption challenges.",
|
||||
difficulty: "beginner",
|
||||
file: "scenarios/scenario4.json",
|
||||
cybok: [
|
||||
{ ka: "AC", topic: "Algorithms, Schemes and Protocols", keywords: ["Encoding vs Cryptography", "Caesar cipher", "Vigenere cipher", "SYMMETRIC CRYPTOGRAPHY - AES (ADVANCED ENCRYPTION STANDARD)"] },
|
||||
{ ka: "F", topic: "Artifact Analysis", keywords: ["Encoding and alternative data formats"] },
|
||||
{ ka: "WAM", topic: "Fundamental Concepts and Approaches", keywords: ["ENCODING", "BASE64"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "captain_meow",
|
||||
title: "Captain Meow's Disappearance",
|
||||
description: "Your beloved kitty sidekick, Captain Meow, has vanished without a trace! Follow the cryptic clues to find him before it's too late.",
|
||||
difficulty: "medium",
|
||||
file: "scenarios/scenario1.json",
|
||||
cybok: [
|
||||
{ ka: "F", topic: "Operating System Analysis", keywords: ["Steganography", "Encoding and alternative data formats", "SEARCH FOR EVIDENCE", "METADATA"] },
|
||||
{ ka: "POR", topic: "Privacy Technologies and Democratic Values", keywords: ["METADATA", "STEGANOGRAPHY"] },
|
||||
{ ka: "AC", topic: "Cryptographic Implementation", keywords: ["Cryptographic Libraries", "ENCRYPTION - TOOLS"] },
|
||||
{ ka: "AC", topic: "Physical Security", keywords: ["Fingerprint Authentication", "Bluetooth Security", "Physical Locks"] },
|
||||
{ ka: "AC", topic: "Hashing and Integrity", keywords: ["Hash Functions", "MD5 Hash"] },
|
||||
{ ka: "AC", topic: "Encoding and Representation", keywords: ["Base64 Encoding", "Octal Encoding", "Hexadecimal (Hex) Encoding"] },
|
||||
{ ka: "AC", topic: "Algorithms, Schemes and Protocols", keywords: ["ADVANCED ENCRYPTION STANDARD (AES)", "ECB (ELECTRONIC CODE BOOK) BLOCK CIPHER MODE"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "ceo_exfil",
|
||||
"title": "CEO Data Exfiltration",
|
||||
"description": "Infiltrate the CEO's office and exfiltrate sensitive company data. You'll need to bypass physical security and find ways to access restricted areas.",
|
||||
"difficulty": "medium",
|
||||
"file": "scenarios/ceo_exfil.json",
|
||||
"cybok": [
|
||||
{ "ka": "F", "topic": "Artifact Analysis", "keywords": ["digital evidence", "document analysis"] },
|
||||
{ "ka": "AAA", "topic": "Authorisation", "keywords": ["physical access control", "access control mechanisms"] },
|
||||
{ "ka": "WAM", "topic": "Fundamental Concepts and Approaches", "keywords": ["BLUETOOTH SECURITY", "DEVICE PAIRING"] }
|
||||
],
|
||||
"cybok_themes": [
|
||||
{ "ka": "LR", "topic": "Computer Crimes", "keywords": ["crimes against information systems", "evidence and proof", "CORPORATE ESPIONAGE"] },
|
||||
{ "ka": "F", "topic": "Definitions and Conceptual Models", "keywords": ["forensic science", "digital (forensic) trace", "conceptual models"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "cybok_heist",
|
||||
"title": "CyBOK Heist: Recover the LaTeX Files",
|
||||
"description": "You are a cybersecurity student tasked with recovering the Professor's backup of the CyBOK LaTeX source files for the CyBOK 1.1 release. Time to put your physical security skills to the test!",
|
||||
"difficulty": "beginner",
|
||||
"file": "scenarios/cybok_heist.json",
|
||||
"cybok": [
|
||||
{ "ka": "AC", "topic": "Cryptography", "keywords": ["Base64 encoding", "Password security"] },
|
||||
{ "ka": "AAA", "topic": "Access Control", "keywords": ["Physical locks", "Key-based access", "PIN-based access"] },
|
||||
{ "ka": "WAM", "topic": "Fundamental Concepts", "keywords": ["Knowledge Areas", "CyBOK Framework"] }
|
||||
],
|
||||
"cybok_themes": [
|
||||
{ "ka": "F", "topic": "Artifact Analysis", "keywords": ["Physical security", "Security through obscurity"] },
|
||||
{ "ka": "LR", "topic": "Ethical and Legal", "keywords": ["Educational security testing"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "asymmetric_encryption",
|
||||
title: "Asymmetric Encryption with RSA",
|
||||
description: "Solve cryptographic puzzles using RSA and Diffie-Hellman to escape from a cursed ghost town before you're turned into a llama!",
|
||||
difficulty: "intermediate",
|
||||
file: "scenarios/scenario2.json",
|
||||
cybok: [
|
||||
{ ka: "AC", topic: "Algorithms, Schemes and Protocols", keywords: ["CRYPTOGRAPHY - ASYMMETRIC - RSA", "DIFFIE-HELLMAN ALGORITHM"] },
|
||||
{ ka: "AC", topic: "Public-Key Cryptography", keywords: ["public-key encryption", "public-key signatures", "RSA MODULUS", "RSA PROBLEM", "RSA TRANSFORM"] },
|
||||
{ ka: "AC", topic: "Key Management", keywords: ["key generation"] },
|
||||
{ ka: "AC", topic: "Cryptographic Implementation", keywords: ["Cryptographic Libraries", "ENCRYPTION - TOOLS"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "symmetric_encryption",
|
||||
title: "Symmetric Encryption with AES",
|
||||
description: "Recover Dr. Knowitall's time machine blueprints by solving AES encryption puzzles before the self-destruct sequence activates.",
|
||||
difficulty: "intermediate",
|
||||
file: "scenarios/scenario3.json",
|
||||
cybok: [
|
||||
{ ka: "AC", topic: "Algorithms, Schemes and Protocols", keywords: ["ADVANCED ENCRYPTION STANDARD (AES)", "ECB (ELECTRONIC CODE BOOK) BLOCK CIPHER MODE"] },
|
||||
{ ka: "AC", topic: "Symmetric Cryptography", keywords: ["symmetric primitives", "symmetric encryption and authentication"] },
|
||||
{ ka: "AC", topic: "Cryptographic Implementation", keywords: ["Cryptographic Libraries", "ENCRYPTION - TOOLS", "Hexadecimal Encoding"] }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "biometric_breach",
|
||||
"title": "Biometric Security Breach",
|
||||
"description": "Test the company's biometric security systems by collecting and spoofing fingerprint data to gain unauthorized access.",
|
||||
"difficulty": "hard",
|
||||
"file": "scenarios/biometric_breach.json",
|
||||
"cybok": [
|
||||
{ "ka": "F", "topic": "Operating System Analysis", "keywords": ["Data acquisition", "BIOMETRIC ANALYSIS", "FINGERPRINT COLLECTION"] },
|
||||
{ "ka": "SOIM", "topic": "Monitor: Data Sources", "keywords": ["SECURITY LOGS", "ACCESS LOG ANALYSIS"] },
|
||||
{ "ka": "AAA", "topic": "Authorisation", "keywords": ["ACCESS CONTROL", "BIOMETRIC ACCESS CONTROLS", "IDENTITY VERIFICATION"] },
|
||||
{ "ka": "SOIM", "topic": "Execute: Mitigation and Countermeasures", "keywords": ["INCIDENT RESPONSE", "EVIDENCE RECOVERY"] }
|
||||
],
|
||||
"cybok_themes": [
|
||||
{ "ka": "LR", "topic": "Computer Crimes", "keywords": ["crimes against information systems", "evidence and proof", "INDUSTRIAL ESPIONAGE"] },
|
||||
{ "ka": "AAA", "topic": "Authentication", "keywords": ["BIOMETRIC AUTHENTICATION", "identity management", "authentication in distributed systems"] },
|
||||
{ "ka": "SOIM", "topic": "Human Factors: Incident Management", "keywords": ["incident response methodologies", "SECURITY INCIDENT INVESTIGATION"] }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
// Function to create scenario cards
|
||||
function createScenarioCards() {
|
||||
const scenarioList = document.getElementById('scenario-list');
|
||||
|
||||
// CyBOK Knowledge Area abbreviation mapping
|
||||
const cybokFullNames = {
|
||||
"IC": "Introduction to CyBOK",
|
||||
"FM": "Formal Methods",
|
||||
"RMG": "Risk Management & Governance",
|
||||
"LR": "Law & Regulation",
|
||||
"HF": "Human Factors",
|
||||
"POR": "Privacy & Online Rights",
|
||||
"MAT": "Malware & Attack Technologies",
|
||||
"AB": "Adversarial Behaviours",
|
||||
"SOIM": "Security Operations & Incident Management",
|
||||
"F": "Forensics",
|
||||
"C": "Cryptography",
|
||||
"AC": "Applied Cryptography",
|
||||
"OSV": "Operating Systems & Virtualisation Security",
|
||||
"DSS": "Distributed Systems Security",
|
||||
"AAA": "Authentication, Authorisation and Accountability",
|
||||
"SS": "Software Security",
|
||||
"WAM": "Web & Mobile Security",
|
||||
"SSL": "Secure Software Lifecycle",
|
||||
"NS": "Network Security",
|
||||
"HS": "Hardware Security",
|
||||
"CPS": "Cyber Physical Systems",
|
||||
"PLT": "Physical Layer and Telecommunications Security"
|
||||
};
|
||||
|
||||
scenarios.forEach(scenario => {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'scenario-card';
|
||||
card.onclick = function() {
|
||||
launchScenario(scenario.file);
|
||||
};
|
||||
|
||||
const difficultyClass = `difficulty-${scenario.difficulty.toLowerCase()}`;
|
||||
|
||||
let cybokHTML = '';
|
||||
if (scenario.cybok) {
|
||||
// Group by Knowledge Area
|
||||
const kaGroups = {};
|
||||
scenario.cybok.forEach(item => {
|
||||
if (!kaGroups[item.ka]) {
|
||||
kaGroups[item.ka] = [];
|
||||
}
|
||||
kaGroups[item.ka].push(item);
|
||||
});
|
||||
|
||||
const badgesHTML = Object.keys(kaGroups).map(ka => {
|
||||
const topics = kaGroups[ka];
|
||||
const kaFullName = cybokFullNames[ka] || ka;
|
||||
const tooltipContent = `
|
||||
<div class="cybok-tooltip-title">${kaFullName} Topics:</div>
|
||||
<ul class="cybok-tooltip-list">
|
||||
${topics.map(item => `
|
||||
<li>
|
||||
<strong>${item.topic}</strong>
|
||||
<ul>
|
||||
${item.keywords.map(keyword => `<li>${keyword}</li>`).join('')}
|
||||
</ul>
|
||||
</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
`;
|
||||
|
||||
return `
|
||||
<div class="cybok-badge">
|
||||
CyBOK ${ka}
|
||||
<div class="cybok-tooltip">
|
||||
${tooltipContent}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
cybokHTML = `
|
||||
<div class="scenario-cybok-badges">
|
||||
${badgesHTML}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
card.innerHTML = `
|
||||
<div class="scenario-title">${scenario.title}</div>
|
||||
<div class="scenario-description">${scenario.description}</div>
|
||||
${cybokHTML}
|
||||
<div class="scenario-difficulty ${difficultyClass}">${scenario.difficulty.toUpperCase()}</div>
|
||||
`;
|
||||
|
||||
scenarioList.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
||||
// Function to launch the game with selected scenario
|
||||
function launchScenario(scenarioFile) {
|
||||
window.location.href = `index.html?scenario=${encodeURIComponent(scenarioFile)}`;
|
||||
}
|
||||
|
||||
// Initialize the page
|
||||
document.addEventListener('DOMContentLoaded', createScenarioCards);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user