init: initialize project - 2 games
This commit is contained in:
commit
4740d0003b
7 changed files with 1784 additions and 0 deletions
215
find-and-write/index.html
Normal file
215
find-and-write/index.html
Normal file
|
|
@ -0,0 +1,215 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Classroom Word Search Game</title>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.23.5/babel.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="text/babel">
|
||||
const { useState, useEffect } = React;
|
||||
|
||||
function WordSearchGame() {
|
||||
const wordLists = {
|
||||
animals: ['elephant', 'giraffe', 'penguin', 'dolphin', 'kangaroo', 'octopus', 'butterfly', 'zebra'],
|
||||
colors: ['purple', 'orange', 'yellow', 'green', 'blue', 'red', 'brown', 'pink'],
|
||||
food: ['pizza', 'banana', 'cookie', 'apple', 'sandwich', 'pasta', 'carrot', 'burger'],
|
||||
school: ['pencil', 'eraser', 'notebook', 'teacher', 'student', 'library', 'classroom', 'homework'],
|
||||
// Arabic categories for beginners
|
||||
arabicAnimals: ['فيل', 'أسد', 'قطة', 'كلب', 'زرافة', 'فأر', 'سمكة', 'طائر'],
|
||||
arabicColors: ['أحمر', 'أزرق', 'أخضر', 'أصفر', 'أسود', 'أبيض', 'بني', 'برتقالي'],
|
||||
arabicNumbers: ['واحد', 'اثنان', 'ثلاثة', 'أربعة', 'خمسة', 'ستة', 'سبعة', 'ثمانية'],
|
||||
arabicGreetings: ['مرحبا', 'صباح الخير', 'مساء الخير', 'شكرا', 'عفوا', 'مع السلامة', 'كيف حالك', 'أنا بخير']
|
||||
};
|
||||
|
||||
const [category, setCategory] = useState('animals');
|
||||
const [isArabic, setIsArabic] = useState(false);
|
||||
const [displayedWords, setDisplayedWords] = useState([]);
|
||||
const [timer, setTimer] = useState(300);
|
||||
|
||||
const randomPosition = () => ({
|
||||
left: `${Math.random() * 70 + 15}%`,
|
||||
top: `${Math.random() * 50 + 20}%`, // Reduced vertical range to avoid bottom section
|
||||
transform: `rotate(${Math.random() * 360}deg)`
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// When language is toggled, update to appropriate category
|
||||
if (isArabic && !category.startsWith('arabic')) {
|
||||
setCategory('arabicAnimals');
|
||||
} else if (!isArabic && category.startsWith('arabic')) {
|
||||
setCategory('animals');
|
||||
}
|
||||
}, [isArabic]);
|
||||
|
||||
useEffect(() => {
|
||||
const words = wordLists[category].map((word, index) => ({
|
||||
id: index,
|
||||
text: word,
|
||||
...randomPosition()
|
||||
}));
|
||||
setDisplayedWords(words);
|
||||
}, [category]);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setTimer((prev) => (prev > 0 ? prev - 1 : 0));
|
||||
}, 1000);
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
// Reset timer when language changes
|
||||
useEffect(() => {
|
||||
setTimer(300);
|
||||
}, [isArabic]);
|
||||
|
||||
const changeCategory = () => {
|
||||
// Filter categories based on language selection
|
||||
const categories = Object.keys(wordLists).filter(cat =>
|
||||
isArabic ? cat.startsWith('arabic') : !cat.startsWith('arabic')
|
||||
);
|
||||
const currentIndex = categories.indexOf(category);
|
||||
const nextIndex = (currentIndex + 1) % categories.length;
|
||||
setCategory(categories[nextIndex]);
|
||||
setTimer(300);
|
||||
};
|
||||
|
||||
const toggleLanguage = () => {
|
||||
setIsArabic(!isArabic);
|
||||
// Set to first category of the selected language
|
||||
const categories = Object.keys(wordLists).filter(cat =>
|
||||
!isArabic ? cat.startsWith('arabic') : !cat.startsWith('arabic')
|
||||
);
|
||||
setCategory(categories[0]);
|
||||
setTimer(300);
|
||||
};
|
||||
|
||||
// Format category name for display
|
||||
const formatCategoryName = (cat) => {
|
||||
if (cat.startsWith('arabic')) {
|
||||
// Convert arabicAnimals to "Arabic Animals"
|
||||
return cat.replace('arabic', 'Arabic ').replace(/([A-Z])/g, ' $1').trim();
|
||||
}
|
||||
return cat;
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="relative w-full h-screen bg-gray-100 overflow-hidden">
|
||||
<div className="absolute top-0 left-0 right-0 p-4 bg-white shadow-md flex justify-between items-center">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-2xl">📚</span>
|
||||
<span className="text-2xl font-bold">Find and Write: {formatCategoryName(category)}</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-4">
|
||||
<button
|
||||
onClick={toggleLanguage}
|
||||
className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600"
|
||||
>
|
||||
{isArabic ? "Switch to English" : "Switch to Arabic"}
|
||||
</button>
|
||||
<button
|
||||
onClick={changeCategory}
|
||||
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
|
||||
>
|
||||
Change Category
|
||||
</button>
|
||||
<div className="text-xl">
|
||||
Words to find: {wordLists[category].length}
|
||||
</div>
|
||||
<div className="text-xl">
|
||||
Time: {Math.floor(timer / 60)}:{(timer % 60).toString().padStart(2, '0')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute top-20 left-4 right-4 bg-yellow-100 p-4 rounded-lg shadow">
|
||||
<p className="text-lg">
|
||||
🤫 Silently find and write down as many {formatCategoryName(category)} as you can!
|
||||
Look carefully - words might be rotated!
|
||||
{isArabic && (
|
||||
<span className="block mt-2 text-gray-700">
|
||||
<strong>Beginner tip:</strong> Try to find and memorize these Arabic words. Check the help section at the bottom for learning tips!
|
||||
</span>
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mt-32 relative w-full h-full">
|
||||
{displayedWords.map((word) => (
|
||||
<div
|
||||
key={word.id}
|
||||
className={`absolute font-bold select-none ${isArabic ? 'text-3xl' : 'text-4xl'} text-gray-700`}
|
||||
style={{
|
||||
left: word.left,
|
||||
top: word.top,
|
||||
transform: word.transform,
|
||||
direction: isArabic ? 'rtl' : 'ltr',
|
||||
fontFamily: isArabic ? "'Arial', 'Tahoma', sans-serif" : 'inherit'
|
||||
}}
|
||||
>
|
||||
{word.text}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{isArabic && (
|
||||
<div className="fixed bottom-0 left-0 right-0 bg-blue-100 p-2 shadow" style={{ maxHeight: '25vh', overflowY: 'auto' }}>
|
||||
<button
|
||||
className="absolute top-1 right-2 bg-red-500 text-white rounded-full w-6 h-6 flex items-center justify-center text-xs"
|
||||
onClick={() => document.querySelector('.help-section').classList.toggle('hidden')}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
<h3 className="text-lg font-bold text-center">Arabic Learning Guide</h3>
|
||||
<div className="help-section grid grid-cols-1 md:grid-cols-4 gap-2 text-sm mt-1">
|
||||
<div>
|
||||
<strong>Animals (الحيوانات):</strong>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>فيل - elephant</li>
|
||||
<li>أسد - lion</li>
|
||||
<li>قطة - cat</li>
|
||||
<li>كلب - dog</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Colors (الألوان):</strong>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>أحمر - red</li>
|
||||
<li>أزرق - blue</li>
|
||||
<li>أخضر - green</li>
|
||||
<li>أصفر - yellow</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Numbers (الأرقام):</strong>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>واحد - one</li>
|
||||
<li>اثنان - two</li>
|
||||
<li>ثلاثة - three</li>
|
||||
<li>أربعة - four</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Greetings (التحيات):</strong>
|
||||
<ul className="list-disc pl-5">
|
||||
<li>مرحبا - hello</li>
|
||||
<li>شكرا - thank you</li>
|
||||
<li>مع السلامة - goodbye</li>
|
||||
<li>كيف حالك - how are you</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.render(<WordSearchGame />, document.getElementById('root'));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue