eaglelandsonce's picture
Update index.html
338c93a verified
Raw
History Blame Contribute Delete
8.86 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Data Factory TicTacToe</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gradient-to-br from-blue-50 to-indigo-100 flex items-center justify-center min-h-screen">
<div class="max-w-5xl w-full bg-white rounded-2xl shadow-lg p-6">
<h1 class="text-3xl font-extrabold mb-4 text-center text-indigo-800">Data Factory TicTacToe</h1>
<p class="text-center text-sm text-gray-600 mb-4">
Source: <a href="https://learn.microsoft.com/en-us/azure/architecture/databases/architecture/azure-data-factory-on-azure-landing-zones-baseline"
class="text-blue-600 underline"
target="_blank">
Azure Data Factory on Azure Landing Zones - Baseline
</a>
</p>
<div id="banner" class="hidden bg-green-100 border border-green-300 text-green-800 font-bold text-center py-2 rounded mb-4"></div>
<div class="flex items-start justify-center space-x-4">
<div id="board" class="grid grid-cols-3 gap-1 border-4 border-gray-300 rounded-lg p-2 bg-white mx-auto"></div>
<div id="questionPanel" class="w-1/2 bg-gray-50 rounded-lg shadow p-4">
<h2 id="panelQuestion" class="text-xl font-semibold text-gray-800">Select a square to view the question</h2>
<ul id="panelChoices" class="mt-4 space-y-2"></ul>
<p id="panelHint" class="mt-3 text-sm text-gray-600 hidden"></p>
<button id="hintBtn" class="mt-4 px-3 py-1 bg-gray-200 text-gray-700 rounded hover:bg-gray-300">Show Hint</button>
</div>
</div>
<div class="flex justify-between mt-6">
<p id="status" class="text-lg font-medium text-gray-800"></p>
<button id="restartBtn" class="px-4 py-2 bg-indigo-700 text-white rounded hover:bg-indigo-800">Restart</button>
</div>
</div>
<script>
const questions = [
{
question: 'What role does Azure Data Factory play in a landing zone architecture?',
choices: [
'Used only for SQL data ingestion',
'Mainly responsible for security policies',
'Orchestrates and operationalizes data movement and transformation',
'Acts as a backup tool for Azure Blob storage'
],
answer: 3,
hint: 'Think of it as a control tower for your data.'
},
{
question: 'What is a recommended best practice for integrating ADF in an enterprise-scale landing zone?',
choices: [
'Deploy ADF in the sandbox environment only',
'Use managed virtual networks and private endpoints',
'Always expose ADF over the public internet',
'Avoid using parameterized pipelines'
],
answer: 2,
hint: 'Security and isolation are key.'
},
{
question: 'Why should managed identity be enabled for ADF?',
choices: [
'To allow GitHub integration',
'To access other Azure services securely',
'To improve dashboard rendering',
'To manage DNS zones'
],
answer: 2,
hint: 'It’s a way for ADF to securely authenticate with other resources.'
},
{
question: 'What type of data flow can be used within ADF for transformation at scale?',
choices: [
'Synapse pipelines',
'Mapping Data Flows',
'Azure Monitor logs',
'Power BI models'
],
answer: 2,
hint: 'It’s a visual data transformation feature built into ADF.'
},
{
question: 'ADF pipelines are best managed with which DevOps approach?',
choices: [
'Drag and drop only',
'Random deployment',
'CI/CD using Git integration and Azure DevOps',
'PowerShell only deployments'
],
answer: 3,
hint: 'Think automation, source control, and repeatability.'
},
{
question: 'What’s the benefit of using a managed VNet in ADF?',
choices: [
'More internet bandwidth',
'Can bypass firewalls',
'Enables secure access to data sources without public exposure',
'Increases billing efficiency'
],
answer: 3,
hint: 'This feature is important for securing access to data sources.'
},
{
question: 'Which Azure service is often paired with ADF for data storage in a pipeline?',
choices: [
'Azure Bastion',
'Azure Blob Storage or Data Lake',
'Azure Kubernetes Service',
'Azure Front Door'
],
answer: 2,
hint: 'Think storage for structured and unstructured data.'
},
{
question: 'What helps ensure traceability and observability in ADF pipelines?',
choices: [
'Private DNS Zones',
'Diagnostic Settings with Log Analytics',
'Azure Load Balancer',
'Virtual Machines'
],
answer: 2,
hint: 'Logs, metrics, and monitoring dashboards.'
},
{
question: 'What should be used to protect ADF against data exfiltration?',
choices: [
'NSG rules alone',
'Private endpoints and VNet integration',
'Disabling all triggers',
'Using public endpoints only'
],
answer: 2,
hint: 'Prevent data leakage by restricting public access.'
}
];
let currentPlayer, boardState, cellQuestions, selectedCell;
const boardEl = document.getElementById('board');
const statusEl = document.getElementById('status');
const bannerEl = document.getElementById('banner');
const hintBtn = document.getElementById('hintBtn');
const panelQuestion = document.getElementById('panelQuestion');
const panelChoices = document.getElementById('panelChoices');
const panelHint = document.getElementById('panelHint');
const restartBtn = document.getElementById('restartBtn');
function initGame() {
currentPlayer = 'X';
boardState = Array(9).fill('');
bannerEl.classList.add('hidden');
statusEl.innerText = '';
const shuffled = questions.sort(() => 0.5 - Math.random());
cellQuestions = shuffled.slice(0, 9);
panelQuestion.innerText = 'Select a square to view the question';
panelChoices.innerHTML = '';
panelHint.classList.add('hidden');
renderBoard();
}
function renderBoard() {
boardEl.innerHTML = '';
boardState.forEach((mark, idx) => {
const btn = document.createElement('button');
let cls = 'bg-white h-24 w-24 flex items-center justify-center text-2xl font-bold rounded-lg shadow hover:bg-gray-100';
if (mark === 'X') cls += ' text-blue-600';
if (mark === 'O') cls += ' text-red-600';
btn.className = cls;
btn.innerText = mark;
btn.disabled = mark !== '';
btn.addEventListener('click', () => openQuestion(idx));
boardEl.appendChild(btn);
});
statusEl.innerText = `Current: ${currentPlayer}`;
}
function openQuestion(idx) {
selectedCell = idx;
const q = cellQuestions[idx];
panelQuestion.innerText = q.question;
panelChoices.innerHTML = '';
panelHint.classList.add('hidden');
panelHint.innerText = q.hint;
q.choices.forEach((c, i) => {
const li = document.createElement('li');
const btn = document.createElement('button');
btn.innerText = c;
btn.className = 'w-full text-left px-4 py-2 bg-gray-100 rounded hover:bg-gray-200';
btn.addEventListener('click', () => handleAnswer(i + 1));
li.appendChild(btn);
panelChoices.appendChild(li);
});
}
function handleAnswer(choice) {
const q = cellQuestions[selectedCell];
if (choice === q.answer) {
boardState[selectedCell] = currentPlayer;
renderBoard();
if (checkWin()) return endGame(`${currentPlayer} wins!`);
if (boardState.every(c => c)) return endGame('Stalemate!');
} else {
alert('Incorrect! Turn missed.');
}
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
statusEl.innerText = `Current: ${currentPlayer}`;
}
function checkWin() {
const wins = [
[0,1,2],[3,4,5],[6,7,8],
[0,3,6],[1,4,7],[2,5,8],
[0,4,8],[2,4,6]
];
return wins.some(combo => combo.every(i => boardState[i] === currentPlayer));
}
function endGame(msg) {
bannerEl.innerText = `🎉 ${msg}`;
bannerEl.classList.remove('hidden');
document.querySelectorAll('#board button').forEach(b => b.disabled = true);
}
hintBtn.addEventListener('click', () => panelHint.classList.toggle('hidden'));
restartBtn.addEventListener('click', initGame);
initGame();
</script>
</body>
</html>