eaglelandsonce's picture
Update index.html
717a140 verified
Raw
History Blame Contribute Delete
7.8 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Data Factory Intro TicTacToe</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gradient-to-br from-green-50 to-teal-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-teal-800">Data Factory Intro TicTacToe</h1>
<p class="text-center text-sm text-gray-600 mb-4">
Source: <a href="https://learn.microsoft.com/en-us/azure/data-factory/introduction"
class="text-blue-600 underline" target="_blank">
Azure Data Factory Introduction
</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-teal-700 text-white rounded hover:bg-teal-800">Restart</button>
</div>
</div>
<script>
const questions = [
{
question: 'What is Azure Data Factory primarily used for?',
choices: [
'Writing SQL queries',
'Orchestrating data movement and transformation',
'Hosting Power BI dashboards',
'Managing Kubernetes clusters'
],
answer: 2,
hint: 'Think about data workflows in the cloud.'
},
{
question: 'Which component defines the actions in a pipeline?',
choices: ['Integration Runtime', 'Linked Service', 'Activity', 'Dataset'],
answer: 3,
hint: 'It’s the smallest functional unit of work.'
},
{
question: 'What does a dataset represent?',
choices: ['A processing activity', 'Data schema and location', 'User identity', 'Network resource'],
answer: 2,
hint: 'It points to or references the data you use.'
},
{
question: 'What is a linked service in ADF?',
choices: ['Data storage itself', 'Connection information to resources', 'Transformation logic', 'Security policy'],
answer: 2,
hint: 'Think connection string to external resource.'
},
{
question: 'What is the purpose of Integration Runtime?',
choices: ['Define datasets', 'Provide compute environment', 'Visualize pipelines', 'Monitor logs'],
answer: 2,
hint: 'It powers data movement and transformation.'
},
{
question: 'Which transformation feature allows visual Spark-based logic?',
choices: ['Mapping Data Flows', 'Power BI', 'Azure Functions', 'Logic Apps'],
answer: 1,
hint: 'It abstracts Spark cluster complexity.'
},
{
question: 'How can pipelines be automated and version-controlled?',
choices: ['PowerShell only', 'CI/CD with Git or Azure DevOps', 'Manual export/import', 'Direct editing in portal'],
answer: 2,
hint: 'Best for DevOps and automation.'
},
{
question: 'How does ADF monitor pipeline executions?',
choices: ['Azure Monitor & UI', 'Export logs manually', 'Only email alerts', 'No monitoring'],
answer: 1,
hint: 'It integrates with Azure Monitor and portal UI.'
},
{
question: 'ADF supports ingestion from which data sources?',
choices: [
'Only Azure Blob Storage',
'Over 90 connectors including on-prem and cloud',
'Only REST APIs',
'Only SQL databases'
],
answer: 2,
hint: 'It integrates with many source types.'
}
];
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>