Spaces:
Running
Running
File size: 9,660 Bytes
df2e204 f0fe359 df2e204 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Masking Millionaire</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-100 min-h-screen flex items-center justify-center p-6">
<div class="bg-white p-8 rounded-2xl shadow-xl w-full max-w-2xl">
<h1 class="text-4xl font-bold text-indigo-600 text-center mb-2">Masking Millionaire</h1>
<p class="text-center text-sm text-gray-500 mb-6">
Content source:
<a href="https://learn.microsoft.com/en-us/fabric/data-warehouse/dynamic-data-masking"
target="_blank"
class="underline hover:text-indigo-700">
Dynamic Data Masking in Fabric Data Warehouse
</a>
</p>
<div id="board">
<div id="question" class="text-2xl font-semibold text-gray-800 mb-4"></div>
<div id="choices" class="space-y-3"></div>
<div id="lifelines" class="flex justify-around mt-6">
<button id="life5050" class="lifeline bg-yellow-400 hover:bg-yellow-500 text-white font-medium py-2 px-4 rounded-lg shadow">
50:50
</button>
<button id="lifePoll" class="lifeline bg-blue-400 hover:bg-blue-500 text-white font-medium py-2 px-4 rounded-lg shadow">
Ask the Class
</button>
<button id="lifeHint" class="lifeline bg-green-400 hover:bg-green-500 text-white font-medium py-2 px-4 rounded-lg shadow">
Ask an Expert
</button>
</div>
<div id="poll" class="text-sm text-gray-700 mt-4"></div>
<div id="hint" class="text-sm italic text-gray-600 mt-2"></div>
<button id="next" class="hidden mt-8 bg-indigo-600 hover:bg-indigo-700 text-white font-semibold py-2 px-6 rounded-lg shadow">
Next Question
</button>
</div>
</div>
<script>
// Masking quiz data
const questions = [
{ q: "Which feature simplifies obfuscation of sensitive data without modifying existing application queries?", choices: ["Column-level security","Dynamic data masking","Row-level security","Transparent data encryption"], correct: 1, hint: "It applies masks at query results, not at storage." },
{ q: "How many built-in masking functions does dynamic data masking provide in Fabric Data Warehouse?", choices: ["2","3","4","5"], correct: 2, hint: "The options: default, email, random, custom string." },
{ q: "Which mask function replaces string data with 'XXXX' based on data type?", choices: ["default()","email()","random()","partial()"], correct: 0, hint: "This is full masking according to the data type." },
{ q: "Which mask function exposes the first letter of an email and the constant suffix '.com'?", choices: ["default()","email()","random()","partial()"], correct: 1, hint: "It formats answer like aXXX@XXXX.com." },
{ q: "Which function masks numeric data with a random value within a specified range?", choices: ["default()","email()","random(start,end)","partial()"], correct: 2, hint: "Syntax: random([start],[end])." },
{ q: "Which masking function allows you to expose prefix and suffix with custom padding?", choices: ["default()","email()","random()","partial(prefix,pad,suffix)"], correct: 3, hint: "It’s called 'partial'." },
{ q: "Which Transact-SQL command is used to add a mask to an existing column?", choices: ["ADD MASK","MASK COLUMN","ALTER COLUMN... ADD MASKED WITH","CREATE MASK"], correct: 2, hint: "Use ALTER COLUMN ... ADD MASKED WITH." },
{ q: "Which permission is required to add, replace, or remove a mask on a column?", choices: ["UNMASK","ALTER ANY MASK","CONTROL","SELECT"], correct: 1, hint: "This permission targets mask operations." },
{ q: "Which permission grants a user the ability to view unmasked data specifically?", choices: ["UNMASK","ALTER ANY MASK","CONTROL","SELECT"], correct: 0, hint: "It’s literally named UNMASK." },
{ q: "The CONTROL permission on the database includes which of the following?", choices: ["UNMASK only","ALTER ANY MASK only","Both UNMASK and ALTER ANY MASK","None of the above"], correct: 2, hint: "It covers full mask management." },
{ q: "Dynamic data masking in Fabric Data Warehouse is complementary to which security feature?", choices: ["Transparent data encryption","Column-level security","Backup encryption","Data classification"], correct: 1, hint: "Think of restricting rows and fields." },
{ q: "By default, what value is used to mask datetime columns?", choices: ["0000-00-00","1900-01-01 00:00:00.0000000","1970-01-01","NULL"], correct: 1, hint: "It uses SQL Server’s default minimal date." },
{ q: "What is a limitation of dynamic data masking regarding security?", choices: ["Cannot mask numeric data","Protects against brute-force inference","Only applies to SELECT queries","Doesn't prevent malicious inference"], correct: 3, hint: "Unprivileged users can still infer data." },
{ q: "Who sees unmasked data by default in a masked table?", choices: ["Contributors","All database users","Unprivileged users","All users"], correct: 0, hint: "Workspace roles like Admin, Member or Contributor." },
{ q: "Which object-level security should you combine with dynamic data masking?", choices: ["Row-level security only","Column-level security only","Both row-level and column-level security","None"], correct: 2, hint: "Use multiple data protection features." }
];
const prizes = [100,200,300,500,1000,2000,4000,8000,16000,32000,64000,125000,250000,500000,1000000];
let idx = 0;
let currentPrize = prizes[0];
// Redistribute correct answers evenly across A–D
questions.forEach((q, i) => {
const target = i % 4;
if (q.correct !== target) {
[q.choices[target], q.choices[q.correct]] = [q.choices[q.correct], q.choices[target]];
q.correct = target;
}
});
const qEl = document.getElementById('question');
const cEl = document.getElementById('choices');
const pollEl = document.getElementById('poll');
const hintEl = document.getElementById('hint');
const nextBtn = document.getElementById('next');
const boardEl = document.getElementById('board');
function updateQuestionDisplay() {
qEl.textContent = `$${currentPrize}: ${questions[idx].q}`;
}
function showQuestion() {
['life5050','lifePoll','lifeHint'].forEach(id => {
const btn = document.getElementById(id);
btn.disabled = false;
btn.classList.remove('opacity-50');
});
pollEl.textContent = '';
hintEl.textContent = '';
nextBtn.classList.add('hidden');
currentPrize = prizes[idx];
updateQuestionDisplay();
cEl.innerHTML = questions[idx].choices.map((ch,i) =>
`<button class="choice bg-indigo-500 hover:bg-indigo-600 text-white font-medium py-2 px-4 rounded w-full" data-i="${i}">` +
`${String.fromCharCode(65+i)}. ${ch}</button>`
).join('');
document.querySelectorAll('.choice').forEach(btn => {
btn.disabled = false;
btn.onclick = selectAnswer;
});
}
function selectAnswer(e) {
const chosen = +e.target.dataset.i;
const corr = questions[idx].correct;
document.querySelectorAll('.choice').forEach(b => b.disabled = true);
if (chosen === corr) {
e.target.classList.replace('bg-indigo-500','bg-green-500');
} else {
e.target.classList.replace('bg-indigo-500','bg-red-500');
document.querySelector(`.choice[data-i="${corr}"]`).classList.replace('bg-indigo-500','bg-green-500');
}
nextBtn.classList.remove('hidden');
}
// 50:50 Lifeline
document.getElementById('life5050').onclick = () => {
const btn = document.getElementById('life5050');
if (btn.disabled) return;
btn.disabled = true;
btn.classList.add('opacity-50');
const corr = questions[idx].correct;
questions[idx].choices
.map((_, i) => i)
.filter(i => i !== corr)
.sort(() => Math.random() - 0.5)
.slice(0, 2)
.forEach(i => {
const b = document.querySelector(`.choice[data-i="${i}"]`);
b.disabled = true;
b.classList.add('opacity-50');
});
currentPrize = Math.floor(currentPrize / 2);
updateQuestionDisplay();
};
// Ask the Class
document.getElementById('lifePoll').onclick = () => {
const btn = document.getElementById('lifePoll');
if (btn.disabled) return;
btn.disabled = true;
btn.classList.add('opacity-50');
const corr = questions[idx].correct;
const pct = [0,0,0,0];
pct[corr] = 70 + Math.floor(Math.random() * 21);
let rem = 100 - pct[corr];
questions[idx].choices.forEach((_, i) => {
if (i !== corr) {
const alloc = Math.floor(rem / 3);
pct[i] = alloc;
rem -= alloc;
}
});
pollEl.textContent = `Class Poll: A:${pct[0]}% B:${pct[1]}% C:${pct[2]}% D:${pct[3]}%`;
};
// Ask an Expert
document.getElementById('lifeHint').onclick = () => {
const btn = document.getElementById('lifeHint');
if (btn.disabled) return;
btn.disabled = true;
btn.classList.add('opacity-50');
hintEl.textContent = `Expert Hint: ${questions[idx].hint}`;
};
// Next Question
nextBtn.onclick = () => {
idx++;
if (idx < questions.length) {
showQuestion();
} else {
boardEl.innerHTML = '<div class="text-3xl font-bold text-green-600 text-center">🎉 Congratulations! You’ve mastered Masking Millionaire! 🎉</div>';
}
};
// Start
showQuestion();
</script>
</body>
</html>
|