eaglelandsonce's picture
Update index.html
d0a5785 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Missing Values Tic-Tac-Toe</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gradient-to-br from-yellow-50 to-rose-100 min-h-screen flex items-center justify-center p-6">
<div class="w-full max-w-5xl bg-white rounded-2xl shadow-xl p-6">
<h1 class="text-3xl md:text-4xl font-extrabold text-center text-rose-700">Missing Values Tic-Tac-Toe</h1>
<p class="text-center text-sm text-gray-600 mt-2">
Source:
<a class="text-blue-600 underline" target="_blank" rel="noopener"
href="https://www.linkedin.com/pulse/creating-managing-missing-values-data-traditional-ai-driven-lively-eb3se/">
Creating and Managing Missing Values in Data — Michael Lively
</a>
</p>
<div id="banner" class="hidden bg-rose-100 border border-rose-300 text-rose-900 font-semibold text-center py-2 rounded mt-4"></div>
<div class="mt-6 flex flex-col md:flex-row md:space-x-6 space-y-4 md:space-y-0">
<!-- Board -->
<div id="board" class="grid grid-cols-3 gap-2 p-2 bg-gray-50 rounded-xl border-4 border-gray-200 mx-auto"></div>
<!-- Question Panel -->
<div id="questionPanel" class="md:w-1/2 w-full bg-gray-50 rounded-xl shadow-inner p-4">
<h2 id="panelQuestion" class="text-lg md: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>
<div class="mt-4 flex items-center space-x-2">
<button id="hintBtn" class="px-3 py-1.5 bg-gray-200 text-gray-700 rounded hover:bg-gray-300">Show Hint</button>
<button id="clearBtn" class="px-3 py-1.5 bg-white border rounded hover:bg-gray-100">Clear Panel</button>
</div>
</div>
</div>
<div class="flex flex-col md:flex-row md:items-center md:justify-between mt-6 space-y-3 md:space-y-0">
<p id="status" class="text-lg font-medium text-gray-800"></p>
<div class="flex items-center space-x-2">
<label class="text-sm text-gray-600">Mode:</label>
<select id="mode" class="border rounded px-2 py-1 text-sm">
<option value="two">Two Players (X vs O)</option>
<option value="solo">Solo (You are X)</option>
</select>
<button id="restartBtn" class="px-4 py-2 bg-rose-700 text-white rounded hover:bg-rose-800">Restart</button>
</div>
</div>
</div>
<script>
const randShuffle = (arr) => arr
.map(x => ({ x, r: Math.random() }))
.sort((a,b) => a.r - b.r)
.map(o => o.x);
// --- Question Bank (about Missing Values) ---
const QUESTION_BANK = [
{
question: 'Why do we sometimes create missing values deliberately?',
choices: [
'To corrupt the dataset permanently',
'To test imputation methods, stress-test models, and teach data handling',
'To hide sensitive features before analysis',
'To reduce dataset size'
],
answer: 2,
hint: 'Think about research, robustness, and teaching use cases.'
},
{
question: 'What does MCAR stand for?',
choices: [
'Missing Completely at Random',
'Managed Cases at Runtime',
'Mean Correction Algorithm Rule',
'Missing Computations in AI Regression'
],
answer: 1,
hint: 'It is the simplest type of missingness.'
},
{
question: 'Which traditional method is simplest but can distort variance?',
choices: [
'KNN Imputation',
'Mean/Median/Mode Imputation',
'Regression Imputation',
'GAN-based Imputation'
],
answer: 2,
hint: 'It just fills gaps with averages or modes.'
},
{
question: 'When is regression imputation best applied?',
choices: [
'When relationships are nonlinear',
'When values are missing completely at random',
'When strong linear correlations exist between variables',
'When text and tabular data are mixed'
],
answer: 3,
hint: 'Think straight-line relationships between variables.'
},
{
question: 'Which AI method iteratively predicts missing values for multiple variables?',
choices: ['Autoencoders', 'MICE', 'Bayesian Networks', 'GANs'],
answer: 2,
hint: 'Its name includes the word “Chained Equations”.'
},
{
question: 'Which deep learning model can reconstruct data by compressing and rebuilding inputs?',
choices: ['Decision Trees', 'Autoencoders', 'Support Vector Machines', 'Random Forests'],
answer: 2,
hint: 'It learns a latent representation of data.'
},
{
question: 'What makes GAN-based imputations (like GAIN) powerful?',
choices: [
'They always predict exact ground truth',
'They use adversarial training to generate realistic missing values',
'They only work for text data',
'They are deterministic and rule-based'
],
answer: 2,
hint: 'Think “generator vs. discriminator”.'
},
{
question: 'When is a Bayesian or EM approach most appropriate?',
choices: [
'When uncertainty must be quantified',
'When data is always complete',
'When no computation budget is available',
'When working only with images'
],
answer: 1,
hint: 'They provide distributions, not just point estimates.'
},
{
question: 'What type of data benefits most from Graph Neural Networks in imputation?',
choices: [
'Time series only',
'Graph-structured or relational data',
'Image pixel grids',
'Independent random samples'
],
answer: 2,
hint: 'Think networks: molecules, social media, transport.'
},
{
question: 'Which modern AI technique can handle hybrid text + tabular data?',
choices: [
'Self-supervised models and LLMs',
'Linear regression',
'Mode imputation',
'Support Vector Machines'
],
answer: 1,
hint: 'Think masked language models applied to structured data.'
}
];
// --- Game State ---
let currentPlayer, boardState, selectedCell, cellQuestions, mode;
const boardEl = document.getElementById('board');
const statusEl = document.getElementById('status');
const bannerEl = document.getElementById('banner');
const hintBtn = document.getElementById('hintBtn');
const clearBtn = document.getElementById('clearBtn');
const panelQuestion = document.getElementById('panelQuestion');
const panelChoices = document.getElementById('panelChoices');
const panelHint = document.getElementById('panelHint');
const restartBtn = document.getElementById('restartBtn');
const modeSel = document.getElementById('mode');
function initGame() {
mode = modeSel.value;
currentPlayer = 'X';
boardState = Array(9).fill('');
bannerEl.classList.add('hidden');
statusEl.innerText = '';
selectedCell = null;
const picked = randShuffle(QUESTION_BANK).slice(0, 9).map(q => {
const original = q.choices.map((c, i) => ({ text: c, idx: i + 1 }));
const shuffled = randShuffle(original);
const newChoices = shuffled.map(o => o.text);
const newAnswerIndex = shuffled.findIndex(o => o.idx === q.answer) + 1;
return {
question: q.question,
choices: newChoices,
answer: newAnswerIndex,
hint: q.hint || ''
};
});
cellQuestions = picked;
panelQuestion.innerText = 'Select a square to view the question';
panelChoices.innerHTML = '';
panelHint.classList.add('hidden');
panelHint.innerText = '';
renderBoard();
}
function renderBoard() {
boardEl.innerHTML = '';
boardState.forEach((mark, idx) => {
const btn = document.createElement('button');
let cls = 'bg-white h-24 w-24 md:h-28 md:w-28 flex items-center justify-center text-3xl font-extrabold rounded-xl shadow hover:bg-gray-100 transition';
if (mark === 'X') cls += ' text-rose-700';
if (mark === 'O') cls += ' text-sky-700';
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(currentPlayer)) return endGame(`${currentPlayer} wins!`);
if (boardState.every(c => c)) return endGame('Stalemate!');
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
statusEl.innerText = `Current: ${currentPlayer}`;
if (mode === 'solo' && currentPlayer === 'O') {
setTimeout(aiMove, 450);
}
} else {
alert('Incorrect! Turn missed.');
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
statusEl.innerText = `Current: ${currentPlayer}`;
if (mode === 'solo' && currentPlayer === 'O') {
setTimeout(aiMove, 450);
}
}
}
function checkWin(player) {
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] === player));
}
function endGame(msg) {
bannerEl.innerText = `🎉 ${msg}`;
bannerEl.classList.remove('hidden');
document.querySelectorAll('#board button').forEach(b => b.disabled = true);
}
function aiMove() {
const open = boardState.map((v,i) => v === '' ? i : null).filter(v => v !== null);
if (open.length === 0) return;
const pick = open[Math.floor(Math.random() * open.length)];
const q = cellQuestions[pick];
const aiCorrect = Math.random() < 0.55;
if (aiCorrect) {
boardState[pick] = 'O';
renderBoard();
if (checkWin('O')) return endGame('O wins!');
if (boardState.every(c => c)) return endGame('Stalemate!');
currentPlayer = 'X';
statusEl.innerText = `Current: ${currentPlayer}`;
} else {
currentPlayer = 'X';
statusEl.innerText = `Current: ${currentPlayer}`;
}
}
hintBtn.addEventListener('click', () => panelHint.classList.toggle('hidden'));
clearBtn.addEventListener('click', () => {
panelQuestion.innerText = 'Select a square to view the question';
panelChoices.innerHTML = '';
panelHint.classList.add('hidden');
panelHint.innerText = '';
});
restartBtn.addEventListener('click', initGame);
modeSel.addEventListener('change', initGame);
initGame();
</script>
</body>
</html>