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>