sdelay-dlya-menya-sayt-dlya/script.js

663 lines
27 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Данные по уровням
const levelsData = {
A1: {
title: "A1 - Beginner (Начинающий)",
theory: [
{
title: "Глагол to be (быть)",
content: "Глагол to be используется в настоящем времени: I am, You/We/They are, He/She/It is.",
example: "I am a student. (Я студент) / She is a teacher. (Она учитель)"
},
{
title: "Артикли a/an/the",
content: "Неопределённый артикль a/an используется с исчисляемыми существительными в единственном числе. Определённый артикль the - когда говорим о чём-то конкретном.",
example: "a book (какая-то книга) / the book (конкретная книга)"
},
{
title: "Множественное число",
content: "Большинство существительных образуют множественное число добавлением -s. Исключения: man→men, woman→women, child→children.",
example: "cat→cats, box→boxes, person→people"
},
{
title: "Present Simple",
content: "Настоящее простое время для регулярных действий. Для he/she/it добавляем -s к глаголу.",
example: "I work every day. / He works every day."
}
],
vocabulary: [
{ en: "hello", ru: "привет" }, { en: "goodbye", ru: "до свидания" },
{ en: "please", ru: "пожалуйста" }, { en: "thank you", ru: "спасибо" },
{ en: "yes", ru: "да" }, { en: "no", ru: "нет" },
{ en: "I", ru: "я" }, { en: "you", ru: "ты, вы" },
{ en: "he", ru: "он" }, { en: "she", ru: "она" },
{ en: "we", ru: "мы" }, { en: "they", ru: "они" },
{ en: "family", ru: "семья" }, { en: "friend", ru: "друг" },
{ en: "house", ru: "дом" }, { en: "water", ru: "вода" },
{ en: "food", ru: "еда" }, { en: "time", ru: "время" },
{ en: "day", ru: "день" }, { en: "night", ru: "ночь" }
],
exercises: [
{
question: "Выберите правильную форму: I ___ a student.",
options: ["am", "is", "are"],
correct: 0
},
{
question: "Выберите правильный перевод: 'Она учитель'",
options: ["She am a teacher", "She is a teacher", "She are a teacher"],
correct: 1
},
{
question: "Множественное число от 'cat':",
options: ["cat", "cats", "cates"],
correct: 1
}
]
},
A2: {
title: "A2 - Elementary (Элементарный)",
theory: [
{
title: "Present Continuous",
content: "Настоящее длительное время: am/is/are + глагол-ing. Используется для действий в момент речи.",
example: "I am reading now. (Я читаю сейчас)"
},
{
title: "Past Simple",
content: "Прошедшее простое время. Правильные глаголы: +ed, неправильные - вторая форма.",
example: "I worked yesterday. / I went to school."
},
{
title: "Модальные глаголы",
content: "can (мочь), must (должен), should (следует). После модального глагола инфинитив без to.",
example: "I can swim. / You must go. / He should study."
},
{
title: "Степени сравнения прилагательных",
content: "Короткие: -er, -est. Длинные: more, the most. Исключения: good→better→the best.",
example: "big→bigger→the biggest / beautiful→more beautiful→the most beautiful"
}
],
vocabulary: [
{ en: "yesterday", ru: "вчера" }, { en: "tomorrow", ru: "завтра" },
{ en: "today", ru: "сегодня" }, { en: "morning", ru: "утро" },
{ en: "evening", ru: "вечер" }, { en: "week", ru: "неделя" },
{ en: "month", ru: "месяц" }, { en: "year", ru: "год" },
{ en: "work", ru: "работа" }, { en: "study", ru: "учиться" },
{ en: "learn", ru: "изучать" }, { en: "speak", ru: "говорить" },
{ en: "understand", ru: "понимать" }, { en: "know", ru: "знать" },
{ en: "think", ru: "думать" }, { en: "want", ru: "хотеть" },
{ en: "need", ru: "нуждаться" }, { en: "like", ru: "нравиться" },
{ en: "love", ru: "любить" }, { en: "hate", ru: "ненавидеть" }
],
exercises: [
{
question: "Выберите правильную форму: She ___ now.",
options: ["reads", "is reading", "read"],
correct: 1
},
{
question: "Past Simple от 'go':",
options: ["goed", "gone", "went"],
correct: 2
},
{
question: "'Более красивый' по-английски:",
options: ["beautifuler", "more beautiful", "beautifulest"],
correct: 1
}
]
},
B1: {
title: "B1 - Intermediate (Средний)",
theory: [
{
title: "Present Perfect",
content: "have/has + V3 (третья форма). Действие завершилось к настоящему моменту или важен результат.",
example: "I have finished my work. (Я закончил работу)"
},
{
title: "Future Simple",
content: "will + инфинитив без to. Используется для будущих действий, обещаний, предсказаний.",
example: "I will call you tomorrow."
},
{
title: "Условные предложения 1 типа",
content: "If + Present Simple, will + инфинитив. Реальные условия в будущем.",
example: "If it rains, I will stay at home."
},
{
title: "Пассивный залог",
content: "be + V3 (третья форма). Подлежащее подвергается действию.",
example: "The book was written by Tolstoy."
}
],
vocabulary: [
{ en: "experience", ru: "опыт" }, { en: "opportunity", ru: "возможность" },
{ en: "decision", ru: "решение" }, { en: "development", ru: "развитие" },
{ en: "information", ru: "информация" }, { en: "knowledge", ru: "знание" },
{ en: "ability", ru: "способность" }, { en: "difference", ru: "разница" },
{ en: "important", ru: "важный" }, { en: "necessary", ru: "необходимый" },
{ en: "possible", ru: "возможный" }, { en: "available", ru: "доступный" },
{ en: "recently", ru: "недавно" }, { en: "probably", ru: "вероятно" },
{ en: "actually", ru: "на самом деле" }, { en: "especially", ru: "особенно" },
{ en: "however", ru: "однако" }, { en: "therefore", ru: "поэтому" },
{ en: "although", ru: "хотя" }, { en: "because", ru: "потому что" }
],
exercises: [
{
question: "Выберите: I ___ already ___ this film.",
options: ["did / see", "have / seen", "will / see"],
correct: 1
},
{
question: "If you ___ hard, you will pass the exam.",
options: ["study", "will study", "studied"],
correct: 0
},
{
question: "Пассивный залог: 'The letter ___ yesterday.'",
options: ["sent", "was sent", "is sent"],
correct: 1
}
]
},
B2: {
title: "B2 - Upper-Intermediate (Выше среднего)",
theory: [
{
title: "Present Perfect Continuous",
content: "have/has been + глагол-ing. Действие началось в прошлом и продолжается до сих пор.",
example: "I have been studying English for 3 years."
},
{
title: "Условные предложения 2 типа",
content: "If + Past Simple, would + инфинитив. Маловероятные или нереальные условия.",
example: "If I had money, I would buy a car."
},
{
title: "Косвенная речь",
content: "При передаче чужих слов времена сдвигаются в прошлое.",
example: "He said that he was tired."
},
{
title: "Модальные глаголы совершенного вида",
content: "must have done (должно быть сделал), should have done (следовало сделать), could have done (мог бы сделать).",
example: "You should have told me earlier."
}
],
vocabulary: [
{ en: "accomplish", ru: "достигать" }, { en: "significant", ru: "значительный" },
{ en: "consequently", ru: "следовательно" }, { en: "furthermore", ru: "более того" },
{ en: "nevertheless", ru: "тем не менее" }, { en: "meanwhile", ru: "между тем" },
{ en: "sufficient", ru: "достаточный" }, { en: "appropriate", ru: "подходящий" },
{ en: "considerable", ru: "значительный" }, { en: "potential", ru: "потенциал" },
{ en: "challenge", ru: "вызов, сложность" }, { en: "approach", ru: "подход" },
{ en: "concept", ru: "концепция" }, { en: "context", ru: "контекст" },
{ en: "evidence", ru: "доказательство" }, { en: "factor", ru: "фактор" },
{ en: "aspect", ru: "аспект" }, { en: "issue", ru: "вопрос, проблема" },
{ en: "trend", ru: "тенденция" }, { en: "strategy", ru: "стратегия" }
],
exercises: [
{
question: "I ___ for 2 hours when you called.",
options: ["studied", "have been studying", "had been studying"],
correct: 2
},
{
question: "If I ___ you, I would accept the offer.",
options: ["am", "were", "would be"],
correct: 1
},
{
question: "He said he ___ busy.",
options: ["is", "was", "will be"],
correct: 1
}
]
},
C1: {
title: "C1 - Advanced (Продвинутый)",
theory: [
{
title: "Inversion",
content: "Инверсия для эмфазы: Never have I seen, Not only did he... Используется в формальной речи.",
example: "Never have I been so surprised!"
},
{
title: "Mixed Conditionals",
content: "Смешанные условные предложения: комбинация разных времён в условии и результате.",
example: "If I had studied harder, I would be at a better university now."
},
{
title: "Subjunctive Mood",
content: "Сослагательное наклонение: I suggest that he go, It's important that she be informed.",
example: "I recommend that he see a doctor."
},
{
title: "Cleft Sentences",
content: "Расщеплённые предложения для выделения: What I need is... / It was John who...",
example: "What I really want is to travel the world."
}
],
vocabulary: [
{ en: "unprecedented", ru: "беспрецедентный" }, { en: "comprehensive", ru: "всесторонний" },
{ en: "sophisticated", ru: "сложный, изощрённый" }, { en: "simultaneously", ru: "одновременно" },
{ en: "subsequently", ru: "впоследствии" }, { en: "inevitably", ru: "неизбежно" },
{ en: "predominantly", ru: "преимущественно" }, { en: "notwithstanding", ru: "несмотря на" },
{ en: "implementation", ru: "осуществление" }, { en: "sustainability", ru: "устойчивость" },
{ en: "methodology", ru: "методология" }, { en: "infrastructure", ru: "инфраструктура" },
{ en: "phenomenon", ru: "феномен" }, { en: "hypothesis", ru: "гипотеза" },
{ en: "paradigm", ru: "парадигма" }, { en: "implication", ru: "последствие" },
{ en: "credibility", ru: "достоверность" }, { en: "authenticity", ru: "подлинность" },
{ en: "spontaneous", ru: "спонтанный" }, { en: "meticulous", ru: "скрупулёзный" }
],
exercises: [
{
question: "Выберите правильную инверсию: '___ such a beautiful place.'",
options: ["Never I have seen", "Never have I seen", "I have never seen"],
correct: 1
},
{
question: "Mixed Conditional: 'If she had taken the job, she ___ in London now.'",
options: ["would live", "will live", "would have lived"],
correct: 0
},
{
question: "Subjunctive: 'I suggest that he ___ immediately.'",
options: ["leaves", "leave", "will leave"],
correct: 1
}
]
}
};
// Текущее состояние
let currentLevel = null;
let chatSessionId = null;
// DOM элементы
const levelsSection = document.getElementById('levels-section');
const levelContent = document.getElementById('level-content');
const levelTitle = document.getElementById('level-title');
const backBtn = document.getElementById('back-btn');
const tabBtns = document.querySelectorAll('.tab-btn');
const tabContents = document.querySelectorAll('.tab-content');
const vocabSearch = document.getElementById('vocab-search');
// Учитель
const teacherBtn = document.getElementById('teacher-btn');
const teacherChat = document.getElementById('teacher-chat');
const closeChat = document.getElementById('close-chat');
const chatMessages = document.getElementById('chat-messages');
const chatInput = document.getElementById('chat-input');
const sendBtn = document.getElementById('send-btn');
// Инициализация
function init() {
// Клик по уровням
document.querySelectorAll('.level-card').forEach(card => {
card.addEventListener('click', () => {
const level = card.dataset.level;
showLevel(level);
});
});
// Назад
backBtn.addEventListener('click', () => {
levelContent.classList.add('hidden');
levelsSection.classList.remove('hidden');
currentLevel = null;
});
// Табы
tabBtns.forEach(btn => {
btn.addEventListener('click', () => {
const tab = btn.dataset.tab;
switchTab(tab);
});
});
// Поиск слов
vocabSearch.addEventListener('input', (e) => {
filterVocabulary(e.target.value);
});
// Учитель
teacherBtn.addEventListener('click', toggleChat);
closeChat.addEventListener('click', toggleChat);
sendBtn.addEventListener('click', sendMessage);
chatInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') sendMessage();
});
}
// Показать уровень
function showLevel(level) {
currentLevel = level;
const data = levelsData[level];
levelTitle.textContent = data.title;
// Теория
const theoryContent = document.getElementById('theory-content');
theoryContent.innerHTML = data.theory.map(t => `
<div class="theory-card">
<h4>${t.title}</h4>
<p>${t.content}</p>
<div class="example">💡 ${t.example}</div>
</div>
`).join('');
// Словарь
const vocabContent = document.getElementById('vocab-content');
renderVocabulary(data.vocabulary);
// Упражнения
const practiceContent = document.getElementById('practice-content');
practiceContent.innerHTML = data.exercises.map((ex, idx) => `
<div class="exercise-card">
<div class="exercise-question">${idx + 1}. ${ex.question}</div>
<div class="exercise-options">
${ex.options.map((opt, i) => `
<div class="exercise-option" data-exercise="${idx}" data-option="${i}">${opt}</div>
`).join('')}
</div>
<div class="exercise-feedback" id="feedback-${idx}"></div>
</div>
`).join('');
// Обработчики упражнений
document.querySelectorAll('.exercise-option').forEach(opt => {
opt.addEventListener('click', handleExerciseClick);
});
// Переключение
levelsSection.classList.add('hidden');
levelContent.classList.remove('hidden');
}
// Переключение таба
function switchTab(tab) {
tabBtns.forEach(btn => btn.classList.remove('active'));
tabContents.forEach(content => content.classList.remove('active'));
document.querySelector(`[data-tab="${tab}"]`).classList.add('active');
document.getElementById(tab).classList.add('active');
}
// Рендер словаря
function renderVocabulary(vocab) {
const vocabContent = document.getElementById('vocab-content');
vocabContent.innerHTML = vocab.map(w => `
<div class="vocab-item">
<span class="word-en">${w.en}</span>
<span class="word-ru">${w.ru}</span>
</div>
`).join('');
}
// Фильтр словаря
function filterVocabulary(query) {
const data = levelsData[currentLevel];
const filtered = data.vocabulary.filter(w =>
w.en.toLowerCase().includes(query.toLowerCase()) ||
w.ru.toLowerCase().includes(query.toLowerCase())
);
renderVocabulary(filtered);
}
// Обработка упражнения
function handleExerciseClick(e) {
const option = e.target;
const exerciseIdx = parseInt(option.dataset.exercise);
const selectedOption = parseInt(option.dataset.option);
const exercise = levelsData[currentLevel].exercises[exerciseIdx];
const feedback = document.getElementById(`feedback-${exerciseIdx}`);
// Блокируем повторные клики
const parent = option.parentElement;
if (parent.querySelector('.correct') || parent.querySelector('.incorrect')) return;
// Проверка
if (selectedOption === exercise.correct) {
option.classList.add('correct');
feedback.textContent = '✅ Правильно!';
feedback.className = 'exercise-feedback correct';
} else {
option.classList.add('incorrect');
const correctOption = parent.children[exercise.correct];
correctOption.classList.add('correct');
feedback.textContent = '❌ Неправильно. Правильный ответ выделен зелёным.';
feedback.className = 'exercise-feedback incorrect';
}
}
// Учитель - функции
function toggleChat() {
teacherChat.classList.toggle('hidden');
if (!teacherChat.classList.contains('hidden')) {
chatInput.focus();
}
}
async function sendMessage() {
const text = chatInput.value.trim();
if (!text) return;
// Добавляем сообщение студента
addMessage(text, 'student');
chatInput.value = '';
// Показываем индикатор набора
showTypingIndicator();
try {
// Получаем ответ от ИИ
const response = await askTeacher(text);
hideTypingIndicator();
addMessage(response, 'teacher');
} catch (error) {
hideTypingIndicator();
addMessage('Извини, я временно недоступен. Попробуй ещё раз!', 'teacher');
console.error('Teacher error:', error);
}
}
function addMessage(text, type) {
const messageDiv = document.createElement('div');
messageDiv.className = `message ${type}`;
messageDiv.innerHTML = `<div class="message-bubble">${text}</div>`;
chatMessages.appendChild(messageDiv);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
function showTypingIndicator() {
const typing = document.createElement('div');
typing.className = 'message teacher';
typing.id = 'typing-indicator';
typing.innerHTML = `
<div class="message-bubble">
<div class="typing-indicator">
<div class="typing-dot"></div>
<div class="typing-dot"></div>
<div class="typing-dot"></div>
</div>
</div>
`;
chatMessages.appendChild(typing);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
function hideTypingIndicator() {
const typing = document.getElementById('typing-indicator');
if (typing) typing.remove();
}
// Готовые ответы для статической версии (без сервера)
const teacherResponses = {
greetings: {
keywords: ['hello', 'hi', 'привет', 'здравствуй', 'good morning', 'good afternoon'],
answers: [
'Hello! Great to see you! How can I help you with English today?',
'Hi there! Ready to practice English? What would you like to work on?',
'Hello! I\'m your English teacher. Ask me anything about grammar, vocabulary, or let\'s just chat!'
]
},
thanks: {
keywords: ['thank', 'спасибо', 'thanks'],
answers: [
'You\'re welcome! Keep up the good work! 👍',
'Anytime! That\'s what I\'m here for! 😊',
'No problem! Feel free to ask more questions!'
]
},
help: {
keywords: ['help', 'помощь', 'помоги', 'explain', 'объясни'],
answers: [
'I can help you with: grammar rules, vocabulary, pronunciation tips, or just conversation practice. What do you need?',
'Sure! I can explain grammar, check your sentences, or suggest words. What topic interests you?'
]
},
grammar: {
keywords: ['grammar', 'грамматик', 'rule', 'правило', 'tense', 'время'],
answers: [
'Grammar is important! The key is practice. Start with Present Simple - it\'s the most common tense. Example: "I work every day." Want me to explain more?',
'English grammar has 12 tenses, but you only need 5-6 for daily conversation. Which tense would you like to learn?'
]
},
vocabulary: {
keywords: ['word', 'слово', 'vocabulary', 'translate', 'перевод', 'meaning'],
answers: [
'Great question! Building vocabulary takes time. Try learning 5-10 new words daily and use them in sentences. What word interests you?',
'I can help with translations! Just tell me the word you want to know.'
]
},
practice: {
keywords: ['practice', 'практик', 'speak', 'говорить', 'chat', 'болтать'],
answers: [
'Let\'s practice! Tell me about your day in English. Don\'t worry about mistakes - I\'ll help you correct them!',
'Great! Let\'s have a conversation. What topics interest you? Hobbies, work, travel, movies?'
]
},
mistake: {
keywords: ['mistake', 'ошибка', 'wrong', 'correct', 'правильно'],
answers: [
'Mistakes are how we learn! Don\'t be afraid to make them. Even native speakers make mistakes!',
'Good catch! Let me explain the rule so you remember it better.'
]
},
goodbye: {
keywords: ['bye', 'goodbye', 'пока', 'до свидания', 'see you'],
answers: [
'Goodbye! Keep practicing and you\'ll improve fast! See you next time! 👋',
'Bye! Great job today! Come back when you want to practice more!'
]
},
encouragement: {
keywords: ['hard', 'трудно', 'difficult', 'can\'t', 'не могу', 'impossible'],
answers: [
'Learning English takes time, but you\'re doing great! Every day you\'re getting better. Keep going! 💪',
'I understand it can be challenging. Break it into small steps. What specifically is difficult? I\'ll help!'
]
},
level: {
keywords: ['level', 'уровень', 'beginner', 'intermediate', 'advanced'],
answers: [
'Choose your level from the cards above! Each level has theory, vocabulary, and exercises. Start where you feel comfortable.',
'Don\'t worry too much about levels. Just start practicing and you\'ll naturally progress!'
]
}
};
const fallbackAnswers = [
'Interesting! Tell me more about it in English. Practice makes perfect! 😊',
'I see! Can you give me an example sentence? I\'ll help you check it.',
'That\'s a great topic! What specific aspect would you like to discuss?',
'Good question! Let me think... Actually, the best way to learn is through practice. Try making a sentence with this!',
'Hmm, I\'m not sure I understand completely. Can you rephrase that? Or ask me something more specific about English.'
];
function getStaticResponse(message) {
const lower = message.toLowerCase();
// Ищем совпадения по ключевым словам
for (const [category, data] of Object.entries(teacherResponses)) {
if (data.keywords.some(kw => lower.includes(kw))) {
const answers = data.answers;
return answers[Math.floor(Math.random() * answers.length)];
}
}
// Определяем язык
const isRussian = /[а-яА-ЯёЁ]/.test(message);
if (isRussian) {
const ruResponses = [
'Отличный вопрос! Попробуй задать его на английском - я помогу с переводом и грамматикой.',
'Интересно! Расскажи подробнее. Не бойся делать ошибки - я помогу их исправить.',
'Хорошо! Давай обсудим это. Какой аспект тебя интересует?',
'Вопрос понятен! Лучший способ выучить - практиковаться. Попробуй составить предложение на эту тему!',
'Я тут, чтобы помочь! Спроси что-то конкретное о грамматике, словах или давай поболтаем на английском.'
];
return ruResponses[Math.floor(Math.random() * ruResponses.length)];
}
// English fallback
return fallbackAnswers[Math.floor(Math.random() * fallbackAnswers.length)];
}
async function askTeacher(message) {
// Пробуем серверный ИИ (если есть)
try {
const levelContext = currentLevel ? `Current student level: ${currentLevel}. ` : '';
const messages = [
{
role: 'system',
content: `You are a friendly and supportive English teacher. Your tasks:
1. Communicate at the student's level
2. Correct mistakes gently and explain grammar rules
3. Help with vocabulary and constructions
4. Encourage and motivate
5. Answer grammar questions
${levelContext}Respond briefly (2-4 sentences), in a friendly manner. If the student writes in Russian, respond in Russian with English examples. If in English, respond in English but you can add translations of difficult words.`
},
{
role: 'user',
content: message
}
];
const response = await fetch('/api/ai', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ messages }),
timeout: 5000
});
if (!response.ok) {
throw new Error('AI error: ' + response.status);
}
const data = await response.json();
const answer = data.choices?.[0]?.message?.content;
if (!answer) {
throw new Error('Empty AI response');
}
return answer.replace(/\n/g, '<br>');
} catch (error) {
// Фолбэк на статические ответы
console.log('Using static responses:', error.message);
return getStaticResponse(message);
}
}
// Запуск
init();