undefined / index.html
Magneticdogson's picture
улучши код, доюбавь свои предложения и переведи на русский язык
a398606 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Math Whiskers: Гениальные математические котики</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f3f4f6;
overflow-x: hidden;
}
.container {
max-width: 600px;
}
.vibrant-button {
background-image: linear-gradient(to right, #4ade80, #16a34a);
transition: all 0.3s ease-in-out;
}
.vibrant-button:hover {
transform: scale(1.05);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
@keyframes bounce {
0%, 100% {
transform: translateY(-25%);
animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
}
50% {
transform: translateY(0);
animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
}
}
.animate-bounce-slow {
animation: bounce 2s infinite;
}
@keyframes pop-up {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
.animate-pop {
animation: pop-up 0.5s ease-in-out;
}
@keyframes shake {
10%, 90% { transform: translate3d(-1px, 0, 0); }
20%, 80% { transform: translate3d(2px, 0, 0); }
30%, 50%, 70% { transform: translate3d(-4px, 0, 0); }
40%, 60% { transform: translate3d(4px, 0, 0); }
}
.animate-shake {
animation: shake 0.82s cubic-bezier(.36,.07,.19,.97) both;
}
@keyframes slide-in {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
.animate-slide-in {
animation: slide-in 0.5s ease-out forwards;
}
.correct-answer-button {
background-color: #10b981;
color: white;
animation: pop-up 0.5s ease-in-out;
}
.incorrect-answer-button {
background-color: #ef4444;
color: white;
animation: shake 0.5s ease-in-out;
}
.confetti {
position: absolute;
width: 10px;
height: 10px;
background-color: var(--color);
border-radius: 50%;
opacity: 0;
animation: confetti-fall 2.5s ease-out forwards;
}
@keyframes confetti-fall {
0% {
transform: translateY(0) rotate(0deg);
opacity: 1;
}
100% {
transform: translateY(100vh) rotate(720deg);
opacity: 0;
}
}
</style>
</head>
<body class="flex items-center justify-center min-h-screen p-4">
<div id="app" class="bg-white p-6 rounded-3xl shadow-2xl w-full container text-center transform transition-all duration-500 ease-in-out scale-100">
<div id="loading-screen" class="space-y-4">
<h1 class="text-2xl font-bold text-gray-800">Math Whiskers</h1>
<p class="text-gray-600 flex items-center justify-center">
Загружаем пушистый интеллект...
<span class="animate-bounce-slow ml-2 text-2xl">🐱</span>
</p>
</div>
<div id="settings-screen" class="hidden space-y-6">
<h1 class="text-3xl font-bold text-gray-800">Math Whiskers 😺</h1>
<p class="text-gray-600">Отточи свои математические навыки с пушистыми друзьями!</p>
<div class="space-y-4">
<h2 class="text-xl font-semibold text-gray-700">Выбери своего математического зверя</h2>
<div class="flex justify-center space-x-4">
<label class="cursor-pointer">
<input type="radio" name="avatar" value="🐱" class="hidden" checked>
<span class="text-5xl transition-transform transform hover:scale-125 duration-200">🐱</span>
</label>
<label class="cursor-pointer">
<input type="radio" name="avatar" value="🦁" class="hidden">
<span class="text-5xl transition-transform transform hover:scale-125 duration-200">🦁</span>
</label>
<label class="cursor-pointer">
<input type="radio" name="avatar" value="🐻" class="hidden">
<span class="text-5xl transition-transform transform hover:scale-125 duration-200">🐻</span>
</label>
<label class="cursor-pointer">
<input type="radio" name="avatar" value="🐰" class="hidden">
<span class="text-5xl transition-transform transform hover:scale-125 duration-200">🐰</span>
</label>
</div>
</div>
<div class="space-y-4">
<h2 class="text-xl font-semibold text-gray-700">Уровень сложности</h2>
<div class="flex justify-center space-x-4">
<label class="flex items-center space-x-2">
<input type="radio" name="difficulty" value="easy" class="form-radio text-blue-600 h-5 w-5" checked>
<span class="text-gray-700">Котёнок (до 10)</span>
</label>
<label class="flex items-center space-x-2">
<input type="radio" name="difficulty" value="medium" class="form-radio text-blue-600 h-5 w-5">
<span class="text-gray-700">Кот (до 20)</span>
</label>
<label class="flex items-center space-x-2">
<input type="radio" name="difficulty" value="hard" class="form-radio text-blue-600 h-5 w-5">
<span class="text-gray-700">Тигр (до 50)</span>
</label>
</div>
</div>
<div class="space-y-4">
<h2 class="text-xl font-semibold text-gray-700">Математические операции</h2>
<div class="flex justify-center space-x-4">
<label class="flex items-center space-x-2">
<input type="radio" name="operation" value="+" class="form-radio text-blue-600 h-5 w-5" checked>
<span class="text-gray-700">Сложение</span>
</label>
<label class="flex items-center space-x-2">
<input type="radio" name="operation" value="-" class="form-radio text-blue-600 h-5 w-5">
<span class="text-gray-700">Вычитание</span>
</label>
<label class="flex items-center space-x-2">
<input type="radio" name="operation" value="both" class="form-radio text-blue-600 h-5 w-5">
<span class="text-gray-700">Обе операции</span>
</label>
</div>
</div>
<div class="space-y-4">
<h2 class="text-xl font-semibold text-gray-700">Количество вопросов</h2>
<div class="flex justify-center space-x-4">
<label class="flex items-center space-x-2">
<input type="radio" name="numQuestions" value="10" class="form-radio text-blue-600 h-5 w-5" checked>
<span class="text-gray-700">10</span>
</label>
<label class="flex items-center space-x-2">
<input type="radio" name="numQuestions" value="15" class="form-radio text-blue-600 h-5 w-5">
<span class="text-gray-700">15</span>
</label>
<label class="flex items-center space-x-2">
<input type="radio" name="numQuestions" value="20" class="form-radio text-blue-600 h-5 w-5">
<span class="text-gray-700">20</span>
</label>
</div>
</div>
<button id="start-btn" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-full shadow-lg transition-all duration-300 transform hover:scale-105 focus:outline-none focus:ring-4 focus:ring-blue-300">
Начать тренировку
</button>
</div>
<div id="quiz-screen" class="hidden space-y-6">
<div class="flex flex-col items-center mb-4">
<div id="quiz-avatar-display" class="text-7xl mb-4"></div>
</div>
<h2 id="question-text" class="text-5xl font-bold text-gray-800 mb-6"></h2>
<div id="answer-buttons" class="grid grid-cols-2 gap-4"></div>
<p id="message-text" class="min-h-[2rem] text-xl font-semibold"></p>
<button id="show-hint-btn" class="mt-4 bg-yellow-400 hover:bg-yellow-500 text-white font-bold py-2 px-4 rounded-full shadow-md transition-all duration-300 transform hover:scale-105">
Подсказка 🐾
</button>
<div id="emoji-hint-display" class="text-6xl flex items-center justify-center hidden"></div>
<div class="space-y-2 mt-4">
<p class="text-sm text-gray-600">Correct: <span id="correct-count">0</span> | Incorrect: <span id="incorrect-count">0</span></p>
<div id="score-cells-container" class="flex justify-center flex-wrap gap-1"></div>
</div>
</div>
<div id="results-screen" class="hidden space-y-6">
<h2 class="text-3xl font-bold text-gray-800">Тренировка завершена!</h2>
<p id="final-feedback" class="text-2xl font-semibold text-gray-700"></p>
<p id="final-score" class="text-xl text-gray-600 mt-2"></p>
<p class="text-sm text-gray-500 mb-2 flex items-center justify-center">
Ваш профиль: <span id="user-avatar-display" class="ml-2 text-2xl"></span>
</p>
<button id="restart-btn" class="w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-6 rounded-full shadow-lg transition-all duration-300 transform hover:scale-105 focus:outline-none focus:ring-4 focus:ring-blue-300">
Попробовать снова
</button>
</div>
</div>
<div id="confetti-container" class="absolute inset-0 z-50 pointer-events-none"></div>
<script>
// Elements
const loadingScreen = document.getElementById('loading-screen');
const settingsScreen = document.getElementById('settings-screen');
const quizScreen = document.getElementById('quiz-screen');
const resultsScreen = document.getElementById('results-screen');
const startBtn = document.getElementById('start-btn');
const restartBtn = document.getElementById('restart-btn');
const questionText = document.getElementById('question-text');
const answerButtons = document.getElementById('answer-buttons');
const messageText = document.getElementById('message-text');
const correctCount = document.getElementById('correct-count');
const incorrectCount = document.getElementById('incorrect-count');
const scoreCellsContainer = document.getElementById('score-cells-container');
const finalFeedbackText = document.getElementById('final-feedback');
const finalScoreText = document.getElementById('final-score');
const userAvatarDisplay = document.getElementById('user-avatar-display');
const quizAvatarDisplay = document.getElementById('quiz-avatar-display');
const emojiHintDisplay = document.getElementById('emoji-hint-display');
const showHintBtn = document.getElementById('show-hint-btn');
const confettiContainer = document.getElementById('confetti-container');
// Audio Context
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
function playSound(frequency, duration) {
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.type = 'sine';
oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);
gainNode.gain.setValueAtTime(0, audioContext.currentTime);
gainNode.gain.linearRampToValueAtTime(1, audioContext.currentTime + 0.01);
gainNode.gain.linearRampToValueAtTime(0, audioContext.currentTime + duration);
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
oscillator.start(audioContext.currentTime);
oscillator.stop(audioContext.currentTime + duration);
}
// State
let currentQuestionIndex = 0;
let score = { correct: 0, incorrect: 0 };
let questions = [];
let numQuestions = 10;
let difficulty = 'easy';
let operation = '+';
let avatar = '🐱';
let questionResults = [];
// Helper functions
function shuffleArray(array) {
for (let i = array.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
function generateAppleEmojis(count) {
return '🍎'.repeat(count);
}
function generateQuestion(index) {
let startMax, endMax;
if (difficulty === 'easy') {
startMax = 5;
endMax = 10;
} else if (difficulty === 'medium') {
startMax = 10;
endMax = 20;
} else {
startMax = 20;
endMax = 50;
}
const progressionFactor = index / (numQuestions - 1);
const currentMaxNumber = Math.floor(startMax + (endMax - startMax) * progressionFactor);
let a = Math.floor(Math.random() * currentMaxNumber) + 1;
let b = Math.floor(Math.random() * currentMaxNumber) + 1;
let selectedOperation = operation;
if (selectedOperation === 'both') {
selectedOperation = Math.random() > 0.5 ? '+' : '-';
}
if (selectedOperation === '-') {
if (b > a) {
[a, b] = [b, a];
}
}
let correctAnswer;
if (selectedOperation === '+') {
correctAnswer = a + b;
} else {
correctAnswer = a - b;
}
let answers = [correctAnswer];
while (answers.length < 4) {
let incorrectAnswer = correctAnswer + Math.floor(Math.random() * 5) * (Math.random() > 0.5 ? 1 : -1);
if (!answers.includes(incorrectAnswer) && incorrectAnswer >= 0) {
answers.push(incorrectAnswer);
}
}
shuffleArray(answers);
return {
text: `${a} ${selectedOperation} ${b} = ?`,
correctAnswer: correctAnswer,
answers: answers,
a: a,
b: b,
operation: selectedOperation
};
}
function startTest() {
// Get settings
difficulty = document.querySelector('input[name="difficulty"]:checked').value;
numQuestions = parseInt(document.querySelector('input[name="numQuestions"]:checked').value);
avatar = document.querySelector('input[name="avatar"]:checked').value;
operation = document.querySelector('input[name="operation"]:checked').value;
currentQuestionIndex = 0;
score = { correct: 0, incorrect: 0 };
questionResults = [];
questions = [];
for (let i = 0; i < numQuestions; i++) {
questions.push(generateQuestion(i));
}
settingsScreen.classList.add('hidden');
quizScreen.classList.remove('hidden');
quizScreen.classList.add('animate-slide-in');
userAvatarDisplay.textContent = avatar;
quizAvatarDisplay.textContent = avatar;
showQuestion();
updateScoreCells();
}
function showQuestion() {
if (currentQuestionIndex >= numQuestions) {
showResults();
return;
}
messageText.textContent = '';
answerButtons.innerHTML = '';
emojiHintDisplay.classList.add('hidden');
const currentQuestion = questions[currentQuestionIndex];
questionText.textContent = currentQuestion.text;
questionText.classList.remove('animate-pop', 'animate-shake');
if (currentQuestion.a <= 10 && currentQuestion.b <= 10) {
const aEmojis = generateAppleEmojis(currentQuestion.a);
const bEmojis = generateAppleEmojis(currentQuestion.b);
const opEmoji = currentQuestion.operation === '+' ? '➕' : '➖';
emojiHintDisplay.innerHTML = `${aEmojis} ${opEmoji} ${bEmojis} = `;
} else {
emojiHintDisplay.innerHTML = '';
}
currentQuestion.answers.forEach(answer => {
const button = document.createElement('button');
button.textContent = answer;
button.classList.add('bg-gray-200', 'hover:bg-gray-300', 'text-gray-800', 'font-bold', 'py-4', 'px-4', 'rounded-xl', 'transition-all', 'duration-200', 'transform', 'hover:scale-105', 'text-2xl', 'focus:outline-none');
button.onclick = () => checkAnswer(button, answer, currentQuestion.correctAnswer);
answerButtons.appendChild(button);
});
}
function checkAnswer(selectedButton, selectedAnswer, correctAnswer) {
Array.from(answerButtons.children).forEach(btn => btn.disabled = true);
const isCorrect = selectedAnswer === correctAnswer;
questionResults.push(isCorrect);
if (isCorrect) {
messageText.textContent = `Правильно! Мур-р-р! 🎉`;
messageText.classList.add('text-green-600');
messageText.classList.remove('text-red-600');
score.correct++;
playSound(440, 0.2);
questionText.classList.add('animate-pop');
selectedButton.classList.remove('hover:bg-gray-300');
selectedButton.classList.add('correct-answer-button');
} else {
messageText.textContent = `Ошибка... 😿 Правильный ответ: ${correctAnswer}.`;
messageText.classList.add('text-red-600');
messageText.classList.remove('text-green-600');
score.incorrect++;
playSound(220, 0.2);
questionText.classList.add('animate-shake');
selectedButton.classList.remove('hover:bg-gray-300');
selectedButton.classList.add('incorrect-answer-button');
Array.from(answerButtons.children).forEach(btn => {
if (parseInt(btn.textContent) === correctAnswer) {
btn.classList.add('border-4', 'border-green-500');
}
});
}
updateScoreCells();
setTimeout(() => {
currentQuestionIndex++;
showQuestion();
}, 2000);
}
function updateScoreCells() {
scoreCellsContainer.innerHTML = '';
questionResults.forEach(isCorrect => {
const cell = document.createElement('div');
cell.classList.add('w-6', 'h-6', 'rounded-full', 'shadow-md');
if (isCorrect) {
cell.classList.add('bg-green-500');
} else {
cell.classList.add('bg-red-500');
}
scoreCellsContainer.appendChild(cell);
});
const remainingQuestions = numQuestions - questionResults.length;
for (let i = 0; i < remainingQuestions; i++) {
const cell = document.createElement('div');
cell.classList.add('w-6', 'h-6', 'rounded-full', 'bg-gray-300');
scoreCellsContainer.appendChild(cell);
}
correctCount.textContent = score.correct;
incorrectCount.textContent = score.incorrect;
}
function startConfettiAnimation() {
const colors = ['#f44336', '#e91e63', '#9c27b0', '#673ab7', '#3f51b5', '#2196f3', '#03a9f4', '#00bcd4', '#009688', '#4caf50', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107', '#ff9800', '#ff5722'];
const numberOfConfetti = 50;
for (let i = 0; i < numberOfConfetti; i++) {
const confetti = document.createElement('div');
confetti.classList.add('confetti');
confetti.style.left = `${Math.random() * 100}vw`;
confetti.style.animationDelay = `${Math.random() * 2.5}s`;
confetti.style.setProperty('--color', colors[Math.floor(Math.random() * colors.length)]);
confettiContainer.appendChild(confetti);
}
setTimeout(() => {
confettiContainer.innerHTML = '';
}, 3000);
}
function showResults() {
quizScreen.classList.add('hidden');
resultsScreen.classList.remove('hidden');
finalScoreText.textContent = `Your score: ${score.correct} out of ${numQuestions}`;
const percentage = (score.correct / numQuestions) * 100;
let feedbackText = '';
if (percentage >= 80) {
feedbackText = 'Идеально! Ты математический гений! 🎉';
startConfettiAnimation();
} else if (percentage >= 70) {
feedbackText = 'Отличный результат! Продолжай тренироваться! ✨';
} else {
feedbackText = 'Не переживай - с каждой тренировкой будет лучше! 💪';
}
finalFeedbackText.textContent = feedbackText;
}
function resetGame() {
resultsScreen.classList.add('hidden');
settingsScreen.classList.remove('hidden');
currentQuestionIndex = 0;
score = { correct: 0, incorrect: 0 };
questions = [];
questionResults = [];
messageText.textContent = '';
updateScoreCells();
}
// Event listeners
startBtn.addEventListener('click', startTest);
restartBtn.addEventListener('click', resetGame);
showHintBtn.addEventListener('click', () => {
emojiHintDisplay.classList.remove('hidden');
});
document.querySelectorAll('input[name="avatar"]').forEach(radio => {
radio.addEventListener('change', () => {
document.querySelectorAll('input[name="avatar"] + span').forEach(label => {
label.classList.remove('ring-4', 'ring-blue-500', 'ring-offset-2');
});
if (radio.checked) {
radio.nextElementSibling.classList.add('ring-4', 'ring-blue-500', 'ring-offset-2');
}
});
});
// Initialize
window.onload = function() {
loadingScreen.classList.add('hidden');
settingsScreen.classList.remove('hidden');
document.querySelector('input[name="avatar"]:checked').nextElementSibling.classList.add('ring-4', 'ring-blue-500', 'ring-offset-2');
};
</script>
</body>
</html>