ieeeColors = ({
navy: "#2C3E50",
teal: "#16A085",
orange: "#E67E22",
gray: "#7F8C8D",
red: "#c0392b",
green: "#27ae60",
purple: "#6B2D5B",
blue: "#3498DB"
})
// Violation types with descriptions
violationTypes = [
{
id: "consent_missing",
title: "Missing or Invalid Consent",
description: "No consent mechanism or consent not freely given, specific, informed, and unambiguous",
regulation: ["GDPR", "CCPA", "HIPAA", "COPPA"]
},
{
id: "consent_bundled",
title: "Bundled Consent",
description: "Consent bundled with terms of service or required for non-essential features",
regulation: ["GDPR", "CCPA"]
},
{
id: "data_excessive",
title: "Excessive Data Collection",
description: "Collecting more data than necessary for stated purpose (violates data minimization)",
regulation: ["GDPR", "CCPA", "HIPAA"]
},
{
id: "purpose_unclear",
title: "Unclear Purpose Specification",
description: "Purpose for data collection not clearly stated or too vague",
regulation: ["GDPR", "CCPA", "HIPAA"]
},
{
id: "deletion_missing",
title: "No Right to Deletion",
description: "No mechanism for users to request data deletion or right to be forgotten",
regulation: ["GDPR", "CCPA"]
},
{
id: "portability_missing",
title: "No Data Portability",
description: "No way for users to export their data in machine-readable format",
regulation: ["GDPR", "CCPA"]
},
{
id: "third_party_undisclosed",
title: "Undisclosed Third-Party Sharing",
description: "Sharing data with third parties without clear disclosure or consent",
regulation: ["GDPR", "CCPA", "HIPAA"]
},
{
id: "retention_indefinite",
title: "Indefinite Data Retention",
description: "No retention policy or keeping data longer than necessary",
regulation: ["GDPR", "CCPA", "HIPAA"]
},
{
id: "children_no_parental",
title: "Children's Data Without Parental Consent",
description: "Collecting data from children under 13/16 without verifiable parental consent",
regulation: ["COPPA", "GDPR"]
},
{
id: "security_inadequate",
title: "Inadequate Security Measures",
description: "No encryption, weak authentication, or insufficient data protection",
regulation: ["GDPR", "CCPA", "HIPAA"]
},
{
id: "pia_missing",
title: "Missing Privacy Impact Assessment",
description: "No PIA/DPIA conducted for high-risk data processing",
regulation: ["GDPR", "HIPAA"]
},
{
id: "dpo_missing",
title: "Missing Data Protection Officer",
description: "No DPO designated for large-scale sensitive data processing",
regulation: ["GDPR", "HIPAA"]
},
{
id: "breach_no_notification",
title: "No Breach Notification Plan",
description: "No process to notify users/authorities of data breaches within required timelines",
regulation: ["GDPR", "CCPA", "HIPAA"]
},
{
id: "cross_border_inadequate",
title: "Inadequate Cross-Border Transfer Safeguards",
description: "Transferring data internationally without adequacy decision or SCCs",
regulation: ["GDPR"]
},
{
id: "opt_out_missing",
title: "No Opt-Out for Data Sale",
description: "Selling personal data without providing clear opt-out mechanism",
regulation: ["CCPA"]
},
{
id: "privacy_by_design_missing",
title: "Privacy by Design Not Implemented",
description: "Privacy not built into system architecture from the start",
regulation: ["GDPR"]
}
]
// Deployment scenarios by difficulty level
scenarios = ({
consumer: [
{
id: 1,
title: "Smart Home Security Camera",
category: "Consumer IoT",
description: "A startup is launching a WiFi-enabled security camera for homes. The camera streams video to the cloud, uses facial recognition to identify family members, and shares clips with a third-party AI service for threat detection.",
productDetails: {
userLocation: "EU and USA",
dataCollected: "Video footage, facial biometrics, audio, device usage patterns, WiFi network info",
dataStorage: "Cloud storage in USA, retained indefinitely",
thirdParties: "AI analysis service (unencrypted sharing), cloud storage provider",
userInterface: "Mobile app with basic on/off toggle"
},
regulations: ["GDPR", "CCPA"],
violations: [
"consent_missing",
"data_excessive",
"retention_indefinite",
"third_party_undisclosed",
"portability_missing",
"pia_missing",
"cross_border_inadequate"
],
maxViolations: 7,
hint: "Focus on consent quality, data minimization, third-party sharing, and cross-border transfers."
},
{
id: 2,
title: "Kids' Smartwatch with GPS",
category: "Consumer IoT",
description: "A wearable device for children aged 6-12 that tracks location, allows calls, and has a companion app for parents. The company plans to use aggregate location data to create 'safety maps' and share insights with schools.",
productDetails: {
userLocation: "USA (all states)",
dataCollected: "Real-time GPS location, call logs, contacts, photos, voice messages, child's name and age",
dataStorage: "Cloud (USA), retained for 5 years for 'safety analytics'",
thirdParties: "School districts, mapping service, analytics partner",
userInterface: "Parent app with basic privacy settings"
},
regulations: ["COPPA", "CCPA"],
violations: [
"children_no_parental",
"consent_bundled",
"data_excessive",
"retention_indefinite",
"third_party_undisclosed",
"deletion_missing"
],
maxViolations: 6,
hint: "Children's data requires special protection. Check COPPA requirements and parental consent mechanisms."
},
{
id: 3,
title: "Voice-Activated Home Assistant",
category: "Consumer IoT",
description: "A smart speaker with always-on voice activation. It records conversations for 'quality improvement' and shares anonymized transcripts with advertisers. Privacy policy is accepted during setup.",
productDetails: {
userLocation: "EU, UK, and USA California",
dataCollected: "Voice recordings, conversation transcripts, device IDs, music preferences, shopping queries",
dataStorage: "Cloud indefinitely; 'anonymized' data sold to advertisers",
thirdParties: "Advertising networks, analytics companies, music services",
userInterface: "Mute button; settings accessible only via website"
},
regulations: ["GDPR", "CCPA"],
violations: [
"consent_bundled",
"purpose_unclear",
"opt_out_missing",
"retention_indefinite",
"third_party_undisclosed",
"portability_missing",
"deletion_missing"
],
maxViolations: 7,
hint: "Always-on recording raises consent issues. Check for bundled consent and data sale opt-out."
},
{
id: 4,
title: "Fitness Tracker with Health Insights",
category: "Consumer IoT",
description: "A wristband that monitors heart rate, sleep, steps, and GPS location. The app offers 'personalized health coaching' by sharing data with wellness companies and insurance partners.",
productDetails: {
userLocation: "EU and USA (multiple states)",
dataCollected: "Heart rate, sleep patterns, GPS routes, weight, age, gender, meal photos",
dataStorage: "Cloud storage, retained indefinitely for 'long-term health trends'",
thirdParties: "Wellness coaches, insurance companies, research institutions",
userInterface: "App with opt-in checkboxes (pre-selected) for 'enhanced features'"
},
regulations: ["GDPR", "CCPA"],
violations: [
"consent_bundled",
"data_excessive",
"third_party_undisclosed",
"retention_indefinite",
"pia_missing",
"purpose_unclear",
"deletion_missing"
],
maxViolations: 7,
hint: "Health data is sensitive. Pre-selected checkboxes aren't valid consent. Check insurance sharing."
}
],
healthcare: [
{
id: 5,
title: "Remote Patient Monitoring System",
category: "Healthcare IoT",
description: "A hospital deploys IoT devices to monitor patients at home (blood pressure, glucose, weight). Data is sent to doctors and shared with a cloud analytics platform for research.",
productDetails: {
userLocation: "USA (multiple states including California)",
dataCollected: "Vital signs, medications, diagnosis codes, doctor notes, patient demographics",
dataStorage: "Cloud provider (USA), retained for 7 years, encrypted at rest only",
thirdParties: "Cloud analytics platform, medical research institution (de-identified data)",
userInterface: "Nurse provides verbal consent during setup; no written authorization"
},
regulations: ["HIPAA", "CCPA"],
violations: [
"consent_missing",
"security_inadequate",
"third_party_undisclosed",
"dpo_missing",
"pia_missing",
"breach_no_notification"
],
maxViolations: 6,
hint: "HIPAA requires written authorization and Business Associate Agreements. Check encryption standards."
},
{
id: 6,
title: "Mental Health Chatbot App",
category: "Healthcare IoT",
description: "An AI-powered app for therapy sessions via text/voice. Conversations are stored indefinitely to 'improve AI algorithms' and anonymized transcripts are sold to pharmaceutical companies.",
productDetails: {
userLocation: "EU and USA",
dataCollected: "Therapy session transcripts, mental health diagnoses, mood logs, voice recordings",
dataStorage: "Cloud (USA), indefinite retention, third-party AI training service",
thirdParties: "AI training company, pharmaceutical research, academic institutions",
userInterface: "Click-through consent in app onboarding"
},
regulations: ["GDPR", "HIPAA", "CCPA"],
violations: [
"consent_missing",
"data_excessive",
"retention_indefinite",
"third_party_undisclosed",
"pia_missing",
"dpo_missing",
"purpose_unclear",
"cross_border_inadequate"
],
maxViolations: 8,
hint: "Mental health data is highly sensitive. Click-through consent isn't sufficient for HIPAA PHI."
},
{
id: 7,
title: "Smart Pill Dispenser",
category: "Healthcare IoT",
description: "A device that dispenses medication on schedule and tracks adherence. It sends data to caregivers and shares adherence statistics with pharmaceutical companies for 'medication effectiveness studies'.",
productDetails: {
userLocation: "USA and Canada",
dataCollected: "Medication names/doses, adherence rates, patient demographics, caregiver contacts",
dataStorage: "Cloud storage, retained for 10 years",
thirdParties: "Pharmaceutical companies, insurance providers, caregiver monitoring service",
userInterface: "Setup by caregiver; patient not informed of data sharing"
},
regulations: ["HIPAA", "CCPA"],
violations: [
"consent_missing",
"third_party_undisclosed",
"data_excessive",
"pia_missing",
"breach_no_notification",
"dpo_missing"
],
maxViolations: 6,
hint: "Patient must provide consent, not just caregiver. Pharma sharing needs explicit authorization."
},
{
id: 8,
title: "Hospital IoT Bed Sensors",
category: "Healthcare IoT",
description: "Sensors in hospital beds monitor patient movement, pressure points, and sleep. Data feeds into hospital EHR and is shared with equipment vendors for 'product improvement'.",
productDetails: {
userLocation: "USA (California) and EU",
dataCollected: "Patient movement, bed exit events, pressure ulcer risk scores, linked to medical records",
dataStorage: "Hospital servers + vendor cloud (EU), retained indefinitely",
thirdParties: "Medical equipment vendor, hospital IT department, maintenance service",
userInterface: "Patients sign general hospital admission forms (no specific IoT disclosure)"
},
regulations: ["HIPAA", "GDPR", "CCPA"],
violations: [
"consent_bundled",
"third_party_undisclosed",
"pia_missing",
"retention_indefinite",
"cross_border_inadequate",
"breach_no_notification"
],
maxViolations: 6,
hint: "General consent forms don't cover specific IoT data sharing. Check BAAs for vendors."
}
],
smartcity: [
{
id: 9,
title: "Smart City Traffic Monitoring",
category: "Smart City IoT",
description: "City deploys 500 cameras with facial recognition and license plate readers at intersections. Data is used for traffic optimization and shared with law enforcement. Historical footage is retained indefinitely.",
productDetails: {
userLocation: "EU city",
dataCollected: "Facial images, license plates, vehicle types, pedestrian counts, movement patterns",
dataStorage: "Municipal data center, indefinite retention",
thirdParties: "Law enforcement, traffic research institutes, city planning department",
userInterface: "Public signage about cameras; no opt-out mechanism"
},
regulations: ["GDPR"],
violations: [
"consent_missing",
"pia_missing",
"dpo_missing",
"retention_indefinite",
"purpose_unclear",
"data_excessive",
"privacy_by_design_missing"
],
maxViolations: 7,
hint: "Public surveillance requires legitimate interest justification and DPIA. Check necessity and proportionality."
},
{
id: 10,
title: "Smart Waste Management System",
category: "Smart City IoT",
description: "Trash bins with sensors to optimize collection routes. RFID tags on bins link to household addresses. The city shares bin usage data with recycling companies and uses it to enforce waste regulations.",
productDetails: {
userLocation: "USA California",
dataCollected: "Bin weight, collection times, household address, waste composition, violation history",
dataStorage: "City database, 7-year retention, shared with private contractors",
thirdParties: "Waste management companies, recycling processors, enforcement agency",
userInterface: "Included in city utility bills; no explicit consent mechanism"
},
regulations: ["CCPA"],
violations: [
"consent_missing",
"purpose_unclear",
"third_party_undisclosed",
"portability_missing",
"deletion_missing",
"opt_out_missing"
],
maxViolations: 6,
hint: "Household-level data is personal information under CCPA. Check disclosure and opt-out rights."
},
{
id: 11,
title: "Public WiFi with Location Tracking",
category: "Smart City IoT",
description: "City offers free WiFi that tracks user locations across access points to 'improve city services'. Movement data is anonymized and sold to retailers for foot traffic analysis.",
productDetails: {
userLocation: "EU and UK",
dataCollected: "Device MAC addresses, location history, dwell times, app usage (via DPI)",
dataStorage: "City servers + analytics partner cloud, indefinite for 'urban planning research'",
thirdParties: "Retail analytics companies, advertising networks, urban planning consultants",
userInterface: "Click-through terms of service when joining WiFi"
},
regulations: ["GDPR"],
violations: [
"consent_bundled",
"purpose_unclear",
"data_excessive",
"third_party_undisclosed",
"retention_indefinite",
"pia_missing",
"deletion_missing",
"cross_border_inadequate"
],
maxViolations: 8,
hint: "Location tracking and data sale require explicit consent. Click-through isn't enough for sensitive data."
},
{
id: 12,
title: "Smart Parking Enforcement",
category: "Smart City IoT",
description: "Parking spaces with sensors detect vehicles and link to license plate databases. The system tracks how long cars park and shares data with insurance companies for 'usage-based insurance' and with mall owners for customer insights.",
productDetails: {
userLocation: "USA (multiple states including California)",
dataCollected: "License plates, parking duration, GPS coordinates, linked vehicle owner info",
dataStorage: "City database + third-party cloud, 10-year retention",
thirdParties: "Insurance companies, shopping mall operators, analytics vendors",
userInterface: "Posted signage in parking areas; no privacy policy"
},
regulations: ["CCPA"],
violations: [
"consent_missing",
"third_party_undisclosed",
"opt_out_missing",
"retention_indefinite",
"purpose_unclear",
"portability_missing",
"deletion_missing"
],
maxViolations: 7,
hint: "License plate + owner info = personal data. Insurance and mall sharing needs clear disclosure."
}
]
})
// ----------------------------------------------------------------------------
// SECTION 2: GAME STATE MANAGEMENT
// ----------------------------------------------------------------------------
mutable gameState = ({
difficulty: "consumer",
currentScenarioIndex: 0,
score: 0,
answered: false,
selectedViolations: new Set(),
correctViolations: 0,
missedViolations: 0,
falsePositives: 0,
totalScenarios: 0,
gameComplete: false,
showFeedback: false,
scenarioScores: []
})
// Get current scenario
currentScenario = scenarios[gameState.difficulty][gameState.currentScenarioIndex]
// Calculate total scenarios for current difficulty
totalScenarios = scenarios[gameState.difficulty].length
// Get violation details by ID
function getViolationById(id) {
return violationTypes.find(v => v.id === id);
}
// ----------------------------------------------------------------------------
// SECTION 3: GAME LOGIC FUNCTIONS
// ----------------------------------------------------------------------------
function toggleViolation(violationId) {
if (gameState.answered) return;
const newSelected = new Set(gameState.selectedViolations);
if (newSelected.has(violationId)) {
newSelected.delete(violationId);
} else {
newSelected.add(violationId);
}
mutable gameState = { ...gameState, selectedViolations: newSelected };
}
function submitAnswer() {
if (gameState.answered) return;
const actualViolations = new Set(currentScenario.violations);
const selectedViolations = gameState.selectedViolations;
// Calculate correct, missed, and false positives
let correct = 0;
let missed = 0;
let falsePos = 0;
// Correct identifications
selectedViolations.forEach(v => {
if (actualViolations.has(v)) correct++;
else falsePos++;
});
// Missed violations
actualViolations.forEach(v => {
if (!selectedViolations.has(v)) missed++;
});
// Calculate score: +10 for each correct, -5 for each false positive, 0 for missed
const scenarioScore = Math.max(0, (correct * 10) - (falsePos * 5));
// Update total score
const newScores = [...gameState.scenarioScores, {
scenarioId: currentScenario.id,
correct,
missed,
falsePos,
score: scenarioScore,
maxPossible: actualViolations.size * 10
}];
mutable gameState = {
...gameState,
answered: true,
showFeedback: true,
score: gameState.score + scenarioScore,
correctViolations: gameState.correctViolations + correct,
missedViolations: gameState.missedViolations + missed,
falsePositives: gameState.falsePositives + falsePos,
totalScenarios: gameState.totalScenarios + 1,
scenarioScores: newScores
};
}
function nextScenario() {
const nextIndex = gameState.currentScenarioIndex + 1;
if (nextIndex >= scenarios[gameState.difficulty].length) {
mutable gameState = { ...gameState, gameComplete: true };
} else {
mutable gameState = {
...gameState,
currentScenarioIndex: nextIndex,
answered: false,
selectedViolations: new Set(),
showFeedback: false
};
}
}
function changeDifficulty(difficulty) {
mutable gameState = {
difficulty: difficulty,
currentScenarioIndex: 0,
score: 0,
answered: false,
selectedViolations: new Set(),
correctViolations: 0,
missedViolations: 0,
falsePositives: 0,
totalScenarios: 0,
gameComplete: false,
showFeedback: false,
scenarioScores: []
};
}
function restartGame() {
mutable gameState = {
...gameState,
currentScenarioIndex: 0,
score: 0,
answered: false,
selectedViolations: new Set(),
correctViolations: 0,
missedViolations: 0,
falsePositives: 0,
totalScenarios: 0,
gameComplete: false,
showFeedback: false,
scenarioScores: []
};
}
// ----------------------------------------------------------------------------
// SECTION 4: UI RENDERING
// ----------------------------------------------------------------------------
viewof privacyGame = {
const container = html`<div class="privacy-game-container">
<div class="game-header">
<h2>🔐 Privacy Compliance Audit Challenge</h2>
<p>Identify all privacy violations before product launch</p>
</div>
<div class="game-controls">
<button class="difficulty-btn consumer ${gameState.difficulty === 'consumer' ? 'active' : ''}"
onclick=${() => changeDifficulty('consumer')}>
🏠 Consumer IoT
</button>
<button class="difficulty-btn healthcare ${gameState.difficulty === 'healthcare' ? 'active' : ''}"
onclick=${() => changeDifficulty('healthcare')}>
🏥 Healthcare
</button>
<button class="difficulty-btn smartcity ${gameState.difficulty === 'smartcity' ? 'active' : ''}"
onclick=${() => changeDifficulty('smartcity')}>
🏙️ Smart City
</button>
</div>
<div class="progress-bar">
<div class="progress-fill" style="width: ${(gameState.currentScenarioIndex / totalScenarios) * 100}%"></div>
</div>
<div class="game-stats">
<div class="stat-card">
<div class="stat-value">${gameState.score}</div>
<div class="stat-label">Total Score</div>
</div>
<div class="stat-card">
<div class="stat-value">${gameState.currentScenarioIndex + 1}/${totalScenarios}</div>
<div class="stat-label">Scenario</div>
</div>
<div class="stat-card">
<div class="stat-value">${gameState.correctViolations}</div>
<div class="stat-label">Found</div>
</div>
<div class="stat-card">
<div class="stat-value">${gameState.missedViolations}</div>
<div class="stat-label">Missed</div>
</div>
</div>
<div id="game-content"></div>
</div>`;
const gameContent = container.querySelector("#game-content");
if (gameState.gameComplete) {
renderGameComplete(gameContent);
} else {
renderScenario(gameContent);
}
return container;
}
function renderScenario(container) {
const scenario = currentScenario;
const actualViolations = new Set(scenario.violations);
container.innerHTML = `
<div class="scenario-card">
<div class="scenario-header">
<div class="scenario-title">${scenario.title}</div>
<div class="scenario-badges">
<div class="scenario-number">Case ${scenario.id}</div>
${scenario.regulations.map(reg =>
`<span class="regulation-badge badge-${reg.toLowerCase()}">${reg}</span>`
).join('')}
</div>
</div>
<div class="scenario-description">
<strong>${scenario.category}:</strong> ${scenario.description}
</div>
<div class="product-details">
<h4>📋 Product/Service Details</h4>
<div class="detail-grid">
${Object.entries(scenario.productDetails).map(([key, value]) => `
<div class="detail-item">
<div class="detail-label">${formatLabel(key)}:</div>
<div class="detail-value">${value}</div>
</div>
`).join('')}
</div>
</div>
<div class="violations-section">
<div class="violations-title">
🔍 Privacy Audit: Select ALL violations you can identify (${scenario.maxViolations} total)
</div>
<div class="violation-options">
${violationTypes.map(violation => {
const isSelected = gameState.selectedViolations.has(violation.id);
const isActualViolation = actualViolations.has(violation.id);
let optionClass = 'violation-option';
let indicator = '';
if (gameState.answered) {
optionClass += ' disabled';
if (isSelected && isActualViolation) {
optionClass += ' correct';
indicator = '<span class="violation-indicator">✓</span>';
} else if (!isSelected && isActualViolation) {
optionClass += ' missed';
indicator = '<span class="violation-indicator">⚠️</span>';
} else if (isSelected && !isActualViolation) {
optionClass += ' incorrect';
indicator = '<span class="violation-indicator">✗</span>';
}
} else if (isSelected) {
optionClass += ' selected';
}
return `
<label class="${optionClass}">
<input type="checkbox"
class="violation-checkbox"
${isSelected ? 'checked' : ''}
${gameState.answered ? 'disabled' : ''}
onchange="toggleViolation('${violation.id}')">
<div class="violation-content">
<div class="violation-title">${violation.title}</div>
<div class="violation-description">${violation.description}</div>
</div>
${indicator}
</label>
`;
}).join('')}
</div>
</div>
<div class="hint-box">
<strong>💡 Hint:</strong> ${scenario.hint}
</div>
<div class="action-buttons">
<button class="action-btn submit"
onclick="submitAnswer()"
${gameState.answered ? 'disabled' : ''}>
✓ Submit Audit Report
</button>
<button class="action-btn next"
onclick="nextScenario()"
${!gameState.answered ? 'disabled' : ''}>
→ Next Case
</button>
</div>
<div class="feedback-panel ${gameState.showFeedback ? 'show' : ''} ${getFeedbackClass()}">
${gameState.showFeedback ? renderFeedback() : ''}
</div>
</div>
`;
}
function formatLabel(key) {
return key.split(/(?=[A-Z])/).map(word =>
word.charAt(0).toUpperCase() + word.slice(1)
).join(' ');
}
function getFeedbackClass() {
if (!gameState.answered) return '';
const lastScore = gameState.scenarioScores[gameState.scenarioScores.length - 1];
const accuracy = lastScore.correct / (lastScore.correct + lastScore.missed + lastScore.falsePos);
if (accuracy >= 0.9 && lastScore.falsePos === 0) return 'perfect';
if (accuracy >= 0.6) return 'partial';
return 'poor';
}
function renderFeedback() {
const scenario = currentScenario;
const actualViolations = new Set(scenario.violations);
const selectedViolations = gameState.selectedViolations;
const lastScore = gameState.scenarioScores[gameState.scenarioScores.length - 1];
const correct = [];
const missed = [];
const falsePos = [];
selectedViolations.forEach(v => {
if (actualViolations.has(v)) {
correct.push(getViolationById(v));
} else {
falsePos.push(getViolationById(v));
}
});
actualViolations.forEach(v => {
if (!selectedViolations.has(v)) {
missed.push(getViolationById(v));
}
});
let title = '';
let emoji = '';
if (lastScore.missed === 0 && lastScore.falsePos === 0) {
title = 'Perfect Audit!';
emoji = '🏆';
} else if (lastScore.correct >= lastScore.missed) {
title = 'Good Catch!';
emoji = '✅';
} else {
title = 'Audit Incomplete';
emoji = '📋';
}
return `
<div class="feedback-title">
${emoji} ${title}
</div>
<div class="feedback-score">
Score: ${lastScore.score} / ${lastScore.maxPossible} points
(${lastScore.correct} correct, ${lastScore.missed} missed, ${lastScore.falsePos} false positives)
</div>
<div class="feedback-content">
${correct.length > 0 ? `
<div class="feedback-section">
<h5>✅ Correctly Identified (${correct.length}):</h5>
<ul class="feedback-list">
${correct.map(v => `<li><strong>${v.title}:</strong> ${v.description}</li>`).join('')}
</ul>
</div>
` : ''}
${missed.length > 0 ? `
<div class="feedback-section" style="background: rgba(243, 156, 18, 0.2);">
<h5>⚠️ Missed Violations (${missed.length}):</h5>
<ul class="feedback-list">
${missed.map(v => `<li><strong>${v.title}:</strong> ${v.description} <em>(Required by: ${v.regulation.join(', ')})</em></li>`).join('')}
</ul>
</div>
` : ''}
${falsePos.length > 0 ? `
<div class="feedback-section" style="background: rgba(231, 76, 60, 0.2);">
<h5>✗ Incorrect Selections (${falsePos.length}):</h5>
<ul class="feedback-list">
${falsePos.map(v => `<li><strong>${v.title}:</strong> Not applicable in this scenario</li>`).join('')}
</ul>
</div>
` : ''}
<div class="feedback-section">
<h5>📚 Key Lessons:</h5>
<ul class="feedback-list">
${generateKeyLessons(scenario, missed, falsePos).map(lesson => `<li>${lesson}</li>`).join('')}
</ul>
</div>
</div>
`;
}
function generateKeyLessons(scenario, missed, falsePos) {
const lessons = [];
// Lesson based on scenario category
if (scenario.category === "Consumer IoT") {
lessons.push("Consumer IoT devices must obtain clear, specific consent for data collection and processing");
} else if (scenario.category === "Healthcare IoT") {
lessons.push("Healthcare IoT requires HIPAA-compliant written authorization and Business Associate Agreements");
} else if (scenario.category === "Smart City IoT") {
lessons.push("Public sector IoT must demonstrate legitimate interest and conduct Privacy Impact Assessments");
}
// Lessons from common missed violations
if (missed.some(v => v.id === 'pia_missing')) {
lessons.push("High-risk data processing (biometrics, health, location tracking) requires Privacy Impact Assessments");
}
if (missed.some(v => v.id === 'children_no_parental')) {
lessons.push("COPPA requires verifiable parental consent before collecting data from children under 13");
}
if (missed.some(v => v.id === 'third_party_undisclosed')) {
lessons.push("All third-party data sharing must be clearly disclosed with specific purposes");
}
if (missed.some(v => v.id === 'consent_bundled')) {
lessons.push("Consent cannot be bundled with terms of service or required for non-essential features");
}
// Regulation-specific lessons
if (scenario.regulations.includes('GDPR')) {
lessons.push("GDPR requires data minimization, purpose limitation, and storage limitation principles");
}
if (scenario.regulations.includes('CCPA')) {
lessons.push("CCPA mandates clear opt-out mechanisms for data sale and sensitive information use");
}
return lessons.slice(0, 4); // Limit to 4 key lessons
}
function renderGameComplete(container) {
const maxScore = gameState.scenarioScores.reduce((sum, s) => sum + s.maxPossible, 0);
const scorePercentage = Math.round((gameState.score / maxScore) * 100);
const totalPossibleViolations = gameState.scenarioScores.reduce((sum, s) =>
sum + s.correct + s.missed, 0
);
const detectionRate = Math.round((gameState.correctViolations / totalPossibleViolations) * 100);
let feedback, emoji;
if (scorePercentage >= 90 && gameState.falsePositives <= 2) {
feedback = "Outstanding! You're a privacy compliance expert!";
emoji = "🏆";
} else if (scorePercentage >= 75) {
feedback = "Great work! You have a strong understanding of privacy regulations!";
emoji = "🎉";
} else if (scorePercentage >= 60) {
feedback = "Good effort! Review the feedback to strengthen your compliance knowledge.";
emoji = "👍";
} else {
feedback = "Keep learning! Privacy compliance is complex - review the scenarios and try again.";
emoji = "📚";
}
container.innerHTML = `
<div class="game-complete">
<div class="complete-icon">${emoji}</div>
<div class="complete-title">Audit Complete!</div>
<div class="complete-score">
Final Score: ${gameState.score} / ${maxScore} (${scorePercentage}%)
</div>
<div class="complete-feedback">${feedback}</div>
<div class="performance-breakdown">
<h3 style="text-align: center; color: #2C3E50; margin-bottom: 16px;">Performance Summary</h3>
<div class="performance-item">
<span>Violations Correctly Identified:</span>
<strong style="color: #27ae60;">${gameState.correctViolations}</strong>
</div>
<div class="performance-item">
<span>Violations Missed:</span>
<strong style="color: #E67E22;">${gameState.missedViolations}</strong>
</div>
<div class="performance-item">
<span>False Positives:</span>
<strong style="color: #c0392b;">${gameState.falsePositives}</strong>
</div>
<div class="performance-item">
<span>Detection Rate:</span>
<strong style="color: #3498DB;">${detectionRate}%</strong>
</div>
</div>
<div style="margin: 24px 0; text-align: left; max-width: 700px; margin-left: auto; margin-right: auto;">
<h3>What You've Learned:</h3>
<ul style="line-height: 1.8;">
<li><strong>Consent Requirements:</strong> Must be freely given, specific, informed, and unambiguous (not bundled)</li>
<li><strong>Data Minimization:</strong> Only collect data necessary for stated, legitimate purposes</li>
<li><strong>User Rights:</strong> Provide deletion, portability, and access rights with clear mechanisms</li>
<li><strong>Third-Party Sharing:</strong> Requires explicit disclosure and appropriate safeguards</li>
<li><strong>Privacy by Design:</strong> Build privacy protections into system architecture from the start</li>
<li><strong>Impact Assessments:</strong> Conduct PIAs/DPIAs for high-risk data processing</li>
<li><strong>Special Categories:</strong> Children's data and health data require enhanced protections</li>
</ul>
</div>
<button class="restart-btn" onclick="restartGame()">
🔄 Audit More Cases
</button>
<div style="margin-top: 24px;">
<p style="font-size: 0.9em; color: #666;">
Try different difficulty levels to master Consumer IoT, Healthcare, and Smart City compliance!
</p>
</div>
</div>
`;
}
// Make functions globally accessible
window.toggleViolation = toggleViolation;