type-master / index.html
A3qualityo's picture
Sabse achchha typing game banao - Initial Deployment
df0aaa0 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TypeMaster - Typing Game</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes pulse {
0%, 100% { transform: scale(1); }
50% { transform: scale(1.05); }
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
25% { transform: translateX(-5px); }
75% { transform: translateX(5px); }
}
.pulse {
animation: pulse 1.5s infinite;
}
.shake {
animation: shake 0.3s ease-in-out;
}
.glow {
box-shadow: 0 0 15px rgba(59, 130, 246, 0.7);
}
.word-highlight {
background-color: rgba(96, 165, 250, 0.3);
border-radius: 4px;
padding: 2px 4px;
}
</style>
</head>
<body class="bg-gray-900 text-white min-h-screen flex flex-col">
<header class="bg-gray-800 py-6 px-4 shadow-lg">
<div class="container mx-auto flex justify-between items-center">
<h1 class="text-3xl font-bold text-blue-400 flex items-center">
<i class="fas fa-keyboard mr-2"></i> TypeMaster
</h1>
<div id="sound-toggle" class="cursor-pointer text-xl text-blue-400 hover:text-blue-300">
<i class="fas fa-volume-up"></i>
</div>
</div>
</header>
<main class="flex-grow container mx-auto px-4 py-8 flex flex-col items-center">
<div class="w-full max-w-4xl">
<!-- Game Info Section -->
<section class="bg-gray-800 rounded-xl p-6 mb-8 shadow-lg">
<div class="flex flex-col md:flex-row justify-between items-center mb-6">
<div class="flex items-center space-x-4 mb-4 md:mb-0">
<div class="bg-blue-500 px-4 py-2 rounded-lg">
<span class="text-sm font-semibold">Time</span>
<div class="text-3xl font-bold" id="timer">60</div>
</div>
<div class="bg-purple-500 px-4 py-2 rounded-lg">
<span class="text-sm font-semibold">Score</span>
<div class="text-3xl font-bold" id="score">0</div>
</div>
<div class="bg-green-500 px-4 py-2 rounded-lg">
<span class="text-sm font-semibold">WPM</span>
<div class="text-3xl font-bold" id="wpm">0</div>
</div>
<div class="bg-yellow-500 px-4 py-2 rounded-lg">
<span class="text-sm font-semibold">Accuracy</span>
<div class="text-3xl font-bold" id="accuracy">100%</div>
</div>
</div>
<div class="flex items-center space-x-4">
<div>
<label class="block text-sm font-medium mb-1" for="difficulty">Difficulty</label>
<select id="difficulty" class="bg-gray-700 border border-gray-600 rounded-lg px-3 py-2 text-sm focus:ring-blue-500 focus:border-blue-500">
<option value="easy">Easy</option>
<option value="medium" selected>Medium</option>
<option value="hard">Hard</option>
<option value="insane">Insane</option>
</select>
</div>
<button id="restart-btn" class="bg-red-500 hover:bg-red-600 text-white font-medium py-2 px-4 rounded-lg transition flex items-center">
<i class="fas fa-redo mr-2"></i> Restart
</button>
</div>
</div>
<div class="mb-4">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold">Instructions</h2>
<span id="game-status" class="bg-blue-500 text-xs px-2 py-1 rounded-full">Ready</span>
</div>
<p class="text-gray-300 mt-1 text-sm">Type the words below as quickly and accurately as possible. The game ends when time runs out.</p>
</div>
</section>
<!-- Typing Area -->
<section class="relative mb-8">
<div class="bg-gray-800 rounded-xl p-6 shadow-lg">
<div class="mb-4 flex items-center justify-between">
<h2 class="text-xl font-bold text-blue-400">Your Typing Test</h2>
<span id="words-count" class="bg-gray-700 px-3 py-1 rounded-full text-sm">0/10 words</span>
</div>
<div id="word-display" class="bg-gray-900 text-2xl font-mono p-6 rounded-lg h-32 overflow-auto mb-4 flex flex-wrap gap-2">
<!-- Words will appear here -->
</div>
<div class="relative">
<input type="text" id="word-input" class="w-full bg-gray-700 border-2 border-gray-600 rounded-lg py-3 px-4 text-xl focus:outline-none focus:border-blue-500 transition"
placeholder="Type the word here..." autocomplete="off" autofocus>
<div id="input-status" class="absolute right-3 top-1/2 transform -translate-y-1/2 text-xl hidden">
<i class="fas fa-check-circle text-green-500"></i>
</div>
</div>
<div class="mt-4 text-sm text-gray-400">
<span id="current-progress" class="text-blue-400 font-medium">0 characters typed</span>
<span id="mistakes" class="float-right text-red-400">0 mistakes</span>
</div>
</div>
</section>
<!-- Results Section (Hidden by default) -->
<section id="results-section" class="hidden bg-gray-800 rounded-xl p-6 shadow-lg">
<h2 class="text-2xl font-bold text-center mb-6 text-blue-400">Game Results</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6">
<div class="bg-gray-900 p-6 rounded-lg text-center">
<div class="text-5xl font-bold text-blue-400 mb-2" id="final-score">0</div>
<div class="text-lg font-medium">Total Score</div>
</div>
<div class="bg-gray-900 p-6 rounded-lg text-center">
<div class="text-5xl font-bold text-green-400 mb-2" id="final-wpm">0</div>
<div class="text-lg font-medium">Words Per Minute</div>
</div>
<div class="bg-gray-900 p-6 rounded-lg text-center">
<div class="text-5xl font-bold text-yellow-400 mb-2" id="final-accuracy">100%</div>
<div class="text-lg font-medium">Accuracy</div>
</div>
</div>
<div class="mt-6 grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-gray-900 p-4 rounded-lg">
<div class="mb-1 flex justify-between">
<span class="text-gray-400">Correct words:</span>
<span class="font-medium" id="correct-words">0</span>
</div>
<div class="mb-1 flex justify-between">
<span class="text-gray-400">Incorrect words:</span>
<span class="font-medium" id="incorrect-words">0</span>
</div>
<div class="mb-1 flex justify-between">
<span class="text-gray-400">Character count:</span>
<span class="font-medium" id="characters-typed">0</span>
</div>
</div>
<div class="bg-gray-900 p-4 rounded-lg">
<div class="mb-1 flex justify-between">
<span class="text-gray-400">Mistakes:</span>
<span class="font-medium" id="total-mistakes">0</span>
</div>
<div class="mb-1 flex justify-between">
<span class="text-gray-400">Time played:</span>
<span class="font-medium" id="time-played">60s</span>
</div>
<div class="mb-1 flex justify-between">
<span class="text-gray-400">Difficulty:</span>
<span class="font-medium" id="played-difficulty">Medium</span>
</div>
</div>
</div>
<div class="mt-6 text-center">
<button id="play-again-btn" class="bg-blue-500 hover:bg-blue-600 text-white font-bold py-3 px-6 rounded-lg text-lg transition">
<i class="fas fa-play mr-2"></i> Play Again
</button>
</div>
</section>
</div>
</main>
<footer class="bg-gray-800 py-4 px-4 text-center text-gray-400 text-sm">
<p>Made with <i class="fas fa-heart text-red-500"></i> by TypeMaster | &copy; 2023 All rights reserved</p>
</footer>
<script>
// DOM Elements
const wordDisplay = document.getElementById('word-display');
const wordInput = document.getElementById('word-input');
const timerDisplay = document.getElementById('timer');
const scoreDisplay = document.getElementById('score');
const wpmDisplay = document.getElementById('wpm');
const accuracyDisplay = document.getElementById('accuracy');
const wordsCountDisplay = document.getElementById('words-count');
const difficultySelect = document.getElementById('difficulty');
const restartBtn = document.getElementById('restart-btn');
const resultsSection = document.getElementById('results-section');
const gameStatus = document.getElementById('game-status');
const inputStatus = document.getElementById('input-status');
const currentProgress = document.getElementById('current-progress');
const mistakesDisplay = document.getElementById('mistakes');
const soundToggle = document.getElementById('sound-toggle');
const playAgainBtn = document.getElementById('play-again-btn');
// Game variables
let words = [];
let currentWordIndex = 0;
let score = 0;
let timeLeft = 60;
let timer;
let gameActive = false;
let correctWords = 0;
let incorrectWords = 0;
let totalCharacters = 0;
let correctCharacters = 0;
let mistakes = 0;
let startTime;
let wordCount = 10;
let soundEnabled = true;
let currentDifficulty = 'medium';
// Word banks for different difficulty levels
const wordBanks = {
easy: [
'cat', 'dog', 'sun', 'fun', 'run', 'big', 'red', 'blue', 'tree', 'book',
'ball', 'fish', 'moon', 'star', 'love', 'happy', 'beach', 'apple', 'house', 'school',
'water', 'music', 'smile', 'green', 'pizza', 'friend', 'summer', 'winter', 'flower', 'cloud'
],
medium: [
'computer', 'keyboard', 'monitor', 'internet', 'browser', 'website', 'program',
'network', 'digital', 'gaming', 'mobile', 'system', 'developer', 'software',
'hardware', 'database', 'algorithm', 'security', 'password', 'interface',
'graphics', 'console', 'wireless', 'function', 'virtual', 'language', 'storage',
'battery', 'process', 'service'
],
hard: [
'pneumonoultramicroscopicsilicovolcanoconiosis', 'hippopotomonstrosesquipedaliophobia',
'supercalifragilisticexpialidocious', 'pseudopseudohypoparathyroidism',
'floccinaucinihilipilification', 'antidisestablishmentarianism',
'honorificabilitudinitatibus', 'thyroparathyroidectomized',
'dichlorodifluoromethane', 'incomprehensibilities', 'uncharacteristically',
'counterrevolutionary', 'internationalization', 'electroencephalogram'
],
insane: [
'zyzzyva', 'quizzify', 'jazziness', 'pizzazz', 'huzzah', 'buzzword',
'fuzzbox', 'whizzbang', 'razzmatazz', 'squeezebox', 'zigzagging',
'syzygy', 'xylophone', 'yacht', 'sphinx', 'mnemonic', 'rhythm',
'fjord', 'crypt', 'gypsy', 'python', 'awkward', 'zombie', 'xenon'
]
};
// Initialize game
function initGame() {
// Reset game state
currentWordIndex = 0;
score = 0;
correctWords = 0;
incorrectWords = 0;
totalCharacters = 0;
correctCharacters = 0;
mistakes = 0;
timeLeft = 60;
gameActive = false;
// Update UI
scoreDisplay.textContent = '0';
wpmDisplay.textContent = '0';
accuracyDisplay.textContent = '100%';
wordsCountDisplay.textContent = '0/' + wordCount + ' words';
mistakesDisplay.textContent = '0 mistakes';
currentProgress.textContent = '0 characters typed';
gameStatus.textContent = 'Ready';
gameStatus.className = 'bg-blue-500 text-xs px-2 py-1 rounded-full';
// Generate words based on difficulty
currentDifficulty = difficultySelect.value;
const wordBank = wordBanks[currentDifficulty];
words = [];
for (let i = 0; i < wordCount; i++) {
const randomIndex = Math.floor(Math.random() * wordBank.length);
words.push(wordBank[randomIndex]);
}
// Display words
displayWords();
// Clear input and enable
wordInput.value = '';
wordInput.disabled = false;
wordInput.focus();
// Hide results
resultsSection.classList.add('hidden');
// Start timer when first key is pressed
wordInput.addEventListener('keydown', startGameOnFirstKey);
}
// Start game on first key press
function startGameOnFirstKey(e) {
if (!gameActive && e.key !== 'Shift' && e.key !== 'Tab' && e.key !== 'CapsLock' && !e.ctrlKey && !e.metaKey && !e.altKey) {
gameActive = true;
gameStatus.textContent = 'Playing';
gameStatus.className = 'bg-green-500 text-xs px-2 py-1 rounded-full';
startTimer();
startTime = new Date();
wordInput.removeEventListener('keydown', startGameOnFirstKey);
}
}
// Display words in the word display area
function displayWords() {
wordDisplay.innerHTML = '';
words.forEach((word, index) => {
const wordSpan = document.createElement('span');
wordSpan.textContent = word;
if (index === currentWordIndex) {
wordSpan.className = 'word-highlight text-yellow-400';
} else if (index < currentWordIndex) {
wordSpan.className = 'text-green-400';
} else {
wordSpan.className = 'text-white';
}
wordDisplay.appendChild(wordSpan);
// Add space between words but not after last word
if (index < words.length - 1) {
const spaceSpan = document.createElement('span');
spaceSpan.textContent = ' ';
wordDisplay.appendChild(spaceSpan);
}
});
// Update words count
wordsCountDisplay.textContent = currentWordIndex + '/' + wordCount + ' words';
}
// Start timer
function startTimer() {
timer = setInterval(() => {
timeLeft--;
timerDisplay.textContent = timeLeft;
if (timeLeft <= 10) {
timerDisplay.classList.add('text-red-500', 'pulse');
}
if (timeLeft <= 0) {
endGame();
}
// Update WPM every second
updateWPM();
}, 1000);
}
// Update Words Per Minute
function updateWPM() {
if (correctWords === 0 || !startTime) return;
const now = new Date();
const timeElapsed = (now - startTime) / 1000 / 60; // in minutes
const wpm = Math.round(correctWords / timeElapsed);
wpmDisplay.textContent = wpm;
// Update accuracy
const accuracy = totalCharacters > 0 ? Math.round((correctCharacters / totalCharacters) * 100) : 100;
accuracyDisplay.textContent = accuracy + '%';
}
// Handle word input
wordInput.addEventListener('input', (e) => {
const inputText = wordInput.value.trim();
const currentWord = words[currentWordIndex];
totalCharacters = inputText.length;
currentProgress.textContent = totalCharacters + ' characters typed';
// Check if word is complete
if (inputText === currentWord) {
handleCorrectWord();
}
});
wordInput.addEventListener('keydown', (e) => {
if (e.key === ' ') {
e.preventDefault();
checkCurrentWord();
} else if (e.key === 'Enter') {
e.preventDefault();
checkCurrentWord();
}
});
// Check if current word matches input
function checkCurrentWord() {
const inputText = wordInput.value.trim();
const currentWord = words[currentWordIndex];
if (inputText === currentWord) {
handleCorrectWord();
} else {
handleIncorrectWord();
}
}
// Handle correct word
function handleCorrectWord() {
if (soundEnabled) {
playSound('correct');
}
// Update stats
correctWords++;
correctCharacters += words[currentWordIndex].length;
// Calculate score (based on word length and speed)
const wordScore = words[currentWordIndex].length * 5;
score += wordScore;
// Animate UI
inputStatus.innerHTML = '<i class="fas fa-check-circle text-green-500"></i>';
inputStatus.classList.remove('hidden');
scoreDisplay.textContent = score;
scoreDisplay.classList.add('glow');
setTimeout(() => {
inputStatus.classList.add('hidden');
scoreDisplay.classList.remove('glow');
}, 500);
// Move to next word
moveToNextWord();
}
// Handle incorrect word
function handleIncorrectWord() {
if (soundEnabled) {
playSound('incorrect');
}
// Update stats
incorrectWords++;
mistakes++;
mistakesDisplay.textContent = mistakes + ' mistakes';
// Animate UI
wordInput.classList.add('shake', 'border-red-500');
inputStatus.innerHTML = '<i class="fas fa-times-circle text-red-500"></i>';
inputStatus.classList.remove('hidden');
setTimeout(() => {
wordInput.classList.remove('shake', 'border-red-500');
inputStatus.classList.add('hidden');
}, 500);
}
// Move to next word or end game if all words are done
function moveToNextWord() {
currentWordIndex++;
wordInput.value = '';
// Update progress
currentProgress.textContent = '0 characters typed';
if (currentWordIndex >= words.length) {
// All words completed before time ran out
if (gameActive) {
wordCount += 5; // Increase word count for next round
initGame(); // Start new round with more words
}
} else {
displayWords();
}
}
// End game
function endGame() {
clearInterval(timer);
gameActive = false;
// Disable input
wordInput.disabled = true;
// Update game status
gameStatus.textContent = 'Finished';
gameStatus.className = 'bg-red-500 text-xs px-2 py-1 rounded-full';
// Calculate final stats
const now = new Date();
const timePlayedInMinutes = (now - startTime) / 1000 / 60;
const finalWPM = Math.round(correctWords / timePlayedInMinutes);
const finalAccuracy = totalCharacters > 0 ? Math.round((correctCharacters / totalCharacters) * 100) : 100;
// Show results
document.getElementById('final-score').textContent = score;
document.getElementById('final-wpm').textContent = finalWPM;
document.getElementById('final-accuracy').textContent = finalAccuracy + '%';
document.getElementById('correct-words').textContent = correctWords;
document.getElementById('incorrect-words').textContent = incorrectWords;
document.getElementById('characters-typed').textContent = totalCharacters;
document.getElementById('total-mistakes').textContent = mistakes;
document.getElementById('time-played').textContent = Math.round((60 - timeLeft) * 10) / 10 + 's';
document.getElementById('played-difficulty').textContent = currentDifficulty.charAt(0).toUpperCase() + currentDifficulty.slice(1);
resultsSection.classList.remove('hidden');
// Scroll to results
resultsSection.scrollIntoView({ behavior: 'smooth' });
if (soundEnabled) {
playSound('gameover');
}
}
// Play sound
function playSound(type) {
if (!soundEnabled) return;
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const oscillator = audioContext.createOscillator();
const gainNode = audioContext.createGain();
oscillator.connect(gainNode);
gainNode.connect(audioContext.destination);
switch(type) {
case 'correct':
oscillator.frequency.value = 880;
oscillator.type = 'sine';
break;
case 'incorrect':
oscillator.frequency.value = 220;
oscillator.type = 'square';
break;
case 'gameover':
oscillator.frequency.setValueAtTime(440, audioContext.currentTime);
oscillator.frequency.exponentialRampToValueAtTime(55, audioContext.currentTime + 0.5);
oscillator.type = 'sawtooth';
break;
}
gainNode.gain.exponentialRampToValueAtTime(0.00001, audioContext.currentTime + 0.3);
oscillator.start();
oscillator.stop(audioContext.currentTime + 0.3);
}
// Event listeners
restartBtn.addEventListener('click', initGame);
playAgainBtn.addEventListener('click', initGame);
difficultySelect.addEventListener('change', () => {
if (!gameActive) {
initGame();
}
});
soundToggle.addEventListener('click', () => {
soundEnabled = !soundEnabled;
if (soundEnabled) {
soundToggle.innerHTML = '<i class="fas fa-volume-up"></i>';
soundToggle.classList.add('text-blue-400');
soundToggle.classList.remove('text-gray-500');
} else {
soundToggle.innerHTML = '<i class="fas fa-volume-mute"></i>';
soundToggle.classList.remove('text-blue-400');
soundToggle.classList.add('text-gray-500');
}
});
// Initialize game on load
document.addEventListener('DOMContentLoaded', initGame);
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=A3qualityo/type-master" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>