eaglelandsonce's picture
Update index.html
3d761ef verified
Raw
History Blame Contribute Delete
10.2 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Classification Tic Tac Toe</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 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">Classification Tic Tac Toe</h1>
<p class="text-center mb-4 text-sm text-gray-600">
Reference: <a href="https://www.linkedin.com/pulse/generative-ai-action-building-end-to-end-text-pipelines-lively-qur9e" class="text-teal-600 hover:underline" target="_blank">Generative AI Action: Building End-to-End Text Pipelines</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">
<!-- Game Board -->
<div id="board" class="grid grid-cols-3 gap-1 border-4 border-teal-300 rounded-lg p-2 bg-white mx-auto"></div>
<!-- Question Panel -->
<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-600 text-white rounded hover:bg-teal-700">Restart</button>
</div>
</div>
<script>
const questions = [
{
question: 'What is the primary difference between Text-to-Label and Text-to-Text tasks?',
choices: [
'They both generate text',
'Text-to-Label assigns categories; Text-to-Text generates new text',
'Text-to-Label uses images; Text-to-Text uses audio',
'They require the same prompt structure'
],
answer: 2,
hint: 'One is classification, the other is generation.'
},
{
question: 'Which metric quantifies the harmonic mean of precision and recall?',
choices: ['Accuracy', 'F1 Score', 'Precision', 'Recall'],
answer: 2,
hint: 'It balances false positives and false negatives.'
},
{
question: 'What summarization method selects important sentences directly from the source?',
choices: ['Abstractive', 'Extractive', 'Generative', 'Reductive'],
answer: 2,
hint: 'It works by splicing source sentences.'
},
{
question: 'Which classification approach assigns categories without any task-specific training data?',
choices: ['Few-shot', 'Zero-shot', 'Fine-tuning', 'Reinforcement learning'],
answer: 2,
hint: 'No labeled examples are provided.'
},
{
question: 'In Aspect-Based Sentiment Classification, what does ABSC pinpoint?',
choices: [
'Overall sentiment',
'Sentiment on specific aspects',
'Grammar errors',
'Translation quality'
],
answer: 2,
hint: 'It isolates sentiment for individual topics.'
},
{
question: 'Which library is used to score abstractive summaries with ROUGE-L?',
choices: ['nltk', 'sklearn', 'rouge_score', 'transformers'],
answer: 3,
hint: 'Its name starts with "rouge".'
},
{
question: 'What is a common pitfall when relying solely on automated metrics?',
choices: [
'Missing edge cases',
'Overfitting data',
'Slow inference',
'High cost'
],
answer: 1,
hint: 'You might overlook unusual inputs.'
},
{
question: 'What practice helps detect model drift over time?',
choices: [
'Data augmentation',
'Ongoing monitoring',
'One-time evaluation',
'Hyperparameter tuning'
],
answer: 2,
hint: 'It involves continuous checks.'
},
{
question: 'In hands-on exercises, which tool is suggested for building a real-time aspect-sentiment dashboard?',
choices: ['Flask', 'Streamlit', 'Django', 'Dash'],
answer: 2,
hint: 'A Python app framework with instant reload.'
}
];
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');
// Utility: in-place shuffle
function shuffle(arr) {
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
// Build a balanced list of target positions for the correct answer (1..k)
function buildBalancedPositions(nQuestions, kChoices) {
const base = Math.floor(nQuestions / kChoices); // minimum per slot
const remainder = nQuestions % kChoices; // spread extras
const slots = [];
for (let pos = 1; pos <= kChoices; pos++) {
for (let c = 0; c < base; c++) slots.push(pos);
}
// distribute remainder to random positions
const extra = shuffle(Array.from({length: kChoices}, (_, i) => i + 1)).slice(0, remainder);
slots.push(...extra);
return shuffle(slots); // random order across questions
}
function initGame() {
currentPlayer = 'X';
boardState = Array(9).fill('');
bannerEl.classList.add('hidden');
statusEl.innerText = '';
// Pick 9 questions at random
const shuffledQs = shuffle([...questions]).slice(0, 9);
// For 4-choice questions, balance the correct-answer positions ~evenly
const kChoices = 4;
const targetPositions = buildBalancedPositions(shuffledQs.length, kChoices); // 1..4
// For each question, place the correct choice at its assigned target slot,
// and fill the rest with shuffled distractors.
cellQuestions = shuffledQs.map((q, idx) => {
const originalCorrectIdx0 = q.answer - 1; // convert to 0-based
const correctText = q.choices[originalCorrectIdx0];
const wrongs = q.choices.filter((_, i) => i !== originalCorrectIdx0);
shuffle(wrongs);
const targetPos1 = targetPositions[idx]; // 1..4
const targetPos0 = targetPos1 - 1; // 0..3
const newChoices = Array(kChoices).fill(null);
newChoices[targetPos0] = correctText;
// Fill remaining slots with wrong answers
let w = 0;
for (let i = 0; i < kChoices; i++) {
if (newChoices[i] === null) {
newChoices[i] = wrongs[w++];
}
}
return {
question: q.question,
choices: newChoices,
answer: targetPos1, // 1-based
hint: q.hint
};
});
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-teal-50 rounded hover:bg-teal-100';
btn.addEventListener('click', () => handleAnswer(i + 1)); // keep 1-based
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>