Files
Pokemon-Type-Quiz/src/main.ts
Tobias Christian Nauen 89c3cd91c2 first ai implementation
2026-03-05 17:36:08 +01:00

157 lines
4.5 KiB
TypeScript

import { Game } from './lib/game';
import { getTypeInfo, TypeName } from './lib/types';
import './style.css';
const app = document.getElementById('app')!;
const game = new Game(render);
game.nextQuestion();
function renderTypeBadge(name: TypeName, size: 'small' | 'large' = 'small'): string {
const info = getTypeInfo(name);
const sizeClass = size === 'large' ? 'type-badge-large' : '';
return `<span class="type-badge ${sizeClass}" style="background: ${info.backgroundColor}; color: ${info.color}">${info.name}</span>`;
}
function render(): void {
const state = game.getState();
const { options, startKey } = game.getOptions();
const stats = game.getStats();
if (!state.currentQuestion) {
app.innerHTML = '<div class="loading">Loading...</div>';
return;
}
const q = state.currentQuestion;
const defenderHtml = q.defenderTypes.length === 1
? renderTypeBadge(q.defenderTypes[0], 'large')
: `${renderTypeBadge(q.defenderTypes[0], 'large')} / ${renderTypeBadge(q.defenderTypes[1], 'large')}`;
const optionsHtml = options.map((opt, i) => {
let cls = 'option-btn';
if (state.showResult) {
if (opt.value === q.correctAnswer) {
cls += ' correct';
} else if (i === state.selectedIndex && !state.isCorrect) {
cls += ' wrong';
}
} else if (i === state.selectedIndex) {
cls += ' selected';
}
const shortcut = `${startKey + i}`;
const disabled = state.showResult ? 'disabled' : '';
return `
<button class="${cls}" data-index="${i}" ${disabled}>
<span class="option-key">${shortcut}</span>
<span class="option-label">${opt.label}</span>
</button>
`;
}).join('');
const resultHtml = state.showResult ? `
<div class="result ${state.isCorrect ? 'correct' : 'wrong'}">
${state.isCorrect
? '<div class="result-title">✓ Correct!</div>'
: `<div class="result-title">✗ Wrong</div>
<div class="explanation">${game.getExplanation()}</div>`
}
<button class="next-btn">Next Question (Enter)</button>
</div>
` : '';
app.innerHTML = `
<div class="game-container">
<header class="header">
<h1>Pokemon Type Quiz</h1>
<div class="stats">
<span class="stat">Streak: ${state.streak}</span>
<span class="stat">Accuracy: ${stats.accuracy.toFixed(1)}%</span>
<span class="stat">Total: ${stats.total}</span>
</div>
</header>
<div class="settings">
<label class="toggle">
<input type="checkbox" ${state.settings.allowDualTypes ? 'checked' : ''} id="dualToggle">
<span class="toggle-label">Allow Dual Types</span>
</label>
</div>
<div class="question">
<div class="question-label">Attacking Type</div>
<div class="attack-type">${renderTypeBadge(q.attackType, 'large')}</div>
<div class="vs">against</div>
<div class="question-label">Defending Type${q.defenderTypes.length > 1 ? 's' : ''}</div>
<div class="defender-types">${defenderHtml}</div>
</div>
<div class="options">
${optionsHtml}
</div>
${resultHtml}
<footer class="footer">
<span class="hint">Press ${startKey}-${startKey + options.length - 1} to select • Enter to continue</span>
</footer>
</div>
`;
attachEventListeners();
}
function attachEventListeners(): void {
document.querySelectorAll('.option-btn').forEach(btn => {
btn.addEventListener('click', () => {
const index = parseInt(btn.getAttribute('data-index')!);
game.selectAnswer(index);
});
});
const dualToggle = document.getElementById('dualToggle') as HTMLInputElement;
if (dualToggle) {
dualToggle.addEventListener('change', () => {
game.setAllowDualTypes(dualToggle.checked);
});
}
const nextBtn = document.querySelector('.next-btn');
if (nextBtn) {
nextBtn.addEventListener('click', () => {
game.nextQuestion();
});
}
}
document.addEventListener('keydown', (e) => {
const state = game.getState();
const { options, startKey } = game.getOptions();
if (state.showResult) {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
game.nextQuestion();
}
return;
}
const num = parseInt(e.key);
if (num >= startKey && num < startKey + options.length) {
e.preventDefault();
game.selectAnswer(num - startKey);
}
if (e.key === 'Enter') {
if (state.selectedAnswer !== null) {
e.preventDefault();
}
}
});
render();