From 033adf023eb3acffb9c9089b8d8c2f27ef69d91b Mon Sep 17 00:00:00 2001 From: Drobysh Date: Sun, 20 Sep 2026 11:45:58 +0000 Subject: [PATCH] initial commit (backend) --- .env.save | 19 + .gitignore | 9 + __init__.py | 0 add_levels.py | 258 + add_sentences.py | 75 + archive_old_data.py | 221 + auth.py | 108 + config.py | 63 + database.py | 870 ++++ export_backend.sh | 55 + fix_learning.py | 43 + fix_polish_options.py | 135 + fix_review.py | 113 + full_reset.py | 85 + generate_daily_phrase.py | 200 + generate_levels_v2.py | 273 ++ init_options_language.py | 75 + init_teacher_data.py | 195 + load_all_words.py | 55 + main.py | 286 ++ pytest.ini | 17 + requirements.txt | 38 + reset_my_progress.py | 65 + routers/__init__.py | 0 routers/achievements.py | 530 +++ routers/admin.py | 148 + routers/admin_content.py | 1213 +++++ routers/assistant.py | 480 ++ routers/bubblewords.py | 274 ++ routers/feed.py | 725 +++ routers/game.py | 330 ++ routers/hints.py | 152 + routers/leaderboard.py | 333 ++ routers/learning.py | 872 ++++ routers/learning_data/__init__.py | 40 + routers/learning_data/level_a1.py | 7358 +++++++++++++++++++++++++++++ routers/learning_data/level_a2.py | 6420 +++++++++++++++++++++++++ routers/learning_data/level_b1.py | 3 + routers/learning_data/level_b2.py | 3 + routers/learning_data/level_c1.py | 3 + routers/learning_data/level_c2.py | 3 + routers/learning_profile.py | 56 + routers/orchestrator.py | 286 ++ routers/pronunciation.py | 46 + routers/sentences.py | 290 ++ routers/support.py | 359 ++ routers/teacher.py | 1164 +++++ routers/tts.py | 99 + routers/typing.py | 141 + routers/users.py | 106 + routers/wordquiz.py | 282 ++ sentences_a1.csv | 201 + sentences_a2.csv | 101 + sentences_b1.csv | 101 + services/__init__.py | 0 services/grid_generator.py | 0 services/word_bank.py | 0 tests/__init__.py | 1 + tests/conftest.py | 120 + tests/test_achievements.py | 75 + tests/test_mastery.py | 171 + tests/test_orchestrator.py | 99 + words_a1.csv | 758 +++ words_a2.csv | 843 ++++ words_b1.csv | 848 ++++ 65 files changed, 28292 insertions(+) create mode 100644 .env.save create mode 100644 .gitignore create mode 100644 __init__.py create mode 100644 add_levels.py create mode 100644 add_sentences.py create mode 100644 archive_old_data.py create mode 100644 auth.py create mode 100644 config.py create mode 100644 database.py create mode 100755 export_backend.sh create mode 100644 fix_learning.py create mode 100644 fix_polish_options.py create mode 100644 fix_review.py create mode 100644 full_reset.py create mode 100644 generate_daily_phrase.py create mode 100644 generate_levels_v2.py create mode 100644 init_options_language.py create mode 100644 init_teacher_data.py create mode 100644 load_all_words.py create mode 100644 main.py create mode 100644 pytest.ini create mode 100644 requirements.txt create mode 100644 reset_my_progress.py create mode 100644 routers/__init__.py create mode 100644 routers/achievements.py create mode 100644 routers/admin.py create mode 100644 routers/admin_content.py create mode 100644 routers/assistant.py create mode 100644 routers/bubblewords.py create mode 100644 routers/feed.py create mode 100644 routers/game.py create mode 100644 routers/hints.py create mode 100644 routers/leaderboard.py create mode 100644 routers/learning.py create mode 100644 routers/learning_data/__init__.py create mode 100644 routers/learning_data/level_a1.py create mode 100644 routers/learning_data/level_a2.py create mode 100644 routers/learning_data/level_b1.py create mode 100644 routers/learning_data/level_b2.py create mode 100644 routers/learning_data/level_c1.py create mode 100644 routers/learning_data/level_c2.py create mode 100644 routers/learning_profile.py create mode 100644 routers/orchestrator.py create mode 100644 routers/pronunciation.py create mode 100644 routers/sentences.py create mode 100644 routers/support.py create mode 100644 routers/teacher.py create mode 100644 routers/tts.py create mode 100644 routers/typing.py create mode 100644 routers/users.py create mode 100644 routers/wordquiz.py create mode 100644 sentences_a1.csv create mode 100644 sentences_a2.csv create mode 100644 sentences_b1.csv create mode 100644 services/__init__.py create mode 100644 services/grid_generator.py create mode 100644 services/word_bank.py create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/test_achievements.py create mode 100644 tests/test_mastery.py create mode 100644 tests/test_orchestrator.py create mode 100644 words_a1.csv create mode 100644 words_a2.csv create mode 100644 words_b1.csv diff --git a/.env.save b/.env.save new file mode 100644 index 0000000..ee43fb0 --- /dev/null +++ b/.env.save @@ -0,0 +1,19 @@ +BOT_TOKEN=8886420359:AAEZgOsEBEk3pthIEJboUIb0MJZk0mGFX-A +DB_PASSWORD=filwords123 +BOT_SECRET=filwords_secret_2024_random_string_here +ADMIN_IDS=6694989403 +FRONTEND_ORIGIN=https://filwordspl.com +DB_USER=filwords +DB_NAME=filwords +DB_HOST=localhost +DB_PORT=5432 +TOGETHER_API_KEY=tgp_v1_7aSO98nDDhBtZS2sq1_Q1Q61AD7V1TrKKAiNbJlsusc +SENTRY_DSN=https://a285ea156048a1adc7f0d00b3d49e90c@o4512063249121280.ingest.de.sentry.io/4512063274090576 +ENV=production +# Версия приложения (используется в Sentry release) +APP_VERSION=3.3.8щ + +SENTRY_AUTH_TOKEN=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 +SENTRY_ORG_SLUG=drobysh +SENTRY_PROJECT_SLUG=filwords-backend +SENTRY_API_BASE=https://de.sentry.io/api/0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..335bf28 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +.env +venv/ +__pycache__/ +*.pyc +tts_cache/ +archive/ +uploads/ +*.log +.DS_Store diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/add_levels.py b/add_levels.py new file mode 100644 index 0000000..2a67d04 --- /dev/null +++ b/add_levels.py @@ -0,0 +1,258 @@ +""" +Безопасное добавление уровней без удаления старых. +Использует только words.csv. +""" +import asyncio +import asyncpg +import json +import random +import csv +from config import DB_CONFIG + + +DIRECTIONS = [(-1,0),(0,-1),(0,1),(1,0)] +ALPHABET = "AĄBCĆDEĘFGHIJKLŁMNŃOÓPRSŚTUWYZŹŻ" + + +def load_words_from_csv(filenames): + words_by_theme = {} + translations = {} + for filename in filenames: + with open(filename, 'r', encoding='utf-8') as f: + reader = csv.DictReader(f) + for row in reader: + theme = row['theme'] + word = row['polish'].lower() + if theme not in words_by_theme: + words_by_theme[theme] = [] + if word not in words_by_theme[theme]: + words_by_theme[theme].append(word) + translations[word] = { + 'en': row['english'], + 'ru': row['russian'], + 'uk': row['ukrainian'] + } + return words_by_theme, translations + + +def get_words_for_grid(words_by_theme, theme, num_words, grid_size): + max_len = grid_size + candidates = [w for w in words_by_theme[theme] if len(w) <= max_len] + if len(candidates) < num_words: + candidates = words_by_theme[theme] + random.shuffle(candidates) + return candidates[:num_words] + + +def try_place_word(word, grid_size, occupied, max_attempts=500): + word = word.upper() + for _ in range(max_attempts): + start = (random.randrange(grid_size), random.randrange(grid_size)) + if start in occupied: + continue + path = [start] + visited = {start} + ok = True + for _ in range(len(word) - 1): + r, c = path[-1] + candidates = [] + for dr, dc in DIRECTIONS: + nr, nc = r + dr, c + dc + if 0 <= nr < grid_size and 0 <= nc < grid_size: + if (nr, nc) not in occupied and (nr, nc) not in visited: + candidates.append((nr, nc)) + if not candidates: + ok = False + break + nxt = random.choice(candidates) + path.append(nxt) + visited.add(nxt) + if ok and len(path) == len(word): + return path + return None + + +def fill_empty_cells(grid, grid_size, occupied, words_by_theme, all_words): + empty_cells = set() + for r in range(grid_size): + for c in range(grid_size): + if (r, c) not in occupied: + empty_cells.add((r, c)) + + if not empty_cells: + return [], {} + + filler_words = [] + for theme in words_by_theme: + for w in words_by_theme[theme]: + if 2 <= len(w) <= 4 and w not in all_words: + filler_words.append(w) + + filler_words = sorted(list(set(filler_words)), key=len, reverse=True) + random.shuffle(filler_words) + + filled_paths = {} + filled_words = [] + remaining_empty = empty_cells.copy() + + for word in filler_words: + if len(word) > len(remaining_empty): + continue + + for _ in range(500): + if not remaining_empty: + break + start = random.choice(list(remaining_empty)) + + path = [start] + visited = {start} + ok = True + + for _ in range(len(word) - 1): + r, c = path[-1] + candidates = [] + for dr, dc in DIRECTIONS: + nr, nc = r + dr, c + dc + if 0 <= nr < grid_size and 0 <= nc < grid_size: + if (nr, nc) in remaining_empty and (nr, nc) not in visited: + candidates.append((nr, nc)) + if not candidates: + ok = False + break + nxt = random.choice(candidates) + path.append(nxt) + visited.add(nxt) + + if ok and len(path) == len(word): + for (r, c), letter in zip(path, word.upper()): + grid[r][c] = letter + if (r, c) in remaining_empty: + remaining_empty.remove((r, c)) + + filled_paths[word] = [list(p) for p in path] + filled_words.append(word) + break + + for r, c in remaining_empty: + grid[r][c] = random.choice(ALPHABET) + + return filled_words, filled_paths + + +def generate_grid(words, grid_size, words_by_theme, max_restarts=200): + words_sorted = sorted(words, key=len, reverse=True) + for _ in range(max_restarts): + grid = [['' for _ in range(grid_size)] for _ in range(grid_size)] + occupied = set() + word_paths = {} + success = True + + for word in words_sorted: + path = try_place_word(word, grid_size, occupied) + if path is None: + success = False + break + for (r, c), letter in zip(path, word.upper()): + grid[r][c] = letter + occupied.update(path) + word_paths[word] = [list(p) for p in path] + + if not success: + continue + + all_words = set(words_sorted) + filled_words, filled_paths = fill_empty_cells( + grid, grid_size, occupied, words_by_theme, all_words + ) + + word_paths.update(filled_paths) + all_placed_words = words_sorted + filled_words + + return grid, word_paths, all_placed_words + + return None, None, None + + +async def save_level(conn, level_num, grid_size, theme, grid, word_paths, words, translations): + level = await conn.fetchrow( + """INSERT INTO levels (level_number, grid_size, theme, grid_letters, word_paths) + VALUES ($1, $2, $3, $4, $5) RETURNING id""", + level_num, grid_size, theme, json.dumps(grid), json.dumps(word_paths) + ) + level_id = level['id'] + for word in words: + trans = translations.get(word, {}) + await conn.execute( + """INSERT INTO level_words (level_id, word_pl, translation_ru, translation_uk, translation_en) + VALUES ($1, $2, $3, $4, $5)""", + level_id, word, + trans.get('ru', ''), + trans.get('uk', ''), + trans.get('en', '') + ) + + +async def main(): + # ============ НАСТРОЙКИ ============ + words_by_theme, translations = load_words_from_csv([ + 'words.csv' + ]) + + NEW_LEVEL_CONFIG = [ + (25, 10, 9), # 25 уровней: 10x10, 9 слов + (25, 10, 10), # 25 уровней: 10x10, 10 слов + (25, 10, 11), # 25 уровней: 10x10, 11 слов + (25, 10, 12), # 25 уровней: 10x10, 12 слов + ] + # ================================== + + conn = await asyncpg.connect(**DB_CONFIG) + + current_max = await conn.fetchval("SELECT COALESCE(MAX(level_number), 0) FROM levels") + print(f"Сейчас уровней в базе: {current_max}") + print(f"Добавляем уровни {current_max + 1}–{current_max + 100}") + + themes = list(words_by_theme.keys()) + random.shuffle(themes) + + level_num = current_max + theme_idx = 0 + total_generated = 0 + + for count, grid_size, num_words in NEW_LEVEL_CONFIG: + for i in range(count): + level_num += 1 + + for attempt in range(15): + theme = themes[theme_idx % len(themes)] + theme_idx += 1 + + words = get_words_for_grid(words_by_theme, theme, num_words, grid_size) + if len(words) < num_words: + continue + + grid, word_paths, all_words = generate_grid( + words, grid_size, words_by_theme + ) + if grid is not None: + await save_level( + conn, level_num, grid_size, theme, + grid, word_paths, all_words, translations + ) + total_cells = grid_size * grid_size + filled_cells = sum(len(w) for w in all_words) + print(f"✅ Level {level_num}: {grid_size}x{grid_size}, " + f"theme={theme}, words={len(all_words)} ({num_words} main), " + f"fill={filled_cells}/{total_cells}") + total_generated += 1 + break + else: + print(f"❌ FAILED: Level {level_num} after 15 attempts") + level_num -= 1 + + await conn.close() + print(f"\n🎉 Готово! Добавлено {total_generated} новых уровней. Теперь всего уровней: {level_num}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/add_sentences.py b/add_sentences.py new file mode 100644 index 0000000..cd3f31d --- /dev/null +++ b/add_sentences.py @@ -0,0 +1,75 @@ +""" +Загрузка предложений по уровням (A1, A2, B1). +Каждый уровень загружается из отдельного CSV файла. +Нумерация предложений начинается с 1 для каждого уровня. +""" +import asyncio +import asyncpg +import csv +from config import DB_CONFIG + + +def load_sentences_from_csv(filename): + """Загружает предложения из CSV файла (формат: polish,english,russian,ukrainian).""" + sentences = [] + with open(filename, 'r', encoding='utf-8') as f: + reader = csv.DictReader(f) + for row in reader: + sentences.append({ + "sentence_pl": row["polish"].strip(), + "translation_ru": row.get("russian", ""), + "translation_uk": row.get("ukrainian", ""), + "translation_en": row.get("english", ""), + }) + return sentences + + +async def main(): + conn = await asyncpg.connect(**DB_CONFIG) + + level_files = [ + ("A1", "sentences_a1.csv"), + ("A2", "sentences_a2.csv"), + ("B1", "sentences_b1.csv"), + ] + + total_added = 0 + + for level, filename in level_files: + print(f"\n{'='*50}") + print(f"Загружаю предложения уровня {level} из {filename}") + print(f"{'='*50}") + + sentences = load_sentences_from_csv(filename) + + # Удаляем старые предложения этого уровня + await conn.execute("DELETE FROM sentences WHERE level = $1", level) + + # Нумерация начинается с 1 для каждого уровня + max_num = 0 + + added = 0 + for s in sentences: + max_num += 1 + words_count = len(s["sentence_pl"].split()) + difficulty = 1 if words_count <= 4 else 2 if words_count <= 6 else 3 + + await conn.execute( + """INSERT INTO sentences (sentence_number, sentence_pl, translation_ru, translation_uk, translation_en, difficulty, level) + VALUES ($1, $2, $3, $4, $5, $6, $7)""", + max_num, s["sentence_pl"], + s["translation_ru"], s["translation_uk"], s["translation_en"], + difficulty, level + ) + added += 1 + print(f"✅ {level} #{max_num}: {s['sentence_pl'][:60]}...") + + total_added += added + print(f"Добавлено {added} предложений уровня {level}") + + await conn.close() + print(f"\n🎉 Готово! Всего добавлено {total_added} предложений") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/archive_old_data.py b/archive_old_data.py new file mode 100644 index 0000000..29105a0 --- /dev/null +++ b/archive_old_data.py @@ -0,0 +1,221 @@ +""" +Архивация старых данных: +1. Ответы старше 30 дней → user_learning_answers_archive (агрегаты) +2. Данные архива старше 1 года → JSON файлы на диске +3. Удаление из основных таблиц + +Запуск: python3 archive_old_data.py +Или через cron: 0 3 * * * cd /root/filwordspl/backend && source venv/bin/activate && python3 archive_old_data.py +""" +import asyncio +import asyncpg +import json +import os +import logging +from datetime import datetime, timedelta, timezone +from decimal import Decimal +from pathlib import Path +from config import DB_CONFIG + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +# Настройки +HOT_DAYS = 30 # Сколько дней хранить в основной таблице +ARCHIVE_DIR = Path("/root/filwordspl/backend/archive") # Директория для JSON файлов + + +def serialize_value(value): + """Преобразует Decimal и datetime в JSON-совместимые типы.""" + if value is None: + return None + if hasattr(value, 'isoformat'): + return value.isoformat() + if isinstance(value, Decimal): + return float(value) + if isinstance(value, (int, float, bool, str)): + return value + return str(value) + + +async def archive_learning_answers(conn): + """Переносит ответы старше 30 дней в архивную таблицу.""" + + # Переносим в архив + moved = await conn.execute(""" + INSERT INTO user_learning_answers_archive (user_id, skill_tag, correct, wrong_because, created_at) + SELECT user_id, skill_tag, correct, wrong_because, created_at::date + FROM user_learning_answers + WHERE created_at < NOW() - INTERVAL '30 days' + """) + + # Удаляем из основной таблицы + deleted = await conn.execute(""" + DELETE FROM user_learning_answers + WHERE created_at < NOW() - INTERVAL '30 days' + """) + + logger.info(f"Архивация ответов: перенесено={moved}, удалено={deleted}") + return moved, deleted + + +async def export_archive_to_json(conn): + """Экспортирует данные архива старше 1 года в JSON файлы.""" + + # Получаем данные старше 1 года + old_records = await conn.fetch(""" + SELECT * FROM user_learning_answers_archive + WHERE created_at < NOW() - INTERVAL '1 year' + """) + + if not old_records: + logger.info("Нет данных старше 1 года для экспорта") + return 0 + + # Группируем по году и пользователю + grouped = {} + for record in old_records: + year = record["created_at"].year if record["created_at"] else datetime.now().year + user_id = record["user_id"] + + if year not in grouped: + grouped[year] = {} + if user_id not in grouped[year]: + grouped[year][user_id] = [] + + grouped[year][user_id].append({ + "id": record["id"], + "user_id": record["user_id"], + "skill_tag": record["skill_tag"], + "correct": record["correct"], + "wrong_because": record["wrong_because"], + "created_at": serialize_value(record["created_at"]), + "archived_at": serialize_value(record["archived_at"]), + }) + + # Сохраняем в JSON файлы + total_saved = 0 + for year, users in grouped.items(): + year_dir = ARCHIVE_DIR / str(year) + year_dir.mkdir(parents=True, exist_ok=True) + + for user_id, records in users.items(): + file_path = year_dir / f"user_{user_id}_answers.json" + + # Если файл существует — дополняем + existing_data = [] + if file_path.exists(): + try: + with open(file_path, 'r', encoding='utf-8') as f: + existing_data = json.load(f) + except: + existing_data = [] + + all_data = existing_data + records + + with open(file_path, 'w', encoding='utf-8') as f: + json.dump(all_data, f, ensure_ascii=False, indent=2) + + total_saved += len(records) + + # Удаляем экспортированные записи из архива + if old_records: + ids = [r["id"] for r in old_records] + await conn.execute(""" + DELETE FROM user_learning_answers_archive WHERE id = ANY($1) + """, ids) + + logger.info(f"Экспортировано в JSON: {total_saved} записей") + return total_saved + + +async def archive_chat_history(conn): + """Архивирует старую историю чата (старше 6 месяцев).""" + + # Экспортируем старую историю в JSON + old_messages = await conn.fetch(""" + SELECT * FROM chat_history + WHERE created_at < NOW() - INTERVAL '6 months' + """) + + if old_messages: + # Группируем по году и пользователю + grouped = {} + for msg in old_messages: + year = msg["created_at"].year if msg["created_at"] else datetime.now().year + user_id = msg["user_id"] + + if year not in grouped: + grouped[year] = {} + if user_id not in grouped[year]: + grouped[year][user_id] = [] + + grouped[year][user_id].append({ + "id": msg["id"], + "user_id": msg["user_id"], + "message": msg["message"], + "is_user": msg["is_user"], + "created_at": serialize_value(msg["created_at"]), + }) + + # Сохраняем в JSON + total_saved = 0 + for year, users in grouped.items(): + year_dir = ARCHIVE_DIR / str(year) + year_dir.mkdir(parents=True, exist_ok=True) + + for user_id, messages in users.items(): + file_path = year_dir / f"user_{user_id}_chat.json" + + existing_data = [] + if file_path.exists(): + try: + with open(file_path, 'r', encoding='utf-8') as f: + existing_data = json.load(f) + except: + existing_data = [] + + all_data = existing_data + messages + + with open(file_path, 'w', encoding='utf-8') as f: + json.dump(all_data, f, ensure_ascii=False, indent=2) + + total_saved += len(messages) + + # Удаляем старые сообщения + await conn.execute(""" + DELETE FROM chat_history + WHERE created_at < NOW() - INTERVAL '6 months' + """) + + logger.info(f"Архивация чата: {total_saved} сообщений в JSON") + return total_saved + + logger.info("Нет старой истории чата для архивации") + return 0 + + +async def main(): + logger.info("=== Начало архивации ===") + + conn = await asyncpg.connect(**DB_CONFIG) + + try: + # 1. Архивация ответов + moved, deleted = await archive_learning_answers(conn) + + # 2. Экспорт архива в JSON + exported = await export_archive_to_json(conn) + + # 3. Архивация чата + chat_archived = await archive_chat_history(conn) + + logger.info(f"=== Архивация завершена: ответы={moved}, JSON={exported}, чат={chat_archived} ===") + except Exception as e: + logger.error(f"Ошибка архивации: {str(e)}") + finally: + await conn.close() + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/auth.py b/auth.py new file mode 100644 index 0000000..da948af --- /dev/null +++ b/auth.py @@ -0,0 +1,108 @@ +import time +import hmac +import hashlib +import json +from urllib.parse import unquote +from fastapi import Request, HTTPException +from config import BOT_TOKEN, MAX_INITDATA_AGE + + +async def verify_telegram_initdata(init_data: str): + """Проверяет подпись initData от Telegram с проверкой срока действия""" + try: + # Парсим initData + data = {} + for chunk in init_data.split('&'): + if '=' in chunk: + key, value = chunk.split('=', 1) + data[key] = unquote(value) + + # Извлекаем hash + received_hash = data.pop('hash', '') + + if not received_hash: + raise HTTPException(401, "Hash not found in initData") + + # Проверяем auth_date (не старше MAX_INITDATA_AGE из config) + auth_date_str = data.get('auth_date', '0') + try: + auth_date = int(auth_date_str) + current_time = int(time.time()) + + if current_time - auth_date > MAX_INITDATA_AGE: + raise HTTPException(401, "initData expired") + + if auth_date > current_time + 60: + raise HTTPException(401, "initData from future") + + except ValueError: + raise HTTPException(401, "Invalid auth_date") + + # Сортируем ключи и создаем строку для проверки + check_arr = [] + for key in sorted(data.keys()): + check_arr.append(f"{key}={data[key]}") + check_string = '\n'.join(check_arr) + + # Создаем секретный ключ + secret_key = hmac.new( + 'WebAppData'.encode(), + BOT_TOKEN.encode(), + hashlib.sha256 + ).digest() + + # Вычисляем hash + calculated_hash = hmac.new( + secret_key, + check_string.encode(), + hashlib.sha256 + ).hexdigest() + + if calculated_hash != received_hash: + raise HTTPException(401, "Invalid initData signature") + + # Извлекаем данные пользователя + user_data_str = data.get('user', '{}') + try: + user_data = json.loads(user_data_str) + except json.JSONDecodeError: + raise HTTPException(401, "Invalid user data JSON") + + user_id = user_data.get('id') + username = user_data.get('username', '') + first_name = user_data.get('first_name', '') + + if not user_id: + raise HTTPException(401, "User ID not found in initData") + + return user_id, username + + except HTTPException: + raise + except Exception as e: + raise HTTPException(401, f"Auth error: {str(e)}") + + +async def require_auth(request: Request): + """Извлекает и проверяет initData из запроса""" + # Пробуем из query-параметров + init_data = request.query_params.get('initData', '') + + if not init_data: + # Пробуем из заголовков + init_data = request.headers.get('X-Telegram-InitData', '') + + if not init_data: + # Пробуем из тела для POST запросов + # (некоторые клиенты могут отправлять initData в теле) + pass + + if not init_data: + raise HTTPException(401, "initData required. Pass as query parameter 'initData' or header 'X-Telegram-InitData'") + + # Декодируем URL-encoded initData если нужно + if '%' in init_data: + init_data = unquote(init_data) + + user_id, username = await verify_telegram_initdata(init_data) + return user_id, username \ No newline at end of file diff --git a/config.py b/config.py new file mode 100644 index 0000000..bc076e3 --- /dev/null +++ b/config.py @@ -0,0 +1,63 @@ +import os +from dotenv import load_dotenv + +load_dotenv() + +# Проверка критических переменных +for var in ["BOT_TOKEN", "DB_PASSWORD", "BOT_SECRET"]: + if var not in os.environ: + raise RuntimeError(f"Missing required environment variable: {var}") + +BOT_TOKEN = os.environ["BOT_TOKEN"] +BOT_SECRET = os.environ["BOT_SECRET"] + +# Together AI для AI-помощника +TOGETHER_API_KEY = os.getenv("TOGETHER_API_KEY", "") + +DB_CONFIG = { + "user": os.getenv("DB_USER", "filwords"), + "password": os.environ["DB_PASSWORD"], + "database": os.getenv("DB_NAME", "filwords"), + "host": os.getenv("DB_HOST", "localhost"), + "port": int(os.getenv("DB_PORT", "5432")), +} + +ADMIN_IDS = [int(id_str) for id_str in os.getenv("ADMIN_IDS", "6694989403").split(",") if id_str] +FRONTEND_ORIGIN = os.getenv("FRONTEND_ORIGIN", "https://filwordspl.com") + +# 🔧 ИСПРАВЛЕНО: единое значение — 24 часа. +# Раньше в auth.py было локально 24 часа, а здесь 3600 (1 час) — это был конфликт. +# Теперь значение берётся ТОЛЬКО отсюда. +MAX_INITDATA_AGE = 24 * 60 * 60 # 24 часа в секундах + +SUPPORTED_LANGUAGES = {"pl", "ru", "uk", "en"} + +# ============ 🔧 НОВОЕ (18.09.2026): настройки для FeedModal ============ +# Папка для хранения картинок feed-постов. +# Путь совпадает с backend/, файлы доступны как static mounts (см. main.py при необходимости). +UPLOADS_DIR = os.getenv("UPLOADS_DIR", "/root/filwordspl/backend/uploads") + +# Автосоздание папки — безопасно запускать повторно (exist_ok=True) +os.makedirs(UPLOADS_DIR, exist_ok=True) + +# Секции карусели (совпадают с SECTION_CONFIG в FeedModal.tsx) +FEED_SECTIONS = {"news", "partners", "contacts", "apps"} + +# Лимит картинок на один пост (совпадает с описанием — до 3) +MAX_FEED_ATTACHMENTS = 3 + +# Лимит размера одной картинки — 5 МБ +MAX_FEED_IMAGE_SIZE_MB = 5 +MAX_FEED_IMAGE_SIZE_BYTES = MAX_FEED_IMAGE_SIZE_MB * 1024 * 1024 + +# Разрешённые MIME-типы для картинок feed +FEED_ALLOWED_IMAGE_TYPES = { + "image/jpeg", + "image/jpg", + "image/png", + "image/webp", + "image/gif", +} + +# Языки, на которые переводим feed-посты (используется в admin_feed translate) +FEED_TARGET_LANGUAGES = ["pl", "ru", "uk", "en"] \ No newline at end of file diff --git a/database.py b/database.py new file mode 100644 index 0000000..4320d1a --- /dev/null +++ b/database.py @@ -0,0 +1,870 @@ +import asyncpg +import logging +from config import DB_CONFIG + +logger = logging.getLogger(__name__) +db_pool = None + +async def get_pool(): + global db_pool + if db_pool is None: + db_pool = await asyncpg.create_pool(**DB_CONFIG, min_size=2, max_size=10) + return db_pool + +async def init_db(): + pool = await get_pool() + async with pool.acquire() as conn: + # ============ users ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS users ( + id SERIAL PRIMARY KEY, + telegram_id BIGINT UNIQUE NOT NULL, + username TEXT, + app_language TEXT DEFAULT 'pl', + current_level TEXT DEFAULT 'A1', + last_completed_level INTEGER DEFAULT 0, + created_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ Авто-миграция: добавляем current_level в users ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'users' AND column_name = 'current_level' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE users + ADD COLUMN current_level TEXT DEFAULT 'A1' + """) + logger.info("Added current_level column to users") + + # ============ levels ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS levels ( + id SERIAL PRIMARY KEY, + level_number INTEGER NOT NULL, + grid_size INTEGER NOT NULL, + game_type TEXT DEFAULT 'wordsearch', + level TEXT DEFAULT 'A1', + grid_letters JSONB NOT NULL DEFAULT '[]', + word_paths JSONB NOT NULL DEFAULT '{}' + ) + """) + + # ============ Убираем старый UNIQUE constraint с levels.level_number ============ + await conn.execute(""" + ALTER TABLE levels DROP CONSTRAINT IF EXISTS levels_level_number_key + """) + + # ============ Добавляем составной UNIQUE (level, level_number) ============ + await conn.execute(""" + DO $$ + BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint + WHERE conname = 'levels_level_number_unique' + ) THEN + ALTER TABLE levels ADD CONSTRAINT levels_level_number_unique UNIQUE (level, level_number); + END IF; + END $$; + """) + + # ============ level_words ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS level_words ( + id SERIAL PRIMARY KEY, + level_id INTEGER REFERENCES levels(id) ON DELETE CASCADE, + word_pl TEXT NOT NULL, + translation_ru TEXT DEFAULT '', + translation_uk TEXT DEFAULT '', + translation_en TEXT DEFAULT '', + level TEXT DEFAULT 'A1' + ) + """) + + # ============ Авто-миграция: добавляем level в level_words ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'level_words' AND column_name = 'level' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE level_words + ADD COLUMN level TEXT DEFAULT 'A1' + """) + logger.info("Added level column to level_words") + + # ============ user_progress ============ + existing = await conn.fetchrow(""" + SELECT data_type + FROM information_schema.columns + WHERE table_name = 'user_progress' AND column_name = 'user_id' + """) + + if existing and existing['data_type'] != 'bigint': + logger.info("Migrating user_progress.user_id from INTEGER to BIGINT") + await conn.execute(""" + ALTER TABLE user_progress + DROP CONSTRAINT IF EXISTS user_progress_pkey CASCADE + """) + await conn.execute(""" + ALTER TABLE user_progress + DROP CONSTRAINT IF EXISTS user_progress_user_id_fkey + """) + await conn.execute(""" + ALTER TABLE user_progress + ALTER COLUMN user_id TYPE BIGINT + """) + await conn.execute(""" + ALTER TABLE user_progress + ADD PRIMARY KEY (user_id, level_id) + """) + await conn.execute(""" + ALTER TABLE user_progress + ADD FOREIGN KEY (user_id) REFERENCES users(telegram_id) ON DELETE CASCADE + """) + elif not existing: + await conn.execute(""" + CREATE TABLE IF NOT EXISTS user_progress ( + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + level_id INTEGER REFERENCES levels(id) ON DELETE CASCADE, + completed_at TIMESTAMP, + hints_used INTEGER DEFAULT 0, + score INTEGER DEFAULT 0, + level TEXT DEFAULT 'A1', + PRIMARY KEY (user_id, level_id) + ) + """) + + # ============ Авто-миграция: добавляем level в user_progress ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'user_progress' AND column_name = 'level' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE user_progress + ADD COLUMN level TEXT DEFAULT 'A1' + """) + logger.info("Added level column to user_progress") + + # ============ sentences ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS sentences ( + id SERIAL PRIMARY KEY, + sentence_number INTEGER NOT NULL, + sentence_pl TEXT NOT NULL, + translation_ru TEXT DEFAULT '', + translation_uk TEXT DEFAULT '', + translation_en TEXT DEFAULT '', + difficulty INTEGER DEFAULT 1, + level TEXT DEFAULT 'A1' + ) + """) + + # ============ Убираем старый UNIQUE constraint с sentences.sentence_number ============ + await conn.execute(""" + ALTER TABLE sentences DROP CONSTRAINT IF EXISTS sentences_sentence_number_key + """) + + # ============ Добавляем составной UNIQUE (level, sentence_number) ============ + await conn.execute(""" + DO $$ + BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_constraint + WHERE conname = 'sentences_sentence_number_unique' + ) THEN + ALTER TABLE sentences ADD CONSTRAINT sentences_sentence_number_unique UNIQUE (level, sentence_number); + END IF; + END $$; + """) + + # ============ sentence_progress ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS sentence_progress ( + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + sentence_id INTEGER REFERENCES sentences(id) ON DELETE CASCADE, + completed_at TIMESTAMP, + score INTEGER DEFAULT 0, + level TEXT DEFAULT 'A1', + PRIMARY KEY (user_id, sentence_id) + ) + """) + + # ============ Авто-миграция: добавляем level в sentence_progress ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'sentence_progress' AND column_name = 'level' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE sentence_progress + ADD COLUMN level TEXT DEFAULT 'A1' + """) + logger.info("Added level column to sentence_progress") + + # ============ typing_progress ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS typing_progress ( + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + sentence_id INTEGER REFERENCES sentences(id) ON DELETE CASCADE, + completed_at TIMESTAMP DEFAULT NOW(), + PRIMARY KEY (user_id, sentence_id) + ) + """) + + # ============ Индекс для typing_progress ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_typing_progress_user ON typing_progress(user_id)") + + # ============ chat_history ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS chat_history ( + id SERIAL PRIMARY KEY, + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + message TEXT NOT NULL, + is_user BOOLEAN DEFAULT TRUE, + created_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ Индекс для chat_history ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_chat_history_user ON chat_history(user_id, created_at DESC)") + + # ============ chat_usage ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS chat_usage ( + id SERIAL PRIMARY KEY, + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + usage_date DATE DEFAULT CURRENT_DATE, + message_count INTEGER DEFAULT 0, + UNIQUE (user_id, usage_date) + ) + """) + + # ============ Индекс для chat_usage ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_chat_usage_user ON chat_usage(user_id, usage_date DESC)") + + # ============ learning_levels ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS learning_levels ( + id SERIAL PRIMARY KEY, + code VARCHAR(10) UNIQUE NOT NULL, + name_pl TEXT NOT NULL, + name_ru TEXT NOT NULL, + name_uk TEXT NOT NULL, + name_en TEXT NOT NULL, + sort_order INT NOT NULL, + is_active BOOLEAN DEFAULT TRUE + ) + """) + + # ============ learning_topics ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS learning_topics ( + id SERIAL PRIMARY KEY, + topic_id VARCHAR(100) UNIQUE NOT NULL, + level_code VARCHAR(10) NOT NULL, + order_number INT NOT NULL, + name_pl TEXT NOT NULL, + name_ru TEXT NOT NULL, + name_uk TEXT NOT NULL, + name_en TEXT NOT NULL, + description_pl TEXT, + description_ru TEXT, + description_uk TEXT, + description_en TEXT, + is_active BOOLEAN DEFAULT TRUE, + UNIQUE(level_code, order_number) + ) + """) + + # ============ learning_lessons ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS learning_lessons ( + id SERIAL PRIMARY KEY, + lesson_id VARCHAR(120) UNIQUE NOT NULL, + topic_id VARCHAR(100) NOT NULL REFERENCES learning_topics(topic_id), + order_number INT NOT NULL, + skill_tag VARCHAR(100) NOT NULL, + title_pl TEXT NOT NULL, + title_ru TEXT NOT NULL, + title_uk TEXT NOT NULL, + title_en TEXT NOT NULL, + objective_pl TEXT, + objective_ru TEXT, + objective_uk TEXT, + objective_en TEXT, + explanation_pl TEXT, + explanation_ru TEXT, + explanation_uk TEXT, + explanation_en TEXT, + is_active BOOLEAN DEFAULT TRUE, + UNIQUE(topic_id, order_number) + ) + """) + + # ============ lesson_examples ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS lesson_examples ( + id SERIAL PRIMARY KEY, + lesson_id VARCHAR(120) NOT NULL REFERENCES learning_lessons(lesson_id), + order_number INT NOT NULL, + text_pl TEXT NOT NULL, + text_ru TEXT, + text_uk TEXT, + text_en TEXT, + audio_url TEXT + ) + """) + + # ============ learning_questions ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS learning_questions ( + id SERIAL PRIMARY KEY, + question_id VARCHAR(150) UNIQUE NOT NULL, + lesson_id VARCHAR(120) REFERENCES learning_lessons(lesson_id), + topic_id VARCHAR(100) NOT NULL REFERENCES learning_topics(topic_id), + context_type VARCHAR(50) NOT NULL, + question_type VARCHAR(50) NOT NULL, + skill_tag VARCHAR(100) NOT NULL, + difficulty INT NOT NULL CHECK (difficulty BETWEEN 1 AND 3), + prompt_pl TEXT, + prompt_ru TEXT, + prompt_uk TEXT, + prompt_en TEXT, + correct_answer TEXT, + hint_type VARCHAR(50), + hint_value TEXT, + is_test_question BOOLEAN DEFAULT FALSE, + test_order INT, + options_language TEXT DEFAULT 'pl' + ) + """) + + # ============ Авто-миграция: добавляем options_language ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'learning_questions' AND column_name = 'options_language' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE learning_questions + ADD COLUMN options_language TEXT DEFAULT 'pl' + """) + logger.info("Added options_language column to learning_questions") + + # ============ question_options ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS question_options ( + id SERIAL PRIMARY KEY, + question_id VARCHAR(150) NOT NULL REFERENCES learning_questions(question_id), + option_key VARCHAR(20) NOT NULL, + text_pl TEXT, + text_ru TEXT, + text_uk TEXT, + text_en TEXT, + is_correct BOOLEAN NOT NULL, + wrong_because VARCHAR(100), + UNIQUE(question_id, option_key) + ) + """) + + # ============ learning_sessions ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS learning_sessions ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + level_code VARCHAR(10) NOT NULL, + topic_id VARCHAR(100) NOT NULL, + session_type VARCHAR(30) NOT NULL, + started_at TIMESTAMP NOT NULL DEFAULT NOW(), + completed_at TIMESTAMP, + is_completed BOOLEAN DEFAULT FALSE + ) + """) + + # ============ user_learning_answers ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS user_learning_answers ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + session_id BIGINT NOT NULL REFERENCES learning_sessions(id), + level_code VARCHAR(10) NOT NULL, + topic_id VARCHAR(100) NOT NULL, + lesson_id VARCHAR(120), + question_id VARCHAR(150) NOT NULL, + selected_answer TEXT, + correct BOOLEAN, + skill_tag VARCHAR(100) NOT NULL, + question_type VARCHAR(50) NOT NULL, + context_type VARCHAR(50) NOT NULL, + difficulty INT NOT NULL, + time_taken_ms INT, + attempt_number INT DEFAULT 1, + hint_used BOOLEAN DEFAULT FALSE, + wrong_because VARCHAR(100), + is_final_answer BOOLEAN DEFAULT TRUE, + created_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ user_lesson_progress ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS user_lesson_progress ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + lesson_id VARCHAR(120) NOT NULL, + started_at TIMESTAMP, + completed_at TIMESTAMP, + attempts_count INT DEFAULT 0, + correct_count INT DEFAULT 0, + best_score NUMERIC(5,2), + average_time_ms INT, + completed BOOLEAN DEFAULT FALSE, + UNIQUE(user_id, lesson_id) + ) + """) + + # ============ user_topic_progress ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS user_topic_progress ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + topic_id VARCHAR(100) NOT NULL, + lessons_total INT DEFAULT 0, + lessons_completed INT DEFAULT 0, + test_started BOOLEAN DEFAULT FALSE, + test_completed BOOLEAN DEFAULT FALSE, + test_score NUMERIC(5,2), + topic_mastery NUMERIC(5,2), + confidence NUMERIC(5,2), + completed_at TIMESTAMP, + UNIQUE(user_id, topic_id) + ) + """) + + # ============ user_skill_mastery (Analytics 2.0 + Этап 2) ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS user_skill_mastery ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + skill_tag VARCHAR(100) NOT NULL, + attempts_count INT DEFAULT 0, + correct_count INT DEFAULT 0, + recognition_attempts INT DEFAULT 0, + recognition_correct INT DEFAULT 0, + recognition_score NUMERIC(5,2), + production_attempts INT DEFAULT 0, + production_correct INT DEFAULT 0, + production_score NUMERIC(5,2), + application_attempts INT DEFAULT 0, + application_correct INT DEFAULT 0, + application_score NUMERIC(5,2), + retention_score NUMERIC(5,2) DEFAULT 0, + hint_dependency NUMERIC(5,2) DEFAULT 0, + average_time_ms INT DEFAULT 0, + median_time_ms INT DEFAULT 0, + median_correct_time_ms INT DEFAULT 0, + median_wrong_time_ms INT DEFAULT 0, + recent_accuracy NUMERIC(5,2) DEFAULT 0, + last_3_accuracy NUMERIC(5,2), + last_5_accuracy NUMERIC(5,2), + last_10_accuracy NUMERIC(5,2), + long_term_accuracy NUMERIC(5,2) DEFAULT 0, + mastery_score NUMERIC(5,2) DEFAULT 0, + previous_mastery_score NUMERIC(5,2) DEFAULT 0, + mastery_delta NUMERIC(5,2) DEFAULT 0, + trend TEXT DEFAULT 'insufficient_data', + retention_status TEXT DEFAULT 'fresh', + fluency_score NUMERIC(5,2) DEFAULT 0, + passive_knowledge_score NUMERIC(5,2) DEFAULT 0, + active_knowledge_score NUMERIC(5,2) DEFAULT 0, + confidence NUMERIC(5,2) DEFAULT 0, + error_count INT DEFAULT 0, + repeated_error_count INT DEFAULT 0, + days_since_last_attempt INT DEFAULT 0, + last_attempt_at TIMESTAMP, + UNIQUE(user_id, skill_tag) + ) + """) + + # ============ Авто-миграции для user_skill_mastery (Этап 2) ============ + stage2_columns = { + "previous_mastery_score": "NUMERIC(5,2) DEFAULT 0", + "mastery_delta": "NUMERIC(5,2) DEFAULT 0", + "trend": "TEXT DEFAULT 'insufficient_data'", + "retention_status": "TEXT DEFAULT 'fresh'", + "fluency_score": "NUMERIC(5,2) DEFAULT 0", + "passive_knowledge_score": "NUMERIC(5,2) DEFAULT 0", + "active_knowledge_score": "NUMERIC(5,2) DEFAULT 0", + } + + for col_name, col_type in stage2_columns.items(): + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'user_skill_mastery' AND column_name = $1 + """, col_name) + if not col_exists: + await conn.execute(f""" + ALTER TABLE user_skill_mastery + ADD COLUMN {col_name} {col_type} + """) + logger.info(f"Added {col_name} column to user_skill_mastery") + + # ============ ai_user_context ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS ai_user_context ( + user_id BIGINT PRIMARY KEY, + current_level VARCHAR(10), + completed_topics INT DEFAULT 0, + level_topics_total INT DEFAULT 0, + level_completion_percent NUMERIC(5,2) DEFAULT 0, + completed_lessons INT DEFAULT 0, + overall_mastery NUMERIC(5,2) DEFAULT 0, + strong_skills JSONB DEFAULT '[]', + weak_skills JSONB DEFAULT '[]', + uncertain_skills JSONB DEFAULT '[]', + recurring_errors JSONB DEFAULT '[]', + recommended_topics JSONB DEFAULT '[]', + recommended_lessons JSONB DEFAULT '[]', + last_analysis_at TIMESTAMP, + analytics_enabled BOOLEAN DEFAULT FALSE + ) + """) + + # ============ Авто-миграция: добавляем level_topics_total ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'ai_user_context' AND column_name = 'level_topics_total' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE ai_user_context + ADD COLUMN level_topics_total INT DEFAULT 0 + """) + logger.info("Added level_topics_total column to ai_user_context") + + # ============ Авто-миграция: добавляем level_completion_percent ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'ai_user_context' AND column_name = 'level_completion_percent' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE ai_user_context + ADD COLUMN level_completion_percent NUMERIC(5,2) DEFAULT 0 + """) + logger.info("Added level_completion_percent column to ai_user_context") + + # ============ achievements ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS achievements ( + id SERIAL PRIMARY KEY, + code TEXT UNIQUE NOT NULL, + category TEXT DEFAULT 'general', + name_pl TEXT NOT NULL, + name_ru TEXT NOT NULL, + name_uk TEXT NOT NULL, + name_en TEXT NOT NULL, + description_pl TEXT DEFAULT '', + description_ru TEXT DEFAULT '', + description_uk TEXT DEFAULT '', + description_en TEXT DEFAULT '', + icon TEXT DEFAULT '🏆', + requirement_type TEXT NOT NULL, + requirement_value INTEGER DEFAULT 0 + ) + """) + + # ============ user_achievements ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS user_achievements ( + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + achievement_id INTEGER REFERENCES achievements(id) ON DELETE CASCADE, + unlocked_at TIMESTAMP DEFAULT NOW(), + PRIMARY KEY (user_id, achievement_id) + ) + """) + + # ============ daily_logins ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS daily_logins ( + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + login_date DATE DEFAULT CURRENT_DATE, + PRIMARY KEY (user_id, login_date) + ) + """) + + # ============ word_quiz_progress ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS word_quiz_progress ( + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + words_guessed INTEGER DEFAULT 0, + total_score INTEGER DEFAULT 0, + PRIMARY KEY (user_id) + ) + """) + + # ============ Авто-миграция: добавляем correct_streak ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'word_quiz_progress' AND column_name = 'correct_streak' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE word_quiz_progress + ADD COLUMN correct_streak INTEGER DEFAULT 0 + """) + logger.info("Added correct_streak column to word_quiz_progress") + + # ============ Авто-миграция: добавляем recent_words ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'word_quiz_progress' AND column_name = 'recent_words' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE word_quiz_progress + ADD COLUMN recent_words TEXT[] DEFAULT '{}' + """) + logger.info("Added recent_words column to word_quiz_progress") + + # ============ Авто-миграция: добавляем level в word_quiz_progress ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'word_quiz_progress' AND column_name = 'level' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE word_quiz_progress + ADD COLUMN level TEXT DEFAULT 'A1' + """) + logger.info("Added level column to word_quiz_progress") + + # ============ bubble_words_progress ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS bubble_words_progress ( + user_id BIGINT REFERENCES users(telegram_id) ON DELETE CASCADE, + levels_completed INTEGER DEFAULT 0, + total_score INTEGER DEFAULT 0, + PRIMARY KEY (user_id) + ) + """) + + # ============ Авто-миграция: добавляем level в bubble_words_progress ============ + col_exists = await conn.fetchval(""" + SELECT 1 FROM information_schema.columns + WHERE table_name = 'bubble_words_progress' AND column_name = 'level' + """) + if not col_exists: + await conn.execute(""" + ALTER TABLE bubble_words_progress + ADD COLUMN level TEXT DEFAULT 'A1' + """) + logger.info("Added level column to bubble_words_progress") + + # ============ wrong_because_explanations ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS wrong_because_explanations ( + id SERIAL PRIMARY KEY, + wrong_because VARCHAR(100) UNIQUE NOT NULL, + explanation_pl TEXT NOT NULL, + explanation_ru TEXT NOT NULL, + explanation_uk TEXT NOT NULL, + explanation_en TEXT NOT NULL + ) + """) + + # ============ teacher_reactions ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS teacher_reactions ( + id SERIAL PRIMARY KEY, + reaction_type VARCHAR(50) NOT NULL, + text_pl TEXT NOT NULL, + text_ru TEXT NOT NULL, + text_uk TEXT NOT NULL, + text_en TEXT NOT NULL + ) + """) + + # ============ Индекс для teacher_reactions ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_teacher_reactions_type ON teacher_reactions(reaction_type)") + + # ============ teacher_chat_history ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS teacher_chat_history ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL UNIQUE, + messages JSONB NOT NULL DEFAULT '[]', + updated_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ teacher_ai_usage ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS teacher_ai_usage ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + usage_date DATE DEFAULT CURRENT_DATE, + command_count INTEGER DEFAULT 0, + UNIQUE(user_id, usage_date) + ) + """) + + # ============ daily_phrases — фраза дня ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS daily_phrases ( + id SERIAL PRIMARY KEY, + phrase_date DATE UNIQUE NOT NULL, + phrase_pl TEXT NOT NULL, + translations JSONB NOT NULL DEFAULT '{}', + grammar_breakdowns JSONB NOT NULL DEFAULT '{}', + created_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ Индекс для daily_phrases ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_daily_phrases_date ON daily_phrases(phrase_date DESC)") + + # ============ СИСТЕМА ПОДДЕРЖКИ ============ + # ============ support_tickets ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS support_tickets ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + status TEXT DEFAULT 'open', + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ Индекс для support_tickets ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_support_tickets_user ON support_tickets(user_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_support_tickets_status ON support_tickets(status)") + + # ============ support_messages ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS support_messages ( + id BIGSERIAL PRIMARY KEY, + ticket_id BIGINT NOT NULL REFERENCES support_tickets(id) ON DELETE CASCADE, + sender_id BIGINT NOT NULL, + message TEXT NOT NULL, + is_read BOOLEAN DEFAULT FALSE, + created_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ Индекс для support_messages ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_support_messages_ticket ON support_messages(ticket_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_support_messages_sender ON support_messages(sender_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_support_messages_unread ON support_messages(ticket_id, is_read)") + + # ============ 🔧 НОВОЕ (18.09.2026): feed_posts — посты для карусели ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS feed_posts ( + id BIGSERIAL PRIMARY KEY, + section TEXT NOT NULL, + source_language TEXT NOT NULL DEFAULT 'ru', + + title_pl TEXT, + title_ru TEXT, + title_uk TEXT, + title_en TEXT, + + body_pl TEXT, + body_ru TEXT, + body_uk TEXT, + body_en TEXT, + + link_url TEXT, + telegram_url TEXT, + + author_id BIGINT NOT NULL, + is_pinned BOOLEAN DEFAULT FALSE, + is_published BOOLEAN DEFAULT TRUE, + created_at TIMESTAMP DEFAULT NOW(), + updated_at TIMESTAMP DEFAULT NOW(), + edited_at TIMESTAMP, + expires_at TIMESTAMP + ) + """) + + # ============ Индексы для feed_posts ============ + await conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_feed_posts_section + ON feed_posts(section, created_at DESC) + """) + + await conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_feed_posts_pinned + ON feed_posts(section, is_pinned DESC, created_at DESC) + """) + + await conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_feed_posts_published + ON feed_posts(section, is_published) + """) + + # ============ 🔧 НОВОЕ (18.09.2026): feed_attachments — картинки к постам (до 3) ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS feed_attachments ( + id BIGSERIAL PRIMARY KEY, + post_id BIGINT NOT NULL REFERENCES feed_posts(id) ON DELETE CASCADE, + file_path TEXT NOT NULL, + file_type TEXT DEFAULT 'image', + order_number INT NOT NULL DEFAULT 0, + created_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ Индекс для feed_attachments ============ + await conn.execute(""" + CREATE INDEX IF NOT EXISTS idx_feed_attachments_post + ON feed_attachments(post_id, order_number) + """) + + # ============ user_learning_answers_archive ============ + await conn.execute(""" + CREATE TABLE IF NOT EXISTS user_learning_answers_archive ( + id BIGSERIAL PRIMARY KEY, + user_id BIGINT NOT NULL, + skill_tag VARCHAR(100) NOT NULL, + correct BOOLEAN, + wrong_because VARCHAR(100), + created_at DATE, + archived_at TIMESTAMP DEFAULT NOW() + ) + """) + + # ============ Индексы для архива ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_archive_user_date ON user_learning_answers_archive(user_id, created_at)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_archive_skill_tag ON user_learning_answers_archive(skill_tag)") + + # ============ Индексы ============ + await conn.execute("CREATE INDEX IF NOT EXISTS idx_levels_number ON levels(level_number)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_levels_level ON levels(level)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_levels_level_number ON levels(level, level_number)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_user_progress_user ON user_progress(user_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_level_words_level_id ON level_words(level_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_level_words_level ON level_words(level)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_users_telegram ON users(telegram_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_sentences_number ON sentences(sentence_number)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_sentences_level ON sentences(level)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_sentences_level_number ON sentences(level, sentence_number)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_sentence_progress_user ON sentence_progress(user_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_typing_progress_user ON typing_progress(user_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_user_progress_score ON user_progress(score DESC)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_sentence_progress_score ON sentence_progress(score DESC)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_user_achievements_user ON user_achievements(user_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_daily_logins_user ON daily_logins(user_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_daily_logins_date ON daily_logins(login_date DESC)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_learning_topics_level ON learning_topics(level_code)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_learning_lessons_topic ON learning_lessons(topic_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_learning_questions_lesson ON learning_questions(lesson_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_learning_questions_topic ON learning_questions(topic_id)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_learning_answers_user ON user_learning_answers(user_id, created_at DESC)") + await conn.execute("CREATE INDEX IF NOT EXISTS idx_skill_mastery_user ON user_skill_mastery(user_id)") + + logger.info("Database initialized") \ No newline at end of file diff --git a/export_backend.sh b/export_backend.sh new file mode 100755 index 0000000..79b3ef1 --- /dev/null +++ b/export_backend.sh @@ -0,0 +1,55 @@ +#!/bin/bash +# Собирает весь backend в один .md файл + +PROJECT_DIR="/root/filwordspl/backend" +OUTPUT="/root/FILWORDS_BACKEND_$(date +%Y%m%d_%H%M).md" + +{ + echo "# 🐍 Filwords PL — Backend" + echo "" + echo "**Дата:** $(date)" + echo "**Путь:** $PROJECT_DIR" + echo "" + + # Все .py файлы (кроме venv и __pycache__) + for f in $(find "$PROJECT_DIR" -type f -name "*.py" -not -path "*/venv/*" -not -path "*/__pycache__/*" | sort); do + REL_PATH="${f#$PROJECT_DIR/}" + echo "### \`$REL_PATH\`" + echo '```python' + cat "$f" + echo '```' + echo "" + done + + # Конфиги + for f in "$PROJECT_DIR/requirements.txt" "$PROJECT_DIR/pytest.ini" "$PROJECT_DIR/.gitignore"; do + if [ -f "$f" ]; then + REL_PATH="${f#$PROJECT_DIR/}" + echo "### \`$REL_PATH\`" + echo '```' + cat "$f" + echo '```' + echo "" + fi + done + + # Тесты + if [ -d "$PROJECT_DIR/tests" ]; then + for f in $(find "$PROJECT_DIR/tests" -type f -name "*.py" | sort); do + REL_PATH="${f#$PROJECT_DIR/}" + echo "### \`$REL_PATH\`" + echo '```python' + cat "$f" + echo '```' + echo "" + done + fi + +} > "$OUTPUT" + +echo "🔍 Проверка секретов (должно быть 0):" +grep -c -E "(sk-[a-zA-Z0-9]{20,}|postgresql://[^ ]*:[^ ]*@|BOT_TOKEN\s*=\s*[\"'][0-9]|password\s*=\s*[\"'][^\"']{4,})" "$OUTPUT" || echo "0" + +echo "✅ Готово: $OUTPUT" +echo "📊 Размер: $(du -h "$OUTPUT" | cut -f1)" +echo "📏 Строк: $(wc -l < "$OUTPUT")" \ No newline at end of file diff --git a/fix_learning.py b/fix_learning.py new file mode 100644 index 0000000..dbfb8bf --- /dev/null +++ b/fix_learning.py @@ -0,0 +1,43 @@ +with open('routers/learning.py', 'r') as f: + content = f.read() + +# Добавляем regex для удаления технических ID +content = content.replace( + ''' data = response.json() + ai_response = data["choices"][0]["message"]["content"].strip() + ai_response = ai_response.replace("**", "").replace("*", "").replace("#", "") + + return {"analytics_enabled": True, "response": ai_response}''', + ''' data = response.json() + ai_response = data["choices"][0]["message"]["content"].strip() + ai_response = ai_response.replace("**", "").replace("*", "").replace("#", "") + + # Убираем технические ID в скобках: (self_intro), (family_masz_mam) и т.д. + import re + ai_response = re.sub(r'\\s*\\([a-z_]+_[a-z_]+\\)', '', ai_response) + + return {"analytics_enabled": True, "response": ai_response}''' +) + +# Убираем из промпта упоминание процента завершения уровня (правило 12) +content = content.replace( + '''12. ВАЖНО: level_completion_percent показывает сколько тем пройдено из ВСЕГО уровня (A1 = 30+ тем). Если пройдено 5 тем из 30+ — это только начало (около 16%), а не "почти готово". НЕ говори что уровень почти завершён, если пройдено меньше 100%. +''', + '''12. ВАЖНО: НИКОГДА не упоминай процент завершения уровня, количество пройденных тем или сколько тем осталось. Не говори "ты прошёл X тем" или "осталось Y тем". Просто анализируй навыки. +''' +) + +# Убираем из user_prompt пункт про прогресс +content = content.replace( + '''5. Твой общий прогресс и мотивация + +В конце напиши: "Жду тебя в разделе Повторение!\\""""''', + '''5. Твоя мотивация (без упоминания процентов и количества тем) + +В конце напиши: "Жду тебя в разделе Повторение!\\""""''' +) + +with open('routers/learning.py', 'w') as f: + f.write(content) + +print("learning.py fixed!") diff --git a/fix_polish_options.py b/fix_polish_options.py new file mode 100644 index 0000000..a2e5494 --- /dev/null +++ b/fix_polish_options.py @@ -0,0 +1,135 @@ +""" +Патч: исправляет колонку text_pl в question_options там, где при заполнении +контента по ошибке продублировали русский перевод вместо настоящей польской +фразы (вопросы типа "Co oznacza / Co znaczy ...?"). + +Затронуто 12 question_id по темам: greetings, family, food, home, +numbers_time (3 шт.), colors_clothes, weather_seasons. + +Запуск на сервере: + python3 fix_polish_options.py +Требует переменную DB_CONFIG из config.py (как остальные твои скрипты). + +Скрипт идемпотентен: можно запускать повторно, ничего не сломает — +он просто перезапишет text_pl тем же корректным значением. +""" +import asyncio +import asyncpg +from config import DB_CONFIG + + +# Каждая запись: (question_id, option_key, правильный польский текст) +FIXES = [ + # ==================== Тема 1: Greetings ==================== + ("a1_greetings_t09", "A", "Jak się nazywasz?"), + ("a1_greetings_t09", "B", "Jak się masz?"), + ("a1_greetings_t09", "C", "Gdzie mieszkasz?"), + ("a1_greetings_t09", "D", "Do widzenia."), + + # ==================== Тема 3: Family ==================== + # Один и тот же набор опций встречается в уроке и в тесте + ("a1_family_l07_q1", "A", "Masz siostrę?"), + ("a1_family_l07_q1", "B", "Czy to jest twoja siostra?"), + ("a1_family_l07_q1", "C", "Jesteś siostrą?"), + ("a1_family_l07_q1", "D", "Gdzie jest twoja siostra?"), + + ("a1_family_t06", "A", "Masz siostrę?"), + ("a1_family_t06", "B", "Czy to jest twoja siostra?"), + ("a1_family_t06", "C", "Jesteś siostrą?"), + ("a1_family_t06", "D", "Gdzie jest twoja siostra?"), + + # ==================== Тема 4: Food ==================== + ("a1_food_l08_q1", "A", "Co jesz na śniadanie?"), + ("a1_food_l08_q1", "B", "Co pijesz rano?"), + ("a1_food_l08_q1", "C", "Kiedy jesz śniadanie?"), + ("a1_food_l08_q1", "D", "Czy lubisz śniadanie?"), + + # ==================== Тема 5: Home ==================== + ("a1_home_l09_q1", "A", "Ile masz pokoi?"), + ("a1_home_l09_q1", "B", "Gdzie jest twój pokój?"), + ("a1_home_l09_q1", "C", "Czy podoba ci się twój pokój?"), + ("a1_home_l09_q1", "D", "Jaki jest twój pokój?"), + + # ==================== Тема 6: Numbers/Time ==================== + ("a1_numbers_time_l05_q1", "A", "Która godzina?"), + ("a1_numbers_time_l05_q1", "B", "Jaki dziś dzień?"), + ("a1_numbers_time_l05_q1", "C", "Ile masz lat?"), + ("a1_numbers_time_l05_q1", "D", "Gdzie jesteś?"), + + ("a1_numbers_time_t04", "A", "Która godzina?"), + ("a1_numbers_time_t04", "B", "Jaki dziś dzień?"), + ("a1_numbers_time_t04", "C", "Ile masz lat?"), + ("a1_numbers_time_t04", "D", "Gdzie jesteś?"), + + ("a1_numbers_time_l06_q1", "A", "za piętnaście piąta"), + ("a1_numbers_time_l06_q1", "B", "kwadrans po czwartej"), + ("a1_numbers_time_l06_q1", "C", "wpół do piątej"), + ("a1_numbers_time_l06_q1", "D", "dokładnie piąta"), + + ("a1_numbers_time_l07_q1", "A", "O której godzinie?"), + ("a1_numbers_time_l07_q1", "B", "Która godzina?"), + ("a1_numbers_time_l07_q1", "C", "Jaki dziś dzień?"), + ("a1_numbers_time_l07_q1", "D", "Jak długo?"), + + ("a1_numbers_time_t05", "A", "O której godzinie?"), + ("a1_numbers_time_t05", "B", "Która godzina?"), + ("a1_numbers_time_t05", "C", "Jaki dziś dzień?"), + ("a1_numbers_time_t05", "D", "Jak długo?"), + + # ==================== Тема 7: Colors/Clothes ==================== + ("a1_colors_clothes_l09_q1", "A", "Jakiego koloru jest...?"), + ("a1_colors_clothes_l09_q1", "B", "Która godzina jest...?"), + ("a1_colors_clothes_l09_q1", "C", "Ile kosztuje...?"), + ("a1_colors_clothes_l09_q1", "D", "Gdzie jest...?"), + + ("a1_colors_clothes_t06", "A", "Jakiego koloru jest...?"), + ("a1_colors_clothes_t06", "B", "Która godzina jest...?"), + ("a1_colors_clothes_t06", "C", "Ile kosztuje...?"), + ("a1_colors_clothes_t06", "D", "Gdzie jest...?"), + + # ==================== Тема 8: Weather/Seasons ==================== + ("a1_weather_seasons_l09_q1", "A", "Jutro będzie padać deszcz."), + ("a1_weather_seasons_l09_q1", "B", "Wczoraj padał deszcz."), + ("a1_weather_seasons_l09_q1", "C", "Dziś pada deszcz."), + ("a1_weather_seasons_l09_q1", "D", "Jutro będzie zimno."), + + ("a1_weather_seasons_t06", "A", "Jutro będzie padać deszcz."), + ("a1_weather_seasons_t06", "B", "Wczoraj padał deszcz."), + ("a1_weather_seasons_t06", "C", "Dziś pada deszcz."), + ("a1_weather_seasons_t06", "D", "Jutro będzie zimno."), +] + + +async def main(): + pool = await asyncpg.create_pool(**DB_CONFIG) + updated = 0 + not_found = [] + + async with pool.acquire() as conn: + for question_id, option_key, correct_pl in FIXES: + result = await conn.execute(""" + UPDATE question_options + SET text_pl = $3 + WHERE question_id = $1 AND option_key = $2 + """, question_id, option_key, correct_pl) + + # asyncpg возвращает строку вида "UPDATE 1" или "UPDATE 0" + affected = int(result.split()[-1]) + if affected == 0: + not_found.append((question_id, option_key)) + else: + updated += affected + + await pool.close() + + print(f"✅ Обновлено записей: {updated} из {len(FIXES)}") + if not_found: + print(f"⚠️ Не найдено в БД (проверь question_id/option_key вручную):") + for qid, key in not_found: + print(f" - {qid} / {key}") + else: + print("🎉 Все записи найдены и обновлены.") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/fix_review.py b/fix_review.py new file mode 100644 index 0000000..ba6e1db --- /dev/null +++ b/fix_review.py @@ -0,0 +1,113 @@ +import re + +with open('routers/review.py', 'r') as f: + content = f.read() + +# Полный SKILL_TAG_DESCRIPTION (как в learning.py) +full_skill_tags = '''# Понятные названия навыков +SKILL_TAG_DESCRIPTION = """ +Понятные названия навыков (используй ИХ в ответе, а не технические ID): +- family_vocabulary → "слова по теме «Семья»" +- family_possessive → "мой/моя (mój/moja)" +- family_accusative → "винительный падеж (mam brata, mam siostrę)" +- family_questions → "вопросы о семье (Masz brata?)" +- family_description → "рассказ о семье" +- family_babcia_dziadek → "бабушка и дедушка" +- family_brat_siostra → "брат и сестра" +- family_masz_mam → "у меня есть / у тебя есть" +- family_duza_mala → "большая/маленькая семья" +- family_mama_tata → "мама и папа" +- family_maz_zona → "муж и жена" +- family_dzieci → "дети" +- family_wujek_ciocia → "дядя и тётя" +- family_kto_to_jest → "вопрос «Кто это?»" +- asking_name → "вопрос «Как тебя зовут?»" +- answering_name → "ответ на вопрос об имени" +- formal_address_pan_pani → "вежливое обращение Pan/Pani" +- greeting_formal → "формальные приветствия" +- greeting_informal → "неформальные приветствия" +- asking_origin → "вопрос «Откуда ты?»" +- answering_origin → "ответ о происхождении" +- asking_residence → "вопрос «Где ты живёшь?»" +- answering_residence → "ответ о месте жительства" +- self_description → "рассказ о себе" +- self_intro → "представление себя" +- how_are_you → "вопрос «Как дела?»" +- responding_how_are_you → "ответ на «Как дела?»" +- farewell_formal → "формальные прощания" +- farewell_informal → "неформальные прощания" +- mieszkac_conjugation → "спряжение глагола mieszkać" +- skad_vs_gdzie → "разница между Skąd и Gdzie" +- country_vocabulary → "названия стран" +- nationality_forms → "национальности" +- city_vocabulary → "названия городов" +- food_vocabulary → "слова по теме «Еда»" +- food_fruits_vegetables → "фрукты и овощи" +- food_drinks → "напитки" +- food_meals → "приёмы пищи" +- food_lubie → "глагол lubić (любить)" +- home_vocabulary → "слова по теме «Дом»" +- home_furniture → "мебель" +- home_location → "предлоги места (w, na)" +- home_ownership → "mam dom, mam mieszkanie" +- home_description → "описание дома/квартиры" + +НИКОГДА не пиши технические ID навыков в ответе. Всегда заменяй их на понятные названия из списка выше. +"""''' + +# Заменяем короткий SKILL_TAG_DESCRIPTION на полный +content = re.sub( + r'# Понятные названия навыков\nSKILL_TAG_DESCRIPTION = """.*?"""', + full_skill_tags, + content, + flags=re.DOTALL +) + +# Добавляем attempts_count >= 2 в SQL +content = content.replace( + ''' WHERE user_id = $1 + AND ( + mastery_score < 75 + OR retention_status IN ('needs_review', 'overdue') + OR repeated_error_count > 0 + )''', + ''' WHERE user_id = $1 + AND attempts_count >= 2 + AND ( + mastery_score < 75 + OR retention_status IN ('needs_review', 'overdue') + OR repeated_error_count > 0 + )''' +) + +# Добавляем regex для удаления технических ID +content = content.replace( + ''' data = response.json() + review_text = data["choices"][0]["message"]["content"].strip() + review_text = review_text.replace("**", "").replace("*", "").replace("#", "")''', + ''' data = response.json() + review_text = data["choices"][0]["message"]["content"].strip() + review_text = review_text.replace("**", "").replace("*", "").replace("#", "") + + # Убираем технические ID в скобках + import re + review_text = re.sub(r'\\s*\\([a-z_]+_[a-z_]+\\), '', review_text)''' +) + +# Добавляем правила в промпт +content = content.replace( + '''5. Каждый мини-урок: правило + 2 примера + 1 задание +6. Не пиши технические ID навыков — используй понятные названия +7. Будь дружелюбным и мотивирующим"""''', + '''5. Каждый мини-урок: правило + 2 примера + 1 задание +6. Не пиши технические ID навыков — используй понятные названия +7. Будь дружелюбным и мотивирующим +8. ВАЖНО: Никогда не давай готовый ответ на задание в том же сообщении. Задание должно оставаться открытым. +9. ВАЖНО: В списках слов-подсказок используй только польские слова, без смешения языков. +10. ВАЖНО: Если mastery >= 75 и навык включён из-за retention_status (needs_review/overdue) — формулируй как "быстрое освежение", а не "давай разберём с нуля"."""''' +) + +with open('routers/review.py', 'w') as f: + f.write(content) + +print("review.py fixed!") diff --git a/full_reset.py b/full_reset.py new file mode 100644 index 0000000..5f6822a --- /dev/null +++ b/full_reset.py @@ -0,0 +1,85 @@ +""" +Полный сброс прогресса пользователя. +Очищает ВСЕ данные по играм, урокам, чат-учителю, достижениям. +Не трогает: users (остаётся), tts_cache (аудио). + +Запуск: python3 full_reset.py +""" +import asyncio +import asyncpg +from config import DB_CONFIG + +USER_ID = 6694989403 + + +async def main(): + pool = await asyncpg.create_pool(**DB_CONFIG) + + async with pool.acquire() as conn: + # Проверяем пользователя + user_exists = await conn.fetchval(""" + SELECT 1 FROM users WHERE telegram_id = $1 + """, USER_ID) + + if not user_exists: + print(f"❌ Пользователь {USER_ID} не найден!") + await pool.close() + return + + # Список таблиц для очистки (по user_id) + user_tables = [ + "user_progress", # Филворды + "sentence_progress", # Предложения + "typing_progress", # Печать + "word_quiz_progress", # Выбери слово + "bubble_words_progress", # Пузыри слов + "user_learning_answers", # Ответы на уроки + "user_lesson_progress", # Прогресс уроков + "user_topic_progress", # Прогресс тем + "user_skill_mastery", # Мастерство + "learning_sessions", # Сессии обучения + "teacher_chat_history", # История чата учителя + "teacher_ai_usage", # AI-команды + "chat_history", # AI-чат + "chat_usage", # Использование AI + "user_achievements", # Достижения + "daily_logins", # Входы + "ai_user_context", # AI-контекст + ] + + total_deleted = 0 + + for table in user_tables: + try: + result = await conn.execute(f""" + DELETE FROM {table} WHERE user_id = $1 + """, USER_ID) + affected = int(result.split()[-1]) + total_deleted += affected + print(f"🗑️ {table}: удалено {affected}") + except Exception as e: + print(f"⚠️ {table}: {str(e)}") + + # Сбрасываем last_completed_level + await conn.execute(""" + UPDATE users SET last_completed_level = 0, current_level = 'A1' + WHERE telegram_id = $1 + """, USER_ID) + print("✅ last_completed_level = 0, current_level = A1") + + # Очищаем архив ответов + try: + result = await conn.execute(""" + DELETE FROM user_learning_answers_archive WHERE user_id = $1 + """, USER_ID) + print(f"🗑️ user_learning_answers_archive: удалено {result.split()[-1]}") + except Exception as e: + print(f"⚠️ archive: {str(e)}") + + await pool.close() + print(f"\n🎉 Готово! Удалено {total_deleted} записей.") + print("Можно начинать тестирование с чистого листа!") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/generate_daily_phrase.py b/generate_daily_phrase.py new file mode 100644 index 0000000..7e9072f --- /dev/null +++ b/generate_daily_phrase.py @@ -0,0 +1,200 @@ +""" +Автоматическая генерация фразы дня. +Запускается через cron в 03:00 UTC (= 06:00 Минск). + +Что делает: +1. Проверяет, есть ли фраза на сегодня в daily_phrases +2. Если нет — генерирует через AI (MiniMax-M3) +3. Пишет в daily_phrases с phrase_date = CURRENT_DATE + +Fallback: если AI упал — пишет запасную фразу. +""" +import asyncio +import asyncpg +import httpx +import json +import logging +import random +from datetime import datetime, timezone +from config import DB_CONFIG, TOGETHER_API_KEY + +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(levelname)s - %(message)s' +) +logger = logging.getLogger(__name__) + +TOGETHER_API_URL = "https://api.together.xyz/v1/chat/completions" +TEACHER_MODEL = "MiniMaxAI/MiniMax-M3" + +# Список тем для фразы дня +TOPICS_LIST = [ + "приветствие и знакомство", + "семья и друзья", + "еда и напитки", + "покупки и магазины", + "транспорт и путешествия", + "работа и профессии", + "погода и времена года", + "дом и квартира", + "хобби и свободное время", + "здоровье и самочувствие", + "город и местность", + "ежедневная рутина", +] + +# Fallback фраза, если AI упал +FALLBACK_PHRASE = "Lepiej późno niż wcale." +FALLBACK_TRANSLATIONS = { + "ru": "Лучше поздно, чем никогда.", + "uk": "Краще пізно, ніж ніколи.", + "en": "Better late than never." +} +FALLBACK_GRAMMAR = { + "pl": "Lepiej - przysłówek w stopniu wyższym. Późno - przysłówek.", + "ru": "Lepiej - наречие в сравнительной степени. Późno - наречие.", + "uk": "Lepiej - прислівник у вищому ступені. Późno - прислівник.", + "en": "Lepiej - adverb in comparative degree. Późno - adverb." +} + + +async def call_ai(system_prompt: str, user_prompt: str, max_tokens: int = 1000) -> str: + """Вызывает AI и возвращает ответ.""" + if not TOGETHER_API_KEY: + logger.error("TOGETHER_API_KEY not configured") + return "" + + try: + async with httpx.AsyncClient(timeout=90.0) as client: + response = await client.post( + TOGETHER_API_URL, + headers={ + "Authorization": f"Bearer {TOGETHER_API_KEY}", + "Content-Type": "application/json", + }, + json={ + "model": TEACHER_MODEL, + "messages": [ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_prompt}, + ], + "max_tokens": max_tokens, + "temperature": 0.7, + }, + ) + + if response.status_code != 200: + logger.error(f"AI API error: {response.status_code}, body={response.text[:200]}") + return "" + + data = response.json() + return data["choices"][0]["message"]["content"].strip() + + except Exception as e: + logger.error(f"AI call error: {e}") + return "" + + +async def generate_phrase() -> tuple: + """ + Генерирует фразу дня через AI. + Возвращает (phrase_pl, translations_dict, grammar_dict). + """ + selected_topic = random.choice(TOPICS_LIST) + + system_prompt = f"""Ты — учитель польского языка. Создай фразу дня для изучения польского. +Тема фразы: {selected_topic}. +Фраза должна быть уровня A2-B1, полезной в повседневной жизни. + +Верни ответ строго в таком формате (без markdown, просто текст): + +PHRASE: [фраза на польском] +RU: [перевод на русский] +UK: [перевод на украинский] +EN: [перевод на английский] +PL_GRAMMAR: [грамматический разбор на польском, 1-2 предложения] +RU_GRAMMAR: [грамматический разбор на русском, 1-2 предложения] +UK_GRAMMAR: [грамматический разбор на украинском, 1-2 предложения] +EN_GRAMMAR: [грамматический разбор на английском, 1-2 предложения]""" + + user_prompt = f"Создай фразу дня на тему: {selected_topic}." + + ai_response = await call_ai(system_prompt, user_prompt, max_tokens=1000) + + if not ai_response: + logger.warning("AI returned empty response, using fallback") + return FALLBACK_PHRASE, FALLBACK_TRANSLATIONS, FALLBACK_GRAMMAR + + # Парсим ответ + phrase_pl = FALLBACK_PHRASE + translations = FALLBACK_TRANSLATIONS.copy() + grammar_breakdowns = FALLBACK_GRAMMAR.copy() + + for line in ai_response.strip().split('\n'): + line = line.strip() + if line.startswith('PHRASE:'): + phrase_pl = line.replace('PHRASE:', '').strip() + elif line.startswith('RU:'): + translations["ru"] = line.replace('RU:', '').strip() + elif line.startswith('UK:'): + translations["uk"] = line.replace('UK:', '').strip() + elif line.startswith('EN:'): + translations["en"] = line.replace('EN:', '').strip() + elif line.startswith('PL_GRAMMAR:'): + grammar_breakdowns["pl"] = line.replace('PL_GRAMMAR:', '').strip() + elif line.startswith('RU_GRAMMAR:'): + grammar_breakdowns["ru"] = line.replace('RU_GRAMMAR:', '').strip() + elif line.startswith('UK_GRAMMAR:'): + grammar_breakdowns["uk"] = line.replace('UK_GRAMMAR:', '').strip() + elif line.startswith('EN_GRAMMAR:'): + grammar_breakdowns["en"] = line.replace('EN_GRAMMAR:', '').strip() + + logger.info(f"Generated phrase for topic '{selected_topic}': {phrase_pl[:60]}...") + return phrase_pl, translations, grammar_breakdowns + + +async def main(): + logger.info("=== Начало генерации фразы дня ===") + + conn = await asyncpg.connect(**DB_CONFIG) + + try: + today = datetime.now(timezone.utc).date() + + # Проверяем, есть ли уже фраза на сегодня + existing = await conn.fetchrow(""" + SELECT id FROM daily_phrases WHERE phrase_date = $1 + """, today) + + if existing: + logger.info(f"Phrase for {today} already exists, skipping") + return + + # Генерируем новую фразу + logger.info(f"Generating phrase for {today}...") + phrase_pl, translations, grammar_breakdowns = await generate_phrase() + + # Пишем в БД + await conn.execute(""" + INSERT INTO daily_phrases (phrase_date, phrase_pl, translations, grammar_breakdowns) + VALUES ($1, $2, $3::jsonb, $4::jsonb) + ON CONFLICT (phrase_date) DO UPDATE SET + phrase_pl = EXCLUDED.phrase_pl, + translations = EXCLUDED.translations, + grammar_breakdowns = EXCLUDED.grammar_breakdowns + """, today, phrase_pl, + json.dumps(translations, ensure_ascii=False), + json.dumps(grammar_breakdowns, ensure_ascii=False)) + + logger.info(f"✅ Phrase for {today} saved: {phrase_pl}") + + except Exception as e: + logger.error(f"Error: {e}") + finally: + await conn.close() + + logger.info("=== Готово ===") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/generate_levels_v2.py b/generate_levels_v2.py new file mode 100644 index 0000000..b02b96c --- /dev/null +++ b/generate_levels_v2.py @@ -0,0 +1,273 @@ +import asyncio +import asyncpg +import json +import random +import csv +from config import DB_CONFIG + +DIRECTIONS = [(-1,0),(0,-1),(0,1),(1,0)] +ALPHABET = "AĄBCĆDEĘFGHIJKLŁMNŃOÓPRSŚTUWYZŹŻ" + +def load_words_from_csv(filename): + """Загружает слова из CSV файла без тем. Возвращает список слов и словарь переводов.""" + words = [] + translations = {} + with open(filename, 'r', encoding='utf-8') as f: + reader = csv.DictReader(f) + for row in reader: + word = row['polish'].strip().lower() + if word and word not in words: + words.append(word) + translations[word] = { + 'en': row.get('english', ''), + 'ru': row.get('russian', ''), + 'uk': row.get('ukrainian', '') + } + return words, translations + +def get_words_for_grid(all_words, num_words, grid_size): + """Выбирает случайные слова подходящей длины.""" + max_len = grid_size + candidates = [w for w in all_words if len(w) <= max_len] + if len(candidates) < num_words: + candidates = all_words + random.shuffle(candidates) + return candidates[:num_words] + +def try_place_word(word, grid_size, occupied, max_attempts=500): + word = word.upper() + for _ in range(max_attempts): + start = (random.randrange(grid_size), random.randrange(grid_size)) + if start in occupied: + continue + path = [start] + visited = {start} + ok = True + for _ in range(len(word) - 1): + r, c = path[-1] + candidates = [] + for dr, dc in DIRECTIONS: + nr, nc = r + dr, c + dc + if 0 <= nr < grid_size and 0 <= nc < grid_size: + if (nr, nc) not in occupied and (nr, nc) not in visited: + candidates.append((nr, nc)) + if not candidates: + ok = False + break + nxt = random.choice(candidates) + path.append(nxt) + visited.add(nxt) + if ok and len(path) == len(word): + return path + return None + +def fill_empty_cells(grid, grid_size, occupied, all_words, used_words): + """Заполняет пустые клетки короткими словами из того же уровня.""" + empty_cells = set() + for r in range(grid_size): + for c in range(grid_size): + if (r, c) not in occupied: + empty_cells.add((r, c)) + + if not empty_cells: + return [], {} + + filler_words = [w for w in all_words if 2 <= len(w) <= 4 and w not in used_words] + filler_words = sorted(list(set(filler_words)), key=len, reverse=True) + random.shuffle(filler_words) + + filled_paths = {} + filled_words = [] + remaining_empty = empty_cells.copy() + + for word in filler_words: + if len(word) > len(remaining_empty): + continue + + for _ in range(500): + if not remaining_empty: + break + start = random.choice(list(remaining_empty)) + + path = [start] + visited = {start} + ok = True + + for _ in range(len(word) - 1): + r, c = path[-1] + candidates = [] + for dr, dc in DIRECTIONS: + nr, nc = r + dr, c + dc + if 0 <= nr < grid_size and 0 <= nc < grid_size: + if (nr, nc) in remaining_empty and (nr, nc) not in visited: + candidates.append((nr, nc)) + if not candidates: + ok = False + break + nxt = random.choice(candidates) + path.append(nxt) + visited.add(nxt) + + if ok and len(path) == len(word): + for (r, c), letter in zip(path, word.upper()): + grid[r][c] = letter + if (r, c) in remaining_empty: + remaining_empty.remove((r, c)) + + filled_paths[word] = [list(p) for p in path] + filled_words.append(word) + break + + for r, c in remaining_empty: + grid[r][c] = random.choice(ALPHABET) + + return filled_words, filled_paths + +def generate_grid(words, grid_size, all_words, used_words, max_restarts=200): + words_sorted = sorted(words, key=len, reverse=True) + for _ in range(max_restarts): + grid = [['' for _ in range(grid_size)] for _ in range(grid_size)] + occupied = set() + word_paths = {} + success = True + + for word in words_sorted: + path = try_place_word(word, grid_size, occupied) + if path is None: + success = False + break + for (r, c), letter in zip(path, word.upper()): + grid[r][c] = letter + occupied.update(path) + word_paths[word] = [list(p) for p in path] + + if not success: + continue + + all_used = set(words_sorted) | used_words + filled_words, filled_paths = fill_empty_cells( + grid, grid_size, occupied, all_words, all_used + ) + + word_paths.update(filled_paths) + all_placed_words = words_sorted + filled_words + + return grid, word_paths, all_placed_words + + return None, None, None + +async def save_level(conn, level_num, grid_size, level_name, grid, word_paths, words, translations): + level = await conn.fetchrow( + """INSERT INTO levels (level_number, grid_size, level, grid_letters, word_paths) + VALUES ($1, $2, $3, $4, $5) RETURNING id""", + level_num, grid_size, level_name, json.dumps(grid), json.dumps(word_paths) + ) + level_id = level['id'] + for word in words: + trans = translations.get(word, {}) + await conn.execute( + """INSERT INTO level_words (level_id, word_pl, translation_ru, translation_uk, translation_en, level) + VALUES ($1, $2, $3, $4, $5, $6)""", + level_id, word, + trans.get('ru', ''), + trans.get('uk', ''), + trans.get('en', ''), + level_name + ) + +async def main(): + # Конфигурация уровней: 550 уровней на каждый уровень польского + level_configs = [ + { + "name": "A1", + "file": "words_a1.csv", + "levels": [ + (50, 4, 3), # 50 уровней: 4x4, 3 слова + (100, 5, 4), # 100 уровней: 5x5, 4 слова + (200, 6, 5), # 200 уровней: 6x6, 5 слов + (200, 6, 6), # 200 уровней: 6x6, 6 слов + ], + }, + { + "name": "A2", + "file": "words_a2.csv", + "levels": [ + (100, 6, 5), # 100 уровней: 6x6, 5 слов + (150, 7, 6), # 150 уровней: 7x7, 6 слов + (150, 8, 7), # 150 уровней: 8x8, 7 слов + (150, 8, 8), # 150 уровней: 8x8, 8 слов + ], + }, + { + "name": "B1", + "file": "words_b1.csv", + "levels": [ + (100, 8, 7), # 100 уровней: 8x8, 7 слов + (150, 9, 8), # 150 уровней: 9x9, 8 слов + (150, 10, 9), # 150 уровней: 10x10, 9 слов + (150, 10, 10), # 150 уровней: 10x10, 10 слов + ], + }, + ] + + conn = await asyncpg.connect(**DB_CONFIG) + + # Очищаем старые данные + await conn.execute("DELETE FROM level_words") + await conn.execute("DELETE FROM user_progress") + await conn.execute("DELETE FROM sentence_progress") + await conn.execute("DELETE FROM word_quiz_progress") + await conn.execute("DELETE FROM bubble_words_progress") + await conn.execute("DELETE FROM levels") + await conn.execute("ALTER SEQUENCE levels_id_seq RESTART WITH 1") + await conn.execute("UPDATE users SET last_completed_level = 0, current_level = 'A1'") + + total_generated = 0 + + for level_config in level_configs: + level_name = level_config["name"] + filename = level_config["file"] + + print(f"\n{'='*50}") + print(f"Генерирую уровни для {level_name} из {filename}") + print(f"{'='*50}") + + all_words, translations = load_words_from_csv(filename) + print(f"Загружено слов: {len(all_words)}") + + if len(all_words) < 10: + print(f"❌ Слишком мало слов в {filename}") + continue + + used_words = set() + level_num = 0 + + for count, grid_size, num_words in level_config["levels"]: + for i in range(count): + level_num += 1 + + for attempt in range(20): + words = get_words_for_grid(all_words, num_words, grid_size) + if len(words) < num_words: + continue + + grid, word_paths, all_placed_words = generate_grid( + words, grid_size, all_words, used_words + ) + if grid is not None: + await save_level( + conn, level_num, grid_size, level_name, + grid, word_paths, all_placed_words, translations + ) + used_words.update(all_placed_words) + total_generated += 1 + print(f"✅ {level_name} Level {level_num}: {grid_size}x{grid_size}, {len(all_placed_words)} words") + break + else: + print(f"❌ {level_name} Level {level_num}: FAILED after 20 attempts") + + await conn.close() + print(f"\n🎉 Готово! Сгенерировано уровней: {total_generated}") + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/init_options_language.py b/init_options_language.py new file mode 100644 index 0000000..bff9ae2 --- /dev/null +++ b/init_options_language.py @@ -0,0 +1,75 @@ +""" +Заполняет поле options_language в learning_questions. +Определяет, на каком языке показывать варианты ответов: +- 'user' — для вопросов "Что означает...?" (варианты на языке пользователя) +- 'pl' — для остальных (варианты на польском) + +Запуск: python3 init_options_language.py +""" +import asyncio +import asyncpg +from config import DB_CONFIG + + +# Ключевые фразы, которые означают "вопрос на понимание смысла" +USER_LANG_PATTERNS = [ + 'co oznacza', + 'co znaczy', + 'что означает', + 'що означає', + 'what does', + 'what means', + 'переведи', + 'переклади', + 'przetłumacz', + 'translate', +] + + +async def main(): + pool = await asyncpg.create_pool(**DB_CONFIG) + + async with pool.acquire() as conn: + # Получаем все вопросы + questions = await conn.fetch(""" + SELECT question_id, prompt_pl, prompt_ru, prompt_uk, prompt_en + FROM learning_questions + """) + + user_lang_count = 0 + pl_lang_count = 0 + + for q in questions: + # Собираем все промпты в один текст для проверки + all_prompts = ' '.join([ + q['prompt_pl'] or '', + q['prompt_ru'] or '', + q['prompt_uk'] or '', + q['prompt_en'] or '', + ]).lower() + + # Определяем язык вариантов + is_user_lang = any(pattern in all_prompts for pattern in USER_LANG_PATTERNS) + options_language = 'user' if is_user_lang else 'pl' + + await conn.execute(""" + UPDATE learning_questions + SET options_language = $2 + WHERE question_id = $1 + """, q['question_id'], options_language) + + if is_user_lang: + user_lang_count += 1 + else: + pl_lang_count += 1 + + print(f"✅ options_language = 'user': {user_lang_count} вопросов") + print(f"✅ options_language = 'pl': {pl_lang_count} вопросов") + print(f" Всего: {user_lang_count + pl_lang_count}") + + await pool.close() + print("\n🎉 Готово!") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/init_teacher_data.py b/init_teacher_data.py new file mode 100644 index 0000000..9bbb133 --- /dev/null +++ b/init_teacher_data.py @@ -0,0 +1,195 @@ +""" +Инициализация данных для чат-учителя: +1. wrong_because_explanations — объяснения ошибок +2. teacher_reactions — банк реакций (Марек) + +Запуск: python3 init_teacher_data.py +""" +import asyncio +import asyncpg +from config import DB_CONFIG + + +# ============ Объяснения ошибок ============ +WRONG_BECAUSE_EXPLANATIONS = [ + { + "wrong_because": "wrong_word", + "pl": "To nie jest właściwe słowo w tym kontekście.", + "ru": "Это не подходящее слово в данном контексте.", + "uk": "Це не відповідне слово в даному контексті.", + "en": "This is not the right word in this context." + }, + { + "wrong_because": "wrong_gender", + "pl": "Uwaga na rodzaj gramatyczny! W języku polskim rzeczowniki mają rodzaje: męski, żeński i nijaki.", + "ru": "Обрати внимание на грамматический род! В польском языке существительные бывают мужского, женского и среднего рода.", + "uk": "Зверни увагу на граматичний рід! У польській мові іменники бувають чоловічого, жіночого та середнього роду.", + "en": "Pay attention to grammatical gender! Polish nouns have masculine, feminine and neuter genders." + }, + { + "wrong_because": "wrong_case", + "pl": "Sprawdź przypadek gramatyczny. W języku polskim jest 7 przypadków!", + "ru": "Проверь грамматический падеж. В польском языке 7 падежей!", + "uk": "Перевір граматичний відмінок. У польській мові 7 відмінків!", + "en": "Check the grammatical case. Polish has 7 cases!" + }, + { + "wrong_because": "wrong_number", + "pl": "Uwaga na liczbę! Pojedyncza czy mnoga?", + "ru": "Обрати внимание на число! Единственное или множественное?", + "uk": "Зверни увагу на число! Однина чи множина?", + "en": "Pay attention to number! Singular or plural?" + }, + { + "wrong_because": "wrong_sentence_type", + "pl": "To nie jest właściwy typ zdania (oznajmujące, pytające, rozkazujące).", + "ru": "Это не правильный тип предложения (повествовательное, вопросительное, повелительное).", + "uk": "Це не правильний тип речення (розповідне, питальне, наказове).", + "en": "This is not the right sentence type (declarative, interrogative, imperative)." + }, + { + "wrong_because": "wrong_translation", + "pl": "Tłumaczenie nie jest dokładne. Spróbuj jeszcze raz.", + "ru": "Перевод не точный. Попробуй ещё раз.", + "uk": "Переклад не точний. Спробуй ще раз.", + "en": "The translation is not accurate. Try again." + }, + { + "wrong_because": "wrong_context", + "pl": "To słowo nie pasuje do kontekstu zdania.", + "ru": "Это слово не подходит к контексту предложения.", + "uk": "Це слово не підходить до контексту речення.", + "en": "This word doesn't fit the sentence context." + }, +] + + +# ============ Реакции учителя Марека (нейтральные, без гендерной привязки) ============ +# 30 на "correct", 20 на "almost", 20 на "wrong" +TEACHER_REACTIONS = [ + # ===== ПРАВИЛЬНЫЕ ОТВЕТЫ (30) ===== + {"type": "correct", "pl": "Świetnie! Dokładnie tak!", "ru": "Отлично! Именно так!", "uk": "Чудово! Саме так!", "en": "Great! Exactly right!"}, + {"type": "correct", "pl": "Brawo! Świetna robota!", "ru": "Браво! Отличная работа!", "uk": "Браво! Чудова робота!", "en": "Bravo! Great job!"}, + {"type": "correct", "pl": "Doskonale! Tak trzymaj!", "ru": "Превосходно! Так держать!", "uk": "Чудово! Так тримати!", "en": "Excellent! Keep it up!"}, + {"type": "correct", "pl": "Zgadza się! Widzę ogromny postęp!", "ru": "Верно! Вижу огромный прогресс!", "uk": "Вірно! Бачу величезний прогрес!", "en": "Correct! I see huge progress!"}, + {"type": "correct", "pl": "Perfekcyjnie! Zasługujesz na pochwałę!", "ru": "Идеально! Это заслуживает похвалы!", "uk": "Ідеально! Це заслуговує на похвалу!", "en": "Perfect! This deserves praise!"}, + {"type": "correct", "pl": "Tak jest! Bez żadnych błędów!", "ru": "Так точно! Без единой ошибки!", "uk": "Так точно! Без жодної помилки!", "en": "That's it! No mistakes at all!"}, + {"type": "correct", "pl": "Pięknie! Od razu widać postępy!", "ru": "Красиво! Сразу виден прогресс!", "uk": "Гарно! Одразу видно прогрес!", "en": "Beautiful! Progress is visible!"}, + {"type": "correct", "pl": "O tak! To jest poprawna odpowiedź!", "ru": "О да! Это правильный ответ!", "uk": "О так! Це правильна відповідь!", "en": "Oh yes! That's the correct answer!"}, + {"type": "correct", "pl": "Wspaniale! Z każdym razem lepiej!", "ru": "Замечательно! С каждым разом лучше!", "uk": "Чудово! З кожним разом краще!", "en": "Wonderful! Better every time!"}, + {"type": "correct", "pl": "Dokładnie o to chodziło!", "ru": "Именно это и имелось в виду!", "uk": "Саме це і малося на увазі!", "en": "That's exactly what I meant!"}, + {"type": "correct", "pl": "Super! To naprawdę imponujące!", "ru": "Супер! Это впечатляет!", "uk": "Супер! Це вражає!", "en": "Super! That's impressive!"}, + {"type": "correct", "pl": "Zgadza się! Polskie słowa nie są ci straszne!", "ru": "Верно! Польские слова не страшны!", "uk": "Вірно! Польські слова не страшні!", "en": "Right! Polish words don't scare you!"}, + {"type": "correct", "pl": "Idealnie! Jak rodowity Polak!", "ru": "Идеально! Как у носителя языка!", "uk": "Ідеально! Як у носія мови!", "en": "Perfect! Like a native speaker!"}, + {"type": "correct", "pl": "Masz rację! Pamięć działa świetnie!", "ru": "Верно! Память работает отлично!", "uk": "Вірно! Пам'ять працює чудово!", "en": "Right! Memory works great!"}, + {"type": "correct", "pl": "Świetna odpowiedź! Tak trzymaj dalej!", "ru": "Отличный ответ! Продолжай в том же духе!", "uk": "Чудова відповідь! Продовжуй у тому ж дусі!", "en": "Great answer! Keep it up!"}, + {"type": "correct", "pl": "Brawo! Widzę, że naprawdę się uczysz!", "ru": "Браво! Видно, что идёт настоящая учёба!", "uk": "Браво! Видно, що йде справжнє навчання!", "en": "Bravo! Real learning is happening!"}, + {"type": "correct", "pl": "Oczywiście! Dokładnie tak!", "ru": "Конечно! Именно так!", "uk": "Звісно! Саме так!", "en": "Of course! Exactly like that!"}, + {"type": "correct", "pl": "Znakomicie! Nie mogę się doczekać następnego pytania!", "ru": "Великолепно! Жду следующего вопроса!", "uk": "Чудово! Чекаю наступного питання!", "en": "Excellent! Can't wait for the next question!"}, + {"type": "correct", "pl": "Tak! To poprawna forma!", "ru": "Да! Это правильная форма!", "uk": "Так! Це правильна форма!", "en": "Yes! That's the correct form!"}, + {"type": "correct", "pl": "Prawidłowo! Jestem dumny z twoich postępów!", "ru": "Правильно! Я горжусь твоими успехами!", "uk": "Правильно! Я пишаюся твоїми успіхами!", "en": "Correct! I'm proud of your progress!"}, + {"type": "correct", "pl": "Dobrze! Nawet nie musiałeś się zastanawiać!", "ru": "Хорошо! Даже не пришлось задумываться!", "uk": "Добре! Навіть не довелося задумуватися!", "en": "Good! Didn't even hesitate!"}, + {"type": "correct", "pl": "Dokładnie! Język polski nie ma przed tobą tajemnic!", "ru": "Точно! У польского языка нет секретов!", "uk": "Точно! У польської мови немає секретів!", "en": "Exactly! Polish has no secrets!"}, + {"type": "correct", "pl": "Tak jest! Ciężka praca się opłaca!", "ru": "Так! Усердная работа окупается!", "uk": "Так! Наполеглива праця окупається!", "en": "That's it! Hard work pays off!"}, + {"type": "correct", "pl": "Doskonale! Zasługujesz na przerwę, ale najpierw kolejne pytanie!", "ru": "Отлично! Заслужил(а) перерыв, но сначала следующий вопрос!", "uk": "Чудово! Заслужив(ла) перерву, але спочатку наступне питання!", "en": "Excellent! You deserve a break, but first the next question!"}, + {"type": "correct", "pl": "Fantastycznie! Twoja wiedza rośnie!", "ru": "Фантастика! Знания растут!", "uk": "Фантастика! Знання ростуть!", "en": "Fantastic! Knowledge is growing!"}, + {"type": "correct", "pl": "Świetny wynik! Jestem pod wrażeniem!", "ru": "Отличный результат! Я впечатлён!", "uk": "Чудовий результат! Я вражений!", "en": "Great result! I'm impressed!"}, + {"type": "correct", "pl": "Brawo! Tak trzymaj!", "ru": "Браво! Так держать!", "uk": "Браво! Так тримати!", "en": "Bravo! Keep it up!"}, + {"type": "correct", "pl": "Zgadza się! Coraz lepiej ci idzie!", "ru": "Верно! Всё лучше и лучше получается!", "uk": "Вірно! Все краще і краще виходить!", "en": "Right! Getting better and better!"}, + {"type": "correct", "pl": "Dokładnie! Nic dodać, nic ująć!", "ru": "Точно! Ни добавить, ни убавить!", "uk": "Точно! Ні додати, ні відняти!", "en": "Exactly! Nothing to add, nothing to subtract!"}, + {"type": "correct", "pl": "Wspaniała robota! Jestem naprawdę dumny!", "ru": "Отличная работа! Я правда горжусь!", "uk": "Чудова робота! Я справді пишаюся!", "en": "Wonderful work! Truly proud!"}, + + # ===== ПОЧТИ ПРАВИЛЬНО (20) ===== + {"type": "almost", "pl": "Prawie! Jeszcze chwila...", "ru": "Почти! Ещё чуть-чуть...", "uk": "Майже! Ще трохи...", "en": "Almost! Just a little more..."}, + {"type": "almost", "pl": "Blisko! Spróbuj jeszcze raz.", "ru": "Близко! Попробуй ещё раз.", "uk": "Близько! Спробуй ще раз.", "en": "Close! Try again."}, + {"type": "almost", "pl": "Niewiele brakowało!", "ru": "Чуть-чуть не хватило!", "uk": "Трішки не вистачило!", "en": "So close!"}, + {"type": "almost", "pl": "Jesteś na dobrej drodze!", "ru": "Ты на правильном пути!", "uk": "Ти на правильному шляху!", "en": "You're on the right track!"}, + {"type": "almost", "pl": "Prawie dobrze! Jeszcze raz!", "ru": "Почти хорошо! Ещё раз!", "uk": "Майже добре! Ще раз!", "en": "Almost right! One more time!"}, + {"type": "almost", "pl": "Jeszcze troszeczkę...", "ru": "Ещё чуточку...", "uk": "Ще трішечки...", "en": "Just a tiny bit more..."}, + {"type": "almost", "pl": "Blisko, ale nie dokładnie. Pomyśl jeszcze chwilę.", "ru": "Близко, но не точно. Подумай ещё немного.", "uk": "Близько, але не точно. Подумай ще трохи.", "en": "Close, but not quite. Think a bit more."}, + {"type": "almost", "pl": "Dobra intuicja! Ale spróbuj poprawić.", "ru": "Хорошая интуиция! Но попробуй исправить.", "uk": "Гарна інтуїція! Але спробуй виправити.", "en": "Good intuition! But try to correct it."}, + {"type": "almost", "pl": "To nie jest złe, ale nie do końca to, o co pytam.", "ru": "Это неплохо, но не совсем то, о чём я спрашиваю.", "uk": "Це непогано, але не зовсім те, про що я питаю.", "en": "Not bad, but not quite what I'm asking."}, + {"type": "almost", "pl": "Jesteś bardzo blisko! Mała poprawka i będzie idealnie.", "ru": "Очень близко! Маленькая поправка и будет идеально.", "uk": "Дуже близько! Маленьке виправлення і буде ідеально.", "en": "Very close! Small correction and it'll be perfect."}, + {"type": "almost", "pl": "Prawie! Sprawdź jeszcze raz pisownię.", "ru": "Почти! Проверь ещё раз написание.", "uk": "Майже! Перевір ще раз написання.", "en": "Almost! Check the spelling again."}, + {"type": "almost", "pl": "Niewielka pomyłka! Skup się na szczegółach.", "ru": "Небольшая ошибка! Сосредоточься на деталях.", "uk": "Невелика помилка! Зосередься на деталях.", "en": "Small mistake! Focus on the details."}, + {"type": "almost", "pl": "Blisko! Jeden mały krok do sukcesu.", "ru": "Близко! Один маленький шаг до успеха.", "uk": "Близько! Один маленький крок до успіху.", "en": "Close! One small step to success."}, + {"type": "almost", "pl": "Jesteś blisko! Ale nie tym razem.", "ru": "Близко! Но не в этот раз.", "uk": "Близько! Але не цього разу.", "en": "Close! But not this time."}, + {"type": "almost", "pl": "Prawie! Nie zatrzymuj się teraz.", "ru": "Почти! Не останавливайся сейчас.", "uk": "Майже! Не зупиняйся зараз.", "en": "Almost! Don't stop now."}, + {"type": "almost", "pl": "Jeszcze jeden krok! Spróbuj ponownie.", "ru": "Ещё один шаг! Попробуй снова.", "uk": "Ще один крок! Спробуй знову.", "en": "One more step! Try again."}, + {"type": "almost", "pl": "Niewiele brakuje do perfekcji!", "ru": "Немного не хватает до совершенства!", "uk": "Трішки не вистачає до досконалості!", "en": "Just a bit short of perfection!"}, + {"type": "almost", "pl": "Bardzo blisko! Jeszcze jedna próba.", "ru": "Очень близко! Ещё одна попытка.", "uk": "Дуже близько! Ще одна спроба.", "en": "Very close! One more attempt."}, + {"type": "almost", "pl": "Prawie udało się! Nie poddawaj się.", "ru": "Почти получилось! Не сдавайся.", "uk": "Майже вийшло! Не здавайся.", "en": "Almost got it! Don't give up."}, + {"type": "almost", "pl": "Mała poprawka i będzie idealnie!", "ru": "Маленькая поправка и будет идеально!", "uk": "Маленьке виправлення і буде ідеально!", "en": "Small correction and it'll be perfect!"}, + + # ===== НЕПРАВИЛЬНЫЕ ОТВЕТЫ (20) ===== + {"type": "wrong", "pl": "Nie tym razem. Nie poddawaj się!", "ru": "Не в этот раз. Не сдавайся!", "uk": "Не цього разу. Не здавайся!", "en": "Not this time. Don't give up!"}, + {"type": "wrong", "pl": "To nie to. Spróbuj jeszcze raz!", "ru": "Это не то. Попробуй ещё раз!", "uk": "Це не те. Спробуй ще раз!", "en": "That's not it. Try again!"}, + {"type": "wrong", "pl": "Zdarza się! Ważne, że próbujesz.", "ru": "Бывает! Главное, что ты пытаешься.", "uk": "Буває! Головне, що ти намагаєшся.", "en": "It happens! What matters is that you try."}, + {"type": "wrong", "pl": "Błąd to część nauki!", "ru": "Ошибка — часть обучения!", "uk": "Помилка — частина навчання!", "en": "Mistakes are part of learning!"}, + {"type": "wrong", "pl": "Nie szkodzi! Uczymy się na błędach.", "ru": "Ничего страшного! Мы учимся на ошибках.", "uk": "Нічого страшного! Ми вчимося на помилках.", "en": "No worries! We learn from mistakes."}, + {"type": "wrong", "pl": "Nie martw się! Każdy mistrz kiedyś zaczynał od zera.", "ru": "Не переживай! Каждый мастер когда-то начинал с нуля.", "uk": "Не хвилюйся! Кожен майстер колись починав з нуля.", "en": "Don't worry! Every master started from zero."}, + {"type": "wrong", "pl": "Pomyłka to dobry znak — znaczy, że próbujesz!", "ru": "Ошибка — хороший знак, значит есть попытка!", "uk": "Помилка — гарний знак, значить є спроба!", "en": "A mistake is a good sign — it means you're trying!"}, + {"type": "wrong", "pl": "Nie udało się, ale nie przestawaj!", "ru": "Не получилось, но не останавливайся!", "uk": "Не вийшло, але не зупиняйся!", "en": "Didn't work, but don't stop!"}, + {"type": "wrong", "pl": "Sprawdź dokładnie i spróbuj ponownie.", "ru": "Проверь внимательно и попробуй снова.", "uk": "Перевір уважно і спробуй знову.", "en": "Check carefully and try again."}, + {"type": "wrong", "pl": "Nie tym razem, ale doceniam twoje zaangażowanie!", "ru": "Не в этот раз, но я ценю усердие!", "uk": "Не цього разу, але я ціную старанність!", "en": "Not this time, but I appreciate the effort!"}, + {"type": "wrong", "pl": "Spokojnie! Nawet najlepsi popełniają błędy.", "ru": "Спокойно! Даже лучшие ошибаются.", "uk": "Спокійно! Навіть найкращі помиляються.", "en": "Relax! Even the best make mistakes."}, + {"type": "wrong", "pl": "Nie poddawaj się! Jesteś bliżej niż myślisz.", "ru": "Не сдавайся! Ты ближе, чем думаешь.", "uk": "Не здавайся! Ти ближче, ніж думаєш.", "en": "Don't give up! You're closer than you think."}, + {"type": "wrong", "pl": "Spróbuj inaczej! Może pomoże inne podejście.", "ru": "Попробуй иначе! Может, поможет другой подход.", "uk": "Спробуй інакше! Може, допоможе інший підхід.", "en": "Try differently! Maybe another approach will help."}, + {"type": "wrong", "pl": "Nie zniechęcaj się! To normalny etap nauki.", "ru": "Не расстраивайся! Это нормальный этап обучения.", "uk": "Не засмучуйся! Це нормальний етап навчання.", "en": "Don't be discouraged! It's a normal stage of learning."}, + {"type": "wrong", "pl": "Każdy błąd to lekcja na przyszłość!", "ru": "Каждая ошибка — урок на будущее!", "uk": "Кожна помилка — урок на майбутнє!", "en": "Every mistake is a lesson for the future!"}, + {"type": "wrong", "pl": "Nie martw się! Mózg najlepiej uczy się na błędach.", "ru": "Не переживай! Мозг лучше всего учится на ошибках.", "uk": "Не хвилюйся! Мозок найкраще вчиться на помилках.", "en": "Don't worry! The brain learns best from mistakes."}, + {"type": "wrong", "pl": "To normalne! Nawet ja czasem się mylę.", "ru": "Это нормально! Даже я иногда ошибаюсь.", "uk": "Це нормально! Навіть я іноді помиляюся.", "en": "That's normal! Even I make mistakes sometimes."}, + {"type": "wrong", "pl": "Ważne, że się uczysz! Błędy to część drogi.", "ru": "Важно, что ты учишься! Ошибки — часть пути.", "uk": "Важливо, що ти вчишся! Помилки — частина шляху.", "en": "What matters is that you're learning! Mistakes are part of the journey."}, + {"type": "wrong", "pl": "Nie przejmuj się! Następnym razem się uda.", "ru": "Не переживай! В следующий раз получится.", "uk": "Не хвилюйся! Наступного разу вийде.", "en": "Don't worry! Next time it'll work."}, + {"type": "wrong", "pl": "Uczymy się razem! To dopiero początek.", "ru": "Мы учимся вместе! Это только начало.", "uk": "Ми вчимося разом! Це тільки початок.", "en": "We're learning together! This is just the beginning."}, +] + + +async def main(): + pool = await asyncpg.create_pool(**DB_CONFIG) + async with pool.acquire() as conn: + # ============ Очищаем старые реакции ============ + await conn.execute("DELETE FROM teacher_reactions") + print("🗑️ Старые реакции удалены") + + # ============ Заполняем wrong_because_explanations ============ + for item in WRONG_BECAUSE_EXPLANATIONS: + await conn.execute(""" + INSERT INTO wrong_because_explanations (wrong_because, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, $2, $3, $4, $5) + ON CONFLICT (wrong_because) DO UPDATE SET + explanation_pl = $2, + explanation_ru = $3, + explanation_uk = $4, + explanation_en = $5 + """, item["wrong_because"], item["pl"], item["ru"], item["uk"], item["en"]) + + print(f"✅ Добавлено {len(WRONG_BECAUSE_EXPLANATIONS)} объяснений ошибок") + + # ============ Заполняем teacher_reactions ============ + correct_count = 0 + almost_count = 0 + wrong_count = 0 + + for item in TEACHER_REACTIONS: + await conn.execute(""" + INSERT INTO teacher_reactions (reaction_type, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5) + """, item["type"], item["pl"], item["ru"], item["uk"], item["en"]) + + if item["type"] == "correct": + correct_count += 1 + elif item["type"] == "almost": + almost_count += 1 + else: + wrong_count += 1 + + print(f"✅ Добавлено реакций: correct={correct_count}, almost={almost_count}, wrong={wrong_count}") + print(f" Всего: {len(TEACHER_REACTIONS)}") + + await pool.close() + print("\n🎉 Готово! Марек готов к работе!") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/load_all_words.py b/load_all_words.py new file mode 100644 index 0000000..bd555f3 --- /dev/null +++ b/load_all_words.py @@ -0,0 +1,55 @@ +import csv +import asyncpg +import asyncio +from config import DB_CONFIG + +async def load_all(): + pool = await asyncpg.create_pool(**DB_CONFIG) + async with pool.acquire() as conn: + level_files = [ + ("A1", "words_a1.csv"), + ("A2", "words_a2.csv"), + ("B1", "words_b1.csv"), + ] + + total_added = 0 + + for level, fname in level_files: + print(f'\n{"="*50}') + print(f'Loading {fname} (level {level})...') + print(f'{"="*50}') + + # 🔧 ФИКС: удаляем ВСЕ строки уровня, независимо от level_id + deleted = await conn.execute( + "DELETE FROM level_words WHERE level = $1", + level + ) + print(f' Deleted old entries: {deleted}') + + count = 0 + with open(fname, 'r', encoding='utf-8') as f: + reader = csv.DictReader(f) + for row in reader: + word = row['polish'].strip().lower() + if word: + await conn.execute( + '''INSERT INTO level_words (level_id, word_pl, translation_ru, translation_uk, translation_en, level) + VALUES (NULL, $1, $2, $3, $4, $5) + ON CONFLICT (level, word_pl) DO NOTHING''', + word, + row.get('russian', ''), + row.get('ukrainian', ''), + row.get('english', ''), + level + ) + count += 1 + + total_added += count + print(f' Added {count} words from {fname} (level {level})') + + await pool.close() + + print(f'\n🎉 Готово! Всего загружено {total_added} слов.') + +if __name__ == '__main__': + asyncio.run(load_all()) \ No newline at end of file diff --git a/main.py b/main.py new file mode 100644 index 0000000..25a54f9 --- /dev/null +++ b/main.py @@ -0,0 +1,286 @@ +import asyncio +import logging +import os +import re +import time +from collections import defaultdict +from pathlib import Path +from fastapi import FastAPI, Request, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse +from fastapi.staticfiles import StaticFiles +from config import FRONTEND_ORIGIN, UPLOADS_DIR +from database import init_db +from routers import users, game, hints, leaderboard, sentences, achievements, wordquiz, bubblewords, pronunciation, assistant, learning, tts, typing, teacher, support, admin, feed, admin_content +from routers.sentences import init_sentences +from routers.achievements import init_achievements +from routers.learning_data import init_learning_data + +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') +logger = logging.getLogger(__name__) + +# ============ Версия ============ +# Читается из .env (переменная APP_VERSION). Если не задана — fallback "1.0.0". +# Фронт живёт на Cloudflare Pages, там своя версия в index.html — они не обязаны совпадать. +# При деплое новой версии фронта обнови APP_VERSION в .env и перезапусти filwords-api. +APP_VERSION = os.getenv("APP_VERSION", "1.0.0") + +# ============ Sentry (мониторинг ошибок) ============ +# ВАЖНО: инициализация ДО создания FastAPI-приложения +SENTRY_DSN = os.getenv("SENTRY_DSN", "") +if SENTRY_DSN: + try: + import sentry_sdk + from sentry_sdk.integrations.fastapi import FastApiIntegration + from sentry_sdk.integrations.starlette import StarletteIntegration + + sentry_sdk.init( + dsn=SENTRY_DSN, + integrations=[ + StarletteIntegration(transaction_style="endpoint"), + FastApiIntegration(transaction_style="endpoint"), + ], + traces_sample_rate=0.2, # 20% запросов для performance monitoring + environment=os.getenv("ENV", "production"), + release=f"filwords@{APP_VERSION}", + send_default_pii=False, # НЕ отправляем IP/headers/cookies пользователей + ) + logger.info(f"Sentry initialized (release=filwords@{APP_VERSION})") + except Exception as e: + logger.error(f"Failed to initialize Sentry: {e}") +else: + logger.warning("SENTRY_DSN not set — Sentry disabled") + +app = FastAPI(title="Filwords PL API") + +# ============ Rate Limiting ============ +class RateLimiter: + def __init__(self): + self.requests = defaultdict(list) + self.limits = { + "default": {"max_requests": 60, "window": 60}, + "/game/check-word": {"max_requests": 30, "window": 60}, + "/game/complete-level": {"max_requests": 10, "window": 60}, + "/sentences/check": {"max_requests": 20, "window": 60}, + "/leaderboard": {"max_requests": 10, "window": 60}, + "/assistant/chat": {"max_requests": 20, "window": 60}, + "/learning/answer": {"max_requests": 30, "window": 60}, + "/tts": {"max_requests": 30, "window": 60}, + "/review": {"max_requests": 10, "window": 60}, + "/typing/check": {"max_requests": 20, "window": 60}, + "/teacher/answer": {"max_requests": 30, "window": 60}, + "/teacher/start": {"max_requests": 10, "window": 60}, + "/teacher/explain": {"max_requests": 10, "window": 60}, + "/teacher/translate": {"max_requests": 10, "window": 60}, + "/teacher/example": {"max_requests": 10, "window": 60}, + "/support/send": {"max_requests": 10, "window": 60}, + "/support/admin-reply": {"max_requests": 30, "window": 60}, + "/support/translate": {"max_requests": 20, "window": 60}, + # 🔧 НОВОЕ (18.09.2026): лимиты для feed + "/admin/feed/post": {"max_requests": 20, "window": 60}, + "/admin/feed/upload-image": {"max_requests": 10, "window": 60}, + "/admin/feed/translate": {"max_requests": 10, "window": 60}, + } + self._cleanup_task = None + + def _cleanup(self): + now = time.time() + for key in list(self.requests.keys()): + self.requests[key] = [t for t in self.requests[key] if now - t < 60] + if not self.requests[key]: + del self.requests[key] + + async def start_cleanup(self): + while True: + await asyncio.sleep(60) + self._cleanup() + + def is_allowed(self, key: str, path: str) -> bool: + now = time.time() + + limit_config = self.limits.get(path, self.limits["default"]) + max_requests = limit_config["max_requests"] + window = limit_config["window"] + + self.requests[key] = [t for t in self.requests[key] if now - t < window] + + if len(self.requests[key]) >= max_requests: + return False + + self.requests[key].append(now) + return True + + def get_retry_after(self, key: str, path: str) -> int: + if not self.requests[key]: + return 0 + limit_config = self.limits.get(path, self.limits["default"]) + window = limit_config["window"] + oldest = min(self.requests[key]) + return max(0, int(window - (time.time() - oldest))) + +rate_limiter = RateLimiter() + +# ============ Rate Limiting Middleware ============ +@app.middleware("http") +async def rate_limit_middleware(request: Request, call_next): + path = request.url.path + + if path in ["/", "/health"]: + return await call_next(request) + + client_ip = request.client.host if request.client else "unknown" + rate_key = f"{client_ip}:{path}" + + if not rate_limiter.is_allowed(rate_key, path): + retry_after = rate_limiter.get_retry_after(rate_key, path) + return JSONResponse( + status_code=429, + content={ + "error": "Too many requests", + "retry_after": retry_after + }, + headers={"Retry-After": str(retry_after)} + ) + + start_time = time.time() + response = await call_next(request) + duration = time.time() - start_time + + if duration > 1.0: + logger.warning(f"Slow request: {request.method} {path} - {duration:.2f}s") + + return response + +# ============ CORS ============ +# 🔧 ОБНОВЛЕНО: добавлен PUT — нужен для редактирования feed-постов +app.add_middleware( + CORSMiddleware, + allow_origins=[FRONTEND_ORIGIN], + allow_credentials=False, + allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"], + allow_headers=["*"], +) + +# ============ 🔧 НОВОЕ (18.09.2026): статика для картинок feed-постов ============ +# Файлы лежат в /root/filwordspl/backend/uploads/feed/{filename} +# URL на фронте: https://api.filwordspl.com/uploads/feed/{filename} +app.mount("/uploads", StaticFiles(directory=UPLOADS_DIR), name="uploads") + +# ============ Роутеры ============ +app.include_router(users.router) +app.include_router(game.router) +app.include_router(hints.router) +app.include_router(leaderboard.router) +app.include_router(sentences.router) +app.include_router(achievements.router) +app.include_router(wordquiz.router) +app.include_router(bubblewords.router) +app.include_router(pronunciation.router) +app.include_router(assistant.router) +app.include_router(learning.router) +app.include_router(tts.router) +app.include_router(typing.router) +app.include_router(teacher.router) +app.include_router(support.router) +app.include_router(admin.router) +# 🔧 НОВОЕ (18.09.2026): feed — посты карусели (публичный + админский) +app.include_router(feed.router) +# 🔧 НОВОЕ (19.09.2026): admin content — контент-менеджер (только для админов) +app.include_router(admin_content.router) + +# ============ Фоновое обновление кэша рейтинга ============ +async def refresh_leaderboard_cache_loop(): + await asyncio.sleep(10) + while True: + try: + from database import get_pool + pool = await get_pool() + async with pool.acquire() as conn: + await conn.execute("REFRESH MATERIALIZED VIEW CONCURRENTLY leaderboard_cache") + except Exception as e: + logger.error(f"Failed to refresh leaderboard cache: {e}") + await asyncio.sleep(30) + +# ============ Startup ============ +@app.on_event("startup") +async def startup(): + await init_db() + await init_sentences() + await init_achievements() + await init_learning_data() + + asyncio.create_task(rate_limiter.start_cleanup()) + + from database import get_pool + pool = await get_pool() + async with pool.acquire() as conn: + # Пересоздаём materialized view с новой структурой (с level) + await conn.execute("DROP MATERIALIZED VIEW IF EXISTS leaderboard_cache") + await conn.execute(""" + CREATE MATERIALIZED VIEW IF NOT EXISTS leaderboard_cache AS + SELECT + u.telegram_id, + u.username, + u.current_level, + COALESCE(ws.total, 0) + COALESCE(s.total, 0) + COALESCE(wq.total, 0) + COALESCE(bw.total, 0) as total_score, + COALESCE(ws.total, 0) as wordsearch_score, + COALESCE(s.total, 0) as sentence_score, + COALESCE(wq.total, 0) as wordquiz_score, + COALESCE(wq.words_guessed, 0) as words_guessed, + COALESCE(bw.total, 0) as bubblewords_score, + COALESCE(bw.levels_completed, 0) as bubble_levels_completed + FROM users u + LEFT JOIN ( + SELECT user_id, SUM(score) as total + FROM user_progress + WHERE completed_at IS NOT NULL + GROUP BY user_id + ) ws ON u.telegram_id = ws.user_id + LEFT JOIN ( + SELECT user_id, SUM(score) as total + FROM sentence_progress + WHERE completed_at IS NOT NULL + GROUP BY user_id + ) s ON u.telegram_id = s.user_id + LEFT JOIN ( + SELECT user_id, total_score as total, words_guessed + FROM word_quiz_progress + ) wq ON u.telegram_id = wq.user_id + LEFT JOIN ( + SELECT user_id, total_score as total, levels_completed + FROM bubble_words_progress + ) bw ON u.telegram_id = bw.user_id + WHERE COALESCE(ws.total, 0) + COALESCE(s.total, 0) + COALESCE(wq.total, 0) + COALESCE(bw.total, 0) > 0 + ORDER BY total_score DESC + """) + + await conn.execute(""" + CREATE UNIQUE INDEX IF NOT EXISTS idx_leaderboard_cache_user + ON leaderboard_cache (telegram_id) + """) + + logger.info("Leaderboard cache created") + + asyncio.create_task(refresh_leaderboard_cache_loop()) + + logger.info(f"Filwords API v{APP_VERSION} started") + +# ============ Базовые эндпоинты ============ +@app.get("/") +async def root(): + return {"status": "ok", "app": "Filwords PL", "version": APP_VERSION} + +@app.get("/health") +async def health(): + try: + from database import get_pool + pool = await get_pool() + async with pool.acquire() as conn: + await conn.fetchval("SELECT 1") + return {"status": "ok", "database": "connected"} + except Exception as e: + logger.error(f"Healthcheck failed: {e}") + return JSONResponse( + status_code=503, + content={"status": "error", "database": "disconnected"} + ) \ No newline at end of file diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 0000000..a0db359 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,17 @@ +[pytest] +asyncio_mode = auto +asyncio_default_fixture_loop_scope = session +asyncio_default_test_loop_scope = session +testpaths = tests +python_files = test_*.py +python_classes = Test* +python_functions = test_* +pythonpath = . +addopts = + -v + --tb=short + --strict-markers +markers = + asyncio: async test + integration: tests requiring real DB connection + unit: pure logic tests (no DB) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2bc0de3 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,38 @@ +aiohappyeyeballs==2.7.1 +aiohttp==3.14.3 +aiosignal==1.4.0 +annotated-doc==0.0.4 +annotated-types==0.8.0 +anyio==4.14.2 +asyncpg==0.31.0 +attrs==26.1.0 +certifi==2026.7.22 +click==8.4.2 +edge-tts==7.2.8 +fastapi==0.140.0 +frozenlist==1.8.0 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.18 +iniconfig==2.3.0 +multidict==6.7.1 +packaging==26.3 +pillow==12.3.0 +pluggy==1.6.0 +propcache==0.5.2 +pydantic==2.13.4 +pydantic_core==2.46.4 +Pygments==2.21.0 +pytest==9.1.1 +pytest-asyncio==1.4.0 +python-dotenv==1.2.2 +python-multipart==0.0.32 +sentry-sdk==2.69.1 +starlette==1.3.1 +tabulate==0.10.0 +typing-inspection==0.4.2 +typing_extensions==4.16.0 +urllib3==2.7.0 +uvicorn==0.51.0 +yarl==1.24.5 diff --git a/reset_my_progress.py b/reset_my_progress.py new file mode 100644 index 0000000..ba76682 --- /dev/null +++ b/reset_my_progress.py @@ -0,0 +1,65 @@ +""" +Сброс прогресса пользователя по разделу "Учитель" и "Уроки". +Очищает: user_learning_answers, user_lesson_progress, user_topic_progress, +user_skill_mastery, learning_sessions, teacher_chat_history, teacher_ai_usage. + +Запуск: python3 reset_my_progress.py +""" +import asyncio +import asyncpg +from config import DB_CONFIG + +# ID пользователя для сброса (твой Telegram ID) +USER_ID = 6694989403 + + +async def main(): + pool = await asyncpg.create_pool(**DB_CONFIG) + + async with pool.acquire() as conn: + # Проверяем, что пользователь существует + user_exists = await conn.fetchval(""" + SELECT 1 FROM users WHERE telegram_id = $1 + """, USER_ID) + + if not user_exists: + print(f"❌ Пользователь {USER_ID} не найден!") + await pool.close() + return + + # Список таблиц для очистки + tables = [ + "user_learning_answers", + "user_lesson_progress", + "user_topic_progress", + "user_skill_mastery", + "learning_sessions", + "teacher_chat_history", + "teacher_ai_usage", + ] + + for table in tables: + result = await conn.execute(f""" + DELETE FROM {table} WHERE user_id = $1 + """, USER_ID) + affected = int(result.split()[-1]) + print(f"🗑️ {table}: удалено {affected} записей") + + # Также очищаем ai_user_context + result = await conn.execute(""" + DELETE FROM ai_user_context WHERE user_id = $1 + """, USER_ID) + print(f"🗑️ ai_user_context: удалено {result.split()[-1]} записей") + + # Сбрасываем last_completed_level + await conn.execute(""" + UPDATE users SET last_completed_level = 0 WHERE telegram_id = $1 + """, USER_ID) + print("✅ last_completed_level сброшен на 0") + + await pool.close() + print("\n🎉 Готово! Можно начинать заново!") + + +if __name__ == "__main__": + asyncio.run(main()) \ No newline at end of file diff --git a/routers/__init__.py b/routers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/routers/achievements.py b/routers/achievements.py new file mode 100644 index 0000000..d776b6b --- /dev/null +++ b/routers/achievements.py @@ -0,0 +1,530 @@ +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool + +router = APIRouter(prefix="/achievements", tags=["achievements"]) + +# ============ Данные 52 достижений ============ +ACHIEVEMENTS_DATA = [ + # ===== Word Search (11) ===== + {"code": "first_level", "category": "wordsearch", "icon": "🔰", + "name_pl": "Pierwszy krok", "name_ru": "Первый шаг", "name_uk": "Перший крок", "name_en": "First Step", + "desc_pl": "Ukończ 1 poziom filwordów", "desc_ru": "Пройти 1 уровень филвордов", "desc_uk": "Пройти 1 рівень філвордів", "desc_en": "Complete 1 word search level", + "type": "levels_completed", "value": 1}, + + {"code": "ten_levels", "category": "wordsearch", "icon": "⭐", + "name_pl": "Gracz", "name_ru": "Игрок", "name_uk": "Гравець", "name_en": "Player", + "desc_pl": "Ukończ 10 poziomów filwordów", "desc_ru": "Пройти 10 уровней филвордов", "desc_uk": "Пройти 10 рівнів філвордів", "desc_en": "Complete 10 word search levels", + "type": "levels_completed", "value": 10}, + + {"code": "fifty_levels", "category": "wordsearch", "icon": "🏅", + "name_pl": "Ekspert", "name_ru": "Эксперт", "name_uk": "Експерт", "name_en": "Expert", + "desc_pl": "Ukończ 50 poziomów filwordów", "desc_ru": "Пройти 50 уровней филвордов", "desc_uk": "Пройти 50 рівнів філвордів", "desc_en": "Complete 50 word search levels", + "type": "levels_completed", "value": 50}, + + {"code": "hundred_levels", "category": "wordsearch", "icon": "👑", + "name_pl": "Król", "name_ru": "Король", "name_uk": "Король", "name_en": "King", + "desc_pl": "Ukończ 100 poziomów filwordów", "desc_ru": "Пройти 100 уровней филвордов", "desc_uk": "Пройти 100 рівнів філвордів", "desc_en": "Complete 100 word search levels", + "type": "levels_completed", "value": 100}, + + {"code": "ws_200", "category": "wordsearch", "icon": "🎯", + "name_pl": "Mistrz", "name_ru": "Мастер", "name_uk": "Майстер", "name_en": "Master", + "desc_pl": "Ukończ 200 poziomów filwordów", "desc_ru": "Пройти 200 уровней филвордов", "desc_uk": "Пройти 200 рівнів філвордів", "desc_en": "Complete 200 word search levels", + "type": "levels_completed", "value": 200}, + + {"code": "ws_500", "category": "wordsearch", "icon": "🌟", + "name_pl": "Legenda filwordów", "name_ru": "Легенда филвордов", "name_uk": "Легенда філвордів", "name_en": "Word Search Legend", + "desc_pl": "Ukończ 500 poziomów filwordów", "desc_ru": "Пройти 500 уровней филвордов", "desc_uk": "Пройти 500 рівнів філвордів", "desc_en": "Complete 500 word search levels", + "type": "levels_completed", "value": 500}, + + {"code": "no_hints", "category": "wordsearch", "icon": "💡", + "name_pl": "Bystrzak", "name_ru": "Умница", "name_uk": "Розумник", "name_en": "Smart", + "desc_pl": "Ukończ poziom bez podpowiedzi", "desc_ru": "Пройти уровень без подсказок", "desc_uk": "Пройти рівень без підказок", "desc_en": "Complete a level without hints", + "type": "no_hints_level", "value": 1}, + + {"code": "streak_5", "category": "wordsearch", "icon": "🔥", + "name_pl": "Seria", "name_ru": "Серия", "name_uk": "Серія", "name_en": "Streak", + "desc_pl": "Ukończ 5 poziomów z rzędu", "desc_ru": "Пройти 5 уровней подряд", "desc_uk": "Пройти 5 рівнів поспіль", "desc_en": "Complete 5 levels in a row", + "type": "level_streak", "value": 5}, + + {"code": "speed_60", "category": "wordsearch", "icon": "⚡", + "name_pl": "Szybki", "name_ru": "Быстрый", "name_uk": "Швидкий", "name_en": "Fast", + "desc_pl": "Ukończ poziom w mniej niż 60 sekund", "desc_ru": "Пройти уровень быстрее 60 секунд", "desc_uk": "Пройти рівень швидше 60 секунд", "desc_en": "Complete a level in under 60 seconds", + "type": "speed_level", "value": 60}, + + {"code": "ws_speed_30", "category": "wordsearch", "icon": "🚀", + "name_pl": "Błyskawica", "name_ru": "Молния", "name_uk": "Блискавка", "name_en": "Lightning", + "desc_pl": "Ukończ poziom w mniej niż 30 sekund", "desc_ru": "Пройти уровень быстрее 30 секунд", "desc_uk": "Пройти рівень швидше 30 секунд", "desc_en": "Complete a level in under 30 seconds", + "type": "speed_level", "value": 30}, + + {"code": "perfect_5", "category": "wordsearch", "icon": "🎯", + "name_pl": "Snajper", "name_ru": "Снайпер", "name_uk": "Снайпер", "name_en": "Sniper", + "desc_pl": "Znajdź 5 słów bez błędu", "desc_ru": "Найти 5 слов подряд без ошибок", "desc_uk": "Знайти 5 слів без помилки", "desc_en": "Find 5 words without mistakes", + "type": "perfect_words", "value": 5}, + + # ===== Sentence Builder (10) ===== + {"code": "first_sentence", "category": "sentence", "icon": "📝", + "name_pl": "Debiutant", "name_ru": "Дебютант", "name_uk": "Дебютант", "name_en": "Debutant", + "desc_pl": "Ułóż 1 zdanie", "desc_ru": "Составить 1 предложение", "desc_uk": "Скласти 1 речення", "desc_en": "Build 1 sentence", + "type": "sentences_completed", "value": 1}, + + {"code": "ten_sentences", "category": "sentence", "icon": "✍️", + "name_pl": "Autor", "name_ru": "Автор", "name_uk": "Автор", "name_en": "Author", + "desc_pl": "Ułóż 10 zdań", "desc_ru": "Составить 10 предложений", "desc_uk": "Скласти 10 речень", "desc_en": "Build 10 sentences", + "type": "sentences_completed", "value": 10}, + + {"code": "fifty_sentences", "category": "sentence", "icon": "🎓", + "name_pl": "Profesor", "name_ru": "Профессор", "name_uk": "Професор", "name_en": "Professor", + "desc_pl": "Ułóż 50 zdań", "desc_ru": "Составить 50 предложений", "desc_uk": "Скласти 50 речень", "desc_en": "Build 50 sentences", + "type": "sentences_completed", "value": 50}, + + {"code": "hundred_sentences", "category": "sentence", "icon": "📚", + "name_pl": "Bibliotekarz", "name_ru": "Библиотекарь", "name_uk": "Бібліотекар", "name_en": "Librarian", + "desc_pl": "Ułóż 100 zdań", "desc_ru": "Составить 100 предложений", "desc_uk": "Скласти 100 речень", "desc_en": "Build 100 sentences", + "type": "sentences_completed", "value": 100}, + + {"code": "sentence_200", "category": "sentence", "icon": "📖", + "name_pl": "Pisarz", "name_ru": "Писатель", "name_uk": "Письменник", "name_en": "Writer", + "desc_pl": "Ułóż 200 zdań", "desc_ru": "Составить 200 предложений", "desc_uk": "Скласти 200 речень", "desc_en": "Build 200 sentences", + "type": "sentences_completed", "value": 200}, + + {"code": "perfect_sentence_5", "category": "sentence", "icon": "✨", + "name_pl": "Perfekcjonista", "name_ru": "Перфекционист", "name_uk": "Перфекціоніст", "name_en": "Perfectionist", + "desc_pl": "Ułóż 5 zdań bez błędu", "desc_ru": "Составить 5 предложений без единой ошибки", "desc_uk": "Скласти 5 речень без жодної помилки", "desc_en": "Build 5 sentences without mistakes", + "type": "perfect_sentences", "value": 5}, + + {"code": "sentence_perfect_10", "category": "sentence", "icon": "💎", + "name_pl": "Mistrz zdań", "name_ru": "Мастер предложений", "name_uk": "Майстер речень", "name_en": "Sentence Master", + "desc_pl": "Ułóż 10 zdań bez błędu", "desc_ru": "Составить 10 предложений без ошибок", "desc_uk": "Скласти 10 речень без помилок", "desc_en": "Build 10 sentences without mistakes", + "type": "perfect_sentences", "value": 10}, + + {"code": "sentence_streak_10", "category": "sentence", "icon": "💪", + "name_pl": "Nieomylny", "name_ru": "Безошибочный", "name_uk": "Безпомилковий", "name_en": "Flawless", + "desc_pl": "Ułóż 10 zdań z rzędu bez błędu", "desc_ru": "Составить 10 предложений подряд без ошибок", "desc_uk": "Скласти 10 речень поспіль без помилок", "desc_en": "Build 10 sentences in a row without mistakes", + "type": "sentence_streak", "value": 10}, + + {"code": "speed_10", "category": "sentence", "icon": "🚀", + "name_pl": "Turbo", "name_ru": "Турбо", "name_uk": "Турбо", "name_en": "Turbo", + "desc_pl": "Ułóż zdanie w mniej niż 10 sekund", "desc_ru": "Составить предложение быстрее 10 секунд", "desc_uk": "Скласти речення швидше 10 секунд", "desc_en": "Build a sentence in under 10 seconds", + "type": "speed_sentence", "value": 10}, + + {"code": "sentence_speed_5", "category": "sentence", "icon": "⚡", + "name_pl": "Ekspres", "name_ru": "Экспресс", "name_uk": "Експрес", "name_en": "Express", + "desc_pl": "Ułóż zdanie w mniej niż 5 sekund", "desc_ru": "Составить предложение быстрее 5 секунд", "desc_uk": "Скласти речення швидше 5 секунд", "desc_en": "Build a sentence in under 5 seconds", + "type": "speed_sentence", "value": 5}, + + # ===== Word Quiz (8) ===== + {"code": "quiz_10", "category": "wordquiz", "icon": "🧠", + "name_pl": "Myśliciel", "name_ru": "Мыслитель", "name_uk": "Мислитель", "name_en": "Thinker", + "desc_pl": "Odgadnij 10 słów w Quiz słownym", "desc_ru": "Угадать 10 слов в Квизе слов", "desc_uk": "Відгадати 10 слів у Квізі слів", "desc_en": "Guess 10 words in Word Quiz", + "type": "quiz_guessed", "value": 10}, + + {"code": "quiz_50", "category": "wordquiz", "icon": "🎓", + "name_pl": "Mistrz quizu", "name_ru": "Мастер квиза", "name_uk": "Майстер квізу", "name_en": "Quiz Master", + "desc_pl": "Odgadnij 50 słów w Quiz słownym", "desc_ru": "Угадать 50 слов в Квизе слов", "desc_uk": "Відгадати 50 слів у Квізі слів", "desc_en": "Guess 50 words in Word Quiz", + "type": "quiz_guessed", "value": 50}, + + {"code": "quiz_100", "category": "wordquiz", "icon": "🏆", + "name_pl": "Mózg", "name_ru": "Мозг", "name_uk": "Мозок", "name_en": "Brain", + "desc_pl": "Odgadnij 100 słów w Quiz słownym", "desc_ru": "Угадать 100 слов в Квизе слов", "desc_uk": "Відгадати 100 слів у Квізі слів", "desc_en": "Guess 100 words in Word Quiz", + "type": "quiz_guessed", "value": 100}, + + {"code": "quiz_perfect_10", "category": "wordquiz", "icon": "💎", + "name_pl": "Idealny wynik", "name_ru": "Идеальный результат", "name_uk": "Ідеальний результат", "name_en": "Perfect Score", + "desc_pl": "Odgadnij 10 słów bez pomyłki", "desc_ru": "Угадать 10 слов без ошибок", "desc_uk": "Відгадати 10 слів без помилок", "desc_en": "Guess 10 words without mistakes", + "type": "quiz_perfect_streak", "value": 10}, + + {"code": "quiz_streak_20", "category": "wordquiz", "icon": "🔥", + "name_pl": "Niepowstrzymany", "name_ru": "Неудержимый", "name_uk": "Невтримний", "name_en": "Unstoppable", + "desc_pl": "Odgadnij 20 słów z rzędu", "desc_ru": "Угадать 20 слов подряд", "desc_uk": "Відгадати 20 слів поспіль", "desc_en": "Guess 20 words in a row", + "type": "quiz_perfect_streak", "value": 20}, + + {"code": "quiz_speed", "category": "wordquiz", "icon": "⚡", + "name_pl": "Błyskawica", "name_ru": "Молния", "name_uk": "Блискавка", "name_en": "Lightning", + "desc_pl": "Odgadnij słowo w mniej niż 3 sekundy", "desc_ru": "Угадать слово быстрее 3 секунд", "desc_uk": "Відгадати слово швидше 3 секунд", "desc_en": "Guess a word in under 3 seconds", + "type": "quiz_speed", "value": 3}, + + {"code": "quiz_speed_2", "category": "wordquiz", "icon": "🚀", + "name_pl": "Super szybki", "name_ru": "Супер быстрый", "name_uk": "Супер швидкий", "name_en": "Super Fast", + "desc_pl": "Odgadnij słowo w mniej niż 2 sekundy", "desc_ru": "Угадать слово быстрее 2 секунд", "desc_uk": "Відгадати слово швидше 2 секунд", "desc_en": "Guess a word in under 2 seconds", + "type": "quiz_speed", "value": 2}, + + {"code": "quiz_no_mistakes", "category": "wordquiz", "icon": "🏆", + "name_pl": "Bezbłędny", "name_ru": "Безошибочный", "name_uk": "Безпомилковий", "name_en": "Flawless", + "desc_pl": "Odgadnij słowo bez żadnej pomyłki", "desc_ru": "Угадать слово без единой ошибки", "desc_uk": "Відгадати слово без жодної помилки", "desc_en": "Guess a word without any mistakes", + "type": "quiz_no_mistakes", "value": 1}, + + # ===== Bubble Words (8) ===== + {"code": "bubble_5", "category": "bubblewords", "icon": "🫧", + "name_pl": "Początkujący", "name_ru": "Начинающий", "name_uk": "Початківець", "name_en": "Beginner", + "desc_pl": "Ukończ 5 poziomów w Bąbelkach słów", "desc_ru": "Пройти 5 уровней в Пузырях слов", "desc_uk": "Пройти 5 рівнів у Бульбашках слів", "desc_en": "Complete 5 levels in Bubble Words", + "type": "bubble_levels", "value": 5}, + + {"code": "bubble_25", "category": "bubblewords", "icon": "🌟", + "name_pl": "Bąbelkowy mistrz", "name_ru": "Пузырьковый мастер", "name_uk": "Бульбашковий майстер", "name_en": "Bubble Master", + "desc_pl": "Ukończ 25 poziomów w Bąbelkach słów", "desc_ru": "Пройти 25 уровней в Пузырях слов", "desc_uk": "Пройти 25 рівнів у Бульбашках слів", "desc_en": "Complete 25 levels in Bubble Words", + "type": "bubble_levels", "value": 25}, + + {"code": "bubble_50", "category": "bubblewords", "icon": "💪", + "name_pl": "Bańkowy wojownik", "name_ru": "Пузырьковый воин", "name_uk": "Бульбашковий воїн", "name_en": "Bubble Warrior", + "desc_pl": "Ukończ 50 poziomów w Bąbelkach słów", "desc_ru": "Пройти 50 уровней в Пузырях слов", "desc_uk": "Пройти 50 рівнів у Бульбашках слів", "desc_en": "Complete 50 levels in Bubble Words", + "type": "bubble_levels", "value": 50}, + + {"code": "bubble_100", "category": "bubblewords", "icon": "👑", + "name_pl": "Król bąbelków", "name_ru": "Король пузырей", "name_uk": "Король бульбашок", "name_en": "Bubble King", + "desc_pl": "Ukończ 100 poziomów w Bąbelkach słów", "desc_ru": "Пройти 100 уровней в Пузырях слов", "desc_uk": "Пройти 100 рівнів у Бульбашках слів", "desc_en": "Complete 100 levels in Bubble Words", + "type": "bubble_levels", "value": 100}, + + {"code": "bubble_no_hints", "category": "bubblewords", "icon": "💡", + "name_pl": "Samodzielny", "name_ru": "Самостоятельный", "name_uk": "Самостійний", "name_en": "Independent", + "desc_pl": "Ukończ poziom bez podpowiedzi", "desc_ru": "Пройти уровень без подсказок", "desc_uk": "Пройти рівень без підказок", "desc_en": "Complete a level without hints", + "type": "bubble_no_hints", "value": 1}, + + {"code": "bubble_perfect", "category": "bubblewords", "icon": "✨", + "name_pl": "Perfekcyjny", "name_ru": "Идеальный", "name_uk": "Ідеальний", "name_en": "Perfect", + "desc_pl": "Ukończ poziom z maksymalną punktacją (100)", "desc_ru": "Пройти уровень с максимальным счётом (100)", "desc_uk": "Пройти рівень з максимальним рахунком (100)", "desc_en": "Complete a level with maximum score (100)", + "type": "bubble_perfect", "value": 1}, + + {"code": "bubble_speed", "category": "bubblewords", "icon": "🚀", + "name_pl": "Szybki bańki", "name_ru": "Быстрые пузыри", "name_uk": "Швидкі бульбашки", "name_en": "Fast Bubbles", + "desc_pl": "Ukończ poziom w mniej niż 45 sekund", "desc_ru": "Пройти уровень быстрее 45 секунд", "desc_uk": "Пройти рівень швидше 45 секунд", "desc_en": "Complete a level in under 45 seconds", + "type": "bubble_speed", "value": 45}, + + {"code": "bubble_speed_30", "category": "bubblewords", "icon": "⚡", + "name_pl": "Bąbelkowa błyskawica", "name_ru": "Пузырьковая молния", "name_uk": "Бульбашкова блискавка", "name_en": "Bubble Lightning", + "desc_pl": "Ukończ poziom w mniej niż 30 sekund", "desc_ru": "Пройти уровень быстрее 30 секунд", "desc_uk": "Пройти рівень швидше 30 секунд", "desc_en": "Complete a level in under 30 seconds", + "type": "bubble_speed", "value": 30}, + + # ===== General (15) ===== + {"code": "score_1000", "category": "general", "icon": "🌟", + "name_pl": "Wschodząca gwiazda", "name_ru": "Восходящая звезда", "name_uk": "Висхідна зірка", "name_en": "Rising Star", + "desc_pl": "Zdobądź 1000 punktów", "desc_ru": "Набрать 1000 очков", "desc_uk": "Набрати 1000 балів", "desc_en": "Earn 1000 points", + "type": "total_score", "value": 1000}, + + {"code": "score_5000", "category": "general", "icon": "💎", + "name_pl": "Diament", "name_ru": "Бриллиант", "name_uk": "Діамант", "name_en": "Diamond", + "desc_pl": "Zdobądź 5000 punktów", "desc_ru": "Набрать 5000 очков", "desc_uk": "Набрати 5000 балів", "desc_en": "Earn 5000 points", + "type": "total_score", "value": 5000}, + + {"code": "score_10000", "category": "general", "icon": "💯", + "name_pl": "Legenda", "name_ru": "Легенда", "name_uk": "Легенда", "name_en": "Legend", + "desc_pl": "Zdobądź 10000 punktów", "desc_ru": "Набрать 10000 очков", "desc_uk": "Набрати 10000 балів", "desc_en": "Earn 10000 points", + "type": "total_score", "value": 10000}, + + {"code": "score_25000", "category": "general", "icon": "🦄", + "name_pl": "Jednorożec", "name_ru": "Единорог", "name_uk": "Єдиноріг", "name_en": "Unicorn", + "desc_pl": "Zdobądź 25000 punktów", "desc_ru": "Набрать 25000 очков", "desc_uk": "Набрати 25000 балів", "desc_en": "Earn 25000 points", + "type": "total_score", "value": 25000}, + + {"code": "rank_1", "category": "general", "icon": "🏆", + "name_pl": "Mistrz", "name_ru": "Чемпион", "name_uk": "Чемпіон", "name_en": "Champion", + "desc_pl": "Zajmij 1 miejsce w rankingu", "desc_ru": "Занять 1 место в рейтинге", "desc_uk": "Зайняти 1 місце в рейтингу", "desc_en": "Reach 1st place on leaderboard", + "type": "rank_reached", "value": 1}, + + {"code": "rank_top3", "category": "general", "icon": "🥇", + "name_pl": "Medalista", "name_ru": "Призёр", "name_uk": "Призер", "name_en": "Medalist", + "desc_pl": "Zajmij miejsce w top 3", "desc_ru": "Попасть в топ-3 рейтинга", "desc_uk": "Потрапити в топ-3 рейтингу", "desc_en": "Reach top 3 on leaderboard", + "type": "rank_reached", "value": 3}, + + {"code": "login_3", "category": "general", "icon": "📊", + "name_pl": "Stały gracz", "name_ru": "Постоянный игрок", "name_uk": "Постійний гравець", "name_en": "Regular Player", + "desc_pl": "Zaloguj się 3 dni z rzędu", "desc_ru": "Заходить 3 дня подряд", "desc_uk": "Заходити 3 дні поспіль", "desc_en": "Log in 3 days in a row", + "type": "login_streak", "value": 3}, + + {"code": "login_7", "category": "general", "icon": "🔥", + "name_pl": "Tygodniowa seria", "name_ru": "Недельная серия", "name_uk": "Тижнева серія", "name_en": "Weekly Streak", + "desc_pl": "Zaloguj się 7 dni z rzędu", "desc_ru": "Заходить 7 дней подряд", "desc_uk": "Заходити 7 днів поспіль", "desc_en": "Log in 7 days in a row", + "type": "login_streak", "value": 7}, + + {"code": "change_language", "category": "general", "icon": "🌍", + "name_pl": "Poliglota", "name_ru": "Полиглот", "name_uk": "Поліглот", "name_en": "Polyglot", + "desc_pl": "Zmień język interfejsu", "desc_ru": "Сменить язык интерфейса", "desc_uk": "Змінити мову інтерфейсу", "desc_en": "Change interface language", + "type": "language_changed", "value": 1}, + + # 🔧 ИСПРАВЛЕНО: Заменено достижение "Открой Грамматику" на "Открой меню учителя" + {"code": "open_teacher_menu", "category": "general", "icon": "🎓", + "name_pl": "Uczeń", "name_ru": "Ученик", "name_uk": "Учень", "name_en": "Student", + "desc_pl": "Otwórz menu nauczyciela", "desc_ru": "Открыть меню учителя", "desc_uk": "Відкрити меню вчителя", "desc_en": "Open the teacher menu", + "type": "teacher_menu_opened", "value": 1}, + + {"code": "open_cheatsheets", "category": "general", "icon": "📝", + "name_pl": "Ciekawski", "name_ru": "Любознательный", "name_uk": "Допитливий", "name_en": "Curious", + "desc_pl": "Otwórz sekcję Ściągi", "desc_ru": "Открыть раздел Шпаргалки", "desc_uk": "Відкрити розділ Шпаргалки", "desc_en": "Open the Cheatsheets section", + "type": "cheatsheets_opened", "value": 1}, + + {"code": "open_pronunciation", "category": "general", "icon": "🔊", + "name_pl": "Słuchacz", "name_ru": "Слушатель", "name_uk": "Слухач", "name_en": "Listener", + "desc_pl": "Otwórz sekcję Wymowa", "desc_ru": "Открыть раздел Произношение", "desc_uk": "Відкрити розділ Вимова", "desc_en": "Open the Pronunciation section", + "type": "pronunciation_opened", "value": 1}, + + {"code": "open_ai_assistant", "category": "general", "icon": "🤖", + "name_pl": "Asystent AI", "name_ru": "AI-помощник", "name_uk": "AI-помічник", "name_en": "AI Assistant", + "desc_pl": "Otwórz Asystenta AI", "desc_ru": "Открыть AI-помощника", "desc_uk": "Відкрити AI-помічника", "desc_en": "Open the AI Assistant", + "type": "ai_assistant_opened", "value": 1}, + + {"code": "open_alphabet", "category": "general", "icon": "🔤", + "name_pl": "Alfabetysta", "name_ru": "Алфавитист", "name_uk": "Алфавітист", "name_en": "Alphabetist", + "desc_pl": "Otwórz sekcję Alfabet", "desc_ru": "Открыть раздел Алфавит", "desc_uk": "Відкрити розділ Алфавіт", "desc_en": "Open the Alphabet section", + "type": "alphabet_opened", "value": 1}, + + {"code": "open_rules", "category": "general", "icon": "📐", + "name_pl": "Gramatyk", "name_ru": "Грамматик", "name_uk": "Граматик", "name_en": "Grammarian", + "desc_pl": "Otwórz sekcję Zasady", "desc_ru": "Открыть раздел Правила", "desc_uk": "Відкрити розділ Правила", "desc_en": "Open the Rules section", + "type": "rules_opened", "value": 1}, + + # 🔧 НОВОЕ: Достижение за открытие Прогресса + {"code": "open_progress", "category": "general", "icon": "📊", + "name_pl": "Planista", "name_ru": "Планировщик", "name_uk": "Планувальник", "name_en": "Planner", + "desc_pl": "Otwórz sekcję Postęp", "desc_ru": "Открыть раздел Прогресс", "desc_uk": "Відкрити розділ Прогрес", "desc_en": "Open the Progress section", + "type": "progress_opened", "value": 1}, +] + + +async def init_achievements(): + """Добавляет новые достижения, не трогая существующие""" + pool = await get_pool() + async with pool.acquire() as conn: + for a in ACHIEVEMENTS_DATA: + exists = await conn.fetchval( + "SELECT 1 FROM achievements WHERE code = $1", a["code"] + ) + if not exists: + await conn.execute( + """INSERT INTO achievements (code, category, icon, + name_pl, name_ru, name_uk, name_en, + description_pl, description_ru, description_uk, description_en, + requirement_type, requirement_value) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)""", + a["code"], a["category"], a["icon"], + a["name_pl"], a["name_ru"], a["name_uk"], a["name_en"], + a["desc_pl"], a["desc_ru"], a["desc_uk"], a["desc_en"], + a["type"], a["value"] + ) + else: + # 🔧 НОВОЕ: Обновляем существующие достижения (на случай изменения названий) + await conn.execute(""" + UPDATE achievements SET + category = $2, + icon = $3, + name_pl = $4, + name_ru = $5, + name_uk = $6, + name_en = $7, + description_pl = $8, + description_ru = $9, + description_uk = $10, + description_en = $11, + requirement_type = $12, + requirement_value = $13 + WHERE code = $1 + """, a["code"], a["category"], a["icon"], + a["name_pl"], a["name_ru"], a["name_uk"], a["name_en"], + a["desc_pl"], a["desc_ru"], a["desc_uk"], a["desc_en"], + a["type"], a["value"]) + + +@router.get("") +async def get_all_achievements(request: Request): + """Получить все достижения""" + await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch("SELECT * FROM achievements ORDER BY id") + + return { + "achievements": [dict(row) for row in rows] + } + + +@router.get("/user") +async def get_user_achievements(request: Request): + """Получить достижения пользователя""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch(""" + SELECT a.*, + CASE WHEN ua.user_id IS NOT NULL THEN TRUE ELSE FALSE END as unlocked, + ua.unlocked_at + FROM achievements a + LEFT JOIN user_achievements ua ON a.id = ua.achievement_id AND ua.user_id = $1 + ORDER BY a.id + """, telegram_id) + + achievements = [] + for row in rows: + a = dict(row) + if a.get("unlocked_at"): + a["unlocked_at"] = a["unlocked_at"].isoformat() + achievements.append(a) + + total = len(achievements) + unlocked = sum(1 for a in achievements if a["unlocked"]) + + return { + "achievements": achievements, + "total": total, + "unlocked": unlocked, + "progress_percent": round((unlocked / total * 100), 1) if total > 0 else 0 + } + + +async def check_and_award_achievements(telegram_id: int, achievement_type: str, value: int = 1): + """ + Проверяет и выдаёт достижения пользователю. + Возвращает названия на языке пользователя. + """ + pool = await get_pool() + async with pool.acquire() as conn: + user_lang = await conn.fetchval( + "SELECT app_language FROM users WHERE telegram_id = $1", telegram_id + ) + if not user_lang or user_lang not in ["pl", "ru", "uk", "en"]: + user_lang = "pl" + + matching = await conn.fetch(""" + SELECT a.* FROM achievements a + WHERE a.requirement_type = $1 + AND a.requirement_value <= $2 + AND a.id NOT IN ( + SELECT achievement_id FROM user_achievements WHERE user_id = $3 + ) + """, achievement_type, value, telegram_id) + + newly_unlocked = [] + name_field = f"name_{user_lang}" + + for ach in matching: + await conn.execute( + "INSERT INTO user_achievements (user_id, achievement_id) VALUES ($1, $2) ON CONFLICT DO NOTHING", + telegram_id, ach["id"] + ) + newly_unlocked.append({ + "id": ach["id"], + "code": ach["code"], + "icon": ach["icon"], + "name": ach[name_field], + }) + + return newly_unlocked + + +@router.post("/track-login") +async def track_login(request: Request): + """Отмечает ежедневный вход пользователя и проверяет достижения серии""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + await conn.execute( + "INSERT INTO daily_logins (user_id, login_date) VALUES ($1, CURRENT_DATE) ON CONFLICT DO NOTHING", + telegram_id + ) + + streak = await conn.fetchval(""" + WITH dates AS ( + SELECT login_date, + login_date - ROW_NUMBER() OVER (ORDER BY login_date DESC)::int AS grp + FROM daily_logins + WHERE user_id = $1 + ORDER BY login_date DESC + ) + SELECT COUNT(*) FROM dates WHERE grp = (SELECT grp FROM dates LIMIT 1) + """, telegram_id) + + streak = streak or 0 + + new_achievements = await check_and_award_achievements(telegram_id, "login_streak", streak) + + return { + "login_streak": streak, + "new_achievements": new_achievements + } + + +# 🔧 НОВОЕ: Трекинг открытия меню учителя +@router.post("/track-teacher-menu") +async def track_teacher_menu_opened(request: Request): + """Отмечает открытие меню учителя и выдаёт достижение""" + telegram_id, _ = await require_auth(request) + + new_achievements = await check_and_award_achievements(telegram_id, "teacher_menu_opened", 1) + + return { + "new_achievements": new_achievements + } + + +# 🔧 НОВОЕ: Трекинг открытия Прогресса +@router.post("/track-progress") +async def track_progress_opened(request: Request): + """Отмечает открытие раздела Прогресс и выдаёт достижение""" + telegram_id, _ = await require_auth(request) + + new_achievements = await check_and_award_achievements(telegram_id, "progress_opened", 1) + + return { + "new_achievements": new_achievements + } + + +@router.post("/track-cheatsheets") +async def track_cheatsheets_opened(request: Request): + """Отмечает открытие раздела Шпаргалки и выдаёт достижение""" + telegram_id, _ = await require_auth(request) + + new_achievements = await check_and_award_achievements(telegram_id, "cheatsheets_opened", 1) + + return { + "new_achievements": new_achievements + } + + +@router.post("/track-pronunciation") +async def track_pronunciation_opened(request: Request): + """Отмечает открытие раздела Произношение и выдаёт достижение""" + telegram_id, _ = await require_auth(request) + + new_achievements = await check_and_award_achievements(telegram_id, "pronunciation_opened", 1) + + return { + "new_achievements": new_achievements + } + + +@router.post("/track-ai-assistant") +async def track_ai_assistant_opened(request: Request): + """Отмечает открытие AI-помощника и выдаёт достижение""" + telegram_id, _ = await require_auth(request) + + new_achievements = await check_and_award_achievements(telegram_id, "ai_assistant_opened", 1) + + return { + "new_achievements": new_achievements + } + + +@router.post("/track-alphabet") +async def track_alphabet_opened(request: Request): + """Отмечает открытие раздела Алфавит и выдаёт достижение""" + telegram_id, _ = await require_auth(request) + + new_achievements = await check_and_award_achievements(telegram_id, "alphabet_opened", 1) + + return { + "new_achievements": new_achievements + } + + +@router.post("/track-rules") +async def track_rules_opened(request: Request): + """Отмечает открытие раздела Правила и выдаёт достижение""" + telegram_id, _ = await require_auth(request) + + new_achievements = await check_and_award_achievements(telegram_id, "rules_opened", 1) + + return { + "new_achievements": new_achievements + } \ No newline at end of file diff --git a/routers/admin.py b/routers/admin.py new file mode 100644 index 0000000..6560eda --- /dev/null +++ b/routers/admin.py @@ -0,0 +1,148 @@ +""" +Admin Router — админ-панель с реальной статистикой проекта. +1. /admin/dashboard — общая статистика (юзеры, онлайн, по уровням) +2. /admin/sentry-errors — ошибки из Sentry (через API) +""" +import os +import logging +import httpx +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool +from config import ADMIN_IDS + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/admin", tags=["admin"]) + +# ============ Настройки Sentry ============ +SENTRY_AUTH_TOKEN = os.getenv("SENTRY_AUTH_TOKEN", "") +SENTRY_ORG_SLUG = os.getenv("SENTRY_ORG_SLUG", "drobysh") +SENTRY_PROJECT_SLUG = os.getenv("SENTRY_PROJECT_SLUG", "filwords-backend") +SENTRY_API_BASE = os.getenv("SENTRY_API_BASE", "https://de.sentry.io/api/0") + + +def _require_admin(telegram_id: int): + """Проверка, что пользователь — админ.""" + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + +@router.get("/dashboard") +async def get_admin_dashboard(request: Request): + """ + Общая статистика проекта: + - Всего пользователей / новых сегодня / онлайн + - Активных за 24 часа + - Распределение по уровням языка + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + # Всего пользователей + total_users = await conn.fetchval("SELECT COUNT(*) FROM users") or 0 + + # Новых сегодня + new_today = await conn.fetchval( + "SELECT COUNT(*) FROM users WHERE created_at::date = CURRENT_DATE" + ) or 0 + + # Онлайн за последние 30 минут + online_now = await conn.fetchval(""" + SELECT COUNT(DISTINCT user_id) FROM ( + SELECT user_id FROM user_progress WHERE completed_at > NOW() - INTERVAL '30 minutes' + UNION + SELECT user_id FROM sentence_progress WHERE completed_at > NOW() - INTERVAL '30 minutes' + UNION + SELECT user_id FROM daily_logins WHERE login_date = CURRENT_DATE + ) active + """) or 0 + + # Активных за 24 часа + active_24h = await conn.fetchval(""" + SELECT COUNT(DISTINCT user_id) FROM ( + SELECT user_id FROM user_progress WHERE completed_at > NOW() - INTERVAL '24 hours' + UNION + SELECT user_id FROM sentence_progress WHERE completed_at > NOW() - INTERVAL '24 hours' + UNION + SELECT user_id FROM user_learning_answers WHERE created_at > NOW() - INTERVAL '24 hours' + UNION + SELECT user_id FROM daily_logins WHERE login_date = CURRENT_DATE + ) active + """) or 0 + + # Распределение по уровням + level_counts = {} + for lvl in ["A1", "A2", "B1", "B2", "C1", "C2"]: + count = await conn.fetchval( + "SELECT COUNT(*) FROM users WHERE current_level = $1", lvl + ) or 0 + level_counts[lvl] = count + + return { + "total_users": total_users, + "new_today": new_today, + "online_now": online_now, + "active_24h": active_24h, + "level_counts": level_counts, + } + + +@router.get("/sentry-errors") +async def get_sentry_errors(request: Request): + """ + Последние ошибки из Sentry. + Возвращает только unresolved (нерешённые) за последние 24 часа. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + if not SENTRY_AUTH_TOKEN: + return {"errors": [], "error": "SENTRY_AUTH_TOKEN not configured"} + + url = f"{SENTRY_API_BASE}/projects/{SENTRY_ORG_SLUG}/{SENTRY_PROJECT_SLUG}/issues/" + params = { + "query": "is:unresolved", + "statsPeriod": "24h", + "limit": 20, + } + headers = { + "Authorization": f"Bearer {SENTRY_AUTH_TOKEN}", + } + + try: + async with httpx.AsyncClient(timeout=10.0) as client: + response = await client.get(url, params=params, headers=headers) + + if response.status_code != 200: + logger.error(f"Sentry API error: {response.status_code} — {response.text[:200]}") + return {"errors": [], "error": f"Sentry API: {response.status_code}"} + + raw_issues = response.json() + + errors = [] + for issue in raw_issues: + errors.append({ + "id": issue.get("id"), + "short_id": issue.get("shortId"), + "title": issue.get("title"), + "culprit": issue.get("culprit"), + "level": issue.get("level"), + "count": int(issue.get("count", 0)), + "user_count": issue.get("userCount", 0), + "first_seen": issue.get("firstSeen"), + "last_seen": issue.get("lastSeen"), + "permalink": issue.get("permalink"), + "priority": issue.get("priority"), + }) + + return {"errors": errors, "count": len(errors)} + + except httpx.TimeoutException: + logger.error("Sentry API timeout") + return {"errors": [], "error": "Sentry API timeout"} + except Exception as e: + logger.error(f"Sentry API unexpected error: {e}") + return {"errors": [], "error": str(e)} \ No newline at end of file diff --git a/routers/admin_content.py b/routers/admin_content.py new file mode 100644 index 0000000..acab249 --- /dev/null +++ b/routers/admin_content.py @@ -0,0 +1,1213 @@ +""" +Admin Content Router — контент-менеджер для редактирования уроков, слов и текстов. + +Доступ: только для ADMIN_IDS. +Логика: препод (ты) правит контент через дашборд, без захода в код. + +Разделы: +- GET /admin/content/summary — сводка по уровням +- GET /admin/content/words/levels — уровни слов (счётчики) +- GET /admin/content/words/level/{level} — список слов уровня +- GET /admin/content/words/word/{word_id} — одно слово +- PUT /admin/content/words/word/{word_id} — обновить слово +- POST /admin/content/words/level/{level} — добавить слово +- GET /admin/content/texts/levels — уровни текстов +- GET /admin/content/texts/level/{level} — список текстов +- GET /admin/content/texts/text/{text_id} — один текст +- PUT /admin/content/texts/text/{text_id} — обновить текст +- POST /admin/content/texts/level/{level} — добавить текст +- GET /admin/content/lessons/levels — уровни уроков (счётчики тем) +- GET /admin/content/lessons/level/{level}/topics — темы уровня +- GET /admin/content/lessons/topic/{topic_id} — тема + уроки + тест +- GET /admin/content/lessons/lesson/{lesson_id} — урок целиком (WYSIWYG) +- PUT /admin/content/lessons/lesson/{lesson_id} — сохранить урок (Вариант B) +- GET /admin/content/wrong-because — справочник wrong_because + +🔧 ФИКС (19.09.2026): в words-эндпоинтах фильтруем только строки с level_id IS NULL. +Причина: в level_words хранятся ДВЕ категории строк: + 1. Слова уровня для Word Quiz / Bubble Words → level_id IS NULL. + 2. Привязки слов к игровым уровням Филвордов → level_id != NULL. +В дашборде преподу нужны только "чистые" слова уровня (level_id IS NULL). +Строки с level_id != NULL используются игрой и остаются нетронутыми. +При обновлении слова (PUT) — обновляем ВСЕ строки с этим (level, word_pl), +чтобы Филворды получили актуальный перевод. + +🔧 НОВОЕ (19.09.2026, вечер): раздел «Уроки» — 6 эндпоинтов для LessonsEditor. +- Уровни → Темы → Уроки (иерархия как в словах/текстах). +- WYSIWYG-модалка редактирует: title, objective, explanation, examples, questions, options. +- Сохранение урока целиком (Вариант B) — одна транзакция. +- option_key генерируется бэкендом: A, B, C, D... по порядку массива. +- correct_answer в learning_questions = option_key того варианта, где is_correct=true. +- test_order пересчитывается 1..N по порядку для теста темы (is_test_question=TRUE). +- level_code НЕ трогаем — он вычисляется через topic_id → learning_topics.level_code. +""" +import logging +import re +from typing import Optional + +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool +from config import ADMIN_IDS + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/admin/content", tags=["admin-content"]) + +LEVELS = ["A1", "A2", "B1", "B2", "C1", "C2"] + + +def _require_admin(telegram_id: int) -> None: + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + +# ============ SUMMARY ============ + +@router.get("/summary") +async def get_content_summary(request: Request): + """ + Сводка по всем уровням: темы, уроки, слова, тексты, последняя правка. + Слова считаются только level_id IS NULL (чистые слова уровня). + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + level_rows = await conn.fetch(""" + SELECT code, name_ru, sort_order + FROM learning_levels + WHERE is_active = TRUE + ORDER BY sort_order + """) + + result = [] + for lvl in level_rows: + code = lvl["code"] + + topics_total = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_topics WHERE level_code = $1 + """, code) or 0 + + lessons_total = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_lessons l + JOIN learning_topics t ON l.topic_id = t.topic_id + WHERE t.level_code = $1 + """, code) or 0 + + # 🔧 ФИКС: только level_id IS NULL + words_total = await conn.fetchval(""" + SELECT COUNT(*) FROM level_words WHERE level = $1 AND level_id IS NULL + """, code) or 0 + + texts_total = await conn.fetchval(""" + SELECT COUNT(*) FROM sentences WHERE level = $1 + """, code) or 0 + + last_edited = await conn.fetchval(""" + SELECT MAX(edited_at) FROM ( + SELECT edited_at FROM learning_topics WHERE level_code = $1 + UNION ALL + SELECT l.edited_at FROM learning_lessons l + JOIN learning_topics t ON l.topic_id = t.topic_id + WHERE t.level_code = $1 + UNION ALL + SELECT edited_at FROM level_words WHERE level = $1 AND level_id IS NULL + UNION ALL + SELECT edited_at FROM sentences WHERE level = $1 + ) sub + """, code) + + result.append({ + "code": code, + "name_ru": lvl["name_ru"], + "topics_total": topics_total, + "lessons_total": lessons_total, + "words_total": words_total, + "texts_total": texts_total, + "last_edited": last_edited.isoformat() if last_edited else None, + }) + + return {"levels": result} + + +# ============ WORDS ============ + +@router.get("/words/levels") +async def get_word_levels(request: Request): + """Уровни A1–C2 с количеством слов (только level_id IS NULL).""" + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + level_rows = await conn.fetch(""" + SELECT code, name_ru, sort_order + FROM learning_levels + WHERE is_active = TRUE + ORDER BY sort_order + """) + + result = [] + for lvl in level_rows: + code = lvl["code"] + # 🔧 ФИКС: только level_id IS NULL + count = await conn.fetchval( + "SELECT COUNT(*) FROM level_words WHERE level = $1 AND level_id IS NULL", code + ) or 0 + last_edited = await conn.fetchval( + "SELECT MAX(edited_at) FROM level_words WHERE level = $1 AND level_id IS NULL", code + ) + result.append({ + "code": code, + "name_ru": lvl["name_ru"], + "words_count": count, + "last_edited": last_edited.isoformat() if last_edited else None, + }) + + return {"levels": result} + + +@router.get("/words/level/{level}") +async def get_level_words( + request: Request, + level: str, + q: Optional[str] = None, + limit: int = 1000, +): + """ + Список слов уровня — только строки с level_id IS NULL. + Поиск по word_pl / translation_ru / translation_uk / translation_en. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + if level not in LEVELS: + raise HTTPException(400, f"Invalid level: {level}") + + if limit < 1: + limit = 1 + elif limit > 2000: + limit = 2000 + + pool = await get_pool() + async with pool.acquire() as conn: + if q and q.strip(): + pattern = f"%{q.strip()}%" + rows = await conn.fetch(""" + SELECT id, word_pl, translation_ru, translation_uk, translation_en, + edited_at + FROM level_words + WHERE level = $1 + AND level_id IS NULL + AND ( + word_pl ILIKE $2 + OR translation_ru ILIKE $2 + OR translation_uk ILIKE $2 + OR translation_en ILIKE $2 + ) + ORDER BY word_pl ASC + LIMIT $3 + """, level, pattern, limit) + else: + rows = await conn.fetch(""" + SELECT id, word_pl, translation_ru, translation_uk, translation_en, + edited_at + FROM level_words + WHERE level = $1 + AND level_id IS NULL + ORDER BY word_pl ASC + LIMIT $2 + """, level, limit) + + return { + "level": level, + "count": len(rows), + "words": [ + { + "id": r["id"], + "word_pl": r["word_pl"], + "translation_ru": r["translation_ru"] or "", + "translation_uk": r["translation_uk"] or "", + "translation_en": r["translation_en"] or "", + "edited_at": r["edited_at"].isoformat() if r["edited_at"] else None, + } + for r in rows + ], + } + + +@router.get("/words/word/{word_id}") +async def get_word(request: Request, word_id: int): + """Одно слово по id.""" + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + row = await conn.fetchrow(""" + SELECT id, word_pl, translation_ru, translation_uk, translation_en, level, edited_at + FROM level_words WHERE id = $1 + """, word_id) + + if not row: + raise HTTPException(404, "Word not found") + + return { + "id": row["id"], + "word_pl": row["word_pl"], + "translation_ru": row["translation_ru"] or "", + "translation_uk": row["translation_uk"] or "", + "translation_en": row["translation_en"] or "", + "level": row["level"], + "edited_at": row["edited_at"].isoformat() if row["edited_at"] else None, + } + + +@router.put("/words/word/{word_id}") +async def update_word(request: Request, word_id: int): + """ + Обновить слово. + Обновляем ВСЕ строки с этим (level, word_pl) — включая привязки к игровым + уровням Филвордов (level_id != NULL), чтобы игра получила новый перевод. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + body = await request.json() + word_pl = (body.get("word_pl") or "").strip() + translation_ru = (body.get("translation_ru") or "").strip() + translation_uk = (body.get("translation_uk") or "").strip() + translation_en = (body.get("translation_en") or "").strip() + + if not word_pl: + raise HTTPException(400, "word_pl is required") + + pool = await get_pool() + async with pool.acquire() as conn: + existing = await conn.fetchrow(""" + SELECT level, word_pl FROM level_words WHERE id = $1 + """, word_id) + + if not existing: + raise HTTPException(404, "Word not found") + + old_word_pl = existing["word_pl"] + level = existing["level"] + + # 🔧 ФИКС: обновляем все строки с этим (level, old_word_pl) + result = await conn.execute(""" + UPDATE level_words + SET word_pl = $1, + translation_ru = $2, + translation_uk = $3, + translation_en = $4, + edited_at = NOW() + WHERE level = $5 AND word_pl = $6 + """, word_pl, translation_ru, translation_uk, translation_en, level, old_word_pl) + + affected = int(result.split()[-1]) + + logger.info( + f"[admin_content] word '{old_word_pl}' -> '{word_pl}' in {level}: " + f"{affected} rows updated by admin {telegram_id}" + ) + + return {"status": "ok", "word_id": word_id, "rows_updated": affected} + + +@router.post("/words/level/{level}") +async def create_word(request: Request, level: str): + """Добавить слово в уровень (level_id = NULL).""" + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + if level not in LEVELS: + raise HTTPException(400, f"Invalid level: {level}") + + body = await request.json() + word_pl = (body.get("word_pl") or "").strip() + translation_ru = (body.get("translation_ru") or "").strip() + translation_uk = (body.get("translation_uk") or "").strip() + translation_en = (body.get("translation_en") or "").strip() + + if not word_pl: + raise HTTPException(400, "word_pl is required") + + pool = await get_pool() + async with pool.acquire() as conn: + existing = await conn.fetchval(""" + SELECT id FROM level_words + WHERE level = $1 AND level_id IS NULL AND LOWER(word_pl) = LOWER($2) + """, level, word_pl) + if existing: + raise HTTPException(409, f"Word '{word_pl}' already exists in {level}") + + row = await conn.fetchrow(""" + INSERT INTO level_words + (level_id, word_pl, translation_ru, translation_uk, translation_en, level, edited_at) + VALUES (NULL, $1, $2, $3, $4, $5, NOW()) + RETURNING id + """, word_pl, translation_ru, translation_uk, translation_en, level) + + logger.info( + f"[admin_content] word created: #{row['id']} '{word_pl}' in {level} " + f"by admin {telegram_id}" + ) + + return {"status": "ok", "word_id": row["id"]} + + +# ============ TEXTS (sentences) ============ + +@router.get("/texts/levels") +async def get_text_levels(request: Request): + """Уровни A1–C2 с количеством текстов и последней правкой.""" + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + level_rows = await conn.fetch(""" + SELECT code, name_ru, sort_order + FROM learning_levels + WHERE is_active = TRUE + ORDER BY sort_order + """) + + result = [] + for lvl in level_rows: + code = lvl["code"] + count = await conn.fetchval( + "SELECT COUNT(*) FROM sentences WHERE level = $1", code + ) or 0 + last_edited = await conn.fetchval( + "SELECT MAX(edited_at) FROM sentences WHERE level = $1", code + ) + result.append({ + "code": code, + "name_ru": lvl["name_ru"], + "texts_count": count, + "last_edited": last_edited.isoformat() if last_edited else None, + }) + + return {"levels": result} + + +@router.get("/texts/level/{level}") +async def get_level_texts( + request: Request, + level: str, + q: Optional[str] = None, + limit: int = 1000, +): + """Список текстов уровня с опциональным поиском.""" + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + if level not in LEVELS: + raise HTTPException(400, f"Invalid level: {level}") + + if limit < 1: + limit = 1 + elif limit > 2000: + limit = 2000 + + pool = await get_pool() + async with pool.acquire() as conn: + if q and q.strip(): + pattern = f"%{q.strip()}%" + rows = await conn.fetch(""" + SELECT id, sentence_number, sentence_pl, + translation_ru, translation_uk, translation_en, + difficulty, edited_at + FROM sentences + WHERE level = $1 + AND ( + sentence_pl ILIKE $2 + OR translation_ru ILIKE $2 + OR translation_uk ILIKE $2 + OR translation_en ILIKE $2 + ) + ORDER BY sentence_number ASC + LIMIT $3 + """, level, pattern, limit) + else: + rows = await conn.fetch(""" + SELECT id, sentence_number, sentence_pl, + translation_ru, translation_uk, translation_en, + difficulty, edited_at + FROM sentences + WHERE level = $1 + ORDER BY sentence_number ASC + LIMIT $2 + """, level, limit) + + return { + "level": level, + "count": len(rows), + "texts": [ + { + "id": r["id"], + "sentence_number": r["sentence_number"], + "sentence_pl": r["sentence_pl"], + "translation_ru": r["translation_ru"] or "", + "translation_uk": r["translation_uk"] or "", + "translation_en": r["translation_en"] or "", + "difficulty": r["difficulty"], + "edited_at": r["edited_at"].isoformat() if r["edited_at"] else None, + } + for r in rows + ], + } + + +@router.get("/texts/text/{text_id}") +async def get_text(request: Request, text_id: int): + """Один текст по id.""" + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + row = await conn.fetchrow(""" + SELECT id, sentence_number, sentence_pl, + translation_ru, translation_uk, translation_en, + difficulty, level, edited_at + FROM sentences WHERE id = $1 + """, text_id) + + if not row: + raise HTTPException(404, "Text not found") + + return { + "id": row["id"], + "sentence_number": row["sentence_number"], + "sentence_pl": row["sentence_pl"], + "translation_ru": row["translation_ru"] or "", + "translation_uk": row["translation_uk"] or "", + "translation_en": row["translation_en"] or "", + "difficulty": row["difficulty"], + "level": row["level"], + "edited_at": row["edited_at"].isoformat() if row["edited_at"] else None, + } + + +def _compute_difficulty(sentence_pl: str) -> int: + """Пересчитывает difficulty по количеству слов (как в load_sentences.py).""" + words_count = len(sentence_pl.split()) + if words_count <= 4: + return 1 + elif words_count <= 6: + return 2 + return 3 + + +@router.put("/texts/text/{text_id}") +async def update_text(request: Request, text_id: int): + """ + Обновить текст. + Difficulty пересчитывается автоматически по количеству слов в sentence_pl. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + body = await request.json() + sentence_pl = (body.get("sentence_pl") or "").strip() + translation_ru = (body.get("translation_ru") or "").strip() + translation_uk = (body.get("translation_uk") or "").strip() + translation_en = (body.get("translation_en") or "").strip() + + if not sentence_pl: + raise HTTPException(400, "sentence_pl is required") + + difficulty = _compute_difficulty(sentence_pl) + + pool = await get_pool() + async with pool.acquire() as conn: + exists = await conn.fetchval("SELECT 1 FROM sentences WHERE id = $1", text_id) + if not exists: + raise HTTPException(404, "Text not found") + + await conn.execute(""" + UPDATE sentences + SET sentence_pl = $1, + translation_ru = $2, + translation_uk = $3, + translation_en = $4, + difficulty = $5, + edited_at = NOW() + WHERE id = $6 + """, sentence_pl, translation_ru, translation_uk, translation_en, difficulty, text_id) + + logger.info(f"[admin_content] text #{text_id} updated by admin {telegram_id}") + + return {"status": "ok", "text_id": text_id, "difficulty": difficulty} + + +@router.post("/texts/level/{level}") +async def create_text(request: Request, level: str): + """ + Добавить текст в уровень. + Нумерация: max(sentence_number) + 1 для этого уровня. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + if level not in LEVELS: + raise HTTPException(400, f"Invalid level: {level}") + + body = await request.json() + sentence_pl = (body.get("sentence_pl") or "").strip() + translation_ru = (body.get("translation_ru") or "").strip() + translation_uk = (body.get("translation_uk") or "").strip() + translation_en = (body.get("translation_en") or "").strip() + + if not sentence_pl: + raise HTTPException(400, "sentence_pl is required") + + difficulty = _compute_difficulty(sentence_pl) + + pool = await get_pool() + async with pool.acquire() as conn: + existing = await conn.fetchval(""" + SELECT id FROM sentences WHERE level = $1 AND LOWER(sentence_pl) = LOWER($2) + """, level, sentence_pl) + if existing: + raise HTTPException(409, f"This sentence already exists in {level}") + + next_num = await conn.fetchval(""" + SELECT COALESCE(MAX(sentence_number), 0) + 1 FROM sentences WHERE level = $1 + """, level) or 1 + + row = await conn.fetchrow(""" + INSERT INTO sentences + (sentence_number, sentence_pl, translation_ru, translation_uk, translation_en, difficulty, level, edited_at) + VALUES ($1, $2, $3, $4, $5, $6, $7, NOW()) + RETURNING id + """, next_num, sentence_pl, translation_ru, translation_uk, translation_en, difficulty, level) + + logger.info( + f"[admin_content] text created: #{row['id']} in {level} by admin {telegram_id}" + ) + + return {"status": "ok", "text_id": row["id"], "sentence_number": next_num} + + +# ============ LESSONS ============ + +@router.get("/lessons/levels") +async def get_lesson_levels(request: Request): + """ + Уровни A1–C2 с количеством тем и последней правкой. + Считаем только активные темы. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + level_rows = await conn.fetch(""" + SELECT code, name_ru, sort_order + FROM learning_levels + WHERE is_active = TRUE + ORDER BY sort_order + """) + + result = [] + for lvl in level_rows: + code = lvl["code"] + + topics_count = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_topics + WHERE level_code = $1 AND is_active = TRUE + """, code) or 0 + + lessons_count = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_lessons l + JOIN learning_topics t ON l.topic_id = t.topic_id + WHERE t.level_code = $1 AND l.is_active = TRUE + """, code) or 0 + + last_edited = await conn.fetchval(""" + SELECT MAX(edited_at) FROM ( + SELECT t.edited_at FROM learning_topics t + WHERE t.level_code = $1 + UNION ALL + SELECT l.edited_at FROM learning_lessons l + JOIN learning_topics t ON l.topic_id = t.topic_id + WHERE t.level_code = $1 + ) sub + """, code) + + result.append({ + "code": code, + "name_ru": lvl["name_ru"], + "topics_count": topics_count, + "lessons_count": lessons_count, + "last_edited": last_edited.isoformat() if last_edited else None, + }) + + return {"levels": result} + + +@router.get("/lessons/level/{level}/topics") +async def get_lesson_topics(request: Request, level: str): + """ + Темы уровня с количеством уроков и вопросов в тесте. + Сортировка: order_number ASC. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + if level not in LEVELS: + raise HTTPException(400, f"Invalid level: {level}") + + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch(""" + SELECT + topic_id, + order_number, + name_pl, name_ru, name_uk, name_en, + is_active + FROM learning_topics + WHERE level_code = $1 AND is_active = TRUE + ORDER BY order_number ASC + """, level) + + result = [] + for r in rows: + topic_id = r["topic_id"] + + lessons_count = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_lessons + WHERE topic_id = $1 AND is_active = TRUE + """, topic_id) or 0 + + test_questions_count = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_questions + WHERE topic_id = $1 AND is_test_question = TRUE + """, topic_id) or 0 + + result.append({ + "topic_id": topic_id, + "order_number": r["order_number"], + "name_pl": r["name_pl"], + "name_ru": r["name_ru"], + "name_uk": r["name_uk"], + "name_en": r["name_en"], + "lessons_count": lessons_count, + "test_questions_count": test_questions_count, + }) + + return {"level": level, "topics": result} + + +@router.get("/lessons/topic/{topic_id}") +async def get_lesson_topic(request: Request, topic_id: str): + """ + Тема целиком: инфо о теме + список уроков + информация о тесте темы. + Уроки сортируются по order_number ASC. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + topic = await conn.fetchrow(""" + SELECT topic_id, level_code, order_number, + name_pl, name_ru, name_uk, name_en, + description_pl, description_ru, description_uk, description_en + FROM learning_topics + WHERE topic_id = $1 + """, topic_id) + + if not topic: + raise HTTPException(404, "Topic not found") + + lessons_rows = await conn.fetch(""" + SELECT lesson_id, order_number, skill_tag, + title_pl, title_ru, title_uk, title_en, + is_active + FROM learning_lessons + WHERE topic_id = $1 AND is_active = TRUE + ORDER BY order_number ASC + """, topic_id) + + lessons = [] + for l in lessons_rows: + lessons.append({ + "lesson_id": l["lesson_id"], + "order_number": l["order_number"], + "skill_tag": l["skill_tag"], + "title_pl": l["title_pl"], + "title_ru": l["title_ru"], + "title_uk": l["title_uk"], + "title_en": l["title_en"], + }) + + # Считаем вопросы теста темы + test_questions_count = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_questions + WHERE topic_id = $1 AND is_test_question = TRUE + """, topic_id) or 0 + + # Проверяем, есть ли вообще тест-вопросы + has_test = test_questions_count > 0 + + return { + "topic": { + "topic_id": topic["topic_id"], + "level_code": topic["level_code"], + "order_number": topic["order_number"], + "name_pl": topic["name_pl"], + "name_ru": topic["name_ru"], + "name_uk": topic["name_uk"], + "name_en": topic["name_en"], + "description_pl": topic["description_pl"], + "description_ru": topic["description_ru"], + "description_uk": topic["description_uk"], + "description_en": topic["description_en"], + }, + "lessons": lessons, + "has_test": has_test, + "test_questions_count": test_questions_count, + } + + +@router.get("/lessons/lesson/{lesson_id}") +async def get_lesson(request: Request, lesson_id: str): + """ + Урок целиком для WYSIWYG-редактора: + - lesson: title, objective, explanation (4 языка) + метаданные + - examples: список примеров (order_number ASC) + - questions: список вопросов урока (is_test_question = FALSE) + - options: список вариантов + - wrong_because_text: человекочитаемый текст для неправильных вариантов + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + lesson = await conn.fetchrow(""" + SELECT lesson_id, topic_id, order_number, skill_tag, + title_pl, title_ru, title_uk, title_en, + objective_pl, objective_ru, objective_uk, objective_en, + explanation_pl, explanation_ru, explanation_uk, explanation_en, + is_active + FROM learning_lessons + WHERE lesson_id = $1 + """, lesson_id) + + if not lesson: + raise HTTPException(404, "Lesson not found") + + # Примеры + examples_rows = await conn.fetch(""" + SELECT id, order_number, text_pl, text_ru, text_uk, text_en, audio_url + FROM lesson_examples + WHERE lesson_id = $1 + ORDER BY order_number ASC + """, lesson_id) + + examples = [ + { + "id": e["id"], + "order_number": e["order_number"], + "text_pl": e["text_pl"] or "", + "text_ru": e["text_ru"] or "", + "text_uk": e["text_uk"] or "", + "text_en": e["text_en"] or "", + "audio_url": e["audio_url"], + } + for e in examples_rows + ] + + # Вопросы урока (не тест темы) + questions_rows = await conn.fetch(""" + SELECT question_id, context_type, question_type, skill_tag, difficulty, + prompt_pl, prompt_ru, prompt_uk, prompt_en, + correct_answer, hint_type, hint_value, options_language, + is_test_question, test_order + FROM learning_questions + WHERE lesson_id = $1 AND is_test_question = FALSE + ORDER BY id ASC + """, lesson_id) + + # Справочник wrong_because → человекочитаемый текст (RU) + wb_rows = await conn.fetch(""" + SELECT wrong_because, explanation_ru + FROM wrong_because_explanations + """) + wb_map = {w["wrong_because"]: w["explanation_ru"] for w in wb_rows} + + questions = [] + for q in questions_rows: + options_rows = await conn.fetch(""" + SELECT option_key, text_pl, text_ru, text_uk, text_en, + is_correct, wrong_because + FROM question_options + WHERE question_id = $1 + ORDER BY option_key ASC + """, q["question_id"]) + + options = [] + for o in options_rows: + wb_code = o["wrong_because"] + options.append({ + "option_key": o["option_key"], + "text_pl": o["text_pl"] or "", + "text_ru": o["text_ru"] or "", + "text_uk": o["text_uk"] or "", + "text_en": o["text_en"] or "", + "is_correct": o["is_correct"], + "wrong_because": wb_code, + "wrong_because_text": wb_map.get(wb_code, "") if wb_code else "", + }) + + questions.append({ + "question_id": q["question_id"], + "context_type": q["context_type"], + "question_type": q["question_type"], + "skill_tag": q["skill_tag"], + "difficulty": q["difficulty"], + "prompt_pl": q["prompt_pl"] or "", + "prompt_ru": q["prompt_ru"] or "", + "prompt_uk": q["prompt_uk"] or "", + "prompt_en": q["prompt_en"] or "", + "correct_answer": q["correct_answer"] or "", + "hint_type": q["hint_type"], + "hint_value": q["hint_value"], + "options_language": q["options_language"] or "pl", + "options": options, + }) + + return { + "lesson": { + "lesson_id": lesson["lesson_id"], + "topic_id": lesson["topic_id"], + "order_number": lesson["order_number"], + "skill_tag": lesson["skill_tag"], + "title_pl": lesson["title_pl"] or "", + "title_ru": lesson["title_ru"] or "", + "title_uk": lesson["title_uk"] or "", + "title_en": lesson["title_en"] or "", + "objective_pl": lesson["objective_pl"] or "", + "objective_ru": lesson["objective_ru"] or "", + "objective_uk": lesson["objective_uk"] or "", + "objective_en": lesson["objective_en"] or "", + "explanation_pl": lesson["explanation_pl"] or "", + "explanation_ru": lesson["explanation_ru"] or "", + "explanation_uk": lesson["explanation_uk"] or "", + "explanation_en": lesson["explanation_en"] or "", + }, + "examples": examples, + "questions": questions, + } + + +@router.put("/lessons/lesson/{lesson_id}") +async def update_lesson(request: Request, lesson_id: str): + """ + Сохранить урок целиком (Вариант B) — одна транзакция: + 1. UPDATE learning_lessons (title, objective, explanation, edited_at). + 2. DELETE + INSERT lesson_examples. + 3. UPDATE learning_questions (prompt, correct_answer, hint_type, hint_value, edited_at). + 4. DELETE + INSERT question_options (option_key генерируется A/B/C/D/...). + + Тело запроса: + { + "title_pl": "...", "title_en": "...", "title_ru": "...", "title_uk": "...", + "objective_pl": "...", "objective_en": "...", "objective_ru": "...", "objective_uk": "...", + "explanation_pl": "...", "explanation_en": "...", "explanation_ru": "...", "explanation_uk": "...", + "examples": [ + {"text_pl": "...", "text_en": "...", "text_ru": "...", "text_uk": "..."} + ], + "questions": [ + { + "question_id": "a1_greetings_l01_q1", + "prompt_pl": "...", "prompt_en": "...", "prompt_ru": "...", "prompt_uk": "...", + "hint_type": "first_letter" | null, + "hint_value": "j" | null, + "options": [ + {"text_pl": "...", "text_en": "...", "text_ru": "...", "text_uk": "...", + "is_correct": true, "wrong_because": null}, + {"text_pl": "...", "text_en": "...", "text_ru": "...", "text_uk": "...", + "is_correct": false, "wrong_because": "wrong_case"} + ] + } + ] + } + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + body = await request.json() + + # ============ 1. Валидация ============ + + title_pl = (body.get("title_pl") or "").strip() + title_ru = (body.get("title_ru") or "").strip() + title_uk = (body.get("title_uk") or "").strip() + title_en = (body.get("title_en") or "").strip() + + if not title_pl: + raise HTTPException(400, "title_pl is required") + + objective_pl = (body.get("objective_pl") or "").strip() + objective_ru = (body.get("objective_ru") or "").strip() + objective_uk = (body.get("objective_uk") or "").strip() + objective_en = (body.get("objective_en") or "").strip() + + explanation_pl = (body.get("explanation_pl") or "").strip() + explanation_ru = (body.get("explanation_ru") or "").strip() + explanation_uk = (body.get("explanation_uk") or "").strip() + explanation_en = (body.get("explanation_en") or "").strip() + + examples_raw = body.get("examples") or [] + if not isinstance(examples_raw, list): + raise HTTPException(400, "examples must be a list") + + examples = [] + for ex in examples_raw: + text_pl = (ex.get("text_pl") or "").strip() + if not text_pl: + continue # пропускаем пустые примеры + examples.append({ + "text_pl": text_pl, + "text_ru": (ex.get("text_ru") or "").strip(), + "text_uk": (ex.get("text_uk") or "").strip(), + "text_en": (ex.get("text_en") or "").strip(), + }) + + questions_raw = body.get("questions") or [] + if not isinstance(questions_raw, list): + raise HTTPException(400, "questions must be a list") + + # Валидация вопросов + questions = [] + for q in questions_raw: + question_id = (q.get("question_id") or "").strip() + if not question_id: + raise HTTPException(400, "question_id is required for every question") + + prompt_pl = (q.get("prompt_pl") or "").strip() + if not prompt_pl: + raise HTTPException(400, f"prompt_pl is required for question {question_id}") + + options_raw = q.get("options") or [] + if not isinstance(options_raw, list) or len(options_raw) == 0: + raise HTTPException(400, f"At least one option required for question {question_id}") + + # Проверка: ровно один правильный вариант + correct_count = sum(1 for o in options_raw if o.get("is_correct") is True) + if correct_count != 1: + raise HTTPException( + 400, + f"Question {question_id}: exactly one option must be is_correct=true " + f"(got {correct_count})" + ) + + # Генерируем option_key A, B, C, D... + options = [] + correct_answer = None + for idx, o in enumerate(options_raw): + option_key = chr(ord('A') + idx) # A, B, C, D... + + text_pl_opt = (o.get("text_pl") or "").strip() + if not text_pl_opt: + raise HTTPException( + 400, + f"Option {option_key} of question {question_id}: text_pl is required" + ) + + is_correct = bool(o.get("is_correct")) + if is_correct: + correct_answer = option_key + + wrong_because = o.get("wrong_because") + if is_correct: + wrong_because = None # у правильного wrong_because нет + elif not wrong_because: + wrong_because = None # оставляем None если пусто + + options.append({ + "option_key": option_key, + "text_pl": text_pl_opt, + "text_ru": (o.get("text_ru") or "").strip(), + "text_uk": (o.get("text_uk") or "").strip(), + "text_en": (o.get("text_en") or "").strip(), + "is_correct": is_correct, + "wrong_because": wrong_because, + }) + + hint_type = q.get("hint_type") + if hint_type: + hint_type = str(hint_type).strip() or None + + hint_value = q.get("hint_value") + if hint_value: + hint_value = str(hint_value).strip() or None + + questions.append({ + "question_id": question_id, + "prompt_pl": prompt_pl, + "prompt_ru": (q.get("prompt_ru") or "").strip(), + "prompt_uk": (q.get("prompt_uk") or "").strip(), + "prompt_en": (q.get("prompt_en") or "").strip(), + "correct_answer": correct_answer, + "hint_type": hint_type, + "hint_value": hint_value, + "options": options, + }) + + # ============ 2. Транзакция ============ + + pool = await get_pool() + async with pool.acquire() as conn: + async with conn.transaction(): + # Проверяем, что урок существует + exists = await conn.fetchval( + "SELECT 1 FROM learning_lessons WHERE lesson_id = $1", lesson_id + ) + if not exists: + raise HTTPException(404, "Lesson not found") + + # --- 2.1. UPDATE learning_lessons --- + await conn.execute(""" + UPDATE learning_lessons + SET title_pl = $1, + title_ru = $2, + title_uk = $3, + title_en = $4, + objective_pl = $5, + objective_ru = $6, + objective_uk = $7, + objective_en = $8, + explanation_pl = $9, + explanation_ru = $10, + explanation_uk = $11, + explanation_en = $12, + edited_at = NOW() + WHERE lesson_id = $13 + """, + title_pl, title_ru, title_uk, title_en, + objective_pl, objective_ru, objective_uk, objective_en, + explanation_pl, explanation_ru, explanation_uk, explanation_en, + lesson_id, + ) + + # --- 2.2. DELETE + INSERT lesson_examples --- + await conn.execute( + "DELETE FROM lesson_examples WHERE lesson_id = $1", lesson_id + ) + + for idx, ex in enumerate(examples, start=1): + await conn.execute(""" + INSERT INTO lesson_examples + (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + """, + lesson_id, idx, + ex["text_pl"], ex["text_ru"], ex["text_uk"], ex["text_en"], + ) + + # --- 2.3. UPDATE learning_questions + DELETE + INSERT question_options --- + for q in questions: + # Проверяем, что вопрос принадлежит этому уроку + q_exists = await conn.fetchval(""" + SELECT 1 FROM learning_questions + WHERE question_id = $1 AND lesson_id = $2 + """, q["question_id"], lesson_id) + + if not q_exists: + raise HTTPException( + 400, + f"Question {q['question_id']} does not belong to lesson {lesson_id}" + ) + + await conn.execute(""" + UPDATE learning_questions + SET prompt_pl = $1, + prompt_ru = $2, + prompt_uk = $3, + prompt_en = $4, + correct_answer = $5, + hint_type = $6, + hint_value = $7, + edited_at = NOW() + WHERE question_id = $8 + """, + q["prompt_pl"], q["prompt_ru"], q["prompt_uk"], q["prompt_en"], + q["correct_answer"], q["hint_type"], q["hint_value"], + q["question_id"], + ) + + # Удаляем старые опции + await conn.execute( + "DELETE FROM question_options WHERE question_id = $1", + q["question_id"], + ) + + # Вставляем новые + for o in q["options"]: + await conn.execute(""" + INSERT INTO question_options + (question_id, option_key, text_pl, text_ru, text_uk, text_en, + is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + """, + q["question_id"], o["option_key"], + o["text_pl"], o["text_ru"], o["text_uk"], o["text_en"], + o["is_correct"], o["wrong_because"], + ) + + logger.info( + f"[admin_content] lesson '{lesson_id}' updated by admin {telegram_id}: " + f"{len(examples)} examples, {len(questions)} questions" + ) + + return { + "status": "ok", + "lesson_id": lesson_id, + "examples_count": len(examples), + "questions_count": len(questions), + } + + +# ============ WRONG BECAUSE (справочник) ============ + +@router.get("/wrong-because") +async def get_wrong_because(request: Request): + """ + Справочник wrong_because — 7 записей. + Отдаём код + 4 языка, чтобы фронт мог показать человекочитаемый текст + на языке интерфейса препода. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch(""" + SELECT wrong_because, explanation_pl, explanation_ru, + explanation_uk, explanation_en + FROM wrong_because_explanations + ORDER BY wrong_because ASC + """) + + return { + "items": [ + { + "wrong_because": r["wrong_because"], + "explanation_pl": r["explanation_pl"] or "", + "explanation_ru": r["explanation_ru"] or "", + "explanation_uk": r["explanation_uk"] or "", + "explanation_en": r["explanation_en"] or "", + } + for r in rows + ] + } \ No newline at end of file diff --git a/routers/assistant.py b/routers/assistant.py new file mode 100644 index 0000000..1b26c9d --- /dev/null +++ b/routers/assistant.py @@ -0,0 +1,480 @@ +""" +AI Assistant Router — чат-помощник с историей, контекстом, лимитами и статистикой. +Лёгкие запросы → GPT-OSS 20B, сложные → GPT-OSS 120B. +Бесплатный лимит: 5 сообщений в день (кроме админов). +""" +import logging +import time +import json +import httpx +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from config import TOGETHER_API_KEY, ADMIN_IDS +from database import get_pool + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/assistant", tags=["assistant"]) + +TOGETHER_API_URL = "https://api.together.xyz/v1/chat/completions" + +# Модели +EASY_MODEL = "openai/gpt-oss-20b" +HARD_MODEL = "openai/gpt-oss-120b" + +# Максимум сообщений в истории (10 последних) +MAX_HISTORY = 10 + +# Бесплатный лимит сообщений в день +FREE_DAILY_LIMIT = 5 + +LEVELS = ["A1", "A2", "B1", "B2", "C1", "C2"] + +SYSTEM_PROMPT = """Ты — AI-помощник Filwords PL, приложения для изучения польского языка. + +Твои задачи: +1. Переводить фразы с русского/украинского/английского на польский и обратно +2. Объяснять грамматику польского языка простыми словами +3. Отвечать на вопросы о польском языке +4. Давать примеры использования слов и фраз +5. Помогать с повседневными фразами (магазин, врач, работа, учёба) + +ОПРЕДЕЛЕНИЕ ЯЗЫКА ПОЛЬЗОВАТЕЛЯ: +- Если пользователь пишет на русском — отвечай на русском +- Если на украинском — отвечай на украинском +- Если на польском — отвечай на польском +- Если на английском — отвечай на английском +- ВСЕГДА отвечай на языке пользователя! +- Польские слова и фразы в примерах оставляй на польском, но объяснения и комментарии — на языке пользователя + +ВАЖНЫЕ ПРАВИЛА: +- НЕ используй markdown (никаких **, *, #, `, ```) +- Пиши простым текстом +- Для перевода используй формат: Польская фраза → Перевод +- Будь кратким, но полезным +- Отвечай на языке пользователя +- Не упоминай, что ты AI или модель. Ты — помощник Filwords.""" + +# Ключевые слова для сложных запросов (на 4 языках) +HARD_KEYWORDS = [ + # Русские + "объясни", "почему", "грамматик", "правило", "разница", "расскажи", + "подробно", "история", "примеры", "спряжение", "склонение", "падеж", + "урок", "мини-урок", "занятие", "обучение", + # Украинские + "поясни", "чому", "граматик", "правило", "різниця", "розкажи", + "докладно", "історія", "приклади", "відмінювання", "відмінок", + "урок", "міні-урок", "заняття", "навчання", + # Польские + "wytłumacz", "dlaczego", "gramatyk", "zasada", "różnica", "opowiedz", + "szczegółowo", "historia", "przykłady", "koniugacja", "deklinacja", "przypadek", + "lekcja", "mini-lekcja", "zajęcia", "nauka", + # Английские + "explain", "why", "grammar", "rule", "difference", "tell me", + "detailed", "history", "examples", "conjugation", "declension", "case", + "lesson", "mini-lesson", "class", "learning", +] + +# Ключевые слова для лёгких запросов +EASY_KEYWORDS = [ + # Русские + "переведи", "как сказать", "что значит", "привет", "спасибо", "пока", + # Украинские + "переклади", "як сказати", "що означає", "привіт", "дякую", "бувай", + # Польские + "przetłumacz", "jak powiedzieć", "co znaczy", "cześć", "dziękuję", + # Английские + "translate", "how to say", "what does", "hello", "thank you", "bye", +] + + +def get_model_for_message(message: str) -> str: + """Определяет какая модель нужна: лёгкая или сложная""" + msg_lower = message.lower() + + if any(kw in msg_lower for kw in HARD_KEYWORDS): + logger.info(f"Using HARD model for message: {message[:50]}...") + return HARD_MODEL + + if len(message) > 150: + logger.info(f"Using HARD model (long message, {len(message)} chars)") + return HARD_MODEL + + logger.info(f"Using EASY model for message: {message[:50]}...") + return EASY_MODEL + + +def clean_response(text: str) -> str: + """Убирает markdown-символы из ответа""" + text = text.replace("**", "").replace("*", "") + text = text.replace("###", "").replace("##", "").replace("#", "") + text = text.replace("```", "").replace("`", "") + return text.strip() + + +async def save_message(user_id: int, message: str, is_user: bool): + """Сохраняет сообщение в БД и удаляет старые (оставляет только 10 последних)""" + pool = await get_pool() + async with pool.acquire() as conn: + await conn.execute( + """INSERT INTO chat_history (user_id, message, is_user) VALUES ($1, $2, $3)""", + user_id, message, is_user + ) + + await conn.execute(""" + DELETE FROM chat_history + WHERE user_id = $1 + AND id NOT IN ( + SELECT id FROM chat_history + WHERE user_id = $1 + ORDER BY id DESC + LIMIT $2 + ) + """, user_id, MAX_HISTORY) + + +async def get_history(user_id: int) -> list: + """Получает историю чата (последние 10 сообщений)""" + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch(""" + SELECT message, is_user FROM chat_history + WHERE user_id = $1 + ORDER BY id ASC + """, user_id) + + return [{"role": "user" if row["is_user"] else "assistant", "content": row["message"]} for row in rows] + + +async def get_daily_usage(user_id: int) -> int: + """Получает количество сообщений за сегодня""" + pool = await get_pool() + async with pool.acquire() as conn: + count = await conn.fetchval(""" + SELECT message_count FROM chat_usage + WHERE user_id = $1 AND usage_date = CURRENT_DATE + """, user_id) + return count or 0 + + +async def increment_daily_usage(user_id: int): + """Увеличивает счётчик сообщений за сегодня""" + pool = await get_pool() + async with pool.acquire() as conn: + await conn.execute(""" + INSERT INTO chat_usage (user_id, usage_date, message_count) + VALUES ($1, CURRENT_DATE, 1) + ON CONFLICT (user_id, usage_date) + DO UPDATE SET message_count = chat_usage.message_count + 1 + """, user_id) + + +@router.post("/chat") +async def chat(request: Request): + """Принимает сообщение пользователя и возвращает ответ AI""" + telegram_id, _ = await require_auth(request) + + if not TOGETHER_API_KEY: + raise HTTPException(500, "AI API key not configured") + + body = await request.json() + user_message = body.get("message", "").strip() + + if not user_message: + raise HTTPException(400, "Message is required") + + if len(user_message) > 500: + raise HTTPException(400, "Message too long (max 500 characters)") + + is_admin = telegram_id in ADMIN_IDS + + if not is_admin: + daily_usage = await get_daily_usage(telegram_id) + if daily_usage >= FREE_DAILY_LIMIT: + return { + "limit_exceeded": True, + "daily_limit": FREE_DAILY_LIMIT, + "used": daily_usage, + "remaining": 0, + "response": "Dziś wykorzystałeś już wszystkie darmowe zapytania. Wróć jutro!", + } + + await save_message(telegram_id, user_message, True) + + if not is_admin: + await increment_daily_usage(telegram_id) + + history = await get_history(telegram_id) + + model = get_model_for_message(user_message) + logger.info(f"Assistant chat: user={telegram_id}, model={model}, msg_len={len(user_message)}, history={len(history)}") + + start_time = time.time() + + try: + async with httpx.AsyncClient(timeout=45.0) as client: + response = await client.post( + TOGETHER_API_URL, + headers={ + "Authorization": f"Bearer {TOGETHER_API_KEY}", + "Content-Type": "application/json", + }, + json={ + "model": model, + "messages": [ + {"role": "system", "content": SYSTEM_PROMPT}, + *history, + ], + "max_tokens": 2500, + "temperature": 0.7, + }, + ) + + elapsed_time = time.time() - start_time + logger.info(f"Assistant response: status={response.status_code}, time={elapsed_time:.2f}s") + + if response.status_code != 200: + logger.error(f"AI API error: {response.status_code}, body={response.text[:200]}") + raise HTTPException(500, f"AI API error: {response.status_code}") + + data = response.json() + ai_response = data["choices"][0]["message"]["content"].strip() + ai_response = clean_response(ai_response) + + await save_message(telegram_id, ai_response, False) + + remaining = FREE_DAILY_LIMIT if is_admin else max(0, FREE_DAILY_LIMIT - await get_daily_usage(telegram_id)) + + logger.info(f"Assistant answer: len={len(ai_response)}, model={model}") + + return { + "response": ai_response, + "model_used": model, + "limit_exceeded": False, + "daily_limit": FREE_DAILY_LIMIT if not is_admin else None, + "remaining": remaining if not is_admin else None, + } + + except HTTPException: + raise + except httpx.TimeoutException: + logger.error(f"AI API timeout after {time.time() - start_time:.2f}s") + raise HTTPException(500, "AI service timeout") + except Exception as e: + logger.error(f"AI service error: {str(e)}") + raise HTTPException(500, f"AI service error: {str(e)}") + + +@router.post("/save-analytics") +async def save_analytics(request: Request): + """Сохраняет ответ аналитики в историю чата""" + telegram_id, _ = await require_auth(request) + body = await request.json() + message = body.get("message", "").strip() + + if not message: + raise HTTPException(400, "Message is required") + + await save_message(telegram_id, message, False) + + return {"status": "ok"} + + +@router.get("/stats/personal") +async def get_personal_stats(request: Request): + """Возвращает личную статистику пользователя для AI""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow("SELECT current_level, app_language FROM users WHERE telegram_id = $1", telegram_id) + if not user: + raise HTTPException(401, "User not registered") + + current_level = user["current_level"] or "A1" + + # Прогресс по каждому уровню + level_progress = {} + total_score = 0 + total_achievements = await conn.fetchval(""" + SELECT COUNT(*) FROM user_achievements WHERE user_id = $1 + """, telegram_id) or 0 + + for level in LEVELS: + # Филворды + ws_total = await conn.fetchval("SELECT COUNT(*) FROM levels WHERE level = $1", level) or 0 + ws_completed = await conn.fetchval( + "SELECT COUNT(DISTINCT level_id) FROM user_progress WHERE user_id = $1 AND level = $2 AND completed_at IS NOT NULL", + telegram_id, level + ) or 0 + ws_percent = round((ws_completed / ws_total * 100), 1) if ws_total > 0 else 0 + + # Предложения + s_total = await conn.fetchval("SELECT COUNT(*) FROM sentences WHERE level = $1", level) or 0 + s_completed = await conn.fetchval( + "SELECT COUNT(*) FROM sentence_progress WHERE user_id = $1 AND level = $2 AND completed_at IS NOT NULL", + telegram_id, level + ) or 0 + s_percent = round((s_completed / s_total * 100), 1) if s_total > 0 else 0 + + # Очки уровня + ws_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM user_progress WHERE user_id = $1 AND level = $2 AND completed_at IS NOT NULL", + telegram_id, level + ) or 0 + s_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM sentence_progress WHERE user_id = $1 AND level = $2 AND completed_at IS NOT NULL", + telegram_id, level + ) or 0 + wq_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM word_quiz_progress WHERE user_id = $1 AND level = $2", + telegram_id, level + ) or 0 + bw_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM bubble_words_progress WHERE user_id = $1 AND level = $2", + telegram_id, level + ) or 0 + + level_total = ws_score + s_score + wq_score + bw_score + total_score += level_total + + level_progress[level] = { + "wordsearch_percent": ws_percent, + "wordsearch_completed": ws_completed, + "wordsearch_total": ws_total, + "sentence_percent": s_percent, + "sentence_completed": s_completed, + "sentence_total": s_total, + "total_score": level_total, + } + + # Квиз и пузыри общие + wq_words = await conn.fetchval( + "SELECT COALESCE(words_guessed, 0) FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + bw_levels = await conn.fetchval( + "SELECT COALESCE(levels_completed, 0) FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) or 0 + + # Уроки + completed_topics = await conn.fetchval( + "SELECT COUNT(*) FROM user_topic_progress WHERE user_id = $1 AND test_completed = TRUE", + telegram_id + ) or 0 + + return { + "current_level": current_level, + "total_score": total_score, + "achievements": total_achievements, + "words_guessed": wq_words, + "bubble_levels": bw_levels, + "completed_topics": completed_topics, + "level_progress": level_progress, + } + + +@router.get("/stats/admin") +async def get_admin_stats(request: Request): + """Возвращает админ-статистику""" + telegram_id, _ = await require_auth(request) + + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + pool = await get_pool() + async with pool.acquire() as conn: + total_users = await conn.fetchval("SELECT COUNT(*) FROM users") or 0 + new_today = await conn.fetchval("SELECT COUNT(*) FROM users WHERE created_at::date = CURRENT_DATE") or 0 + + online_now = await conn.fetchval(""" + SELECT COUNT(DISTINCT user_id) FROM ( + SELECT user_id FROM user_progress WHERE completed_at > NOW() - INTERVAL '30 minutes' + UNION + SELECT user_id FROM sentence_progress WHERE completed_at > NOW() - INTERVAL '30 minutes' + UNION + SELECT user_id FROM daily_logins WHERE login_date = CURRENT_DATE + ) active + """) or 0 + + # Языки + language_counts = {} + for lang in ["pl", "ru", "uk", "en"]: + count = await conn.fetchval("SELECT COUNT(*) FROM users WHERE app_language = $1", lang) or 0 + language_counts[lang] = count + + # Уровни + level_counts = {} + for level in LEVELS: + count = await conn.fetchval("SELECT COUNT(*) FROM users WHERE current_level = $1", level) or 0 + level_counts[level] = count + + return { + "total_users": total_users, + "new_today": new_today, + "online_now": online_now, + "language_counts": language_counts, + "level_counts": level_counts, + } + + +@router.get("/limit") +async def get_limit(request: Request): + """Возвращает информацию о лимите пользователя""" + telegram_id, _ = await require_auth(request) + + is_admin = telegram_id in ADMIN_IDS + if is_admin: + return { + "is_admin": True, + "daily_limit": None, + "used": 0, + "remaining": None, + } + + daily_usage = await get_daily_usage(telegram_id) + remaining = max(0, FREE_DAILY_LIMIT - daily_usage) + + return { + "is_admin": False, + "daily_limit": FREE_DAILY_LIMIT, + "used": daily_usage, + "remaining": remaining, + } + + +@router.get("/history") +async def get_chat_history(request: Request): + """Возвращает историю чата пользователя""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch(""" + SELECT message, is_user, created_at FROM chat_history + WHERE user_id = $1 + ORDER BY id ASC + """, telegram_id) + + history = [] + for row in rows: + history.append({ + "message": row["message"], + "is_user": row["is_user"], + "created_at": row["created_at"].isoformat() if row["created_at"] else None, + }) + + return {"history": history} + + +@router.post("/history/clear") +async def clear_chat_history(request: Request): + """Очищает историю чата пользователя""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + await conn.execute("DELETE FROM chat_history WHERE user_id = $1", telegram_id) + + return {"status": "ok"} \ No newline at end of file diff --git a/routers/bubblewords.py b/routers/bubblewords.py new file mode 100644 index 0000000..350266a --- /dev/null +++ b/routers/bubblewords.py @@ -0,0 +1,274 @@ +import random +import time +import hashlib # 🔧 НОВОЕ: импорт hashlib для стабильного хэширования +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool + +router = APIRouter(prefix="/bubblewords", tags=["bubblewords"]) + + +def split_word_into_parts(word: str, forbidden_parts: set = None) -> list: + """Разбивает польское слово на части по 1-3 буквы. + forbidden_parts — части, которые уже заняты другими словами на уровне. + Если не удалось найти уникальное разбиение — добавляет суффикс с индексом слова.""" + if forbidden_parts is None: + forbidden_parts = set() + + n = len(word) + attempts = 0 + max_attempts = 50 # Увеличиваем попытки + + while attempts < max_attempts: + parts = [] + i = 0 + + while i < n: + remaining = n - i + + if remaining == 1: + parts.append(word[i:]) + i += 1 + elif remaining == 2: + if random.random() < 0.4: + parts.append(word[i:i+1]) + parts.append(word[i+1:]) + else: + parts.append(word[i:]) + i += 2 + elif remaining == 3: + choice = random.choice([1, 2, 3]) + if choice == 1: + parts.append(word[i:i+1]) + parts.append(word[i+1:]) + elif choice == 2: + parts.append(word[i:i+2]) + parts.append(word[i+2:]) + else: + parts.append(word[i:]) + i += 3 + elif remaining == 4: + choice = random.choice([(2, 2), (1, 3), (3, 1), (1, 1, 2), (2, 1, 1)]) + for size in choice: + parts.append(word[i:i+size]) + i += size + elif remaining == 5: + choice = random.choice([(2, 3), (3, 2), (2, 2, 1), (2, 1, 2)]) + for size in choice: + parts.append(word[i:i+size]) + i += size + elif remaining == 6: + choice = random.choice([(3, 3), (2, 2, 2), (3, 2, 1), (2, 3, 1)]) + for size in choice: + parts.append(word[i:i+size]) + i += size + else: + size = random.choice([2, 3]) + if i + size > n: + size = n - i + parts.append(word[i:i+size]) + i += size + + # Проверяем конфликт + conflict = False + for part in parts: + if part in forbidden_parts: + conflict = True + break + + if not conflict: + return parts + + attempts += 1 + + # Если за 50 попыток не нашли уникальное разбиение — + # разбиваем слово ПО БУКВАМ и добавляем суффикс с хешем слова + # Такой суффикс гарантированно уникален для каждого слова + # 🔧 ИСПРАВЛЕНО: заменён hash() на hashlib.md5 для стабильности между запусками + word_hash = hashlib.md5(word.encode('utf-8')).hexdigest()[:4] # Берём первые 4 символа MD5 + unique_parts = [] + for idx, letter in enumerate(word): + unique_parts.append(f"{letter}.{word_hash}.{idx}") + + return unique_parts + + +@router.get("/next") +async def get_next_bubble_level(request: Request): + """Выдаёт слова и их части для уровня пузырей с фильтрацией по уровню.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT app_language, current_level FROM users WHERE telegram_id = $1", telegram_id + ) + if not user: + raise HTTPException(401, "User not registered") + + lang = user["app_language"] or "pl" + current_level = user["current_level"] or "A1" + + progress = await conn.fetchrow( + "SELECT levels_completed FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) + current_bubble_level = (progress["levels_completed"] if progress else 0) + 1 + + # Прогрессия по количеству слов на уровне + if current_bubble_level <= 10: + num_words = random.choice([3, 4]) + elif current_bubble_level <= 25: + num_words = random.choice([5, 6]) + else: + num_words = random.choice([7, 8]) + + # Запрос слов с фильтром по уровню и level_id IS NULL + words = await conn.fetch(""" + SELECT word_pl, translation_ru, translation_uk, translation_en + FROM ( + SELECT DISTINCT ON (word_pl) word_pl, translation_ru, translation_uk, translation_en + FROM level_words + WHERE level = $1 AND level_id IS NULL + ) AS unique_words + ORDER BY RANDOM() + LIMIT $2 + """, current_level, num_words) + + if len(words) < 2: + raise HTTPException(404, "Not enough words") + + translation_field = f"translation_{lang}" + + result_words = [] + all_parts = [] + forbidden_parts = set() + + for w in words: + word_pl = w["word_pl"] + parts = split_word_into_parts(word_pl, forbidden_parts) + translation = w.get(translation_field) or w.get("translation_en") or word_pl + + result_words.append({ + "word_pl": word_pl, + "translation": translation, + "parts": parts, + }) + + for part in parts: + forbidden_parts.add(part) + all_parts.append({ + "text": part, + "word_pl": word_pl, + }) + + random.shuffle(all_parts) + + return { + "words": result_words, + "bubbles": all_parts, + "level": current_bubble_level, + } + + +@router.post("/complete") +async def complete_bubble_level(request: Request): + """Завершение уровня пузырей, начисление очков и проверка достижений""" + telegram_id, _ = await require_auth(request) + body = await request.json() + hints_used = body.get("hints_used", 0) + words_count = body.get("words_count", 3) + completion_time = body.get("completion_time") + + hints_used = min(max(0, hints_used), 3) + score = max(10, 100 - hints_used * 10) + + pool = await get_pool() + async with pool.acquire() as conn: + user_exists = await conn.fetchval( + "SELECT 1 FROM users WHERE telegram_id = $1", telegram_id + ) + if not user_exists: + raise HTTPException(401, "User not registered") + + # Получаем current_level пользователя + current_level = await conn.fetchval( + "SELECT current_level FROM users WHERE telegram_id = $1", telegram_id + ) or "A1" + + await conn.execute(""" + INSERT INTO bubble_words_progress (user_id, levels_completed, total_score, level) + VALUES ($1, 1, $2, $3) + ON CONFLICT (user_id) DO UPDATE + SET levels_completed = bubble_words_progress.levels_completed + 1, + total_score = bubble_words_progress.total_score + $2, + level = $3 + """, telegram_id, score, current_level) + + # Проверка достижений + from routers.achievements import check_and_award_achievements + new_achievements = [] + + total_levels = await conn.fetchval( + "SELECT levels_completed FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) or 0 + ach = await check_and_award_achievements(telegram_id, "bubble_levels", total_levels) + new_achievements.extend(ach) + + if hints_used == 0: + ach = await check_and_award_achievements(telegram_id, "bubble_no_hints", 1) + new_achievements.extend(ach) + + if score == 100: + ach = await check_and_award_achievements(telegram_id, "bubble_perfect", 1) + new_achievements.extend(ach) + + if completion_time is not None and completion_time > 0 and int(completion_time) <= 45: + ach = await check_and_award_achievements(telegram_id, "bubble_speed", 45) + new_achievements.extend(ach) + + wordsearch_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM user_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + sentence_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM sentence_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + wordquiz_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + bubblewords_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) or 0 + grand_total = wordsearch_score + sentence_score + wordquiz_score + bubblewords_score + ach = await check_and_award_achievements(telegram_id, "total_score", grand_total) + new_achievements.extend(ach) + + return { + "status": "ok", + "score": score, + "completion_time": completion_time, + "new_achievements": new_achievements, + } + + +@router.get("/progress") +async def get_bubble_progress(request: Request): + """Статистика пользователя в Bubble Words""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + progress = await conn.fetchrow( + "SELECT levels_completed, total_score FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) + + return { + "levels_completed": progress["levels_completed"] if progress else 0, + "total_score": progress["total_score"] if progress else 0, + } \ No newline at end of file diff --git a/routers/feed.py b/routers/feed.py new file mode 100644 index 0000000..80a1852 --- /dev/null +++ b/routers/feed.py @@ -0,0 +1,725 @@ +""" +Feed Router — посты для карусели (новости / партнёры / контакты / приложения). + +Публичные эндпоинты: +- GET /feed/{section}?lang={lang} — лента постов с локализацией +- GET /feed/post/{id}?lang={lang} — один пост + +Админские эндпоинты: +- POST /admin/feed/post — создать пост + автоперевод на 4 языка +- PUT /admin/feed/post/{id} — редактировать (опционально перевести заново) +- POST /admin/feed/post/{id}/delete — удалить (вложения удалит CASCADE) +- POST /admin/feed/upload-image — загрузить картинку (multipart, до 3 на пост) +- POST /admin/feed/translate — перевести title+body вручную (без сохранения) + +Логика локализации: +- В БД хранятся 4 версии поста (title_pl/ru/uk/en, body_pl/ru/uk/en). +- Юзер получает только свою версию. +- Fallback: _{lang} → _en → _pl. +""" +import logging +import json +import re +import uuid +import os +from pathlib import Path +from typing import Optional, Any + +import httpx +from fastapi import APIRouter, Request, HTTPException, UploadFile, File, Form +from auth import require_auth +from database import get_pool +from config import ( + TOGETHER_API_KEY, + ADMIN_IDS, + FEED_SECTIONS, + FEED_TARGET_LANGUAGES, + MAX_FEED_ATTACHMENTS, + MAX_FEED_IMAGE_SIZE_BYTES, + FEED_ALLOWED_IMAGE_TYPES, + UPLOADS_DIR, +) + +logger = logging.getLogger(__name__) + +router = APIRouter(tags=["feed"]) + +TOGETHER_API_URL = "https://api.together.xyz/v1/chat/completions" +TRANSLATE_MODEL = "MiniMaxAI/MiniMax-M3" + +# 🔧 ФИКС: бэк отдаёт полный URL картинки, чтобы фронт не гадал, +# куда склеивать относительный путь /uploads/feed/... +API_PUBLIC_URL = "https://api.filwordspl.com" + + +# ============ HELPERS ============ + +def _require_admin(telegram_id: int) -> None: + """Проверка, что пользователь — админ. Бросает 403 если нет.""" + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + +def _localized_field(row: dict, field: str, lang: str) -> str: + """ + Достаёт локализованное поле из строки БД. + Fallback: _{lang} → _en → _pl → ''. + """ + if not row: + return "" + return ( + row.get(f"{field}_{lang}") + or row.get(f"{field}_en") + or row.get(f"{field}_pl") + or "" + ) + + +def _serialize_post(row: dict, attachments: list, lang: str) -> dict: + """ + Собирает финальный объект поста для фронта: + локализованный title/body, ссылки, метаданные, картинки. + """ + return { + "id": row["id"], + "section": row["section"], + "title": _localized_field(row, "title", lang), + "body": _localized_field(row, "body", lang), + "images": [ + f"{API_PUBLIC_URL}{a['file_path']}" if a["file_path"].startswith("/") else a["file_path"] + for a in attachments + ], + "linkUrl": row.get("link_url"), + "telegramUrl": row.get("telegram_url"), + "createdAt": row["created_at"].isoformat() if row.get("created_at") else None, + "updatedAt": row["updated_at"].isoformat() if row.get("updated_at") else None, + "expiresAt": row["expires_at"].isoformat() if row.get("expires_at") else None, + "isPinned": bool(row.get("is_pinned")), + } + + +# ============ ПУБЛИЧНЫЕ ЭНДПОИНТЫ ============ + +@router.get("/feed/{section}") +async def get_feed_section(request: Request, section: str, lang: Optional[str] = None): + """ + Возвращает ленту постов для секции (news / partners / contacts / apps). + + - Закреплённые посты — сверху. + - Остальные — по created_at DESC. + - Истёкшие (expires_at < NOW()) — НЕ отдаём. + - Опубликованные (is_published = TRUE) — только они. + """ + telegram_id, _ = await require_auth(request) + + if section not in FEED_SECTIONS: + raise HTTPException(400, f"Invalid section: {section}") + + pool = await get_pool() + async with pool.acquire() as conn: + # Если lang не передан — берём из профиля юзера + if not lang or lang not in FEED_TARGET_LANGUAGES: + lang = await conn.fetchval( + "SELECT app_language FROM users WHERE telegram_id = $1", + telegram_id, + ) or "pl" + if lang not in FEED_TARGET_LANGUAGES: + lang = "pl" + + # Тянем посты: закреплённые сверху, потом по дате + rows = await conn.fetch(""" + SELECT * + FROM feed_posts + WHERE section = $1 + AND is_published = TRUE + AND (expires_at IS NULL OR expires_at > NOW()) + ORDER BY is_pinned DESC, created_at DESC + """, section) + + if not rows: + return {"posts": [], "section": section, "lang": lang} + + # Одним запросом тянем все вложения для всех постов (без N+1) + post_ids = [r["id"] for r in rows] + att_rows = await conn.fetch(""" + SELECT post_id, file_path, order_number + FROM feed_attachments + WHERE post_id = ANY($1::bigint[]) + ORDER BY post_id, order_number ASC + """, post_ids) + + # Группируем вложения по post_id + att_by_post: dict[int, list] = {} + for a in att_rows: + att_by_post.setdefault(a["post_id"], []).append(dict(a)) + + posts = [ + _serialize_post(dict(r), att_by_post.get(r["id"], []), lang) + for r in rows + ] + + return {"posts": posts, "section": section, "lang": lang} + + +@router.get("/feed/post/{post_id}") +async def get_feed_post(request: Request, post_id: int, lang: Optional[str] = None): + """Возвращает один пост по ID (с локализацией).""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + if not lang or lang not in FEED_TARGET_LANGUAGES: + lang = await conn.fetchval( + "SELECT app_language FROM users WHERE telegram_id = $1", + telegram_id, + ) or "pl" + if lang not in FEED_TARGET_LANGUAGES: + lang = "pl" + + row = await conn.fetchrow(""" + SELECT * FROM feed_posts WHERE id = $1 AND is_published = TRUE + """, post_id) + + if not row: + raise HTTPException(404, "Post not found") + + att_rows = await conn.fetch(""" + SELECT file_path, order_number + FROM feed_attachments + WHERE post_id = $1 + ORDER BY order_number ASC + """, post_id) + + return _serialize_post(dict(row), [dict(a) for a in att_rows], lang) + + +# ============ AI-ПЕРЕВОД ============ + +async def translate_to_all_languages( + title: str, + body: str, + source_lang: str, +) -> dict: + """ + Переводит title и body с source_lang на все 4 языка (PL/RU/UK/EN). + + Возвращает dict с 8 полями: + title_pl, title_ru, title_uk, title_en, + body_pl, body_ru, body_uk, body_en. + + Если AI упал или вернул невалидный JSON — возвращает пустой dict. + Caller должен решить, использовать ли fallback (source_lang для всех языков). + """ + if not TOGETHER_API_KEY: + logger.error("TOGETHER_API_KEY not configured — cannot translate") + return {} + + if source_lang not in FEED_TARGET_LANGUAGES: + logger.error(f"Invalid source_lang: {source_lang}") + return {} + + system_prompt = f"""Ты — переводчик. Переведи title и body на 4 языка: PL, RU, UK, EN. +Язык оригинала: {source_lang}. + +Верни СТРОГО JSON без markdown и без пояснений: +{{ + "title_pl": "...", "title_ru": "...", "title_uk": "...", "title_en": "...", + "body_pl": "...", "body_ru": "...", "body_uk": "...", "body_en": "..." +}} + +ВАЖНО: +- Если source_lang = ru, то title_ru и body_ru оставь БЕЗ изменений. +- Если source_lang = pl, то title_pl и body_pl оставь БЕЗ изменений. +- Если source_lang = uk, то title_uk и body_uk оставь БЕЗ изменений. +- Если source_lang = en, то title_en и body_en оставь БЕЗ изменений. +- Сохраняй переносы строк внутри body (используй \\n в JSON). +- Не добавляй никаких полей кроме указанных 8. +- Если title пустой — оставь все title_* пустыми строками.""" + + user_prompt = f"title: {title}\nbody: {body}" + + try: + async with httpx.AsyncClient(timeout=90.0) as client: + response = await client.post( + TOGETHER_API_URL, + headers={ + "Authorization": f"Bearer {TOGETHER_API_KEY}", + "Content-Type": "application/json", + }, + json={ + "model": TRANSLATE_MODEL, + "messages": [ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_prompt}, + ], + "max_tokens": 2000, + "temperature": 0.3, + }, + ) + + if response.status_code != 200: + logger.error( + f"Translate API error: {response.status_code}, body={response.text[:200]}" + ) + return {} + + data = response.json() + raw = data["choices"][0]["message"]["content"].strip() + + # Если AI обернул в ```json ... ``` — снимаем обёртку + if raw.startswith("```"): + raw = re.sub(r'^```(?:json)?\s*', '', raw) + raw = re.sub(r'\s*```$', '', raw) + + # Иногда AI добавляет текст до/после JSON — вырезаем первый {...} + json_match = re.search(r'\{.*\}', raw, re.DOTALL) + if not json_match: + logger.error(f"AI response has no JSON: {raw[:200]}") + return {} + + parsed = json.loads(json_match.group(0)) + + # Валидация: все 8 полей должны быть строками + expected_keys = [ + "title_pl", "title_ru", "title_uk", "title_en", + "body_pl", "body_ru", "body_uk", "body_en", + ] + result = {} + for key in expected_keys: + value = parsed.get(key, "") + result[key] = str(value) if value is not None else "" + + # Гарантия: source_lang остаётся без изменений + result[f"title_{source_lang}"] = title + result[f"body_{source_lang}"] = body + + return result + + except json.JSONDecodeError as e: + logger.error(f"Failed to parse AI JSON: {e}") + return {} + except Exception as e: + logger.error(f"Translate error: {str(e)}") + return {} + + +# ============ АДМИНСКИЕ ЭНДПОИНТЫ ============ + +@router.post("/admin/feed/post") +async def admin_create_feed_post(request: Request): + """ + Создать feed-пост. + + Тело запроса (JSON): + { + "section": "news" | "partners" | "contacts" | "apps", + "source_language": "ru" | "pl" | "uk" | "en", + "title": "Заголовок на source_language", + "body": "Текст поста на source_language", + "link_url": "https://..." (опционально), + "telegram_url": "https://t.me/..." (опционально), + "is_pinned": false (опционально), + "expires_at": "2026-10-15T23:59:59Z" (опционально, для partners) + } + + Backend автоматически переведёт title/body на 4 языка через MiniMax-M3. + Если перевод упал — сохраняем source_language для всех языков (fallback). + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + body = await request.json() + + section = body.get("section", "").strip() + source_language = body.get("source_language", "ru").strip().lower() + title = (body.get("title") or "").strip() + post_body = (body.get("body") or "").strip() + link_url = (body.get("link_url") or "").strip() or None + telegram_url = (body.get("telegram_url") or "").strip() or None + is_pinned = bool(body.get("is_pinned", False)) + expires_at_raw = body.get("expires_at") + + # Валидация + if section not in FEED_SECTIONS: + raise HTTPException(400, f"Invalid section. Allowed: {sorted(FEED_SECTIONS)}") + + if source_language not in FEED_TARGET_LANGUAGES: + raise HTTPException(400, f"Invalid source_language. Allowed: {FEED_TARGET_LANGUAGES}") + + if not title and not post_body: + raise HTTPException(400, "Either title or body is required") + + if len(title) > 200: + raise HTTPException(400, "Title too long (max 200 characters)") + + if len(post_body) > 5000: + raise HTTPException(400, "Body too long (max 5000 characters)") + + # Парсим expires_at если передан + expires_at = None + if expires_at_raw: + try: + from datetime import datetime, timezone + # Поддерживаем ISO 8601 с 'Z' или без + normalized = expires_at_raw.replace("Z", "+00:00") + expires_at = datetime.fromisoformat(normalized) + if expires_at.tzinfo is None: + expires_at = expires_at.replace(tzinfo=timezone.utc) + except (ValueError, AttributeError): + raise HTTPException(400, "Invalid expires_at format (use ISO 8601)") + + # Переводим на 4 языка + logger.info(f"Translating feed post from {source_language} → PL/RU/UK/EN") + translations = await translate_to_all_languages(title, post_body, source_language) + + # Fallback: если перевод не удался — копируем source для всех языков + if not translations: + logger.warning("Translation failed — falling back to source_language for all") + translations = {} + for lang in FEED_TARGET_LANGUAGES: + translations[f"title_{lang}"] = title + translations[f"body_{lang}"] = post_body + + pool = await get_pool() + async with pool.acquire() as conn: + row = await conn.fetchrow(""" + INSERT INTO feed_posts ( + section, source_language, + title_pl, title_ru, title_uk, title_en, + body_pl, body_ru, body_uk, body_en, + link_url, telegram_url, + author_id, is_pinned, is_published, expires_at + ) VALUES ( + $1, $2, + $3, $4, $5, $6, + $7, $8, $9, $10, + $11, $12, + $13, $14, TRUE, $15 + ) + RETURNING id + """, + section, source_language, + translations["title_pl"], translations["title_ru"], + translations["title_uk"], translations["title_en"], + translations["body_pl"], translations["body_ru"], + translations["body_uk"], translations["body_en"], + link_url, telegram_url, + telegram_id, is_pinned, expires_at, + ) + + return {"status": "ok", "post_id": row["id"]} + + +@router.put("/admin/feed/post/{post_id}") +async def admin_update_feed_post(request: Request, post_id: int): + """ + Редактировать feed-пост. + + Тело запроса (JSON) — все поля опциональны: + { + "title": "...", (на source_language) + "body": "...", (на source_language) + "link_url": "..." | null, + "telegram_url": "..." | null, + "is_pinned": true/false, + "is_published": true/false, + "expires_at": "..." | null, + "translate_again": true — перевести заново через AI + } + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + body = await request.json() + + pool = await get_pool() + async with pool.acquire() as conn: + existing = await conn.fetchrow(""" + SELECT * FROM feed_posts WHERE id = $1 + """, post_id) + + if not existing: + raise HTTPException(404, "Post not found") + + source_language = existing["source_language"] + + # Мерджим поля: если не передано — оставляем старое + title = body.get("title", existing.get(f"title_{source_language}") or "") + post_body = body.get("body", existing.get(f"body_{source_language}") or "") + link_url = body.get("link_url", existing["link_url"]) + telegram_url = body.get("telegram_url", existing["telegram_url"]) + is_pinned = body.get("is_pinned", existing["is_pinned"]) + is_published = body.get("is_published", existing["is_published"]) + + # expires_at: явное None → очистить, отсутствие ключа → оставить + if "expires_at" in body: + expires_at_raw = body.get("expires_at") + if expires_at_raw is None: + expires_at = None + else: + try: + from datetime import datetime, timezone + normalized = str(expires_at_raw).replace("Z", "+00:00") + expires_at = datetime.fromisoformat(normalized) + if expires_at.tzinfo is None: + expires_at = expires_at.replace(tzinfo=timezone.utc) + except (ValueError, AttributeError): + raise HTTPException(400, "Invalid expires_at format (use ISO 8601)") + else: + expires_at = existing["expires_at"] + + # Если translate_again = True — переводим заново + if body.get("translate_again"): + logger.info(f"Re-translating feed post #{post_id} from {source_language}") + translations = await translate_to_all_languages(title, post_body, source_language) + + if not translations: + logger.warning("Translation failed — keeping old translations for other languages") + # Оставляем старые версии для не-source языков, обновляем только source + translations = { + "title_pl": existing["title_pl"], "title_ru": existing["title_ru"], + "title_uk": existing["title_uk"], "title_en": existing["title_en"], + "body_pl": existing["body_pl"], "body_ru": existing["body_ru"], + "body_uk": existing["body_uk"], "body_en": existing["body_en"], + } + translations[f"title_{source_language}"] = title + translations[f"body_{source_language}"] = post_body + else: + # Без translate_again — обновляем ТОЛЬКО source_language, остальные не трогаем + translations = { + "title_pl": existing["title_pl"], "title_ru": existing["title_ru"], + "title_uk": existing["title_uk"], "title_en": existing["title_en"], + "body_pl": existing["body_pl"], "body_ru": existing["body_ru"], + "body_uk": existing["body_uk"], "body_en": existing["body_en"], + } + translations[f"title_{source_language}"] = title + translations[f"body_{source_language}"] = post_body + + await conn.execute(""" + UPDATE feed_posts SET + title_pl = $1, title_ru = $2, title_uk = $3, title_en = $4, + body_pl = $5, body_ru = $6, body_uk = $7, body_en = $8, + link_url = $9, telegram_url = $10, + is_pinned = $11, is_published = $12, + expires_at = $13, + updated_at = NOW(), + edited_at = NOW() + WHERE id = $14 + """, + translations["title_pl"], translations["title_ru"], + translations["title_uk"], translations["title_en"], + translations["body_pl"], translations["body_ru"], + translations["body_uk"], translations["body_en"], + link_url, telegram_url, + is_pinned, is_published, + expires_at, + post_id, + ) + + return {"status": "ok", "post_id": post_id} + + +# 🔧 ФИКС (18.09.2026): POST вместо DELETE. +# Причина: Telegram WebView (iOS / macOS) не пропускает DELETE из-за CORS preflight, +# который Cloudflare кеширует на 20 дней. POST без Content-Type — simple request, +# preflight не отправляется, Cloudflare не вмешивается. +# +# 🔧 ФИКС (19.09.2026): удаляем не только запись из БД, но и файлы с диска. +# Раньше файлы копились мёртвым грузом (27 мёртвых файлов за день тестов). +@router.post("/admin/feed/post/{post_id}/delete") +async def admin_delete_feed_post(request: Request, post_id: int): + """ + Удалить feed-пост (POST вместо DELETE — обход CORS preflight в WebView). + + Что делаем: + 1. Читаем пути всех файлов поста из feed_attachments ДО удаления из БД. + 2. Удаляем пост из БД (ON DELETE CASCADE уберёт вложения). + 3. Удаляем файлы с диска. + + Если файл уже удалён вручную / нет прав — не роняем запрос, только логируем. + Пост из БД уже удалён — файл вторичен. + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + pool = await get_pool() + async with pool.acquire() as conn: + # 1. Читаем пути файлов ДО удаления + attachment_rows = await conn.fetch(""" + SELECT file_path FROM feed_attachments WHERE post_id = $1 + """, post_id) + + # 2. Удаляем пост (CASCADE уберёт feed_attachments) + result = await conn.execute(""" + DELETE FROM feed_posts WHERE id = $1 + """, post_id) + + affected = int(result.split()[-1]) + if affected == 0: + raise HTTPException(404, "Post not found") + + logger.info(f"Feed post #{post_id} deleted by admin {telegram_id}") + + # 3. Удаляем файлы с диска (вне pool.acquire — чтобы не держать коннект) + # file_path в БД = "/uploads/feed/16_0_abc.jpg" + # на диске = "/root/filwordspl/backend/uploads/feed/16_0_abc.jpg" + # UPLOADS_DIR = "/root/filwordspl/backend/uploads" (Path) + removed_count = 0 + failed_count = 0 + + for row in attachment_rows: + file_path = row["file_path"] # "/uploads/feed/16_0_abc.jpg" + # Убираем префикс "/uploads/" → "feed/16_0_abc.jpg" + rel_path = file_path.replace("/uploads/", "", 1).lstrip("/") + abs_path = Path(UPLOADS_DIR) / rel_path + + try: + if abs_path.exists(): + abs_path.unlink() + removed_count += 1 + logger.info(f"[delete_feed_post] removed file: {abs_path}") + else: + logger.warning(f"[delete_feed_post] file not found: {abs_path}") + except Exception as e: + failed_count += 1 + # Не роняем запрос — пост уже удалён из БД, файл вторичен + logger.error(f"[delete_feed_post] failed to remove {abs_path}: {e}") + + if removed_count or failed_count: + logger.info( + f"[delete_feed_post] post #{post_id}: " + f"files removed={removed_count}, failed={failed_count}" + ) + + return {"status": "ok", "files_removed": removed_count} + + +@router.post("/admin/feed/upload-image") +async def admin_upload_feed_image( + request: Request, + post_id: int = Form(...), + file: UploadFile = File(...), +): + """ + Загрузить картинку к посту. + - Максимум MAX_FEED_ATTACHMENTS (3) на пост. + - Максимум MAX_FEED_IMAGE_SIZE_MB (5 МБ) на файл. + - Только image/jpeg, image/png, image/webp, image/gif. + + Возвращает путь к файлу (используется как URL на фронте). + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + # Валидация MIME-типа + content_type = (file.content_type or "").lower() + if content_type not in FEED_ALLOWED_IMAGE_TYPES: + raise HTTPException( + 400, + f"Invalid image type: {content_type}. Allowed: {sorted(FEED_ALLOWED_IMAGE_TYPES)}", + ) + + # Читаем файл, проверяем размер + content = await file.read() + if len(content) == 0: + raise HTTPException(400, "Empty file") + + if len(content) > MAX_FEED_IMAGE_SIZE_BYTES: + raise HTTPException( + 400, + f"File too large: {len(content)} bytes. Max: {MAX_FEED_IMAGE_SIZE_BYTES} bytes", + ) + + pool = await get_pool() + async with pool.acquire() as conn: + # Проверяем, что пост существует + post_exists = await conn.fetchval( + "SELECT 1 FROM feed_posts WHERE id = $1", post_id + ) + if not post_exists: + raise HTTPException(404, "Post not found") + + # Проверяем лимит вложений + current_count = await conn.fetchval(""" + SELECT COUNT(*) FROM feed_attachments WHERE post_id = $1 + """, post_id) or 0 + + if current_count >= MAX_FEED_ATTACHMENTS: + raise HTTPException( + 400, + f"Max {MAX_FEED_ATTACHMENTS} attachments per post (already {current_count})", + ) + + # Готовим имя файла: {post_id}_{order}_{uuid8}.{ext} + ext_map = { + "image/jpeg": "jpg", + "image/jpg": "jpg", + "image/png": "png", + "image/webp": "webp", + "image/gif": "gif", + } + ext = ext_map.get(content_type, "jpg") + order_number = current_count # 0, 1, 2 + filename = f"{post_id}_{order_number}_{uuid.uuid4().hex[:8]}.{ext}" + + # Сохраняем на диск + feed_uploads_dir = Path(UPLOADS_DIR) / "feed" + feed_uploads_dir.mkdir(parents=True, exist_ok=True) + file_path_disk = feed_uploads_dir / filename + file_path_disk.write_bytes(content) + + # Публичный URL для фронта (относительный — фронт сам подставит API_BASE) + public_path = f"/uploads/feed/{filename}" + + # Пишем в БД + await conn.execute(""" + INSERT INTO feed_attachments (post_id, file_path, file_type, order_number) + VALUES ($1, $2, $3, $4) + """, post_id, public_path, "image", order_number) + + return { + "status": "ok", + "file_path": public_path, + "order_number": order_number, + } + + +@router.post("/admin/feed/translate") +async def admin_translate_feed(request: Request): + """ + Перевести title+body БЕЗ сохранения в БД. + Используется для превью перевода в админ-UI. + + Тело запроса: + { + "title": "...", + "body": "...", + "source_language": "ru" + } + + Возвращает: + { + "title_pl": "...", "title_ru": "...", "title_uk": "...", "title_en": "...", + "body_pl": "...", "body_ru": "...", "body_uk": "...", "body_en": "..." + } + """ + telegram_id, _ = await require_auth(request) + _require_admin(telegram_id) + + body = await request.json() + title = (body.get("title") or "").strip() + post_body = (body.get("body") or "").strip() + source_language = body.get("source_language", "ru").strip().lower() + + if source_language not in FEED_TARGET_LANGUAGES: + raise HTTPException(400, f"Invalid source_language. Allowed: {FEED_TARGET_LANGUAGES}") + + if not title and not post_body: + raise HTTPException(400, "Either title or body is required") + + translations = await translate_to_all_languages(title, post_body, source_language) + + if not translations: + raise HTTPException(500, "Translation failed (AI unavailable or invalid response)") + + return translations \ No newline at end of file diff --git a/routers/game.py b/routers/game.py new file mode 100644 index 0000000..93291bf --- /dev/null +++ b/routers/game.py @@ -0,0 +1,330 @@ +import json +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool + +router = APIRouter(prefix="/game", tags=["game"]) + + +@router.get("/progress") +async def get_progress(request: Request): + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT last_completed_level, current_level FROM users WHERE telegram_id = $1", + telegram_id + ) + + if not user: + return { + "last_completed_level": 0, + "total_score": 0, + "current_level": "A1" + } + + current_level = user["current_level"] or "A1" + + # Очки из филвордов + wordsearch_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM user_progress WHERE user_id = $1", + telegram_id + ) + + # Очки из предложений + sentence_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM sentence_progress WHERE user_id = $1", + telegram_id + ) + + # Очки из квиза + wordquiz_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) + + # Очки из Bubble Words + bubblewords_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) + + total_score = (wordsearch_score or 0) + (sentence_score or 0) + (wordquiz_score or 0) + (bubblewords_score or 0) + + return { + "last_completed_level": user["last_completed_level"] or 0, + "total_score": total_score, + "current_level": current_level + } + + +@router.get("/level/{level_number}") +async def get_level(request: Request, level_number: int): + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT app_language, current_level, last_completed_level FROM users WHERE telegram_id = $1", telegram_id + ) + + if not user: + raise HTTPException(401, "User not registered") + + lang = user["app_language"] or "pl" + current_level = user["current_level"] or "A1" + last_completed = user["last_completed_level"] or 0 + + # Проверяем, что уровень доступен (не дальше следующего за пройденным) + if level_number > 1 and level_number > last_completed + 1: + raise HTTPException(403, "Level not available yet. Complete previous level first.") + + # Получаем уровень по его номеру ВНУТРИ выбранного уровня + level = await conn.fetchrow( + "SELECT * FROM levels WHERE level = $1 AND level_number = $2", current_level, level_number + ) + + if not level: + raise HTTPException(404, "Level not found") + + words = await conn.fetch( + "SELECT * FROM level_words WHERE level_id = $1", level["id"] + ) + + progress = await conn.fetchrow( + "SELECT * FROM user_progress WHERE user_id = $1 AND level_id = $2", + telegram_id, level["id"], + ) + + word_list = [] + for w in words: + translation = w.get(f"translation_{lang}", "") or w.get("translation_pl", "") or w.get("translation_en", "") + word_list.append({ + "word_pl": w["word_pl"], + "translation": translation, + }) + + grid_letters = level["grid_letters"] + if isinstance(grid_letters, str): + grid_letters = json.loads(grid_letters) + + word_paths = level["word_paths"] + if isinstance(word_paths, str): + word_paths = json.loads(word_paths) + + return { + "level": { + "id": level["id"], + "level_number": level["level_number"], + "grid_size": level["grid_size"], + "grid_letters": grid_letters, + "word_paths": word_paths, + "level": level["level"], + }, + "words": word_list, + "progress": { + "completed": progress is not None, + "hints_used": progress["hints_used"] if progress else 0, + "score": progress["score"] if progress else 0, + }, + } + + +@router.post("/check-word") +async def check_word(request: Request): + telegram_id, _ = await require_auth(request) + body = await request.json() + level_id = body.get("level_id") + selected_cells = body.get("cells", []) + + if not level_id or not selected_cells: + raise HTTPException(400, "level_id and cells required") + + pool = await get_pool() + found_word = None + perfect_count = body.get("perfect_streak", 0) + + async with pool.acquire() as conn: + level = await conn.fetchrow("SELECT * FROM levels WHERE id = $1", level_id) + if not level: + raise HTTPException(404, "Level not found") + + word_paths = level["word_paths"] + if isinstance(word_paths, str): + word_paths = json.loads(word_paths) + + grid_letters = level["grid_letters"] + if isinstance(grid_letters, str): + grid_letters = json.loads(grid_letters) + + selected_word = '' + for cell in selected_cells: + r, c = cell[0], cell[1] + try: + selected_word += grid_letters[r][c] + except (IndexError, TypeError): + continue + selected_word = selected_word.lower() + + for word in word_paths.keys(): + if word.lower() == selected_word: + found_word = word + break + + # 🔧 ИСПРАВЛЕНО: вызов достижений ВНЕ блока async with pool.acquire() + if found_word: + from routers.achievements import check_and_award_achievements + + new_achievements = [] + if perfect_count > 0: + ach = await check_and_award_achievements(telegram_id, "perfect_words", perfect_count) + new_achievements.extend(ach) + + return { + "status": "ok", + "found": True, + "word": found_word, + "new_achievements": new_achievements + } + + return {"status": "ok", "found": False} + + +@router.post("/complete-level") +async def complete_level(request: Request): + """Завершение уровня с проверкой на читерство и выдачей достижений""" + telegram_id, _ = await require_auth(request) + body = await request.json() + level_id = body.get("level_id") + hints_used = body.get("hints_used", 0) + completion_time = body.get("completion_time") + perfect_streak = body.get("perfect_streak", 0) + + if not level_id: + raise HTTPException(400, "level_id required") + + hints_used = min(max(0, hints_used), 3) + + # Защита от читерства: минимальное время 5 секунд + if completion_time is not None and completion_time < 5: + raise HTTPException(400, "Completion time too fast. Minimum 5 seconds required.") + + pool = await get_pool() + + # 🔧 ИСПРАВЛЕНО: все проверки и запись прогресса — внутри одного блока + # все данные для достижений собираем здесь, а сами вызовы делаем снаружи + already_completed = False + existing_score = 0 + score = 0 + levels_completed = 0 + grand_total = 0 + + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT id, telegram_id, last_completed_level, current_level FROM users WHERE telegram_id = $1", + telegram_id + ) + if not user: + raise HTTPException(401, "User not registered") + + level = await conn.fetchrow( + "SELECT id, level_number, grid_size, level FROM levels WHERE id = $1", level_id + ) + if not level: + raise HTTPException(404, "Level not found") + + current_level_number = level["level_number"] + level_name = level["level"] or "A1" + + # Проверяем, что уровень принадлежит текущему уровню пользователя + if level_name != (user["current_level"] or "A1"): + raise HTTPException(403, "This level does not belong to your current level") + + existing_progress = await conn.fetchrow( + "SELECT score FROM user_progress WHERE user_id = $1 AND level_id = $2", + telegram_id, level_id + ) + + if existing_progress: + already_completed = True + existing_score = existing_progress["score"] + else: + score = max(10, 100 - hints_used * 10) + + await conn.execute( + """INSERT INTO user_progress (user_id, level_id, completed_at, hints_used, score, level) + VALUES ($1, $2, NOW(), $3, $4, $5)""", + telegram_id, level_id, hints_used, score, level_name, + ) + + # Обновляем last_completed_level (максимальный номер пройденного уровня) + await conn.execute( + """UPDATE users + SET last_completed_level = GREATEST(last_completed_level, $2) + WHERE telegram_id = $1""", + telegram_id, current_level_number, + ) + + # Собираем данные для достижений внутри блока + levels_completed = await conn.fetchval( + "SELECT COUNT(*) FROM user_progress WHERE user_id = $1", + telegram_id + ) or 0 + + total_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM user_progress WHERE user_id = $1", + telegram_id + ) or 0 + sentence_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM sentence_progress WHERE user_id = $1", + telegram_id + ) or 0 + wordquiz_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + bubblewords_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) or 0 + grand_total = total_score + sentence_score + wordquiz_score + bubblewords_score + + # Если уровень уже был пройден — просто возвращаем результат + if already_completed: + return { + "status": "ok", + "score": existing_score, + "already_completed": True, + "new_achievements": [] + } + + # 🔧 ИСПРАВЛЕНО: вызовы достижений ВНЕ блока async with pool.acquire() + from routers.achievements import check_and_award_achievements + new_achievements = [] + + ach = await check_and_award_achievements(telegram_id, "levels_completed", levels_completed) + new_achievements.extend(ach) + + if hints_used == 0: + ach = await check_and_award_achievements(telegram_id, "no_hints_level", 1) + new_achievements.extend(ach) + + if completion_time is not None and completion_time > 0: + if int(completion_time) <= 60: + ach = await check_and_award_achievements(telegram_id, "speed_level", 60) + new_achievements.extend(ach) + + ach = await check_and_award_achievements(telegram_id, "total_score", grand_total) + new_achievements.extend(ach) + + if perfect_streak >= 5: + ach = await check_and_award_achievements(telegram_id, "perfect_words", perfect_streak) + new_achievements.extend(ach) + + return { + "status": "ok", + "score": score, + "already_completed": False, + "new_achievements": new_achievements + } \ No newline at end of file diff --git a/routers/hints.py b/routers/hints.py new file mode 100644 index 0000000..664821a --- /dev/null +++ b/routers/hints.py @@ -0,0 +1,152 @@ +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool + +router = APIRouter(prefix="/hints", tags=["hints"]) + +@router.get("/first-letter/{level_id}") +async def get_first_letter_hint(request: Request, level_id: int): + """Подсказка: показывает первую букву случайного ненайденного слова""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + # Проверяем, что уровень существует + level = await conn.fetchrow("SELECT * FROM levels WHERE id = $1", level_id) + if not level: + raise HTTPException(404, "Level not found") + + # Проверяем, что пользователь существует + user_exists = await conn.fetchval( + "SELECT 1 FROM users WHERE telegram_id = $1", telegram_id + ) + if not user_exists: + raise HTTPException(401, "User not registered") + + # Получаем прогресс пользователя по этому уровню + progress = await conn.fetchrow( + "SELECT hints_used FROM user_progress WHERE user_id = $1 AND level_id = $2", + telegram_id, level_id + ) + + hints_already_used = progress["hints_used"] if progress else 0 + + # Получаем все слова уровня + words = await conn.fetch( + "SELECT word_pl FROM level_words WHERE level_id = $1", level_id + ) + + if not words: + raise HTTPException(404, "No words found for this level") + + word_paths = level["word_paths"] + if isinstance(word_paths, str): + import json + word_paths = json.loads(word_paths) + + # Находим первое слово, у которого есть путь + all_level_words = [w["word_pl"] for w in words] + + # Ищем слово с путём (сначала основные, потом filler-слова) + found_word = None + first_cell = None + + for word in all_level_words: + if word in word_paths and word_paths[word]: + found_word = word + first_cell = word_paths[word][0] + break + + if not found_word: + # Если пути не нашлись — берём любое слово + found_word = all_level_words[0] + first_cell = [0, 0] + + return { + "status": "ok", + "word": found_word, + "first_cell": first_cell, + "hints_used_total": hints_already_used, + } + +@router.get("/word-list/{level_id}") +async def get_word_list(request: Request, level_id: int): + """Подсказка: показывает список всех слов уровня с переводами""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + # Проверяем, что уровень существует + level = await conn.fetchrow("SELECT id FROM levels WHERE id = $1", level_id) + if not level: + raise HTTPException(404, "Level not found") + + # Проверяем, что пользователь существует + user_exists = await conn.fetchval( + "SELECT 1 FROM users WHERE telegram_id = $1", telegram_id + ) + if not user_exists: + raise HTTPException(401, "User not registered") + + # Получаем прогресс пользователя + progress = await conn.fetchrow( + "SELECT hints_used FROM user_progress WHERE user_id = $1 AND level_id = $2", + telegram_id, level_id + ) + + hints_already_used = progress["hints_used"] if progress else 0 + + # Получаем слова + words = await conn.fetch( + "SELECT * FROM level_words WHERE level_id = $1 ORDER BY word_pl", level_id + ) + + # Определяем язык пользователя + user = await conn.fetchrow( + "SELECT app_language FROM users WHERE telegram_id = $1", telegram_id + ) + lang = user["app_language"] if user else "pl" + + # Формируем список с переводами + translation_field = f"translation_{lang}" + word_list = [] + for w in words: + translation = ( + w.get(translation_field) or + w.get("translation_pl") or + w.get("translation_en") or + "" + ) + word_list.append({ + "word_pl": w["word_pl"], + "translation": translation, + }) + + return { + "status": "ok", + "words": word_list, + "total_words": len(word_list), + "hints_used_total": hints_already_used, + } + +@router.get("/remaining/{level_id}") +async def get_remaining_hints(request: Request, level_id: int): + """Возвращает количество оставшихся подсказок для уровня""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + progress = await conn.fetchrow( + "SELECT hints_used FROM user_progress WHERE user_id = $1 AND level_id = $2", + telegram_id, level_id + ) + + hints_used = progress["hints_used"] if progress else 0 + max_hints = 3 + remaining = max(0, max_hints - hints_used) + + return { + "max_hints": max_hints, + "hints_used": hints_used, + "remaining": remaining, + } \ No newline at end of file diff --git a/routers/leaderboard.py b/routers/leaderboard.py new file mode 100644 index 0000000..aef948d --- /dev/null +++ b/routers/leaderboard.py @@ -0,0 +1,333 @@ +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool +from config import ADMIN_IDS + +router = APIRouter(prefix="/leaderboard", tags=["leaderboard"]) + +LEVELS = ["A1", "A2", "B1", "B2", "C1", "C2"] + + +@router.get("") +async def get_leaderboard(request: Request, limit: int = 50): + """Рейтинг игроков — быстрое чтение из кэша""" + telegram_id, _ = await require_auth(request) + + if limit < 1: + limit = 1 + elif limit > 100: + limit = 100 + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT 1, current_level FROM users WHERE telegram_id = $1", telegram_id + ) + if not user: + raise HTTPException(401, "User not registered") + + current_level = user["current_level"] or "A1" + + # Быстрое чтение из MATERIALIZED VIEW + rows = await conn.fetch(""" + SELECT * FROM leaderboard_cache + ORDER BY total_score DESC + LIMIT $1 + """, limit) + + leaderboard = [] + for i, row in enumerate(rows): + leaderboard.append({ + "rank": i + 1, + "telegram_id": row["telegram_id"], + "username": row["username"] or f"Player{row['telegram_id']}", + "total_score": row["total_score"], + "wordsearch_score": row["wordsearch_score"], + "sentence_score": row["sentence_score"], + "wordquiz_score": row["wordquiz_score"], + "words_guessed": row["words_guessed"], + "bubblewords_score": row["bubblewords_score"], + "bubble_levels_completed": row["bubble_levels_completed"], + "levels_completed": 0, + "sentences_completed": 0, + }) + + # Место пользователя + user_rank = await conn.fetchval(""" + SELECT COUNT(*) + 1 FROM leaderboard_cache + WHERE total_score > ( + SELECT COALESCE(total_score, 0) FROM leaderboard_cache WHERE telegram_id = $1 + ) + """, telegram_id) + + # Персональная статистика пользователя + my_row = await conn.fetchrow(""" + SELECT * FROM leaderboard_cache WHERE telegram_id = $1 + """, telegram_id) + + if my_row: + my_wordsearch = my_row["wordsearch_score"] + my_sentence = my_row["sentence_score"] + my_wordquiz = my_row["wordquiz_score"] + my_words_guessed = my_row["words_guessed"] + my_bubblewords = my_row["bubblewords_score"] + my_bubble_levels = my_row["bubble_levels_completed"] + else: + my_wordsearch = 0 + my_sentence = 0 + my_wordquiz = 0 + my_words_guessed = 0 + my_bubblewords = 0 + my_bubble_levels = 0 + + # Считаем НАПРЯМУЮ из основных таблиц + my_wordsearch_levels = await conn.fetchval( + "SELECT COUNT(DISTINCT level_id) FROM user_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + + my_sentences_completed = await conn.fetchval( + "SELECT COUNT(*) FROM sentence_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + + # Если пользователя нет в кэше — считаем очки из основных таблиц + if not my_row: + my_wordsearch = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM user_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + + my_sentence = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM sentence_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + + my_wordquiz = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + + my_words_guessed = await conn.fetchval( + "SELECT COALESCE(words_guessed, 0) FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + + my_bubblewords = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) or 0 + + my_bubble_levels = await conn.fetchval( + "SELECT COALESCE(levels_completed, 0) FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) or 0 + + my_total = my_wordsearch + my_sentence + my_wordquiz + my_bubblewords + my_position = user_rank or 1 + + # 🔧 ФИКС N+1 (19.09.2026): 48 запросов → 5. + # Было: цикл по 6 уровням × 8 запросов = 48 round-trip к БД. + # Стало: 5 агрегированных запросов + сборка level_stats в Python. + + # 1. Справочники (не зависят от юзера) — одним запросом + ref_row = await conn.fetchrow(""" + SELECT + (SELECT COUNT(*) FROM levels WHERE level = 'A1') AS a1_levels, + (SELECT COUNT(*) FROM levels WHERE level = 'A2') AS a2_levels, + (SELECT COUNT(*) FROM levels WHERE level = 'B1') AS b1_levels, + (SELECT COUNT(*) FROM levels WHERE level = 'B2') AS b2_levels, + (SELECT COUNT(*) FROM levels WHERE level = 'C1') AS c1_levels, + (SELECT COUNT(*) FROM levels WHERE level = 'C2') AS c2_levels, + (SELECT COUNT(*) FROM sentences WHERE level = 'A1') AS a1_sent, + (SELECT COUNT(*) FROM sentences WHERE level = 'A2') AS a2_sent, + (SELECT COUNT(*) FROM sentences WHERE level = 'B1') AS b1_sent, + (SELECT COUNT(*) FROM sentences WHERE level = 'B2') AS b2_sent, + (SELECT COUNT(*) FROM sentences WHERE level = 'C1') AS c1_sent, + (SELECT COUNT(*) FROM sentences WHERE level = 'C2') AS c2_sent + """) + + # 2. Очки и прогресс по всем уровням сразу — 4 запроса с GROUP BY + ws_rows = await conn.fetch(""" + SELECT level, + COALESCE(SUM(score), 0) AS score, + COUNT(*) AS completed + FROM user_progress + WHERE user_id = $1 AND completed_at IS NOT NULL + GROUP BY level + """, telegram_id) + ws_by_level = {r["level"]: r for r in ws_rows} + + s_rows = await conn.fetch(""" + SELECT level, + COALESCE(SUM(score), 0) AS score, + COUNT(*) AS completed + FROM sentence_progress + WHERE user_id = $1 AND completed_at IS NOT NULL + GROUP BY level + """, telegram_id) + s_by_level = {r["level"]: r for r in s_rows} + + wq_rows = await conn.fetch(""" + SELECT level, COALESCE(total_score, 0) AS score + FROM word_quiz_progress + WHERE user_id = $1 + """, telegram_id) + wq_by_level = {r["level"]: r for r in wq_rows} + + bw_rows = await conn.fetch(""" + SELECT level, COALESCE(total_score, 0) AS score + FROM bubble_words_progress + WHERE user_id = $1 + """, telegram_id) + bw_by_level = {r["level"]: r for r in bw_rows} + + # 3. Собираем level_stats в Python — без единого запроса + level_stats = {} + for lvl in LEVELS: + lvl_lower = lvl.lower() + + ws_score = ws_by_level.get(lvl, {}).get("score", 0) or 0 + ws_completed = ws_by_level.get(lvl, {}).get("completed", 0) or 0 + s_score = s_by_level.get(lvl, {}).get("score", 0) or 0 + s_completed = s_by_level.get(lvl, {}).get("completed", 0) or 0 + wq_score = wq_by_level.get(lvl, {}).get("score", 0) or 0 + bw_score = bw_by_level.get(lvl, {}).get("score", 0) or 0 + + total_ws_levels = ref_row[f"{lvl_lower}_levels"] or 0 + total_sentences = ref_row[f"{lvl_lower}_sent"] or 0 + + total_items = total_ws_levels + total_sentences + completed_items = ws_completed + s_completed + progress_percent = round((completed_items / total_items * 100), 1) if total_items > 0 else 0 + + level_stats[lvl] = { + "total_score": ws_score + s_score + wq_score + bw_score, + "progress_percent": progress_percent, + "wordsearch_score": ws_score, + "sentence_score": s_score, + "wordquiz_score": wq_score, + "bubblewords_score": bw_score, + } + + # 🔧 ИСПРАВЛЕНО: вызов достижений ВНЕ блока async with pool.acquire() + from routers.achievements import check_and_award_achievements + if my_position <= 3: + await check_and_award_achievements(telegram_id, "rank_reached", my_position) + + return { + "leaderboard": leaderboard, + "current_level": current_level, + "my_rank": { + "rank": my_position, + "telegram_id": telegram_id, + "total_score": my_total, + "wordsearch_score": my_wordsearch, + "wordsearch_levels": my_wordsearch_levels, + "sentence_score": my_sentence, + "sentences_completed": my_sentences_completed, + "wordquiz_score": my_wordquiz, + "words_guessed": my_words_guessed, + "bubblewords_score": my_bubblewords, + "bubble_levels_completed": my_bubble_levels, + }, + "level_stats": level_stats, + } + + +@router.get("/admin/stats") +async def get_admin_stats(request: Request): + """Админ-статистика: только для ADMIN_IDS""" + telegram_id, _ = await require_auth(request) + + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + pool = await get_pool() + async with pool.acquire() as conn: + total_users = await conn.fetchval("SELECT COUNT(*) FROM users") or 0 + + new_today = await conn.fetchval( + "SELECT COUNT(*) FROM users WHERE created_at::date = CURRENT_DATE" + ) or 0 + + online_now = await conn.fetchval(""" + SELECT COUNT(DISTINCT user_id) FROM ( + SELECT user_id FROM user_progress WHERE completed_at > NOW() - INTERVAL '30 minutes' + UNION + SELECT user_id FROM sentence_progress WHERE completed_at > NOW() - INTERVAL '30 minutes' + UNION + SELECT user_id FROM daily_logins WHERE login_date = CURRENT_DATE + ) active + """) or 0 + + ws_players = await conn.fetchval( + "SELECT COUNT(DISTINCT user_id) FROM user_progress WHERE completed_at IS NOT NULL" + ) or 0 + + s_players = await conn.fetchval( + "SELECT COUNT(DISTINCT user_id) FROM sentence_progress WHERE completed_at IS NOT NULL" + ) or 0 + + wq_players = await conn.fetchval( + "SELECT COUNT(*) FROM word_quiz_progress WHERE words_guessed > 0" + ) or 0 + + bw_players = await conn.fetchval( + "SELECT COUNT(*) FROM bubble_words_progress WHERE levels_completed > 0" + ) or 0 + + # 🔧 ИСПРАВЛЕНО: 'open_flashcards' → 'open_teacher_menu' + # Раньше метрика всегда была 0, потому что такого кода достижения больше нет + teacher_menu_opened = await conn.fetchval(""" + SELECT COUNT(*) FROM user_achievements ua + JOIN achievements a ON ua.achievement_id = a.id + WHERE a.code = 'open_teacher_menu' + """) or 0 + + # Количество пользователей по уровням + level_counts = {} + for lvl in LEVELS: + count = await conn.fetchval( + "SELECT COUNT(*) FROM users WHERE current_level = $1", lvl + ) or 0 + level_counts[lvl] = count + + return { + "total_users": total_users, + "new_today": new_today, + "online_now": online_now, + "wordsearch_players": ws_players, + "sentence_players": s_players, + "wordquiz_players": wq_players, + "bubblewords_players": bw_players, + "teacher_menu_opened": teacher_menu_opened, + "level_counts": level_counts, + } + + +@router.get("/top") +async def get_top_players(request: Request): + """Топ-3 игрока для главного экрана — из кэша""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch(""" + SELECT telegram_id, username, total_score + FROM leaderboard_cache + ORDER BY total_score DESC + LIMIT 3 + """) + + top3 = [] + medals = ["🥇", "🥈", "🥉"] + for i, row in enumerate(rows): + top3.append({ + "rank": i + 1, + "medal": medals[i], + "username": row["username"] or f"Player{row['telegram_id']}", + "total_score": row["total_score"], + }) + + return {"top3": top3} \ No newline at end of file diff --git a/routers/learning.py b/routers/learning.py new file mode 100644 index 0000000..66a0f69 --- /dev/null +++ b/routers/learning.py @@ -0,0 +1,872 @@ +""" +Learning Router — система уроков Filwords PL. +Уровни → Темы → Уроки → Финальный тест → Аналитика. +Данные в отдельных файлах: learning_data/level_*.py +""" +import logging +import json +import statistics +from datetime import datetime, timezone +import httpx +import re +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool +from config import TOGETHER_API_KEY +from .learning_data import init_learning_data +from .learning_profile import get_weak_skills, get_strong_skills + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/learning", tags=["learning"]) + +TOGETHER_API_URL = "https://api.together.xyz/v1/chat/completions" +ANALYTICS_MODEL = "MiniMaxAI/MiniMax-M3" + +# Доступные функции приложения (для AI — чтобы не галлюцинировал) +AVAILABLE_FEATURES = [ + "lessons", + "grammar_rules", + "cheat_sheets", + "word_game", + "sentence_game", + "choose_word", + "word_bubbles", + "pronunciation", + "ai_chat", +] + +# Понятные названия разделов для пользователя +AVAILABLE_FEATURES_DESCRIPTION = """ +Доступные разделы приложения (называй их ТАК, как они называются в интерфейсе пользователя): +- "Уроки" — уроки и тесты +- "Филворды" — игра в слова (найди слова в сетке букв) +- "Составь предложение" — составление предложений из слов +- "Выбери слово" — выбор правильного перевода +- "Пузыри слов" — сбор слов из пузырей +- "Произношение" — практика произношения +- "Грамматика" — правила и шпаргалки +- "AI-помощник" — чат с ИИ + +НИКОГДА не используй технические названия: word_game, sentence_game, choose_word, word_bubbles, ai_chat, lessons, pronunciation, grammar_rules, cheat_sheets. +""" + + +async def get_skill_names(conn): + """Загружает понятные названия навыков из БД (title_ru уроков).""" + rows = await conn.fetch(""" + SELECT DISTINCT ON (skill_tag) skill_tag, title_ru + FROM learning_lessons + WHERE is_active = TRUE + ORDER BY skill_tag, order_number + """) + return {r["skill_tag"]: r["title_ru"] for r in rows} + + +async def get_weak_lessons(conn, skill_tags): + """Находит уроки для перепрохождения по слабым навыкам.""" + rows = await conn.fetch(""" + SELECT DISTINCT ON (l.skill_tag) l.lesson_id, l.skill_tag, l.title_ru, t.name_ru as topic_name + FROM learning_lessons l + JOIN learning_topics t ON l.topic_id = t.topic_id + WHERE l.skill_tag = ANY($1) AND l.is_active = TRUE + ORDER BY l.skill_tag, l.order_number + """, skill_tags) + return [dict(r) for r in rows] + + +async def update_skill_mastery(conn, user_id: int, skill_tag: str): + """Рассчитывает и обновляет мастерство по навыку на основе всех ответов пользователя""" + + # Все ответы по навыку с question_type и wrong_because + answers = await conn.fetch(""" + SELECT correct, time_taken_ms, hint_used, question_type, wrong_because, is_final_answer, created_at + FROM user_learning_answers + WHERE user_id = $1 AND skill_tag = $2 + ORDER BY created_at ASC + """, user_id, skill_tag) + + if not answers: + return None + + total_attempts = len(answers) + correct_count = sum(1 for a in answers if a["correct"]) + accuracy = (correct_count / total_attempts * 100) if total_attempts > 0 else 0 + + # Последние попытки + recent = answers[-5:] + recent_correct = sum(1 for a in recent if a["correct"]) + recent_accuracy = (recent_correct / len(recent) * 100) if recent else 0 + + # last_3 / last_5 / last_10 accuracy + def calc_last_n(n): + last_n = answers[-n:] if len(answers) >= n else None + if not last_n or len(last_n) < n: + return None + correct = sum(1 for a in last_n if a["correct"]) + return round((correct / n * 100), 2) + + last_3_accuracy = calc_last_n(3) + last_5_accuracy = calc_last_n(5) + last_10_accuracy = calc_last_n(10) + + # Время: среднее, медиана + all_times = [a["time_taken_ms"] for a in answers if a["time_taken_ms"] and a["time_taken_ms"] > 0] + correct_times = [a["time_taken_ms"] for a in answers if a["correct"] and a["time_taken_ms"] and a["time_taken_ms"] > 0] + wrong_times = [a["time_taken_ms"] for a in answers if not a["correct"] and a["time_taken_ms"] and a["time_taken_ms"] > 0] + + avg_time_ms = int(sum(correct_times) / len(correct_times)) if correct_times else 0 + median_time_ms = int(statistics.median(all_times)) if all_times else 0 + median_correct_time_ms = int(statistics.median(correct_times)) if correct_times else 0 + median_wrong_time_ms = int(statistics.median(wrong_times)) if wrong_times else 0 + + # Зависимость от подсказок + hints_used = sum(1 for a in answers if a["hint_used"]) + hint_dependency = (hints_used / total_attempts * 100) if total_attempts > 0 else 0 + + # Разделение recognition / production / application + recognition_answers = [a for a in answers if a["question_type"] == "recognition"] + production_answers = [a for a in answers if a["question_type"] == "production"] + application_answers = [a for a in answers if a["question_type"] == "application"] + + recognition_attempts = len(recognition_answers) + recognition_correct = sum(1 for a in recognition_answers if a["correct"]) + production_attempts = len(production_answers) + production_correct = sum(1 for a in production_answers if a["correct"]) + application_attempts = len(application_answers) + application_correct = sum(1 for a in application_answers if a["correct"]) + + recognition_score = round((recognition_correct / recognition_attempts * 100), 2) if recognition_attempts > 0 else None + production_score = round((production_correct / production_attempts * 100), 2) if production_attempts > 0 else None + application_score = round((application_correct / application_attempts * 100), 2) if application_attempts > 0 else None + + # Passive / Active knowledge + passive_knowledge = recognition_score if recognition_score is not None else 0 + active_scores = [s for s in [production_score, application_score] if s is not None] + active_knowledge = round(sum(active_scores) / len(active_scores), 2) if active_scores else 0 + + # Ошибки + error_count = sum(1 for a in answers if not a["correct"] and a["wrong_because"]) + error_types = {} + for a in answers: + if not a["correct"] and a["wrong_because"]: + error_types[a["wrong_because"]] = error_types.get(a["wrong_because"], 0) + 1 + repeated_error_count = sum(1 for count in error_types.values() if count >= 2) + + # Дней с последней попытки + last_attempt = answers[-1]["created_at"] + if last_attempt: + now = datetime.now(timezone.utc) + if last_attempt.tzinfo is None: + last_attempt = last_attempt.replace(tzinfo=timezone.utc) + days_since = (now - last_attempt).days + else: + days_since = 0 + + # Мастерство + no_hint_score = max(0, 100 - hint_dependency) + mastery = round(accuracy * 0.4 + recent_accuracy * 0.3 + no_hint_score * 0.3, 2) + + # Получаем прошлый mastery для расчёта delta + previous_row = await conn.fetchrow(""" + SELECT mastery_score, previous_mastery_score FROM user_skill_mastery + WHERE user_id = $1 AND skill_tag = $2 + """, user_id, skill_tag) + + previous_mastery = float(previous_row["mastery_score"]) if previous_row and previous_row["mastery_score"] else mastery + mastery_delta = round(mastery - previous_mastery, 2) + + # Trend + if total_attempts < 3: + trend = "insufficient_data" + elif last_3_accuracy is not None and last_10_accuracy is not None: + if last_3_accuracy > last_10_accuracy + 5: + trend = "improving" + elif last_3_accuracy < last_10_accuracy - 5: + trend = "declining" + else: + trend = "stable" + elif last_3_accuracy is not None and accuracy is not None: + if last_3_accuracy > accuracy + 5: + trend = "improving" + elif last_3_accuracy < accuracy - 5: + trend = "declining" + else: + trend = "stable" + else: + trend = "stable" + + # Retention status + if days_since == 0: + retention_status = "fresh" + elif days_since <= 3: + retention_status = "fresh" + elif days_since <= 7: + retention_status = "aging" + elif days_since <= 14: + retention_status = "needs_review" + else: + retention_status = "overdue" + + # Fluency score: скорость + точность + автоматизация + speed_score = 100 if median_correct_time_ms and median_correct_time_ms < 5000 else (50 if median_correct_time_ms and median_correct_time_ms < 15000 else 20) + fluency = round(accuracy * 0.4 + active_knowledge * 0.3 + speed_score * 0.3, 2) + + # Уверенность + if len(recent) >= 3: + if all(a["correct"] for a in recent[-3:]): + confidence = min(100, mastery + 15) + elif not any(a["correct"] for a in recent[-3:]): + confidence = max(0, mastery - 20) + else: + confidence = mastery + else: + confidence = mastery + confidence = round(min(100, max(0, confidence)), 2) + + # Сохраняем в user_skill_mastery + await conn.execute(""" + INSERT INTO user_skill_mastery ( + user_id, skill_tag, attempts_count, correct_count, + recognition_attempts, recognition_correct, recognition_score, + production_attempts, production_correct, production_score, + application_attempts, application_correct, application_score, + retention_score, hint_dependency, average_time_ms, median_time_ms, + median_correct_time_ms, median_wrong_time_ms, + recent_accuracy, last_3_accuracy, last_5_accuracy, last_10_accuracy, + long_term_accuracy, mastery_score, previous_mastery_score, mastery_delta, + trend, retention_status, fluency_score, passive_knowledge_score, active_knowledge_score, + confidence, error_count, repeated_error_count, days_since_last_attempt, last_attempt_at + ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, 0, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, NOW()) + ON CONFLICT (user_id, skill_tag) DO UPDATE SET + attempts_count = $3, + correct_count = $4, + recognition_attempts = $5, + recognition_correct = $6, + recognition_score = $7, + production_attempts = $8, + production_correct = $9, + production_score = $10, + application_attempts = $11, + application_correct = $12, + application_score = $13, + hint_dependency = $14, + average_time_ms = $15, + median_time_ms = $16, + median_correct_time_ms = $17, + median_wrong_time_ms = $18, + recent_accuracy = $19, + last_3_accuracy = $20, + last_5_accuracy = $21, + last_10_accuracy = $22, + long_term_accuracy = $23, + mastery_score = $24, + previous_mastery_score = $25, + mastery_delta = $26, + trend = $27, + retention_status = $28, + fluency_score = $29, + passive_knowledge_score = $30, + active_knowledge_score = $31, + confidence = $32, + error_count = $33, + repeated_error_count = $34, + days_since_last_attempt = $35, + last_attempt_at = NOW() + """, user_id, skill_tag, total_attempts, correct_count, recognition_attempts, recognition_correct, recognition_score, production_attempts, production_correct, production_score, application_attempts, application_correct, application_score, hint_dependency, avg_time_ms, median_time_ms, median_correct_time_ms, median_wrong_time_ms, recent_accuracy, last_3_accuracy, last_5_accuracy, last_10_accuracy, accuracy, mastery, previous_mastery, mastery_delta, trend, retention_status, fluency, passive_knowledge, active_knowledge, confidence, error_count, repeated_error_count, days_since) + + return { + "skill_tag": skill_tag, + "attempts": total_attempts, + "accuracy": round(accuracy, 1), + "recent_accuracy": round(recent_accuracy, 1), + "recognition_score": recognition_score, + "production_score": production_score, + "application_score": application_score, + "mastery": mastery, + "mastery_delta": mastery_delta, + "trend": trend, + "retention_status": retention_status, + "fluency": fluency, + "passive_knowledge": passive_knowledge, + "active_knowledge": active_knowledge, + "confidence": confidence, + } + + +async def update_topic_progress(conn, user_id: int, topic_id: str): + """Обновляет прогресс темы: lessons_total, lessons_completed, topic_mastery""" + + # Общее количество уроков в теме + lessons_total = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_lessons WHERE topic_id = $1 AND is_active = TRUE + """, topic_id) or 0 + + # Количество завершённых уроков + lessons_completed = await conn.fetchval(""" + SELECT COUNT(*) FROM user_lesson_progress WHERE user_id = $1 AND lesson_id IN ( + SELECT lesson_id FROM learning_lessons WHERE topic_id = $2 + ) AND completed = TRUE + """, user_id, topic_id) or 0 + + # Тестовый результат + test_row = await conn.fetchrow(""" + SELECT test_completed, test_score FROM user_topic_progress WHERE user_id = $1 AND topic_id = $2 + """, user_id, topic_id) + + test_completed = test_row["test_completed"] if test_row else False + test_score = float(test_row["test_score"]) if test_row and test_row["test_score"] else 0 + + # Среднее мастерство по навыкам темы + skills_avg = await conn.fetchval(""" + SELECT COALESCE(AVG(mastery_score), 0) FROM user_skill_mastery + WHERE user_id = $1 AND skill_tag IN ( + SELECT DISTINCT skill_tag FROM learning_questions WHERE topic_id = $2 + ) + """, user_id, topic_id) or 0 + + # Мастерство темы + if test_completed and test_score > 0: + topic_mastery = round(float(skills_avg) * 0.4 + float(test_score) * 0.6, 2) + else: + topic_mastery = round(float(skills_avg), 2) + + # Обновляем + await conn.execute(""" + INSERT INTO user_topic_progress (user_id, topic_id, lessons_total, lessons_completed, test_completed, test_score, topic_mastery) + VALUES ($1, $2, $3, $4, $5, $6, $7) + ON CONFLICT (user_id, topic_id) DO UPDATE SET + lessons_total = $3, + lessons_completed = $4, + test_completed = $5, + test_score = $6, + topic_mastery = $7 + """, user_id, topic_id, lessons_total, lessons_completed, test_completed, test_score, topic_mastery) + + return { + "lessons_total": lessons_total, + "lessons_completed": lessons_completed, + "test_completed": test_completed, + "test_score": round(test_score, 1), + "topic_mastery": topic_mastery, + } + + +async def update_ai_context(conn, user_id: int): + """Обновляет AI-контекст пользователя: сильные/слабые навыки, общее мастерство, прогресс уровня""" + + # Получаем текущий уровень + current_level = await conn.fetchval(""" + SELECT current_level FROM users WHERE telegram_id = $1 + """, user_id) or "A1" + + # Все темы пользователя + topics = await conn.fetch(""" + SELECT topic_id, topic_mastery, test_completed FROM user_topic_progress WHERE user_id = $1 + """, user_id) + + completed_topics = sum(1 for t in topics if t["test_completed"]) + completed_lessons = await conn.fetchval(""" + SELECT COUNT(*) FROM user_lesson_progress WHERE user_id = $1 AND completed = TRUE + """, user_id) or 0 + + # Всего тем в уровне + level_topics_total = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_topics WHERE level_code = $1 AND is_active = TRUE + """, current_level) or 0 + + # Процент завершения уровня + level_completion_percent = round((completed_topics / level_topics_total * 100), 2) if level_topics_total > 0 else 0 + + # Общее мастерство + overall_mastery = await conn.fetchval(""" + SELECT COALESCE(AVG(topic_mastery), 0) FROM user_topic_progress WHERE user_id = $1 + """, user_id) or 0 + overall_mastery = float(overall_mastery) if overall_mastery else 0 + + # Сильные и слабые навыки — используем общий источник + strong_skills = await get_strong_skills(conn, user_id, limit=8) + weak_skills = await get_weak_skills(conn, user_id, limit=5) + + strong_skill_tags = [s["skill_tag"] for s in strong_skills] + weak_skill_tags = [s["skill_tag"] for s in weak_skills] + + # Частые ошибки + errors = await conn.fetch(""" + SELECT wrong_because, COUNT(*) as cnt + FROM user_learning_answers + WHERE user_id = $1 AND wrong_because IS NOT NULL AND correct = FALSE + GROUP BY wrong_because + ORDER BY cnt DESC + LIMIT 5 + """, user_id) + + recurring_errors = [e["wrong_because"] for e in errors] + + # Обновляем ai_user_context + await conn.execute(""" + INSERT INTO ai_user_context (user_id, current_level, completed_topics, level_topics_total, level_completion_percent, completed_lessons, overall_mastery, strong_skills, weak_skills, recurring_errors, analytics_enabled, last_analysis_at) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, TRUE, NOW()) + ON CONFLICT (user_id) DO UPDATE SET + current_level = $2, + completed_topics = $3, + level_topics_total = $4, + level_completion_percent = $5, + completed_lessons = $6, + overall_mastery = $7, + strong_skills = $8, + weak_skills = $9, + recurring_errors = $10, + analytics_enabled = TRUE, + last_analysis_at = NOW() + """, user_id, current_level, completed_topics, level_topics_total, level_completion_percent, completed_lessons, round(float(overall_mastery), 2), json.dumps(strong_skill_tags), json.dumps(weak_skill_tags), json.dumps(recurring_errors)) + + return { + "completed_topics": completed_topics, + "level_topics_total": level_topics_total, + "level_completion_percent": level_completion_percent, + "completed_lessons": completed_lessons, + "overall_mastery": round(float(overall_mastery), 2), + "strong_skills": strong_skill_tags, + "weak_skills": weak_skill_tags, + } + + +@router.get("/levels") +async def get_learning_levels(request: Request): + """Получить все уровни обучения""" + await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch("SELECT * FROM learning_levels WHERE is_active = TRUE ORDER BY sort_order") + return {"levels": [dict(row) for row in rows]} + + +@router.get("/topics") +async def get_topics(request: Request, level: str = "A1"): + """Получить темы для уровня""" + await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + rows = await conn.fetch("SELECT * FROM learning_topics WHERE level_code = $1 AND is_active = TRUE ORDER BY order_number", level) + return {"topics": [dict(row) for row in rows]} + + +@router.get("/topics/{topic_id}") +async def get_topic(request: Request, topic_id: str): + """Получить информацию о теме и список уроков""" + telegram_id, _ = await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + topic = await conn.fetchrow("SELECT * FROM learning_topics WHERE topic_id = $1", topic_id) + if not topic: + raise HTTPException(404, "Topic not found") + + lessons = await conn.fetch("SELECT * FROM learning_lessons WHERE topic_id = $1 AND is_active = TRUE ORDER BY order_number", topic_id) + + progress = await conn.fetchrow("SELECT * FROM user_topic_progress WHERE user_id = $1 AND topic_id = $2", telegram_id, topic_id) + + lesson_progress = await conn.fetch(""" + SELECT lesson_id, completed FROM user_lesson_progress WHERE user_id = $1 + """, telegram_id) + progress_map = {lp["lesson_id"]: lp["completed"] for lp in lesson_progress} + + lessons_data = [] + for lesson in lessons: + l = dict(lesson) + l["completed"] = progress_map.get(lesson["lesson_id"], False) + lessons_data.append(l) + + return { + "topic": dict(topic), + "lessons": lessons_data, + "progress": dict(progress) if progress else None, + } + + +@router.get("/lessons/{lesson_id}") +async def get_lesson(request: Request, lesson_id: str): + """Получить урок с примерами и вопросами""" + telegram_id, _ = await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + lesson = await conn.fetchrow("SELECT * FROM learning_lessons WHERE lesson_id = $1", lesson_id) + if not lesson: + raise HTTPException(404, "Lesson not found") + + examples = await conn.fetch("SELECT * FROM lesson_examples WHERE lesson_id = $1 ORDER BY order_number", lesson_id) + questions = await conn.fetch("SELECT * FROM learning_questions WHERE lesson_id = $1 AND is_test_question = FALSE ORDER BY id", lesson_id) + + questions_data = [] + for q in questions: + options = await conn.fetch("SELECT * FROM question_options WHERE question_id = $1", q["question_id"]) + questions_data.append({ + "question": dict(q), + "options": [dict(o) for o in options], + }) + + progress = await conn.fetchrow("SELECT * FROM user_lesson_progress WHERE user_id = $1 AND lesson_id = $2", telegram_id, lesson_id) + + return { + "lesson": dict(lesson), + "examples": [dict(e) for e in examples], + "questions": questions_data, + "progress": dict(progress) if progress else None, + } + + +@router.get("/test/{topic_id}") +async def get_topic_test(request: Request, topic_id: str): + """Получить вопросы финального теста""" + await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + questions = await conn.fetch("SELECT * FROM learning_questions WHERE topic_id = $1 AND is_test_question = TRUE ORDER BY test_order", topic_id) + + questions_data = [] + for q in questions: + options = await conn.fetch("SELECT * FROM question_options WHERE question_id = $1", q["question_id"]) + questions_data.append({ + "question": dict(q), + "options": [dict(o) for o in options], + }) + + return {"test": questions_data, "total": len(questions_data)} + + +@router.post("/session/start") +async def start_session(request: Request): + """Начать новую сессию обучения""" + telegram_id, _ = await require_auth(request) + body = await request.json() + level_code = body.get("level_code", "A1") + topic_id = body.get("topic_id", "") + session_type = body.get("session_type", "lesson") + + pool = await get_pool() + async with pool.acquire() as conn: + row = await conn.fetchrow(""" + INSERT INTO learning_sessions (user_id, level_code, topic_id, session_type) + VALUES ($1, $2, $3, $4) RETURNING id + """, telegram_id, level_code, topic_id, session_type) + + return {"session_id": row["id"]} + + +@router.post("/answer") +async def save_answer(request: Request): + """Сохранить ответ пользователя""" + telegram_id, _ = await require_auth(request) + body = await request.json() + session_id = body.get("session_id") + question_id = body.get("question_id") + selected_answer = body.get("answer", "") + time_taken_ms = body.get("time_taken_ms", 0) + is_final = body.get("is_final_answer", True) + + if not session_id or not question_id: + raise HTTPException(400, "session_id and question_id required") + + pool = await get_pool() + async with pool.acquire() as conn: + question = await conn.fetchrow("SELECT * FROM learning_questions WHERE question_id = $1", question_id) + if not question: + raise HTTPException(404, "Question not found") + + correct = selected_answer.strip().lower() == (question["correct_answer"] or "").strip().lower() + + wrong_because = None + if not correct: + option = await conn.fetchrow(""" + SELECT wrong_because FROM question_options + WHERE question_id = $1 AND option_key = $2 + """, question_id, selected_answer) + if option: + wrong_because = option["wrong_because"] + + session = await conn.fetchrow("SELECT * FROM learning_sessions WHERE id = $1", session_id) + + await conn.execute(""" + INSERT INTO user_learning_answers (user_id, session_id, level_code, topic_id, lesson_id, question_id, selected_answer, correct, skill_tag, question_type, context_type, difficulty, time_taken_ms, hint_used, wrong_because, is_final_answer) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16) + """, telegram_id, session_id, session["level_code"], session["topic_id"], question["lesson_id"], question_id, selected_answer, correct, question["skill_tag"], question["question_type"], question["context_type"], question["difficulty"], time_taken_ms, False, wrong_because, is_final) + + return {"correct": correct, "wrong_because": wrong_because} + + +@router.post("/session/complete") +async def complete_session(request: Request): + """Завершить сессию: обновляет прогресс урока/теста, мастерство навыков, прогресс темы и AI-контекст""" + telegram_id, _ = await require_auth(request) + body = await request.json() + session_id = body.get("session_id") + + pool = await get_pool() + async with pool.acquire() as conn: + session = await conn.fetchrow("SELECT * FROM learning_sessions WHERE id = $1 AND user_id = $2", session_id, telegram_id) + if not session: + raise HTTPException(404, "Session not found") + + await conn.execute("UPDATE learning_sessions SET is_completed = TRUE, completed_at = NOW() WHERE id = $1", session_id) + + stats = await conn.fetchrow(""" + SELECT COUNT(*) as total, COALESCE(SUM(CASE WHEN correct THEN 1 ELSE 0 END), 0) as correct_count + FROM user_learning_answers WHERE session_id = $1 AND is_final_answer = TRUE + """, session_id) + + topic_id = session["topic_id"] + + # Обновляем прогресс урока + if session["session_type"] == "lesson": + lesson_row = await conn.fetchrow(""" + SELECT DISTINCT lesson_id FROM user_learning_answers WHERE session_id = $1 AND lesson_id IS NOT NULL + """, session_id) + + if lesson_row and lesson_row["lesson_id"]: + lesson_id = lesson_row["lesson_id"] + score = (stats["correct_count"] / stats["total"] * 100) if stats["total"] > 0 else 0 + + await conn.execute(""" + INSERT INTO user_lesson_progress (user_id, lesson_id, started_at, completed_at, attempts_count, correct_count, best_score, completed) + VALUES ($1, $2, NOW(), NOW(), 1, $3, $4, TRUE) + ON CONFLICT (user_id, lesson_id) DO UPDATE + SET completed_at = NOW(), + attempts_count = user_lesson_progress.attempts_count + 1, + correct_count = user_lesson_progress.correct_count + $3, + best_score = GREATEST(user_lesson_progress.best_score, $4), + completed = TRUE + """, telegram_id, lesson_id, stats["correct_count"], score) + + # Обновляем прогресс темы если это тест + if session["session_type"] == "topic_test": + test_score = (stats["correct_count"] / stats["total"] * 100) if stats["total"] > 0 else 0 + + await conn.execute(""" + INSERT INTO user_topic_progress (user_id, topic_id, test_started, test_completed, test_score, completed_at) + VALUES ($1, $2, TRUE, TRUE, $3, NOW()) + ON CONFLICT (user_id, topic_id) DO UPDATE + SET test_completed = TRUE, + test_score = $3, + completed_at = NOW() + """, telegram_id, topic_id, test_score) + + # Обновляем мастерство по всем навыкам из этой сессии + skill_tags = await conn.fetch(""" + SELECT DISTINCT skill_tag FROM user_learning_answers WHERE session_id = $1 + """, session_id) + + for st in skill_tags: + await update_skill_mastery(conn, telegram_id, st["skill_tag"]) + + # Обновляем прогресс темы ТОЛЬКО для lesson и topic_test + if session["session_type"] in ("lesson", "topic_test") and topic_id: + await update_topic_progress(conn, telegram_id, topic_id) + + # Обновляем AI-контекст (всегда) + await update_ai_context(conn, telegram_id) + + return {"status": "ok", "total": stats["total"], "correct_count": stats["correct_count"]} + + +@router.get("/progress") +async def get_learning_progress(request: Request): + """Получить прогресс пользователя по всем темам""" + telegram_id, _ = await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + topics = await conn.fetch(""" + SELECT tp.*, up.lessons_completed, up.lessons_total, up.test_completed, up.test_score, up.topic_mastery + FROM learning_topics tp + LEFT JOIN user_topic_progress up ON tp.topic_id = up.topic_id AND up.user_id = $1 + ORDER BY tp.level_code, tp.order_number + """, telegram_id) + return {"progress": [dict(t) for t in topics]} + + +@router.post("/analytics") +async def get_analytics(request: Request): + """Анализирует результаты пользователя через AI на основе user_skill_mastery и user_topic_progress""" + telegram_id, _ = await require_auth(request) + + if not TOGETHER_API_KEY: + raise HTTPException(500, "AI API key not configured") + + pool = await get_pool() + async with pool.acquire() as conn: + # Получаем слабые навыки из ОБЩЕГО источника + weak_skills = await get_weak_skills(conn, telegram_id, limit=5) + + if not weak_skills: + return {"analytics_enabled": False, "message": "Отличная работа! У тебя нет слабых навыков."} + + # Загружаем названия навыков из БД + skill_names = await get_skill_names(conn) + skill_tag_lines = '\n'.join([f'- {tag} → "{name}"' for tag, name in skill_names.items()]) + + # Находим уроки для перепрохождения + weak_skill_tags = [s["skill_tag"] for s in weak_skills] + weak_lessons = await get_weak_lessons(conn, weak_skill_tags) + weak_lessons_lines = '\n'.join([f'- {l["title_ru"]} (тема: {l["topic_name"]})' for l in weak_lessons]) + + # Формируем профиль + weak_skills_json = [] + for s in weak_skills: + weak_skills_json.append({ + "skill": s["skill_tag"], + "mastery": round(float(s["mastery_score"]), 1) if s["mastery_score"] else 0, + "repeated_errors": s["repeated_error_count"] or 0, + "retention": s["retention_status"] or "fresh", + "trend": s["trend"] or "stable", + "recent_accuracy": round(float(s["recent_accuracy"]), 1) if s["recent_accuracy"] else 0, + }) + + user_profile = { + "weak_skills": weak_skills_json, + "weak_lessons": [dict(l) for l in weak_lessons], + } + + system_prompt = f"""Ты — AI-наставник польского языка в приложении Filwords PL. +Проанализируй слабые стороны пользователя и скажи что нужно перепройти. + +Понятные названия навыков (используй ИХ в ответе, а не технические ID): +{skill_tag_lines} + +ПРАВИЛА: +1. Не используй markdown +2. Отвечай на языке пользователя +3. НЕ говори о сильных сторонах — только о слабых +4. Говори ТОЛЬКО о тех навыках, которые перечислены в weak_skills +5. Для каждого слабого навыка укажи конкретный урок для перепрохождения +6. НАЗВАНИЯ НАВЫКОВ: всегда заменяй технические ID на понятные названия +7. ОБРАЩАЙСЯ К ПОЛЬЗОВАТЕЛЮ НА "ТЫ" +8. НИКОГДА не пиши имена метрик: mastery, recent_accuracy, retention_status и т.п. — только русский перевод +9. НЕ упоминай процент завершения уровня или количество пройденных тем +10. В конце предложи нажать кнопку "Потренировать слабые темы" — она уже есть под этим сообщением.""" + + user_prompt = f"""Слабые навыки пользователя: + +{json.dumps(user_profile, ensure_ascii=False, indent=2)} + +Напиши: +1. Какие темы ты не понял (конкретные навыки, понятными названиями) +2. Какие уроки нужно перепройти: +{weak_lessons_lines} +3. Нажми кнопку "Потренировать слабые темы" для практики + +В конце напиши: "Готов потренироваться? Нажимай кнопку ниже!\"""" + + async with httpx.AsyncClient(timeout=90.0) as client: + response = await client.post( + TOGETHER_API_URL, + headers={ + "Authorization": f"Bearer {TOGETHER_API_KEY}", + "Content-Type": "application/json", + }, + json={ + "model": ANALYTICS_MODEL, + "messages": [ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": user_prompt}, + ], + "max_tokens": 1000, + "temperature": 0.7, + }, + ) + + if response.status_code != 200: + raise HTTPException(500, f"AI API error: {response.status_code}") + + data = response.json() + ai_response = data["choices"][0]["message"]["content"].strip() + ai_response = ai_response.replace("**", "").replace("*", "").replace("#", "") + + # Убираем технические ID в скобках + ai_response = re.sub(r'\s*\([a-z_]+_[a-z_]+\)', '', ai_response) + + # Если ответ пустой - запасной текст + if not ai_response or len(ai_response) < 10: + ai_response = "Перепройди уроки по слабым темам. Нажми кнопку ниже, чтобы потренироваться!" + + return { + "analytics_enabled": True, + "response": ai_response, + "weak_skills": weak_skills_json, + "has_practice_available": len(weak_skills_json) > 0, + "cta_label": "Потренировать слабые темы", + } + + +@router.get("/ai/context") +async def get_ai_context(request: Request): + """Получить AI-контекст пользователя""" + telegram_id, _ = await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + context = await conn.fetchrow("SELECT * FROM ai_user_context WHERE user_id = $1", telegram_id) + if not context: + return {"analytics_enabled": False, "message": "Пройди первую тему, и я смогу начать анализировать твой прогресс."} + return {"context": dict(context)} + + +@router.post("/practice/start") +async def start_weak_skills_practice(request: Request): + """Собирает сессию практики из реального банка вопросов по слабым навыкам. + Ноль обращений к LLM - только SQL.""" + telegram_id, _ = await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + weak = await get_weak_skills(conn, telegram_id, limit=5) + if not weak: + return {"has_weak_skills": False, "message": "Нет слабых навыков - отличная работа!"} + + skill_tags = [s["skill_tag"] for s in weak] + + # Забираем краткое объяснение правила для каждого слабого навыка + explanations = await conn.fetch(""" + SELECT DISTINCT ON (skill_tag) skill_tag, explanation_ru, explanation_uk, explanation_en, explanation_pl + FROM learning_lessons + WHERE skill_tag = ANY($1) + ORDER BY skill_tag, order_number + """, skill_tags) + explanations_map = {e["skill_tag"]: dict(e) for e in explanations} + + # Вопросы вперемешку по всем слабым навыкам, только не тестовые + questions = await conn.fetch(""" + SELECT * FROM learning_questions + WHERE skill_tag = ANY($1) AND is_test_question = FALSE + ORDER BY random() + LIMIT 10 + """, skill_tags) + + if not questions: + return {"has_weak_skills": True, "questions": [], "message": "Для этих навыков пока нет вопросов в базе."} + + # Получаем уровень пользователя + user_level = await conn.fetchval(""" + SELECT current_level FROM users WHERE telegram_id = $1 + """, telegram_id) or "A1" + + session = await conn.fetchrow(""" + INSERT INTO learning_sessions (user_id, level_code, topic_id, session_type) + VALUES ($1, $2, '', 'weak_skills_practice') RETURNING id + """, telegram_id, user_level) + + questions_data = [] + for q in questions: + options = await conn.fetch( + "SELECT * FROM question_options WHERE question_id = $1", q["question_id"] + ) + questions_data.append({"question": dict(q), "options": [dict(o) for o in options]}) + + # Загружаем понятные названия навыков из БД + skill_names = await get_skill_names(conn) + + return { + "has_weak_skills": True, + "session_id": session["id"], + "explanations": [ + {"skill_tag": tag, "name": skill_names.get(tag, tag), **explanations_map.get(tag, {})} + for tag in skill_tags + ], + "questions": questions_data, + } \ No newline at end of file diff --git a/routers/learning_data/__init__.py b/routers/learning_data/__init__.py new file mode 100644 index 0000000..ddbb9c5 --- /dev/null +++ b/routers/learning_data/__init__.py @@ -0,0 +1,40 @@ +""" +Learning Data Package — данные всех уровней. +Каждый уровень в отдельном файле. +""" +import logging +from database import get_pool +from . import level_a1, level_a2, level_b1, level_b2, level_c1, level_c2 + +logger = logging.getLogger(__name__) + + +async def init_learning_data(): + """Инициализирует уровни и все темы""" + pool = await get_pool() + async with pool.acquire() as conn: + # ============ УРОВНИ ============ + levels = [ + ("A1", "Poziom A1", "Уровень A1", "Рівень A1", "Level A1", 1), + ("A2", "Poziom A2", "Уровень A2", "Рівень A2", "Level A2", 2), + ("B1", "Poziom B1", "Уровень B1", "Рівень B1", "Level B1", 3), + ("B2", "Poziom B2", "Уровень B2", "Рівень B2", "Level B2", 4), + ("C1", "Poziom C1", "Уровень C1", "Рівень C1", "Level C1", 5), + ("C2", "Poziom C2", "Уровень C2", "Рівень C2", "Level C2", 6), + ] + for code, pl, ru, uk, en, sort in levels: + await conn.execute(""" + INSERT INTO learning_levels (code, name_pl, name_ru, name_uk, name_en, sort_order) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT (code) DO NOTHING + """, code, pl, ru, uk, en, sort) + + # Загружаем данные каждого уровня + await level_a1.init_level_a1(conn) + await level_a2.init_level_a2(conn) + await level_b1.init_level_b1(conn) + await level_b2.init_level_b2(conn) + await level_c1.init_level_c1(conn) + await level_c2.init_level_c2(conn) + + logger.info("Learning data fully initialized") \ No newline at end of file diff --git a/routers/learning_data/level_a1.py b/routers/learning_data/level_a1.py new file mode 100644 index 0000000..27af9b3 --- /dev/null +++ b/routers/learning_data/level_a1.py @@ -0,0 +1,7358 @@ +""" +Level A1 — данные всех тем уровня A1. +Тема 1: Приветствия и знакомство (a1_greetings) +""" + + +async def init_level_a1(conn): + """Инициализирует все темы уровня A1""" + + # ==================== ТЕМА 1: ПРИВЕТСТВИЯ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_greetings', 'A1', 1, + 'Powitania i poznawanie się', + 'Приветствия и знакомство', + 'Привітання та знайомство', + 'Greetings and introductions') + ON CONFLICT (topic_id) DO NOTHING + """) + + # Уроки + lessons = [ + ("a1_greetings_l01", 1, "greeting_formal", "Formalne powitanie", "Формальное приветствие", "Формальне привітання", "Formal greeting", + "„Dzień dobry” to podstawowe, bezpieczne formalne powitanie. Używamy go rano i w ciągu dnia.", + "«Dzień dobry» — основное безопасное формальное приветствие. Используется утром и днём.", + "«Dzień dobry» — основне безпечне формальне привітання. Використовується вранці та вдень.", + "“Dzień dobry” is the basic safe formal greeting. Used in the morning and during the day."), + ("a1_greetings_l02", 2, "greeting_informal", "Nieformalne powitanie", "Неформальное приветствие", "Неформальне привітання", "Informal greeting", + "„Cześć!” jest bardzo częstym nieformalnym powitaniem. Używamy go z przyjaciółmi i rodziną.", + "«Cześć!» — очень распространённое неформальное приветствие. Используется с друзьями и семьёй.", + "«Cześć!» — поширене неформальне привітання. Використовується з друзями та родиною.", + "“Cześć!” is a common informal greeting. Used with friends and family."), + ("a1_greetings_l03", 3, "self_intro", "Przedstawianie się", "Как представиться", "Як представитися", "Introducing yourself", + "Możesz powiedzieć „Jestem Anna” albo „Nazywam się Anna”.", + "Можно сказать «Jestem Anna» или «Nazywam się Anna».", + "Можна сказати «Jestem Anna» або «Nazywam się Anna».", + "You can say “Jestem Anna” or “Nazywam się Anna”."), + ("a1_greetings_l04", 4, "asking_name", "Pytanie o imię", "Как спросить имя", "Як запитати ім'я", "Asking someone's name", + "„Jak się nazywasz?” to nieformalne pytanie o imię.", + "«Jak się nazywasz?» — неформальный вопрос «Как тебя зовут?».", + "«Jak się nazywasz?» — неформальне запитання «Як тебе звати?».", + "“Jak się nazywasz?” is an informal way to ask someone's name."), + ("a1_greetings_l05", 5, "answering_name", "Odpowiadanie na pytanie o imię", "Отвечаем на вопрос об имени", "Відповідаємо на запитання про ім'я", "Answering a question about your name", + "Na pytanie „Jak się nazywasz?” możesz odpowiedzieć „Nazywam się Anna.”", + "На вопрос «Как тебя зовут?» можно ответить «Nazywam się Anna».", + "На запитання «Як тебе звати?» можна відповісти «Nazywam się Anna».", + "To answer “What is your name?”, you can say “Nazywam się Anna.”"), + ("a1_greetings_l06", 6, "formal_address_pan_pani", "Forma Pan/Pani", "Формальное обращение Pan/Pani", "Формальне звертання Pan/Pani", "Formal address: Pan/Pani", + "W formalnej rozmowie używamy „Pan” wobec mężczyzny i „Pani” wobec kobiety.", + "В формальной речи к мужчине обращаются «Pan», к женщине — «Pani».", + "У формальному спілкуванні до чоловіка звертаються «Pan», до жінки — «Pani».", + "In formal Polish, “Pan” is used for a man and “Pani” for a woman."), + ("a1_greetings_l07", 7, "how_are_you", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", + "„Jak się masz?” to nieformalne pytanie o samopoczucie.", + "«Jak się masz?» — неформальный вопрос о том, как у человека дела.", + "«Jak się masz?» — неформальне запитання про те, як у людини справи.", + "“Jak się masz?” is an informal question asking how someone is doing."), + ("a1_greetings_l08", 8, "responding_how_are_you", "Odpowiadanie na „Jak się masz?”", "Отвечаем на «Как дела?»", "Відповідаємо на «Як справи?»", "Responding to “How are you?”", + "Na „Jak się masz?” możesz odpowiedzieć „Dobrze, dziękuję. A ty?”", + "На «Как дела?» можно ответить «Dobrze, dziękuję. A ty?»", + "На «Як справи?» можна відповісти «Dobrze, dziękuję. A ty?»", + "To “How are you?” you can answer “Dobrze, dziękuję. A ty?”"), + ("a1_greetings_l09", 9, "farewell_formal", "Formalne pożegnanie", "Формальное прощание", "Формальне прощання", "Formal farewell", + "„Do widzenia!” to podstawowe formalne pożegnanie.", + "«Do widzenia!» — основное формальное прощание.", + "«Do widzenia!» — основне формальне прощання.", + "“Do widzenia!” is the basic formal farewell."), + ("a1_greetings_l10", 10, "farewell_informal", "Nieformalne pożegnanie", "Неформальное прощание", "Неформальне прощання", "Informal farewell", + "W nieformalnej rozmowie możesz powiedzieć „Cześć!”, „Na razie!” albo „Pa!”.", + "В неформальном общении можно сказать «Cześć!», «Na razie!» или «Pa!».", + "У неформальному спілкуванні можна сказати «Cześć!», «Na razie!» або «Pa!».", + "In informal conversation, you can say “Cześć!”, “Na razie!” or “Pa!”."), + ] + + for lesson in lessons: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_greetings', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + # Примеры + examples = [ + ("a1_greetings_l01", 1, "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!"), + ("a1_greetings_l01", 2, "Dzień dobry, Panie Adamie.", "Добрый день, пан Адам.", "Добрий день, пане Адаме.", "Good morning, Mr. Adam."), + ("a1_greetings_l01", 3, "Dzień dobry, Pani Anno.", "Добрый день, пани Анна.", "Добрий день, пані Анно.", "Good morning, Mrs. Anna."), + ("a1_greetings_l02", 1, "Cześć, Anna!", "Привет, Анна!", "Привіт, Анно!", "Hi, Anna!"), + ("a1_greetings_l02", 2, "Cześć! Co słychać?", "Привет! Как дела?", "Привіт! Як справи?", "Hi! What's up?"), + ("a1_greetings_l02", 3, "Cześć! Do jutra!", "Привет! До завтра!", "Привіт! До завтра!", "Hi! See you tomorrow!"), + ("a1_greetings_l03", 1, "Jestem Piotr.", "Я Пётр.", "Я Пьотр.", "I am Piotr."), + ("a1_greetings_l03", 2, "Jestem Maria.", "Я Мария.", "Я Марія.", "I am Maria."), + ("a1_greetings_l03", 3, "Nazywam się Oleg.", "Меня зовут Олег.", "Мене звати Олег.", "My name is Oleg."), + ("a1_greetings_l04", 1, "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?"), + ("a1_greetings_l04", 2, "Cześć! Jak się nazywasz?", "Привет! Как тебя зовут?", "Привіт! Як тебе звати?", "Hi! What's your name?"), + ("a1_greetings_l05", 1, "Nazywam się Piotr.", "Меня зовут Пётр.", "Мене звати Пьотр.", "My name is Piotr."), + ("a1_greetings_l05", 2, "Nazywam się Anna.", "Меня зовут Анна.", "Мене звати Анна.", "My name is Anna."), + ("a1_greetings_l06", 1, "Jak Pan się nazywa?", "Как вас зовут? (к мужчине)", "Як вас звати? (до чоловіка)", "What is your name? (to a man)"), + ("a1_greetings_l06", 2, "Jak Pani się nazywa?", "Как вас зовут? (к женщине)", "Як вас звати? (до жінки)", "What is your name? (to a woman)"), + ("a1_greetings_l07", 1, "Cześć! Jak się masz?", "Привет! Как дела?", "Привіт! Як справи?", "Hi! How are you?"), + ("a1_greetings_l07", 2, "Hej, jak się masz?", "Эй, как дела?", "Гей, як справи?", "Hey, how are you?"), + ("a1_greetings_l08", 1, "Dobrze, dziękuję. A ty?", "Хорошо, спасибо. А ты?", "Добре, дякую. А ти?", "Good, thank you. And you?"), + ("a1_greetings_l08", 2, "W porządku. A ty?", "В порядке. А ты?", "В порядку. А ти?", "All right. And you?"), + ("a1_greetings_l09", 1, "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!"), + ("a1_greetings_l09", 2, "Do widzenia, Pani Anno.", "До свидания, пани Анна.", "До побачення, пані Анно.", "Goodbye, Mrs. Anna."), + ("a1_greetings_l10", 1, "Na razie!", "Пока!", "Бувай!", "See you!"), + ("a1_greetings_l10", 2, "Pa!", "Пока!", "Па!", "Bye!"), + ("a1_greetings_l10", 3, "Cześć! Do jutra!", "Пока! До завтра!", "Бувай! До завтра!", "Bye! See you tomorrow!"), + ] + + for ex in examples: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + # Вопросы уроков + questions = [ + ("a1_greetings_l01_q1", "a1_greetings_l01", "lesson_practice", "recognition", "greeting_formal", 1, + "Wchodzisz do urzędu. Jak się przywitasz?", "Вы входите в уженд. Как вы поздороваетесь?", "Ви заходите до установи. Як ви привітаєтеся?", "You enter a government office. How do you greet?", + "B", None, None), + ("a1_greetings_l02_q1", "a1_greetings_l02", "lesson_practice", "recognition", "greeting_informal", 1, + "Spotykasz przyjaciela na uniwersytecie. Jak się przywitasz?", "Вы встретили друга в университете. Как поздороваетесь?", "Ти зустрічаєш друга в університеті. Як привітаєшся?", "You meet a friend at university. How do you greet?", + "B", None, None), + ("a1_greetings_l03_q1", "a1_greetings_l03", "lesson_practice", "recognition", "self_intro", 1, + "Jak powiedzieć „Ja Maria”?", "Как правильно сказать «Я Мария»?", "Як правильно сказати «Я Марія»?", "How to say “I am Maria”?", + "B", None, None), + ("a1_greetings_l03_q2", "a1_greetings_l03", "lesson_practice", "production", "self_intro", 2, + "Wstaw słowo: „Ja ___ Michał.”", "Вставьте слово: «Ja ___ Michał.»", "Вставте слово: «Ja ___ Michał.»", "Complete: “Ja ___ Michał.”", + "jestem", "first_letter", "j"), + ("a1_greetings_l04_q1", "a1_greetings_l04", "lesson_practice", "recognition", "asking_name", 1, + "Jak zapytać o imię nowego kolegi?", "Как спросить имя у нового друга?", "Як запитати ім'я у нового друга?", "How to ask a new friend's name?", + "A", None, None), + ("a1_greetings_l05_q1", "a1_greetings_l05", "lesson_practice", "application", "answering_name", 1, + "Wybierz poprawną odpowiedź na: „Jak się nazywasz?”", "Выберите правильный ответ на: «Как тебя зовут?»", "Виберіть правильну відповідь на: «Як тебе звати?»", "Choose the correct answer to: “What's your name?”", + "B", None, None), + ("a1_greetings_l05_q2", "a1_greetings_l05", "lesson_practice", "production", "answering_name", 2, + "Wstaw słowo: „___ się Ewa.”", "Вставьте слово: «___ się Ewa.»", "Вставте слово: «___ się Ewa.»", "Complete: “___ się Ewa.”", + "Nazywam", "first_letter", "N"), + ("a1_greetings_l06_q1", "a1_greetings_l06", "lesson_practice", "application", "formal_address_pan_pani", 2, + "Formalnie zwracasz się do kobiety. Jak zapytać o imię?", "Вы формально обращаетесь к женщине. Как спросить её имя?", "Формально звертаєтесь до жінки. Як запитати її ім'я?", "You formally address a woman. How to ask her name?", + "C", None, None), + ("a1_greetings_l06_q2", "a1_greetings_l06", "lesson_practice", "recognition", "formal_address_pan_pani", 2, + "Wybierz poprawną formę dla mężczyzny:", "Выберите правильное обращение к мужчине:", "Виберіть правильне звертання до чоловіка:", "Choose the correct form for a man:", + "B", None, None), + ("a1_greetings_l07_q1", "a1_greetings_l07", "lesson_practice", "recognition", "how_are_you", 1, + "Co oznacza „Jak się masz?”", "Что означает «Jak się masz?»?", "Що означає «Jak się masz?»?", "What does “Jak się masz?” mean?", + "B", None, None), + ("a1_greetings_l08_q1", "a1_greetings_l08", "lesson_practice", "application", "responding_how_are_you", 1, + "Wybierz poprawną odpowiedź:", "Выберите правильный ответ:", "Виберіть правильну відповідь:", "Choose the correct answer:", + "A", None, None), + ("a1_greetings_l08_q2", "a1_greetings_l08", "lesson_practice", "production", "responding_how_are_you", 2, + "Wstaw słowo: „Dobrze, ___. A ty?”", "Вставьте слово: «Dobrze, ___. A ty?»", "Вставте слово: «Dobrze, ___. A ty?»", "Complete: “Dobrze, ___. A ty?”", + "dziękuję", "first_letter", "d"), + ("a1_greetings_l09_q1", "a1_greetings_l09", "lesson_practice", "application", "farewell_formal", 1, + "Kończysz rozmowę z pracownikiem urzędu. Co powiesz?", "Вы закончили разговор с сотрудником уженда. Что скажете?", "Закінчуєте розмову з працівником установи. Що скажете?", "You end a conversation with an office worker. What do you say?", + "B", None, None), + ("a1_greetings_l10_q1", "a1_greetings_l10", "lesson_practice", "application", "farewell_informal", 1, + "Żegnasz się z przyjacielem. Wybierz odpowiedni wariant.", "Вы прощаетесь с другом. Выберите подходящий вариант.", "Ви прощаєтесь з другом. Виберіть відповідний варіант.", "You say goodbye to a friend. Choose the right option.", + "B", None, None), + ] + + for q in questions: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_greetings', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + # Варианты ответов + options = [ + ("a1_greetings_l01_q1", "A", "Cześć!", "Привет!", "Привіт!", "Hi!", False, "too_informal"), + ("a1_greetings_l01_q1", "B", "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!", True, None), + ("a1_greetings_l01_q1", "C", "Dobranoc!", "Спокойной ночи!", "На добраніч!", "Good night!", False, "wrong_time_of_day"), + ("a1_greetings_l01_q1", "D", "Na razie!", "Пока!", "Бувай!", "See you!", False, "is_farewell_not_greeting"), + ("a1_greetings_l02_q1", "A", "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!", False, "too_formal"), + ("a1_greetings_l02_q1", "B", "Cześć!", "Привет!", "Привіт!", "Hi!", True, None), + ("a1_greetings_l02_q1", "C", "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!", False, "is_farewell_not_greeting"), + ("a1_greetings_l02_q1", "D", "Dobranoc!", "Спокойной ночи!", "На добраніч!", "Good night!", False, "wrong_context"), + ("a1_greetings_l03_q1", "A", "Ja jesteś Maria.", "Я есть Мария.", "Я є Марія.", "I are Maria.", False, "wrong_person"), + ("a1_greetings_l03_q1", "B", "Ja jestem Maria.", "Я Мария.", "Я Марія.", "I am Maria.", True, None), + ("a1_greetings_l03_q1", "C", "Ja jest Maria.", "Я есть Мария.", "Я є Марія.", "I is Maria.", False, "wrong_person"), + ("a1_greetings_l03_q1", "D", "Ja są Maria.", "Я есть Мария.", "Я є Марія.", "I are Maria.", False, "wrong_number"), + ("a1_greetings_l04_q1", "A", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", True, None), + ("a1_greetings_l04_q1", "B", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_greetings_l04_q1", "C", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", False, "wrong_question_meaning"), + ("a1_greetings_l04_q1", "D", "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!", False, "wrong_phrase_category"), + ("a1_greetings_l05_q1", "A", "Dzień dobry.", "Добрый день.", "Добрий день.", "Good morning.", False, "wrong_response"), + ("a1_greetings_l05_q1", "B", "Nazywam się Tomek.", "Меня зовут Томек.", "Мене звати Томек.", "My name is Tomek.", True, None), + ("a1_greetings_l05_q1", "C", "Do widzenia.", "До свидания.", "До побачення.", "Goodbye.", False, "wrong_phrase_category"), + ("a1_greetings_l05_q1", "D", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_greetings_l06_q1", "A", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "too_informal"), + ("a1_greetings_l06_q1", "B", "Jak Pan się nazywa?", "Как вас зовут? (м)", "Як вас звати? (ч)", "What is your name? (m)", False, "wrong_gender"), + ("a1_greetings_l06_q1", "C", "Jak Pani się nazywa?", "Как вас зовут? (ж)", "Як вас звати? (ж)", "What is your name? (f)", True, None), + ("a1_greetings_l06_q1", "D", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_greetings_l06_q2", "A", "Pani", "Пани", "Пані", "Mrs.", False, "wrong_gender"), + ("a1_greetings_l06_q2", "B", "Pan", "Пан", "Пан", "Mr.", True, None), + ("a1_greetings_l06_q2", "C", "Ty", "Ты", "Ти", "You", False, "too_informal"), + ("a1_greetings_l06_q2", "D", "Ona", "Она", "Вона", "She", False, "wrong_word"), + ("a1_greetings_l07_q1", "A", "Jak masz na imię?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "confused_with_name_question"), + ("a1_greetings_l07_q1", "B", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", True, None), + ("a1_greetings_l07_q1", "C", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", False, "confused_with_origin_question"), + ("a1_greetings_l07_q1", "D", "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!", False, "confused_with_farewell"), + ("a1_greetings_l08_q1", "A", "Dobrze, dziękuję.", "Хорошо, спасибо.", "Добре, дякую.", "Good, thank you.", True, None), + ("a1_greetings_l08_q1", "B", "Nazywam się Anna.", "Меня зовут Анна.", "Мене звати Анна.", "My name is Anna.", False, "wrong_response"), + ("a1_greetings_l08_q1", "C", "Do widzenia.", "До свидания.", "До побачення.", "Goodbye.", False, "wrong_phrase_category"), + ("a1_greetings_l08_q1", "D", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_question_meaning"), + ("a1_greetings_l09_q1", "A", "Cześć!", "Привет!", "Привіт!", "Hi!", False, "too_informal"), + ("a1_greetings_l09_q1", "B", "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!", True, None), + ("a1_greetings_l09_q1", "C", "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!", False, "is_greeting_not_farewell"), + ("a1_greetings_l09_q1", "D", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_phrase_category"), + ("a1_greetings_l10_q1", "A", "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!", False, "too_formal"), + ("a1_greetings_l10_q1", "B", "Na razie!", "Пока!", "Бувай!", "See you!", True, None), + ("a1_greetings_l10_q1", "C", "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!", False, "is_greeting_not_farewell"), + ("a1_greetings_l10_q1", "D", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_phrase_category"), + ] + + for opt in options: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # Финальный тест + test_questions = [ + ("a1_greetings_t01", None, "topic_test", "recognition", "greeting_formal", 1, + "Przyszedłeś do lekarza rano. Jak się przywitasz?", "Вы пришли к врачу утром. Как поздороваетесь?", "Ви прийшли до лікаря вранці. Як привітаєтесь?", "You came to the doctor in the morning. How do you greet?", + "B", None, None, 1), + ("a1_greetings_t02", None, "topic_test", "application", "greeting_informal", 1, + "Spotkałeś dobrego przyjaciela. Co powiesz?", "Вы встретили хорошего друга. Что скажете?", "Ви зустріли хорошого друга. Що скажете?", "You met a good friend. What do you say?", + "B", None, None, 2), + ("a1_greetings_t03", None, "topic_test", "recognition", "self_intro", 2, + "Wybierz poprawny wariant: „Ja Anna”.", "Выберите правильный вариант: «Я Анна».", "Виберіть правильний варіант: «Я Анна».", "Choose the correct option: “I am Anna”.", + "B", None, None, 3), + ("a1_greetings_t04", None, "topic_test", "production", "self_intro", 2, + "Uzupełnij: „Ja ___ Oleg.”", "Заполните: «Ja ___ Oleg.»", "Заповніть: «Ja ___ Oleg.»", "Complete: “Ja ___ Oleg.”", + "jestem", "first_letter", "j", 4), + ("a1_greetings_t05", None, "topic_test", "application", "asking_name", 1, + "Jak nieformalnie zapytać o imię?", "Как неформально спросить имя?", "Як неформально запитати ім'я?", "How to informally ask for a name?", + "B", None, None, 5), + ("a1_greetings_t06", None, "topic_test", "application", "answering_name", 2, + "Ktoś pyta: „Jak się nazywasz?” Jak odpowiesz?", "Человек спрашивает: «Jak się nazywasz?» Как ответить?", "Людина питає: «Jak się nazywasz?» Як відповісти?", "Someone asks: “Jak się nazywasz?” How do you answer?", + "B", None, None, 6), + ("a1_greetings_t07", None, "topic_test", "application", "formal_address_pan_pani", 2, + "Zwracasz się do kobiety w urzędzie. Jak zapytać o imię?", "Вы обращаетесь к женщине в уженде. Как спросить её имя?", "Звертаєтесь до жінки в установі. Як запитати її ім'я?", "You address a woman at the office. How to ask her name?", + "C", None, None, 7), + ("a1_greetings_t08", None, "topic_test", "recognition", "formal_address_pan_pani", 2, + "Rozmawiasz z mężczyzną formalnie. Który wariant jest poprawny?", "Вы разговариваете с мужчиной формально. Какой вариант правильный?", "Розмовляєте з чоловіком формально. Який варіант правильний?", "You talk to a man formally. Which option is correct?", + "B", None, None, 8), + ("a1_greetings_t09", None, "topic_test", "recognition", "how_are_you", 1, + "Co oznacza „Jak się masz?”", "Что означает «Jak się masz?»?", "Що означає «Jak się masz?»?", "What does “Jak się masz?” mean?", + "B", None, None, 9), + ("a1_greetings_t10", None, "topic_test", "application", "responding_how_are_you", 1, + "Kolega pyta: „Jak się masz?” Która odpowiedź jest najlepsza?", "Друг спрашивает: «Jak się masz?» Какой ответ лучше всего?", "Друг питає: «Jak się masz?» Яка відповідь найкраща?", "A friend asks: “Jak się masz?” Which answer is best?", + "A", None, None, 10), + ("a1_greetings_t11", None, "topic_test", "production", "responding_how_are_you", 2, + "Uzupełnij: „Dobrze, ___. A ty?”", "Заполните: «Dobrze, ___. A ty?»", "Заповніть: «Dobrze, ___. A ty?»", "Complete: “Dobrze, ___. A ty?”", + "dziękuję", "first_letter", "d", 11), + ("a1_greetings_t12", None, "topic_test", "application", "farewell_formal", 1, + "Kończysz rozmowę z pracownikiem urzędu.", "Вы закончили разговор с сотрудником уженда.", "Закінчуєте розмову з працівником установи.", "You end a conversation with an office worker.", + "C", None, None, 12), + ("a1_greetings_t13", None, "topic_test", "application", "farewell_informal", 1, + "Żegnasz się z przyjacielem.", "Вы прощаетесь с другом.", "Ви прощаєтесь з другом.", "You say goodbye to a friend.", + "B", None, None, 13), + ("a1_greetings_t14", None, "topic_test", "application", "answering_name", 2, + "Wybierz poprawną replikę: „Cześć! Jak się nazywasz?” → ___", "Выберите правильную реплику: «Cześć! Jak się nazywasz?» → ___", "Виберіть правильну репліку: «Cześć! Jak się nazywasz?» → ___", "Choose the right reply: “Cześć! Jak się nazywasz?” → ___", + "A", None, None, 14), + ("a1_greetings_t15", None, "topic_test", "application", "formal_address_pan_pani", 2, + "Uzupełnij dialog: „Dzień dobry, jak Pani się nazywa?” → ___", "Дополните диалог: «Dzień dobry, jak Pani się nazywa?» → ___", "Доповніть діалог: «Dzień dobry, jak Pani się nazywa?» → ___", "Complete the dialogue: “Dzień dobry, jak Pani się nazywa?” → ___", + "A", None, None, 15), + ("a1_greetings_t16", None, "topic_test", "application", "greeting_formal", 2, + "Wybierz odpowiednią replikę dla pierwszej rozmowy z pracownikiem urzędu.", "Выберите подходящую реплику для первого разговора с сотрудником уженда.", "Виберіть відповідну репліку для першої розмови з працівником установи.", "Choose the right phrase for a first conversation with an office worker.", + "B", None, None, 16), + ("a1_greetings_t17", None, "topic_test", "recognition", "greeting_informal", 2, + "Które słowo może być używane i na powitanie, i na pożegnanie?", "Какое слово может использоваться и при встрече, и при прощании?", "Яке слово може використовуватися і при зустрічі, і при прощанні?", "Which word can be used for both greeting and farewell?", + "B", None, None, 17), + ("a1_greetings_t18", None, "topic_test", "production", "formal_address_pan_pani", 2, + "Wstaw słowo: „Jak ___ się nazywa?” (formalnie do kobiety)", "Вставьте слово: «Jak ___ się nazywa?» (формально к женщине)", "Вставте слово: «Jak ___ się nazywa?» (формально до жінки)", "Insert the word: “Jak ___ się nazywa?” (formally to a woman)", + "Pani", "first_letter", "P", 18), + ("a1_greetings_t19", None, "topic_test", "application", "responding_how_are_you", 2, + "Rozmówca mówi: „Cześć! Jak się masz?” Wybierz najlepszą odpowiedź.", "Собеседник говорит: «Cześć! Jak się masz?» Выберите лучший ответ.", "Співрозмовник каже: «Cześć! Jak się masz?» Виберіть найкращу відповідь.", "The speaker says: “Cześć! Jak się masz?” Choose the best answer.", + "A", None, None, 19), + ("a1_greetings_t20", None, "topic_test", "application", "formal_address_pan_pani", 3, + "Pierwszy raz spotykasz nieznajomego mężczyznę w pracy rano. Chcesz się przywitać i zapytać o imię formalnie.", "Вы впервые встречаете незнакомого мужчину на работе утром. Хотите поздороваться и спросить имя формально.", "Вперше зустрічаєте незнайомого чоловіка на роботі вранці. Хочете привітатися і запитати ім'я формально.", "You meet an unknown man at work in the morning. You want to greet and ask his name formally.", + "B", None, None, 20), + ] + + for q in test_questions: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_greetings', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options = [ + ("a1_greetings_t01", "A", "Cześć!", "Привет!", "Привіт!", "Hi!", False, "too_informal"), + ("a1_greetings_t01", "B", "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!", True, None), + ("a1_greetings_t01", "C", "Na razie!", "Пока!", "Бувай!", "See you!", False, "farewell"), + ("a1_greetings_t01", "D", "Pa!", "Пока!", "Па!", "Bye!", False, "farewell"), + ("a1_greetings_t02", "A", "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!", False, "too_formal"), + ("a1_greetings_t02", "B", "Cześć!", "Привет!", "Привіт!", "Hi!", True, None), + ("a1_greetings_t02", "C", "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!", False, "farewell"), + ("a1_greetings_t02", "D", "Dobranoc!", "Спокойной ночи!", "На добраніч!", "Good night!", False, "wrong_context"), + ("a1_greetings_t03", "A", "Ja jesteś Anna.", "Я есть Анна.", "Я є Анна.", "I are Anna.", False, "wrong_person"), + ("a1_greetings_t03", "B", "Ja jestem Anna.", "Я Анна.", "Я Анна.", "I am Anna.", True, None), + ("a1_greetings_t03", "C", "Ja jest Anna.", "Я есть Анна.", "Я є Анна.", "I is Anna.", False, "wrong_person"), + ("a1_greetings_t03", "D", "Ja są Anna.", "Я есть Анна.", "Я є Анна.", "I are Anna.", False, "wrong_number"), + ("a1_greetings_t05", "A", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_greetings_t05", "B", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", True, None), + ("a1_greetings_t05", "C", "Jak Pan się nazywa?", "Как вас зовут? (м)", "Як вас звати? (ч)", "What is your name? (m)", False, "too_formal"), + ("a1_greetings_t05", "D", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", False, "wrong_question_meaning"), + ("a1_greetings_t06", "A", "Dobrze, dziękuję.", "Хорошо, спасибо.", "Добре, дякую.", "Good, thank you.", False, "wrong_response"), + ("a1_greetings_t06", "B", "Nazywam się Piotr.", "Меня зовут Пётр.", "Мене звати Пьотр.", "My name is Piotr.", True, None), + ("a1_greetings_t06", "C", "Do widzenia.", "До свидания.", "До побачення.", "Goodbye.", False, "wrong_phrase_category"), + ("a1_greetings_t06", "D", "Jestem się Piotr.", "Я есть Пётр.", "Я є Пьотр.", "I am Piotr.", False, "wrong_construction"), + ("a1_greetings_t07", "A", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "too_informal"), + ("a1_greetings_t07", "B", "Jak Pan się nazywa?", "Как вас зовут? (м)", "Як вас звати? (ч)", "What is your name? (m)", False, "wrong_gender"), + ("a1_greetings_t07", "C", "Jak Pani się nazywa?", "Как вас зовут? (ж)", "Як вас звати? (ж)", "What is your name? (f)", True, None), + ("a1_greetings_t07", "D", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_greetings_t08", "A", "Jak Pani się nazywa?", "Как вас зовут? (ж)", "Як вас звати? (ж)", "What is your name? (f)", False, "wrong_gender"), + ("a1_greetings_t08", "B", "Jak Pan się nazywa?", "Как вас зовут? (м)", "Як вас звати? (ч)", "What is your name? (m)", True, None), + ("a1_greetings_t08", "C", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "too_informal"), + ("a1_greetings_t08", "D", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_greetings_t09", "A", "Как тебя зовут?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "confused_with_name_question"), + ("a1_greetings_t09", "B", "Как дела?", "Как дела?", "Як справи?", "How are you?", True, None), + ("a1_greetings_t09", "C", "Где ты живёшь?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", False, "confused_with_origin_question"), + ("a1_greetings_t09", "D", "До свидания.", "До свидания.", "До побачення.", "Goodbye.", False, "confused_with_farewell"), + ("a1_greetings_t10", "A", "Dobrze, dziękuję.", "Хорошо, спасибо.", "Добре, дякую.", "Good, thank you.", True, None), + ("a1_greetings_t10", "B", "Nazywam się Anna.", "Меня зовут Анна.", "Мене звати Анна.", "My name is Anna.", False, "wrong_response"), + ("a1_greetings_t10", "C", "Do widzenia.", "До свидания.", "До побачення.", "Goodbye.", False, "wrong_phrase_category"), + ("a1_greetings_t10", "D", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_question_meaning"), + ("a1_greetings_t12", "A", "Cześć!", "Привет!", "Привіт!", "Hi!", False, "too_informal"), + ("a1_greetings_t12", "B", "Na razie!", "Пока!", "Бувай!", "See you!", False, "too_informal"), + ("a1_greetings_t12", "C", "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!", True, None), + ("a1_greetings_t12", "D", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_phrase_category"), + ("a1_greetings_t13", "A", "Do widzenia!", "До свидания!", "До побачення!", "Goodbye!", False, "too_formal"), + ("a1_greetings_t13", "B", "Na razie!", "Пока!", "Бувай!", "See you!", True, None), + ("a1_greetings_t13", "C", "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!", False, "is_greeting_not_farewell"), + ("a1_greetings_t13", "D", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_phrase_category"), + ("a1_greetings_t14", "A", "Nazywam się Tomek.", "Меня зовут Томек.", "Мене звати Томек.", "My name is Tomek.", True, None), + ("a1_greetings_t14", "B", "Do widzenia.", "До свидания.", "До побачення.", "Goodbye.", False, "wrong_phrase_category"), + ("a1_greetings_t14", "C", "Dobrze, dziękuję.", "Хорошо, спасибо.", "Добре, дякую.", "Good, thank you.", False, "wrong_response"), + ("a1_greetings_t14", "D", "Dzień dobry.", "Добрый день.", "Добрий день.", "Good morning.", False, "wrong_context"), + ("a1_greetings_t15", "A", "Nazywam się Anna.", "Меня зовут Анна.", "Мене звати Анна.", "My name is Anna.", True, None), + ("a1_greetings_t15", "B", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_greetings_t15", "C", "Cześć!", "Привет!", "Привіт!", "Hi!", False, "too_informal"), + ("a1_greetings_t15", "D", "Na razie!", "Пока!", "Бувай!", "See you!", False, "wrong_phrase_category"), + ("a1_greetings_t16", "A", "Cześć!", "Привет!", "Привіт!", "Hi!", False, "too_informal"), + ("a1_greetings_t16", "B", "Dzień dobry!", "Добрый день!", "Добрий день!", "Good morning!", True, None), + ("a1_greetings_t16", "C", "Pa!", "Пока!", "Па!", "Bye!", False, "farewell"), + ("a1_greetings_t16", "D", "Na razie!", "Пока!", "Бувай!", "See you!", False, "farewell"), + ("a1_greetings_t17", "A", "Dzień dobry", "Добрый день", "Добрий день", "Good morning", False, "greeting_only"), + ("a1_greetings_t17", "B", "Cześć", "Привет", "Привіт", "Hi", True, None), + ("a1_greetings_t17", "C", "Do widzenia", "До свидания", "До побачення", "Goodbye", False, "farewell_only"), + ("a1_greetings_t17", "D", "Dobranoc", "Спокойной ночи", "На добраніч", "Good night", False, "wrong_context"), + ("a1_greetings_t19", "A", "Dobrze, dziękuję. A ty?", "Хорошо, спасибо. А ты?", "Добре, дякую. А ти?", "Good, thank you. And you?", True, None), + ("a1_greetings_t19", "B", "Nazywam się Oleg.", "Меня зовут Олег.", "Мене звати Олег.", "My name is Oleg.", False, "wrong_response"), + ("a1_greetings_t19", "C", "Do widzenia, Pani.", "До свидания, пани.", "До побачення, пані.", "Goodbye, Mrs.", False, "too_formal"), + ("a1_greetings_t19", "D", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_question_meaning"), + ("a1_greetings_t20", "A", "Cześć! Jak się nazywasz?", "Привет! Как тебя зовут?", "Привіт! Як тебе звати?", "Hi! What's your name?", False, "too_informal"), + ("a1_greetings_t20", "B", "Dzień dobry. Jak Pan się nazywa?", "Добрый день. Как вас зовут?", "Добрий день. Як вас звати?", "Good morning. What is your name?", True, None), + ("a1_greetings_t20", "C", "Cześć! Jak się masz?", "Привет! Как дела?", "Привіт! Як справи?", "Hi! How are you?", False, "too_informal"), + ("a1_greetings_t20", "D", "Na razie! Jak się nazywasz?", "Пока! Как тебя зовут?", "Бувай! Як тебе звати?", "Bye! What's your name?", False, "wrong_phrase_category"), + ] + + for opt in test_options: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # ==================== ТЕМА 2: SKĄD JESTEŚ? GDZIE MIESZKASZ? ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_origin_residence', 'A1', 2, + 'Skąd jesteś? Gdzie mieszkasz?', + 'Откуда ты? Где живёшь?', + 'Звідки ти? Де живеш?', + 'Where are you from? Where do you live?') + ON CONFLICT (topic_id) DO NOTHING + """) + + # Уроки темы 2 + lessons_t2 = [ + ("a1_origin_l01", 1, "asking_origin", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", + "Skąd jesteś? — pytamy, skąd ktoś pochodzi.", + "Skąd jesteś? — «Откуда ты?»", + "Skąd jesteś? — «Звідки ти?»", + "Skąd jesteś? — “Where are you from?”"), + ("a1_origin_l02", 2, "answering_origin", "Jestem z...", "Я из...", "Я з...", "I am from...", + "Jestem z + kraj/miejsce. Przykłady: Jestem z Polski, Jestem z Ukrainy.", + "Jestem z... — «Я из...»", + "Jestem z... — «Я з...»", + "Jestem z... — “I am from...”"), + ("a1_origin_l03", 3, "country_vocabulary", "Kraje", "Страны", "Країни", "Countries", + "Polska, Ukraina, Białoruś, Rosja, Niemcy, Francja, Hiszpania, Włochy, Wielka Brytania, USA.", + "Учимся узнавать распространённые названия стран непосредственно на польском.", + "Вчимося впізнавати поширені назви країн польською.", + "Learn to recognize common country names in Polish."), + ("a1_origin_l04", 4, "nationality_forms", "Narodowość", "Национальность", "Національність", "Nationality", + "Polska → Polak/Polka. Ukraina → Ukrainiec/Ukrainka. Białoruś → Białorusin/Białorusinka. Forma zależy od płci.", + "Форма зависит от пола говорящего. Мужчина: Jestem Białorusinem. Женщина: Jestem Białorusinką.", + "Форма залежить від статі. Чоловік: Jestem Białorusinem. Жінка: Jestem Białorusinką.", + "The nationality form can change depending on gender."), + ("a1_origin_l05", 5, "asking_residence", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", + "Gdzie mieszkasz? — «Где ты живёшь?» Gdzie = «где».", + "Gdzie mieszkasz? — «Где ты живёшь?» Не путайте со Skąd jesteś?", + "Gdzie mieszkasz? — «Де ти живеш?» Не плутайте зі Skąd jesteś?", + "Gdzie mieszkasz? — “Where do you live?” Don't confuse with Skąd jesteś?”"), + ("a1_origin_l06", 6, "answering_residence", "Mieszkam w...", "Я живу в...", "Я живу в...", "I live in...", + "Mieszkam w + miejsce. Przykłady: Mieszkam w Warszawie, Mieszkam w Krakowie.", + "Mieszkam w... — «Я живу в...»", + "Mieszkam w... — «Я живу в...»", + "Mieszkam w... — “I live in...”"), + ("a1_origin_l07", 7, "city_vocabulary", "Miasta", "Города", "Міста", "Cities", + "Warszawa, Kraków, Gdańsk, Wrocław, Poznań, Łódź, Mińsk, Lwów.", + "Учимся узнавать распространённые названия городов на польском.", + "Вчимося впізнавати поширені назви міст польською.", + "Learn to recognize common city names in Polish."), + ("a1_origin_l08", 8, "skad_vs_gdzie", "Skąd czy Gdzie?", "Skąd или Gdzie?", "Skąd чи Gdzie?", "Skąd or Gdzie?", + "Skąd? = откуда. Gdzie? = где. Skąd jesteś? Gdzie mieszkasz?", + "Skąd? = откуда. Gdzie? = где. Это ключевое различие темы.", + "Skąd? = звідки. Gdzie? = де. Це ключова відмінність теми.", + "Skąd? = where from. Gdzie? = where. This is a key distinction."), + ("a1_origin_l09", 9, "mieszkac_conjugation", "Mieszkam / mieszkasz", "Mieszkam / mieszkasz", "Mieszkam / mieszkasz", "Mieszkam / mieszkasz", + "Ja mieszkam. Ty mieszkasz.", + "«Я» → mieszkam. «Ты» → mieszkasz.", + "«Я» → mieszkam. «Ти» → mieszkasz.", + "“I” → mieszkam. “you” → mieszkasz."), + ("a1_origin_l10", 10, "self_description", "O sobie", "О себе", "Про себе", "About myself", + "Cześć! Nazywam się Anna. Jestem z Ukrainy. Mieszkam w Warszawie.", + "«Привет! Меня зовут Анна. Я из Украины. Я живу в Варшаве».", + "«Привіт! Мене звати Анна. Я з України. Я живу у Варшаві».", + "“Hi! My name is Anna. I am from Ukraine. I live in Warsaw.”"), + ] + + for lesson in lessons_t2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_origin_residence', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + # Примеры темы 2 + examples_t2 = [ + ("a1_origin_l01", 1, "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?"), + ("a1_origin_l01", 2, "Cześć! Skąd jesteś?", "Привет! Откуда ты?", "Привіт! Звідки ти?", "Hi! Where are you from?"), + ("a1_origin_l02", 1, "Jestem z Polski.", "Я из Польши.", "Я з Польщі.", "I am from Poland."), + ("a1_origin_l02", 2, "Jestem z Ukrainy.", "Я из Украины.", "Я з України.", "I am from Ukraine."), + ("a1_origin_l03", 1, "Polska", "Польша", "Польща", "Poland"), + ("a1_origin_l03", 2, "Niemcy", "Германия", "Німеччина", "Germany"), + ("a1_origin_l04", 1, "Jestem Polakiem.", "Я поляк.", "Я поляк.", "I am Polish (male)."), + ("a1_origin_l04", 2, "Jestem Ukrainką.", "Я украинка.", "Я українка.", "I am Ukrainian (female)."), + ("a1_origin_l05", 1, "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?"), + ("a1_origin_l06", 1, "Mieszkam w Warszawie.", "Я живу в Варшаве.", "Я живу у Варшаві.", "I live in Warsaw."), + ("a1_origin_l06", 2, "Mieszkam w Krakowie.", "Я живу в Кракове.", "Я живу у Кракові.", "I live in Kraków."), + ("a1_origin_l07", 1, "Warszawa", "Варшава", "Варшава", "Warsaw"), + ("a1_origin_l07", 2, "Kraków", "Краков", "Краків", "Kraków"), + ("a1_origin_l08", 1, "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?"), + ("a1_origin_l08", 2, "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?"), + ("a1_origin_l09", 1, "Ja mieszkam.", "Я живу.", "Я живу.", "I live."), + ("a1_origin_l09", 2, "Ty mieszkasz.", "Ты живёшь.", "Ти живеш.", "You live."), + ("a1_origin_l10", 1, "Nazywam się Anna. Jestem z Ukrainy. Mieszkam w Warszawie.", "Меня зовут Анна. Я из Украины. Я живу в Варшаве.", "Мене звати Анна. Я з України. Я живу у Варшаві.", "My name is Anna. I am from Ukraine. I live in Warsaw."), + ] + + for ex in examples_t2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + # Вопросы уроков темы 2 + questions_t2 = [ + ("a1_origin_l01_q1", "a1_origin_l01", "lesson_practice", "recognition", "asking_origin", 1, + "Chcesz zapytać nową osobę, skąd pochodzi.", "Вы познакомились с новым человеком и хотите спросить, откуда он.", "Ви познайомилися з новою людиною і хочете запитати, звідки вона.", + "You met a new person and want to ask where they are from.", + "B", None, None), + ("a1_origin_l02_q1", "a1_origin_l02", "lesson_practice", "recognition", "answering_origin", 1, + "Wstaw słowo: Jestem ___ Ukrainy.", "Вставьте слово: Jestem ___ Ukrainy.", "Вставте слово: Jestem ___ Ukrainy.", + "Insert the word: Jestem ___ Ukrainy.", + "B", None, None), + ("a1_origin_l03_q1", "a1_origin_l03", "lesson_practice", "recognition", "country_vocabulary", 1, + "Jak po polsku „Niemcy”?", "Как по-польски «Германия»?", "Як польською «Німеччина»?", + "How to say “Germany” in Polish?", + "B", None, None), + ("a1_origin_l04_q1", "a1_origin_l04", "lesson_practice", "recognition", "nationality_forms", 2, + "Mężczyzna mówi: „Jestem Białorusinem”.", "Мужчина говорит: «Я белорус».", "Чоловік говорить: «Я білорус».", + "A man says: “I am Belarusian”.", + "B", None, None), + ("a1_origin_l05_q1", "a1_origin_l05", "lesson_practice", "recognition", "asking_residence", 1, + "Chcesz zapytać kolegę, gdzie mieszka.", "Вы хотите спросить друга, где он живёт.", "Ви хочете запитати друга, де він живе.", + "You want to ask a friend where they live.", + "B", None, None), + ("a1_origin_l06_q1", "a1_origin_l06", "lesson_practice", "recognition", "answering_residence", 1, + "Wybierz poprawny wariant.", "Выберите правильный вариант.", "Виберіть правильний варіант.", + "Choose the correct option.", + "B", None, None), + ("a1_origin_l07_q1", "a1_origin_l07", "lesson_practice", "recognition", "city_vocabulary", 1, + "Jak po polsku „Warszawa”?", "Как по-польски «Варшава»?", "Як польською «Варшава»?", + "How to say “Warsaw” in Polish?", + "A", None, None), + ("a1_origin_l08_q1", "a1_origin_l08", "lesson_practice", "recognition", "skad_vs_gdzie", 2, + "Wybierz poprawne słowo: ___ mieszkasz?", "Выберите правильное слово: ___ mieszkasz?", "Виберіть правильне слово: ___ mieszkasz?", + "Choose the correct word: ___ mieszkasz?", + "B", None, None), + ("a1_origin_l09_q1", "a1_origin_l09", "lesson_practice", "recognition", "mieszkac_conjugation", 2, + "Ty ___ w Warszawie.", "Ty ___ w Warszawie.", "Ty ___ w Warszawie.", + "Ty ___ w Warszawie.", + "B", None, None), + ("a1_origin_l10_q1", "a1_origin_l10", "lesson_practice", "recognition", "self_description", 2, + "Który wariant jest poprawny?", "Какой вариант правильный?", "Який варіант правильний?", + "Which option is correct?", + "A", None, None), + ] + + for q in questions_t2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_origin_residence', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + # Варианты ответов темы 2 + options_t2 = [ + ("a1_origin_l01_q1", "A", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", False, "wrong_question_meaning"), + ("a1_origin_l01_q1", "B", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", True, None), + ("a1_origin_l01_q1", "C", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_question_meaning"), + ("a1_origin_l01_q1", "D", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_origin_l02_q1", "A", "w", "в", "в", "in", False, "wrong_preposition"), + ("a1_origin_l02_q1", "B", "z", "из", "з", "from", True, None), + ("a1_origin_l02_q1", "C", "do", "до", "до", "to", False, "wrong_preposition"), + ("a1_origin_l02_q1", "D", "na", "на", "на", "on", False, "wrong_preposition"), + ("a1_origin_l03_q1", "A", "Francja", "Франция", "Франція", "France", False, "wrong_country"), + ("a1_origin_l03_q1", "B", "Niemcy", "Германия", "Німеччина", "Germany", True, None), + ("a1_origin_l03_q1", "C", "Hiszpania", "Испания", "Іспанія", "Spain", False, "wrong_country"), + ("a1_origin_l03_q1", "D", "Włochy", "Италия", "Італія", "Italy", False, "wrong_country"), + ("a1_origin_l04_q1", "A", "Jestem Białorusinką.", "Я белоруска.", "Я білоруска.", "I am Belarusian (female).", False, "wrong_gender_form"), + ("a1_origin_l04_q1", "B", "Jestem Białorusinem.", "Я белорус.", "Я білорус.", "I am Belarusian (male).", True, None), + ("a1_origin_l04_q1", "C", "Jestem Białoruś.", "Я Беларусь.", "Я Білорусь.", "I am Belarus.", False, "country_not_nationality"), + ("a1_origin_l04_q1", "D", "Jestem Białoruska.", "Я белорусская.", "Я білоруська.", "I am Belarusian.", False, "wrong_gender_form"), + ("a1_origin_l05_q1", "A", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", False, "confused_with_origin_question"), + ("a1_origin_l05_q1", "B", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", True, None), + ("a1_origin_l05_q1", "C", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_origin_l05_q1", "D", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_question_meaning"), + ("a1_origin_l06_q1", "A", "Mieszkam z Warszawie.", "Я живу в Варшаве.", "Я живу у Варшаві.", "I live in Warsaw.", False, "wrong_preposition"), + ("a1_origin_l06_q1", "B", "Mieszkam w Warszawie.", "Я живу в Варшаве.", "Я живу у Варшаві.", "I live in Warsaw.", True, None), + ("a1_origin_l06_q1", "C", "Mieszkam do Warszawie.", "Я живу в Варшаве.", "Я живу у Варшаві.", "I live in Warsaw.", False, "wrong_preposition"), + ("a1_origin_l06_q1", "D", "Mieszkam na Warszawie.", "Я живу в Варшаве.", "Я живу у Варшаві.", "I live in Warsaw.", False, "wrong_preposition"), + ("a1_origin_l07_q1", "A", "Warszawa", "Варшава", "Варшава", "Warsaw", True, None), + ("a1_origin_l07_q1", "B", "Wrocław", "Вроцлав", "Вроцлав", "Wrocław", False, "wrong_city"), + ("a1_origin_l07_q1", "C", "Kraków", "Краков", "Краків", "Kraków", False, "wrong_city"), + ("a1_origin_l07_q1", "D", "Gdańsk", "Гданьск", "Гданськ", "Gdańsk", False, "wrong_city"), + ("a1_origin_l08_q1", "A", "Skąd", "Откуда", "Звідки", "Where from", False, "confused_with_origin_question"), + ("a1_origin_l08_q1", "B", "Gdzie", "Где", "Де", "Where", True, None), + ("a1_origin_l08_q1", "C", "Jak", "Как", "Як", "How", False, "wrong_question_word"), + ("a1_origin_l08_q1", "D", "Kiedy", "Когда", "Коли", "When", False, "wrong_question_word"), + ("a1_origin_l09_q1", "A", "mieszkam", "живу", "живу", "live (I)", False, "wrong_person_1st_sing"), + ("a1_origin_l09_q1", "B", "mieszkasz", "живёшь", "живеш", "live (you)", True, None), + ("a1_origin_l09_q1", "C", "mieszka", "живёт", "живе", "lives", False, "wrong_person_3rd_sing"), + ("a1_origin_l09_q1", "D", "mieszkać", "жить", "жити", "to live", False, "infinitive_not_conjugated"), + ("a1_origin_l10_q1", "A", "Nazywam się Anna. Jestem z Ukrainy. Mieszkam w Warszawie.", "Меня зовут Анна. Я из Украины. Я живу в Варшаве.", "Мене звати Анна. Я з України. Я живу у Варшаві.", "My name is Anna. I am from Ukraine. I live in Warsaw.", True, None), + ("a1_origin_l10_q1", "B", "Nazywam Anna. Jestem Ukraina. Mieszkam z Warszawa.", "Неправильно.", "Неправильно.", "Incorrect.", False, "multiple_grammar_errors"), + ("a1_origin_l10_q1", "C", "Jestem się Anna. Skąd Polski. Gdzie Kraków.", "Неправильно.", "Неправильно.", "Incorrect.", False, "multiple_grammar_errors"), + ("a1_origin_l10_q1", "D", "Nazywam się Anna. Jestem w Ukrainy. Mieszkam z Warszawie.", "Неправильно.", "Неправильно.", "Incorrect.", False, "wrong_prepositions"), + ] + + for opt in options_t2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # Финальный тест темы 2 (15 вопросов) + test_questions_t2 = [ + ("a1_origin_t01", None, "topic_test", "recognition", "asking_origin", 1, + "Chcesz zapytać, skąd ktoś pochodzi.", "Вы хотите узнать, откуда человек.", "Ви хочете дізнатися, звідки людина.", + "You want to know where someone is from.", + "B", None, None, 1), + ("a1_origin_t02", None, "topic_test", "recognition", "answering_origin", 1, + "Jestem ___ Polski.", "Jestem ___ Polski.", "Jestem ___ Polski.", + "Jestem ___ Polski.", + "B", None, None, 2), + ("a1_origin_t03", None, "topic_test", "recognition", "country_vocabulary", 1, + "Jak po polsku „Francja”?", "Как по-польски «Франция»?", "Як польською «Франція»?", + "How to say “France” in Polish?", + "A", None, None, 3), + ("a1_origin_t04", None, "topic_test", "application", "nationality_forms", 2, + "Kobieta mówi: „Jestem Ukrainką”.", "Женщина говорит: «Я украинка».", "Жінка говорить: «Я українка».", + "A woman says: “I am Ukrainian”.", + "B", None, None, 4), + ("a1_origin_t05", None, "topic_test", "recognition", "asking_residence", 1, + "„Gdzie mieszkasz?”", "«Где ты живёшь?»", "«Де ти живеш?»", + "“Where do you live?”", + "B", None, None, 5), + ("a1_origin_t06", None, "topic_test", "recognition", "answering_residence", 1, + "Wybierz poprawne zdanie.", "Выберите правильное предложение.", "Виберіть правильне речення.", + "Choose the correct sentence.", + "B", None, None, 6), + ("a1_origin_t07", None, "topic_test", "recognition", "city_vocabulary", 1, + "Który wariant to „Wrocław”?", "Какой вариант означает «Вроцлав»?", "Який варіант означає «Вроцлав»?", + "Which option means “Wrocław”?", + "A", None, None, 7), + ("a1_origin_t08", None, "topic_test", "application", "skad_vs_gdzie", 2, + "Chcesz zapytać, skąd ktoś jest.", "Вы хотите узнать, откуда человек.", "Ви хочете дізнатися, звідки людина.", + "You want to know where someone is from.", + "B", None, None, 8), + ("a1_origin_t09", None, "topic_test", "recognition", "mieszkac_conjugation", 2, + "Ja ___ w Warszawie.", "Ja ___ w Warszawie.", "Ja ___ w Warszawie.", + "Ja ___ w Warszawie.", + "B", None, None, 9), + ("a1_origin_t10", None, "topic_test", "application", "self_description", 2, + "Który wariant to poprawne przedstawienie się?", "Какой вариант является правильным коротким представлением?", "Який варіант є правильним коротким представленням?", + "Which option is a correct self-introduction?", + "A", None, None, 10), + ("a1_origin_t11", None, "topic_test", "application", "answering_origin", 2, + "Anna mówi: „Jestem z Białorusi”.", "Анна говорит: «Я из Беларуси».", "Анна говорить: «Я з Білорусі».", + "Anna says: “I am from Belarus”.", + "A", None, None, 11), + ("a1_origin_t12", None, "topic_test", "application", "answering_residence", 2, + "Paweł mieszka w Warszawie.", "Павел живёт в Варшаве.", "Павло живе у Варшаві.", + "Paweł lives in Warsaw.", + "A", None, None, 12), + ("a1_origin_t13", None, "topic_test", "production", "asking_origin", 2, + "Wpisz brakujące słowo: Skąd ___?", "Впишите пропущенное слово: Skąd ___?", "Впишіть пропущене слово: Skąd ___?", + "Fill in the missing word: Skąd ___?", + "jesteś", "first_letter", "j", 13), + ("a1_origin_t14", None, "topic_test", "production", "mieszkac_conjugation", 2, + "Wpisz: Ty ___ w Warszawie.", "Впишите: Ty ___ w Warszawie.", "Впишіть: Ty ___ w Warszawie.", + "Fill in: Ty ___ w Warszawie.", + "mieszkasz", "first_letter", "m", 14), + ("a1_origin_t15", None, "topic_test", "application", "self_description", 3, + "Chcesz powiedzieć: „Jestem z Ukrainy i mieszkam w Warszawie”.", "Вы хотите сказать: «Я из Украины и живу в Варшаве».", "Ви хочете сказати: «Я з України і живу у Варшаві».", + "You want to say: “I am from Ukraine and I live in Warsaw”.", + "A", None, None, 15), + ] + + for q in test_questions_t2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_origin_residence', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t2 = [ + ("a1_origin_t01", "A", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", False, "wrong_question_meaning"), + ("a1_origin_t01", "B", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", True, None), + ("a1_origin_t01", "C", "Jak się masz?", "Как дела?", "Як справи?", "How are you?", False, "wrong_question_meaning"), + ("a1_origin_t01", "D", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_question_meaning"), + ("a1_origin_t02", "A", "w", "в", "в", "in", False, "wrong_preposition"), + ("a1_origin_t02", "B", "z", "из", "з", "from", True, None), + ("a1_origin_t02", "C", "do", "до", "до", "to", False, "wrong_preposition"), + ("a1_origin_t02", "D", "na", "на", "на", "on", False, "wrong_preposition"), + ("a1_origin_t03", "A", "Francja", "Франция", "Франція", "France", True, None), + ("a1_origin_t03", "B", "Francuz", "Француз", "Француз", "Frenchman", False, "wrong_word_form"), + ("a1_origin_t03", "C", "Fryzja", "Фризия", "Фризія", "Frisia", False, "wrong_country"), + ("a1_origin_t03", "D", "Finlandia", "Финляндия", "Фінляндія", "Finland", False, "wrong_country"), + ("a1_origin_t04", "A", "Jestem Ukrainiec.", "Я украинец.", "Я українець.", "I am Ukrainian (male).", False, "wrong_gender_form"), + ("a1_origin_t04", "B", "Jestem Ukrainką.", "Я украинка.", "Я українка.", "I am Ukrainian (female).", True, None), + ("a1_origin_t04", "C", "Jestem Ukraina.", "Я Украина.", "Я Україна.", "I am Ukraine.", False, "country_not_nationality"), + ("a1_origin_t04", "D", "Jestem Ukraiński.", "Я украинский.", "Я український.", "I am Ukrainian.", False, "wrong_word_form"), + ("a1_origin_t05", "A", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", False, "confused_with_origin_question"), + ("a1_origin_t05", "B", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", True, None), + ("a1_origin_t05", "C", "Gdzie jesteś z?", "Где ты из?", "Де ти з?", "Where are you from?", False, "wrong_question_meaning"), + ("a1_origin_t05", "D", "Jak mieszkasz?", "Как ты живёшь?", "Як ти живеш?", "How do you live?", False, "wrong_question_meaning"), + ("a1_origin_t06", "A", "Mieszkam z Krakowie.", "Я живу в Кракове.", "Я живу у Кракові.", "I live in Kraków.", False, "wrong_preposition"), + ("a1_origin_t06", "B", "Mieszkam w Krakowie.", "Я живу в Кракове.", "Я живу у Кракові.", "I live in Kraków.", True, None), + ("a1_origin_t06", "C", "Mieszkam Krakowie.", "Я живу Краков.", "Я живу Краків.", "I live Kraków.", False, "missing_preposition"), + ("a1_origin_t06", "D", "Mieszkam do Krakowie.", "Я живу в Кракове.", "Я живу у Кракові.", "I live in Kraków.", False, "wrong_preposition"), + ("a1_origin_t07", "A", "Wrocław", "Вроцлав", "Вроцлав", "Wrocław", True, None), + ("a1_origin_t07", "B", "Warszawa", "Варшава", "Варшава", "Warsaw", False, "wrong_city"), + ("a1_origin_t07", "C", "Włochy", "Италия", "Італія", "Italy", False, "wrong_city"), + ("a1_origin_t07", "D", "Wiedeń", "Вена", "Відень", "Vienna", False, "wrong_city"), + ("a1_origin_t08", "A", "Gdzie jesteś?", "Где ты?", "Де ти?", "Where are you?", False, "wrong_question_meaning"), + ("a1_origin_t08", "B", "Skąd jesteś?", "Откуда ты?", "Звідки ти?", "Where are you from?", True, None), + ("a1_origin_t08", "C", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", False, "wrong_question_meaning"), + ("a1_origin_t08", "D", "Jak mieszkasz?", "Как ты живёшь?", "Як ти живеш?", "How do you live?", False, "wrong_question_meaning"), + ("a1_origin_t09", "A", "mieszkasz", "живёшь", "живеш", "live (you)", False, "wrong_person_2nd_sing"), + ("a1_origin_t09", "B", "mieszkam", "живу", "живу", "live (I)", True, None), + ("a1_origin_t09", "C", "mieszka", "живёт", "живе", "lives", False, "wrong_person_3rd_sing"), + ("a1_origin_t09", "D", "mieszkać", "жить", "жити", "to live", False, "infinitive_not_conjugated"), + ("a1_origin_t10", "A", "Nazywam się Piotr. Jestem z Polski. Mieszkam w Krakowie.", "Меня зовут Пётр. Я из Польши. Я живу в Кракове.", "Мене звати Пьотр. Я з Польщі. Я живу у Кракові.", "My name is Piotr. I am from Poland. I live in Kraków.", True, None), + ("a1_origin_t10", "B", "Nazywam Piotr. Jestem Polska. Mieszkam z Kraków.", "Неправильно.", "Неправильно.", "Incorrect.", False, "multiple_grammar_errors"), + ("a1_origin_t10", "C", "Jestem się Piotr. Skąd Polski. Gdzie Kraków.", "Неправильно.", "Неправильно.", "Incorrect.", False, "multiple_grammar_errors"), + ("a1_origin_t10", "D", "Nazywam się Piotr. Jestem w Polski. Mieszkam z Krakowie.", "Неправильно.", "Неправильно.", "Incorrect.", False, "wrong_prepositions"), + ("a1_origin_t11", "A", "Jestem z Białorusi.", "Я из Беларуси.", "Я з Білорусі.", "I am from Belarus.", True, None), + ("a1_origin_t11", "B", "Jestem w Białorusi.", "Я в Беларуси.", "Я в Білорусі.", "I am in Belarus.", False, "wrong_preposition"), + ("a1_origin_t11", "C", "Mieszkam z Białorusi.", "Я живу из Беларуси.", "Я живу з Білорусі.", "I live from Belarus.", False, "wrong_verb_meaning"), + ("a1_origin_t11", "D", "Jestem Białoruś.", "Я Беларусь.", "Я Білорусь.", "I am Belarus.", False, "country_not_sentence"), + ("a1_origin_t12", "A", "Mieszkam w Warszawie.", "Я живу в Варшаве.", "Я живу у Варшаві.", "I live in Warsaw.", True, None), + ("a1_origin_t12", "B", "Mieszkasz w Warszawie.", "Ты живёшь в Варшаве.", "Ти живеш у Варшаві.", "You live in Warsaw.", False, "wrong_person_2nd_sing"), + ("a1_origin_t12", "C", "Jestem z Warszawie.", "Я из Варшавы.", "Я з Варшави.", "I am from Warsaw.", False, "wrong_preposition"), + ("a1_origin_t12", "D", "Gdzie Warszawa.", "Где Варшава.", "Де Варшава.", "Where Warsaw.", False, "incomplete_sentence"), + ("a1_origin_t15", "A", "Jestem z Ukrainy. Mieszkam w Warszawie.", "Я из Украины и живу в Варшаве.", "Я з України і живу у Варшаві.", "I am from Ukraine and I live in Warsaw.", True, None), + ("a1_origin_t15", "B", "Jestem w Ukrainie. Mieszkam z Warszawy.", "Неправильно.", "Неправильно.", "Incorrect.", False, "wrong_prepositions"), + ("a1_origin_t15", "C", "Mieszkam z Ukrainy. Jestem w Warszawie.", "Неправильно.", "Неправильно.", "Incorrect.", False, "wrong_verb_meaning"), + ("a1_origin_t15", "D", "Jestem Ukraina. Mieszkam Warszawa.", "Неправильно.", "Неправильно.", "Incorrect.", False, "multiple_grammar_errors"), + ] + + for opt in test_options_t2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # ==================== ТЕМА 3: СЕМЬЯ И ДРУЗЬЯ (ПЕРЕДЕЛАННАЯ) ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_family', 'A1', 3, + 'Rodzina i przyjaciele', + 'Семья и друзья', + 'Сім''я та друзі', + 'Family and Friends') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t3 = [ + ("a1_family_l01", 1, "family_vocabulary", "Rodzice i rodzeństwo", "Родители и родные братья/сёстры", "Батьки та рідні брати/сестри", "Parents and siblings", + "Podstawowe słowa rodzinne: mama, tata razem to rodzice. Brat i siostra razem to rodzeństwo.", + "Основные семейные слова: mama и tata вместе — это rodzice. Brat и siostra вместе — это rodzeństwo.", + "Основні сімейні слова: mama і tata разом — це rodzice. Brat і siostra разом — це rodzeństwo.", + "Basic family words: mama and tata together are rodzice. Brat and siostra together are rodzeństwo."), + ("a1_family_l02", 2, "family_vocabulary", "Dalsza rodzina", "Дальняя родня", "Далека родина", "Extended family", + "Babcia i dziadek razem to dziadkowie. Brat mamy lub taty to wujek, siostra mamy lub taty to ciocia.", + "Babcia и dziadek вместе — это dziadkowie. Брат мамы или папы — это wujek, сестра мамы или папы — это ciocia.", + "Babcia і dziadek разом — це dziadkowie. Брат мами чи тата — це wujek, сестра мами чи тата — це ciocia.", + "Babcia and dziadek together are dziadkowie. Mom's or dad's brother is wujek, mom's or dad's sister is ciocia."), + ("a1_family_l03", 3, "family_possessive", "Mój czy moja?", "Mój или moja?", "Mój чи moja?", "Mój or moja?", + "„Mój” używamy z rzeczownikami rodzaju męskiego: mój brat, mój tata. „Moja” używamy z rzeczownikami rodzaju żeńskiego: moja mama, moja siostra.", + "„Mój” используется со словами мужского рода: mój brat, mój tata. „Moja” — со словами женского рода: moja mama, moja siostra.", + "„Mój” використовується зі словами чоловічого роду: mój brat, mój tata. „Moja” — зі словами жіночого роду: moja mama, moja siostra.", + "„Mój” is used with masculine nouns: mój brat, mój tata. „Moja” is used with feminine nouns: moja mama, moja siostra."), + ("a1_family_l04", 4, "family_possessive", "Moi czy moje?", "Moi или moje?", "Moi чи moje?", "Moi or moje?", + "W liczbie mnogiej: „moi” używamy dla grup osób, w których jest chociaż jeden mężczyzna — moi rodzice. „Moje” używamy dla wszystkiego innego — moje dzieci.", + "Во множественном числе: „moi” используется для групп людей, где есть хотя бы один мужчина — moi rodzice. „Moje” — для всего остального — moje dzieci.", + "У множині: „moi” використовується для груп людей, де є хоча б один чоловік — moi rodzice. „Moje” — для всього іншого — moje dzieci.", + "In the plural: „moi” is used for groups that include at least one man — moi rodzice. „Moje” is used for everything else — moje dzieci."), + ("a1_family_l05", 5, "family_accusative", "Mam brata, mam siostrę", "У меня есть брат, у меня есть сестра", "У мене є брат, у мене є сестра", "I have a brother, I have a sister", + "Po „mam” rzeczowniki zmieniają końcówkę (biernik): brat → brata, siostra → siostrę, syn → syna, córka → córkę.", + "После „mam” существительные меняют окончание (винительный падеж): brat → brata, siostra → siostrę, syn → syna, córka → córkę.", + "Після „mam” іменники змінюють закінчення (знахідний відмінок): brat → brata, siostra → siostrę, syn → syna, córka → córkę.", + "After „mam” nouns change their ending (accusative): brat → brata, siostra → siostrę, syn → syna, córka → córkę."), + ("a1_family_l06", 6, "family_accusative", "Mam dużą rodzinę", "У меня большая семья", "У мене велика родина", "I have a big family", + "Gdy dodajemy przymiotnik, on też zmienia końcówkę: duża rodzina → mam dużą rodzinę. Mały brat → mam małego brata.", + "Когда добавляем прилагательное, оно тоже меняет окончание: duża rodzina → mam dużą rodzinę. Mały brat → mam małego brata.", + "Коли додаємо прикметник, він теж змінює закінчення: duża rodzina → mam dużą rodzinę. Mały brat → mam małego brata.", + "When an adjective is added, it also changes its ending: duża rodzina → mam dużą rodzinę. Mały brat → mam małego brata."), + ("a1_family_l07", 7, "family_questions", "Masz brata?", "У тебя есть брат?", "У тебе є брат?", "Do you have a brother?", + "Pytanie „Masz + biernik?” pyta, czy ktoś posiada coś/kogoś. Odpowiadamy „Tak, mam ___.” albo „Nie, nie mam ___.”", + "Вопрос „Masz + винительный?” спрашивает, есть ли у кого-то что-то/кто-то. Отвечаем „Tak, mam ___.” или „Nie, nie mam ___.”", + "Питання „Masz + знахідний?” запитує, чи є у когось щось/хтось. Відповідаємо „Tak, mam ___.” або „Nie, nie mam ___.”", + "The question „Masz + accusative?” asks whether someone has something/someone. We answer „Tak, mam ___.” or „Nie, nie mam ___.”"), + ("a1_family_l08", 8, "family_questions", "Kto to jest?", "Кто это?", "Хто це?", "Who is this?", + "„Kto to jest?” pytamy, gdy chcemy wiedzieć, kim jest osoba. Odpowiadamy „To jest mój/moja ___.”", + "„Kto to jest?” спрашиваем, когда хотим узнать, кто человек. Отвечаем „To jest mój/moja ___.”", + "„Kto to jest?” запитуємо, коли хочемо дізнатися, хто людина. Відповідаємо „To jest mój/moja ___.”", + "We ask „Kto to jest?” when we want to know who a person is. We answer „To jest mój/moja ___.”"), + ("a1_family_l09", 9, "family_description", "Opowiadam o rodzinie", "Рассказываю о семье", "Розповідаю про родину", "Talking about my family", + "Żeby opowiedzieć o rodzinie, łączymy kilka zdań: Mam dużą rodzinę. Mam mamę, tatę, brata i siostrę.", + "Чтобы рассказать о семье, соединяем несколько предложений: Mam dużą rodzinę. Mam mamę, tatę, brata i siostrę.", + "Щоб розповісти про родину, з'єднуємо кілька речень: Mam dużą rodzinę. Mam mamę, tatę, brata i siostrę.", + "To talk about your family, combine several sentences: Mam dużą rodzinę. Mam mamę, tatę, brata i siostrę."), + ("a1_family_l10", 10, "family_description", "Duża czy mała rodzina?", "Большая или маленькая семья?", "Велика чи мала родина?", "Big or small family?", + "Możemy połączyć pytanie i pełną odpowiedź: „Masz dużą rodzinę?” — „Tak, mam dużą rodzinę: mamę, tatę, brata i siostrę.”", + "Можно соединить вопрос и полный ответ: „Masz dużą rodzinę?” — „Tak, mam dużą rodzinę: mamę, tatę, brata i siostrę.”", + "Можна поєднати питання і повну відповідь: „Masz dużą rodzinę?” — „Tak, mam dużą rodzinę: mamę, tatę, brata i siostrę.”", + "You can combine a question and a full answer: „Masz dużą rodzinę?” — „Tak, mam dużą rodzinę: mamę, tatę, brata i siostrę.”"), + ] + + for lesson in lessons_t3: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_family', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t3 = [ + ("a1_family_l01", 1, "Mama i tata to rodzice.", "Мама и папа — это родители.", "Мама і тато — це батьки.", "Mom and dad are parents."), + ("a1_family_l01", 2, "Brat i siostra to rodzeństwo.", "Брат и сестра — это братья и сёстры.", "Брат і сестра — це брати і сестри.", "Brother and sister are siblings."), + ("a1_family_l01", 3, "To jest moja mama, a to mój tata.", "Это моя мама, а это мой папа.", "Це моя мама, а це мій тато.", "This is my mom, and this is my dad."), + ("a1_family_l02", 1, "Babcia i dziadek to dziadkowie.", "Бабушка и дедушка вместе — это dziadkowie.", "Бабуся і дідусь разом — це dziadkowie.", "Grandma and grandpa together are dziadkowie."), + ("a1_family_l02", 2, "To jest mój wujek, a to moja ciocia.", "Это мой дядя, а это моя тётя.", "Це мій дядько, а це моя тітка.", "This is my uncle, and this is my aunt."), + ("a1_family_l02", 3, "Mam kuzyna i kuzynkę.", "У меня есть двоюродный брат и двоюродная сестра.", "У мене є двоюрідний брат і двоюрідна сестра.", "I have a male cousin and a female cousin."), + ("a1_family_l03", 1, "To jest mój brat.", "Это мой брат.", "Це мій брат.", "This is my brother."), + ("a1_family_l03", 2, "To jest moja siostra.", "Это моя сестра.", "Це моя сестра.", "This is my sister."), + ("a1_family_l03", 3, "Mój tata i moja mama pracują.", "Мой папа и моя мама работают.", "Мій тато і моя мама працюють.", "My dad and my mom work."), + ("a1_family_l04", 1, "To są moi rodzice.", "Это мои родители.", "Це мої батьки.", "These are my parents."), + ("a1_family_l04", 2, "To są moje dzieci.", "Это мои дети.", "Це мої діти.", "These are my children."), + ("a1_family_l04", 3, "Moi dziadkowie mieszkają w Krakowie.", "Мои бабушка и дедушка живут в Кракове.", "Мої бабуся і дідусь живуть у Кракові.", "My grandparents live in Kraków."), + ("a1_family_l05", 1, "Mam brata.", "У меня есть брат.", "У мене є брат.", "I have a brother."), + ("a1_family_l05", 2, "Mam siostrę.", "У меня есть сестра.", "У мене є сестра.", "I have a sister."), + ("a1_family_l05", 3, "Mam syna i córkę.", "У меня есть сын и дочь.", "У мене є син і дочка.", "I have a son and a daughter."), + ("a1_family_l06", 1, "Mam dużą rodzinę.", "У меня большая семья.", "У мене велика родина.", "I have a big family."), + ("a1_family_l06", 2, "Mam małą rodzinę.", "У меня маленькая семья.", "У мене мала родина.", "I have a small family."), + ("a1_family_l06", 3, "Mam starszego brata i młodszą siostrę.", "У меня есть старший брат и младшая сестра.", "У мене є старший брат і молодша сестра.", "I have an older brother and a younger sister."), + ("a1_family_l07", 1, "Masz brata?", "У тебя есть брат?", "У тебе є брат?", "Do you have a brother?"), + ("a1_family_l07", 2, "Tak, mam brata.", "Да, у меня есть брат.", "Так, у мене є брат.", "Yes, I have a brother."), + ("a1_family_l07", 3, "Nie, nie mam siostry.", "Нет, у меня нет сестры.", "Ні, у мене немає сестри.", "No, I don't have a sister."), + ("a1_family_l08", 1, "Kto to jest?", "Кто это?", "Хто це?", "Who is this?"), + ("a1_family_l08", 2, "To jest moja mama.", "Это моя мама.", "Це моя мама.", "This is my mom."), + ("a1_family_l08", 3, "To jest mój brat, Adam.", "Это мой брат, Адам.", "Це мій брат, Адам.", "This is my brother, Adam."), + ("a1_family_l09", 1, "Mam dużą rodzinę.", "У меня большая семья.", "У мене велика родина.", "I have a big family."), + ("a1_family_l09", 2, "Mam mamę, tatę, brata i siostrę.", "У меня есть мама, папа, брат и сестра.", "У мене є мама, тато, брат і сестра.", "I have a mom, a dad, a brother and a sister."), + ("a1_family_l09", 3, "Moja mama ma na imię Anna.", "Мою маму зовут Анна.", "Мою маму звати Анна.", "My mom's name is Anna."), + ("a1_family_l10", 1, "Masz dużą rodzinę?", "У тебя большая семья?", "У тебе велика родина?", "Do you have a big family?"), + ("a1_family_l10", 2, "Tak, mam dużą rodzinę: mamę, tatę, brata i siostrę.", "Да, у меня большая семья: мама, папа, брат и сестра.", "Так, у мене велика родина: мама, тато, брат і сестра.", "Yes, I have a big family: mom, dad, brother and sister."), + ("a1_family_l10", 3, "Nie, mam małą rodzinę: tylko mamę i tatę.", "Нет, у меня маленькая семья: только мама и папа.", "Ні, у мене мала родина: тільки мама і тато.", "No, I have a small family: just mom and dad."), + ] + + for ex in examples_t3: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t3 = [ + ("a1_family_l01_q1", "a1_family_l01", "lesson_practice", "recognition", "family_vocabulary", 1, + "Jak nazywa się rodzic płci żeńskiej?", "Как называется родитель женского пола?", "Як називається батько жіночої статі?", "What do you call the female parent?", + "B", None, None), + ("a1_family_l01_q2", "a1_family_l01", "lesson_practice", "production", "family_vocabulary", 1, + "Wpisz brakujące słowo: Mama i tata to ___. (родители)", "Вставьте пропущенное слово: Mama i tata to ___. (родители)", "Вставте пропущене слово: Mama i tata to ___. (батьки)", "Fill in the missing word: Mama i tata to ___. (parents)", + "rodzice", "first_letter", "r"), + ("a1_family_l01_q3", "a1_family_l01", "lesson_practice", "application", "family_vocabulary", 1, + "Pokazujesz koledze zdjęcie i mówisz o swoim bracie i siostrze razem. Jak ich nazwiesz?", "Вы показываете другу фото и говорите о своих брате и сестре вместе. Как вы их назовёте?", "Ви показуєте другу фото і говорите про свого брата і сестру разом. Як ви їх назвете?", "You show a friend a photo and talk about your brother and sister together. What do you call them?", + "B", None, None), + ("a1_family_l02_q1", "a1_family_l02", "lesson_practice", "recognition", "family_vocabulary", 1, + "Jak po polsku powiesz „бабушка”?", "Как по-польски «бабушка»?", "Як польською «бабуся»?", "How do you say “grandma” in Polish?", + "B", None, None), + ("a1_family_l02_q2", "a1_family_l02", "lesson_practice", "production", "family_vocabulary", 2, + "Wpisz brakujące słowo: Brat mamy to mój ___. (дядя)", "Вставьте пропущенное слово: Brat mamy to mój ___. (дядя)", "Вставте пропущене слово: Brat mamy to mój ___. (дядько)", "Fill in the missing word: Brat mamy to mój ___. (uncle)", + "wujek", "first_letter", "w"), + ("a1_family_l02_q3", "a1_family_l02", "lesson_practice", "application", "family_vocabulary", 2, + "Pokazujesz zdjęcie syna swojego wujka. Kim on dla ciebie jest?", "Вы показываете фото сына своего дяди. Кем он вам приходится?", "Ви показуєте фото сина свого дядька. Ким він вам доводиться?", "You show a photo of your uncle's son. Who is he to you?", + "B", None, None), + ("a1_family_l03_q1", "a1_family_l03", "lesson_practice", "recognition", "family_possessive", 1, + "Wybierz poprawną formę: To jest ___ brat.", "Выберите правильную форму: To jest ___ brat.", "Виберіть правильну форму: To jest ___ brat.", "Choose the correct form: To jest ___ brat.", + "A", None, None), + ("a1_family_l03_q2", "a1_family_l03", "lesson_practice", "production", "family_possessive", 1, + "Wpisz brakujące słowo: To jest ___ siostra. (моя)", "Вставьте пропущенное слово: To jest ___ siostra. (моя)", "Вставте пропущене слово: To jest ___ siostra. (моя)", "Fill in the missing word: To jest ___ siostra. (my)", + "moja", "first_letter", "m"), + ("a1_family_l03_q3", "a1_family_l03", "lesson_practice", "application", "family_possessive", 2, + "Pokazujesz zdjęcie taty koledze. Jak powiesz?", "Вы показываете фото папы другу. Как вы скажете?", "Ви показуєте фото тата другу. Як ви скажете?", "You show a photo of your dad to a friend. What do you say?", + "B", None, None), + ("a1_family_l04_q1", "a1_family_l04", "lesson_practice", "recognition", "family_possessive", 2, + "Wybierz poprawną formę: To są ___ rodzice.", "Выберите правильную форму: To są ___ rodzice.", "Виберіть правильну форму: To są ___ rodzice.", "Choose the correct form: To są ___ rodzice.", + "B", None, None), + ("a1_family_l04_q2", "a1_family_l04", "lesson_practice", "production", "family_possessive", 2, + "Wpisz brakujące słowo: To są ___ dzieci. (мои)", "Вставьте пропущенное слово: To są ___ dzieci. (мои)", "Вставте пропущене слово: To są ___ dzieci. (мої)", "Fill in the missing word: To są ___ dzieci. (my)", + "moje", "first_letter", "m"), + ("a1_family_l04_q3", "a1_family_l04", "lesson_practice", "application", "family_possessive", 2, + "Mówisz o swoich dziadkach (babci i dziadku razem). Jak powiesz?", "Вы говорите о своих бабушке и дедушке вместе. Как вы скажете?", "Ви говорите про свою бабусю і дідуся разом. Як ви скажете?", "You talk about your grandma and grandpa together. What do you say?", + "B", None, None), + ("a1_family_l05_q1", "a1_family_l05", "lesson_practice", "recognition", "family_accusative", 2, + "Wybierz poprawną formę: Mam ___. (brat)", "Выберите правильную форму: Mam ___. (brat)", "Виберіть правильну форму: Mam ___. (brat)", "Choose the correct form: Mam ___. (brat)", + "B", None, None), + ("a1_family_l05_q2", "a1_family_l05", "lesson_practice", "production", "family_accusative", 2, + "Wpisz brakujące słowo: Mam ___. (сестра)", "Вставьте пропущенное слово: Mam ___. (сестра)", "Вставте пропущене слово: Mam ___. (сестра)", "Fill in the missing word: Mam ___. (sister)", + "siostrę", "first_letter", "s"), + ("a1_family_l05_q3", "a1_family_l05", "lesson_practice", "application", "family_accusative", 2, + "Kolega pyta, czy masz rodzeństwo. Chcesz powiedzieć, że masz brata. Co powiesz?", "Друг спрашивает, есть ли у тебя братья/сёстры. Ты хочешь сказать, что у тебя есть брат. Что ты скажешь?", "Друг питає, чи є у тебе брати/сестри. Ти хочеш сказати, що у тебе є брат. Що ти скажеш?", "A friend asks if you have siblings. You want to say you have a brother. What do you say?", + "B", None, None), + ("a1_family_l06_q1", "a1_family_l06", "lesson_practice", "recognition", "family_accusative", 2, + "Wybierz poprawną formę: Mam ___ rodzinę. (duża)", "Выберите правильную форму: Mam ___ rodzinę. (duża)", "Виберіть правильну форму: Mam ___ rodzinę. (duża)", "Choose the correct form: Mam ___ rodzinę. (big)", + "B", None, None), + ("a1_family_l06_q2", "a1_family_l06", "lesson_practice", "production", "family_accusative", 2, + "Wpisz brakujące słowo: Mam ___ rodzinę. (маленькая)", "Вставьте пропущенное слово: Mam ___ rodzinę. (маленькая)", "Вставте пропущене слово: Mam ___ rodzinę. (маленька)", "Fill in the missing word: Mam ___ rodzinę. (small)", + "małą", "first_letter", "m"), + ("a1_family_l06_q3", "a1_family_l06", "lesson_practice", "application", "family_accusative", 3, + "Chcesz powiedzieć, że masz starszego brata. Co powiesz?", "Ты хочешь сказать, что у тебя есть старший брат. Что ты скажешь?", "Ти хочеш сказати, що у тебе є старший брат. Що ти скажеш?", "You want to say you have an older brother. What do you say?", + "B", None, None), + ("a1_family_l07_q1", "a1_family_l07", "lesson_practice", "recognition", "family_questions", 1, + "Co znaczy „Masz siostrę?”", "Что означает «Masz siostrę?»", "Що означає «Masz siostrę?»", "What does “Masz siostrę?” mean?", + "A", None, None), + ("a1_family_l07_q2", "a1_family_l07", "lesson_practice", "production", "family_questions", 2, + "Uzupełnij dialog: — ___ brata? — Tak, mam brata. (ty)", "Дополните диалог: — ___ brata? — Tak, mam brata. (ты)", "Доповніть діалог: — ___ brata? — Tak, mam brata. (ти)", "Complete the dialogue: — ___ brata? — Tak, mam brata. (you)", + "Masz", "first_letter", "M"), + ("a1_family_l07_q3", "a1_family_l07", "lesson_practice", "application", "family_questions", 2, + "Chcesz zapytać kolegę, czy ma siostrę. Co powiesz?", "Ты хочешь спросить друга, есть ли у него сестра. Что ты скажешь?", "Ти хочеш запитати друга, чи є у нього сестра. Що ти скажеш?", "You want to ask a friend if he has a sister. What do you say?", + "B", None, None), + ("a1_family_l08_q1", "a1_family_l08", "lesson_practice", "recognition", "family_questions", 1, + "Które pytanie oznacza «Кто это?»", "Какой вопрос означает «Кто это?»", "Яке питання означає «Хто це?»", "Which question means “Who is this?”", + "B", None, None), + ("a1_family_l08_q2", "a1_family_l08", "lesson_practice", "production", "family_questions", 2, + "Uzupełnij: — Kto to jest? — To jest ___ mama. (моя)", "Дополните: — Kto to jest? — To jest ___ mama. (моя)", "Доповніть: — Kto to jest? — To jest ___ mama. (моя)", "Complete: — Kto to jest? — To jest ___ mama. (my)", + "moja", "first_letter", "m"), + ("a1_family_l08_q3", "a1_family_l08", "lesson_practice", "application", "family_questions", 2, + "Kolega pokazuje zdjęcie i pyta „Kto to jest?” o twoim bracie. Co odpowiesz?", "Друг показывает фото и спрашивает «Kto to jest?» о твоём брате. Что ты ответишь?", "Друг показує фото і питає «Kto to jest?» про твого брата. Що ти відповіси?", "A friend shows a photo and asks “Kto to jest?” about your brother. How do you answer?", + "B", None, None), + ("a1_family_l09_q1", "a1_family_l09", "lesson_practice", "recognition", "family_description", 2, + "Które zdanie poprawnie opisuje rodzinę?", "Какое предложение правильно описывает семью?", "Яке речення правильно описує родину?", "Which sentence correctly describes a family?", + "B", None, None), + ("a1_family_l09_q2", "a1_family_l09", "lesson_practice", "production", "family_description", 2, + "Przetłumacz: «У меня есть брат и сестра».", "Переведите: «У меня есть брат и сестра».", "Перекладіть: «У мене є брат і сестра».", "Translate: “I have a brother and a sister.”", + "Mam brata i siostrę", "first_letter", "M"), + ("a1_family_l09_q3", "a1_family_l09", "lesson_practice", "application", "family_description", 3, + "Chcesz opowiedzieć koledze o swojej rodzinie: masz mamę, tatę i brata. Jak zaczniesz zdanie?", "Ты хочешь рассказать другу о своей семье: у тебя есть мама, папа и брат. Как ты начнёшь предложение?", "Ти хочеш розповісти другу про свою родину: у тебе є мама, тато і брат. Як ти почнеш речення?", "You want to tell a friend about your family: you have a mom, dad and brother. How do you start the sentence?", + "B", None, None), + ("a1_family_l10_q1", "a1_family_l10", "lesson_practice", "recognition", "family_description", 2, + "Co znaczy „Masz dużą rodzinę?”", "Что означает «Masz dużą rodzinę?»", "Що означає «Masz dużą rodzinę?»", "What does “Masz dużą rodzinę?” mean?", + "A", None, None), + ("a1_family_l10_q2", "a1_family_l10", "lesson_practice", "production", "family_description", 3, + "Przetłumacz: «У меня большая семья: мама, папа, брат и сестра».", "Переведите: «У меня большая семья: мама, папа, брат и сестра».", "Перекладіть: «У мене велика родина: мама, тато, брат і сестра».", "Translate: “I have a big family: mom, dad, brother and sister.”", + "Mam dużą rodzinę: mamę, tatę, brata i siostrę", "first_letter", "M"), + ("a1_family_l10_q3", "a1_family_l10", "lesson_practice", "application", "family_description", 3, + "Kolega pyta „Masz dużą rodzinę?” Chcesz odpowiedzieć, że tak, i wymienić mamę, tatę, brata i siostrę. Co powiesz?", "Друг спрашивает «Masz dużą rodzinę?» Ты хочешь ответить, что да, и перечислить маму, папу, брата и сестру. Что ты скажешь?", "Друг питає «Masz dużą rodzinę?» Ти хочеш відповісти, що так, і перелічити маму, тата, брата і сестру. Що ти скажеш?", "A friend asks “Masz dużą rodzinę?” You want to say yes and list mom, dad, brother and sister. What do you say?", + "A", None, None), + ] + + for q in questions_t3: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_family', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t3 = [ + ("a1_family_l01_q1", "A", "tata", "папа", "тато", "dad", False, "wrong_gender"), + ("a1_family_l01_q1", "B", "mama", "мама", "мама", "mom", True, None), + ("a1_family_l01_q1", "C", "brat", "брат", "брат", "brother", False, "wrong_word"), + ("a1_family_l01_q1", "D", "rodzice", "родители", "батьки", "parents", False, "wrong_number"), + ("a1_family_l01_q3", "A", "rodzice", "родители", "батьки", "parents", False, "wrong_word"), + ("a1_family_l01_q3", "B", "rodzeństwo", "братья и сёстры", "брати і сестри", "siblings", True, None), + ("a1_family_l01_q3", "C", "dzieci", "дети", "діти", "children", False, "wrong_word"), + ("a1_family_l01_q3", "D", "dziadkowie", "бабушка и дедушка", "бабуся і дідусь", "grandparents", False, "wrong_word"), + ("a1_family_l02_q1", "A", "dziadek", "дедушка", "дідусь", "grandpa", False, "wrong_gender"), + ("a1_family_l02_q1", "B", "babcia", "бабушка", "бабуся", "grandma", True, None), + ("a1_family_l02_q1", "C", "ciocia", "тётя", "тітка", "aunt", False, "wrong_word"), + ("a1_family_l02_q1", "D", "wujek", "дядя", "дядько", "uncle", False, "wrong_gender"), + ("a1_family_l02_q3", "A", "brat", "брат", "брат", "brother", False, "wrong_word"), + ("a1_family_l02_q3", "B", "kuzyn", "двоюродный брат", "двоюрідний брат", "cousin", True, None), + ("a1_family_l02_q3", "C", "wnuk", "внук", "онук", "grandson", False, "wrong_word"), + ("a1_family_l02_q3", "D", "syn", "сын", "син", "son", False, "wrong_word"), + ("a1_family_l03_q1", "A", "mój", "мой", "мій", "my (m)", True, None), + ("a1_family_l03_q1", "B", "moja", "моя", "моя", "my (f)", False, "wrong_gender"), + ("a1_family_l03_q1", "C", "moje", "мои", "мої", "my (n/pl)", False, "wrong_gender"), + ("a1_family_l03_q1", "D", "moi", "мои", "мої", "my (masc. pl)", False, "wrong_number"), + ("a1_family_l03_q3", "A", "To jest moja tata.", "Это моя папа.", "Це моя тато.", "This is my dad. (wrong gender)", False, "wrong_gender"), + ("a1_family_l03_q3", "B", "To jest mój tata.", "Это мой папа.", "Це мій тато.", "This is my dad.", True, None), + ("a1_family_l03_q3", "C", "To jest moje tata.", "Это моё папа.", "Це моє тато.", "This is my dad. (wrong gender)", False, "wrong_gender"), + ("a1_family_l03_q3", "D", "To jest moi tata.", "Это мои папа.", "Це мої тато.", "This is my dad. (wrong number)", False, "wrong_number"), + ("a1_family_l04_q1", "A", "moje", "мои", "мої", "my", False, "wrong_gender"), + ("a1_family_l04_q1", "B", "moi", "мои", "мої", "my (masc. personal pl)", True, None), + ("a1_family_l04_q1", "C", "mój", "мой", "мій", "my (m sing)", False, "wrong_number"), + ("a1_family_l04_q1", "D", "moja", "моя", "моя", "my (f sing)", False, "wrong_number"), + ("a1_family_l04_q3", "A", "To jest mój dziadek.", "Это мой дедушка.", "Це мій дідусь.", "This is my grandpa.", False, "wrong_number"), + ("a1_family_l04_q3", "B", "To są moi dziadkowie.", "Это мои бабушка и дедушка.", "Це мої бабуся і дідусь.", "These are my grandparents.", True, None), + ("a1_family_l04_q3", "C", "To są moje dziadkowie.", "Это мои бабушка и дедушка.", "Це мої бабуся і дідусь.", "These are my grandparents. (wrong gender)", False, "wrong_gender"), + ("a1_family_l04_q3", "D", "To jest moja babcia.", "Это моя бабушка.", "Це моя бабуся.", "This is my grandma.", False, "wrong_context"), + ("a1_family_l05_q1", "A", "brat", "брат", "брат", "brother", False, "wrong_case"), + ("a1_family_l05_q1", "B", "brata", "брата", "брата", "brother (acc.)", True, None), + ("a1_family_l05_q1", "C", "bratem", "братом", "братом", "brother (instr.)", False, "wrong_case"), + ("a1_family_l05_q1", "D", "bracia", "братья", "брати", "brothers", False, "wrong_number"), + ("a1_family_l05_q3", "A", "Mam brat.", "У меня брат.", "У мене брат.", "I have brother. (wrong case)", False, "wrong_case"), + ("a1_family_l05_q3", "B", "Mam brata.", "У меня есть брат.", "У мене є брат.", "I have a brother.", True, None), + ("a1_family_l05_q3", "C", "Jestem brat.", "Я брат.", "Я брат.", "I am brother.", False, "wrong_sentence_type"), + ("a1_family_l05_q3", "D", "To brat.", "Это брат.", "Це брат.", "This is a brother.", False, "wrong_sentence_type"), + ("a1_family_l06_q1", "A", "duża", "большая", "велика", "big (nom.)", False, "wrong_case"), + ("a1_family_l06_q1", "B", "dużą", "большую", "велику", "big (acc.)", True, None), + ("a1_family_l06_q1", "C", "duży", "большой", "великий", "big (masc.)", False, "wrong_gender"), + ("a1_family_l06_q1", "D", "duże", "большие", "великі", "big (n/pl)", False, "wrong_gender"), + ("a1_family_l06_q3", "A", "Mam starszy brat.", "У меня старший брат. (неправильно)", "У мене старший брат. (неправильно)", "I have older brother. (wrong case)", False, "wrong_case"), + ("a1_family_l06_q3", "B", "Mam starszego brata.", "У меня есть старший брат.", "У мене є старший брат.", "I have an older brother.", True, None), + ("a1_family_l06_q3", "C", "Jestem starszy brat.", "Я старший брат.", "Я старший брат.", "I am older brother.", False, "wrong_sentence_type"), + ("a1_family_l06_q3", "D", "Mam stara brata.", "У меня старая брат. (неправильно)", "У мене стара брат. (неправильно)", "I have old (f) brother. (wrong gender)", False, "wrong_gender"), + ("a1_family_l07_q1", "A", "У тебя есть сестра?", "У тебя есть сестра?", "У тебе є сестра?", "Do you have a sister?", True, None), + ("a1_family_l07_q1", "B", "Это твоя сестра?", "Это твоя сестра?", "Це твоя сестра?", "Is this your sister?", False, "wrong_translation"), + ("a1_family_l07_q1", "C", "Ты сестра?", "Ты сестра?", "Ти сестра?", "Are you a sister?", False, "wrong_translation"), + ("a1_family_l07_q1", "D", "Где твоя сестра?", "Где твоя сестра?", "Де твоя сестра?", "Where is your sister?", False, "wrong_translation"), + ("a1_family_l07_q3", "A", "Mam siostrę.", "У меня есть сестра.", "У мене є сестра.", "I have a sister.", False, "wrong_sentence_type"), + ("a1_family_l07_q3", "B", "Masz siostrę?", "У тебя есть сестра?", "У тебе є сестра?", "Do you have a sister?", True, None), + ("a1_family_l07_q3", "C", "To jest siostra.", "Это сестра.", "Це сестра.", "This is a sister.", False, "wrong_sentence_type"), + ("a1_family_l07_q3", "D", "Moja siostra.", "Моя сестра.", "Моя сестра.", "My sister.", False, "wrong_sentence_type"), + ("a1_family_l08_q1", "A", "Co to jest?", "Что это?", "Що це?", "What is this?", False, "wrong_word"), + ("a1_family_l08_q1", "B", "Kto to jest?", "Кто это?", "Хто це?", "Who is this?", True, None), + ("a1_family_l08_q1", "C", "Gdzie to jest?", "Где это?", "Де це?", "Where is this?", False, "wrong_word"), + ("a1_family_l08_q1", "D", "Jak to jest?", "Как это?", "Як це?", "How is this?", False, "wrong_word"), + ("a1_family_l08_q3", "A", "Masz brata?", "У тебя есть брат?", "У тебе є брат?", "Do you have a brother?", False, "wrong_sentence_type"), + ("a1_family_l08_q3", "B", "To jest mój brat.", "Это мой брат.", "Це мій брат.", "This is my brother.", True, None), + ("a1_family_l08_q3", "C", "Mam brata.", "У меня есть брат.", "У мене є брат.", "I have a brother.", False, "wrong_context"), + ("a1_family_l08_q3", "D", "Jestem brat.", "Я брат.", "Я брат.", "I am brother.", False, "wrong_sentence_type"), + ("a1_family_l09_q1", "A", "Mam duża rodzina.", "У меня большая семья. (неправильно)", "У мене велика родина. (неправильно)", "I have big family. (wrong case)", False, "wrong_case"), + ("a1_family_l09_q1", "B", "Mam dużą rodzinę.", "У меня большая семья.", "У мене велика родина.", "I have a big family.", True, None), + ("a1_family_l09_q1", "C", "Jestem duża rodzina.", "Я большая семья.", "Я велика родина.", "I am big family.", False, "wrong_sentence_type"), + ("a1_family_l09_q1", "D", "To duża rodzina.", "Это большая семья.", "Це велика родина.", "This is a big family.", False, "wrong_sentence_type"), + ("a1_family_l09_q3", "A", "Ja rodzina mamę, tatę i brata.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_family_l09_q3", "B", "Mam mamę, tatę i brata.", "У меня есть мама, папа и брат.", "У мене є мама, тато і брат.", "I have a mom, a dad and a brother.", True, None), + ("a1_family_l09_q3", "C", "Moja rodzina jestem mamę, tatę i brata.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_family_l09_q3", "D", "Jestem mama, tata i brat.", "Я мама, папа и брат.", "Я мама, тато і брат.", "I am mom, dad and brother.", False, "wrong_sentence_type"), + ("a1_family_l10_q1", "A", "У тебя большая семья?", "У тебя большая семья?", "У тебе велика родина?", "Do you have a big family?", True, None), + ("a1_family_l10_q1", "B", "У тебя есть семья?", "У тебя есть семья?", "У тебе є родина?", "Do you have a family?", False, "wrong_translation"), + ("a1_family_l10_q1", "C", "Твоя семья далеко?", "Твоя семья далеко?", "Твоя родина далеко?", "Is your family far away?", False, "wrong_translation"), + ("a1_family_l10_q1", "D", "Сколько тебе лет?", "Сколько тебе лет?", "Скільки тобі років?", "How old are you?", False, "wrong_translation"), + ("a1_family_l10_q3", "A", "Tak, mam dużą rodzinę: mamę, tatę, brata i siostrę.", "Да, у меня большая семья: мама, папа, брат и сестра.", "Так, у мене велика родина: мама, тато, брат і сестра.", "Yes, I have a big family: mom, dad, brother and sister.", True, None), + ("a1_family_l10_q3", "B", "Tak, mam duża rodzina: mama, tata, brat, siostra.", "Неправильная форма падежа.", "Неправильна форма відмінка.", "Wrong case form.", False, "wrong_case"), + ("a1_family_l10_q3", "C", "Nie, nie mam rodziny.", "Нет, у меня нет семьи.", "Ні, у мене немає родини.", "No, I don't have a family.", False, "wrong_context"), + ("a1_family_l10_q3", "D", "Tak, jestem duża rodzina.", "Да, я большая семья.", "Так, я велика родина.", "Yes, I am a big family.", False, "wrong_sentence_type"), + ] + + for opt in options_t3: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t3 = [ + ("a1_family_t01", None, "topic_test", "recognition", "family_vocabulary", 1, + "Jak po polsku powiesz „бабушка”?", "Как по-польски «бабушка»?", "Як польською «бабуся»?", "How do you say “grandma” in Polish?", + "B", None, None, 1), + ("a1_family_t02", None, "topic_test", "recognition", "family_vocabulary", 1, + "Jak po polsku powiesz „дядя”?", "Как по-польски «дядя»?", "Як польською «дядько»?", "How do you say “uncle” in Polish?", + "C", None, None, 2), + ("a1_family_t03", None, "topic_test", "recognition", "family_possessive", 1, + "Wybierz poprawną formę: ___ brat.", "Выберите правильную форму: ___ brat.", "Виберіть правильну форму: ___ brat.", "Choose the correct form: ___ brat.", + "A", None, None, 3), + ("a1_family_t04", None, "topic_test", "recognition", "family_possessive", 2, + "Wybierz poprawną formę: ___ rodzice.", "Выберите правильную форму: ___ rodzice.", "Виберіть правильну форму: ___ rodzice.", "Choose the correct form: ___ rodzice.", + "B", None, None, 4), + ("a1_family_t05", None, "topic_test", "recognition", "family_accusative", 2, + "Wybierz poprawną formę: Mam ___. (brat)", "Выберите правильную форму: Mam ___. (brat)", "Виберіть правильну форму: Mam ___. (brat)", "Choose the correct form: Mam ___. (brat)", + "B", None, None, 5), + ("a1_family_t06", None, "topic_test", "recognition", "family_questions", 1, + "Co znaczy „Masz siostrę?”", "Что означает «Masz siostrę?»", "Що означає «Masz siostrę?»", "What does “Masz siostrę?” mean?", + "A", None, None, 6), + ("a1_family_t07", None, "topic_test", "application", "family_vocabulary", 1, + "Pokazujesz zdjęcie matki swojej mamy. Jak ją nazwiesz?", "Ты показываешь фото матери своей мамы. Как ты её назовёшь?", "Ти показуєш фото матері своєї мами. Як ти її назвеш?", "You show a photo of your mom's mother. What do you call her?", + "B", None, None, 7), + ("a1_family_t08", None, "topic_test", "application", "family_possessive", 2, + "Mówisz koledze o swoim bracie. Jak powiesz?", "Ты говоришь другу о своём брате. Что ты скажешь?", "Ти говориш другу про свого брата. Що ти скажеш?", "You tell a friend about your brother. What do you say?", + "B", None, None, 8), + ("a1_family_t09", None, "topic_test", "application", "family_accusative", 2, + "Kolega pyta, czy masz rodzeństwo. Chcesz powiedzieć, że masz brata. Co powiesz?", "Друг спрашивает, есть ли у тебя братья/сёстры. Ты хочешь сказать, что у тебя есть брат. Что ты скажешь?", "Друг питає, чи є у тебе брати/сестри. Ти хочеш сказати, що у тебе є брат. Що ти скажеш?", "A friend asks if you have siblings. You want to say you have a brother. What do you say?", + "B", None, None, 9), + ("a1_family_t10", None, "topic_test", "application", "family_questions", 2, + "Chcesz zapytać kolegę, czy ma siostrę. Co powiesz?", "Ты хочешь спросить друга, есть ли у него сестра. Что ты скажешь?", "Ти хочеш запитати друга, чи є у нього сестра. Що ти скажеш?", "You want to ask a friend if he has a sister. What do you say?", + "B", None, None, 10), + ("a1_family_t11", None, "topic_test", "application", "family_questions", 2, + "Kolega pyta „Kto to jest?”, pokazując zdjęcie twojej mamy. Co odpowiesz?", "Друг спрашивает «Kto to jest?», показывая фото твоей мамы. Что ты ответишь?", "Друг питає «Kto to jest?», показуючи фото твоєї мами. Що ти відповіси?", "A friend asks “Kto to jest?” while showing a photo of your mom. How do you answer?", + "B", None, None, 11), + ("a1_family_t12", None, "topic_test", "application", "family_description", 3, + "Opisujesz swoją rodzinę koledze. Chcesz powiedzieć, że jest duża. Co powiesz?", "Ты описываешь свою семью другу. Ты хочешь сказать, что она большая. Что ты скажешь?", "Ти описуєш свою родину другу. Ти хочеш сказати, що вона велика. Що ти скажеш?", "You describe your family to a friend. You want to say it's big. What do you say?", + "B", None, None, 12), + ("a1_family_t13", None, "topic_test", "production", "family_vocabulary", 1, + "Wpisz brakujące słowo: To jest moja ___. (сестра)", "Вставьте пропущенное слово: To jest moja ___. (сестра)", "Вставте пропущене слово: To jest moja ___. (сестра)", "Fill in the missing word: To jest moja ___. (sister)", + "siostra", "first_letter", "s", 13), + ("a1_family_t14", None, "topic_test", "production", "family_possessive", 2, + "Wpisz brakujące słowo: To są ___ rodzice. (мои)", "Вставьте пропущенное слово: To są ___ rodzice. (мои)", "Вставте пропущене слово: To są ___ rodzice. (мої)", "Fill in the missing word: To są ___ rodzice. (my)", + "moi", "first_letter", "m", 14), + ("a1_family_t15", None, "topic_test", "production", "family_accusative", 2, + "Wpisz brakujące słowo: Mam ___. (сестра, винительный)", "Вставьте пропущенное слово: Mam ___. (сестра, винительный)", "Вставте пропущене слово: Mam ___. (сестра, знахідний)", "Fill in the missing word: Mam ___. (sister, accusative)", + "siostrę", "first_letter", "s", 15), + ("a1_family_t16", None, "topic_test", "production", "family_accusative", 2, + "Wpisz brakujące słowo: Mam dużą ___. (семья, винительный)", "Вставьте пропущенное слово: Mam dużą ___. (семья, винительный)", "Вставте пропущене слово: Mam dużą ___. (родина, знахідний)", "Fill in the missing word: Mam dużą ___. (family, accusative)", + "rodzinę", "first_letter", "r", 16), + ("a1_family_t17", None, "topic_test", "production", "family_questions", 2, + "Uzupełnij dialog: — ___ brata? — Tak, mam brata. (ty)", "Дополните диалог: — ___ brata? — Tak, mam brata. (ты)", "Доповніть діалог: — ___ brata? — Tak, mam brata. (ти)", "Complete the dialogue: — ___ brata? — Tak, mam brata. (you)", + "Masz", "first_letter", "M", 17), + ("a1_family_t18", None, "topic_test", "production", "family_description", 3, + "Przetłumacz: «У меня есть брат и сестра».", "Переведите: «У меня есть брат и сестра».", "Перекладіть: «У мене є брат і сестра».", "Translate: “I have a brother and a sister.”", + "Mam brata i siostrę", "first_letter", "M", 18), + ("a1_family_t19", None, "topic_test", "mixed", "family_description", 3, + "Przetłumacz cały dialog: «— У тебя есть брат? — Да, это мой брат, Адам.»", "Переведите весь диалог: «— У тебя есть брат? — Да, это мой брат, Адам.»", "Перекладіть весь діалог: «— У тебе є брат? — Так, це мій брат, Адам.»", "Translate the whole dialogue: “— Do you have a brother? — Yes, this is my brother, Adam.”", + "Masz brata? Tak, to jest mój brat, Adam", "first_letter", "M", 19), + ("a1_family_t20", None, "topic_test", "mixed", "family_description", 3, + "Opisz jednym zdaniem: masz dużą rodzinę — mamę, tatę, brata i siostrę.", "Опиши одним предложением: у тебя большая семья — мама, папа, брат и сестра.", "Опиши одним реченням: у тебе велика родина — мама, тато, брат і сестра.", "Describe in one sentence: you have a big family — mom, dad, brother and sister.", + "Mam dużą rodzinę: mamę, tatę, brata i siostrę", "first_letter", "M", 20), + ] + + for q in test_questions_t3: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_family', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t3 = [ + ("a1_family_t01", "A", "dziadek", "дедушка", "дідусь", "grandpa", False, "wrong_gender"), + ("a1_family_t01", "B", "babcia", "бабушка", "бабуся", "grandma", True, None), + ("a1_family_t01", "C", "ciocia", "тётя", "тітка", "aunt", False, "wrong_word"), + ("a1_family_t01", "D", "wujek", "дядя", "дядько", "uncle", False, "wrong_gender"), + ("a1_family_t02", "A", "dziadek", "дедушка", "дідусь", "grandpa", False, "wrong_word"), + ("a1_family_t02", "B", "kuzyn", "двоюродный брат", "двоюрідний брат", "cousin", False, "wrong_word"), + ("a1_family_t02", "C", "wujek", "дядя", "дядько", "uncle", True, None), + ("a1_family_t02", "D", "brat", "брат", "брат", "brother", False, "wrong_word"), + ("a1_family_t03", "A", "mój", "мой", "мій", "my (m)", True, None), + ("a1_family_t03", "B", "moja", "моя", "моя", "my (f)", False, "wrong_gender"), + ("a1_family_t03", "C", "moje", "мои", "мої", "my (n/pl)", False, "wrong_gender"), + ("a1_family_t03", "D", "moi", "мои", "мої", "my (masc. pl)", False, "wrong_number"), + ("a1_family_t04", "A", "moje", "мои", "мої", "my", False, "wrong_gender"), + ("a1_family_t04", "B", "moi", "мои", "мої", "my (masc. personal pl)", True, None), + ("a1_family_t04", "C", "mój", "мой", "мій", "my (m sing)", False, "wrong_number"), + ("a1_family_t04", "D", "moja", "моя", "моя", "my (f sing)", False, "wrong_number"), + ("a1_family_t05", "A", "brat", "брат", "брат", "brother", False, "wrong_case"), + ("a1_family_t05", "B", "brata", "брата", "брата", "brother (acc.)", True, None), + ("a1_family_t05", "C", "bratem", "братом", "братом", "brother (instr.)", False, "wrong_case"), + ("a1_family_t05", "D", "bracia", "братья", "брати", "brothers", False, "wrong_number"), + ("a1_family_t06", "A", "У тебя есть сестра?", "У тебя есть сестра?", "У тебе є сестра?", "Do you have a sister?", True, None), + ("a1_family_t06", "B", "Это твоя сестра?", "Это твоя сестра?", "Це твоя сестра?", "Is this your sister?", False, "wrong_translation"), + ("a1_family_t06", "C", "Ты сестра?", "Ты сестра?", "Ти сестра?", "Are you a sister?", False, "wrong_translation"), + ("a1_family_t06", "D", "Где твоя сестра?", "Где твоя сестра?", "Де твоя сестра?", "Where is your sister?", False, "wrong_translation"), + ("a1_family_t07", "A", "ciocia", "тётя", "тітка", "aunt", False, "wrong_word"), + ("a1_family_t07", "B", "babcia", "бабушка", "бабуся", "grandma", True, None), + ("a1_family_t07", "C", "kuzynka", "двоюродная сестра", "двоюрідна сестра", "cousin (f)", False, "wrong_word"), + ("a1_family_t07", "D", "mama", "мама", "мама", "mom", False, "wrong_context"), + ("a1_family_t08", "A", "To jest moja brat.", "Это моя брат. (неправильно)", "Це моя брат. (неправильно)", "This is my (f) brother. (wrong gender)", False, "wrong_gender"), + ("a1_family_t08", "B", "To jest mój brat.", "Это мой брат.", "Це мій брат.", "This is my brother.", True, None), + ("a1_family_t08", "C", "To jest moje brat.", "Это моё брат. (неправильно)", "Це моє брат. (неправильно)", "This is my (n) brother. (wrong gender)", False, "wrong_gender"), + ("a1_family_t08", "D", "To jest moi brat.", "Это мои брат. (неправильно)", "Це мої брат. (неправильно)", "This is my (pl) brother. (wrong number)", False, "wrong_number"), + ("a1_family_t09", "A", "Mam brat.", "У меня брат. (неправильно)", "У мене брат. (неправильно)", "I have brother. (wrong case)", False, "wrong_case"), + ("a1_family_t09", "B", "Mam brata.", "У меня есть брат.", "У мене є брат.", "I have a brother.", True, None), + ("a1_family_t09", "C", "Jestem brat.", "Я брат.", "Я брат.", "I am brother.", False, "wrong_sentence_type"), + ("a1_family_t09", "D", "To brat.", "Это брат.", "Це брат.", "This is a brother.", False, "wrong_sentence_type"), + ("a1_family_t10", "A", "Mam siostrę.", "У меня есть сестра.", "У мене є сестра.", "I have a sister.", False, "wrong_sentence_type"), + ("a1_family_t10", "B", "Masz siostrę?", "У тебя есть сестра?", "У тебе є сестра?", "Do you have a sister?", True, None), + ("a1_family_t10", "C", "To jest siostra.", "Это сестра.", "Це сестра.", "This is a sister.", False, "wrong_sentence_type"), + ("a1_family_t10", "D", "Moja siostra.", "Моя сестра.", "Моя сестра.", "My sister.", False, "wrong_sentence_type"), + ("a1_family_t11", "A", "Masz mamę?", "У тебя есть мама?", "У тебе є мама?", "Do you have a mom?", False, "wrong_sentence_type"), + ("a1_family_t11", "B", "To jest moja mama.", "Это моя мама.", "Це моя мама.", "This is my mom.", True, None), + ("a1_family_t11", "C", "Mam mamę.", "У меня есть мама.", "У мене є мама.", "I have a mom.", False, "wrong_context"), + ("a1_family_t11", "D", "Jestem mama.", "Я мама.", "Я мама.", "I am mom.", False, "wrong_sentence_type"), + ("a1_family_t12", "A", "Mam duża rodzina.", "У меня большая семья. (неправильно)", "У мене велика родина. (неправильно)", "I have big family. (wrong case)", False, "wrong_case"), + ("a1_family_t12", "B", "Mam dużą rodzinę.", "У меня большая семья.", "У мене велика родина.", "I have a big family.", True, None), + ("a1_family_t12", "C", "Jestem duża rodzina.", "Я большая семья.", "Я велика родина.", "I am big family.", False, "wrong_sentence_type"), + ("a1_family_t12", "D", "To duża rodzina.", "Это большая семья.", "Це велика родина.", "This is a big family.", False, "wrong_sentence_type"), + ("a1_family_t19", "A", "Masz brata? Tak, to jest mój brat, Adam.", "У тебя есть брат? Да, это мой брат, Адам.", "У тебе є брат? Так, це мій брат, Адам.", "Do you have a brother? Yes, this is my brother, Adam.", True, None), + ("a1_family_t19", "B", "Mam brata? Tak, jestem mój brat, Adam.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_family_t19", "C", "Masz brat? Tak, to moja brat, Adam.", "Неправильные падежи.", "Неправильні відмінки.", "Wrong cases.", False, "wrong_case"), + ("a1_family_t19", "D", "Czy brata? Tak, mój brat Adam.", "Неполная конструкция.", "Неповна конструкція.", "Incomplete construction.", False, "wrong_sentence_type"), + ("a1_family_t20", "A", "Mam dużą rodzinę: mamę, tatę, brata i siostrę.", "У меня большая семья: мама, папа, брат и сестра.", "У мене велика родина: мама, тато, брат і сестра.", "I have a big family: mom, dad, brother and sister.", True, None), + ("a1_family_t20", "B", "Mam duża rodzina: mama, tata, brat, siostra.", "Неправильные падежи.", "Неправильні відмінки.", "Wrong cases.", False, "wrong_case"), + ("a1_family_t20", "C", "Jestem duża rodzina z mamą, tatą, bratem i siostrą.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_family_t20", "D", "Nie mam dużej rodziny.", "У меня нет большой семьи.", "У мене немає великої родини.", "I don't have a big family.", False, "wrong_context"), + ] + + for opt in test_options_t3: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # ==================== ТЕМА 4: ЕДА И НАПИТКИ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_food', 'A1', 4, + 'Jedzenie i picie', + 'Еда и напитки', + 'Їжа та напої', + 'Food and Drinks') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t4 = [ + ("a1_food_l01", 1, "food_vocabulary", "Podstawowe produkty", "Основные продукты", "Основні продукти", "Basic products", + "Podstawowe słowa: chleb (rodzaj męski), mleko (rodzaj nijaki), ser (rodzaj męski), jajko (rodzaj nijaki). To rzeczy, które kupujemy najczęściej.", + "Основные слова: chleb (мужской род), mleko (средний род), ser (мужской род), jajko (средний род). Это продукты, которые покупаем чаще всего.", + "Основні слова: chleb (чоловічий рід), mleko (середній рід), ser (чоловічий рід), jajko (середній рід). Це продукти, які купуємо найчастіше.", + "Basic words: chleb (masculine), mleko (neuter), ser (masculine), jajko (neuter). These are things we buy most often."), + ("a1_food_l02", 2, "food_vocabulary", "W kuchni", "На кухне", "На кухні", "In the kitchen", + "Więcej produktów do gotowania: mąka, cukier, sól, ryż, makaron. Tych słów używamy, gdy mówimy o gotowaniu.", + "Больше продуктов для готовки: mąka (мука), cukier (сахар), sól (соль), ryż (рис), makaron (макароны). Эти слова используем, когда говорим о готовке.", + "Більше продуктів для готування: mąka (борошно), cukier (цукор), sól (сіль), ryż (рис), makaron (макарони). Ці слова використовуємо, коли говоримо про готування.", + "More cooking ingredients: mąka (flour), cukier (sugar), sól (salt), ryż (rice), makaron (pasta). We use these words when talking about cooking."), + ("a1_food_l03", 3, "food_fruits_vegetables", "Owoce", "Фрукты", "Фрукти", "Fruits", + "Owoce: jabłko, banan, gruszka, pomarańcza. „Jabłko” jest rodzaju nijakiego, „banan” rodzaju męskiego, „gruszka” i „pomarańcza” rodzaju żeńskiego.", + "Фрукты: jabłko (яблоко), banan (банан), gruszka (груша), pomarańcza (апельсин). „Jabłko” среднего рода, „banan” мужского, „gruszka” и „pomarańcza” женского.", + "Фрукти: jabłko (яблуко), banan (банан), gruszka (груша), pomarańcza (апельсин). „Jabłko” середнього роду, „banan” чоловічого, „gruszka” і „pomarańcza” жіночого.", + "Fruits: jabłko (apple), banan (banana), gruszka (pear), pomarańcza (orange). „Jabłko” is neuter, „banan” is masculine, „gruszka” and „pomarańcza” are feminine."), + ("a1_food_l04", 4, "food_fruits_vegetables", "Warzywa", "Овощи", "Овочі", "Vegetables", + "Warzywa: pomidor, ziemniak, marchewka, ogórek. „Pomidor”, „ziemniak” i „ogórek” są rodzaju męskiego, „marchewka” jest rodzaju żeńskiego.", + "Овощи: pomidor (помидор), ziemniak (картофель), marchewka (морковь), ogórek (огурец). „Pomidor”, „ziemniak” и „ogórek” мужского рода, „marchewka” — женского.", + "Овочі: pomidor (помідор), ziemniak (картопля), marchewka (морква), ogórek (огірок). „Pomidor”, „ziemniak” і „ogórek” чоловічого роду, „marchewka” — жіночого.", + "Vegetables: pomidor (tomato), ziemniak (potato), marchewka (carrot), ogórek (cucumber). „Pomidor”, „ziemniak” and „ogórek” are masculine, „marchewka” is feminine."), + ("a1_food_l05", 5, "food_drinks", "Podstawowe napoje", "Основные напитки", "Основні напої", "Basic drinks", + "Napoje: woda, herbata, kawa. Wszystkie są rodzaju żeńskiego. Czasownik „pić” łączy się z biernikiem: piję wodę, piję herbatę, piję kawę.", + "Напитки: woda (вода), herbata (чай), kawa (кофе). Все женского рода. Глагол „pić” требует винительного падежа: piję wodę, piję herbatę, piję kawę.", + "Напої: woda (вода), herbata (чай), kawa (кава). Усі жіночого роду. Дієслово „pić” вимагає знахідного відмінка: piję wodę, piję herbatę, piję kawę.", + "Drinks: woda (water), herbata (tea), kawa (coffee). All are feminine. The verb „pić” (to drink) takes the accusative: piję wodę, piję herbatę, piję kawę."), + ("a1_food_l06", 6, "food_drinks", "Więcej napojów", "Больше напитков", "Більше напоїв", "More drinks", + "Więcej napojów: sok, lemoniada. Odmiana czasownika „pić”: ja piję, ty pijesz, on/ona pije.", + "Больше напитков: sok (сок), lemoniada (лимонад). Спряжение глагола „pić”: ja piję, ty pijesz, on/ona pije.", + "Більше напоїв: sok (сік), lemoniada (лимонад). Відмінювання дієслова „pić”: ja piję, ty pijesz, on/ona pije.", + "More drinks: sok (juice), lemoniada (lemonade). Conjugation of „pić” (to drink): ja piję, ty pijesz, on/ona pije."), + ("a1_food_l07", 7, "food_meals", "Posiłki", "Приёмы пищи", "Прийоми їжі", "Meals", + "Posiłki w ciągu dnia: śniadanie (rano), obiad (w południe), kolacja (wieczorem). Te trzy słowa mają różne rodzaje: śniadanie — nijaki, obiad — męski, kolacja — żeński.", + "Приёмы пищи в течение дня: śniadanie (завтрак, утром), obiad (обед, в полдень), kolacja (ужин, вечером). Śniadanie среднего рода, obiad мужского, kolacja женского.", + "Прийоми їжі протягом дня: śniadanie (сніданок, вранці), obiad (обід, опівдні), kolacja (вечеря, ввечері). Śniadanie середнього роду, obiad чоловічого, kolacja жіночого.", + "Meals during the day: śniadanie (breakfast, morning), obiad (lunch, midday), kolacja (dinner, evening). Śniadanie is neuter, obiad is masculine, kolacja is feminine."), + ("a1_food_l08", 8, "food_meals", "Co jesz na...?", "Что ты ешь на...?", "Що ти їси на...?", "What do you eat for...?", + "Pytamy „Co jesz na śniadanie/obiad/kolację?” i odpowiadamy „Na śniadanie jem ___.” Zwróć uwagę: „kolację” ma końcówkę biernika, bo jest po „na”.", + "Спрашиваем „Co jesz na śniadanie/obiad/kolację?” и отвечаем „Na śniadanie jem ___.” Обрати внимание: „kolację” имеет окончание винительного падежа, потому что стоит после „na”.", + "Запитуємо „Co jesz na śniadanie/obiad/kolację?” і відповідаємо „Na śniadanie jem ___.” Зверни увагу: „kolację” має закінчення знахідного відмінка, бо стоїть після „na”.", + "We ask „Co jesz na śniadanie/obiad/kolację?” and answer „Na śniadanie jem ___.” Note: „kolację” has an accusative ending because it follows „na”."), + ("a1_food_l09", 9, "food_lubie", "Lubię + biernik", "Lubię + винительный падеж", "Lubię + знахідний відмінок", "Lubię + accusative", + "Czasownik „lubić” łączy się z biernikiem: lubię chleb (bez zmiany), lubię jabłko (bez zmiany), lubię kawę (kawa → kawę). Rzeczowniki męskie nieżywotne i nijakie się nie zmieniają, żeńskie dostają końcówkę -ę.", + "Глагол „lubić” требует винительного падежа: lubię chleb (без изменений), lubię jabłko (без изменений), lubię kawę (kawa → kawę). Мужские неодушевлённые и средний род не меняются, женский род получает окончание -ę.", + "Дієслово „lubić” вимагає знахідного відмінка: lubię chleb (без змін), lubię jabłko (без змін), lubię kawę (kawa → kawę). Чоловічі неістоти і середній рід не змінюються, жіночий рід отримує закінчення -ę.", + "The verb „lubić” (to like) takes the accusative: lubię chleb (unchanged), lubię jabłko (unchanged), lubię kawę (kawa → kawę). Masculine inanimate and neuter nouns stay the same; feminine nouns get the -ę ending."), + ("a1_food_l10", 10, "food_lubie", "Nie lubię + dopełniacz", "Nie lubię + родительный падеж", "Nie lubię + родовий відмінок", "Nie lubię + genitive", + "Po zaprzeczeniu „nie lubię” rzeczownik zmienia się na dopełniacz: nie lubię kawy (a nie „kawę”), nie lubię sera (a nie „ser”). W liczbie mnogiej: nie lubię jabłek (a nie „jabłka”).", + "После отрицания „nie lubię” существительное меняется на родительный падеж: nie lubię kawy (а не „kawę”), nie lubię sera (а не „ser”). Во множественном числе: nie lubię jabłek (а не „jabłka”).", + "Після заперечення „nie lubię” іменник змінюється на родовий відмінок: nie lubię kawy (а не „kawę”), nie lubię sera (а не „ser”). У множині: nie lubię jabłek (а не „jabłka”).", + "After the negation „nie lubię”, the noun switches to the genitive: nie lubię kawy (not „kawę”), nie lubię sera (not „ser”). In the plural: nie lubię jabłek (not „jabłka”)."), + ] + + for lesson in lessons_t4: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_food', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t4 = [ + ("a1_food_l01", 1, "Kupuję chleb i mleko.", "Я покупаю хлеб и молоко.", "Я купую хліб і молоко.", "I buy bread and milk."), + ("a1_food_l01", 2, "Ser jest w lodówce.", "Сыр в холодильнике.", "Сир у холодильнику.", "The cheese is in the fridge."), + ("a1_food_l01", 3, "Jem jajko na śniadanie.", "Я ем яйцо на завтрак.", "Я їм яйце на сніданок.", "I eat an egg for breakfast."), + ("a1_food_l02", 1, "W kuchni mam mąkę i cukier.", "На кухне у меня есть мука и сахар.", "На кухні у мене є борошно і цукор.", "In the kitchen I have flour and sugar."), + ("a1_food_l02", 2, "Gotuję ryż i makaron.", "Я готовлю рис и макароны.", "Я готую рис і макарони.", "I'm cooking rice and pasta."), + ("a1_food_l02", 3, "Dodaję sól do zupy.", "Я добавляю соль в суп.", "Я додаю сіль до супу.", "I add salt to the soup."), + ("a1_food_l03", 1, "Lubię jabłka i banany.", "Я люблю яблоки и бананы.", "Я люблю яблука і банани.", "I like apples and bananas."), + ("a1_food_l03", 2, "Pomarańcza jest słodka.", "Апельсин сладкий.", "Апельсин солодкий.", "The orange is sweet."), + ("a1_food_l03", 3, "Kupuję gruszki na targu.", "Я покупаю груши на рынке.", "Я купую груші на ринку.", "I buy pears at the market."), + ("a1_food_l04", 1, "Kupuję pomidory i ogórki.", "Я покупаю помидоры и огурцы.", "Я купую помідори та огірки.", "I buy tomatoes and cucumbers."), + ("a1_food_l04", 2, "Gotuję ziemniaki.", "Я варю картофель.", "Я варю картоплю.", "I'm cooking potatoes."), + ("a1_food_l04", 3, "Marchewka jest pomarańczowa.", "Морковь оранжевая.", "Морква помаранчева.", "The carrot is orange."), + ("a1_food_l05", 1, "Piję wodę rano.", "Я пью воду утром.", "Я п'ю воду вранці.", "I drink water in the morning."), + ("a1_food_l05", 2, "Lubię herbatę z cytryną.", "Я люблю чай с лимоном.", "Я люблю чай з лимоном.", "I like tea with lemon."), + ("a1_food_l05", 3, "Piję kawę codziennie.", "Я пью кофе каждый день.", "Я п'ю каву щодня.", "I drink coffee every day."), + ("a1_food_l06", 1, "Piję sok pomarańczowy.", "Я пью апельсиновый сок.", "Я п'ю апельсиновий сік.", "I drink orange juice."), + ("a1_food_l06", 2, "Dzieci piją lemoniadę latem.", "Дети пьют лимонад летом.", "Діти п'ють лимонад влітку.", "Children drink lemonade in summer."), + ("a1_food_l06", 3, "Co pijesz?", "Что ты пьёшь?", "Що ти п'єш?", "What do you drink?"), + ("a1_food_l07", 1, "Jem śniadanie o ósmej.", "Я завтракаю в восемь.", "Я снідаю о восьмій.", "I have breakfast at eight."), + ("a1_food_l07", 2, "Jem obiad o dwunastej.", "Я обедаю в двенадцать.", "Я обідаю о дванадцятій.", "I have lunch at twelve."), + ("a1_food_l07", 3, "Kolacja jest wieczorem.", "Ужин вечером.", "Вечеря ввечері.", "Dinner is in the evening."), + ("a1_food_l08", 1, "Co jesz na śniadanie?", "Что ты ешь на завтрак?", "Що ти їси на сніданок?", "What do you eat for breakfast?"), + ("a1_food_l08", 2, "Na śniadanie jem chleb i ser.", "На завтрак я ем хлеб и сыр.", "На сніданок я їм хліб і сир.", "For breakfast I eat bread and cheese."), + ("a1_food_l08", 3, "Co jesz na obiad?", "Что ты ешь на обед?", "Що ти їси на обід?", "What do you eat for lunch?"), + ("a1_food_l09", 1, "Lubię chleb.", "Я люблю хлеб.", "Я люблю хліб.", "I like bread."), + ("a1_food_l09", 2, "Lubię jabłko.", "Я люблю яблоко.", "Я люблю яблуко.", "I like an apple."), + ("a1_food_l09", 3, "Lubię kawę.", "Я люблю кофе.", "Я люблю каву.", "I like coffee."), + ("a1_food_l10", 1, "Lubię jabłka.", "Я люблю яблоки.", "Я люблю яблука.", "I like apples."), + ("a1_food_l10", 2, "Nie lubię kawy.", "Я не люблю кофе.", "Я не люблю каву.", "I don't like coffee."), + ("a1_food_l10", 3, "Nie lubię sera.", "Я не люблю сыр.", "Я не люблю сир.", "I don't like cheese."), + ] + + for ex in examples_t4: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t4 = [ + ("a1_food_l01_q1", "a1_food_l01", "lesson_practice", "recognition", "food_vocabulary", 1, + "Jak po polsku „молоко”?", "Как по-польски «молоко»?", "Як польською «молоко»?", "How do you say “milk” in Polish?", + "A", None, None), + ("a1_food_l01_q2", "a1_food_l01", "lesson_practice", "production", "food_vocabulary", 1, + "Wpisz brakujące słowo: Kupuję ___. (хлеб)", "Вставьте пропущенное слово: Kupuję ___. (хлеб)", "Вставте пропущене слово: Kupuję ___. (хліб)", "Fill in the missing word: Kupuję ___. (bread)", + "chleb", "first_letter", "c"), + ("a1_food_l01_q3", "a1_food_l01", "lesson_practice", "application", "food_vocabulary", 1, + "Chcesz kupić coś, co robi się z mleka. Co kupisz?", "Ты хочешь купить что-то, что делают из молока. Что ты купишь?", "Ти хочеш купити щось, що роблять з молока. Що ти купиш?", "You want to buy something made from milk. What do you buy?", + "B", None, None), + ("a1_food_l02_q1", "a1_food_l02", "lesson_practice", "recognition", "food_vocabulary", 1, + "Jak po polsku „сахар”?", "Как по-польски «сахар»?", "Як польською «цукор»?", "How do you say “sugar” in Polish?", + "B", None, None), + ("a1_food_l02_q2", "a1_food_l02", "lesson_practice", "production", "food_vocabulary", 1, + "Wpisz brakujące słowo: Gotuję ___. (рис)", "Вставьте пропущенное слово: Gotuję ___. (рис)", "Вставте пропущене слово: Gotuję ___. (рис)", "Fill in the missing word: Gotuję ___. (rice)", + "ryż", "first_letter", "r"), + ("a1_food_l02_q3", "a1_food_l02", "lesson_practice", "application", "food_vocabulary", 1, + "Gotujesz zupę, ale jest bez smaku. Czego dodasz?", "Ты варишь суп, но он невкусный. Что ты добавишь?", "Ти вариш суп, але він несмачний. Що ти додаси?", "You're cooking soup, but it's bland. What do you add?", + "C", None, None), + ("a1_food_l03_q1", "a1_food_l03", "lesson_practice", "recognition", "food_fruits_vegetables", 1, + "Jak po polsku „банан”?", "Как по-польски «банан»?", "Як польською «банан»?", "How do you say “banana” in Polish?", + "A", None, None), + ("a1_food_l03_q2", "a1_food_l03", "lesson_practice", "production", "food_fruits_vegetables", 1, + "Wpisz brakujące słowo: Jem ___. (яблоко)", "Вставьте пропущенное слово: Jem ___. (яблоко)", "Вставте пропущене слово: Jem ___. (яблуко)", "Fill in the missing word: Jem ___. (apple)", + "jabłko", "first_letter", "j"), + ("a1_food_l03_q3", "a1_food_l03", "lesson_practice", "application", "food_fruits_vegetables", 1, + "Chcesz kupić owoc, który jest długi i żółty. Co kupisz?", "Ты хочешь купить фрукт, который длинный и жёлтый. Что ты купишь?", "Ти хочеш купити фрукт, який довгий і жовтий. Що ти купиш?", "You want to buy a fruit that is long and yellow. What do you buy?", + "A", None, None), + ("a1_food_l04_q1", "a1_food_l04", "lesson_practice", "recognition", "food_fruits_vegetables", 1, + "Jak po polsku „картофель”?", "Как по-польски «картофель»?", "Як польською «картопля»?", "How do you say “potato” in Polish?", + "B", None, None), + ("a1_food_l04_q2", "a1_food_l04", "lesson_practice", "production", "food_fruits_vegetables", 1, + "Wpisz brakujące słowo: Kupuję ___. (помидор)", "Вставьте пропущенное слово: Kupuję ___. (помидор)", "Вставте пропущене слово: Kupuję ___. (помідор)", "Fill in the missing word: Kupuję ___. (tomato)", + "pomidor", "first_letter", "p"), + ("a1_food_l04_q3", "a1_food_l04", "lesson_practice", "application", "food_fruits_vegetables", 1, + "Robisz sałatkę. Potrzebujesz warzywa, które jest pomarańczowe. Co wybierzesz?", "Ты делаешь салат. Тебе нужен овощ, который оранжевый. Что ты выберешь?", "Ти робиш салат. Тобі потрібен овоч, який помаранчевий. Що ти вибереш?", "You're making a salad. You need a vegetable that is orange. What do you choose?", + "D", None, None), + ("a1_food_l05_q1", "a1_food_l05", "lesson_practice", "recognition", "food_drinks", 2, + "Jak po polsku „чай”?", "Как по-польски «чай»?", "Як польською «чай»?", "How do you say “tea” in Polish?", + "B", None, None), + ("a1_food_l05_q2", "a1_food_l05", "lesson_practice", "production", "food_drinks", 2, + "Wpisz brakujące słowo: Piję ___. (кофе, винительный)", "Вставьте пропущенное слово: Piję ___. (кофе, винительный)", "Вставте пропущене слово: Piję ___. (кава, знахідний)", "Fill in the missing word: Piję ___. (coffee, accusative)", + "kawę", "first_letter", "k"), + ("a1_food_l05_q3", "a1_food_l05", "lesson_practice", "application", "food_drinks", 2, + "Rano jesteś bardzo zmęczony. Co wypijesz, żeby się obudzić?", "Утром ты очень уставший. Что ты выпьешь, чтобы проснуться?", "Вранці ти дуже втомлений. Що ти вип'єш, щоб прокинутися?", "You're very tired in the morning. What do you drink to wake up?", + "B", None, None), + ("a1_food_l06_q1", "a1_food_l06", "lesson_practice", "recognition", "food_drinks", 2, + "Jak po polsku „сок”?", "Как по-польски «сок»?", "Як польською «сік»?", "How do you say “juice” in Polish?", + "C", None, None), + ("a1_food_l06_q2", "a1_food_l06", "lesson_practice", "production", "food_drinks", 2, + "Wpisz brakujące słowo: Ty ___ sok. (пьёшь)", "Вставьте пропущенное слово: Ty ___ sok. (пьёшь)", "Вставте пропущене слово: Ty ___ sok. (п'єш)", "Fill in the missing word: Ty ___ sok. (you drink)", + "pijesz", "first_letter", "p"), + ("a1_food_l06_q3", "a1_food_l06", "lesson_practice", "application", "food_drinks", 2, + "Kolega pyta „Co pijesz?” Chcesz odpowiedzieć, że pijesz sok. Co powiesz?", "Друг спрашивает «Co pijesz?» Ты хочешь ответить, что пьёшь сок. Что ты скажешь?", "Друг питає «Co pijesz?» Ти хочеш відповісти, що п'єш сік. Що ти скажеш?", "A friend asks “Co pijesz?” You want to answer that you're drinking juice. What do you say?", + "A", None, None), + ("a1_food_l07_q1", "a1_food_l07", "lesson_practice", "recognition", "food_meals", 2, + "Jak po polsku „ужин”?", "Как по-польски «ужин»?", "Як польською «вечеря»?", "How do you say “dinner” in Polish?", + "C", None, None), + ("a1_food_l07_q2", "a1_food_l07", "lesson_practice", "production", "food_meals", 2, + "Wpisz brakujące słowo: Jem ___ rano. (завтрак)", "Вставьте пропущенное слово: Jem ___ rano. (завтрак)", "Вставте пропущене слово: Jem ___ rano. (сніданок)", "Fill in the missing word: Jem ___ rano. (breakfast)", + "śniadanie", "first_letter", "ś"), + ("a1_food_l07_q3", "a1_food_l07", "lesson_practice", "application", "food_meals", 2, + "Jest wieczór, godzina 19:00. Co teraz jesz?", "Сейчас вечер, 19:00. Что ты сейчас ешь?", "Зараз вечір, 19:00. Що ти зараз їси?", "It's evening, 7 PM. What are you eating now?", + "C", None, None), + ("a1_food_l08_q1", "a1_food_l08", "lesson_practice", "recognition", "food_meals", 2, + "Co znaczy „Co jesz na śniadanie?”", "Что означает «Co jesz na śniadanie?»", "Що означає «Co jesz na śniadanie?»", "What does “Co jesz na śniadanie?” mean?", + "A", None, None), + ("a1_food_l08_q2", "a1_food_l08", "lesson_practice", "production", "food_meals", 2, + "Wpisz brakujące słowo: Na ___ jem jajko. (завтрак)", "Вставьте пропущенное слово: Na ___ jem jajko. (завтрак)", "Вставте пропущене слово: Na ___ jem jajko. (сніданок)", "Fill in the missing word: Na ___ jem jajko. (breakfast)", + "śniadanie", "first_letter", "ś"), + ("a1_food_l08_q3", "a1_food_l08", "lesson_practice", "application", "food_meals", 2, + "Kolega pyta „Co jesz na obiad?” Chcesz odpowiedzieć, że jesz ziemniaki i pomidory. Co powiesz?", "Друг спрашивает «Co jesz na obiad?» Ты хочешь ответить, что ешь картофель и помидоры. Что ты скажешь?", "Друг питає «Co jesz na obiad?» Ти хочеш відповісти, що їси картоплю і помідори. Що ти скажеш?", "A friend asks “Co jesz na obiad?” You want to answer that you eat potatoes and tomatoes. What do you say?", + "B", None, None), + ("a1_food_l09_q1", "a1_food_l09", "lesson_practice", "recognition", "food_lubie", 3, + "Wybierz poprawną formę: Lubię ___. (kawa)", "Выберите правильную форму: Lubię ___. (kawa)", "Виберіть правильну форму: Lubię ___. (kawa)", "Choose the correct form: Lubię ___. (kawa)", + "B", None, None), + ("a1_food_l09_q2", "a1_food_l09", "lesson_practice", "production", "food_lubie", 3, + "Wpisz brakujące słowo: Lubię ___. (яблоко)", "Вставьте пропущенное слово: Lubię ___. (яблоко)", "Вставте пропущене слово: Lubię ___. (яблуко)", "Fill in the missing word: Lubię ___. (apple)", + "jabłko", "first_letter", "j"), + ("a1_food_l09_q3", "a1_food_l09", "lesson_practice", "application", "food_lubie", 3, + "Kolega pyta, co lubisz jeść. Chcesz powiedzieć, że lubisz ser. Co powiesz?", "Друг спрашивает, что ты любишь есть. Ты хочешь сказать, что любишь сыр. Что ты скажешь?", "Друг питає, що ти любиш їсти. Ти хочеш сказати, що любиш сир. Що ти скажеш?", "A friend asks what you like to eat. You want to say you like cheese. What do you say?", + "A", None, None), + ("a1_food_l10_q1", "a1_food_l10", "lesson_practice", "recognition", "food_lubie", 3, + "Wybierz poprawną formę: Nie lubię ___. (kawa)", "Выберите правильную форму: Nie lubię ___. (kawa)", "Виберіть правильну форму: Nie lubię ___. (kawa)", "Choose the correct form: Nie lubię ___. (kawa)", + "C", None, None), + ("a1_food_l10_q2", "a1_food_l10", "lesson_practice", "production", "food_lubie", 3, + "Wpisz brakujące słowo: Nie lubię ___. (сыр, родительный)", "Вставьте пропущенное слово: Nie lubię ___. (сыр, родительный)", "Вставте пропущене слово: Nie lubię ___. (сир, родовий)", "Fill in the missing word: Nie lubię ___. (cheese, genitive)", + "sera", "first_letter", "s"), + ("a1_food_l10_q3", "a1_food_l10", "lesson_practice", "application", "food_lubie", 3, + "Kolega pyta, czy lubisz kawę. Nie lubisz jej. Co powiesz?", "Друг спрашивает, любишь ли ты кофе. Ты его не любишь. Что ты скажешь?", "Друг питає, чи любиш ти каву. Ти її не любиш. Що ти скажеш?", "A friend asks if you like coffee. You don't like it. What do you say?", + "A", None, None), + ] + + for q in questions_t4: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_food', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t4 = [ + ("a1_food_l01_q1", "A", "mleko", "молоко", "молоко", "milk", True, None), + ("a1_food_l01_q1", "B", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a1_food_l01_q1", "C", "ser", "сыр", "сир", "cheese", False, "wrong_word"), + ("a1_food_l01_q1", "D", "jajko", "яйцо", "яйце", "egg", False, "wrong_word"), + ("a1_food_l01_q3", "A", "chleb", "хлеб", "хліб", "bread", False, "wrong_context"), + ("a1_food_l01_q3", "B", "ser", "сыр", "сир", "cheese", True, None), + ("a1_food_l01_q3", "C", "mleko", "молоко", "молоко", "milk", False, "wrong_context"), + ("a1_food_l01_q3", "D", "jajko", "яйцо", "яйце", "egg", False, "wrong_context"), + ("a1_food_l02_q1", "A", "sól", "соль", "сіль", "salt", False, "wrong_word"), + ("a1_food_l02_q1", "B", "cukier", "сахар", "цукор", "sugar", True, None), + ("a1_food_l02_q1", "C", "mąka", "мука", "борошно", "flour", False, "wrong_word"), + ("a1_food_l02_q1", "D", "ryż", "рис", "рис", "rice", False, "wrong_word"), + ("a1_food_l02_q3", "A", "cukier", "сахар", "цукор", "sugar", False, "wrong_context"), + ("a1_food_l02_q3", "B", "mąka", "мука", "борошно", "flour", False, "wrong_context"), + ("a1_food_l02_q3", "C", "sól", "соль", "сіль", "salt", True, None), + ("a1_food_l02_q3", "D", "ryż", "рис", "рис", "rice", False, "wrong_context"), + ("a1_food_l03_q1", "A", "banan", "банан", "банан", "banana", True, None), + ("a1_food_l03_q1", "B", "jabłko", "яблоко", "яблуко", "apple", False, "wrong_word"), + ("a1_food_l03_q1", "C", "gruszka", "груша", "груша", "pear", False, "wrong_word"), + ("a1_food_l03_q1", "D", "pomarańcza", "апельсин", "апельсин", "orange", False, "wrong_word"), + ("a1_food_l03_q3", "A", "banan", "банан", "банан", "banana", True, None), + ("a1_food_l03_q3", "B", "jabłko", "яблоко", "яблуко", "apple", False, "wrong_context"), + ("a1_food_l03_q3", "C", "gruszka", "груша", "груша", "pear", False, "wrong_context"), + ("a1_food_l03_q3", "D", "pomarańcza", "апельсин", "апельсин", "orange", False, "wrong_context"), + ("a1_food_l04_q1", "A", "pomidor", "помидор", "помідор", "tomato", False, "wrong_word"), + ("a1_food_l04_q1", "B", "ziemniak", "картофель", "картопля", "potato", True, None), + ("a1_food_l04_q1", "C", "ogórek", "огурец", "огірок", "cucumber", False, "wrong_word"), + ("a1_food_l04_q1", "D", "marchewka", "морковь", "морква", "carrot", False, "wrong_word"), + ("a1_food_l04_q3", "A", "pomidor", "помидор", "помідор", "tomato", False, "wrong_context"), + ("a1_food_l04_q3", "B", "ziemniak", "картофель", "картопля", "potato", False, "wrong_context"), + ("a1_food_l04_q3", "C", "ogórek", "огурец", "огірок", "cucumber", False, "wrong_context"), + ("a1_food_l04_q3", "D", "marchewka", "морковь", "морква", "carrot", True, None), + ("a1_food_l05_q1", "A", "woda", "вода", "вода", "water", False, "wrong_word"), + ("a1_food_l05_q1", "B", "herbata", "чай", "чай", "tea", True, None), + ("a1_food_l05_q1", "C", "kawa", "кофе", "кава", "coffee", False, "wrong_word"), + ("a1_food_l05_q1", "D", "sok", "сок", "сік", "juice", False, "wrong_word"), + ("a1_food_l05_q3", "A", "Piję wodę.", "Я пью воду.", "Я п'ю воду.", "I drink water.", False, "wrong_context"), + ("a1_food_l05_q3", "B", "Piję kawę.", "Я пью кофе.", "Я п'ю каву.", "I drink coffee.", True, None), + ("a1_food_l05_q3", "C", "Piję herbatę.", "Я пью чай.", "Я п'ю чай.", "I drink tea.", False, "wrong_context"), + ("a1_food_l05_q3", "D", "Jem chleb.", "Я ем хлеб.", "Я їм хліб.", "I eat bread.", False, "wrong_word"), + ("a1_food_l06_q1", "A", "woda", "вода", "вода", "water", False, "wrong_word"), + ("a1_food_l06_q1", "B", "lemoniada", "лимонад", "лимонад", "lemonade", False, "wrong_word"), + ("a1_food_l06_q1", "C", "sok", "сок", "сік", "juice", True, None), + ("a1_food_l06_q1", "D", "herbata", "чай", "чай", "tea", False, "wrong_word"), + ("a1_food_l06_q3", "A", "Piję sok.", "Я пью сок.", "Я п'ю сік.", "I drink juice.", True, None), + ("a1_food_l06_q3", "B", "Pijesz sok.", "Ты пьёшь сок.", "Ти п'єш сік.", "You drink juice.", False, "wrong_sentence_type"), + ("a1_food_l06_q3", "C", "Piję woda.", "Я пью вода. (неправильно)", "Я п'ю вода. (неправильно)", "I drink water. (wrong case)", False, "wrong_case"), + ("a1_food_l06_q3", "D", "Jem sok.", "Я ем сок. (неправильно)", "Я їм сік. (неправильно)", "I eat juice. (wrong verb)", False, "wrong_word"), + ("a1_food_l07_q1", "A", "śniadanie", "завтрак", "сніданок", "breakfast", False, "wrong_word"), + ("a1_food_l07_q1", "B", "obiad", "обед", "обід", "lunch", False, "wrong_word"), + ("a1_food_l07_q1", "C", "kolacja", "ужин", "вечеря", "dinner", True, None), + ("a1_food_l07_q1", "D", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a1_food_l07_q3", "A", "śniadanie", "завтрак", "сніданок", "breakfast", False, "wrong_context"), + ("a1_food_l07_q3", "B", "obiad", "обед", "обід", "lunch", False, "wrong_context"), + ("a1_food_l07_q3", "C", "kolacja", "ужин", "вечеря", "dinner", True, None), + ("a1_food_l07_q3", "D", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a1_food_l08_q1", "A", "Что ты ешь на завтрак?", "Что ты ешь на завтрак?", "Що ти їси на сніданок?", "What do you eat for breakfast?", True, None), + ("a1_food_l08_q1", "B", "Что ты пьёшь утром?", "Что ты пьёшь утром?", "Що ти п'єш вранці?", "What do you drink in the morning?", False, "wrong_translation"), + ("a1_food_l08_q1", "C", "Когда ты завтракаешь?", "Когда ты завтракаешь?", "Коли ти снідаєш?", "When do you have breakfast?", False, "wrong_translation"), + ("a1_food_l08_q1", "D", "Любишь ли ты завтрак?", "Любишь ли ты завтрак?", "Чи любиш ти сніданок?", "Do you like breakfast?", False, "wrong_translation"), + ("a1_food_l08_q3", "A", "Obiad jem ziemniaki i pomidory.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_food_l08_q3", "B", "Na obiad jem ziemniaki i pomidory.", "На обед я ем картофель и помидоры.", "На обід я їм картоплю і помідори.", "For lunch I eat potatoes and tomatoes.", True, None), + ("a1_food_l08_q3", "C", "Jestem ziemniaki i pomidory na obiad.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_food_l08_q3", "D", "Nie jem ziemniaki i pomidory.", "Я не ем картофель и помидоры.", "Я не їм картоплю і помідори.", "I don't eat potatoes and tomatoes.", False, "wrong_context"), + ("a1_food_l09_q1", "A", "kawa", "кофе", "кава", "coffee (nom.)", False, "wrong_case"), + ("a1_food_l09_q1", "B", "kawę", "кофе (вин.)", "каву (знах.)", "coffee (acc.)", True, None), + ("a1_food_l09_q1", "C", "kawie", "кофе (местн.)", "кава (місц.)", "coffee (loc.)", False, "wrong_case"), + ("a1_food_l09_q1", "D", "kawą", "кофе (тв.)", "кава (ор.)", "coffee (instr.)", False, "wrong_case"), + ("a1_food_l09_q3", "A", "Lubię ser.", "Я люблю сыр.", "Я люблю сир.", "I like cheese.", True, None), + ("a1_food_l09_q3", "B", "Lubię sera.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_food_l09_q3", "C", "Jestem ser.", "Я сыр.", "Я сир.", "I am cheese.", False, "wrong_sentence_type"), + ("a1_food_l09_q3", "D", "To ser.", "Это сыр.", "Це сир.", "This is cheese.", False, "wrong_sentence_type"), + ("a1_food_l10_q1", "A", "kawę", "кофе (вин.)", "каву (знах.)", "coffee (acc.)", False, "wrong_case"), + ("a1_food_l10_q1", "B", "kawa", "кофе (им.)", "кава (наз.)", "coffee (nom.)", False, "wrong_case"), + ("a1_food_l10_q1", "C", "kawy", "кофе (род.)", "кави (род.)", "coffee (gen.)", True, None), + ("a1_food_l10_q1", "D", "kawą", "кофе (тв.)", "кава (ор.)", "coffee (instr.)", False, "wrong_case"), + ("a1_food_l10_q3", "A", "Nie lubię kawy.", "Я не люблю кофе.", "Я не люблю каву.", "I don't like coffee.", True, None), + ("a1_food_l10_q3", "B", "Nie lubię kawę.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_food_l10_q3", "C", "Lubię kawy.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_case"), + ("a1_food_l10_q3", "D", "Nie jestem kawa.", "Я не кофе.", "Я не кава.", "I am not coffee.", False, "wrong_sentence_type"), + ] + + for opt in options_t4: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t4 = [ + ("a1_food_t01", None, "topic_test", "recognition", "food_vocabulary", 1, + "Jak po polsku „сыр”?", "Как по-польски «сыр»?", "Як польською «сир»?", "How do you say “cheese” in Polish?", + "B", None, None, 1), + ("a1_food_t02", None, "topic_test", "recognition", "food_vocabulary", 1, + "Jak po polsku „сахар”?", "Как по-польски «сахар»?", "Як польською «цукор»?", "How do you say “sugar” in Polish?", + "A", None, None, 2), + ("a1_food_t03", None, "topic_test", "recognition", "food_fruits_vegetables", 1, + "Jak po polsku „помидор”?", "Как по-польски «помидор»?", "Як польською «помідор»?", "How do you say “tomato” in Polish?", + "C", None, None, 3), + ("a1_food_t04", None, "topic_test", "recognition", "food_drinks", 1, + "Jak po polsku „сок”?", "Как по-польски «сок»?", "Як польською «сік»?", "How do you say “juice” in Polish?", + "B", None, None, 4), + ("a1_food_t05", None, "topic_test", "recognition", "food_meals", 1, + "Jak po polsku „ужин”?", "Как по-польски «ужин»?", "Як польською «вечеря»?", "How do you say “dinner” in Polish?", + "D", None, None, 5), + ("a1_food_t06", None, "topic_test", "recognition", "food_lubie", 2, + "Wybierz poprawną formę: Lubię ___. (herbata)", "Выберите правильную форму: Lubię ___. (herbata)", "Виберіть правильну форму: Lubię ___. (herbata)", "Choose the correct form: Lubię ___. (herbata)", + "A", None, None, 6), + ("a1_food_t07", None, "topic_test", "application", "food_vocabulary", 2, + "Chcesz kupić coś, co robi się z mleka. Co kupisz?", "Ты хочешь купить что-то, что делают из молока. Что ты купишь?", "Ти хочеш купити щось, що роблять з молока. Що ти купиш?", "You want to buy something made from milk. What do you buy?", + "B", None, None, 7), + ("a1_food_t08", None, "topic_test", "application", "food_fruits_vegetables", 2, + "Robisz sałatkę. Potrzebujesz warzywa, które jest pomarańczowe. Co wybierzesz?", "Ты делаешь салат. Тебе нужен овощ, который оранжевый. Что ты выберешь?", "Ти робиш салат. Тобі потрібен овоч, який помаранчевий. Що ти вибереш?", "You're making a salad. You need a vegetable that is orange. What do you choose?", + "D", None, None, 8), + ("a1_food_t09", None, "topic_test", "application", "food_drinks", 2, + "Rano jesteś bardzo zmęczony. Co wypijesz, żeby się obudzić?", "Утром ты очень уставший. Что ты выпьешь, чтобы проснуться?", "Вранці ти дуже втомлений. Що ти вип'єш, щоб прокинутися?", "You're very tired in the morning. What do you drink to wake up?", + "B", None, None, 9), + ("a1_food_t10", None, "topic_test", "application", "food_meals", 2, + "Jest wieczór, godzina 19:00. Co teraz jesz?", "Сейчас вечер, 19:00. Что ты сейчас ешь?", "Зараз вечір, 19:00. Що ти зараз їси?", "It's evening, 7 PM. What are you eating now?", + "C", None, None, 10), + ("a1_food_t11", None, "topic_test", "application", "food_meals", 2, + "Kolega pyta „Co jesz na obiad?” Chcesz odpowiedzieć, że jesz ziemniaki. Co powiesz?", "Друг спрашивает «Co jesz na obiad?» Ты хочешь ответить, что ешь картофель. Что ты скажешь?", "Друг питає «Co jesz na obiad?» Ти хочеш відповісти, що їси картоплю. Що ти скажеш?", "A friend asks “Co jesz na obiad?” You want to answer that you eat potatoes. What do you say?", + "B", None, None, 11), + ("a1_food_t12", None, "topic_test", "application", "food_lubie", 2, + "Kolega pyta, czy lubisz kawę. Nie lubisz jej. Co powiesz?", "Друг спрашивает, любишь ли ты кофе. Ты его не любишь. Что ты скажешь?", "Друг питає, чи любиш ти каву. Ти її не любиш. Що ти скажеш?", "A friend asks if you like coffee. You don't like it. What do you say?", + "A", None, None, 12), + ("a1_food_t13", None, "topic_test", "production", "food_vocabulary", 1, + "Wpisz brakujące słowo: Kupuję ___. (хлеб)", "Вставьте пропущенное слово: Kupuję ___. (хлеб)", "Вставте пропущене слово: Kupuję ___. (хліб)", "Fill in the missing word: Kupuję ___. (bread)", + "chleb", "first_letter", "c", 13), + ("a1_food_t14", None, "topic_test", "production", "food_fruits_vegetables", 1, + "Wpisz brakujące słowo: Jem ___. (яблоко)", "Вставьте пропущенное слово: Jem ___. (яблоко)", "Вставте пропущене слово: Jem ___. (яблуко)", "Fill in the missing word: Jem ___. (apple)", + "jabłko", "first_letter", "j", 14), + ("a1_food_t15", None, "topic_test", "production", "food_drinks", 2, + "Wpisz brakujące słowo: Piję ___. (кофе, винительный)", "Вставьте пропущенное слово: Piję ___. (кофе, винительный)", "Вставте пропущене слово: Piję ___. (кава, знахідний)", "Fill in the missing word: Piję ___. (coffee, accusative)", + "kawę", "first_letter", "k", 15), + ("a1_food_t16", None, "topic_test", "production", "food_meals", 1, + "Wpisz brakujące słowo: Jem ___ rano. (завтрак)", "Вставьте пропущенное слово: Jem ___ rano. (завтрак)", "Вставте пропущене слово: Jem ___ rano. (сніданок)", "Fill in the missing word: Jem ___ rano. (breakfast)", + "śniadanie", "first_letter", "ś", 16), + ("a1_food_t17", None, "topic_test", "production", "food_lubie", 2, + "Wpisz brakujące słowo: Lubię ___. (сыр)", "Вставьте пропущенное слово: Lubię ___. (сыр)", "Вставте пропущене слово: Lubię ___. (сир)", "Fill in the missing word: Lubię ___. (cheese)", + "ser", "first_letter", "s", 17), + ("a1_food_t18", None, "topic_test", "production", "food_lubie", 3, + "Wpisz brakujące słowo: Nie lubię ___. (сыр, родительный)", "Вставьте пропущенное слово: Nie lubię ___. (сыр, родительный)", "Вставте пропущене слово: Nie lubię ___. (сир, родовий)", "Fill in the missing word: Nie lubię ___. (cheese, genitive)", + "sera", "first_letter", "s", 18), + ("a1_food_t19", None, "topic_test", "mixed", "food_lubie", 3, + "Wybierz poprawne tłumaczenie: «Я не люблю кофе, но люблю чай».", "Выберите правильный перевод: «Я не люблю кофе, но люблю чай».", "Виберіть правильний переклад: «Я не люблю каву, але люблю чай».", "Choose the correct translation: “I don't like coffee, but I like tea.”", + "A", None, None, 19), + ("a1_food_t20", None, "topic_test", "mixed", "food_meals", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Что ты ешь на завтрак? — Я ем хлеб и яйцо.»", "Выберите правильный перевод диалога: «— Что ты ешь на завтрак? — Я ем хлеб и яйцо.»", "Виберіть правильний переклад діалогу: «— Що ти їси на сніданок? — Я їм хліб і яйце.»", "Choose the correct translation of the dialogue: “— What do you eat for breakfast? — I eat bread and an egg.”", + "A", None, None, 20), + ] + + for q in test_questions_t4: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_food', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t4 = [ + ("a1_food_t01", "A", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a1_food_t01", "B", "ser", "сыр", "сир", "cheese", True, None), + ("a1_food_t01", "C", "mleko", "молоко", "молоко", "milk", False, "wrong_word"), + ("a1_food_t01", "D", "jajko", "яйцо", "яйце", "egg", False, "wrong_word"), + ("a1_food_t02", "A", "cukier", "сахар", "цукор", "sugar", True, None), + ("a1_food_t02", "B", "sól", "соль", "сіль", "salt", False, "wrong_word"), + ("a1_food_t02", "C", "mąka", "мука", "борошно", "flour", False, "wrong_word"), + ("a1_food_t02", "D", "ryż", "рис", "рис", "rice", False, "wrong_word"), + ("a1_food_t03", "A", "ogórek", "огурец", "огірок", "cucumber", False, "wrong_word"), + ("a1_food_t03", "B", "ziemniak", "картофель", "картопля", "potato", False, "wrong_word"), + ("a1_food_t03", "C", "pomidor", "помидор", "помідор", "tomato", True, None), + ("a1_food_t03", "D", "marchewka", "морковь", "морква", "carrot", False, "wrong_word"), + ("a1_food_t04", "A", "woda", "вода", "вода", "water", False, "wrong_word"), + ("a1_food_t04", "B", "sok", "сок", "сік", "juice", True, None), + ("a1_food_t04", "C", "herbata", "чай", "чай", "tea", False, "wrong_word"), + ("a1_food_t04", "D", "kawa", "кофе", "кава", "coffee", False, "wrong_word"), + ("a1_food_t05", "A", "śniadanie", "завтрак", "сніданок", "breakfast", False, "wrong_word"), + ("a1_food_t05", "B", "obiad", "обед", "обід", "lunch", False, "wrong_word"), + ("a1_food_t05", "C", "sok", "сок", "сік", "juice", False, "wrong_word"), + ("a1_food_t05", "D", "kolacja", "ужин", "вечеря", "dinner", True, None), + ("a1_food_t06", "A", "herbatę", "чай (вин.)", "чай (знах.)", "tea (acc.)", True, None), + ("a1_food_t06", "B", "herbata", "чай (им.)", "чай (наз.)", "tea (nom.)", False, "wrong_case"), + ("a1_food_t06", "C", "herbacie", "чай (местн.)", "чай (місц.)", "tea (loc.)", False, "wrong_case"), + ("a1_food_t06", "D", "herbatą", "чай (тв.)", "чай (ор.)", "tea (instr.)", False, "wrong_case"), + ("a1_food_t07", "A", "chleb", "хлеб", "хліб", "bread", False, "wrong_context"), + ("a1_food_t07", "B", "ser", "сыр", "сир", "cheese", True, None), + ("a1_food_t07", "C", "mleko", "молоко", "молоко", "milk", False, "wrong_context"), + ("a1_food_t07", "D", "jajko", "яйцо", "яйце", "egg", False, "wrong_context"), + ("a1_food_t08", "A", "pomidor", "помидор", "помідор", "tomato", False, "wrong_context"), + ("a1_food_t08", "B", "ziemniak", "картофель", "картопля", "potato", False, "wrong_context"), + ("a1_food_t08", "C", "ogórek", "огурец", "огірок", "cucumber", False, "wrong_context"), + ("a1_food_t08", "D", "marchewka", "морковь", "морква", "carrot", True, None), + ("a1_food_t09", "A", "Piję wodę.", "Я пью воду.", "Я п'ю воду.", "I drink water.", False, "wrong_context"), + ("a1_food_t09", "B", "Piję kawę.", "Я пью кофе.", "Я п'ю каву.", "I drink coffee.", True, None), + ("a1_food_t09", "C", "Piję herbatę.", "Я пью чай.", "Я п'ю чай.", "I drink tea.", False, "wrong_context"), + ("a1_food_t09", "D", "Jem chleb.", "Я ем хлеб.", "Я їм хліб.", "I eat bread.", False, "wrong_word"), + ("a1_food_t10", "A", "śniadanie", "завтрак", "сніданок", "breakfast", False, "wrong_context"), + ("a1_food_t10", "B", "obiad", "обед", "обід", "lunch", False, "wrong_context"), + ("a1_food_t10", "C", "kolacja", "ужин", "вечеря", "dinner", True, None), + ("a1_food_t10", "D", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a1_food_t11", "A", "Obiad jem ziemniaki.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_food_t11", "B", "Na obiad jem ziemniaki.", "На обед я ем картофель.", "На обід я їм картоплю.", "For lunch I eat potatoes.", True, None), + ("a1_food_t11", "C", "Jestem ziemniaki na obiad.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_food_t11", "D", "Nie jem ziemniaki.", "Я не ем картофель.", "Я не їм картоплю.", "I don't eat potatoes.", False, "wrong_context"), + ("a1_food_t12", "A", "Nie lubię kawy.", "Я не люблю кофе.", "Я не люблю каву.", "I don't like coffee.", True, None), + ("a1_food_t12", "B", "Nie lubię kawę.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_food_t12", "C", "Lubię kawy.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_case"), + ("a1_food_t12", "D", "Nie jestem kawa.", "Я не кофе.", "Я не кава.", "I am not coffee.", False, "wrong_sentence_type"), + ("a1_food_t19", "A", "Nie lubię kawy, ale lubię herbatę.", "Я не люблю кофе, но люблю чай.", "Я не люблю каву, але люблю чай.", "I don't like coffee, but I like tea.", True, None), + ("a1_food_t19", "B", "Nie lubię kawę, ale lubię herbata.", "Неправильные падежи.", "Неправильні відмінки.", "Wrong cases.", False, "wrong_case"), + ("a1_food_t19", "C", "Lubię kawy, ale nie lubię herbatę.", "Смысл перевёрнут.", "Сенс перевернуто.", "Meaning is reversed.", False, "wrong_translation"), + ("a1_food_t19", "D", "Nie jestem kawa, ale jestem herbata.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_food_t20", "A", "Co jesz na śniadanie? Jem chleb i jajko.", "Что ты ешь на завтрак? Я ем хлеб и яйцо.", "Що ти їси на сніданок? Я їм хліб і яйце.", "What do you eat for breakfast? I eat bread and an egg.", True, None), + ("a1_food_t20", "B", "Co jem na śniadanie? Jesz chleb i jajko.", "Лица перепутаны.", "Особи переплутані.", "Persons are mixed up.", False, "wrong_sentence_type"), + ("a1_food_t20", "C", "Co pijesz na śniadanie? Piję chleb i jajko.", "Неправильный глагол.", "Неправильне дієслово.", "Wrong verb.", False, "wrong_word"), + ("a1_food_t20", "D", "Co jesz na obiad? Jem chleb i jajko.", "Неправильный приём пищи.", "Неправильний прийом їжі.", "Wrong meal.", False, "wrong_context"), + ] + + for opt in test_options_t4: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # ==================== ТЕМА 5: ДОМ И КВАРТИРА ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_home', 'A1', 5, + 'Dom i mieszkanie', + 'Дом и квартира', + 'Будинок і квартира', + 'House and Apartment') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t5 = [ + ("a1_home_l01", 1, "home_vocabulary", "Dom i mieszkanie", "Дом и квартира", "Будинок і квартира", "House and apartment", + "Dom (rodzaj męski) to budynek, w którym mieszka jedna rodzina. Mieszkanie (rodzaj nijaki) to część większego budynku (bloku). „Mam dom” i „mam mieszkanie” — oba zdania są poprawne, zależą od tego, gdzie mieszkasz.", + "Dom (мужской род) — это здание, в котором живёт одна семья. Mieszkanie (средний род) — это часть большего здания (блока). „Mam dom” и „mam mieszkanie” — оба предложения правильные, зависят от того, где ты живёшь.", + "Dom (чоловічий рід) — це будівля, в якій живе одна родина. Mieszkanie (середній рід) — це частина більшої будівлі (блоку). „Mam dom” і „mam mieszkanie” — обидва речення правильні, залежать від того, де ти живеш.", + "Dom (masculine) is a building where one family lives. Mieszkanie (neuter) is part of a larger building (apartment block). „Mam dom” and „mam mieszkanie” are both correct, depending on where you live."), + + ("a1_home_l02", 2, "home_vocabulary", "Pokoje w domu", "Комнаты в доме", "Кімнати в будинку", "Rooms in the house", + "Pokoje: pokój (ogólne słowo na pomieszczenie), kuchnia, łazienka, sypialnia, salon (pokój, w którym się odpoczywa i ogląda telewizję).", + "Комнаты: pokój (общее слово для помещения), kuchnia (кухня), łazienka (ванная), sypialnia (спальня), salon (гостиная, комната для отдыха и просмотра телевизора).", + "Кімнати: pokój (загальне слово для приміщення), kuchnia (кухня), łazienka (ванна), sypialnia (спальня), salon (вітальня, кімната для відпочинку і перегляду телевізора).", + "Rooms: pokój (general word for a room), kuchnia (kitchen), łazienka (bathroom), sypialnia (bedroom), salon (living room, where you relax and watch TV)."), + + ("a1_home_l03", 3, "home_furniture", "Meble", "Мебель", "Меблі", "Furniture", + "Podstawowe meble: stół, krzesło, łóżko, szafa. „Stół” i „krzesło” są w kuchni lub salonie, „łóżko” i „szafa” zwykle są w sypialni.", + "Основная мебель: stół (стол), krzesło (стул), łóżko (кровать), szafa (шкаф). „Stół” и „krzesło” обычно на кухне или в гостиной, „łóżko” и „szafa” — обычно в спальне.", + "Основні меблі: stół (стіл), krzesło (стілець), łóżko (ліжко), szafa (шафа). „Stół” і „krzesło” зазвичай на кухні чи у вітальні, „łóżko” і „szafa” — зазвичай у спальні.", + "Basic furniture: stół (table), krzesło (chair), łóżko (bed), szafa (wardrobe). „Stół” and „krzesło” are usually in the kitchen or living room; „łóżko” and „szafa” are usually in the bedroom."), + + ("a1_home_l04", 4, "home_furniture", "Więcej mebli", "Больше мебели", "Більше меблів", "More furniture", + "Więcej przedmiotów w domu: kanapa, lodówka, okno, drzwi. „Drzwi” to słowo, które w polskim występuje tylko w liczbie mnogiej (jak „nożyczki”).", + "Больше предметов в доме: kanapa (диван), lodówka (холодильник), okno (окно), drzwi (дверь). „Drzwi” — слово, которое в польском существует только во множественном числе (как „ножницы”).", + "Більше предметів у домі: kanapa (диван), lodówka (холодильник), okno (вікно), drzwi (двері). „Drzwi” — слово, яке в польській мові існує тільки у множині (як „ножиці”).", + "More household items: kanapa (sofa), lodówka (fridge), okno (window), drzwi (door). „Drzwi” is a word that in Polish exists only in the plural (like “scissors”)."), + + ("a1_home_l05", 5, "home_location", "Gdzie jest? — w kuchni", "Где это? — в кухне", "Де це? — на кухні", "Where is it? — in the kitchen", + "Po przyimku „w” rzeczowniki zmieniają końcówkę (miejscownik): kuchnia → w kuchni, łazienka → w łazience, salon → w salonie, sypialnia → w sypialni, dom → w domu, mieszkanie → w mieszkaniu.", + "После предлога „w” существительные меняют окончание (местный падеж): kuchnia → w kuchni, łazienka → w łazience, salon → w salonie, sypialnia → w sypialni, dom → w domu, mieszkanie → w mieszkaniu.", + "Після прийменника „w” іменники змінюють закінчення (місцевий відмінок): kuchnia → w kuchni, łazienka → w łazience, salon → w salonie, sypialnia → w sypialni, dom → w domu, mieszkanie → w mieszkaniu.", + "After the preposition „w” (in), nouns change their ending (locative case): kuchnia → w kuchni, łazienka → w łazience, salon → w salonie, sypialnia → w sypialni, dom → w domu, mieszkanie → w mieszkaniu."), + + ("a1_home_l06", 6, "home_location", "Na stole — miejscownik z „na”", "На столе — местный падеж с „na”", "На столі — місцевий відмінок з „na”", "On the table — locative with „na”", + "Po przyimku „na” rzeczowniki też zmieniają końcówkę: stół → na stole, łóżko → na łóżku, krzesło → na krześle, okno → na oknie.", + "После предлога „na” существительные тоже меняют окончание: stół → na stole, łóżko → na łóżku, krzesło → na krześle, okno → na oknie.", + "Після прийменника „na” іменники теж змінюють закінчення: stół → na stole, łóżko → na łóżku, krzesło → na krześle, okno → na oknie.", + "After the preposition „na” (on), nouns also change their ending: stół → na stole, łóżko → na łóżku, krzesło → na krześle, okno → na oknie."), + + ("a1_home_l07", 7, "home_ownership", "Mam dom, mam mieszkanie", "У меня есть дом, у меня есть квартира", "У мене є будинок, у мене є квартира", "I have a house, I have an apartment", + "Po „mam” rzeczowniki nijakie i męskie nieżywotne nie zmieniają końcówki: mam dom (bez zmiany), mam mieszkanie (bez zmiany), mam pokój (bez zmiany).", + "После „mam” существительные среднего рода и мужского неодушевлённого не меняют окончание: mam dom (без изменений), mam mieszkanie (без изменений), mam pokój (без изменений).", + "Після „mam” іменники середнього роду і чоловічого неістоти не змінюють закінчення: mam dom (без змін), mam mieszkanie (без змін), mam pokój (без змін).", + "After „mam”, neuter and masculine inanimate nouns don't change their ending: mam dom (unchanged), mam mieszkanie (unchanged), mam pokój (unchanged)."), + + ("a1_home_l08", 8, "home_ownership", "Mam małą kawalerkę", "У меня маленькая студия", "У мене маленька квартира-студія", "I have a small studio apartment", + "Rzeczowniki żeńskie po „mam” zmieniają końcówkę: kawalerka → mam kawalerkę, kuchnia → mam kuchnię. Przymiotnik też się zmienia: mała → małą, duża → dużą. Po zaprzeczeniu „nie mam” wraca dopełniacz: nie mam dużej łazienki.", + "Существительные женского рода после „mam” меняют окончание: kawalerka → mam kawalerkę, kuchnia → mam kuchnię. Прилагательное тоже меняется: mała → małą, duża → dużą. После отрицания „nie mam” возвращается родительный падеж: nie mam dużej łazienki.", + "Іменники жіночого роду після „mam” змінюють закінчення: kawalerka → mam kawalerkę, kuchnia → mam kuchnię. Прикметник теж змінюється: mała → małą, duża → dużą. Після заперечення „nie mam” повертається родовий відмінок: nie mam dużej łazienki.", + "Feminine nouns change their ending after „mam”: kawalerka → mam kawalerkę, kuchnia → mam kuchnię. The adjective changes too: mała → małą, duża → dużą. After the negation „nie mam”, the genitive returns: nie mam dużej łazienki."), + + ("a1_home_l09", 9, "home_description", "Ile masz pokoi?", "Сколько у тебя комнат?", "Скільки у тебе кімнат?", "How many rooms do you have?", + "Po liczebnikach 2–4 rzeczownik ma formę mianownika liczby mnogiej: dwa pokoje, trzy pokoje, cztery pokoje. Pytanie „Ile masz pokoi?” używa dopełniacza liczby mnogiej „pokoi” — warto ją zapamiętać jako całość.", + "После числительных 2–4 существительное имеет форму именительного падежа множественного числа: dwa pokoje, trzy pokoje, cztery pokoje. В вопросе „Ile masz pokoi?” используется родительный падеж множественного числа „pokoi” — её стоит запомнить целиком.", + "Після числівників 2–4 іменник має форму називного відмінка множини: dwa pokoje, trzy pokoje, cztery pokoje. У питанні „Ile masz pokoi?” використовується родовий відмінок множини „pokoi” — її варто запам'ятати цілком.", + "After the numbers 2–4, the noun has the nominative plural form: dwa pokoje, trzy pokoje, cztery pokoje. The question „Ile masz pokoi?” uses the genitive plural „pokoi” — worth memorizing as a whole."), + + ("a1_home_l10", 10, "home_description", "Opisuję swoje mieszkanie", "Описываю свою квартиру", "Описую свою квартиру", "Describing my apartment", + "Żeby opisać mieszkanie, łączymy nazwy pokoi, liczby i przymiotniki w jedno zdanie: Mam małe mieszkanie: kuchnię, łazienkę i sypialnię. Mam dwa pokoje.", + "Чтобы описать квартиру, соединяем названия комнат, числа и прилагательные в одно предложение: Mam małe mieszkanie: kuchnię, łazienkę i sypialnię. Mam dwa pokoje.", + "Щоб описати квартиру, з'єднуємо назви кімнат, числа і прикметники в одне речення: Mam małe mieszkanie: kuchnię, łazienkę i sypialnię. Mam dwa pokoje.", + "To describe an apartment, we combine room names, numbers and adjectives into one sentence: Mam małe mieszkanie: kuchnię, łazienkę i sypialnię. Mam dwa pokoje."), + ] + + for lesson in lessons_t5: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_home', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t5 = [ + ("a1_home_l01", 1, "Mam dom.", "У меня есть дом.", "У мене є будинок.", "I have a house."), + ("a1_home_l01", 2, "Mam mieszkanie.", "У меня есть квартира.", "У мене є квартира.", "I have an apartment."), + ("a1_home_l01", 3, "Mieszkam w domu, a mój kolega mieszka w mieszkaniu.", "Я живу в доме, а мой друг живёт в квартире.", "Я живу в будинку, а мій друг живе в квартирі.", "I live in a house, and my friend lives in an apartment."), + + ("a1_home_l02", 1, "W moim domu jest kuchnia i łazienka.", "В моём доме есть кухня и ванная.", "У моєму будинку є кухня і ванна.", "In my house there is a kitchen and a bathroom."), + ("a1_home_l02", 2, "Sypialnia jest mała.", "Спальня маленькая.", "Спальня маленька.", "The bedroom is small."), + ("a1_home_l02", 3, "Salon jest duży i jasny.", "Гостиная большая и светлая.", "Вітальня велика і світла.", "The living room is big and bright."), + + ("a1_home_l03", 1, "W kuchni są stół i krzesła.", "На кухне есть стол и стулья.", "На кухні є стіл і стільці.", "In the kitchen there are a table and chairs."), + ("a1_home_l03", 2, "Śpię na łóżku.", "Я сплю на кровати.", "Я сплю на ліжку.", "I sleep on the bed."), + ("a1_home_l03", 3, "Ubrania są w szafie.", "Одежда в шкафу.", "Одяг у шафі.", "The clothes are in the wardrobe."), + + ("a1_home_l04", 1, "W salonie jest kanapa.", "В гостиной есть диван.", "У вітальні є диван.", "There is a sofa in the living room."), + ("a1_home_l04", 2, "Mleko jest w lodówce.", "Молоко в холодильнике.", "Молоко в холодильнику.", "The milk is in the fridge."), + ("a1_home_l04", 3, "Okno jest otwarte, a drzwi są zamknięte.", "Окно открыто, а дверь закрыта.", "Вікно відкрите, а двері зачинені.", "The window is open, and the door is closed."), + + ("a1_home_l05", 1, "Gotuję w kuchni.", "Я готовлю на кухне.", "Я готую на кухні.", "I cook in the kitchen."), + ("a1_home_l05", 2, "Myję się w łazience.", "Я моюсь в ванной.", "Я миюся у ванній.", "I wash myself in the bathroom."), + ("a1_home_l05", 3, "Oglądam telewizję w salonie.", "Я смотрю телевизор в гостиной.", "Я дивлюся телевізор у вітальні.", "I watch TV in the living room."), + + ("a1_home_l06", 1, "Talerz jest na stole.", "Тарелка на столе.", "Тарілка на столі.", "The plate is on the table."), + ("a1_home_l06", 2, "Kot śpi na łóżku.", "Кот спит на кровати.", "Кіт спить на ліжку.", "The cat sleeps on the bed."), + ("a1_home_l06", 3, "Kwiaty są na oknie.", "Цветы на окне.", "Квіти на вікні.", "The flowers are on the window."), + + ("a1_home_l07", 1, "Mam dom.", "У меня есть дом.", "У мене є будинок.", "I have a house."), + ("a1_home_l07", 2, "Mam mieszkanie.", "У меня есть квартира.", "У мене є квартира.", "I have an apartment."), + ("a1_home_l07", 3, "Mam duży pokój.", "У меня большая комната.", "У мене велика кімната.", "I have a big room."), + + ("a1_home_l08", 1, "Mam małą kawalerkę.", "У меня маленькая студия.", "У мене маленька квартира-студія.", "I have a small studio apartment."), + ("a1_home_l08", 2, "Mam dużą kuchnię.", "У меня большая кухня.", "У мене велика кухня.", "I have a big kitchen."), + ("a1_home_l08", 3, "Nie mam dużej łazienki.", "У меня нет большой ванной.", "У мене немає великої ванної.", "I don't have a big bathroom."), + + ("a1_home_l09", 1, "Mam dwa pokoje.", "У меня две комнаты.", "У мене дві кімнати.", "I have two rooms."), + ("a1_home_l09", 2, "Mam trzy pokoje.", "У меня три комнаты.", "У мене три кімнати.", "I have three rooms."), + ("a1_home_l09", 3, "Ile masz pokoi?", "Сколько у тебя комнат?", "Скільки у тебе кімнат?", "How many rooms do you have?"), + + ("a1_home_l10", 1, "Mam małe mieszkanie: kuchnię, łazienkę i sypialnię.", "У меня маленькая квартира: кухня, ванная и спальня.", "У мене маленька квартира: кухня, ванна і спальня.", "I have a small apartment: a kitchen, a bathroom and a bedroom."), + ("a1_home_l10", 2, "W salonie jest duża kanapa.", "В гостиной большой диван.", "У вітальні великий диван.", "There is a big sofa in the living room."), + ("a1_home_l10", 3, "Mam dwa pokoje i małą kuchnię.", "У меня две комнаты и маленькая кухня.", "У мене дві кімнати і маленька кухня.", "I have two rooms and a small kitchen."), + ] + + for ex in examples_t5: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t5 = [ + # L01 — home_vocabulary (difficulty 1) + ("a1_home_l01_q1", "a1_home_l01", "lesson_practice", "recognition", "home_vocabulary", 1, + "Jak po polsku „квартира”?", "Как по-польски «квартира»?", "Як польською «квартира»?", "How do you say “apartment” in Polish?", + "B", None, None), + ("a1_home_l01_q2", "a1_home_l01", "lesson_practice", "production", "home_vocabulary", 1, + "Wpisz brakujące słowo: Mam ___. (дом)", "Вставьте пропущенное слово: Mam ___. (дом)", "Вставте пропущене слово: Mam ___. (будинок)", "Fill in the missing word: Mam ___. (house)", + "dom", "first_letter", "d"), + ("a1_home_l01_q3", "a1_home_l01", "lesson_practice", "application", "home_vocabulary", 1, + "Mieszkasz w bloku, na trzecim piętrze. Co masz?", "Ты живёшь в блоке, на третьем этаже. Что у тебя?", "Ти живеш у блоці, на третьому поверсі. Що у тебе?", "You live in an apartment block, on the third floor. What do you have?", + "A", None, None), + + # L02 — home_vocabulary (difficulty 1) + ("a1_home_l02_q1", "a1_home_l02", "lesson_practice", "recognition", "home_vocabulary", 1, + "Jak po polsku „ванная”?", "Как по-польски «ванная»?", "Як польською «ванна»?", "How do you say “bathroom” in Polish?", + "C", None, None), + ("a1_home_l02_q2", "a1_home_l02", "lesson_practice", "production", "home_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (спальня)", "Вставьте пропущенное слово: To jest ___. (спальня)", "Вставте пропущене слово: To jest ___. (спальня)", "Fill in the missing word: To jest ___. (bedroom)", + "sypialnia", "first_letter", "s"), + ("a1_home_l02_q3", "a1_home_l02", "lesson_practice", "application", "home_vocabulary", 1, + "Chcesz ugotować obiad. Do którego pokoju pójdziesz?", "Ты хочешь приготовить обед. В какую комнату ты пойдёшь?", "Ти хочеш приготувати обід. До якої кімнати ти підеш?", "You want to cook lunch. Which room do you go to?", + "A", None, None), + + # L03 — home_furniture (difficulty 1) + ("a1_home_l03_q1", "a1_home_l03", "lesson_practice", "recognition", "home_furniture", 1, + "Jak po polsku „стул”?", "Как по-польски «стул»?", "Як польською «стілець»?", "How do you say “chair” in Polish?", + "B", None, None), + ("a1_home_l03_q2", "a1_home_l03", "lesson_practice", "production", "home_furniture", 1, + "Wpisz brakujące słowo: To jest ___. (кровать)", "Вставьте пропущенное слово: To jest ___. (кровать)", "Вставте пропущене слово: To jest ___. (ліжко)", "Fill in the missing word: To jest ___. (bed)", + "łóżko", "first_letter", "ł"), + ("a1_home_l03_q3", "a1_home_l03", "lesson_practice", "application", "home_furniture", 1, + "Chcesz powiesić ubrania. Gdzie je włożysz?", "Ты хочешь повесить одежду. Куда ты её положишь?", "Ти хочеш повісити одяг. Куди ти його покладеш?", "You want to hang your clothes. Where do you put them?", + "A", None, None), + + # L04 — home_furniture (difficulty 1) + ("a1_home_l04_q1", "a1_home_l04", "lesson_practice", "recognition", "home_furniture", 1, + "Jak po polsku „холодильник”?", "Как по-польски «холодильник»?", "Як польською «холодильник»?", "How do you say “fridge” in Polish?", + "B", None, None), + ("a1_home_l04_q2", "a1_home_l04", "lesson_practice", "production", "home_furniture", 1, + "Wpisz brakujące słowo: To jest ___. (диван)", "Вставьте пропущенное слово: To jest ___. (диван)", "Вставте пропущене слово: To jest ___. (диван)", "Fill in the missing word: To jest ___. (sofa)", + "kanapa", "first_letter", "k"), + ("a1_home_l04_q3", "a1_home_l04", "lesson_practice", "application", "home_furniture", 1, + "Chcesz obejrzeć film w salonie. Na czym usiądziesz?", "Ты хочешь посмотреть фильм в гостиной. На чём ты сядешь?", "Ти хочеш подивитися фільм у вітальні. На чому ти сядеш?", "You want to watch a movie in the living room. What do you sit on?", + "A", None, None), + + # L05 — home_location (difficulty 2) + ("a1_home_l05_q1", "a1_home_l05", "lesson_practice", "recognition", "home_location", 2, + "Wybierz poprawną formę: Gotuję ___. (w + kuchnia)", "Выберите правильную форму: Gotuję ___. (w + kuchnia)", "Виберіть правильну форму: Gotuję ___. (w + kuchnia)", "Choose the correct form: Gotuję ___. (w + kuchnia)", + "A", None, None), + ("a1_home_l05_q2", "a1_home_l05", "lesson_practice", "production", "home_location", 2, + "Wpisz brakujące słowo: Myję się w ___. (ванная)", "Вставьте пропущенное слово: Myję się w ___. (ванная)", "Вставте пропущене слово: Myję się w ___. (ванна)", "Fill in the missing word: Myję się w ___. (bathroom)", + "łazience", "first_letter", "ł"), + ("a1_home_l05_q3", "a1_home_l05", "lesson_practice", "application", "home_location", 2, + "Gdzie oglądasz telewizję?", "Где ты смотришь телевизор?", "Де ти дивишся телевізор?", "Where do you watch TV?", + "A", None, None), + + # L06 — home_location (difficulty 2) + ("a1_home_l06_q1", "a1_home_l06", "lesson_practice", "recognition", "home_location", 2, + "Wybierz poprawną formę: Talerz jest ___. (na + stół)", "Выберите правильную форму: Talerz jest ___. (na + stół)", "Виберіть правильну форму: Talerz jest ___. (na + stół)", "Choose the correct form: Talerz jest ___. (na + stół)", + "B", None, None), + ("a1_home_l06_q2", "a1_home_l06", "lesson_practice", "production", "home_location", 2, + "Wpisz brakujące słowo: Kot śpi na ___. (кровать)", "Вставьте пропущенное слово: Kot śpi na ___. (кровать)", "Вставте пропущене слово: Kot śpi na ___. (ліжко)", "Fill in the missing word: Kot śpi na ___. (bed)", + "łóżku", "first_letter", "ł"), + ("a1_home_l06_q3", "a1_home_l06", "lesson_practice", "application", "home_location", 2, + "Widzisz kwiaty przy oknie. Gdzie one są?", "Ты видишь цветы у окна. Где они?", "Ти бачиш квіти біля вікна. Де вони?", "You see flowers by the window. Where are they?", + "A", None, None), + + # L07 — home_ownership (difficulty 2) + ("a1_home_l07_q1", "a1_home_l07", "lesson_practice", "recognition", "home_ownership", 2, + "Wybierz poprawną formę: Mam ___. (dom)", "Выберите правильную форму: Mam ___. (dom)", "Виберіть правильну форму: Mam ___. (dom)", "Choose the correct form: Mam ___. (dom)", + "A", None, None), + ("a1_home_l07_q2", "a1_home_l07", "lesson_practice", "production", "home_ownership", 2, + "Wpisz brakujące słowo: Mam ___. (квартира)", "Вставьте пропущенное слово: Mam ___. (квартира)", "Вставте пропущене слово: Mam ___. (квартира)", "Fill in the missing word: Mam ___. (apartment)", + "mieszkanie", "first_letter", "m"), + ("a1_home_l07_q3", "a1_home_l07", "lesson_practice", "application", "home_ownership", 2, + "Chcesz powiedzieć, że masz duży dom. Co powiesz?", "Ты хочешь сказать, что у тебя большой дом. Что ты скажешь?", "Ти хочеш сказати, що у тебе великий будинок. Що ти скажеш?", "You want to say you have a big house. What do you say?", + "A", None, None), + + # L08 — home_ownership (difficulty 2) + ("a1_home_l08_q1", "a1_home_l08", "lesson_practice", "recognition", "home_ownership", 2, + "Wybierz poprawną formę: Mam małą ___. (kawalerka)", "Выберите правильную форму: Mam małą ___. (kawalerka)", "Виберіть правильну форму: Mam małą ___. (kawalerka)", "Choose the correct form: Mam małą ___. (kawalerka)", + "A", None, None), + ("a1_home_l08_q2", "a1_home_l08", "lesson_practice", "production", "home_ownership", 2, + "Wpisz brakujące słowo: Mam dużą ___. (кухня)", "Вставьте пропущенное слово: Mam dużą ___. (кухня)", "Вставте пропущене слово: Mam dużą ___. (кухня)", "Fill in the missing word: Mam dużą ___. (kitchen)", + "kuchnię", "first_letter", "k"), + ("a1_home_l08_q3", "a1_home_l08", "lesson_practice", "application", "home_ownership", 2, + "Chcesz powiedzieć, że nie masz dużej łazienki. Co powiesz?", "Ты хочешь сказать, что у тебя нет большой ванной. Что ты скажешь?", "Ти хочеш сказати, що у тебе немає великої ванної. Що ти скажеш?", "You want to say you don't have a big bathroom. What do you say?", + "A", None, None), + + # L09 — home_description (difficulty 3) + ("a1_home_l09_q1", "a1_home_l09", "lesson_practice", "recognition", "home_description", 3, + "Co znaczy „Ile masz pokoi?”", "Что означает «Ile masz pokoi?»", "Що означає «Ile masz pokoi?»", "What does “Ile masz pokoi?” mean?", + "A", None, None), + ("a1_home_l09_q2", "a1_home_l09", "lesson_practice", "production", "home_description", 3, + "Wpisz brakujące słowo: Mam dwa ___. (комнаты)", "Вставьте пропущенное слово: Mam dwa ___. (комнаты)", "Вставте пропущене слово: Mam dwa ___. (кімнати)", "Fill in the missing word: Mam dwa ___. (rooms)", + "pokoje", "first_letter", "p"), + ("a1_home_l09_q3", "a1_home_l09", "lesson_practice", "application", "home_description", 3, + "Kolega pyta „Ile masz pokoi?” Masz trzy pokoje. Co powiesz?", "Друг спрашивает «Ile masz pokoi?» У тебя три комнаты. Что ты скажешь?", "Друг питає «Ile masz pokoi?» У тебе три кімнати. Що ти скажеш?", "A friend asks “Ile masz pokoi?” You have three rooms. What do you say?", + "A", None, None), + + # L10 — home_description (difficulty 3) + ("a1_home_l10_q1", "a1_home_l10", "lesson_practice", "recognition", "home_description", 3, + "Które zdanie poprawnie opisuje mieszkanie?", "Какое предложение правильно описывает квартиру?", "Яке речення правильно описує квартиру?", "Which sentence correctly describes an apartment?", + "B", None, None), + ("a1_home_l10_q2", "a1_home_l10", "lesson_practice", "production", "home_description", 3, + "Przetłumacz: «У меня маленькая квартира: кухня, ванная и спальня».", "Переведите: «У меня маленькая квартира: кухня, ванная и спальня».", "Перекладіть: «У мене маленька квартира: кухня, ванна і спальня».", "Translate: “I have a small apartment: a kitchen, a bathroom and a bedroom.”", + "Mam małe mieszkanie: kuchnię, łazienkę i sypialnię", "first_letter", "M"), + ("a1_home_l10_q3", "a1_home_l10", "lesson_practice", "application", "home_description", 3, + "Chcesz opisać koledze swoje mieszkanie: masz dwa pokoje i małą kuchnię. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою квартиру: у тебя две комнаты и маленькая кухня. Как ты начнёшь предложение?", "Ти хочеш описати другу свою квартиру: у тебе дві кімнати і маленька кухня. Як ти почнеш речення?", "You want to describe your apartment to a friend: you have two rooms and a small kitchen. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t5: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_home', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t5 = [ + # L01 + ("a1_home_l01_q1", "A", "dom", "дом", "будинок", "house", False, "wrong_word"), + ("a1_home_l01_q1", "B", "mieszkanie", "квартира", "квартира", "apartment", True, None), + ("a1_home_l01_q1", "C", "pokój", "комната", "кімната", "room", False, "wrong_word"), + ("a1_home_l01_q1", "D", "kuchnia", "кухня", "кухня", "kitchen", False, "wrong_word"), + + ("a1_home_l01_q3", "A", "mieszkanie", "квартира", "квартира", "apartment", True, None), + ("a1_home_l01_q3", "B", "dom", "дом", "будинок", "house", False, "wrong_context"), + ("a1_home_l01_q3", "C", "pokój", "комната", "кімната", "room", False, "wrong_context"), + ("a1_home_l01_q3", "D", "kuchnia", "кухня", "кухня", "kitchen", False, "wrong_word"), + + # L02 + ("a1_home_l02_q1", "A", "sypialnia", "спальня", "спальня", "bedroom", False, "wrong_word"), + ("a1_home_l02_q1", "B", "salon", "гостиная", "вітальня", "living room", False, "wrong_word"), + ("a1_home_l02_q1", "C", "łazienka", "ванная", "ванна", "bathroom", True, None), + ("a1_home_l02_q1", "D", "kuchnia", "кухня", "кухня", "kitchen", False, "wrong_word"), + + ("a1_home_l02_q3", "A", "kuchnia", "кухня", "кухня", "kitchen", True, None), + ("a1_home_l02_q3", "B", "łazienka", "ванная", "ванна", "bathroom", False, "wrong_context"), + ("a1_home_l02_q3", "C", "sypialnia", "спальня", "спальня", "bedroom", False, "wrong_context"), + ("a1_home_l02_q3", "D", "salon", "гостиная", "вітальня", "living room", False, "wrong_context"), + + # L03 + ("a1_home_l03_q1", "A", "stół", "стол", "стіл", "table", False, "wrong_word"), + ("a1_home_l03_q1", "B", "krzesło", "стул", "стілець", "chair", True, None), + ("a1_home_l03_q1", "C", "łóżko", "кровать", "ліжко", "bed", False, "wrong_word"), + ("a1_home_l03_q1", "D", "szafa", "шкаф", "шафа", "wardrobe", False, "wrong_word"), + + ("a1_home_l03_q3", "A", "szafa", "шкаф", "шафа", "wardrobe", True, None), + ("a1_home_l03_q3", "B", "stół", "стол", "стіл", "table", False, "wrong_context"), + ("a1_home_l03_q3", "C", "łóżko", "кровать", "ліжко", "bed", False, "wrong_context"), + ("a1_home_l03_q3", "D", "krzesło", "стул", "стілець", "chair", False, "wrong_context"), + + # L04 + ("a1_home_l04_q1", "A", "okno", "окно", "вікно", "window", False, "wrong_word"), + ("a1_home_l04_q1", "B", "lodówka", "холодильник", "холодильник", "fridge", True, None), + ("a1_home_l04_q1", "C", "kanapa", "диван", "диван", "sofa", False, "wrong_word"), + ("a1_home_l04_q1", "D", "drzwi", "дверь", "двері", "door", False, "wrong_word"), + + ("a1_home_l04_q3", "A", "kanapa", "диван", "диван", "sofa", True, None), + ("a1_home_l04_q3", "B", "łóżko", "кровать", "ліжко", "bed", False, "wrong_context"), + ("a1_home_l04_q3", "C", "krzesło", "стул", "стілець", "chair", False, "wrong_context"), + ("a1_home_l04_q3", "D", "stół", "стол", "стіл", "table", False, "wrong_context"), + + # L05 + ("a1_home_l05_q1", "A", "w kuchni", "на кухне", "на кухні", "in the kitchen", True, None), + ("a1_home_l05_q1", "B", "w kuchnia", "на кухне (неправильно)", "на кухні (неправильно)", "in the kitchen (wrong case)", False, "wrong_case"), + ("a1_home_l05_q1", "C", "w kuchnię", "на кухне (неправильно)", "на кухні (неправильно)", "in the kitchen (wrong case)", False, "wrong_case"), + ("a1_home_l05_q1", "D", "w kuchnią", "на кухне (неправильно)", "на кухні (неправильно)", "in the kitchen (wrong case)", False, "wrong_case"), + + ("a1_home_l05_q3", "A", "Oglądam telewizję w salonie.", "Я смотрю телевизор в гостиной.", "Я дивлюся телевізор у вітальні.", "I watch TV in the living room.", True, None), + ("a1_home_l05_q3", "B", "Oglądam telewizję w kuchni.", "Я смотрю телевизор на кухне.", "Я дивлюся телевізор на кухні.", "I watch TV in the kitchen.", False, "wrong_context"), + ("a1_home_l05_q3", "C", "Oglądam telewizję w łazience.", "Я смотрю телевизор в ванной.", "Я дивлюся телевізор у ванній.", "I watch TV in the bathroom.", False, "wrong_context"), + ("a1_home_l05_q3", "D", "Oglądam telewizję w sypialni.", "Я смотрю телевизор в спальне.", "Я дивлюся телевізор у спальні.", "I watch TV in the bedroom.", False, "wrong_context"), + + # L06 + ("a1_home_l06_q1", "A", "na stół", "на стол (неправильно)", "на стіл (неправильно)", "on the table (wrong case)", False, "wrong_case"), + ("a1_home_l06_q1", "B", "na stole", "на столе", "на столі", "on the table", True, None), + ("a1_home_l06_q1", "C", "na stołem", "на столе (неправильно)", "на столі (неправильно)", "on the table (wrong case)", False, "wrong_case"), + ("a1_home_l06_q1", "D", "na stołu", "на столе (неправильно)", "на столі (неправильно)", "on the table (wrong case)", False, "wrong_case"), + + ("a1_home_l06_q3", "A", "Kwiaty są na oknie.", "Цветы на окне.", "Квіти на вікні.", "The flowers are on the window.", True, None), + ("a1_home_l06_q3", "B", "Kwiaty są na stole.", "Цветы на столе.", "Квіти на столі.", "The flowers are on the table.", False, "wrong_context"), + ("a1_home_l06_q3", "C", "Kwiaty są na łóżku.", "Цветы на кровати.", "Квіти на ліжку.", "The flowers are on the bed.", False, "wrong_context"), + ("a1_home_l06_q3", "D", "Kwiaty są na krześle.", "Цветы на стуле.", "Квіти на стільці.", "The flowers are on the chair.", False, "wrong_context"), + + # L07 + ("a1_home_l07_q1", "A", "dom", "дом", "будинок", "house", True, None), + ("a1_home_l07_q1", "B", "domu", "дома (неправильно)", "будинку (неправильно)", "house (wrong case)", False, "wrong_case"), + ("a1_home_l07_q1", "C", "domem", "домом (неправильно)", "будинком (неправильно)", "house (wrong case)", False, "wrong_case"), + ("a1_home_l07_q1", "D", "domowi", "дому (неправильно)", "будинкові (неправильно)", "house (wrong case)", False, "wrong_case"), + + ("a1_home_l07_q3", "A", "Mam duży dom.", "У меня большой дом.", "У мене великий будинок.", "I have a big house.", True, None), + ("a1_home_l07_q3", "B", "Mam duża dom.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_home_l07_q3", "C", "Jestem duży dom.", "Я большой дом.", "Я великий будинок.", "I am a big house.", False, "wrong_sentence_type"), + ("a1_home_l07_q3", "D", "To duży dom.", "Это большой дом.", "Це великий будинок.", "This is a big house.", False, "wrong_sentence_type"), + + # L08 + ("a1_home_l08_q1", "A", "kawalerkę", "студию (вин.)", "квартиру-студію (знах.)", "studio (acc.)", True, None), + ("a1_home_l08_q1", "B", "kawalerka", "студия (им.)", "квартира-студія (наз.)", "studio (nom.)", False, "wrong_case"), + ("a1_home_l08_q1", "C", "kawalerki", "студии (род.)", "квартири-студії (род.)", "studio (gen.)", False, "wrong_case"), + ("a1_home_l08_q1", "D", "kawalerką", "студией (тв.)", "квартирою-студією (ор.)", "studio (instr.)", False, "wrong_case"), + + ("a1_home_l08_q3", "A", "Nie mam dużej łazienki.", "У меня нет большой ванной.", "У мене немає великої ванної.", "I don't have a big bathroom.", True, None), + ("a1_home_l08_q3", "B", "Nie mam duża łazienka.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_home_l08_q3", "C", "Mam dużą łazienkę.", "У меня есть большая ванная. (неверный смысл)", "У мене є велика ванна. (неправильний сенс)", "I have a big bathroom. (wrong meaning)", False, "wrong_context"), + ("a1_home_l08_q3", "D", "Nie jestem duża łazienka.", "Я не большая ванная.", "Я не велика ванна.", "I am not a big bathroom.", False, "wrong_sentence_type"), + + # L09 + ("a1_home_l09_q1", "A", "Сколько у тебя комнат?", "Сколько у тебя комнат?", "Скільки у тебе кімнат?", "How many rooms do you have?", True, None), + ("a1_home_l09_q1", "B", "Где твоя комната?", "Где твоя комната?", "Де твоя кімната?", "Where is your room?", False, "wrong_translation"), + ("a1_home_l09_q1", "C", "Тебе нравится твоя комната?", "Тебе нравится твоя комната?", "Тобі подобається твоя кімната?", "Do you like your room?", False, "wrong_translation"), + ("a1_home_l09_q1", "D", "Какая у тебя комната?", "Какая у тебя комната?", "Яка у тебе кімната?", "What is your room like?", False, "wrong_translation"), + + ("a1_home_l09_q3", "A", "Mam trzy pokoje.", "У меня три комнаты.", "У мене три кімнати.", "I have three rooms.", True, None), + ("a1_home_l09_q3", "B", "Mam trzy pokój.", "Неправильное число.", "Неправильне число.", "Wrong number form.", False, "wrong_number"), + ("a1_home_l09_q3", "C", "Jestem trzy pokoje.", "Я три комнаты.", "Я три кімнати.", "I am three rooms.", False, "wrong_sentence_type"), + ("a1_home_l09_q3", "D", "To trzy pokoje.", "Это три комнаты.", "Це три кімнати.", "This is three rooms.", False, "wrong_sentence_type"), + + # L10 + ("a1_home_l10_q1", "A", "Mam mała mieszkanie.", "Неправильный род.", "Неправильний рід.", "Wrong gender agreement.", False, "wrong_gender"), + ("a1_home_l10_q1", "B", "Mam małe mieszkanie.", "У меня маленькая квартира.", "У мене маленька квартира.", "I have a small apartment.", True, None), + ("a1_home_l10_q1", "C", "Jestem małe mieszkanie.", "Я маленькая квартира.", "Я маленька квартира.", "I am a small apartment.", False, "wrong_sentence_type"), + ("a1_home_l10_q1", "D", "To małe mieszkanie.", "Это маленькая квартира.", "Це маленька квартира.", "This is a small apartment.", False, "wrong_sentence_type"), + + ("a1_home_l10_q3", "A", "Mam dwa pokoje i małą kuchnię.", "У меня две комнаты и маленькая кухня.", "У мене дві кімнати і маленька кухня.", "I have two rooms and a small kitchen.", True, None), + ("a1_home_l10_q3", "B", "Ja pokoje i kuchnia.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_home_l10_q3", "C", "Moje mieszkanie jestem dwa pokoje.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_home_l10_q3", "D", "Jestem dwa pokoje i mała kuchnia.", "Я две комнаты и маленькая кухня.", "Я дві кімнати і маленька кухня.", "I am two rooms and a small kitchen.", False, "wrong_sentence_type"), + ] + + for opt in options_t5: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t5 = [ + ("a1_home_t01", None, "topic_test", "recognition", "home_vocabulary", 1, + "Jak po polsku „квартира”?", "Как по-польски «квартира»?", "Як польською «квартира»?", "How do you say “apartment” in Polish?", + "B", None, None, 1), + ("a1_home_t02", None, "topic_test", "recognition", "home_vocabulary", 1, + "Jak po polsku „ванная”?", "Как по-польски «ванная»?", "Як польською «ванна»?", "How do you say “bathroom” in Polish?", + "C", None, None, 2), + ("a1_home_t03", None, "topic_test", "recognition", "home_furniture", 1, + "Jak po polsku „холодильник”?", "Как по-польски «холодильник»?", "Як польською «холодильник»?", "How do you say “fridge” in Polish?", + "B", None, None, 3), + ("a1_home_t04", None, "topic_test", "recognition", "home_furniture", 1, + "Jak po polsku „кровать”?", "Как по-польски «кровать»?", "Як польською «ліжко»?", "How do you say “bed” in Polish?", + "D", None, None, 4), + ("a1_home_t05", None, "topic_test", "recognition", "home_ownership", 1, + "Wybierz poprawną formę: Mam ___. (dom)", "Выберите правильную форму: Mam ___. (dom)", "Виберіть правильну форму: Mam ___. (dom)", "Choose the correct form: Mam ___. (dom)", + "A", None, None, 5), + ("a1_home_t06", None, "topic_test", "recognition", "home_location", 2, + "Wybierz poprawną formę: Gotuję ___. (w + kuchnia)", "Выберите правильную форму: Gotuję ___. (w + kuchnia)", "Виберіть правильну форму: Gotuję ___. (w + kuchnia)", "Choose the correct form: Gotuję ___. (w + kuchnia)", + "A", None, None, 6), + + ("a1_home_t07", None, "topic_test", "application", "home_vocabulary", 2, + "Mieszkasz w bloku, na trzecim piętrze. Co masz?", "Ты живёшь в блоке, на третьем этаже. Что у тебя?", "Ти живеш у блоці, на третьому поверсі. Що у тебе?", "You live in an apartment block, on the third floor. What do you have?", + "A", None, None, 7), + ("a1_home_t08", None, "topic_test", "application", "home_furniture", 2, + "Chcesz obejrzeć film w salonie. Na czym usiądziesz?", "Ты хочешь посмотреть фильм в гостиной. На чём ты сядешь?", "Ти хочеш подивитися фільм у вітальні. На чому ти сядеш?", "You want to watch a movie in the living room. What do you sit on?", + "A", None, None, 8), + ("a1_home_t09", None, "topic_test", "application", "home_location", 2, + "Widzisz kwiaty przy oknie. Gdzie one są?", "Ты видишь цветы у окна. Где они?", "Ти бачиш квіти біля вікна. Де вони?", "You see flowers by the window. Where are they?", + "A", None, None, 9), + ("a1_home_t10", None, "topic_test", "application", "home_location", 2, + "Gdzie oglądasz telewizję?", "Где ты смотришь телевизор?", "Де ти дивишся телевізор?", "Where do you watch TV?", + "A", None, None, 10), + ("a1_home_t11", None, "topic_test", "application", "home_ownership", 2, + "Chcesz powiedzieć, że nie masz dużej łazienki. Co powiesz?", "Ты хочешь сказать, что у тебя нет большой ванной. Что ты скажешь?", "Ти хочеш сказати, що у тебе немає великої ванної. Що ти скажеш?", "You want to say you don't have a big bathroom. What do you say?", + "A", None, None, 11), + ("a1_home_t12", None, "topic_test", "application", "home_description", 3, + "Chcesz opisać koledze swoje mieszkanie: masz dwa pokoje i małą kuchnię. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою квартиру: у тебя две комнаты и маленькая кухня. Как ты начнёшь предложение?", "Ти хочеш описати другу свою квартиру: у тебе дві кімнати і маленька кухня. Як ти почнеш речення?", "You want to describe your apartment to a friend: you have two rooms and a small kitchen. How do you start the sentence?", + "A", None, None, 12), + + ("a1_home_t13", None, "topic_test", "production", "home_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (спальня)", "Вставьте пропущенное слово: To jest ___. (спальня)", "Вставте пропущене слово: To jest ___. (спальня)", "Fill in the missing word: To jest ___. (bedroom)", + "sypialnia", "first_letter", "s", 13), + ("a1_home_t14", None, "topic_test", "production", "home_furniture", 1, + "Wpisz brakujące słowo: To jest ___. (диван)", "Вставьте пропущенное слово: To jest ___. (диван)", "Вставте пропущене слово: To jest ___. (диван)", "Fill in the missing word: To jest ___. (sofa)", + "kanapa", "first_letter", "k", 14), + ("a1_home_t15", None, "topic_test", "production", "home_location", 2, + "Wpisz brakujące słowo: Myję się w ___. (ванная)", "Вставьте пропущенное слово: Myję się w ___. (ванная)", "Вставте пропущене слово: Myję się w ___. (ванна)", "Fill in the missing word: Myję się w ___. (bathroom)", + "łazience", "first_letter", "ł", 15), + ("a1_home_t16", None, "topic_test", "production", "home_location", 2, + "Wpisz brakujące słowo: Kot śpi na ___. (кровать)", "Вставьте пропущенное слово: Kot śpi na ___. (кровать)", "Вставте пропущене слово: Kot śpi na ___. (ліжко)", "Fill in the missing word: Kot śpi na ___. (bed)", + "łóżku", "first_letter", "ł", 16), + ("a1_home_t17", None, "topic_test", "production", "home_ownership", 2, + "Wpisz brakujące słowo: Mam dużą ___. (кухня)", "Вставьте пропущенное слово: Mam dużą ___. (кухня)", "Вставте пропущене слово: Mam dużą ___. (кухня)", "Fill in the missing word: Mam dużą ___. (kitchen)", + "kuchnię", "first_letter", "k", 17), + ("a1_home_t18", None, "topic_test", "production", "home_description", 3, + "Przetłumacz: «У меня маленькая квартира: кухня, ванная и спальня».", "Переведите: «У меня маленькая квартира: кухня, ванная и спальня».", "Перекладіть: «У мене маленька квартира: кухня, ванна і спальня».", "Translate: “I have a small apartment: a kitchen, a bathroom and a bedroom.”", + "Mam małe mieszkanie: kuchnię, łazienkę i sypialnię", "first_letter", "M", 18), + + ("a1_home_t19", None, "topic_test", "mixed", "home_location", 3, + "Wybierz poprawne tłumaczenie: «Тарелка на столе, а кот спит на кровати».", "Выберите правильный перевод: «Тарелка на столе, а кот спит на кровати».", "Виберіть правильний переклад: «Тарілка на столі, а кіт спить на ліжку».", "Choose the correct translation: “The plate is on the table, and the cat sleeps on the bed.”", + "A", None, None, 19), + ("a1_home_t20", None, "topic_test", "mixed", "home_description", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Сколько у тебя комнат? — У меня две комнаты и маленькая кухня.»", "Выберите правильный перевод диалога: «— Сколько у тебя комнат? — У меня две комнаты и маленькая кухня.»", "Виберіть правильний переклад діалогу: «— Скільки у тебе кімнат? — У мене дві кімнати і маленька кухня.»", "Choose the correct translation of the dialogue: “— How many rooms do you have? — I have two rooms and a small kitchen.”", + "A", None, None, 20), + ] + + for q in test_questions_t5: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_home', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t5 = [ + ("a1_home_t01", "A", "dom", "дом", "будинок", "house", False, "wrong_word"), + ("a1_home_t01", "B", "mieszkanie", "квартира", "квартира", "apartment", True, None), + ("a1_home_t01", "C", "pokój", "комната", "кімната", "room", False, "wrong_word"), + ("a1_home_t01", "D", "kuchnia", "кухня", "кухня", "kitchen", False, "wrong_word"), + + ("a1_home_t02", "A", "sypialnia", "спальня", "спальня", "bedroom", False, "wrong_word"), + ("a1_home_t02", "B", "salon", "гостиная", "вітальня", "living room", False, "wrong_word"), + ("a1_home_t02", "C", "łazienka", "ванная", "ванна", "bathroom", True, None), + ("a1_home_t02", "D", "kuchnia", "кухня", "кухня", "kitchen", False, "wrong_word"), + + ("a1_home_t03", "A", "okno", "окно", "вікно", "window", False, "wrong_word"), + ("a1_home_t03", "B", "lodówka", "холодильник", "холодильник", "fridge", True, None), + ("a1_home_t03", "C", "kanapa", "диван", "диван", "sofa", False, "wrong_word"), + ("a1_home_t03", "D", "drzwi", "дверь", "двері", "door", False, "wrong_word"), + + ("a1_home_t04", "A", "stół", "стол", "стіл", "table", False, "wrong_word"), + ("a1_home_t04", "B", "krzesło", "стул", "стілець", "chair", False, "wrong_word"), + ("a1_home_t04", "C", "szafa", "шкаф", "шафа", "wardrobe", False, "wrong_word"), + ("a1_home_t04", "D", "łóżko", "кровать", "ліжко", "bed", True, None), + + ("a1_home_t05", "A", "dom", "дом", "будинок", "house", True, None), + ("a1_home_t05", "B", "domu", "дома (неправильно)", "будинку (неправильно)", "house (wrong case)", False, "wrong_case"), + ("a1_home_t05", "C", "domem", "домом (неправильно)", "будинком (неправильно)", "house (wrong case)", False, "wrong_case"), + ("a1_home_t05", "D", "domowi", "дому (неправильно)", "будинкові (неправильно)", "house (wrong case)", False, "wrong_case"), + + ("a1_home_t06", "A", "w kuchni", "на кухне", "на кухні", "in the kitchen", True, None), + ("a1_home_t06", "B", "w kuchnia", "на кухне (неправильно)", "на кухні (неправильно)", "in the kitchen (wrong case)", False, "wrong_case"), + ("a1_home_t06", "C", "w kuchnię", "на кухне (неправильно)", "на кухні (неправильно)", "in the kitchen (wrong case)", False, "wrong_case"), + ("a1_home_t06", "D", "w kuchnią", "на кухне (неправильно)", "на кухні (неправильно)", "in the kitchen (wrong case)", False, "wrong_case"), + + ("a1_home_t07", "A", "mieszkanie", "квартира", "квартира", "apartment", True, None), + ("a1_home_t07", "B", "dom", "дом", "будинок", "house", False, "wrong_context"), + ("a1_home_t07", "C", "pokój", "комната", "кімната", "room", False, "wrong_context"), + ("a1_home_t07", "D", "kuchnia", "кухня", "кухня", "kitchen", False, "wrong_word"), + + ("a1_home_t08", "A", "kanapa", "диван", "диван", "sofa", True, None), + ("a1_home_t08", "B", "łóżko", "кровать", "ліжко", "bed", False, "wrong_context"), + ("a1_home_t08", "C", "krzesło", "стул", "стілець", "chair", False, "wrong_context"), + ("a1_home_t08", "D", "stół", "стол", "стіл", "table", False, "wrong_context"), + + ("a1_home_t09", "A", "Kwiaty są na oknie.", "Цветы на окне.", "Квіти на вікні.", "The flowers are on the window.", True, None), + ("a1_home_t09", "B", "Kwiaty są na stole.", "Цветы на столе.", "Квіти на столі.", "The flowers are on the table.", False, "wrong_context"), + ("a1_home_t09", "C", "Kwiaty są na łóżku.", "Цветы на кровати.", "Квіти на ліжку.", "The flowers are on the bed.", False, "wrong_context"), + ("a1_home_t09", "D", "Kwiaty są na krześle.", "Цветы на стуле.", "Квіти на стільці.", "The flowers are on the chair.", False, "wrong_context"), + + ("a1_home_t10", "A", "Oglądam telewizję w salonie.", "Я смотрю телевизор в гостиной.", "Я дивлюся телевізор у вітальні.", "I watch TV in the living room.", True, None), + ("a1_home_t10", "B", "Oglądam telewizję w kuchni.", "Я смотрю телевизор на кухне.", "Я дивлюся телевізор на кухні.", "I watch TV in the kitchen.", False, "wrong_context"), + ("a1_home_t10", "C", "Oglądam telewizję w łazience.", "Я смотрю телевизор в ванной.", "Я дивлюся телевізор у ванній.", "I watch TV in the bathroom.", False, "wrong_context"), + ("a1_home_t10", "D", "Oglądam telewizję w sypialni.", "Я смотрю телевизор в спальне.", "Я дивлюся телевізор у спальні.", "I watch TV in the bedroom.", False, "wrong_context"), + + ("a1_home_t11", "A", "Nie mam dużej łazienki.", "У меня нет большой ванной.", "У мене немає великої ванної.", "I don't have a big bathroom.", True, None), + ("a1_home_t11", "B", "Nie mam duża łazienka.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_home_t11", "C", "Mam dużą łazienkę.", "У меня есть большая ванная. (неверный смысл)", "У мене є велика ванна. (неправильний сенс)", "I have a big bathroom. (wrong meaning)", False, "wrong_context"), + ("a1_home_t11", "D", "Nie jestem duża łazienka.", "Я не большая ванная.", "Я не велика ванна.", "I am not a big bathroom.", False, "wrong_sentence_type"), + + ("a1_home_t12", "A", "Mam dwa pokoje i małą kuchnię.", "У меня две комнаты и маленькая кухня.", "У мене дві кімнати і маленька кухня.", "I have two rooms and a small kitchen.", True, None), + ("a1_home_t12", "B", "Ja pokoje i kuchnia.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_home_t12", "C", "Moje mieszkanie jestem dwa pokoje.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_home_t12", "D", "Jestem dwa pokoje i mała kuchnia.", "Я две комнаты и маленькая кухня.", "Я дві кімнати і маленька кухня.", "I am two rooms and a small kitchen.", False, "wrong_sentence_type"), + + ("a1_home_t19", "A", "Talerz jest na stole, a kot śpi na łóżku.", "Тарелка на столе, а кот спит на кровати.", "Тарілка на столі, а кіт спить на ліжку.", "The plate is on the table, and the cat sleeps on the bed.", True, None), + ("a1_home_t19", "B", "Talerz jest na stół, a kot śpi na łóżko.", "Неправильные падежи.", "Неправильні відмінки.", "Wrong cases.", False, "wrong_case"), + ("a1_home_t19", "C", "Talerz śpi na stole, a kot jest na łóżku.", "Глаголы перепутаны.", "Дієслова переплутані.", "Verbs are mixed up.", False, "wrong_word"), + ("a1_home_t19", "D", "Talerz jest na łóżku, a kot śpi na stole.", "Места перепутаны.", "Місця переплутані.", "Locations are swapped.", False, "wrong_context"), + + ("a1_home_t20", "A", "Ile masz pokoi? Mam dwa pokoje i małą kuchnię.", "Сколько у тебя комнат? У меня две комнаты и маленькая кухня.", "Скільки у тебе кімнат? У мене дві кімнати і маленька кухня.", "How many rooms do you have? I have two rooms and a small kitchen.", True, None), + ("a1_home_t20", "B", "Ile masz pokój? Jestem dwa pokoje i mała kuchnia.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_home_t20", "C", "Gdzie masz pokoi? Mam dwa pokoje i małą kuchnię.", "Неправильное вопросительное слово.", "Неправильне питальне слово.", "Wrong question word.", False, "wrong_word"), + ("a1_home_t20", "D", "Ile masz pokoi? Nie mam pokoi.", "Смысл ответа неверный.", "Сенс відповіді неправильний.", "Wrong meaning in the answer.", False, "wrong_context"), + ] + + for opt in test_options_t5: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # ==================== ТЕМА 6: ЧИСЛА, ВРЕМЯ, ДНИ НЕДЕЛИ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_numbers_time', 'A1', 6, + 'Liczby, godzina, dni tygodnia', + 'Числа, время, дни недели', + 'Числа, час, дні тижня', + 'Numbers, Time, Days of the Week') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t6 = [ + ("a1_numbers_time_l01", 1, "numbers_cardinal", "Liczby 1–10", "Числа 1–10", "Числа 1–10", "Numbers 1–10", + "Podstawowe liczby: zero, jeden, dwa, trzy, cztery, pięć, sześć, siedem, osiem, dziewięć, dziesięć. Używamy ich przy wieku, cenach i adresach.", + "Основные числа: zero (ноль), jeden (один), dwa (два) ... dziesięć (десять). Используются при возрасте, ценах и адресах.", + "Основні числа: zero (нуль), jeden (один), dwa (два) ... dziesięć (десять). Використовуються при віці, цінах та адресах.", + "Basic numbers: zero, jeden (one), dwa (two) ... dziesięć (ten). Used for age, prices, and addresses."), + + ("a1_numbers_time_l02", 2, "numbers_cardinal", "Liczby 11–20", "Числа 11–20", "Числа 11–20", "Numbers 11–20", + "Liczby od jedenastu do dwudziestu: jedenaście, dwanaście, trzynaście, czternaście, piętnaście, szesnaście, siedemnaście, osiemnaście, dziewiętnaście, dwadzieścia.", + "Числа от одиннадцати до двадцати: jedenaście (одиннадцать) ... dwadzieścia (двадцать).", + "Числа від одинадцяти до двадцяти: jedenaście (одинадцять) ... dwadzieścia (двадцять).", + "Numbers from eleven to twenty: jedenaście (eleven) ... dwadzieścia (twenty)."), + + ("a1_numbers_time_l03", 3, "numbers_tens", "Dziesiątki: 20–100", "Десятки: 20–100", "Десятки: 20–100", "Tens: 20–100", + "Dziesiątki: dwadzieścia, trzydzieści, czterdzieści, pięćdziesiąt, sześćdziesiąt, siedemdziesiąt, osiemdziesiąt, dziewięćdziesiąt, sto.", + "Десятки: dwadzieścia (двадцать), trzydzieści (тридцать) ... sto (сто).", + "Десятки: dwadzieścia (двадцять), trzydzieści (тридцять) ... sto (сто).", + "Tens: dwadzieścia (twenty), trzydzieści (thirty) ... sto (hundred)."), + + ("a1_numbers_time_l04", 4, "numbers_tens", "Liczby złożone: 21–99", "Составные числа: 21–99", "Складені числа: 21–99", "Compound numbers: 21–99", + "Liczby złożone tworzymy, łącząc dziesiątki i jedności ze spacją, bez żadnej zmiany końcówek: dwadzieścia jeden (21), trzydzieści pięć (35), pięćdziesiąt trzy (53).", + "Составные числа образуются соединением десятков и единиц через пробел, без изменения окончаний: dwadzieścia jeden (21), trzydzieści pięć (35), pięćdziesiąt trzy (53).", + "Складені числа утворюються поєднанням десятків і одиниць через пробіл, без зміни закінчень: dwadzieścia jeden (21), trzydzieści pięć (35), pięćdziesiąt trzy (53).", + "Compound numbers are formed by combining tens and units with a space, without changing endings: dwadzieścia jeden (21), trzydzieści pięć (35), pięćdziesiąt trzy (53)."), + + ("a1_numbers_time_l05", 5, "time_telling", "Która godzina? Pełne godziny", "Который час? Целые часы", "Котра година? Цілі години", "What time is it? Full hours", + "„Godzina” jest rodzaju żeńskiego, dlatego godziny nazywamy formami żeńskimi: pierwsza, druga, trzecia, czwarta, piąta, szósta, siódma, ósma, dziewiąta, dziesiąta, jedenasta, dwunasta.", + "„Godzina” (час) женского рода, поэтому часы называются женскими формами: pierwsza (первый), druga (второй) ... dwunasta (двенадцатый).", + "„Godzina” (година) жіночого роду, тому години називаються жіночими формами: pierwsza (перша), druga (друга) ... dwunasta (дванадцята).", + "„Godzina” (hour) is feminine, so hours use feminine forms: pierwsza (one), druga (two) ... dwunasta (twelve)."), + + ("a1_numbers_time_l06", 6, "time_telling", "Minuty: po, za, wpół", "Минуты: po, za, wpół", "Хвилини: po, za, wpół", "Minutes: po, za, wpół", + "Minuty wyrażamy słowami: „po” (после — pięć po pierwszej), „za” (без — za dziesięć druga), „wpół do” (половина — wpół do trzeciej), „kwadrans” (четверть — kwadrans po czwartej, za kwadrans piąta).", + "Минуты выражаем словами: „po” (после — pięć po pierwszej = пять минут второго), „za” (без — za dziesięć druga = без десяти два), „wpół do” (половина — wpół do trzeciej), „kwadrans” (четверть — kwadrans po czwartej, za kwadrans piąta).", + "Хвилини виражаємо словами: „po” (після — pięć po pierwszej), „za” (без — za dziesięć druga), „wpół do” (половина — wpół do trzeciej), „kwadrans” (чверть — kwadrans po czwartej, za kwadrans piąta).", + "Minutes are expressed with: „po” (past — pięć po pierwszej = five past one), „za” (to — za dziesięć druga = ten to two), „wpół do” (half past — wpół do trzeciej), „kwadrans” (quarter — kwadrans po czwartej, za kwadrans piąta)."), + + ("a1_numbers_time_l07", 7, "time_expressions", "O której godzinie?", "Во сколько?", "О котрій годині?", "At what time?", + "Pytamy „O której godzinie?”, gdy chcemy poznać czas czynności. Odpowiadamy „o” + godzina w miejscowniku: o pierwszej, o ósmej, o dziewiątej.", + "Спрашиваем „O której godzinie?”, когда хотим узнать время действия. Отвечаем „o” + час в местном падеже: o pierwszej, o ósmej, o dziewiątej.", + "Запитуємо „O której godzinie?”, коли хочемо дізнатися час дії. Відповідаємо „o” + година в місцевому відмінку: o pierwszej, o ósmej, o dziewiątej.", + "We ask „O której godzinie?” when we want to know the time of an action. We answer with „o” + the hour in the locative: o pierwszej, o ósmej, o dziewiątej."), + + ("a1_numbers_time_l08", 8, "time_expressions", "Rano, po południu, wieczorem", "Утром, днём, вечером", "Вранці, вдень, ввечері", "Morning, afternoon, evening", + "Pory dnia: rano (утром), przed południem (до полудня), w południe (в полдень), po południu (после полудня), wieczorem (вечером), w nocy (ночью).", + "Части суток: rano (утром), przed południem (до полудня), w południe (в полдень), po południu (после полудня), wieczorem (вечером), w nocy (ночью).", + "Частини доби: rano (вранці), przed południem (до полудня), w południe (опівдні), po południu (після полудня), wieczorem (ввечері), w nocy (вночі).", + "Times of day: rano (in the morning), przed południem (before noon), w południe (at noon), po południu (in the afternoon), wieczorem (in the evening), w nocy (at night)."), + + ("a1_numbers_time_l09", 9, "days_weekdays", "Dni tygodnia", "Дни недели", "Дні тижня", "Days of the week", + "Dni tygodnia: poniedziałek, wtorek, środa, czwartek, piątek, sobota, niedziela.", + "Дни недели: poniedziałek (понедельник), wtorek (вторник), środa (среда), czwartek (четверг), piątek (пятница), sobota (суббота), niedziela (воскресенье).", + "Дні тижня: poniedziałek (понеділок), wtorek (вівторок), środa (середа), czwartek (четвер), piątek (п'ятниця), sobota (субота), niedziela (неділя).", + "Days of the week: poniedziałek (Monday), wtorek (Tuesday), środa (Wednesday), czwartek (Thursday), piątek (Friday), sobota (Saturday), niedziela (Sunday)."), + + ("a1_numbers_time_l10", 10, "days_weekdays", "W poniedziałek — dzień tygodnia w zdaniu", "В понедельник — день недели в предложении", "У понеділок — день тижня в реченні", "On Monday — the day of the week in a sentence", + "Mówiąc, kiedy coś się dzieje, używamy „w” + dzień tygodnia: w poniedziałek, we wtorek (wyjątek fonetyczny — „we”, nie „w”), w środę, w czwartek, w piątek, w sobotę, w niedzielę. Rzeczowniki żeńskie (środa, sobota, niedziela) zmieniają końcówkę na biernik.", + "Говоря, когда что-то происходит, используем „w” + день недели: w poniedziałek, we wtorek (фонетическое исключение — „we”, а не „w”), w środę, w czwartek, w piątek, w sobotę, w niedzielę. Существительные женского рода (środa, sobota, niedziela) меняют окончание на винительный падеж.", + "Кажучи, коли щось відбувається, використовуємо „w” + день тижня: w poniedziałek, we wtorek (фонетичний виняток — „we”, а не „w”), w środę, w czwartek, w piątek, w sobotę, w niedzielę. Іменники жіночого роду (środa, sobota, niedziela) змінюють закінчення на знахідний відмінок.", + "To say when something happens, we use „w” + day of the week: w poniedziałek, we wtorek (phonetic exception — „we”, not „w”), w środę, w czwartek, w piątek, w sobotę, w niedzielę. Feminine nouns (środa, sobota, niedziela) switch to the accusative ending."), + ] + + for lesson in lessons_t6: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_numbers_time', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t6 = [ + ("a1_numbers_time_l01", 1, "Mam jeden telefon.", "У меня один телефон.", "У мене один телефон.", "I have one phone."), + ("a1_numbers_time_l01", 2, "Mam dwa psy.", "У меня две собаки.", "У мене два пси.", "I have two dogs."), + ("a1_numbers_time_l01", 3, "Liczę do dziesięciu.", "Я считаю до десяти.", "Я рахую до десяти.", "I count to ten."), + + ("a1_numbers_time_l02", 1, "Mam jedenaście lat.", "Мне одиннадцать лет.", "Мені одинадцять років.", "I am eleven years old."), + ("a1_numbers_time_l02", 2, "W klasie jest piętnaście osób.", "В классе пятнадцать человек.", "У класі п'ятнадцять осіб.", "There are fifteen people in the class."), + ("a1_numbers_time_l02", 3, "Dwadzieścia to dwa razy dziesięć.", "Двадцать — это дважды десять.", "Двадцять — це двічі десять.", "Twenty is two times ten."), + + ("a1_numbers_time_l03", 1, "Moja babcia ma sześćdziesiąt lat.", "Моей бабушке шестьдесят лет.", "Моїй бабусі шістдесят років.", "My grandma is sixty years old."), + ("a1_numbers_time_l03", 2, "Bilet kosztuje sto złotych.", "Билет стоит сто злотых.", "Квиток коштує сто злотих.", "The ticket costs a hundred zloty."), + ("a1_numbers_time_l03", 3, "Czterdzieści to cztery razy dziesięć.", "Сорок — это четырежды десять.", "Сорок — це чотири рази по десять.", "Forty is four times ten."), + + ("a1_numbers_time_l04", 1, "Mam dwadzieścia jeden lat.", "Мне двадцать один год.", "Мені двадцять один рік.", "I am twenty-one years old."), + ("a1_numbers_time_l04", 2, "W autobusie jest trzydzieści pięć miejsc.", "В автобусе тридцать пять мест.", "В автобусі тридцять п'ять місць.", "There are thirty-five seats in the bus."), + ("a1_numbers_time_l04", 3, "Numer kończy się na pięćdziesiąt trzy.", "Номер заканчивается на пятьдесят три.", "Номер закінчується на п'ятдесят три.", "The number ends in fifty-three."), + + ("a1_numbers_time_l05", 1, "Która godzina? Jest pierwsza.", "Который час? Час.", "Котра година? Перша.", "What time is it? It's one o'clock."), + ("a1_numbers_time_l05", 2, "Jest ósma rano.", "Восемь утра.", "Восьма ранку.", "It's eight in the morning."), + ("a1_numbers_time_l05", 3, "Jest dwunasta w południe.", "Двенадцать дня.", "Дванадцята дня.", "It's twelve noon."), + + ("a1_numbers_time_l06", 1, "Jest wpół do trzeciej.", "Половина третьего.", "Пів на третю.", "It's half past two."), + ("a1_numbers_time_l06", 2, "Jest kwadrans po czwartej.", "Четверть пятого.", "Чверть на п'яту.", "It's a quarter past four."), + ("a1_numbers_time_l06", 3, "Jest za dziesięć siódma.", "Без десяти семь.", "За десять сьома.", "It's ten to seven."), + + ("a1_numbers_time_l07", 1, "O której godzinie zaczyna się lekcja?", "Во сколько начинается урок?", "О котрій годині починається урок?", "What time does the lesson start?"), + ("a1_numbers_time_l07", 2, "Lekcja zaczyna się o ósmej.", "Урок начинается в восемь.", "Урок починається о восьмій.", "The lesson starts at eight."), + ("a1_numbers_time_l07", 3, "Spotkamy się o siódmej wieczorem.", "Встретимся в семь вечера.", "Зустрінемося о сьомій увечері.", "We'll meet at seven in the evening."), + + ("a1_numbers_time_l08", 1, "Pracuję rano i po południu.", "Я работаю утром и днём.", "Я працюю вранці і вдень.", "I work in the morning and afternoon."), + ("a1_numbers_time_l08", 2, "Śpię w nocy.", "Я сплю ночью.", "Я сплю вночі.", "I sleep at night."), + ("a1_numbers_time_l08", 3, "Spotykamy się wieczorem.", "Мы встречаемся вечером.", "Ми зустрічаємося ввечері.", "We meet in the evening."), + + ("a1_numbers_time_l09", 1, "Dziś jest poniedziałek.", "Сегодня понедельник.", "Сьогодні понеділок.", "Today is Monday."), + ("a1_numbers_time_l09", 2, "Jutro będzie wtorek.", "Завтра будет вторник.", "Завтра буде вівторок.", "Tomorrow will be Tuesday."), + ("a1_numbers_time_l09", 3, "Weekend to sobota i niedziela.", "Выходные — это суббота и воскресенье.", "Вихідні — це субота і неділя.", "The weekend is Saturday and Sunday."), + + ("a1_numbers_time_l10", 1, "W poniedziałek pracuję.", "В понедельник я работаю.", "У понеділок я працюю.", "I work on Monday."), + ("a1_numbers_time_l10", 2, "We wtorek mam lekcję polskiego.", "Во вторник у меня урок польского.", "У вівторок у мене урок польської.", "On Tuesday I have a Polish lesson."), + ("a1_numbers_time_l10", 3, "W niedzielę odpoczywam.", "В воскресенье я отдыхаю.", "У неділю я відпочиваю.", "On Sunday I rest."), + ] + + for ex in examples_t6: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t6 = [ + # L01 — numbers_cardinal (difficulty 1) + ("a1_numbers_time_l01_q1", "a1_numbers_time_l01", "lesson_practice", "recognition", "numbers_cardinal", 1, + "Jak po polsku „пять”?", "Как по-польски «пять»?", "Як польською «п'ять»?", "How do you say “five” in Polish?", + "B", None, None), + ("a1_numbers_time_l01_q2", "a1_numbers_time_l01", "lesson_practice", "production", "numbers_cardinal", 1, + "Wpisz brakujące słowo: To jest liczba ___. (шесть)", "Вставьте пропущенное слово: To jest liczba ___. (шесть)", "Вставте пропущене слово: To jest liczba ___. (шість)", "Fill in the missing word: To jest liczba ___. (six)", + "sześć", "first_letter", "s"), + ("a1_numbers_time_l01_q3", "a1_numbers_time_l01", "lesson_practice", "application", "numbers_cardinal", 1, + "Ktoś pyta, ile masz lat. Masz osiem lat. Co powiesz?", "Кто-то спрашивает, сколько тебе лет. Тебе восемь лет. Что ты скажешь?", "Хтось питає, скільки тобі років. Тобі вісім років. Що ти скажеш?", "Someone asks how old you are. You are eight. What do you say?", + "A", None, None), + + # L02 — numbers_cardinal (difficulty 1) + ("a1_numbers_time_l02_q1", "a1_numbers_time_l02", "lesson_practice", "recognition", "numbers_cardinal", 1, + "Jak po polsku „пятнадцать”?", "Как по-польски «пятнадцать»?", "Як польською «п'ятнадцять»?", "How do you say “fifteen” in Polish?", + "B", None, None), + ("a1_numbers_time_l02_q2", "a1_numbers_time_l02", "lesson_practice", "production", "numbers_cardinal", 1, + "Wpisz brakujące słowo: To jest liczba ___. (двадцать)", "Вставьте пропущенное слово: To jest liczba ___. (двадцать)", "Вставте пропущене слово: To jest liczba ___. (двадцять)", "Fill in the missing word: To jest liczba ___. (twenty)", + "dwadzieścia", "first_letter", "d"), + ("a1_numbers_time_l02_q3", "a1_numbers_time_l02", "lesson_practice", "application", "numbers_cardinal", 1, + "Ktoś pyta, ile masz lat. Masz siedemnaście lat. Co powiesz?", "Кто-то спрашивает, сколько тебе лет. Тебе семнадцать лет. Что ты скажешь?", "Хтось питає, скільки тобі років. Тобі сімнадцять років. Що ти скажеш?", "Someone asks how old you are. You are seventeen. What do you say?", + "A", None, None), + + # L03 — numbers_tens (difficulty 1) + ("a1_numbers_time_l03_q1", "a1_numbers_time_l03", "lesson_practice", "recognition", "numbers_tens", 1, + "Jak po polsku „пятьдесят”?", "Как по-польски «пятьдесят»?", "Як польською «п'ятдесят»?", "How do you say “fifty” in Polish?", + "B", None, None), + ("a1_numbers_time_l03_q2", "a1_numbers_time_l03", "lesson_practice", "production", "numbers_tens", 1, + "Wpisz brakujące słowo: To jest liczba ___. (сто)", "Вставьте пропущенное слово: To jest liczba ___. (сто)", "Вставте пропущене слово: To jest liczba ___. (сто)", "Fill in the missing word: To jest liczba ___. (hundred)", + "sto", "first_letter", "s"), + ("a1_numbers_time_l03_q3", "a1_numbers_time_l03", "lesson_practice", "application", "numbers_tens", 1, + "Chcesz kupić bilet za sto złotych. Ile to kosztuje?", "Ты хочешь купить билет за сто злотых. Сколько это стоит?", "Ти хочеш купити квиток за сто злотих. Скільки це коштує?", "You want to buy a ticket for a hundred zloty. How much does it cost?", + "A", None, None), + + # L04 — numbers_tens (difficulty 1) + ("a1_numbers_time_l04_q1", "a1_numbers_time_l04", "lesson_practice", "recognition", "numbers_tens", 1, + "Jak po polsku „тридцать пять”?", "Как по-польски «тридцать пять»?", "Як польською «тридцять п'ять»?", "How do you say “thirty-five” in Polish?", + "A", None, None), + ("a1_numbers_time_l04_q2", "a1_numbers_time_l04", "lesson_practice", "production", "numbers_tens", 1, + "Wpisz brakujące słowo: Mam ___ lat. (двадцать один)", "Вставьте пропущенное слово: Mam ___ lat. (двадцать один)", "Вставте пропущене слово: Mam ___ lat. (двадцять один)", "Fill in the missing word: Mam ___ lat. (twenty-one)", + "dwadzieścia jeden", "first_letter", "d"), + ("a1_numbers_time_l04_q3", "a1_numbers_time_l04", "lesson_practice", "application", "numbers_tens", 1, + "Ktoś pyta, ile masz lat. Masz dwadzieścia pięć lat. Co powiesz?", "Кто-то спрашивает, сколько тебе лет. Тебе двадцать пять лет. Что ты скажешь?", "Хтось питає, скільки тобі років. Тобі двадцять п'ять років. Що ти скажеш?", "Someone asks how old you are. You are twenty-five. What do you say?", + "A", None, None), + + # L05 — time_telling (difficulty 2) + ("a1_numbers_time_l05_q1", "a1_numbers_time_l05", "lesson_practice", "recognition", "time_telling", 2, + "Co znaczy „Która godzina?”", "Что означает «Która godzina?»", "Що означає «Która godzina?»", "What does “Która godzina?” mean?", + "A", None, None), + ("a1_numbers_time_l05_q2", "a1_numbers_time_l05", "lesson_practice", "production", "time_telling", 2, + "Wpisz brakujące słowo: Jest ___. (третий час)", "Вставьте пропущенное слово: Jest ___. (третий час)", "Вставте пропущене слово: Jest ___. (третя година)", "Fill in the missing word: Jest ___. (three o'clock)", + "trzecia", "first_letter", "t"), + ("a1_numbers_time_l05_q3", "a1_numbers_time_l05", "lesson_practice", "application", "time_telling", 2, + "Zegar pokazuje 5:00. Która jest godzina?", "Часы показывают 5:00. Который час?", "Годинник показує 5:00. Котра година?", "The clock shows 5:00. What time is it?", + "A", None, None), + + # L06 — time_telling (difficulty 2) + ("a1_numbers_time_l06_q1", "a1_numbers_time_l06", "lesson_practice", "recognition", "time_telling", 2, + "Co znaczy „za kwadrans piąta”?", "Что означает «za kwadrans piąta»?", "Що означає «za kwadrans piąta»?", "What does “za kwadrans piąta” mean?", + "A", None, None), + ("a1_numbers_time_l06_q2", "a1_numbers_time_l06", "lesson_practice", "production", "time_telling", 2, + "Wpisz brakujące słowo: Jest ___ do trzeciej. (половина)", "Вставьте пропущенное слово: Jest ___ do trzeciej. (половина)", "Вставте пропущене слово: Jest ___ do trzeciej. (половина)", "Fill in the missing word: Jest ___ do trzeciej. (half)", + "wpół", "first_letter", "w"), + ("a1_numbers_time_l06_q3", "a1_numbers_time_l06", "lesson_practice", "application", "time_telling", 2, + "Zegar pokazuje 2:30. Która jest godzina?", "Часы показывают 2:30. Который час?", "Годинник показує 2:30. Котра година?", "The clock shows 2:30. What time is it?", + "A", None, None), + + # L07 — time_expressions (difficulty 2) + ("a1_numbers_time_l07_q1", "a1_numbers_time_l07", "lesson_practice", "recognition", "time_expressions", 2, + "Co znaczy „O której godzinie?”", "Что означает «O której godzinie?»", "Що означає «O której godzinie?»", "What does “O której godzinie?” mean?", + "A", None, None), + ("a1_numbers_time_l07_q2", "a1_numbers_time_l07", "lesson_practice", "production", "time_expressions", 2, + "Wpisz brakujące słowo: Zaczynam pracę ___ ósmej. (в)", "Вставьте пропущенное слово: Zaczynam pracę ___ ósmej. (в)", "Вставте пропущене слово: Zaczynam pracę ___ ósmej. (о)", "Fill in the missing word: Zaczynam pracę ___ ósmej. (at)", + "o", "first_letter", "o"), + ("a1_numbers_time_l07_q3", "a1_numbers_time_l07", "lesson_practice", "application", "time_expressions", 2, + "Kolega pyta „O której godzinie zaczyna się film?” Film zaczyna się o dziewiątej. Co powiesz?", "Друг спрашивает «O której godzinie zaczyna się film?» Фильм начинается в девять. Что ты скажешь?", "Друг питає «O której godzinie zaczyna się film?» Фільм починається о дев'ятій. Що ти скажеш?", "A friend asks “O której godzinie zaczyna się film?” The movie starts at nine. What do you say?", + "A", None, None), + + # L08 — time_expressions (difficulty 2) + ("a1_numbers_time_l08_q1", "a1_numbers_time_l08", "lesson_practice", "recognition", "time_expressions", 2, + "Jak po polsku „вечером”?", "Как по-польски «вечером»?", "Як польською «ввечері»?", "How do you say “in the evening” in Polish?", + "A", None, None), + ("a1_numbers_time_l08_q2", "a1_numbers_time_l08", "lesson_practice", "production", "time_expressions", 2, + "Wpisz brakujące słowo: Śpię ___. (ночью)", "Вставьте пропущенное слово: Śpię ___. (ночью)", "Вставте пропущене слово: Śpię ___. (вночі)", "Fill in the missing word: Śpię ___. (at night)", + "w nocy", "first_letter", "w"), + ("a1_numbers_time_l08_q3", "a1_numbers_time_l08", "lesson_practice", "application", "time_expressions", 2, + "Jest godzina 21:00. Jaka to pora dnia?", "Сейчас 21:00. Какая это часть суток?", "Зараз 21:00. Яка це частина доби?", "It's 21:00. What time of day is that?", + "A", None, None), + + # L09 — days_weekdays (difficulty 3) + ("a1_numbers_time_l09_q1", "a1_numbers_time_l09", "lesson_practice", "recognition", "days_weekdays", 3, + "Jak po polsku „среда”?", "Как по-польски «среда»?", "Як польською «середа»?", "How do you say “Wednesday” in Polish?", + "A", None, None), + ("a1_numbers_time_l09_q2", "a1_numbers_time_l09", "lesson_practice", "production", "days_weekdays", 3, + "Wpisz brakujące słowo: Dziś jest ___. (пятница)", "Вставьте пропущенное слово: Dziś jest ___. (пятница)", "Вставте пропущене слово: Dziś jest ___. (п'ятниця)", "Fill in the missing word: Dziś jest ___. (Friday)", + "piątek", "first_letter", "p"), + ("a1_numbers_time_l09_q3", "a1_numbers_time_l09", "lesson_practice", "application", "days_weekdays", 3, + "Dziś jest sobota. Jaki dzień będzie jutro?", "Сегодня суббота. Какой день будет завтра?", "Сьогодні субота. Який день буде завтра?", "Today is Saturday. What day will it be tomorrow?", + "A", None, None), + + # L10 — days_weekdays (difficulty 3) + ("a1_numbers_time_l10_q1", "a1_numbers_time_l10", "lesson_practice", "recognition", "days_weekdays", 3, + "Wybierz poprawną formę: ___ wtorek. (w/we)", "Выберите правильную форму: ___ wtorek. (w/we)", "Виберіть правильну форму: ___ wtorek. (w/we)", "Choose the correct form: ___ wtorek. (w/we)", + "B", None, None), + ("a1_numbers_time_l10_q2", "a1_numbers_time_l10", "lesson_practice", "production", "days_weekdays", 3, + "Wpisz brakujące słowo: W ___ odpoczywam. (воскресенье, винительный)", "Вставьте пропущенное слово: W ___ odpoczywam. (воскресенье, винительный)", "Вставте пропущене слово: W ___ odpoczywam. (неділя, знахідний)", "Fill in the missing word: W ___ odpoczywam. (Sunday, accusative)", + "niedzielę", "first_letter", "n"), + ("a1_numbers_time_l10_q3", "a1_numbers_time_l10", "lesson_practice", "application", "days_weekdays", 3, + "Chcesz powiedzieć, że masz lekcję we wtorek. Co powiesz?", "Ты хочешь сказать, что у тебя урок во вторник. Что ты скажешь?", "Ти хочеш сказати, що у тебе урок у вівторок. Що ти скажеш?", "You want to say you have a lesson on Tuesday. What do you say?", + "A", None, None), + ] + + for q in questions_t6: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_numbers_time', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t6 = [ + # L01 + ("a1_numbers_time_l01_q1", "A", "cztery", "четыре", "чотири", "four", False, "wrong_word"), + ("a1_numbers_time_l01_q1", "B", "pięć", "пять", "п'ять", "five", True, None), + ("a1_numbers_time_l01_q1", "C", "sześć", "шесть", "шість", "six", False, "wrong_word"), + ("a1_numbers_time_l01_q1", "D", "siedem", "семь", "сім", "seven", False, "wrong_word"), + + ("a1_numbers_time_l01_q3", "A", "Mam osiem lat.", "Мне восемь лет.", "Мені вісім років.", "I am eight years old.", True, None), + ("a1_numbers_time_l01_q3", "B", "Jestem osiem lat.", "Я восемь лет.", "Я вісім років.", "I am eight years. (wrong construction)", False, "wrong_sentence_type"), + ("a1_numbers_time_l01_q3", "C", "Osiem lat mam ja.", "Восемь лет имею я. (неправильный порядок)", "Вісім років маю я. (неправильний порядок)", "Eight years I have. (wrong construction)", False, "wrong_sentence_type"), + ("a1_numbers_time_l01_q3", "D", "Mam osiem rok.", "Мне восемь год. (неправильно)", "Мені вісім рік. (неправильно)", "I am eight year. (wrong number form)", False, "wrong_number"), + + # L02 + ("a1_numbers_time_l02_q1", "A", "dziesięć", "десять", "десять", "ten", False, "wrong_word"), + ("a1_numbers_time_l02_q1", "B", "piętnaście", "пятнадцать", "п'ятнадцять", "fifteen", True, None), + ("a1_numbers_time_l02_q1", "C", "dwadzieścia", "двадцать", "двадцять", "twenty", False, "wrong_word"), + ("a1_numbers_time_l02_q1", "D", "pięć", "пять", "п'ять", "five", False, "wrong_word"), + + ("a1_numbers_time_l02_q3", "A", "Mam siedemnaście lat.", "Мне семнадцать лет.", "Мені сімнадцять років.", "I am seventeen years old.", True, None), + ("a1_numbers_time_l02_q3", "B", "Mam siedemnaście rok.", "Мне семнадцать год. (неправильно)", "Мені сімнадцять рік. (неправильно)", "I am seventeen year. (wrong number form)", False, "wrong_number"), + ("a1_numbers_time_l02_q3", "C", "Jestem siedemnaście lat.", "Я семнадцать лет.", "Я сімнадцять років.", "I am seventeen years. (wrong construction)", False, "wrong_sentence_type"), + ("a1_numbers_time_l02_q3", "D", "Mam osiemnaście lat.", "Мне восемнадцать лет. (неверное число)", "Мені вісімнадцять років. (невірне число)", "I am eighteen years old. (wrong number)", False, "wrong_word"), + + # L03 + ("a1_numbers_time_l03_q1", "A", "czterdzieści", "сорок", "сорок", "forty", False, "wrong_word"), + ("a1_numbers_time_l03_q1", "B", "pięćdziesiąt", "пятьдесят", "п'ятдесят", "fifty", True, None), + ("a1_numbers_time_l03_q1", "C", "sześćdziesiąt", "шестьдесят", "шістдесят", "sixty", False, "wrong_word"), + ("a1_numbers_time_l03_q1", "D", "sto", "сто", "сто", "hundred", False, "wrong_word"), + + ("a1_numbers_time_l03_q3", "A", "Sto złotych.", "Сто злотых.", "Сто злотих.", "A hundred zloty.", True, None), + ("a1_numbers_time_l03_q3", "B", "Dziesięć złotych.", "Десять злотых. (неверное число)", "Десять злотих. (невірне число)", "Ten zloty. (wrong number)", False, "wrong_word"), + ("a1_numbers_time_l03_q3", "C", "Tysiąc złotych.", "Тысяча злотых. (неверное число)", "Тисяча злотих. (невірне число)", "A thousand zloty. (wrong number)", False, "wrong_word"), + ("a1_numbers_time_l03_q3", "D", "Sto lat.", "Сто лет. (неверная единица)", "Сто років. (невірна одиниця)", "A hundred years. (wrong unit)", False, "wrong_word"), + + # L04 + ("a1_numbers_time_l04_q1", "A", "trzydzieści pięć", "тридцать пять", "тридцять п'ять", "thirty-five", True, None), + ("a1_numbers_time_l04_q1", "B", "pięćdziesiąt trzy", "пятьдесят три", "п'ятдесят три", "fifty-three", False, "wrong_word"), + ("a1_numbers_time_l04_q1", "C", "dwadzieścia pięć", "двадцать пять", "двадцять п'ять", "twenty-five", False, "wrong_word"), + ("a1_numbers_time_l04_q1", "D", "czterdzieści pięć", "сорок пять", "сорок п'ять", "forty-five", False, "wrong_word"), + + ("a1_numbers_time_l04_q3", "A", "Mam dwadzieścia pięć lat.", "Мне двадцать пять лет.", "Мені двадцять п'ять років.", "I am twenty-five years old.", True, None), + ("a1_numbers_time_l04_q3", "B", "Mam dwadzieścia pięć rok.", "Неправильная форма числа.", "Неправильна форма числа.", "Wrong number form.", False, "wrong_number"), + ("a1_numbers_time_l04_q3", "C", "Jestem dwadzieścia pięć lat.", "Я двадцать пять лет.", "Я двадцять п'ять років.", "I am twenty-five years. (wrong construction)", False, "wrong_sentence_type"), + ("a1_numbers_time_l04_q3", "D", "Mam piętnaście lat.", "Мне пятнадцать лет. (неверное число)", "Мені п'ятнадцять років. (невірне число)", "I am fifteen years old. (wrong number)", False, "wrong_word"), + + # L05 + ("a1_numbers_time_l05_q1", "A", "Который час?", "Который час?", "Котра година?", "What time is it?", True, None), + ("a1_numbers_time_l05_q1", "B", "Какой сегодня день?", "Какой сегодня день?", "Який сьогодні день?", "What day is it today?", False, "wrong_translation"), + ("a1_numbers_time_l05_q1", "C", "Сколько тебе лет?", "Сколько тебе лет?", "Скільки тобі років?", "How old are you?", False, "wrong_translation"), + ("a1_numbers_time_l05_q1", "D", "Где ты находишься?", "Где ты находишься?", "Де ти знаходишся?", "Where are you?", False, "wrong_translation"), + + ("a1_numbers_time_l05_q3", "A", "Jest piąta.", "Пять часов.", "П'ята година.", "It's five o'clock.", True, None), + ("a1_numbers_time_l05_q3", "B", "Jest pięć.", "Неправильная форма — просто число, не время.", "Неправильна форма — просто число, не час.", "Just a number, not a time form.", False, "wrong_word"), + ("a1_numbers_time_l05_q3", "C", "Jest piąty.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_numbers_time_l05_q3", "D", "Jest szósta.", "Шесть часов. (неверное время)", "Шоста година. (невірний час)", "It's six o'clock. (wrong time)", False, "wrong_context"), + + # L06 + ("a1_numbers_time_l06_q1", "A", "без четверти пять", "без четверти пять", "без чверті п'ята", "quarter to five", True, None), + ("a1_numbers_time_l06_q1", "B", "четверть пятого", "четверть пятого", "чверть на п'яту", "quarter past five", False, "wrong_translation"), + ("a1_numbers_time_l06_q1", "C", "половина пятого", "половина пятого", "половина п'ятої", "half past four", False, "wrong_translation"), + ("a1_numbers_time_l06_q1", "D", "ровно пять", "ровно пять", "рівно п'ята", "exactly five", False, "wrong_translation"), + + ("a1_numbers_time_l06_q3", "A", "Jest wpół do trzeciej.", "Половина третьего.", "Пів на третю.", "It's half past two.", True, None), + ("a1_numbers_time_l06_q3", "B", "Jest kwadrans po trzeciej.", "Четверть четвёртого. (неверное время)", "Чверть на четверту. (невірний час)", "It's a quarter past three. (wrong time)", False, "wrong_context"), + ("a1_numbers_time_l06_q3", "C", "Jest za dziesięć trzecia.", "Без десяти три. (неверное время)", "За десять третя. (невірний час)", "It's ten to three. (wrong time)", False, "wrong_context"), + ("a1_numbers_time_l06_q3", "D", "Jest trzecia.", "Три часа. (неверное время)", "Третя година. (невірний час)", "It's three o'clock. (wrong time)", False, "wrong_context"), + + # L07 + ("a1_numbers_time_l07_q1", "A", "Во сколько?", "Во сколько?", "О котрій?", "At what time?", True, None), + ("a1_numbers_time_l07_q1", "B", "Который час?", "Который час?", "Котра година?", "What time is it?", False, "wrong_translation"), + ("a1_numbers_time_l07_q1", "C", "Какой сегодня день?", "Какой сегодня день?", "Який сьогодні день?", "What day is it today?", False, "wrong_translation"), + ("a1_numbers_time_l07_q1", "D", "Как долго?", "Как долго?", "Як довго?", "How long?", False, "wrong_translation"), + + ("a1_numbers_time_l07_q3", "A", "Film zaczyna się o dziewiątej.", "Фильм начинается в девять.", "Фільм починається о дев'ятій.", "The movie starts at nine.", True, None), + ("a1_numbers_time_l07_q3", "B", "Film zaczyna dziewiątej.", "Пропущен предлог.", "Пропущено прийменник.", "Missing preposition.", False, "wrong_sentence_type"), + ("a1_numbers_time_l07_q3", "C", "Film jest o dziewiątej.", "Неправильный глагол.", "Неправильне дієслово.", "Wrong verb.", False, "wrong_word"), + ("a1_numbers_time_l07_q3", "D", "Film zaczyna się o ósmej.", "Фильм начинается в восемь. (неверное время)", "Фільм починається о восьмій. (невірний час)", "The movie starts at eight. (wrong time)", False, "wrong_context"), + + # L08 + ("a1_numbers_time_l08_q1", "A", "wieczorem", "вечером", "ввечері", "in the evening", True, None), + ("a1_numbers_time_l08_q1", "B", "rano", "утром", "вранці", "in the morning", False, "wrong_word"), + ("a1_numbers_time_l08_q1", "C", "w nocy", "ночью", "вночі", "at night", False, "wrong_word"), + ("a1_numbers_time_l08_q1", "D", "w południe", "в полдень", "опівдні", "at noon", False, "wrong_word"), + + ("a1_numbers_time_l08_q3", "A", "Wieczorem.", "Вечером.", "Ввечері.", "In the evening.", True, None), + ("a1_numbers_time_l08_q3", "B", "Rano.", "Утром. (неверная часть суток)", "Вранці. (невірна частина доби)", "In the morning. (wrong time of day)", False, "wrong_context"), + ("a1_numbers_time_l08_q3", "C", "W południe.", "В полдень. (неверная часть суток)", "Опівдні. (невірна частина доби)", "At noon. (wrong time of day)", False, "wrong_context"), + ("a1_numbers_time_l08_q3", "D", "Po południu.", "Днём. (неверная часть суток)", "Вдень. (невірна частина доби)", "In the afternoon. (wrong time of day)", False, "wrong_context"), + + # L09 + ("a1_numbers_time_l09_q1", "A", "środa", "среда", "середа", "Wednesday", True, None), + ("a1_numbers_time_l09_q1", "B", "czwartek", "четверг", "четвер", "Thursday", False, "wrong_word"), + ("a1_numbers_time_l09_q1", "C", "wtorek", "вторник", "вівторок", "Tuesday", False, "wrong_word"), + ("a1_numbers_time_l09_q1", "D", "piątek", "пятница", "п'ятниця", "Friday", False, "wrong_word"), + + ("a1_numbers_time_l09_q3", "A", "Niedziela.", "Воскресенье.", "Неділя.", "Sunday.", True, None), + ("a1_numbers_time_l09_q3", "B", "Poniedziałek.", "Понедельник. (неверный день)", "Понеділок. (невірний день)", "Monday. (wrong day)", False, "wrong_context"), + ("a1_numbers_time_l09_q3", "C", "Piątek.", "Пятница. (неверный день)", "П'ятниця. (невірний день)", "Friday. (wrong day)", False, "wrong_context"), + ("a1_numbers_time_l09_q3", "D", "Sobota.", "Суббота. (сегодняшний день, не завтрашний)", "Субота. (сьогоднішній день, не завтрашній)", "Saturday. (today, not tomorrow)", False, "wrong_context"), + + # L10 + ("a1_numbers_time_l10_q1", "A", "w", "в (неправильно перед wtorek)", "в (неправильно перед wtorek)", "in (wrong before wtorek)", False, "wrong_word"), + ("a1_numbers_time_l10_q1", "B", "we", "во", "у", "on (correct before wtorek)", True, None), + ("a1_numbers_time_l10_q1", "C", "na", "на", "на", "on (wrong preposition)", False, "wrong_word"), + ("a1_numbers_time_l10_q1", "D", "do", "до", "до", "to (wrong preposition)", False, "wrong_word"), + + ("a1_numbers_time_l10_q3", "A", "We wtorek mam lekcję.", "Во вторник у меня урок.", "У вівторок у мене урок.", "On Tuesday I have a lesson.", True, None), + ("a1_numbers_time_l10_q3", "B", "W wtorek mam lekcję.", "Неправильная форма предлога.", "Неправильна форма прийменника.", "Wrong preposition form.", False, "wrong_word"), + ("a1_numbers_time_l10_q3", "C", "We wtorku mam lekcję.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_numbers_time_l10_q3", "D", "Mam lekcję wtorek.", "Пропущен предлог.", "Пропущено прийменник.", "Missing preposition.", False, "wrong_sentence_type"), + ] + + for opt in options_t6: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t6 = [ + ("a1_numbers_time_t01", None, "topic_test", "recognition", "numbers_cardinal", 1, + "Jak po polsku „пять”?", "Как по-польски «пять»?", "Як польською «п'ять»?", "How do you say “five” in Polish?", + "B", None, None, 1), + ("a1_numbers_time_t02", None, "topic_test", "recognition", "numbers_cardinal", 1, + "Jak po polsku „пятнадцать”?", "Как по-польски «пятнадцать»?", "Як польською «п'ятнадцять»?", "How do you say “fifteen” in Polish?", + "B", None, None, 2), + ("a1_numbers_time_t03", None, "topic_test", "recognition", "numbers_tens", 1, + "Jak po polsku „пятьдесят”?", "Как по-польски «пятьдесят»?", "Як польською «п'ятдесят»?", "How do you say “fifty” in Polish?", + "B", None, None, 3), + ("a1_numbers_time_t04", None, "topic_test", "recognition", "time_telling", 1, + "Co znaczy „Która godzina?”", "Что означает «Która godzina?»", "Що означає «Która godzina?»", "What does “Która godzina?” mean?", + "A", None, None, 4), + ("a1_numbers_time_t05", None, "topic_test", "recognition", "time_expressions", 1, + "Co znaczy „O której godzinie?”", "Что означает «O której godzinie?»", "Що означає «O której godzinie?»", "What does “O której godzinie?” mean?", + "A", None, None, 5), + ("a1_numbers_time_t06", None, "topic_test", "recognition", "days_weekdays", 1, + "Jak po polsku „среда”?", "Как по-польски «среда»?", "Як польською «середа»?", "How do you say “Wednesday” in Polish?", + "A", None, None, 6), + + ("a1_numbers_time_t07", None, "topic_test", "application", "numbers_cardinal", 2, + "Ktoś pyta, ile masz lat. Masz dziewięć lat. Co powiesz?", "Кто-то спрашивает, сколько тебе лет. Тебе девять лет. Что ты скажешь?", "Хтось питає, скільки тобі років. Тобі дев'ять років. Що ти скажеш?", "Someone asks how old you are. You are nine. What do you say?", + "A", None, None, 7), + ("a1_numbers_time_t08", None, "topic_test", "application", "numbers_tens", 2, + "Chcesz kupić bilet za sto złotych. Ile to kosztuje?", "Ты хочешь купить билет за сто злотых. Сколько это стоит?", "Ти хочеш купити квиток за сто злотих. Скільки це коштує?", "You want to buy a ticket for a hundred zloty. How much does it cost?", + "A", None, None, 8), + ("a1_numbers_time_t09", None, "topic_test", "application", "time_telling", 2, + "Zegar pokazuje 6:00. Która jest godzina?", "Часы показывают 6:00. Который час?", "Годинник показує 6:00. Котра година?", "The clock shows 6:00. What time is it?", + "A", None, None, 9), + ("a1_numbers_time_t10", None, "topic_test", "application", "time_telling", 2, + "Zegar pokazuje 4:30. Która jest godzina?", "Часы показывают 4:30. Который час?", "Годинник показує 4:30. Котра година?", "The clock shows 4:30. What time is it?", + "A", None, None, 10), + ("a1_numbers_time_t11", None, "topic_test", "application", "time_expressions", 2, + "Kolega pyta „O której godzinie zaczyna się lekcja?” Lekcja zaczyna się o ósmej. Co powiesz?", "Друг спрашивает «O której godzinie zaczyna się lekcja?» Урок начинается в восемь. Что ты скажешь?", "Друг питає «O której godzinie zaczyna się lekcja?» Урок починається о восьмій. Що ти скажеш?", "A friend asks “O której godzinie zaczyna się lekcja?” The lesson starts at eight. What do you say?", + "A", None, None, 11), + + ("a1_numbers_time_t12", None, "topic_test", "application", "days_weekdays", 3, + "Chcesz powiedzieć, że masz lekcję we wtorek. Co powiesz?", "Ты хочешь сказать, что у тебя урок во вторник. Что ты скажешь?", "Ти хочеш сказати, що у тебе урок у вівторок. Що ти скажеш?", "You want to say you have a lesson on Tuesday. What do you say?", + "A", None, None, 12), + + ("a1_numbers_time_t13", None, "topic_test", "production", "numbers_cardinal", 1, + "Wpisz brakujące słowo: To jest liczba ___. (шесть)", "Вставьте пропущенное слово: To jest liczba ___. (шесть)", "Вставте пропущене слово: To jest liczba ___. (шість)", "Fill in the missing word: To jest liczba ___. (six)", + "sześć", "first_letter", "s", 13), + ("a1_numbers_time_t14", None, "topic_test", "production", "numbers_tens", 3, + "Wpisz brakujące słowo: Mam ___ lat. (двадцать один)", "Вставьте пропущенное слово: Mam ___ lat. (двадцать один)", "Вставте пропущене слово: Mam ___ lat. (двадцять один)", "Fill in the missing word: Mam ___ lat. (twenty-one)", + "dwadzieścia jeden", "first_letter", "d", 14), + ("a1_numbers_time_t15", None, "topic_test", "production", "time_telling", 2, + "Wpisz brakujące słowo: Jest ___. (четвёртый час)", "Вставьте пропущенное слово: Jest ___. (четвёртый час)", "Вставте пропущене слово: Jest ___. (четверта година)", "Fill in the missing word: Jest ___. (four o'clock)", + "czwarta", "first_letter", "c", 15), + ("a1_numbers_time_t16", None, "topic_test", "production", "time_telling", 3, + "Wpisz brakujące słowo: Jest ___ do trzeciej. (половина)", "Вставьте пропущенное слово: Jest ___ do trzeciej. (половина)", "Вставте пропущене слово: Jest ___ do trzeciej. (половина)", "Fill in the missing word: Jest ___ do trzeciej. (half)", + "wpół", "first_letter", "w", 16), + ("a1_numbers_time_t17", None, "topic_test", "production", "time_expressions", 1, + "Wpisz brakujące słowo: Śpię ___. (ночью)", "Вставьте пропущенное слово: Śpię ___. (ночью)", "Вставте пропущене слово: Śpię ___. (вночі)", "Fill in the missing word: Śpię ___. (at night)", + "w nocy", "first_letter", "w", 17), + ("a1_numbers_time_t18", None, "topic_test", "production", "days_weekdays", 3, + "Wpisz brakujące słowo: W ___ odpoczywam. (воскресенье, винительный)", "Вставьте пропущенное слово: W ___ odpoczywam. (воскресенье, винительный)", "Вставте пропущене слово: W ___ odpoczywam. (неділя, знахідний)", "Fill in the missing word: W ___ odpoczywam. (Sunday, accusative)", + "niedzielę", "first_letter", "n", 18), + + ("a1_numbers_time_t19", None, "topic_test", "mixed", "numbers_tens", 3, + "Wybierz poprawne tłumaczenie: «Мне двадцать пять лет».", "Выберите правильный перевод: «Мне двадцать пять лет».", "Виберіть правильний переклад: «Мені двадцять п'ять років».", "Choose the correct translation: “I am twenty-five years old.”", + "A", None, None, 19), + ("a1_numbers_time_t20", None, "topic_test", "mixed", "time_expressions", 3, + "Wybierz poprawne tłumaczenie: «Урок начинается в девять утра в понедельник».", "Выберите правильный перевод: «Урок начинается в девять утра в понедельник».", "Виберіть правильний переклад: «Урок починається о дев'ятій ранку в понеділок».", "Choose the correct translation: “The lesson starts at nine in the morning on Monday.”", + "A", None, None, 20), + ] + + for q in test_questions_t6: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_numbers_time', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t6 = [ + ("a1_numbers_time_t01", "A", "cztery", "четыре", "чотири", "four", False, "wrong_word"), + ("a1_numbers_time_t01", "B", "pięć", "пять", "п'ять", "five", True, None), + ("a1_numbers_time_t01", "C", "sześć", "шесть", "шість", "six", False, "wrong_word"), + ("a1_numbers_time_t01", "D", "siedem", "семь", "сім", "seven", False, "wrong_word"), + + ("a1_numbers_time_t02", "A", "dziesięć", "десять", "десять", "ten", False, "wrong_word"), + ("a1_numbers_time_t02", "B", "piętnaście", "пятнадцать", "п'ятнадцять", "fifteen", True, None), + ("a1_numbers_time_t02", "C", "dwadzieścia", "двадцать", "двадцять", "twenty", False, "wrong_word"), + ("a1_numbers_time_t02", "D", "pięć", "пять", "п'ять", "five", False, "wrong_word"), + + ("a1_numbers_time_t03", "A", "czterdzieści", "сорок", "сорок", "forty", False, "wrong_word"), + ("a1_numbers_time_t03", "B", "pięćdziesiąt", "пятьдесят", "п'ятдесят", "fifty", True, None), + ("a1_numbers_time_t03", "C", "sześćdziesiąt", "шестьдесят", "шістдесят", "sixty", False, "wrong_word"), + ("a1_numbers_time_t03", "D", "sto", "сто", "сто", "hundred", False, "wrong_word"), + + ("a1_numbers_time_t04", "A", "Который час?", "Который час?", "Котра година?", "What time is it?", True, None), + ("a1_numbers_time_t04", "B", "Какой сегодня день?", "Какой сегодня день?", "Який сьогодні день?", "What day is it today?", False, "wrong_translation"), + ("a1_numbers_time_t04", "C", "Сколько тебе лет?", "Сколько тебе лет?", "Скільки тобі років?", "How old are you?", False, "wrong_translation"), + ("a1_numbers_time_t04", "D", "Где ты находишься?", "Где ты находишься?", "Де ти знаходишся?", "Where are you?", False, "wrong_translation"), + + ("a1_numbers_time_t05", "A", "Во сколько?", "Во сколько?", "О котрій?", "At what time?", True, None), + ("a1_numbers_time_t05", "B", "Который час?", "Который час?", "Котра година?", "What time is it?", False, "wrong_translation"), + ("a1_numbers_time_t05", "C", "Какой сегодня день?", "Какой сегодня день?", "Який сьогодні день?", "What day is it today?", False, "wrong_translation"), + ("a1_numbers_time_t05", "D", "Как долго?", "Как долго?", "Як довго?", "How long?", False, "wrong_translation"), + + ("a1_numbers_time_t06", "A", "środa", "среда", "середа", "Wednesday", True, None), + ("a1_numbers_time_t06", "B", "czwartek", "четверг", "четвер", "Thursday", False, "wrong_word"), + ("a1_numbers_time_t06", "C", "wtorek", "вторник", "вівторок", "Tuesday", False, "wrong_word"), + ("a1_numbers_time_t06", "D", "piątek", "пятница", "п'ятниця", "Friday", False, "wrong_word"), + + ("a1_numbers_time_t07", "A", "Mam dziewięć lat.", "Мне девять лет.", "Мені дев'ять років.", "I am nine years old.", True, None), + ("a1_numbers_time_t07", "B", "Mam dziewięć rok.", "Неправильная форма числа.", "Неправильна форма числа.", "Wrong number form.", False, "wrong_number"), + ("a1_numbers_time_t07", "C", "Jestem dziewięć lat.", "Я девять лет.", "Я дев'ять років.", "I am nine years. (wrong construction)", False, "wrong_sentence_type"), + ("a1_numbers_time_t07", "D", "Mam dziesięć lat.", "Мне десять лет. (неверное число)", "Мені десять років. (невірне число)", "I am ten years old. (wrong number)", False, "wrong_word"), + + ("a1_numbers_time_t08", "A", "Sto złotych.", "Сто злотых.", "Сто злотих.", "A hundred zloty.", True, None), + ("a1_numbers_time_t08", "B", "Dziesięć złotych.", "Десять злотых. (неверное число)", "Десять злотих. (невірне число)", "Ten zloty. (wrong number)", False, "wrong_word"), + ("a1_numbers_time_t08", "C", "Tysiąc złotych.", "Тысяча злотых. (неверное число)", "Тисяча злотих. (невірне число)", "A thousand zloty. (wrong number)", False, "wrong_word"), + ("a1_numbers_time_t08", "D", "Sto lat.", "Сто лет. (неверная единица)", "Сто років. (невірна одиниця)", "A hundred years. (wrong unit)", False, "wrong_word"), + + ("a1_numbers_time_t09", "A", "Jest szósta.", "Шесть часов.", "Шоста година.", "It's six o'clock.", True, None), + ("a1_numbers_time_t09", "B", "Jest szósty.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_numbers_time_t09", "C", "Jest sześć.", "Просто число, не время.", "Просто число, не час.", "Just a number, not a time form.", False, "wrong_word"), + ("a1_numbers_time_t09", "D", "Jest siódma.", "Семь часов. (неверное время)", "Сьома година. (невірний час)", "It's seven o'clock. (wrong time)", False, "wrong_context"), + + ("a1_numbers_time_t10", "A", "Jest wpół do piątej.", "Половина пятого.", "Пів на п'яту.", "It's half past four.", True, None), + ("a1_numbers_time_t10", "B", "Jest wpół do czwartej.", "Половина четвёртого. (неверное время)", "Пів на четверту. (невірний час)", "It's half past three. (wrong time)", False, "wrong_context"), + ("a1_numbers_time_t10", "C", "Jest kwadrans po czwartej.", "Четверть пятого. (неверное время)", "Чверть на п'яту. (невірний час)", "It's a quarter past four. (wrong time)", False, "wrong_context"), + ("a1_numbers_time_t10", "D", "Jest czwarta.", "Четыре часа. (неверное время)", "Четверта година. (невірний час)", "It's four o'clock. (wrong time)", False, "wrong_context"), + + ("a1_numbers_time_t11", "A", "Lekcja zaczyna się o ósmej.", "Урок начинается в восемь.", "Урок починається о восьмій.", "The lesson starts at eight.", True, None), + ("a1_numbers_time_t11", "B", "Lekcja zaczyna ósmej.", "Пропущен предлог.", "Пропущено прийменник.", "Missing preposition.", False, "wrong_sentence_type"), + ("a1_numbers_time_t11", "C", "Lekcja jest o ósmej.", "Неправильный глагол.", "Неправильне дієслово.", "Wrong verb.", False, "wrong_word"), + ("a1_numbers_time_t11", "D", "Lekcja zaczyna się o dziewiątej.", "Урок начинается в девять. (неверное время)", "Урок починається о дев'ятій. (невірний час)", "The lesson starts at nine. (wrong time)", False, "wrong_context"), + + ("a1_numbers_time_t12", "A", "We wtorek mam lekcję.", "Во вторник у меня урок.", "У вівторок у мене урок.", "On Tuesday I have a lesson.", True, None), + ("a1_numbers_time_t12", "B", "W wtorek mam lekcję.", "Неправильная форма предлога.", "Неправильна форма прийменника.", "Wrong preposition form.", False, "wrong_word"), + ("a1_numbers_time_t12", "C", "We wtorku mam lekcję.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_numbers_time_t12", "D", "Mam lekcję wtorek.", "Пропущен предлог.", "Пропущено прийменник.", "Missing preposition.", False, "wrong_sentence_type"), + + ("a1_numbers_time_t19", "A", "Mam dwadzieścia pięć lat.", "Мне двадцать пять лет.", "Мені двадцять п'ять років.", "I am twenty-five years old.", True, None), + ("a1_numbers_time_t19", "B", "Mam dwadzieścia pięć rok.", "Неправильная форма числа.", "Неправильна форма числа.", "Wrong number form.", False, "wrong_number"), + ("a1_numbers_time_t19", "C", "Jestem dwadzieścia pięć lat.", "Я двадцать пять лет.", "Я двадцять п'ять років.", "I am twenty-five years. (wrong construction)", False, "wrong_sentence_type"), + ("a1_numbers_time_t19", "D", "Mam piętnaście lat.", "Мне пятнадцать лет. (неверное число)", "Мені п'ятнадцять років. (невірне число)", "I am fifteen years old. (wrong number)", False, "wrong_word"), + + ("a1_numbers_time_t20", "A", "Lekcja zaczyna się o dziewiątej rano w poniedziałek.", "Урок начинается в девять утра в понедельник.", "Урок починається о дев'ятій ранку в понеділок.", "The lesson starts at nine in the morning on Monday.", True, None), + ("a1_numbers_time_t20", "B", "Lekcja zaczyna się o dziewiątej wieczorem w poniedziałek.", "Неверная часть суток.", "Невірна частина доби.", "Wrong time of day.", False, "wrong_context"), + ("a1_numbers_time_t20", "C", "Lekcja zaczyna się o dziewiątej rano we wtorek.", "Неверный день недели.", "Невірний день тижня.", "Wrong day of the week.", False, "wrong_context"), + ("a1_numbers_time_t20", "D", "Lekcja jest dziewiątej rano poniedziałek.", "Пропущены предлоги.", "Пропущено прийменники.", "Missing prepositions.", False, "wrong_sentence_type"), + ] + + for opt in test_options_t6: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # ==================== ТЕМА 7: ЦВЕТА И ОДЕЖДА ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_colors_clothes', 'A1', 7, + 'Kolory i ubrania', + 'Цвета и одежда', + 'Кольори та одяг', + 'Colors and Clothes') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t7 = [ + ("a1_colors_clothes_l01", 1, "colors_basic", "Podstawowe kolory", "Основные цвета", "Основні кольори", "Basic colors", + "Podstawowe kolory to: czerwony, niebieski, żółty, zielony, czarny, biały. „Kolor” jest rodzaju męskiego. Na razie używamy kolorów w formie męskiej (kończącej się na -y lub -i), tak jak w słowie „kolor”.", + "Основные цвета: czerwony (красный), niebieski (синий), żółty (жёлтый), zielony (зелёный), czarny (чёрный), biały (белый). „Kolor” (цвет) мужского рода. Пока используем цвета в форме мужского рода (окончание -y или -i), как в слове „kolor”.", + "Основні кольори: czerwony (червоний), niebieski (синій), żółty (жовтий), zielony (зелений), czarny (чорний), biały (білий). „Kolor” (колір) чоловічого роду. Поки використовуємо кольори у формі чоловічого роду (закінчення -y або -i), як у слові „kolor”.", + "Basic colors: czerwony (red), niebieski (blue), żółty (yellow), zielony (green), czarny (black), biały (white). „Kolor” (color) is masculine. For now we use colors in the masculine form (ending in -y or -i), like the word „kolor” itself."), + + ("a1_colors_clothes_l02", 2, "colors_basic", "Więcej kolorów", "Больше цветов", "Більше кольорів", "More colors", + "Więcej kolorów: różowy, brązowy, szary, pomarańczowy, fioletowy. Te słowa też są w formie męskiej.", + "Больше цветов: różowy (розовый), brązowy (коричневый), szary (серый), pomarańczowy (оранжевый), fioletowy (фиолетовый). Эти слова тоже в форме мужского рода.", + "Більше кольорів: różowy (рожевий), brązowy (коричневий), szary (сірий), pomarańczowy (помаранчевий), fioletowy (фіолетовий). Ці слова теж у формі чоловічого роду.", + "More colors: różowy (pink), brązowy (brown), szary (grey), pomarańczowy (orange), fioletowy (purple). These words are also in the masculine form."), + + ("a1_colors_clothes_l03", 3, "colors_agreement", "Kolor pasuje do rodzaju", "Цвет согласуется с родом", "Колір узгоджується з родом", "Color matches the gender", + "Przymiotniki-kolory zmieniają końcówkę zależnie od rodzaju rzeczownika: rodzaj męski -y/-i (czerwony sweter), rodzaj żeński -a (czerwona sukienka), rodzaj nijaki -e (czerwone ubranie).", + "Прилагательные-цвета меняют окончание в зависимости от рода существительного: мужской род -y/-i (czerwony sweter — красный свитер), женский род -a (czerwona sukienka — красное платье), средний род -e (czerwone ubranie — красная одежда).", + "Прикметники-кольори змінюють закінчення залежно від роду іменника: чоловічий рід -y/-i (czerwony sweter — червоний светр), жіночий рід -a (czerwona sukienka — червона сукня), середній рід -e (czerwone ubranie — червоний одяг).", + "Color adjectives change their ending depending on the noun's gender: masculine -y/-i (czerwony sweter — red sweater), feminine -a (czerwona sukienka — red dress), neuter -e (czerwone ubranie — red garment)."), + + ("a1_colors_clothes_l04", 4, "colors_agreement", "Kolor w liczbie mnogiej", "Цвет во множественном числе", "Колір у множині", "Color in the plural", + "W liczbie mnogiej (dla rzeczowników niemęskoosobowych) przymiotnik-kolor ma końcówkę -e, tak samo jak w rodzaju nijakim: czerwone buty, niebieskie spodnie, białe skarpetki.", + "Во множественном числе (для неличных существительных) прилагательное-цвет имеет окончание -e, так же как в среднем роде: czerwone buty (красные ботинки), niebieskie spodnie (синие брюки), białe skarpetki (белые носки).", + "У множині (для неособових іменників) прикметник-колір має закінчення -e, так само як у середньому роді: czerwone buty (червоні черевики), niebieskie spodnie (сині штани), białe skarpetki (білі шкарпетки).", + "In the plural (for non-personal nouns), the color adjective has the ending -e, the same as in the neuter: czerwone buty (red shoes), niebieskie spodnie (blue trousers), białe skarpetki (white socks)."), + + ("a1_colors_clothes_l05", 5, "clothing_basic", "Podstawowe ubrania", "Основная одежда", "Основний одяг", "Basic clothing", + "Podstawowe ubrania: sweter (rodzaj męski), sukienka (rodzaj żeński), spodnie (słowo tylko w liczbie mnogiej, jak „drzwi”), koszula (rodzaj żeński), buty (liczba mnoga od „but”, rodzaj męski).", + "Основная одежда: sweter (свитер, мужской род), sukienka (платье, женский род), spodnie (брюки, слово только во множественном числе, как „drzwi”), koszula (рубашка, женский род), buty (ботинки, множественное число от „but”, мужской род).", + "Основний одяг: sweter (светр, чоловічий рід), sukienka (сукня, жіночий рід), spodnie (штани, слово тільки у множині, як „drzwi”), koszula (сорочка, жіночий рід), buty (взуття, множина від „but”, чоловічий рід).", + "Basic clothing: sweter (sweater, masculine), sukienka (dress, feminine), spodnie (trousers, a word used only in the plural, like „drzwi”), koszula (shirt, feminine), buty (shoes, plural of „but”, masculine)."), + + ("a1_colors_clothes_l06", 6, "clothing_basic", "Więcej ubrań", "Больше одежды", "Більше одягу", "More clothing", + "Więcej ubrań: kurtka (rodzaj żeński), czapka (rodzaj żeński), szalik (rodzaj męski), rękawiczki (liczba mnoga, rodzaj żeński), skarpetki (liczba mnoga, rodzaj żeński).", + "Больше одежды: kurtka (куртка, женский род), czapka (шапка, женский род), szalik (шарф, мужской род), rękawiczki (перчатки, множественное число, женский род), skarpetki (носки, множественное число, женский род).", + "Більше одягу: kurtka (куртка, жіночий рід), czapka (шапка, жіночий рід), szalik (шарф, чоловічий рід), rękawiczki (рукавички, множина, жіночий рід), skarpetki (шкарпетки, множина, жіночий рід).", + "More clothing: kurtka (jacket, feminine), czapka (cap, feminine), szalik (scarf, masculine), rękawiczki (gloves, plural, feminine), skarpetki (socks, plural, feminine)."), + + ("a1_colors_clothes_l07", 7, "clothing_wearing", "Noszę + biernik", "Ношу + винительный падеж", "Ношу + знахідний відмінок", "Noszę + accusative", + "Czasownik „nosić” (ja noszę, ty nosisz, on/ona nosi) łączy się z biernikiem: noszę sweter (bez zmiany), noszę sukienkę (sukienka → sukienkę), noszę spodnie (bez zmiany, liczba mnoga).", + "Глагол „nosić” (носить: ja noszę, ty nosisz, on/ona nosi) требует винительного падежа: noszę sweter (без изменений), noszę sukienkę (sukienka → sukienkę), noszę spodnie (без изменений, множественное число).", + "Дієслово „nosić” (носити: ja noszę, ty nosisz, on/ona nosi) вимагає знахідного відмінка: noszę sweter (без змін), noszę sukienkę (sukienka → sukienkę), noszę spodnie (без змін, множина).", + "The verb „nosić” (to wear: ja noszę, ty nosisz, on/ona nosi) takes the accusative: noszę sweter (unchanged), noszę sukienkę (sukienka → sukienkę), noszę spodnie (unchanged, plural)."), + + ("a1_colors_clothes_l08", 8, "clothing_wearing", "Kolorowe ubranie w bierniku", "Цветная одежда в винительном падеже", "Кольоровий одяг у знахідному відмінку", "Colored clothing in the accusative", + "Gdy łączymy kolor z ubraniem w bierniku: rodzaj żeński — przymiotnik dostaje końcówkę -ą (mam na sobie czerwoną sukienkę), rodzaj męski nieżywotny i liczba mnoga — bez zmiany (mam na sobie niebieski sweter, mam na sobie czarne buty).", + "Когда соединяем цвет с одеждой в винительном падеже: женский род — прилагательное получает окончание -ą (mam na sobie czerwoną sukienkę = на мне красное платье), мужской неодушевлённый и множественное число — без изменений (mam na sobie niebieski sweter, mam na sobie czarne buty).", + "Коли поєднуємо колір з одягом у знахідному відмінку: жіночий рід — прикметник отримує закінчення -ą (mam na sobie czerwoną sukienkę = на мені червона сукня), чоловічий неістотний і множина — без змін (mam na sobie niebieski sweter, mam na sobie czarne buty).", + "When combining a color with clothing in the accusative: feminine — the adjective gets the ending -ą (mam na sobie czerwoną sukienkę = I'm wearing a red dress), masculine inanimate and plural — unchanged (mam na sobie niebieski sweter, mam na sobie czarne buty)."), + + ("a1_colors_clothes_l09", 9, "color_description", "Jakiego koloru jest...?", "Какого цвета...?", "Якого кольору...?", "What color is...?", + "Pytamy „Jakiego koloru jest...?” (dosłownie: jakiego koloru — dopełniacz), a odpowiadamy zdaniem z „jest” i przymiotnikiem w mianowniku, dopasowanym do rodzaju: Jakiego koloru jest twoja kurtka? Ona jest niebieska.", + "Спрашиваем „Jakiego koloru jest...?” (дословно: какого цвета — родительный падеж), а отвечаем предложением с „jest” и прилагательным в именительном падеже, согласованным по роду: Jakiego koloru jest twoja kurtka? Ona jest niebieska. (Какого цвета твоя куртка? Она синяя.)", + "Запитуємо „Jakiego koloru jest...?” (дослівно: якого кольору — родовий відмінок), а відповідаємо реченням з „jest” і прикметником у називному відмінку, узгодженим за родом: Jakiego koloru jest twoja kurtka? Ona jest niebieska. (Якого кольору твоя куртка? Вона синя.)", + "We ask „Jakiego koloru jest...?” (literally: of what color — genitive), and we answer with a sentence using „jest” and an adjective in the nominative, agreeing in gender: Jakiego koloru jest twoja kurtka? Ona jest niebieska. (What color is your jacket? It is blue.)"), + + ("a1_colors_clothes_l10", 10, "color_description", "Opisuję swój strój", "Описываю свой наряд", "Описую свій одяг", "Describing my outfit", + "Żeby opisać cały strój, łączymy kilka ubrań i kolorów w jednym zdaniu za pomocą „i”: Mam na sobie niebieską sukienkę i czarne buty.", + "Чтобы описать весь наряд, соединяем несколько предметов одежды и цветов в одном предложении с помощью „i” (и): Mam na sobie niebieską sukienkę i czarne buty. (На мне синее платье и чёрные ботинки.)", + "Щоб описати весь одяг, поєднуємо кілька речей і кольорів в одному реченні за допомогою „i” (і): Mam na sobie niebieską sukienkę i czarne buty. (На мені синя сукня і чорні черевики.)", + "To describe a whole outfit, we combine several clothing items and colors in one sentence using „i” (and): Mam na sobie niebieską sukienkę i czarne buty. (I'm wearing a blue dress and black shoes.)"), + ] + + for lesson in lessons_t7: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_colors_clothes', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t7 = [ + ("a1_colors_clothes_l01", 1, "Mam czerwony samochód.", "У меня красная машина.", "У мене червоний автомобіль.", "I have a red car."), + ("a1_colors_clothes_l01", 2, "Kot jest czarny.", "Кот чёрный.", "Кіт чорний.", "The cat is black."), + ("a1_colors_clothes_l01", 3, "Banan jest żółty.", "Банан жёлтый.", "Банан жовтий.", "The banana is yellow."), + + ("a1_colors_clothes_l02", 1, "Mam różowy plecak.", "У меня розовый рюкзак.", "У мене рожевий рюкзак.", "I have a pink backpack."), + ("a1_colors_clothes_l02", 2, "Ten stół jest brązowy.", "Этот стол коричневый.", "Цей стіл коричневий.", "This table is brown."), + ("a1_colors_clothes_l02", 3, "Kot jest szary.", "Кот серый.", "Кіт сірий.", "The cat is grey."), + + ("a1_colors_clothes_l03", 1, "Mam czerwony sweter.", "У меня красный свитер.", "У мене червоний светр.", "I have a red sweater."), + ("a1_colors_clothes_l03", 2, "Ta sukienka jest czerwona.", "Это платье красное.", "Ця сукня червона.", "This dress is red."), + ("a1_colors_clothes_l03", 3, "To ubranie jest czerwone.", "Эта одежда красная.", "Цей одяг червоний.", "This garment is red."), + + ("a1_colors_clothes_l04", 1, "Mam czerwone buty.", "У меня красные ботинки.", "У мене червоні черевики.", "I have red shoes."), + ("a1_colors_clothes_l04", 2, "Te spodnie są niebieskie.", "Эти брюки синие.", "Ці штани сині.", "These trousers are blue."), + ("a1_colors_clothes_l04", 3, "Skarpetki są białe.", "Носки белые.", "Шкарпетки білі.", "The socks are white."), + + ("a1_colors_clothes_l05", 1, "Mam nowy sweter.", "У меня новый свитер.", "У мене новий светр.", "I have a new sweater."), + ("a1_colors_clothes_l05", 2, "Sukienka jest w szafie.", "Платье в шкафу.", "Сукня в шафі.", "The dress is in the wardrobe."), + ("a1_colors_clothes_l05", 3, "Spodnie są na krześle.", "Брюки на стуле.", "Штани на стільці.", "The trousers are on the chair."), + + ("a1_colors_clothes_l06", 1, "Kurtka jest w szafie.", "Куртка в шкафу.", "Куртка в шафі.", "The jacket is in the wardrobe."), + ("a1_colors_clothes_l06", 2, "Czapka jest na stole.", "Шапка на столе.", "Шапка на столі.", "The cap is on the table."), + ("a1_colors_clothes_l06", 3, "Rękawiczki są ciepłe.", "Перчатки тёплые.", "Рукавички теплі.", "The gloves are warm."), + + ("a1_colors_clothes_l07", 1, "Noszę sweter.", "Я ношу свитер.", "Я ношу светр.", "I wear a sweater."), + ("a1_colors_clothes_l07", 2, "Ona nosi sukienkę.", "Она носит платье.", "Вона носить сукню.", "She wears a dress."), + ("a1_colors_clothes_l07", 3, "Dzisiaj noszę spodnie.", "Сегодня я ношу брюки.", "Сьогодні я ношу штани.", "Today I'm wearing trousers."), + + ("a1_colors_clothes_l08", 1, "Mam na sobie niebieski sweter.", "На мне синий свитер.", "На мені синій светр.", "I'm wearing a blue sweater."), + ("a1_colors_clothes_l08", 2, "Mam na sobie czerwoną sukienkę.", "На мне красное платье.", "На мені червона сукня.", "I'm wearing a red dress."), + ("a1_colors_clothes_l08", 3, "Mam na sobie czarne buty.", "На мне чёрные ботинки.", "На мені чорні черевики.", "I'm wearing black shoes."), + + ("a1_colors_clothes_l09", 1, "Jakiego koloru jest twoja kurtka?", "Какого цвета твоя куртка?", "Якого кольору твоя куртка?", "What color is your jacket?"), + ("a1_colors_clothes_l09", 2, "Ona jest niebieska.", "Она синяя.", "Вона синя.", "It is blue."), + ("a1_colors_clothes_l09", 3, "Jakiego koloru są twoje buty?", "Какого цвета твои ботинки?", "Якого кольору твої черевики?", "What color are your shoes?"), + + ("a1_colors_clothes_l10", 1, "Mam na sobie niebieską sukienkę i czarne buty.", "На мне синее платье и чёрные ботинки.", "На мені синя сукня і чорні черевики.", "I'm wearing a blue dress and black shoes."), + ("a1_colors_clothes_l10", 2, "Noszę zielony sweter i szare spodnie.", "Я ношу зелёный свитер и серые брюки.", "Я ношу зелений светр і сірі штани.", "I'm wearing a green sweater and grey trousers."), + ("a1_colors_clothes_l10", 3, "Mam czerwoną czapkę i białe rękawiczki.", "У меня красная шапка и белые перчатки.", "У мене червона шапка і білі рукавички.", "I have a red cap and white gloves."), + ] + + for ex in examples_t7: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t7 = [ + # L01 — colors_basic (difficulty 1) + ("a1_colors_clothes_l01_q1", "a1_colors_clothes_l01", "lesson_practice", "recognition", "colors_basic", 1, + "Jak po polsku „красный”?", "Как по-польски «красный»?", "Як польською «червоний»?", "How do you say “red” in Polish?", + "B", None, None), + ("a1_colors_clothes_l01_q2", "a1_colors_clothes_l01", "lesson_practice", "production", "colors_basic", 1, + "Wpisz brakujące słowo: Kot jest ___. (чёрный)", "Вставьте пропущенное слово: Kot jest ___. (чёрный)", "Вставте пропущене слово: Kot jest ___. (чорний)", "Fill in the missing word: Kot jest ___. (black)", + "czarny", "first_letter", "c"), + ("a1_colors_clothes_l01_q3", "a1_colors_clothes_l01", "lesson_practice", "application", "colors_basic", 1, + "Widzisz banana. Jakiego jest koloru?", "Ты видишь банан. Какого он цвета?", "Ти бачиш банан. Якого він кольору?", "You see a banana. What color is it?", + "A", None, None), + + # L02 — colors_basic (difficulty 1) + ("a1_colors_clothes_l02_q1", "a1_colors_clothes_l02", "lesson_practice", "recognition", "colors_basic", 1, + "Jak po polsku „розовый”?", "Как по-польски «розовый»?", "Як польською «рожевий»?", "How do you say “pink” in Polish?", + "B", None, None), + ("a1_colors_clothes_l02_q2", "a1_colors_clothes_l02", "lesson_practice", "production", "colors_basic", 1, + "Wpisz brakujące słowo: Ten stół jest ___. (коричневый)", "Вставьте пропущенное слово: Ten stół jest ___. (коричневый)", "Вставте пропущене слово: Ten stół jest ___. (коричневий)", "Fill in the missing word: Ten stół jest ___. (brown)", + "brązowy", "first_letter", "b"), + ("a1_colors_clothes_l02_q3", "a1_colors_clothes_l02", "lesson_practice", "application", "colors_basic", 1, + "Widzisz pomarańczę. Jakiego jest koloru?", "Ты видишь апельсин. Какого он цвета?", "Ти бачиш апельсин. Якого він кольору?", "You see an orange. What color is it?", + "A", None, None), + + # L03 — colors_agreement (difficulty 1) + ("a1_colors_clothes_l03_q1", "a1_colors_clothes_l03", "lesson_practice", "recognition", "colors_agreement", 1, + "Wybierz poprawną formę: Ta sukienka jest ___. (czerwony)", "Выберите правильную форму: Ta sukienka jest ___. (czerwony)", "Виберіть правильну форму: Ta sukienka jest ___. (czerwony)", "Choose the correct form: Ta sukienka jest ___. (czerwony)", + "B", None, None), + ("a1_colors_clothes_l03_q2", "a1_colors_clothes_l03", "lesson_practice", "production", "colors_agreement", 1, + "Wpisz brakujące słowo: To ubranie jest ___. (czerwony, средний род)", "Вставьте пропущенное слово: To ubranie jest ___. (czerwony, средний род)", "Вставте пропущене слово: To ubranie jest ___. (czerwony, середній рід)", "Fill in the missing word: To ubranie jest ___. (czerwony, neuter)", + "czerwone", "first_letter", "c"), + ("a1_colors_clothes_l03_q3", "a1_colors_clothes_l03", "lesson_practice", "application", "colors_agreement", 1, + "Opisujesz sukienkę, która jest czerwona. Co powiesz?", "Ты описываешь платье, которое красное. Что ты скажешь?", "Ти описуєш сукню, яка червона. Що ти скажеш?", "You're describing a dress that is red. What do you say?", + "A", None, None), + + # L04 — colors_agreement (difficulty 1) + ("a1_colors_clothes_l04_q1", "a1_colors_clothes_l04", "lesson_practice", "recognition", "colors_agreement", 1, + "Wybierz poprawną formę: Te buty są ___. (czerwony)", "Выберите правильную форму: Te buty są ___. (czerwony)", "Виберіть правильну форму: Te buty są ___. (czerwony)", "Choose the correct form: Te buty są ___. (czerwony)", + "C", None, None), + ("a1_colors_clothes_l04_q2", "a1_colors_clothes_l04", "lesson_practice", "production", "colors_agreement", 1, + "Wpisz brakujące słowo: Skarpetki są ___. (белый, множественное число)", "Вставьте пропущенное слово: Skarpetki są ___. (белый, множественное число)", "Вставте пропущене слово: Skarpetki są ___. (білий, множина)", "Fill in the missing word: Skarpetki są ___. (white, plural)", + "białe", "first_letter", "b"), + ("a1_colors_clothes_l04_q3", "a1_colors_clothes_l04", "lesson_practice", "application", "colors_agreement", 1, + "Masz niebieskie spodnie. Co powiesz o nich?", "У тебя синие брюки. Что ты о них скажешь?", "У тебе сині штани. Що ти про них скажеш?", "You have blue trousers. What do you say about them?", + "A", None, None), + + # L05 — clothing_basic (difficulty 2) + ("a1_colors_clothes_l05_q1", "a1_colors_clothes_l05", "lesson_practice", "recognition", "clothing_basic", 2, + "Jak po polsku „платье”?", "Как по-польски «платье»?", "Як польською «сукня»?", "How do you say “dress” in Polish?", + "B", None, None), + ("a1_colors_clothes_l05_q2", "a1_colors_clothes_l05", "lesson_practice", "production", "clothing_basic", 2, + "Wpisz brakujące słowo: To jest ___. (брюки)", "Вставьте пропущенное слово: To jest ___. (брюки)", "Вставте пропущене слово: To jest ___. (штани)", "Fill in the missing word: To jest ___. (trousers)", + "spodnie", "first_letter", "s"), + ("a1_colors_clothes_l05_q3", "a1_colors_clothes_l05", "lesson_practice", "application", "clothing_basic", 2, + "Jest zimno. Chcesz założyć coś ciepłego na górę. Co wybierzesz?", "Холодно. Ты хочешь надеть что-то тёплое сверху. Что ты выберешь?", "Холодно. Ти хочеш одягнути щось тепле зверху. Що ти виберешь?", "It's cold. You want to put on something warm on top. What do you choose?", + "A", None, None), + + # L06 — clothing_basic (difficulty 2) + ("a1_colors_clothes_l06_q1", "a1_colors_clothes_l06", "lesson_practice", "recognition", "clothing_basic", 2, + "Jak po polsku „шарф”?", "Как по-польски «шарф»?", "Як польською «шарф»?", "How do you say “scarf” in Polish?", + "C", None, None), + ("a1_colors_clothes_l06_q2", "a1_colors_clothes_l06", "lesson_practice", "production", "clothing_basic", 2, + "Wpisz brakujące słowo: To jest ___. (куртка)", "Вставьте пропущенное слово: To jest ___. (куртка)", "Вставте пропущене слово: To jest ___. (куртка)", "Fill in the missing word: To jest ___. (jacket)", + "kurtka", "first_letter", "k"), + ("a1_colors_clothes_l06_q3", "a1_colors_clothes_l06", "lesson_practice", "application", "clothing_basic", 2, + "Jest zimno na dworze. Co włożysz na ręce?", "На улице холодно. Что ты наденешь на руки?", "На вулиці холодно. Що ти вдягнеш на руки?", "It's cold outside. What do you put on your hands?", + "A", None, None), + + # L07 — clothing_wearing (difficulty 2) + ("a1_colors_clothes_l07_q1", "a1_colors_clothes_l07", "lesson_practice", "recognition", "clothing_wearing", 2, + "Wybierz poprawną formę: Noszę ___. (sukienka)", "Выберите правильную форму: Noszę ___. (sukienka)", "Виберіть правильну форму: Noszę ___. (sukienka)", "Choose the correct form: Noszę ___. (sukienka)", + "B", None, None), + ("a1_colors_clothes_l07_q2", "a1_colors_clothes_l07", "lesson_practice", "production", "clothing_wearing", 2, + "Wpisz brakujące słowo: Dzisiaj ___ spodnie. (ношу)", "Вставьте пропущенное слово: Dzisiaj ___ spodnie. (ношу)", "Вставте пропущене слово: Dzisiaj ___ spodnie. (ношу)", "Fill in the missing word: Dzisiaj ___ spodnie. (I wear)", + "noszę", "first_letter", "n"), + ("a1_colors_clothes_l07_q3", "a1_colors_clothes_l07", "lesson_practice", "application", "clothing_wearing", 2, + "Kolega pyta, co dzisiaj nosisz. Nosisz sweter. Co powiesz?", "Друг спрашивает, что ты сегодня носишь. Ты носишь свитер. Что ты скажешь?", "Друг питає, що ти сьогодні носиш. Ти носиш светр. Що ти скажеш?", "A friend asks what you're wearing today. You're wearing a sweater. What do you say?", + "A", None, None), + + # L08 — clothing_wearing (difficulty 2) + ("a1_colors_clothes_l08_q1", "a1_colors_clothes_l08", "lesson_practice", "recognition", "clothing_wearing", 2, + "Wybierz poprawną formę: Mam na sobie ___ sukienkę. (czerwony)", "Выберите правильную форму: Mam na sobie ___ sukienkę. (czerwony)", "Виберіть правильну форму: Mam na sobie ___ sukienkę. (czerwony)", "Choose the correct form: Mam na sobie ___ sukienkę. (czerwony)", + "C", None, None), + ("a1_colors_clothes_l08_q2", "a1_colors_clothes_l08", "lesson_practice", "production", "clothing_wearing", 2, + "Wpisz brakujące słowo: Mam na sobie czarne ___. (ботинки)", "Вставьте пропущенное слово: Mam na sobie czarne ___. (ботинки)", "Вставте пропущене слово: Mam na sobie czarne ___. (черевики)", "Fill in the missing word: Mam na sobie czarne ___. (shoes)", + "buty", "first_letter", "b"), + ("a1_colors_clothes_l08_q3", "a1_colors_clothes_l08", "lesson_practice", "application", "clothing_wearing", 2, + "Masz na sobie niebieski sweter. Co powiesz?", "На тебе синий свитер. Что ты скажешь?", "На тобі синій светр. Що ти скажеш?", "You're wearing a blue sweater. What do you say?", + "A", None, None), + + # L09 — color_description (difficulty 3) + ("a1_colors_clothes_l09_q1", "a1_colors_clothes_l09", "lesson_practice", "recognition", "color_description", 3, + "Co znaczy „Jakiego koloru jest...?”", "Что означает «Jakiego koloru jest...?»", "Що означає «Jakiego koloru jest...?»", "What does “Jakiego koloru jest...?” mean?", + "A", None, None), + ("a1_colors_clothes_l09_q2", "a1_colors_clothes_l09", "lesson_practice", "production", "color_description", 3, + "Wpisz brakujące słowo: Jakiego koloru ___ twoja kurtka? (jest)", "Вставьте пропущенное слово: Jakiego koloru ___ twoja kurtka? (jest)", "Вставте пропущене слово: Jakiego koloru ___ twoja kurtka? (jest)", "Fill in the missing word: Jakiego koloru ___ twoja kurtka? (is)", + "jest", "first_letter", "j"), + ("a1_colors_clothes_l09_q3", "a1_colors_clothes_l09", "lesson_practice", "application", "color_description", 3, + "Kolega pyta „Jakiego koloru są twoje buty?” Twoje buty są czarne. Co powiesz?", "Друг спрашивает «Jakiego koloru są twoje buty?» Твои ботинки чёрные. Что ты скажешь?", "Друг питає «Jakiego koloru są twoje buty?» Твої черевики чорні. Що ти скажеш?", "A friend asks “Jakiego koloru są twoje buty?” Your shoes are black. What do you say?", + "A", None, None), + + # L10 — color_description (difficulty 3) + ("a1_colors_clothes_l10_q1", "a1_colors_clothes_l10", "lesson_practice", "recognition", "color_description", 3, + "Które zdanie poprawnie opisuje strój?", "Какое предложение правильно описывает наряд?", "Яке речення правильно описує одяг?", "Which sentence correctly describes an outfit?", + "B", None, None), + ("a1_colors_clothes_l10_q2", "a1_colors_clothes_l10", "lesson_practice", "production", "color_description", 3, + "Przetłumacz: «Я ношу зелёный свитер и серые брюки».", "Переведите: «Я ношу зелёный свитер и серые брюки».", "Перекладіть: «Я ношу зелений светр і сірі штани».", "Translate: “I'm wearing a green sweater and grey trousers.”", + "Noszę zielony sweter i szare spodnie", "first_letter", "N"), + ("a1_colors_clothes_l10_q3", "a1_colors_clothes_l10", "lesson_practice", "application", "color_description", 3, + "Chcesz opisać koledze swój strój: masz niebieską sukienkę i czarne buty. Jak zaczniesz zdanie?", "Ты хочешь описать другу свой наряд: у тебя синее платье и чёрные ботинки. Как ты начнёшь предложение?", "Ти хочеш описати другу свій одяг: у тебе синя сукня і чорні черевики. Як ти почнеш речення?", "You want to describe your outfit to a friend: you have a blue dress and black shoes. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t7: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_colors_clothes', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t7 = [ + # L01 + ("a1_colors_clothes_l01_q1", "A", "zielony", "зелёный", "зелений", "green", False, "wrong_word"), + ("a1_colors_clothes_l01_q1", "B", "czerwony", "красный", "червоний", "red", True, None), + ("a1_colors_clothes_l01_q1", "C", "żółty", "жёлтый", "жовтий", "yellow", False, "wrong_word"), + ("a1_colors_clothes_l01_q1", "D", "czarny", "чёрный", "чорний", "black", False, "wrong_word"), + + ("a1_colors_clothes_l01_q3", "A", "żółty", "жёлтый", "жовтий", "yellow", True, None), + ("a1_colors_clothes_l01_q3", "B", "czerwony", "красный", "червоний", "red", False, "wrong_context"), + ("a1_colors_clothes_l01_q3", "C", "niebieski", "синий", "синій", "blue", False, "wrong_context"), + ("a1_colors_clothes_l01_q3", "D", "czarny", "чёрный", "чорний", "black", False, "wrong_context"), + + # L02 + ("a1_colors_clothes_l02_q1", "A", "szary", "серый", "сірий", "grey", False, "wrong_word"), + ("a1_colors_clothes_l02_q1", "B", "różowy", "розовый", "рожевий", "pink", True, None), + ("a1_colors_clothes_l02_q1", "C", "brązowy", "коричневый", "коричневий", "brown", False, "wrong_word"), + ("a1_colors_clothes_l02_q1", "D", "fioletowy", "фиолетовый", "фіолетовий", "purple", False, "wrong_word"), + + ("a1_colors_clothes_l02_q3", "A", "pomarańczowy", "оранжевый", "помаранчевий", "orange", True, None), + ("a1_colors_clothes_l02_q3", "B", "różowy", "розовый", "рожевий", "pink", False, "wrong_context"), + ("a1_colors_clothes_l02_q3", "C", "fioletowy", "фиолетовый", "фіолетовий", "purple", False, "wrong_context"), + ("a1_colors_clothes_l02_q3", "D", "szary", "серый", "сірий", "grey", False, "wrong_context"), + + # L03 + ("a1_colors_clothes_l03_q1", "A", "czerwony", "красный (муж.)", "червоний (чол.)", "red (masc.)", False, "wrong_gender"), + ("a1_colors_clothes_l03_q1", "B", "czerwona", "красная (жен.)", "червона (жін.)", "red (fem.)", True, None), + ("a1_colors_clothes_l03_q1", "C", "czerwone", "красное (ср.)", "червоне (сер.)", "red (neut.)", False, "wrong_gender"), + ("a1_colors_clothes_l03_q1", "D", "czerwoną", "красную (вин.)", "червону (знах.)", "red (acc.)", False, "wrong_case"), + + ("a1_colors_clothes_l03_q3", "A", "Ta sukienka jest czerwona.", "Это платье красное.", "Ця сукня червона.", "This dress is red.", True, None), + ("a1_colors_clothes_l03_q3", "B", "Ta sukienka jest czerwony.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_l03_q3", "C", "To ubranie jest czerwona.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_l03_q3", "D", "Ten sweter jest czerwona.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + + # L04 + ("a1_colors_clothes_l04_q1", "A", "czerwony", "красный (ед. ч., муж.)", "червоний (одн., чол.)", "red (sg. masc.)", False, "wrong_number"), + ("a1_colors_clothes_l04_q1", "B", "czerwona", "красная (жен.)", "червона (жін.)", "red (fem.)", False, "wrong_gender"), + ("a1_colors_clothes_l04_q1", "C", "czerwone", "красные (мн. ч.)", "червоні (мн.)", "red (plural)", True, None), + ("a1_colors_clothes_l04_q1", "D", "czerwoną", "красную (вин.)", "червону (знах.)", "red (acc.)", False, "wrong_case"), + + ("a1_colors_clothes_l04_q3", "A", "Spodnie są niebieskie.", "Брюки синие.", "Штани сині.", "The trousers are blue.", True, None), + ("a1_colors_clothes_l04_q3", "B", "Spodnie są niebieski.", "Неправильное число.", "Неправильне число.", "Wrong number form.", False, "wrong_number"), + ("a1_colors_clothes_l04_q3", "C", "Spodnie są niebieska.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_l04_q3", "D", "Spodnie jest niebieskie.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + # L05 + ("a1_colors_clothes_l05_q1", "A", "sweter", "свитер", "светр", "sweater", False, "wrong_word"), + ("a1_colors_clothes_l05_q1", "B", "sukienka", "платье", "сукня", "dress", True, None), + ("a1_colors_clothes_l05_q1", "C", "koszula", "рубашка", "сорочка", "shirt", False, "wrong_word"), + ("a1_colors_clothes_l05_q1", "D", "kurtka", "куртка", "куртка", "jacket", False, "wrong_word"), + + ("a1_colors_clothes_l05_q3", "A", "sweter", "свитер", "светр", "sweater", True, None), + ("a1_colors_clothes_l05_q3", "B", "sukienka", "платье", "сукня", "dress", False, "wrong_context"), + ("a1_colors_clothes_l05_q3", "C", "spodnie", "брюки", "штани", "trousers", False, "wrong_context"), + ("a1_colors_clothes_l05_q3", "D", "buty", "ботинки", "черевики", "shoes", False, "wrong_context"), + + # L06 + ("a1_colors_clothes_l06_q1", "A", "czapka", "шапка", "шапка", "cap", False, "wrong_word"), + ("a1_colors_clothes_l06_q1", "B", "rękawiczki", "перчатки", "рукавички", "gloves", False, "wrong_word"), + ("a1_colors_clothes_l06_q1", "C", "szalik", "шарф", "шарф", "scarf", True, None), + ("a1_colors_clothes_l06_q1", "D", "skarpetki", "носки", "шкарпетки", "socks", False, "wrong_word"), + + ("a1_colors_clothes_l06_q3", "A", "rękawiczki", "перчатки", "рукавички", "gloves", True, None), + ("a1_colors_clothes_l06_q3", "B", "czapka", "шапка", "шапка", "cap", False, "wrong_context"), + ("a1_colors_clothes_l06_q3", "C", "szalik", "шарф", "шарф", "scarf", False, "wrong_context"), + ("a1_colors_clothes_l06_q3", "D", "skarpetki", "носки", "шкарпетки", "socks", False, "wrong_context"), + + # L07 + ("a1_colors_clothes_l07_q1", "A", "sukienka", "платье (им.)", "сукня (наз.)", "dress (nom.)", False, "wrong_case"), + ("a1_colors_clothes_l07_q1", "B", "sukienkę", "платье (вин.)", "сукню (знах.)", "dress (acc.)", True, None), + ("a1_colors_clothes_l07_q1", "C", "sukience", "платье (местн.)", "сукня (місц.)", "dress (loc.)", False, "wrong_case"), + ("a1_colors_clothes_l07_q1", "D", "sukienką", "платье (тв.)", "сукня (ор.)", "dress (instr.)", False, "wrong_case"), + + ("a1_colors_clothes_l07_q3", "A", "Noszę sweter.", "Я ношу свитер.", "Я ношу светр.", "I wear a sweater.", True, None), + ("a1_colors_clothes_l07_q3", "B", "Noszę swetra.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_colors_clothes_l07_q3", "C", "Jestem sweter.", "Я свитер.", "Я светр.", "I am a sweater.", False, "wrong_sentence_type"), + ("a1_colors_clothes_l07_q3", "D", "Mam sweter nosić.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + # L08 + ("a1_colors_clothes_l08_q1", "A", "czerwony", "красный (муж.)", "червоний (чол.)", "red (masc.)", False, "wrong_gender"), + ("a1_colors_clothes_l08_q1", "B", "czerwona", "красная (им.)", "червона (наз.)", "red (nom.)", False, "wrong_case"), + ("a1_colors_clothes_l08_q1", "C", "czerwoną", "красную (вин.)", "червону (знах.)", "red (acc.)", True, None), + ("a1_colors_clothes_l08_q1", "D", "czerwone", "красное (ср.)", "червоне (сер.)", "red (neut.)", False, "wrong_gender"), + + ("a1_colors_clothes_l08_q3", "A", "Mam na sobie niebieski sweter.", "На мне синий свитер.", "На мені синій светр.", "I'm wearing a blue sweater.", True, None), + ("a1_colors_clothes_l08_q3", "B", "Mam na sobie niebieską sweter.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_l08_q3", "C", "Mam na sobie niebieskie sweter.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_l08_q3", "D", "Jestem niebieski sweter.", "Я синий свитер.", "Я синій светр.", "I am a blue sweater.", False, "wrong_sentence_type"), + + # L09 + ("a1_colors_clothes_l09_q1", "A", "Какого цвета...?", "Какого цвета...?", "Якого кольору...?", "What color is...?", True, None), + ("a1_colors_clothes_l09_q1", "B", "Который час...?", "Который час...?", "Котра година...?", "What time is it...?", False, "wrong_translation"), + ("a1_colors_clothes_l09_q1", "C", "Сколько стоит...?", "Сколько стоит...?", "Скільки коштує...?", "How much does it cost...?", False, "wrong_translation"), + ("a1_colors_clothes_l09_q1", "D", "Где находится...?", "Где находится...?", "Де знаходиться...?", "Where is...?", False, "wrong_translation"), + + ("a1_colors_clothes_l09_q3", "A", "One są czarne.", "Они чёрные.", "Вони чорні.", "They are black.", True, None), + ("a1_colors_clothes_l09_q3", "B", "One jest czarne.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_colors_clothes_l09_q3", "C", "One są czarny.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_l09_q3", "D", "One są czarna.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + + # L10 + ("a1_colors_clothes_l10_q1", "A", "Mam na sobie niebieska sukienkę i czarne buty.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_colors_clothes_l10_q1", "B", "Mam na sobie niebieską sukienkę i czarne buty.", "На мне синее платье и чёрные ботинки.", "На мені синя сукня і чорні черевики.", "I'm wearing a blue dress and black shoes.", True, None), + ("a1_colors_clothes_l10_q1", "C", "Mam na sobie niebieski sukienkę i czarni buty.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_l10_q1", "D", "Jestem niebieska sukienka i czarne buty.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + ("a1_colors_clothes_l10_q3", "A", "Mam na sobie niebieską sukienkę i czarne buty.", "На мне синее платье и чёрные ботинки.", "На мені синя сукня і чорні черевики.", "I'm wearing a blue dress and black shoes.", True, None), + ("a1_colors_clothes_l10_q3", "B", "Ja sukienka i buty.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_colors_clothes_l10_q3", "C", "Jestem niebieska sukienka.", "Я синее платье.", "Я синя сукня.", "I am a blue dress.", False, "wrong_sentence_type"), + ("a1_colors_clothes_l10_q3", "D", "Mam na sobie niebieski sukienkę i czarny buty.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ] + + for opt in options_t7: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t7 = [ + ("a1_colors_clothes_t01", None, "topic_test", "recognition", "colors_basic", 1, + "Jak po polsku „красный”?", "Как по-польски «красный»?", "Як польською «червоний»?", "How do you say “red” in Polish?", + "B", None, None, 1), + ("a1_colors_clothes_t02", None, "topic_test", "recognition", "colors_basic", 1, + "Jak po polsku „розовый”?", "Как по-польски «розовый»?", "Як польською «рожевий»?", "How do you say “pink” in Polish?", + "B", None, None, 2), + ("a1_colors_clothes_t03", None, "topic_test", "recognition", "colors_agreement", 1, + "Wybierz poprawną formę: Ta sukienka jest ___. (czerwony)", "Выберите правильную форму: Ta sukienka jest ___. (czerwony)", "Виберіть правильну форму: Ta sukienka jest ___. (czerwony)", "Choose the correct form: Ta sukienka jest ___. (czerwony)", + "B", None, None, 3), + ("a1_colors_clothes_t04", None, "topic_test", "recognition", "clothing_basic", 2, + "Jak po polsku „платье”?", "Как по-польски «платье»?", "Як польською «сукня»?", "How do you say “dress” in Polish?", + "B", None, None, 4), + ("a1_colors_clothes_t05", None, "topic_test", "recognition", "clothing_wearing", 2, + "Wybierz poprawną formę: Noszę ___. (sukienka)", "Выберите правильную форму: Noszę ___. (sukienka)", "Виберіть правильну форму: Noszę ___. (sukienka)", "Choose the correct form: Noszę ___. (sukienka)", + "B", None, None, 5), + ("a1_colors_clothes_t06", None, "topic_test", "recognition", "color_description", 3, + "Co znaczy „Jakiego koloru jest...?”", "Что означает «Jakiego koloru jest...?»", "Що означає «Jakiego koloru jest...?»", "What does “Jakiego koloru jest...?” mean?", + "A", None, None, 6), + + ("a1_colors_clothes_t07", None, "topic_test", "application", "colors_agreement", 1, + "Masz niebieskie spodnie. Co powiesz o nich?", "У тебя синие брюки. Что ты о них скажешь?", "У тебе сині штани. Що ти про них скажеш?", "You have blue trousers. What do you say about them?", + "A", None, None, 7), + ("a1_colors_clothes_t08", None, "topic_test", "application", "clothing_basic", 2, + "Jest zimno. Chcesz założyć coś ciepłego na górę. Co wybierzesz?", "Холодно. Ты хочешь надеть что-то тёплое сверху. Что ты выберешь?", "Холодно. Ти хочеш одягнути щось тепле зверху. Що ти виберешь?", "It's cold. You want to put on something warm on top. What do you choose?", + "A", None, None, 8), + ("a1_colors_clothes_t09", None, "topic_test", "application", "clothing_basic", 2, + "Jest zimno na dworze. Co włożysz na ręce?", "На улице холодно. Что ты наденешь на руки?", "На вулиці холодно. Що ти вдягнеш на руки?", "It's cold outside. What do you put on your hands?", + "A", None, None, 9), + ("a1_colors_clothes_t10", None, "topic_test", "application", "clothing_wearing", 2, + "Kolega pyta, co dzisiaj nosisz. Nosisz sweter. Co powiesz?", "Друг спрашивает, что ты сегодня носишь. Ты носишь свитер. Что ты скажешь?", "Друг питає, що ти сьогодні носиш. Ти носиш светр. Що ти скажеш?", "A friend asks what you're wearing today. You're wearing a sweater. What do you say?", + "A", None, None, 10), + ("a1_colors_clothes_t11", None, "topic_test", "application", "clothing_wearing", 2, + "Masz na sobie niebieski sweter. Co powiesz?", "На тебе синий свитер. Что ты скажешь?", "На тобі синій светр. Що ти скажеш?", "You're wearing a blue sweater. What do you say?", + "A", None, None, 11), + ("a1_colors_clothes_t12", None, "topic_test", "application", "color_description", 3, + "Kolega pyta „Jakiego koloru są twoje buty?” Twoje buty są czarne. Co powiesz?", "Друг спрашивает «Jakiego koloru są twoje buty?» Твои ботинки чёрные. Что ты скажешь?", "Друг питає «Jakiego koloru są twoje buty?» Твої черевики чорні. Що ти скажеш?", "A friend asks “Jakiego koloru są twoje buty?” Your shoes are black. What do you say?", + "A", None, None, 12), + + ("a1_colors_clothes_t13", None, "topic_test", "production", "colors_basic", 1, + "Wpisz brakujące słowo: Kot jest ___. (чёрный)", "Вставьте пропущенное слово: Kot jest ___. (чёрный)", "Вставте пропущене слово: Kot jest ___. (чорний)", "Fill in the missing word: Kot jest ___. (black)", + "czarny", "first_letter", "c", 13), + ("a1_colors_clothes_t14", None, "topic_test", "production", "colors_agreement", 1, + "Wpisz brakujące słowo: To ubranie jest ___. (czerwony, средний род)", "Вставьте пропущенное слово: To ubranie jest ___. (czerwony, средний род)", "Вставте пропущене слово: To ubranie jest ___. (czerwony, середній рід)", "Fill in the missing word: To ubranie jest ___. (czerwony, neuter)", + "czerwone", "first_letter", "c", 14), + ("a1_colors_clothes_t15", None, "topic_test", "production", "clothing_basic", 1, + "Wpisz brakujące słowo: To jest ___. (брюки)", "Вставьте пропущенное слово: To jest ___. (брюки)", "Вставте пропущене слово: To jest ___. (штани)", "Fill in the missing word: To jest ___. (trousers)", + "spodnie", "first_letter", "s", 15), + ("a1_colors_clothes_t16", None, "topic_test", "production", "clothing_wearing", 2, + "Wpisz brakujące słowo: Dzisiaj ___ spodnie. (ношу)", "Вставьте пропущенное слово: Dzisiaj ___ spodnie. (ношу)", "Вставте пропущене слово: Dzisiaj ___ spodnie. (ношу)", "Fill in the missing word: Dzisiaj ___ spodnie. (I wear)", + "noszę", "first_letter", "n", 16), + ("a1_colors_clothes_t17", None, "topic_test", "production", "color_description", 3, + "Wpisz brakujące słowo: Jakiego koloru ___ twoja kurtka? (jest)", "Вставьте пропущенное слово: Jakiego koloru ___ twoja kurtka? (jest)", "Вставте пропущене слово: Jakiego koloru ___ twoja kurtka? (jest)", "Fill in the missing word: Jakiego koloru ___ twoja kurtka? (is)", + "jest", "first_letter", "j", 17), + ("a1_colors_clothes_t18", None, "topic_test", "production", "color_description", 3, + "Przetłumacz: «Я ношу зелёный свитер и серые брюки».", "Переведите: «Я ношу зелёный свитер и серые брюки».", "Перекладіть: «Я ношу зелений светр і сірі штани».", "Translate: “I'm wearing a green sweater and grey trousers.”", + "Noszę zielony sweter i szare spodnie", "first_letter", "N", 18), + + ("a1_colors_clothes_t19", None, "topic_test", "mixed", "clothing_wearing", 3, + "Wybierz poprawne tłumaczenie: «На мне красное платье и чёрные ботинки».", "Выберите правильный перевод: «На мне красное платье и чёрные ботинки».", "Виберіть правильний переклад: «На мені червона сукня і чорні черевики».", "Choose the correct translation: “I'm wearing a red dress and black shoes.”", + "A", None, None, 19), + ("a1_colors_clothes_t20", None, "topic_test", "mixed", "color_description", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Какого цвета твоя куртка? — Она синяя.»", "Выберите правильный перевод диалога: «— Какого цвета твоя куртка? — Она синяя.»", "Виберіть правильний переклад діалогу: «— Якого кольору твоя куртка? — Вона синя.»", "Choose the correct translation of the dialogue: “— What color is your jacket? — It is blue.”", + "A", None, None, 20), + ] + + for q in test_questions_t7: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_colors_clothes', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t7 = [ + ("a1_colors_clothes_t01", "A", "zielony", "зелёный", "зелений", "green", False, "wrong_word"), + ("a1_colors_clothes_t01", "B", "czerwony", "красный", "червоний", "red", True, None), + ("a1_colors_clothes_t01", "C", "żółty", "жёлтый", "жовтий", "yellow", False, "wrong_word"), + ("a1_colors_clothes_t01", "D", "czarny", "чёрный", "чорний", "black", False, "wrong_word"), + + ("a1_colors_clothes_t02", "A", "szary", "серый", "сірий", "grey", False, "wrong_word"), + ("a1_colors_clothes_t02", "B", "różowy", "розовый", "рожевий", "pink", True, None), + ("a1_colors_clothes_t02", "C", "brązowy", "коричневый", "коричневий", "brown", False, "wrong_word"), + ("a1_colors_clothes_t02", "D", "fioletowy", "фиолетовый", "фіолетовий", "purple", False, "wrong_word"), + + ("a1_colors_clothes_t03", "A", "czerwony", "красный (муж.)", "червоний (чол.)", "red (masc.)", False, "wrong_gender"), + ("a1_colors_clothes_t03", "B", "czerwona", "красная (жен.)", "червона (жін.)", "red (fem.)", True, None), + ("a1_colors_clothes_t03", "C", "czerwone", "красное (ср.)", "червоне (сер.)", "red (neut.)", False, "wrong_gender"), + ("a1_colors_clothes_t03", "D", "czerwoną", "красную (вин.)", "червону (знах.)", "red (acc.)", False, "wrong_case"), + + ("a1_colors_clothes_t04", "A", "sweter", "свитер", "светр", "sweater", False, "wrong_word"), + ("a1_colors_clothes_t04", "B", "sukienka", "платье", "сукня", "dress", True, None), + ("a1_colors_clothes_t04", "C", "koszula", "рубашка", "сорочка", "shirt", False, "wrong_word"), + ("a1_colors_clothes_t04", "D", "kurtka", "куртка", "куртка", "jacket", False, "wrong_word"), + + ("a1_colors_clothes_t05", "A", "sukienka", "платье (им.)", "сукня (наз.)", "dress (nom.)", False, "wrong_case"), + ("a1_colors_clothes_t05", "B", "sukienkę", "платье (вин.)", "сукню (знах.)", "dress (acc.)", True, None), + ("a1_colors_clothes_t05", "C", "sukience", "платье (местн.)", "сукня (місц.)", "dress (loc.)", False, "wrong_case"), + ("a1_colors_clothes_t05", "D", "sukienką", "платье (тв.)", "сукня (ор.)", "dress (instr.)", False, "wrong_case"), + + ("a1_colors_clothes_t06", "A", "Какого цвета...?", "Какого цвета...?", "Якого кольору...?", "What color is...?", True, None), + ("a1_colors_clothes_t06", "B", "Который час...?", "Который час...?", "Котра година...?", "What time is it...?", False, "wrong_translation"), + ("a1_colors_clothes_t06", "C", "Сколько стоит...?", "Сколько стоит...?", "Скільки коштує...?", "How much does it cost...?", False, "wrong_translation"), + ("a1_colors_clothes_t06", "D", "Где находится...?", "Где находится...?", "Де знаходиться...?", "Where is...?", False, "wrong_translation"), + + ("a1_colors_clothes_t07", "A", "Spodnie są niebieskie.", "Брюки синие.", "Штани сині.", "The trousers are blue.", True, None), + ("a1_colors_clothes_t07", "B", "Spodnie są niebieski.", "Неправильное число.", "Неправильне число.", "Wrong number form.", False, "wrong_number"), + ("a1_colors_clothes_t07", "C", "Spodnie są niebieska.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_t07", "D", "Spodnie jest niebieskie.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + ("a1_colors_clothes_t08", "A", "sweter", "свитер", "светр", "sweater", True, None), + ("a1_colors_clothes_t08", "B", "sukienka", "платье", "сукня", "dress", False, "wrong_context"), + ("a1_colors_clothes_t08", "C", "spodnie", "брюки", "штани", "trousers", False, "wrong_context"), + ("a1_colors_clothes_t08", "D", "buty", "ботинки", "черевики", "shoes", False, "wrong_context"), + + ("a1_colors_clothes_t09", "A", "rękawiczki", "перчатки", "рукавички", "gloves", True, None), + ("a1_colors_clothes_t09", "B", "czapka", "шапка", "шапка", "cap", False, "wrong_context"), + ("a1_colors_clothes_t09", "C", "szalik", "шарф", "шарф", "scarf", False, "wrong_context"), + ("a1_colors_clothes_t09", "D", "skarpetki", "носки", "шкарпетки", "socks", False, "wrong_context"), + + ("a1_colors_clothes_t10", "A", "Noszę sweter.", "Я ношу свитер.", "Я ношу светр.", "I wear a sweater.", True, None), + ("a1_colors_clothes_t10", "B", "Noszę swetra.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_colors_clothes_t10", "C", "Jestem sweter.", "Я свитер.", "Я светр.", "I am a sweater.", False, "wrong_sentence_type"), + ("a1_colors_clothes_t10", "D", "Mam sweter nosić.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + ("a1_colors_clothes_t11", "A", "Mam na sobie niebieski sweter.", "На мне синий свитер.", "На мені синій светр.", "I'm wearing a blue sweater.", True, None), + ("a1_colors_clothes_t11", "B", "Mam na sobie niebieską sweter.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_t11", "C", "Mam na sobie niebieskie sweter.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_t11", "D", "Jestem niebieski sweter.", "Я синий свитер.", "Я синій светр.", "I am a blue sweater.", False, "wrong_sentence_type"), + + ("a1_colors_clothes_t12", "A", "One są czarne.", "Они чёрные.", "Вони чорні.", "They are black.", True, None), + ("a1_colors_clothes_t12", "B", "One jest czarne.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_colors_clothes_t12", "C", "One są czarny.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + ("a1_colors_clothes_t12", "D", "One są czarna.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + + ("a1_colors_clothes_t19", "A", "Mam na sobie czerwoną sukienkę i czarne buty.", "На мне красное платье и чёрные ботинки.", "На мені червона сукня і чорні черевики.", "I'm wearing a red dress and black shoes.", True, None), + ("a1_colors_clothes_t19", "B", "Mam na sobie czerwona sukienkę i czarny buty.", "Неправильные падежи.", "Неправильні відмінки.", "Wrong cases.", False, "wrong_case"), + ("a1_colors_clothes_t19", "C", "Jestem czerwona sukienka i czarne buty.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_colors_clothes_t19", "D", "Mam na sobie czerwony sukienkę i czarna buty.", "Неправильный род.", "Неправильний рід.", "Wrong gender.", False, "wrong_gender"), + + ("a1_colors_clothes_t20", "A", "Jakiego koloru jest twoja kurtka? Ona jest niebieska.", "Какого цвета твоя куртка? Она синяя.", "Якого кольору твоя куртка? Вона синя.", "What color is your jacket? It is blue.", True, None), + ("a1_colors_clothes_t20", "B", "Jaki kolor twoja kurtka? On jest niebieski.", "Неправильный падеж и род.", "Неправильний відмінок і рід.", "Wrong case and gender.", False, "wrong_case"), + ("a1_colors_clothes_t20", "C", "Ile kosztuje twoja kurtka? Ona jest niebieska.", "Неправильный вопрос.", "Неправильне питання.", "Wrong question.", False, "wrong_translation"), + ("a1_colors_clothes_t20", "D", "Jakiego koloru jest twoja kurtka? Ona jest czerwona.", "Неверный ответ по смыслу.", "Невірна відповідь за змістом.", "Wrong meaning in the answer.", False, "wrong_context"), + ] + + for opt in test_options_t7: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # ==================== ТЕМА 8: ПОГОДА И ВРЕМЕНА ГОДА ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_weather_seasons', 'A1', 8, + 'Pogoda i pory roku', + 'Погода и времена года', + 'Погода та пори року', + 'Weather and Seasons') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t8 = [ + ("a1_weather_seasons_l01", 1, "weather_vocabulary", "Zjawiska pogodowe", "Погодные явления", "Погодні явища", "Weather phenomena", + "Podstawowe zjawiska pogodowe: pada deszcz, pada śnieg, świeci słońce, wieje wiatr. „Deszcz”, „śnieg” i „wiatr” są rodzaju męskiego, „słońce” jest rodzaju nijakiego.", + "Основные погодные явления: pada deszcz (идёт дождь), pada śnieg (идёт снег), świeci słońce (светит солнце), wieje wiatr (дует ветер). „Deszcz”, „śnieg” и „wiatr” мужского рода, „słońce” среднего рода.", + "Основні погодні явища: pada deszcz (йде дощ), pada śnieg (йде сніг), świeci słońce (світить сонце), wieje wiatr (дме вітер). „Deszcz”, „śnieg” і „wiatr” чоловічого роду, „słońce” середнього роду.", + "Basic weather phenomena: pada deszcz (it's raining), pada śnieg (it's snowing), świeci słońce (the sun is shining), wieje wiatr (the wind is blowing). „Deszcz”, „śnieg” and „wiatr” are masculine, „słońce” is neuter."), + + ("a1_weather_seasons_l02", 2, "weather_vocabulary", "Jest zimno, jest ciepło", "Холодно, тепло", "Холодно, тепло", "It's cold, it's warm", + "Temperaturę opisujemy zdaniem bezosobowym „jest” + przysłówek: jest zimno, jest chłodno, jest ciepło, jest gorąco. To przysłówki, dlatego nie zmieniają się przez rodzaj.", + "Температуру описываем безличным предложением „jest” + наречие: jest zimno (холодно), jest chłodno (прохладно), jest ciepło (тепло), jest gorąco (жарко). Это наречия, поэтому они не меняются по родам.", + "Температуру описуємо безособовим реченням „jest” + прислівник: jest zimno (холодно), jest chłodno (прохолодно), jest ciepło (тепло), jest gorąco (спекотно). Це прислівники, тому вони не змінюються за родами.", + "We describe temperature with the impersonal sentence „jest” + adverb: jest zimno (it's cold), jest chłodno (it's cool), jest ciepło (it's warm), jest gorąco (it's hot). These are adverbs, so they don't change by gender."), + + ("a1_weather_seasons_l03", 3, "weather_description", "Jaka jest pogoda?", "Какая погода?", "Яка погода?", "What's the weather like?", + "„Pogoda” jest rodzaju żeńskiego, dlatego przymiotnik opisujący pogodę ma końcówkę -a: pogoda jest ładna, pogoda jest brzydka, pogoda jest słoneczna, pogoda jest deszczowa.", + "„Pogoda” (погода) женского рода, поэтому прилагательное, описывающее погоду, имеет окончание -a: pogoda jest ładna (хорошая), pogoda jest brzydka (плохая), pogoda jest słoneczna (солнечная), pogoda jest deszczowa (дождливая).", + "„Pogoda” (погода) жіночого роду, тому прикметник, що описує погоду, має закінчення -a: pogoda jest ładna (гарна), pogoda jest brzydka (погана), pogoda jest słoneczna (сонячна), pogoda jest deszczowa (дощова).", + "„Pogoda” (weather) is feminine, so the adjective describing weather has the ending -a: pogoda jest ładna (nice), pogoda jest brzydka (bad), pogoda jest słoneczna (sunny), pogoda jest deszczowa (rainy)."), + + ("a1_weather_seasons_l04", 4, "weather_description", "Niebo jest zachmurzone", "Небо облачное", "Небо хмарне", "The sky is cloudy", + "„Niebo” jest rodzaju nijakiego, dlatego przymiotnik ma końcówkę -e: niebo jest zachmurzone, niebo jest czyste, niebo jest niebieskie.", + "„Niebo” (небо) среднего рода, поэтому прилагательное имеет окончание -e: niebo jest zachmurzone (облачное), niebo jest czyste (чистое), niebo jest niebieskie (голубое).", + "„Niebo” (небо) середнього роду, тому прикметник має закінчення -e: niebo jest zachmurzone (хмарне), niebo jest czyste (чисте), niebo jest niebieskie (блакитне).", + "„Niebo” (sky) is neuter, so the adjective has the ending -e: niebo jest zachmurzone (cloudy), niebo jest czyste (clear), niebo jest niebieskie (blue)."), + + ("a1_weather_seasons_l05", 5, "seasons_vocabulary", "Pory roku", "Времена года", "Пори року", "Seasons", + "Pory roku: wiosna (rodzaj żeński), lato (rodzaj nijaki), jesień (rodzaj żeński), zima (rodzaj żeński).", + "Времена года: wiosna (весна, женский род), lato (лето, средний род), jesień (осень, женский род), zima (зима, женский род).", + "Пори року: wiosna (весна, жіночий рід), lato (літо, середній рід), jesień (осінь, жіночий рід), zima (зима, жіночий рід).", + "Seasons: wiosna (spring, feminine), lato (summer, neuter), jesień (autumn, feminine), zima (winter, feminine)."), + + ("a1_weather_seasons_l06", 6, "seasons_vocabulary", "Lubię + biernik pór roku", "Lubię + винительный падеж", "Lubię + знахідний відмінок", "Lubię + accusative", + "Czasownik „lubić” łączy się z biernikiem: lubię wiosnę (wiosna → wiosnę), lubię lato (bez zmiany), lubię jesień (bez zmiany), lubię zimę (zima → zimę).", + "Глагол „lubić” требует винительного падежа: lubię wiosnę (wiosna → wiosnę), lubię lato (без изменений), lubię jesień (без изменений), lubię zimę (zima → zimę).", + "Дієслово „lubić” вимагає знахідного відмінка: lubię wiosnę (wiosna → wiosnę), lubię lato (без змін), lubię jesień (без змін), lubię zimę (zima → zimę).", + "The verb „lubić” (to like) takes the accusative: lubię wiosnę (wiosna → wiosnę), lubię lato (unchanged), lubię jesień (unchanged), lubię zimę (zima → zimę)."), + + ("a1_weather_seasons_l07", 7, "seasons_time", "Zimą, latem — kiedy?", "Зимой, летом — когда?", "Взимку, влітку — коли?", "In winter, in summer — when?", + "Żeby powiedzieć, kiedy coś się dzieje w danej porze roku, używamy narzędnika bez przyimka: wiosną, latem, jesienią, zimą.", + "Чтобы сказать, когда что-то происходит в определённое время года, используем творительный падеж без предлога: wiosną (весной), latem (летом), jesienią (осенью), zimą (зимой).", + "Щоб сказати, коли щось відбувається в певну пору року, використовуємо орудний відмінок без прийменника: wiosną (навесні), latem (влітку), jesienią (восени), zimą (взимку).", + "To say when something happens during a season, we use the instrumental without a preposition: wiosną (in spring), latem (in summer), jesienią (in autumn), zimą (in winter)."), + + ("a1_weather_seasons_l08", 8, "seasons_time", "Pogoda w porach roku", "Погода в разные времена года", "Погода в різні пори року", "Weather in different seasons", + "Łączymy porę roku z pogodą w jednym zdaniu: Zimą jest zimno i pada śnieg. Latem jest gorąco i świeci słońce.", + "Соединяем время года и погоду в одном предложении: Zimą jest zimno i pada śnieg (Зимой холодно и идёт снег). Latem jest gorąco i świeci słońce (Летом жарко и светит солнце).", + "Поєднуємо пору року і погоду в одному реченні: Zimą jest zimno i pada śnieg (Взимку холодно і йде сніг). Latem jest gorąco i świeci słońce (Влітку спекотно і світить сонце).", + "We combine a season and the weather in one sentence: Zimą jest zimno i pada śnieg (In winter it's cold and it snows). Latem jest gorąco i świeci słońce (In summer it's hot and the sun shines)."), + + ("a1_weather_seasons_l09", 9, "weather_forecast", "Jutro będzie...", "Завтра будет...", "Завтра буде...", "Tomorrow it will be...", + "O przyszłej pogodzie mówimy z czasownikiem „będzie” + przysłówek lub bezokolicznik: jutro będzie zimno, jutro będzie padać deszcz.", + "О будущей погоде говорим с глаголом „będzie” + наречие или инфинитив: jutro będzie zimno (завтра будет холодно), jutro będzie padać deszcz (завтра будет идти дождь).", + "Про майбутню погоду говоримо з дієсловом „będzie” + прислівник або інфінітив: jutro będzie zimno (завтра буде холодно), jutro będzie padać deszcz (завтра йтиме дощ).", + "We talk about future weather with „będzie” + an adverb or infinitive: jutro będzie zimno (tomorrow it will be cold), jutro będzie padać deszcz (tomorrow it will rain)."), + + ("a1_weather_seasons_l10", 10, "weather_forecast", "Pełna prognoza pogody", "Полный прогноз погоды", "Повний прогноз погоди", "A full weather forecast", + "Łączymy teraźniejszość i przyszłość w jednym opisie pogody: Dziś jest ciepło i słonecznie, ale jutro będzie zimno i będzie padać deszcz.", + "Соединяем настоящее и будущее в одном описании погоды: Dziś jest ciepło i słonecznie, ale jutro będzie zimno i będzie padać deszcz. (Сегодня тепло и солнечно, но завтра будет холодно и будет идти дождь.)", + "Поєднуємо теперішнє і майбутнє в одному описі погоди: Dziś jest ciepło i słonecznie, ale jutro będzie zimno i będzie padać deszcz. (Сьогодні тепло і сонячно, але завтра буде холодно і йтиме дощ.)", + "We combine present and future in one weather description: Dziś jest ciepło i słonecznie, ale jutro będzie zimno i będzie padać deszcz. (Today it's warm and sunny, but tomorrow it will be cold and it will rain.)"), + ] + + for lesson in lessons_t8: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_weather_seasons', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t8 = [ + ("a1_weather_seasons_l01", 1, "Pada deszcz.", "Идёт дождь.", "Йде дощ.", "It's raining."), + ("a1_weather_seasons_l01", 2, "Świeci słońce.", "Светит солнце.", "Світить сонце.", "The sun is shining."), + ("a1_weather_seasons_l01", 3, "Wieje silny wiatr.", "Дует сильный ветер.", "Дме сильний вітер.", "A strong wind is blowing."), + + ("a1_weather_seasons_l02", 1, "Jest zimno.", "Холодно.", "Холодно.", "It's cold."), + ("a1_weather_seasons_l02", 2, "Jest bardzo gorąco.", "Очень жарко.", "Дуже спекотно.", "It's very hot."), + ("a1_weather_seasons_l02", 3, "Jest chłodno rano.", "Утром прохладно.", "Вранці прохолодно.", "It's cool in the morning."), + + ("a1_weather_seasons_l03", 1, "Pogoda jest ładna.", "Погода хорошая.", "Погода гарна.", "The weather is nice."), + ("a1_weather_seasons_l03", 2, "Dzisiaj pogoda jest brzydka.", "Сегодня погода плохая.", "Сьогодні погода погана.", "Today the weather is bad."), + ("a1_weather_seasons_l03", 3, "Pogoda jest słoneczna.", "Погода солнечная.", "Погода сонячна.", "The weather is sunny."), + + ("a1_weather_seasons_l04", 1, "Niebo jest zachmurzone.", "Небо облачное.", "Небо хмарне.", "The sky is cloudy."), + ("a1_weather_seasons_l04", 2, "Niebo jest czyste.", "Небо чистое.", "Небо чисте.", "The sky is clear."), + ("a1_weather_seasons_l04", 3, "Niebo jest niebieskie.", "Небо голубое.", "Небо блакитне.", "The sky is blue."), + + ("a1_weather_seasons_l05", 1, "Wiosna jest ciepła.", "Весна тёплая.", "Весна тепла.", "Spring is warm."), + ("a1_weather_seasons_l05", 2, "Lato jest gorące.", "Лето жаркое.", "Літо спекотне.", "Summer is hot."), + ("a1_weather_seasons_l05", 3, "Zima jest zimna.", "Зима холодная.", "Зима холодна.", "Winter is cold."), + + ("a1_weather_seasons_l06", 1, "Lubię wiosnę.", "Я люблю весну.", "Я люблю весну.", "I like spring."), + ("a1_weather_seasons_l06", 2, "Lubię lato.", "Я люблю лето.", "Я люблю літо.", "I like summer."), + ("a1_weather_seasons_l06", 3, "Lubię jesień.", "Я люблю осень.", "Я люблю осінь.", "I like autumn."), + + ("a1_weather_seasons_l07", 1, "Zimą pada śnieg.", "Зимой идёт снег.", "Взимку йде сніг.", "In winter it snows."), + ("a1_weather_seasons_l07", 2, "Latem jest gorąco.", "Летом жарко.", "Влітку спекотно.", "In summer it's hot."), + ("a1_weather_seasons_l07", 3, "Wiosną jest ciepło.", "Весной тепло.", "Навесні тепло.", "In spring it's warm."), + + ("a1_weather_seasons_l08", 1, "Zimą jest zimno i pada śnieg.", "Зимой холодно и идёт снег.", "Взимку холодно і йде сніг.", "In winter it's cold and it snows."), + ("a1_weather_seasons_l08", 2, "Latem jest gorąco i świeci słońce.", "Летом жарко и светит солнце.", "Влітку спекотно і світить сонце.", "In summer it's hot and the sun shines."), + ("a1_weather_seasons_l08", 3, "Jesienią pada deszcz i wieje wiatr.", "Осенью идёт дождь и дует ветер.", "Восени йде дощ і дме вітер.", "In autumn it rains and the wind blows."), + + ("a1_weather_seasons_l09", 1, "Jutro będzie zimno.", "Завтра будет холодно.", "Завтра буде холодно.", "Tomorrow it will be cold."), + ("a1_weather_seasons_l09", 2, "Jutro będzie padać deszcz.", "Завтра будет идти дождь.", "Завтра йтиме дощ.", "Tomorrow it will rain."), + ("a1_weather_seasons_l09", 3, "W weekend będzie ciepło.", "На выходных будет тепло.", "На вихідних буде тепло.", "It will be warm on the weekend."), + + ("a1_weather_seasons_l10", 1, "Dziś jest ciepło, ale jutro będzie zimno.", "Сегодня тепло, но завтра будет холодно.", "Сьогодні тепло, але завтра буде холодно.", "Today it's warm, but tomorrow it will be cold."), + ("a1_weather_seasons_l10", 2, "Dzisiaj świeci słońce, a jutro będzie padać deszcz.", "Сегодня светит солнце, а завтра будет идти дождь.", "Сьогодні світить сонце, а завтра йтиме дощ.", "Today the sun is shining, and tomorrow it will rain."), + ("a1_weather_seasons_l10", 3, "W tym tygodniu jest słonecznie, w przyszłym będzie pochmurno.", "На этой неделе солнечно, на следующей будет пасмурно.", "Цього тижня сонячно, наступного буде хмарно.", "This week it's sunny, next week it will be cloudy."), + ] + + for ex in examples_t8: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t8 = [ + # L01 — weather_vocabulary (difficulty 1) + ("a1_weather_seasons_l01_q1", "a1_weather_seasons_l01", "lesson_practice", "recognition", "weather_vocabulary", 1, + "Jak po polsku „дождь”?", "Как по-польски «дождь»?", "Як польською «дощ»?", "How do you say “rain” in Polish?", + "A", None, None), + ("a1_weather_seasons_l01_q2", "a1_weather_seasons_l01", "lesson_practice", "production", "weather_vocabulary", 1, + "Wpisz brakujące słowo: ___ deszcz. (идёт)", "Вставьте пропущенное слово: ___ deszcz. (идёт)", "Вставте пропущене слово: ___ deszcz. (йде)", "Fill in the missing word: ___ deszcz. (falls)", + "Pada", "first_letter", "P"), + ("a1_weather_seasons_l01_q3", "a1_weather_seasons_l01", "lesson_practice", "application", "weather_vocabulary", 1, + "Widzisz krople wody spadające z nieba. Co się dzieje?", "Ты видишь капли воды, падающие с неба. Что происходит?", "Ти бачиш краплі води, що падають з неба. Що відбувається?", "You see drops of water falling from the sky. What's happening?", + "A", None, None), + + # L02 — weather_vocabulary (difficulty 1) + ("a1_weather_seasons_l02_q1", "a1_weather_seasons_l02", "lesson_practice", "recognition", "weather_vocabulary", 1, + "Jak po polsku „жарко”?", "Как по-польски «жарко»?", "Як польською «спекотно»?", "How do you say “hot” (weather) in Polish?", + "C", None, None), + ("a1_weather_seasons_l02_q2", "a1_weather_seasons_l02", "lesson_practice", "production", "weather_vocabulary", 1, + "Wpisz brakujące słowo: Jest bardzo ___. (холодно)", "Вставьте пропущенное слово: Jest bardzo ___. (холодно)", "Вставте пропущене слово: Jest bardzo ___. (холодно)", "Fill in the missing word: Jest bardzo ___. (cold)", + "zimno", "first_letter", "z"), + ("a1_weather_seasons_l02_q3", "a1_weather_seasons_l02", "lesson_practice", "application", "weather_vocabulary", 1, + "Jest lato, temperatura to 35 stopni. Jak jest?", "Сейчас лето, температура 35 градусов. Как сейчас?", "Зараз літо, температура 35 градусів. Як зараз?", "It's summer, the temperature is 35 degrees. What's it like?", + "A", None, None), + + # L03 — weather_description (difficulty 1) + ("a1_weather_seasons_l03_q1", "a1_weather_seasons_l03", "lesson_practice", "recognition", "weather_description", 1, + "Wybierz poprawną formę: Pogoda jest ___. (ładny)", "Выберите правильную форму: Pogoda jest ___. (ładny)", "Виберіть правильну форму: Pogoda jest ___. (ładny)", "Choose the correct form: Pogoda jest ___. (ładny)", + "B", None, None), + ("a1_weather_seasons_l03_q2", "a1_weather_seasons_l03", "lesson_practice", "production", "weather_description", 1, + "Wpisz brakujące słowo: Pogoda jest ___. (солнечная)", "Вставьте пропущенное слово: Pogoda jest ___. (солнечная)", "Вставте пропущене слово: Pogoda jest ___. (сонячна)", "Fill in the missing word: Pogoda jest ___. (sunny)", + "słoneczna", "first_letter", "s"), + ("a1_weather_seasons_l03_q3", "a1_weather_seasons_l03", "lesson_practice", "application", "weather_description", 1, + "Cały dzień świeci słońce i nie ma chmur. Jaka jest pogoda?", "Целый день светит солнце и нет облаков. Какая погода?", "Цілий день світить сонце і немає хмар. Яка погода?", "The sun shines all day and there are no clouds. What's the weather like?", + "A", None, None), + + # L04 — weather_description (difficulty 1) + ("a1_weather_seasons_l04_q1", "a1_weather_seasons_l04", "lesson_practice", "recognition", "weather_description", 1, + "Wybierz poprawną formę: Niebo jest ___. (czysty)", "Выберите правильную форму: Niebo jest ___. (czysty)", "Виберіть правильну форму: Niebo jest ___. (czysty)", "Choose the correct form: Niebo jest ___. (czysty)", + "C", None, None), + ("a1_weather_seasons_l04_q2", "a1_weather_seasons_l04", "lesson_practice", "production", "weather_description", 1, + "Wpisz brakujące słowo: Niebo jest ___. (облачное)", "Вставьте пропущенное слово: Niebo jest ___. (облачное)", "Вставте пропущене слово: Niebo jest ___. (хмарне)", "Fill in the missing word: Niebo jest ___. (cloudy)", + "zachmurzone", "first_letter", "z"), + ("a1_weather_seasons_l04_q3", "a1_weather_seasons_l04", "lesson_practice", "application", "weather_description", 1, + "Na niebie jest dużo chmur. Jakie jest niebo?", "На небе много облаков. Какое небо?", "На небі багато хмар. Яке небо?", "There are many clouds in the sky. What is the sky like?", + "A", None, None), + + # L05 — seasons_vocabulary (difficulty 2) + ("a1_weather_seasons_l05_q1", "a1_weather_seasons_l05", "lesson_practice", "recognition", "seasons_vocabulary", 2, + "Jak po polsku „осень”?", "Как по-польски «осень»?", "Як польською «осінь»?", "How do you say “autumn” in Polish?", + "B", None, None), + ("a1_weather_seasons_l05_q2", "a1_weather_seasons_l05", "lesson_practice", "production", "seasons_vocabulary", 2, + "Wpisz brakujące słowo: ___ jest zimna. (зима)", "Вставьте пропущенное слово: ___ jest zimna. (зима)", "Вставте пропущене слово: ___ jest zimna. (зима)", "Fill in the missing word: ___ jest zimna. (winter)", + "Zima", "first_letter", "Z"), + ("a1_weather_seasons_l05_q3", "a1_weather_seasons_l05", "lesson_practice", "application", "seasons_vocabulary", 2, + "Jest bardzo gorąco, ludzie jadą nad morze. Jaka to pora roku?", "Очень жарко, люди едут на море. Какое сейчас время года?", "Дуже спекотно, люди їдуть на море. Яка це пора року?", "It's very hot, people are going to the seaside. What season is it?", + "A", None, None), + + # L06 — seasons_vocabulary (difficulty 2) + ("a1_weather_seasons_l06_q1", "a1_weather_seasons_l06", "lesson_practice", "recognition", "seasons_vocabulary", 2, + "Wybierz poprawną formę: Lubię ___. (wiosna)", "Выберите правильную форму: Lubię ___. (wiosna)", "Виберіть правильну форму: Lubię ___. (wiosna)", "Choose the correct form: Lubię ___. (wiosna)", + "A", None, None), + ("a1_weather_seasons_l06_q2", "a1_weather_seasons_l06", "lesson_practice", "production", "seasons_vocabulary", 2, + "Wpisz brakujące słowo: Lubię ___. (осень)", "Вставьте пропущенное слово: Lubię ___. (осень)", "Вставте пропущене слово: Lubię ___. (осінь)", "Fill in the missing word: Lubię ___. (autumn)", + "jesień", "first_letter", "j"), + ("a1_weather_seasons_l06_q3", "a1_weather_seasons_l06", "lesson_practice", "application", "seasons_vocabulary", 2, + "Kolega pyta, jaką porę roku lubisz. Lubisz lato. Co powiesz?", "Друг спрашивает, какое время года ты любишь. Ты любишь лето. Что ты скажешь?", "Друг питає, яку пору року ти любиш. Ти любиш літо. Що ти скажеш?", "A friend asks what season you like. You like summer. What do you say?", + "A", None, None), + + # L07 — seasons_time (difficulty 2) + ("a1_weather_seasons_l07_q1", "a1_weather_seasons_l07", "lesson_practice", "recognition", "seasons_time", 2, + "Wybierz poprawną formę: ___ pada śnieg. (zima)", "Выберите правильную форму: ___ pada śnieg. (zima)", "Виберіть правильну форму: ___ pada śnieg. (zima)", "Choose the correct form: ___ pada śnieg. (zima)", + "A", None, None), + ("a1_weather_seasons_l07_q2", "a1_weather_seasons_l07", "lesson_practice", "production", "seasons_time", 2, + "Wpisz brakujące słowo: ___ jest ciepło. (весной)", "Вставьте пропущенное слово: ___ jest ciepło. (весной)", "Вставте пропущене слово: ___ jest ciepło. (навесні)", "Fill in the missing word: ___ jest ciepło. (in spring)", + "Wiosną", "first_letter", "W"), + ("a1_weather_seasons_l07_q3", "a1_weather_seasons_l07", "lesson_practice", "application", "seasons_time", 2, + "Chcesz powiedzieć, że latem jest gorąco. Co powiesz?", "Ты хочешь сказать, что летом жарко. Что ты скажешь?", "Ти хочеш сказати, що влітку спекотно. Що ти скажеш?", "You want to say that it's hot in summer. What do you say?", + "A", None, None), + + # L08 — seasons_time (difficulty 2) + ("a1_weather_seasons_l08_q1", "a1_weather_seasons_l08", "lesson_practice", "recognition", "seasons_time", 2, + "Które zdanie poprawnie opisuje zimę?", "Какое предложение правильно описывает зиму?", "Яке речення правильно описує зиму?", "Which sentence correctly describes winter?", + "B", None, None), + ("a1_weather_seasons_l08_q2", "a1_weather_seasons_l08", "lesson_practice", "production", "seasons_time", 2, + "Przetłumacz: «Осенью идёт дождь и дует ветер».", "Переведите: «Осенью идёт дождь и дует ветер».", "Перекладіть: «Восени йде дощ і дме вітер».", "Translate: “In autumn it rains and the wind blows.”", + "Jesienią pada deszcz i wieje wiatr", "first_letter", "J"), + ("a1_weather_seasons_l08_q3", "a1_weather_seasons_l08", "lesson_practice", "application", "seasons_time", 2, + "Chcesz opisać zimę koledze: jest zimno i pada śnieg. Jak zaczniesz zdanie?", "Ты хочешь описать другу зиму: холодно и идёт снег. Как ты начнёшь предложение?", "Ти хочеш описати другу зиму: холодно і йде сніг. Як ти почнеш речення?", "You want to describe winter to a friend: it's cold and it snows. How do you start the sentence?", + "A", None, None), + + # L09 — weather_forecast (difficulty 3) + ("a1_weather_seasons_l09_q1", "a1_weather_seasons_l09", "lesson_practice", "recognition", "weather_forecast", 3, + "Co znaczy „Jutro będzie padać deszcz”?", "Что означает «Jutro będzie padać deszcz»?", "Що означає «Jutro będzie padać deszcz»?", "What does “Jutro będzie padać deszcz” mean?", + "A", None, None), + ("a1_weather_seasons_l09_q2", "a1_weather_seasons_l09", "lesson_practice", "production", "weather_forecast", 3, + "Wpisz brakujące słowo: Jutro ___ zimno. (будет)", "Вставьте пропущенное слово: Jutro ___ zimno. (будет)", "Вставте пропущене слово: Jutro ___ zimno. (буде)", "Fill in the missing word: Jutro ___ zimno. (will be)", + "będzie", "first_letter", "b"), + ("a1_weather_seasons_l09_q3", "a1_weather_seasons_l09", "lesson_practice", "application", "weather_forecast", 3, + "Sprawdzasz prognozę: jutro pada deszcz. Co powiesz?", "Ты смотришь прогноз: завтра дождь. Что ты скажешь?", "Ти дивишся прогноз: завтра дощ. Що ти скажеш?", "You check the forecast: rain tomorrow. What do you say?", + "A", None, None), + + # L10 — weather_forecast (difficulty 3) + ("a1_weather_seasons_l10_q1", "a1_weather_seasons_l10", "lesson_practice", "recognition", "weather_forecast", 3, + "Które zdanie poprawnie łączy dziś i jutro?", "Какое предложение правильно соединяет сегодня и завтра?", "Яке речення правильно поєднує сьогодні і завтра?", "Which sentence correctly links today and tomorrow?", + "B", None, None), + ("a1_weather_seasons_l10_q2", "a1_weather_seasons_l10", "lesson_practice", "production", "weather_forecast", 3, + "Przetłumacz: «Сегодня тепло, но завтра будет холодно».", "Переведите: «Сегодня тепло, но завтра будет холодно».", "Перекладіть: «Сьогодні тепло, але завтра буде холодно».", "Translate: “Today it's warm, but tomorrow it will be cold.”", + "Dziś jest ciepło, ale jutro będzie zimno", "first_letter", "D"), + ("a1_weather_seasons_l10_q3", "a1_weather_seasons_l10", "lesson_practice", "application", "weather_forecast", 3, + "Chcesz opisać koledze pogodę: dziś słońce, jutro deszcz. Jak zaczniesz zdanie?", "Ты хочешь описать другу погоду: сегодня солнце, завтра дождь. Как ты начнёшь предложение?", "Ти хочеш описати другу погоду: сьогодні сонце, завтра дощ. Як ти почнеш речення?", "You want to describe the weather to a friend: sun today, rain tomorrow. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t8: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_weather_seasons', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t8 = [ + # L01 + ("a1_weather_seasons_l01_q1", "A", "deszcz", "дождь", "дощ", "rain", True, None), + ("a1_weather_seasons_l01_q1", "B", "śnieg", "снег", "сніг", "snow", False, "wrong_word"), + ("a1_weather_seasons_l01_q1", "C", "wiatr", "ветер", "вітер", "wind", False, "wrong_word"), + ("a1_weather_seasons_l01_q1", "D", "słońce", "солнце", "сонце", "sun", False, "wrong_word"), + + ("a1_weather_seasons_l01_q3", "A", "Pada deszcz.", "Идёт дождь.", "Йде дощ.", "It's raining.", True, None), + ("a1_weather_seasons_l01_q3", "B", "Świeci słońce.", "Светит солнце.", "Світить сонце.", "The sun is shining.", False, "wrong_context"), + ("a1_weather_seasons_l01_q3", "C", "Wieje wiatr.", "Дует ветер.", "Дме вітер.", "The wind is blowing.", False, "wrong_context"), + ("a1_weather_seasons_l01_q3", "D", "Pada śnieg.", "Идёт снег.", "Йде сніг.", "It's snowing.", False, "wrong_context"), + + # L02 + ("a1_weather_seasons_l02_q1", "A", "zimno", "холодно", "холодно", "cold", False, "wrong_word"), + ("a1_weather_seasons_l02_q1", "B", "chłodno", "прохладно", "прохолодно", "cool", False, "wrong_word"), + ("a1_weather_seasons_l02_q1", "C", "gorąco", "жарко", "спекотно", "hot", True, None), + ("a1_weather_seasons_l02_q1", "D", "ciepło", "тепло", "тепло", "warm", False, "wrong_word"), + + ("a1_weather_seasons_l02_q3", "A", "Jest gorąco.", "Жарко.", "Спекотно.", "It's hot.", True, None), + ("a1_weather_seasons_l02_q3", "B", "Jest zimno.", "Холодно. (неверная температура)", "Холодно. (невірна температура)", "It's cold. (wrong temperature)", False, "wrong_context"), + ("a1_weather_seasons_l02_q3", "C", "Jest chłodno.", "Прохладно. (неверная температура)", "Прохолодно. (невірна температура)", "It's cool. (wrong temperature)", False, "wrong_context"), + ("a1_weather_seasons_l02_q3", "D", "Pada śnieg.", "Идёт снег. (неверное явление для лета)", "Йде сніг. (невірне явище для літа)", "It's snowing. (wrong for summer)", False, "wrong_context"), + + # L03 + ("a1_weather_seasons_l03_q1", "A", "ładny", "хороший (муж.)", "гарний (чол.)", "nice (masc.)", False, "wrong_gender"), + ("a1_weather_seasons_l03_q1", "B", "ładna", "хорошая (жен.)", "гарна (жін.)", "nice (fem.)", True, None), + ("a1_weather_seasons_l03_q1", "C", "ładne", "хорошее (ср.)", "гарне (сер.)", "nice (neut.)", False, "wrong_gender"), + ("a1_weather_seasons_l03_q1", "D", "ładną", "хорошую (вин.)", "гарну (знах.)", "nice (acc.)", False, "wrong_case"), + + ("a1_weather_seasons_l03_q3", "A", "Pogoda jest słoneczna.", "Погода солнечная.", "Погода сонячна.", "The weather is sunny.", True, None), + ("a1_weather_seasons_l03_q3", "B", "Pogoda jest deszczowa.", "Погода дождливая. (неверная погода)", "Погода дощова. (невірна погода)", "The weather is rainy. (wrong weather)", False, "wrong_context"), + ("a1_weather_seasons_l03_q3", "C", "Pogoda jest brzydka.", "Погода плохая. (неверная погода)", "Погода погана. (невірна погода)", "The weather is bad. (wrong weather)", False, "wrong_context"), + ("a1_weather_seasons_l03_q3", "D", "Niebo jest zachmurzone.", "Небо облачное. (не соответствует контексту)", "Небо хмарне. (не відповідає контексту)", "The sky is cloudy. (wrong context)", False, "wrong_context"), + + # L04 + ("a1_weather_seasons_l04_q1", "A", "czysty", "чистый (муж.)", "чистий (чол.)", "clear (masc.)", False, "wrong_gender"), + ("a1_weather_seasons_l04_q1", "B", "czysta", "чистая (жен.)", "чиста (жін.)", "clear (fem.)", False, "wrong_gender"), + ("a1_weather_seasons_l04_q1", "C", "czyste", "чистое (ср.)", "чисте (сер.)", "clear (neut.)", True, None), + ("a1_weather_seasons_l04_q1", "D", "czystym", "чистым (тв.)", "чистим (ор.)", "clear (instr.)", False, "wrong_case"), + + ("a1_weather_seasons_l04_q3", "A", "Niebo jest zachmurzone.", "Небо облачное.", "Небо хмарне.", "The sky is cloudy.", True, None), + ("a1_weather_seasons_l04_q3", "B", "Niebo jest czyste.", "Небо чистое. (противоречит описанию)", "Небо чисте. (суперечить опису)", "The sky is clear. (contradicts the description)", False, "wrong_context"), + ("a1_weather_seasons_l04_q3", "C", "Pogoda jest słoneczna.", "Погода солнечная. (не соответствует контексту)", "Погода сонячна. (не відповідає контексту)", "The weather is sunny. (wrong context)", False, "wrong_context"), + ("a1_weather_seasons_l04_q3", "D", "Jest gorąco.", "Жарко. (не о небе)", "Спекотно. (не про небо)", "It's hot. (not about the sky)", False, "wrong_context"), + + # L05 + ("a1_weather_seasons_l05_q1", "A", "zima", "зима", "зима", "winter", False, "wrong_word"), + ("a1_weather_seasons_l05_q1", "B", "jesień", "осень", "осінь", "autumn", True, None), + ("a1_weather_seasons_l05_q1", "C", "wiosna", "весна", "весна", "spring", False, "wrong_word"), + ("a1_weather_seasons_l05_q1", "D", "lato", "лето", "літо", "summer", False, "wrong_word"), + + ("a1_weather_seasons_l05_q3", "A", "Lato.", "Лето.", "Літо.", "Summer.", True, None), + ("a1_weather_seasons_l05_q3", "B", "Zima.", "Зима. (неверное время года)", "Зима. (невірна пора року)", "Winter. (wrong season)", False, "wrong_context"), + ("a1_weather_seasons_l05_q3", "C", "Jesień.", "Осень. (неверное время года)", "Осінь. (невірна пора року)", "Autumn. (wrong season)", False, "wrong_context"), + ("a1_weather_seasons_l05_q3", "D", "Wiosna.", "Весна. (неверное время года)", "Весна. (невірна пора року)", "Spring. (wrong season)", False, "wrong_context"), + + # L06 + ("a1_weather_seasons_l06_q1", "A", "wiosnę", "весну (вин.)", "весну (знах.)", "spring (acc.)", True, None), + ("a1_weather_seasons_l06_q1", "B", "wiosna", "весна (им.)", "весна (наз.)", "spring (nom.)", False, "wrong_case"), + ("a1_weather_seasons_l06_q1", "C", "wiosny", "весны (род.)", "весни (род.)", "spring (gen.)", False, "wrong_case"), + ("a1_weather_seasons_l06_q1", "D", "wiosną", "весной (тв.)", "весною (ор.)", "spring (instr.)", False, "wrong_case"), + + ("a1_weather_seasons_l06_q3", "A", "Lubię lato.", "Я люблю лето.", "Я люблю літо.", "I like summer.", True, None), + ("a1_weather_seasons_l06_q3", "B", "Lubię lata.", "Неправильная форма.", "Неправильна форма.", "Wrong form.", False, "wrong_case"), + ("a1_weather_seasons_l06_q3", "C", "Jestem lato.", "Я лето.", "Я літо.", "I am summer.", False, "wrong_sentence_type"), + ("a1_weather_seasons_l06_q3", "D", "Lubię zimę.", "Я люблю зиму. (неверное время года)", "Я люблю зиму. (невірна пора року)", "I like winter. (wrong season)", False, "wrong_context"), + + # L07 + ("a1_weather_seasons_l07_q1", "A", "Zimą", "Зимой", "Взимку", "In winter", True, None), + ("a1_weather_seasons_l07_q1", "B", "Zima", "Зима (им.)", "Зима (наз.)", "Winter (nom.)", False, "wrong_case"), + ("a1_weather_seasons_l07_q1", "C", "Zimę", "Зиму (вин.)", "Зиму (знах.)", "Winter (acc.)", False, "wrong_case"), + ("a1_weather_seasons_l07_q1", "D", "Zimy", "Зимы (род.)", "Зими (род.)", "Winter (gen.)", False, "wrong_case"), + + ("a1_weather_seasons_l07_q3", "A", "Latem jest gorąco.", "Летом жарко.", "Влітку спекотно.", "In summer it's hot.", True, None), + ("a1_weather_seasons_l07_q3", "B", "Lato jest gorąco.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_weather_seasons_l07_q3", "C", "Zimą jest gorąco.", "Зимой жарко. (неверная пора года)", "Взимку спекотно. (невірна пора року)", "In winter it's hot. (wrong season)", False, "wrong_context"), + ("a1_weather_seasons_l07_q3", "D", "Jest gorąco latem pora.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + # L08 + ("a1_weather_seasons_l08_q1", "A", "Zimą jest gorąco i świeci słońce.", "Зимой жарко и светит солнце. (неверная погода)", "Взимку спекотно і світить сонце. (невірна погода)", "In winter it's hot and the sun shines. (wrong weather)", False, "wrong_context"), + ("a1_weather_seasons_l08_q1", "B", "Zimą jest zimno i pada śnieg.", "Зимой холодно и идёт снег.", "Взимку холодно і йде сніг.", "In winter it's cold and it snows.", True, None), + ("a1_weather_seasons_l08_q1", "C", "Zima jest zimno i pada śnieg.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_weather_seasons_l08_q1", "D", "Zimą jest ciepło i pada deszcz.", "Зимой тепло и идёт дождь. (неверная погода)", "Взимку тепло і йде дощ. (невірна погода)", "In winter it's warm and it rains. (wrong weather)", False, "wrong_context"), + + ("a1_weather_seasons_l08_q3", "A", "Zimą jest zimno i pada śnieg.", "Зимой холодно и идёт снег.", "Взимку холодно і йде сніг.", "In winter it's cold and it snows.", True, None), + ("a1_weather_seasons_l08_q3", "B", "Ja zimno i śnieg.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_weather_seasons_l08_q3", "C", "Jestem zimno i pada śnieg.", "Я холодно и идёт снег.", "Я холодно і йде сніг.", "I am cold and it snows. (wrong construction)", False, "wrong_sentence_type"), + ("a1_weather_seasons_l08_q3", "D", "Latem jest zimno i pada śnieg.", "Летом холодно и идёт снег. (неверная пора года)", "Влітку холодно і йде сніг. (невірна пора року)", "In summer it's cold and it snows. (wrong season)", False, "wrong_context"), + + # L09 + ("a1_weather_seasons_l09_q1", "A", "Завтра будет идти дождь.", "Завтра будет идти дождь.", "Завтра йтиме дощ.", "Tomorrow it will rain.", True, None), + ("a1_weather_seasons_l09_q1", "B", "Вчера шёл дождь.", "Вчера шёл дождь.", "Вчора йшов дощ.", "It rained yesterday.", False, "wrong_translation"), + ("a1_weather_seasons_l09_q1", "C", "Сегодня идёт дождь.", "Сегодня идёт дождь.", "Сьогодні йде дощ.", "It's raining today.", False, "wrong_translation"), + ("a1_weather_seasons_l09_q1", "D", "Завтра будет холодно.", "Завтра будет холодно.", "Завтра буде холодно.", "Tomorrow it will be cold.", False, "wrong_translation"), + + ("a1_weather_seasons_l09_q3", "A", "Jutro będzie padać deszcz.", "Завтра будет идти дождь.", "Завтра йтиме дощ.", "Tomorrow it will rain.", True, None), + ("a1_weather_seasons_l09_q3", "B", "Wczoraj padał deszcz.", "Вчера шёл дождь. (неверное время)", "Вчора йшов дощ. (невірний час)", "It rained yesterday. (wrong tense)", False, "wrong_context"), + ("a1_weather_seasons_l09_q3", "C", "Dziś pada deszcz.", "Сегодня идёт дождь. (неверное время)", "Сьогодні йде дощ. (невірний час)", "It's raining today. (wrong tense)", False, "wrong_context"), + ("a1_weather_seasons_l09_q3", "D", "Jutro będzie gorąco.", "Завтра будет жарко. (неверный прогноз)", "Завтра буде спекотно. (невірний прогноз)", "Tomorrow it will be hot. (wrong forecast)", False, "wrong_context"), + + # L10 + ("a1_weather_seasons_l10_q1", "A", "Dziś jest zimno, ale jutro było ciepło.", "Неправильное время (было вместо будет).", "Неправильний час (було замість буде).", "Wrong tense (was instead of will be).", False, "wrong_sentence_type"), + ("a1_weather_seasons_l10_q1", "B", "Dziś jest ciepło, ale jutro będzie zimno.", "Сегодня тепло, но завтра будет холодно.", "Сьогодні тепло, але завтра буде холодно.", "Today it's warm, but tomorrow it will be cold.", True, None), + ("a1_weather_seasons_l10_q1", "C", "Jutro jest ciepło, ale dziś będzie zimno.", "Дни перепутаны.", "Дні переплутані.", "Days are swapped.", False, "wrong_context"), + ("a1_weather_seasons_l10_q1", "D", "Dziś będzie ciepło, ale jutro jest zimno.", "Времена перепутаны.", "Часи переплутані.", "Tenses are swapped.", False, "wrong_sentence_type"), + + ("a1_weather_seasons_l10_q3", "A", "Dzisiaj świeci słońce, a jutro będzie padać deszcz.", "Сегодня светит солнце, а завтра будет идти дождь.", "Сьогодні світить сонце, а завтра йтиме дощ.", "Today the sun is shining, and tomorrow it will rain.", True, None), + ("a1_weather_seasons_l10_q3", "B", "Ja słońce i deszcz.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_weather_seasons_l10_q3", "C", "Jestem słońce, a jutro deszcz.", "Я солнце, а завтра дождь.", "Я сонце, а завтра дощ.", "I am the sun, and tomorrow rain. (wrong construction)", False, "wrong_sentence_type"), + ("a1_weather_seasons_l10_q3", "D", "Dzisiaj pada deszcz, a jutro będzie słońce.", "Дни перепутаны местами.", "Дні переплутані місцями.", "Days are swapped.", False, "wrong_context"), + ] + + for opt in options_t8: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t8 = [ + ("a1_weather_seasons_t01", None, "topic_test", "recognition", "weather_vocabulary", 1, + "Jak po polsku „дождь”?", "Как по-польски «дождь»?", "Як польською «дощ»?", "How do you say “rain” in Polish?", + "A", None, None, 1), + ("a1_weather_seasons_t02", None, "topic_test", "recognition", "weather_vocabulary", 1, + "Jak po polsku „жарко”?", "Как по-польски «жарко»?", "Як польською «спекотно»?", "How do you say “hot” (weather) in Polish?", + "C", None, None, 2), + ("a1_weather_seasons_t03", None, "topic_test", "recognition", "weather_description", 1, + "Wybierz poprawną formę: Pogoda jest ___. (ładny)", "Выберите правильную форму: Pogoda jest ___. (ładny)", "Виберіть правильну форму: Pogoda jest ___. (ładny)", "Choose the correct form: Pogoda jest ___. (ładny)", + "B", None, None, 3), + ("a1_weather_seasons_t04", None, "topic_test", "recognition", "seasons_vocabulary", 2, + "Jak po polsku „осень”?", "Как по-польски «осень»?", "Як польською «осінь»?", "How do you say “autumn” in Polish?", + "B", None, None, 4), + ("a1_weather_seasons_t05", None, "topic_test", "recognition", "seasons_time", 2, + "Wybierz poprawną formę: ___ pada śnieg. (zima)", "Выберите правильную форму: ___ pada śnieg. (zima)", "Виберіть правильну форму: ___ pada śnieg. (zima)", "Choose the correct form: ___ pada śnieg. (zima)", + "A", None, None, 5), + ("a1_weather_seasons_t06", None, "topic_test", "recognition", "weather_forecast", 3, + "Co znaczy „Jutro będzie padać deszcz”?", "Что означает «Jutro będzie padać deszcz»?", "Що означає «Jutro będzie padać deszcz»?", "What does “Jutro będzie padać deszcz” mean?", + "A", None, None, 6), + + ("a1_weather_seasons_t07", None, "topic_test", "application", "weather_vocabulary", 1, + "Widzisz krople wody spadające z nieba. Co się dzieje?", "Ты видишь капли воды, падающие с неба. Что происходит?", "Ти бачиш краплі води, що падають з неба. Що відбувається?", "You see drops of water falling from the sky. What's happening?", + "A", None, None, 7), + ("a1_weather_seasons_t08", None, "topic_test", "application", "weather_description", 1, + "Na niebie jest dużo chmur. Jakie jest niebo?", "На небе много облаков. Какое небо?", "На небі багато хмар. Яке небо?", "There are many clouds in the sky. What is the sky like?", + "A", None, None, 8), + ("a1_weather_seasons_t09", None, "topic_test", "application", "seasons_vocabulary", 2, + "Kolega pyta, jaką porę roku lubisz. Lubisz lato. Co powiesz?", "Друг спрашивает, какое время года ты любишь. Ты любишь лето. Что ты скажешь?", "Друг питає, яку пору року ти любиш. Ти любиш літо. Що ти скажеш?", "A friend asks what season you like. You like summer. What do you say?", + "A", None, None, 9), + ("a1_weather_seasons_t10", None, "topic_test", "application", "seasons_time", 2, + "Chcesz powiedzieć, że latem jest gorąco. Co powiesz?", "Ты хочешь сказать, что летом жарко. Что ты скажешь?", "Ти хочеш сказати, що влітку спекотно. Що ти скажеш?", "You want to say that it's hot in summer. What do you say?", + "A", None, None, 10), + ("a1_weather_seasons_t11", None, "topic_test", "application", "weather_forecast", 3, + "Sprawdzasz prognozę: jutro pada deszcz. Co powiesz?", "Ты смотришь прогноз: завтра дождь. Что ты скажешь?", "Ти дивишся прогноз: завтра дощ. Що ти скажеш?", "You check the forecast: rain tomorrow. What do you say?", + "A", None, None, 11), + ("a1_weather_seasons_t12", None, "topic_test", "application", "weather_forecast", 3, + "Chcesz opisać koledze pogodę: dziś słońce, jutro deszcz. Jak zaczniesz zdanie?", "Ты хочешь описать другу погоду: сегодня солнце, завтра дождь. Как ты начнёшь предложение?", "Ти хочеш описати другу погоду: сьогодні сонце, завтра дощ. Як ти почнеш речення?", "You want to describe the weather to a friend: sun today, rain tomorrow. How do you start the sentence?", + "A", None, None, 12), + + ("a1_weather_seasons_t13", None, "topic_test", "production", "weather_vocabulary", 1, + "Wpisz brakujące słowo: Jest bardzo ___. (холодно)", "Вставьте пропущенное слово: Jest bardzo ___. (холодно)", "Вставте пропущене слово: Jest bardzo ___. (холодно)", "Fill in the missing word: Jest bardzo ___. (cold)", + "zimno", "first_letter", "z", 13), + ("a1_weather_seasons_t14", None, "topic_test", "production", "weather_description", 1, + "Wpisz brakujące słowo: Niebo jest ___. (облачное)", "Вставьте пропущенное слово: Niebo jest ___. (облачное)", "Вставте пропущене слово: Niebo jest ___. (хмарне)", "Fill in the missing word: Niebo jest ___. (cloudy)", + "zachmurzone", "first_letter", "z", 14), + ("a1_weather_seasons_t15", None, "topic_test", "production", "seasons_vocabulary", 2, + "Wpisz brakujące słowo: Lubię ___. (осень)", "Вставьте пропущенное слово: Lubię ___. (осень)", "Вставте пропущене слово: Lubię ___. (осінь)", "Fill in the missing word: Lubię ___. (autumn)", + "jesień", "first_letter", "j", 15), + ("a1_weather_seasons_t16", None, "topic_test", "production", "seasons_time", 2, + "Wpisz brakujące słowo: ___ jest ciepło. (весной)", "Вставьте пропущенное слово: ___ jest ciepło. (весной)", "Вставте пропущене слово: ___ jest ciepło. (навесні)", "Fill in the missing word: ___ jest ciepło. (in spring)", + "Wiosną", "first_letter", "W", 16), + ("a1_weather_seasons_t17", None, "topic_test", "production", "weather_forecast", 3, + "Wpisz brakujące słowo: Jutro ___ zimno. (будет)", "Вставьте пропущенное слово: Jutro ___ zimno. (будет)", "Вставте пропущене слово: Jutro ___ zimno. (буде)", "Fill in the missing word: Jutro ___ zimno. (will be)", + "będzie", "first_letter", "b", 17), + ("a1_weather_seasons_t18", None, "topic_test", "production", "seasons_time", 2, + "Przetłumacz: «Осенью идёт дождь и дует ветер».", "Переведите: «Осенью идёт дождь и дует ветер».", "Перекладіть: «Восени йде дощ і дме вітер».", "Translate: “In autumn it rains and the wind blows.”", + "Jesienią pada deszcz i wieje wiatr", "first_letter", "J", 18), + + ("a1_weather_seasons_t19", None, "topic_test", "mixed", "weather_forecast", 3, + "Wybierz poprawne tłumaczenie: «Сегодня тепло, но завтра будет холодно».", "Выберите правильный перевод: «Сегодня тепло, но завтра будет холодно».", "Виберіть правильний переклад: «Сьогодні тепло, але завтра буде холодно».", "Choose the correct translation: “Today it's warm, but tomorrow it will be cold.”", + "A", None, None, 19), + ("a1_weather_seasons_t20", None, "topic_test", "mixed", "weather_forecast", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Какая сегодня погода? — Сегодня светит солнце, а завтра будет идти дождь.»", "Выберите правильный перевод диалога: «— Какая сегодня погода? — Сегодня светит солнце, а завтра будет идти дождь.»", "Виберіть правильний переклад діалогу: «— Яка сьогодні погода? — Сьогодні світить сонце, а завтра йтиме дощ.»", "Choose the correct translation of the dialogue: “— What's the weather like today? — Today the sun is shining, and tomorrow it will rain.”", + "A", None, None, 20), + ] + + for q in test_questions_t8: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_weather_seasons', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t8 = [ + ("a1_weather_seasons_t01", "A", "deszcz", "дождь", "дощ", "rain", True, None), + ("a1_weather_seasons_t01", "B", "śnieg", "снег", "сніг", "snow", False, "wrong_word"), + ("a1_weather_seasons_t01", "C", "wiatr", "ветер", "вітер", "wind", False, "wrong_word"), + ("a1_weather_seasons_t01", "D", "słońce", "солнце", "сонце", "sun", False, "wrong_word"), + + ("a1_weather_seasons_t02", "A", "zimno", "холодно", "холодно", "cold", False, "wrong_word"), + ("a1_weather_seasons_t02", "B", "chłodno", "прохладно", "прохолодно", "cool", False, "wrong_word"), + ("a1_weather_seasons_t02", "C", "gorąco", "жарко", "спекотно", "hot", True, None), + ("a1_weather_seasons_t02", "D", "ciepło", "тепло", "тепло", "warm", False, "wrong_word"), + + ("a1_weather_seasons_t03", "A", "ładny", "хороший (муж.)", "гарний (чол.)", "nice (masc.)", False, "wrong_gender"), + ("a1_weather_seasons_t03", "B", "ładna", "хорошая (жен.)", "гарна (жін.)", "nice (fem.)", True, None), + ("a1_weather_seasons_t03", "C", "ładne", "хорошее (ср.)", "гарне (сер.)", "nice (neut.)", False, "wrong_gender"), + ("a1_weather_seasons_t03", "D", "ładną", "хорошую (вин.)", "гарну (знах.)", "nice (acc.)", False, "wrong_case"), + + ("a1_weather_seasons_t04", "A", "zima", "зима", "зима", "winter", False, "wrong_word"), + ("a1_weather_seasons_t04", "B", "jesień", "осень", "осінь", "autumn", True, None), + ("a1_weather_seasons_t04", "C", "wiosna", "весна", "весна", "spring", False, "wrong_word"), + ("a1_weather_seasons_t04", "D", "lato", "лето", "літо", "summer", False, "wrong_word"), + + ("a1_weather_seasons_t05", "A", "Zimą", "Зимой", "Взимку", "In winter", True, None), + ("a1_weather_seasons_t05", "B", "Zima", "Зима (им.)", "Зима (наз.)", "Winter (nom.)", False, "wrong_case"), + ("a1_weather_seasons_t05", "C", "Zimę", "Зиму (вин.)", "Зиму (знах.)", "Winter (acc.)", False, "wrong_case"), + ("a1_weather_seasons_t05", "D", "Zimy", "Зимы (род.)", "Зими (род.)", "Winter (gen.)", False, "wrong_case"), + + ("a1_weather_seasons_t06", "A", "Завтра будет идти дождь.", "Завтра будет идти дождь.", "Завтра йтиме дощ.", "Tomorrow it will rain.", True, None), + ("a1_weather_seasons_t06", "B", "Вчера шёл дождь.", "Вчера шёл дождь.", "Вчора йшов дощ.", "It rained yesterday.", False, "wrong_translation"), + ("a1_weather_seasons_t06", "C", "Сегодня идёт дождь.", "Сегодня идёт дождь.", "Сьогодні йде дощ.", "It's raining today.", False, "wrong_translation"), + ("a1_weather_seasons_t06", "D", "Завтра будет холодно.", "Завтра будет холодно.", "Завтра буде холодно.", "Tomorrow it will be cold.", False, "wrong_translation"), + + ("a1_weather_seasons_t07", "A", "Pada deszcz.", "Идёт дождь.", "Йде дощ.", "It's raining.", True, None), + ("a1_weather_seasons_t07", "B", "Świeci słońce.", "Светит солнце.", "Світить сонце.", "The sun is shining.", False, "wrong_context"), + ("a1_weather_seasons_t07", "C", "Wieje wiatr.", "Дует ветер.", "Дме вітер.", "The wind is blowing.", False, "wrong_context"), + ("a1_weather_seasons_t07", "D", "Pada śnieg.", "Идёт снег.", "Йде сніг.", "It's snowing.", False, "wrong_context"), + + ("a1_weather_seasons_t08", "A", "Niebo jest zachmurzone.", "Небо облачное.", "Небо хмарне.", "The sky is cloudy.", True, None), + ("a1_weather_seasons_t08", "B", "Niebo jest czyste.", "Небо чистое. (противоречит описанию)", "Небо чисте. (суперечить опису)", "The sky is clear. (contradicts the description)", False, "wrong_context"), + ("a1_weather_seasons_t08", "C", "Pogoda jest słoneczna.", "Погода солнечная. (не соответствует контексту)", "Погода сонячна. (не відповідає контексту)", "The weather is sunny. (wrong context)", False, "wrong_context"), + ("a1_weather_seasons_t08", "D", "Jest gorąco.", "Жарко. (не о небе)", "Спекотно. (не про небо)", "It's hot. (not about the sky)", False, "wrong_context"), + + ("a1_weather_seasons_t09", "A", "Lubię lato.", "Я люблю лето.", "Я люблю літо.", "I like summer.", True, None), + ("a1_weather_seasons_t09", "B", "Lubię lata.", "Неправильная форма.", "Неправильна форма.", "Wrong form.", False, "wrong_case"), + ("a1_weather_seasons_t09", "C", "Jestem lato.", "Я лето.", "Я літо.", "I am summer.", False, "wrong_sentence_type"), + ("a1_weather_seasons_t09", "D", "Lubię zimę.", "Я люблю зиму. (неверное время года)", "Я люблю зиму. (невірна пора року)", "I like winter. (wrong season)", False, "wrong_context"), + + ("a1_weather_seasons_t10", "A", "Latem jest gorąco.", "Летом жарко.", "Влітку спекотно.", "In summer it's hot.", True, None), + ("a1_weather_seasons_t10", "B", "Lato jest gorąco.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_weather_seasons_t10", "C", "Zimą jest gorąco.", "Зимой жарко. (неверная пора года)", "Взимку спекотно. (невірна пора року)", "In winter it's hot. (wrong season)", False, "wrong_context"), + ("a1_weather_seasons_t10", "D", "Jest gorąco latem pora.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + ("a1_weather_seasons_t11", "A", "Jutro będzie padać deszcz.", "Завтра будет идти дождь.", "Завтра йтиме дощ.", "Tomorrow it will rain.", True, None), + ("a1_weather_seasons_t11", "B", "Wczoraj padał deszcz.", "Вчера шёл дождь. (неверное время)", "Вчора йшов дощ. (невірний час)", "It rained yesterday. (wrong tense)", False, "wrong_context"), + ("a1_weather_seasons_t11", "C", "Dziś pada deszcz.", "Сегодня идёт дождь. (неверное время)", "Сьогодні йде дощ. (невірний час)", "It's raining today. (wrong tense)", False, "wrong_context"), + ("a1_weather_seasons_t11", "D", "Jutro będzie gorąco.", "Завтра будет жарко. (неверный прогноз)", "Завтра буде спекотно. (невірний прогноз)", "Tomorrow it will be hot. (wrong forecast)", False, "wrong_context"), + + ("a1_weather_seasons_t12", "A", "Dzisiaj świeci słońce, a jutro będzie padać deszcz.", "Сегодня светит солнце, а завтра будет идти дождь.", "Сьогодні світить сонце, а завтра йтиме дощ.", "Today the sun is shining, and tomorrow it will rain.", True, None), + ("a1_weather_seasons_t12", "B", "Ja słońce i deszcz.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_weather_seasons_t12", "C", "Jestem słońce, a jutro deszcz.", "Я солнце, а завтра дождь.", "Я сонце, а завтра дощ.", "I am the sun, and tomorrow rain. (wrong construction)", False, "wrong_sentence_type"), + ("a1_weather_seasons_t12", "D", "Dzisiaj pada deszcz, a jutro będzie słońce.", "Дни перепутаны местами.", "Дні переплутані місцями.", "Days are swapped.", False, "wrong_context"), + + ("a1_weather_seasons_t19", "A", "Dziś jest ciepło, ale jutro będzie zimno.", "Сегодня тепло, но завтра будет холодно.", "Сьогодні тепло, але завтра буде холодно.", "Today it's warm, but tomorrow it will be cold.", True, None), + ("a1_weather_seasons_t19", "B", "Dziś jest zimno, ale jutro było ciepło.", "Неправильное время.", "Неправильний час.", "Wrong tense.", False, "wrong_sentence_type"), + ("a1_weather_seasons_t19", "C", "Jutro jest ciepło, ale dziś będzie zimno.", "Дни перепутаны.", "Дні переплутані.", "Days are swapped.", False, "wrong_context"), + ("a1_weather_seasons_t19", "D", "Dziś będzie ciepło, ale jutro jest zimno.", "Времена перепутаны.", "Часи переплутані.", "Tenses are swapped.", False, "wrong_sentence_type"), + + ("a1_weather_seasons_t20", "A", "Jaka jest dziś pogoda? Dzisiaj świeci słońce, a jutro będzie padać deszcz.", "Какая сегодня погода? Сегодня светит солнце, а завтра будет идти дождь.", "Яка сьогодні погода? Сьогодні світить сонце, а завтра йтиме дощ.", "What's the weather like today? Today the sun is shining, and tomorrow it will rain.", True, None), + ("a1_weather_seasons_t20", "B", "Jaka jest dziś pogoda? Wczoraj świeciło słońce.", "Неправильное время в ответе.", "Неправильний час у відповіді.", "Wrong tense in the answer.", False, "wrong_sentence_type"), + ("a1_weather_seasons_t20", "C", "Ile kosztuje pogoda? Dzisiaj świeci słońce.", "Неправильный вопрос.", "Неправильне питання.", "Wrong question.", False, "wrong_translation"), + ("a1_weather_seasons_t20", "D", "Jaka jest dziś pogoda? Dzisiaj pada deszcz, a jutro będzie słońce.", "Дни перепутаны в ответе.", "Дні переплутані у відповіді.", "Days are swapped in the answer.", False, "wrong_context"), + ] + + for opt in test_options_t8: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 9: ТРАНСПОРТ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_transport', 'A1', 9, + 'Transport', + 'Транспорт', + 'Транспорт', + 'Transport') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t9 = [ + ("a1_transport_l01", 1, "transport_vocabulary", "Podstawowe środki transportu", "Основные виды транспорта", "Основні види транспорту", "Basic means of transport", + "Podstawowe środki transportu: autobus, tramwaj, pociąg, samochód. Wszystkie te słowa są rodzaju męskiego.", + "Основные виды транспорта: autobus (автобус), tramwaj (трамвай), pociąg (поезд), samochód (машина). Все эти слова мужского рода.", + "Основні види транспорту: autobus (автобус), tramwaj (трамвай), pociąg (потяг), samochód (машина). Усі ці слова чоловічого роду.", + "Basic means of transport: autobus (bus), tramwaj (tram), pociąg (train), samochód (car). All these words are masculine."), + + ("a1_transport_l02", 2, "transport_vocabulary_more", "Więcej środków transportu", "Больше видов транспорта", "Більше видів транспорту", "More means of transport", + "Więcej środków transportu: rower, samolot, metro, taksówka. „Rower” i „samolot” są rodzaju męskiego, „metro” jest rodzaju nijakiego, „taksówka” jest rodzaju żeńskiego.", + "Больше видов транспорта: rower (велосипед), samolot (самолёт), metro (метро), taksówka (такси). „Rower” и „samolot” мужского рода, „metro” среднего рода, „taksówka” женского рода.", + "Більше видів транспорту: rower (велосипед), samolot (літак), metro (метро), taksówka (таксі). „Rower” і „samolot” чоловічого роду, „metro” середнього роду, „taksówka” жіночого роду.", + "More means of transport: rower (bike), samolot (plane), metro (subway), taksówka (taxi). „Rower” and „samolot” are masculine, „metro” is neuter, „taksówka” is feminine."), + + ("a1_transport_l03", 3, "transport_verb_jechac", "Jadę, jedziesz — czasownik jechać", "Jadę, jedziesz — глагол jechać", "Jadę, jedziesz — дієслово jechać", "Jadę, jedziesz — the verb jechać", + "Czasownika „jechać” używamy dla podróży pojazdem: ja jadę, ty jedziesz, on/ona jedzie.", + "Глагол „jechać” (ехать) используем для поездки на транспорте: ja jadę (я еду), ty jedziesz (ты едешь), on/ona jedzie (он/она едет).", + "Дієслово „jechać” (їхати) використовуємо для подорожі транспортом: ja jadę (я їду), ty jedziesz (ти їдеш), on/ona jedzie (він/вона їде).", + "The verb „jechać” (to go/ride) is used for travelling by vehicle: ja jadę (I go), ty jedziesz (you go), on/ona jedzie (he/she goes)."), + + ("a1_transport_l04", 4, "transport_verb_isc", "Idę czy jadę? — iść i jechać", "Idę czy jadę? — иду или еду", "Idę czy jadę? — йду чи їду", "Idę or jadę? — iść vs jechać", + "„Iść” używamy, gdy idziemy pieszo: idę do szkoły. „Jechać” używamy, gdy podróżujemy pojazdem: jadę do szkoły autobusem.", + "„Iść” используем, когда идём пешком: idę do szkoły (я иду в школу). „Jechać” используем, когда путешествуем на транспорте: jadę do szkoły autobusem (я еду в школу на автобусе).", + "„Iść” використовуємо, коли йдемо пішки: idę do szkoły (я йду до школи). „Jechać” використовуємо, коли подорожуємо транспортом: jadę do szkoły autobusem (я їду до школи автобусом).", + "„Iść” is used when going on foot: idę do szkoły (I'm going to school). „Jechać” is used when travelling by vehicle: jadę do szkoły autobusem (I'm going to school by bus)."), + + ("a1_transport_l05", 5, "transport_instrumental", "Jadę autobusem — narzędnik", "Jadę autobusem — творительный падеж", "Jadę autobusem — орудний відмінок", "Jadę autobusem — the instrumental", + "Żeby powiedzieć, jakim środkiem transportu jedziemy, używamy narzędnika bez przyimka: autobus → autobusem, tramwaj → tramwajem, pociąg → pociągiem, samochód → samochodem, rower → rowerem.", + "Чтобы сказать, на каком транспорте едем, используем творительный падеж без предлога: autobus → autobusem, tramwaj → tramwajem, pociąg → pociągiem, samochód → samochodem, rower → rowerem.", + "Щоб сказати, яким транспортом їдемо, використовуємо орудний відмінок без прийменника: autobus → autobusem, tramwaj → tramwajem, pociąg → pociągiem, samochód → samochodem, rower → rowerem.", + "To say which vehicle you're travelling by, we use the instrumental without a preposition: autobus → autobusem, tramwaj → tramwajem, pociąg → pociągiem, samochód → samochodem, rower → rowerem."), + + ("a1_transport_l06", 6, "transport_ticket", "Kupuję bilet", "Покупаю билет", "Купую квиток", "Buying a ticket", + "„Bilet” jest rodzaju męskiego. Po „mam” i „kupuję” rzeczowniki męskie nieżywotne się nie zmieniają: mam bilet, kupuję bilet.", + "„Bilet” (билет) мужского рода. После „mam” и „kupuję” мужские неодушевлённые существительные не меняются: mam bilet, kupuję bilet.", + "„Bilet” (квиток) чоловічого роду. Після „mam” і „kupuję” чоловічі неістоти не змінюються: mam bilet, kupuję bilet.", + "„Bilet” (ticket) is masculine. After „mam” and „kupuję”, masculine inanimate nouns don't change: mam bilet, kupuję bilet."), + + ("a1_transport_l07", 7, "transport_asking_directions", "Jak dojadę do...?", "Как мне доехать до...?", "Як мені доїхати до...?", "How do I get to...?", + "Pytania „Jak dojadę do + dopełniacz?” używamy, gdy pytamy, jak dotrzeć do miejsca. Przykład: Jak dojadę do dworca?", + "Вопрос „Jak dojadę do + родительный падеж?” используем, когда спрашиваем, как добраться до места. Пример: Jak dojadę do dworca? (Как мне доехать до вокзала?)", + "Питання „Jak dojadę do + родовий відмінок?” використовуємо, коли запитуємо, як дістатися до місця. Приклад: Jak dojadę do dworca? (Як мені доїхати до вокзалу?)", + "We use the question „Jak dojadę do + genitive?” to ask how to get to a place. Example: Jak dojadę do dworca? (How do I get to the station?)"), + + ("a1_transport_l08", 8, "transport_places", "Przystanek, dworzec, lotnisko", "Остановка, вокзал, аэропорт", "Зупинка, вокзал, аеропорт", "Stop, station, airport", + "Miejsca związane z transportem: przystanek (autobusowy lub tramwajowy), dworzec (kolejowy), lotnisko, stacja (metra).", + "Места, связанные с транспортом: przystanek (остановка автобуса или трамвая), dworzec (вокзал), lotnisko (аэропорт), stacja (станция метро).", + "Місця, пов'язані з транспортом: przystanek (зупинка автобуса чи трамвая), dworzec (вокзал), lotnisko (аеропорт), stacja (станція метро).", + "Places related to transport: przystanek (bus or tram stop), dworzec (train station), lotnisko (airport), stacja (metro station)."), + + ("a1_transport_l09", 9, "transport_frequency", "Jak często jeździsz...?", "Как часто ты ездишь...?", "Як часто ти їздиш...?", "How often do you go...?", + "Gdy mówimy o częstotliwości, używamy czasownika „jeździć” (a nie „jechać”): często jeżdżę, rzadko jeżdżę. Pytamy „Jak często jeździsz + narzędnik?” Odpowiadamy przysłówkami: często, czasami, rzadko, codziennie, zawsze, nigdy.", + "Когда говорим о частоте, используем глагол „jeździć” (а не „jechać”): często jeżdżę (я часто езжу), rzadko jeżdżę (я редко езжу). Спрашиваем „Jak często jeździsz + творительный падеж?” Отвечаем наречиями: często, czasami, rzadko, codziennie, zawsze, nigdy.", + "Коли говоримо про частоту, використовуємо дієслово „jeździć” (а не „jechać”): często jeżdżę (я часто їжджу), rzadko jeżdżę (я рідко їжджу). Запитуємо „Jak często jeździsz + орудний відмінок?” Відповідаємо прислівниками: często, czasami, rzadko, codziennie, zawsze, nigdy.", + "When talking about frequency, we use the verb „jeździć” (not „jechać”): często jeżdżę (I often go), rzadko jeżdżę (I rarely go). We ask „Jak często jeździsz + instrumental?” We answer with adverbs: często, czasami, rzadko, codziennie, zawsze, nigdy."), + + ("a1_transport_l10", 10, "transport_description", "Opisuję swoją podróż do pracy", "Описываю свою поездку на работу", "Описую свою поїздку на роботу", "Describing my trip to work", + "Żeby opisać codzienną podróż, łączymy kilka zdań: Codziennie jadę do pracy autobusem. Bilet kupuję w kiosku. Podróż trwa dwadzieścia minut.", + "Чтобы описать ежедневную поездку, соединяем несколько предложений: Codziennie jadę do pracy autobusem. Bilet kupuję w kiosku. Podróż trwa dwadzieścia minut. (Каждый день я еду на работу на автобусе. Билет покупаю в киоске. Поездка длится двадцать минут.)", + "Щоб описати щоденну поїздку, поєднуємо кілька речень: Codziennie jadę do pracy autobusem. Bilet kupuję w kiosku. Podróż trwa dwadzieścia minut. (Щодня я їду на роботу автобусом. Квиток купую в кіоску. Поїздка триває двадцять хвилин.)", + "To describe a daily trip, we combine several sentences: Codziennie jadę do pracy autobusem. Bilet kupuję w kiosku. Podróż trwa dwadzieścia minut. (Every day I go to work by bus. I buy the ticket at the kiosk. The trip takes twenty minutes.)"), + ] + + for lesson in lessons_t9: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_transport', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t9 = [ + ("a1_transport_l01", 1, "Jadę autobusem.", "Я еду на автобусе.", "Я їду автобусом.", "I'm going by bus."), + ("a1_transport_l01", 2, "Tramwaj jest szybki.", "Трамвай быстрый.", "Трамвай швидкий.", "The tram is fast."), + ("a1_transport_l01", 3, "Pociąg jedzie do Warszawy.", "Поезд едет в Варшаву.", "Потяг їде до Варшави.", "The train is going to Warsaw."), + + ("a1_transport_l02", 1, "Mam nowy rower.", "У меня новый велосипед.", "У мене новий велосипед.", "I have a new bike."), + ("a1_transport_l02", 2, "Samolot leci do Krakowa.", "Самолёт летит в Краков.", "Літак летить до Кракова.", "The plane is flying to Kraków."), + ("a1_transport_l02", 3, "Jadę metrem do centrum.", "Я еду на метро в центр.", "Я їду метро в центр.", "I'm going by subway to the center."), + + ("a1_transport_l03", 1, "Jadę do pracy.", "Я еду на работу.", "Я їду на роботу.", "I'm going to work."), + ("a1_transport_l03", 2, "Jedziesz do domu?", "Ты едешь домой?", "Ти їдеш додому?", "Are you going home?"), + ("a1_transport_l03", 3, "On jedzie do szkoły autobusem.", "Он едет в школу на автобусе.", "Він їде до школи автобусом.", "He's going to school by bus."), + + ("a1_transport_l04", 1, "Idę do szkoły pieszo.", "Я иду в школу пешком.", "Я йду до школи пішки.", "I'm walking to school."), + ("a1_transport_l04", 2, "Jadę do pracy samochodem.", "Я еду на работу на машине.", "Я їду на роботу машиною.", "I'm driving to work by car."), + ("a1_transport_l04", 3, "Idziesz czy jedziesz?", "Ты идёшь пешком или едешь?", "Ти йдеш пішки чи їдеш?", "Are you walking or riding?"), + + ("a1_transport_l05", 1, "Jadę autobusem.", "Я еду на автобусе.", "Я їду автобусом.", "I'm going by bus."), + ("a1_transport_l05", 2, "Jedziemy pociągiem.", "Мы едем на поезде.", "Ми їдемо потягом.", "We're going by train."), + ("a1_transport_l05", 3, "Jedzie rowerem do parku.", "Он/она едет на велосипеде в парк.", "Він/вона їде велосипедом до парку.", "He/she is riding a bike to the park."), + + ("a1_transport_l06", 1, "Kupuję bilet na dworcu.", "Я покупаю билет на вокзале.", "Я купую квиток на вокзалі.", "I buy a ticket at the station."), + ("a1_transport_l06", 2, "Mam bilet na pociąg.", "У меня есть билет на поезд.", "У мене є квиток на потяг.", "I have a train ticket."), + ("a1_transport_l06", 3, "Ile kosztuje bilet?", "Сколько стоит билет?", "Скільки коштує квиток?", "How much does the ticket cost?"), + + ("a1_transport_l07", 1, "Jak dojadę do dworca?", "Как мне доехать до вокзала?", "Як мені доїхати до вокзалу?", "How do I get to the station?"), + ("a1_transport_l07", 2, "Jak dojadę do lotniska?", "Как мне доехать до аэропорта?", "Як мені доїхати до аеропорту?", "How do I get to the airport?"), + ("a1_transport_l07", 3, "Przepraszam, jak dojadę do centrum?", "Извините, как мне доехать до центра?", "Перепрошую, як мені доїхати до центру?", "Excuse me, how do I get to the center?"), + + ("a1_transport_l08", 1, "Przystanek jest blisko.", "Остановка близко.", "Зупинка близько.", "The stop is close."), + ("a1_transport_l08", 2, "Dworzec jest w centrum.", "Вокзал в центре.", "Вокзал у центрі.", "The station is downtown."), + ("a1_transport_l08", 3, "Lotnisko jest daleko od miasta.", "Аэропорт далеко от города.", "Аеропорт далеко від міста.", "The airport is far from the city."), + + ("a1_transport_l09", 1, "Często jeżdżę autobusem.", "Я часто езжу на автобусе.", "Я часто їжджу автобусом.", "I often go by bus."), + ("a1_transport_l09", 2, "Rzadko jeżdżę samochodem.", "Я редко езжу на машине.", "Я рідко їжджу машиною.", "I rarely go by car."), + ("a1_transport_l09", 3, "Nigdy nie jeżdżę metrem.", "Я никогда не езжу на метро.", "Я ніколи не їжджу метро.", "I never go by subway."), + + ("a1_transport_l10", 1, "Codziennie jadę do pracy autobusem.", "Каждый день я еду на работу на автобусе.", "Щодня я їду на роботу автобусом.", "Every day I go to work by bus."), + ("a1_transport_l10", 2, "Bilet kupuję w kiosku.", "Билет я покупаю в киоске.", "Квиток я купую в кіоску.", "I buy the ticket at the kiosk."), + ("a1_transport_l10", 3, "Podróż trwa dwadzieścia minut.", "Поездка длится двадцать минут.", "Поїздка триває двадцять хвилин.", "The trip takes twenty minutes."), + ] + + for ex in examples_t9: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t9 = [ + # L01 — transport_vocabulary (difficulty 1) + ("a1_transport_l01_q1", "a1_transport_l01", "lesson_practice", "recognition", "transport_vocabulary", 1, + "Jak po polsku „автобус”?", "Как по-польски «автобус»?", "Як польською «автобус»?", "How do you say “bus” in Polish?", + "A", None, None), + ("a1_transport_l01_q2", "a1_transport_l01", "lesson_practice", "production", "transport_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (поезд)", "Вставьте пропущенное слово: To jest ___. (поезд)", "Вставте пропущене слово: To jest ___. (потяг)", "Fill in the missing word: To jest ___. (train)", + "pociąg", "first_letter", "p"), + ("a1_transport_l01_q3", "a1_transport_l01", "lesson_practice", "application", "transport_vocabulary", 1, + "Widzisz duży pojazd, który jeździ po szynach w mieście. Co to jest?", "Ты видишь большой транспорт, который ездит по рельсам в городе. Что это?", "Ти бачиш великий транспорт, що їздить по рейках у місті. Що це?", "You see a big vehicle running on rails in the city. What is it?", + "B", None, None), + + # L02 — transport_vocabulary_more (difficulty 1) + ("a1_transport_l02_q1", "a1_transport_l02", "lesson_practice", "recognition", "transport_vocabulary_more", 1, + "Jak po polsku „такси”?", "Как по-польски «такси»?", "Як польською «таксі»?", "How do you say “taxi” in Polish?", + "A", None, None), + ("a1_transport_l02_q2", "a1_transport_l02", "lesson_practice", "production", "transport_vocabulary_more", 1, + "Wpisz brakujące słowo: To jest ___. (велосипед)", "Вставьте пропущенное слово: To jest ___. (велосипед)", "Вставте пропущене слово: To jest ___. (велосипед)", "Fill in the missing word: To jest ___. (bike)", + "rower", "first_letter", "r"), + ("a1_transport_l02_q3", "a1_transport_l02", "lesson_practice", "application", "transport_vocabulary_more", 1, + "Chcesz szybko polecieć nad oceanem. Czym polecisz?", "Ты хочешь быстро перелететь через океан. Чем ты полетишь?", "Ти хочеш швидко перелетіти через океан. Чим ти полетиш?", "You want to quickly fly over the ocean. What do you fly?", + "B", None, None), + + # L03 — transport_verb_jechac (difficulty 1) + ("a1_transport_l03_q1", "a1_transport_l03", "lesson_practice", "recognition", "transport_verb_jechac", 1, + "Wybierz poprawną formę: Ja ___. (jechać)", "Выберите правильную форму: Ja ___. (jechać)", "Виберіть правильну форму: Ja ___. (jechać)", "Choose the correct form: Ja ___. (jechać)", + "A", None, None), + ("a1_transport_l03_q2", "a1_transport_l03", "lesson_practice", "production", "transport_verb_jechac", 1, + "Wpisz brakujące słowo: Ty ___ do domu. (едешь)", "Вставьте пропущенное слово: Ty ___ do domu. (едешь)", "Вставте пропущене слово: Ty ___ do domu. (їдеш)", "Fill in the missing word: Ty ___ do domu. (you go)", + "jedziesz", "first_letter", "j"), + ("a1_transport_l03_q3", "a1_transport_l03", "lesson_practice", "application", "transport_verb_jechac", 1, + "Kolega pyta, dokąd jedziesz. Jedziesz do pracy. Co powiesz?", "Друг спрашивает, куда ты едешь. Ты едешь на работу. Что ты скажешь?", "Друг питає, куди ти їдеш. Ти їдеш на роботу. Що ти скажеш?", "A friend asks where you're going. You're going to work. What do you say?", + "A", None, None), + + # L04 — transport_verb_isc (difficulty 1) + ("a1_transport_l04_q1", "a1_transport_l04", "lesson_practice", "recognition", "transport_verb_isc", 1, + "Idziesz pieszo do sklepu, który jest blisko. Jak powiesz?", "Ты идёшь пешком в магазин, который близко. Что ты скажешь?", "Ти йдеш пішки до магазину, який близько. Що ти скажеш?", "You're walking to a nearby shop. What do you say?", + "A", None, None), + ("a1_transport_l04_q2", "a1_transport_l04", "lesson_practice", "production", "transport_verb_isc", 1, + "Wpisz brakujące słowo: ___ do szkoły pieszo. (иду)", "Вставьте пропущенное слово: ___ do szkoły pieszo. (иду)", "Вставте пропущене слово: ___ do szkoły pieszo. (йду)", "Fill in the missing word: ___ do szkoły pieszo. (I go)", + "Idę", "first_letter", "I"), + ("a1_transport_l04_q3", "a1_transport_l04", "lesson_practice", "application", "transport_verb_isc", 1, + "Sklep jest bardzo daleko. Idziesz czy jedziesz?", "Магазин очень далеко. Ты идёшь пешком или едешь?", "Магазин дуже далеко. Ти йдеш пішки чи їдеш?", "The shop is very far. Are you walking or riding?", + "B", None, None), + + # L05 — transport_instrumental (difficulty 2) + ("a1_transport_l05_q1", "a1_transport_l05", "lesson_practice", "recognition", "transport_instrumental", 2, + "Wybierz poprawną formę: Jadę ___. (autobus)", "Выберите правильную форму: Jadę ___. (autobus)", "Виберіть правильну форму: Jadę ___. (autobus)", "Choose the correct form: Jadę ___. (autobus)", + "B", None, None), + ("a1_transport_l05_q2", "a1_transport_l05", "lesson_practice", "production", "transport_instrumental", 2, + "Wpisz brakujące słowo: Jadę ___. (поезд, творительный)", "Вставьте пропущенное слово: Jadę ___. (поезд, творительный)", "Вставте пропущене слово: Jadę ___. (потяг, орудний)", "Fill in the missing word: Jadę ___. (train, instrumental)", + "pociągiem", "first_letter", "p"), + ("a1_transport_l05_q3", "a1_transport_l05", "lesson_practice", "application", "transport_instrumental", 2, + "Chcesz powiedzieć, że jedziesz do pracy na rowerze. Co powiesz?", "Ты хочешь сказать, что едешь на работу на велосипеде. Что ты скажешь?", "Ти хочеш сказати, що їдеш на роботу на велосипеді. Що ти скажеш?", "You want to say you're going to work by bike. What do you say?", + "A", None, None), + + # L06 — transport_ticket (difficulty 2) + ("a1_transport_l06_q1", "a1_transport_l06", "lesson_practice", "recognition", "transport_ticket", 2, + "Jak po polsku „билет”?", "Как по-польски «билет»?", "Як польською «квиток»?", "How do you say “ticket” in Polish?", + "A", None, None), + ("a1_transport_l06_q2", "a1_transport_l06", "lesson_practice", "production", "transport_ticket", 2, + "Wpisz brakujące słowo: Kupuję ___. (билет)", "Вставьте пропущенное слово: Kupuję ___. (билет)", "Вставте пропущене слово: Kupuję ___. (квиток)", "Fill in the missing word: Kupuję ___. (ticket)", + "bilet", "first_letter", "b"), + ("a1_transport_l06_q3", "a1_transport_l06", "lesson_practice", "application", "transport_ticket", 2, + "Jesteś na dworcu i chcesz kupić bilet na pociąg. Co powiesz?", "Ты на вокзале и хочешь купить билет на поезд. Что ты скажешь?", "Ти на вокзалі і хочеш купити квиток на потяг. Що ти скажеш?", "You're at the station and want to buy a train ticket. What do you say?", + "A", None, None), + + # L07 — transport_asking_directions (difficulty 2) + ("a1_transport_l07_q1", "a1_transport_l07", "lesson_practice", "recognition", "transport_asking_directions", 2, + "Co oznacza „Jak dojadę do dworca?”", "Что означает «Jak dojadę do dworca?»", "Що означає «Jak dojadę do dworca?»", "What does “Jak dojadę do dworca?” mean?", + "A", None, None), + ("a1_transport_l07_q2", "a1_transport_l07", "lesson_practice", "production", "transport_asking_directions", 2, + "Wpisz brakujące słowo: Jak ___ do dworca? (доеду)", "Вставьте пропущенное слово: Jak ___ do dworca? (доеду)", "Вставте пропущене слово: Jak ___ do dworca? (доїду)", "Fill in the missing word: Jak ___ do dworca? (do I get)", + "dojadę", "first_letter", "d"), + ("a1_transport_l07_q3", "a1_transport_l07", "lesson_practice", "application", "transport_asking_directions", 2, + "Zgubiłeś się w mieście i chcesz zapytać, jak dotrzeć na lotnisko. Co powiesz?", "Ты заблудился в городе и хочешь спросить, как добраться до аэропорта. Что ты скажешь?", "Ти загубився в місті і хочеш запитати, як дістатися до аеропорту. Що ти скажеш?", "You're lost in the city and want to ask how to get to the airport. What do you say?", + "A", None, None), + + # L08 — transport_places (difficulty 2) + ("a1_transport_l08_q1", "a1_transport_l08", "lesson_practice", "recognition", "transport_places", 2, + "Jak po polsku „вокзал”?", "Как по-польски «вокзал»?", "Як польською «вокзал»?", "How do you say “train station” in Polish?", + "A", None, None), + ("a1_transport_l08_q2", "a1_transport_l08", "lesson_practice", "production", "transport_places", 2, + "Wpisz brakujące słowo: To jest ___. (аэропорт)", "Вставьте пропущенное слово: To jest ___. (аэропорт)", "Вставте пропущене слово: To jest ___. (аеропорт)", "Fill in the missing word: To jest ___. (airport)", + "lotnisko", "first_letter", "l"), + ("a1_transport_l08_q3", "a1_transport_l08", "lesson_practice", "application", "transport_places", 2, + "Czekasz na autobus w miejscu przy drodze. Gdzie jesteś?", "Ты ждёшь автобус в месте у дороги. Где ты?", "Ти чекаєш на автобус у місці біля дороги. Де ти?", "You're waiting for a bus at a spot by the road. Where are you?", + "B", None, None), + + # L09 — transport_frequency (difficulty 3) + ("a1_transport_l09_q1", "a1_transport_l09", "lesson_practice", "recognition", "transport_frequency", 3, + "Co znaczy „Jak często jeździsz autobusem?”", "Что означает «Jak często jeździsz autobusem?»", "Що означає «Jak często jeździsz autobusem?»", "What does “Jak często jeździsz autobusem?” mean?", + "A", None, None), + ("a1_transport_l09_q2", "a1_transport_l09", "lesson_practice", "production", "transport_frequency", 3, + "Wpisz brakujące słowo: ___ jeżdżę autobusem. (часто)", "Вставьте пропущенное слово: ___ jeżdżę autobusem. (часто)", "Вставте пропущене слово: ___ jeżdżę autobusem. (часто)", "Fill in the missing word: ___ jeżdżę autobusem. (often)", + "Często", "first_letter", "C"), + ("a1_transport_l09_q3", "a1_transport_l09", "lesson_practice", "application", "transport_frequency", 3, + "Kolega pyta, jak często jeździsz metrem. Nigdy nie jeździsz. Co powiesz?", "Друг спрашивает, как часто ты ездишь на метро. Ты никогда не ездишь. Что ты скажешь?", "Друг питає, як часто ти їздиш метро. Ти ніколи не їздиш. Що ти скажеш?", "A friend asks how often you take the subway. You never do. What do you say?", + "A", None, None), + + # L10 — transport_description (difficulty 3) + ("a1_transport_l10_q1", "a1_transport_l10", "lesson_practice", "recognition", "transport_description", 3, + "Które zdanie poprawnie opisuje codzienną podróż do pracy?", "Какое предложение правильно описывает ежедневную поездку на работу?", "Яке речення правильно описує щоденну поїздку на роботу?", "Which sentence correctly describes a daily commute to work?", + "A", None, None), + ("a1_transport_l10_q2", "a1_transport_l10", "lesson_practice", "production", "transport_description", 3, + "Przetłumacz: «Билет покупаю в киоске».", "Переведите: «Билет покупаю в киоске».", "Перекладіть: «Квиток купую в кіоску».", "Translate: “I buy the ticket at the kiosk.”", + "Bilet kupuję w kiosku", "first_letter", "B"), + ("a1_transport_l10_q3", "a1_transport_l10", "lesson_practice", "application", "transport_description", 3, + "Chcesz opisać koledze swoją podróż: jedziesz autobusem, bilet kupujesz w kiosku, podróż trwa dwadzieścia minut. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою поездку: едешь на автобусе, билет покупаешь в киоске, поездка длится двадцать минут. Как ты начнёшь предложение?", "Ти хочеш описати другу свою поїздку: їдеш автобусом, квиток купуєш у кіоску, поїздка триває двадцять хвилин. Як ти почнеш речення?", "You want to describe your commute to a friend: you go by bus, buy the ticket at the kiosk, the trip takes twenty minutes. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t9: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_transport', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t9 = [ + # L01 + ("a1_transport_l01_q1", "A", "autobus", "автобус", "автобус", "bus", True, None), + ("a1_transport_l01_q1", "B", "tramwaj", "трамвай", "трамвай", "tram", False, "wrong_word"), + ("a1_transport_l01_q1", "C", "pociąg", "поезд", "потяг", "train", False, "wrong_word"), + ("a1_transport_l01_q1", "D", "samochód", "машина", "машина", "car", False, "wrong_word"), + + ("a1_transport_l01_q3", "A", "autobus", "автобус", "автобус", "bus", False, "wrong_context"), + ("a1_transport_l01_q3", "B", "tramwaj", "трамвай", "трамвай", "tram", True, None), + ("a1_transport_l01_q3", "C", "pociąg", "поезд", "потяг", "train", False, "wrong_context"), + ("a1_transport_l01_q3", "D", "samochód", "машина", "машина", "car", False, "wrong_context"), + + # L02 + ("a1_transport_l02_q1", "A", "taksówka", "такси", "таксі", "taxi", True, None), + ("a1_transport_l02_q1", "B", "rower", "велосипед", "велосипед", "bike", False, "wrong_word"), + ("a1_transport_l02_q1", "C", "samolot", "самолёт", "літак", "plane", False, "wrong_word"), + ("a1_transport_l02_q1", "D", "metro", "метро", "метро", "subway", False, "wrong_word"), + + ("a1_transport_l02_q3", "A", "rower", "велосипед", "велосипед", "bike", False, "wrong_context"), + ("a1_transport_l02_q3", "B", "samolot", "самолёт", "літак", "plane", True, None), + ("a1_transport_l02_q3", "C", "metro", "метро", "метро", "subway", False, "wrong_context"), + ("a1_transport_l02_q3", "D", "taksówka", "такси", "таксі", "taxi", False, "wrong_context"), + + # L03 + ("a1_transport_l03_q1", "A", "jadę", "еду", "їду", "go (I)", True, None), + ("a1_transport_l03_q1", "B", "jedziesz", "едешь", "їдеш", "go (you)", False, "wrong_word"), + ("a1_transport_l03_q1", "C", "jedzie", "едет", "їде", "goes", False, "wrong_word"), + ("a1_transport_l03_q1", "D", "jechać", "ехать", "їхати", "to go", False, "wrong_word"), + + ("a1_transport_l03_q3", "A", "Jadę do pracy.", "Я еду на работу.", "Я їду на роботу.", "I'm going to work.", True, None), + ("a1_transport_l03_q3", "B", "Jedziesz do pracy.", "Ты едешь на работу.", "Ти їдеш на роботу.", "You're going to work.", False, "wrong_word"), + ("a1_transport_l03_q3", "C", "Idę do pracy.", "Я иду на работу.", "Я йду на роботу.", "I'm walking to work.", False, "wrong_context"), + ("a1_transport_l03_q3", "D", "Jedzie do pracy.", "Он/она едет на работу.", "Він/вона їде на роботу.", "He/she is going to work.", False, "wrong_word"), + + # L04 + ("a1_transport_l04_q1", "A", "Idę do sklepu.", "Я иду в магазин.", "Я йду до магазину.", "I'm walking to the shop.", True, None), + ("a1_transport_l04_q1", "B", "Jadę do sklepu.", "Я еду в магазин.", "Я їду до магазину.", "I'm driving to the shop.", False, "wrong_context"), + ("a1_transport_l04_q1", "C", "Jedziesz do sklepu.", "Ты едешь в магазин.", "Ти їдеш до магазину.", "You're driving to the shop.", False, "wrong_word"), + ("a1_transport_l04_q1", "D", "Idziemy do sklepu.", "Мы идём в магазин.", "Ми йдемо до магазину.", "We're walking to the shop.", False, "wrong_number"), + + ("a1_transport_l04_q3", "A", "Idę.", "Я иду.", "Я йду.", "I'm walking.", False, "wrong_context"), + ("a1_transport_l04_q3", "B", "Jadę.", "Я еду.", "Я їду.", "I'm driving.", True, None), + ("a1_transport_l04_q3", "C", "Jedziesz.", "Ты едешь.", "Ти їдеш.", "You're driving.", False, "wrong_word"), + ("a1_transport_l04_q3", "D", "Idziemy.", "Мы идём.", "Ми йдемо.", "We're walking.", False, "wrong_number"), + + # L05 + ("a1_transport_l05_q1", "A", "autobus", "автобус (им.)", "автобус (наз.)", "bus (nom.)", False, "wrong_case"), + ("a1_transport_l05_q1", "B", "autobusem", "автобусе (тв.)", "автобусом (ор.)", "bus (instr.)", True, None), + ("a1_transport_l05_q1", "C", "autobusowi", "автобусу (дат.)", "автобусу (дав.)", "bus (dat.)", False, "wrong_case"), + ("a1_transport_l05_q1", "D", "autobusu", "автобуса (род.)", "автобуса (род.)", "bus (gen.)", False, "wrong_case"), + + ("a1_transport_l05_q3", "A", "Jadę do pracy rowerem.", "Я еду на работу на велосипеде.", "Я їду на роботу велосипедом.", "I go to work by bike.", True, None), + ("a1_transport_l05_q3", "B", "Jadę do pracy rower.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_transport_l05_q3", "C", "Jadę do pracy na rowerem.", "Лишний предлог.", "Зайвий прийменник.", "Extra preposition.", False, "wrong_sentence_type"), + ("a1_transport_l05_q3", "D", "Jadę do pracy roweru.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + + # L06 + ("a1_transport_l06_q1", "A", "bilet", "билет", "квиток", "ticket", True, None), + ("a1_transport_l06_q1", "B", "kasa", "касса", "каса", "ticket office", False, "wrong_word"), + ("a1_transport_l06_q1", "C", "dworzec", "вокзал", "вокзал", "station", False, "wrong_word"), + ("a1_transport_l06_q1", "D", "przystanek", "остановка", "зупинка", "stop", False, "wrong_word"), + + ("a1_transport_l06_q3", "A", "Chcę kupić bilet.", "Я хочу купить билет.", "Я хочу купити квиток.", "I want to buy a ticket.", True, None), + ("a1_transport_l06_q3", "B", "Chcę kupić dworzec.", "Я хочу купить вокзал.", "Я хочу купити вокзал.", "I want to buy a station.", False, "wrong_word"), + ("a1_transport_l06_q3", "C", "Mam bilet już.", "У меня уже есть билет.", "У мене вже є квиток.", "I already have a ticket.", False, "wrong_context"), + ("a1_transport_l06_q3", "D", "Sprzedaję bilet.", "Я продаю билет.", "Я продаю квиток.", "I'm selling a ticket.", False, "wrong_context"), + + # L07 + ("a1_transport_l07_q1", "A", "Jak dojadę do dworca?", "Как мне доехать до вокзала?", "Як мені доїхати до вокзалу?", "How do I get to the station?", True, None), + ("a1_transport_l07_q1", "B", "Gdzie jest przystanek?", "Где остановка?", "Де зупинка?", "Where is the stop?", False, "wrong_translation"), + ("a1_transport_l07_q1", "C", "Ile kosztuje bilet?", "Сколько стоит билет?", "Скільки коштує квиток?", "How much is the ticket?", False, "wrong_translation"), + ("a1_transport_l07_q1", "D", "Kiedy odjeżdża pociąg?", "Когда отправляется поезд?", "Коли відправляється потяг?", "When does the train leave?", False, "wrong_translation"), + + ("a1_transport_l07_q3", "A", "Jak dojadę do lotniska?", "Как мне доехать до аэропорта?", "Як мені доїхати до аеропорту?", "How do I get to the airport?", True, None), + ("a1_transport_l07_q3", "B", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_context"), + ("a1_transport_l07_q3", "C", "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much is it?", False, "wrong_context"), + ("a1_transport_l07_q3", "D", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", False, "wrong_context"), + + # L08 + ("a1_transport_l08_q1", "A", "dworzec", "вокзал", "вокзал", "train station", True, None), + ("a1_transport_l08_q1", "B", "przystanek", "остановка", "зупинка", "stop", False, "wrong_word"), + ("a1_transport_l08_q1", "C", "lotnisko", "аэропорт", "аеропорт", "airport", False, "wrong_word"), + ("a1_transport_l08_q1", "D", "stacja", "станция", "станція", "station", False, "wrong_word"), + + ("a1_transport_l08_q3", "A", "dworzec", "вокзал", "вокзал", "train station", False, "wrong_context"), + ("a1_transport_l08_q3", "B", "przystanek", "остановка", "зупинка", "stop", True, None), + ("a1_transport_l08_q3", "C", "lotnisko", "аэропорт", "аеропорт", "airport", False, "wrong_context"), + ("a1_transport_l08_q3", "D", "stacja", "станция", "станція", "station", False, "wrong_context"), + + # L09 + ("a1_transport_l09_q1", "A", "Jak często jeździsz autobusem?", "Как часто ты ездишь на автобусе?", "Як часто ти їздиш автобусом?", "How often do you go by bus?", True, None), + ("a1_transport_l09_q1", "B", "Dokąd jedziesz autobusem?", "Куда ты едешь на автобусе?", "Куди ти їдеш автобусом?", "Where are you going by bus?", False, "wrong_translation"), + ("a1_transport_l09_q1", "C", "Czy lubisz jeździć autobusem?", "Тебе нравится ездить на автобусе?", "Тобі подобається їздити автобусом?", "Do you like riding the bus?", False, "wrong_translation"), + ("a1_transport_l09_q1", "D", "Ile kosztuje bilet na autobus?", "Сколько стоит билет на автобус?", "Скільки коштує квиток на автобус?", "How much is the bus ticket?", False, "wrong_translation"), + + ("a1_transport_l09_q3", "A", "Nigdy nie jeżdżę metrem.", "Я никогда не езжу на метро.", "Я ніколи не їжджу метро.", "I never go by subway.", True, None), + ("a1_transport_l09_q3", "B", "Zawsze jeżdżę metrem.", "Я всегда езжу на метро.", "Я завжди їжджу метро.", "I always go by subway.", False, "wrong_context"), + ("a1_transport_l09_q3", "C", "Często jeżdżę metrem.", "Я часто езжу на метро.", "Я часто їжджу метро.", "I often go by subway.", False, "wrong_context"), + ("a1_transport_l09_q3", "D", "Nigdy jeżdżę metrem.", "Пропущено отрицание.", "Пропущено заперечення.", "Missing negation.", False, "wrong_sentence_type"), + + # L10 + ("a1_transport_l10_q1", "A", "Codziennie jadę do pracy autobusem.", "Каждый день я еду на работу на автобусе.", "Щодня я їду на роботу автобусом.", "Every day I go to work by bus.", True, None), + ("a1_transport_l10_q1", "B", "Codziennie jadę do pracy autobus.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_transport_l10_q1", "C", "Codziennie jestem do pracy autobusem.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_transport_l10_q1", "D", "Codziennie idę do pracy autobusem.", "Смысл не соответствует: „idę” — пешком, а не автобусом.", "Сенс не відповідає: „idę” — пішки, а не автобусом.", "Meaning mismatch: „idę” is on foot, not by bus.", False, "wrong_context"), + + ("a1_transport_l10_q3", "A", "Jadę do pracy autobusem.", "Я еду на работу на автобусе.", "Я їду на роботу автобусом.", "I go to work by bus.", True, None), + ("a1_transport_l10_q3", "B", "Jestem autobus do pracy.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_transport_l10_q3", "C", "Bilet jestem w kiosku.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_transport_l10_q3", "D", "Autobusem jestem do pracy.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ] + + for opt in options_t9: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t9 = [ + ("a1_transport_t01", None, "topic_test", "recognition", "transport_vocabulary", 1, + "Jak po polsku „поезд”?", "Как по-польски «поезд»?", "Як польською «потяг»?", "How do you say “train” in Polish?", + "B", None, None, 1), + ("a1_transport_t02", None, "topic_test", "recognition", "transport_vocabulary_more", 1, + "Jak po polsku „велосипед”?", "Как по-польски «велосипед»?", "Як польською «велосипед»?", "How do you say “bike” in Polish?", + "C", None, None, 2), + ("a1_transport_t03", None, "topic_test", "recognition", "transport_verb_jechac", 1, + "Wybierz poprawną formę: On ___. (jechać)", "Выберите правильную форму: On ___. (jechać)", "Виберіть правильну форму: On ___. (jechać)", "Choose the correct form: On ___. (jechać)", + "C", None, None, 3), + ("a1_transport_t04", None, "topic_test", "recognition", "transport_verb_isc", 2, + "Idziesz pieszo do parku. Jak powiesz?", "Ты идёшь пешком в парк. Что ты скажешь?", "Ти йдеш пішки до парку. Що ти скажеш?", "You're walking to the park. What do you say?", + "A", None, None, 4), + ("a1_transport_t05", None, "topic_test", "recognition", "transport_instrumental", 2, + "Wybierz poprawną formę: Jadę ___. (rower)", "Выберите правильную форму: Jadę ___. (rower)", "Виберіть правильну форму: Jadę ___. (rower)", "Choose the correct form: Jadę ___. (rower)", + "B", None, None, 5), + ("a1_transport_t06", None, "topic_test", "recognition", "transport_asking_directions", 3, + "Co znaczy „Jak dojadę do dworca?”", "Что означает «Jak dojadę do dworca?»", "Що означає «Jak dojadę do dworca?»", "What does “Jak dojadę do dworca?” mean?", + "A", None, None, 6), + + ("a1_transport_t07", None, "topic_test", "application", "transport_vocabulary", 1, + "Chcesz szybko podróżować po mieście po szynach. Czym pojedziesz?", "Ты хочешь быстро передвигаться по городу по рельсам. Чем ты поедешь?", "Ти хочеш швидко пересуватися містом по рейках. Чим ти поїдеш?", "You want to travel fast around the city on rails. What do you take?", + "B", None, None, 7), + ("a1_transport_t08", None, "topic_test", "application", "transport_vocabulary_more", 1, + "Chcesz polecieć do innego kraju. Czym polecisz?", "Ты хочешь полететь в другую страну. Чем ты полетишь?", "Ти хочеш полетіти в іншу країну. Чим ти полетиш?", "You want to fly to another country. What do you fly?", + "C", None, None, 8), + ("a1_transport_t09", None, "topic_test", "application", "transport_verb_isc", 2, + "Sklep jest bardzo blisko. Idziesz czy jedziesz?", "Магазин очень близко. Ты идёшь пешком или едешь?", "Магазин дуже близько. Ти йдеш пішки чи їдеш?", "The shop is very close. Are you walking or riding?", + "A", None, None, 9), + ("a1_transport_t10", None, "topic_test", "application", "transport_instrumental", 2, + "Chcesz powiedzieć, że jedziesz do szkoły na rowerze. Co powiesz?", "Ты хочешь сказать, что едешь в школу на велосипеде. Что ты скажешь?", "Ти хочеш сказати, що їдеш до школи на велосипеді. Що ти скажеш?", "You want to say you go to school by bike. What do you say?", + "A", None, None, 10), + ("a1_transport_t11", None, "topic_test", "application", "transport_ticket", 2, + "Jesteś na dworcu i chcesz kupić bilet. Co powiesz?", "Ты на вокзале и хочешь купить билет. Что ты скажешь?", "Ти на вокзалі і хочеш купити квиток. Що ти скажеш?", "You're at the station and want to buy a ticket. What do you say?", + "A", None, None, 11), + ("a1_transport_t12", None, "topic_test", "application", "transport_frequency", 3, + "Kolega pyta, jak często jeździsz samochodem. Zawsze jeździsz. Co powiesz?", "Друг спрашивает, как часто ты ездишь на машине. Ты всегда ездишь. Что ты скажешь?", "Друг питає, як часто ти їздиш машиною. Ти завжди їздиш. Що ти скажеш?", "A friend asks how often you drive. You always do. What do you say?", + "A", None, None, 12), + + ("a1_transport_t13", None, "topic_test", "production", "transport_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (машина)", "Вставьте пропущенное слово: To jest ___. (машина)", "Вставте пропущене слово: To jest ___. (машина)", "Fill in the missing word: To jest ___. (car)", + "samochód", "first_letter", "s", 13), + ("a1_transport_t14", None, "topic_test", "production", "transport_vocabulary_more", 1, + "Wpisz brakujące słowo: To jest ___. (метро)", "Вставьте пропущенное слово: To jest ___. (метро)", "Вставте пропущене слово: To jest ___. (метро)", "Fill in the missing word: To jest ___. (subway)", + "metro", "first_letter", "m", 14), + ("a1_transport_t15", None, "topic_test", "production", "transport_verb_jechac", 2, + "Wpisz brakujące słowo: Ona ___ do domu. (едет)", "Вставьте пропущенное слово: Ona ___ do domu. (едет)", "Вставте пропущене слово: Ona ___ do domu. (їде)", "Fill in the missing word: Ona ___ do domu. (she goes)", + "jedzie", "first_letter", "j", 15), + ("a1_transport_t16", None, "topic_test", "production", "transport_instrumental", 2, + "Wpisz brakujące słowo: Jadę ___. (поезд, творительный)", "Вставьте пропущенное слово: Jadę ___. (поезд, творительный)", "Вставте пропущене слово: Jadę ___. (потяг, орудний)", "Fill in the missing word: Jadę ___. (train, instrumental)", + "pociągiem", "first_letter", "p", 16), + ("a1_transport_t17", None, "topic_test", "production", "transport_asking_directions", 3, + "Wpisz brakujące słowo: Jak ___ do lotniska? (доеду)", "Вставьте пропущенное слово: Jak ___ do lotniska? (доеду)", "Вставте пропущене слово: Jak ___ do lotniska? (доїду)", "Fill in the missing word: Jak ___ do lotniska? (do I get)", + "dojadę", "first_letter", "d", 17), + ("a1_transport_t18", None, "topic_test", "production", "transport_description", 3, + "Przetłumacz: «Поездка длится двадцать минут».", "Переведите: «Поездка длится двадцать минут».", "Перекладіть: «Поїздка триває двадцять хвилин».", "Translate: “The trip takes twenty minutes.”", + "Podróż trwa dwadzieścia minut", "first_letter", "P", 18), + + ("a1_transport_t19", None, "topic_test", "mixed", "transport_places", 3, + "Wybierz poprawne tłumaczenie: «Вокзал в центре города, а аэропорт далеко».", "Выберите правильный перевод: «Вокзал в центре города, а аэропорт далеко».", "Виберіть правильний переклад: «Вокзал у центрі міста, а аеропорт далеко».", "Choose the correct translation: “The train station is downtown, and the airport is far away.”", + "A", None, None, 19), + ("a1_transport_t20", None, "topic_test", "mixed", "transport_description", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Как мне доехать до вокзала? — Поезжай на автобусе номер пять.»", "Выберите правильный перевод диалога: «— Как мне доехать до вокзала? — Поезжай на автобусе номер пять.»", "Виберіть правильний переклад діалогу: «— Як мені доїхати до вокзалу? — Їдь автобусом номер п'ять.»", "Choose the correct translation of the dialogue: “— How do I get to the station? — Take bus number five.”", + "A", None, None, 20), + ] + + for q in test_questions_t9: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_transport', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t9 = [ + ("a1_transport_t01", "A", "tramwaj", "трамвай", "трамвай", "tram", False, "wrong_word"), + ("a1_transport_t01", "B", "pociąg", "поезд", "потяг", "train", True, None), + ("a1_transport_t01", "C", "autobus", "автобус", "автобус", "bus", False, "wrong_word"), + ("a1_transport_t01", "D", "samochód", "машина", "машина", "car", False, "wrong_word"), + + ("a1_transport_t02", "A", "samolot", "самолёт", "літак", "plane", False, "wrong_word"), + ("a1_transport_t02", "B", "taksówka", "такси", "таксі", "taxi", False, "wrong_word"), + ("a1_transport_t02", "C", "rower", "велосипед", "велосипед", "bike", True, None), + ("a1_transport_t02", "D", "metro", "метро", "метро", "subway", False, "wrong_word"), + + ("a1_transport_t03", "A", "jadę", "еду", "їду", "go (I)", False, "wrong_word"), + ("a1_transport_t03", "B", "jedziesz", "едешь", "їдеш", "go (you)", False, "wrong_word"), + ("a1_transport_t03", "C", "jedzie", "едет", "їде", "goes", True, None), + ("a1_transport_t03", "D", "jechać", "ехать", "їхати", "to go", False, "wrong_word"), + + ("a1_transport_t04", "A", "Idę do parku.", "Я иду в парк.", "Я йду до парку.", "I'm walking to the park.", True, None), + ("a1_transport_t04", "B", "Jadę do parku.", "Я еду в парк.", "Я їду до парку.", "I'm driving to the park.", False, "wrong_context"), + ("a1_transport_t04", "C", "Jedziesz do parku.", "Ты едешь в парк.", "Ти їдеш до парку.", "You're driving to the park.", False, "wrong_word"), + ("a1_transport_t04", "D", "Idziemy do parku.", "Мы идём в парк.", "Ми йдемо до парку.", "We're walking to the park.", False, "wrong_number"), + + ("a1_transport_t05", "A", "rower", "велосипед (им.)", "велосипед (наз.)", "bike (nom.)", False, "wrong_case"), + ("a1_transport_t05", "B", "rowerem", "велосипеде (тв.)", "велосипедом (ор.)", "bike (instr.)", True, None), + ("a1_transport_t05", "C", "roweru", "велосипеда (род.)", "велосипеда (род.)", "bike (gen.)", False, "wrong_case"), + ("a1_transport_t05", "D", "rowerowi", "велосипеду (дат.)", "велосипеду (дав.)", "bike (dat.)", False, "wrong_case"), + + ("a1_transport_t06", "A", "Как мне доехать до вокзала?", "Как мне доехать до вокзала?", "Як мені доїхати до вокзалу?", "How do I get to the station?", True, None), + ("a1_transport_t06", "B", "Где остановка?", "Где остановка?", "Де зупинка?", "Where is the stop?", False, "wrong_translation"), + ("a1_transport_t06", "C", "Сколько стоит билет?", "Сколько стоит билет?", "Скільки коштує квиток?", "How much is the ticket?", False, "wrong_translation"), + ("a1_transport_t06", "D", "Когда отправляется поезд?", "Когда отправляется поезд?", "Коли відправляється потяг?", "When does the train leave?", False, "wrong_translation"), + + ("a1_transport_t07", "A", "autobus", "автобус", "автобус", "bus", False, "wrong_context"), + ("a1_transport_t07", "B", "tramwaj", "трамвай", "трамвай", "tram", True, None), + ("a1_transport_t07", "C", "samochód", "машина", "машина", "car", False, "wrong_context"), + ("a1_transport_t07", "D", "rower", "велосипед", "велосипед", "bike", False, "wrong_context"), + + ("a1_transport_t08", "A", "rower", "велосипед", "велосипед", "bike", False, "wrong_context"), + ("a1_transport_t08", "B", "metro", "метро", "метро", "subway", False, "wrong_context"), + ("a1_transport_t08", "C", "samolot", "самолёт", "літак", "plane", True, None), + ("a1_transport_t08", "D", "taksówka", "такси", "таксі", "taxi", False, "wrong_context"), + + ("a1_transport_t09", "A", "Idę.", "Я иду.", "Я йду.", "I'm walking.", True, None), + ("a1_transport_t09", "B", "Jadę.", "Я еду.", "Я їду.", "I'm driving.", False, "wrong_context"), + ("a1_transport_t09", "C", "Jedziesz.", "Ты едешь.", "Ти їдеш.", "You're driving.", False, "wrong_word"), + ("a1_transport_t09", "D", "Idziemy.", "Мы идём.", "Ми йдемо.", "We're walking.", False, "wrong_number"), + + ("a1_transport_t10", "A", "Jadę do szkoły rowerem.", "Я еду в школу на велосипеде.", "Я їду до школи велосипедом.", "I go to school by bike.", True, None), + ("a1_transport_t10", "B", "Jadę do szkoły rower.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_transport_t10", "C", "Jadę do szkoły na rowerem.", "Лишний предлог.", "Зайвий прийменник.", "Extra preposition.", False, "wrong_sentence_type"), + ("a1_transport_t10", "D", "Jadę do szkoły roweru.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + + ("a1_transport_t11", "A", "Chcę kupić bilet.", "Я хочу купить билет.", "Я хочу купити квиток.", "I want to buy a ticket.", True, None), + ("a1_transport_t11", "B", "Chcę kupić dworzec.", "Я хочу купить вокзал.", "Я хочу купити вокзал.", "I want to buy a station.", False, "wrong_word"), + ("a1_transport_t11", "C", "Mam bilet już.", "У меня уже есть билет.", "У мене вже є квиток.", "I already have a ticket.", False, "wrong_context"), + ("a1_transport_t11", "D", "Sprzedaję bilet.", "Я продаю билет.", "Я продаю квиток.", "I'm selling a ticket.", False, "wrong_context"), + + ("a1_transport_t12", "A", "Zawsze jeżdżę samochodem.", "Я всегда езжу на машине.", "Я завжди їжджу машиною.", "I always drive.", True, None), + ("a1_transport_t12", "B", "Nigdy nie jeżdżę samochodem.", "Я никогда не езжу на машине.", "Я ніколи не їжджу машиною.", "I never drive.", False, "wrong_context"), + ("a1_transport_t12", "C", "Rzadko jeżdżę samochodem.", "Я редко езжу на машине.", "Я рідко їжджу машиною.", "I rarely drive.", False, "wrong_context"), + ("a1_transport_t12", "D", "Zawsze jeżdżę samochód.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + + ("a1_transport_t19", "A", "Dworzec jest w centrum miasta, a lotnisko jest daleko.", "Вокзал в центре города, а аэропорт далеко.", "Вокзал у центрі міста, а аеропорт далеко.", "The train station is downtown, and the airport is far away.", True, None), + ("a1_transport_t19", "B", "Dworzec jest w centrum miasta, a lotnisko jest blisko.", "Смысл искажён.", "Сенс спотворено.", "Meaning is reversed.", False, "wrong_translation"), + ("a1_transport_t19", "C", "Przystanek jest w centrum miasta, a lotnisko jest daleko.", "Неправильное слово.", "Неправильне слово.", "Wrong word.", False, "wrong_word"), + ("a1_transport_t19", "D", "Dworzec jest daleko, a lotnisko jest w centrum miasta.", "Места перепутаны.", "Місця переплутані.", "Places are swapped.", False, "wrong_translation"), + + ("a1_transport_t20", "A", "Jak dojadę do dworca? Jedź autobusem numer pięć.", "Как мне доехать до вокзала? Поезжай на автобусе номер пять.", "Як мені доїхати до вокзалу? Їдь автобусом номер п'ять.", "How do I get to the station? Take bus number five.", True, None), + ("a1_transport_t20", "B", "Jak dojadę do lotniska? Jedź autobusem numer pięć.", "Неверное место назначения.", "Невірне місце призначення.", "Wrong destination.", False, "wrong_translation"), + ("a1_transport_t20", "C", "Jak dojadę do dworca? Idź autobusem numer pięć.", "Неправильный глагол.", "Неправильне дієслово.", "Wrong verb.", False, "wrong_word"), + ("a1_transport_t20", "D", "Jak dojadę do dworca? Jedź rowerem numer pięć.", "Неправильное слово.", "Неправильне слово.", "Wrong word.", False, "wrong_word"), + ] + + for opt in test_options_t9: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 10: РАБОТА И ПРОФЕССИИ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_work_professions', 'A1', 10, + 'Praca i zawody', + 'Работа и профессии', + 'Робота і професії', + 'Work and Professions') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t10 = [ + ("a1_work_professions_l01", 1, "professions_vocabulary", "Podstawowe zawody", "Основные профессии", "Основні професії", "Basic professions", + "Podstawowe zawody: nauczyciel, lekarz, kucharz, sprzedawca. Te słowa opisują mężczyzn wykonujących dany zawód i są rodzaju męskiego.", + "Основные профессии: nauczyciel (учитель), lekarz (врач), kucharz (повар), sprzedawca (продавец). Эти слова мужского рода и описывают мужчин, выполняющих данную профессию.", + "Основні професії: nauczyciel (вчитель), lekarz (лікар), kucharz (кухар), sprzedawca (продавець). Ці слова чоловічого роду й описують чоловіків, які виконують цю професію.", + "Basic professions: nauczyciel (teacher), lekarz (doctor), kucharz (cook), sprzedawca (salesman). These words are masculine and describe men doing the job."), + + ("a1_work_professions_l02", 2, "professions_vocabulary_fem", "Zawody kobiece", "Женские профессии", "Жіночі професії", "Feminine profession forms", + "Zawody kobiece tworzymy zwykle końcówką -ka: nauczyciel → nauczycielka, lekarz → lekarka, kucharz → kucharka. Wyjątek: sprzedawca → sprzedawczyni.", + "Женские формы профессий обычно образуются окончанием -ka: nauczyciel → nauczycielka, lekarz → lekarka, kucharz → kucharka. Исключение: sprzedawca → sprzedawczyni.", + "Жіночі форми професій зазвичай утворюються закінченням -ka: nauczyciel → nauczycielka, lekarz → lekarka, kucharz → kucharka. Виняток: sprzedawca → sprzedawczyni.", + "Feminine profession forms are usually made with the ending -ka: nauczyciel → nauczycielka, lekarz → lekarka, kucharz → kucharka. Exception: sprzedawca → sprzedawczyni."), + + ("a1_work_professions_l03", 3, "profession_work_jako", "Pracuję jako + mianownik", "Pracuję jako + именительный падеж", "Pracuję jako + називний відмінок", "Pracuję jako + nominative", + "Żeby powiedzieć, jaki mamy zawód, używamy czasownika „pracować” + „jako” + mianownik: pracuję jako nauczyciel, pracujesz jako lekarz, pracuje jako kucharka.", + "Чтобы сказать, кем мы работаем, используем глагол „pracować” + „jako” + именительный падеж: pracuję jako nauczyciel, pracujesz jako lekarz, pracuje jako kucharka.", + "Щоб сказати, ким ми працюємо, використовуємо дієслово „pracować” + „jako” + називний відмінок: pracuję jako nauczyciel, pracujesz jako lekarz, pracuje jako kucharka.", + "To say what job we do, we use „pracować” + „jako” + the nominative: pracuję jako nauczyciel, pracujesz jako lekarz, pracuje jako kucharka."), + + ("a1_work_professions_l04", 4, "profession_identity_instrumental", "Kim jesteś z zawodu?", "Кто ты по профессии?", "Хто ти за професією?", "What's your profession?", + "Pytamy „Kim jesteś z zawodu?”. Odpowiadamy czasownikiem „być” + narzędnik: jestem lekarzem, jesteś nauczycielem, jest kucharzem.", + "Спрашиваем „Kim jesteś z zawodu?” (Кто ты по профессии?). Отвечаем глаголом „być” + творительный падеж: jestem lekarzem, jesteś nauczycielem, jest kucharzem.", + "Запитуємо „Kim jesteś z zawodu?” (Хто ти за професією?). Відповідаємо дієсловом „być” + орудний відмінок: jestem lekarzem, jesteś nauczycielem, jest kucharzem.", + "We ask „Kim jesteś z zawodu?” (What's your profession?). We answer with „być” + the instrumental: jestem lekarzem, jesteś nauczycielem, jest kucharzem."), + + ("a1_work_professions_l05", 5, "workplace_vocabulary", "Miejsca pracy", "Места работы", "Місця роботи", "Places of work", + "Miejsca pracy: biuro (rodzaj nijaki), szpital (rodzaj męski), szkoła (rodzaj żeński), sklep (rodzaj męski), restauracja (rodzaj żeński).", + "Места работы: biuro (офис, средний род), szpital (больница, мужской род), szkoła (школа, женский род), sklep (магазин, мужской род), restauracja (ресторан, женский род).", + "Місця роботи: biuro (офіс, середній рід), szpital (лікарня, чоловічий рід), szkoła (школа, жіночий рід), sklep (магазин, чоловічий рід), restauracja (ресторан, жіночий рід).", + "Places of work: biuro (office, neuter), szpital (hospital, masculine), szkoła (school, feminine), sklep (shop, masculine), restauracja (restaurant, feminine)."), + + ("a1_work_professions_l06", 6, "workplace_locative", "Pracuję w + miejscownik", "Pracuję w + предложный падеж", "Pracuję w + місцевий відмінок", "Pracuję w + locative", + "Żeby powiedzieć, gdzie pracujemy, używamy miejscownika z przyimkiem „w”: biuro → w biurze, szpital → w szpitalu, szkoła → w szkole, sklep → w sklepie, restauracja → w restauracji.", + "Чтобы сказать, где мы работаем, используем предложный падеж с предлогом „w”: biuro → w biurze, szpital → w szpitalu, szkoła → w szkole, sklep → w sklepie, restauracja → w restauracji.", + "Щоб сказати, де ми працюємо, використовуємо місцевий відмінок з прийменником „w”: biuro → w biurze, szpital → w szpitalu, szkoła → w szkole, sklep → w sklepie, restauracja → w restauracji.", + "To say where we work, we use the locative with the preposition „w”: biuro → w biurze, szpital → w szpitalu, szkoła → w szkole, sklep → w sklepie, restauracja → w restauracji."), + + ("a1_work_professions_l07", 7, "work_schedule", "Zaczynam i kończę pracę", "Я начинаю и заканчиваю работу", "Я починаю і закінчую роботу", "I start and finish work", + "Godziny pracy opisujemy czasownikami „zaczynać” i „kończyć” + biernik „pracę”: zaczynam pracę o ósmej, kończę pracę o szesnastej.", + "Часы работы описываем глаголами „zaczynać” и „kończyć” + винительный падеж „pracę”: zaczynam pracę o ósmej (начинаю работу в восемь), kończę pracę o szesnastej (заканчиваю работу в шестнадцать).", + "Робочі години описуємо дієсловами „zaczynać” і „kończyć” + знахідний відмінок „pracę”: zaczynam pracę o ósmej (починаю роботу о восьмій), kończę pracę o szesnastej (закінчую роботу о шістнадцятій).", + "We describe working hours with „zaczynać” and „kończyć” + the accusative „pracę”: zaczynam pracę o ósmej (I start work at eight), kończę pracę o szesnastej (I finish work at four p.m.)."), + + ("a1_work_professions_l08", 8, "job_search", "Szukam pracy", "Я ищу работу", "Я шукаю роботу", "I'm looking for a job", + "Czasownik „szukać” łączy się z dopełniaczem: szukam pracy. Czasownik „mieć” łączy się z biernikiem: mam pracę.", + "Глагол „szukać” требует родительного падежа: szukam pracy (я ищу работу). Глагол „mieć” требует винительного падежа: mam pracę (у меня есть работа).", + "Дієслово „szukać” вимагає родового відмінка: szukam pracy (я шукаю роботу). Дієслово „mieć” вимагає знахідного відмінка: mam pracę (у мене є робота).", + "The verb „szukać” takes the genitive: szukam pracy (I'm looking for a job). The verb „mieć” takes the accusative: mam pracę (I have a job)."), + + ("a1_work_professions_l09", 9, "career_plans", "Chcę zostać + narzędnik", "Chcę zostać + творительный падеж", "Chcę zostać + орудний відмінок", "Chcę zostać + instrumental", + "Żeby mówić o planach zawodowych, używamy „chcę zostać” + narzędnik: chcę zostać lekarzem, chcę zostać nauczycielką.", + "Чтобы говорить о планах на будущую профессию, используем „chcę zostać” + творительный падеж: chcę zostać lekarzem (я хочу стать врачом), chcę zostać nauczycielką (я хочу стать учительницей).", + "Щоб говорити про плани на майбутню професію, використовуємо „chcę zostać” + орудний відмінок: chcę zostać lekarzem (я хочу стати лікарем), chcę zostać nauczycielką (я хочу стати вчителькою).", + "To talk about career plans, we use „chcę zostać” + the instrumental: chcę zostać lekarzem (I want to become a doctor), chcę zostać nauczycielką (I want to become a teacher)."), + + ("a1_work_professions_l10", 10, "work_description", "Opisuję swoją pracę", "Описываю свою работу", "Описую свою роботу", "Describing my job", + "Żeby opisać swoją pracę, łączymy kilka zdań: Pracuję jako nauczycielka. Pracuję w szkole. Zaczynam pracę o ósmej i kończę o szesnastej.", + "Чтобы описать свою работу, соединяем несколько предложений: Pracuję jako nauczycielka. Pracuję w szkole. Zaczynam pracę o ósmej i kończę o szesnastej. (Я работаю учительницей. Я работаю в школе. Я начинаю работу в восемь и заканчиваю в шестнадцать.)", + "Щоб описати свою роботу, поєднуємо кілька речень: Pracuję jako nauczycielka. Pracuję w szkole. Zaczynam pracę o ósmej i kończę o szesnastej. (Я працюю вчителькою. Я працюю в школі. Я починаю роботу о восьмій і закінчую о шістнадцятій.)", + "To describe your job, we combine several sentences: Pracuję jako nauczycielka. Pracuję w szkole. Zaczynam pracę o ósmej i kończę o szesnastej. (I work as a teacher. I work at a school. I start work at eight and finish at four p.m.)"), + ] + + for lesson in lessons_t10: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_work_professions', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t10 = [ + ("a1_work_professions_l01", 1, "To jest lekarz.", "Это врач.", "Це лікар.", "This is a doctor."), + ("a1_work_professions_l01", 2, "To jest nauczyciel.", "Это учитель.", "Це вчитель.", "This is a teacher."), + ("a1_work_professions_l01", 3, "To jest kucharz.", "Это повар.", "Це кухар.", "This is a cook."), + + ("a1_work_professions_l02", 1, "To jest nauczycielka.", "Это учительница.", "Це вчителька.", "This is a female teacher."), + ("a1_work_professions_l02", 2, "To jest lekarka.", "Это врач (женщина).", "Це лікарка.", "This is a female doctor."), + ("a1_work_professions_l02", 3, "To jest sprzedawczyni.", "Это продавщица.", "Це продавщиня.", "This is a saleswoman."), + + ("a1_work_professions_l03", 1, "Pracuję jako nauczyciel.", "Я работаю учителем.", "Я працюю вчителем.", "I work as a teacher."), + ("a1_work_professions_l03", 2, "Pracujesz jako lekarz?", "Ты работаешь врачом?", "Ти працюєш лікарем?", "Do you work as a doctor?"), + ("a1_work_professions_l03", 3, "Ona pracuje jako kucharka.", "Она работает поваром.", "Вона працює кухаркою.", "She works as a cook."), + + ("a1_work_professions_l04", 1, "Kim jesteś z zawodu?", "Кто ты по профессии?", "Хто ти за професією?", "What's your profession?"), + ("a1_work_professions_l04", 2, "Jestem lekarzem.", "Я врач.", "Я лікар.", "I am a doctor."), + ("a1_work_professions_l04", 3, "On jest nauczycielem.", "Он учитель.", "Він вчитель.", "He is a teacher."), + + ("a1_work_professions_l05", 1, "To jest biuro.", "Это офис.", "Це офіс.", "This is an office."), + ("a1_work_professions_l05", 2, "To jest szpital.", "Это больница.", "Це лікарня.", "This is a hospital."), + ("a1_work_professions_l05", 3, "To jest restauracja.", "Это ресторан.", "Це ресторан.", "This is a restaurant."), + + ("a1_work_professions_l06", 1, "Pracuję w biurze.", "Я работаю в офисе.", "Я працюю в офісі.", "I work in an office."), + ("a1_work_professions_l06", 2, "Lekarz pracuje w szpitalu.", "Врач работает в больнице.", "Лікар працює в лікарні.", "The doctor works at a hospital."), + ("a1_work_professions_l06", 3, "Ona pracuje w szkole.", "Она работает в школе.", "Вона працює в школі.", "She works at a school."), + + ("a1_work_professions_l07", 1, "Zaczynam pracę o ósmej.", "Я начинаю работу в восемь.", "Я починаю роботу о восьмій.", "I start work at eight."), + ("a1_work_professions_l07", 2, "Kończę pracę o szesnastej.", "Я заканчиваю работу в шестнадцать.", "Я закінчую роботу о шістнадцятій.", "I finish work at four p.m."), + ("a1_work_professions_l07", 3, "O której godzinie zaczynasz pracę?", "В котором часу ты начинаешь работу?", "О котрій годині ти починаєш роботу?", "What time do you start work?"), + + ("a1_work_professions_l08", 1, "Szukam pracy.", "Я ищу работу.", "Я шукаю роботу.", "I'm looking for a job."), + ("a1_work_professions_l08", 2, "Mam dobrą pracę.", "У меня хорошая работа.", "У мене хороша робота.", "I have a good job."), + ("a1_work_professions_l08", 3, "On szuka nowej pracy.", "Он ищет новую работу.", "Він шукає нову роботу.", "He is looking for a new job."), + + ("a1_work_professions_l09", 1, "Chcę zostać lekarzem.", "Я хочу стать врачом.", "Я хочу стати лікарем.", "I want to become a doctor."), + ("a1_work_professions_l09", 2, "Chcesz zostać nauczycielką?", "Ты хочешь стать учительницей?", "Ти хочеш стати вчителькою?", "Do you want to become a teacher?"), + ("a1_work_professions_l09", 3, "On chce zostać kucharzem.", "Он хочет стать поваром.", "Він хоче стати кухарем.", "He wants to become a cook."), + + ("a1_work_professions_l10", 1, "Pracuję jako nauczycielka.", "Я работаю учительницей.", "Я працюю вчителькою.", "I work as a teacher."), + ("a1_work_professions_l10", 2, "Pracuję w szkole.", "Я работаю в школе.", "Я працюю в школі.", "I work at a school."), + ("a1_work_professions_l10", 3, "Zaczynam pracę o ósmej i kończę o szesnastej.", "Я начинаю работу в восемь и заканчиваю в шестнадцать.", "Я починаю роботу о восьмій і закінчую о шістнадцятій.", "I start work at eight and finish at four p.m."), + ] + + for ex in examples_t10: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t10 = [ + # L01 — professions_vocabulary (difficulty 1) + ("a1_work_professions_l01_q1", "a1_work_professions_l01", "lesson_practice", "recognition", "professions_vocabulary", 1, + "Jak po polsku „врач”?", "Как по-польски «врач»?", "Як польською «лікар»?", "How do you say “doctor” in Polish?", + "A", None, None), + ("a1_work_professions_l01_q2", "a1_work_professions_l01", "lesson_practice", "production", "professions_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (учитель)", "Вставьте пропущенное слово: To jest ___. (учитель)", "Вставте пропущене слово: To jest ___. (вчитель)", "Fill in the missing word: To jest ___. (teacher)", + "nauczyciel", "first_letter", "n"), + ("a1_work_professions_l01_q3", "a1_work_professions_l01", "lesson_practice", "application", "professions_vocabulary", 1, + "Ta osoba leczy chorych ludzi w szpitalu. Kim on jest?", "Этот человек лечит больных людей в больнице. Кто он?", "Ця людина лікує хворих людей у лікарні. Хто він?", "This person treats sick people at the hospital. Who is he?", + "A", None, None), + + # L02 — professions_vocabulary_fem (difficulty 1) + ("a1_work_professions_l02_q1", "a1_work_professions_l02", "lesson_practice", "recognition", "professions_vocabulary_fem", 1, + "Jak po polsku „продавщица”?", "Как по-польски «продавщица»?", "Як польською «продавщиня»?", "How do you say “saleswoman” in Polish?", + "A", None, None), + ("a1_work_professions_l02_q2", "a1_work_professions_l02", "lesson_practice", "production", "professions_vocabulary_fem", 1, + "Wpisz brakujące słowo: To jest ___. (учительница)", "Вставьте пропущенное слово: To jest ___. (учительница)", "Вставте пропущене слово: To jest ___. (вчителька)", "Fill in the missing word: To jest ___. (female teacher)", + "nauczycielka", "first_letter", "n"), + ("a1_work_professions_l02_q3", "a1_work_professions_l02", "lesson_practice", "application", "professions_vocabulary_fem", 1, + "Widzisz kobietę, która gotuje jedzenie w restauracji. Kim ona jest?", "Ты видишь женщину, которая готовит еду в ресторане. Кто она?", "Ти бачиш жінку, яка готує їжу в ресторані. Хто вона?", "You see a woman cooking food at a restaurant. Who is she?", + "A", None, None), + + # L03 — profession_work_jako (difficulty 1) + ("a1_work_professions_l03_q1", "a1_work_professions_l03", "lesson_practice", "recognition", "profession_work_jako", 1, + "Wybierz poprawną formę: Pracuję ___ nauczyciel.", "Выберите правильную форму: Pracuję ___ nauczyciel.", "Виберіть правильну форму: Pracuję ___ nauczyciel.", "Choose the correct form: Pracuję ___ nauczyciel.", + "A", None, None), + ("a1_work_professions_l03_q2", "a1_work_professions_l03", "lesson_practice", "production", "profession_work_jako", 1, + "Wpisz brakujące słowo: Pracuję ___ lekarz. (как)", "Вставьте пропущенное слово: Pracuję ___ lekarz. (как)", "Вставте пропущене слово: Pracuję ___ lekarz. (як)", "Fill in the missing word: Pracuję ___ lekarz. (as)", + "jako", "first_letter", "j"), + ("a1_work_professions_l03_q3", "a1_work_professions_l03", "lesson_practice", "application", "profession_work_jako", 1, + "Kolega pyta, jaki masz zawód. Jesteś kucharzem. Co powiesz?", "Друг спрашивает, кем ты работаешь. Ты повар. Что ты скажешь?", "Друг питає, ким ти працюєш. Ти кухар. Що ти скажеш?", "A friend asks what your job is. You're a cook. What do you say?", + "A", None, None), + + # L04 — profession_identity_instrumental (difficulty 1) + ("a1_work_professions_l04_q1", "a1_work_professions_l04", "lesson_practice", "recognition", "profession_identity_instrumental", 1, + "Wybierz poprawną formę: Jestem ___. (lekarz)", "Выберите правильную форму: Jestem ___. (lekarz)", "Виберіть правильну форму: Jestem ___. (lekarz)", "Choose the correct form: Jestem ___. (lekarz)", + "A", None, None), + ("a1_work_professions_l04_q2", "a1_work_professions_l04", "lesson_practice", "production", "profession_identity_instrumental", 1, + "Wpisz brakujące słowo: Jestem ___. (учитель, творительный)", "Вставьте пропущенное слово: Jestem ___. (учитель, творительный)", "Вставте пропущене слово: Jestem ___. (вчитель, орудний)", "Fill in the missing word: Jestem ___. (teacher, instrumental)", + "nauczycielem", "first_letter", "n"), + ("a1_work_professions_l04_q3", "a1_work_professions_l04", "lesson_practice", "application", "profession_identity_instrumental", 1, + "Kolega pyta „Kim jesteś z zawodu?”. Jesteś kucharzem. Co powiesz?", "Друг спрашивает «Кто ты по профессии?». Ты повар. Что ты скажешь?", "Друг питає «Хто ти за професією?». Ти кухар. Що ти скажеш?", "A friend asks “What's your profession?” You're a cook. What do you say?", + "A", None, None), + + # L05 — workplace_vocabulary (difficulty 2) + ("a1_work_professions_l05_q1", "a1_work_professions_l05", "lesson_practice", "recognition", "workplace_vocabulary", 2, + "Jak po polsku „больница”?", "Как по-польски «больница»?", "Як польською «лікарня»?", "How do you say “hospital” in Polish?", + "A", None, None), + ("a1_work_professions_l05_q2", "a1_work_professions_l05", "lesson_practice", "production", "workplace_vocabulary", 2, + "Wpisz brakujące słowo: To jest ___. (ресторан)", "Вставьте пропущенное слово: To jest ___. (ресторан)", "Вставте пропущене слово: To jest ___. (ресторан)", "Fill in the missing word: To jest ___. (restaurant)", + "restauracja", "first_letter", "r"), + ("a1_work_professions_l05_q3", "a1_work_professions_l05", "lesson_practice", "application", "workplace_vocabulary", 2, + "Chcesz kupić chleb. Dokąd idziesz?", "Ты хочешь купить хлеб. Куда ты идёшь?", "Ти хочеш купити хліб. Куди ти йдеш?", "You want to buy bread. Where do you go?", + "A", None, None), + + # L06 — workplace_locative (difficulty 2) + ("a1_work_professions_l06_q1", "a1_work_professions_l06", "lesson_practice", "recognition", "workplace_locative", 2, + "Wybierz poprawną formę: Pracuję ___. (biuro)", "Выберите правильную форму: Pracuję ___. (biuro)", "Виберіть правильну форму: Pracuję ___. (biuro)", "Choose the correct form: Pracuję ___. (biuro)", + "A", None, None), + ("a1_work_professions_l06_q2", "a1_work_professions_l06", "lesson_practice", "production", "workplace_locative", 2, + "Wpisz brakujące słowo: Pracuję ___. (в магазине)", "Вставьте пропущенное слово: Pracuję ___. (в магазине)", "Вставте пропущене слово: Pracuję ___. (в магазині)", "Fill in the missing word: Pracuję ___. (at a shop)", + "w sklepie", "first_letter", "w"), + ("a1_work_professions_l06_q3", "a1_work_professions_l06", "lesson_practice", "application", "workplace_locative", 2, + "Chcesz powiedzieć koledze, że pracujesz w restauracji. Co powiesz?", "Ты хочешь сказать другу, что работаешь в ресторане. Что ты скажешь?", "Ти хочеш сказати другу, що працюєш в ресторані. Що ти скажеш?", "You want to tell a friend you work at a restaurant. What do you say?", + "A", None, None), + + # L07 — work_schedule (difficulty 2) + ("a1_work_professions_l07_q1", "a1_work_professions_l07", "lesson_practice", "recognition", "work_schedule", 2, + "Wybierz poprawną formę: ___ pracę o ósmej. (начинаю)", "Выберите правильную форму: ___ pracę o ósmej. (начинаю)", "Виберіть правильну форму: ___ pracę o ósmej. (починаю)", "Choose the correct form: ___ pracę o ósmej. (I start)", + "A", None, None), + ("a1_work_professions_l07_q2", "a1_work_professions_l07", "lesson_practice", "production", "work_schedule", 2, + "Wpisz brakujące słowo: ___ pracę o szesnastej. (заканчиваю)", "Вставьте пропущенное слово: ___ pracę o szesnastej. (заканчиваю)", "Вставте пропущене слово: ___ pracę o szesnastej. (закінчую)", "Fill in the missing word: ___ pracę o szesnastej. (I finish)", + "Kończę", "first_letter", "K"), + ("a1_work_professions_l07_q3", "a1_work_professions_l07", "lesson_practice", "application", "work_schedule", 2, + "Kolega pyta, o której zaczynasz pracę. Zaczynasz o ósmej. Co powiesz?", "Друг спрашивает, во сколько ты начинаешь работу. Ты начинаешь в восемь. Что ты скажешь?", "Друг питає, о котрій ти починаєш роботу. Ти починаєш о восьмій. Що ти скажеш?", "A friend asks what time you start work. You start at eight. What do you say?", + "A", None, None), + + # L08 — job_search (difficulty 2) + ("a1_work_professions_l08_q1", "a1_work_professions_l08", "lesson_practice", "recognition", "job_search", 2, + "Wybierz poprawną formę: Szukam ___. (praca)", "Выберите правильную форму: Szukam ___. (praca)", "Виберіть правильну форму: Szukam ___. (praca)", "Choose the correct form: Szukam ___. (praca)", + "A", None, None), + ("a1_work_professions_l08_q2", "a1_work_professions_l08", "lesson_practice", "production", "job_search", 2, + "Wpisz brakujące słowo: Mam dobrą ___. (работу)", "Вставьте пропущенное слово: Mam dobrą ___. (работу)", "Вставте пропущене слово: Mam dobrą ___. (роботу)", "Fill in the missing word: Mam dobrą ___. (job)", + "pracę", "first_letter", "p"), + ("a1_work_professions_l08_q3", "a1_work_professions_l08", "lesson_practice", "application", "job_search", 2, + "Nie masz pracy i chcesz ją znaleźć. Co powiesz?", "У тебя нет работы, и ты хочешь её найти. Что ты скажешь?", "У тебе немає роботи, і ти хочеш її знайти. Що ти скажеш?", "You have no job and want to find one. What do you say?", + "A", None, None), + + # L09 — career_plans (difficulty 3) + ("a1_work_professions_l09_q1", "a1_work_professions_l09", "lesson_practice", "recognition", "career_plans", 3, + "Co znaczy „Chcę zostać lekarzem”?", "Что означает «Chcę zostać lekarzem»?", "Що означає «Chcę zostać lekarzem»?", "What does “Chcę zostać lekarzem” mean?", + "A", None, None), + ("a1_work_professions_l09_q2", "a1_work_professions_l09", "lesson_practice", "production", "career_plans", 3, + "Wpisz brakujące słowo: Chcę ___ nauczycielką. (стать)", "Вставьте пропущенное слово: Chcę ___ nauczycielką. (стать)", "Вставте пропущене слово: Chcę ___ nauczycielką. (стати)", "Fill in the missing word: Chcę ___ nauczycielką. (become)", + "zostać", "first_letter", "z"), + ("a1_work_professions_l09_q3", "a1_work_professions_l09", "lesson_practice", "application", "career_plans", 3, + "Marzysz, żeby w przyszłości leczyć ludzi. Co powiesz?", "Ты мечтаешь в будущем лечить людей. Что ты скажешь?", "Ти мрієш у майбутньому лікувати людей. Що ти скажеш?", "You dream of treating people in the future. What do you say?", + "A", None, None), + + # L10 — work_description (difficulty 3) + ("a1_work_professions_l10_q1", "a1_work_professions_l10", "lesson_practice", "recognition", "work_description", 3, + "Które zdanie poprawnie opisuje pracę nauczycielki?", "Какое предложение правильно описывает работу учительницы?", "Яке речення правильно описує роботу вчительки?", "Which sentence correctly describes a teacher's job?", + "A", None, None), + ("a1_work_professions_l10_q2", "a1_work_professions_l10", "lesson_practice", "production", "work_description", 3, + "Przetłumacz: «Я начинаю работу в восемь и заканчиваю в шестнадцать».", "Переведите: «Я начинаю работу в восемь и заканчиваю в шестнадцать».", "Перекладіть: «Я починаю роботу о восьмій і закінчую о шістнадцятій».", "Translate: “I start work at eight and finish at four p.m.”", + "Zaczynam pracę o ósmej i kończę o szesnastej", "first_letter", "Z"), + ("a1_work_professions_l10_q3", "a1_work_professions_l10", "lesson_practice", "application", "work_description", 3, + "Chcesz opisać koledze swoją pracę: jesteś kucharzem, pracujesz w restauracji, zaczynasz o dziesiątej. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою работу: ты повар, работаешь в ресторане, начинаешь в десять. Как ты начнёшь предложение?", "Ти хочеш описати другу свою роботу: ти кухар, працюєш у ресторані, починаєш о десятій. Як ти почнеш речення?", "You want to describe your job to a friend: you're a cook, you work at a restaurant, you start at ten. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t10: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_work_professions', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t10 = [ + # L01 + ("a1_work_professions_l01_q1", "A", "lekarz", "врач", "лікар", "doctor", True, None), + ("a1_work_professions_l01_q1", "B", "nauczyciel", "учитель", "вчитель", "teacher", False, "wrong_word"), + ("a1_work_professions_l01_q1", "C", "kucharz", "повар", "кухар", "cook", False, "wrong_word"), + ("a1_work_professions_l01_q1", "D", "sprzedawca", "продавец", "продавець", "salesman", False, "wrong_word"), + + ("a1_work_professions_l01_q3", "A", "lekarz", "врач", "лікар", "doctor", True, None), + ("a1_work_professions_l01_q3", "B", "nauczyciel", "учитель", "вчитель", "teacher", False, "wrong_context"), + ("a1_work_professions_l01_q3", "C", "kucharz", "повар", "кухар", "cook", False, "wrong_context"), + ("a1_work_professions_l01_q3", "D", "sprzedawca", "продавец", "продавець", "salesman", False, "wrong_context"), + + # L02 + ("a1_work_professions_l02_q1", "A", "sprzedawczyni", "продавщица", "продавщиня", "saleswoman", True, None), + ("a1_work_professions_l02_q1", "B", "nauczycielka", "учительница", "вчителька", "female teacher", False, "wrong_word"), + ("a1_work_professions_l02_q1", "C", "lekarka", "врач (женщина)", "лікарка", "female doctor", False, "wrong_word"), + ("a1_work_professions_l02_q1", "D", "kucharka", "повариха", "кухарка", "female cook", False, "wrong_word"), + + ("a1_work_professions_l02_q3", "A", "kucharka", "повариха", "кухарка", "female cook", True, None), + ("a1_work_professions_l02_q3", "B", "lekarka", "врач (женщина)", "лікарка", "female doctor", False, "wrong_context"), + ("a1_work_professions_l02_q3", "C", "nauczycielka", "учительница", "вчителька", "female teacher", False, "wrong_context"), + ("a1_work_professions_l02_q3", "D", "sprzedawczyni", "продавщица", "продавщиня", "saleswoman", False, "wrong_context"), + + # L03 + ("a1_work_professions_l03_q1", "A", "jako", "как (в роли)", "як (у ролі)", "as", True, None), + ("a1_work_professions_l03_q1", "B", "jak", "как (сравнение)", "як (порівняння)", "how/like", False, "wrong_word"), + ("a1_work_professions_l03_q1", "C", "jakiś", "какой-то", "якийсь", "some", False, "wrong_word"), + ("a1_work_professions_l03_q1", "D", "jaki", "какой", "який", "what kind of", False, "wrong_word"), + + ("a1_work_professions_l03_q3", "A", "Pracuję jako kucharz.", "Я работаю поваром.", "Я працюю кухарем.", "I work as a cook.", True, None), + ("a1_work_professions_l03_q3", "B", "Pracuję jako lekarz.", "Я работаю врачом. (неверная профессия)", "Я працюю лікарем. (невірна професія)", "I work as a doctor. (wrong job)", False, "wrong_context"), + ("a1_work_professions_l03_q3", "C", "Jestem w kuchni.", "Я на кухне.", "Я на кухні.", "I'm in the kitchen.", False, "wrong_sentence_type"), + ("a1_work_professions_l03_q3", "D", "Mam kucharza.", "У меня есть повар.", "У мене є кухар.", "I have a cook.", False, "wrong_sentence_type"), + + # L04 + ("a1_work_professions_l04_q1", "A", "lekarzem", "врачом (тв.)", "лікарем (ор.)", "doctor (instr.)", True, None), + ("a1_work_professions_l04_q1", "B", "lekarz", "врач (им.)", "лікар (наз.)", "doctor (nom.)", False, "wrong_case"), + ("a1_work_professions_l04_q1", "C", "lekarza", "врача (род.)", "лікаря (род.)", "doctor (gen.)", False, "wrong_case"), + ("a1_work_professions_l04_q1", "D", "lekarzowi", "врачу (дат.)", "лікарю (дав.)", "doctor (dat.)", False, "wrong_case"), + + ("a1_work_professions_l04_q3", "A", "Jestem kucharzem.", "Я повар.", "Я кухар.", "I am a cook.", True, None), + ("a1_work_professions_l04_q3", "B", "Jestem kucharz.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_work_professions_l04_q3", "C", "Pracuję kucharz.", "Пропущено „jako”.", "Пропущено „jako”.", "Missing „jako”.", False, "wrong_sentence_type"), + ("a1_work_professions_l04_q3", "D", "Mam kucharza.", "У меня есть повар.", "У мене є кухар.", "I have a cook.", False, "wrong_context"), + + # L05 + ("a1_work_professions_l05_q1", "A", "szpital", "больница", "лікарня", "hospital", True, None), + ("a1_work_professions_l05_q1", "B", "biuro", "офис", "офіс", "office", False, "wrong_word"), + ("a1_work_professions_l05_q1", "C", "szkoła", "школа", "школа", "school", False, "wrong_word"), + ("a1_work_professions_l05_q1", "D", "sklep", "магазин", "магазин", "shop", False, "wrong_word"), + + ("a1_work_professions_l05_q3", "A", "sklep", "магазин", "магазин", "shop", True, None), + ("a1_work_professions_l05_q3", "B", "szpital", "больница", "лікарня", "hospital", False, "wrong_context"), + ("a1_work_professions_l05_q3", "C", "biuro", "офис", "офіс", "office", False, "wrong_context"), + ("a1_work_professions_l05_q3", "D", "szkoła", "школа", "школа", "school", False, "wrong_context"), + + # L06 + ("a1_work_professions_l06_q1", "A", "w biurze", "в офисе (местн.)", "в офісі (місц.)", "in the office (loc.)", True, None), + ("a1_work_professions_l06_q1", "B", "biuro", "офис (им.)", "офіс (наз.)", "office (nom.)", False, "wrong_case"), + ("a1_work_professions_l06_q1", "C", "w biuro", "неправильная форма", "неправильна форма", "wrong form", False, "wrong_case"), + ("a1_work_professions_l06_q1", "D", "biura", "офиса (род.)", "офісу (род.)", "office (gen.)", False, "wrong_case"), + + ("a1_work_professions_l06_q3", "A", "Pracuję w restauracji.", "Я работаю в ресторане.", "Я працюю в ресторані.", "I work at a restaurant.", True, None), + ("a1_work_professions_l06_q3", "B", "Pracuję restauracja.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_work_professions_l06_q3", "C", "Jestem restauracja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_work_professions_l06_q3", "D", "Mam restaurację.", "У меня есть ресторан.", "У мене є ресторан.", "I have a restaurant.", False, "wrong_context"), + + # L07 + ("a1_work_professions_l07_q1", "A", "Zaczynam", "начинаю", "починаю", "I start", True, None), + ("a1_work_professions_l07_q1", "B", "Zaczynasz", "начинаешь", "починаєш", "you start", False, "wrong_word"), + ("a1_work_professions_l07_q1", "C", "Kończę", "заканчиваю", "закінчую", "I finish", False, "wrong_context"), + ("a1_work_professions_l07_q1", "D", "Kończysz", "заканчиваешь", "закінчуєш", "you finish", False, "wrong_context"), + + ("a1_work_professions_l07_q3", "A", "Zaczynam pracę o ósmej.", "Я начинаю работу в восемь.", "Я починаю роботу о восьмій.", "I start work at eight.", True, None), + ("a1_work_professions_l07_q3", "B", "Kończę pracę o ósmej.", "Я заканчиваю работу в восемь. (неверный контекст)", "Я закінчую роботу о восьмій. (невірний контекст)", "I finish work at eight. (wrong context)", False, "wrong_context"), + ("a1_work_professions_l07_q3", "C", "Pracuję o ósmej godzinie.", "Неестественная конструкция.", "Неприродна конструкція.", "Unnatural construction.", False, "wrong_sentence_type"), + ("a1_work_professions_l07_q3", "D", "Jestem w pracy o ósmej.", "Я на работе в восемь. (не отвечает на вопрос)", "Я на роботі о восьмій. (не відповідає на питання)", "I'm at work at eight. (doesn't answer the question)", False, "wrong_context"), + + # L08 + ("a1_work_professions_l08_q1", "A", "pracy", "работы (род.)", "роботи (род.)", "job (gen.)", True, None), + ("a1_work_professions_l08_q1", "B", "pracę", "работу (вин.)", "роботу (знах.)", "job (acc.)", False, "wrong_case"), + ("a1_work_professions_l08_q1", "C", "praca", "работа (им.)", "робота (наз.)", "job (nom.)", False, "wrong_case"), + ("a1_work_professions_l08_q1", "D", "pracą", "работой (тв.)", "роботою (ор.)", "job (instr.)", False, "wrong_case"), + + ("a1_work_professions_l08_q3", "A", "Szukam pracy.", "Я ищу работу.", "Я шукаю роботу.", "I'm looking for a job.", True, None), + ("a1_work_professions_l08_q3", "B", "Mam pracę.", "У меня есть работа. (противоречит ситуации)", "У мене є робота. (суперечить ситуації)", "I have a job. (contradicts the situation)", False, "wrong_context"), + ("a1_work_professions_l08_q3", "C", "Kończę pracę.", "Я заканчиваю работу. (не о поиске)", "Я закінчую роботу. (не про пошук)", "I'm finishing work. (not about searching)", False, "wrong_context"), + ("a1_work_professions_l08_q3", "D", "Zaczynam pracę.", "Я начинаю работу. (не о поиске)", "Я починаю роботу. (не про пошук)", "I'm starting work. (not about searching)", False, "wrong_context"), + + # L09 + ("a1_work_professions_l09_q1", "A", "Chcę zostać lekarzem.", "Я хочу стать врачом.", "Я хочу стати лікарем.", "I want to become a doctor.", True, None), + ("a1_work_professions_l09_q1", "B", "Jestem lekarzem.", "Я врач.", "Я лікар.", "I am a doctor.", False, "wrong_translation"), + ("a1_work_professions_l09_q1", "C", "Pracuję jako lekarz.", "Я работаю врачом.", "Я працюю лікарем.", "I work as a doctor.", False, "wrong_translation"), + ("a1_work_professions_l09_q1", "D", "Szukam lekarza.", "Я ищу врача.", "Я шукаю лікаря.", "I am looking for a doctor.", False, "wrong_translation"), + + ("a1_work_professions_l09_q3", "A", "Chcę zostać lekarzem.", "Я хочу стать врачом.", "Я хочу стати лікарем.", "I want to become a doctor.", True, None), + ("a1_work_professions_l09_q3", "B", "Chcę zostać kucharzem.", "Я хочу стать поваром. (неверная профессия)", "Я хочу стати кухарем. (невірна професія)", "I want to become a cook. (wrong job)", False, "wrong_context"), + ("a1_work_professions_l09_q3", "C", "Jestem lekarzem.", "Я врач. (не о мечте на будущее)", "Я лікар. (не про мрію на майбутнє)", "I am a doctor. (not about a future dream)", False, "wrong_context"), + ("a1_work_professions_l09_q3", "D", "Szukam pracy.", "Я ищу работу. (слишком общее)", "Я шукаю роботу. (занадто загальне)", "I'm looking for a job. (too general)", False, "wrong_context"), + + # L10 + ("a1_work_professions_l10_q1", "A", "Pracuję jako nauczycielka w szkole.", "Я работаю учительницей в школе.", "Я працюю вчителькою в школі.", "I work as a teacher at a school.", True, None), + ("a1_work_professions_l10_q1", "B", "Pracuję nauczycielka szkoła.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_work_professions_l10_q1", "C", "Jestem nauczycielka w szkole pracuję.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_work_professions_l10_q1", "D", "Pracuję jako lekarz w szpitalu.", "Неверная профессия и место.", "Невірна професія і місце.", "Wrong job and workplace.", False, "wrong_context"), + + ("a1_work_professions_l10_q3", "A", "Pracuję jako kucharz w restauracji.", "Я работаю поваром в ресторане.", "Я працюю кухарем у ресторані.", "I work as a cook at a restaurant.", True, None), + ("a1_work_professions_l10_q3", "B", "Jestem restauracja kucharz.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_work_professions_l10_q3", "C", "Szukam pracy w restauracji.", "Я ищу работу в ресторане. (не соответствует ситуации)", "Я шукаю роботу в ресторані. (не відповідає ситуації)", "I'm looking for a job at a restaurant. (wrong context)", False, "wrong_context"), + ("a1_work_professions_l10_q3", "D", "Chcę zostać kucharzem.", "Я хочу стать поваром. (не о текущей работе)", "Я хочу стати кухарем. (не про поточну роботу)", "I want to become a cook. (not about the current job)", False, "wrong_context"), + ] + + for opt in options_t10: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t10 = [ + ("a1_work_professions_t01", None, "topic_test", "recognition", "professions_vocabulary", 1, + "Jak po polsku „повар”?", "Как по-польски «повар»?", "Як польською «кухар»?", "How do you say “cook” in Polish?", + "A", None, None, 1), + ("a1_work_professions_t02", None, "topic_test", "recognition", "professions_vocabulary_fem", 1, + "Jak po polsku „продавщица”?", "Как по-польски «продавщица»?", "Як польською «продавщиня»?", "How do you say “saleswoman” in Polish?", + "A", None, None, 2), + ("a1_work_professions_t03", None, "topic_test", "recognition", "profession_work_jako", 1, + "Wybierz poprawną formę: Pracuję ___ lekarz.", "Выберите правильную форму: Pracuję ___ lekarz.", "Виберіть правильну форму: Pracuję ___ lekarz.", "Choose the correct form: Pracuję ___ lekarz.", + "A", None, None, 3), + ("a1_work_professions_t04", None, "topic_test", "recognition", "profession_identity_instrumental", 2, + "Wybierz poprawną formę: Jestem ___. (nauczyciel)", "Выберите правильную форму: Jestem ___. (nauczyciel)", "Виберіть правильну форму: Jestem ___. (nauczyciel)", "Choose the correct form: Jestem ___. (nauczyciel)", + "A", None, None, 4), + ("a1_work_professions_t05", None, "topic_test", "recognition", "workplace_vocabulary", 2, + "Jak po polsku „больница”?", "Как по-польски «больница»?", "Як польською «лікарня»?", "How do you say “hospital” in Polish?", + "A", None, None, 5), + ("a1_work_professions_t06", None, "topic_test", "recognition", "career_plans", 3, + "Co znaczy „Chcę zostać lekarzem”?", "Что означает «Chcę zostać lekarzem»?", "Що означає «Chcę zostać lekarzem»?", "What does “Chcę zostać lekarzem” mean?", + "A", None, None, 6), + + ("a1_work_professions_t07", None, "topic_test", "application", "professions_vocabulary", 1, + "Ta osoba uczy dzieci w szkole. Kim ona jest?", "Этот человек учит детей в школе. Кто она?", "Ця людина вчить дітей у школі. Хто вона?", "This person teaches children at school. Who is she?", + "A", None, None, 7), + ("a1_work_professions_t08", None, "topic_test", "application", "professions_vocabulary_fem", 1, + "Widzisz kobietę, która sprzedaje ubrania w sklepie. Kim ona jest?", "Ты видишь женщину, которая продаёт одежду в магазине. Кто она?", "Ти бачиш жінку, яка продає одяг у магазині. Хто вона?", "You see a woman selling clothes at a shop. Who is she?", + "A", None, None, 8), + ("a1_work_professions_t09", None, "topic_test", "application", "workplace_locative", 2, + "Chcesz powiedzieć, że pracujesz w biurze. Co powiesz?", "Ты хочешь сказать, что работаешь в офисе. Что ты скажешь?", "Ти хочеш сказати, що працюєш в офісі. Що ти скажеш?", "You want to say you work in an office. What do you say?", + "A", None, None, 9), + ("a1_work_professions_t10", None, "topic_test", "application", "work_schedule", 2, + "Kolega pyta, kiedy kończysz pracę. Kończysz o szesnastej. Co powiesz?", "Друг спрашивает, когда ты заканчиваешь работу. Ты заканчиваешь в шестнадцать. Что ты скажешь?", "Друг питає, коли ти закінчуєш роботу. Ти закінчуєш о шістнадцятій. Що ти скажеш?", "A friend asks when you finish work. You finish at four p.m. What do you say?", + "A", None, None, 10), + ("a1_work_professions_t11", None, "topic_test", "application", "job_search", 3, + "Nie masz pracy. Chcesz to powiedzieć koledze. Co powiesz?", "У тебя нет работы. Ты хочешь сказать об этом другу. Что ты скажешь?", "У тебе немає роботи. Ти хочеш сказати про це другу. Що ти скажеш?", "You have no job. You want to tell a friend. What do you say?", + "A", None, None, 11), + ("a1_work_professions_t12", None, "topic_test", "application", "career_plans", 3, + "Marzysz, żeby uczyć dzieci w przyszłości. Co powiesz?", "Ты мечтаешь учить детей в будущем. Что ты скажешь?", "Ти мрієш вчити дітей у майбутньому. Що ти скажеш?", "You dream of teaching children in the future. What do you say?", + "A", None, None, 12), + + ("a1_work_professions_t13", None, "topic_test", "production", "professions_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (продавец)", "Вставьте пропущенное слово: To jest ___. (продавец)", "Вставте пропущене слово: To jest ___. (продавець)", "Fill in the missing word: To jest ___. (salesman)", + "sprzedawca", "first_letter", "s", 13), + ("a1_work_professions_t14", None, "topic_test", "production", "professions_vocabulary_fem", 1, + "Wpisz brakujące słowo: To jest ___. (врач, женщина)", "Вставьте пропущенное слово: To jest ___. (врач, женщина)", "Вставте пропущене слово: To jest ___. (лікарка)", "Fill in the missing word: To jest ___. (female doctor)", + "lekarka", "first_letter", "l", 14), + ("a1_work_professions_t15", None, "topic_test", "production", "workplace_vocabulary", 2, + "Wpisz brakujące słowo: To jest ___. (офис)", "Вставьте пропущенное слово: To jest ___. (офис)", "Вставте пропущене слово: To jest ___. (офіс)", "Fill in the missing word: To jest ___. (office)", + "biuro", "first_letter", "b", 15), + ("a1_work_professions_t16", None, "topic_test", "production", "workplace_locative", 2, + "Wpisz brakujące słowo: Pracuję ___. (в школе)", "Вставьте пропущенное слово: Pracuję ___. (в школе)", "Вставте пропущене слово: Pracuję ___. (в школі)", "Fill in the missing word: Pracuję ___. (at school)", + "w szkole", "first_letter", "w", 16), + ("a1_work_professions_t17", None, "topic_test", "production", "career_plans", 3, + "Wpisz brakujące słowo: Chcę ___ lekarzem. (стать)", "Вставьте пропущенное слово: Chcę ___ lekarzem. (стать)", "Вставте пропущене слово: Chcę ___ lekarzem. (стати)", "Fill in the missing word: Chcę ___ lekarzem. (become)", + "zostać", "first_letter", "z", 17), + ("a1_work_professions_t18", None, "topic_test", "production", "work_description", 2, + "Przetłumacz: «Я работаю поваром в ресторане».", "Переведите: «Я работаю поваром в ресторане».", "Перекладіть: «Я працюю кухарем у ресторані».", "Translate: “I work as a cook at a restaurant.”", + "Pracuję jako kucharz w restauracji", "first_letter", "P", 18), + + ("a1_work_professions_t19", None, "topic_test", "mixed", "job_search", 3, + "Wybierz poprawne tłumaczenie: «Я ищу новую работу, потому что хочу стать учителем».", "Выберите правильный перевод: «Я ищу новую работу, потому что хочу стать учителем».", "Виберіть правильний переклад: «Я шукаю нову роботу, тому що хочу стати вчителем».", "Choose the correct translation: “I'm looking for a new job because I want to become a teacher.”", + "A", None, None, 19), + ("a1_work_professions_t20", None, "topic_test", "mixed", "work_description", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Кто ты по профессии? — Я врач, работаю в больнице.»", "Выберите правильный перевод диалога: «— Кто ты по профессии? — Я врач, работаю в больнице.»", "Виберіть правильний переклад діалогу: «— Хто ти за професією? — Я лікар, працюю в лікарні.»", "Choose the correct translation of the dialogue: “— What's your profession? — I'm a doctor, I work at a hospital.”", + "A", None, None, 20), + ] + + for q in test_questions_t10: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_work_professions', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t10 = [ + ("a1_work_professions_t01", "A", "kucharz", "повар", "кухар", "cook", True, None), + ("a1_work_professions_t01", "B", "lekarz", "врач", "лікар", "doctor", False, "wrong_word"), + ("a1_work_professions_t01", "C", "nauczyciel", "учитель", "вчитель", "teacher", False, "wrong_word"), + ("a1_work_professions_t01", "D", "sprzedawca", "продавец", "продавець", "salesman", False, "wrong_word"), + + ("a1_work_professions_t02", "A", "sprzedawczyni", "продавщица", "продавщиня", "saleswoman", True, None), + ("a1_work_professions_t02", "B", "nauczycielka", "учительница", "вчителька", "female teacher", False, "wrong_word"), + ("a1_work_professions_t02", "C", "lekarka", "врач (женщина)", "лікарка", "female doctor", False, "wrong_word"), + ("a1_work_professions_t02", "D", "kucharka", "повариха", "кухарка", "female cook", False, "wrong_word"), + + ("a1_work_professions_t03", "A", "jako", "как (в роли)", "як (у ролі)", "as", True, None), + ("a1_work_professions_t03", "B", "jak", "как (сравнение)", "як (порівняння)", "how/like", False, "wrong_word"), + ("a1_work_professions_t03", "C", "jaki", "какой", "який", "what kind of", False, "wrong_word"), + ("a1_work_professions_t03", "D", "jaka", "какая", "яка", "what kind of (fem.)", False, "wrong_word"), + + ("a1_work_professions_t04", "A", "nauczycielem", "учителем (тв.)", "вчителем (ор.)", "teacher (instr.)", True, None), + ("a1_work_professions_t04", "B", "nauczyciel", "учитель (им.)", "вчитель (наз.)", "teacher (nom.)", False, "wrong_case"), + ("a1_work_professions_t04", "C", "nauczyciela", "учителя (род.)", "вчителя (род.)", "teacher (gen.)", False, "wrong_case"), + ("a1_work_professions_t04", "D", "nauczycielowi", "учителю (дат.)", "вчителю (дав.)", "teacher (dat.)", False, "wrong_case"), + + ("a1_work_professions_t05", "A", "szpital", "больница", "лікарня", "hospital", True, None), + ("a1_work_professions_t05", "B", "biuro", "офис", "офіс", "office", False, "wrong_word"), + ("a1_work_professions_t05", "C", "szkoła", "школа", "школа", "school", False, "wrong_word"), + ("a1_work_professions_t05", "D", "sklep", "магазин", "магазин", "shop", False, "wrong_word"), + + ("a1_work_professions_t06", "A", "Chcę zostać lekarzem.", "Я хочу стать врачом.", "Я хочу стати лікарем.", "I want to become a doctor.", True, None), + ("a1_work_professions_t06", "B", "Jestem lekarzem.", "Я врач.", "Я лікар.", "I am a doctor.", False, "wrong_translation"), + ("a1_work_professions_t06", "C", "Pracuję jako lekarz.", "Я работаю врачом.", "Я працюю лікарем.", "I work as a doctor.", False, "wrong_translation"), + ("a1_work_professions_t06", "D", "Szukam lekarza.", "Я ищу врача.", "Я шукаю лікаря.", "I am looking for a doctor.", False, "wrong_translation"), + + ("a1_work_professions_t07", "A", "nauczycielka", "учительница", "вчителька", "female teacher", True, None), + ("a1_work_professions_t07", "B", "lekarka", "врач (женщина)", "лікарка", "female doctor", False, "wrong_context"), + ("a1_work_professions_t07", "C", "kucharka", "повариха", "кухарка", "female cook", False, "wrong_context"), + ("a1_work_professions_t07", "D", "sprzedawczyni", "продавщица", "продавщиня", "saleswoman", False, "wrong_context"), + + ("a1_work_professions_t08", "A", "sprzedawczyni", "продавщица", "продавщиня", "saleswoman", True, None), + ("a1_work_professions_t08", "B", "nauczycielka", "учительница", "вчителька", "female teacher", False, "wrong_context"), + ("a1_work_professions_t08", "C", "lekarka", "врач (женщина)", "лікарка", "female doctor", False, "wrong_context"), + ("a1_work_professions_t08", "D", "kucharka", "повариха", "кухарка", "female cook", False, "wrong_context"), + + ("a1_work_professions_t09", "A", "Pracuję w biurze.", "Я работаю в офисе.", "Я працюю в офісі.", "I work in an office.", True, None), + ("a1_work_professions_t09", "B", "Pracuję biuro.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_work_professions_t09", "C", "Jestem biuro.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_work_professions_t09", "D", "Mam biuro.", "У меня есть офис.", "У мене є офіс.", "I have an office.", False, "wrong_context"), + + ("a1_work_professions_t10", "A", "Kończę pracę o szesnastej.", "Я заканчиваю работу в шестнадцать.", "Я закінчую роботу о шістнадцятій.", "I finish work at four p.m.", True, None), + ("a1_work_professions_t10", "B", "Zaczynam pracę o szesnastej.", "Я начинаю работу в шестнадцать. (неверный контекст)", "Я починаю роботу о шістнадцятій. (невірний контекст)", "I start work at four p.m. (wrong context)", False, "wrong_context"), + ("a1_work_professions_t10", "C", "Pracuję szesnaście godzin.", "Я работаю шестнадцать часов.", "Я працюю шістнадцять годин.", "I work sixteen hours.", False, "wrong_context"), + ("a1_work_professions_t10", "D", "Jestem w pracy szesnaście.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + ("a1_work_professions_t11", "A", "Szukam pracy.", "Я ищу работу.", "Я шукаю роботу.", "I'm looking for a job.", True, None), + ("a1_work_professions_t11", "B", "Mam pracę.", "У меня есть работа. (противоречит ситуации)", "У мене є робота. (суперечить ситуації)", "I have a job. (contradicts the situation)", False, "wrong_context"), + ("a1_work_professions_t11", "C", "Kończę pracę.", "Я заканчиваю работу.", "Я закінчую роботу.", "I'm finishing work.", False, "wrong_context"), + ("a1_work_professions_t11", "D", "Zostaję lekarzem.", "Я становлюсь врачом. (не о поиске)", "Я стаю лікарем. (не про пошук)", "I'm becoming a doctor. (not about searching)", False, "wrong_context"), + + ("a1_work_professions_t12", "A", "Chcę zostać nauczycielką.", "Я хочу стать учительницей.", "Я хочу стати вчителькою.", "I want to become a teacher.", True, None), + ("a1_work_professions_t12", "B", "Chcę zostać lekarzem.", "Я хочу стать врачом. (неверная профессия)", "Я хочу стати лікарем. (невірна професія)", "I want to become a doctor. (wrong job)", False, "wrong_context"), + ("a1_work_professions_t12", "C", "Jestem nauczycielką.", "Я учительница. (не о мечте)", "Я вчителька. (не про мрію)", "I am a teacher. (not about a dream)", False, "wrong_context"), + ("a1_work_professions_t12", "D", "Szukam pracy.", "Я ищу работу. (слишком общее)", "Я шукаю роботу. (занадто загальне)", "I'm looking for a job. (too general)", False, "wrong_context"), + + ("a1_work_professions_t19", "A", "Szukam nowej pracy, ponieważ chcę zostać nauczycielem.", "Я ищу новую работу, потому что хочу стать учителем.", "Я шукаю нову роботу, тому що хочу стати вчителем.", "I'm looking for a new job because I want to become a teacher.", True, None), + ("a1_work_professions_t19", "B", "Mam nową pracę, ponieważ jestem nauczycielem.", "Смысл искажён.", "Сенс спотворено.", "Meaning is reversed.", False, "wrong_translation"), + ("a1_work_professions_t19", "C", "Szukam nowej szkoły, ponieważ chcę zostać nauczycielem.", "Неправильное слово.", "Неправильне слово.", "Wrong word.", False, "wrong_word"), + ("a1_work_professions_t19", "D", "Nowa praca szukam, chcę nauczyciel zostać.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + ("a1_work_professions_t20", "A", "Kim jesteś z zawodu? Jestem lekarzem, pracuję w szpitalu.", "Кто ты по профессии? Я врач, работаю в больнице.", "Хто ти за професією? Я лікар, працюю в лікарні.", "What's your profession? I'm a doctor, I work at a hospital.", True, None), + ("a1_work_professions_t20", "B", "Gdzie pracujesz? Pracuję w szpitalu jako lekarz.", "Другой вопрос в диалоге.", "Інше питання в діалозі.", "Different question in the dialogue.", False, "wrong_translation"), + ("a1_work_professions_t20", "C", "Kim jesteś z zawodu? Jestem nauczycielem, pracuję w szpitalu.", "Неверная профессия.", "Невірна професія.", "Wrong profession.", False, "wrong_word"), + ("a1_work_professions_t20", "D", "Kim jesteś z zawodu? Jestem lekarzem, pracuję w szkole.", "Неверное место работы.", "Невірне місце роботи.", "Wrong workplace.", False, "wrong_context"), + ] + + for opt in test_options_t10: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 11: ПОКУПКИ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_shopping', 'A1', 11, + 'Zakupy', + 'Покупки', + 'Покупки', + 'Shopping') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t11 = [ + ("a1_shopping_l01", 1, "shopping_vocabulary", "Podstawowe słowa: zakupy", "Основные слова: покупки", "Основні слова: покупки", "Basic shopping words", + "Podstawowe słowa związane z zakupami: sklep, kasa, koszyk, torba. „Kasa” i „torba” są rodzaju żeńskiego, „sklep” i „koszyk” są rodzaju męskiego.", + "Основные слова, связанные с покупками: sklep (магазин), kasa (касса), koszyk (корзина), torba (сумка). „Kasa” и „torba” женского рода, „sklep” и „koszyk” мужского рода.", + "Основні слова, пов'язані з покупками: sklep (магазин), kasa (каса), koszyk (кошик), torba (сумка). „Kasa” і „torba” жіночого роду, „sklep” і „koszyk” чоловічого роду.", + "Basic shopping words: sklep (shop), kasa (checkout), koszyk (basket), torba (bag). „Kasa” and „torba” are feminine, „sklep” and „koszyk” are masculine."), + + ("a1_shopping_l02", 2, "food_vocabulary", "Podstawowe produkty spożywcze", "Основные продукты питания", "Основні продукти харчування", "Basic food products", + "Podstawowe produkty spożywcze: chleb, mleko, ser, jabłko. „Chleb” i „ser” są rodzaju męskiego, „mleko” i „jabłko” są rodzaju nijakiego.", + "Основные продукты питания: chleb (хлеб), mleko (молоко), ser (сыр), jabłko (яблоко). „Chleb” и „ser” мужского рода, „mleko” и „jabłko” среднего рода.", + "Основні продукти харчування: chleb (хліб), mleko (молоко), ser (сир), jabłko (яблуко). „Chleb” і „ser” чоловічого роду, „mleko” і „jabłko” середнього роду.", + "Basic food products: chleb (bread), mleko (milk), ser (cheese), jabłko (apple). „Chleb” and „ser” are masculine, „mleko” and „jabłko” are neuter."), + + ("a1_shopping_l03", 3, "verb_kupowac", "Kupuję, kupujesz — czasownik kupować", "Kupuję, kupujesz — глагол kupować", "Kupuję, kupujesz — дієслово kupować", "Kupuję, kupujesz — the verb kupować", + "Czasownika „kupować” używamy, żeby mówić o kupowaniu: ja kupuję, ty kupujesz, on/ona kupuje.", + "Глагол „kupować” (покупать) используем, чтобы говорить о покупках: ja kupuję (я покупаю), ty kupujesz (ты покупаешь), on/ona kupuje (он/она покупает).", + "Дієслово „kupować” (купувати) використовуємо, щоб говорити про покупки: ja kupuję (я купую), ty kupujesz (ти купуєш), on/ona kupuje (він/вона купує).", + "The verb „kupować” (to buy) is used to talk about buying: ja kupuję (I buy), ty kupujesz (you buy), on/ona kupuje (he/she buys)."), + + ("a1_shopping_l04", 4, "verb_chciec_kupic", "Chcę kupić + biernik", "Chcę kupić + винительный падеж", "Chcę kupić + знахідний відмінок", "Chcę kupić + accusative", + "Żeby powiedzieć, co chcemy kupić, używamy „chcę kupić” + biernik: chcę kupić chleb, chcę kupić mleko, chcę kupić ser.", + "Чтобы сказать, что мы хотим купить, используем „chcę kupić” + винительный падеж: chcę kupić chleb (я хочу купить хлеб), chcę kupić mleko (я хочу купить молоко).", + "Щоб сказати, що ми хочемо купити, використовуємо „chcę kupić” + знахідний відмінок: chcę kupić chleb (я хочу купити хліб), chcę kupić mleko (я хочу купити молоко).", + "To say what we want to buy, we use „chcę kupić” + the accusative: chcę kupić chleb (I want to buy bread), chcę kupić mleko (I want to buy milk)."), + + ("a1_shopping_l05", 5, "prices_ile_kosztuje", "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does this cost?", + "Pytamy o cenę: „Ile to kosztuje?” albo „Ile kosztuje + mianownik?”: Ile kosztuje chleb? Ile kosztuje mleko?", + "Спрашиваем о цене: „Ile to kosztuje?” (Сколько это стоит?) или „Ile kosztuje + именительный падеж?”: Ile kosztuje chleb? (Сколько стоит хлеб?)", + "Запитуємо про ціну: „Ile to kosztuje?” (Скільки це коштує?) або „Ile kosztuje + називний відмінок?”: Ile kosztuje chleb? (Скільки коштує хліб?)", + "We ask about price with „Ile to kosztuje?” (How much does this cost?) or „Ile kosztuje + nominative?”: Ile kosztuje chleb? (How much does the bread cost?)"), + + ("a1_shopping_l06", 6, "numbers_prices", "Złoty, złote, złotych", "Злотый, злотых", "Злотий, злотих", "Zloty, zlote, zlotych", + "Ceny podajemy liczbą + odpowiednią formą słowa „złoty”: jeden złoty (1), dwa/trzy/cztery złote (2-4), pięć złotych (5 i więcej).", + "Цены называем числом + соответствующей формой слова „złoty”: jeden złoty (1), dwa/trzy/cztery złote (2-4), pięć złotych (5 и больше).", + "Ціни називаємо числом + відповідною формою слова „złoty”: jeden złoty (1), dwa/trzy/cztery złote (2-4), pięć złotych (5 і більше).", + "We give prices with a number + the right form of „złoty”: jeden złoty (1), dwa/trzy/cztery złote (2-4), pięć złotych (5 or more)."), + + ("a1_shopping_l07", 7, "quantities_genitive", "Kilogram, litr, kawałek + dopełniacz", "Kilogram, litr, kawałek + родительный падеж", "Kilogram, litr, kawałek + родовий відмінок", "Kilogram, litr, kawałek + genitive", + "Ilości łączymy z dopełniaczem: kilogram jabłek, litr mleka, kawałek sera.", + "Единицы количества требуют родительного падежа: kilogram jabłek (килограмм яблок), litr mleka (литр молока), kawałek sera (кусок сыра).", + "Одиниці кількості вимагають родового відмінка: kilogram jabłek (кілограм яблук), litr mleka (літр молока), kawałek sera (шматок сиру).", + "Quantity words take the genitive: kilogram jabłek (a kilogram of apples), litr mleka (a liter of milk), kawałek sera (a piece of cheese)."), + + ("a1_shopping_l08", 8, "potrzebowac", "Potrzebuję + dopełniacz", "Potrzebuję + родительный падеж", "Potrzebuję + родовий відмінок", "Potrzebuję + genitive", + "Czasownik „potrzebować” łączy się z dopełniaczem: potrzebuję chleba, potrzebujesz mleka, potrzebuje sera.", + "Глагол „potrzebować” (нуждаться) требует родительного падежа: potrzebuję chleba (мне нужен хлеб), potrzebujesz mleka (тебе нужно молоко).", + "Дієслово „potrzebować” (потребувати) вимагає родового відмінка: potrzebuję chleba (мені потрібен хліб), potrzebujesz mleka (тобі потрібне молоко).", + "The verb „potrzebować” (to need) takes the genitive: potrzebuję chleba (I need bread), potrzebujesz mleka (you need milk)."), + + ("a1_shopping_l09", 9, "asking_for_help_shop", "Poproszę / Czy mogę prosić o...?", "Poproszę / Можно мне...?", "Poproszę / Можна мені...?", "Poproszę / Could I have...?", + "W sklepie prosimy grzecznie: „Poproszę” + biernik/dopełniacz ilości, albo „Czy mogę prosić o + biernik?”: Poproszę chleb. Czy mogę prosić o kilogram jabłek?", + "В магазине просим вежливо: „Poproszę” + винительный/родительный падеж количества, или „Czy mogę prosić o + винительный?”: Poproszę chleb (Дайте, пожалуйста, хлеб). Czy mogę prosić o kilogram jabłek? (Можно мне килограмм яблок?)", + "У магазині просимо ввічливо: „Poproszę” + знахідний/родовий відмінок кількості, або „Czy mogę prosić o + знахідний?”: Poproszę chleb (Дайте, будь ласка, хліб). Czy mogę prosić o kilogram jabłek? (Можна мені кілограм яблук?)", + "In a shop we ask politely with „Poproszę” + the accusative/genitive of quantity, or „Czy mogę prosić o + accusative?”: Poproszę chleb (Bread, please). Czy mogę prosić o kilogram jabłek? (Could I have a kilogram of apples?)"), + + ("a1_shopping_l10", 10, "shopping_description", "Opisuję swoje zakupy", "Описываю свои покупки", "Описую свої покупки", "Describing my shopping", + "Żeby opisać zakupy, łączymy kilka zdań: Idę do sklepu. Kupuję chleb, mleko i ser. Płacę w kasie.", + "Чтобы описать покупки, соединяем несколько предложений: Idę do sklepu. Kupuję chleb, mleko i ser. Płacę w kasie. (Я иду в магазин. Я покупаю хлеб, молоко и сыр. Я плачу на кассе.)", + "Щоб описати покупки, поєднуємо кілька речень: Idę do sklepu. Kupuję chleb, mleko i ser. Płacę w kasie. (Я йду до магазину. Я купую хліб, молоко і сир. Я плачу на касі.)", + "To describe shopping, we combine several sentences: Idę do sklepu. Kupuję chleb, mleko i ser. Płacę w kasie. (I'm going to the shop. I'm buying bread, milk and cheese. I pay at the checkout.)"), + ] + + for lesson in lessons_t11: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_shopping', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t11 = [ + ("a1_shopping_l01", 1, "To jest sklep.", "Это магазин.", "Це магазин.", "This is a shop."), + ("a1_shopping_l01", 2, "To jest koszyk.", "Это корзина.", "Це кошик.", "This is a basket."), + ("a1_shopping_l01", 3, "To jest kasa.", "Это касса.", "Це каса.", "This is a checkout."), + + ("a1_shopping_l02", 1, "To jest chleb.", "Это хлеб.", "Це хліб.", "This is bread."), + ("a1_shopping_l02", 2, "To jest mleko.", "Это молоко.", "Це молоко.", "This is milk."), + ("a1_shopping_l02", 3, "To jest ser.", "Это сыр.", "Це сир.", "This is cheese."), + + ("a1_shopping_l03", 1, "Kupuję chleb.", "Я покупаю хлеб.", "Я купую хліб.", "I'm buying bread."), + ("a1_shopping_l03", 2, "Kupujesz mleko?", "Ты покупаешь молоко?", "Ти купуєш молоко?", "Are you buying milk?"), + ("a1_shopping_l03", 3, "Ona kupuje jabłka.", "Она покупает яблоки.", "Вона купує яблука.", "She's buying apples."), + + ("a1_shopping_l04", 1, "Chcę kupić chleb.", "Я хочу купить хлеб.", "Я хочу купити хліб.", "I want to buy bread."), + ("a1_shopping_l04", 2, "Chcesz kupić ser?", "Ты хочешь купить сыр?", "Ти хочеш купити сир?", "Do you want to buy cheese?"), + ("a1_shopping_l04", 3, "On chce kupić jabłka.", "Он хочет купить яблоки.", "Він хоче купити яблука.", "He wants to buy apples."), + + ("a1_shopping_l05", 1, "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does this cost?"), + ("a1_shopping_l05", 2, "Ile kosztuje chleb?", "Сколько стоит хлеб?", "Скільки коштує хліб?", "How much does the bread cost?"), + ("a1_shopping_l05", 3, "Ten ser kosztuje dziesięć złotych.", "Этот сыр стоит десять злотых.", "Цей сир коштує десять злотих.", "This cheese costs ten zlotys."), + + ("a1_shopping_l06", 1, "To kosztuje jeden złoty.", "Это стоит один злотый.", "Це коштує один злотий.", "This costs one zloty."), + ("a1_shopping_l06", 2, "To kosztuje trzy złote.", "Это стоит три злотых.", "Це коштує три злотих.", "This costs three zlotys."), + ("a1_shopping_l06", 3, "To kosztuje dziesięć złotych.", "Это стоит десять злотых.", "Це коштує десять злотих.", "This costs ten zlotys."), + + ("a1_shopping_l07", 1, "Poproszę kilogram jabłek.", "Дайте, пожалуйста, килограмм яблок.", "Дайте, будь ласка, кілограм яблук.", "A kilogram of apples, please."), + ("a1_shopping_l07", 2, "Kupuję litr mleka.", "Я покупаю литр молока.", "Я купую літр молока.", "I'm buying a liter of milk."), + ("a1_shopping_l07", 3, "Chcę kawałek sera.", "Я хочу кусок сыра.", "Я хочу шматок сиру.", "I want a piece of cheese."), + + ("a1_shopping_l08", 1, "Potrzebuję chleba.", "Мне нужен хлеб.", "Мені потрібен хліб.", "I need bread."), + ("a1_shopping_l08", 2, "Potrzebujesz mleka?", "Тебе нужно молоко?", "Тобі потрібне молоко?", "Do you need milk?"), + ("a1_shopping_l08", 3, "Ona potrzebuje jabłek.", "Ей нужны яблоки.", "Їй потрібні яблука.", "She needs apples."), + + ("a1_shopping_l09", 1, "Poproszę chleb.", "Дайте, пожалуйста, хлеб.", "Дайте, будь ласка, хліб.", "Bread, please."), + ("a1_shopping_l09", 2, "Czy mogę prosić o kilogram jabłek?", "Можно мне килограмм яблок, пожалуйста?", "Можна мені кілограм яблук, будь ласка?", "Could I have a kilogram of apples, please?"), + ("a1_shopping_l09", 3, "Poproszę litr mleka.", "Дайте, пожалуйста, литр молока.", "Дайте, будь ласка, літр молока.", "A liter of milk, please."), + + ("a1_shopping_l10", 1, "Idę do sklepu.", "Я иду в магазин.", "Я йду до магазину.", "I'm going to the shop."), + ("a1_shopping_l10", 2, "Kupuję chleb, mleko i ser.", "Я покупаю хлеб, молоко и сыр.", "Я купую хліб, молоко і сир.", "I'm buying bread, milk and cheese."), + ("a1_shopping_l10", 3, "Płacę w kasie.", "Я плачу на кассе.", "Я плачу на касі.", "I pay at the checkout."), + ] + + for ex in examples_t11: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t11 = [ + # L01 — shopping_vocabulary (difficulty 1) + ("a1_shopping_l01_q1", "a1_shopping_l01", "lesson_practice", "recognition", "shopping_vocabulary", 1, + "Jak po polsku „сумка”?", "Как по-польски «сумка»?", "Як польською «сумка»?", "How do you say “bag” in Polish?", + "A", None, None), + ("a1_shopping_l01_q2", "a1_shopping_l01", "lesson_practice", "production", "shopping_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (корзина)", "Вставьте пропущенное слово: To jest ___. (корзина)", "Вставте пропущене слово: To jest ___. (кошик)", "Fill in the missing word: To jest ___. (basket)", + "koszyk", "first_letter", "k"), + ("a1_shopping_l01_q3", "a1_shopping_l01", "lesson_practice", "application", "shopping_vocabulary", 1, + "Chcesz zapłacić za zakupy. Dokąd idziesz?", "Ты хочешь заплатить за покупки. Куда ты идёшь?", "Ти хочеш заплатити за покупки. Куди ти йдеш?", "You want to pay for your shopping. Where do you go?", + "A", None, None), + + # L02 — food_vocabulary (difficulty 1) + ("a1_shopping_l02_q1", "a1_shopping_l02", "lesson_practice", "recognition", "food_vocabulary", 1, + "Jak po polsku „молоко”?", "Как по-польски «молоко»?", "Як польською «молоко»?", "How do you say “milk” in Polish?", + "A", None, None), + ("a1_shopping_l02_q2", "a1_shopping_l02", "lesson_practice", "production", "food_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (яблоко)", "Вставьте пропущенное слово: To jest ___. (яблоко)", "Вставте пропущене слово: To jest ___. (яблуко)", "Fill in the missing word: To jest ___. (apple)", + "jabłko", "first_letter", "j"), + ("a1_shopping_l02_q3", "a1_shopping_l02", "lesson_practice", "application", "food_vocabulary", 1, + "Widzisz na półce żółty produkt zrobiony z mleka. Co to jest?", "Ты видишь на полке жёлтый продукт из молока. Что это?", "Ти бачиш на полиці жовтий продукт з молока. Що це?", "You see a yellow product made from milk on the shelf. What is it?", + "A", None, None), + + # L03 — verb_kupowac (difficulty 1) + ("a1_shopping_l03_q1", "a1_shopping_l03", "lesson_practice", "recognition", "verb_kupowac", 1, + "Wybierz poprawną formę: Ja ___. (kupować)", "Выберите правильную форму: Ja ___. (kupować)", "Виберіть правильну форму: Ja ___. (kupować)", "Choose the correct form: Ja ___. (kupować)", + "A", None, None), + ("a1_shopping_l03_q2", "a1_shopping_l03", "lesson_practice", "production", "verb_kupowac", 1, + "Wpisz brakujące słowo: Ty ___ ser. (покупаешь)", "Вставьте пропущенное слово: Ty ___ ser. (покупаешь)", "Вставте пропущене слово: Ty ___ ser. (купуєш)", "Fill in the missing word: Ty ___ ser. (you buy)", + "kupujesz", "first_letter", "k"), + ("a1_shopping_l03_q3", "a1_shopping_l03", "lesson_practice", "application", "verb_kupowac", 1, + "Jesteś w sklepie i bierzesz chleb do koszyka. Co robisz?", "Ты в магазине и берёшь хлеб в корзину. Что ты делаешь?", "Ти в магазині і береш хліб у кошик. Що ти робиш?", "You're at the shop putting bread in your basket. What are you doing?", + "A", None, None), + + # L04 — verb_chciec_kupic (difficulty 1) + ("a1_shopping_l04_q1", "a1_shopping_l04", "lesson_practice", "recognition", "verb_chciec_kupic", 1, + "Wybierz poprawną formę: Chcę kupić ___. (mleko)", "Выберите правильную форму: Chcę kupić ___. (mleko)", "Виберіть правильну форму: Chcę kupić ___. (mleko)", "Choose the correct form: Chcę kupić ___. (mleko)", + "A", None, None), + ("a1_shopping_l04_q2", "a1_shopping_l04", "lesson_practice", "production", "verb_chciec_kupic", 1, + "Wpisz brakujące słowo: Chcę kupić ___. (сыр)", "Вставьте пропущенное слово: Chcę kupić ___. (сыр)", "Вставте пропущене слово: Chcę kupić ___. (сир)", "Fill in the missing word: Chcę kupić ___. (cheese)", + "ser", "first_letter", "s"), + ("a1_shopping_l04_q3", "a1_shopping_l04", "lesson_practice", "application", "verb_chciec_kupic", 1, + "Jesteś w sklepie i chcesz kupić chleb. Co powiesz sprzedawcy?", "Ты в магазине и хочешь купить хлеб. Что ты скажешь продавцу?", "Ти в магазині і хочеш купити хліб. Що ти скажеш продавцю?", "You're at the shop and want to buy bread. What do you tell the seller?", + "A", None, None), + + # L05 — prices_ile_kosztuje (difficulty 2) + ("a1_shopping_l05_q1", "a1_shopping_l05", "lesson_practice", "recognition", "prices_ile_kosztuje", 2, + "Co znaczy „Ile to kosztuje?”", "Что означает «Ile to kosztuje?»", "Що означає «Ile to kosztuje?»", "What does “Ile to kosztuje?” mean?", + "A", None, None), + ("a1_shopping_l05_q2", "a1_shopping_l05", "lesson_practice", "production", "prices_ile_kosztuje", 2, + "Wpisz brakujące słowo: ___ kosztuje chleb? (сколько)", "Вставьте пропущенное слово: ___ kosztuje chleb? (сколько)", "Вставте пропущене слово: ___ kosztuje chleb? (скільки)", "Fill in the missing word: ___ kosztuje chleb? (how much)", + "Ile", "first_letter", "I"), + ("a1_shopping_l05_q3", "a1_shopping_l05", "lesson_practice", "application", "prices_ile_kosztuje", 2, + "Chcesz zapytać sprzedawcę o cenę mleka. Co powiesz?", "Ты хочешь спросить продавца о цене молока. Что ты скажешь?", "Ти хочеш запитати продавця про ціну молока. Що ти скажеш?", "You want to ask the seller the price of milk. What do you say?", + "A", None, None), + + # L06 — numbers_prices (difficulty 2) + ("a1_shopping_l06_q1", "a1_shopping_l06", "lesson_practice", "recognition", "numbers_prices", 2, + "Wybierz poprawną formę: To kosztuje pięć ___. (złoty)", "Выберите правильную форму: To kosztuje pięć ___. (złoty)", "Виберіть правильну форму: To kosztuje pięć ___. (złoty)", "Choose the correct form: To kosztuje pięć ___. (złoty)", + "A", None, None), + ("a1_shopping_l06_q2", "a1_shopping_l06", "lesson_practice", "production", "numbers_prices", 2, + "Wpisz brakujące słowo: To kosztuje dwa ___. (злотых, 2-4)", "Вставьте пропущенное слово: To kosztuje dwa ___. (злотых, 2-4)", "Вставте пропущене слово: To kosztuje dwa ___. (злотих, 2-4)", "Fill in the missing word: To kosztuje dwa ___. (zlotys, 2-4)", + "złote", "first_letter", "z"), + ("a1_shopping_l06_q3", "a1_shopping_l06", "lesson_practice", "application", "numbers_prices", 2, + "Chleb kosztuje trzy złote. Jak to powiesz?", "Хлеб стоит три злотых. Как ты это скажешь?", "Хліб коштує три злотих. Як ти це скажеш?", "The bread costs three zlotys. How do you say it?", + "A", None, None), + + # L07 — quantities_genitive (difficulty 2) + ("a1_shopping_l07_q1", "a1_shopping_l07", "lesson_practice", "recognition", "quantities_genitive", 2, + "Wybierz poprawną formę: kilogram ___. (jabłka)", "Выберите правильную форму: kilogram ___. (jabłka)", "Виберіть правильну форму: kilogram ___. (jabłka)", "Choose the correct form: kilogram ___. (jabłka)", + "A", None, None), + ("a1_shopping_l07_q2", "a1_shopping_l07", "lesson_practice", "production", "quantities_genitive", 2, + "Wpisz brakujące słowo: litr ___. (молока)", "Вставьте пропущенное слово: litr ___. (молока)", "Вставте пропущене слово: litr ___. (молока)", "Fill in the missing word: litr ___. (of milk)", + "mleka", "first_letter", "m"), + ("a1_shopping_l07_q3", "a1_shopping_l07", "lesson_practice", "application", "quantities_genitive", 2, + "Chcesz kupić duży kawałek sera. Co powiesz?", "Ты хочешь купить большой кусок сыра. Что ты скажешь?", "Ти хочеш купити великий шматок сиру. Що ти скажеш?", "You want to buy a big piece of cheese. What do you say?", + "A", None, None), + + # L08 — potrzebowac (difficulty 2) + ("a1_shopping_l08_q1", "a1_shopping_l08", "lesson_practice", "recognition", "potrzebowac", 2, + "Wybierz poprawną formę: Potrzebuję ___. (chleb)", "Выберите правильную форму: Potrzebuję ___. (chleb)", "Виберіть правильну форму: Potrzebuję ___. (chleb)", "Choose the correct form: Potrzebuję ___. (chleb)", + "A", None, None), + ("a1_shopping_l08_q2", "a1_shopping_l08", "lesson_practice", "production", "potrzebowac", 2, + "Wpisz brakujące słowo: Potrzebuję ___. (сыра)", "Вставьте пропущенное слово: Potrzebuję ___. (сыра)", "Вставте пропущене слово: Potrzebuję ___. (сиру)", "Fill in the missing word: Potrzebuję ___. (cheese)", + "sera", "first_letter", "s"), + ("a1_shopping_l08_q3", "a1_shopping_l08", "lesson_practice", "application", "potrzebowac", 2, + "W lodówce nie masz mleka. Co powiesz?", "У тебя в холодильнике нет молока. Что ты скажешь?", "У тебе в холодильнику немає молока. Що ти скажеш?", "You have no milk in the fridge. What do you say?", + "A", None, None), + + # L09 — asking_for_help_shop (difficulty 3) + ("a1_shopping_l09_q1", "a1_shopping_l09", "lesson_practice", "recognition", "asking_for_help_shop", 3, + "Co znaczy „Czy mogę prosić o kilogram jabłek?”", "Что означает «Czy mogę prosić o kilogram jabłek?»", "Що означає «Czy mogę prosić o kilogram jabłek?»", "What does “Czy mogę prosić o kilogram jabłek?” mean?", + "A", None, None), + ("a1_shopping_l09_q2", "a1_shopping_l09", "lesson_practice", "production", "asking_for_help_shop", 3, + "Wpisz brakujące słowo: ___ chleb. (дайте, пожалуйста)", "Вставьте пропущенное слово: ___ chleb. (дайте, пожалуйста)", "Вставте пропущене слово: ___ chleb. (дайте, будь ласка)", "Fill in the missing word: ___ chleb. (please, may I have)", + "Poproszę", "first_letter", "P"), + ("a1_shopping_l09_q3", "a1_shopping_l09", "lesson_practice", "application", "asking_for_help_shop", 3, + "Jesteś w sklepie i grzecznie prosisz o ser. Co powiesz?", "Ты в магазине и вежливо просишь сыр. Что ты скажешь?", "Ти в магазині і ввічливо просиш сир. Що ти скажеш?", "You're at the shop and politely ask for cheese. What do you say?", + "A", None, None), + + # L10 — shopping_description (difficulty 3) + ("a1_shopping_l10_q1", "a1_shopping_l10", "lesson_practice", "recognition", "shopping_description", 3, + "Które zdanie poprawnie opisuje zakupy?", "Какое предложение правильно описывает покупки?", "Яке речення правильно описує покупки?", "Which sentence correctly describes shopping?", + "A", None, None), + ("a1_shopping_l10_q2", "a1_shopping_l10", "lesson_practice", "production", "shopping_description", 3, + "Przetłumacz: «Я плачу на кассе».", "Переведите: «Я плачу на кассе».", "Перекладіть: «Я плачу на касі».", "Translate: “I pay at the checkout.”", + "Płacę w kasie", "first_letter", "P"), + ("a1_shopping_l10_q3", "a1_shopping_l10", "lesson_practice", "application", "shopping_description", 3, + "Chcesz opisać koledze swoje zakupy: idziesz do sklepu, kupujesz chleb i mleko, płacisz w kasie. Jak zaczniesz zdanie?", "Ты хочешь описать другу свои покупки: идёшь в магазин, покупаешь хлеб и молоко, платишь на кассе. Как ты начнёшь предложение?", "Ти хочеш описати другу свої покупки: йдеш до магазину, купуєш хліб і молоко, платиш на касі. Як ти почнеш речення?", "You want to describe your shopping trip to a friend: you go to the shop, buy bread and milk, pay at the checkout. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t11: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_shopping', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t11 = [ + # L01 + ("a1_shopping_l01_q1", "A", "torba", "сумка", "сумка", "bag", True, None), + ("a1_shopping_l01_q1", "B", "koszyk", "корзина", "кошик", "basket", False, "wrong_word"), + ("a1_shopping_l01_q1", "C", "kasa", "касса", "каса", "checkout", False, "wrong_word"), + ("a1_shopping_l01_q1", "D", "sklep", "магазин", "магазин", "shop", False, "wrong_word"), + + ("a1_shopping_l01_q3", "A", "kasa", "касса", "каса", "checkout", True, None), + ("a1_shopping_l01_q3", "B", "koszyk", "корзина", "кошик", "basket", False, "wrong_context"), + ("a1_shopping_l01_q3", "C", "torba", "сумка", "сумка", "bag", False, "wrong_context"), + ("a1_shopping_l01_q3", "D", "sklep", "магазин", "магазин", "shop", False, "wrong_context"), + + # L02 + ("a1_shopping_l02_q1", "A", "mleko", "молоко", "молоко", "milk", True, None), + ("a1_shopping_l02_q1", "B", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a1_shopping_l02_q1", "C", "ser", "сыр", "сир", "cheese", False, "wrong_word"), + ("a1_shopping_l02_q1", "D", "jabłko", "яблоко", "яблуко", "apple", False, "wrong_word"), + + ("a1_shopping_l02_q3", "A", "ser", "сыр", "сир", "cheese", True, None), + ("a1_shopping_l02_q3", "B", "chleb", "хлеб", "хліб", "bread", False, "wrong_context"), + ("a1_shopping_l02_q3", "C", "mleko", "молоко", "молоко", "milk", False, "wrong_context"), + ("a1_shopping_l02_q3", "D", "jabłko", "яблоко", "яблуко", "apple", False, "wrong_context"), + + # L03 + ("a1_shopping_l03_q1", "A", "kupuję", "покупаю", "купую", "buy (I)", True, None), + ("a1_shopping_l03_q1", "B", "kupujesz", "покупаешь", "купуєш", "buy (you)", False, "wrong_word"), + ("a1_shopping_l03_q1", "C", "kupuje", "покупает", "купує", "buys", False, "wrong_word"), + ("a1_shopping_l03_q1", "D", "kupować", "покупать", "купувати", "to buy", False, "wrong_word"), + + ("a1_shopping_l03_q3", "A", "Kupuję chleb.", "Я покупаю хлеб.", "Я купую хліб.", "I'm buying bread.", True, None), + ("a1_shopping_l03_q3", "B", "Sprzedaję chleb.", "Я продаю хлеб.", "Я продаю хліб.", "I'm selling bread.", False, "wrong_context"), + ("a1_shopping_l03_q3", "C", "Mam chleb.", "У меня есть хлеб.", "У мене є хліб.", "I have bread.", False, "wrong_context"), + ("a1_shopping_l03_q3", "D", "Szukam chleba.", "Я ищу хлеб.", "Я шукаю хліб.", "I'm looking for bread.", False, "wrong_context"), + + # L04 + ("a1_shopping_l04_q1", "A", "mleko", "молоко (вин.)", "молоко (знах.)", "milk (acc.)", True, None), + ("a1_shopping_l04_q1", "B", "mleka", "молока (род.)", "молока (род.)", "milk (gen.)", False, "wrong_case"), + ("a1_shopping_l04_q1", "C", "mlekiem", "молоком (тв.)", "молоком (ор.)", "milk (instr.)", False, "wrong_case"), + ("a1_shopping_l04_q1", "D", "mleku", "молоке (местн.)", "молоці (місц.)", "milk (loc.)", False, "wrong_case"), + + ("a1_shopping_l04_q3", "A", "Chcę kupić chleb.", "Я хочу купить хлеб.", "Я хочу купити хліб.", "I want to buy bread.", True, None), + ("a1_shopping_l04_q3", "B", "Kupuję chleb wczoraj.", "Неправильное время.", "Неправильний час.", "Wrong tense.", False, "wrong_sentence_type"), + ("a1_shopping_l04_q3", "C", "Sprzedaję chleb.", "Я продаю хлеб.", "Я продаю хліб.", "I'm selling bread.", False, "wrong_context"), + ("a1_shopping_l04_q3", "D", "Mam chleb.", "У меня есть хлеб.", "У мене є хліб.", "I have bread.", False, "wrong_context"), + + # L05 + ("a1_shopping_l05_q1", "A", "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does this cost?", True, None), + ("a1_shopping_l05_q1", "B", "Co to jest?", "Что это?", "Що це?", "What is this?", False, "wrong_translation"), + ("a1_shopping_l05_q1", "C", "Gdzie to jest?", "Где это?", "Де це?", "Where is this?", False, "wrong_translation"), + ("a1_shopping_l05_q1", "D", "Kiedy to jest?", "Когда это?", "Коли це?", "When is this?", False, "wrong_translation"), + + ("a1_shopping_l05_q3", "A", "Ile kosztuje mleko?", "Сколько стоит молоко?", "Скільки коштує молоко?", "How much does the milk cost?", True, None), + ("a1_shopping_l05_q3", "B", "Co to jest mleko?", "Что это молоко? (неверная конструкция)", "Що це молоко? (невірна конструкція)", "What is this milk? (wrong construction)", False, "wrong_sentence_type"), + ("a1_shopping_l05_q3", "C", "Gdzie jest mleko?", "Где молоко? (неверный вопрос)", "Де молоко? (невірне питання)", "Where is the milk? (wrong question)", False, "wrong_context"), + ("a1_shopping_l05_q3", "D", "Chcę mleko.", "Я хочу молоко. (не о цене)", "Я хочу молоко. (не про ціну)", "I want milk. (not about price)", False, "wrong_context"), + + # L06 + ("a1_shopping_l06_q1", "A", "złotych", "злотых (5+)", "злотих (5+)", "zlotys (5+)", True, None), + ("a1_shopping_l06_q1", "B", "złote", "злотых (2-4)", "злотих (2-4)", "zlotys (2-4)", False, "wrong_number"), + ("a1_shopping_l06_q1", "C", "złoty", "злотый (1)", "злотий (1)", "zloty (1)", False, "wrong_number"), + ("a1_shopping_l06_q1", "D", "złotego", "неправильная форма", "неправильна форма", "wrong form", False, "wrong_case"), + + ("a1_shopping_l06_q3", "A", "Chleb kosztuje trzy złote.", "Хлеб стоит три злотых.", "Хліб коштує три злотих.", "The bread costs three zlotys.", True, None), + ("a1_shopping_l06_q3", "B", "Chleb kosztuje trzy złoty.", "Неправильная форма числа.", "Неправильна форма числа.", "Wrong numeral form.", False, "wrong_number"), + ("a1_shopping_l06_q3", "C", "Chleb kosztuje trzy złotych.", "Неправильная форма числа.", "Неправильна форма числа.", "Wrong numeral form.", False, "wrong_number"), + ("a1_shopping_l06_q3", "D", "Chleb jest za darmo.", "Хлеб бесплатный. (противоречит ситуации)", "Хліб безкоштовний. (суперечить ситуації)", "The bread is free. (contradicts the situation)", False, "wrong_context"), + + # L07 + ("a1_shopping_l07_q1", "A", "jabłek", "яблок (род. мн.)", "яблук (род. мн.)", "apples (gen. pl.)", True, None), + ("a1_shopping_l07_q1", "B", "jabłka", "яблоки (им. мн.)", "яблука (наз. мн.)", "apples (nom. pl.)", False, "wrong_case"), + ("a1_shopping_l07_q1", "C", "jabłkiem", "яблоком (тв.)", "яблуком (ор.)", "apple (instr.)", False, "wrong_case"), + ("a1_shopping_l07_q1", "D", "jabłku", "яблоке (местн.)", "яблуці (місц.)", "apple (loc.)", False, "wrong_case"), + + ("a1_shopping_l07_q3", "A", "Poproszę kawałek sera.", "Дайте, пожалуйста, кусок сыра.", "Дайте, будь ласка, шматок сиру.", "A piece of cheese, please.", True, None), + ("a1_shopping_l07_q3", "B", "Poproszę kawałek chleba.", "Дайте, пожалуйста, кусок хлеба. (неверный продукт)", "Дайте, будь ласка, шматок хліба. (невірний продукт)", "A piece of bread, please. (wrong product)", False, "wrong_context"), + ("a1_shopping_l07_q3", "C", "Mam kawałek sera.", "У меня есть кусок сыра.", "У мене є шматок сиру.", "I have a piece of cheese.", False, "wrong_context"), + ("a1_shopping_l07_q3", "D", "Sprzedaję kawałek sera.", "Я продаю кусок сыра.", "Я продаю шматок сиру.", "I'm selling a piece of cheese.", False, "wrong_context"), + + # L08 + ("a1_shopping_l08_q1", "A", "chleba", "хлеба (род.)", "хліба (род.)", "bread (gen.)", True, None), + ("a1_shopping_l08_q1", "B", "chleb", "хлеб (им.)", "хліб (наз.)", "bread (nom.)", False, "wrong_case"), + ("a1_shopping_l08_q1", "C", "chlebem", "хлебом (тв.)", "хлібом (ор.)", "bread (instr.)", False, "wrong_case"), + ("a1_shopping_l08_q1", "D", "chlebowi", "хлебу (дат.)", "хлібу (дав.)", "bread (dat.)", False, "wrong_case"), + + ("a1_shopping_l08_q3", "A", "Potrzebuję mleka.", "Мне нужно молоко.", "Мені потрібне молоко.", "I need milk.", True, None), + ("a1_shopping_l08_q3", "B", "Mam mleko.", "У меня есть молоко. (противоречит ситуации)", "У мене є молоко. (суперечить ситуації)", "I have milk. (contradicts the situation)", False, "wrong_context"), + ("a1_shopping_l08_q3", "C", "Kupuję mleko wczoraj.", "Неправильное время.", "Неправильний час.", "Wrong tense.", False, "wrong_sentence_type"), + ("a1_shopping_l08_q3", "D", "Sprzedaję mleko.", "Я продаю молоко.", "Я продаю молоко.", "I'm selling milk.", False, "wrong_context"), + + # L09 + ("a1_shopping_l09_q1", "A", "Czy mogę prosić o kilogram jabłek?", "Можно мне килограмм яблок, пожалуйста?", "Можна мені кілограм яблук, будь ласка?", "Could I have a kilogram of apples, please?", True, None), + ("a1_shopping_l09_q1", "B", "Ile kosztuje kilogram jabłek?", "Сколько стоит килограмм яблок?", "Скільки коштує кілограм яблук?", "How much does a kilogram of apples cost?", False, "wrong_translation"), + ("a1_shopping_l09_q1", "C", "Gdzie są jabłka?", "Где яблоки?", "Де яблука?", "Where are the apples?", False, "wrong_translation"), + ("a1_shopping_l09_q1", "D", "Nie lubię jabłek.", "Я не люблю яблоки.", "Я не люблю яблука.", "I don't like apples.", False, "wrong_translation"), + + ("a1_shopping_l09_q3", "A", "Poproszę ser.", "Дайте, пожалуйста, сыр.", "Дайте, будь ласка, сир.", "Cheese, please.", True, None), + ("a1_shopping_l09_q3", "B", "Daj ser!", "Дай сыр! (грубо)", "Дай сир! (грубо)", "Give me cheese! (rude)", False, "wrong_sentence_type"), + ("a1_shopping_l09_q3", "C", "Chcę ser teraz!", "Я хочу сыр сейчас! (грубо)", "Я хочу сир зараз! (грубо)", "I want cheese now! (rude)", False, "wrong_sentence_type"), + ("a1_shopping_l09_q3", "D", "Ser jest mój.", "Сыр мой.", "Сир мій.", "The cheese is mine.", False, "wrong_context"), + + # L10 + ("a1_shopping_l10_q1", "A", "Idę do sklepu i kupuję chleb.", "Я иду в магазин и покупаю хлеб.", "Я йду до магазину і купую хліб.", "I'm going to the shop and buying bread.", True, None), + ("a1_shopping_l10_q1", "B", "Idę do sklep i kupuję chleb.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_shopping_l10_q1", "C", "Jestem sklep kupuję chleb.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_shopping_l10_q1", "D", "Idę do szkoły i kupuję chleb.", "Неверное место. (не соответствует контексту покупок)", "Невірне місце. (не відповідає контексту покупок)", "Wrong place. (doesn't match the shopping context)", False, "wrong_context"), + + ("a1_shopping_l10_q3", "A", "Idę do sklepu i kupuję chleb i mleko.", "Я иду в магазин и покупаю хлеб и молоко.", "Я йду до магазину і купую хліб і молоко.", "I'm going to the shop and buying bread and milk.", True, None), + ("a1_shopping_l10_q3", "B", "Jestem sklep i mam chleb.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_shopping_l10_q3", "C", "Sklep idę kupuję.", "Неправильный порядок слов и падеж.", "Неправильний порядок слів і відмінок.", "Wrong word order and case.", False, "wrong_sentence_type"), + ("a1_shopping_l10_q3", "D", "Chcę kupić sklep.", "Я хочу купить магазин. (неверный смысл)", "Я хочу купити магазин. (невірний сенс)", "I want to buy the shop. (wrong meaning)", False, "wrong_context"), + ] + + for opt in options_t11: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t11 = [ + ("a1_shopping_t01", None, "topic_test", "recognition", "shopping_vocabulary", 1, + "Jak po polsku „сумка”?", "Как по-польски «сумка»?", "Як польською «сумка»?", "How do you say “bag” in Polish?", + "A", None, None, 1), + ("a1_shopping_t02", None, "topic_test", "recognition", "food_vocabulary", 1, + "Jak po polsku „молоко”?", "Как по-польски «молоко»?", "Як польською «молоко»?", "How do you say “milk” in Polish?", + "A", None, None, 2), + ("a1_shopping_t03", None, "topic_test", "recognition", "verb_kupowac", 1, + "Wybierz poprawną formę: Ona ___. (kupować)", "Выберите правильную форму: Ona ___. (kupować)", "Виберіть правильну форму: Ona ___. (kupować)", "Choose the correct form: Ona ___. (kupować)", + "A", None, None, 3), + ("a1_shopping_t04", None, "topic_test", "recognition", "verb_chciec_kupic", 2, + "Wybierz poprawną formę: Chcę kupić ___. (ser)", "Выберите правильную форму: Chcę kupić ___. (ser)", "Виберіть правильну форму: Chcę kupić ___. (ser)", "Choose the correct form: Chcę kupić ___. (ser)", + "A", None, None, 4), + ("a1_shopping_t05", None, "topic_test", "recognition", "prices_ile_kosztuje", 2, + "Co znaczy „Ile to kosztuje?”", "Что означает «Ile to kosztuje?»", "Що означає «Ile to kosztuje?»", "What does “Ile to kosztuje?” mean?", + "A", None, None, 5), + ("a1_shopping_t06", None, "topic_test", "recognition", "asking_for_help_shop", 3, + "Co znaczy „Czy mogę prosić o kilogram jabłek?”", "Что означает «Czy mogę prosić o kilogram jabłek?»", "Що означає «Czy mogę prosić o kilogram jabłek?»", "What does “Czy mogę prosić o kilogram jabłek?” mean?", + "A", None, None, 6), + + ("a1_shopping_t07", None, "topic_test", "application", "shopping_vocabulary", 1, + "Chcesz zapłacić za zakupy. Dokąd idziesz?", "Ты хочешь заплатить за покупки. Куда ты идёшь?", "Ти хочеш заплатити за покупки. Куди ти йдеш?", "You want to pay for your shopping. Where do you go?", + "A", None, None, 7), + ("a1_shopping_t08", None, "topic_test", "application", "food_vocabulary", 1, + "Widzisz na półce żółty produkt zrobiony z mleka. Co to jest?", "Ты видишь на полке жёлтый продукт из молока. Что это?", "Ти бачиш на полиці жовтий продукт з молока. Що це?", "You see a yellow product made from milk on the shelf. What is it?", + "A", None, None, 8), + ("a1_shopping_t09", None, "topic_test", "application", "numbers_prices", 2, + "Chleb kosztuje trzy złote. Jak to powiesz?", "Хлеб стоит три злотых. Как ты это скажешь?", "Хліб коштує три злотих. Як ти це скажеш?", "The bread costs three zlotys. How do you say it?", + "A", None, None, 9), + ("a1_shopping_t10", None, "topic_test", "application", "quantities_genitive", 2, + "Chcesz kupić duży kawałek sera. Co powiesz?", "Ты хочешь купить большой кусок сыра. Что ты скажешь?", "Ти хочеш купити великий шматок сиру. Що ти скажеш?", "You want to buy a big piece of cheese. What do you say?", + "A", None, None, 10), + ("a1_shopping_t11", None, "topic_test", "application", "potrzebowac", 3, + "W lodówce nie masz mleka. Co powiesz?", "У тебя в холодильнике нет молока. Что ты скажешь?", "У тебе в холодильнику немає молока. Що ти скажеш?", "You have no milk in the fridge. What do you say?", + "A", None, None, 11), + ("a1_shopping_t12", None, "topic_test", "application", "asking_for_help_shop", 3, + "Jesteś w sklepie i grzecznie prosisz o ser. Co powiesz?", "Ты в магазине и вежливо просишь сыр. Что ты скажешь?", "Ти в магазині і ввічливо просиш сир. Що ти скажеш?", "You're at the shop and politely ask for cheese. What do you say?", + "A", None, None, 12), + + ("a1_shopping_t13", None, "topic_test", "production", "shopping_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (корзина)", "Вставьте пропущенное слово: To jest ___. (корзина)", "Вставте пропущене слово: To jest ___. (кошик)", "Fill in the missing word: To jest ___. (basket)", + "koszyk", "first_letter", "k", 13), + ("a1_shopping_t14", None, "topic_test", "production", "food_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (яблоко)", "Вставьте пропущенное слово: To jest ___. (яблоко)", "Вставте пропущене слово: To jest ___. (яблуко)", "Fill in the missing word: To jest ___. (apple)", + "jabłko", "first_letter", "j", 14), + ("a1_shopping_t15", None, "topic_test", "production", "numbers_prices", 2, + "Wpisz brakujące słowo: To kosztuje dwa ___. (злотых, 2-4)", "Вставьте пропущенное слово: To kosztuje dwa ___. (злотых, 2-4)", "Вставте пропущене слово: To kosztuje dwa ___. (злотих, 2-4)", "Fill in the missing word: To kosztuje dwa ___. (zlotys, 2-4)", + "złote", "first_letter", "z", 15), + ("a1_shopping_t16", None, "topic_test", "production", "quantities_genitive", 2, + "Wpisz brakujące słowo: litr ___. (молока)", "Вставьте пропущенное слово: litr ___. (молока)", "Вставте пропущене слово: litr ___. (молока)", "Fill in the missing word: litr ___. (of milk)", + "mleka", "first_letter", "m", 16), + ("a1_shopping_t17", None, "topic_test", "production", "asking_for_help_shop", 3, + "Wpisz brakujące słowo: ___ chleb. (дайте, пожалуйста)", "Вставьте пропущенное слово: ___ chleb. (дайте, пожалуйста)", "Вставте пропущене слово: ___ chleb. (дайте, будь ласка)", "Fill in the missing word: ___ chleb. (please, may I have)", + "Poproszę", "first_letter", "P", 17), + ("a1_shopping_t18", None, "topic_test", "production", "shopping_description", 2, + "Przetłumacz: «Я плачу на кассе».", "Переведите: «Я плачу на кассе».", "Перекладіть: «Я плачу на касі».", "Translate: “I pay at the checkout.”", + "Płacę w kasie", "first_letter", "P", 18), + + ("a1_shopping_t19", None, "topic_test", "mixed", "shopping_description", 3, + "Wybierz poprawne tłumaczenie: «Я иду в магазин и покупаю хлеб, молоко и сыр».", "Выберите правильный перевод: «Я иду в магазин и покупаю хлеб, молоко и сыр».", "Виберіть правильний переклад: «Я йду до магазину і купую хліб, молоко і сир».", "Choose the correct translation: “I'm going to the shop and buying bread, milk and cheese.”", + "A", None, None, 19), + ("a1_shopping_t20", None, "topic_test", "mixed", "prices_ile_kosztuje", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Сколько стоит хлеб? — Хлеб стоит два злотых.»", "Выберите правильный перевод диалога: «— Сколько стоит хлеб? — Хлеб стоит два злотых.»", "Виберіть правильний переклад діалогу: «— Скільки коштує хліб? — Хліб коштує два злотих.»", "Choose the correct translation of the dialogue: “— How much does the bread cost? — The bread costs two zlotys.”", + "A", None, None, 20), + ] + + for q in test_questions_t11: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_shopping', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t11 = [ + ("a1_shopping_t01", "A", "torba", "сумка", "сумка", "bag", True, None), + ("a1_shopping_t01", "B", "koszyk", "корзина", "кошик", "basket", False, "wrong_word"), + ("a1_shopping_t01", "C", "kasa", "касса", "каса", "checkout", False, "wrong_word"), + ("a1_shopping_t01", "D", "sklep", "магазин", "магазин", "shop", False, "wrong_word"), + + ("a1_shopping_t02", "A", "mleko", "молоко", "молоко", "milk", True, None), + ("a1_shopping_t02", "B", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a1_shopping_t02", "C", "ser", "сыр", "сир", "cheese", False, "wrong_word"), + ("a1_shopping_t02", "D", "jabłko", "яблоко", "яблуко", "apple", False, "wrong_word"), + + ("a1_shopping_t03", "A", "kupuje", "покупает", "купує", "buys", True, None), + ("a1_shopping_t03", "B", "kupuję", "покупаю", "купую", "buy (I)", False, "wrong_word"), + ("a1_shopping_t03", "C", "kupujesz", "покупаешь", "купуєш", "buy (you)", False, "wrong_word"), + ("a1_shopping_t03", "D", "kupować", "покупать", "купувати", "to buy", False, "wrong_word"), + + ("a1_shopping_t04", "A", "ser", "сыр (вин.)", "сир (знах.)", "cheese (acc.)", True, None), + ("a1_shopping_t04", "B", "sera", "сыра (род.)", "сиру (род.)", "cheese (gen.)", False, "wrong_case"), + ("a1_shopping_t04", "C", "serem", "сыром (тв.)", "сиром (ор.)", "cheese (instr.)", False, "wrong_case"), + ("a1_shopping_t04", "D", "serowi", "сыру (дат.)", "сиру (дав.)", "cheese (dat.)", False, "wrong_case"), + + ("a1_shopping_t05", "A", "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does this cost?", True, None), + ("a1_shopping_t05", "B", "Co to jest?", "Что это?", "Що це?", "What is this?", False, "wrong_translation"), + ("a1_shopping_t05", "C", "Gdzie to jest?", "Где это?", "Де це?", "Where is this?", False, "wrong_translation"), + ("a1_shopping_t05", "D", "Kiedy to jest?", "Когда это?", "Коли це?", "When is this?", False, "wrong_translation"), + + ("a1_shopping_t06", "A", "Czy mogę prosić o kilogram jabłek?", "Можно мне килограмм яблок, пожалуйста?", "Можна мені кілограм яблук, будь ласка?", "Could I have a kilogram of apples, please?", True, None), + ("a1_shopping_t06", "B", "Ile kosztuje kilogram jabłek?", "Сколько стоит килограмм яблок?", "Скільки коштує кілограм яблук?", "How much does a kilogram of apples cost?", False, "wrong_translation"), + ("a1_shopping_t06", "C", "Gdzie są jabłka?", "Где яблоки?", "Де яблука?", "Where are the apples?", False, "wrong_translation"), + ("a1_shopping_t06", "D", "Nie lubię jabłek.", "Я не люблю яблоки.", "Я не люблю яблука.", "I don't like apples.", False, "wrong_translation"), + + ("a1_shopping_t07", "A", "kasa", "касса", "каса", "checkout", True, None), + ("a1_shopping_t07", "B", "koszyk", "корзина", "кошик", "basket", False, "wrong_context"), + ("a1_shopping_t07", "C", "torba", "сумка", "сумка", "bag", False, "wrong_context"), + ("a1_shopping_t07", "D", "sklep", "магазин", "магазин", "shop", False, "wrong_context"), + + ("a1_shopping_t08", "A", "ser", "сыр", "сир", "cheese", True, None), + ("a1_shopping_t08", "B", "chleb", "хлеб", "хліб", "bread", False, "wrong_context"), + ("a1_shopping_t08", "C", "mleko", "молоко", "молоко", "milk", False, "wrong_context"), + ("a1_shopping_t08", "D", "jabłko", "яблоко", "яблуко", "apple", False, "wrong_context"), + + ("a1_shopping_t09", "A", "Chleb kosztuje trzy złote.", "Хлеб стоит три злотых.", "Хліб коштує три злотих.", "The bread costs three zlotys.", True, None), + ("a1_shopping_t09", "B", "Chleb kosztuje trzy złoty.", "Неправильная форма числа.", "Неправильна форма числа.", "Wrong numeral form.", False, "wrong_number"), + ("a1_shopping_t09", "C", "Chleb kosztuje trzy złotych.", "Неправильная форма числа.", "Неправильна форма числа.", "Wrong numeral form.", False, "wrong_number"), + ("a1_shopping_t09", "D", "Chleb jest za darmo.", "Хлеб бесплатный.", "Хліб безкоштовний.", "The bread is free.", False, "wrong_context"), + + ("a1_shopping_t10", "A", "Poproszę kawałek sera.", "Дайте, пожалуйста, кусок сыра.", "Дайте, будь ласка, шматок сиру.", "A piece of cheese, please.", True, None), + ("a1_shopping_t10", "B", "Poproszę kawałek chleba.", "Дайте, пожалуйста, кусок хлеба. (неверный продукт)", "Дайте, будь ласка, шматок хліба. (невірний продукт)", "A piece of bread, please. (wrong product)", False, "wrong_context"), + ("a1_shopping_t10", "C", "Mam kawałek sera.", "У меня есть кусок сыра.", "У мене є шматок сиру.", "I have a piece of cheese.", False, "wrong_context"), + ("a1_shopping_t10", "D", "Sprzedaję kawałek sera.", "Я продаю кусок сыра.", "Я продаю шматок сиру.", "I'm selling a piece of cheese.", False, "wrong_context"), + + ("a1_shopping_t11", "A", "Potrzebuję mleka.", "Мне нужно молоко.", "Мені потрібне молоко.", "I need milk.", True, None), + ("a1_shopping_t11", "B", "Mam mleko.", "У меня есть молоко. (противоречит ситуации)", "У мене є молоко. (суперечить ситуації)", "I have milk. (contradicts the situation)", False, "wrong_context"), + ("a1_shopping_t11", "C", "Kupuję mleko wczoraj.", "Неправильное время.", "Неправильний час.", "Wrong tense.", False, "wrong_sentence_type"), + ("a1_shopping_t11", "D", "Sprzedaję mleko.", "Я продаю молоко.", "Я продаю молоко.", "I'm selling milk.", False, "wrong_context"), + + ("a1_shopping_t12", "A", "Poproszę ser.", "Дайте, пожалуйста, сыр.", "Дайте, будь ласка, сир.", "Cheese, please.", True, None), + ("a1_shopping_t12", "B", "Daj ser!", "Дай сыр! (грубо)", "Дай сир! (грубо)", "Give me cheese! (rude)", False, "wrong_sentence_type"), + ("a1_shopping_t12", "C", "Chcę ser teraz!", "Я хочу сыр сейчас! (грубо)", "Я хочу сир зараз! (грубо)", "I want cheese now! (rude)", False, "wrong_sentence_type"), + ("a1_shopping_t12", "D", "Ser jest mój.", "Сыр мой.", "Сир мій.", "The cheese is mine.", False, "wrong_context"), + + ("a1_shopping_t19", "A", "Idę do sklepu i kupuję chleb, mleko i ser.", "Я иду в магазин и покупаю хлеб, молоко и сыр.", "Я йду до магазину і купую хліб, молоко і сир.", "I'm going to the shop and buying bread, milk and cheese.", True, None), + ("a1_shopping_t19", "B", "Byłem w sklepie i kupiłem chleb, mleko i ser.", "Неправильное время (прошедшее вместо настоящего).", "Неправильний час (минулий замість теперішнього).", "Wrong tense (past instead of present).", False, "wrong_sentence_type"), + ("a1_shopping_t19", "C", "Idę do szkoły i kupuję chleb, mleko i ser.", "Неправильное слово.", "Неправильне слово.", "Wrong word.", False, "wrong_word"), + ("a1_shopping_t19", "D", "Sklep idę kupuję chleb mleko ser.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + ("a1_shopping_t20", "A", "Ile kosztuje chleb? Chleb kosztuje dwa złote.", "Сколько стоит хлеб? Хлеб стоит два злотых.", "Скільки коштує хліб? Хліб коштує два злотих.", "How much does the bread cost? The bread costs two zlotys.", True, None), + ("a1_shopping_t20", "B", "Co to jest chleb? Chleb kosztuje dwa złote.", "Неправильный вопрос.", "Неправильне питання.", "Wrong question.", False, "wrong_translation"), + ("a1_shopping_t20", "C", "Ile kosztuje mleko? Chleb kosztuje dwa złote.", "Продукты в вопросе и ответе не совпадают.", "Продукти в питанні й відповіді не збігаються.", "Products in question and answer don't match.", False, "wrong_word"), + ("a1_shopping_t20", "D", "Ile kosztuje chleb? Chleb kosztuje dwa złotych.", "Неправильная форма числа (для 2-4 нужно „złote”).", "Неправильна форма числа (для 2-4 потрібно „złote”).", "Wrong numeral form (2-4 needs „złote”).", False, "wrong_number"), + ] + + for opt in test_options_t11: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 12: ХОББИ И СВОБОДНОЕ ВРЕМЯ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_hobbies_free_time', 'A1', 12, + 'Hobby i czas wolny', + 'Хобби и свободное время', + 'Хобі та вільний час', + 'Hobbies and Free Time') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t12 = [ + ("a1_hobbies_free_time_l01", 1, "free_time_activities_verbs", "Czasowniki: hobby", "Глаголы: хобби", "Дієслова: хобі", "Verbs: hobbies", + "Podstawowe czasowniki opisujące hobby: czytać, gotować, tańczyć, pływać. To bezokoliczniki — podstawowe formy czasowników.", + "Основные глаголы, описывающие хобби: czytać (читать), gotować (готовить), tańczyć (танцевать), pływać (плавать). Это инфинитивы — словарные формы глаголов.", + "Основні дієслова, що описують хобі: czytać (читати), gotować (готувати), tańczyć (танцювати), pływać (плавати). Це інфінітиви — словникові форми дієслів.", + "Basic verbs describing hobbies: czytać (to read), gotować (to cook), tańczyć (to dance), pływać (to swim). These are infinitives — the dictionary forms of verbs."), + + ("a1_hobbies_free_time_l02", 2, "lubic_bezokolicznik", "Lubię + bezokolicznik", "Lubię + инфинитив", "Lubię + інфінітив", "Lubię + infinitive", + "Czasownik „lubić” + bezokolicznik wyraża zamiłowanie do czynności: lubię czytać, lubisz gotować, lubi tańczyć.", + "Глагол „lubić” (любить) + инфинитив выражает любовь к действию: lubię czytać (я люблю читать), lubisz gotować (ты любишь готовить), lubi tańczyć (он/она любит танцевать).", + "Дієслово „lubić” (любити) + інфінітив виражає любов до дії: lubię czytać (я люблю читати), lubisz gotować (ти любиш готувати), lubi tańczyć (він/вона любить танцювати).", + "The verb „lubić” (to like) + infinitive expresses fondness for an activity: lubię czytać (I like reading), lubisz gotować (you like cooking), lubi tańczyć (he/she likes dancing)."), + + ("a1_hobbies_free_time_l03", 3, "hobby_nouns", "Hobby jako rzeczownik", "Хобби как существительное", "Хобі як іменник", "Hobbies as nouns", + "Hobby możemy też nazwać rzeczownikiem: sport, muzyka, taniec. Po „lubić” używamy biernika: lubię sport, lubię muzykę, lubię taniec.", + "Хобби можно также назвать существительным: sport (спорт), muzyka (музыка), taniec (танцы). После „lubić” используем винительный падеж: lubię sport, lubię muzykę, lubię taniec.", + "Хобі можна також назвати іменником: sport (спорт), muzyka (музика), taniec (танці). Після „lubić” використовуємо знахідний відмінок: lubię sport, lubię muzykę, lubię taniec.", + "A hobby can also be named with a noun: sport, muzyka (music), taniec (dance). After „lubić” we use the accusative: lubię sport, lubię muzykę, lubię taniec."), + + ("a1_hobbies_free_time_l04", 4, "czas_wolny_vocabulary", "Słowa: czas wolny", "Слова: свободное время", "Слова: вільний час", "Words: free time", + "Słowa związane z czasem wolnym: czas wolny, weekend, wieczór, sobota. „Sobota” jest rodzaju żeńskiego, pozostałe są rodzaju męskiego.", + "Слова, связанные со свободным временем: czas wolny (свободное время), weekend (выходные), wieczór (вечер), sobota (суббота). „Sobota” женского рода, остальные мужского рода.", + "Слова, пов'язані з вільним часом: czas wolny (вільний час), weekend (вихідні), wieczór (вечір), sobota (субота). „Sobota” жіночого роду, решта чоловічого роду.", + "Words related to free time: czas wolny (free time), weekend, wieczór (evening), sobota (Saturday). „Sobota” is feminine, the rest are masculine."), + + ("a1_hobbies_free_time_l05", 5, "jak_czesto_hobby", "Jak często? — przysłówki", "Как часто? — наречия", "Як часто? — прислівники", "How often? — adverbs", + "Częstotliwość hobby opisujemy przysłówkami: często, czasami, rzadko, codziennie, w weekendy, nigdy.", + "Частоту хобби описываем наречиями: często (часто), czasami (иногда), rzadko (редко), codziennie (каждый день), w weekendy (по выходным), nigdy (никогда).", + "Частоту хобі описуємо прислівниками: często (часто), czasami (іноді), rzadko (рідко), codziennie (щодня), w weekendy (у вихідні), nigdy (ніколи).", + "We describe how often we do a hobby with adverbs: często (often), czasami (sometimes), rzadko (rarely), codziennie (every day), w weekendy (on weekends), nigdy (never)."), + + ("a1_hobbies_free_time_l06", 6, "preferencje_najbardziej", "Najbardziej lubię...", "Больше всего люблю...", "Найбільше люблю...", "I like ... the most", + "Żeby powiedzieć o ulubionym hobby, używamy „najbardziej lubię” + bezokolicznik: najbardziej lubię czytać, najbardziej lubię pływać.", + "Чтобы сказать о любимом хобби, используем „najbardziej lubię” + инфинитив: najbardziej lubię czytać (больше всего я люблю читать), najbardziej lubię pływać (больше всего я люблю плавать).", + "Щоб сказати про улюблене хобі, використовуємо „najbardziej lubię” + інфінітив: najbardziej lubię czytać (найбільше я люблю читати), najbardziej lubię pływać (найбільше я люблю плавати).", + "To talk about a favorite hobby, we use „najbardziej lubię” + infinitive: najbardziej lubię czytać (I like reading the most), najbardziej lubię pływać (I like swimming the most)."), + + ("a1_hobbies_free_time_l07", 7, "grac_w_na", "Grać w + biernik / grać na + miejscownik", "Grać w + винительный / grać na + предложный", "Grać w + знахідний / grać na + місцевий", "Grać w + accusative / grać na + locative", + "Konstrukcja „grać w” + biernik dotyczy gier i sportów: grać w piłkę nożną, grać w szachy. Konstrukcja „grać na” + miejscownik dotyczy instrumentów: grać na gitarze, grać na pianinie.", + "Конструкция „grać w” + винительный падеж используется для игр и спорта: grać w piłkę nożną (играть в футбол), grać w szachy (играть в шахматы). Конструкция „grać na” + предложный падеж используется для инструментов: grać na gitarze (играть на гитаре).", + "Конструкція „grać w” + знахідний відмінок використовується для ігор і спорту: grać w piłkę nożną (грати у футбол), grać w szachy (грати в шахи). Конструкція „grać na” + місцевий відмінок використовується для інструментів: grać na gitarze (грати на гітарі).", + "The construction „grać w” + accusative is used for games and sports: grać w piłkę nożną (to play football), grać w szachy (to play chess). The construction „grać na” + locative is used for instruments: grać na gitarze (to play the guitar)."), + + ("a1_hobbies_free_time_l08", 8, "spedzac_czas_z", "Spędzać czas z + narzędnik", "Spędzać czas z + творительный падеж", "Spędzać czas z + орудний відмінок", "Spędzać czas z + instrumental", + "Żeby powiedzieć, z kim spędzamy czas, używamy „spędzać czas z” + narzędnik: spędzam czas z przyjaciółmi, spędzam czas z rodziną.", + "Чтобы сказать, с кем мы проводим время, используем „spędzać czas z” + творительный падеж: spędzam czas z przyjaciółmi (я провожу время с друзьями), spędzam czas z rodziną (я провожу время с семьёй).", + "Щоб сказати, з ким ми проводимо час, використовуємо „spędzać czas z” + орудний відмінок: spędzam czas z przyjaciółmi (я проводжу час з друзями), spędzam czas z rodziną (я проводжу час з родиною).", + "To say who we spend time with, we use „spędzać czas z” + the instrumental: spędzam czas z przyjaciółmi (I spend time with friends), spędzam czas z rodziną (I spend time with family)."), + + ("a1_hobbies_free_time_l09", 9, "planning_free_time", "Będę + bezokolicznik", "Będę + инфинитив", "Będę + інфінітив", "Będę + infinitive", + "O planach na wolny czas mówimy z czasownikiem „będę” + bezokolicznik: w weekend będę czytać, jutro będę grać w piłkę.", + "О планах на свободное время говорим с глаголом „będę” + инфинитив: w weekend będę czytać (в выходные я буду читать), jutro będę grać w piłkę (завтра я буду играть в футбол).", + "Про плани на вільний час говоримо з дієсловом „będę” + інфінітив: w weekend będę czytać (у вихідні я буду читати), jutro będę grać w piłkę (завтра я гратиму у футбол).", + "We talk about free-time plans with „będę” + infinitive: w weekend będę czytać (on the weekend I'll read), jutro będę grać w piłkę (tomorrow I'll play football)."), + + ("a1_hobbies_free_time_l10", 10, "hobby_description", "Opisuję swoje hobby", "Описываю своё хобби", "Описую своє хобі", "Describing my hobby", + "Żeby opisać swoje hobby, łączymy kilka zdań: Lubię czytać książki. Często czytam wieczorem. W weekendy spędzam czas z przyjaciółmi.", + "Чтобы описать своё хобби, соединяем несколько предложений: Lubię czytać książki. Często czytam wieczorem. W weekendy spędzam czas z przyjaciółmi. (Я люблю читать книги. Я часто читаю вечером. По выходным я провожу время с друзьями.)", + "Щоб описати своє хобі, поєднуємо кілька речень: Lubię czytać książki. Często czytam wieczorem. W weekendy spędzam czas z przyjaciółmi. (Я люблю читати книги. Я часто читаю ввечері. У вихідні я проводжу час з друзями.)", + "To describe your hobby, we combine several sentences: Lubię czytać książki. Często czytam wieczorem. W weekendy spędzam czas z przyjaciółmi. (I like reading books. I often read in the evening. On weekends I spend time with friends.)"), + ] + + for lesson in lessons_t12: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_hobbies_free_time', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t12 = [ + ("a1_hobbies_free_time_l01", 1, "Chcę czytać.", "Я хочу читать.", "Я хочу читати.", "I want to read."), + ("a1_hobbies_free_time_l01", 2, "Chcę gotować.", "Я хочу готовить.", "Я хочу готувати.", "I want to cook."), + ("a1_hobbies_free_time_l01", 3, "Chcę tańczyć.", "Я хочу танцевать.", "Я хочу танцювати.", "I want to dance."), + + ("a1_hobbies_free_time_l02", 1, "Lubię czytać.", "Я люблю читать.", "Я люблю читати.", "I like reading."), + ("a1_hobbies_free_time_l02", 2, "Lubisz gotować?", "Ты любишь готовить?", "Ти любиш готувати?", "Do you like cooking?"), + ("a1_hobbies_free_time_l02", 3, "On lubi tańczyć.", "Он любит танцевать.", "Він любить танцювати.", "He likes dancing."), + + ("a1_hobbies_free_time_l03", 1, "Lubię sport.", "Я люблю спорт.", "Я люблю спорт.", "I like sports."), + ("a1_hobbies_free_time_l03", 2, "Lubię muzykę.", "Я люблю музыку.", "Я люблю музику.", "I like music."), + ("a1_hobbies_free_time_l03", 3, "Lubisz taniec?", "Ты любишь танцы?", "Ти любиш танці?", "Do you like dance?"), + + ("a1_hobbies_free_time_l04", 1, "Mam dużo czasu wolnego.", "У меня много свободного времени.", "У мене багато вільного часу.", "I have a lot of free time."), + ("a1_hobbies_free_time_l04", 2, "W weekend odpoczywam.", "На выходных я отдыхаю.", "На вихідних я відпочиваю.", "I rest on the weekend."), + ("a1_hobbies_free_time_l04", 3, "Wieczorem czytam książkę.", "Вечером я читаю книгу.", "Ввечері я читаю книгу.", "In the evening I read a book."), + + ("a1_hobbies_free_time_l05", 1, "Często czytam książki.", "Я часто читаю книги.", "Я часто читаю книги.", "I often read books."), + ("a1_hobbies_free_time_l05", 2, "Rzadko gotuję.", "Я редко готовлю.", "Я рідко готую.", "I rarely cook."), + ("a1_hobbies_free_time_l05", 3, "W weekendy tańczę.", "По выходным я танцую.", "У вихідні я танцюю.", "On weekends I dance."), + + ("a1_hobbies_free_time_l06", 1, "Najbardziej lubię czytać.", "Больше всего я люблю читать.", "Найбільше я люблю читати.", "I like reading the most."), + ("a1_hobbies_free_time_l06", 2, "Najbardziej lubię sport.", "Больше всего я люблю спорт.", "Найбільше я люблю спорт.", "I like sports the most."), + ("a1_hobbies_free_time_l06", 3, "Co najbardziej lubisz robić?", "Что тебе больше всего нравится делать?", "Що тобі найбільше подобається робити?", "What do you like doing the most?"), + + ("a1_hobbies_free_time_l07", 1, "Gram w piłkę nożną.", "Я играю в футбол.", "Я граю у футбол.", "I play football."), + ("a1_hobbies_free_time_l07", 2, "Gram na gitarze.", "Я играю на гитаре.", "Я граю на гітарі.", "I play the guitar."), + ("a1_hobbies_free_time_l07", 3, "Grasz w szachy?", "Ты играешь в шахматы?", "Ти граєш у шахи?", "Do you play chess?"), + + ("a1_hobbies_free_time_l08", 1, "Spędzam czas z przyjaciółmi.", "Я провожу время с друзьями.", "Я проводжу час з друзями.", "I spend time with friends."), + ("a1_hobbies_free_time_l08", 2, "Spędzasz czas z rodziną?", "Ты проводишь время с семьёй?", "Ти проводиш час з родиною?", "Do you spend time with family?"), + ("a1_hobbies_free_time_l08", 3, "On spędza czas z siostrą.", "Он проводит время с сестрой.", "Він проводить час із сестрою.", "He spends time with his sister."), + + ("a1_hobbies_free_time_l09", 1, "W weekend będę czytać.", "В выходные я буду читать.", "У вихідні я буду читати.", "On the weekend I'll read."), + ("a1_hobbies_free_time_l09", 2, "Jutro będę grać w piłkę nożną.", "Завтра я буду играть в футбол.", "Завтра я гратиму у футбол.", "Tomorrow I'll play football."), + ("a1_hobbies_free_time_l09", 3, "Wieczorem będziemy gotować razem.", "Вечером мы будем готовить вместе.", "Ввечері ми будемо готувати разом.", "In the evening we'll cook together."), + + ("a1_hobbies_free_time_l10", 1, "Lubię czytać książki.", "Я люблю читать книги.", "Я люблю читати книги.", "I like reading books."), + ("a1_hobbies_free_time_l10", 2, "Często czytam wieczorem.", "Я часто читаю вечером.", "Я часто читаю ввечері.", "I often read in the evening."), + ("a1_hobbies_free_time_l10", 3, "W weekendy spędzam czas z przyjaciółmi.", "По выходным я провожу время с друзьями.", "У вихідні я проводжу час з друзями.", "On weekends I spend time with friends."), + ] + + for ex in examples_t12: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t12 = [ + # L01 — free_time_activities_verbs (difficulty 1) + ("a1_hobbies_free_time_l01_q1", "a1_hobbies_free_time_l01", "lesson_practice", "recognition", "free_time_activities_verbs", 1, + "Jak po polsku „плавать”?", "Как по-польски «плавать»?", "Як польською «плавати»?", "How do you say “to swim” in Polish?", + "A", None, None), + ("a1_hobbies_free_time_l01_q2", "a1_hobbies_free_time_l01", "lesson_practice", "production", "free_time_activities_verbs", 1, + "Wpisz brakujące słowo: Chcę ___. (готовить)", "Вставьте пропущенное слово: Chcę ___. (готовить)", "Вставте пропущене слово: Chcę ___. (готувати)", "Fill in the missing word: Chcę ___. (to cook)", + "gotować", "first_letter", "g"), + ("a1_hobbies_free_time_l01_q3", "a1_hobbies_free_time_l01", "lesson_practice", "application", "free_time_activities_verbs", 1, + "Robisz ruchy w wodzie w basenie. Jaki to czasownik?", "Ты делаешь движения в воде в бассейне. Какой это глагол?", "Ти робиш рухи у воді в басейні. Яке це дієслово?", "You're moving through water at the pool. What's this verb?", + "A", None, None), + + # L02 — lubic_bezokolicznik (difficulty 1) + ("a1_hobbies_free_time_l02_q1", "a1_hobbies_free_time_l02", "lesson_practice", "recognition", "lubic_bezokolicznik", 1, + "Wybierz poprawną formę: Ja ___ czytać. (lubić)", "Выберите правильную форму: Ja ___ czytać. (lubić)", "Виберіть правильну форму: Ja ___ czytać. (lubić)", "Choose the correct form: Ja ___ czytać. (lubić)", + "A", None, None), + ("a1_hobbies_free_time_l02_q2", "a1_hobbies_free_time_l02", "lesson_practice", "production", "lubic_bezokolicznik", 1, + "Wpisz brakujące słowo: Ty ___ pływać? (любишь)", "Вставьте пропущенное слово: Ty ___ pływać? (любишь)", "Вставте пропущене слово: Ty ___ pływać? (любиш)", "Fill in the missing word: Ty ___ pływać? (do you like)", + "lubisz", "first_letter", "l"), + ("a1_hobbies_free_time_l02_q3", "a1_hobbies_free_time_l02", "lesson_practice", "application", "lubic_bezokolicznik", 1, + "Kolega pyta, czy lubisz gotować. Tak, bardzo. Co powiesz?", "Друг спрашивает, любишь ли ты готовить. Да, очень. Что ты скажешь?", "Друг питає, чи любиш ти готувати. Так, дуже. Що ти скажеш?", "A friend asks if you like cooking. Yes, very much. What do you say?", + "A", None, None), + + # L03 — hobby_nouns (difficulty 1) + ("a1_hobbies_free_time_l03_q1", "a1_hobbies_free_time_l03", "lesson_practice", "recognition", "hobby_nouns", 1, + "Wybierz poprawną formę: Lubię ___. (muzyka)", "Выберите правильную форму: Lubię ___. (muzyka)", "Виберіть правильну форму: Lubię ___. (muzyka)", "Choose the correct form: Lubię ___. (muzyka)", + "A", None, None), + ("a1_hobbies_free_time_l03_q2", "a1_hobbies_free_time_l03", "lesson_practice", "production", "hobby_nouns", 1, + "Wpisz brakujące słowo: Lubię ___. (спорт)", "Вставьте пропущенное слово: Lubię ___. (спорт)", "Вставте пропущене слово: Lubię ___. (спорт)", "Fill in the missing word: Lubię ___. (sports)", + "sport", "first_letter", "s"), + ("a1_hobbies_free_time_l03_q3", "a1_hobbies_free_time_l03", "lesson_practice", "application", "hobby_nouns", 1, + "Kolega pyta, co lubisz. Lubisz taniec. Co powiesz?", "Друг спрашивает, что ты любишь. Ты любишь танцы. Что ты скажешь?", "Друг питає, що ти любиш. Ти любиш танці. Що ти скажеш?", "A friend asks what you like. You like dance. What do you say?", + "A", None, None), + + # L04 — czas_wolny_vocabulary (difficulty 1) + ("a1_hobbies_free_time_l04_q1", "a1_hobbies_free_time_l04", "lesson_practice", "recognition", "czas_wolny_vocabulary", 1, + "Jak po polsku „выходные”?", "Как по-польски «выходные»?", "Як польською «вихідні»?", "How do you say “weekend” in Polish?", + "A", None, None), + ("a1_hobbies_free_time_l04_q2", "a1_hobbies_free_time_l04", "lesson_practice", "production", "czas_wolny_vocabulary", 1, + "Wpisz brakujące słowo: ___ czytam książkę. (вечером)", "Вставьте пропущенное слово: ___ czytam książkę. (вечером)", "Вставте пропущене слово: ___ czytam książkę. (ввечері)", "Fill in the missing word: ___ czytam książkę. (in the evening)", + "Wieczorem", "first_letter", "W"), + ("a1_hobbies_free_time_l04_q3", "a1_hobbies_free_time_l04", "lesson_practice", "application", "czas_wolny_vocabulary", 1, + "Chcesz powiedzieć, że masz dużo czasu bez obowiązków. Co powiesz?", "Ты хочешь сказать, что у тебя много времени без обязательств. Что ты скажешь?", "Ти хочеш сказати, що маєш багато часу без обов'язків. Що ти скажеш?", "You want to say you have a lot of time without obligations. What do you say?", + "A", None, None), + + # L05 — jak_czesto_hobby (difficulty 2) + ("a1_hobbies_free_time_l05_q1", "a1_hobbies_free_time_l05", "lesson_practice", "recognition", "jak_czesto_hobby", 2, + "Co znaczy „W weekendy tańczę”?", "Что означает «W weekendy tańczę»?", "Що означає «W weekendy tańczę»?", "What does “W weekendy tańczę” mean?", + "A", None, None), + ("a1_hobbies_free_time_l05_q2", "a1_hobbies_free_time_l05", "lesson_practice", "production", "jak_czesto_hobby", 2, + "Wpisz brakujące słowo: ___ czytam książki. (часто)", "Вставьте пропущенное слово: ___ czytam książki. (часто)", "Вставте пропущене слово: ___ czytam książki. (часто)", "Fill in the missing word: ___ czytam książki. (often)", + "Często", "first_letter", "C"), + ("a1_hobbies_free_time_l05_q3", "a1_hobbies_free_time_l05", "lesson_practice", "application", "jak_czesto_hobby", 2, + "Kolega pyta, jak często gotujesz. Robisz to rzadko. Co powiesz?", "Друг спрашивает, как часто ты готовишь. Ты делаешь это редко. Что ты скажешь?", "Друг питає, як часто ти готуєш. Ти робиш це рідко. Що ти скажеш?", "A friend asks how often you cook. You rarely do. What do you say?", + "A", None, None), + + # L06 — preferencje_najbardziej (difficulty 2) + ("a1_hobbies_free_time_l06_q1", "a1_hobbies_free_time_l06", "lesson_practice", "recognition", "preferencje_najbardziej", 2, + "Wybierz poprawną formę: Najbardziej lubię ___. (pływać)", "Выберите правильную форму: Najbardziej lubię ___. (pływać)", "Виберіть правильну форму: Najbardziej lubię ___. (pływać)", "Choose the correct form: Najbardziej lubię ___. (pływać)", + "A", None, None), + ("a1_hobbies_free_time_l06_q2", "a1_hobbies_free_time_l06", "lesson_practice", "production", "preferencje_najbardziej", 2, + "Wpisz brakujące słowo: Najbardziej lubię ___. (танцевать)", "Вставьте пропущенное слово: Najbardziej lubię ___. (танцевать)", "Вставте пропущене слово: Najbardziej lubię ___. (танцювати)", "Fill in the missing word: Najbardziej lubię ___. (to dance)", + "tańczyć", "first_letter", "t"), + ("a1_hobbies_free_time_l06_q3", "a1_hobbies_free_time_l06", "lesson_practice", "application", "preferencje_najbardziej", 2, + "Kolega pyta, co najbardziej lubisz robić w wolnym czasie. Uwielbiasz czytać. Co powiesz?", "Друг спрашивает, что тебе больше всего нравится делать в свободное время. Ты обожаешь читать. Что ты скажешь?", "Друг питає, що тобі найбільше подобається робити у вільний час. Ти обожнюєш читати. Що ти скажеш?", "A friend asks what you like doing most in your free time. You love reading. What do you say?", + "A", None, None), + + # L07 — grac_w_na (difficulty 2) + ("a1_hobbies_free_time_l07_q1", "a1_hobbies_free_time_l07", "lesson_practice", "recognition", "grac_w_na", 2, + "Wybierz poprawną formę: Gram ___ gitarze. (на)", "Выберите правильную форму: Gram ___ gitarze. (на)", "Виберіть правильну форму: Gram ___ gitarze. (на)", "Choose the correct form: Gram ___ gitarze. (on)", + "A", None, None), + ("a1_hobbies_free_time_l07_q2", "a1_hobbies_free_time_l07", "lesson_practice", "production", "grac_w_na", 2, + "Wpisz brakujące słowo: Gram ___ piłkę nożną. (в)", "Вставьте пропущенное слово: Gram ___ piłkę nożną. (в)", "Вставте пропущене слово: Gram ___ piłkę nożną. (у)", "Fill in the missing word: Gram ___ piłkę nożną. (at)", + "w", "first_letter", "w"), + ("a1_hobbies_free_time_l07_q3", "a1_hobbies_free_time_l07", "lesson_practice", "application", "grac_w_na", 2, + "Chcesz powiedzieć, że grasz na pianinie. Co powiesz?", "Ты хочешь сказать, что играешь на пианино. Что ты скажешь?", "Ти хочеш сказати, що граєш на піаніно. Що ти скажеш?", "You want to say you play the piano. What do you say?", + "A", None, None), + + # L08 — spedzac_czas_z (difficulty 2) + ("a1_hobbies_free_time_l08_q1", "a1_hobbies_free_time_l08", "lesson_practice", "recognition", "spedzac_czas_z", 2, + "Wybierz poprawną formę: Spędzam czas z ___. (przyjaciele)", "Выберите правильную форму: Spędzam czas z ___. (przyjaciele)", "Виберіть правильну форму: Spędzam czas z ___. (przyjaciele)", "Choose the correct form: Spędzam czas z ___. (przyjaciele)", + "A", None, None), + ("a1_hobbies_free_time_l08_q2", "a1_hobbies_free_time_l08", "lesson_practice", "production", "spedzac_czas_z", 2, + "Wpisz brakujące słowo: Spędzam czas z ___. (семьёй)", "Вставьте пропущенное слово: Spędzam czas z ___. (семьёй)", "Вставте пропущене слово: Spędzam czas z ___. (родиною)", "Fill in the missing word: Spędzam czas z ___. (family)", + "rodziną", "first_letter", "r"), + ("a1_hobbies_free_time_l08_q3", "a1_hobbies_free_time_l08", "lesson_practice", "application", "spedzac_czas_z", 2, + "Chcesz powiedzieć, że w weekend spotykasz się z przyjaciółmi. Co powiesz?", "Ты хочешь сказать, что на выходных встречаешься с друзьями. Что ты скажешь?", "Ти хочеш сказати, що на вихідних зустрічаєшся з друзями. Що ти скажеш?", "You want to say you meet friends on the weekend. What do you say?", + "A", None, None), + + # L09 — planning_free_time (difficulty 3) + ("a1_hobbies_free_time_l09_q1", "a1_hobbies_free_time_l09", "lesson_practice", "recognition", "planning_free_time", 3, + "Co znaczy „W weekend będę czytać”?", "Что означает «W weekend będę czytać»?", "Що означає «W weekend będę czytać»?", "What does “W weekend będę czytać” mean?", + "A", None, None), + ("a1_hobbies_free_time_l09_q2", "a1_hobbies_free_time_l09", "lesson_practice", "production", "planning_free_time", 3, + "Wpisz brakujące słowo: Jutro ___ grać w piłkę. (буду)", "Вставьте пропущенное слово: Jutro ___ grać w piłkę. (буду)", "Вставте пропущене слово: Jutro ___ grać w piłkę. (буду)", "Fill in the missing word: Jutro ___ grać w piłkę. (I'll)", + "będę", "first_letter", "b"), + ("a1_hobbies_free_time_l09_q3", "a1_hobbies_free_time_l09", "lesson_practice", "application", "planning_free_time", 3, + "Planujesz jutro grać w szachy z kolegą. Co powiesz?", "Ты планируешь завтра играть в шахматы с другом. Что ты скажешь?", "Ти плануєш завтра грати в шахи з другом. Що ти скажеш?", "You plan to play chess with a friend tomorrow. What do you say?", + "A", None, None), + + # L10 — hobby_description (difficulty 3) + ("a1_hobbies_free_time_l10_q1", "a1_hobbies_free_time_l10", "lesson_practice", "recognition", "hobby_description", 3, + "Które zdanie poprawnie opisuje hobby?", "Какое предложение правильно описывает хобби?", "Яке речення правильно описує хобі?", "Which sentence correctly describes a hobby?", + "A", None, None), + ("a1_hobbies_free_time_l10_q2", "a1_hobbies_free_time_l10", "lesson_practice", "production", "hobby_description", 3, + "Przetłumacz: «По выходным я провожу время с друзьями».", "Переведите: «По выходным я провожу время с друзьями».", "Перекладіть: «У вихідні я проводжу час з друзями».", "Translate: “On weekends I spend time with friends.”", + "W weekendy spędzam czas z przyjaciółmi", "first_letter", "W"), + ("a1_hobbies_free_time_l10_q3", "a1_hobbies_free_time_l10", "lesson_practice", "application", "hobby_description", 3, + "Chcesz opisać koledze swoje hobby: lubisz grać w piłkę nożną, robisz to często, w weekendy grasz z przyjaciółmi. Jak zaczniesz zdanie?", "Ты хочешь описать другу своё хобби: тебе нравится играть в футбол, ты делаешь это часто, по выходным играешь с друзьями. Как ты начнёшь предложение?", "Ти хочеш описати другу своє хобі: тобі подобається грати у футбол, ти робиш це часто, у вихідні граєш з друзями. Як ти почнеш речення?", "You want to describe your hobby to a friend: you like playing football, you do it often, on weekends you play with friends. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t12: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_hobbies_free_time', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t12 = [ + # L01 + ("a1_hobbies_free_time_l01_q1", "A", "pływać", "плавать", "плавати", "to swim", True, None), + ("a1_hobbies_free_time_l01_q1", "B", "tańczyć", "танцевать", "танцювати", "to dance", False, "wrong_word"), + ("a1_hobbies_free_time_l01_q1", "C", "gotować", "готовить", "готувати", "to cook", False, "wrong_word"), + ("a1_hobbies_free_time_l01_q1", "D", "czytać", "читать", "читати", "to read", False, "wrong_word"), + + ("a1_hobbies_free_time_l01_q3", "A", "pływać", "плавать", "плавати", "to swim", True, None), + ("a1_hobbies_free_time_l01_q3", "B", "tańczyć", "танцевать", "танцювати", "to dance", False, "wrong_context"), + ("a1_hobbies_free_time_l01_q3", "C", "gotować", "готовить", "готувати", "to cook", False, "wrong_context"), + ("a1_hobbies_free_time_l01_q3", "D", "czytać", "читать", "читати", "to read", False, "wrong_context"), + + # L02 + ("a1_hobbies_free_time_l02_q1", "A", "lubię", "люблю", "люблю", "like (I)", True, None), + ("a1_hobbies_free_time_l02_q1", "B", "lubisz", "любишь", "любиш", "like (you)", False, "wrong_word"), + ("a1_hobbies_free_time_l02_q1", "C", "lubi", "любит", "любить", "likes", False, "wrong_word"), + ("a1_hobbies_free_time_l02_q1", "D", "lubić", "любить (инф.)", "любити (інф.)", "to like", False, "wrong_word"), + + ("a1_hobbies_free_time_l02_q3", "A", "Lubię gotować.", "Я люблю готовить.", "Я люблю готувати.", "I like cooking.", True, None), + ("a1_hobbies_free_time_l02_q3", "B", "Lubię gotowanie wczoraj.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_l02_q3", "C", "Gotuję teraz.", "Я готовлю сейчас. (не отвечает на вопрос)", "Я готую зараз. (не відповідає на питання)", "I'm cooking now. (doesn't answer the question)", False, "wrong_context"), + ("a1_hobbies_free_time_l02_q3", "D", "Chcę gotować sklep.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + # L03 + ("a1_hobbies_free_time_l03_q1", "A", "muzykę", "музыку (вин.)", "музику (знах.)", "music (acc.)", True, None), + ("a1_hobbies_free_time_l03_q1", "B", "muzyka", "музыка (им.)", "музика (наз.)", "music (nom.)", False, "wrong_case"), + ("a1_hobbies_free_time_l03_q1", "C", "muzyki", "музыки (род.)", "музики (род.)", "music (gen.)", False, "wrong_case"), + ("a1_hobbies_free_time_l03_q1", "D", "muzyką", "музыкой (тв.)", "музикою (ор.)", "music (instr.)", False, "wrong_case"), + + ("a1_hobbies_free_time_l03_q3", "A", "Lubię taniec.", "Я люблю танцы.", "Я люблю танці.", "I like dance.", True, None), + ("a1_hobbies_free_time_l03_q3", "B", "Lubię tańczyć wczoraj.", "Неправильное время.", "Неправильний час.", "Wrong tense.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_l03_q3", "C", "Tańczę teraz.", "Я танцую сейчас. (не отвечает на вопрос)", "Я танцюю зараз. (не відповідає на питання)", "I'm dancing now. (doesn't answer the question)", False, "wrong_context"), + ("a1_hobbies_free_time_l03_q3", "D", "Chcę taniec kupić.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + # L04 + ("a1_hobbies_free_time_l04_q1", "A", "weekend", "выходные", "вихідні", "weekend", True, None), + ("a1_hobbies_free_time_l04_q1", "B", "wieczór", "вечер", "вечір", "evening", False, "wrong_word"), + ("a1_hobbies_free_time_l04_q1", "C", "sobota", "суббота", "субота", "Saturday", False, "wrong_word"), + ("a1_hobbies_free_time_l04_q1", "D", "czas wolny", "свободное время", "вільний час", "free time", False, "wrong_word"), + + ("a1_hobbies_free_time_l04_q3", "A", "Mam dużo czasu wolnego.", "У меня много свободного времени.", "У мене багато вільного часу.", "I have a lot of free time.", True, None), + ("a1_hobbies_free_time_l04_q3", "B", "Mam dużo pracy.", "У меня много работы. (противоречит ситуации)", "У мене багато роботи. (суперечить ситуації)", "I have a lot of work. (contradicts the situation)", False, "wrong_context"), + ("a1_hobbies_free_time_l04_q3", "C", "Jestem w pracy.", "Я на работе. (противоречит ситуации)", "Я на роботі. (суперечить ситуації)", "I'm at work. (contradicts the situation)", False, "wrong_context"), + ("a1_hobbies_free_time_l04_q3", "D", "Nie mam czasu.", "У меня нет времени. (противоречит ситуации)", "У мене немає часу. (суперечить ситуації)", "I have no time. (contradicts the situation)", False, "wrong_context"), + + # L05 + ("a1_hobbies_free_time_l05_q1", "A", "W weekendy tańczę.", "По выходным я танцую.", "У вихідні я танцюю.", "On weekends I dance.", True, None), + ("a1_hobbies_free_time_l05_q1", "B", "Codziennie tańczę.", "Я танцую каждый день.", "Я танцюю щодня.", "I dance every day.", False, "wrong_translation"), + ("a1_hobbies_free_time_l05_q1", "C", "Nigdy nie tańczę.", "Я никогда не танцую.", "Я ніколи не танцюю.", "I never dance.", False, "wrong_translation"), + ("a1_hobbies_free_time_l05_q1", "D", "Czasami czytam.", "Иногда я читаю.", "Іноді я читаю.", "Sometimes I read.", False, "wrong_translation"), + + ("a1_hobbies_free_time_l05_q3", "A", "Rzadko gotuję.", "Я редко готовлю.", "Я рідко готую.", "I rarely cook.", True, None), + ("a1_hobbies_free_time_l05_q3", "B", "Często gotuję.", "Я часто готовлю. (неверная частота)", "Я часто готую. (невірна частота)", "I often cook. (wrong frequency)", False, "wrong_context"), + ("a1_hobbies_free_time_l05_q3", "C", "Nigdy nie gotuję.", "Я никогда не готовлю. (неверная частота)", "Я ніколи не готую. (невірна частота)", "I never cook. (wrong frequency)", False, "wrong_context"), + ("a1_hobbies_free_time_l05_q3", "D", "Codziennie gotuję.", "Я готовлю каждый день. (неверная частота)", "Я готую щодня. (невірна частота)", "I cook every day. (wrong frequency)", False, "wrong_context"), + + # L06 + ("a1_hobbies_free_time_l06_q1", "A", "pływać", "плавать (инф.)", "плавати (інф.)", "to swim", True, None), + ("a1_hobbies_free_time_l06_q1", "B", "pływam", "плаваю", "плаваю", "I swim", False, "wrong_word"), + ("a1_hobbies_free_time_l06_q1", "C", "pływasz", "плаваешь", "плаваєш", "you swim", False, "wrong_word"), + ("a1_hobbies_free_time_l06_q1", "D", "pływa", "плавает", "плаває", "swims", False, "wrong_word"), + + ("a1_hobbies_free_time_l06_q3", "A", "Najbardziej lubię czytać.", "Больше всего я люблю читать.", "Найбільше я люблю читати.", "I like reading the most.", True, None), + ("a1_hobbies_free_time_l06_q3", "B", "Najbardziej lubię gotować.", "Больше всего я люблю готовить. (неверное хобби)", "Найбільше я люблю готувати. (невірне хобі)", "I like cooking the most. (wrong hobby)", False, "wrong_context"), + ("a1_hobbies_free_time_l06_q3", "C", "Czytam czasami.", "Я иногда читаю. (не о любимом занятии)", "Я іноді читаю. (не про улюблене заняття)", "I sometimes read. (not about a favorite)", False, "wrong_context"), + ("a1_hobbies_free_time_l06_q3", "D", "Nie lubię czytać.", "Я не люблю читать. (противоречит ситуации)", "Я не люблю читати. (суперечить ситуації)", "I don't like reading. (contradicts the situation)", False, "wrong_context"), + + # L07 + ("a1_hobbies_free_time_l07_q1", "A", "na", "на", "на", "on", True, None), + ("a1_hobbies_free_time_l07_q1", "B", "w", "в", "у", "at", False, "wrong_word"), + ("a1_hobbies_free_time_l07_q1", "C", "do", "до", "до", "to", False, "wrong_word"), + ("a1_hobbies_free_time_l07_q1", "D", "z", "с", "з", "with", False, "wrong_word"), + + ("a1_hobbies_free_time_l07_q3", "A", "Gram na pianinie.", "Я играю на пианино.", "Я граю на піаніно.", "I play the piano.", True, None), + ("a1_hobbies_free_time_l07_q3", "B", "Gram w pianino.", "Неправильный предлог для инструмента.", "Неправильний прийменник для інструменту.", "Wrong preposition for an instrument.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_l07_q3", "C", "Gram pianino.", "Пропущен предлог.", "Пропущено прийменник.", "Missing preposition.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_l07_q3", "D", "Mam pianino.", "У меня есть пианино. (не о игре)", "У мене є піаніно. (не про гру)", "I have a piano. (not about playing)", False, "wrong_context"), + + # L08 + ("a1_hobbies_free_time_l08_q1", "A", "przyjaciółmi", "друзьями (тв.)", "друзями (ор.)", "friends (instr.)", True, None), + ("a1_hobbies_free_time_l08_q1", "B", "przyjaciele", "друзья (им.)", "друзі (наз.)", "friends (nom.)", False, "wrong_case"), + ("a1_hobbies_free_time_l08_q1", "C", "przyjaciół", "друзей (род.)", "друзів (род.)", "friends (gen.)", False, "wrong_case"), + ("a1_hobbies_free_time_l08_q1", "D", "przyjaciołom", "друзьям (дат.)", "друзям (дав.)", "friends (dat.)", False, "wrong_case"), + + ("a1_hobbies_free_time_l08_q3", "A", "Spędzam czas z przyjaciółmi.", "Я провожу время с друзьями.", "Я проводжу час з друзями.", "I spend time with friends.", True, None), + ("a1_hobbies_free_time_l08_q3", "B", "Mam przyjaciół.", "У меня есть друзья. (не о проведении времени)", "У мене є друзі. (не про проведення часу)", "I have friends. (not about spending time)", False, "wrong_context"), + ("a1_hobbies_free_time_l08_q3", "C", "Lubię przyjaciół.", "Я люблю друзей. (не о встрече)", "Я люблю друзів. (не про зустріч)", "I like friends. (not about meeting)", False, "wrong_context"), + ("a1_hobbies_free_time_l08_q3", "D", "Szukam przyjaciół.", "Я ищу друзей. (не о встрече)", "Я шукаю друзів. (не про зустріч)", "I'm looking for friends. (not about meeting)", False, "wrong_context"), + + # L09 + ("a1_hobbies_free_time_l09_q1", "A", "W weekend będę czytać.", "В выходные я буду читать.", "У вихідні я буду читати.", "On the weekend I'll read.", True, None), + ("a1_hobbies_free_time_l09_q1", "B", "W weekend czytałem.", "В выходные я читал.", "У вихідні я читав.", "On the weekend I read (past).", False, "wrong_translation"), + ("a1_hobbies_free_time_l09_q1", "C", "Codziennie czytam.", "Я читаю каждый день.", "Я читаю щодня.", "I read every day.", False, "wrong_translation"), + ("a1_hobbies_free_time_l09_q1", "D", "Nie lubię czytać.", "Я не люблю читать.", "Я не люблю читати.", "I don't like reading.", False, "wrong_translation"), + + ("a1_hobbies_free_time_l09_q3", "A", "Jutro będę grać w szachy.", "Завтра я буду играть в шахматы.", "Завтра я гратиму в шахи.", "Tomorrow I'll play chess.", True, None), + ("a1_hobbies_free_time_l09_q3", "B", "Wczoraj grałem w szachy.", "Вчера я играл в шахматы. (неверное время)", "Вчора я грав у шахи. (невірний час)", "Yesterday I played chess. (wrong tense)", False, "wrong_context"), + ("a1_hobbies_free_time_l09_q3", "C", "Nigdy nie gram w szachy.", "Я никогда не играю в шахматы. (противоречит ситуации)", "Я ніколи не граю в шахи. (суперечить ситуації)", "I never play chess. (contradicts the situation)", False, "wrong_context"), + ("a1_hobbies_free_time_l09_q3", "D", "Lubię szachy.", "Я люблю шахматы. (не о планах)", "Я люблю шахи. (не про плани)", "I like chess. (not about plans)", False, "wrong_context"), + + # L10 + ("a1_hobbies_free_time_l10_q1", "A", "Lubię czytać książki i często to robię wieczorem.", "Я люблю читать книги и часто делаю это вечером.", "Я люблю читати книги і часто роблю це ввечері.", "I like reading books and I often do it in the evening.", True, None), + ("a1_hobbies_free_time_l10_q1", "B", "Lubię czytać książka wieczorem.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_hobbies_free_time_l10_q1", "C", "Jestem czytać książki wieczorem.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_l10_q1", "D", "Lubię gotować książki wieczorem.", "Бессмысленное сочетание слов.", "Безглузде поєднання слів.", "Nonsensical word combination.", False, "wrong_context"), + + ("a1_hobbies_free_time_l10_q3", "A", "Lubię grać w piłkę nożną i często to robię.", "Я люблю играть в футбол и часто это делаю.", "Я люблю грати у футбол і часто це роблю.", "I like playing football and I often do it.", True, None), + ("a1_hobbies_free_time_l10_q3", "B", "Piłka nożna jestem lubię.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_l10_q3", "C", "Gram piłka nożna czasami wczoraj.", "Неправильный падеж и время.", "Неправильний відмінок і час.", "Wrong case and tense.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_l10_q3", "D", "Chcę kupić piłkę nożną.", "Я хочу купить футбольный мяч. (не о хобби)", "Я хочу купити футбольний м'яч. (не про хобі)", "I want to buy a football. (not about the hobby)", False, "wrong_context"), + ] + + for opt in options_t12: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t12 = [ + ("a1_hobbies_free_time_t01", None, "topic_test", "recognition", "free_time_activities_verbs", 1, + "Jak po polsku „плавать”?", "Как по-польски «плавать»?", "Як польською «плавати»?", "How do you say “to swim” in Polish?", + "A", None, None, 1), + ("a1_hobbies_free_time_t02", None, "topic_test", "recognition", "lubic_bezokolicznik", 1, + "Wybierz poprawną formę: On ___ tańczyć. (lubić)", "Выберите правильную форму: On ___ tańczyć. (lubić)", "Виберіть правильну форму: On ___ tańczyć. (lubić)", "Choose the correct form: On ___ tańczyć. (lubić)", + "A", None, None, 2), + ("a1_hobbies_free_time_t03", None, "topic_test", "recognition", "hobby_nouns", 1, + "Wybierz poprawną formę: Lubię ___. (sport)", "Выберите правильную форму: Lubię ___. (sport)", "Виберіть правильну форму: Lubię ___. (sport)", "Choose the correct form: Lubię ___. (sport)", + "A", None, None, 3), + ("a1_hobbies_free_time_t04", None, "topic_test", "recognition", "czas_wolny_vocabulary", 2, + "Jak po polsku „выходные”?", "Как по-польски «выходные»?", "Як польською «вихідні»?", "How do you say “weekend” in Polish?", + "A", None, None, 4), + ("a1_hobbies_free_time_t05", None, "topic_test", "recognition", "jak_czesto_hobby", 2, + "Co znaczy „W weekendy tańczę”?", "Что означает «W weekendy tańczę»?", "Що означає «W weekendy tańczę»?", "What does “W weekendy tańczę” mean?", + "A", None, None, 5), + ("a1_hobbies_free_time_t06", None, "topic_test", "recognition", "grac_w_na", 3, + "Wybierz poprawną formę: Gram ___ szachy. (в)", "Выберите правильную форму: Gram ___ szachy. (в)", "Виберіть правильну форму: Gram ___ szachy. (у)", "Choose the correct form: Gram ___ szachy. (at)", + "A", None, None, 6), + + ("a1_hobbies_free_time_t07", None, "topic_test", "application", "free_time_activities_verbs", 1, + "Robisz ruchy w wodzie w basenie. Jaki to czasownik?", "Ты делаешь движения в воде в бассейне. Какой это глагол?", "Ти робиш рухи у воді в басейні. Яке це дієслово?", "You're moving through water at the pool. What's this verb?", + "A", None, None, 7), + ("a1_hobbies_free_time_t08", None, "topic_test", "application", "hobby_nouns", 1, + "Kolega pyta, co lubisz. Lubisz muzykę. Co powiesz?", "Друг спрашивает, что ты любишь. Ты любишь музыку. Что ты скажешь?", "Друг питає, що ти любиш. Ти любиш музику. Що ти скажеш?", "A friend asks what you like. You like music. What do you say?", + "A", None, None, 8), + ("a1_hobbies_free_time_t09", None, "topic_test", "application", "preferencje_najbardziej", 2, + "Kolega pyta, co najbardziej lubisz robić. Uwielbiasz pływać. Co powiesz?", "Друг спрашивает, что тебе больше всего нравится делать. Ты обожаешь плавать. Что ты скажешь?", "Друг питає, що тобі найбільше подобається робити. Ти обожнюєш плавати. Що ти скажеш?", "A friend asks what you like doing most. You love swimming. What do you say?", + "A", None, None, 9), + ("a1_hobbies_free_time_t10", None, "topic_test", "application", "spedzac_czas_z", 2, + "Chcesz powiedzieć, że w weekend spotykasz się z rodziną. Co powiesz?", "Ты хочешь сказать, что на выходных встречаешься с семьёй. Что ты скажешь?", "Ти хочеш сказати, що на вихідних зустрічаєшся з родиною. Що ти скажеш?", "You want to say you meet family on the weekend. What do you say?", + "A", None, None, 10), + ("a1_hobbies_free_time_t11", None, "topic_test", "application", "planning_free_time", 3, + "Planujesz jutro czytać książkę. Co powiesz?", "Ты планируешь завтра читать книгу. Что ты скажешь?", "Ти плануєш завтра читати книгу. Що ти скажеш?", "You plan to read a book tomorrow. What do you say?", + "A", None, None, 11), + ("a1_hobbies_free_time_t12", None, "topic_test", "application", "hobby_description", 3, + "Chcesz opisać koledze swoje hobby: lubisz gotować, robisz to często wieczorem. Jak zaczniesz zdanie?", "Ты хочешь описать другу своё хобби: тебе нравится готовить, ты делаешь это часто вечером. Как ты начнёшь предложение?", "Ти хочеш описати другу своє хобі: тобі подобається готувати, ти робиш це часто ввечері. Як ти почнеш речення?", "You want to describe your hobby to a friend: you like cooking, you do it often in the evening. How do you start the sentence?", + "A", None, None, 12), + + ("a1_hobbies_free_time_t13", None, "topic_test", "production", "free_time_activities_verbs", 1, + "Wpisz brakujące słowo: Chcę ___. (танцевать)", "Вставьте пропущенное слово: Chcę ___. (танцевать)", "Вставте пропущене слово: Chcę ___. (танцювати)", "Fill in the missing word: Chcę ___. (to dance)", + "tańczyć", "first_letter", "t", 13), + ("a1_hobbies_free_time_t14", None, "topic_test", "production", "hobby_nouns", 1, + "Wpisz brakujące słowo: Lubię ___. (музыку)", "Вставьте пропущенное слово: Lubię ___. (музыку)", "Вставте пропущене слово: Lubię ___. (музику)", "Fill in the missing word: Lubię ___. (music)", + "muzykę", "first_letter", "m", 14), + ("a1_hobbies_free_time_t15", None, "topic_test", "production", "czas_wolny_vocabulary", 2, + "Wpisz brakujące słowo: ___ czytam książkę. (вечером)", "Вставьте пропущенное слово: ___ czytam książkę. (вечером)", "Вставте пропущене слово: ___ czytam książkę. (ввечері)", "Fill in the missing word: ___ czytam książkę. (in the evening)", + "Wieczorem", "first_letter", "W", 15), + ("a1_hobbies_free_time_t16", None, "topic_test", "production", "jak_czesto_hobby", 2, + "Wpisz brakujące słowo: ___ czytam książki. (часто)", "Вставьте пропущенное слово: ___ czytam książki. (часто)", "Вставте пропущене слово: ___ czytam książki. (часто)", "Fill in the missing word: ___ czytam książki. (often)", + "Często", "first_letter", "C", 16), + ("a1_hobbies_free_time_t17", None, "topic_test", "production", "grac_w_na", 3, + "Wpisz brakujące słowo: Gram ___ gitarze. (на)", "Вставьте пропущенное слово: Gram ___ gitarze. (на)", "Вставте пропущене слово: Gram ___ gitarze. (на)", "Fill in the missing word: Gram ___ gitarze. (on)", + "na", "first_letter", "n", 17), + ("a1_hobbies_free_time_t18", None, "topic_test", "production", "spedzac_czas_z", 2, + "Wpisz brakujące słowo: Spędzam czas z ___. (семьёй)", "Вставьте пропущенное слово: Spędzam czas z ___. (семьёй)", "Вставте пропущене слово: Spędzam czas z ___. (родиною)", "Fill in the missing word: Spędzam czas z ___. (family)", + "rodziną", "first_letter", "r", 18), + + ("a1_hobbies_free_time_t19", None, "topic_test", "mixed", "hobby_description", 3, + "Wybierz poprawne tłumaczenie: «Я люблю читать книги и часто делаю это вечером».", "Выберите правильный перевод: «Я люблю читать книги и часто делаю это вечером».", "Виберіть правильний переклад: «Я люблю читати книги і часто роблю це ввечері».", "Choose the correct translation: “I like reading books and I often do it in the evening.”", + "A", None, None, 19), + ("a1_hobbies_free_time_t20", None, "topic_test", "mixed", "grac_w_na", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Что ты любишь делать в свободное время? — Я люблю играть в футбол с друзьями.»", "Выберите правильный перевод диалога: «— Что ты любишь делать в свободное время? — Я люблю играть в футбол с друзьями.»", "Виберіть правильний переклад діалогу: «— Що ти любиш робити у вільний час? — Я люблю грати у футбол з друзями.»", "Choose the correct translation of the dialogue: “— What do you like to do in your free time? — I like playing football with friends.”", + "A", None, None, 20), + ] + + for q in test_questions_t12: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_hobbies_free_time', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t12 = [ + ("a1_hobbies_free_time_t01", "A", "pływać", "плавать", "плавати", "to swim", True, None), + ("a1_hobbies_free_time_t01", "B", "tańczyć", "танцевать", "танцювати", "to dance", False, "wrong_word"), + ("a1_hobbies_free_time_t01", "C", "gotować", "готовить", "готувати", "to cook", False, "wrong_word"), + ("a1_hobbies_free_time_t01", "D", "czytać", "читать", "читати", "to read", False, "wrong_word"), + + ("a1_hobbies_free_time_t02", "A", "lubi", "любит", "любить", "likes", True, None), + ("a1_hobbies_free_time_t02", "B", "lubię", "люблю", "люблю", "like (I)", False, "wrong_word"), + ("a1_hobbies_free_time_t02", "C", "lubisz", "любишь", "любиш", "like (you)", False, "wrong_word"), + ("a1_hobbies_free_time_t02", "D", "lubić", "любить (инф.)", "любити (інф.)", "to like", False, "wrong_word"), + + ("a1_hobbies_free_time_t03", "A", "sport", "спорт (вин.)", "спорт (знах.)", "sports (acc.)", True, None), + ("a1_hobbies_free_time_t03", "B", "sportu", "спорта (род.)", "спорту (род.)", "sports (gen.)", False, "wrong_case"), + ("a1_hobbies_free_time_t03", "C", "sportem", "спортом (тв.)", "спортом (ор.)", "sports (instr.)", False, "wrong_case"), + ("a1_hobbies_free_time_t03", "D", "sportowi", "спорту (дат.)", "спорту (дав.)", "sports (dat.)", False, "wrong_case"), + + ("a1_hobbies_free_time_t04", "A", "weekend", "выходные", "вихідні", "weekend", True, None), + ("a1_hobbies_free_time_t04", "B", "wieczór", "вечер", "вечір", "evening", False, "wrong_word"), + ("a1_hobbies_free_time_t04", "C", "sobota", "суббота", "субота", "Saturday", False, "wrong_word"), + ("a1_hobbies_free_time_t04", "D", "czas wolny", "свободное время", "вільний час", "free time", False, "wrong_word"), + + ("a1_hobbies_free_time_t05", "A", "W weekendy tańczę.", "По выходным я танцую.", "У вихідні я танцюю.", "On weekends I dance.", True, None), + ("a1_hobbies_free_time_t05", "B", "Codziennie tańczę.", "Я танцую каждый день.", "Я танцюю щодня.", "I dance every day.", False, "wrong_translation"), + ("a1_hobbies_free_time_t05", "C", "Nigdy nie tańczę.", "Я никогда не танцую.", "Я ніколи не танцюю.", "I never dance.", False, "wrong_translation"), + ("a1_hobbies_free_time_t05", "D", "Czasami czytam.", "Иногда я читаю.", "Іноді я читаю.", "Sometimes I read.", False, "wrong_translation"), + + ("a1_hobbies_free_time_t06", "A", "w", "в", "у", "at", True, None), + ("a1_hobbies_free_time_t06", "B", "na", "на", "на", "on", False, "wrong_word"), + ("a1_hobbies_free_time_t06", "C", "do", "до", "до", "to", False, "wrong_word"), + ("a1_hobbies_free_time_t06", "D", "z", "с", "з", "with", False, "wrong_word"), + + ("a1_hobbies_free_time_t07", "A", "pływać", "плавать", "плавати", "to swim", True, None), + ("a1_hobbies_free_time_t07", "B", "tańczyć", "танцевать", "танцювати", "to dance", False, "wrong_context"), + ("a1_hobbies_free_time_t07", "C", "gotować", "готовить", "готувати", "to cook", False, "wrong_context"), + ("a1_hobbies_free_time_t07", "D", "czytać", "читать", "читати", "to read", False, "wrong_context"), + + ("a1_hobbies_free_time_t08", "A", "Lubię muzykę.", "Я люблю музыку.", "Я люблю музику.", "I like music.", True, None), + ("a1_hobbies_free_time_t08", "B", "Lubię muzyka.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_hobbies_free_time_t08", "C", "Muzyka lubię.", "Неправильный порядок и падеж.", "Неправильний порядок і відмінок.", "Wrong word order and case.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_t08", "D", "Chcę muzykę kupić.", "Неестественная конструкция.", "Неприродна конструкція.", "Unnatural construction.", False, "wrong_context"), + + ("a1_hobbies_free_time_t09", "A", "Najbardziej lubię pływać.", "Больше всего я люблю плавать.", "Найбільше я люблю плавати.", "I like swimming the most.", True, None), + ("a1_hobbies_free_time_t09", "B", "Najbardziej lubię gotować.", "Больше всего я люблю готовить. (неверное хобби)", "Найбільше я люблю готувати. (невірне хобі)", "I like cooking the most. (wrong hobby)", False, "wrong_context"), + ("a1_hobbies_free_time_t09", "C", "Pływam czasami.", "Я иногда плаваю. (не о любимом занятии)", "Я іноді плаваю. (не про улюблене заняття)", "I sometimes swim. (not about a favorite)", False, "wrong_context"), + ("a1_hobbies_free_time_t09", "D", "Nie lubię pływać.", "Я не люблю плавать. (противоречит ситуации)", "Я не люблю плавати. (суперечить ситуації)", "I don't like swimming. (contradicts the situation)", False, "wrong_context"), + + ("a1_hobbies_free_time_t10", "A", "Spędzam czas z rodziną.", "Я провожу время с семьёй.", "Я проводжу час з родиною.", "I spend time with family.", True, None), + ("a1_hobbies_free_time_t10", "B", "Mam rodzinę.", "У меня есть семья. (не о проведении времени)", "У мене є родина. (не про проведення часу)", "I have a family. (not about spending time)", False, "wrong_context"), + ("a1_hobbies_free_time_t10", "C", "Lubię rodzinę.", "Я люблю семью. (не о встрече)", "Я люблю родину. (не про зустріч)", "I like my family. (not about meeting)", False, "wrong_context"), + ("a1_hobbies_free_time_t10", "D", "Szukam rodziny.", "Я ищу семью. (не о встрече)", "Я шукаю родину. (не про зустріч)", "I'm looking for a family. (not about meeting)", False, "wrong_context"), + + ("a1_hobbies_free_time_t11", "A", "Jutro będę czytać książkę.", "Завтра я буду читать книгу.", "Завтра я буду читати книгу.", "Tomorrow I'll read a book.", True, None), + ("a1_hobbies_free_time_t11", "B", "Wczoraj czytałem książkę.", "Вчера я читал книгу. (неверное время)", "Вчора я читав книгу. (невірний час)", "Yesterday I read a book. (wrong tense)", False, "wrong_context"), + ("a1_hobbies_free_time_t11", "C", "Nigdy nie czytam książek.", "Я никогда не читаю книг. (противоречит ситуации)", "Я ніколи не читаю книг. (суперечить ситуації)", "I never read books. (contradicts the situation)", False, "wrong_context"), + ("a1_hobbies_free_time_t11", "D", "Lubię książki.", "Я люблю книги. (не о планах)", "Я люблю книги. (не про плани)", "I like books. (not about plans)", False, "wrong_context"), + + ("a1_hobbies_free_time_t12", "A", "Lubię gotować i często to robię wieczorem.", "Я люблю готовить и часто делаю это вечером.", "Я люблю готувати і часто роблю це ввечері.", "I like cooking and I often do it in the evening.", True, None), + ("a1_hobbies_free_time_t12", "B", "Gotowanie jestem lubię.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_t12", "C", "Gotuję czasami wczoraj.", "Смешение времени.", "Змішування часу.", "Mixed tense.", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_t12", "D", "Chcę kupić gotowanie.", "Бессмысленное сочетание слов.", "Безглузде поєднання слів.", "Nonsensical word combination.", False, "wrong_context"), + + ("a1_hobbies_free_time_t19", "A", "Lubię czytać książki i często to robię wieczorem.", "Я люблю читать книги и часто делаю это вечером.", "Я люблю читати книги і часто роблю це ввечері.", "I like reading books and I often do it in the evening.", True, None), + ("a1_hobbies_free_time_t19", "B", "Lubiłem czytać książki wieczorem.", "Неправильное время (прошедшее вместо настоящего).", "Неправильний час (минулий замість теперішнього).", "Wrong tense (past instead of present).", False, "wrong_sentence_type"), + ("a1_hobbies_free_time_t19", "C", "Lubię gotować książki i często to robię wieczorem.", "Неправильный глагол (бессмысленное сочетание).", "Неправильне дієслово (безглузде поєднання).", "Wrong verb (nonsensical combination).", False, "wrong_word"), + ("a1_hobbies_free_time_t19", "D", "Książki czytać lubię wieczorem często.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + + ("a1_hobbies_free_time_t20", "A", "Co lubisz robić w wolnym czasie? Lubię grać w piłkę nożną z przyjaciółmi.", "Что ты любишь делать в свободное время? Я люблю играть в футбол с друзьями.", "Що ти любиш робити у вільний час? Я люблю грати у футбол з друзями.", "What do you like to do in your free time? I like playing football with friends.", True, None), + ("a1_hobbies_free_time_t20", "B", "Gdzie jest twój wolny czas? Lubię grać w piłkę nożną z przyjaciółmi.", "Неправильный вопрос.", "Неправильне питання.", "Wrong question.", False, "wrong_translation"), + ("a1_hobbies_free_time_t20", "C", "Co lubisz robić w wolnym czasie? Lubię grać na piłce nożnej z przyjaciółmi.", "Неправильный предлог (piłka nożna требует „grać w”).", "Неправильний прийменник (piłka nożna вимагає „grać w”).", "Wrong preposition (piłka nożna needs „grać w”).", False, "wrong_word"), + ("a1_hobbies_free_time_t20", "D", "Co lubisz robić w wolnym czasie? Lubię grać w piłkę nożną sam.", "Не соответствует контексту (речь о друзьях, а не в одиночку).", "Не відповідає контексту (мова про друзів, а не наодинці).", "Doesn't match the context (it's about friends, not alone).", False, "wrong_context"), + ] + + for opt in test_options_t12: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # ==================== ТЕМА 13: ЗДОРОВЬЕ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_health', 'A1', 13, + 'Zdrowie', + 'Здоровье', + 'Здоров''я', + 'Health') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t13 = [ + ("a1_health_l01", 1, "body_parts_vocabulary", "Podstawowe słowa: części ciała", "Основные слова: части тела", "Основні слова: частини тіла", "Basic words: body parts", + "Podstawowe słowa dotyczące ciała: głowa, ręka, noga, brzuch. „Głowa”, „ręka” i „noga” są rodzaju żeńskiego, „brzuch” jest rodzaju męskiego.", + "Основные слова, связанные с телом: głowa (голова), ręka (рука), noga (нога), brzuch (живот). „Głowa”, „ręka” и „noga” женского рода, „brzuch” мужского рода.", + "Основні слова, пов'язані з тілом: głowa (голова), ręka (рука), noga (нога), brzuch (живіт). „Głowa”, „ręka” і „noga” жіночого роду, „brzuch” чоловічого роду.", + "Basic words related to the body: głowa (head), ręka (hand/arm), noga (leg), brzuch (stomach). „Głowa”, „ręka” and „noga” are feminine, „brzuch” is masculine."), + + ("a1_health_l02", 2, "boli_mnie", "Boli mnie + mianownik", "Boli mnie + именительный падеж", "Boli mnie + називний відмінок", "Boli mnie + nominative", + "Konstrukcji „boli mnie” + mianownik używamy, żeby mówić o bólu: boli mnie głowa, boli mnie brzuch, boli mnie noga.", + "Конструкцию „boli mnie” (у меня болит) + именительный падеж используем, чтобы говорить о боли: boli mnie głowa (у меня болит голова), boli mnie brzuch (у меня болит живот), boli mnie noga (у меня болит нога).", + "Конструкцію „boli mnie” (у мене болить) + називний відмінок використовуємо, щоб говорити про біль: boli mnie głowa (у мене болить голова), boli mnie brzuch (у мене болить живіт), boli mnie noga (у мене болить нога).", + "We use the construction „boli mnie” (it hurts me) + nominative to talk about pain: boli mnie głowa (my head hurts), boli mnie brzuch (my stomach hurts), boli mnie noga (my leg hurts)."), + + ("a1_health_l03", 3, "czuc_sie", "Czuję się + przysłówek", "Czuję się + наречие", "Czuję się + прислівник", "Czuję się + adverb", + "Czasownika „czuć się” używamy z przysłówkiem, żeby opisać samopoczucie: czuję się dobrze, czuję się źle, czuję się lepiej.", + "Глагол „czuć się” (чувствовать себя) используем с наречием, чтобы описать самочувствие: czuję się dobrze (я чувствую себя хорошо), czuję się źle (я чувствую себя плохо), czuję się lepiej (я чувствую себя лучше).", + "Дієслово „czuć się” (почуватися) використовуємо з прислівником, щоб описати самопочуття: czuję się dobrze (я почуваюся добре), czuję się źle (я почуваюся погано), czuję się lepiej (я почуваюся краще).", + "The verb „czuć się” (to feel) is used with an adverb to describe how you feel: czuję się dobrze (I feel good), czuję się źle (I feel bad), czuję się lepiej (I feel better)."), + + ("a1_health_l04", 4, "u_lekarza_vocabulary", "Słowa: u lekarza", "Слова: у врача", "Слова: у лікаря", "Words: at the doctor's", + "Podstawowe słowa związane z wizytą u lekarza: lekarz, szpital, apteka, recepta. „Lekarz” i „szpital” są rodzaju męskiego, „apteka” i „recepta” są rodzaju żeńskiego.", + "Основные слова, связанные с визитом к врачу: lekarz (врач), szpital (больница), apteka (аптека), recepta (рецепт). „Lekarz” и „szpital” мужского рода, „apteka” и „recepta” женского рода.", + "Основні слова, пов'язані з візитом до лікаря: lekarz (лікар), szpital (лікарня), apteka (аптека), recepta (рецепт). „Lekarz” і „szpital” чоловічого роду, „apteka” і „recepta” жіночого роду.", + "Basic words related to a doctor's visit: lekarz (doctor), szpital (hospital), apteka (pharmacy), recepta (prescription). „Lekarz” and „szpital” are masculine, „apteka” and „recepta” are feminine."), + + ("a1_health_l05", 5, "objawy_choroby", "Mam + biernik (objawy)", "Mam + винительный падеж (симптомы)", "Mam + знахідний відмінок (симптоми)", "Mam + accusative (symptoms)", + "Żeby opisać objawy choroby, używamy „mam” + biernik: mam kaszel, mam katar, mam gorączkę.", + "Чтобы описать симптомы болезни, используем „mam” (у меня есть) + винительный падеж: mam kaszel (у меня кашель), mam katar (у меня насморк), mam gorączkę (у меня температура).", + "Щоб описати симптоми хвороби, використовуємо „mam” (у мене є) + знахідний відмінок: mam kaszel (у мене кашель), mam katar (у мене нежить), mam gorączkę (у мене температура).", + "To describe symptoms of illness, we use „mam” (I have) + accusative: mam kaszel (I have a cough), mam katar (I have a runny nose), mam gorączkę (I have a fever)."), + + ("a1_health_l06", 6, "brac_leki", "Biorę lekarstwo + biernik", "Biorę lekarstwo + винительный падеж", "Biorę lekarstwo + знахідний відмінок", "Biorę lekarstwo + accusative", + "Czasownik „brać” + biernik: biorę lekarstwo, biorę tabletkę, biorę tabletki.", + "Глагол „brać” (принимать/брать) + винительный падеж: biorę lekarstwo (я принимаю лекарство), biorę tabletkę (я принимаю таблетку), biorę tabletki (я принимаю таблетки).", + "Дієслово „brać” (приймати/брати) + знахідний відмінок: biorę lekarstwo (я приймаю ліки), biorę tabletkę (я приймаю таблетку), biorę tabletki (я приймаю таблетки).", + "The verb „brać” (to take) + accusative: biorę lekarstwo (I take medicine), biorę tabletkę (I take a pill), biorę tabletki (I take pills)."), + + ("a1_health_l07", 7, "musiec_isc_do_lekarza", "Muszę iść do + dopełniacz", "Muszę iść do + родительный падеж", "Muszę iść do + родовий відмінок", "Muszę iść do + genitive", + "Konstrukcja „muszę iść do” + dopełniacz: muszę iść do lekarza, muszę iść do apteki, muszę iść do szpitala.", + "Конструкция „muszę iść do” (мне нужно пойти в/к) + родительный падеж: muszę iść do lekarza (мне нужно пойти к врачу), muszę iść do apteki (мне нужно пойти в аптеку), muszę iść do szpitala (мне нужно пойти в больницу).", + "Конструкція „muszę iść do” (мені треба піти до) + родовий відмінок: muszę iść do lekarza (мені треба піти до лікаря), muszę iść do apteki (мені треба піти в аптеку), muszę iść do szpitala (мені треба піти в лікарню).", + "The construction „muszę iść do” (I have to go to) + genitive: muszę iść do lekarza (I have to go to the doctor), muszę iść do apteki (I have to go to the pharmacy), muszę iść do szpitala (I have to go to the hospital)."), + + ("a1_health_l08", 8, "zdrowy_tryb_zycia", "Zdrowy tryb życia — czasowniki", "Здоровый образ жизни — глаголы", "Здоровий спосіб життя — дієслова", "Healthy lifestyle — verbs", + "Żeby mówić o zdrowym trybie życia, używamy czasowników: zdrowo się odżywiać, uprawiać sport, dużo spać.", + "Чтобы говорить о здоровом образе жизни, используем глаголы: zdrowo się odżywiać (здорово питаться), uprawiać sport (заниматься спортом), dużo spać (много спать).", + "Щоб говорити про здоровий спосіб життя, використовуємо дієслова: zdrowo się odżywiać (здорово харчуватися), uprawiać sport (займатися спортом), dużo spać (багато спати).", + "To talk about a healthy lifestyle, we use verbs: zdrowo się odżywiać (to eat healthily), uprawiać sport (to do sports), dużo spać (to sleep a lot)."), + + ("a1_health_l09", 9, "dawac_rady_zdrowotne", "Powinieneś/powinnaś + bezokolicznik", "Powinieneś/powinnaś + инфинитив", "Powinieneś/powinnaś + інфінітив", "Powinieneś/powinnaś + infinitive", + "Żeby dać radę zdrowotną, używamy „powinieneś” (do mężczyzny) lub „powinnaś” (do kobiety) + bezokolicznik: powinieneś odpoczywać, powinnaś pić dużo wody.", + "Чтобы дать совет о здоровье, используем „powinieneś” (мужчине) или „powinnaś” (женщине) + инфинитив: powinieneś odpoczywać (тебе следует отдохнуть), powinnaś pić dużo wody (тебе следует пить много воды).", + "Щоб дати пораду щодо здоров'я, використовуємо „powinieneś” (чоловіку) або „powinnaś” (жінці) + інфінітив: powinieneś odpoczywać (тобі варто відпочити), powinnaś pić dużo wody (тобі варто пити багато води).", + "To give health advice, we use „powinieneś” (to a man) or „powinnaś” (to a woman) + infinitive: powinieneś odpoczywać (you should rest), powinnaś pić dużo wody (you should drink a lot of water)."), + + ("a1_health_l10", 10, "opisuje_samopoczucie", "Opisuję swoje samopoczucie", "Описываю своё самочувствие", "Описую своє самопочуття", "Describing how I feel", + "Żeby opisać samopoczucie, łączymy kilka zdań: Źle się czuję. Boli mnie głowa. Muszę iść do lekarza.", + "Чтобы описать самочувствие, соединяем несколько предложений: Źle się czuję. Boli mnie głowa. Muszę iść do lekarza. (Я плохо себя чувствую. У меня болит голова. Мне нужно пойти к врачу.)", + "Щоб описати самопочуття, поєднуємо кілька речень: Źle się czuję. Boli mnie głowa. Muszę iść do lekarza. (Я погано почуваюся. У мене болить голова. Мені треба піти до лікаря.)", + "To describe how you feel, we combine several sentences: Źle się czuję. Boli mnie głowa. Muszę iść do lekarza. (I feel bad. My head hurts. I have to go to the doctor.)"), + ] + + for lesson in lessons_t13: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_health', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t13 = [ + ("a1_health_l01", 1, "To jest głowa.", "Это голова.", "Це голова.", "This is a head."), + ("a1_health_l01", 2, "To jest ręka.", "Это рука.", "Це рука.", "This is a hand."), + ("a1_health_l01", 3, "To jest noga.", "Это нога.", "Це нога.", "This is a leg."), + + ("a1_health_l02", 1, "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts."), + ("a1_health_l02", 2, "Boli cię brzuch?", "У тебя болит живот?", "У тебе болить живіт?", "Does your stomach hurt?"), + ("a1_health_l02", 3, "Boli go noga.", "У него болит нога.", "У нього болить нога.", "His leg hurts."), + + ("a1_health_l03", 1, "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good."), + ("a1_health_l03", 2, "Czujesz się źle?", "Ты чувствуешь себя плохо?", "Ти почуваєшся погано?", "Do you feel bad?"), + ("a1_health_l03", 3, "Ona czuje się lepiej.", "Она чувствует себя лучше.", "Вона почувається краще.", "She feels better."), + + ("a1_health_l04", 1, "To jest lekarz.", "Это врач.", "Це лікар.", "This is a doctor."), + ("a1_health_l04", 2, "To jest apteka.", "Это аптека.", "Це аптека.", "This is a pharmacy."), + ("a1_health_l04", 3, "To jest szpital.", "Это больница.", "Це лікарня.", "This is a hospital."), + + ("a1_health_l05", 1, "Mam kaszel.", "У меня кашель.", "У мене кашель.", "I have a cough."), + ("a1_health_l05", 2, "Masz katar?", "У тебя насморк?", "У тебе нежить?", "Do you have a runny nose?"), + ("a1_health_l05", 3, "On ma gorączkę.", "У него температура.", "У нього температура.", "He has a fever."), + + ("a1_health_l06", 1, "Biorę lekarstwo.", "Я принимаю лекарство.", "Я приймаю ліки.", "I'm taking medicine."), + ("a1_health_l06", 2, "Bierzesz tabletkę?", "Ты принимаешь таблетку?", "Ти приймаєш таблетку?", "Are you taking a pill?"), + ("a1_health_l06", 3, "Ona bierze tabletki.", "Она принимает таблетки.", "Вона приймає таблетки.", "She's taking pills."), + + ("a1_health_l07", 1, "Muszę iść do lekarza.", "Мне нужно пойти к врачу.", "Мені треба піти до лікаря.", "I have to go to the doctor."), + ("a1_health_l07", 2, "Musisz iść do apteki.", "Тебе нужно пойти в аптеку.", "Тобі треба піти в аптеку.", "You have to go to the pharmacy."), + ("a1_health_l07", 3, "On musi iść do szpitala.", "Ему нужно пойти в больницу.", "Йому треба піти в лікарню.", "He has to go to the hospital."), + + ("a1_health_l08", 1, "Uprawiam sport.", "Я занимаюсь спортом.", "Я займаюся спортом.", "I do sports."), + ("a1_health_l08", 2, "Zdrowo się odżywiasz?", "Ты здорово питаешься?", "Ти здорово харчуєшся?", "Do you eat healthily?"), + ("a1_health_l08", 3, "Ona dużo śpi.", "Она много спит.", "Вона багато спить.", "She sleeps a lot."), + + ("a1_health_l09", 1, "Powinieneś odpoczywać.", "Тебе следует отдохнуть.", "Тобі варто відпочити.", "You should rest."), + ("a1_health_l09", 2, "Powinnaś pić dużo wody.", "Тебе следует пить много воды.", "Тобі варто пити багато води.", "You should drink a lot of water."), + ("a1_health_l09", 3, "Powinien iść do lekarza.", "Ему следует пойти к врачу.", "Йому варто піти до лікаря.", "He should go to the doctor."), + + ("a1_health_l10", 1, "Źle się czuję.", "Я плохо себя чувствую.", "Я погано почуваюся.", "I feel bad."), + ("a1_health_l10", 2, "Boli mnie głowa i gardło.", "У меня болит голова и горло.", "У мене болить голова і горло.", "My head and throat hurt."), + ("a1_health_l10", 3, "Muszę iść do lekarza.", "Мне нужно пойти к врачу.", "Мені треба піти до лікаря.", "I have to go to the doctor."), + ] + + for ex in examples_t13: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t13 = [ + # L01 — body_parts_vocabulary (diff 1) + ("a1_health_l01_q1", "a1_health_l01", "lesson_practice", "recognition", "body_parts_vocabulary", 1, + "Jak po polsku „рука”?", "Как по-польски «рука»?", "Як польською «рука»?", "How do you say “hand” in Polish?", + "B", None, None), + ("a1_health_l01_q2", "a1_health_l01", "lesson_practice", "production", "body_parts_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (нога)", "Вставьте пропущенное слово: To jest ___. (нога)", "Вставте пропущене слово: To jest ___. (нога)", "Fill in the missing word: To jest ___. (leg)", + "noga", "first_letter", "n"), + ("a1_health_l01_q3", "a1_health_l01", "lesson_practice", "application", "body_parts_vocabulary", 1, + "Zakładasz czapkę na zimno. Na jaką część ciała ją zakładasz?", "Ты надеваешь шапку от холода. На какую часть тела ты её надеваешь?", "Ти надягаєш шапку від холоду. На яку частину тіла ти її надягаєш?", "You put on a hat because it's cold. Which body part do you put it on?", + "D", None, None), + + # L02 — boli_mnie (diff 1) + ("a1_health_l02_q1", "a1_health_l02", "lesson_practice", "recognition", "boli_mnie", 1, + "Wybierz poprawną formę: ___ mnie głowa. (boleć)", "Выберите правильную форму: ___ mnie głowa. (boleć)", "Виберіть правильну форму: ___ mnie głowa. (boleć)", "Choose the correct form: ___ mnie głowa. (boleć)", + "C", None, None), + ("a1_health_l02_q2", "a1_health_l02", "lesson_practice", "production", "boli_mnie", 1, + "Wpisz brakujące słowo: Boli mnie ___. (живот)", "Вставьте пропущенное слово: Boli mnie ___. (живот)", "Вставте пропущене слово: Boli mnie ___. (живіт)", "Fill in the missing word: Boli mnie ___. (stomach)", + "brzuch", "first_letter", "b"), + ("a1_health_l02_q3", "a1_health_l02", "lesson_practice", "application", "boli_mnie", 1, + "Zjadłeś za dużo i czujesz ból. Co powiesz?", "Ты съел слишком много и чувствуешь боль. Что ты скажешь?", "Ти з'їв забагато і відчуваєш біль. Що ти скажеш?", "You ate too much and feel pain. What do you say?", + "B", None, None), + + # L03 — czuc_sie (diff 1) + ("a1_health_l03_q1", "a1_health_l03", "lesson_practice", "recognition", "czuc_sie", 1, + "Wybierz poprawną formę: Ja ___ się dobrze. (czuć)", "Выберите правильную форму: Ja ___ się dobrze. (czuć)", "Виберіть правильну форму: Ja ___ się dobrze. (czuć)", "Choose the correct form: Ja ___ się dobrze. (czuć)", + "D", None, None), + ("a1_health_l03_q2", "a1_health_l03", "lesson_practice", "production", "czuc_sie", 1, + "Wpisz brakujące słowo: Ty ___ się źle? (чувствуешь)", "Вставьте пропущенное слово: Ty ___ się źle? (чувствуешь)", "Вставте пропущене слово: Ty ___ się źle? (почуваєшся)", "Fill in the missing word: Ty ___ się źle? (do you feel)", + "czujesz", "first_letter", "c"), + ("a1_health_l03_q3", "a1_health_l03", "lesson_practice", "application", "czuc_sie", 1, + "Kolega pyta, jak się czujesz. Czujesz się lepiej niż wczoraj. Co powiesz?", "Друг спрашивает, как ты себя чувствуешь. Ты чувствуешь себя лучше, чем вчера. Что ты скажешь?", "Друг питає, як ти почуваєшся. Ти почуваєшся краще, ніж учора. Що ти скажеш?", "A friend asks how you feel. You feel better than yesterday. What do you say?", + "A", None, None), + + # L04 — u_lekarza_vocabulary (diff 1) + ("a1_health_l04_q1", "a1_health_l04", "lesson_practice", "recognition", "u_lekarza_vocabulary", 1, + "Jak po polsku „аптека”?", "Как по-польски «аптека»?", "Як польською «аптека»?", "How do you say “pharmacy” in Polish?", + "C", None, None), + ("a1_health_l04_q2", "a1_health_l04", "lesson_practice", "production", "u_lekarza_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (больница)", "Вставьте пропущенное слово: To jest ___. (больница)", "Вставте пропущене слово: To jest ___. (лікарня)", "Fill in the missing word: To jest ___. (hospital)", + "szpital", "first_letter", "s"), + ("a1_health_l04_q3", "a1_health_l04", "lesson_practice", "application", "u_lekarza_vocabulary", 1, + "Potrzebujesz kupić lekarstwo. Dokąd idziesz?", "Тебе нужно купить лекарство. Куда ты идёшь?", "Тобі треба купити ліки. Куди ти йдеш?", "You need to buy medicine. Where do you go?", + "B", None, None), + + # L05 — objawy_choroby (diff 2) + ("a1_health_l05_q1", "a1_health_l05", "lesson_practice", "recognition", "objawy_choroby", 2, + "Wybierz poprawną formę: Mam ___. (gorączka)", "Выберите правильную форму: Mam ___. (gorączka)", "Виберіть правильну форму: Mam ___. (gorączka)", "Choose the correct form: Mam ___. (gorączka)", + "D", None, None), + ("a1_health_l05_q2", "a1_health_l05", "lesson_practice", "production", "objawy_choroby", 2, + "Wpisz brakujące słowo: Mam ___. (кашель)", "Вставьте пропущенное слово: Mam ___. (кашель)", "Вставте пропущене слово: Mam ___. (кашель)", "Fill in the missing word: Mam ___. (cough)", + "kaszel", "first_letter", "k"), + ("a1_health_l05_q3", "a1_health_l05", "lesson_practice", "application", "objawy_choroby", 2, + "Masz katar i kaszlesz. Co powiesz lekarzowi?", "У тебя насморк и ты кашляешь. Что ты скажешь врачу?", "У тебе нежить і ти кашляєш. Що ти скажеш лікарю?", "You have a runny nose and are coughing. What do you tell the doctor?", + "A", None, None), + + # L06 — brac_leki (diff 2) + ("a1_health_l06_q1", "a1_health_l06", "lesson_practice", "recognition", "brac_leki", 2, + "Wybierz poprawną formę: Biorę ___. (tabletka)", "Выберите правильную форму: Biorę ___. (tabletka)", "Виберіть правильну форму: Biorę ___. (tabletka)", "Choose the correct form: Biorę ___. (tabletka)", + "C", None, None), + ("a1_health_l06_q2", "a1_health_l06", "lesson_practice", "production", "brac_leki", 2, + "Wpisz brakujące słowo: Biorę ___. (лекарство)", "Вставьте пропущенное слово: Biorę ___. (лекарство)", "Вставте пропущене слово: Biorę ___. (ліки)", "Fill in the missing word: Biorę ___. (medicine)", + "lekarstwo", "first_letter", "l"), + ("a1_health_l06_q3", "a1_health_l06", "lesson_practice", "application", "brac_leki", 2, + "Lekarz mówi, żebyś brał tabletki dwa razy dziennie. Co robisz rano?", "Врач говорит, чтобы ты принимал таблетки два раза в день. Что ты делаешь утром?", "Лікар каже, щоб ти приймав таблетки двічі на день. Що ти робиш вранці?", "The doctor says to take pills twice a day. What do you do in the morning?", + "B", None, None), + + # L07 — musiec_isc_do_lekarza (diff 2) + ("a1_health_l07_q1", "a1_health_l07", "lesson_practice", "recognition", "musiec_isc_do_lekarza", 2, + "Wybierz poprawną formę: Muszę iść do ___. (lekarz)", "Выберите правильную форму: Muszę iść do ___. (lekarz)", "Виберіть правильну форму: Muszę iść do ___. (lekarz)", "Choose the correct form: Muszę iść do ___. (lekarz)", + "D", None, None), + ("a1_health_l07_q2", "a1_health_l07", "lesson_practice", "production", "musiec_isc_do_lekarza", 2, + "Wpisz brakujące słowo: Muszę iść do ___. (аптеки)", "Вставьте пропущенное слово: Muszę iść do ___. (аптеки)", "Вставте пропущене слово: Muszę iść do ___. (аптеки)", "Fill in the missing word: Muszę iść do ___. (the pharmacy)", + "apteki", "first_letter", "a"), + ("a1_health_l07_q3", "a1_health_l07", "lesson_practice", "application", "musiec_isc_do_lekarza", 2, + "Masz gorączkę i kaszel. Co powiesz?", "У тебя температура и кашель. Что ты скажешь?", "У тебе температура і кашель. Що ти скажеш?", "You have a fever and a cough. What do you say?", + "C", None, None), + + # L08 — zdrowy_tryb_zycia (diff 2) + ("a1_health_l08_q1", "a1_health_l08", "lesson_practice", "recognition", "zdrowy_tryb_zycia", 2, + "Wybierz poprawną formę: On ___ sport. (uprawiać)", "Выберите правильную форму: On ___ sport. (uprawiać)", "Виберіть правильну форму: On ___ sport. (uprawiać)", "Choose the correct form: On ___ sport. (uprawiać)", + "A", None, None), + ("a1_health_l08_q2", "a1_health_l08", "lesson_practice", "production", "zdrowy_tryb_zycia", 2, + "Wpisz brakujące słowo: Ona dużo ___. (спит)", "Вставьте пропущенное слово: Ona dużo ___. (спит)", "Вставте пропущене слово: Ona dużo ___. (спить)", "Fill in the missing word: Ona dużo ___. (sleeps)", + "śpi", "first_letter", "ś"), + ("a1_health_l08_q3", "a1_health_l08", "lesson_practice", "application", "zdrowy_tryb_zycia", 2, + "Chcesz być zdrowy i mieć dużo energii. Co robisz codziennie?", "Ты хочешь быть здоровым и иметь много энергии. Что ты делаешь каждый день?", "Ти хочеш бути здоровим і мати багато енергії. Що ти робиш щодня?", "You want to be healthy and have a lot of energy. What do you do every day?", + "D", None, None), + + # L09 — dawac_rady_zdrowotne (diff 3) + ("a1_health_l09_q1", "a1_health_l09", "lesson_practice", "recognition", "dawac_rady_zdrowotne", 3, + "Co znaczy „Powinieneś iść do lekarza”?", "Что означает «Powinieneś iść do lekarza»?", "Що означає «Powinieneś iść do lekarza»?", "What does “Powinieneś iść do lekarza” mean?", + "C", None, None), + ("a1_health_l09_q2", "a1_health_l09", "lesson_practice", "production", "dawac_rady_zdrowotne", 3, + "Wpisz brakujące słowo: ___ pić dużo wody. (тебе следует, к женщине)", "Вставьте пропущенное слово: ___ pić dużo wody. (тебе следует, к женщине)", "Вставте пропущене слово: ___ pić dużo wody. (тобі варто, до жінки)", "Fill in the missing word: ___ pić dużo wody. (you should, to a woman)", + "Powinnaś", "first_letter", "P"), + ("a1_health_l09_q3", "a1_health_l09", "lesson_practice", "application", "dawac_rady_zdrowotne", 3, + "Twoja koleżanka źle się czuje i ma gorączkę. Jaką radę jej dasz?", "Твоя подруга плохо себя чувствует и у неё температура. Какой совет ты ей дашь?", "Твоя подруга погано почувається і в неї температура. Яку пораду ти їй даси?", "Your friend feels bad and has a fever. What advice do you give her?", + "B", None, None), + + # L10 — opisuje_samopoczucie (diff 3) + ("a1_health_l10_q1", "a1_health_l10", "lesson_practice", "recognition", "opisuje_samopoczucie", 3, + "Które zdanie poprawnie opisuje samopoczucie?", "Какое предложение правильно описывает самочувствие?", "Яке речення правильно описує самопочуття?", "Which sentence correctly describes how someone feels?", + "D", None, None), + ("a1_health_l10_q2", "a1_health_l10", "lesson_practice", "production", "opisuje_samopoczucie", 3, + "Przetłumacz: «Мне нужно пойти к врачу».", "Переведите: «Мне нужно пойти к врачу».", "Перекладіть: «Мені потрібно піти до лікаря».", "Translate: “I have to go to the doctor.”", + "Muszę iść do lekarza", "first_letter", "M"), + ("a1_health_l10_q3", "a1_health_l10", "lesson_practice", "application", "opisuje_samopoczucie", 3, + "Chcesz opisać koledze swoje samopoczucie: źle się czujesz, boli cię głowa, musisz iść do lekarza. Jak zaczniesz zdanie?", "Ты хочешь описать другу своё самочувствие: ты плохо себя чувствуешь, у тебя болит голова, тебе нужно пойти к врачу. Как ты начнёшь предложение?", "Ти хочеш описати другу своє самопочуття: ти погано почуваєшся, у тебе болить голова, тобі треба піти до лікаря. Як ти почнеш речення?", "You want to describe how you feel to a friend: you feel bad, your head hurts, you have to go to the doctor. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t13: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_health', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t13 = [ + # L01 + ("a1_health_l01_q1", "A", "noga", "нога", "нога", "leg", False, "wrong_word"), + ("a1_health_l01_q1", "B", "ręka", "рука", "рука", "hand", True, None), + ("a1_health_l01_q1", "C", "głowa", "голова", "голова", "head", False, "wrong_word"), + ("a1_health_l01_q1", "D", "brzuch", "живот", "живіт", "stomach", False, "wrong_word"), + + ("a1_health_l01_q3", "A", "ręka", "рука", "рука", "hand", False, "wrong_context"), + ("a1_health_l01_q3", "B", "noga", "нога", "нога", "leg", False, "wrong_context"), + ("a1_health_l01_q3", "C", "brzuch", "живот", "живіт", "stomach", False, "wrong_context"), + ("a1_health_l01_q3", "D", "głowa", "голова", "голова", "head", True, None), + + # L02 + ("a1_health_l02_q1", "A", "Bolę", "неправильная форма", "неправильна форма", "wrong form", False, "wrong_word"), + ("a1_health_l02_q1", "B", "Bolisz", "болишь", "болиш", "you hurt", False, "wrong_word"), + ("a1_health_l02_q1", "C", "Boli", "болит", "болить", "hurts", True, None), + ("a1_health_l02_q1", "D", "Boleć", "болеть (инф.)", "боліти (інф.)", "to hurt", False, "wrong_word"), + + ("a1_health_l02_q3", "A", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", False, "wrong_context"), + ("a1_health_l02_q3", "B", "Boli mnie brzuch.", "У меня болит живот.", "У мене болить живіт.", "My stomach hurts.", True, None), + ("a1_health_l02_q3", "C", "Mam gorączkę.", "У меня температура.", "У мене температура.", "I have a fever.", False, "wrong_context"), + ("a1_health_l02_q3", "D", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", False, "wrong_context"), + + # L03 + ("a1_health_l03_q1", "A", "czujesz", "чувствуешь", "почуваєшся", "feel (you)", False, "wrong_word"), + ("a1_health_l03_q1", "B", "czuje", "чувствует", "почувається", "feels", False, "wrong_word"), + ("a1_health_l03_q1", "C", "czuć", "чувствовать (инф.)", "почуватися (інф.)", "to feel", False, "wrong_word"), + ("a1_health_l03_q1", "D", "czuję", "чувствую", "почуваюся", "feel (I)", True, None), + + ("a1_health_l03_q3", "A", "Czuję się lepiej.", "Я чувствую себя лучше.", "Я почуваюся краще.", "I feel better.", True, None), + ("a1_health_l03_q3", "B", "Czuję się źle.", "Я чувствую себя плохо.", "Я почуваюся погано.", "I feel bad.", False, "wrong_context"), + ("a1_health_l03_q3", "C", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", False, "wrong_context"), + ("a1_health_l03_q3", "D", "Muszę iść do lekarza.", "Мне нужно пойти к врачу.", "Мені треба піти до лікаря.", "I have to go to the doctor.", False, "wrong_context"), + + # L04 + ("a1_health_l04_q1", "A", "lekarz", "врач", "лікар", "doctor", False, "wrong_word"), + ("a1_health_l04_q1", "B", "szpital", "больница", "лікарня", "hospital", False, "wrong_word"), + ("a1_health_l04_q1", "C", "apteka", "аптека", "аптека", "pharmacy", True, None), + ("a1_health_l04_q1", "D", "recepta", "рецепт", "рецепт", "prescription", False, "wrong_word"), + + ("a1_health_l04_q3", "A", "szpital", "больница", "лікарня", "hospital", False, "wrong_context"), + ("a1_health_l04_q3", "B", "apteka", "аптека", "аптека", "pharmacy", True, None), + ("a1_health_l04_q3", "C", "lekarz", "врач", "лікар", "doctor", False, "wrong_context"), + ("a1_health_l04_q3", "D", "recepta", "рецепт", "рецепт", "prescription", False, "wrong_context"), + + # L05 + ("a1_health_l05_q1", "A", "gorączka", "температура (им.)", "температура (наз.)", "fever (nom.)", False, "wrong_case"), + ("a1_health_l05_q1", "B", "gorączki", "температуры (род.)", "температури (род.)", "fever (gen.)", False, "wrong_case"), + ("a1_health_l05_q1", "C", "gorączką", "температурой (тв.)", "температурою (ор.)", "fever (instr.)", False, "wrong_case"), + ("a1_health_l05_q1", "D", "gorączkę", "температуру (вин.)", "температуру (знах.)", "fever (acc.)", True, None), + + ("a1_health_l05_q3", "A", "Mam katar i kaszel.", "У меня насморк и кашель.", "У мене нежить і кашель.", "I have a runny nose and a cough.", True, None), + ("a1_health_l05_q3", "B", "Mam gorączkę i kaszel.", "У меня температура и кашель.", "У мене температура і кашель.", "I have a fever and a cough.", False, "wrong_context"), + ("a1_health_l05_q3", "C", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", False, "wrong_context"), + ("a1_health_l05_q3", "D", "Muszę iść do apteki.", "Мне нужно пойти в аптеку.", "Мені треба піти в аптеку.", "I have to go to the pharmacy.", False, "wrong_context"), + + # L06 + ("a1_health_l06_q1", "A", "tabletka", "таблетка (им.)", "таблетка (наз.)", "pill (nom.)", False, "wrong_case"), + ("a1_health_l06_q1", "B", "tabletki", "таблетки (мн./род.)", "таблетки (мн./род.)", "pills (pl./gen.)", False, "wrong_case"), + ("a1_health_l06_q1", "C", "tabletkę", "таблетку (вин.)", "таблетку (знах.)", "pill (acc.)", True, None), + ("a1_health_l06_q1", "D", "tabletką", "таблеткой (тв.)", "таблеткою (ор.)", "pill (instr.)", False, "wrong_case"), + + ("a1_health_l06_q3", "A", "Biorę lekarstwo wczoraj.", "Неправильное время.", "Неправильний час.", "Wrong tense.", False, "wrong_sentence_type"), + ("a1_health_l06_q3", "B", "Biorę tabletkę.", "Я принимаю таблетку.", "Я приймаю таблетку.", "I take a pill.", True, None), + ("a1_health_l06_q3", "C", "Sprzedaję tabletkę.", "Я продаю таблетку.", "Я продаю таблетку.", "I'm selling a pill.", False, "wrong_context"), + ("a1_health_l06_q3", "D", "Mam tabletkę.", "У меня есть таблетка.", "У мене є таблетка.", "I have a pill.", False, "wrong_context"), + + # L07 + ("a1_health_l07_q1", "A", "lekarz", "врач (им.)", "лікар (наз.)", "doctor (nom.)", False, "wrong_case"), + ("a1_health_l07_q1", "B", "lekarzem", "врачом (тв.)", "лікарем (ор.)", "doctor (instr.)", False, "wrong_case"), + ("a1_health_l07_q1", "C", "lekarzowi", "врачу (дат.)", "лікарю (дав.)", "doctor (dat.)", False, "wrong_case"), + ("a1_health_l07_q1", "D", "lekarza", "врача (род.)", "лікаря (род.)", "doctor (gen.)", True, None), + + ("a1_health_l07_q3", "A", "Muszę iść do apteki.", "Мне нужно пойти в аптеку.", "Мені треба піти в аптеку.", "I have to go to the pharmacy.", False, "wrong_context"), + ("a1_health_l07_q3", "B", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", False, "wrong_context"), + ("a1_health_l07_q3", "C", "Muszę iść do lekarza.", "Мне нужно пойти к врачу.", "Мені треба піти до лікаря.", "I have to go to the doctor.", True, None), + ("a1_health_l07_q3", "D", "Uprawiam sport.", "Я занимаюсь спортом.", "Я займаюся спортом.", "I do sports.", False, "wrong_context"), + + # L08 + ("a1_health_l08_q1", "A", "uprawia", "занимается", "займається", "does (sports)", True, None), + ("a1_health_l08_q1", "B", "uprawiam", "занимаюсь", "займаюся", "I do", False, "wrong_word"), + ("a1_health_l08_q1", "C", "uprawiasz", "занимаешься", "займаєшся", "you do", False, "wrong_word"), + ("a1_health_l08_q1", "D", "uprawiać", "заниматься (инф.)", "займатися (інф.)", "to do", False, "wrong_word"), + + ("a1_health_l08_q3", "A", "Biorę lekarstwo.", "Я принимаю лекарство.", "Я приймаю ліки.", "I take medicine.", False, "wrong_context"), + ("a1_health_l08_q3", "B", "Idę do szpitala.", "Я иду в больницу.", "Я йду в лікарню.", "I go to the hospital.", False, "wrong_context"), + ("a1_health_l08_q3", "C", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", False, "wrong_context"), + ("a1_health_l08_q3", "D", "Uprawiam sport.", "Я занимаюсь спортом.", "Я займаюся спортом.", "I do sports.", True, None), + + # L09 + ("a1_health_l09_q1", "A", "Chcesz iść do lekarza.", "Ты хочешь пойти к врачу.", "Ти хочеш піти до лікаря.", "You want to go to the doctor.", False, "wrong_translation"), + ("a1_health_l09_q1", "B", "Musisz iść do apteki.", "Тебе нужно пойти в аптеку.", "Тобі треба піти в аптеку.", "You have to go to the pharmacy.", False, "wrong_translation"), + ("a1_health_l09_q1", "C", "Powinieneś iść do lekarza.", "Тебе следует пойти к врачу.", "Тобі варто піти до лікаря.", "You should go to the doctor.", True, None), + ("a1_health_l09_q1", "D", "Idziesz do lekarza.", "Ты идёшь к врачу.", "Ти йдеш до лікаря.", "You're going to the doctor.", False, "wrong_translation"), + + ("a1_health_l09_q3", "A", "Powinnaś iść do szkoły.", "Тебе следует пойти в школу.", "Тобі варто піти до школи.", "You should go to school.", False, "wrong_context"), + ("a1_health_l09_q3", "B", "Powinnaś iść do lekarza.", "Тебе следует пойти к врачу.", "Тобі варто піти до лікаря.", "You should go to the doctor.", True, None), + ("a1_health_l09_q3", "C", "Musisz uprawiać sport.", "Тебе нужно заниматься спортом.", "Тобі треба займатися спортом.", "You have to do sports.", False, "wrong_context"), + ("a1_health_l09_q3", "D", "Czujesz się dobrze.", "Ты чувствуешь себя хорошо.", "Ти почуваєшся добре.", "You feel good.", False, "wrong_context"), + + # L10 + ("a1_health_l10_q1", "A", "Źle się czuć i boli ja głowa.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_health_l10_q1", "B", "Źle jestem czuć głowa.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_health_l10_q1", "C", "Dobrze uprawiam lekarza.", "Бессмысленное сочетание слов.", "Безглузде поєднання слів.", "Nonsensical word combination.", False, "wrong_context"), + ("a1_health_l10_q1", "D", "Źle się czuję i boli mnie głowa.", "Я плохо себя чувствую, и у меня болит голова.", "Я погано почуваюся, і у мене болить голова.", "I feel bad and my head hurts.", True, None), + + ("a1_health_l10_q3", "A", "Źle się czuję.", "Я плохо себя чувствую.", "Я погано почуваюся.", "I feel bad.", True, None), + ("a1_health_l10_q3", "B", "Dobrze się czuję.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", False, "wrong_context"), + ("a1_health_l10_q3", "C", "Uprawiam sport.", "Я занимаюсь спортом.", "Я займаюся спортом.", "I do sports.", False, "wrong_context"), + ("a1_health_l10_q3", "D", "Jestem lekarzem.", "Я врач.", "Я лікар.", "I am a doctor.", False, "wrong_context"), + ] + + for opt in options_t13: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t13 = [ + ("a1_health_t01", None, "topic_test", "recognition", "body_parts_vocabulary", 1, + "Jak po polsku „рука”?", "Как по-польски «рука»?", "Як польською «рука»?", "How do you say “hand” in Polish?", + "B", None, None, 1), + ("a1_health_t02", None, "topic_test", "recognition", "boli_mnie", 1, + "Wybierz poprawną formę: ___ mnie głowa. (boleć)", "Выберите правильную форму: ___ mnie głowa. (boleć)", "Виберіть правильну форму: ___ mnie głowa. (boleć)", "Choose the correct form: ___ mnie głowa. (boleć)", + "C", None, None, 2), + ("a1_health_t03", None, "topic_test", "recognition", "czuc_sie", 1, + "Wybierz poprawną formę: Ja ___ się dobrze. (czuć)", "Выберите правильную форму: Ja ___ się dobrze. (czuć)", "Виберіть правильну форму: Ja ___ się dobrze. (czuć)", "Choose the correct form: Ja ___ się dobrze. (czuć)", + "D", None, None, 3), + ("a1_health_t04", None, "topic_test", "recognition", "u_lekarza_vocabulary", 1, + "Jak po polsku „аптека”?", "Как по-польски «аптека»?", "Як польською «аптека»?", "How do you say “pharmacy” in Polish?", + "A", None, None, 4), + ("a1_health_t05", None, "topic_test", "recognition", "objawy_choroby", 2, + "Wybierz poprawną formę: Mam ___. (gorączka)", "Выберите правильную форму: Mam ___. (gorączka)", "Виберіть правильну форму: Mam ___. (gorączka)", "Choose the correct form: Mam ___. (gorączka)", + "B", None, None, 5), + ("a1_health_t06", None, "topic_test", "recognition", "dawac_rady_zdrowotne", 3, + "Co znaczy „Powinieneś iść do lekarza”?", "Что означает «Powinieneś iść do lekarza»?", "Що означає «Powinieneś iść do lekarza»?", "What does “Powinieneś iść do lekarza” mean?", + "C", None, None, 6), + + ("a1_health_t07", None, "topic_test", "application", "body_parts_vocabulary", 1, + "Zakładasz czapkę na zimno. Na jaką część ciała ją zakładasz?", "Ты надеваешь шапку от холода. На какую часть тела ты её надеваешь?", "Ти надягаєш шапку від холоду. На яку частину тіла ти її надягаєш?", "You put on a hat because it's cold. Which body part do you put it on?", + "D", None, None, 7), + ("a1_health_t08", None, "topic_test", "application", "boli_mnie", 1, + "Zjadłeś za dużo i czujesz ból. Co powiesz?", "Ты съел слишком много и чувствуешь боль. Что ты скажешь?", "Ти з'їв забагато і відчуваєш біль. Що ти скажеш?", "You ate too much and feel pain. What do you say?", + "A", None, None, 8), + ("a1_health_t09", None, "topic_test", "application", "czuc_sie", 1, + "Kolega pyta, jak się czujesz. Czujesz się lepiej niż wczoraj. Co powiesz?", "Друг спрашивает, как ты себя чувствуешь. Ты чувствуешь себя лучше, чем вчера. Что ты скажешь?", "Друг питає, як ти почуваєшся. Ти почуваєшся краще, ніж учора. Що ти скажеш?", "A friend asks how you feel. You feel better than yesterday. What do you say?", + "B", None, None, 9), + ("a1_health_t10", None, "topic_test", "application", "brac_leki", 2, + "Lekarz mówi, żebyś brał tabletki dwa razy dziennie. Co robisz rano?", "Врач говорит, чтобы ты принимал таблетки два раза в день. Что ты делаешь утром?", "Лікар каже, щоб ти приймав таблетки двічі на день. Що ти робиш вранці?", "The doctor says to take pills twice a day. What do you do in the morning?", + "C", None, None, 10), + ("a1_health_t11", None, "topic_test", "application", "musiec_isc_do_lekarza", 2, + "Masz gorączkę i kaszel. Co powiesz?", "У тебя температура и кашель. Что ты скажешь?", "У тебе температура і кашель. Що ти скажеш?", "You have a fever and a cough. What do you say?", + "D", None, None, 11), + ("a1_health_t12", None, "topic_test", "application", "dawac_rady_zdrowotne", 3, + "Twoja koleżanka źle się czuje i ma gorączkę. Jaką radę jej dasz?", "Твоя подруга плохо себя чувствует и у неё температура. Какой совет ты ей дашь?", "Твоя подруга погано почувається і в неї температура. Яку пораду ти їй даси?", "Your friend feels bad and has a fever. What advice do you give her?", + "A", None, None, 12), + + ("a1_health_t13", None, "topic_test", "production", "body_parts_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (нога)", "Вставьте пропущенное слово: To jest ___. (нога)", "Вставте пропущене слово: To jest ___. (нога)", "Fill in the missing word: To jest ___. (leg)", + "noga", "first_letter", "n", 13), + ("a1_health_t14", None, "topic_test", "production", "u_lekarza_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (больница)", "Вставьте пропущенное слово: To jest ___. (больница)", "Вставте пропущене слово: To jest ___. (лікарня)", "Fill in the missing word: To jest ___. (hospital)", + "szpital", "first_letter", "s", 14), + ("a1_health_t15", None, "topic_test", "production", "objawy_choroby", 2, + "Wpisz brakujące słowo: Mam ___. (кашель)", "Вставьте пропущенное слово: Mam ___. (кашель)", "Вставте пропущене слово: Mam ___. (кашель)", "Fill in the missing word: Mam ___. (cough)", + "kaszel", "first_letter", "k", 15), + ("a1_health_t16", None, "topic_test", "production", "brac_leki", 2, + "Wpisz brakujące słowo: Biorę ___. (лекарство)", "Вставьте пропущенное слово: Biorę ___. (лекарство)", "Вставте пропущене слово: Biorę ___. (ліки)", "Fill in the missing word: Biorę ___. (medicine)", + "lekarstwo", "first_letter", "l", 16), + ("a1_health_t17", None, "topic_test", "production", "musiec_isc_do_lekarza", 2, + "Wpisz brakujące słowo: Muszę iść do ___. (аптеки)", "Вставьте пропущенное слово: Muszę iść do ___. (аптеки)", "Вставте пропущене слово: Muszę iść do ___. (аптеки)", "Fill in the missing word: Muszę iść do ___. (the pharmacy)", + "apteki", "first_letter", "a", 17), + ("a1_health_t18", None, "topic_test", "production", "opisuje_samopoczucie", 3, + "Przetłumacz: «Мне нужно пойти к врачу».", "Переведите: «Мне нужно пойти к врачу».", "Перекладіть: «Мені потрібно піти до лікаря».", "Translate: “I have to go to the doctor.”", + "Muszę iść do lekarza", "first_letter", "M", 18), + + ("a1_health_t19", None, "topic_test", "recognition", "opisuje_samopoczucie", 3, + "Wybierz poprawne tłumaczenie: «Я плохо себя чувствую, у меня болит голова и мне нужно пойти к врачу».", "Выберите правильный перевод: «Я плохо себя чувствую, у меня болит голова и мне нужно пойти к врачу».", "Виберіть правильний переклад: «Я погано почуваюся, у мене болить голова і мені треба піти до лікаря».", "Choose the correct translation: “I feel bad, my head hurts and I have to go to the doctor.”", + "B", None, None, 19), + ("a1_health_t20", None, "topic_test", "recognition", "dawac_rady_zdrowotne", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Как ты себя чувствуешь? — Я чувствую себя плохо, у меня температура. — Ты должен пойти к врачу.»", "Выберите правильный перевод диалога: «— Как ты себя чувствуешь? — Я чувствую себя плохо, у меня температура. — Ты должен пойти к врачу.»", "Виберіть правильний переклад діалогу: «— Як ти почуваєшся? — Я почуваюся погано, у мене температура. — Ти маєш піти до лікаря.»", "Choose the correct translation of the dialogue: “— How do you feel? — I feel bad, I have a fever. — You should go to the doctor.”", + "C", None, None, 20), + ] + + for q in test_questions_t13: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_health', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t13 = [ + # t01 — правильный B=ręka + ("a1_health_t01", "A", "noga", "нога", "нога", "leg", False, "wrong_word"), + ("a1_health_t01", "B", "ręka", "рука", "рука", "hand", True, None), + ("a1_health_t01", "C", "głowa", "голова", "голова", "head", False, "wrong_word"), + ("a1_health_t01", "D", "brzuch", "живот", "живіт", "stomach", False, "wrong_word"), + + # t02 — правильный C=Boli + ("a1_health_t02", "A", "Bolę", "неправильная форма", "неправильна форма", "wrong form", False, "wrong_word"), + ("a1_health_t02", "B", "Bolisz", "болишь", "болиш", "you hurt", False, "wrong_word"), + ("a1_health_t02", "C", "Boli", "болит", "болить", "hurts", True, None), + ("a1_health_t02", "D", "Boleć", "болеть (инф.)", "боліти (інф.)", "to hurt", False, "wrong_word"), + + # t03 — правильный D=czuję + ("a1_health_t03", "A", "czujesz", "чувствуешь", "почуваєшся", "feel (you)", False, "wrong_word"), + ("a1_health_t03", "B", "czuje", "чувствует", "почувається", "feels", False, "wrong_word"), + ("a1_health_t03", "C", "czuć", "чувствовать (инф.)", "почуватися (інф.)", "to feel", False, "wrong_word"), + ("a1_health_t03", "D", "czuję", "чувствую", "почуваюся", "feel (I)", True, None), + + # t04 — правильный A=apteka + ("a1_health_t04", "A", "apteka", "аптека", "аптека", "pharmacy", True, None), + ("a1_health_t04", "B", "lekarz", "врач", "лікар", "doctor", False, "wrong_word"), + ("a1_health_t04", "C", "szpital", "больница", "лікарня", "hospital", False, "wrong_word"), + ("a1_health_t04", "D", "recepta", "рецепт", "рецепт", "prescription", False, "wrong_word"), + + # t05 — правильный B=gorączkę + ("a1_health_t05", "A", "gorączka", "температура (им.)", "температура (наз.)", "fever (nom.)", False, "wrong_case"), + ("a1_health_t05", "B", "gorączkę", "температуру (вин.)", "температуру (знах.)", "fever (acc.)", True, None), + ("a1_health_t05", "C", "gorączki", "температуры (род.)", "температури (род.)", "fever (gen.)", False, "wrong_case"), + ("a1_health_t05", "D", "gorączką", "температурой (тв.)", "температурою (ор.)", "fever (instr.)", False, "wrong_case"), + + # t06 — правильный C=Powinieneś iść do lekarza + ("a1_health_t06", "A", "Chcesz iść do lekarza.", "Ты хочешь пойти к врачу.", "Ти хочеш піти до лікаря.", "You want to go to the doctor.", False, "wrong_translation"), + ("a1_health_t06", "B", "Musisz iść do apteki.", "Тебе нужно пойти в аптеку.", "Тобі треба піти в аптеку.", "You have to go to the pharmacy.", False, "wrong_translation"), + ("a1_health_t06", "C", "Powinieneś iść do lekarza.", "Тебе следует пойти к врачу.", "Тобі варто піти до лікаря.", "You should go to the doctor.", True, None), + ("a1_health_t06", "D", "Idziesz do lekarza.", "Ты идёшь к врачу.", "Ти йдеш до лікаря.", "You're going to the doctor.", False, "wrong_translation"), + + # t07 — правильный D=głowa + ("a1_health_t07", "A", "ręka", "рука", "рука", "hand", False, "wrong_context"), + ("a1_health_t07", "B", "noga", "нога", "нога", "leg", False, "wrong_context"), + ("a1_health_t07", "C", "brzuch", "живот", "живіт", "stomach", False, "wrong_context"), + ("a1_health_t07", "D", "głowa", "голова", "голова", "head", True, None), + + # t08 — правильный A=Boli mnie brzuch + ("a1_health_t08", "A", "Boli mnie brzuch.", "У меня болит живот.", "У мене болить живіт.", "My stomach hurts.", True, None), + ("a1_health_t08", "B", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", False, "wrong_context"), + ("a1_health_t08", "C", "Mam gorączkę.", "У меня температура.", "У мене температура.", "I have a fever.", False, "wrong_context"), + ("a1_health_t08", "D", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", False, "wrong_context"), + + # t09 — правильный B=Czuję się lepiej + ("a1_health_t09", "A", "Czuję się źle.", "Я чувствую себя плохо.", "Я почуваюся погано.", "I feel bad.", False, "wrong_context"), + ("a1_health_t09", "B", "Czuję się lepiej.", "Я чувствую себя лучше.", "Я почуваюся краще.", "I feel better.", True, None), + ("a1_health_t09", "C", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", False, "wrong_context"), + ("a1_health_t09", "D", "Muszę iść do lekarza.", "Мне нужно пойти к врачу.", "Мені треба піти до лікаря.", "I have to go to the doctor.", False, "wrong_context"), + + # t10 — правильный C=Biorę tabletkę + ("a1_health_t10", "A", "Biorę lekarstwo wczoraj.", "Неправильное время.", "Неправильний час.", "Wrong tense.", False, "wrong_sentence_type"), + ("a1_health_t10", "B", "Sprzedaję tabletkę.", "Я продаю таблетку.", "Я продаю таблетку.", "I'm selling a pill.", False, "wrong_context"), + ("a1_health_t10", "C", "Biorę tabletkę.", "Я принимаю таблетку.", "Я приймаю таблетку.", "I take a pill.", True, None), + ("a1_health_t10", "D", "Mam tabletkę.", "У меня есть таблетка.", "У мене є таблетка.", "I have a pill.", False, "wrong_context"), + + # t11 — правильный D=Muszę iść do lekarza + ("a1_health_t11", "A", "Muszę iść do apteki.", "Мне нужно пойти в аптеку.", "Мені треба піти в аптеку.", "I have to go to the pharmacy.", False, "wrong_context"), + ("a1_health_t11", "B", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", False, "wrong_context"), + ("a1_health_t11", "C", "Uprawiam sport.", "Я занимаюсь спортом.", "Я займаюся спортом.", "I do sports.", False, "wrong_context"), + ("a1_health_t11", "D", "Muszę iść do lekarza.", "Мне нужно пойти к врачу.", "Мені треба піти до лікаря.", "I have to go to the doctor.", True, None), + + # t12 — правильный A=Powinnaś iść do lekarza + ("a1_health_t12", "A", "Powinnaś iść do lekarza.", "Тебе следует пойти к врачу.", "Тобі варто піти до лікаря.", "You should go to the doctor.", True, None), + ("a1_health_t12", "B", "Powinnaś iść do szkoły.", "Тебе следует пойти в школу.", "Тобі варто піти до школи.", "You should go to school.", False, "wrong_context"), + ("a1_health_t12", "C", "Musisz uprawiać sport.", "Тебе нужно заниматься спортом.", "Тобі треба займатися спортом.", "You have to do sports.", False, "wrong_context"), + ("a1_health_t12", "D", "Czujesz się dobrze.", "Ты чувствуешь себя хорошо.", "Ти почуваєшся добре.", "You feel good.", False, "wrong_context"), + + # t19 — правильный B + ("a1_health_t19", "A", "Źle czułem się, bolała mnie głowa i musiałem iść do lekarza.", "Неправильное время (прошедшее вместо настоящего).", "Неправильний час (минулий замість теперішнього).", "Wrong tense (past instead of present).", False, "wrong_sentence_type"), + ("a1_health_t19", "B", "Źle się czuję, boli mnie głowa i muszę iść do lekarza.", "Я плохо себя чувствую, у меня болит голова и мне нужно пойти к врачу.", "Я погано почуваюся, у мене болить голова і мені треба піти до лікаря.", "I feel bad, my head hurts and I have to go to the doctor.", True, None), + ("a1_health_t19", "C", "Źle się czuję, boli mnie noga i muszę iść do lekarza.", "Неправильная часть тела.", "Неправильна частина тіла.", "Wrong body part.", False, "wrong_word"), + ("a1_health_t19", "D", "Dobrze się czuję, boli mnie głowa i muszę iść do apteki.", "Противоречит смыслу и неверное место.", "Суперечить змісту і невірне місце.", "Contradicts the meaning and wrong place.", False, "wrong_context"), + + # t20 — правильный C + ("a1_health_t20", "A", "Jak się nazywasz? — Czuję się źle, mam gorączkę. — Powinieneś iść do lekarza.", "Неправильный вопрос.", "Неправильне питання.", "Wrong question.", False, "wrong_translation"), + ("a1_health_t20", "B", "Jak się czujesz? — Czuję się dobrze, mam gorączkę. — Powinieneś iść do lekarza.", "Противоречие: чувствую себя хорошо, но с температурой.", "Суперечність: почуваюся добре, але з температурою.", "Contradiction: feels good but has a fever.", False, "wrong_context"), + ("a1_health_t20", "C", "Jak się czujesz? — Czuję się źle, mam gorączkę. — Powinieneś iść do lekarza.", "Как ты себя чувствуешь? — Я чувствую себя плохо, у меня температура. — Тебе следует пойти к врачу.", "Як ти почуваєшся? — Я почуваюся погано, у мене температура. — Тобі варто піти до лікаря.", "How do you feel? — I feel bad, I have a fever. — You should go to the doctor.", True, None), + ("a1_health_t20", "D", "Jak się czujesz? — Czuję się źle, mam katar. — Powinieneś iść do lekarza.", "Неправильный симптом (насморк вместо температуры).", "Неправильний симптом (нежить замість температури).", "Wrong symptom (runny nose instead of fever).", False, "wrong_word"), + ] + + for opt in test_options_t13: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 14: ГОРОД И МЕСТНОСТЬ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_city', 'A1', 14, + 'Miasto i okolica', + 'Город и местность', + 'Місто і місцевість', + 'City and Area') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t14 = [ + ("a1_city_l01", 1, "city_places_vocabulary", "Podstawowe słowa: miasto", "Основные слова: город", "Основні слова: місто", "Basic words: city", + "Podstawowe słowa dotyczące miasta: miasto, ulica, most, park. „Miasto” jest rodzaju nijakiego, „ulica” jest rodzaju żeńskiego, „most” i „park” są rodzaju męskiego.", + "Основные слова, связанные с городом: miasto (город), ulica (улица), most (мост), park (парк). „Miasto” среднего рода, „ulica” женского рода, „most” и „park” мужского рода.", + "Основні слова, пов'язані з містом: miasto (місто), ulica (вулиця), most (міст), park (парк). „Miasto” середнього роду, „ulica” жіночого роду, „most” і „park” чоловічого роду.", + "Basic words related to the city: miasto (city), ulica (street), most (bridge), park. „Miasto” is neuter, „ulica” is feminine, „most” and „park” are masculine."), + + ("a1_city_l02", 2, "gdzie_jest", "Gdzie jest? + mianownik", "Gdzie jest? + именительный падеж", "Gdzie jest? + називний відмінок", "Gdzie jest? + nominative", + "Pytania o miejsce zadajemy słowem „gdzie jest” + mianownik: gdzie jest park, gdzie jest most, gdzie jest ulica.", + "Вопрос о местонахождении задаём словом „gdzie jest” (где находится) + именительный падеж: gdzie jest park (где парк), gdzie jest most (где мост), gdzie jest ulica (где улица).", + "Питання про місцезнаходження ставимо словом „gdzie jest” (де знаходиться) + називний відмінок: gdzie jest park (де парк), gdzie jest most (де міст), gdzie jest ulica (де вулиця).", + "We ask about location with „gdzie jest” (where is) + nominative: gdzie jest park (where is the park), gdzie jest most (where is the bridge), gdzie jest ulica (where is the street)."), + + ("a1_city_l03", 3, "przyimki_miejsca", "Przyimki miejsca: w, na, obok, przed", "Предлоги места: w, na, obok, przed", "Прийменники місця: w, na, obok, przed", "Prepositions of place: w, na, obok, przed", + "Przyimki miejsca łączą się z różnymi przypadkami: „w” + miejscownik (w mieście), „na” + miejscownik (na ulicy), „obok” + dopełniacz (obok parku), „przed” + narzędnik (przed mostem).", + "Предлоги места требуют разных падежей: „w” + предложный (w mieście — в городе), „na” + предложный (na ulicy — на улице), „obok” + родительный (obok parku — рядом с парком), „przed” + творительный (przed mostem — перед мостом).", + "Прийменники місця вимагають різних відмінків: „w” + місцевий (w mieście — у місті), „na” + місцевий (na ulicy — на вулиці), „obok” + родовий (obok parku — біля парку), „przed” + орудний (przed mostem — перед мостом).", + "Prepositions of place take different cases: „w” + locative (w mieście — in the city), „na” + locative (na ulicy — on the street), „obok” + genitive (obok parku — next to the park), „przed” + instrumental (przed mostem — in front of the bridge)."), + + ("a1_city_l04", 4, "kierunki_vocabulary", "Słowa: kierunki", "Слова: направления", "Слова: напрямки", "Words: directions", + "Podstawowe słowa dotyczące kierunków: prosto, w prawo, w lewo, na rogu.", + "Основные слова о направлениях: prosto (прямо), w prawo (направо), w lewo (налево), na rogu (на углу).", + "Основні слова про напрямки: prosto (прямо), w prawo (праворуч), w lewo (ліворуч), na rogu (на розі).", + "Basic words about directions: prosto (straight ahead), w prawo (to the right), w lewo (to the left), na rogu (on the corner)."), + + ("a1_city_l05", 5, "jak_dojsc", "Jak dojść do + dopełniacz", "Jak dojść do + родительный падеж", "Jak dojść do + родовий відмінок", "Jak dojść do + genitive", + "Pytanie „jak dojść do” + dopełniacz służy do pytania o drogę: jak dojść do parku, jak dojść do dworca, jak dojść do biblioteki.", + "Вопрос „jak dojść do” (как дойти до) + родительный падеж используется, чтобы спросить дорогу: jak dojść do parku (как дойти до парка), jak dojść do dworca (как дойти до вокзала), jak dojść do biblioteki (как дойти до библиотеки).", + "Питання „jak dojść do” (як дійти до) + родовий відмінок використовується, щоб запитати дорогу: jak dojść do parku (як дійти до парку), jak dojść do dworca (як дійти до вокзалу), jak dojść do biblioteki (як дійти до бібліотеки).", + "The question „jak dojść do” (how to get to) + genitive is used to ask for directions: jak dojść do parku (how to get to the park), jak dojść do dworca (how to get to the station), jak dojść do biblioteki (how to get to the library)."), + + ("a1_city_l06", 6, "miejsca_w_miescie", "Słowa: miejsca w mieście", "Слова: места в городе", "Слова: місця в місті", "Words: places in the city", + "Kolejne miejsca w mieście: dworzec, przystanek, biblioteka, muzeum. „Dworzec” i „przystanek” są rodzaju męskiego, „biblioteka” jest rodzaju żeńskiego, „muzeum” jest rodzaju nijakiego.", + "Ещё места в городе: dworzec (вокзал), przystanek (остановка), biblioteka (библиотека), muzeum (музей). „Dworzec” и „przystanek” мужского рода, „biblioteka” женского рода, „muzeum” среднего рода.", + "Ще місця в місті: dworzec (вокзал), przystanek (зупинка), biblioteka (бібліотека), muzeum (музей). „Dworzec” і „przystanek” чоловічого роду, „biblioteka” жіночого роду, „muzeum” середнього роду.", + "More places in the city: dworzec (station), przystanek (bus stop), biblioteka (library), muzeum (museum). „Dworzec” and „przystanek” are masculine, „biblioteka” is feminine, „muzeum” is neuter."), + + ("a1_city_l07", 7, "jechac_srodkami_transportu", "Jadę + narzędnik", "Jadę + творительный падеж", "Jadę + орудний відмінок", "Jadę + instrumental", + "Czasownik „jechać” + narzędnik środka transportu: jadę autobusem, jadę tramwajem, jadę metrem.", + "Глагол „jechać” (ехать) + творительный падеж средства передвижения: jadę autobusem (я еду на автобусе), jadę tramwajem (я еду на трамвае), jadę metrem (я еду на метро).", + "Дієслово „jechać” (їхати) + орудний відмінок засобу пересування: jadę autobusem (я їду автобусом), jadę tramwajem (я їду трамваєм), jadę metrem (я їду метро).", + "The verb „jechać” (to go/ride) + instrumental of the means of transport: jadę autobusem (I go by bus), jadę tramwajem (I go by tram), jadę metrem (I go by metro)."), + + ("a1_city_l08", 8, "opis_miejsca", "Przymiotniki: opis miejsca", "Прилагательные: описание места", "Прикметники: опис місця", "Adjectives: describing a place", + "Przymiotniki opisujące miejsce zgadzają się z rzeczownikiem: duże miasto, mała ulica, stary most, nowy park.", + "Прилагательные, описывающие место, согласуются с существительным: duże miasto (большой город), mała ulica (маленькая улица), stary most (старый мост), nowy park (новый парк).", + "Прикметники, що описують місце, узгоджуються з іменником: duże miasto (велике місто), mała ulica (маленька вулиця), stary most (старий міст), nowy park (новий парк).", + "Adjectives describing a place agree with the noun: duże miasto (a big city), mała ulica (a small street), stary most (an old bridge), nowy park (a new park)."), + + ("a1_city_l09", 9, "dawac_wskazowki", "Tryb rozkazujący: wskazówki", "Повелительное наклонение: указания", "Наказовий спосіб: вказівки", "Imperative: giving directions", + "Żeby dać wskazówki, używamy trybu rozkazującego: idź prosto, skręć w prawo, skręć w lewo.", + "Чтобы дать указания, используем повелительное наклонение: idź prosto (иди прямо), skręć w prawo (поверни направо), skręć w lewo (поверни налево).", + "Щоб дати вказівки, використовуємо наказовий спосіб: idź prosto (іди прямо), skręć w prawo (поверни праворуч), skręć w lewo (поверни ліворуч).", + "To give directions, we use the imperative: idź prosto (go straight ahead), skręć w prawo (turn right), skręć w lewo (turn left)."), + + ("a1_city_l10", 10, "opisuje_miasto", "Opisuję swoje miasto", "Описываю свой город", "Описую своє місто", "Describing my city", + "Żeby opisać miasto, łączymy kilka zdań: Mieszkam w dużym mieście. Blisko jest park. Jadę tam autobusem.", + "Чтобы описать город, соединяем несколько предложений: Mieszkam w dużym mieście. Blisko jest park. Jadę tam autobusem. (Я живу в большом городе. Рядом есть парк. Я еду туда на автобусе.)", + "Щоб описати місто, поєднуємо кілька речень: Mieszkam w dużym mieście. Blisko jest park. Jadę tam autobusem. (Я живу у великому місті. Поруч є парк. Я їду туди автобусом.)", + "To describe your city, we combine several sentences: Mieszkam w dużym mieście. Blisko jest park. Jadę tam autobusem. (I live in a big city. There's a park nearby. I go there by bus.)"), + ] + + for lesson in lessons_t14: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_city', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t14 = [ + ("a1_city_l01", 1, "To jest miasto.", "Это город.", "Це місто.", "This is a city."), + ("a1_city_l01", 2, "To jest ulica.", "Это улица.", "Це вулиця.", "This is a street."), + ("a1_city_l01", 3, "To jest most.", "Это мост.", "Це міст.", "This is a bridge."), + + ("a1_city_l02", 1, "Gdzie jest park?", "Где парк?", "Де парк?", "Where is the park?"), + ("a1_city_l02", 2, "Gdzie jest most?", "Где мост?", "Де міст?", "Where is the bridge?"), + ("a1_city_l02", 3, "Ulica jest tutaj.", "Улица здесь.", "Вулиця тут.", "The street is here."), + + ("a1_city_l03", 1, "Mieszkam w mieście.", "Я живу в городе.", "Я живу в місті.", "I live in the city."), + ("a1_city_l03", 2, "Jestem na ulicy.", "Я на улице.", "Я на вулиці.", "I am on the street."), + ("a1_city_l03", 3, "Park jest obok mostu.", "Парк рядом с мостом.", "Парк біля мосту.", "The park is next to the bridge."), + + ("a1_city_l04", 1, "Idę prosto.", "Я иду прямо.", "Я йду прямо.", "I'm walking straight ahead."), + ("a1_city_l04", 2, "Skręcam w prawo.", "Я поворачиваю направо.", "Я повертаю праворуч.", "I'm turning right."), + ("a1_city_l04", 3, "Sklep jest na rogu.", "Магазин на углу.", "Магазин на розі.", "The shop is on the corner."), + + ("a1_city_l05", 1, "Jak dojść do parku?", "Как дойти до парка?", "Як дійти до парку?", "How do I get to the park?"), + ("a1_city_l05", 2, "Jak dojść do dworca?", "Как дойти до вокзала?", "Як дійти до вокзалу?", "How do I get to the station?"), + ("a1_city_l05", 3, "Jak dojść do biblioteki?", "Как дойти до библиотеки?", "Як дійти до бібліотеки?", "How do I get to the library?"), + + ("a1_city_l06", 1, "To jest dworzec.", "Это вокзал.", "Це вокзал.", "This is a station."), + ("a1_city_l06", 2, "To jest przystanek.", "Это остановка.", "Це зупинка.", "This is a bus stop."), + ("a1_city_l06", 3, "To jest muzeum.", "Это музей.", "Це музей.", "This is a museum."), + + ("a1_city_l07", 1, "Jadę autobusem.", "Я еду на автобусе.", "Я їду автобусом.", "I go by bus."), + ("a1_city_l07", 2, "Jedziesz tramwajem?", "Ты едешь на трамвае?", "Ти їдеш трамваєм?", "Do you go by tram?"), + ("a1_city_l07", 3, "Ona jedzie metrem.", "Она едет на метро.", "Вона їде метро.", "She goes by metro."), + + ("a1_city_l08", 1, "To jest duże miasto.", "Это большой город.", "Це велике місто.", "This is a big city."), + ("a1_city_l08", 2, "To jest mała ulica.", "Это маленькая улица.", "Це маленька вулиця.", "This is a small street."), + ("a1_city_l08", 3, "To jest stary most.", "Это старый мост.", "Це старий міст.", "This is an old bridge."), + + ("a1_city_l09", 1, "Idź prosto.", "Иди прямо.", "Іди прямо.", "Go straight ahead."), + ("a1_city_l09", 2, "Skręć w prawo.", "Поверни направо.", "Поверни праворуч.", "Turn right."), + ("a1_city_l09", 3, "Skręć w lewo przy moście.", "Поверни налево у моста.", "Поверни ліворуч біля мосту.", "Turn left at the bridge."), + + ("a1_city_l10", 1, "Mieszkam w dużym mieście.", "Я живу в большом городе.", "Я живу у великому місті.", "I live in a big city."), + ("a1_city_l10", 2, "Blisko jest park.", "Рядом есть парк.", "Поруч є парк.", "There's a park nearby."), + ("a1_city_l10", 3, "Jadę tam autobusem.", "Я еду туда на автобусе.", "Я їду туди автобусом.", "I go there by bus."), + ] + + for ex in examples_t14: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t14 = [ + # L01 — city_places_vocabulary (difficulty 1) + ("a1_city_l01_q1", "a1_city_l01", "lesson_practice", "recognition", "city_places_vocabulary", 1, + "Jak po polsku „улица”?", "Как по-польски «улица»?", "Як польською «вулиця»?", "How do you say “street” in Polish?", + "C", None, None), + ("a1_city_l01_q2", "a1_city_l01", "lesson_practice", "production", "city_places_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (парк)", "Вставьте пропущенное слово: To jest ___. (парк)", "Вставте пропущене слово: To jest ___. (парк)", "Fill in the missing word: To jest ___. (park)", + "park", "first_letter", "p"), + ("a1_city_l01_q3", "a1_city_l01", "lesson_practice", "application", "city_places_vocabulary", 1, + "Chcesz przejść przez rzekę. Czego szukasz?", "Ты хочешь перейти через реку. Что ты ищешь?", "Ти хочеш перейти через річку. Що ти шукаєш?", "You want to cross the river. What are you looking for?", + "B", None, None), + + # L02 — gdzie_jest (difficulty 1) + ("a1_city_l02_q1", "a1_city_l02", "lesson_practice", "recognition", "gdzie_jest", 1, + "Co znaczy „Gdzie jest park?”?", "Что означает «Gdzie jest park?»?", "Що означає «Gdzie jest park?»?", "What does “Gdzie jest park?” mean?", + "B", None, None), + ("a1_city_l02_q2", "a1_city_l02", "lesson_practice", "production", "gdzie_jest", 1, + "Wpisz brakujące słowo: ___ jest most? (где)", "Вставьте пропущенное слово: ___ jest most? (где)", "Вставте пропущене слово: ___ jest most? (де)", "Fill in the missing word: ___ jest most? (where)", + "Gdzie", "first_letter", "G"), + ("a1_city_l02_q3", "a1_city_l02", "lesson_practice", "application", "gdzie_jest", 1, + "Nie wiesz, w którym miejscu jest ulica. Co pytasz?", "Ты не знаешь, где находится улица. Что ты спрашиваешь?", "Ти не знаєш, де знаходиться вулиця. Що ти питаєш?", "You don't know where the street is. What do you ask?", + "D", None, None), + + # L03 — przyimki_miejsca (difficulty 1) + ("a1_city_l03_q1", "a1_city_l03", "lesson_practice", "recognition", "przyimki_miejsca", 1, + "Wybierz poprawną formę: Jestem w ___. (miasto)", "Выберите правильную форму: Jestem w ___. (miasto)", "Виберіть правильну форму: Jestem w ___. (miasto)", "Choose the correct form: Jestem w ___. (miasto)", + "A", None, None), + ("a1_city_l03_q2", "a1_city_l03", "lesson_practice", "production", "przyimki_miejsca", 1, + "Wpisz brakujące słowo: Park jest ___ mostu. (рядом)", "Вставьте пропущенное слово: Park jest ___ mostu. (рядом)", "Вставте пропущене слово: Park jest ___ mostu. (поруч)", "Fill in the missing word: Park jest ___ mostu. (next to)", + "obok", "first_letter", "o"), + ("a1_city_l03_q3", "a1_city_l03", "lesson_practice", "application", "przyimki_miejsca", 1, + "Chcesz powiedzieć, że mieszkasz w tym mieście. Co powiesz?", "Ты хочешь сказать, что живёшь в этом городе. Что ты скажешь?", "Ти хочеш сказати, що живеш у цьому місті. Що ти скажеш?", "You want to say you live in this city. What do you say?", + "C", None, None), + + # L04 — kierunki_vocabulary (difficulty 1) + ("a1_city_l04_q1", "a1_city_l04", "lesson_practice", "recognition", "kierunki_vocabulary", 1, + "Jak po polsku „налево”?", "Как по-польски «налево»?", "Як польською «ліворуч»?", "How do you say “to the left” in Polish?", + "D", None, None), + ("a1_city_l04_q2", "a1_city_l04", "lesson_practice", "production", "kierunki_vocabulary", 1, + "Wpisz brakujące słowo: Sklep jest ___. (на углу)", "Вставьте пропущенное слово: Sklep jest ___. (на углу)", "Вставте пропущене слово: Sklep jest ___. (на розі)", "Fill in the missing word: Sklep jest ___. (on the corner)", + "na rogu", "first_letter", "n"), + ("a1_city_l04_q3", "a1_city_l04", "lesson_practice", "application", "kierunki_vocabulary", 1, + "Chcesz iść cały czas w tym samym kierunku, bez skręcania. Co robisz?", "Ты хочешь идти всё время в одном направлении, не поворачивая. Что ты делаешь?", "Ти хочеш йти весь час в одному напрямку, не повертаючи. Що ти робиш?", "You want to keep walking in the same direction without turning. What do you do?", + "A", None, None), + + # L05 — jak_dojsc (difficulty 2) + ("a1_city_l05_q1", "a1_city_l05", "lesson_practice", "recognition", "jak_dojsc", 2, + "Wybierz poprawną formę: Jak dojść do ___? (park)", "Выберите правильную форму: Jak dojść do ___? (park)", "Виберіть правильну форму: Jak dojść do ___? (park)", "Choose the correct form: Jak dojść do ___? (park)", + "B", None, None), + ("a1_city_l05_q2", "a1_city_l05", "lesson_practice", "production", "jak_dojsc", 2, + "Wpisz brakujące słowo: Jak dojść do ___? (вокзала)", "Вставьте пропущенное слово: Jak dojść do ___? (вокзала)", "Вставте пропущене слово: Jak dojść do ___? (вокзалу)", "Fill in the missing word: Jak dojść do ___? (the station)", + "dworca", "first_letter", "d"), + ("a1_city_l05_q3", "a1_city_l05", "lesson_practice", "application", "jak_dojsc", 2, + "Jesteś w obcym mieście i szukasz biblioteki. Co pytasz przechodnia?", "Ты в незнакомом городе и ищешь библиотеку. Что ты спрашиваешь прохожего?", "Ти в незнайомому місті і шукаєш бібліотеку. Що ти питаєш перехожого?", "You're in an unfamiliar city and looking for a library. What do you ask a passer-by?", + "D", None, None), + + # L06 — miejsca_w_miescie (difficulty 2) + ("a1_city_l06_q1", "a1_city_l06", "lesson_practice", "recognition", "miejsca_w_miescie", 2, + "Jak po polsku „остановка”?", "Как по-польски «остановка»?", "Як польською «зупинка»?", "How do you say “bus stop” in Polish?", + "C", None, None), + ("a1_city_l06_q2", "a1_city_l06", "lesson_practice", "production", "miejsca_w_miescie", 2, + "Wpisz brakujące słowo: To jest ___. (библиотека)", "Вставьте пропущенное слово: To jest ___. (библиотека)", "Вставте пропущене слово: To jest ___. (бібліотека)", "Fill in the missing word: To jest ___. (library)", + "biblioteka", "first_letter", "b"), + ("a1_city_l06_q3", "a1_city_l06", "lesson_practice", "application", "miejsca_w_miescie", 2, + "Czekasz na autobus. Gdzie stoisz?", "Ты ждёшь автобус. Где ты стоишь?", "Ти чекаєш на автобус. Де ти стоїш?", "You're waiting for the bus. Where are you standing?", + "A", None, None), + + # L07 — jechac_srodkami_transportu (difficulty 2) + ("a1_city_l07_q1", "a1_city_l07", "lesson_practice", "recognition", "jechac_srodkami_transportu", 2, + "Wybierz poprawną formę: Jadę ___. (autobus)", "Выберите правильную форму: Jadę ___. (autobus)", "Виберіть правильну форму: Jadę ___. (autobus)", "Choose the correct form: Jadę ___. (autobus)", + "D", None, None), + ("a1_city_l07_q2", "a1_city_l07", "lesson_practice", "production", "jechac_srodkami_transportu", 2, + "Wpisz brakujące słowo: Jadę ___. (трамваем)", "Вставьте пропущенное слово: Jadę ___. (трамваем)", "Вставте пропущене слово: Jadę ___. (трамваєм)", "Fill in the missing word: Jadę ___. (by tram)", + "tramwajem", "first_letter", "t"), + ("a1_city_l07_q3", "a1_city_l07", "lesson_practice", "application", "jechac_srodkami_transportu", 2, + "Chcesz dostać się do centrum metrem. Co powiesz?", "Ты хочешь добраться до центра на метро. Что ты скажешь?", "Ти хочеш дістатися до центру метро. Що ти скажеш?", "You want to get downtown by metro. What do you say?", + "B", None, None), + + # L08 — opis_miejsca (difficulty 2) + ("a1_city_l08_q1", "a1_city_l08", "lesson_practice", "recognition", "opis_miejsca", 2, + "Wybierz poprawną formę: To jest ___ park. (nowy)", "Выберите правильную форму: To jest ___ park. (nowy)", "Виберіть правильну форму: To jest ___ park. (nowy)", "Choose the correct form: To jest ___ park. (nowy)", + "C", None, None), + ("a1_city_l08_q2", "a1_city_l08", "lesson_practice", "production", "opis_miejsca", 2, + "Wpisz brakujące słowo: To jest ___ miasto. (большой)", "Вставьте пропущенное слово: To jest ___ miasto. (большой)", "Вставте пропущене слово: To jest ___ miasto. (велике)", "Fill in the missing word: To jest ___ miasto. (big)", + "duże", "first_letter", "d"), + ("a1_city_l08_q3", "a1_city_l08", "lesson_practice", "application", "opis_miejsca", 2, + "Opisujesz stary most w twoim mieście. Co powiesz?", "Ты описываешь старый мост в своём городе. Что ты скажешь?", "Ти описуєш старий міст у своєму місті. Що ти скажеш?", "You're describing an old bridge in your city. What do you say?", + "A", None, None), + + # L09 — dawac_wskazowki (difficulty 3) + ("a1_city_l09_q1", "a1_city_l09", "lesson_practice", "recognition", "dawac_wskazowki", 3, + "Co znaczy „Skręć w prawo”?", "Что означает «Skręć w prawo»?", "Що означає «Skręć w prawo»?", "What does “Skręć w prawo” mean?", + "D", None, None), + ("a1_city_l09_q2", "a1_city_l09", "lesson_practice", "production", "dawac_wskazowki", 3, + "Wpisz brakujące słowo: ___ prosto. (иди)", "Вставьте пропущенное слово: ___ prosto. (иди)", "Вставте пропущене слово: ___ prosto. (іди)", "Fill in the missing word: ___ prosto. (go)", + "Idź", "first_letter", "I"), + ("a1_city_l09_q3", "a1_city_l09", "lesson_practice", "application", "dawac_wskazowki", 3, + "Pokazujesz koledze drogę i chcesz, żeby szedł cały czas w tę samą stronę. Co powiesz?", "Ты показываешь другу дорогу и хочешь, чтобы он шёл всё время в одну сторону. Что ты скажешь?", "Ти показуєш другу дорогу і хочеш, щоб він ішов увесь час в один бік. Що ти скажеш?", "You're showing a friend the way and want them to keep walking the same direction. What do you say?", + "B", None, None), + + # L10 — opisuje_miasto (difficulty 3) + ("a1_city_l10_q1", "a1_city_l10", "lesson_practice", "recognition", "opisuje_miasto", 3, + "Które zdanie poprawnie opisuje miasto?", "Какое предложение правильно описывает город?", "Яке речення правильно описує місто?", "Which sentence correctly describes a city?", + "A", None, None), + ("a1_city_l10_q2", "a1_city_l10", "lesson_practice", "production", "opisuje_miasto", 3, + "Przetłumacz: «Я еду туда на автобусе».", "Переведите: «Я еду туда на автобусе».", "Перекладіть: «Я їду туди автобусом».", "Translate: “I go there by bus.”", + "Jadę tam autobusem", "first_letter", "J"), + ("a1_city_l10_q3", "a1_city_l10", "lesson_practice", "application", "opisuje_miasto", 3, + "Chcesz opisać koledze swoje miasto: mieszkasz w dużym mieście, blisko jest park, jeździsz tam autobusem. Jak zaczniesz zdanie?", "Ты хочешь описать другу свой город: ты живёшь в большом городе, рядом есть парк, ты ездишь туда на автобусе. Как ты начнёшь предложение?", "Ти хочеш описати другу своє місто: ти живеш у великому місті, поруч є парк, ти їздиш туди автобусом. Як ти почнеш речення?", "You want to describe your city to a friend: you live in a big city, there's a park nearby, you go there by bus. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t14: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_city', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t14 = [ + # L01 + ("a1_city_l01_q1", "A", "miasto", "город", "місто", "city", False, "wrong_word"), + ("a1_city_l01_q1", "B", "most", "мост", "міст", "bridge", False, "wrong_word"), + ("a1_city_l01_q1", "C", "ulica", "улица", "вулиця", "street", True, None), + ("a1_city_l01_q1", "D", "park", "парк", "парк", "park", False, "wrong_word"), + + ("a1_city_l01_q3", "A", "ulica", "улица", "вулиця", "street", False, "wrong_context"), + ("a1_city_l01_q3", "B", "most", "мост", "міст", "bridge", True, None), + ("a1_city_l01_q3", "C", "miasto", "город", "місто", "city", False, "wrong_context"), + ("a1_city_l01_q3", "D", "park", "парк", "парк", "park", False, "wrong_context"), + + # L02 + ("a1_city_l02_q1", "A", "Jaki to park?", "Какой это парк?", "Який це парк?", "What kind of park is this?", False, "wrong_translation"), + ("a1_city_l02_q1", "B", "Gdzie jest park?", "Где парк?", "Де парк?", "Where is the park?", True, None), + ("a1_city_l02_q1", "C", "Ile kosztuje park?", "Сколько стоит парк?", "Скільки коштує парк?", "How much does the park cost?", False, "wrong_translation"), + ("a1_city_l02_q1", "D", "Czy to jest park?", "Это парк?", "Це парк?", "Is this a park?", False, "wrong_translation"), + + ("a1_city_l02_q3", "A", "Ulica jest tutaj.", "Улица здесь.", "Вулиця тут.", "The street is here.", False, "wrong_context"), + ("a1_city_l02_q3", "B", "Jaka to ulica?", "Какая это улица?", "Яка це вулиця?", "What street is this?", False, "wrong_translation"), + ("a1_city_l02_q3", "C", "Ile kosztuje ulica?", "Сколько стоит улица?", "Скільки коштує вулиця?", "How much does the street cost?", False, "wrong_context"), + ("a1_city_l02_q3", "D", "Gdzie jest ulica?", "Где улица?", "Де вулиця?", "Where is the street?", True, None), + + # L03 + ("a1_city_l03_q1", "A", "mieście", "городе (местн.)", "місті (місц.)", "city (loc.)", True, None), + ("a1_city_l03_q1", "B", "miasto", "город (им.)", "місто (наз.)", "city (nom.)", False, "wrong_case"), + ("a1_city_l03_q1", "C", "miastem", "городом (тв.)", "містом (ор.)", "city (instr.)", False, "wrong_case"), + ("a1_city_l03_q1", "D", "miastu", "городу (дат.)", "місту (дав.)", "city (dat.)", False, "wrong_case"), + + ("a1_city_l03_q3", "A", "Idę do miasta.", "Я иду в город.", "Я йду до міста.", "I'm going to the city.", False, "wrong_context"), + ("a1_city_l03_q3", "B", "Miasto jest duże.", "Город большой.", "Місто велике.", "The city is big.", False, "wrong_context"), + ("a1_city_l03_q3", "C", "Mieszkam w mieście.", "Я живу в городе.", "Я живу в місті.", "I live in the city.", True, None), + ("a1_city_l03_q3", "D", "Szukam miasta.", "Я ищу город.", "Я шукаю місто.", "I'm looking for the city.", False, "wrong_context"), + + # L04 + ("a1_city_l04_q1", "A", "w prawo", "направо", "праворуч", "to the right", False, "wrong_word"), + ("a1_city_l04_q1", "B", "prosto", "прямо", "прямо", "straight ahead", False, "wrong_word"), + ("a1_city_l04_q1", "C", "na rogu", "на углу", "на розі", "on the corner", False, "wrong_word"), + ("a1_city_l04_q1", "D", "w lewo", "налево", "ліворуч", "to the left", True, None), + + ("a1_city_l04_q3", "A", "Idę prosto.", "Я иду прямо.", "Я йду прямо.", "I'm walking straight ahead.", True, None), + ("a1_city_l04_q3", "B", "Skręcam w prawo.", "Я поворачиваю направо.", "Я повертаю праворуч.", "I'm turning right.", False, "wrong_context"), + ("a1_city_l04_q3", "C", "Skręcam w lewo.", "Я поворачиваю налево.", "Я повертаю ліворуч.", "I'm turning left.", False, "wrong_context"), + ("a1_city_l04_q3", "D", "Stoję na rogu.", "Я стою на углу.", "Я стою на розі.", "I'm standing on the corner.", False, "wrong_context"), + + # L05 + ("a1_city_l05_q1", "A", "park", "парк (им.)", "парк (наз.)", "park (nom.)", False, "wrong_case"), + ("a1_city_l05_q1", "B", "parku", "парка (род.)", "парку (род.)", "park (gen.)", True, None), + ("a1_city_l05_q1", "C", "parkiem", "парком (тв.)", "парком (ор.)", "park (instr.)", False, "wrong_case"), + ("a1_city_l05_q1", "D", "parkowi", "парку (дат.)", "парку (дав.)", "park (dat.)", False, "wrong_case"), + + ("a1_city_l05_q3", "A", "Ile kosztuje biblioteka?", "Сколько стоит библиотека?", "Скільки коштує бібліотека?", "How much does the library cost?", False, "wrong_context"), + ("a1_city_l05_q3", "B", "Czy lubisz bibliotekę?", "Тебе нравится библиотека?", "Тобі подобається бібліотека?", "Do you like the library?", False, "wrong_context"), + ("a1_city_l05_q3", "C", "Biblioteka jest ładna.", "Библиотека красивая.", "Бібліотека гарна.", "The library is nice.", False, "wrong_context"), + ("a1_city_l05_q3", "D", "Jak dojść do biblioteki?", "Как дойти до библиотеки?", "Як дійти до бібліотеки?", "How do I get to the library?", True, None), + + # L06 + ("a1_city_l06_q1", "A", "dworzec", "вокзал", "вокзал", "station", False, "wrong_word"), + ("a1_city_l06_q1", "B", "biblioteka", "библиотека", "бібліотека", "library", False, "wrong_word"), + ("a1_city_l06_q1", "C", "przystanek", "остановка", "зупинка", "bus stop", True, None), + ("a1_city_l06_q1", "D", "muzeum", "музей", "музей", "museum", False, "wrong_word"), + + ("a1_city_l06_q3", "A", "przystanek", "остановка", "зупинка", "bus stop", True, None), + ("a1_city_l06_q3", "B", "dworzec", "вокзал", "вокзал", "station", False, "wrong_context"), + ("a1_city_l06_q3", "C", "biblioteka", "библиотека", "бібліотека", "library", False, "wrong_context"), + ("a1_city_l06_q3", "D", "muzeum", "музей", "музей", "museum", False, "wrong_context"), + + # L07 + ("a1_city_l07_q1", "A", "autobus", "автобус (им.)", "автобус (наз.)", "bus (nom.)", False, "wrong_case"), + ("a1_city_l07_q1", "B", "autobusowi", "автобусу (дат.)", "автобусу (дав.)", "bus (dat.)", False, "wrong_case"), + ("a1_city_l07_q1", "C", "autobusu", "автобуса (род.)", "автобуса (род.)", "bus (gen.)", False, "wrong_case"), + ("a1_city_l07_q1", "D", "autobusem", "автобусом (тв.)", "автобусом (ор.)", "bus (instr.)", True, None), + + ("a1_city_l07_q3", "A", "Jadę autobusem.", "Я еду на автобусе.", "Я їду автобусом.", "I go by bus.", False, "wrong_context"), + ("a1_city_l07_q3", "B", "Jadę metrem.", "Я еду на метро.", "Я їду метро.", "I go by metro.", True, None), + ("a1_city_l07_q3", "C", "Idę prosto.", "Я иду прямо.", "Я йду прямо.", "I'm walking straight ahead.", False, "wrong_context"), + ("a1_city_l07_q3", "D", "Jadę tramwajem.", "Я еду на трамвае.", "Я їду трамваєм.", "I go by tram.", False, "wrong_context"), + + # L08 + ("a1_city_l08_q1", "A", "nowa", "новая (ж.р.)", "нова (ж.р.)", "new (fem.)", False, "wrong_gender"), + ("a1_city_l08_q1", "B", "nowe", "новое (ср.р.)", "нове (сер.р.)", "new (neut.)", False, "wrong_gender"), + ("a1_city_l08_q1", "C", "nowy", "новый (м.р.)", "новий (чол.р.)", "new (masc.)", True, None), + ("a1_city_l08_q1", "D", "nowego", "неправильная форма", "неправильна форма", "wrong form", False, "wrong_case"), + + ("a1_city_l08_q3", "A", "To jest stary most.", "Это старый мост.", "Це старий міст.", "This is an old bridge.", True, None), + ("a1_city_l08_q3", "B", "To jest nowy park.", "Это новый парк.", "Це новий парк.", "This is a new park.", False, "wrong_context"), + ("a1_city_l08_q3", "C", "To jest mała ulica.", "Это маленькая улица.", "Це маленька вулиця.", "This is a small street.", False, "wrong_context"), + ("a1_city_l08_q3", "D", "To jest duże miasto.", "Это большой город.", "Це велике місто.", "This is a big city.", False, "wrong_context"), + + # L09 + ("a1_city_l09_q1", "A", "Idź prosto.", "Иди прямо.", "Іди прямо.", "Go straight ahead.", False, "wrong_translation"), + ("a1_city_l09_q1", "B", "Skręć w lewo.", "Поверни налево.", "Поверни ліворуч.", "Turn left.", False, "wrong_translation"), + ("a1_city_l09_q1", "C", "Stój tutaj.", "Стой здесь.", "Стій тут.", "Stand here.", False, "wrong_translation"), + ("a1_city_l09_q1", "D", "Skręć w prawo.", "Поверни направо.", "Поверни праворуч.", "Turn right.", True, None), + + ("a1_city_l09_q3", "A", "Skręć w prawo.", "Поверни направо.", "Поверни праворуч.", "Turn right.", False, "wrong_context"), + ("a1_city_l09_q3", "B", "Idź prosto.", "Иди прямо.", "Іди прямо.", "Go straight ahead.", True, None), + ("a1_city_l09_q3", "C", "Skręć w lewo.", "Поверни налево.", "Поверни ліворуч.", "Turn left.", False, "wrong_context"), + ("a1_city_l09_q3", "D", "Stój tutaj.", "Стой здесь.", "Стій тут.", "Stand here.", False, "wrong_context"), + + # L10 + ("a1_city_l10_q1", "A", "Mieszkam w dużym mieście i blisko jest park.", "Я живу в большом городе, и рядом есть парк.", "Я живу у великому місті, і поруч є парк.", "I live in a big city and there's a park nearby.", True, None), + ("a1_city_l10_q1", "B", "Mieszkam w duże miasto i blisko jest park.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a1_city_l10_q1", "C", "Jestem duże miasto blisko park.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a1_city_l10_q1", "D", "Jadę autobus do park.", "Неправильный падеж после предлогов.", "Неправильний відмінок після прийменників.", "Wrong case after the prepositions.", False, "wrong_case"), + + ("a1_city_l10_q3", "A", "Blisko jest park.", "Рядом есть парк.", "Поруч є парк.", "There's a park nearby.", False, "wrong_context"), + ("a1_city_l10_q3", "B", "Jadę tam autobusem.", "Я еду туда на автобусе.", "Я їду туди автобусом.", "I go there by bus.", False, "wrong_context"), + ("a1_city_l10_q3", "C", "Mieszkam w dużym mieście.", "Я живу в большом городе.", "Я живу у великому місті.", "I live in a big city.", True, None), + ("a1_city_l10_q3", "D", "Skręć w prawo.", "Поверни направо.", "Поверни праворуч.", "Turn right.", False, "wrong_context"), + ] + + for opt in options_t14: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t14 = [ + ("a1_city_t01", None, "topic_test", "recognition", "city_places_vocabulary", 1, + "Jak po polsku „улица”?", "Как по-польски «улица»?", "Як польською «вулиця»?", "How do you say “street” in Polish?", + "C", None, None, 1), + ("a1_city_t02", None, "topic_test", "recognition", "gdzie_jest", 1, + "Co znaczy „Gdzie jest park?”?", "Что означает «Gdzie jest park?»?", "Що означає «Gdzie jest park?»?", "What does “Gdzie jest park?” mean?", + "B", None, None, 2), + ("a1_city_t03", None, "topic_test", "recognition", "przyimki_miejsca", 1, + "Wybierz poprawną formę: Jestem w ___. (miasto)", "Выберите правильную форму: Jestem w ___. (miasto)", "Виберіть правильну форму: Jestem w ___. (miasto)", "Choose the correct form: Jestem w ___. (miasto)", + "A", None, None, 3), + ("a1_city_t04", None, "topic_test", "recognition", "kierunki_vocabulary", 1, + "Jak po polsku „налево”?", "Как по-польски «налево»?", "Як польською «ліворуч»?", "How do you say “to the left” in Polish?", + "D", None, None, 4), + ("a1_city_t05", None, "topic_test", "recognition", "jak_dojsc", 2, + "Wybierz poprawną formę: Jak dojść do ___? (park)", "Выберите правильную форму: Jak dojść do ___? (park)", "Виберіть правильну форму: Jak dojść do ___? (park)", "Choose the correct form: Jak dojść do ___? (park)", + "B", None, None, 5), + ("a1_city_t06", None, "topic_test", "recognition", "dawac_wskazowki", 3, + "Co znaczy „Skręć w prawo”?", "Что означает «Skręć w prawo»?", "Що означає «Skręć w prawo»?", "What does “Skręć w prawo” mean?", + "D", None, None, 6), + + ("a1_city_t07", None, "topic_test", "application", "city_places_vocabulary", 1, + "Chcesz przejść przez rzekę. Czego szukasz?", "Ты хочешь перейти через реку. Что ты ищешь?", "Ти хочеш перейти через річку. Що ти шукаєш?", "You want to cross the river. What are you looking for?", + "B", None, None, 7), + ("a1_city_t08", None, "topic_test", "application", "gdzie_jest", 1, + "Nie wiesz, w którym miejscu jest ulica. Co pytasz?", "Ты не знаешь, где находится улица. Что ты спрашиваешь?", "Ти не знаєш, де знаходиться вулиця. Що ти питаєш?", "You don't know where the street is. What do you ask?", + "D", None, None, 8), + ("a1_city_t09", None, "topic_test", "application", "przyimki_miejsca", 1, + "Chcesz powiedzieć, że mieszkasz w tym mieście. Co powiesz?", "Ты хочешь сказать, что живёшь в этом городе. Что ты скажешь?", "Ти хочеш сказати, що живеш у цьому місті. Що ти скажеш?", "You want to say you live in this city. What do you say?", + "C", None, None, 9), + ("a1_city_t10", None, "topic_test", "application", "miejsca_w_miescie", 2, + "Czekasz na autobus. Gdzie stoisz?", "Ты ждёшь автобус. Где ты стоишь?", "Ти чекаєш на автобус. Де ти стоїш?", "You're waiting for the bus. Where are you standing?", + "A", None, None, 10), + ("a1_city_t11", None, "topic_test", "application", "jechac_srodkami_transportu", 2, + "Chcesz dostać się do centrum metrem. Co powiesz?", "Ты хочешь добраться до центра на метро. Что ты скажешь?", "Ти хочеш дістатися до центру метро. Що ти скажеш?", "You want to get downtown by metro. What do you say?", + "B", None, None, 11), + ("a1_city_t12", None, "topic_test", "application", "dawac_wskazowki", 3, + "Pokazujesz koledze drogę i chcesz, żeby szedł cały czas w tę samą stronę. Co powiesz?", "Ты показываешь другу дорогу и хочешь, чтобы он шёл всё время в одну сторону. Что ты скажешь?", "Ти показуєш другу дорогу і хочеш, щоб він ішов увесь час в один бік. Що ти скажеш?", "You're showing a friend the way and want them to keep walking the same direction. What do you say?", + "B", None, None, 12), + + ("a1_city_t13", None, "topic_test", "production", "city_places_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (парк)", "Вставьте пропущенное слово: To jest ___. (парк)", "Вставте пропущене слово: To jest ___. (парк)", "Fill in the missing word: To jest ___. (park)", + "park", "first_letter", "p", 13), + ("a1_city_t14", None, "topic_test", "production", "kierunki_vocabulary", 1, + "Wpisz brakujące słowo: Sklep jest ___. (на углу)", "Вставьте пропущенное слово: Sklep jest ___. (на углу)", "Вставте пропущене слово: Sklep jest ___. (на розі)", "Fill in the missing word: Sklep jest ___. (on the corner)", + "na rogu", "first_letter", "n", 14), + ("a1_city_t15", None, "topic_test", "production", "jak_dojsc", 2, + "Wpisz brakujące słowo: Jak dojść do ___? (вокзала)", "Вставьте пропущенное слово: Jak dojść do ___? (вокзала)", "Вставте пропущене слово: Jak dojść do ___? (вокзалу)", "Fill in the missing word: Jak dojść do ___? (the station)", + "dworca", "first_letter", "d", 15), + ("a1_city_t16", None, "topic_test", "production", "miejsca_w_miescie", 2, + "Wpisz brakujące słowo: To jest ___. (библиотека)", "Вставьте пропущенное слово: To jest ___. (библиотека)", "Вставте пропущене слово: To jest ___. (бібліотека)", "Fill in the missing word: To jest ___. (library)", + "biblioteka", "first_letter", "b", 16), + ("a1_city_t17", None, "topic_test", "production", "jechac_srodkami_transportu", 2, + "Wpisz brakujące słowo: Jadę ___. (трамваем)", "Вставьте пропущенное слово: Jadę ___. (трамваем)", "Вставте пропущене слово: Jadę ___. (трамваєм)", "Fill in the missing word: Jadę ___. (by tram)", + "tramwajem", "first_letter", "t", 17), + ("a1_city_t18", None, "topic_test", "production", "opisuje_miasto", 3, + "Przetłumacz: «Я еду туда на автобусе».", "Переведите: «Я еду туда на автобусе».", "Перекладіть: «Я їду туди автобусом».", "Translate: “I go there by bus.”", + "Jadę tam autobusem", "first_letter", "J", 18), + + ("a1_city_t19", None, "topic_test", "recognition", "opisuje_miasto", 3, + "Wybierz poprawne tłumaczenie: «Я живу в большом городе, и рядом есть парк».", "Выберите правильный перевод: «Я живу в большом городе, и рядом есть парк».", "Виберіть правильний переклад: «Я живу у великому місті, і поруч є парк».", "Choose the correct translation: “I live in a big city and there's a park nearby.”", + "C", None, None, 19), + ("a1_city_t20", None, "topic_test", "recognition", "jak_dojsc", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Как дойти до вокзала? — Иди прямо, потом поверни направо.»", "Выберите правильный перевод диалога: «— Как дойти до вокзала? — Иди прямо, потом поверни направо.»", "Виберіть правильний переклад діалогу: «— Як дійти до вокзалу? — Іди прямо, потім поверни праворуч.»", "Choose the correct translation of the dialogue: “— How do I get to the station? — Go straight ahead, then turn right.”", + "D", None, None, 20), + ] + + for q in test_questions_t14: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_city', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t14 = [ + ("a1_city_t01", "A", "miasto", "город", "місто", "city", False, "wrong_word"), + ("a1_city_t01", "B", "most", "мост", "міст", "bridge", False, "wrong_word"), + ("a1_city_t01", "C", "ulica", "улица", "вулиця", "street", True, None), + ("a1_city_t01", "D", "park", "парк", "парк", "park", False, "wrong_word"), + + ("a1_city_t02", "A", "Jaki to park?", "Какой это парк?", "Який це парк?", "What kind of park is this?", False, "wrong_translation"), + ("a1_city_t02", "B", "Gdzie jest park?", "Где парк?", "Де парк?", "Where is the park?", True, None), + ("a1_city_t02", "C", "Ile kosztuje park?", "Сколько стоит парк?", "Скільки коштує парк?", "How much does the park cost?", False, "wrong_translation"), + ("a1_city_t02", "D", "Czy to jest park?", "Это парк?", "Це парк?", "Is this a park?", False, "wrong_translation"), + + ("a1_city_t03", "A", "mieście", "городе (местн.)", "місті (місц.)", "city (loc.)", True, None), + ("a1_city_t03", "B", "miasto", "город (им.)", "місто (наз.)", "city (nom.)", False, "wrong_case"), + ("a1_city_t03", "C", "miastem", "городом (тв.)", "містом (ор.)", "city (instr.)", False, "wrong_case"), + ("a1_city_t03", "D", "miastu", "городу (дат.)", "місту (дав.)", "city (dat.)", False, "wrong_case"), + + ("a1_city_t04", "A", "w prawo", "направо", "праворуч", "to the right", False, "wrong_word"), + ("a1_city_t04", "B", "prosto", "прямо", "прямо", "straight ahead", False, "wrong_word"), + ("a1_city_t04", "C", "na rogu", "на углу", "на розі", "on the corner", False, "wrong_word"), + ("a1_city_t04", "D", "w lewo", "налево", "ліворуч", "to the left", True, None), + + ("a1_city_t05", "A", "park", "парк (им.)", "парк (наз.)", "park (nom.)", False, "wrong_case"), + ("a1_city_t05", "B", "parku", "парка (род.)", "парку (род.)", "park (gen.)", True, None), + ("a1_city_t05", "C", "parkiem", "парком (тв.)", "парком (ор.)", "park (instr.)", False, "wrong_case"), + ("a1_city_t05", "D", "parkowi", "парку (дат.)", "парку (дав.)", "park (dat.)", False, "wrong_case"), + + ("a1_city_t06", "A", "Idź prosto.", "Иди прямо.", "Іди прямо.", "Go straight ahead.", False, "wrong_translation"), + ("a1_city_t06", "B", "Skręć w lewo.", "Поверни налево.", "Поверни ліворуч.", "Turn left.", False, "wrong_translation"), + ("a1_city_t06", "C", "Stój tutaj.", "Стой здесь.", "Стій тут.", "Stand here.", False, "wrong_translation"), + ("a1_city_t06", "D", "Skręć w prawo.", "Поверни направо.", "Поверни праворуч.", "Turn right.", True, None), + + ("a1_city_t07", "A", "ulica", "улица", "вулиця", "street", False, "wrong_context"), + ("a1_city_t07", "B", "most", "мост", "міст", "bridge", True, None), + ("a1_city_t07", "C", "miasto", "город", "місто", "city", False, "wrong_context"), + ("a1_city_t07", "D", "park", "парк", "парк", "park", False, "wrong_context"), + + ("a1_city_t08", "A", "Ulica jest tutaj.", "Улица здесь.", "Вулиця тут.", "The street is here.", False, "wrong_context"), + ("a1_city_t08", "B", "Jaka to ulica?", "Какая это улица?", "Яка це вулиця?", "What street is this?", False, "wrong_translation"), + ("a1_city_t08", "C", "Ile kosztuje ulica?", "Сколько стоит улица?", "Скільки коштує вулиця?", "How much does the street cost?", False, "wrong_context"), + ("a1_city_t08", "D", "Gdzie jest ulica?", "Где улица?", "Де вулиця?", "Where is the street?", True, None), + + ("a1_city_t09", "A", "Idę do miasta.", "Я иду в город.", "Я йду до міста.", "I'm going to the city.", False, "wrong_context"), + ("a1_city_t09", "B", "Miasto jest duże.", "Город большой.", "Місто велике.", "The city is big.", False, "wrong_context"), + ("a1_city_t09", "C", "Mieszkam w mieście.", "Я живу в городе.", "Я живу в місті.", "I live in the city.", True, None), + ("a1_city_t09", "D", "Szukam miasta.", "Я ищу город.", "Я шукаю місто.", "I'm looking for the city.", False, "wrong_context"), + + ("a1_city_t10", "A", "przystanek", "остановка", "зупинка", "bus stop", True, None), + ("a1_city_t10", "B", "dworzec", "вокзал", "вокзал", "station", False, "wrong_context"), + ("a1_city_t10", "C", "biblioteka", "библиотека", "бібліотека", "library", False, "wrong_context"), + ("a1_city_t10", "D", "muzeum", "музей", "музей", "museum", False, "wrong_context"), + + ("a1_city_t11", "A", "Jadę autobusem.", "Я еду на автобусе.", "Я їду автобусом.", "I go by bus.", False, "wrong_context"), + ("a1_city_t11", "B", "Jadę metrem.", "Я еду на метро.", "Я їду метро.", "I go by metro.", True, None), + ("a1_city_t11", "C", "Idę prosto.", "Я иду прямо.", "Я йду прямо.", "I'm walking straight ahead.", False, "wrong_context"), + ("a1_city_t11", "D", "Jadę tramwajem.", "Я еду на трамвае.", "Я їду трамваєм.", "I go by tram.", False, "wrong_context"), + + ("a1_city_t12", "A", "Skręć w prawo.", "Поверни направо.", "Поверни праворуч.", "Turn right.", False, "wrong_context"), + ("a1_city_t12", "B", "Idź prosto.", "Иди прямо.", "Іди прямо.", "Go straight ahead.", True, None), + ("a1_city_t12", "C", "Skręć w lewo.", "Поверни налево.", "Поверни ліворуч.", "Turn left.", False, "wrong_context"), + ("a1_city_t12", "D", "Stój tutaj.", "Стой здесь.", "Стій тут.", "Stand here.", False, "wrong_context"), + + ("a1_city_t19", "A", "Mieszkam w małym mieście i blisko jest park.", "Я живу в маленьком городе, и рядом есть парк.", "Я живу в маленькому місті, і поруч є парк.", "I live in a small city and there's a park nearby.", False, "wrong_word"), + ("a1_city_t19", "B", "Mieszkam w dużym mieście i daleko jest park.", "Я живу в большом городе, и далеко есть парк.", "Я живу у великому місті, і далеко є парк.", "I live in a big city and the park is far away.", False, "wrong_context"), + ("a1_city_t19", "C", "Mieszkam w dużym mieście i blisko jest park.", "Я живу в большом городе, и рядом есть парк.", "Я живу у великому місті, і поруч є парк.", "I live in a big city and there's a park nearby.", True, None), + ("a1_city_t19", "D", "Mieszkałem w dużym mieście i blisko był park.", "Неправильное время (прошедшее вместо настоящего).", "Неправильний час (минулий замість теперішнього).", "Wrong tense (past instead of present).", False, "wrong_sentence_type"), + + ("a1_city_t20", "A", "Jak dojść do biblioteki? — Idź prosto, potem skręć w prawo.", "Неправильное место (библиотека вместо вокзала).", "Неправильне місце (бібліотека замість вокзалу).", "Wrong place (library instead of station).", False, "wrong_word"), + ("a1_city_t20", "B", "Jak dojść do dworca? — Idź prosto, potem skręć w lewo.", "Неправильное направление (налево вместо направо).", "Неправильний напрямок (ліворуч замість праворуч).", "Wrong direction (left instead of right).", False, "wrong_translation"), + ("a1_city_t20", "C", "Gdzie jest dworzec? — Idź prosto, potem skręć w prawo.", "Неправильный вопрос (где находится вместо как дойти).", "Неправильне питання (де знаходиться замість як дійти).", "Wrong question (where is instead of how to get to).", False, "wrong_translation"), + ("a1_city_t20", "D", "Jak dojść do dworca? — Idź prosto, potem skręć w prawo.", "Как дойти до вокзала? — Иди прямо, потом поверни направо.", "Як дійти до вокзалу? — Іди прямо, потім поверни праворуч.", "How do I get to the station? — Go straight ahead, then turn right.", True, None), + ] + + for opt in test_options_t14: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 15: ЕЖЕДНЕВНАЯ РУТИНА ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a1_daily_routine', 'A1', 15, + 'Codzienna rutyna', + 'Ежедневная рутина', + 'Щоденна рутина', + 'Daily Routine') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t15 = [ + ("a1_daily_routine_l01", 1, "daily_routine_verbs", "Podstawowe czasowniki: rutyna dnia", "Основные глаголы: распорядок дня", "Основні дієслова: розпорядок дня", "Basic verbs: daily routine", + "Podstawowe czasowniki opisujące dzień: wstawać, myć się, jeść, spać. To bezokoliczniki — podstawowe formy czasowników.", + "Основные глаголы, описывающие день: wstawać (вставать), myć się (мыться), jeść (есть), spać (спать). Это инфинитивы — словарные формы глаголов.", + "Основні дієслова, що описують день: wstawać (вставати), myć się (митися), jeść (їсти), spać (спати). Це інфінітиви — словникові форми дієслів.", + "Basic verbs describing the day: wstawać (to get up), myć się (to wash oneself), jeść (to eat), spać (to sleep). These are infinitives — the dictionary forms of verbs."), + + ("a1_daily_routine_l02", 2, "o_ktorej_godzinie", "O której godzinie? + liczebnik", "O której godzinie? + числительное", "O której godzinie? + числівник", "O której godzinie? + numeral", + "Pytamy o czas czynności: „O której godzinie?” + liczebnik: O której godzinie wstajesz? Wstaję o siódmej.", + "Спрашиваем о времени действия: „O której godzinie?” (В котором часу?) + числительное: O której godzinie wstajesz? (Во сколько ты встаёшь?) Wstaję o siódmej. (Я встаю в семь.)", + "Запитуємо про час дії: „O której godzinie?” (О котрій годині?) + числівник: O której godzinie wstajesz? (О котрій годині ти встаєш?) Wstaję o siódmej. (Я встаю о сьомій.)", + "We ask about the time of an action: „O której godzinie?” (At what time?) + numeral: O której godzinie wstajesz? (What time do you get up?) Wstaję o siódmej. (I get up at seven.)"), + + ("a1_daily_routine_l03", 3, "czasowniki_zwrotne", "Czasowniki zwrotne: się", "Возвратные глаголы: się", "Зворотні дієслова: się", "Reflexive verbs: się", + "Czasowniki zwrotne mają cząstkę „się”: myć się, ubierać się, czesać się.", + "Возвратные глаголы имеют частицу „się”: myć się (мыться), ubierać się (одеваться), czesać się (причёсываться).", + "Зворотні дієслова мають частку „się”: myć się (митися), ubierać się (одягатися), czesać się (розчісуватися).", + "Reflexive verbs have the particle „się”: myć się (to wash oneself), ubierać się (to get dressed), czesać się (to comb one's hair)."), + + ("a1_daily_routine_l04", 4, "posilki_vocabulary", "Słowa: posiłki", "Слова: приёмы пищи", "Слова: прийоми їжі", "Words: meals", + "Podstawowe słowa dotyczące posiłków: śniadanie, obiad, kolacja, przekąska. „Śniadanie” jest rodzaju nijakiego, „obiad” jest rodzaju męskiego, „kolacja” i „przekąska” są rodzaju żeńskiego.", + "Основные слова о приёмах пищи: śniadanie (завтрак), obiad (обед), kolacja (ужин), przekąska (перекус). „Śniadanie” среднего рода, „obiad” мужского рода, „kolacja” и „przekąska” женского рода.", + "Основні слова про прийоми їжі: śniadanie (сніданок), obiad (обід), kolacja (вечеря), przekąska (перекус). „Śniadanie” середнього роду, „obiad” чоловічого роду, „kolacja” і „przekąska” жіночого роду.", + "Basic words about meals: śniadanie (breakfast), obiad (lunch/dinner), kolacja (supper), przekąska (snack). „Śniadanie” is neuter, „obiad” is masculine, „kolacja” and „przekąska” are feminine."), + + ("a1_daily_routine_l05", 5, "wstaje_o", "Wstaję o + godzina", "Wstaję o + время", "Wstaję o + час", "Wstaję o + time", + "Żeby powiedzieć, o której godzinie coś robimy, używamy „o” + liczebnik w formie żeńskiej: wstaję o siódmej, jem śniadanie o ósmej, kończę pracę o szesnastej.", + "Чтобы сказать, во сколько мы что-то делаем, используем „o” + числительное в форме женского рода: wstaję o siódmej (я встаю в семь), jem śniadanie o ósmej (я завтракаю в восемь), kończę pracę o szesnastej (я заканчиваю работу в шестнадцать).", + "Щоб сказати, о котрій годині ми щось робимо, використовуємо „o” + числівник у формі жіночого роду: wstaję o siódmej (я встаю о сьомій), jem śniadanie o ósmej (я снідаю о восьмій), kończę pracę o szesnastej (я закінчую роботу о шістнадцятій).", + "To say at what time we do something, we use „o” + the feminine form of the numeral: wstaję o siódmej (I get up at seven), jem śniadanie o ósmej (I have breakfast at eight), kończę pracę o szesnastej (I finish work at sixteen)."), + + ("a1_daily_routine_l06", 6, "kolejnosc_czynnosci", "Kolejność czynności: najpierw, potem", "Порядок действий: najpierw, potem", "Порядок дій: najpierw, potem", "Order of actions: najpierw, potem", + "Żeby opisać kolejność czynności, używamy słów: najpierw, potem, później, na końcu.", + "Чтобы описать порядок действий, используем слова: najpierw (сначала), potem (потом), później (позже), na końcu (в конце).", + "Щоб описати порядок дій, використовуємо слова: najpierw (спочатку), potem (потім), później (пізніше), na końcu (наприкінці).", + "To describe the order of actions, we use the words: najpierw (first), potem (then), później (later), na końcu (finally)."), + + ("a1_daily_routine_l07", 7, "dni_tygodnia", "Dni tygodnia", "Дни недели", "Дні тижня", "Days of the week", + "Dni tygodnia: poniedziałek, wtorek, czwartek i piątek są rodzaju męskiego. Środa, sobota i niedziela są rodzaju żeńskiego.", + "Дни недели: poniedziałek, wtorek, czwartek и piątek мужского рода. Środa, sobota и niedziela женского рода.", + "Дні тижня: poniedziałek, wtorek, czwartek і piątek чоловічого роду. Środa, sobota і niedziela жіночого роду.", + "Days of the week: poniedziałek, wtorek, czwartek and piątek are masculine. Środa, sobota and niedziela are feminine."), + + ("a1_daily_routine_l08", 8, "zaczynac_konczyc", "Zaczynać/kończyć + biernik", "Zaczynać/kończyć + винительный падеж", "Zaczynać/kończyć + знахідний відмінок", "Zaczynać/kończyć + accusative", + "Czasowniki „zaczynać” i „kończyć” + biernik: zaczynam pracę, kończę pracę, zaczynam naukę.", + "Глаголы „zaczynać” (начинать) и „kończyć” (заканчивать) + винительный падеж: zaczynam pracę (я начинаю работу), kończę pracę (я заканчиваю работу), zaczynam naukę (я начинаю учёбу).", + "Дієслова „zaczynać” (починати) і „kończyć” (закінчувати) + знахідний відмінок: zaczynam pracę (я починаю роботу), kończę pracę (я закінчую роботу), zaczynam naukę (я починаю навчання).", + "The verbs „zaczynać” (to start) and „kończyć” (to finish) + accusative: zaczynam pracę (I start work), kończę pracę (I finish work), zaczynam naukę (I start studying)."), + + ("a1_daily_routine_l09", 9, "przed_po", "Przed + narzędnik / po + miejscownik", "Przed + творительный / po + предложный", "Przed + орудний / po + місцевий", "Przed + instrumental / po + locative", + "Przyimek „przed” + narzędnik i przyimek „po” + miejscownik określają kolejność w czasie: przed śniadaniem, po pracy, po obiedzie.", + "Предлог „przed” (перед) + творительный падеж и предлог „po” (после) + предложный падеж определяют порядок во времени: przed śniadaniem (перед завтраком), po pracy (после работы), po obiedzie (после обеда).", + "Прийменник „przed” (перед) + орудний відмінок і прийменник „po” (після) + місцевий відмінок визначають порядок у часі: przed śniadaniem (перед сніданком), po pracy (після роботи), po obiedzie (після обіду).", + "The preposition „przed” (before) + instrumental and the preposition „po” (after) + locative express order in time: przed śniadaniem (before breakfast), po pracy (after work), po obiedzie (after lunch)."), + + ("a1_daily_routine_l10", 10, "opisuje_dzien", "Opisuję swój dzień", "Описываю свой день", "Описую свій день", "Describing my day", + "Żeby opisać swój dzień, łączymy kilka zdań: Wstaję o siódmej. Najpierw myję się, potem jem śniadanie. Po pracy odpoczywam.", + "Чтобы описать свой день, соединяем несколько предложений: Wstaję o siódmej. Najpierw myję się, potem jem śniadanie. Po pracy odpoczywam. (Я встаю в семь. Сначала я моюсь, потом завтракаю. После работы я отдыхаю.)", + "Щоб описати свій день, поєднуємо кілька речень: Wstaję o siódmej. Najpierw myję się, potem jem śniadanie. Po pracy odpoczywam. (Я встаю о сьомій. Спочатку я миюся, потім снідаю. Після роботи я відпочиваю.)", + "To describe your day, we combine several sentences: Wstaję o siódmej. Najpierw myję się, potem jem śniadanie. Po pracy odpoczywam. (I get up at seven. First I wash, then I have breakfast. After work I rest.)"), + ] + + for lesson in lessons_t15: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a1_daily_routine', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t15 = [ + ("a1_daily_routine_l01", 1, "Wstaję rano.", "Я встаю утром.", "Я встаю вранці.", "I get up in the morning."), + ("a1_daily_routine_l01", 2, "Jem śniadanie.", "Я завтракаю.", "Я їм сніданок.", "I eat breakfast."), + ("a1_daily_routine_l01", 3, "Śpię w nocy.", "Я сплю ночью.", "Я сплю вночі.", "I sleep at night."), + + ("a1_daily_routine_l02", 1, "O której godzinie wstajesz?", "Во сколько ты встаёшь?", "О котрій годині ти встаєш?", "What time do you get up?"), + ("a1_daily_routine_l02", 2, "Wstaję o siódmej.", "Я встаю в семь.", "Я встаю о сьомій.", "I get up at seven."), + ("a1_daily_routine_l02", 3, "Jem obiad o dwunastej.", "Я обедаю в двенадцать.", "Я обідаю о дванадцятій.", "I have lunch at twelve."), + + ("a1_daily_routine_l03", 1, "Myję się rano.", "Я умываюсь утром.", "Я вмиваюся вранці.", "I wash myself in the morning."), + ("a1_daily_routine_l03", 2, "Ubierasz się szybko?", "Ты одеваешься быстро?", "Ти одягаєшся швидко?", "Do you get dressed quickly?"), + ("a1_daily_routine_l03", 3, "On czesze się przed lustrem.", "Он причёсывается перед зеркалом.", "Він розчісується перед дзеркалом.", "He combs his hair in front of the mirror."), + + ("a1_daily_routine_l04", 1, "Jem śniadanie o ósmej.", "Я завтракаю в восемь.", "Я снідаю о восьмій.", "I have breakfast at eight."), + ("a1_daily_routine_l04", 2, "Obiad jest o dwunastej.", "Обед в двенадцать.", "Обід о дванадцятій.", "Lunch is at twelve."), + ("a1_daily_routine_l04", 3, "Kolacja jest wieczorem.", "Ужин вечером.", "Вечеря ввечері.", "Supper is in the evening."), + + ("a1_daily_routine_l05", 1, "Wstaję o siódmej.", "Я встаю в семь.", "Я встаю о сьомій.", "I get up at seven."), + ("a1_daily_routine_l05", 2, "Jem śniadanie o ósmej.", "Я завтракаю в восемь.", "Я снідаю о восьмій.", "I have breakfast at eight."), + ("a1_daily_routine_l05", 3, "Kończę pracę o szesnastej.", "Я заканчиваю работу в шестнадцать.", "Я закінчую роботу о шістнадцятій.", "I finish work at sixteen."), + + ("a1_daily_routine_l06", 1, "Najpierw myję się, potem jem śniadanie.", "Сначала я умываюсь, потом завтракаю.", "Спочатку я вмиваюся, потім снідаю.", "First I wash, then I have breakfast."), + ("a1_daily_routine_l06", 2, "Później idę do pracy.", "Позже я иду на работу.", "Пізніше я йду на роботу.", "Later I go to work."), + ("a1_daily_routine_l06", 3, "Na końcu idę spać.", "В конце я иду спать.", "Наприкінці я йду спати.", "Finally I go to sleep."), + + ("a1_daily_routine_l07", 1, "W poniedziałek pracuję.", "В понедельник я работаю.", "У понеділок я працюю.", "On Monday I work."), + ("a1_daily_routine_l07", 2, "We wtorek mam zajęcia.", "Во вторник у меня занятия.", "У вівторок у мене заняття.", "On Tuesday I have classes."), + ("a1_daily_routine_l07", 3, "W niedzielę odpoczywam.", "В воскресенье я отдыхаю.", "У неділю я відпочиваю.", "On Sunday I rest."), + + ("a1_daily_routine_l08", 1, "Zaczynam pracę o ósmej.", "Я начинаю работу в восемь.", "Я починаю роботу о восьмій.", "I start work at eight."), + ("a1_daily_routine_l08", 2, "Kończysz pracę o szesnastej?", "Ты заканчиваешь работу в шестнадцать?", "Ти закінчуєш роботу о шістнадцятій?", "Do you finish work at sixteen?"), + ("a1_daily_routine_l08", 3, "Ona zaczyna naukę o dziewiątej.", "Она начинает учёбу в девять.", "Вона починає навчання о дев'ятій.", "She starts studying at nine."), + + ("a1_daily_routine_l09", 1, "Myję się przed śniadaniem.", "Я умываюсь перед завтраком.", "Я вмиваюся перед сніданком.", "I wash before breakfast."), + ("a1_daily_routine_l09", 2, "Odpoczywam po pracy.", "Я отдыхаю после работы.", "Я відпочиваю після роботи.", "I rest after work."), + ("a1_daily_routine_l09", 3, "Idę spać po kolacji.", "Я иду спать после ужина.", "Я йду спати після вечері.", "I go to sleep after supper."), + + ("a1_daily_routine_l10", 1, "Wstaję o siódmej.", "Я встаю в семь.", "Я встаю о сьомій.", "I get up at seven."), + ("a1_daily_routine_l10", 2, "Najpierw myję się, potem jem śniadanie.", "Сначала я умываюсь, потом завтракаю.", "Спочатку я вмиваюся, потім снідаю.", "First I wash, then I have breakfast."), + ("a1_daily_routine_l10", 3, "Po pracy odpoczywam.", "После работы я отдыхаю.", "Після роботи я відпочиваю.", "After work I rest."), + ] + + for ex in examples_t15: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t15 = [ + # L01 — daily_routine_verbs (difficulty 1) + ("a1_daily_routine_l01_q1", "a1_daily_routine_l01", "lesson_practice", "recognition", "daily_routine_verbs", 1, + "Jak po polsku „спать”?", "Как по-польски «спать»?", "Як польською «спати»?", "How do you say “to sleep” in Polish?", + "B", None, None), + ("a1_daily_routine_l01_q2", "a1_daily_routine_l01", "lesson_practice", "production", "daily_routine_verbs", 1, + "Wpisz brakujące słowo: ___ śniadanie. (ем)", "Вставьте пропущенное слово: ___ śniadanie. (ем)", "Вставте пропущене слово: ___ śniadanie. (їм)", "Fill in the missing word: ___ śniadanie. (I eat)", + "Jem", "first_letter", "J"), + ("a1_daily_routine_l01_q3", "a1_daily_routine_l01", "lesson_practice", "application", "daily_routine_verbs", 1, + "Jest rano i musisz otworzyć oczy i podnieść się z łóżka. Co robisz?", "Утро, и тебе нужно открыть глаза и подняться с кровати. Что ты делаешь?", "Ранок, і тобі треба розплющити очі та встати з ліжка. Що ти робиш?", "It's morning and you need to open your eyes and get out of bed. What do you do?", + "D", None, None), + + # L02 — o_ktorej_godzinie (difficulty 1) + ("a1_daily_routine_l02_q1", "a1_daily_routine_l02", "lesson_practice", "recognition", "o_ktorej_godzinie", 1, + "Co znaczy „O której godzinie wstajesz?”?", "Что означает «O której godzinie wstajesz?»?", "Що означає «O której godzinie wstajesz?»?", "What does “O której godzinie wstajesz?” mean?", + "C", None, None), + ("a1_daily_routine_l02_q2", "a1_daily_routine_l02", "lesson_practice", "production", "o_ktorej_godzinie", 1, + "Wpisz brakujące słowo: Wstaję ___ siódmej. (в)", "Вставьте пропущенное слово: Wstaję ___ siódmej. (в)", "Вставте пропущене слово: Wstaję ___ siódmej. (о)", "Fill in the missing word: Wstaję ___ siódmej. (at)", + "o", "first_letter", "o"), + ("a1_daily_routine_l02_q3", "a1_daily_routine_l02", "lesson_practice", "application", "o_ktorej_godzinie", 1, + "Kolega pyta, kiedy jesz obiad. Jesz o dwunastej. Co powiesz?", "Друг спрашивает, когда ты обедаешь. Ты обедаешь в двенадцать. Что ты скажешь?", "Друг питає, коли ти обідаєш. Ти обідаєш о дванадцятій. Що ти скажеш?", "A friend asks when you have lunch. You have lunch at twelve. What do you say?", + "A", None, None), + + # L03 — czasowniki_zwrotne (difficulty 1) + ("a1_daily_routine_l03_q1", "a1_daily_routine_l03", "lesson_practice", "recognition", "czasowniki_zwrotne", 1, + "Wybierz poprawną formę: Ja ___ się. (myć)", "Выберите правильную форму: Ja ___ się. (myć)", "Виберіть правильну форму: Ja ___ się. (myć)", "Choose the correct form: Ja ___ się. (myć)", + "D", None, None), + ("a1_daily_routine_l03_q2", "a1_daily_routine_l03", "lesson_practice", "production", "czasowniki_zwrotne", 1, + "Wpisz brakujące słowo: Ty ___ się szybko? (одеваешься)", "Вставьте пропущенное слово: Ty ___ się szybko? (одеваешься)", "Вставте пропущене слово: Ty ___ się szybko? (одягаєшся)", "Fill in the missing word: Ty ___ się szybko? (do you get dressed)", + "ubierasz", "first_letter", "u"), + ("a1_daily_routine_l03_q3", "a1_daily_routine_l03", "lesson_practice", "application", "czasowniki_zwrotne", 1, + "Stoisz przed lustrem i porządkujesz włosy. Co robisz?", "Ты стоишь перед зеркалом и приводишь в порядок волосы. Что ты делаешь?", "Ти стоїш перед дзеркалом і впорядковуєш волосся. Що ти робиш?", "You're standing in front of the mirror fixing your hair. What are you doing?", + "B", None, None), + + # L04 — posilki_vocabulary (difficulty 1) + ("a1_daily_routine_l04_q1", "a1_daily_routine_l04", "lesson_practice", "recognition", "posilki_vocabulary", 1, + "Jak po polsku „ужин”?", "Как по-польски «ужин»?", "Як польською «вечеря»?", "How do you say “supper” in Polish?", + "A", None, None), + ("a1_daily_routine_l04_q2", "a1_daily_routine_l04", "lesson_practice", "production", "posilki_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (перекус)", "Вставьте пропущенное слово: To jest ___. (перекус)", "Вставте пропущене слово: To jest ___. (перекус)", "Fill in the missing word: To jest ___. (snack)", + "przekąska", "first_letter", "p"), + ("a1_daily_routine_l04_q3", "a1_daily_routine_l04", "lesson_practice", "application", "posilki_vocabulary", 1, + "Jest południe i chcesz coś zjeść w środku dnia. Co jesz?", "Полдень, и ты хочешь что-нибудь съесть в середине дня. Что ты ешь?", "Полудень, і ти хочеш щось з'їсти в середині дня. Що ти їси?", "It's noon and you want to eat something in the middle of the day. What do you eat?", + "C", None, None), + + # L05 — wstaje_o (difficulty 2) + ("a1_daily_routine_l05_q1", "a1_daily_routine_l05", "lesson_practice", "recognition", "wstaje_o", 2, + "Wybierz poprawną formę: Wstaję o ___. (siódma)", "Выберите правильную форму: Wstaję o ___. (siódma)", "Виберіть правильну форму: Wstaję o ___. (siódma)", "Choose the correct form: Wstaję o ___. (siódma)", + "B", None, None), + ("a1_daily_routine_l05_q2", "a1_daily_routine_l05", "lesson_practice", "production", "wstaje_o", 2, + "Wpisz brakujące słowo: Kończę pracę ___ szesnastej. (в)", "Вставьте пропущенное слово: Kończę pracę ___ szesnastej. (в)", "Вставте пропущене слово: Kończę pracę ___ szesnastej. (о)", "Fill in the missing word: Kończę pracę ___ szesnastej. (at)", + "o", "first_letter", "o"), + ("a1_daily_routine_l05_q3", "a1_daily_routine_l05", "lesson_practice", "application", "wstaje_o", 2, + "Chcesz powiedzieć, że jesz śniadanie o godzinie ósmej. Co powiesz?", "Ты хочешь сказать, что завтракаешь в восемь часов. Что ты скажешь?", "Ти хочеш сказати, що снідаєш о восьмій годині. Що ти скажеш?", "You want to say you have breakfast at eight o'clock. What do you say?", + "D", None, None), + + # L06 — kolejnosc_czynnosci (difficulty 2) + ("a1_daily_routine_l06_q1", "a1_daily_routine_l06", "lesson_practice", "recognition", "kolejnosc_czynnosci", 2, + "Co znaczy „Najpierw myję się, potem jem śniadanie”?", "Что означает «Najpierw myję się, potem jem śniadanie»?", "Що означає «Najpierw myję się, potem jem śniadanie»?", "What does “Najpierw myję się, potem jem śniadanie” mean?", + "C", None, None), + ("a1_daily_routine_l06_q2", "a1_daily_routine_l06", "lesson_practice", "production", "kolejnosc_czynnosci", 2, + "Wpisz brakujące słowo: ___ idę do pracy. (позже)", "Вставьте пропущенное слово: ___ idę do pracy. (позже)", "Вставте пропущене слово: ___ idę do pracy. (пізніше)", "Fill in the missing word: ___ idę do pracy. (later)", + "Później", "first_letter", "P"), + ("a1_daily_routine_l06_q3", "a1_daily_routine_l06", "lesson_practice", "application", "kolejnosc_czynnosci", 2, + "Opisujesz kolejność: robisz coś jako pierwszą czynność dnia. Jakiego słowa użyjesz?", "Ты описываешь порядок: ты делаешь что-то как первое действие дня. Какое слово ты используешь?", "Ти описуєш порядок: ти робиш щось як першу дію дня. Яке слово ти використаєш?", "You're describing an order: you do something as the first action of the day. Which word do you use?", + "A", None, None), + + # L07 — dni_tygodnia (difficulty 2) + ("a1_daily_routine_l07_q1", "a1_daily_routine_l07", "lesson_practice", "recognition", "dni_tygodnia", 2, + "Jak po polsku „воскресенье”?", "Как по-польски «воскресенье»?", "Як польською «неділя»?", "How do you say “Sunday” in Polish?", + "D", None, None), + ("a1_daily_routine_l07_q2", "a1_daily_routine_l07", "lesson_practice", "production", "dni_tygodnia", 2, + "Wpisz brakujące słowo: W ___ pracuję. (понедельник)", "Вставьте пропущенное слово: W ___ pracuję. (понедельник)", "Вставте пропущене слово: W ___ pracuję. (понеділок)", "Fill in the missing word: W ___ pracuję. (Monday)", + "poniedziałek", "first_letter", "p"), + ("a1_daily_routine_l07_q3", "a1_daily_routine_l07", "lesson_practice", "application", "dni_tygodnia", 2, + "To ostatni dzień weekendu i odpoczywasz. Jaki to dzień?", "Это последний день выходных, и ты отдыхаешь. Какой это день?", "Це останній день вихідних, і ти відпочиваєш. Який це день?", "It's the last day of the weekend and you're resting. What day is it?", + "B", None, None), + + # L08 — zaczynac_konczyc (difficulty 2) + ("a1_daily_routine_l08_q1", "a1_daily_routine_l08", "lesson_practice", "recognition", "zaczynac_konczyc", 2, + "Wybierz poprawną formę: Zaczynam ___. (praca)", "Выберите правильную форму: Zaczynam ___. (praca)", "Виберіть правильну форму: Zaczynam ___. (praca)", "Choose the correct form: Zaczynam ___. (praca)", + "A", None, None), + ("a1_daily_routine_l08_q2", "a1_daily_routine_l08", "lesson_practice", "production", "zaczynac_konczyc", 2, + "Wpisz brakujące słowo: Kończę ___. (учёбу)", "Вставьте пропущенное слово: Kończę ___. (учёбу)", "Вставте пропущене слово: Kończę ___. (навчання)", "Fill in the missing word: Kończę ___. (studying)", + "naukę", "first_letter", "n"), + ("a1_daily_routine_l08_q3", "a1_daily_routine_l08", "lesson_practice", "application", "zaczynac_konczyc", 2, + "Jest ósma rano i idziesz do biura. Co robisz?", "Восемь утра, и ты идёшь в офис. Что ты делаешь?", "Восьма ранку, і ти йдеш в офіс. Що ти робиш?", "It's eight in the morning and you're going to the office. What are you doing?", + "C", None, None), + + # L09 — przed_po (difficulty 3) + ("a1_daily_routine_l09_q1", "a1_daily_routine_l09", "lesson_practice", "recognition", "przed_po", 3, + "Co znaczy „Odpoczywam po pracy”?", "Что означает «Odpoczywam po pracy»?", "Що означає «Odpoczywam po pracy»?", "What does “Odpoczywam po pracy” mean?", + "B", None, None), + ("a1_daily_routine_l09_q2", "a1_daily_routine_l09", "lesson_practice", "production", "przed_po", 3, + "Wpisz brakujące słowo: Myję się ___ śniadaniem. (перед)", "Вставьте пропущенное слово: Myję się ___ śniadaniem. (перед)", "Вставте пропущене слово: Myję się ___ śniadaniem. (перед)", "Fill in the missing word: Myję się ___ śniadaniem. (before)", + "przed", "first_letter", "p"), + ("a1_daily_routine_l09_q3", "a1_daily_routine_l09", "lesson_practice", "application", "przed_po", 3, + "Zjadłeś kolację i teraz chcesz iść spać. Co powiesz?", "Ты поужинал и теперь хочешь идти спать. Что ты скажешь?", "Ти повечеряв і тепер хочеш іти спати. Що ти скажеш?", "You've had supper and now want to go to sleep. What do you say?", + "D", None, None), + + # L10 — opisuje_dzien (difficulty 3) + ("a1_daily_routine_l10_q1", "a1_daily_routine_l10", "lesson_practice", "recognition", "opisuje_dzien", 3, + "Które zdanie poprawnie opisuje dzień?", "Какое предложение правильно описывает день?", "Яке речення правильно описує день?", "Which sentence correctly describes a day?", + "C", None, None), + ("a1_daily_routine_l10_q2", "a1_daily_routine_l10", "lesson_practice", "production", "opisuje_dzien", 3, + "Przetłumacz: «После работы я отдыхаю».", "Переведите: «После работы я отдыхаю».", "Перекладіть: «Після роботи я відпочиваю».", "Translate: “After work I rest.”", + "Po pracy odpoczywam", "first_letter", "P"), + ("a1_daily_routine_l10_q3", "a1_daily_routine_l10", "lesson_practice", "application", "opisuje_dzien", 3, + "Chcesz opisać koledze swój dzień: wstajesz o siódmej, myjesz się, jesz śniadanie. Jak zaczniesz zdanie?", "Ты хочешь описать другу свой день: ты встаёшь в семь, умываешься, завтракаешь. Как ты начнёшь предложение?", "Ти хочеш описати другу свій день: ти встаєш о сьомій, вмиваєшся, снідаєш. Як ти почнеш речення?", "You want to describe your day to a friend: you get up at seven, wash, have breakfast. How do you start the sentence?", + "A", None, None), + ] + + for q in questions_t15: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a1_daily_routine', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t15 = [ + # L01 + ("a1_daily_routine_l01_q1", "A", "jeść", "есть", "їсти", "to eat", False, "wrong_word"), + ("a1_daily_routine_l01_q1", "B", "spać", "спать", "спати", "to sleep", True, None), + ("a1_daily_routine_l01_q1", "C", "wstawać", "вставать", "вставати", "to get up", False, "wrong_word"), + ("a1_daily_routine_l01_q1", "D", "myć się", "умываться", "вмиватися", "to wash oneself", False, "wrong_word"), + + ("a1_daily_routine_l01_q3", "A", "jem", "я ем", "я їм", "I eat", False, "wrong_context"), + ("a1_daily_routine_l01_q3", "B", "śpię", "я сплю", "я сплю", "I sleep", False, "wrong_context"), + ("a1_daily_routine_l01_q3", "C", "myję się", "я умываюсь", "я вмиваюся", "I wash myself", False, "wrong_context"), + ("a1_daily_routine_l01_q3", "D", "wstaję", "я встаю", "я встаю", "I get up", True, None), + + # L02 + ("a1_daily_routine_l02_q1", "A", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_translation"), + ("a1_daily_routine_l02_q1", "B", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", False, "wrong_translation"), + ("a1_daily_routine_l02_q1", "C", "O której godzinie wstajesz?", "Во сколько ты встаёшь?", "О котрій годині ти встаєш?", "What time do you get up?", True, None), + ("a1_daily_routine_l02_q1", "D", "Co robisz wieczorem?", "Что ты делаешь вечером?", "Що ти робиш увечері?", "What do you do in the evening?", False, "wrong_translation"), + + ("a1_daily_routine_l02_q3", "A", "Jem obiad o dwunastej.", "Я обедаю в двенадцать.", "Я обідаю о дванадцятій.", "I have lunch at twelve.", True, None), + ("a1_daily_routine_l02_q3", "B", "Jem śniadanie o dwunastej.", "Я завтракаю в двенадцать.", "Я снідаю о дванадцятій.", "I have breakfast at twelve.", False, "wrong_context"), + ("a1_daily_routine_l02_q3", "C", "Wstaję o dwunastej.", "Я встаю в двенадцать.", "Я встаю о дванадцятій.", "I get up at twelve.", False, "wrong_context"), + ("a1_daily_routine_l02_q3", "D", "Kończę pracę o dwunastej.", "Я заканчиваю работу в двенадцать.", "Я закінчую роботу о дванадцятій.", "I finish work at twelve.", False, "wrong_context"), + + # L03 + ("a1_daily_routine_l03_q1", "A", "myjesz", "умываешься", "вмиваєшся", "wash (you)", False, "wrong_word"), + ("a1_daily_routine_l03_q1", "B", "myje", "умывается", "вмивається", "washes", False, "wrong_word"), + ("a1_daily_routine_l03_q1", "C", "myć", "умываться (инф.)", "вмиватися (інф.)", "to wash", False, "wrong_word"), + ("a1_daily_routine_l03_q1", "D", "myję", "умываюсь", "вмиваюся", "wash (I)", True, None), + + ("a1_daily_routine_l03_q3", "A", "myjesz się", "умываешься", "вмиваєшся", "you're washing", False, "wrong_context"), + ("a1_daily_routine_l03_q3", "B", "czeszesz się", "причёсываешься", "розчісуєшся", "you're combing your hair", True, None), + ("a1_daily_routine_l03_q3", "C", "ubierasz się", "одеваешься", "одягаєшся", "you're getting dressed", False, "wrong_context"), + ("a1_daily_routine_l03_q3", "D", "jesz śniadanie", "завтракаешь", "снідаєш", "you're having breakfast", False, "wrong_context"), + + # L04 + ("a1_daily_routine_l04_q1", "A", "kolacja", "ужин", "вечеря", "supper", True, None), + ("a1_daily_routine_l04_q1", "B", "śniadanie", "завтрак", "сніданок", "breakfast", False, "wrong_word"), + ("a1_daily_routine_l04_q1", "C", "obiad", "обед", "обід", "lunch", False, "wrong_word"), + ("a1_daily_routine_l04_q1", "D", "przekąska", "перекус", "перекус", "snack", False, "wrong_word"), + + ("a1_daily_routine_l04_q3", "A", "śniadanie", "завтрак", "сніданок", "breakfast", False, "wrong_context"), + ("a1_daily_routine_l04_q3", "B", "kolację", "ужин", "вечерю", "supper", False, "wrong_context"), + ("a1_daily_routine_l04_q3", "C", "obiad", "обед", "обід", "lunch", True, None), + ("a1_daily_routine_l04_q3", "D", "przekąskę", "перекус", "перекус", "snack", False, "wrong_context"), + + # L05 + ("a1_daily_routine_l05_q1", "A", "siódma", "семь (им.)", "сьома (наз.)", "seven (nom.)", False, "wrong_case"), + ("a1_daily_routine_l05_q1", "B", "siódmej", "семь (после „o”)", "сьомій (після „o”)", "seven (after „o”)", True, None), + ("a1_daily_routine_l05_q1", "C", "siódmą", "семь (вин.)", "сьому (знах.)", "seven (acc.)", False, "wrong_case"), + ("a1_daily_routine_l05_q1", "D", "siódmy", "неправильная форма рода", "неправильна форма роду", "wrong gender form", False, "wrong_gender"), + + ("a1_daily_routine_l05_q3", "A", "Wstaję o ósmej.", "Я встаю в восемь.", "Я встаю о восьмій.", "I get up at eight.", False, "wrong_context"), + ("a1_daily_routine_l05_q3", "B", "Kończę pracę o ósmej.", "Я заканчиваю работу в восемь.", "Я закінчую роботу о восьмій.", "I finish work at eight.", False, "wrong_context"), + ("a1_daily_routine_l05_q3", "C", "Idę spać o ósmej.", "Я иду спать в восемь.", "Я йду спати о восьмій.", "I go to sleep at eight.", False, "wrong_context"), + ("a1_daily_routine_l05_q3", "D", "Jem śniadanie o ósmej.", "Я завтракаю в восемь.", "Я снідаю о восьмій.", "I have breakfast at eight.", True, None), + + # L06 + ("a1_daily_routine_l06_q1", "A", "Potem myję się, najpierw jem śniadanie.", "Потом я умываюсь, сначала я завтракаю.", "Потім я вмиваюся, спочатку я снідаю.", "Then I wash, first I have breakfast.", False, "wrong_translation"), + ("a1_daily_routine_l06_q1", "B", "Na końcu myję się i jem śniadanie.", "В конце я умываюсь и завтракаю.", "Наприкінці я вмиваюся і снідаю.", "Finally I wash and have breakfast.", False, "wrong_translation"), + ("a1_daily_routine_l06_q1", "C", "Najpierw myję się, potem jem śniadanie.", "Сначала я умываюсь, потом завтракаю.", "Спочатку я вмиваюся, потім снідаю.", "First I wash, then I have breakfast.", True, None), + ("a1_daily_routine_l06_q1", "D", "Później myję się, nigdy nie jem śniadania.", "Позже я умываюсь, никогда не завтракаю.", "Пізніше я вмиваюся, ніколи не снідаю.", "Later I wash, I never have breakfast.", False, "wrong_translation"), + + ("a1_daily_routine_l06_q3", "A", "Najpierw", "Сначала", "Спочатку", "First", True, None), + ("a1_daily_routine_l06_q3", "B", "Potem", "Потом", "Потім", "Then", False, "wrong_context"), + ("a1_daily_routine_l06_q3", "C", "Później", "Позже", "Пізніше", "Later", False, "wrong_context"), + ("a1_daily_routine_l06_q3", "D", "Na końcu", "В конце", "Наприкінці", "Finally", False, "wrong_context"), + + # L07 + ("a1_daily_routine_l07_q1", "A", "poniedziałek", "понедельник", "понеділок", "Monday", False, "wrong_word"), + ("a1_daily_routine_l07_q1", "B", "wtorek", "вторник", "вівторок", "Tuesday", False, "wrong_word"), + ("a1_daily_routine_l07_q1", "C", "sobota", "суббота", "субота", "Saturday", False, "wrong_word"), + ("a1_daily_routine_l07_q1", "D", "niedziela", "воскресенье", "неділя", "Sunday", True, None), + + ("a1_daily_routine_l07_q3", "A", "sobota", "суббота", "субота", "Saturday", False, "wrong_context"), + ("a1_daily_routine_l07_q3", "B", "niedziela", "воскресенье", "неділя", "Sunday", True, None), + ("a1_daily_routine_l07_q3", "C", "poniedziałek", "понедельник", "понеділок", "Monday", False, "wrong_context"), + ("a1_daily_routine_l07_q3", "D", "wtorek", "вторник", "вівторок", "Tuesday", False, "wrong_context"), + + # L08 + ("a1_daily_routine_l08_q1", "A", "pracę", "работу (вин.)", "роботу (знах.)", "work (acc.)", True, None), + ("a1_daily_routine_l08_q1", "B", "praca", "работа (им.)", "робота (наз.)", "work (nom.)", False, "wrong_case"), + ("a1_daily_routine_l08_q1", "C", "pracy", "работы (род.)", "роботи (род.)", "work (gen.)", False, "wrong_case"), + ("a1_daily_routine_l08_q1", "D", "pracą", "работой (тв.)", "роботою (ор.)", "work (instr.)", False, "wrong_case"), + + ("a1_daily_routine_l08_q3", "A", "Kończę pracę.", "Я заканчиваю работу.", "Я закінчую роботу.", "I finish work.", False, "wrong_context"), + ("a1_daily_routine_l08_q3", "B", "Kończę naukę.", "Я заканчиваю учёбу.", "Я закінчую навчання.", "I finish studying.", False, "wrong_context"), + ("a1_daily_routine_l08_q3", "C", "Zaczynam pracę.", "Я начинаю работу.", "Я починаю роботу.", "I start work.", True, None), + ("a1_daily_routine_l08_q3", "D", "Zaczynam kolację.", "Я начинаю ужин.", "Я починаю вечерю.", "I start supper.", False, "wrong_context"), + + # L09 + ("a1_daily_routine_l09_q1", "A", "Odpoczywam przed pracą.", "Я отдыхаю перед работой.", "Я відпочиваю перед роботою.", "I rest before work.", False, "wrong_translation"), + ("a1_daily_routine_l09_q1", "B", "Odpoczywam po pracy.", "Я отдыхаю после работы.", "Я відпочиваю після роботи.", "I rest after work.", True, None), + ("a1_daily_routine_l09_q1", "C", "Pracuję po odpoczynku.", "Я работаю после отдыха.", "Я працюю після відпочинку.", "I work after resting.", False, "wrong_translation"), + ("a1_daily_routine_l09_q1", "D", "Nigdy nie odpoczywam.", "Я никогда не отдыхаю.", "Я ніколи не відпочиваю.", "I never rest.", False, "wrong_translation"), + + ("a1_daily_routine_l09_q3", "A", "Idę spać przed kolacją.", "Я иду спать перед ужином.", "Я йду спати перед вечерею.", "I go to sleep before supper.", False, "wrong_context"), + ("a1_daily_routine_l09_q3", "B", "Jem kolację po spaniu.", "Я ужинаю после сна.", "Я вечеряю після сну.", "I have supper after sleeping.", False, "wrong_context"), + ("a1_daily_routine_l09_q3", "C", "Myję się po kolacji.", "Я умываюсь после ужина.", "Я вмиваюся після вечері.", "I wash after supper.", False, "wrong_context"), + ("a1_daily_routine_l09_q3", "D", "Idę spać po kolacji.", "Я иду спать после ужина.", "Я йду спати після вечері.", "I go to sleep after supper.", True, None), + + # L10 + ("a1_daily_routine_l10_q1", "A", "Wstaję o siódma i myć się.", "Неправильный падеж и форма глагола.", "Неправильний відмінок і форма дієслова.", "Wrong case and verb form.", False, "wrong_case"), + ("a1_daily_routine_l10_q1", "B", "Wstaję siódmej i myję się.", "Пропущен предлог „o”.", "Пропущено прийменник „o”.", "Missing preposition „o”.", False, "wrong_sentence_type"), + ("a1_daily_routine_l10_q1", "C", "Wstaję o siódmej i myję się.", "Я встаю в семь и умываюсь.", "Я встаю о сьомій і вмиваюся.", "I get up at seven and wash myself.", True, None), + ("a1_daily_routine_l10_q1", "D", "Jestem wstaję o siódmej.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + + ("a1_daily_routine_l10_q3", "A", "Wstaję o siódmej.", "Я встаю в семь.", "Я встаю о сьомій.", "I get up at seven.", True, None), + ("a1_daily_routine_l10_q3", "B", "Po pracy odpoczywam.", "После работы я отдыхаю.", "Після роботи я відпочиваю.", "After work I rest.", False, "wrong_context"), + ("a1_daily_routine_l10_q3", "C", "Idę spać po kolacji.", "Я иду спать после ужина.", "Я йду спати після вечері.", "I go to sleep after supper.", False, "wrong_context"), + ("a1_daily_routine_l10_q3", "D", "Najpierw myję się.", "Сначала я умываюсь.", "Спочатку я вмиваюся.", "First I wash.", False, "wrong_context"), + ] + + for opt in options_t15: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t15 = [ + ("a1_daily_routine_t01", None, "topic_test", "recognition", "daily_routine_verbs", 1, + "Jak po polsku „спать”?", "Как по-польски «спать»?", "Як польською «спати»?", "How do you say “to sleep” in Polish?", + "B", None, None, 1), + ("a1_daily_routine_t02", None, "topic_test", "recognition", "o_ktorej_godzinie", 1, + "Co znaczy „O której godzinie wstajesz?”?", "Что означает «O której godzinie wstajesz?»?", "Що означає «O której godzinie wstajesz?»?", "What does “O której godzinie wstajesz?” mean?", + "C", None, None, 2), + ("a1_daily_routine_t03", None, "topic_test", "recognition", "czasowniki_zwrotne", 1, + "Wybierz poprawną formę: Ja ___ się. (myć)", "Выберите правильную форму: Ja ___ się. (myć)", "Виберіть правильну форму: Ja ___ się. (myć)", "Choose the correct form: Ja ___ się. (myć)", + "D", None, None, 3), + ("a1_daily_routine_t04", None, "topic_test", "recognition", "posilki_vocabulary", 1, + "Jak po polsku „ужин”?", "Как по-польски «ужин»?", "Як польською «вечеря»?", "How do you say “supper” in Polish?", + "A", None, None, 4), + ("a1_daily_routine_t05", None, "topic_test", "recognition", "wstaje_o", 2, + "Wybierz poprawną formę: Wstaję o ___. (siódma)", "Выберите правильную форму: Wstaję o ___. (siódma)", "Виберіть правильну форму: Wstaję o ___. (siódma)", "Choose the correct form: Wstaję o ___. (siódma)", + "B", None, None, 5), + ("a1_daily_routine_t06", None, "topic_test", "recognition", "przed_po", 3, + "Co znaczy „Odpoczywam po pracy”?", "Что означает «Odpoczywam po pracy»?", "Що означає «Odpoczywam po pracy»?", "What does “Odpoczywam po pracy” mean?", + "B", None, None, 6), + + ("a1_daily_routine_t07", None, "topic_test", "application", "daily_routine_verbs", 1, + "Jest rano i musisz otworzyć oczy i podnieść się z łóżka. Co robisz?", "Утро, и тебе нужно открыть глаза и подняться с кровати. Что ты делаешь?", "Ранок, і тобі треба розплющити очі та встати з ліжка. Що ти робиш?", "It's morning and you need to open your eyes and get out of bed. What do you do?", + "D", None, None, 7), + ("a1_daily_routine_t08", None, "topic_test", "application", "o_ktorej_godzinie", 1, + "Kolega pyta, kiedy jesz obiad. Jesz o dwunastej. Co powiesz?", "Друг спрашивает, когда ты обедаешь. Ты обедаешь в двенадцать. Что ты скажешь?", "Друг питає, коли ти обідаєш. Ти обідаєш о дванадцятій. Що ти скажеш?", "A friend asks when you have lunch. You have lunch at twelve. What do you say?", + "A", None, None, 8), + ("a1_daily_routine_t09", None, "topic_test", "application", "czasowniki_zwrotne", 1, + "Stoisz przed lustrem i porządkujesz włosy. Co robisz?", "Ты стоишь перед зеркалом и приводишь в порядок волосы. Что ты делаешь?", "Ти стоїш перед дзеркалом і впорядковуєш волосся. Що ти робиш?", "You're standing in front of the mirror fixing your hair. What are you doing?", + "B", None, None, 9), + ("a1_daily_routine_t10", None, "topic_test", "application", "kolejnosc_czynnosci", 2, + "Opisujesz kolejność: robisz coś jako pierwszą czynność dnia. Jakiego słowa użyjesz?", "Ты описываешь порядок: ты делаешь что-то как первое действие дня. Какое слово ты используешь?", "Ти описуєш порядок: ти робиш щось як першу дію дня. Яке слово ти використаєш?", "You're describing an order: you do something as the first action of the day. Which word do you use?", + "A", None, None, 10), + ("a1_daily_routine_t11", None, "topic_test", "application", "dni_tygodnia", 2, + "To ostatni dzień weekendu i odpoczywasz. Jaki to dzień?", "Это последний день выходных, и ты отдыхаешь. Какой это день?", "Це останній день вихідних, і ти відпочиваєш. Який це день?", "It's the last day of the weekend and you're resting. What day is it?", + "B", None, None, 11), + ("a1_daily_routine_t12", None, "topic_test", "application", "przed_po", 3, + "Zjadłeś kolację i teraz chcesz iść spać. Co powiesz?", "Ты поужинал и теперь хочешь идти спать. Что ты скажешь?", "Ти повечеряв і тепер хочеш іти спати. Що ти скажеш?", "You've had supper and now want to go to sleep. What do you say?", + "D", None, None, 12), + + ("a1_daily_routine_t13", None, "topic_test", "production", "daily_routine_verbs", 1, + "Wpisz brakujące słowo: ___ śniadanie. (ем)", "Вставьте пропущенное слово: ___ śniadanie. (ем)", "Вставте пропущене слово: ___ śniadanie. (їм)", "Fill in the missing word: ___ śniadanie. (I eat)", + "Jem", "first_letter", "J", 13), + ("a1_daily_routine_t14", None, "topic_test", "production", "posilki_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (перекус)", "Вставьте пропущенное слово: To jest ___. (перекус)", "Вставте пропущене слово: To jest ___. (перекус)", "Fill in the missing word: To jest ___. (snack)", + "przekąska", "first_letter", "p", 14), + ("a1_daily_routine_t15", None, "topic_test", "production", "wstaje_o", 2, + "Wpisz brakujące słowo: Kończę pracę ___ szesnastej. (в)", "Вставьте пропущенное слово: Kończę pracę ___ szesnastej. (в)", "Вставте пропущене слово: Kończę pracę ___ szesnastej. (о)", "Fill in the missing word: Kończę pracę ___ szesnastej. (at)", + "o", "first_letter", "o", 15), + ("a1_daily_routine_t16", None, "topic_test", "production", "kolejnosc_czynnosci", 2, + "Wpisz brakujące słowo: ___ idę do pracy. (позже)", "Вставьте пропущенное слово: ___ idę do pracy. (позже)", "Вставте пропущене слово: ___ idę do pracy. (пізніше)", "Fill in the missing word: ___ idę do pracy. (later)", + "Później", "first_letter", "P", 16), + ("a1_daily_routine_t17", None, "topic_test", "production", "dni_tygodnia", 2, + "Wpisz brakujące słowo: W ___ pracuję. (понедельник)", "Вставьте пропущенное слово: W ___ pracuję. (понедельник)", "Вставте пропущене слово: W ___ pracuję. (понеділок)", "Fill in the missing word: W ___ pracuję. (Monday)", + "poniedziałek", "first_letter", "p", 17), + ("a1_daily_routine_t18", None, "topic_test", "production", "opisuje_dzien", 3, + "Przetłumacz: «После работы я отдыхаю».", "Переведите: «После работы я отдыхаю».", "Перекладіть: «Після роботи я відпочиваю».", "Translate: “After work I rest.”", + "Po pracy odpoczywam", "first_letter", "P", 18), + + ("a1_daily_routine_t19", None, "topic_test", "recognition", "opisuje_dzien", 3, + "Wybierz poprawne tłumaczenie: «Я встаю в семь, умываюсь и завтракаю в восемь».", "Выберите правильный перевод: «Я встаю в семь, умываюсь и завтракаю в восемь».", "Виберіть правильний переклад: «Я встаю о сьомій, вмиваюся і снідаю о восьмій».", "Choose the correct translation: “I get up at seven, wash myself and have breakfast at eight.”", + "C", None, None, 19), + ("a1_daily_routine_t20", None, "topic_test", "recognition", "zaczynac_konczyc", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Во сколько ты начинаешь работу? — Я начинаю работу в восемь, а заканчиваю в шестнадцать.»", "Выберите правильный перевод диалога: «— Во сколько ты начинаешь работу? — Я начинаю работу в восемь, а заканчиваю в шестнадцать.»", "Виберіть правильний переклад діалогу: «— О котрій годині ти починаєш роботу? — Я починаю роботу о восьмій, а закінчую о шістнадцятій.»", "Choose the correct translation of the dialogue: “— What time do you start work? — I start work at eight and finish at sixteen.”", + "D", None, None, 20), + ] + + for q in test_questions_t15: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a1_daily_routine', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t15 = [ + ("a1_daily_routine_t01", "A", "jeść", "есть", "їсти", "to eat", False, "wrong_word"), + ("a1_daily_routine_t01", "B", "spać", "спать", "спати", "to sleep", True, None), + ("a1_daily_routine_t01", "C", "wstawać", "вставать", "вставати", "to get up", False, "wrong_word"), + ("a1_daily_routine_t01", "D", "myć się", "умываться", "вмиватися", "to wash oneself", False, "wrong_word"), + + ("a1_daily_routine_t02", "A", "Jak się nazywasz?", "Как тебя зовут?", "Як тебе звати?", "What's your name?", False, "wrong_translation"), + ("a1_daily_routine_t02", "B", "Gdzie mieszkasz?", "Где ты живёшь?", "Де ти живеш?", "Where do you live?", False, "wrong_translation"), + ("a1_daily_routine_t02", "C", "O której godzinie wstajesz?", "Во сколько ты встаёшь?", "О котрій годині ти встаєш?", "What time do you get up?", True, None), + ("a1_daily_routine_t02", "D", "Co robisz wieczorem?", "Что ты делаешь вечером?", "Що ти робиш увечері?", "What do you do in the evening?", False, "wrong_translation"), + + ("a1_daily_routine_t03", "A", "myjesz", "умываешься", "вмиваєшся", "wash (you)", False, "wrong_word"), + ("a1_daily_routine_t03", "B", "myje", "умывается", "вмивається", "washes", False, "wrong_word"), + ("a1_daily_routine_t03", "C", "myć", "умываться (инф.)", "вмиватися (інф.)", "to wash", False, "wrong_word"), + ("a1_daily_routine_t03", "D", "myję", "умываюсь", "вмиваюся", "wash (I)", True, None), + + ("a1_daily_routine_t04", "A", "kolacja", "ужин", "вечеря", "supper", True, None), + ("a1_daily_routine_t04", "B", "śniadanie", "завтрак", "сніданок", "breakfast", False, "wrong_word"), + ("a1_daily_routine_t04", "C", "obiad", "обед", "обід", "lunch", False, "wrong_word"), + ("a1_daily_routine_t04", "D", "przekąska", "перекус", "перекус", "snack", False, "wrong_word"), + + ("a1_daily_routine_t05", "A", "siódma", "семь (им.)", "сьома (наз.)", "seven (nom.)", False, "wrong_case"), + ("a1_daily_routine_t05", "B", "siódmej", "семь (после „o”)", "сьомій (після „o”)", "seven (after „o”)", True, None), + ("a1_daily_routine_t05", "C", "siódmą", "семь (вин.)", "сьому (знах.)", "seven (acc.)", False, "wrong_case"), + ("a1_daily_routine_t05", "D", "siódmy", "неправильная форма рода", "неправильна форма роду", "wrong gender form", False, "wrong_gender"), + + ("a1_daily_routine_t06", "A", "Odpoczywam przed pracą.", "Я отдыхаю перед работой.", "Я відпочиваю перед роботою.", "I rest before work.", False, "wrong_translation"), + ("a1_daily_routine_t06", "B", "Odpoczywam po pracy.", "Я отдыхаю после работы.", "Я відпочиваю після роботи.", "I rest after work.", True, None), + ("a1_daily_routine_t06", "C", "Pracuję po odpoczynku.", "Я работаю после отдыха.", "Я працюю після відпочинку.", "I work after resting.", False, "wrong_translation"), + ("a1_daily_routine_t06", "D", "Nigdy nie odpoczywam.", "Я никогда не отдыхаю.", "Я ніколи не відпочиваю.", "I never rest.", False, "wrong_translation"), + + ("a1_daily_routine_t07", "A", "jem", "я ем", "я їм", "I eat", False, "wrong_context"), + ("a1_daily_routine_t07", "B", "śpię", "я сплю", "я сплю", "I sleep", False, "wrong_context"), + ("a1_daily_routine_t07", "C", "myję się", "я умываюсь", "я вмиваюся", "I wash myself", False, "wrong_context"), + ("a1_daily_routine_t07", "D", "wstaję", "я встаю", "я встаю", "I get up", True, None), + + ("a1_daily_routine_t08", "A", "Jem obiad o dwunastej.", "Я обедаю в двенадцать.", "Я обідаю о дванадцятій.", "I have lunch at twelve.", True, None), + ("a1_daily_routine_t08", "B", "Jem śniadanie o dwunastej.", "Я завтракаю в двенадцать.", "Я снідаю о дванадцятій.", "I have breakfast at twelve.", False, "wrong_context"), + ("a1_daily_routine_t08", "C", "Wstaję o dwunastej.", "Я встаю в двенадцать.", "Я встаю о дванадцятій.", "I get up at twelve.", False, "wrong_context"), + ("a1_daily_routine_t08", "D", "Kończę pracę o dwunastej.", "Я заканчиваю работу в двенадцать.", "Я закінчую роботу о дванадцятій.", "I finish work at twelve.", False, "wrong_context"), + + ("a1_daily_routine_t09", "A", "myjesz się", "умываешься", "вмиваєшся", "you're washing", False, "wrong_context"), + ("a1_daily_routine_t09", "B", "czeszesz się", "причёсываешься", "розчісуєшся", "you're combing your hair", True, None), + ("a1_daily_routine_t09", "C", "ubierasz się", "одеваешься", "одягаєшся", "you're getting dressed", False, "wrong_context"), + ("a1_daily_routine_t09", "D", "jesz śniadanie", "завтракаешь", "снідаєш", "you're having breakfast", False, "wrong_context"), + + ("a1_daily_routine_t10", "A", "Najpierw", "Сначала", "Спочатку", "First", True, None), + ("a1_daily_routine_t10", "B", "Potem", "Потом", "Потім", "Then", False, "wrong_context"), + ("a1_daily_routine_t10", "C", "Później", "Позже", "Пізніше", "Later", False, "wrong_context"), + ("a1_daily_routine_t10", "D", "Na końcu", "В конце", "Наприкінці", "Finally", False, "wrong_context"), + + ("a1_daily_routine_t11", "A", "sobota", "суббота", "субота", "Saturday", False, "wrong_context"), + ("a1_daily_routine_t11", "B", "niedziela", "воскресенье", "неділя", "Sunday", True, None), + ("a1_daily_routine_t11", "C", "poniedziałek", "понедельник", "понеділок", "Monday", False, "wrong_context"), + ("a1_daily_routine_t11", "D", "wtorek", "вторник", "вівторок", "Tuesday", False, "wrong_context"), + + ("a1_daily_routine_t12", "A", "Idę spać przed kolacją.", "Я иду спать перед ужином.", "Я йду спати перед вечерею.", "I go to sleep before supper.", False, "wrong_context"), + ("a1_daily_routine_t12", "B", "Jem kolację po spaniu.", "Я ужинаю после сна.", "Я вечеряю після сну.", "I have supper after sleeping.", False, "wrong_context"), + ("a1_daily_routine_t12", "C", "Myję się po kolacji.", "Я умываюсь после ужина.", "Я вмиваюся після вечері.", "I wash after supper.", False, "wrong_context"), + ("a1_daily_routine_t12", "D", "Idę spać po kolacji.", "Я иду спать после ужина.", "Я йду спати після вечері.", "I go to sleep after supper.", True, None), + + ("a1_daily_routine_t19", "A", "Wstaję o ósmej, myję się i jem śniadanie o siódmej.", "Время перепутано местами.", "Час переплутано місцями.", "The times are swapped.", False, "wrong_context"), + ("a1_daily_routine_t19", "B", "Wstałem o siódmej, umyłem się i zjadłem śniadanie o ósmej.", "Неправильное время (прошедшее вместо настоящего).", "Неправильний час (минулий замість теперішнього).", "Wrong tense (past instead of present).", False, "wrong_sentence_type"), + ("a1_daily_routine_t19", "C", "Wstaję o siódmej, myję się i jem śniadanie o ósmej.", "Я встаю в семь, умываюсь и завтракаю в восемь.", "Я встаю о сьомій, вмиваюся і снідаю о восьмій.", "I get up at seven, wash myself and have breakfast at eight.", True, None), + ("a1_daily_routine_t19", "D", "Wstaję o siódmej, ubieram się i jem obiad o ósmej.", "Неправильный глагол и приём пищи (одеваюсь/обедаю вместо умываюсь/завтракаю).", "Неправильне дієслово і прийом їжі (одягаюся/обідаю замість вмиваюся/снідаю).", "Wrong verb and meal (getting dressed/lunch instead of washing/breakfast).", False, "wrong_word"), + + ("a1_daily_routine_t20", "A", "Kiedy skończysz pracę? — Zaczynam pracę o ósmej, a kończę o szesnastej.", "Неправильный вопрос («когда закончишь» вместо «во сколько начинаешь»).", "Неправильне питання («коли закінчиш» замість «о котрій починаєш»).", "Wrong question (“when will you finish” instead of “what time do you start”).", False, "wrong_translation"), + ("a1_daily_routine_t20", "B", "O której godzinie zaczynasz pracę? — Kończę pracę o ósmej, a zaczynam o szesnastej.", "Глаголы «начинаю» и «заканчиваю» перепутаны местами в ответе.", "Дієслова «починаю» і «закінчую» переплутані місцями у відповіді.", "The verbs “start” and “finish” are swapped in the answer.", False, "wrong_context"), + ("a1_daily_routine_t20", "C", "O której godzinie zaczynasz naukę? — Zaczynam pracę o ósmej, a kończę o szesnastej.", "Несоответствие: вопрос про учёбу, ответ про работу.", "Невідповідність: питання про навчання, відповідь про роботу.", "Mismatch: the question is about studying, the answer about work.", False, "wrong_word"), + ("a1_daily_routine_t20", "D", "O której godzinie zaczynasz pracę? — Zaczynam pracę o ósmej, a kończę o szesnastej.", "Во сколько ты начинаешь работу? — Я начинаю работу в восемь, а заканчиваю в шестнадцать.", "О котрій годині ти починаєш роботу? — Я починаю роботу о восьмій, а закінчую о шістнадцятій.", "What time do you start work? — I start work at eight and finish at sixteen.", True, None), + ] + + for opt in test_options_t15: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) \ No newline at end of file diff --git a/routers/learning_data/level_a2.py b/routers/learning_data/level_a2.py new file mode 100644 index 0000000..ae74749 --- /dev/null +++ b/routers/learning_data/level_a2.py @@ -0,0 +1,6420 @@ +""" +Level A2 — данные всех тем уровня A2. +Тема 1: Praca i kariera (a2_work_career) +Тема 2: Mieszkanie i wynajem (a2_housing_rental) +""" + + +async def init_level_a2(conn): + """Инициализирует все темы уровня A2""" + + # ==================== ТЕМА 1 (A2): РАБОТА И КАРЬЕРА ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_work_career', 'A2', 1, + 'Praca i kariera', + 'Работа и карьера', + 'Робота і кар''єра', + 'Work and Career') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t1_a2 = [ + ("a2_work_career_l01", 1, "zawody_vocabulary", "Podstawowe słowa: zawody", "Основные слова: профессии", "Основні слова: професії", "Basic words: professions", + "Podstawowe nazwy zawodów: kierownik, księgowy, inżynier, prawnik. Wszystkie te słowa są rodzaju męskiego.", + "Основные названия профессий: kierownik (руководитель), księgowy (бухгалтер), inżynier (инженер), prawnik (юрист). Все эти слова мужского рода.", + "Основні назви професій: kierownik (керівник), księgowy (бухгалтер), inżynier (інженер), prawnik (юрист). Усі ці слова чоловічого роду.", + "Basic job titles: kierownik (manager), księgowy (accountant), inżynier (engineer), prawnik (lawyer). All these words are masculine."), + + ("a2_work_career_l02", 2, "pracowac_jako", "Pracuję jako + mianownik", "Pracuję jako + именительный падеж", "Pracuję jako + називний відмінок", "Pracuję jako + nominative", + "Żeby powiedzieć, kim pracujemy, używamy „pracować jako” + mianownik: pracuję jako kierownik, pracujesz jako księgowy, pracuje jako inżynier.", + "Чтобы сказать, кем мы работаем, используем „pracować jako” (работать кем-то) + именительный падеж: pracuję jako kierownik (я работаю руководителем), pracujesz jako księgowy (ты работаешь бухгалтером), pracuje jako inżynier (он/она работает инженером).", + "Щоб сказати, ким ми працюємо, використовуємо „pracować jako” (працювати кимось) + називний відмінок: pracuję jako kierownik (я працюю керівником), pracujesz jako księgowy (ти працюєш бухгалтером), pracuje jako inżynier (він/вона працює інженером).", + "To say what job we do, we use „pracować jako” (to work as) + nominative: pracuję jako kierownik (I work as a manager), pracujesz jako księgowy (you work as an accountant), pracuje jako inżynier (he/she works as an engineer)."), + + ("a2_work_career_l03", 3, "czas_przeszly_praca", "Czas przeszły: -łem/-łam", "Прошедшее время: -łem/-łam", "Минулий час: -łem/-łam", "Past tense: -łem/-łam", + "Czas przeszły tworzymy końcówką „-łem” (mężczyzna) lub „-łam” (kobieta): pracowałem/pracowałam, uczyłem się/uczyłam się, skończyłem/skończyłam studia.", + "Прошедшее время образуем окончанием „-łem” (мужчина) или „-łam” (женщина): pracowałem/pracowałam (я работал/работала), uczyłem się/uczyłam się (я учился/училась), skończyłem/skończyłam studia (я закончил/закончила учёбу).", + "Минулий час утворюємо закінченням „-łem” (чоловік) або „-łam” (жінка): pracowałem/pracowałam (я працював/працювала), uczyłem się/uczyłam się (я вчився/вчилася), skończyłem/skończyłam studia (я закінчив/закінчила навчання).", + "We form the past tense with the ending „-łem” (male speaker) or „-łam” (female speaker): pracowałem/pracowałam (I worked), uczyłem się/uczyłam się (I studied), skończyłem/skończyłam studia (I finished my studies)."), + + ("a2_work_career_l04", 4, "szukac_pracy_vocabulary", "Słowa: szukanie pracy", "Слова: поиск работы", "Слова: пошук роботи", "Words: job searching", + "Podstawowe słowa związane z szukaniem pracy: CV, rozmowa kwalifikacyjna, ogłoszenie, pracodawca.", + "Основные слова, связанные с поиском работы: CV (резюме), rozmowa kwalifikacyjna (собеседование), ogłoszenie (объявление), pracodawca (работодатель).", + "Основні слова, пов'язані з пошуком роботи: CV (резюме), rozmowa kwalifikacyjna (співбесіда), ogłoszenie (оголошення), pracodawca (роботодавець).", + "Basic words related to job searching: CV (resume), rozmowa kwalifikacyjna (job interview), ogłoszenie (job ad), pracodawca (employer)."), + + ("a2_work_career_l05", 5, "umiejetnosci_zawodowe", "Umieć + bezokolicznik / znać + biernik", "Umieć + инфинитив / znać + винительный падеж", "Umieć + інфінітив / znać + знахідний відмінок", "Umieć + infinitive / znać + accusative", + "Czasownik „umieć” + bezokolicznik dotyczy umiejętności: umiem programować. Czasownik „znać” + biernik dotyczy znajomości: znam angielski.", + "Глагол „umieć” (уметь) + инфинитив относится к навыкам: umiem programować (я умею программировать). Глагол „znać” (знать) + винительный падеж относится к владению чем-либо: znam angielski (я знаю английский).", + "Дієслово „umieć” (уміти) + інфінітив стосується навичок: umiem programować (я вмію програмувати). Дієслово „znać” (знати) + знахідний відмінок стосується володіння чимось: znam angielski (я знаю англійську).", + "The verb „umieć” (to know how to) + infinitive is about skills: umiem programować (I know how to program). The verb „znać” (to know) + accusative is about knowledge of something: znam angielski (I know English)."), + + # 🔧 ФИКС L06: title_ru/uk/en переведены (было дублирование польского) + ("a2_work_career_l06", 6, "opisywac_doswiadczenie", + "Pracowałem w + miejscownik, przez + biernik", + "Pracowałem w + предложный падеж, przez + винительный падеж", + "Pracowałem w + місцевий відмінок, przez + знахідний відмінок", + "Pracowałem w + locative, przez + accusative", + "Żeby opisać doświadczenie zawodowe, mówimy „pracowałem w” + miejscownik i „przez” + biernik czasu: pracowałem w banku przez trzy lata.", + "Чтобы описать профессиональный опыт, говорим „pracowałem w” (я работал в) + предложный падеж и „przez” (в течение) + винительный падеж времени: pracowałem w banku przez trzy lata (я работал в банке в течение трёх лет).", + "Щоб описати професійний досвід, кажемо „pracowałem w” (я працював у) + місцевий відмінок і „przez” (протягом) + знахідний відмінок часу: pracowałem w banku przez trzy lata (я працював у банку протягом трьох років).", + "To describe work experience, we say „pracowałem w” (I worked at) + locative and „przez” (for) + accusative of time: pracowałem w banku przez trzy lata (I worked at a bank for three years)."), + + # 🔧 ФИКС L07: title_ru/uk/en переведены (было дублирование польского) + ("a2_work_career_l07", 7, "awans_i_zmiana_pracy", + "Awansować, zmieniać pracę, dostać podwyżkę", + "Продвинуться по службе, сменить работу, получить прибавку", + "Просунутися по службі, змінити роботу, отримати підвищення", + "Get promoted, change jobs, get a raise", + "Czasowniki i wyrażenia dotyczące rozwoju kariery: awansować (dostać wyższe stanowisko), zmieniać pracę, dostać podwyżkę.", + "Глаголы и выражения о развитии карьеры: awansować (продвинуться по службе), zmieniać pracę (менять работу), dostać podwyżkę (получить прибавку к зарплате).", + "Дієслова і вирази про розвиток кар'єри: awansować (просунутися по службі), zmieniać pracę (змінювати роботу), dostać podwyżkę (отримати підвищення зарплати).", + "Verbs and expressions about career growth: awansować (to get promoted), zmieniać pracę (to change jobs), dostać podwyżkę (to get a raise)."), + + ("a2_work_career_l08", 8, "warunki_pracy", "Warunki pracy", "Условия работы", "Умови роботи", "Working conditions", + "Podstawowe słowa dotyczące warunków pracy: pełny etat, część etatu, praca zdalna, praca w biurze.", + "Основные слова об условиях работы: pełny etat (полная занятость), część etatu (неполная занятость), praca zdalna (удалённая работа), praca w biurze (работа в офисе).", + "Основні слова про умови роботи: pełny etat (повна зайнятість), część etatu (неповна зайнятість), praca zdalna (віддалена робота), praca w biurze (робота в офісі).", + "Basic words about working conditions: pełny etat (full-time), część etatu (part-time), praca zdalna (remote work), praca w biurze (office work)."), + + ("a2_work_career_l09", 9, "plany_zawodowe_przyszlosc", "Chciałbym/chciałabym + bezokolicznik", "Chciałbym/chciałabym + инфинитив", "Chciałbym/chciałabym + інфінітив", "Chciałbym/chciałabym + infinitive", + "Żeby mówić o planach zawodowych w sposób grzeczny, używamy trybu przypuszczającego: chciałbym awansować (mężczyzna), chciałabym zmienić pracę (kobieta).", + "Чтобы говорить о профессиональных планах вежливо, используем сослагательное наклонение: chciałbym awansować (мужчина: я хотел бы продвинуться по службе), chciałabym zmienić pracę (женщина: я хотела бы сменить работу).", + "Щоб говорити про професійні плани ввічливо, використовуємо умовний спосіб: chciałbym awansować (чоловік: я хотів би просунутися по службі), chciałabym zmienić pracę (жінка: я хотіла б змінити роботу).", + "To talk about career plans politely, we use the conditional mood: chciałbym awansować (male speaker: I would like to get promoted), chciałabym zmienić pracę (female speaker: I would like to change jobs)."), + + ("a2_work_career_l10", 10, "opisuje_swoja_kariere", "Opisuję swoją karierę", "Описываю свою карьеру", "Описую свою кар'єру", "Describing my career", + "Żeby opisać swoją karierę, łączymy zdania w różnych czasach: Skończyłem studia. Pracowałem w banku przez trzy lata. Teraz pracuję jako kierownik. Chciałbym awansować.", + "Чтобы описать свою карьеру, соединяем предложения в разных временах: Skończyłem studia. Pracowałem w banku przez trzy lata. Teraz pracuję jako kierownik. Chciałbym awansować. (Я закончил учёбу. Я работал в банке в течение трёх лет. Сейчас я работаю руководителем. Я хотел бы продвинуться по службе.)", + "Щоб описати свою кар'єру, поєднуємо речення в різних часах: Skończyłem studia. Pracowałem w banku przez trzy lata. Teraz pracuję jako kierownik. Chciałbym awansować. (Я закінчив навчання. Я працював у банку протягом трьох років. Зараз я працюю керівником. Я хотів би просунутися по службі.)", + "To describe your career, we combine sentences in different tenses: Skończyłem studia. Pracowałem w banku przez trzy lata. Teraz pracuję jako kierownik. Chciałbym awansować. (I finished my studies. I worked at a bank for three years. Now I work as a manager. I would like to get promoted.)"), + ] + + for lesson in lessons_t1_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_work_career', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t1_a2 = [ + ("a2_work_career_l01", 1, "To jest kierownik.", "Это руководитель.", "Це керівник.", "This is a manager."), + ("a2_work_career_l01", 2, "To jest inżynier.", "Это инженер.", "Це інженер.", "This is an engineer."), + ("a2_work_career_l01", 3, "To jest prawnik.", "Это юрист.", "Це юрист.", "This is a lawyer."), + + ("a2_work_career_l02", 1, "Pracuję jako kierownik.", "Я работаю руководителем.", "Я працюю керівником.", "I work as a manager."), + ("a2_work_career_l02", 2, "Pracujesz jako księgowy?", "Ты работаешь бухгалтером?", "Ти працюєш бухгалтером?", "Do you work as an accountant?"), + ("a2_work_career_l02", 3, "On pracuje jako inżynier.", "Он работает инженером.", "Він працює інженером.", "He works as an engineer."), + + ("a2_work_career_l03", 1, "Pracowałem w banku.", "Я работал в банке.", "Я працював у банку.", "I worked at a bank."), + ("a2_work_career_l03", 2, "Uczyłaś się na uniwersytecie?", "Ты училась в университете?", "Ти вчилася в університеті?", "Did you study at university?"), + ("a2_work_career_l03", 3, "Skończyłem studia w zeszłym roku.", "Я закончил учёбу в прошлом году.", "Я закінчив навчання минулого року.", "I finished my studies last year."), + + ("a2_work_career_l04", 1, "Piszę CV.", "Я пишу резюме.", "Я пишу резюме.", "I'm writing my CV."), + ("a2_work_career_l04", 2, "Mam rozmowę kwalifikacyjną jutro.", "У меня завтра собеседование.", "У мене завтра співбесіда.", "I have a job interview tomorrow."), + ("a2_work_career_l04", 3, "Widziałem ciekawe ogłoszenie.", "Я видел интересное объявление.", "Я бачив цікаве оголошення.", "I saw an interesting job ad."), + + ("a2_work_career_l05", 1, "Umiem programować.", "Я умею программировать.", "Я вмію програмувати.", "I know how to program."), + ("a2_work_career_l05", 2, "Znasz angielski?", "Ты знаешь английский?", "Ти знаєш англійську?", "Do you know English?"), + ("a2_work_career_l05", 3, "Ona umie mówić po niemiecku.", "Она умеет говорить по-немецки.", "Вона вміє говорити німецькою.", "She knows how to speak German."), + + ("a2_work_career_l06", 1, "Pracowałem w banku przez trzy lata.", "Я работал в банке в течение трёх лет.", "Я працював у банку протягом трьох років.", "I worked at a bank for three years."), + ("a2_work_career_l06", 2, "Pracowałaś w szkole przez rok?", "Ты работала в школе в течение года?", "Ти працювала в школі протягом року?", "Did you work at a school for a year?"), + ("a2_work_career_l06", 3, "On pracował w firmie przez pięć lat.", "Он работал в компании в течение пяти лет.", "Він працював у компанії протягом п'яти років.", "He worked at a company for five years."), + + ("a2_work_career_l07", 1, "Awansowałem w zeszłym roku.", "Я продвинулся по службе в прошлом году.", "Я просунувся по службі минулого року.", "I got promoted last year."), + ("a2_work_career_l07", 2, "Chcesz zmienić pracę?", "Ты хочешь сменить работу?", "Ти хочеш змінити роботу?", "Do you want to change jobs?"), + ("a2_work_career_l07", 3, "Dostałam podwyżkę.", "Я получила прибавку к зарплате.", "Я отримала підвищення зарплати.", "I got a raise."), + + ("a2_work_career_l08", 1, "Pracuję na pełny etat.", "Я работаю на полную ставку.", "Я працюю на повну ставку.", "I work full-time."), + ("a2_work_career_l08", 2, "Pracujesz zdalnie?", "Ты работаешь удалённо?", "Ти працюєш віддалено?", "Do you work remotely?"), + ("a2_work_career_l08", 3, "On pracuje w biurze.", "Он работает в офисе.", "Він працює в офісі.", "He works in an office."), + + ("a2_work_career_l09", 1, "Chciałbym awansować.", "Я хотел бы продвинуться по службе.", "Я хотів би просунутися по службі.", "I would like to get promoted."), + ("a2_work_career_l09", 2, "Chciałabyś zmienić pracę?", "Ты хотела бы сменить работу?", "Ти хотіла б змінити роботу?", "Would you like to change jobs?"), + ("a2_work_career_l09", 3, "On chciałby pracować zdalnie.", "Он хотел бы работать удалённо.", "Він хотів би працювати віддалено.", "He would like to work remotely."), + + ("a2_work_career_l10", 1, "Skończyłem studia.", "Я закончил учёбу.", "Я закінчив навчання.", "I finished my studies."), + ("a2_work_career_l10", 2, "Pracowałem w banku przez trzy lata.", "Я работал в банке в течение трёх лет.", "Я працював у банку протягом трьох років.", "I worked at a bank for three years."), + ("a2_work_career_l10", 3, "Chciałbym awansować.", "Я хотел бы продвинуться по службе.", "Я хотів би просунутися по службі.", "I would like to get promoted."), + ] + + for ex in examples_t1_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t1_a2 = [ + # L01 — zawody_vocabulary (difficulty 1) + ("a2_work_career_l01_q1", "a2_work_career_l01", "lesson_practice", "recognition", "zawody_vocabulary", 1, + "Jak po polsku „юрист”?", "Как по-польски «юрист»?", "Як польською «юрист»?", "How do you say “lawyer” in Polish?", + "C", None, None), + ("a2_work_career_l01_q2", "a2_work_career_l01", "lesson_practice", "production", "zawody_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (инженер)", "Вставьте пропущенное слово: To jest ___. (инженер)", "Вставте пропущене слово: To jest ___. (інженер)", "Fill in the missing word: To jest ___. (engineer)", + "inżynier", "first_letter", "i"), + ("a2_work_career_l01_q3", "a2_work_career_l01", "lesson_practice", "application", "zawody_vocabulary", 1, + "Osoba zarządza zespołem w firmie. Kim ona jest?", "Человек управляет командой в компании. Кто он?", "Людина керує командою у компанії. Хто вона?", "A person manages a team at a company. What is their job?", + "A", None, None), + + # L02 — pracowac_jako (difficulty 1) + ("a2_work_career_l02_q1", "a2_work_career_l02", "lesson_practice", "recognition", "pracowac_jako", 1, + "Co znaczy „Pracuję jako kierownik”?", "Что означает «Pracuję jako kierownik»?", "Що означає «Pracuję jako kierownik»?", "What does “Pracuję jako kierownik” mean?", + "D", None, None), + ("a2_work_career_l02_q2", "a2_work_career_l02", "lesson_practice", "production", "pracowac_jako", 1, + "Wpisz brakujące słowo: Pracuję ___ inżynier. (кем)", "Вставьте пропущенное слово: Pracuję ___ inżynier. (кем)", "Вставте пропущене слово: Pracuję ___ inżynier. (ким)", "Fill in the missing word: Pracuję ___ inżynier. (as)", + "jako", "first_letter", "j"), + ("a2_work_career_l02_q3", "a2_work_career_l02", "lesson_practice", "application", "pracowac_jako", 1, + "Kolega pyta, kim pracujesz. Pracujesz jako księgowy. Co powiesz?", "Друг спрашивает, кем ты работаешь. Ты работаешь бухгалтером. Что ты скажешь?", "Друг питає, ким ти працюєш. Ти працюєш бухгалтером. Що ти скажеш?", "A friend asks what your job is. You work as an accountant. What do you say?", + "B", None, None), + + # L03 — czas_przeszly_praca (difficulty 1) + ("a2_work_career_l03_q1", "a2_work_career_l03", "lesson_practice", "recognition", "czas_przeszly_praca", 1, + "Wybierz poprawną formę (mężczyzna mówi): Wczoraj ___ w biurze. (pracować)", "Выберите правильную форму (говорит мужчина): Wczoraj ___ w biurze. (pracować)", "Виберіть правильну форму (говорить чоловік): Wczoraj ___ w biurze. (pracować)", "Choose the correct form (a man is speaking): Wczoraj ___ w biurze. (pracować)", + "A", None, None), + ("a2_work_career_l03_q2", "a2_work_career_l03", "lesson_practice", "production", "czas_przeszly_praca", 1, + "Wpisz brakujące słowo (kobieta mówi): ___ studia w zeszłym roku. (закончила)", "Вставьте пропущенное слово (говорит женщина): ___ studia w zeszłym roku. (закончила)", "Вставте пропущене слово (говорить жінка): ___ studia w zeszłym roku. (закінчила)", "Fill in the missing word (a woman is speaking): ___ studia w zeszłym roku. (finished)", + "Skończyłam", "first_letter", "S"), + ("a2_work_career_l03_q3", "a2_work_career_l03", "lesson_practice", "application", "czas_przeszly_praca", 1, + "Mężczyzna opowiada, że skończył naukę na uniwersytecie. Co powie?", "Мужчина рассказывает, что закончил учёбу в университете. Что он скажет?", "Чоловік розповідає, що закінчив навчання в університеті. Що він скаже?", "A man is telling that he finished studying at university. What does he say?", + "C", None, None), + + # L04 — szukac_pracy_vocabulary (difficulty 1) + ("a2_work_career_l04_q1", "a2_work_career_l04", "lesson_practice", "recognition", "szukac_pracy_vocabulary", 1, + "Jak po polsku „собеседование”?", "Как по-польски «собеседование»?", "Як польською «співбесіда»?", "How do you say “job interview” in Polish?", + "B", None, None), + ("a2_work_career_l04_q2", "a2_work_career_l04", "lesson_practice", "production", "szukac_pracy_vocabulary", 1, + "Wpisz brakujące słowo: Piszę ___. (резюме)", "Вставьте пропущенное слово: Piszę ___. (резюме)", "Вставте пропущене слово: Piszę ___. (резюме)", "Fill in the missing word: Piszę ___. (CV)", + "CV", "first_letter", "C"), + ("a2_work_career_l04_q3", "a2_work_career_l04", "lesson_practice", "application", "szukac_pracy_vocabulary", 1, + "Zobaczyłeś w internecie informację o wolnym stanowisku pracy. Co to jest?", "Ты увидел в интернете информацию о вакантной должности. Что это?", "Ти побачив в інтернеті інформацію про вакантну посаду. Що це?", "You saw information about a job opening online. What is it?", + "D", None, None), + + # L05 — umiejetnosci_zawodowe (difficulty 2) + ("a2_work_career_l05_q1", "a2_work_career_l05", "lesson_practice", "recognition", "umiejetnosci_zawodowe", 2, + "Wybierz poprawną formę: Umiem ___. (programować)", "Выберите правильную форму: Umiem ___. (programować)", "Виберіть правильну форму: Umiem ___. (programować)", "Choose the correct form: Umiem ___. (programować)", + "C", None, None), + ("a2_work_career_l05_q2", "a2_work_career_l05", "lesson_practice", "production", "umiejetnosci_zawodowe", 2, + "Wpisz brakujące słowo: ___ angielski. (я знаю)", "Вставьте пропущенное слово: ___ angielski. (я знаю)", "Вставте пропущене слово: ___ angielski. (я знаю)", "Fill in the missing word: ___ angielski. (I know)", + "Znam", "first_letter", "Z"), + ("a2_work_career_l05_q3", "a2_work_career_l05", "lesson_practice", "application", "umiejetnosci_zawodowe", 2, + "Chcesz powiedzieć, że potrafisz mówić po niemiecku. Co powiesz?", "Ты хочешь сказать, что умеешь говорить по-немецки. Что ты скажешь?", "Ти хочеш сказати, що вмієш говорити німецькою. Що ти скажеш?", "You want to say you know how to speak German. What do you say?", + "A", None, None), + + # L06 — opisywac_doswiadczenie (difficulty 2) + ("a2_work_career_l06_q1", "a2_work_career_l06", "lesson_practice", "recognition", "opisywac_doswiadczenie", 2, + "Wybierz poprawną formę: Pracowałem w ___. (szkoła)", "Выберите правильную форму: Pracowałem w ___. (szkoła)", "Виберіть правильну форму: Pracowałem w ___. (szkoła)", "Choose the correct form: Pracowałem w ___. (szkoła)", + "D", None, None), + ("a2_work_career_l06_q2", "a2_work_career_l06", "lesson_practice", "production", "opisywac_doswiadczenie", 2, + "Wpisz brakujące słowo: Pracowałem w firmie ___ pięć lat. (в течение)", "Вставьте пропущенное слово: Pracowałem w firmie ___ pięć lat. (в течение)", "Вставте пропущене слово: Pracowałem w firmie ___ pięć lat. (протягом)", "Fill in the missing word: Pracowałem w firmie ___ pięć lat. (for)", + "przez", "first_letter", "p"), + ("a2_work_career_l06_q3", "a2_work_career_l06", "lesson_practice", "application", "opisywac_doswiadczenie", 2, + "Chcesz powiedzieć, że pracowałaś w szkole przez rok. Co powiesz?", "Ты хочешь сказать, что работала в школе в течение года. Что ты скажешь?", "Ти хочеш сказати, що працювала в школі протягом року. Що ти скажеш?", "You want to say you worked at a school for a year. What do you say?", + "B", None, None), + + # L07 — awans_i_zmiana_pracy (difficulty 2) + ("a2_work_career_l07_q1", "a2_work_career_l07", "lesson_practice", "recognition", "awans_i_zmiana_pracy", 2, + "Co znaczy „Dostałam podwyżkę”?", "Что означает «Dostałam podwyżkę»?", "Що означає «Dostałam podwyżkę»?", "What does “Dostałam podwyżkę” mean?", + "A", None, None), + ("a2_work_career_l07_q2", "a2_work_career_l07", "lesson_practice", "production", "awans_i_zmiana_pracy", 2, + "Wpisz brakujące słowo: Chcę ___ pracę. (сменить)", "Вставьте пропущенное слово: Chcę ___ pracę. (сменить)", "Вставте пропущене слово: Chcę ___ pracę. (змінити)", "Fill in the missing word: Chcę ___ pracę. (change)", + "zmienić", "first_letter", "z"), + ("a2_work_career_l07_q3", "a2_work_career_l07", "lesson_practice", "application", "awans_i_zmiana_pracy", 2, + "Dostałeś wyższe stanowisko w firmie. Co się stało?", "Ты получил более высокую должность в компании. Что произошло?", "Ти отримав вищу посаду в компанії. Що трапилося?", "You got a higher position at the company. What happened?", + "C", None, None), + + # L08 — warunki_pracy (difficulty 2) + ("a2_work_career_l08_q1", "a2_work_career_l08", "lesson_practice", "recognition", "warunki_pracy", 2, + "Jak po polsku „удалённо”?", "Как по-польски «удалённо»?", "Як польською «віддалено»?", "How do you say “remotely” in Polish?", + "B", None, None), + ("a2_work_career_l08_q2", "a2_work_career_l08", "lesson_practice", "production", "warunki_pracy", 2, + "Wpisz brakujące słowo: Pracuję na ___ etat. (полную)", "Вставьте пропущенное слово: Pracuję na ___ etat. (полную)", "Вставте пропущене слово: Pracuję na ___ etat. (повну)", "Fill in the missing word: Pracuję na ___ etat. (full)", + "pełny", "first_letter", "p"), + ("a2_work_career_l08_q3", "a2_work_career_l08", "lesson_practice", "application", "warunki_pracy", 2, + "Codziennie chodzisz do biura i tam pracujesz. Jak pracujesz?", "Ты каждый день ходишь в офис и там работаешь. Как ты работаешь?", "Ти щодня ходиш в офіс і там працюєш. Як ти працюєш?", "You go to the office every day and work there. How do you work?", + "D", None, None), + + # L09 — plany_zawodowe_przyszlosc (difficulty 3) + ("a2_work_career_l09_q1", "a2_work_career_l09", "lesson_practice", "recognition", "plany_zawodowe_przyszlosc", 3, + "Co znaczy „Chciałbym awansować”?", "Что означает «Chciałbym awansować»?", "Що означає «Chciałbym awansować»?", "What does “Chciałbym awansować” mean?", + "C", None, None), + ("a2_work_career_l09_q2", "a2_work_career_l09", "lesson_practice", "production", "plany_zawodowe_przyszlosc", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ zmienić pracę. (я хотела бы)", "Вставьте пропущенное слово (говорит женщина): ___ zmienić pracę. (я хотела бы)", "Вставте пропущене слово (говорить жінка): ___ zmienić pracę. (я хотіла б)", "Fill in the missing word (a woman is speaking): ___ zmienić pracę. (I would like)", + "Chciałabym", "first_letter", "C"), + ("a2_work_career_l09_q3", "a2_work_career_l09", "lesson_practice", "application", "plany_zawodowe_przyszlosc", 3, + "Mężczyzna grzecznie mówi o planie zmiany pracy. Co powie?", "Мужчина вежливо говорит о плане смены работы. Что он скажет?", "Чоловік ввічливо говорить про план зміни роботи. Що він скаже?", "A man politely talks about a plan to change jobs. What does he say?", + "A", None, None), + + # L10 — opisuje_swoja_kariere (difficulty 3) + ("a2_work_career_l10_q1", "a2_work_career_l10", "lesson_practice", "recognition", "opisuje_swoja_kariere", 3, + "Które zdanie poprawnie opisuje karierę?", "Какое предложение правильно описывает карьеру?", "Яке речення правильно описує кар'єру?", "Which sentence correctly describes a career?", + "D", None, None), + ("a2_work_career_l10_q2", "a2_work_career_l10", "lesson_practice", "production", "opisuje_swoja_kariere", 3, + "Przetłumacz: «Я хотел бы продвинуться по службе».", "Переведите: «Я хотел бы продвинуться по службе».", "Перекладіть: «Я хотів би просунутися по службі».", "Translate: “I would like to get promoted.”", + "Chciałbym awansować", "first_letter", "C"), + ("a2_work_career_l10_q3", "a2_work_career_l10", "lesson_practice", "application", "opisuje_swoja_kariere", 3, + "Chcesz opisać koledze swoją karierę: skończyłeś studia, pracowałeś w banku, teraz chcesz awansować. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою карьеру: ты закончил учёбу, работал в банке, теперь хочешь продвинуться по службе. Как ты начнёшь предложение?", "Ти хочеш описати другу свою кар'єру: ти закінчив навчання, працював у банку, тепер хочеш просунутися по службі. Як ти почнеш речення?", "You want to describe your career to a friend: you finished your studies, worked at a bank, now want a promotion. How do you start the sentence?", + "B", None, None), + ] + + for q in questions_t1_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_work_career', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t1_a2 = [ + # L01 + ("a2_work_career_l01_q1", "A", "kierownik", "руководитель", "керівник", "manager", False, "wrong_word"), + ("a2_work_career_l01_q1", "B", "księgowy", "бухгалтер", "бухгалтер", "accountant", False, "wrong_word"), + ("a2_work_career_l01_q1", "C", "prawnik", "юрист", "юрист", "lawyer", True, None), + ("a2_work_career_l01_q1", "D", "inżynier", "инженер", "інженер", "engineer", False, "wrong_word"), + + ("a2_work_career_l01_q3", "A", "kierownik", "руководитель", "керівник", "manager", True, None), + ("a2_work_career_l01_q3", "B", "księgowy", "бухгалтер", "бухгалтер", "accountant", False, "wrong_context"), + ("a2_work_career_l01_q3", "C", "prawnik", "юрист", "юрист", "lawyer", False, "wrong_context"), + ("a2_work_career_l01_q3", "D", "inżynier", "инженер", "інженер", "engineer", False, "wrong_context"), + + # L02 + ("a2_work_career_l02_q1", "A", "Jestem kierownikiem od dziś.", "Я стал руководителем с сегодняшнего дня.", "Я став керівником із сьогодні.", "I've been a manager since today.", False, "wrong_translation"), + ("a2_work_career_l02_q1", "B", "Chcę być kierownikiem.", "Я хочу быть руководителем.", "Я хочу бути керівником.", "I want to be a manager.", False, "wrong_translation"), + ("a2_work_career_l02_q1", "C", "Znam kierownika.", "Я знаю руководителя.", "Я знаю керівника.", "I know the manager.", False, "wrong_translation"), + ("a2_work_career_l02_q1", "D", "Pracuję jako kierownik.", "Я работаю руководителем.", "Я працюю керівником.", "I work as a manager.", True, None), + + ("a2_work_career_l02_q3", "A", "Pracuję jako prawnik.", "Я работаю юристом. (неверная профессия)", "Я працюю юристом. (невірна професія)", "I work as a lawyer. (wrong profession)", False, "wrong_context"), + ("a2_work_career_l02_q3", "B", "Pracuję jako księgowy.", "Я работаю бухгалтером.", "Я працюю бухгалтером.", "I work as an accountant.", True, None), + ("a2_work_career_l02_q3", "C", "Pracuję jako kierownik.", "Я работаю руководителем. (неверная профессия)", "Я працюю керівником. (невірна професія)", "I work as a manager. (wrong profession)", False, "wrong_context"), + ("a2_work_career_l02_q3", "D", "Pracuję jako inżynier.", "Я работаю инженером. (неверная профессия)", "Я працюю інженером. (невірна професія)", "I work as an engineer. (wrong profession)", False, "wrong_context"), + + # L03 + ("a2_work_career_l03_q1", "A", "pracowałem", "работал", "працював", "worked", True, None), + ("a2_work_career_l03_q1", "B", "pracowałam", "работала (форма для женщины)", "працювала (форма для жінки)", "worked (female form)", False, "wrong_gender"), + ("a2_work_career_l03_q1", "C", "pracuję", "работаю (настоящее время)", "працюю (теперішній час)", "work (present tense)", False, "wrong_sentence_type"), + ("a2_work_career_l03_q1", "D", "pracować", "работать (инф.)", "працювати (інф.)", "to work", False, "wrong_word"), + + ("a2_work_career_l03_q3", "A", "Uczę się na uniwersytecie.", "Я учусь в университете. (настоящее время)", "Я навчаюся в університеті. (теперішній час)", "I study at university. (present tense)", False, "wrong_sentence_type"), + ("a2_work_career_l03_q3", "B", "Będę się uczyć na uniwersytecie.", "Я буду учиться в университете. (будущее время)", "Я навчатимуся в університеті. (майбутній час)", "I will study at university. (future tense)", False, "wrong_sentence_type"), + ("a2_work_career_l03_q3", "C", "Uczyłem się na uniwersytecie.", "Я учился в университете.", "Я навчався в університеті.", "I studied at university.", True, None), + ("a2_work_career_l03_q3", "D", "Uczysz się na uniwersytecie.", "Ты учишься в университете. (не тот человек)", "Ти навчаєшся в університеті. (не та особа)", "You study at university. (wrong person)", False, "wrong_context"), + + # L04 + ("a2_work_career_l04_q1", "A", "ogłoszenie", "объявление", "оголошення", "job ad", False, "wrong_word"), + ("a2_work_career_l04_q1", "B", "rozmowa kwalifikacyjna", "собеседование", "співбесіда", "job interview", True, None), + ("a2_work_career_l04_q1", "C", "pracodawca", "работодатель", "роботодавець", "employer", False, "wrong_word"), + ("a2_work_career_l04_q1", "D", "CV", "резюме", "резюме", "CV", False, "wrong_word"), + + ("a2_work_career_l04_q3", "A", "rozmowa kwalifikacyjna", "собеседование", "співбесіда", "job interview", False, "wrong_context"), + ("a2_work_career_l04_q3", "B", "pracodawca", "работодатель", "роботодавець", "employer", False, "wrong_context"), + ("a2_work_career_l04_q3", "C", "CV", "резюме", "резюме", "CV", False, "wrong_context"), + ("a2_work_career_l04_q3", "D", "ogłoszenie", "объявление", "оголошення", "job ad", True, None), + + # L05 + ("a2_work_career_l05_q1", "A", "programuję", "программирую (настоящее время)", "програмую (теперішній час)", "I program (present tense)", False, "wrong_sentence_type"), + ("a2_work_career_l05_q1", "B", "programowanie", "программирование (сущ.)", "програмування (ім.)", "programming (noun)", False, "wrong_word"), + ("a2_work_career_l05_q1", "C", "programować", "программировать (инф.)", "програмувати (інф.)", "to program", True, None), + ("a2_work_career_l05_q1", "D", "programowałem", "программировал (прошедшее время)", "програмував (минулий час)", "I programmed (past tense)", False, "wrong_sentence_type"), + + ("a2_work_career_l05_q3", "A", "Umiem mówić po niemiecku.", "Я умею говорить по-немецки.", "Я вмію говорити німецькою.", "I know how to speak German.", True, None), + ("a2_work_career_l05_q3", "B", "Znam po niemiecku.", "Неправильная конструкция (нужен винительный без «po»).", "Неправильна конструкція (потрібен знахідний без «po»).", "Incorrect construction (needs the accusative without „po”).", False, "wrong_sentence_type"), + ("a2_work_career_l05_q3", "C", "Uczę się niemiecki.", "Неправильный падеж (нужен винительный «niemieckiego»).", "Неправильний відмінок (потрібен знахідний «niemieckiego»).", "Wrong case (needs the accusative „niemieckiego”).", False, "wrong_case"), + ("a2_work_career_l05_q3", "D", "Pracuję po niemiecku.", "Бессмысленное сочетание.", "Безглузде поєднання.", "Doesn't make sense.", False, "wrong_context"), + + # L06 + ("a2_work_career_l06_q1", "A", "szkoła", "школа (им.)", "школа (наз.)", "school (nom.)", False, "wrong_case"), + ("a2_work_career_l06_q1", "B", "szkoły", "школы (род.)", "школи (род.)", "school (gen.)", False, "wrong_case"), + ("a2_work_career_l06_q1", "C", "szkołę", "школу (вин.)", "школу (знах.)", "school (acc.)", False, "wrong_case"), + ("a2_work_career_l06_q1", "D", "szkole", "школе (местн.)", "школі (місц.)", "school (loc.)", True, None), + + ("a2_work_career_l06_q3", "A", "Pracuję w szkole przez rok.", "Я работаю в школе в течение года. (неверное время)", "Я працюю в школі протягом року. (невірний час)", "I work at a school for a year. (wrong tense)", False, "wrong_sentence_type"), + ("a2_work_career_l06_q3", "B", "Pracowałam w szkole przez rok.", "Я работала в школе в течение года.", "Я працювала в школі протягом року.", "I worked at a school for a year.", True, None), + ("a2_work_career_l06_q3", "C", "Będę pracować w szkole przez rok.", "Я буду работать в школе в течение года. (неверное время)", "Я працюватиму в школі протягом року. (невірний час)", "I will work at a school for a year. (wrong tense)", False, "wrong_sentence_type"), + ("a2_work_career_l06_q3", "D", "Pracowałam w banku przez rok.", "Я работала в банке в течение года. (неверное место)", "Я працювала в банку протягом року. (невірне місце)", "I worked at a bank for a year. (wrong place)", False, "wrong_word"), + + # L07 + ("a2_work_career_l07_q1", "A", "Dostałam podwyżkę.", "Я получила прибавку к зарплате.", "Я отримала підвищення зарплати.", "I got a raise.", True, None), + ("a2_work_career_l07_q1", "B", "Straciłam pracę.", "Я потеряла работу.", "Я втратила роботу.", "I lost my job.", False, "wrong_translation"), + ("a2_work_career_l07_q1", "C", "Zmieniłam pracę.", "Я сменила работу.", "Я змінила роботу.", "I changed jobs.", False, "wrong_translation"), + ("a2_work_career_l07_q1", "D", "Awansowałam.", "Я продвинулась по службе.", "Я просунулася по службі.", "I got promoted.", False, "wrong_translation"), + + ("a2_work_career_l07_q3", "A", "Straciłeś pracę.", "Ты потерял работу. (не соответствует ситуации)", "Ти втратив роботу. (не відповідає ситуації)", "You lost your job. (doesn't match the situation)", False, "wrong_context"), + ("a2_work_career_l07_q3", "B", "Dostałeś podwyżkę.", "Ты получил прибавку к зарплате. (не о должности)", "Ти отримав підвищення зарплати. (не про посаду)", "You got a raise. (not about a position)", False, "wrong_context"), + ("a2_work_career_l07_q3", "C", "Awansowałeś.", "Ты продвинулся по службе.", "Ти просунувся по службі.", "You got promoted.", True, None), + ("a2_work_career_l07_q3", "D", "Zmieniłeś pracę.", "Ты сменил работу. (не соответствует ситуации)", "Ти змінив роботу. (не відповідає ситуації)", "You changed jobs. (doesn't match the situation)", False, "wrong_context"), + + # L08 + ("a2_work_career_l08_q1", "A", "pełny etat", "полная занятость", "повна зайнятість", "full-time", False, "wrong_word"), + ("a2_work_career_l08_q1", "B", "zdalnie", "удалённо", "віддалено", "remotely", True, None), + ("a2_work_career_l08_q1", "C", "część etatu", "неполная занятость", "неповна зайнятість", "part-time", False, "wrong_word"), + ("a2_work_career_l08_q1", "D", "w biurze", "в офисе", "в офісі", "in the office", False, "wrong_word"), + + ("a2_work_career_l08_q3", "A", "zdalnie", "удалённо", "віддалено", "remotely", False, "wrong_context"), + ("a2_work_career_l08_q3", "B", "na część etatu", "на неполную ставку", "на неповну ставку", "part-time", False, "wrong_context"), + ("a2_work_career_l08_q3", "C", "w domu", "дома", "вдома", "at home", False, "wrong_context"), + ("a2_work_career_l08_q3", "D", "w biurze", "в офисе", "в офісі", "in the office", True, None), + + # L09 + ("a2_work_career_l09_q1", "A", "Awansowałem.", "Я продвинулся по службе. (прошедшее время)", "Я просунувся по службі. (минулий час)", "I got promoted. (past tense)", False, "wrong_translation"), + ("a2_work_career_l09_q1", "B", "Muszę awansować.", "Я должен продвинуться по службе.", "Я маю просунутися по службі.", "I have to get promoted.", False, "wrong_translation"), + ("a2_work_career_l09_q1", "C", "Chciałbym awansować.", "Я хотел бы продвинуться по службе.", "Я хотів би просунутися по службі.", "I would like to get promoted.", True, None), + ("a2_work_career_l09_q1", "D", "Awansuję jutro.", "Я продвинусь завтра. (будущее время)", "Я просунуся завтра. (майбутній час)", "I'll get promoted tomorrow. (future tense)", False, "wrong_translation"), + + ("a2_work_career_l09_q3", "A", "Chciałbym zmienić pracę.", "Я хотел бы сменить работу.", "Я хотів би змінити роботу.", "I would like to change jobs.", True, None), + ("a2_work_career_l09_q3", "B", "Chciałabym zmienić pracę.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + ("a2_work_career_l09_q3", "C", "Zmieniam pracę.", "Я меняю работу. (настоящее время, не вежливая форма)", "Я змінюю роботу. (теперішній час, не ввічлива форма)", "I'm changing jobs. (present tense, not the polite form)", False, "wrong_sentence_type"), + ("a2_work_career_l09_q3", "D", "Zmieniłem pracę.", "Я сменил работу. (прошедшее время, не о плане)", "Я змінив роботу. (минулий час, не про план)", "I changed jobs. (past tense, not about a plan)", False, "wrong_sentence_type"), + + # L10 + ("a2_work_career_l10_q1", "A", "Skończyłem studia i pracuje w banku.", "Неправильная форма глагола (pracuje вместо pracuję).", "Неправильна форма дієслова (pracuje замість pracuję).", "Wrong verb form (pracuje instead of pracuję).", False, "wrong_sentence_type"), + ("a2_work_career_l10_q1", "B", "Skończyłem studia i pracowałem bank.", "Пропущен предлог и неправильный падеж.", "Пропущено прийменник і неправильний відмінок.", "Missing preposition and wrong case.", False, "wrong_case"), + ("a2_work_career_l10_q1", "C", "Jestem skończyłem studia, teraz pracuję.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_work_career_l10_q1", "D", "Skończyłem studia i teraz pracuję jako kierownik.", "Я закончил учёбу и теперь работаю руководителем.", "Я закінчив навчання і тепер працюю керівником.", "I finished my studies and now I work as a manager.", True, None), + + ("a2_work_career_l10_q3", "A", "Chciałbym awansować.", "Я хотел бы продвинуться по службе. (не начало описания)", "Я хотів би просунутися по службі. (не початок опису)", "I would like to get promoted. (not the opening line)", False, "wrong_context"), + ("a2_work_career_l10_q3", "B", "Skończyłem studia.", "Я закончил учёбу.", "Я закінчив навчання.", "I finished my studies.", True, None), + ("a2_work_career_l10_q3", "C", "Pracowałem w banku przez trzy lata.", "Я работал в банке в течение трёх лет. (не начало описания)", "Я працював у банку протягом трьох років. (не початок опису)", "I worked at a bank for three years. (not the opening line)", False, "wrong_context"), + ("a2_work_career_l10_q3", "D", "Teraz pracuję jako kierownik.", "Сейчас я работаю руководителем. (не начало описания)", "Зараз я працюю керівником. (не початок опису)", "Now I work as a manager. (not the opening line)", False, "wrong_context"), + ] + + for opt in options_t1_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t1_a2 = [ + ("a2_work_career_t01", None, "topic_test", "recognition", "zawody_vocabulary", 1, + "Jak po polsku „юрист”?", "Как по-польски «юрист»?", "Як польською «юрист»?", "How do you say “lawyer” in Polish?", + "C", None, None, 1), + ("a2_work_career_t02", None, "topic_test", "recognition", "pracowac_jako", 1, + "Co znaczy „Pracuję jako kierownik”?", "Что означает «Pracuję jako kierownik»?", "Що означає «Pracuję jako kierownik»?", "What does “Pracuję jako kierownik” mean?", + "D", None, None, 2), + ("a2_work_career_t03", None, "topic_test", "recognition", "czas_przeszly_praca", 1, + "Wybierz poprawną formę (mężczyzna mówi): Wczoraj ___ w biurze. (pracować)", "Выберите правильную форму (говорит мужчина): Wczoraj ___ w biurze. (pracować)", "Виберіть правильну форму (говорить чоловік): Wczoraj ___ w biurze. (pracować)", "Choose the correct form (a man is speaking): Wczoraj ___ w biurze. (pracować)", + "A", None, None, 3), + ("a2_work_career_t04", None, "topic_test", "recognition", "szukac_pracy_vocabulary", 1, + "Jak po polsku „собеседование”?", "Как по-польски «собеседование»?", "Як польською «співбесіда»?", "How do you say “job interview” in Polish?", + "B", None, None, 4), + ("a2_work_career_t05", None, "topic_test", "recognition", "umiejetnosci_zawodowe", 2, + "Wybierz poprawną formę: Umiem ___. (programować)", "Выберите правильную форму: Umiem ___. (programować)", "Виберіть правильну форму: Umiem ___. (programować)", "Choose the correct form: Umiem ___. (programować)", + "C", None, None, 5), + ("a2_work_career_t06", None, "topic_test", "recognition", "plany_zawodowe_przyszlosc", 3, + "Co znaczy „Chciałbym awansować”?", "Что означает «Chciałbym awansować»?", "Що означає «Chciałbym awansować»?", "What does “Chciałbym awansować” mean?", + "C", None, None, 6), + + ("a2_work_career_t07", None, "topic_test", "application", "zawody_vocabulary", 1, + "Osoba zarządza zespołem w firmie. Kim ona jest?", "Человек управляет командой в компании. Кто он?", "Людина керує командою у компанії. Хто вона?", "A person manages a team at a company. What is their job?", + "A", None, None, 7), + ("a2_work_career_t08", None, "topic_test", "application", "pracowac_jako", 1, + "Kolega pyta, kim pracujesz. Pracujesz jako księgowy. Co powiesz?", "Друг спрашивает, кем ты работаешь. Ты работаешь бухгалтером. Что ты скажешь?", "Друг питає, ким ти працюєш. Ти працюєш бухгалтером. Що ти скажеш?", "A friend asks what your job is. You work as an accountant. What do you say?", + "B", None, None, 8), + ("a2_work_career_t09", None, "topic_test", "application", "czas_przeszly_praca", 1, + "Mężczyzna opowiada, że skończył naukę na uniwersytecie. Co powie?", "Мужчина рассказывает, что закончил учёбу в университете. Что он скажет?", "Чоловік розповідає, що закінчив навчання в університеті. Що він скаже?", "A man is telling that he finished studying at university. What does he say?", + "C", None, None, 9), + ("a2_work_career_t10", None, "topic_test", "application", "opisywac_doswiadczenie", 2, + "Chcesz powiedzieć, że pracowałaś w szkole przez rok. Co powiesz?", "Ты хочешь сказать, что работала в школе в течение года. Что ты скажешь?", "Ти хочеш сказати, що працювала в школі протягом року. Що ти скажеш?", "You want to say you worked at a school for a year. What do you say?", + "B", None, None, 10), + ("a2_work_career_t11", None, "topic_test", "application", "awans_i_zmiana_pracy", 2, + "Dostałeś wyższe stanowisko w firmie. Co się stało?", "Ты получил более высокую должность в компании. Что произошло?", "Ти отримав вищу посаду в компанії. Що трапилося?", "You got a higher position at the company. What happened?", + "C", None, None, 11), + ("a2_work_career_t12", None, "topic_test", "application", "plany_zawodowe_przyszlosc", 3, + "Mężczyzna grzecznie mówi o planie zmiany pracy. Co powie?", "Мужчина вежливо говорит о плане смены работы. Что он скажет?", "Чоловік ввічливо говорить про план зміни роботи. Що він скаже?", "A man politely talks about a plan to change jobs. What does he say?", + "A", None, None, 12), + + ("a2_work_career_t13", None, "topic_test", "production", "zawody_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (инженер)", "Вставьте пропущенное слово: To jest ___. (инженер)", "Вставте пропущене слово: To jest ___. (інженер)", "Fill in the missing word: To jest ___. (engineer)", + "inżynier", "first_letter", "i", 13), + ("a2_work_career_t14", None, "topic_test", "production", "szukac_pracy_vocabulary", 1, + "Wpisz brakujące słowo: Piszę ___. (резюме)", "Вставьте пропущенное слово: Piszę ___. (резюме)", "Вставте пропущене слово: Piszę ___. (резюме)", "Fill in the missing word: Piszę ___. (CV)", + "CV", "first_letter", "C", 14), + ("a2_work_career_t15", None, "topic_test", "production", "umiejetnosci_zawodowe", 2, + "Wpisz brakujące słowo: ___ angielski. (я знаю)", "Вставьте пропущенное слово: ___ angielski. (я знаю)", "Вставте пропущене слово: ___ angielski. (я знаю)", "Fill in the missing word: ___ angielski. (I know)", + "Znam", "first_letter", "Z", 15), + ("a2_work_career_t16", None, "topic_test", "production", "opisywac_doswiadczenie", 2, + "Wpisz brakujące słowo: Pracowałem w firmie ___ pięć lat. (в течение)", "Вставьте пропущенное слово: Pracowałem w firmie ___ pięć lat. (в течение)", "Вставте пропущене слово: Pracowałem w firmie ___ pięć lat. (протягом)", "Fill in the missing word: Pracowałem w firmie ___ pięć lat. (for)", + "przez", "first_letter", "p", 16), + ("a2_work_career_t17", None, "topic_test", "production", "awans_i_zmiana_pracy", 2, + "Wpisz brakujące słowo: Chcę ___ pracę. (сменить)", "Вставьте пропущенное слово: Chcę ___ pracę. (сменить)", "Вставте пропущене слово: Chcę ___ pracę. (змінити)", "Fill in the missing word: Chcę ___ pracę. (change)", + "zmienić", "first_letter", "z", 17), + ("a2_work_career_t18", None, "topic_test", "production", "opisuje_swoja_kariere", 3, + "Przetłumacz: «Я хотел бы продвинуться по службе».", "Переведите: «Я хотел бы продвинуться по службе».", "Перекладіть: «Я хотів би просунутися по службі».", "Translate: “I would like to get promoted.”", + "Chciałbym awansować", "first_letter", "C", 18), + + ("a2_work_career_t19", None, "topic_test", "mixed", "opisuje_swoja_kariere", 3, + "Wybierz poprawne tłumaczenie: «Я работал в банке в течение трёх лет, а теперь работаю как руководитель».", "Выберите правильный перевод: «Я работал в банке в течение трёх лет, а теперь работаю как руководитель».", "Виберіть правильний переклад: «Я працював у банку протягом трьох років, а тепер працюю керівником».", "Choose the correct translation: “I worked at a bank for three years, and now I work as a manager.”", + "C", None, None, 19), + ("a2_work_career_t20", None, "topic_test", "mixed", "pracowac_jako", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Кем ты работаешь? — Я работаю инженером, но хотел бы сменить работу.»", "Выберите правильный перевод диалога: «— Кем ты работаешь? — Я работаю инженером, но хотел бы сменить работу.»", "Виберіть правильний переклад діалогу: «— Ким ти працюєш? — Я працюю інженером, але хотів би змінити роботу.»", "Choose the correct translation of the dialogue: “— What's your job? — I work as an engineer, but I'd like to change jobs.”", + "B", None, None, 20), + ] + + for q in test_questions_t1_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_work_career', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t1_a2 = [ + ("a2_work_career_t01", "A", "kierownik", "руководитель", "керівник", "manager", False, "wrong_word"), + ("a2_work_career_t01", "B", "księgowy", "бухгалтер", "бухгалтер", "accountant", False, "wrong_word"), + ("a2_work_career_t01", "C", "prawnik", "юрист", "юрист", "lawyer", True, None), + ("a2_work_career_t01", "D", "inżynier", "инженер", "інженер", "engineer", False, "wrong_word"), + + ("a2_work_career_t02", "A", "Jestem kierownikiem od dziś.", "Я стал руководителем с сегодняшнего дня.", "Я став керівником із сьогодні.", "I've been a manager since today.", False, "wrong_translation"), + ("a2_work_career_t02", "B", "Chcę być kierownikiem.", "Я хочу быть руководителем.", "Я хочу бути керівником.", "I want to be a manager.", False, "wrong_translation"), + ("a2_work_career_t02", "C", "Znam kierownika.", "Я знаю руководителя.", "Я знаю керівника.", "I know the manager.", False, "wrong_translation"), + ("a2_work_career_t02", "D", "Pracuję jako kierownik.", "Я работаю руководителем.", "Я працюю керівником.", "I work as a manager.", True, None), + + ("a2_work_career_t03", "A", "pracowałem", "работал", "працював", "worked", True, None), + ("a2_work_career_t03", "B", "pracowałam", "работала (форма для женщины)", "працювала (форма для жінки)", "worked (female form)", False, "wrong_gender"), + ("a2_work_career_t03", "C", "pracuję", "работаю (настоящее время)", "працюю (теперішній час)", "work (present tense)", False, "wrong_sentence_type"), + ("a2_work_career_t03", "D", "pracować", "работать (инф.)", "працювати (інф.)", "to work", False, "wrong_word"), + + ("a2_work_career_t04", "A", "ogłoszenie", "объявление", "оголошення", "job ad", False, "wrong_word"), + ("a2_work_career_t04", "B", "rozmowa kwalifikacyjna", "собеседование", "співбесіда", "job interview", True, None), + ("a2_work_career_t04", "C", "pracodawca", "работодатель", "роботодавець", "employer", False, "wrong_word"), + ("a2_work_career_t04", "D", "CV", "резюме", "резюме", "CV", False, "wrong_word"), + + ("a2_work_career_t05", "A", "programuję", "программирую (настоящее время)", "програмую (теперішній час)", "I program (present tense)", False, "wrong_sentence_type"), + ("a2_work_career_t05", "B", "programowanie", "программирование (сущ.)", "програмування (ім.)", "programming (noun)", False, "wrong_word"), + ("a2_work_career_t05", "C", "programować", "программировать (инф.)", "програмувати (інф.)", "to program", True, None), + ("a2_work_career_t05", "D", "programowałem", "программировал (прошедшее время)", "програмував (минулий час)", "I programmed (past tense)", False, "wrong_sentence_type"), + + ("a2_work_career_t06", "A", "Awansowałem.", "Я продвинулся по службе. (прошедшее время)", "Я просунувся по службі. (минулий час)", "I got promoted. (past tense)", False, "wrong_translation"), + ("a2_work_career_t06", "B", "Muszę awansować.", "Я должен продвинуться по службе.", "Я маю просунутися по службі.", "I have to get promoted.", False, "wrong_translation"), + ("a2_work_career_t06", "C", "Chciałbym awansować.", "Я хотел бы продвинуться по службе.", "Я хотів би просунутися по службі.", "I would like to get promoted.", True, None), + ("a2_work_career_t06", "D", "Awansuję jutro.", "Я продвинусь завтра. (будущее время)", "Я просунуся завтра. (майбутній час)", "I'll get promoted tomorrow. (future tense)", False, "wrong_translation"), + + ("a2_work_career_t07", "A", "kierownik", "руководитель", "керівник", "manager", True, None), + ("a2_work_career_t07", "B", "księgowy", "бухгалтер", "бухгалтер", "accountant", False, "wrong_context"), + ("a2_work_career_t07", "C", "prawnik", "юрист", "юрист", "lawyer", False, "wrong_context"), + ("a2_work_career_t07", "D", "inżynier", "инженер", "інженер", "engineer", False, "wrong_context"), + + ("a2_work_career_t08", "A", "Pracuję jako prawnik.", "Я работаю юристом. (неверная профессия)", "Я працюю юристом. (невірна професія)", "I work as a lawyer. (wrong profession)", False, "wrong_context"), + ("a2_work_career_t08", "B", "Pracuję jako księgowy.", "Я работаю бухгалтером.", "Я працюю бухгалтером.", "I work as an accountant.", True, None), + ("a2_work_career_t08", "C", "Pracuję jako kierownik.", "Я работаю руководителем. (неверная профессия)", "Я працюю керівником. (невірна професія)", "I work as a manager. (wrong profession)", False, "wrong_context"), + ("a2_work_career_t08", "D", "Pracuję jako inżynier.", "Я работаю инженером. (неверная профессия)", "Я працюю інженером. (невірна професія)", "I work as an engineer. (wrong profession)", False, "wrong_context"), + + ("a2_work_career_t09", "A", "Uczę się na uniwersytecie.", "Я учусь в университете. (настоящее время)", "Я навчаюся в університеті. (теперішній час)", "I study at university. (present tense)", False, "wrong_sentence_type"), + ("a2_work_career_t09", "B", "Będę się uczyć na uniwersytecie.", "Я буду учиться в университете. (будущее время)", "Я навчатимуся в університеті. (майбутній час)", "I will study at university. (future tense)", False, "wrong_sentence_type"), + ("a2_work_career_t09", "C", "Uczyłem się na uniwersytecie.", "Я учился в университете.", "Я навчався в університеті.", "I studied at university.", True, None), + ("a2_work_career_t09", "D", "Uczysz się na uniwersytecie.", "Ты учишься в университете. (не тот человек)", "Ти навчаєшся в університеті. (не та особа)", "You study at university. (wrong person)", False, "wrong_context"), + + ("a2_work_career_t10", "A", "Pracuję w szkole przez rok.", "Я работаю в школе в течение года. (неверное время)", "Я працюю в школі протягом року. (невірний час)", "I work at a school for a year. (wrong tense)", False, "wrong_sentence_type"), + ("a2_work_career_t10", "B", "Pracowałam w szkole przez rok.", "Я работала в школе в течение года.", "Я працювала в школі протягом року.", "I worked at a school for a year.", True, None), + ("a2_work_career_t10", "C", "Będę pracować w szkole przez rok.", "Я буду работать в школе в течение года. (неверное время)", "Я працюватиму в школі протягом року. (невірний час)", "I will work at a school for a year. (wrong tense)", False, "wrong_sentence_type"), + ("a2_work_career_t10", "D", "Pracowałam w banku przez rok.", "Я работала в банке в течение года. (неверное место)", "Я працювала в банку протягом року. (невірне місце)", "I worked at a bank for a year. (wrong place)", False, "wrong_word"), + + ("a2_work_career_t11", "A", "Straciłeś pracę.", "Ты потерял работу. (не соответствует ситуации)", "Ти втратив роботу. (не відповідає ситуації)", "You lost your job. (doesn't match the situation)", False, "wrong_context"), + ("a2_work_career_t11", "B", "Dostałeś podwyżkę.", "Ты получил прибавку к зарплате. (не о должности)", "Ти отримав підвищення зарплати. (не про посаду)", "You got a raise. (not about a position)", False, "wrong_context"), + ("a2_work_career_t11", "C", "Awansowałeś.", "Ты продвинулся по службе.", "Ти просунувся по службі.", "You got promoted.", True, None), + ("a2_work_career_t11", "D", "Zmieniłeś pracę.", "Ты сменил работу. (не соответствует ситуации)", "Ти змінив роботу. (не відповідає ситуації)", "You changed jobs. (doesn't match the situation)", False, "wrong_context"), + + ("a2_work_career_t12", "A", "Chciałbym zmienić pracę.", "Я хотел бы сменить работу.", "Я хотів би змінити роботу.", "I would like to change jobs.", True, None), + ("a2_work_career_t12", "B", "Chciałabym zmienić pracę.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + ("a2_work_career_t12", "C", "Zmieniam pracę.", "Я меняю работу. (настоящее время, не вежливая форма)", "Я змінюю роботу. (теперішній час, не ввічлива форма)", "I'm changing jobs. (present tense, not the polite form)", False, "wrong_sentence_type"), + ("a2_work_career_t12", "D", "Zmieniłem pracę.", "Я сменил работу. (прошедшее время, не о плане)", "Я змінив роботу. (минулий час, не про план)", "I changed jobs. (past tense, not about a plan)", False, "wrong_sentence_type"), + + ("a2_work_career_t19", "A", "Pracuję w banku przez trzy lata, a teraz pracowałem jako kierownik.", "Времена перепутаны местами.", "Часи переплутані місцями.", "The tenses are swapped.", False, "wrong_sentence_type"), + ("a2_work_career_t19", "B", "Będę pracować w banku przez trzy lata, a teraz pracuję jako kierownik.", "Неправильное время (будущее вместо прошедшего).", "Неправильний час (майбутній замість минулого).", "Wrong tense (future instead of past).", False, "wrong_sentence_type"), + ("a2_work_career_t19", "C", "Pracowałem w banku przez trzy lata, a teraz pracuję jako kierownik.", "Я работал в банке в течение трёх лет, а теперь работаю руководителем.", "Я працював у банку протягом трьох років, а тепер працюю керівником.", "I worked at a bank for three years, and now I work as a manager.", True, None), + ("a2_work_career_t19", "D", "Pracowałem w szkole przez trzy lata, a teraz pracuję jako kierownik.", "Неправильное место (школа вместо банка).", "Неправильне місце (школа замість банку).", "Wrong place (school instead of bank).", False, "wrong_word"), + + ("a2_work_career_t20", "A", "Gdzie pracujesz? — Pracuję jako inżynier, ale chciałbym zmienić pracę.", "Неправильный вопрос («где» вместо «кем»).", "Неправильне питання («де» замість «ким»).", "Wrong question (“where” instead of “what's your job”).", False, "wrong_translation"), + ("a2_work_career_t20", "B", "Kim pracujesz? — Pracuję jako inżynier, ale chciałbym zmienić pracę.", "Кем ты работаешь? — Я работаю инженером, но хотел бы сменить работу.", "Ким ти працюєш? — Я працюю інженером, але хотів би змінити роботу.", "What's your job? — I work as an engineer, but I'd like to change jobs.", True, None), + ("a2_work_career_t20", "C", "Kim pracujesz? — Pracowałem jako inżynier, ale chcę zmienić pracę.", "Неправильное время в первой части ответа.", "Неправильний час у першій частині відповіді.", "Wrong tense in the first part of the answer.", False, "wrong_sentence_type"), + ("a2_work_career_t20", "D", "Kim pracujesz? — Pracuję jako prawnik, ale chciałbym zmienić pracę.", "Неправильная профессия (юрист вместо инженера).", "Неправильна професія (юрист замість інженера).", "Wrong profession (lawyer instead of engineer).", False, "wrong_word"), + ] + + for opt in test_options_t1_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 2 (A2): ЖИЛЬЁ И АРЕНДА ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_housing_rental', 'A2', 2, + 'Mieszkanie i wynajem', + 'Жильё и аренда', + 'Житло і оренда', + 'Housing and Rental') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t2_a2 = [ + ("a2_housing_rental_l01", 1, "mieszkanie_vocabulary", "Podstawowe słowa: mieszkanie", "Основные слова: квартира", "Основні слова: квартира", "Basic words: apartment", + "Podstawowe słowa dotyczące mieszkania: pokój, kuchnia, łazienka, balkon. „Pokój” i „balkon” są rodzaju męskiego, „kuchnia” i „łazienka” są rodzaju żeńskiego.", + "Основные слова, связанные с квартирой: pokój (комната), kuchnia (кухня), łazienka (ванная), balkon (балкон). „Pokój” и „balkon” мужского рода, „kuchnia” и „łazienka” женского рода.", + "Основні слова, пов'язані з квартирою: pokój (кімната), kuchnia (кухня), łazienka (ванна), balkon (балкон). „Pokój” і „balkon” чоловічого роду, „kuchnia” і „łazienka” жіночого роду.", + "Basic words related to an apartment: pokój (room), kuchnia (kitchen), łazienka (bathroom), balkon (balcony). „Pokój” and „balkon” are masculine, „kuchnia” and „łazienka” are feminine."), + + ("a2_housing_rental_l02", 2, "wynajmowac_mieszkanie", "Wynajmować + biernik", "Wynajmować + винительный падеж", "Wynajmować + знахідний відмінок", "Wynajmować + accusative", + "Czasownik „wynajmować” + biernik: wynajmuję mieszkanie, wynajmujesz pokój, wynajmuje dom.", + "Глагол „wynajmować” (снимать/сдавать) + винительный падеж: wynajmuję mieszkanie (я снимаю квартиру), wynajmujesz pokój (ты снимаешь комнату), wynajmuje dom (он/она снимает дом).", + "Дієслово „wynajmować” (знімати/здавати) + знахідний відмінок: wynajmuję mieszkanie (я знімаю квартиру), wynajmujesz pokój (ти знімаєш кімнату), wynajmuje dom (він/вона знімає будинок).", + "The verb „wynajmować” (to rent) + accusative: wynajmuję mieszkanie (I rent an apartment), wynajmujesz pokój (you rent a room), wynajmuje dom (he/she rents a house)."), + + ("a2_housing_rental_l03", 3, "czynsz_i_oplaty", "Słowa: czynsz i opłaty", "Слова: аренда и платежи", "Слова: оренда і платежі", "Words: rent and bills", + "Podstawowe słowa dotyczące płatności za mieszkanie: czynsz, rachunki, kaucja, umowa.", + "Основные слова о платежах за жильё: czynsz (арендная плата), rachunki (счета), kaucja (залог), umowa (договор).", + "Основні слова про платежі за житло: czynsz (орендна плата), rachunki (рахунки), kaucja (застава), umowa (договір).", + "Basic words about housing payments: czynsz (rent), rachunki (bills), kaucja (deposit), umowa (contract)."), + + ("a2_housing_rental_l04", 4, "opisywac_mieszkanie_przymiotniki", "Przymiotniki: opis mieszkania", "Прилагательные: описание квартиры", "Прикметники: опис квартири", "Adjectives: describing an apartment", + "Przymiotniki opisujące mieszkanie zgadzają się z rodzajem rzeczownika: duży pokój (męski), jasna kuchnia (żeński), ciasne mieszkanie (nijaki).", + "Прилагательные, описывающие квартиру, согласуются с родом существительного: duży pokój (мужской род — большая комната), jasna kuchnia (женский род — светлая кухня), ciasne mieszkanie (средний род — тесная квартира).", + "Прикметники, що описують квартиру, узгоджуються з родом іменника: duży pokój (чоловічий рід — велика кімната), jasna kuchnia (жіночий рід — світла кухня), ciasne mieszkanie (середній рід — тісна квартира).", + "Adjectives describing an apartment agree with the noun's gender: duży pokój (masculine — a big room), jasna kuchnia (feminine — a bright kitchen), ciasne mieszkanie (neuter — a cramped apartment)."), + + ("a2_housing_rental_l05", 5, "szukac_mieszkania", "Szukam + dopełniacz", "Szukam + родительный падеж", "Szukam + родовий відмінок", "Szukam + genitive", + "Czasownik „szukać” + dopełniacz: szukam mieszkania, szukam pokoju, szukam domu.", + "Глагол „szukać” (искать) + родительный падеж: szukam mieszkania (я ищу квартиру), szukam pokoju (я ищу комнату), szukam domu (я ищу дом).", + "Дієслово „szukać” (шукати) + родовий відмінок: szukam mieszkania (я шукаю квартиру), szukam pokoju (я шукаю кімнату), szukam domu (я шукаю будинок).", + "The verb „szukać” (to look for) + genitive: szukam mieszkania (I'm looking for an apartment), szukam pokoju (I'm looking for a room), szukam domu (I'm looking for a house)."), + + ("a2_housing_rental_l06", 6, "umowa_najmu", "Podpisywać umowę, płacić kaucję", "Подписывать договор, платить залог", "Підписувати договір, платити заставу", "Sign a contract, pay a deposit", + "Czasowniki dotyczące formalności najmu: podpisywać umowę (+ biernik), płacić kaucję (+ biernik).", + "Глаголы, связанные с оформлением аренды: podpisywać umowę (подписывать договор, + винительный падеж), płacić kaucję (платить залог, + винительный падеж).", + "Дієслова, пов'язані з оформленням оренди: podpisywać umowę (підписувати договір, + знахідний відмінок), płacić kaucję (платити заставу, + знахідний відмінок).", + "Verbs related to rental formalities: podpisywać umowę (to sign a contract, + accusative), płacić kaucję (to pay a deposit, + accusative)."), + + ("a2_housing_rental_l07", 7, "opisywac_lokalizacje", "Blisko/niedaleko + dopełniacz", "Blisko/niedaleko + родительный падеж", "Blisko/niedaleko + родовий відмінок", "Blisko/niedaleko + genitive", + "Przyimki „blisko” i „niedaleko” + dopełniacz opisują lokalizację: mieszkanie jest blisko centrum, niedaleko szkoły.", + "Предлоги „blisko” (близко) и „niedaleko” (недалеко) + родительный падеж описывают местоположение: mieszkanie jest blisko centrum (квартира рядом с центром), niedaleko szkoły (недалеко от школы).", + "Прийменники „blisko” (близько) і „niedaleko” (недалеко) + родовий відмінок описують місцезнаходження: mieszkanie jest blisko centrum (квартира близько центру), niedaleko szkoły (недалеко від школи).", + "The prepositions „blisko” (close to) and „niedaleko” (not far from) + genitive describe location: mieszkanie jest blisko centrum (the apartment is close to downtown), niedaleko szkoły (not far from the school)."), + + ("a2_housing_rental_l08", 8, "przeprowadzka", "Wprowadzać się / wyprowadzać się", "Wprowadzać się / wyprowadzać się", "Wprowadzać się / wyprowadzać się", "Wprowadzać się / wyprowadzać się", + "Czasowniki zwrotne dotyczące przeprowadzki: wprowadzać się do + dopełniacz (wprowadzam się do nowego mieszkania), wyprowadzać się z + dopełniacz (wyprowadzam się z tego mieszkania).", + "Возвратные глаголы, связанные с переездом: wprowadzać się do + родительный падеж (wprowadzam się do nowego mieszkania — я въезжаю в новую квартиру), wyprowadzać się z + родительный падеж (wyprowadzam się z tego mieszkania — я съезжаю из этой квартиры).", + "Зворотні дієслова, пов'язані з переїздом: wprowadzać się do + родовий відмінок (wprowadzam się do nowego mieszkania — я в'їжджаю в нову квартиру), wyprowadzać się z + родовий відмінок (wyprowadzam się z tego mieszkania — я виїжджаю з цієї квартири).", + "Reflexive verbs related to moving: wprowadzać się do + genitive (wprowadzam się do nowego mieszkania — I'm moving into a new apartment), wyprowadzać się z + genitive (wyprowadzam się z tego mieszkania — I'm moving out of this apartment)."), + + ("a2_housing_rental_l09", 9, "zdania_warunkowe_gdybym", "Gdybym + tryb przypuszczający", "Gdybym + сослагательное наклонение", "Gdybym + умовний спосіб", "Gdybym + conditional mood", + "Zdania warunkowe tworzymy słowem „gdybym” + forma przypuszczająca: gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie.", + "Условные предложения образуем словом „gdybym” (если бы я) + сослагательная форма: gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie (если бы у меня было больше денег, я снял бы квартиру побольше).", + "Умовні речення утворюємо словом „gdybym” (якби я) + умовна форма: gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie (якби в мене було більше грошей, я зняв би більшу квартиру).", + "We form conditional sentences with „gdybym” (if I) + conditional form: gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie (if I had more money, I would rent a bigger apartment)."), + + ("a2_housing_rental_l10", 10, "opisuje_swoje_mieszkanie", "Opisuję swoje mieszkanie", "Описываю свою квартиру", "Описую свою квартиру", "Describing my apartment", + "Żeby opisać swoje mieszkanie, łączymy zdania: Wynajmuję mieszkanie blisko centrum. Mam duży pokój i jasną kuchnię. Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie.", + "Чтобы описать свою квартиру, соединяем предложения: Wynajmuję mieszkanie blisko centrum. Mam duży pokój i jasną kuchnię. Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie. (Я снимаю квартиру рядом с центром. У меня большая комната и светлая кухня. Если бы у меня было больше денег, я снял бы квартиру побольше.)", + "Щоб описати свою квартиру, поєднуємо речення: Wynajmuję mieszkanie blisko centrum. Mam duży pokój i jasną kuchnię. Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie. (Я знімаю квартиру близько центру. У мене велика кімната і світла кухня. Якби в мене було більше грошей, я зняв би більшу квартиру.)", + "To describe your apartment, we combine sentences: Wynajmuję mieszkanie blisko centrum. Mam duży pokój i jasną kuchnię. Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie. (I rent an apartment close to downtown. I have a big room and a bright kitchen. If I had more money, I would rent a bigger apartment.)"), + ] + + for lesson in lessons_t2_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_housing_rental', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t2_a2 = [ + ("a2_housing_rental_l01", 1, "To jest pokój.", "Это комната.", "Це кімната.", "This is a room."), + ("a2_housing_rental_l01", 2, "To jest kuchnia.", "Это кухня.", "Це кухня.", "This is a kitchen."), + ("a2_housing_rental_l01", 3, "To jest balkon.", "Это балкон.", "Це балкон.", "This is a balcony."), + + ("a2_housing_rental_l02", 1, "Wynajmuję mieszkanie.", "Я снимаю квартиру.", "Я знімаю квартиру.", "I rent an apartment."), + ("a2_housing_rental_l02", 2, "Wynajmujesz pokój?", "Ты снимаешь комнату?", "Ти знімаєш кімнату?", "Do you rent a room?"), + ("a2_housing_rental_l02", 3, "On wynajmuje dom.", "Он снимает дом.", "Він знімає будинок.", "He rents a house."), + + ("a2_housing_rental_l03", 1, "Płacę czynsz co miesiąc.", "Я плачу арендную плату каждый месяц.", "Я плачу орендну плату щомісяця.", "I pay rent every month."), + ("a2_housing_rental_l03", 2, "Rachunki są wysokie.", "Счета высокие.", "Рахунки високі.", "The bills are high."), + ("a2_housing_rental_l03", 3, "Muszę zapłacić kaucję.", "Мне нужно заплатить залог.", "Мені потрібно сплатити заставу.", "I have to pay a deposit."), + + ("a2_housing_rental_l04", 1, "To jest duży pokój.", "Это большая комната.", "Це велика кімната.", "This is a big room."), + ("a2_housing_rental_l04", 2, "To jest jasna kuchnia.", "Это светлая кухня.", "Це світла кухня.", "This is a bright kitchen."), + ("a2_housing_rental_l04", 3, "To jest ciasne mieszkanie.", "Это тесная квартира.", "Це тісна квартира.", "This is a cramped apartment."), + + ("a2_housing_rental_l05", 1, "Szukam mieszkania.", "Я ищу квартиру.", "Я шукаю квартиру.", "I'm looking for an apartment."), + ("a2_housing_rental_l05", 2, "Szukasz pokoju?", "Ты ищешь комнату?", "Ти шукаєш кімнату?", "Are you looking for a room?"), + ("a2_housing_rental_l05", 3, "Ona szuka domu.", "Она ищет дом.", "Вона шукає будинок.", "She's looking for a house."), + + ("a2_housing_rental_l06", 1, "Podpisuję umowę.", "Я подписываю договор.", "Я підписую договір.", "I'm signing the contract."), + ("a2_housing_rental_l06", 2, "Płacisz kaucję?", "Ты платишь залог?", "Ти платиш заставу?", "Are you paying the deposit?"), + ("a2_housing_rental_l06", 3, "On podpisał umowę wczoraj.", "Он подписал договор вчера.", "Він підписав договір учора.", "He signed the contract yesterday."), + + ("a2_housing_rental_l07", 1, "Mieszkanie jest blisko centrum.", "Квартира рядом с центром.", "Квартира близько центру.", "The apartment is close to downtown."), + ("a2_housing_rental_l07", 2, "Szkoła jest niedaleko domu.", "Школа недалеко от дома.", "Школа недалеко від будинку.", "The school is not far from home."), + ("a2_housing_rental_l07", 3, "Sklep jest blisko przystanku.", "Магазин рядом с остановкой.", "Магазин близько зупинки.", "The shop is close to the bus stop."), + + ("a2_housing_rental_l08", 1, "Wprowadzam się do nowego mieszkania.", "Я въезжаю в новую квартиру.", "Я в'їжджаю в нову квартиру.", "I'm moving into a new apartment."), + ("a2_housing_rental_l08", 2, "Wyprowadzasz się z tego mieszkania?", "Ты съезжаешь из этой квартиры?", "Ти виїжджаєш з цієї квартири?", "Are you moving out of this apartment?"), + ("a2_housing_rental_l08", 3, "Oni wprowadzają się w sobotę.", "Они въезжают в субботу.", "Вони в'їжджають у суботу.", "They're moving in on Saturday."), + + ("a2_housing_rental_l09", 1, "Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie.", "Если бы у меня было больше денег, я снял бы квартиру побольше.", "Якби в мене було більше грошей, я зняв би більшу квартиру.", "If I had more money, I would rent a bigger apartment."), + ("a2_housing_rental_l09", 2, "Gdybyś miała czas, obejrzałabyś to mieszkanie.", "Если бы у тебя было время, ты бы посмотрела эту квартиру.", "Якби в тебе був час, ти б подивилася цю квартиру.", "If you had time, you would view this apartment."), + ("a2_housing_rental_l09", 3, "Gdyby mieszkanie było tańsze, wynajęlibyśmy je.", "Если бы квартира была дешевле, мы бы её сняли.", "Якби квартира була дешевшою, ми б її зняли.", "If the apartment were cheaper, we would rent it."), + + ("a2_housing_rental_l10", 1, "Wynajmuję mieszkanie blisko centrum.", "Я снимаю квартиру рядом с центром.", "Я знімаю квартиру близько центру.", "I rent an apartment close to downtown."), + ("a2_housing_rental_l10", 2, "Mam duży pokój i jasną kuchnię.", "У меня большая комната и светлая кухня.", "У мене велика кімната і світла кухня.", "I have a big room and a bright kitchen."), + ("a2_housing_rental_l10", 3, "Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie.", "Если бы у меня было больше денег, я снял бы квартиру побольше.", "Якби в мене було більше грошей, я зняв би більшу квартиру.", "If I had more money, I would rent a bigger apartment."), + ] + + for ex in examples_t2_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t2_a2 = [ + # L01 — mieszkanie_vocabulary (difficulty 1) + ("a2_housing_rental_l01_q1", "a2_housing_rental_l01", "lesson_practice", "recognition", "mieszkanie_vocabulary", 1, + "Jak po polsku „кухня”?", "Как по-польски «кухня»?", "Як польською «кухня»?", "How do you say “kitchen” in Polish?", + "B", None, None), + ("a2_housing_rental_l01_q2", "a2_housing_rental_l01", "lesson_practice", "production", "mieszkanie_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (балкон)", "Вставьте пропущенное слово: To jest ___. (балкон)", "Вставте пропущене слово: To jest ___. (балкон)", "Fill in the missing word: To jest ___. (balcony)", + "balkon", "first_letter", "b"), + ("a2_housing_rental_l01_q3", "a2_housing_rental_l01", "lesson_practice", "application", "mieszkanie_vocabulary", 1, + "Chcesz wziąć prysznic. Dokąd idziesz?", "Ты хочешь принять душ. Куда ты идёшь?", "Ти хочеш прийняти душ. Куди ти йдеш?", "You want to take a shower. Where do you go?", + "D", None, None), + + # L02 — wynajmowac_mieszkanie (difficulty 1) + ("a2_housing_rental_l02_q1", "a2_housing_rental_l02", "lesson_practice", "recognition", "wynajmowac_mieszkanie", 1, + "Co znaczy „Wynajmuję mieszkanie”?", "Что означает «Wynajmuję mieszkanie»?", "Що означає «Wynajmuję mieszkanie»?", "What does “Wynajmuję mieszkanie” mean?", + "A", None, None), + ("a2_housing_rental_l02_q2", "a2_housing_rental_l02", "lesson_practice", "production", "wynajmowac_mieszkanie", 1, + "Wpisz brakujące słowo: Wynajmujesz ___? (комнату)", "Вставьте пропущенное слово: Wynajmujesz ___? (комнату)", "Вставте пропущене слово: Wynajmujesz ___? (кімнату)", "Fill in the missing word: Wynajmujesz ___? (a room)", + "pokój", "first_letter", "p"), + ("a2_housing_rental_l02_q3", "a2_housing_rental_l02", "lesson_practice", "application", "wynajmowac_mieszkanie", 1, + "Kolega pyta, co wynajmujesz. Wynajmujesz dom. Co powiesz?", "Друг спрашивает, что ты снимаешь. Ты снимаешь дом. Что ты скажешь?", "Друг питає, що ти знімаєш. Ти знімаєш будинок. Що ти скажеш?", "A friend asks what you're renting. You're renting a house. What do you say?", + "C", None, None), + + # L03 — czynsz_i_oplaty (difficulty 1) + ("a2_housing_rental_l03_q1", "a2_housing_rental_l03", "lesson_practice", "recognition", "czynsz_i_oplaty", 1, + "Jak po polsku „залог”?", "Как по-польски «залог»?", "Як польською «застава»?", "How do you say “deposit” in Polish?", + "D", None, None), + ("a2_housing_rental_l03_q2", "a2_housing_rental_l03", "lesson_practice", "production", "czynsz_i_oplaty", 1, + "Wpisz brakujące słowo: Płacę ___ co miesiąc. (арендную плату)", "Вставьте пропущенное слово: Płacę ___ co miesiąc. (арендную плату)", "Вставте пропущене слово: Płacę ___ co miesiąc. (орендну плату)", "Fill in the missing word: Płacę ___ co miesiąc. (rent)", + "czynsz", "first_letter", "c"), + ("a2_housing_rental_l03_q3", "a2_housing_rental_l03", "lesson_practice", "application", "czynsz_i_oplaty", 1, + "Musisz zapłacić za prąd i wodę. Co to jest?", "Тебе нужно заплатить за электричество и воду. Что это?", "Тобі треба заплатити за електрику і воду. Що це?", "You have to pay for electricity and water. What is this?", + "B", None, None), + + # L04 — opisywac_mieszkanie_przymiotniki (difficulty 1) + ("a2_housing_rental_l04_q1", "a2_housing_rental_l04", "lesson_practice", "recognition", "opisywac_mieszkanie_przymiotniki", 1, + "Wybierz poprawną formę: To jest ___ kuchnia. (jasny)", "Выберите правильную форму: To jest ___ kuchnia. (jasny)", "Виберіть правильну форму: To jest ___ kuchnia. (jasny)", "Choose the correct form: To jest ___ kuchnia. (jasny)", + "C", None, None), + ("a2_housing_rental_l04_q2", "a2_housing_rental_l04", "lesson_practice", "production", "opisywac_mieszkanie_przymiotniki", 1, + "Wpisz brakujące słowo: To jest ___ pokój. (большой)", "Вставьте пропущенное слово: To jest ___ pokój. (большой)", "Вставте пропущене слово: To jest ___ pokój. (великий)", "Fill in the missing word: To jest ___ pokój. (big)", + "duży", "first_letter", "d"), + ("a2_housing_rental_l04_q3", "a2_housing_rental_l04", "lesson_practice", "application", "opisywac_mieszkanie_przymiotniki", 1, + "Twoje mieszkanie ma mało miejsca, jest bardzo małe. Jak je opiszesz?", "Твоя квартира тесная, в ней мало места. Как ты её опишешь?", "Твоя квартира тісна, в ній мало місця. Як ти її опишеш?", "Your apartment has little space, it's very small. How do you describe it?", + "A", None, None), + + # L05 — szukac_mieszkania (difficulty 2) + ("a2_housing_rental_l05_q1", "a2_housing_rental_l05", "lesson_practice", "recognition", "szukac_mieszkania", 2, + "Wybierz poprawną formę: Szukam ___. (mieszkanie)", "Выберите правильную форму: Szukam ___. (mieszkanie)", "Виберіть правильну форму: Szukam ___. (mieszkanie)", "Choose the correct form: Szukam ___. (mieszkanie)", + "B", None, None), + ("a2_housing_rental_l05_q2", "a2_housing_rental_l05", "lesson_practice", "production", "szukac_mieszkania", 2, + "Wpisz brakujące słowo: Szukam ___. (дома)", "Вставьте пропущенное слово: Szukam ___. (дома)", "Вставте пропущене слово: Szukam ___. (будинку)", "Fill in the missing word: Szukam ___. (a house)", + "domu", "first_letter", "d"), + ("a2_housing_rental_l05_q3", "a2_housing_rental_l05", "lesson_practice", "application", "szukac_mieszkania", 2, + "Chcesz wynająć pokój i zaczynasz go szukać. Co powiesz?", "Ты хочешь снять комнату и начинаешь её искать. Что ты скажешь?", "Ти хочеш зняти кімнату і починаєш її шукати. Що ти скажеш?", "You want to rent a room and start looking for one. What do you say?", + "D", None, None), + + # L06 — umowa_najmu (difficulty 2) + ("a2_housing_rental_l06_q1", "a2_housing_rental_l06", "lesson_practice", "recognition", "umowa_najmu", 2, + "Wybierz poprawną formę: Podpisuję ___. (umowa)", "Выберите правильную форму: Podpisuję ___. (umowa)", "Виберіть правильну форму: Podpisuję ___. (umowa)", "Choose the correct form: Podpisuję ___. (umowa)", + "A", None, None), + ("a2_housing_rental_l06_q2", "a2_housing_rental_l06", "lesson_practice", "production", "umowa_najmu", 2, + "Wpisz brakujące słowo: Muszę zapłacić ___. (залог)", "Вставьте пропущенное слово: Muszę zapłacić ___. (залог)", "Вставте пропущене слово: Muszę zapłacić ___. (заставу)", "Fill in the missing word: Muszę zapłacić ___. (deposit)", + "kaucję", "first_letter", "k"), + ("a2_housing_rental_l06_q3", "a2_housing_rental_l06", "lesson_practice", "application", "umowa_najmu", 2, + "Chcesz formalnie potwierdzić najem podpisem. Co robisz?", "Ты хочешь формально подтвердить аренду подписью. Что ты делаешь?", "Ти хочеш формально підтвердити оренду підписом. Що ти робиш?", "You want to formally confirm the lease with a signature. What are you doing?", + "C", None, None), + + # L07 — opisywac_lokalizacje (difficulty 2) + ("a2_housing_rental_l07_q1", "a2_housing_rental_l07", "lesson_practice", "recognition", "opisywac_lokalizacje", 2, + "Wybierz poprawną formę: Mieszkanie jest niedaleko ___. (szkoła)", "Выберите правильную форму: Mieszkanie jest niedaleko ___. (szkoła)", "Виберіть правильну форму: Mieszkanie jest niedaleko ___. (szkoła)", "Choose the correct form: Mieszkanie jest niedaleko ___. (szkoła)", + "D", None, None), + ("a2_housing_rental_l07_q2", "a2_housing_rental_l07", "lesson_practice", "production", "opisywac_lokalizacje", 2, + "Wpisz brakujące słowo: Sklep jest ___ przystanku. (рядом)", "Вставьте пропущенное слово: Sklep jest ___ przystanku. (рядом)", "Вставте пропущене слово: Sklep jest ___ przystanku. (близько)", "Fill in the missing word: Sklep jest ___ przystanku. (close to)", + "blisko", "first_letter", "b"), + ("a2_housing_rental_l07_q3", "a2_housing_rental_l07", "lesson_practice", "application", "opisywac_lokalizacje", 2, + "Twoje mieszkanie jest bardzo blisko szkoły, prawie obok. Jak to opiszesz?", "Твоя квартира очень близко к школе, почти рядом. Как ты это опишешь?", "Твоя квартира дуже близько до школи, майже поруч. Як ти це опишеш?", "Your apartment is very close to the school, almost next to it. How do you describe it?", + "B", None, None), + + # L08 — przeprowadzka (difficulty 2) + ("a2_housing_rental_l08_q1", "a2_housing_rental_l08", "lesson_practice", "recognition", "przeprowadzka", 2, + "Co znaczy „Wyprowadzam się z tego mieszkania”?", "Что означает «Wyprowadzam się z tego mieszkania»?", "Що означає «Wyprowadzam się z tego mieszkania»?", "What does “Wyprowadzam się z tego mieszkania” mean?", + "C", None, None), + ("a2_housing_rental_l08_q2", "a2_housing_rental_l08", "lesson_practice", "production", "przeprowadzka", 2, + "Wpisz brakujące słowo: Wprowadzam się ___ nowego mieszkania. (в)", "Вставьте пропущенное слово: Wprowadzam się ___ nowego mieszkania. (в)", "Вставте пропущене слово: Wprowadzam się ___ nowego mieszkania. (в)", "Fill in the missing word: Wprowadzam się ___ nowego mieszkania. (into)", + "do", "first_letter", "d"), + ("a2_housing_rental_l08_q3", "a2_housing_rental_l08", "lesson_practice", "application", "przeprowadzka", 2, + "Kupiłeś nowe mieszkanie i teraz się tam przenosisz. Co robisz?", "Ты купил новую квартиру и теперь туда переезжаешь. Что ты делаешь?", "Ти купив нову квартиру і тепер туди переїжджаєш. Що ти робиш?", "You bought a new apartment and are now moving there. What are you doing?", + "A", None, None), + + # L09 — zdania_warunkowe_gdybym (difficulty 3) + ("a2_housing_rental_l09_q1", "a2_housing_rental_l09", "lesson_practice", "recognition", "zdania_warunkowe_gdybym", 3, + "Co znaczy „Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie”?", "Что означает «Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie»?", "Що означає «Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie»?", "What does “Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie” mean?", + "B", None, None), + ("a2_housing_rental_l09_q2", "a2_housing_rental_l09", "lesson_practice", "production", "zdania_warunkowe_gdybym", 3, + "Wpisz brakujące słowo (kobieta mówi): Gdybym ___ czas, obejrzałabym to mieszkanie. (имела)", "Вставьте пропущенное слово (говорит женщина): Gdybym ___ czas, obejrzałabym to mieszkanie. (имела)", "Вставте пропущене слово (говорить жінка): Gdybym ___ czas, obejrzałabym to mieszkanie. (мала)", "Fill in the missing word (a woman is speaking): Gdybym ___ czas, obejrzałabym to mieszkanie. (had)", + "miała", "first_letter", "m"), + ("a2_housing_rental_l09_q3", "a2_housing_rental_l09", "lesson_practice", "application", "zdania_warunkowe_gdybym", 3, + "Chcesz powiedzieć, że gdyby mieszkanie było tańsze, wynajęlibyście je. Co powiesz?", "Ты хочешь сказать, что если бы квартира была дешевле, вы бы её сняли. Что ты скажешь?", "Ти хочеш сказати, що якби квартира була дешевшою, ви б її зняли. Що ти скажеш?", "You want to say that if the apartment were cheaper, you would rent it. What do you say?", + "D", None, None), + + # L10 — opisuje_swoje_mieszkanie (difficulty 3) + ("a2_housing_rental_l10_q1", "a2_housing_rental_l10", "lesson_practice", "recognition", "opisuje_swoje_mieszkanie", 3, + "Które zdanie poprawnie opisuje mieszkanie?", "Какое предложение правильно описывает квартиру?", "Яке речення правильно описує квартиру?", "Which sentence correctly describes an apartment?", + "A", None, None), + ("a2_housing_rental_l10_q2", "a2_housing_rental_l10", "lesson_practice", "production", "opisuje_swoje_mieszkanie", 3, + "Przetłumacz: «Если бы у меня было больше денег, я снял бы квартиру побольше».", "Переведите: «Если бы у меня было больше денег, я снял бы квартиру побольше».", "Перекладіть: «Якби в мене було більше грошей, я зняв би більшу квартиру».", "Translate: “If I had more money, I would rent a bigger apartment.”", + "Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie", "first_letter", "G"), + ("a2_housing_rental_l10_q3", "a2_housing_rental_l10", "lesson_practice", "application", "opisuje_swoje_mieszkanie", 3, + "Chcesz opisać koledze swoje mieszkanie: wynajmujesz je blisko centrum, masz duży pokój i jasną kuchnię. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою квартиру: ты снимаешь её рядом с центром, у тебя большая комната и светлая кухня. Как ты начнёшь предложение?", "Ти хочеш описати другу свою квартиру: ти знімаєш її близько центру, у тебе велика кімната і світла кухня. Як ти почнеш речення?", "You want to describe your apartment to a friend: you rent it close to downtown, you have a big room and a bright kitchen. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t2_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_housing_rental', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t2_a2 = [ + # L01 + ("a2_housing_rental_l01_q1", "A", "pokój", "комната", "кімната", "room", False, "wrong_word"), + ("a2_housing_rental_l01_q1", "B", "kuchnia", "кухня", "кухня", "kitchen", True, None), + ("a2_housing_rental_l01_q1", "C", "łazienka", "ванная", "ванна", "bathroom", False, "wrong_word"), + ("a2_housing_rental_l01_q1", "D", "balkon", "балкон", "балкон", "balcony", False, "wrong_word"), + + ("a2_housing_rental_l01_q3", "A", "pokój", "комната", "кімната", "room", False, "wrong_context"), + ("a2_housing_rental_l01_q3", "B", "kuchnia", "кухня", "кухня", "kitchen", False, "wrong_context"), + ("a2_housing_rental_l01_q3", "C", "balkon", "балкон", "балкон", "balcony", False, "wrong_context"), + ("a2_housing_rental_l01_q3", "D", "łazienka", "ванная", "ванна", "bathroom", True, None), + + # L02 + ("a2_housing_rental_l02_q1", "A", "Wynajmuję mieszkanie.", "Я снимаю квартиру.", "Я знімаю квартиру.", "I rent an apartment.", True, None), + ("a2_housing_rental_l02_q1", "B", "Sprzedaję mieszkanie.", "Я продаю квартиру.", "Я продаю квартиру.", "I'm selling an apartment.", False, "wrong_translation"), + ("a2_housing_rental_l02_q1", "C", "Kupuję mieszkanie.", "Я покупаю квартиру.", "Я купую квартиру.", "I'm buying an apartment.", False, "wrong_translation"), + ("a2_housing_rental_l02_q1", "D", "Szukam mieszkania.", "Я ищу квартиру.", "Я шукаю квартиру.", "I'm looking for an apartment.", False, "wrong_translation"), + + ("a2_housing_rental_l02_q3", "A", "Wynajmuję mieszkanie.", "Я снимаю квартиру. (неверный тип жилья)", "Я знімаю квартиру. (невірний тип житла)", "I rent an apartment. (wrong type of housing)", False, "wrong_context"), + ("a2_housing_rental_l02_q3", "B", "Wynajmuję pokój.", "Я снимаю комнату. (неверный тип жилья)", "Я знімаю кімнату. (невірний тип житла)", "I rent a room. (wrong type of housing)", False, "wrong_context"), + ("a2_housing_rental_l02_q3", "C", "Wynajmuję dom.", "Я снимаю дом.", "Я знімаю будинок.", "I rent a house.", True, None), + ("a2_housing_rental_l02_q3", "D", "Kupuję dom.", "Я покупаю дом. (неверный глагол)", "Я купую будинок. (невірне дієслово)", "I'm buying a house. (wrong verb)", False, "wrong_context"), + + # L03 + ("a2_housing_rental_l03_q1", "A", "czynsz", "арендная плата", "орендна плата", "rent", False, "wrong_word"), + ("a2_housing_rental_l03_q1", "B", "rachunki", "счета", "рахунки", "bills", False, "wrong_word"), + ("a2_housing_rental_l03_q1", "C", "umowa", "договор", "договір", "contract", False, "wrong_word"), + ("a2_housing_rental_l03_q1", "D", "kaucja", "залог", "застава", "deposit", True, None), + + ("a2_housing_rental_l03_q3", "A", "czynsz", "арендная плата", "орендна плата", "rent", False, "wrong_context"), + ("a2_housing_rental_l03_q3", "B", "rachunki", "счета", "рахунки", "bills", True, None), + ("a2_housing_rental_l03_q3", "C", "kaucja", "залог", "застава", "deposit", False, "wrong_context"), + ("a2_housing_rental_l03_q3", "D", "umowa", "договор", "договір", "contract", False, "wrong_context"), + + # L04 + ("a2_housing_rental_l04_q1", "A", "jasny", "светлый (м.р.)", "світлий (чол.р.)", "bright (masc.)", False, "wrong_gender"), + ("a2_housing_rental_l04_q1", "B", "jasne", "светлое (ср.р.)", "світле (сер.р.)", "bright (neut.)", False, "wrong_gender"), + ("a2_housing_rental_l04_q1", "C", "jasna", "светлая (ж.р.)", "світла (жін.р.)", "bright (fem.)", True, None), + ("a2_housing_rental_l04_q1", "D", "jasnego", "неправильная форма", "неправильна форма", "wrong form", False, "wrong_case"), + + ("a2_housing_rental_l04_q3", "A", "To jest ciasne mieszkanie.", "Это тесная квартира.", "Це тісна квартира.", "This is a cramped apartment.", True, None), + ("a2_housing_rental_l04_q3", "B", "To jest duże mieszkanie.", "Это большая квартира. (противоречит ситуации)", "Це велика квартира. (суперечить ситуації)", "This is a big apartment. (contradicts the situation)", False, "wrong_context"), + ("a2_housing_rental_l04_q3", "C", "To jest jasne mieszkanie.", "Это светлая квартира. (не о размере)", "Це світла квартира. (не про розмір)", "This is a bright apartment. (not about size)", False, "wrong_context"), + ("a2_housing_rental_l04_q3", "D", "To jest wygodne mieszkanie.", "Это удобная квартира. (не о размере)", "Це зручна квартира. (не про розмір)", "This is a comfortable apartment. (not about size)", False, "wrong_context"), + + # L05 + ("a2_housing_rental_l05_q1", "A", "mieszkanie", "квартира (им.)", "квартира (наз.)", "apartment (nom.)", False, "wrong_case"), + ("a2_housing_rental_l05_q1", "B", "mieszkania", "квартиры (род.)", "квартири (род.)", "apartment (gen.)", True, None), + ("a2_housing_rental_l05_q1", "C", "mieszkaniu", "квартире (местн.)", "квартирі (місц.)", "apartment (loc.)", False, "wrong_case"), + ("a2_housing_rental_l05_q1", "D", "mieszkaniem", "квартирой (тв.)", "квартирою (ор.)", "apartment (instr.)", False, "wrong_case"), + + ("a2_housing_rental_l05_q3", "A", "Mam pokój.", "У меня есть комната. (противоречит ситуации)", "У мене є кімната. (суперечить ситуації)", "I have a room. (contradicts the situation)", False, "wrong_context"), + ("a2_housing_rental_l05_q3", "B", "Wynajmuję pokój.", "Я снимаю комнату. (уже снял, не ищет)", "Я знімаю кімнату. (уже зняв, не шукає)", "I rent a room. (already rented, not searching)", False, "wrong_context"), + ("a2_housing_rental_l05_q3", "C", "Sprzedaję pokój.", "Я продаю комнату.", "Я продаю кімнату.", "I'm selling a room.", False, "wrong_context"), + ("a2_housing_rental_l05_q3", "D", "Szukam pokoju.", "Я ищу комнату.", "Я шукаю кімнату.", "I'm looking for a room.", True, None), + + # L06 + ("a2_housing_rental_l06_q1", "A", "umowę", "договор (вин.)", "договір (знах.)", "contract (acc.)", True, None), + ("a2_housing_rental_l06_q1", "B", "umowa", "договор (им.)", "договір (наз.)", "contract (nom.)", False, "wrong_case"), + ("a2_housing_rental_l06_q1", "C", "umowy", "договора (род.)", "договору (род.)", "contract (gen.)", False, "wrong_case"), + ("a2_housing_rental_l06_q1", "D", "umową", "договором (тв.)", "договором (ор.)", "contract (instr.)", False, "wrong_case"), + + ("a2_housing_rental_l06_q3", "A", "Płacę czynsz.", "Я плачу арендную плату. (не о формальностях)", "Я плачу орендну плату. (не про формальності)", "I pay rent. (not about formalities)", False, "wrong_context"), + ("a2_housing_rental_l06_q3", "B", "Szukam mieszkania.", "Я ищу квартиру. (не о подписи)", "Я шукаю квартиру. (не про підпис)", "I'm looking for an apartment. (not about a signature)", False, "wrong_context"), + ("a2_housing_rental_l06_q3", "C", "Podpisuję umowę.", "Я подписываю договор.", "Я підписую договір.", "I'm signing the contract.", True, None), + ("a2_housing_rental_l06_q3", "D", "Wprowadzam się.", "Я въезжаю. (не о подписи)", "Я в'їжджаю. (не про підпис)", "I'm moving in. (not about a signature)", False, "wrong_context"), + + # L07 + ("a2_housing_rental_l07_q1", "A", "szkoła", "школа (им.)", "школа (наз.)", "school (nom.)", False, "wrong_case"), + ("a2_housing_rental_l07_q1", "B", "szkole", "школе (местн.)", "школі (місц.)", "school (loc.)", False, "wrong_case"), + ("a2_housing_rental_l07_q1", "C", "szkołę", "школу (вин.)", "школу (знах.)", "school (acc.)", False, "wrong_case"), + ("a2_housing_rental_l07_q1", "D", "szkoły", "школы (род.)", "школи (род.)", "school (gen.)", True, None), + + ("a2_housing_rental_l07_q3", "A", "Mieszkanie jest daleko od szkoły.", "Квартира далеко от школы. (противоречит ситуации)", "Квартира далеко від школи. (суперечить ситуації)", "The apartment is far from the school. (contradicts the situation)", False, "wrong_context"), + ("a2_housing_rental_l07_q3", "B", "Mieszkanie jest blisko szkoły.", "Квартира рядом со школой.", "Квартира близько до школи.", "The apartment is close to the school.", True, None), + ("a2_housing_rental_l07_q3", "C", "Mieszkanie jest w szkole.", "Бессмысленное сочетание.", "Безглузде поєднання.", "Doesn't make sense.", False, "wrong_context"), + ("a2_housing_rental_l07_q3", "D", "Szkoła jest w mieszkaniu.", "Бессмысленное сочетание.", "Безглузде поєднання.", "Doesn't make sense.", False, "wrong_context"), + + # L08 + ("a2_housing_rental_l08_q1", "A", "Wprowadzam się do tego mieszkania.", "Я въезжаю в эту квартиру. (противоположное значение)", "Я в'їжджаю в цю квартиру. (протилежне значення)", "I'm moving into this apartment. (opposite meaning)", False, "wrong_translation"), + ("a2_housing_rental_l08_q1", "B", "Sprzątam to mieszkanie.", "Я убираю эту квартиру.", "Я прибираю цю квартиру.", "I'm cleaning this apartment.", False, "wrong_translation"), + ("a2_housing_rental_l08_q1", "C", "Wyprowadzam się z tego mieszkania.", "Я съезжаю из этой квартиры.", "Я виїжджаю з цієї квартири.", "I'm moving out of this apartment.", True, None), + ("a2_housing_rental_l08_q1", "D", "Kupuję to mieszkanie.", "Я покупаю эту квартиру.", "Я купую цю квартиру.", "I'm buying this apartment.", False, "wrong_translation"), + + ("a2_housing_rental_l08_q3", "A", "Wprowadzam się do nowego mieszkania.", "Я въезжаю в новую квартиру.", "Я в'їжджаю в нову квартиру.", "I'm moving into a new apartment.", True, None), + ("a2_housing_rental_l08_q3", "B", "Wyprowadzam się z nowego mieszkania.", "Я съезжаю из новой квартиры. (противоречит ситуации)", "Я виїжджаю з нової квартири. (суперечить ситуації)", "I'm moving out of the new apartment. (contradicts the situation)", False, "wrong_context"), + ("a2_housing_rental_l08_q3", "C", "Sprzedaję nowe mieszkanie.", "Я продаю новую квартиру. (противоречит ситуации)", "Я продаю нову квартиру. (суперечить ситуації)", "I'm selling the new apartment. (contradicts the situation)", False, "wrong_context"), + ("a2_housing_rental_l08_q3", "D", "Szukam nowego mieszkania.", "Я ищу новую квартиру. (уже нашёл, не ищет)", "Я шукаю нову квартиру. (вже знайшов, не шукає)", "I'm looking for a new apartment. (already found one, not searching)", False, "wrong_context"), + + # L09 + ("a2_housing_rental_l09_q1", "A", "Mam dużo pieniędzy i wynajmuję duże mieszkanie.", "У меня много денег, и я снимаю большую квартиру. (реальная ситуация, не гипотеза)", "У мене багато грошей, і я знімаю велику квартиру. (реальна ситуація, не гіпотеза)", "I have a lot of money and I rent a big apartment. (a real situation, not hypothetical)", False, "wrong_translation"), + ("a2_housing_rental_l09_q1", "B", "Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie.", "Если бы у меня было больше денег, я снял бы квартиру побольше.", "Якби в мене було більше грошей, я зняв би більшу квартиру.", "If I had more money, I would rent a bigger apartment.", True, None), + ("a2_housing_rental_l09_q1", "C", "Będę miał więcej pieniędzy i wynajmę większe mieszkanie.", "У меня будет больше денег, и я сниму квартиру побольше. (будущее, не условное)", "У мене буде більше грошей, і я зніму більшу квартиру. (майбутнє, не умовне)", "I'll have more money and I'll rent a bigger apartment. (future, not conditional)", False, "wrong_translation"), + ("a2_housing_rental_l09_q1", "D", "Miałem więcej pieniędzy i wynająłem większe mieszkanie.", "У меня было больше денег, и я снял квартиру побольше. (прошедшее реальное, не условное)", "У мене було більше грошей, і я зняв більшу квартиру. (минуле реальне, не умовне)", "I had more money and I rented a bigger apartment. (real past, not conditional)", False, "wrong_translation"), + + ("a2_housing_rental_l09_q3", "A", "Mieszkanie jest tańsze, wynajmujemy je.", "Квартира дешевле, мы её снимаем. (не условное предложение)", "Квартира дешевша, ми її знімаємо. (не умовне речення)", "The apartment is cheaper, we're renting it. (not a conditional sentence)", False, "wrong_sentence_type"), + ("a2_housing_rental_l09_q3", "B", "Mieszkanie było tańsze, wynajęliśmy je.", "Квартира была дешевле, мы её сняли. (реальное прошедшее, не условное)", "Квартира була дешевша, ми її зняли. (реальне минуле, не умовне)", "The apartment was cheaper, we rented it. (real past, not conditional)", False, "wrong_sentence_type"), + ("a2_housing_rental_l09_q3", "C", "Mieszkanie będzie tańsze, wynajmiemy je.", "Квартира будет дешевле, мы её снимем. (будущее, не условное)", "Квартира буде дешевша, ми її знімемо. (майбутнє, не умовне)", "The apartment will be cheaper, we'll rent it. (future, not conditional)", False, "wrong_sentence_type"), + ("a2_housing_rental_l09_q3", "D", "Gdyby mieszkanie było tańsze, wynajęlibyśmy je.", "Если бы квартира была дешевле, мы бы её сняли.", "Якби квартира була дешевшою, ми б її зняли.", "If the apartment were cheaper, we would rent it.", True, None), + + # L10 + ("a2_housing_rental_l10_q1", "A", "Wynajmuję mieszkanie blisko centrum i mam duży pokój.", "Я снимаю квартиру рядом с центром, и у меня большая комната.", "Я знімаю квартиру близько центру, і в мене велика кімната.", "I rent an apartment close to downtown and I have a big room.", True, None), + ("a2_housing_rental_l10_q1", "B", "Wynajmuję mieszkania blisko centrum i mam duży pokój.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a2_housing_rental_l10_q1", "C", "Jestem wynajmuję mieszkanie blisko centrum.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_housing_rental_l10_q1", "D", "Wynajmuję mieszkanie centrum blisko pokój duży.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + + ("a2_housing_rental_l10_q3", "A", "Mam duży pokój i jasną kuchnię.", "У меня большая комната и светлая кухня. (не начало описания)", "У мене велика кімната і світла кухня. (не початок опису)", "I have a big room and a bright kitchen. (not the opening line)", False, "wrong_context"), + ("a2_housing_rental_l10_q3", "B", "Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie.", "Если бы у меня было больше денег... (не начало описания)", "Якби в мене було більше грошей... (не початок опису)", "If I had more money... (not the opening line)", False, "wrong_context"), + ("a2_housing_rental_l10_q3", "C", "Wynajmuję mieszkanie blisko centrum.", "Я снимаю квартиру рядом с центром.", "Я знімаю квартиру близько центру.", "I rent an apartment close to downtown.", True, None), + ("a2_housing_rental_l10_q3", "D", "Szukam nowego mieszkania.", "Я ищу новую квартиру. (противоречит ситуации — уже снимает)", "Я шукаю нову квартиру. (суперечить ситуації — вже знімає)", "I'm looking for a new apartment. (contradicts the situation — already renting)", False, "wrong_context"), + ] + + for opt in options_t2_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t2_a2 = [ + ("a2_housing_rental_t01", None, "topic_test", "recognition", "mieszkanie_vocabulary", 1, + "Jak po polsku „кухня”?", "Как по-польски «кухня»?", "Як польською «кухня»?", "How do you say “kitchen” in Polish?", + "B", None, None, 1), + ("a2_housing_rental_t02", None, "topic_test", "recognition", "wynajmowac_mieszkanie", 1, + "Co znaczy „Wynajmuję mieszkanie”?", "Что означает «Wynajmuję mieszkanie»?", "Що означає «Wynajmuję mieszkanie»?", "What does “Wynajmuję mieszkanie” mean?", + "A", None, None, 2), + ("a2_housing_rental_t03", None, "topic_test", "recognition", "czynsz_i_oplaty", 1, + "Jak po polsku „залог”?", "Как по-польски «залог»?", "Як польською «застава»?", "How do you say “deposit” in Polish?", + "D", None, None, 3), + ("a2_housing_rental_t04", None, "topic_test", "recognition", "opisywac_mieszkanie_przymiotniki", 1, + "Wybierz poprawną formę: To jest ___ kuchnia. (jasny)", "Выберите правильную форму: To jest ___ kuchnia. (jasny)", "Виберіть правильну форму: To jest ___ kuchnia. (jasny)", "Choose the correct form: To jest ___ kuchnia. (jasny)", + "C", None, None, 4), + ("a2_housing_rental_t05", None, "topic_test", "recognition", "szukac_mieszkania", 2, + "Wybierz poprawną formę: Szukam ___. (mieszkanie)", "Выберите правильную форму: Szukam ___. (mieszkanie)", "Виберіть правильну форму: Szukam ___. (mieszkanie)", "Choose the correct form: Szukam ___. (mieszkanie)", + "B", None, None, 5), + ("a2_housing_rental_t06", None, "topic_test", "recognition", "zdania_warunkowe_gdybym", 3, + "Co znaczy „Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie”?", "Что означает «Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie»?", "Що означає «Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie»?", "What does “Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie” mean?", + "B", None, None, 6), + + ("a2_housing_rental_t07", None, "topic_test", "application", "mieszkanie_vocabulary", 1, + "Chcesz wziąć prysznic. Dokąd idziesz?", "Ты хочешь принять душ. Куда ты идёшь?", "Ти хочеш прийняти душ. Куди ти йдеш?", "You want to take a shower. Where do you go?", + "D", None, None, 7), + ("a2_housing_rental_t08", None, "topic_test", "application", "wynajmowac_mieszkanie", 1, + "Kolega pyta, co wynajmujesz. Wynajmujesz dom. Co powiesz?", "Друг спрашивает, что ты снимаешь. Ты снимаешь дом. Что ты скажешь?", "Друг питає, що ти знімаєш. Ти знімаєш будинок. Що ти скажеш?", "A friend asks what you're renting. You're renting a house. What do you say?", + "C", None, None, 8), + ("a2_housing_rental_t09", None, "topic_test", "application", "czynsz_i_oplaty", 1, + "Musisz zapłacić za prąd i wodę. Co to jest?", "Тебе нужно заплатить за электричество и воду. Что это?", "Тобі треба заплатити за електрику і воду. Що це?", "You have to pay for electricity and water. What is this?", + "B", None, None, 9), + ("a2_housing_rental_t10", None, "topic_test", "application", "umowa_najmu", 2, + "Chcesz formalnie potwierdzić najem podpisem. Co robisz?", "Ты хочешь формально подтвердить аренду подписью. Что ты делаешь?", "Ти хочеш формально підтвердити оренду підписом. Що ти робиш?", "You want to formally confirm the lease with a signature. What are you doing?", + "C", None, None, 10), + ("a2_housing_rental_t11", None, "topic_test", "application", "opisywac_lokalizacje", 2, + "Twoje mieszkanie jest bardzo blisko szkoły, prawie obok. Jak to opiszesz?", "Твоя квартира очень близко к школе, почти рядом. Как ты это опишешь?", "Твоя квартира дуже близько до школи, майже поруч. Як ти це опишеш?", "Your apartment is very close to the school, almost next to it. How do you describe it?", + "B", None, None, 11), + ("a2_housing_rental_t12", None, "topic_test", "application", "zdania_warunkowe_gdybym", 3, + "Chcesz powiedzieć, że gdyby mieszkanie było tańsze, wynajęlibyście je. Co powiesz?", "Ты хочешь сказать, что если бы квартира была дешевле, вы бы её сняли. Что ты скажешь?", "Ти хочеш сказати, що якби квартира була дешевшою, ви б її зняли. Що ти скажеш?", "You want to say that if the apartment were cheaper, you would rent it. What do you say?", + "D", None, None, 12), + + ("a2_housing_rental_t13", None, "topic_test", "production", "mieszkanie_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (балкон)", "Вставьте пропущенное слово: To jest ___. (балкон)", "Вставте пропущене слово: To jest ___. (балкон)", "Fill in the missing word: To jest ___. (balcony)", + "balkon", "first_letter", "b", 13), + ("a2_housing_rental_t14", None, "topic_test", "production", "opisywac_mieszkanie_przymiotniki", 1, + "Wpisz brakujące słowo: To jest ___ pokój. (большой)", "Вставьте пропущенное слово: To jest ___ pokój. (большой)", "Вставте пропущене слово: To jest ___ pokój. (великий)", "Fill in the missing word: To jest ___ pokój. (big)", + "duży", "first_letter", "d", 14), + ("a2_housing_rental_t15", None, "topic_test", "production", "szukac_mieszkania", 2, + "Wpisz brakujące słowo: Szukam ___. (дома)", "Вставьте пропущенное слово: Szukam ___. (дома)", "Вставте пропущене слово: Szukam ___. (будинку)", "Fill in the missing word: Szukam ___. (a house)", + "domu", "first_letter", "d", 15), + ("a2_housing_rental_t16", None, "topic_test", "production", "umowa_najmu", 2, + "Wpisz brakujące słowo: Muszę zapłacić ___. (залог)", "Вставьте пропущенное слово: Muszę zapłacić ___. (залог)", "Вставте пропущене слово: Muszę zapłacić ___. (заставу)", "Fill in the missing word: Muszę zapłacić ___. (deposit)", + "kaucję", "first_letter", "k", 16), + ("a2_housing_rental_t17", None, "topic_test", "production", "opisywac_lokalizacje", 2, + "Wpisz brakujące słowo: Sklep jest ___ przystanku. (рядом)", "Вставьте пропущенное слово: Sklep jest ___ przystanku. (рядом)", "Вставте пропущене слово: Sklep jest ___ przystanku. (близько)", "Fill in the missing word: Sklep jest ___ przystanku. (close to)", + "blisko", "first_letter", "b", 17), + ("a2_housing_rental_t18", None, "topic_test", "production", "opisuje_swoje_mieszkanie", 3, + "Przetłumacz: «Если бы у меня было больше денег, я снял бы квартиру побольше».", "Переведите: «Если бы у меня было больше денег, я снял бы квартиру побольше».", "Перекладіть: «Якби в мене було більше грошей, я зняв би більшу квартиру».", "Translate: “If I had more money, I would rent a bigger apartment.”", + "Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie", "first_letter", "G", 18), + + ("a2_housing_rental_t19", None, "topic_test", "mixed", "opisuje_swoje_mieszkanie", 3, + "Wybierz poprawne tłumaczenie: «Я снимаю квартиру рядом с центром, у меня большая комната и светлая кухня».", "Выберите правильный перевод: «Я снимаю квартиру рядом с центром, у меня большая комната и светлая кухня».", "Виберіть правильний переклад: «Я знімаю квартиру близько центру, у мене велика кімната і світла кухня».", "Choose the correct translation: “I rent an apartment close to downtown, I have a big room and a bright kitchen.”", + "C", None, None, 19), + ("a2_housing_rental_t20", None, "topic_test", "mixed", "zdania_warunkowe_gdybym", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Если бы у тебя было больше денег, что бы ты сделал? — Я снял бы квартиру побольше.»", "Выберите правильный перевод диалога: «— Если бы у тебя было больше денег, что бы ты сделал? — Я снял бы квартиру побольше.»", "Виберіть правильний переклад діалогу: «— Якби в тебе було більше грошей, що б ти зробив? — Я зняв би більшу квартиру.»", "Choose the correct translation of the dialogue: “— If you had more money, what would you do? — I would rent a bigger apartment.”", + "D", None, None, 20), + ] + + for q in test_questions_t2_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_housing_rental', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t2_a2 = [ + ("a2_housing_rental_t01", "A", "pokój", "комната", "кімната", "room", False, "wrong_word"), + ("a2_housing_rental_t01", "B", "kuchnia", "кухня", "кухня", "kitchen", True, None), + ("a2_housing_rental_t01", "C", "łazienka", "ванная", "ванна", "bathroom", False, "wrong_word"), + ("a2_housing_rental_t01", "D", "balkon", "балкон", "балкон", "balcony", False, "wrong_word"), + + ("a2_housing_rental_t02", "A", "Wynajmuję mieszkanie.", "Я снимаю квартиру.", "Я знімаю квартиру.", "I rent an apartment.", True, None), + ("a2_housing_rental_t02", "B", "Sprzedaję mieszkanie.", "Я продаю квартиру.", "Я продаю квартиру.", "I'm selling an apartment.", False, "wrong_translation"), + ("a2_housing_rental_t02", "C", "Kupuję mieszkanie.", "Я покупаю квартиру.", "Я купую квартиру.", "I'm buying an apartment.", False, "wrong_translation"), + ("a2_housing_rental_t02", "D", "Szukam mieszkania.", "Я ищу квартиру.", "Я шукаю квартиру.", "I'm looking for an apartment.", False, "wrong_translation"), + + ("a2_housing_rental_t03", "A", "czynsz", "арендная плата", "орендна плата", "rent", False, "wrong_word"), + ("a2_housing_rental_t03", "B", "rachunki", "счета", "рахунки", "bills", False, "wrong_word"), + ("a2_housing_rental_t03", "C", "umowa", "договор", "договір", "contract", False, "wrong_word"), + ("a2_housing_rental_t03", "D", "kaucja", "залог", "застава", "deposit", True, None), + + ("a2_housing_rental_t04", "A", "jasny", "светлый (м.р.)", "світлий (чол.р.)", "bright (masc.)", False, "wrong_gender"), + ("a2_housing_rental_t04", "B", "jasne", "светлое (ср.р.)", "світле (сер.р.)", "bright (neut.)", False, "wrong_gender"), + ("a2_housing_rental_t04", "C", "jasna", "светлая (ж.р.)", "світла (жін.р.)", "bright (fem.)", True, None), + ("a2_housing_rental_t04", "D", "jasnego", "неправильная форма", "неправильна форма", "wrong form", False, "wrong_case"), + + ("a2_housing_rental_t05", "A", "mieszkanie", "квартира (им.)", "квартира (наз.)", "apartment (nom.)", False, "wrong_case"), + ("a2_housing_rental_t05", "B", "mieszkania", "квартиры (род.)", "квартири (род.)", "apartment (gen.)", True, None), + ("a2_housing_rental_t05", "C", "mieszkaniu", "квартире (местн.)", "квартирі (місц.)", "apartment (loc.)", False, "wrong_case"), + ("a2_housing_rental_t05", "D", "mieszkaniem", "квартирой (тв.)", "квартирою (ор.)", "apartment (instr.)", False, "wrong_case"), + + ("a2_housing_rental_t06", "A", "Mam dużo pieniędzy i wynajmuję duże mieszkanie.", "У меня много денег, и я снимаю большую квартиру. (реальная ситуация, не гипотеза)", "У мене багато грошей, і я знімаю велику квартиру. (реальна ситуація, не гіпотеза)", "I have a lot of money and I rent a big apartment. (a real situation, not hypothetical)", False, "wrong_translation"), + ("a2_housing_rental_t06", "B", "Gdybym miał więcej pieniędzy, wynająłbym większe mieszkanie.", "Если бы у меня было больше денег, я снял бы квартиру побольше.", "Якби в мене було більше грошей, я зняв би більшу квартиру.", "If I had more money, I would rent a bigger apartment.", True, None), + ("a2_housing_rental_t06", "C", "Będę miał więcej pieniędzy i wynajmę większe mieszkanie.", "У меня будет больше денег, и я сниму квартиру побольше. (будущее, не условное)", "У мене буде більше грошей, і я зніму більшу квартиру. (майбутнє, не умовне)", "I'll have more money and I'll rent a bigger apartment. (future, not conditional)", False, "wrong_translation"), + ("a2_housing_rental_t06", "D", "Miałem więcej pieniędzy i wynająłem większe mieszkanie.", "У меня было больше денег, и я снял квартиру побольше. (прошедшее реальное, не условное)", "У мене було більше грошей, і я зняв більшу квартиру. (минуле реальне, не умовне)", "I had more money and I rented a bigger apartment. (real past, not conditional)", False, "wrong_translation"), + + ("a2_housing_rental_t07", "A", "pokój", "комната", "кімната", "room", False, "wrong_context"), + ("a2_housing_rental_t07", "B", "kuchnia", "кухня", "кухня", "kitchen", False, "wrong_context"), + ("a2_housing_rental_t07", "C", "balkon", "балкон", "балкон", "balcony", False, "wrong_context"), + ("a2_housing_rental_t07", "D", "łazienka", "ванная", "ванна", "bathroom", True, None), + + ("a2_housing_rental_t08", "A", "Wynajmuję mieszkanie.", "Я снимаю квартиру. (неверный тип жилья)", "Я знімаю квартиру. (невірний тип житла)", "I rent an apartment. (wrong type of housing)", False, "wrong_context"), + ("a2_housing_rental_t08", "B", "Wynajmuję pokój.", "Я снимаю комнату. (неверный тип жилья)", "Я знімаю кімнату. (невірний тип житла)", "I rent a room. (wrong type of housing)", False, "wrong_context"), + ("a2_housing_rental_t08", "C", "Wynajmuję dom.", "Я снимаю дом.", "Я знімаю будинок.", "I rent a house.", True, None), + ("a2_housing_rental_t08", "D", "Kupuję dom.", "Я покупаю дом. (неверный глагол)", "Я купую будинок. (невірне дієслово)", "I'm buying a house. (wrong verb)", False, "wrong_context"), + + ("a2_housing_rental_t09", "A", "czynsz", "арендная плата", "орендна плата", "rent", False, "wrong_context"), + ("a2_housing_rental_t09", "B", "rachunki", "счета", "рахунки", "bills", True, None), + ("a2_housing_rental_t09", "C", "kaucja", "залог", "застава", "deposit", False, "wrong_context"), + ("a2_housing_rental_t09", "D", "umowa", "договор", "договір", "contract", False, "wrong_context"), + + ("a2_housing_rental_t10", "A", "Płacę czynsz.", "Я плачу арендную плату. (не о формальностях)", "Я плачу орендну плату. (не про формальності)", "I pay rent. (not about formalities)", False, "wrong_context"), + ("a2_housing_rental_t10", "B", "Szukam mieszkania.", "Я ищу квартиру. (не о подписи)", "Я шукаю квартиру. (не про підпис)", "I'm looking for an apartment. (not about a signature)", False, "wrong_context"), + ("a2_housing_rental_t10", "C", "Podpisuję umowę.", "Я подписываю договор.", "Я підписую договір.", "I'm signing the contract.", True, None), + ("a2_housing_rental_t10", "D", "Wprowadzam się.", "Я въезжаю. (не о подписи)", "Я в'їжджаю. (не про підпис)", "I'm moving in. (not about a signature)", False, "wrong_context"), + + ("a2_housing_rental_t11", "A", "Mieszkanie jest daleko od szkoły.", "Квартира далеко от школы. (противоречит ситуации)", "Квартира далеко від школи. (суперечить ситуації)", "The apartment is far from the school. (contradicts the situation)", False, "wrong_context"), + ("a2_housing_rental_t11", "B", "Mieszkanie jest blisko szkoły.", "Квартира рядом со школой.", "Квартира близько до школи.", "The apartment is close to the school.", True, None), + ("a2_housing_rental_t11", "C", "Mieszkanie jest w szkole.", "Бессмысленное сочетание.", "Безглузде поєднання.", "Doesn't make sense.", False, "wrong_context"), + ("a2_housing_rental_t11", "D", "Szkoła jest w mieszkaniu.", "Бессмысленное сочетание.", "Безглузде поєднання.", "Doesn't make sense.", False, "wrong_context"), + + ("a2_housing_rental_t12", "A", "Mieszkanie jest tańsze, wynajmujemy je.", "Квартира дешевле, мы её снимаем. (не условное предложение)", "Квартира дешевша, ми її знімаємо. (не умовне речення)", "The apartment is cheaper, we're renting it. (not a conditional sentence)", False, "wrong_sentence_type"), + ("a2_housing_rental_t12", "B", "Mieszkanie było tańsze, wynajęliśmy je.", "Квартира была дешевле, мы её сняли. (реальное прошедшее, не условное)", "Квартира була дешевша, ми її зняли. (реальне минуле, не умовне)", "The apartment was cheaper, we rented it. (real past, not conditional)", False, "wrong_sentence_type"), + ("a2_housing_rental_t12", "C", "Mieszkanie będzie tańsze, wynajmiemy je.", "Квартира будет дешевле, мы её снимем. (будущее, не условное)", "Квартира буде дешевша, ми її знімемо. (майбутнє, не умовне)", "The apartment will be cheaper, we'll rent it. (future, not conditional)", False, "wrong_sentence_type"), + ("a2_housing_rental_t12", "D", "Gdyby mieszkanie było tańsze, wynajęlibyśmy je.", "Если бы квартира была дешевле, мы бы её сняли.", "Якби квартира була дешевшою, ми б її зняли.", "If the apartment were cheaper, we would rent it.", True, None), + + ("a2_housing_rental_t19", "A", "Wynajmuję mieszkanie daleko od centrum, mam duży pokój i jasną kuchnię.", "Неверное расположение (далеко вместо рядом).", "Невірне розташування (далеко замість близько).", "Wrong location (far instead of close).", False, "wrong_context"), + ("a2_housing_rental_t19", "B", "Wynajęłam mieszkanie blisko centrum, mam duży pokój i jasną kuchnię.", "Неправильное время (прошедшее вместо настоящего).", "Неправильний час (минулий замість теперішнього).", "Wrong tense (past instead of present).", False, "wrong_sentence_type"), + ("a2_housing_rental_t19", "C", "Wynajmuję mieszkanie blisko centrum, mam duży pokój i jasną kuchnię.", "Я снимаю квартиру рядом с центром, у меня большая комната и светлая кухня.", "Я знімаю квартиру близько центру, у мене велика кімната і світла кухня.", "I rent an apartment close to downtown, I have a big room and a bright kitchen.", True, None), + ("a2_housing_rental_t19", "D", "Wynajmuję mieszkanie blisko centrum, mam ciasny pokój i ciemną kuchnię.", "Противоречит описанию (тесная и тёмная вместо большой и светлой).", "Суперечить опису (тісна і темна замість великої і світлої).", "Contradicts the description (cramped and dark instead of big and bright).", False, "wrong_word"), + + ("a2_housing_rental_t20", "A", "Co robisz, jeśli masz więcej pieniędzy? — Wynajmuję większe mieszkanie.", "Неправильная конструкция (не условное наклонение).", "Неправильна конструкція (не умовний спосіб).", "Incorrect construction (not the conditional mood).", False, "wrong_sentence_type"), + ("a2_housing_rental_t20", "B", "Gdybyś miał więcej pieniędzy, co byś zrobił? — Wynajmuję większe mieszkanie.", "Ответ не в условном наклонении.", "Відповідь не в умовному способі.", "The answer is not in the conditional mood.", False, "wrong_sentence_type"), + ("a2_housing_rental_t20", "C", "Gdybyś miał więcej pieniędzy, co byś zrobił? — Wynająłem większe mieszkanie.", "Ответ в прошедшем времени вместо условного наклонения.", "Відповідь у минулому часі замість умовного способу.", "The answer is in the past tense instead of the conditional mood.", False, "wrong_sentence_type"), + ("a2_housing_rental_t20", "D", "Gdybyś miał więcej pieniędzy, co byś zrobił? — Wynająłbym większe mieszkanie.", "Если бы у тебя было больше денег, что бы ты сделал? — Я снял бы квартиру побольше.", "Якби в тебе було більше грошей, що б ти зробив? — Я зняв би більшу квартиру.", "If you had more money, what would you do? — I would rent a bigger apartment.", True, None), + ] + + for opt in test_options_t2_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 3 (A2): ЗДОРОВЬЕ И ВРАЧ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_health_doctor', 'A2', 3, + 'Zdrowie i lekarz', + 'Здоровье и врач', + 'Здоров''я і лікар', + 'Health and Doctor') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t3_a2 = [ + ("a2_health_doctor_l01", 1, "czesci_ciala_vocabulary", "Podstawowe słowa: części ciała", "Основные слова: части тела", "Основні слова: частини тіла", "Basic words: body parts", + "Podstawowe nazwy części ciała: głowa, brzuch, gardło, plecy. Te słowa mają różny rodzaj: głowa (żeński), brzuch (męski), gardło (nijaki), a „plecy” występuje tylko w liczbie mnogiej.", + "Основные названия частей тела: głowa (голова), brzuch (живот), gardło (горло), plecy (спина). Эти слова разного рода: głowa — женский, brzuch — мужской, gardło — средний, а „plecy” употребляется только во множественном числе.", + "Основні назви частин тіла: głowa (голова), brzuch (живіт), gardło (горло), plecy (спина). Ці слова різного роду: głowa — жіночий, brzuch — чоловічий, gardło — середній, а „plecy” вживається лише у множині.", + "Basic body part names: głowa (head), brzuch (stomach), gardło (throat), plecy (back). These words have different genders: głowa is feminine, brzuch is masculine, gardło is neuter, and „plecy” is used only in the plural."), + + ("a2_health_doctor_l02", 2, "bolec_mnie", "Boli/bolą mnie + mianownik", "Boli/bolą mnie + именительный падеж", "Boli/bolą mnie + називний відмінок", "Boli/bolą mnie + nominative", + "Żeby powiedzieć, że coś boli, używamy „boli mnie” (liczba pojedyncza) lub „bolą mnie” (liczba mnoga) + mianownik: boli mnie głowa, boli mnie gardło, bolą mnie plecy.", + "Чтобы сказать, что что-то болит, используем „boli mnie” (у меня болит, ед. ч.) или „bolą mnie” (у меня болят, мн. ч.) + именительный падеж: boli mnie głowa (у меня болит голова), boli mnie gardło (у меня болит горло), bolą mnie plecy (у меня болит спина).", + "Щоб сказати, що щось болить, використовуємо „boli mnie” (у мене болить, одн.) або „bolą mnie” (у мене болять, мн.) + називний відмінок: boli mnie głowa (у мене болить голова), boli mnie gardło (у мене болить горло), bolą mnie plecy (у мене болить спина).", + "To say something hurts, we use „boli mnie” (singular) or „bolą mnie” (plural) + nominative: boli mnie głowa (my head hurts), boli mnie gardło (my throat hurts), bolą mnie plecy (my back hurts)."), + + ("a2_health_doctor_l03", 3, "czuc_sie_przyslowek", "Czuć się + przysłówek", "Czuć się + наречие", "Czuć się + прислівник", "Czuć się + adverb", + "Czasownik zwrotny „czuć się” + przysłówek opisuje samopoczucie: czuję się źle, czujesz się dobrze, czuje się słabo.", + "Возвратный глагол „czuć się” (чувствовать себя) + наречие описывает самочувствие: czuję się źle (я чувствую себя плохо), czujesz się dobrze (ты чувствуешь себя хорошо), czuje się słabo (он/она чувствует себя слабо).", + "Зворотне дієслово „czuć się” (почуватися) + прислівник описує самопочуття: czuję się źle (я почуваюся погано), czujesz się dobrze (ти почуваєшся добре), czuje się słabo (він/вона почувається слабо).", + "The reflexive verb „czuć się” (to feel) + adverb describes wellbeing: czuję się źle (I feel bad), czujesz się dobrze (you feel good), czuje się słabo (he/she feels weak)."), + + ("a2_health_doctor_l04", 4, "objawy_choroby_vocabulary", "Podstawowe słowa: objawy choroby", "Основные слова: симптомы болезни", "Основні слова: симптоми хвороби", "Basic words: symptoms of illness", + "Podstawowe słowa dotyczące objawów: gorączka, kaszel, katar, ból głowy.", + "Основные слова о симптомах: gorączka (температура), kaszel (кашель), katar (насморк), ból głowy (головная боль).", + "Основні слова про симптоми: gorączka (температура), kaszel (кашель), katar (нежить), ból głowy (головний біль).", + "Basic words about symptoms: gorączka (fever), kaszel (cough), katar (runny nose), ból głowy (headache)."), + + ("a2_health_doctor_l05", 5, "musiec_isc_do_lekarza", "Musieć + bezokolicznik", "Musieć + инфинитив", "Musieć + інфінітив", "Musieć + infinitive", + "Czasownik „musieć” + bezokolicznik wyraża konieczność: muszę iść do lekarza, musisz wziąć lekarstwo, musi odpocząć.", + "Глагол „musieć” (быть должным) + инфинитив выражает необходимость: muszę iść do lekarza (я должен пойти к врачу), musisz wziąć lekarstwo (ты должен принять лекарство), musi odpocząć (он/она должен отдохнуть).", + "Дієслово „musieć” (бути зобов'язаним) + інфінітив виражає необхідність: muszę iść do lekarza (я мушу піти до лікаря), musisz wziąć lekarstwo (ти мусиш прийняти ліки), musi odpocząć (він/вона мусить відпочити).", + "The verb „musieć” (to have to) + infinitive expresses necessity: muszę iść do lekarza (I have to go to the doctor), musisz wziąć lekarstwo (you have to take the medicine), musi odpocząć (he/she has to rest)."), + + ("a2_health_doctor_l06", 6, "umawiac_wizyte", "Umawiać się na wizytę", "Записываться на приём", "Записуватися на прийом", "Make an appointment", + "Czasownik zwrotny „umawiać się” + „na” + biernik: umawiam się na wizytę, umawiasz się na badanie.", + "Возвратный глагол „umawiać się” (договариваться/записываться) + „na” + винительный падеж: umawiam się na wizytę (я записываюсь на приём), umawiasz się na badanie (ты записываешься на обследование).", + "Зворотне дієслово „umawiać się” (домовлятися/записуватися) + „na” + знахідний відмінок: umawiam się na wizytę (я записуюся на прийом), umawiasz się na badanie (ти записуєшся на обстеження).", + "The reflexive verb „umawiać się” (to make an appointment) + „na” + accusative: umawiam się na wizytę (I'm booking an appointment), umawiasz się na badanie (you're booking an examination)."), + + ("a2_health_doctor_l07", 7, "recepta_i_apteka_vocabulary", "Podstawowe słowa: recepta i apteka", "Основные слова: рецепт и аптека", "Основні слова: рецепт і аптека", "Basic words: prescription and pharmacy", + "Podstawowe słowa: recepta, apteka, lekarstwo, tabletki.", + "Основные слова: recepta (рецепт), apteka (аптека), lekarstwo (лекарство), tabletki (таблетки).", + "Основні слова: recepta (рецепт), apteka (аптека), lekarstwo (ліки), tabletki (таблетки).", + "Basic words: recepta (prescription), apteka (pharmacy), lekarstwo (medicine), tabletki (pills)."), + + ("a2_health_doctor_l08", 8, "dawac_rady_zdrowotne", "Powinieneś/powinnaś + bezokolicznik", "Powinieneś/powinnaś + инфинитив", "Powinieneś/powinnaś + інфінітив", "Powinieneś/powinnaś + infinitive", + "Żeby dać radę, używamy „powinieneś” (mężczyzna) lub „powinnaś” (kobieta) + bezokolicznik: powinieneś odpocząć, powinnaś pić dużo wody.", + "Чтобы дать совет, используем „powinieneś” (мужчине) или „powinnaś” (женщине) + инфинитив: powinieneś odpocząć (тебе следует отдохнуть), powinnaś pić dużo wody (тебе следует пить много воды).", + "Щоб дати пораду, використовуємо „powinieneś” (чоловікові) або „powinnaś” (жінці) + інфінітив: powinieneś odpocząć (тобі слід відпочити), powinnaś pić dużo wody (тобі слід пити багато води).", + "To give advice, we use „powinieneś” (to a man) or „powinnaś” (to a woman) + infinitive: powinieneś odpocząć (you should rest), powinnaś pić dużo wody (you should drink a lot of water)."), + + ("a2_health_doctor_l09", 9, "musialem_isc_do_lekarza", "Musiałem/musiałam + bezokolicznik (przeszłość)", "Musiałem/musiałam + инфинитив (прошедшее)", "Musiałem/musiałam + інфінітив (минулий час)", "Musiałem/musiałam + infinitive (past)", + "Czas przeszły konieczności tworzymy „musiałem” (mężczyzna) lub „musiałam” (kobieta) + bezokolicznik: musiałem iść do lekarza, musiałam wziąć lekarstwo.", + "Прошедшее время необходимости образуем „musiałem” (мужчина) или „musiałam” (женщина) + инфинитив: musiałem iść do lekarza (я был вынужден пойти к врачу), musiałam wziąć lekarstwo (я была вынуждена принять лекарство).", + "Минулий час необхідності утворюємо „musiałem” (чоловік) або „musiałam” (жінка) + інфінітив: musiałem iść do lekarza (я мусив піти до лікаря), musiałam wziąć lekarstwo (я мусила прийняти ліки).", + "We form the past tense of necessity with „musiałem” (male speaker) or „musiałam” (female speaker) + infinitive: musiałem iść do lekarza (I had to go to the doctor), musiałam wziąć lekarstwo (I had to take the medicine)."), + + ("a2_health_doctor_l10", 10, "opisuje_swoje_zdrowie", "Opisuję swoje zdrowie", "Описываю своё здоровье", "Описую своє здоров'я", "Describing my health", + "Żeby opisać swoje zdrowie, łączymy zdania: Czuję się źle. Boli mnie głowa i gardło. Muszę iść do lekarza. Powinienem wziąć lekarstwo.", + "Чтобы описать своё здоровье, соединяем предложения: Czuję się źle. Boli mnie głowa i gardło. Muszę iść do lekarza. Powinienem wziąć lekarstwo. (Я чувствую себя плохо. У меня болит голова и горло. Мне нужно пойти к врачу. Мне следует принять лекарство.)", + "Щоб описати своє здоров'я, поєднуємо речення: Czuję się źle. Boli mnie głowa i gardło. Muszę iść do lekarza. Powinienem wziąć lekarstwo. (Я почуваюся погано. У мене болить голова і горло. Мені потрібно піти до лікаря. Мені слід прийняти ліки.)", + "To describe your health, we combine sentences: Czuję się źle. Boli mnie głowa i gardło. Muszę iść do lekarza. Powinienem wziąć lekarstwo. (I feel bad. My head and throat hurt. I have to go to the doctor. I should take medicine.)"), + ] + + for lesson in lessons_t3_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_health_doctor', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t3_a2 = [ + ("a2_health_doctor_l01", 1, "To jest głowa.", "Это голова.", "Це голова.", "This is a head."), + ("a2_health_doctor_l01", 2, "To jest brzuch.", "Это живот.", "Це живіт.", "This is a stomach."), + ("a2_health_doctor_l01", 3, "To są plecy.", "Это спина.", "Це спина.", "This is the back."), + + ("a2_health_doctor_l02", 1, "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts."), + ("a2_health_doctor_l02", 2, "Boli cię gardło?", "У тебя болит горло?", "У тебе болить горло?", "Does your throat hurt?"), + ("a2_health_doctor_l02", 3, "Bolą go plecy.", "У него болит спина.", "У нього болить спина.", "His back hurts."), + + ("a2_health_doctor_l03", 1, "Czuję się źle.", "Я чувствую себя плохо.", "Я почуваюся погано.", "I feel bad."), + ("a2_health_doctor_l03", 2, "Czujesz się dobrze?", "Ты чувствуешь себя хорошо?", "Ти почуваєшся добре?", "Do you feel good?"), + ("a2_health_doctor_l03", 3, "Ona czuje się słabo.", "Она чувствует себя слабо.", "Вона почувається слабо.", "She feels weak."), + + ("a2_health_doctor_l04", 1, "Mam gorączkę.", "У меня температура.", "У мене температура.", "I have a fever."), + ("a2_health_doctor_l04", 2, "Mam kaszel i katar.", "У меня кашель и насморк.", "У мене кашель і нежить.", "I have a cough and a runny nose."), + ("a2_health_doctor_l04", 3, "Mam ból głowy.", "У меня головная боль.", "У мене головний біль.", "I have a headache."), + + ("a2_health_doctor_l05", 1, "Muszę iść do lekarza.", "Я должен пойти к врачу.", "Я маю піти до лікаря.", "I have to go to the doctor."), + ("a2_health_doctor_l05", 2, "Musisz wziąć lekarstwo.", "Ты должен принять лекарство.", "Ти маєш прийняти ліки.", "You have to take the medicine."), + ("a2_health_doctor_l05", 3, "Ona musi odpocząć.", "Она должна отдохнуть.", "Вона має відпочити.", "She has to rest."), + + ("a2_health_doctor_l06", 1, "Umawiam się na wizytę u lekarza.", "Я записываюсь на приём к врачу.", "Я записуюся на прийом до лікаря.", "I'm booking an appointment with the doctor."), + ("a2_health_doctor_l06", 2, "Umawiasz się na badanie?", "Ты записываешься на обследование?", "Ти записуєшся на обстеження?", "Are you booking an examination?"), + ("a2_health_doctor_l06", 3, "On umówił się na wizytę na jutro.", "Он записался на приём на завтра.", "Він записався на прийом на завтра.", "He booked an appointment for tomorrow."), + + ("a2_health_doctor_l07", 1, "Idę do apteki.", "Я иду в аптеку.", "Я йду в аптеку.", "I'm going to the pharmacy."), + ("a2_health_doctor_l07", 2, "Lekarz wypisał mi receptę.", "Врач выписал мне рецепт.", "Лікар виписав мені рецепт.", "The doctor wrote me a prescription."), + ("a2_health_doctor_l07", 3, "Biorę tabletki dwa razy dziennie.", "Я принимаю таблетки два раза в день.", "Я приймаю таблетки двічі на день.", "I take pills twice a day."), + + ("a2_health_doctor_l08", 1, "Powinieneś odpocząć.", "Тебе следует отдохнуть.", "Тобі слід відпочити.", "You should rest."), + ("a2_health_doctor_l08", 2, "Powinnaś pić dużo wody.", "Тебе следует пить много воды.", "Тобі слід пити багато води.", "You should drink a lot of water."), + ("a2_health_doctor_l08", 3, "Powinien iść do lekarza.", "Ему следует пойти к врачу.", "Йому слід піти до лікаря.", "He should go to the doctor."), + + ("a2_health_doctor_l09", 1, "Musiałem iść do lekarza.", "Я был вынужден пойти к врачу.", "Я мусив піти до лікаря.", "I had to go to the doctor."), + ("a2_health_doctor_l09", 2, "Musiałaś wziąć lekarstwo?", "Тебе пришлось принять лекарство?", "Тобі довелося прийняти ліки?", "Did you have to take the medicine?"), + ("a2_health_doctor_l09", 3, "Musiał zostać w domu.", "Ему пришлось остаться дома.", "Йому довелося залишитися вдома.", "He had to stay home."), + + ("a2_health_doctor_l10", 1, "Czuję się źle.", "Я чувствую себя плохо.", "Я почуваюся погано.", "I feel bad."), + ("a2_health_doctor_l10", 2, "Boli mnie głowa i gardło.", "У меня болит голова и горло.", "У мене болить голова і горло.", "My head and throat hurt."), + ("a2_health_doctor_l10", 3, "Muszę iść do lekarza.", "Мне нужно пойти к врачу.", "Мені потрібно піти до лікаря.", "I have to go to the doctor."), + ] + + for ex in examples_t3_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t3_a2 = [ + # L01 — czesci_ciala_vocabulary (difficulty 1) + ("a2_health_doctor_l01_q1", "a2_health_doctor_l01", "lesson_practice", "recognition", "czesci_ciala_vocabulary", 1, + "Jak po polsku „живот”?", "Как по-польски «живот»?", "Як польською «живіт»?", "How do you say “stomach” in Polish?", + "C", None, None), + ("a2_health_doctor_l01_q2", "a2_health_doctor_l01", "lesson_practice", "production", "czesci_ciala_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (горло)", "Вставьте пропущенное слово: To jest ___. (горло)", "Вставте пропущене слово: To jest ___. (горло)", "Fill in the missing word: To jest ___. (throat)", + "gardło", "first_letter", "g"), + ("a2_health_doctor_l01_q3", "a2_health_doctor_l01", "lesson_practice", "application", "czesci_ciala_vocabulary", 1, + "Coś boli cię w środku po jedzeniu, powyżej pasa. Co cię boli?", "У тебя болит внутри после еды, выше пояса. Что у тебя болит?", "У тебе болить всередині після їжі, вище пояса. Що в тебе болить?", "Something hurts inside you after eating, above your waist. What hurts?", + "A", None, None), + + # L02 — bolec_mnie (difficulty 1) + ("a2_health_doctor_l02_q1", "a2_health_doctor_l02", "lesson_practice", "recognition", "bolec_mnie", 1, + "Wybierz poprawną formę: ___ mnie głowa. (boleć)", "Выберите правильную форму: ___ mnie głowa. (boleć)", "Виберіть правильну форму: ___ mnie głowa. (boleć)", "Choose the correct form: ___ mnie głowa. (boleć)", + "A", None, None), + ("a2_health_doctor_l02_q2", "a2_health_doctor_l02", "lesson_practice", "production", "bolec_mnie", 1, + "Wpisz brakujące słowo: ___ mnie plecy. (болит, мн.ч.)", "Вставьте пропущенное слово: ___ mnie plecy. (болит, мн.ч.)", "Вставте пропущене слово: ___ mnie plecy. (болить, мн.)", "Fill in the missing word: ___ mnie plecy. (hurt, plural)", + "Bolą", "first_letter", "B"), + ("a2_health_doctor_l02_q3", "a2_health_doctor_l02", "lesson_practice", "application", "bolec_mnie", 1, + "Masz gorączkę i bardzo boli cię głowa. Co powiesz?", "У тебя температура, и у тебя очень болит голова. Что ты скажешь?", "У тебе температура, і в тебе дуже болить голова. Що ти скажеш?", "You have a fever and a bad headache. What do you say?", + "A", None, None), + + # L03 — czuc_sie_przyslowek (difficulty 1) + ("a2_health_doctor_l03_q1", "a2_health_doctor_l03", "lesson_practice", "recognition", "czuc_sie_przyslowek", 1, + "Co znaczy „Czuję się źle”?", "Что означает «Czuję się źle»?", "Що означає «Czuję się źle»?", "What does “Czuję się źle” mean?", + "D", None, None), + ("a2_health_doctor_l03_q2", "a2_health_doctor_l03", "lesson_practice", "production", "czuc_sie_przyslowek", 1, + "Wpisz brakujące słowo: Ona czuje się ___. (слабо)", "Вставьте пропущенное слово: Ona czuje się ___. (слабо)", "Вставте пропущене слово: Ona czuje się ___. (слабо)", "Fill in the missing word: Ona czuje się ___. (weak)", + "słabo", "first_letter", "s"), + ("a2_health_doctor_l03_q3", "a2_health_doctor_l03", "lesson_practice", "application", "czuc_sie_przyslowek", 1, + "Masz dobry humor i dobrze się czujesz. Co powiesz?", "У тебя хорошее настроение и ты хорошо себя чувствуешь. Что ты скажешь?", "У тебе гарний настрій і ти добре почуваєшся. Що ти скажеш?", "You're in a good mood and feel good. What do you say?", + "B", None, None), + + # L04 — objawy_choroby_vocabulary (difficulty 1) + ("a2_health_doctor_l04_q1", "a2_health_doctor_l04", "lesson_practice", "recognition", "objawy_choroby_vocabulary", 1, + "Jak po polsku „насморк”?", "Как по-польски «насморк»?", "Як польською «нежить»?", "How do you say “runny nose” in Polish?", + "C", None, None), + ("a2_health_doctor_l04_q2", "a2_health_doctor_l04", "lesson_practice", "production", "objawy_choroby_vocabulary", 1, + "Wpisz brakujące słowo: Mam ___. (температуру)", "Вставьте пропущенное слово: Mam ___. (температуру)", "Вставте пропущене слово: Mam ___. (температуру)", "Fill in the missing word: Mam ___. (fever)", + "gorączkę", "first_letter", "g"), + ("a2_health_doctor_l04_q3", "a2_health_doctor_l04", "lesson_practice", "application", "objawy_choroby_vocabulary", 1, + "Masz wysoką temperaturę ciała. Co masz?", "У тебя высокая температура тела. Что у тебя?", "У тебе висока температура тіла. Що в тебе?", "You have a high body temperature. What do you have?", + "A", None, None), + + # L05 — musiec_isc_do_lekarza (difficulty 2) + ("a2_health_doctor_l05_q1", "a2_health_doctor_l05", "lesson_practice", "recognition", "musiec_isc_do_lekarza", 2, + "Wybierz poprawną formę: ___ iść do lekarza. (musieć, ja)", "Выберите правильную форму: ___ iść do lekarza. (musieć, ja)", "Виберіть правильну форму: ___ iść do lekarza. (musieć, ja)", "Choose the correct form: ___ iść do lekarza. (musieć, I)", + "A", None, None), + ("a2_health_doctor_l05_q2", "a2_health_doctor_l05", "lesson_practice", "production", "musiec_isc_do_lekarza", 2, + "Wpisz brakujące słowo: ___ wziąć lekarstwo. (ты должен)", "Вставьте пропущенное слово: ___ wziąć lekarstwo. (ты должен)", "Вставте пропущене слово: ___ wziąć lekarstwo. (ти маєш)", "Fill in the missing word: ___ wziąć lekarstwo. (you have to)", + "Musisz", "first_letter", "M"), + ("a2_health_doctor_l05_q3", "a2_health_doctor_l05", "lesson_practice", "application", "musiec_isc_do_lekarza", 2, + "Źle się czujesz i chcesz powiedzieć, że musisz zobaczyć lekarza. Co powiesz?", "Ты плохо себя чувствуешь и хочешь сказать, что тебе нужно к врачу. Что ты скажешь?", "Ти погано почуваєшся і хочеш сказати, що тобі треба до лікаря. Що ти скажеш?", "You feel bad and want to say you need to see a doctor. What do you say?", + "A", None, None), + + # L06 — umawiac_wizyte (difficulty 2) + ("a2_health_doctor_l06_q1", "a2_health_doctor_l06", "lesson_practice", "recognition", "umawiac_wizyte", 2, + "Wybierz poprawną formę: Umawiam się ___ wizytę.", "Выберите правильную форму: Umawiam się ___ wizytę.", "Виберіть правильну форму: Umawiam się ___ wizytę.", "Choose the correct form: Umawiam się ___ wizytę.", + "A", None, None), + ("a2_health_doctor_l06_q2", "a2_health_doctor_l06", "lesson_practice", "production", "umawiac_wizyte", 2, + "Wpisz brakujące słowo: Umawiasz się na ___? (обследование)", "Вставьте пропущенное слово: Umawiasz się na ___? (обследование)", "Вставте пропущене слово: Umawiasz się na ___? (обстеження)", "Fill in the missing word: Umawiasz się na ___? (an examination)", + "badanie", "first_letter", "b"), + ("a2_health_doctor_l06_q3", "a2_health_doctor_l06", "lesson_practice", "application", "umawiac_wizyte", 2, + "Chcesz zapisać się do lekarza na przyszły tydzień. Co powiesz?", "Ты хочешь записаться к врачу на следующую неделю. Что ты скажешь?", "Ти хочеш записатися до лікаря на наступний тиждень. Що ти скажеш?", "You want to book a doctor's appointment for next week. What do you say?", + "A", None, None), + + # L07 — recepta_i_apteka_vocabulary (difficulty 2) + ("a2_health_doctor_l07_q1", "a2_health_doctor_l07", "lesson_practice", "recognition", "recepta_i_apteka_vocabulary", 2, + "Jak po polsku „рецепт”?", "Как по-польски «рецепт»?", "Як польською «рецепт»?", "How do you say “prescription” in Polish?", + "B", None, None), + ("a2_health_doctor_l07_q2", "a2_health_doctor_l07", "lesson_practice", "production", "recepta_i_apteka_vocabulary", 2, + "Wpisz brakujące słowo: Idę do ___. (аптеки)", "Вставьте пропущенное слово: Idę do ___. (аптеки)", "Вставте пропущене слово: Idę do ___. (аптеки)", "Fill in the missing word: Idę do ___. (pharmacy)", + "apteki", "first_letter", "a"), + ("a2_health_doctor_l07_q3", "a2_health_doctor_l07", "lesson_practice", "application", "recepta_i_apteka_vocabulary", 2, + "Lekarz dał ci dokument, żebyś mógł kupić lekarstwo w aptece. Co to jest?", "Врач дал тебе документ, чтобы ты мог купить лекарство в аптеке. Что это?", "Лікар дав тобі документ, щоб ти міг купити ліки в аптеці. Що це?", "The doctor gave you a document so you can buy medicine at the pharmacy. What is it?", + "A", None, None), + + # L08 — dawac_rady_zdrowotne (difficulty 2) + ("a2_health_doctor_l08_q1", "a2_health_doctor_l08", "lesson_practice", "recognition", "dawac_rady_zdrowotne", 2, + "Wybierz poprawną formę (do kobiety): ___ pić dużo wody.", "Выберите правильную форму (к женщине): ___ pić dużo wody.", "Виберіть правильну форму (до жінки): ___ pić dużo wody.", "Choose the correct form (to a woman): ___ pić dużo wody.", + "A", None, None), + ("a2_health_doctor_l08_q2", "a2_health_doctor_l08", "lesson_practice", "production", "dawac_rady_zdrowotne", 2, + "Wpisz brakujące słowo (do mężczyzny): ___ odpocząć. (тебе следует)", "Вставьте пропущенное слово (к мужчине): ___ odpocząć. (тебе следует)", "Вставте пропущене слово (до чоловіка): ___ odpocząć. (тобі слід)", "Fill in the missing word (to a man): ___ odpocząć. (you should)", + "Powinieneś", "first_letter", "P"), + ("a2_health_doctor_l08_q3", "a2_health_doctor_l08", "lesson_practice", "application", "dawac_rady_zdrowotne", 2, + "Twój kolega ma gorączkę. Co mu powiesz?", "У твоего друга температура. Что ты ему скажешь?", "У твого друга температура. Що ти йому скажеш?", "Your friend has a fever. What do you tell him?", + "A", None, None), + + # L09 — musialem_isc_do_lekarza (difficulty 3) + ("a2_health_doctor_l09_q1", "a2_health_doctor_l09", "lesson_practice", "recognition", "musialem_isc_do_lekarza", 3, + "Co znaczy „Musiałem iść do lekarza”?", "Что означает «Musiałem iść do lekarza»?", "Що означає «Musiałem iść do lekarza»?", "What does “Musiałem iść do lekarza” mean?", + "D", None, None), + ("a2_health_doctor_l09_q2", "a2_health_doctor_l09", "lesson_practice", "production", "musialem_isc_do_lekarza", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ zostać w domu. (мне пришлось)", "Вставьте пропущенное слово (говорит женщина): ___ zostać w domu. (мне пришлось)", "Вставте пропущене слово (говорить жінка): ___ zostać w domu. (мені довелося)", "Fill in the missing word (a woman is speaking): ___ zostać w domu. (I had to)", + "Musiałam", "first_letter", "M"), + ("a2_health_doctor_l09_q3", "a2_health_doctor_l09", "lesson_practice", "application", "musialem_isc_do_lekarza", 3, + "Mężczyzna opowiada, że w zeszłym tygodniu był zmuszony pójść do apteki. Co powie?", "Мужчина рассказывает, что на прошлой неделе был вынужден пойти в аптеку. Что он скажет?", "Чоловік розповідає, що минулого тижня був змушений піти в аптеку. Що він скаже?", "A man is telling that last week he was forced to go to the pharmacy. What does he say?", + "B", None, None), + + # L10 — opisuje_swoje_zdrowie (difficulty 3) + ("a2_health_doctor_l10_q1", "a2_health_doctor_l10", "lesson_practice", "recognition", "opisuje_swoje_zdrowie", 3, + "Które zdanie poprawnie opisuje samopoczucie?", "Какое предложение правильно описывает самочувствие?", "Яке речення правильно описує самопочуття?", "Which sentence correctly describes wellbeing?", + "D", None, None), + ("a2_health_doctor_l10_q2", "a2_health_doctor_l10", "lesson_practice", "production", "opisuje_swoje_zdrowie", 3, + "Przetłumacz: «Мне следует пойти к врачу».", "Переведите: «Мне следует пойти к врачу».", "Перекладіть: «Мені слід піти до лікаря».", "Translate: “I should go to the doctor.”", + "Powinienem iść do lekarza", "first_letter", "P"), + ("a2_health_doctor_l10_q3", "a2_health_doctor_l10", "lesson_practice", "application", "opisuje_swoje_zdrowie", 3, + "Chcesz opisać koledze swoje zdrowie: źle się czujesz, boli cię głowa, musisz iść do lekarza. Jak zaczniesz zdanie?", "Ты хочешь описать другу своё здоровье: ты плохо себя чувствуешь, у тебя болит голова, тебе нужно к врачу. Как ты начнёшь предложение?", "Ти хочеш описати другу своє здоров'я: ти погано почуваєшся, у тебе болить голова, тобі треба до лікаря. Як ти почнеш речення?", "You want to describe your health to a friend: you feel bad, your head hurts, you need to see a doctor. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t3_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_health_doctor', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t3_a2 = [ + # L01 + ("a2_health_doctor_l01_q1", "A", "głowa", "голова", "голова", "head", False, "wrong_word"), + ("a2_health_doctor_l01_q1", "B", "gardło", "горло", "горло", "throat", False, "wrong_word"), + ("a2_health_doctor_l01_q1", "C", "brzuch", "живот", "живіт", "stomach", True, None), + ("a2_health_doctor_l01_q1", "D", "plecy", "спина", "спина", "back", False, "wrong_word"), + + ("a2_health_doctor_l01_q3", "A", "brzuch", "живот", "живіт", "stomach", True, None), + ("a2_health_doctor_l01_q3", "B", "gardło", "горло", "горло", "throat", False, "wrong_context"), + ("a2_health_doctor_l01_q3", "C", "głowa", "голова", "голова", "head", False, "wrong_context"), + ("a2_health_doctor_l01_q3", "D", "plecy", "спина", "спина", "back", False, "wrong_context"), + + # L02 + ("a2_health_doctor_l02_q1", "A", "Boli", "болит", "болить", "hurts", True, None), + ("a2_health_doctor_l02_q1", "B", "Bolą", "болят (мн.ч. — не подходит к «głowa»)", "болять (мн. — не пасує до «głowa»)", "hurt (plural — doesn't fit „głowa”)", False, "wrong_number"), + ("a2_health_doctor_l02_q1", "C", "Boję", "боюсь (другой глагол)", "боюся (інше дієслово)", "I'm afraid (a different verb)", False, "wrong_word"), + ("a2_health_doctor_l02_q1", "D", "Bolałam", "болела (форма для женщины, прошедшее время)", "боліла (форма для жінки, минулий час)", "hurt (female past-tense form)", False, "wrong_sentence_type"), + + ("a2_health_doctor_l02_q3", "A", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", True, None), + ("a2_health_doctor_l02_q3", "B", "Boli mnie gardło.", "У меня болит горло. (не соответствует ситуации)", "У мене болить горло. (не відповідає ситуації)", "My throat hurts. (doesn't match the situation)", False, "wrong_context"), + ("a2_health_doctor_l02_q3", "C", "Bolą mnie plecy.", "У меня болит спина. (не соответствует ситуации)", "У мене болить спина. (не відповідає ситуації)", "My back hurts. (doesn't match the situation)", False, "wrong_context"), + ("a2_health_doctor_l02_q3", "D", "Boli mnie brzuch.", "У меня болит живот. (не соответствует ситуации)", "У мене болить живіт. (не відповідає ситуації)", "My stomach hurts. (doesn't match the situation)", False, "wrong_context"), + + # L03 + ("a2_health_doctor_l03_q1", "A", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", False, "wrong_translation"), + ("a2_health_doctor_l03_q1", "B", "Jestem zmęczony.", "Я устал.", "Я втомився.", "I'm tired.", False, "wrong_translation"), + ("a2_health_doctor_l03_q1", "C", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", False, "wrong_translation"), + ("a2_health_doctor_l03_q1", "D", "Czuję się źle.", "Я чувствую себя плохо.", "Я почуваюся погано.", "I feel bad.", True, None), + + ("a2_health_doctor_l03_q3", "A", "Czuję się źle.", "Я чувствую себя плохо. (противоречит ситуации)", "Я почуваюся погано. (суперечить ситуації)", "I feel bad. (contradicts the situation)", False, "wrong_context"), + ("a2_health_doctor_l03_q3", "B", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", True, None), + ("a2_health_doctor_l03_q3", "C", "Czuję się słabo.", "Я чувствую себя слабо. (противоречит ситуации)", "Я почуваюся слабо. (суперечить ситуації)", "I feel weak. (contradicts the situation)", False, "wrong_context"), + ("a2_health_doctor_l03_q3", "D", "Boli mnie głowa.", "У меня болит голова. (не о самочувствии в целом)", "У мене болить голова. (не про самопочуття загалом)", "My head hurts. (not about overall wellbeing)", False, "wrong_context"), + + # L04 + ("a2_health_doctor_l04_q1", "A", "gorączka", "температура", "температура", "fever", False, "wrong_word"), + ("a2_health_doctor_l04_q1", "B", "kaszel", "кашель", "кашель", "cough", False, "wrong_word"), + ("a2_health_doctor_l04_q1", "C", "katar", "насморк", "нежить", "runny nose", True, None), + ("a2_health_doctor_l04_q1", "D", "ból głowy", "головная боль", "головний біль", "headache", False, "wrong_word"), + + ("a2_health_doctor_l04_q3", "A", "gorączkę", "температуру", "температуру", "fever", True, None), + ("a2_health_doctor_l04_q3", "B", "katar", "насморк", "нежить", "runny nose", False, "wrong_context"), + ("a2_health_doctor_l04_q3", "C", "kaszel", "кашель", "кашель", "cough", False, "wrong_context"), + ("a2_health_doctor_l04_q3", "D", "ból głowy", "головная боль", "головний біль", "headache", False, "wrong_context"), + + # L05 + ("a2_health_doctor_l05_q1", "A", "Muszę", "я должен", "я мушу", "I have to", True, None), + ("a2_health_doctor_l05_q1", "B", "Musisz", "ты должен (не тот человек)", "ти мусиш (не та особа)", "you have to (wrong person)", False, "wrong_context"), + ("a2_health_doctor_l05_q1", "C", "Musi", "он/она должен (не тот человек)", "він/вона мусить (не та особа)", "he/she has to (wrong person)", False, "wrong_context"), + ("a2_health_doctor_l05_q1", "D", "Musiały", "они должны были (неправильное число и время)", "вони мусили (неправильне число і час)", "they had to (wrong number and tense)", False, "wrong_number"), + + ("a2_health_doctor_l05_q3", "A", "Muszę iść do lekarza.", "Мне нужно пойти к врачу.", "Мені треба піти до лікаря.", "I have to go to the doctor.", True, None), + ("a2_health_doctor_l05_q3", "B", "Muszę iść do apteki.", "Мне нужно пойти в аптеку. (не соответствует ситуации)", "Мені треба піти в аптеку. (не відповідає ситуації)", "I have to go to the pharmacy. (doesn't match the situation)", False, "wrong_context"), + ("a2_health_doctor_l05_q3", "C", "Muszę wziąć lekarstwo.", "Мне нужно принять лекарство. (не о враче)", "Мені треба прийняти ліки. (не про лікаря)", "I have to take medicine. (not about the doctor)", False, "wrong_context"), + ("a2_health_doctor_l05_q3", "D", "Muszę odpocząć.", "Мне нужно отдохнуть. (не о враче)", "Мені треба відпочити. (не про лікаря)", "I have to rest. (not about the doctor)", False, "wrong_context"), + + # L06 + ("a2_health_doctor_l06_q1", "A", "na", "на", "на", "for", True, None), + ("a2_health_doctor_l06_q1", "B", "do", "в/к", "в/до", "to", False, "wrong_word"), + ("a2_health_doctor_l06_q1", "C", "w", "в", "в", "in", False, "wrong_word"), + ("a2_health_doctor_l06_q1", "D", "u", "у", "у", "at", False, "wrong_word"), + + ("a2_health_doctor_l06_q3", "A", "Umawiam się na wizytę.", "Я записываюсь на приём.", "Я записуюся на прийом.", "I'm booking an appointment.", True, None), + ("a2_health_doctor_l06_q3", "B", "Idę do apteki.", "Я иду в аптеку. (не о записи)", "Я йду в аптеку. (не про запис)", "I'm going to the pharmacy. (not about booking)", False, "wrong_context"), + ("a2_health_doctor_l06_q3", "C", "Biorę lekarstwo.", "Я принимаю лекарство. (не о записи)", "Я приймаю ліки. (не про запис)", "I'm taking medicine. (not about booking)", False, "wrong_context"), + ("a2_health_doctor_l06_q3", "D", "Czuję się źle.", "Я чувствую себя плохо. (не о записи)", "Я почуваюся погано. (не про запис)", "I feel bad. (not about booking)", False, "wrong_context"), + + # L07 + ("a2_health_doctor_l07_q1", "A", "apteka", "аптека", "аптека", "pharmacy", False, "wrong_word"), + ("a2_health_doctor_l07_q1", "B", "recepta", "рецепт", "рецепт", "prescription", True, None), + ("a2_health_doctor_l07_q1", "C", "lekarstwo", "лекарство", "ліки", "medicine", False, "wrong_word"), + ("a2_health_doctor_l07_q1", "D", "tabletki", "таблетки", "таблетки", "pills", False, "wrong_word"), + + ("a2_health_doctor_l07_q3", "A", "recepta", "рецепт", "рецепт", "prescription", True, None), + ("a2_health_doctor_l07_q3", "B", "apteka", "аптека", "аптека", "pharmacy", False, "wrong_context"), + ("a2_health_doctor_l07_q3", "C", "tabletki", "таблетки", "таблетки", "pills", False, "wrong_context"), + ("a2_health_doctor_l07_q3", "D", "gorączka", "температура", "температура", "fever", False, "wrong_context"), + + # L08 + ("a2_health_doctor_l08_q1", "A", "Powinnaś", "тебе следует (женщине)", "тобі слід (жінці)", "you should (to a woman)", True, None), + ("a2_health_doctor_l08_q1", "B", "Powinieneś", "тебе следует (мужчине)", "тобі слід (чоловікові)", "you should (to a man)", False, "wrong_gender"), + ("a2_health_doctor_l08_q1", "C", "Powinno", "следует (средний род)", "слід (середній рід)", "should (neuter)", False, "wrong_gender"), + ("a2_health_doctor_l08_q1", "D", "Powinni", "им следует (мн.ч.)", "їм слід (мн.)", "they should (plural)", False, "wrong_number"), + + ("a2_health_doctor_l08_q3", "A", "Powinieneś iść do lekarza.", "Тебе следует пойти к врачу.", "Тобі слід піти до лікаря.", "You should go to the doctor.", True, None), + ("a2_health_doctor_l08_q3", "B", "Powinieneś iść do apteki.", "Тебе следует пойти в аптеку. (не первый шаг при температуре)", "Тобі слід піти в аптеку. (не перший крок при температурі)", "You should go to the pharmacy. (not the first step with a fever)", False, "wrong_context"), + ("a2_health_doctor_l08_q3", "C", "Powinieneś pić kawę.", "Тебе следует пить кофе. (плохой совет при болезни)", "Тобі слід пити каву. (погана порада при хворобі)", "You should drink coffee. (bad advice when sick)", False, "wrong_context"), + ("a2_health_doctor_l08_q3", "D", "Powinieneś pracować.", "Тебе следует работать. (плохой совет при болезни)", "Тобі слід працювати. (погана порада при хворобі)", "You should work. (bad advice when sick)", False, "wrong_context"), + + # L09 + ("a2_health_doctor_l09_q1", "A", "Idę do lekarza.", "Я иду к врачу.", "Я йду до лікаря.", "I'm going to the doctor.", False, "wrong_translation"), + ("a2_health_doctor_l09_q1", "B", "Chcę iść do lekarza.", "Я хочу пойти к врачу.", "Я хочу піти до лікаря.", "I want to go to the doctor.", False, "wrong_translation"), + ("a2_health_doctor_l09_q1", "C", "Pójdę do lekarza.", "Я пойду к врачу.", "Я піду до лікаря.", "I will go to the doctor.", False, "wrong_translation"), + ("a2_health_doctor_l09_q1", "D", "Musiałem iść do lekarza.", "Я был вынужден пойти к врачу.", "Я мусив піти до лікаря.", "I had to go to the doctor.", True, None), + + ("a2_health_doctor_l09_q3", "A", "Muszę iść do apteki.", "Мне нужно пойти в аптеку. (настоящее время)", "Мені треба піти в аптеку. (теперішній час)", "I have to go to the pharmacy. (present tense)", False, "wrong_sentence_type"), + ("a2_health_doctor_l09_q3", "B", "Musiałem iść do apteki.", "Я был вынужден пойти в аптеку.", "Я мусив піти в аптеку.", "I had to go to the pharmacy.", True, None), + ("a2_health_doctor_l09_q3", "C", "Będę musiał iść do apteki.", "Мне нужно будет пойти в аптеку. (будущее время)", "Мені треба буде піти в аптеку. (майбутній час)", "I will have to go to the pharmacy. (future tense)", False, "wrong_sentence_type"), + ("a2_health_doctor_l09_q3", "D", "Musiałam iść do apteki.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + + # L10 + ("a2_health_doctor_l10_q1", "A", "Czuję źle się głowa boli mnie.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_health_doctor_l10_q1", "B", "Czuję się źle, boli głowę mnie.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a2_health_doctor_l10_q1", "C", "Czuję się źle, ja boli głowa.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_health_doctor_l10_q1", "D", "Czuję się źle, boli mnie głowa.", "Я чувствую себя плохо, у меня болит голова.", "Я почуваюся погано, у мене болить голова.", "I feel bad, my head hurts.", True, None), + + ("a2_health_doctor_l10_q3", "A", "Muszę iść do lekarza.", "Мне нужно пойти к врачу. (не начало описания)", "Мені треба піти до лікаря. (не початок опису)", "I have to go to the doctor. (not the opening line)", False, "wrong_context"), + ("a2_health_doctor_l10_q3", "B", "Boli mnie głowa.", "У меня болит голова. (не начало описания)", "У мене болить голова. (не початок опису)", "My head hurts. (not the opening line)", False, "wrong_context"), + ("a2_health_doctor_l10_q3", "C", "Czuję się źle.", "Я чувствую себя плохо.", "Я почуваюся погано.", "I feel bad.", True, None), + ("a2_health_doctor_l10_q3", "D", "Powinienem wziąć lekarstwo.", "Мне следует принять лекарство. (не начало описания)", "Мені слід прийняти ліки. (не початок опису)", "I should take medicine. (not the opening line)", False, "wrong_context"), + ] + + for opt in options_t3_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t3_a2 = [ + ("a2_health_doctor_t01", None, "topic_test", "recognition", "czesci_ciala_vocabulary", 1, + "Jak po polsku „живот”?", "Как по-польски «живот»?", "Як польською «живіт»?", "How do you say “stomach” in Polish?", + "C", None, None, 1), + ("a2_health_doctor_t02", None, "topic_test", "recognition", "bolec_mnie", 1, + "Wybierz poprawną formę: ___ mnie głowa. (boleć)", "Выберите правильную форму: ___ mnie głowa. (boleć)", "Виберіть правильну форму: ___ mnie głowa. (boleć)", "Choose the correct form: ___ mnie głowa. (boleć)", + "A", None, None, 2), + ("a2_health_doctor_t03", None, "topic_test", "recognition", "czuc_sie_przyslowek", 1, + "Co znaczy „Czuję się źle”?", "Что означает «Czuję się źle»?", "Що означає «Czuję się źle»?", "What does “Czuję się źle” mean?", + "D", None, None, 3), + ("a2_health_doctor_t04", None, "topic_test", "recognition", "objawy_choroby_vocabulary", 1, + "Jak po polsku „насморк”?", "Как по-польски «насморк»?", "Як польською «нежить»?", "How do you say “runny nose” in Polish?", + "C", None, None, 4), + ("a2_health_doctor_t05", None, "topic_test", "recognition", "musiec_isc_do_lekarza", 2, + "Wybierz poprawną formę: ___ iść do lekarza. (musieć, ja)", "Выберите правильную форму: ___ iść do lekarza. (musieć, ja)", "Виберіть правильну форму: ___ iść do lekarza. (musieć, ja)", "Choose the correct form: ___ iść do lekarza. (musieć, I)", + "A", None, None, 5), + ("a2_health_doctor_t06", None, "topic_test", "recognition", "musialem_isc_do_lekarza", 3, + "Co znaczy „Musiałem iść do lekarza”?", "Что означает «Musiałem iść do lekarza»?", "Що означає «Musiałem iść do lekarza»?", "What does “Musiałem iść do lekarza” mean?", + "D", None, None, 6), + + ("a2_health_doctor_t07", None, "topic_test", "application", "czesci_ciala_vocabulary", 1, + "Coś boli cię w środku po jedzeniu, powyżej pasa. Co cię boli?", "У тебя болит внутри после еды, выше пояса. Что у тебя болит?", "У тебе болить всередині після їжі, вище пояса. Що в тебе болить?", "Something hurts inside you after eating, above your waist. What hurts?", + "A", None, None, 7), + ("a2_health_doctor_t08", None, "topic_test", "application", "bolec_mnie", 1, + "Masz gorączkę i bardzo boli cię głowa. Co powiesz?", "У тебя температура, и у тебя очень болит голова. Что ты скажешь?", "У тебе температура, і в тебе дуже болить голова. Що ти скажеш?", "You have a fever and a bad headache. What do you say?", + "A", None, None, 8), + ("a2_health_doctor_t09", None, "topic_test", "application", "czuc_sie_przyslowek", 1, + "Masz dobry humor i dobrze się czujesz. Co powiesz?", "У тебя хорошее настроение и ты хорошо себя чувствуешь. Что ты скажешь?", "У тебе гарний настрій і ти добре почуваєшся. Що ти скажеш?", "You're in a good mood and feel good. What do you say?", + "B", None, None, 9), + ("a2_health_doctor_t10", None, "topic_test", "application", "umawiac_wizyte", 2, + "Chcesz zapisać się do lekarza na przyszły tydzień. Co powiesz?", "Ты хочешь записаться к врачу на следующую неделю. Что ты скажешь?", "Ти хочеш записатися до лікаря на наступний тиждень. Що ти скажеш?", "You want to book a doctor's appointment for next week. What do you say?", + "A", None, None, 10), + ("a2_health_doctor_t11", None, "topic_test", "application", "recepta_i_apteka_vocabulary", 2, + "Lekarz dał ci dokument, żebyś mógł kupić lekarstwo w aptece. Co to jest?", "Врач дал тебе документ, чтобы ты мог купить лекарство в аптеке. Что это?", "Лікар дав тобі документ, щоб ти міг купити ліки в аптеці. Що це?", "The doctor gave you a document so you can buy medicine at the pharmacy. What is it?", + "A", None, None, 11), + ("a2_health_doctor_t12", None, "topic_test", "application", "musialem_isc_do_lekarza", 3, + "Mężczyzna opowiada, że w zeszłym tygodniu był zmuszony pójść do apteki. Co powie?", "Мужчина рассказывает, что на прошлой неделе был вынужден пойти в аптеку. Что он скажет?", "Чоловік розповідає, що минулого тижня був змушений піти в аптеку. Що він скаже?", "A man is telling that last week he was forced to go to the pharmacy. What does he say?", + "B", None, None, 12), + + ("a2_health_doctor_t13", None, "topic_test", "production", "czesci_ciala_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (горло)", "Вставьте пропущенное слово: To jest ___. (горло)", "Вставте пропущене слово: To jest ___. (горло)", "Fill in the missing word: To jest ___. (throat)", + "gardło", "first_letter", "g", 13), + ("a2_health_doctor_t14", None, "topic_test", "production", "objawy_choroby_vocabulary", 1, + "Wpisz brakujące słowo: Mam ___. (температуру)", "Вставьте пропущенное слово: Mam ___. (температуру)", "Вставте пропущене слово: Mam ___. (температуру)", "Fill in the missing word: Mam ___. (fever)", + "gorączkę", "first_letter", "g", 14), + ("a2_health_doctor_t15", None, "topic_test", "production", "musiec_isc_do_lekarza", 2, + "Wpisz brakujące słowo: ___ wziąć lekarstwo. (ты должен)", "Вставьте пропущенное слово: ___ wziąć lekarstwo. (ты должен)", "Вставте пропущене слово: ___ wziąć lekarstwo. (ти маєш)", "Fill in the missing word: ___ wziąć lekarstwo. (you have to)", + "Musisz", "first_letter", "M", 15), + ("a2_health_doctor_t16", None, "topic_test", "production", "umawiac_wizyte", 2, + "Wpisz brakujące słowo: Umawiasz się na ___? (обследование)", "Вставьте пропущенное слово: Umawiasz się na ___? (обследование)", "Вставте пропущене слово: Umawiasz się na ___? (обстеження)", "Fill in the missing word: Umawiasz się na ___? (an examination)", + "badanie", "first_letter", "b", 16), + ("a2_health_doctor_t17", None, "topic_test", "production", "recepta_i_apteka_vocabulary", 2, + "Wpisz brakujące słowo: Idę do ___. (аптеки)", "Вставьте пропущенное слово: Idę do ___. (аптеки)", "Вставте пропущене слово: Idę do ___. (аптеки)", "Fill in the missing word: Idę do ___. (pharmacy)", + "apteki", "first_letter", "a", 17), + ("a2_health_doctor_t18", None, "topic_test", "production", "opisuje_swoje_zdrowie", 3, + "Przetłumacz: «Мне следует пойти к врачу».", "Переведите: «Мне следует пойти к врачу».", "Перекладіть: «Мені слід піти до лікаря».", "Translate: “I should go to the doctor.”", + "Powinienem iść do lekarza", "first_letter", "P", 18), + + ("a2_health_doctor_t19", None, "topic_test", "mixed", "opisuje_swoje_zdrowie", 3, + "Wybierz poprawne tłumaczenie: «Я плохо себя чувствую, у меня болит голова и горло, мне нужно пойти к врачу».", "Выберите правильный перевод: «Я плохо себя чувствую, у меня болит голова и горло, мне нужно пойти к врачу».", "Виберіть правильний переклад: «Я почуваюся погано, у мене болить голова і горло, мені треба піти до лікаря».", "Choose the correct translation: “I feel bad, my head and throat hurt, I have to go to the doctor.”", + "C", None, None, 19), + ("a2_health_doctor_t20", None, "topic_test", "mixed", "dawac_rady_zdrowotne", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Что с тобой? — Мне следует пойти к врачу, потому что у меня температура.»", "Выберите правильный перевод диалога: «— Что с тобой? — Мне следует пойти к врачу, потому что у меня температура.»", "Виберіть правильний переклад діалогу: «— Що з тобою? — Мені слід піти до лікаря, бо в мене температура.»", "Choose the correct translation of the dialogue: “— What's wrong with you? — I should go to the doctor because I have a fever.”", + "C", None, None, 20), + ] + + for q in test_questions_t3_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_health_doctor', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t3_a2 = [ + ("a2_health_doctor_t01", "A", "głowa", "голова", "голова", "head", False, "wrong_word"), + ("a2_health_doctor_t01", "B", "gardło", "горло", "горло", "throat", False, "wrong_word"), + ("a2_health_doctor_t01", "C", "brzuch", "живот", "живіт", "stomach", True, None), + ("a2_health_doctor_t01", "D", "plecy", "спина", "спина", "back", False, "wrong_word"), + + ("a2_health_doctor_t02", "A", "Boli", "болит", "болить", "hurts", True, None), + ("a2_health_doctor_t02", "B", "Bolą", "болят (мн.ч. — не подходит к «głowa»)", "болять (мн. — не пасує до «głowa»)", "hurt (plural — doesn't fit „głowa”)", False, "wrong_number"), + ("a2_health_doctor_t02", "C", "Boję", "боюсь (другой глагол)", "боюся (інше дієслово)", "I'm afraid (a different verb)", False, "wrong_word"), + ("a2_health_doctor_t02", "D", "Bolałam", "болела (форма для женщины, прошедшее время)", "боліла (форма для жінки, минулий час)", "hurt (female past-tense form)", False, "wrong_sentence_type"), + + ("a2_health_doctor_t03", "A", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", False, "wrong_translation"), + ("a2_health_doctor_t03", "B", "Jestem zmęczony.", "Я устал.", "Я втомився.", "I'm tired.", False, "wrong_translation"), + ("a2_health_doctor_t03", "C", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", False, "wrong_translation"), + ("a2_health_doctor_t03", "D", "Czuję się źle.", "Я чувствую себя плохо.", "Я почуваюся погано.", "I feel bad.", True, None), + + ("a2_health_doctor_t04", "A", "gorączka", "температура", "температура", "fever", False, "wrong_word"), + ("a2_health_doctor_t04", "B", "kaszel", "кашель", "кашель", "cough", False, "wrong_word"), + ("a2_health_doctor_t04", "C", "katar", "насморк", "нежить", "runny nose", True, None), + ("a2_health_doctor_t04", "D", "ból głowy", "головная боль", "головний біль", "headache", False, "wrong_word"), + + ("a2_health_doctor_t05", "A", "Muszę", "я должен", "я мушу", "I have to", True, None), + ("a2_health_doctor_t05", "B", "Musisz", "ты должен (не тот человек)", "ти мусиш (не та особа)", "you have to (wrong person)", False, "wrong_context"), + ("a2_health_doctor_t05", "C", "Musi", "он/она должен (не тот человек)", "він/вона мусить (не та особа)", "he/she has to (wrong person)", False, "wrong_context"), + ("a2_health_doctor_t05", "D", "Musiały", "они должны были (неправильное число и время)", "вони мусили (неправильне число і час)", "they had to (wrong number and tense)", False, "wrong_number"), + + ("a2_health_doctor_t06", "A", "Idę do lekarza.", "Я иду к врачу.", "Я йду до лікаря.", "I'm going to the doctor.", False, "wrong_translation"), + ("a2_health_doctor_t06", "B", "Chcę iść do lekarza.", "Я хочу пойти к врачу.", "Я хочу піти до лікаря.", "I want to go to the doctor.", False, "wrong_translation"), + ("a2_health_doctor_t06", "C", "Pójdę do lekarza.", "Я пойду к врачу.", "Я піду до лікаря.", "I will go to the doctor.", False, "wrong_translation"), + ("a2_health_doctor_t06", "D", "Musiałem iść do lekarza.", "Я был вынужден пойти к врачу.", "Я мусив піти до лікаря.", "I had to go to the doctor.", True, None), + + ("a2_health_doctor_t07", "A", "brzuch", "живот", "живіт", "stomach", True, None), + ("a2_health_doctor_t07", "B", "gardło", "горло", "горло", "throat", False, "wrong_context"), + ("a2_health_doctor_t07", "C", "głowa", "голова", "голова", "head", False, "wrong_context"), + ("a2_health_doctor_t07", "D", "plecy", "спина", "спина", "back", False, "wrong_context"), + + ("a2_health_doctor_t08", "A", "Boli mnie głowa.", "У меня болит голова.", "У мене болить голова.", "My head hurts.", True, None), + ("a2_health_doctor_t08", "B", "Boli mnie gardło.", "У меня болит горло. (не соответствует ситуации)", "У мене болить горло. (не відповідає ситуації)", "My throat hurts. (doesn't match the situation)", False, "wrong_context"), + ("a2_health_doctor_t08", "C", "Bolą mnie plecy.", "У меня болит спина. (не соответствует ситуации)", "У мене болить спина. (не відповідає ситуації)", "My back hurts. (doesn't match the situation)", False, "wrong_context"), + ("a2_health_doctor_t08", "D", "Boli mnie brzuch.", "У меня болит живот. (не соответствует ситуации)", "У мене болить живіт. (не відповідає ситуації)", "My stomach hurts. (doesn't match the situation)", False, "wrong_context"), + + ("a2_health_doctor_t09", "A", "Czuję się źle.", "Я чувствую себя плохо. (противоречит ситуации)", "Я почуваюся погано. (суперечить ситуації)", "I feel bad. (contradicts the situation)", False, "wrong_context"), + ("a2_health_doctor_t09", "B", "Czuję się dobrze.", "Я чувствую себя хорошо.", "Я почуваюся добре.", "I feel good.", True, None), + ("a2_health_doctor_t09", "C", "Czuję się słabo.", "Я чувствую себя слабо. (противоречит ситуации)", "Я почуваюся слабо. (суперечить ситуації)", "I feel weak. (contradicts the situation)", False, "wrong_context"), + ("a2_health_doctor_t09", "D", "Boli mnie głowa.", "У меня болит голова. (не о самочувствии в целом)", "У мене болить голова. (не про самопочуття загалом)", "My head hurts. (not about overall wellbeing)", False, "wrong_context"), + + ("a2_health_doctor_t10", "A", "Umawiam się na wizytę.", "Я записываюсь на приём.", "Я записуюся на прийом.", "I'm booking an appointment.", True, None), + ("a2_health_doctor_t10", "B", "Idę do apteki.", "Я иду в аптеку. (не о записи)", "Я йду в аптеку. (не про запис)", "I'm going to the pharmacy. (not about booking)", False, "wrong_context"), + ("a2_health_doctor_t10", "C", "Biorę lekarstwo.", "Я принимаю лекарство. (не о записи)", "Я приймаю ліки. (не про запис)", "I'm taking medicine. (not about booking)", False, "wrong_context"), + ("a2_health_doctor_t10", "D", "Czuję się źle.", "Я чувствую себя плохо. (не о записи)", "Я почуваюся погано. (не про запис)", "I feel bad. (not about booking)", False, "wrong_context"), + + ("a2_health_doctor_t11", "A", "recepta", "рецепт", "рецепт", "prescription", True, None), + ("a2_health_doctor_t11", "B", "apteka", "аптека", "аптека", "pharmacy", False, "wrong_context"), + ("a2_health_doctor_t11", "C", "tabletki", "таблетки", "таблетки", "pills", False, "wrong_context"), + ("a2_health_doctor_t11", "D", "gorączka", "температура", "температура", "fever", False, "wrong_context"), + + ("a2_health_doctor_t12", "A", "Muszę iść do apteki.", "Мне нужно пойти в аптеку. (настоящее время)", "Мені треба піти в аптеку. (теперішній час)", "I have to go to the pharmacy. (present tense)", False, "wrong_sentence_type"), + ("a2_health_doctor_t12", "B", "Musiałem iść do apteki.", "Я был вынужден пойти в аптеку.", "Я мусив піти в аптеку.", "I had to go to the pharmacy.", True, None), + ("a2_health_doctor_t12", "C", "Będę musiał iść do apteki.", "Мне нужно будет пойти в аптеку. (будущее время)", "Мені треба буде піти в аптеку. (майбутній час)", "I will have to go to the pharmacy. (future tense)", False, "wrong_sentence_type"), + ("a2_health_doctor_t12", "D", "Musiałam iść do apteki.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + + ("a2_health_doctor_t19", "A", "Czułem się źle, bolała mnie głowa i gardło, musiałem iść do lekarza.", "Я чувствовал себя плохо, у меня болели голова и горло, мне нужно было пойти к врачу. (прошедшее время)", "Я почувався погано, у мене боліли голова і горло, мені треба було піти до лікаря. (минулий час)", "I felt bad, my head and throat hurt, I had to go to the doctor. (past tense)", False, "wrong_sentence_type"), + ("a2_health_doctor_t19", "B", "Będę się czuć źle, będzie mnie bolała głowa i gardło, będę musiał iść do lekarza.", "Я буду чувствовать себя плохо, у меня будет болеть голова и горло, мне нужно будет пойти к врачу. (будущее время)", "Я почуватимусь погано, у мене болітиме голова і горло, мені треба буде піти до лікаря. (майбутній час)", "I will feel bad, my head and throat will hurt, I will have to go to the doctor. (future tense)", False, "wrong_sentence_type"), + ("a2_health_doctor_t19", "C", "Czuję się źle, boli mnie głowa i gardło, muszę iść do lekarza.", "Я чувствую себя плохо, у меня болит голова и горло, мне нужно пойти к врачу.", "Я почуваюся погано, у мене болить голова і горло, мені треба піти до лікаря.", "I feel bad, my head and throat hurt, I have to go to the doctor.", True, None), + ("a2_health_doctor_t19", "D", "Czuję się źle, boli mnie brzuch i plecy, muszę iść do apteki.", "Я чувствую себя плохо, у меня болит живот и спина, мне нужно пойти в аптеку. (неверные части тела и место)", "Я почуваюся погано, у мене болить живіт і спина, мені треба піти в аптеку. (невірні частини тіла і місце)", "I feel bad, my stomach and back hurt, I have to go to the pharmacy. (wrong body parts and place)", False, "wrong_word"), + + ("a2_health_doctor_t20", "A", "— Co ci jest? — Muszę iść do lekarza, bo mam gorączkę.", "— Что с тобой? — Мне нужно пойти к врачу, потому что у меня температура. (неверная модальность)", "— Що з тобою? — Мені треба піти до лікаря, бо в мене температура. (невірна модальність)", "— What's wrong with you? — I have to go to the doctor because I have a fever. (wrong modality)", False, "wrong_word"), + ("a2_health_doctor_t20", "B", "— Co ci jest? — Powinienem iść do apteki, bo mam gorączkę.", "— Что с тобой? — Мне следует пойти в аптеку, потому что у меня температура. (неверное место)", "— Що з тобою? — Мені слід піти в аптеку, бо в мене температура. (невірне місце)", "— What's wrong with you? — I should go to the pharmacy because I have a fever. (wrong place)", False, "wrong_word"), + ("a2_health_doctor_t20", "C", "— Co ci jest? — Powinienem iść do lekarza, bo mam gorączkę.", "— Что с тобой? — Мне следует пойти к врачу, потому что у меня температура.", "— Що з тобою? — Мені слід піти до лікаря, бо в мене температура.", "— What's wrong with you? — I should go to the doctor because I have a fever.", True, None), + ("a2_health_doctor_t20", "D", "— Gdzie jesteś? — Powinienem iść do lekarza, bo mam gorączkę.", "— Где ты? — Мне следует пойти к врачу, потому что у меня температура. (неверный вопрос)", "— Де ти? — Мені слід піти до лікаря, бо в мене температура. (невірне питання)", "— Where are you? — I should go to the doctor because I have a fever. (wrong question)", False, "wrong_translation"), + ] + + for opt in test_options_t3_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 4 (A2): ПОКУПКИ И УСЛУГИ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_shopping_services', 'A2', 4, + 'Zakupy i usługi', + 'Покупки и услуги', + 'Покупки і послуги', + 'Shopping and Services') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t4_a2 = [ + ("a2_shopping_services_l01", 1, "sklepy_vocabulary", "Podstawowe słowa: sklepy", "Основные слова: магазины", "Основні слова: магазини", "Basic words: shops", + "Podstawowe nazwy sklepów: sklep spożywczy, piekarnia, apteka, kiosk.", + "Основные названия магазинов: sklep spożywczy (продуктовый магазин), piekarnia (пекарня), apteka (аптека), kiosk (киоск).", + "Основні назви магазинів: sklep spożywczy (продуктовий магазин), piekarnia (пекарня), apteka (аптека), kiosk (кіоск).", + "Basic shop names: sklep spożywczy (grocery store), piekarnia (bakery), apteka (pharmacy), kiosk (kiosk)."), + + ("a2_shopping_services_l02", 2, "kupowac_biernik", "Kupować + biernik", "Kupować + винительный падеж", "Kupować + знахідний відмінок", "Kupować + accusative", + "Czasownik „kupować” + biernik: kupuję chleb, kupujesz mleko, kupuje owoce.", + "Глагол „kupować” (покупать) + винительный падеж: kupuję chleb (я покупаю хлеб), kupujesz mleko (ты покупаешь молоко), kupuje owoce (он/она покупает фрукты).", + "Дієслово „kupować” (купувати) + знахідний відмінок: kupuję chleb (я купую хліб), kupujesz mleko (ти купуєш молоко), kupuje owoce (він/вона купує фрукти).", + "The verb „kupować” (to buy) + accusative: kupuję chleb (I'm buying bread), kupujesz mleko (you're buying milk), kupuje owoce (he/she is buying fruit)."), + + ("a2_shopping_services_l03", 3, "ile_to_kosztuje", "Ile to kosztuje?", "Ile to kosztuje? (Сколько это стоит?)", "Ile to kosztuje? (Скільки це коштує?)", "Ile to kosztuje? (How much does it cost?)", + "Żeby zapytać o cenę, mówimy „Ile to kosztuje?”. Odpowiadamy liczbą + „złotych”: To kosztuje dziesięć złotych.", + "Чтобы спросить о цене, говорим „Ile to kosztuje?” (Сколько это стоит?). Отвечаем числом + „złotych” (злотых): To kosztuje dziesięć złotych (Это стоит десять злотых).", + "Щоб запитати про ціну, кажемо „Ile to kosztuje?” (Скільки це коштує?). Відповідаємо числом + „złotych” (злотих): To kosztuje dziesięć złotych (Це коштує десять злотих).", + "To ask about the price, we say „Ile to kosztuje?” (How much does it cost?). We answer with a number + „złotych” (zlotys): To kosztuje dziesięć złotych (It costs ten zlotys)."), + + ("a2_shopping_services_l04", 4, "ubrania_vocabulary", "Podstawowe słowa: ubrania", "Основные слова: одежда", "Основні слова: одяг", "Basic words: clothes", + "Podstawowe nazwy ubrań: koszula, spodnie, buty, kurtka.", + "Основные названия одежды: koszula (рубашка), spodnie (брюки), buty (обувь), kurtka (куртка).", + "Основні назви одягу: koszula (сорочка), spodnie (штани), buty (взуття), kurtka (куртка).", + "Basic clothing names: koszula (shirt), spodnie (pants), buty (shoes), kurtka (jacket)."), + + ("a2_shopping_services_l05", 5, "przymierzac_i_rozmiar", "Przymierzać + biernik, rozmiar", "Przymierzać + винительный падеж, размер", "Przymierzać + знахідний відмінок, розмір", "Przymierzać + accusative, size", + "Czasownik „przymierzać” + biernik: przymierzam koszulę, przymierzasz buty. Pytamy o rozmiar: Jaki masz rozmiar?", + "Глагол „przymierzać” (примерять) + винительный падеж: przymierzam koszulę (я примеряю рубашку), przymierzasz buty (ты примеряешь обувь). Спрашиваем о размере: Jaki masz rozmiar? (Какой у тебя размер?).", + "Дієслово „przymierzać” (приміряти) + знахідний відмінок: przymierzam koszulę (я приміряю сорочку), przymierzasz buty (ти приміряєш взуття). Питаємо про розмір: Jaki masz rozmiar? (Який у тебе розмір?).", + "The verb „przymierzać” (to try on) + accusative: przymierzam koszulę (I'm trying on a shirt), przymierzasz buty (you're trying on shoes). We ask about size: Jaki masz rozmiar? (What size are you?)."), + + ("a2_shopping_services_l06", 6, "uslugi_vocabulary", "Podstawowe słowa: usługi", "Основные слова: услуги", "Основні слова: послуги", "Basic words: services", + "Podstawowe słowa dotyczące usług: fryzjer, pralnia, naprawa, krawiec.", + "Основные слова об услугах: fryzjer (парикмахер), pralnia (прачечная), naprawa (ремонт), krawiec (портной).", + "Основні слова про послуги: fryzjer (перукар), pralnia (пральня), naprawa (ремонт), krawiec (кравець).", + "Basic words about services: fryzjer (hairdresser), pralnia (laundry), naprawa (repair), krawiec (tailor)."), + + ("a2_shopping_services_l07", 7, "potrzebowac_dopelniacz", "Potrzebować + dopełniacz", "Potrzebować + родительный падеж", "Potrzebować + родовий відмінок", "Potrzebować + genitive", + "Czasownik „potrzebować” + dopełniacz: potrzebuję nowych butów, potrzebujesz kurtki.", + "Глагол „potrzebować” (нуждаться) + родительный падеж: potrzebuję nowych butów (мне нужна новая обувь), potrzebujesz kurtki (тебе нужна куртка).", + "Дієслово „potrzebować” (потребувати) + родовий відмінок: potrzebuję nowych butów (мені потрібне нове взуття), potrzebujesz kurtki (тобі потрібна куртка).", + "The verb „potrzebować” (to need) + genitive: potrzebuję nowych butów (I need new shoes), potrzebujesz kurtki (you need a jacket)."), + + ("a2_shopping_services_l08", 8, "zwracac_i_reklamowac", "Zwracać / reklamować + biernik", "Zwracać / reklamować + винительный падеж", "Zwracać / reklamować + знахідний відмінок", "Zwracać / reklamować + accusative", + "Czasowniki „zwracać” (oddawać) i „reklamować” (zgłaszać wadę) + biernik: zwracam koszulę, reklamuję buty.", + "Глаголы „zwracać” (возвращать) и „reklamować” (предъявлять претензию) + винительный падеж: zwracam koszulę (я возвращаю рубашку), reklamuję buty (я предъявляю претензию на обувь).", + "Дієслова „zwracać” (повертати) і „reklamować” (подавати претензію) + знахідний відмінок: zwracam koszulę (я повертаю сорочку), reklamuję buty (я подаю претензію на взуття).", + "The verbs „zwracać” (to return) and „reklamować” (to file a complaint) + accusative: zwracam koszulę (I'm returning the shirt), reklamuję buty (I'm filing a complaint about the shoes)."), + + ("a2_shopping_services_l09", 9, "przyszly_czas_zakupy", "Czas przyszły: będę + bezokolicznik", "Будущее время: będę + инфинитив", "Майбутній час: będę + інфінітив", "Future tense: będę + infinitive", + "Czas przyszły złożony tworzymy „będę” + bezokolicznik: będę kupować ubrania, będziesz potrzebować butów.", + "Сложное будущее время образуем „będę” (я буду) + инфинитив: będę kupować ubrania (я буду покупать одежду), będziesz potrzebować butów (тебе понадобится обувь).", + "Складний майбутній час утворюємо „będę” (я буду) + інфінітив: będę kupować ubrania (я буду купувати одяг), będziesz potrzebować butów (тобі знадобиться взуття).", + "We form the compound future tense with „będę” (I will) + infinitive: będę kupować ubrania (I will be buying clothes), będziesz potrzebować butów (you will need shoes)."), + + ("a2_shopping_services_l10", 10, "opisuje_swoje_zakupy", "Opisuję swoje zakupy", "Описываю свои покупки", "Описую свої покупки", "Describing my shopping", + "Żeby opisać zakupy, łączymy zdania: Idę do sklepu. Potrzebuję nowych butów. Przymierzam buty i pytam: Ile to kosztuje? Będę kupować więcej ubrań w przyszłym tygodniu.", + "Чтобы описать покупки, соединяем предложения: Idę do sklepu. Potrzebuję nowych butów. Przymierzam buty i pytam: Ile to kosztuje? Będę kupować więcej ubrań w przyszłym tygodniu. (Я иду в магазин. Мне нужна новая обувь. Я примеряю обувь и спрашиваю: Сколько это стоит? Я буду покупать больше одежды на следующей неделе.)", + "Щоб описати покупки, поєднуємо речення: Idę do sklepu. Potrzebuję nowych butów. Przymierzam buty i pytam: Ile to kosztuje? Będę kupować więcej ubrań w przyszłym tygodniu. (Я йду в магазин. Мені потрібне нове взуття. Я приміряю взуття і питаю: Скільки це коштує? Я буду купувати більше одягу наступного тижня.)", + "To describe your shopping, we combine sentences: Idę do sklepu. Potrzebuję nowych butów. Przymierzam buty i pytam: Ile to kosztuje? Będę kupować więcej ubrań w przyszłym tygodniu. (I'm going to the store. I need new shoes. I try on shoes and ask: How much does it cost? I will be buying more clothes next week.)"), + ] + + for lesson in lessons_t4_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_shopping_services', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t4_a2 = [ + ("a2_shopping_services_l01", 1, "To jest sklep spożywczy.", "Это продуктовый магазин.", "Це продуктовий магазин.", "This is a grocery store."), + ("a2_shopping_services_l01", 2, "To jest piekarnia.", "Это пекарня.", "Це пекарня.", "This is a bakery."), + ("a2_shopping_services_l01", 3, "To jest kiosk.", "Это киоск.", "Це кіоск.", "This is a kiosk."), + + ("a2_shopping_services_l02", 1, "Kupuję chleb.", "Я покупаю хлеб.", "Я купую хліб.", "I'm buying bread."), + ("a2_shopping_services_l02", 2, "Kupujesz mleko?", "Ты покупаешь молоко?", "Ти купуєш молоко?", "Are you buying milk?"), + ("a2_shopping_services_l02", 3, "Ona kupuje owoce.", "Она покупает фрукты.", "Вона купує фрукти.", "She's buying fruit."), + + ("a2_shopping_services_l03", 1, "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does it cost?"), + ("a2_shopping_services_l03", 2, "To kosztuje dziesięć złotych.", "Это стоит десять злотых.", "Це коштує десять злотих.", "It costs ten zlotys."), + ("a2_shopping_services_l03", 3, "Chleb kosztuje trzy złote.", "Хлеб стоит три злотых.", "Хліб коштує три злотих.", "Bread costs three zlotys."), + + ("a2_shopping_services_l04", 1, "To jest koszula.", "Это рубашка.", "Це сорочка.", "This is a shirt."), + ("a2_shopping_services_l04", 2, "To są buty.", "Это обувь.", "Це взуття.", "These are shoes."), + ("a2_shopping_services_l04", 3, "To jest kurtka.", "Это куртка.", "Це куртка.", "This is a jacket."), + + ("a2_shopping_services_l05", 1, "Przymierzam koszulę.", "Я примеряю рубашку.", "Я приміряю сорочку.", "I'm trying on a shirt."), + ("a2_shopping_services_l05", 2, "Przymierzasz buty?", "Ты примеряешь обувь?", "Ти приміряєш взуття?", "Are you trying on shoes?"), + ("a2_shopping_services_l05", 3, "Jaki masz rozmiar?", "Какой у тебя размер?", "Який у тебе розмір?", "What size are you?"), + + ("a2_shopping_services_l06", 1, "Idę do fryzjera.", "Я иду к парикмахеру.", "Я йду до перукаря.", "I'm going to the hairdresser."), + ("a2_shopping_services_l06", 2, "Oddaję ubrania do pralni.", "Я сдаю одежду в прачечную.", "Я здаю одяг у пральню.", "I'm dropping off clothes at the laundry."), + ("a2_shopping_services_l06", 3, "Krawiec naprawia spodnie.", "Портной чинит брюки.", "Кравець лагодить штани.", "The tailor is fixing the pants."), + + ("a2_shopping_services_l07", 1, "Potrzebuję nowych butów.", "Мне нужна новая обувь.", "Мені потрібне нове взуття.", "I need new shoes."), + ("a2_shopping_services_l07", 2, "Potrzebujesz kurtki?", "Тебе нужна куртка?", "Тобі потрібна куртка?", "Do you need a jacket?"), + ("a2_shopping_services_l07", 3, "On potrzebuje pomocy krawca.", "Ему нужна помощь портного.", "Йому потрібна допомога кравця.", "He needs the tailor's help."), + + ("a2_shopping_services_l08", 1, "Zwracam koszulę.", "Я возвращаю рубашку.", "Я повертаю сорочку.", "I'm returning the shirt."), + ("a2_shopping_services_l08", 2, "Reklamujesz buty?", "Ты предъявляешь претензию на обувь?", "Ти повертаєш взуття за гарантією?", "Are you making a complaint about the shoes?"), + ("a2_shopping_services_l08", 3, "Ona zwraca kurtkę do sklepu.", "Она возвращает куртку в магазин.", "Вона повертає куртку в магазин.", "She's returning the jacket to the store."), + + ("a2_shopping_services_l09", 1, "Będę kupować ubrania w tym sklepie.", "Я буду покупать одежду в этом магазине.", "Я буду купувати одяг у цьому магазині.", "I will be buying clothes at this store."), + ("a2_shopping_services_l09", 2, "Będziesz potrzebować nowych butów.", "Тебе понадобится новая обувь.", "Тобі знадобиться нове взуття.", "You will need new shoes."), + ("a2_shopping_services_l09", 3, "Będziemy przymierzać kurtki.", "Мы будем примерять куртки.", "Ми будемо приміряти куртки.", "We will be trying on jackets."), + + ("a2_shopping_services_l10", 1, "Idę do sklepu.", "Я иду в магазин.", "Я йду в магазин.", "I'm going to the store."), + ("a2_shopping_services_l10", 2, "Potrzebuję nowych butów.", "Мне нужна новая обувь.", "Мені потрібне нове взуття.", "I need new shoes."), + ("a2_shopping_services_l10", 3, "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does it cost?"), + ] + + for ex in examples_t4_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t4_a2 = [ + # L01 — sklepy_vocabulary (difficulty 1) + ("a2_shopping_services_l01_q1", "a2_shopping_services_l01", "lesson_practice", "recognition", "sklepy_vocabulary", 1, + "Jak po polsku „пекарня”?", "Как по-польски «пекарня»?", "Як польською «пекарня»?", "How do you say “bakery” in Polish?", + "B", None, None), + ("a2_shopping_services_l01_q2", "a2_shopping_services_l01", "lesson_practice", "production", "sklepy_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (киоск)", "Вставьте пропущенное слово: To jest ___. (киоск)", "Вставте пропущене слово: To jest ___. (кіоск)", "Fill in the missing word: To jest ___. (kiosk)", + "kiosk", "first_letter", "k"), + ("a2_shopping_services_l01_q3", "a2_shopping_services_l01", "lesson_practice", "application", "sklepy_vocabulary", 1, + "Chcesz kupić świeży chleb. Dokąd idziesz?", "Ты хочешь купить свежий хлеб. Куда ты идёшь?", "Ти хочеш купити свіжий хліб. Куди ти йдеш?", "You want to buy fresh bread. Where do you go?", + "B", None, None), + + # L02 — kupowac_biernik (difficulty 1) + ("a2_shopping_services_l02_q1", "a2_shopping_services_l02", "lesson_practice", "recognition", "kupowac_biernik", 1, + "Co znaczy „Kupuję chleb”?", "Что означает «Kupuję chleb»?", "Що означає «Kupuję chleb»?", "What does “Kupuję chleb” mean?", + "D", None, None), + ("a2_shopping_services_l02_q2", "a2_shopping_services_l02", "lesson_practice", "production", "kupowac_biernik", 1, + "Wpisz brakujące słowo: Kupujesz ___? (молоко)", "Вставьте пропущенное слово: Kupujesz ___? (молоко)", "Вставте пропущене слово: Kupujesz ___? (молоко)", "Fill in the missing word: Kupujesz ___? (milk)", + "mleko", "first_letter", "m"), + ("a2_shopping_services_l02_q3", "a2_shopping_services_l02", "lesson_practice", "application", "kupowac_biernik", 1, + "Kolega pyta, co kupujesz. Kupujesz owoce. Co powiesz?", "Друг спрашивает, что ты покупаешь. Ты покупаешь фрукты. Что ты скажешь?", "Друг питає, що ти купуєш. Ти купуєш фрукти. Що ти скажеш?", "A friend asks what you're buying. You're buying fruit. What do you say?", + "C", None, None), + + # L03 — ile_to_kosztuje (difficulty 1) + ("a2_shopping_services_l03_q1", "a2_shopping_services_l03", "lesson_practice", "recognition", "ile_to_kosztuje", 1, + "Co znaczy „Ile to kosztuje?”?", "Что означает «Ile to kosztuje?»?", "Що означає «Ile to kosztuje?»?", "What does “Ile to kosztuje?” mean?", + "C", None, None), + ("a2_shopping_services_l03_q2", "a2_shopping_services_l03", "lesson_practice", "production", "ile_to_kosztuje", 1, + "Wpisz brakujące słowo: To ___ dziesięć złotych. (стоит)", "Вставьте пропущенное слово: To ___ dziesięć złotych. (стоит)", "Вставте пропущене слово: To ___ dziesięć złotych. (коштує)", "Fill in the missing word: To ___ dziesięć złotych. (costs)", + "kosztuje", "first_letter", "k"), + ("a2_shopping_services_l03_q3", "a2_shopping_services_l03", "lesson_practice", "application", "ile_to_kosztuje", 1, + "Chcesz zapytać sprzedawcę o cenę chleba. Co powiesz?", "Ты хочешь спросить продавца о цене хлеба. Что ты скажешь?", "Ти хочеш запитати продавця про ціну хліба. Що ти скажеш?", "You want to ask the seller about the price of bread. What do you say?", + "A", None, None), + + # L04 — ubrania_vocabulary (difficulty 1) + ("a2_shopping_services_l04_q1", "a2_shopping_services_l04", "lesson_practice", "recognition", "ubrania_vocabulary", 1, + "Jak po polsku „брюки”?", "Как по-польски «брюки»?", "Як польською «штани»?", "How do you say “pants” in Polish?", + "B", None, None), + ("a2_shopping_services_l04_q2", "a2_shopping_services_l04", "lesson_practice", "production", "ubrania_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (куртка)", "Вставьте пропущенное слово: To jest ___. (куртка)", "Вставте пропущене слово: To jest ___. (куртка)", "Fill in the missing word: To jest ___. (jacket)", + "kurtka", "first_letter", "k"), + ("a2_shopping_services_l04_q3", "a2_shopping_services_l04", "lesson_practice", "application", "ubrania_vocabulary", 1, + "Jest zimno na dworze. Co ubierzesz?", "На улице холодно. Что ты наденешь?", "На вулиці холодно. Що ти вдягнеш?", "It's cold outside. What will you put on?", + "C", None, None), + + # L05 — przymierzac_i_rozmiar (difficulty 2) + ("a2_shopping_services_l05_q1", "a2_shopping_services_l05", "lesson_practice", "recognition", "przymierzac_i_rozmiar", 2, + "Wybierz poprawną formę: Przymierzam ___. (kurtka)", "Выберите правильную форму: Przymierzam ___. (kurtka)", "Виберіть правильну форму: Przymierzam ___. (kurtka)", "Choose the correct form: Przymierzam ___. (kurtka)", + "A", None, None), + ("a2_shopping_services_l05_q2", "a2_shopping_services_l05", "lesson_practice", "production", "przymierzac_i_rozmiar", 2, + "Wpisz brakujące słowo: Jaki masz ___? (размер)", "Вставьте пропущенное слово: Jaki masz ___? (размер)", "Вставте пропущене слово: Jaki masz ___? (розмір)", "Fill in the missing word: Jaki masz ___? (size)", + "rozmiar", "first_letter", "r"), + ("a2_shopping_services_l05_q3", "a2_shopping_services_l05", "lesson_practice", "application", "przymierzac_i_rozmiar", 2, + "W sklepie chcesz sprawdzić, czy buty pasują. Co robisz?", "В магазине ты хочешь проверить, подходит ли обувь. Что ты делаешь?", "У магазині ти хочеш перевірити, чи взуття підходить. Що ти робиш?", "In the store, you want to check if the shoes fit. What are you doing?", + "B", None, None), + + # L06 — uslugi_vocabulary (difficulty 2) + ("a2_shopping_services_l06_q1", "a2_shopping_services_l06", "lesson_practice", "recognition", "uslugi_vocabulary", 2, + "Jak po polsku „парикмахер”?", "Как по-польски «парикмахер»?", "Як польською «перукар»?", "How do you say “hairdresser” in Polish?", + "A", None, None), + ("a2_shopping_services_l06_q2", "a2_shopping_services_l06", "lesson_practice", "production", "uslugi_vocabulary", 2, + "Wpisz brakujące słowo: Oddaję ubrania do ___. (прачечной)", "Вставьте пропущенное слово: Oddaję ubrania do ___. (прачечной)", "Вставте пропущене слово: Oddaję ubrania do ___. (пральні)", "Fill in the missing word: Oddaję ubrania do ___. (laundry)", + "pralni", "first_letter", "p"), + ("a2_shopping_services_l06_q3", "a2_shopping_services_l06", "lesson_practice", "application", "uslugi_vocabulary", 2, + "Twoje spodnie są za długie i potrzebujesz kogoś, kto je skróci. Do kogo idziesz?", "Твои брюки слишком длинные, и тебе нужен кто-то, кто их укоротит. К кому ты идёшь?", "Твої штани занадто довгі, і тобі потрібен хтось, хто їх укоротить. До кого ти йдеш?", "Your pants are too long and you need someone to shorten them. Who do you go to?", + "B", None, None), + + # L07 — potrzebowac_dopelniacz (difficulty 2) + ("a2_shopping_services_l07_q1", "a2_shopping_services_l07", "lesson_practice", "recognition", "potrzebowac_dopelniacz", 2, + "Wybierz poprawną formę: Potrzebuję ___. (nowe buty)", "Выберите правильную форму: Potrzebuję ___. (nowe buty)", "Виберіть правильну форму: Potrzebuję ___. (nowe buty)", "Choose the correct form: Potrzebuję ___. (nowe buty)", + "A", None, None), + ("a2_shopping_services_l07_q2", "a2_shopping_services_l07", "lesson_practice", "production", "potrzebowac_dopelniacz", 2, + "Wpisz brakujące słowo: Potrzebujesz ___? (куртки)", "Вставьте пропущенное слово: Potrzebujesz ___? (куртки)", "Вставте пропущене слово: Potrzebujesz ___? (куртки)", "Fill in the missing word: Potrzebujesz ___? (a jacket)", + "kurtki", "first_letter", "k"), + ("a2_shopping_services_l07_q3", "a2_shopping_services_l07", "lesson_practice", "application", "potrzebowac_dopelniacz", 2, + "Twoje stare buty są zniszczone i chcesz kupić nowe. Co powiesz?", "Твоя старая обувь изношена, и ты хочешь купить новую. Что ты скажешь?", "Твоє старе взуття зношене, і ти хочеш купити нове. Що ти скажеш?", "Your old shoes are worn out and you want to buy new ones. What do you say?", + "A", None, None), + + # L08 — zwracac_i_reklamowac (difficulty 2) + ("a2_shopping_services_l08_q1", "a2_shopping_services_l08", "lesson_practice", "recognition", "zwracac_i_reklamowac", 2, + "Co znaczy „Zwracam koszulę”?", "Что означает «Zwracam koszulę»?", "Що означає «Zwracam koszulę»?", "What does “Zwracam koszulę” mean?", + "D", None, None), + ("a2_shopping_services_l08_q2", "a2_shopping_services_l08", "lesson_practice", "production", "zwracac_i_reklamowac", 2, + "Wpisz brakujące słowo: ___ buty do sklepu. (я возвращаю)", "Вставьте пропущенное слово: ___ buty do sklepu. (я возвращаю)", "Вставте пропущене слово: ___ buty do sklepu. (я повертаю)", "Fill in the missing word: ___ buty do sklepu. (I'm returning)", + "Zwracam", "first_letter", "Z"), + ("a2_shopping_services_l08_q3", "a2_shopping_services_l08", "lesson_practice", "application", "zwracac_i_reklamowac", 2, + "Kupione buty są za małe i chcesz je oddać do sklepu. Co powiesz?", "Купленная обувь мала, и ты хочешь её вернуть в магазин. Что ты скажешь?", "Куплене взуття замале, і ти хочеш його повернути в магазин. Що ти скажеш?", "The shoes you bought are too small and you want to return them to the store. What do you say?", + "C", None, None), + + # L09 — przyszly_czas_zakupy (difficulty 3) + ("a2_shopping_services_l09_q1", "a2_shopping_services_l09", "lesson_practice", "recognition", "przyszly_czas_zakupy", 3, + "Co znaczy „Będę kupować ubrania”?", "Что означает «Będę kupować ubrania»?", "Що означає «Będę kupować ubrania»?", "What does “Będę kupować ubrania” mean?", + "D", None, None), + ("a2_shopping_services_l09_q2", "a2_shopping_services_l09", "lesson_practice", "production", "przyszly_czas_zakupy", 3, + "Wpisz brakujące słowo: ___ potrzebować nowych butów. (ты будешь)", "Вставьте пропущенное слово: ___ potrzebować nowych butów. (ты будешь)", "Вставте пропущене слово: ___ potrzebować nowych butów. (ти будеш)", "Fill in the missing word: ___ potrzebować nowych butów. (you will)", + "Będziesz", "first_letter", "B"), + ("a2_shopping_services_l09_q3", "a2_shopping_services_l09", "lesson_practice", "application", "przyszly_czas_zakupy", 3, + "Planujesz iść jutro na zakupy i kupować nowe ubrania. Co powiesz?", "Ты планируешь завтра пойти по магазинам и купить новую одежду. Что ты скажешь?", "Ти плануєш завтра піти за покупками і купити новий одяг. Що ти скажеш?", "You're planning to go shopping tomorrow and buy new clothes. What do you say?", + "C", None, None), + + # L10 — opisuje_swoje_zakupy (difficulty 3) + ("a2_shopping_services_l10_q1", "a2_shopping_services_l10", "lesson_practice", "recognition", "opisuje_swoje_zakupy", 3, + "Które zdanie poprawnie opisuje zakupy?", "Какое предложение правильно описывает покупки?", "Яке речення правильно описує покупки?", "Which sentence correctly describes shopping?", + "D", None, None), + ("a2_shopping_services_l10_q2", "a2_shopping_services_l10", "lesson_practice", "production", "opisuje_swoje_zakupy", 3, + "Przetłumacz: «Сколько это стоит?»", "Переведите: «Сколько это стоит?»", "Перекладіть: «Скільки це коштує?»", "Translate: “How much does it cost?”", + "Ile to kosztuje?", "first_letter", "I"), + ("a2_shopping_services_l10_q3", "a2_shopping_services_l10", "lesson_practice", "application", "opisuje_swoje_zakupy", 3, + "Chcesz opisać koledze swoje zakupy: idziesz do sklepu, potrzebujesz butów, pytasz o cenę. Jak zaczniesz zdanie?", "Ты хочешь описать другу свои покупки: ты идёшь в магазин, тебе нужна обувь, ты спрашиваешь о цене. Как ты начнёшь предложение?", "Ти хочеш описати другу свої покупки: ти йдеш у магазин, тобі потрібне взуття, ти питаєш про ціну. Як ти почнеш речення?", "You want to describe your shopping to a friend: you go to the store, you need shoes, you ask about the price. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t4_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_shopping_services', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t4_a2 = [ + # L01 + ("a2_shopping_services_l01_q1", "A", "sklep spożywczy", "продуктовый магазин", "продуктовий магазин", "grocery store", False, "wrong_word"), + ("a2_shopping_services_l01_q1", "B", "piekarnia", "пекарня", "пекарня", "bakery", True, None), + ("a2_shopping_services_l01_q1", "C", "apteka", "аптека", "аптека", "pharmacy", False, "wrong_word"), + ("a2_shopping_services_l01_q1", "D", "kiosk", "киоск", "кіоск", "kiosk", False, "wrong_word"), + + ("a2_shopping_services_l01_q3", "A", "sklep spożywczy", "продуктовый магазин", "продуктовий магазин", "grocery store", False, "wrong_context"), + ("a2_shopping_services_l01_q3", "B", "piekarnia", "пекарня", "пекарня", "bakery", True, None), + ("a2_shopping_services_l01_q3", "C", "apteka", "аптека", "аптека", "pharmacy", False, "wrong_context"), + ("a2_shopping_services_l01_q3", "D", "kiosk", "киоск", "кіоск", "kiosk", False, "wrong_context"), + + # L02 + ("a2_shopping_services_l02_q1", "A", "Jem chleb.", "Я ем хлеб.", "Я їм хліб.", "I'm eating bread.", False, "wrong_translation"), + ("a2_shopping_services_l02_q1", "B", "Piekę chleb.", "Я пеку хлеб.", "Я печу хліб.", "I'm baking bread.", False, "wrong_translation"), + ("a2_shopping_services_l02_q1", "C", "Sprzedaję chleb.", "Я продаю хлеб.", "Я продаю хліб.", "I'm selling bread.", False, "wrong_translation"), + ("a2_shopping_services_l02_q1", "D", "Kupuję chleb.", "Я покупаю хлеб.", "Я купую хліб.", "I'm buying bread.", True, None), + + ("a2_shopping_services_l02_q3", "A", "Kupuję chleb.", "Я покупаю хлеб. (не соответствует ситуации)", "Я купую хліб. (не відповідає ситуації)", "I'm buying bread. (doesn't match the situation)", False, "wrong_context"), + ("a2_shopping_services_l02_q3", "B", "Kupuję mleko.", "Я покупаю молоко. (не соответствует ситуации)", "Я купую молоко. (не відповідає ситуації)", "I'm buying milk. (doesn't match the situation)", False, "wrong_context"), + ("a2_shopping_services_l02_q3", "C", "Kupuję owoce.", "Я покупаю фрукты.", "Я купую фрукти.", "I'm buying fruit.", True, None), + ("a2_shopping_services_l02_q3", "D", "Sprzedaję owoce.", "Я продаю фрукты. (неверный глагол)", "Я продаю фрукти. (невірне дієслово)", "I'm selling fruit. (wrong verb)", False, "wrong_context"), + + # L03 + ("a2_shopping_services_l03_q1", "A", "Co to jest?", "Что это?", "Що це?", "What is this?", False, "wrong_translation"), + ("a2_shopping_services_l03_q1", "B", "Gdzie to jest?", "Где это?", "Де це?", "Where is this?", False, "wrong_translation"), + ("a2_shopping_services_l03_q1", "C", "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does it cost?", True, None), + ("a2_shopping_services_l03_q1", "D", "Kiedy to będzie?", "Когда это будет?", "Коли це буде?", "When will it be?", False, "wrong_translation"), + + ("a2_shopping_services_l03_q3", "A", "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does it cost?", True, None), + ("a2_shopping_services_l03_q3", "B", "Co to jest?", "Что это? (не о цене)", "Що це? (не про ціну)", "What is this? (not about price)", False, "wrong_context"), + ("a2_shopping_services_l03_q3", "C", "Gdzie to jest?", "Где это? (не о цене)", "Де це? (не про ціну)", "Where is this? (not about price)", False, "wrong_context"), + ("a2_shopping_services_l03_q3", "D", "Kupuję chleb.", "Я покупаю хлеб. (не вопрос)", "Я купую хліб. (не питання)", "I'm buying bread. (not a question)", False, "wrong_context"), + + # L04 + ("a2_shopping_services_l04_q1", "A", "koszula", "рубашка", "сорочка", "shirt", False, "wrong_word"), + ("a2_shopping_services_l04_q1", "B", "spodnie", "брюки", "штани", "pants", True, None), + ("a2_shopping_services_l04_q1", "C", "buty", "обувь", "взуття", "shoes", False, "wrong_word"), + ("a2_shopping_services_l04_q1", "D", "kurtka", "куртка", "куртка", "jacket", False, "wrong_word"), + + ("a2_shopping_services_l04_q3", "A", "koszulę", "рубашку", "сорочку", "shirt", False, "wrong_context"), + ("a2_shopping_services_l04_q3", "B", "spodnie", "брюки", "штани", "pants", False, "wrong_context"), + ("a2_shopping_services_l04_q3", "C", "kurtkę", "куртку", "куртку", "jacket", True, None), + ("a2_shopping_services_l04_q3", "D", "buty", "обувь", "взуття", "shoes", False, "wrong_context"), + + # L05 + ("a2_shopping_services_l05_q1", "A", "kurtkę", "куртку (вин.)", "куртку (знах.)", "jacket (acc.)", True, None), + ("a2_shopping_services_l05_q1", "B", "kurtka", "куртка (им.)", "куртка (наз.)", "jacket (nom.)", False, "wrong_case"), + ("a2_shopping_services_l05_q1", "C", "kurtki", "куртки (род.)", "куртки (род.)", "jacket (gen.)", False, "wrong_case"), + ("a2_shopping_services_l05_q1", "D", "kurtką", "курткой (тв.)", "курткою (ор.)", "jacket (instr.)", False, "wrong_case"), + + ("a2_shopping_services_l05_q3", "A", "Kupuję buty.", "Я покупаю обувь. (не о примерке)", "Я купую взуття. (не про приміряння)", "I'm buying shoes. (not about trying on)", False, "wrong_context"), + ("a2_shopping_services_l05_q3", "B", "Przymierzam buty.", "Я примеряю обувь.", "Я приміряю взуття.", "I'm trying on shoes.", True, None), + ("a2_shopping_services_l05_q3", "C", "Sprzedaję buty.", "Я продаю обувь. (не о примерке)", "Я продаю взуття. (не про приміряння)", "I'm selling shoes. (not about trying on)", False, "wrong_context"), + ("a2_shopping_services_l05_q3", "D", "Szukam butów.", "Я ищу обувь. (не о примерке)", "Я шукаю взуття. (не про приміряння)", "I'm looking for shoes. (not about trying on)", False, "wrong_context"), + + # L06 + ("a2_shopping_services_l06_q1", "A", "fryzjer", "парикмахер", "перукар", "hairdresser", True, None), + ("a2_shopping_services_l06_q1", "B", "pralnia", "прачечная", "пральня", "laundry", False, "wrong_word"), + ("a2_shopping_services_l06_q1", "C", "naprawa", "ремонт", "ремонт", "repair", False, "wrong_word"), + ("a2_shopping_services_l06_q1", "D", "krawiec", "портной", "кравець", "tailor", False, "wrong_word"), + + ("a2_shopping_services_l06_q3", "A", "fryzjera", "парикмахера", "перукаря", "hairdresser", False, "wrong_context"), + ("a2_shopping_services_l06_q3", "B", "krawca", "портного", "кравця", "tailor", True, None), + ("a2_shopping_services_l06_q3", "C", "pralni", "прачечной", "пральні", "laundry", False, "wrong_context"), + ("a2_shopping_services_l06_q3", "D", "apteki", "аптеки", "аптеки", "pharmacy", False, "wrong_context"), + + # L07 + ("a2_shopping_services_l07_q1", "A", "nowych butów", "новой обуви (род.)", "нового взуття (род.)", "new shoes (gen.)", True, None), + ("a2_shopping_services_l07_q1", "B", "nowe buty", "новая обувь (им./вин.)", "нове взуття (наз./знах.)", "new shoes (nom./acc.)", False, "wrong_case"), + ("a2_shopping_services_l07_q1", "C", "nowym butom", "новой обуви (дат.)", "новому взуттю (дав.)", "new shoes (dat.)", False, "wrong_case"), + ("a2_shopping_services_l07_q1", "D", "nowymi butami", "новой обувью (тв.)", "новим взуттям (ор.)", "new shoes (instr.)", False, "wrong_case"), + + ("a2_shopping_services_l07_q3", "A", "Potrzebuję nowych butów.", "Мне нужна новая обувь.", "Мені потрібне нове взуття.", "I need new shoes.", True, None), + ("a2_shopping_services_l07_q3", "B", "Sprzedaję stare buty.", "Я продаю старую обувь. (не о нужде)", "Я продаю старе взуття. (не про потребу)", "I'm selling old shoes. (not about needing)", False, "wrong_context"), + ("a2_shopping_services_l07_q3", "C", "Przymierzam stare buty.", "Я примеряю старую обувь. (не о нужде)", "Я приміряю старе взуття. (не про потребу)", "I'm trying on old shoes. (not about needing)", False, "wrong_context"), + ("a2_shopping_services_l07_q3", "D", "Kupuję starą kurtkę.", "Я покупаю старую куртку. (неверный предмет)", "Я купую стару куртку. (невірний предмет)", "I'm buying an old jacket. (wrong item)", False, "wrong_word"), + + # L08 + ("a2_shopping_services_l08_q1", "A", "Kupuję koszulę.", "Я покупаю рубашку.", "Я купую сорочку.", "I'm buying the shirt.", False, "wrong_translation"), + ("a2_shopping_services_l08_q1", "B", "Przymierzam koszulę.", "Я примеряю рубашку.", "Я приміряю сорочку.", "I'm trying on the shirt.", False, "wrong_translation"), + ("a2_shopping_services_l08_q1", "C", "Sprzedaję koszulę.", "Я продаю рубашку.", "Я продаю сорочку.", "I'm selling the shirt.", False, "wrong_translation"), + ("a2_shopping_services_l08_q1", "D", "Zwracam koszulę.", "Я возвращаю рубашку.", "Я повертаю сорочку.", "I'm returning the shirt.", True, None), + + ("a2_shopping_services_l08_q3", "A", "Przymierzam buty.", "Я примеряю обувь. (не о возврате)", "Я приміряю взуття. (не про повернення)", "I'm trying on shoes. (not about a return)", False, "wrong_context"), + ("a2_shopping_services_l08_q3", "B", "Kupuję buty.", "Я покупаю обувь. (не о возврате)", "Я купую взуття. (не про повернення)", "I'm buying shoes. (not about a return)", False, "wrong_context"), + ("a2_shopping_services_l08_q3", "C", "Zwracam buty.", "Я возвращаю обувь.", "Я повертаю взуття.", "I'm returning the shoes.", True, None), + ("a2_shopping_services_l08_q3", "D", "Potrzebuję butów.", "Мне нужна обувь. (не о возврате)", "Мені потрібне взуття. (не про повернення)", "I need shoes. (not about a return)", False, "wrong_context"), + + # L09 + ("a2_shopping_services_l09_q1", "A", "Kupiłem ubrania.", "Я купил одежду. (прошедшее время)", "Я купив одяг. (минулий час)", "I bought clothes. (past tense)", False, "wrong_translation"), + ("a2_shopping_services_l09_q1", "B", "Kupuję ubrania.", "Я покупаю одежду. (настоящее время)", "Я купую одяг. (теперішній час)", "I'm buying clothes. (present tense)", False, "wrong_translation"), + ("a2_shopping_services_l09_q1", "C", "Chciałbym kupić ubrania.", "Я хотел бы купить одежду.", "Я хотів би купити одяг.", "I would like to buy clothes.", False, "wrong_translation"), + ("a2_shopping_services_l09_q1", "D", "Będę kupować ubrania.", "Я буду покупать одежду.", "Я буду купувати одяг.", "I will be buying clothes.", True, None), + + ("a2_shopping_services_l09_q3", "A", "Kupuję ubrania.", "Я покупаю одежду. (настоящее время)", "Я купую одяг. (теперішній час)", "I'm buying clothes. (present tense)", False, "wrong_sentence_type"), + ("a2_shopping_services_l09_q3", "B", "Kupiłem ubrania.", "Я купил одежду. (прошедшее время)", "Я купив одяг. (минулий час)", "I bought clothes. (past tense)", False, "wrong_sentence_type"), + ("a2_shopping_services_l09_q3", "C", "Będę kupować ubrania.", "Я буду покупать одежду.", "Я буду купувати одяг.", "I will be buying clothes.", True, None), + ("a2_shopping_services_l09_q3", "D", "Chciałbym kupić ubrania.", "Я хотел бы купить одежду. (условное наклонение)", "Я хотів би купити одяг. (умовний спосіб)", "I would like to buy clothes. (conditional mood)", False, "wrong_sentence_type"), + + # L10 + ("a2_shopping_services_l10_q1", "A", "Idę sklepu do potrzebuję butów.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_shopping_services_l10_q1", "B", "Idę do sklep, potrzebuję buty.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a2_shopping_services_l10_q1", "C", "Ja idę do sklepu, ja potrzebuję butów ja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_shopping_services_l10_q1", "D", "Idę do sklepu, bo potrzebuję nowych butów.", "Я иду в магазин, потому что мне нужна новая обувь.", "Я йду в магазин, бо мені потрібне нове взуття.", "I'm going to the store because I need new shoes.", True, None), + + ("a2_shopping_services_l10_q3", "A", "Ile to kosztuje?", "Сколько это стоит? (не начало описания)", "Скільки це коштує? (не початок опису)", "How much does it cost? (not the opening line)", False, "wrong_context"), + ("a2_shopping_services_l10_q3", "B", "Potrzebuję nowych butów.", "Мне нужна новая обувь. (не начало описания)", "Мені потрібне нове взуття. (не початок опису)", "I need new shoes. (not the opening line)", False, "wrong_context"), + ("a2_shopping_services_l10_q3", "C", "Idę do sklepu.", "Я иду в магазин.", "Я йду в магазин.", "I'm going to the store.", True, None), + ("a2_shopping_services_l10_q3", "D", "Będę kupować więcej ubrań.", "Я буду покупать больше одежды. (не начало описания)", "Я буду купувати більше одягу. (не початок опису)", "I will be buying more clothes. (not the opening line)", False, "wrong_context"), + ] + + for opt in options_t4_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t4_a2 = [ + ("a2_shopping_services_t01", None, "topic_test", "recognition", "sklepy_vocabulary", 1, + "Jak po polsku „пекарня”?", "Как по-польски «пекарня»?", "Як польською «пекарня»?", "How do you say “bakery” in Polish?", + "B", None, None, 1), + ("a2_shopping_services_t02", None, "topic_test", "recognition", "kupowac_biernik", 1, + "Co znaczy „Kupuję chleb”?", "Что означает «Kupuję chleb»?", "Що означає «Kupuję chleb»?", "What does “Kupuję chleb” mean?", + "D", None, None, 2), + ("a2_shopping_services_t03", None, "topic_test", "recognition", "ile_to_kosztuje", 1, + "Co znaczy „Ile to kosztuje?”?", "Что означает «Ile to kosztuje?»?", "Що означає «Ile to kosztuje?»?", "What does “Ile to kosztuje?” mean?", + "C", None, None, 3), + ("a2_shopping_services_t04", None, "topic_test", "recognition", "ubrania_vocabulary", 1, + "Jak po polsku „брюки”?", "Как по-польски «брюки»?", "Як польською «штани»?", "How do you say “pants” in Polish?", + "B", None, None, 4), + ("a2_shopping_services_t05", None, "topic_test", "recognition", "przymierzac_i_rozmiar", 2, + "Wybierz poprawną formę: Przymierzam ___. (kurtka)", "Выберите правильную форму: Przymierzam ___. (kurtka)", "Виберіть правильну форму: Przymierzam ___. (kurtka)", "Choose the correct form: Przymierzam ___. (kurtka)", + "A", None, None, 5), + ("a2_shopping_services_t06", None, "topic_test", "recognition", "przyszly_czas_zakupy", 3, + "Co znaczy „Będę kupować ubrania”?", "Что означает «Będę kupować ubrania»?", "Що означає «Będę kupować ubrania»?", "What does “Będę kupować ubrania” mean?", + "D", None, None, 6), + + ("a2_shopping_services_t07", None, "topic_test", "application", "sklepy_vocabulary", 1, + "Chcesz kupić świeży chleb. Dokąd idziesz?", "Ты хочешь купить свежий хлеб. Куда ты идёшь?", "Ти хочеш купити свіжий хліб. Куди ти йдеш?", "You want to buy fresh bread. Where do you go?", + "B", None, None, 7), + ("a2_shopping_services_t08", None, "topic_test", "application", "kupowac_biernik", 1, + "Kolega pyta, co kupujesz. Kupujesz owoce. Co powiesz?", "Друг спрашивает, что ты покупаешь. Ты покупаешь фрукты. Что ты скажешь?", "Друг питає, що ти купуєш. Ти купуєш фрукти. Що ти скажеш?", "A friend asks what you're buying. You're buying fruit. What do you say?", + "C", None, None, 8), + ("a2_shopping_services_t09", None, "topic_test", "application", "ile_to_kosztuje", 1, + "Chcesz zapytać sprzedawcę o cenę chleba. Co powiesz?", "Ты хочешь спросить продавца о цене хлеба. Что ты скажешь?", "Ти хочеш запитати продавця про ціну хліба. Що ти скажеш?", "You want to ask the seller about the price of bread. What do you say?", + "A", None, None, 9), + ("a2_shopping_services_t10", None, "topic_test", "application", "uslugi_vocabulary", 2, + "Twoje spodnie są za długie i potrzebujesz kogoś, kto je skróci. Do kogo idziesz?", "Твои брюки слишком длинные, и тебе нужен кто-то, кто их укоротит. К кому ты идёшь?", "Твої штани занадто довгі, і тобі потрібен хтось, хто їх укоротить. До кого ти йдеш?", "Your pants are too long and you need someone to shorten them. Who do you go to?", + "B", None, None, 10), + ("a2_shopping_services_t11", None, "topic_test", "application", "potrzebowac_dopelniacz", 2, + "Twoje stare buty są zniszczone i chcesz kupić nowe. Co powiesz?", "Твоя старая обувь изношена, и ты хочешь купить новую. Что ты скажешь?", "Твоє старе взуття зношене, і ти хочеш купити нове. Що ти скажеш?", "Your old shoes are worn out and you want to buy new ones. What do you say?", + "A", None, None, 11), + ("a2_shopping_services_t12", None, "topic_test", "application", "przyszly_czas_zakupy", 3, + "Planujesz iść jutro na zakupy i kupować nowe ubrania. Co powiesz?", "Ты планируешь завтра пойти по магазинам и купить новую одежду. Что ты скажешь?", "Ти плануєш завтра піти за покупками і купити новий одяг. Що ти скажеш?", "You're planning to go shopping tomorrow and buy new clothes. What do you say?", + "C", None, None, 12), + + ("a2_shopping_services_t13", None, "topic_test", "production", "sklepy_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (киоск)", "Вставьте пропущенное слово: To jest ___. (киоск)", "Вставте пропущене слово: To jest ___. (кіоск)", "Fill in the missing word: To jest ___. (kiosk)", + "kiosk", "first_letter", "k", 13), + ("a2_shopping_services_t14", None, "topic_test", "production", "ubrania_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (куртка)", "Вставьте пропущенное слово: To jest ___. (куртка)", "Вставте пропущене слово: To jest ___. (куртка)", "Fill in the missing word: To jest ___. (jacket)", + "kurtka", "first_letter", "k", 14), + ("a2_shopping_services_t15", None, "topic_test", "production", "przymierzac_i_rozmiar", 2, + "Wpisz brakujące słowo: Jaki masz ___? (размер)", "Вставьте пропущенное слово: Jaki masz ___? (размер)", "Вставте пропущене слово: Jaki masz ___? (розмір)", "Fill in the missing word: Jaki masz ___? (size)", + "rozmiar", "first_letter", "r", 15), + ("a2_shopping_services_t16", None, "topic_test", "production", "uslugi_vocabulary", 2, + "Wpisz brakujące słowo: Oddaję ubrania do ___. (прачечной)", "Вставьте пропущенное слово: Oddaję ubrania do ___. (прачечной)", "Вставте пропущене слово: Oddaję ubrania do ___. (пральні)", "Fill in the missing word: Oddaję ubrania do ___. (laundry)", + "pralni", "first_letter", "p", 16), + ("a2_shopping_services_t17", None, "topic_test", "production", "potrzebowac_dopelniacz", 2, + "Wpisz brakujące słowo: Potrzebujesz ___? (куртки)", "Вставьте пропущенное слово: Potrzebujesz ___? (куртки)", "Вставте пропущене слово: Potrzebujesz ___? (куртки)", "Fill in the missing word: Potrzebujesz ___? (a jacket)", + "kurtki", "first_letter", "k", 17), + ("a2_shopping_services_t18", None, "topic_test", "production", "opisuje_swoje_zakupy", 3, + "Przetłumacz: «Сколько это стоит?»", "Переведите: «Сколько это стоит?»", "Перекладіть: «Скільки це коштує?»", "Translate: “How much does it cost?”", + "Ile to kosztuje?", "first_letter", "I", 18), + + ("a2_shopping_services_t19", None, "topic_test", "mixed", "opisuje_swoje_zakupy", 3, + "Wybierz poprawne tłumaczenie: «Я иду в магазин, потому что мне нужна новая куртка, и я хочу спросить, сколько она стоит».", "Выберите правильный перевод: «Я иду в магазин, потому что мне нужна новая куртка, и я хочу спросить, сколько она стоит».", "Виберіть правильний переклад: «Я йду в магазин, бо мені потрібна нова куртка, і я хочу запитати, скільки вона коштує».", "Choose the correct translation: “I'm going to the store because I need a new jacket, and I want to ask how much it costs.”", + "C", None, None, 19), + ("a2_shopping_services_t20", None, "topic_test", "mixed", "przyszly_czas_zakupy", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Сколько стоят эти туфли? — Они стоят сто злотых, но я буду покупать их на следующей неделе.»", "Выберите правильный перевод диалога: «— Сколько стоят эти туфли? — Они стоят сто злотых, но я буду покупать их на следующей неделе.»", "Виберіть правильний переклад діалогу: «— Скільки коштують ці туфлі? — Вони коштують сто злотих, але я буду купувати їх наступного тижня.»", "Choose the correct translation of the dialogue: “— How much do these shoes cost? — They cost a hundred zlotys, but I will be buying them next week.”", + "C", None, None, 20), + ] + + for q in test_questions_t4_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_shopping_services', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t4_a2 = [ + ("a2_shopping_services_t01", "A", "sklep spożywczy", "продуктовый магазин", "продуктовий магазин", "grocery store", False, "wrong_word"), + ("a2_shopping_services_t01", "B", "piekarnia", "пекарня", "пекарня", "bakery", True, None), + ("a2_shopping_services_t01", "C", "apteka", "аптека", "аптека", "pharmacy", False, "wrong_word"), + ("a2_shopping_services_t01", "D", "kiosk", "киоск", "кіоск", "kiosk", False, "wrong_word"), + + ("a2_shopping_services_t02", "A", "Jem chleb.", "Я ем хлеб.", "Я їм хліб.", "I'm eating bread.", False, "wrong_translation"), + ("a2_shopping_services_t02", "B", "Piekę chleb.", "Я пеку хлеб.", "Я печу хліб.", "I'm baking bread.", False, "wrong_translation"), + ("a2_shopping_services_t02", "C", "Sprzedaję chleb.", "Я продаю хлеб.", "Я продаю хліб.", "I'm selling bread.", False, "wrong_translation"), + ("a2_shopping_services_t02", "D", "Kupuję chleb.", "Я покупаю хлеб.", "Я купую хліб.", "I'm buying bread.", True, None), + + ("a2_shopping_services_t03", "A", "Co to jest?", "Что это?", "Що це?", "What is this?", False, "wrong_translation"), + ("a2_shopping_services_t03", "B", "Gdzie to jest?", "Где это?", "Де це?", "Where is this?", False, "wrong_translation"), + ("a2_shopping_services_t03", "C", "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does it cost?", True, None), + ("a2_shopping_services_t03", "D", "Kiedy to będzie?", "Когда это будет?", "Коли це буде?", "When will it be?", False, "wrong_translation"), + + ("a2_shopping_services_t04", "A", "koszula", "рубашка", "сорочка", "shirt", False, "wrong_word"), + ("a2_shopping_services_t04", "B", "spodnie", "брюки", "штани", "pants", True, None), + ("a2_shopping_services_t04", "C", "buty", "обувь", "взуття", "shoes", False, "wrong_word"), + ("a2_shopping_services_t04", "D", "kurtka", "куртка", "куртка", "jacket", False, "wrong_word"), + + ("a2_shopping_services_t05", "A", "kurtkę", "куртку (вин.)", "куртку (знах.)", "jacket (acc.)", True, None), + ("a2_shopping_services_t05", "B", "kurtka", "куртка (им.)", "куртка (наз.)", "jacket (nom.)", False, "wrong_case"), + ("a2_shopping_services_t05", "C", "kurtki", "куртки (род.)", "куртки (род.)", "jacket (gen.)", False, "wrong_case"), + ("a2_shopping_services_t05", "D", "kurtką", "курткой (тв.)", "курткою (ор.)", "jacket (instr.)", False, "wrong_case"), + + ("a2_shopping_services_t06", "A", "Kupiłem ubrania.", "Я купил одежду. (прошедшее время)", "Я купив одяг. (минулий час)", "I bought clothes. (past tense)", False, "wrong_translation"), + ("a2_shopping_services_t06", "B", "Kupuję ubrania.", "Я покупаю одежду. (настоящее время)", "Я купую одяг. (теперішній час)", "I'm buying clothes. (present tense)", False, "wrong_translation"), + ("a2_shopping_services_t06", "C", "Chciałbym kupić ubrania.", "Я хотел бы купить одежду.", "Я хотів би купити одяг.", "I would like to buy clothes.", False, "wrong_translation"), + ("a2_shopping_services_t06", "D", "Będę kupować ubrania.", "Я буду покупать одежду.", "Я буду купувати одяг.", "I will be buying clothes.", True, None), + + ("a2_shopping_services_t07", "A", "sklep spożywczy", "продуктовый магазин", "продуктовий магазин", "grocery store", False, "wrong_context"), + ("a2_shopping_services_t07", "B", "piekarnia", "пекарня", "пекарня", "bakery", True, None), + ("a2_shopping_services_t07", "C", "apteka", "аптека", "аптека", "pharmacy", False, "wrong_context"), + ("a2_shopping_services_t07", "D", "kiosk", "киоск", "кіоск", "kiosk", False, "wrong_context"), + + ("a2_shopping_services_t08", "A", "Kupuję chleb.", "Я покупаю хлеб. (не соответствует ситуации)", "Я купую хліб. (не відповідає ситуації)", "I'm buying bread. (doesn't match the situation)", False, "wrong_context"), + ("a2_shopping_services_t08", "B", "Kupuję mleko.", "Я покупаю молоко. (не соответствует ситуации)", "Я купую молоко. (не відповідає ситуації)", "I'm buying milk. (doesn't match the situation)", False, "wrong_context"), + ("a2_shopping_services_t08", "C", "Kupuję owoce.", "Я покупаю фрукты.", "Я купую фрукти.", "I'm buying fruit.", True, None), + ("a2_shopping_services_t08", "D", "Sprzedaję owoce.", "Я продаю фрукты. (неверный глагол)", "Я продаю фрукти. (невірне дієслово)", "I'm selling fruit. (wrong verb)", False, "wrong_context"), + + ("a2_shopping_services_t09", "A", "Ile to kosztuje?", "Сколько это стоит?", "Скільки це коштує?", "How much does it cost?", True, None), + ("a2_shopping_services_t09", "B", "Co to jest?", "Что это? (не о цене)", "Що це? (не про ціну)", "What is this? (not about price)", False, "wrong_context"), + ("a2_shopping_services_t09", "C", "Gdzie to jest?", "Где это? (не о цене)", "Де це? (не про ціну)", "Where is this? (not about price)", False, "wrong_context"), + ("a2_shopping_services_t09", "D", "Kupuję chleb.", "Я покупаю хлеб. (не вопрос)", "Я купую хліб. (не питання)", "I'm buying bread. (not a question)", False, "wrong_context"), + + ("a2_shopping_services_t10", "A", "fryzjera", "парикмахера", "перукаря", "hairdresser", False, "wrong_context"), + ("a2_shopping_services_t10", "B", "krawca", "портного", "кравця", "tailor", True, None), + ("a2_shopping_services_t10", "C", "pralni", "прачечной", "пральні", "laundry", False, "wrong_context"), + ("a2_shopping_services_t10", "D", "apteki", "аптеки", "аптеки", "pharmacy", False, "wrong_context"), + + ("a2_shopping_services_t11", "A", "Potrzebuję nowych butów.", "Мне нужна новая обувь.", "Мені потрібне нове взуття.", "I need new shoes.", True, None), + ("a2_shopping_services_t11", "B", "Sprzedaję stare buty.", "Я продаю старую обувь. (не о нужде)", "Я продаю старе взуття. (не про потребу)", "I'm selling old shoes. (not about needing)", False, "wrong_context"), + ("a2_shopping_services_t11", "C", "Przymierzam stare buty.", "Я примеряю старую обувь. (не о нужде)", "Я приміряю старе взуття. (не про потребу)", "I'm trying on old shoes. (not about needing)", False, "wrong_context"), + ("a2_shopping_services_t11", "D", "Kupuję starą kurtkę.", "Я покупаю старую куртку. (неверный предмет)", "Я купую стару куртку. (невірний предмет)", "I'm buying an old jacket. (wrong item)", False, "wrong_word"), + + ("a2_shopping_services_t12", "A", "Kupuję ubrania.", "Я покупаю одежду. (настоящее время)", "Я купую одяг. (теперішній час)", "I'm buying clothes. (present tense)", False, "wrong_sentence_type"), + ("a2_shopping_services_t12", "B", "Kupiłem ubrania.", "Я купил одежду. (прошедшее время)", "Я купив одяг. (минулий час)", "I bought clothes. (past tense)", False, "wrong_sentence_type"), + ("a2_shopping_services_t12", "C", "Będę kupować ubrania.", "Я буду покупать одежду.", "Я буду купувати одяг.", "I will be buying clothes.", True, None), + ("a2_shopping_services_t12", "D", "Chciałbym kupić ubrania.", "Я хотел бы купить одежду. (условное наклонение)", "Я хотів би купити одяг. (умовний спосіб)", "I would like to buy clothes. (conditional mood)", False, "wrong_sentence_type"), + + ("a2_shopping_services_t19", "A", "Szedłem do sklepu, bo potrzebowałem nowej kurtki, i chciałem zapytać, ile ona kosztowała.", "Я шёл в магазин, потому что мне нужна была новая куртка, и я хотел спросить, сколько она стоила. (прошедшее время)", "Я йшов у магазин, бо мені потрібна була нова куртка, і я хотів запитати, скільки вона коштувала. (минулий час)", "I was going to the store because I needed a new jacket, and I wanted to ask how much it cost. (past tense)", False, "wrong_sentence_type"), + ("a2_shopping_services_t19", "B", "Będę iść do sklepu, bo będę potrzebować nowej kurtki, i będę chciał zapytać, ile ona będzie kosztować.", "Я буду идти в магазин, потому что мне будет нужна новая куртка, и я захочу спросить, сколько она будет стоить. (будущее время)", "Я буду йти в магазин, бо мені буде потрібна нова куртка, і я захочу запитати, скільки вона буде коштувати. (майбутній час)", "I will be going to the store because I will need a new jacket, and I will want to ask how much it will cost. (future tense)", False, "wrong_sentence_type"), + ("a2_shopping_services_t19", "C", "Idę do sklepu, bo potrzebuję nowej kurtki, i chcę zapytać, ile ona kosztuje.", "Я иду в магазин, потому что мне нужна новая куртка, и я хочу спросить, сколько она стоит.", "Я йду в магазин, бо мені потрібна нова куртка, і я хочу запитати, скільки вона коштує.", "I'm going to the store because I need a new jacket, and I want to ask how much it costs.", True, None), + ("a2_shopping_services_t19", "D", "Idę do apteki, bo potrzebuję nowych butów, i chcę zapytać, ile one kosztują.", "Я иду в аптеку, потому что мне нужна новая обувь, и я хочу спросить, сколько она стоит. (неверное место и предмет)", "Я йду в аптеку, бо мені потрібне нове взуття, і я хочу запитати, скільки воно коштує. (невірне місце і предмет)", "I'm going to the pharmacy because I need new shoes, and I want to ask how much they cost. (wrong place and item)", False, "wrong_word"), + + ("a2_shopping_services_t20", "A", "— Ile kosztuje ten but? — Kosztuje sto złotych, ale będę go kupować w przyszłym tygodniu.", "— Сколько стоит этот туфель? — Он стоит сто злотых, но я буду покупать его на следующей неделе. (неправильное число)", "— Скільки коштує цей черевик? — Він коштує сто злотих, але я буду купувати його наступного тижня. (неправильне число)", "— How much does this shoe cost? — It costs a hundred zlotys, but I will be buying it next week. (wrong number)", False, "wrong_number"), + ("a2_shopping_services_t20", "B", "— Ile kosztowały te buty? — Kosztowały sto złotych, ale kupiłem je w zeszłym tygodniu.", "— Сколько стоили эти туфли? — Они стоили сто злотых, но я купил их на прошлой неделе. (прошедшее время)", "— Скільки коштували ці туфлі? — Вони коштували сто злотих, але я купив їх минулого тижня. (минулий час)", "— How much did these shoes cost? — They cost a hundred zlotys, but I bought them last week. (past tense)", False, "wrong_sentence_type"), + ("a2_shopping_services_t20", "C", "— Ile kosztują te buty? — Kosztują sto złotych, ale będę je kupować w przyszłym tygodniu.", "— Сколько стоят эти туфли? — Они стоят сто злотых, но я буду покупать их на следующей неделе.", "— Скільки коштують ці туфлі? — Вони коштують сто злотих, але я буду купувати їх наступного тижня.", "— How much do these shoes cost? — They cost a hundred zlotys, but I will be buying them next week.", True, None), + ("a2_shopping_services_t20", "D", "— Ile kosztuje ta kurtka? — Kosztuje sto złotych, ale będę ją kupować w przyszłym tygodniu.", "— Сколько стоит эта куртка? — Она стоит сто злотых, но я буду покупать её на следующей неделе. (неверный предмет)", "— Скільки коштує ця куртка? — Вона коштує сто злотих, але я буду купувати її наступного тижня. (невірний предмет)", "— How much does this jacket cost? — It costs a hundred zlotys, but I will be buying it next week. (wrong item)", False, "wrong_word"), + ] + + for opt in test_options_t4_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 5 (A2): ЕДА И РЕСТОРАНЫ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_food_restaurant', 'A2', 5, + 'Jedzenie i restauracje', + 'Еда и рестораны', + 'Їжа і ресторани', + 'Food and Restaurants') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t5_a2 = [ + ("a2_food_restaurant_l01", 1, "jedzenie_vocabulary", "Podstawowe słowa: jedzenie", "Основные слова: еда", "Основні слова: їжа", "Basic words: food", + "Podstawowe nazwy jedzenia: chleb, ser, mięso, warzywa.", + "Основные названия еды: chleb (хлеб), ser (сыр), mięso (мясо), warzywa (овощи).", + "Основні назви їжі: chleb (хліб), ser (сир), mięso (м'ясо), warzywa (овочі).", + "Basic food names: chleb (bread), ser (cheese), mięso (meat), warzywa (vegetables)."), + + ("a2_food_restaurant_l02", 2, "chciec_bezokolicznik", "Chcieć + bezokolicznik", "Chcieć + инфинитив", "Chcieć + інфінітив", "Chcieć + infinitive", + "Czasownik „chcieć” + bezokolicznik: chcę zamówić, chcesz zjeść, chce spróbować.", + "Глагол „chcieć” (хотеть) + инфинитив: chcę zamówić (я хочу заказать), chcesz zjeść (ты хочешь съесть), chce spróbować (он/она хочет попробовать).", + "Дієслово „chcieć” (хотіти) + інфінітив: chcę zamówić (я хочу замовити), chcesz zjeść (ти хочеш з'їсти), chce spróbować (він/вона хоче спробувати).", + "The verb „chcieć” (to want) + infinitive: chcę zamówić (I want to order), chcesz zjeść (you want to eat), chce spróbować (he/she wants to try)."), + + ("a2_food_restaurant_l03", 3, "lubic_biernik", "Lubić + biernik", "Lubić + винительный падеж", "Lubić + знахідний відмінок", "Lubić + accusative", + "Czasownik „lubić” + biernik: lubię pizzę, lubisz zupę, lubi owoce.", + "Глагол „lubić” (любить) + винительный падеж: lubię pizzę (я люблю пиццу), lubisz zupę (ты любишь суп), lubi owoce (он/она любит фрукты).", + "Дієслово „lubić” (любити) + знахідний відмінок: lubię pizzę (я люблю піцу), lubisz zupę (ти любиш суп), lubi owoce (він/вона любить фрукти).", + "The verb „lubić” (to like) + accusative: lubię pizzę (I like pizza), lubisz zupę (you like soup), lubi owoce (he/she likes fruit)."), + + ("a2_food_restaurant_l04", 4, "restauracja_vocabulary", "Podstawowe słowa: restauracja", "Основные слова: ресторан", "Основні слова: ресторан", "Basic words: restaurant", + "Podstawowe słowa: restauracja, kelner, menu, rachunek.", + "Основные слова: restauracja (ресторан), kelner (официант), menu (меню), rachunek (счёт).", + "Основні слова: restauracja (ресторан), kelner (офіціант), menu (меню), rachunek (рахунок).", + "Basic words: restauracja (restaurant), kelner (waiter), menu (menu), rachunek (bill)."), + + ("a2_food_restaurant_l05", 5, "zamawiac_biernik", "Zamawiać + biernik", "Zamawiać + винительный падеж", "Zamawiać + знахідний відмінок", "Zamawiać + accusative", + "Czasownik „zamawiać” + biernik: zamawiam zupę, zamawiasz kawę, zamawia deser.", + "Глагол „zamawiać” (заказывать) + винительный падеж: zamawiam zupę (я заказываю суп), zamawiasz kawę (ты заказываешь кофе), zamawia deser (он/она заказывает десерт).", + "Дієслово „zamawiać” (замовляти) + знахідний відмінок: zamawiam zupę (я замовляю суп), zamawiasz kawę (ти замовляєш каву), zamawia deser (він/вона замовляє десерт).", + "The verb „zamawiać” (to order) + accusative: zamawiam zupę (I'm ordering soup), zamawiasz kawę (you're ordering coffee), zamawia deser (he/she is ordering dessert)."), + + ("a2_food_restaurant_l06", 6, "poprosic_o", "Poprosić o + biernik", "Poprosić o + винительный падеж", "Poprosić o + знахідний відмінок", "Poprosić o + accusative", + "Czasownik „poprosić” + „o” + biernik: poproszę o rachunek, poprosisz o wodę.", + "Глагол „poprosić” (попросить) + „o” + винительный падеж: poproszę o rachunek (я попрошу счёт), poprosisz o wodę (ты попросишь воду).", + "Дієслово „poprosić” (попросити) + „o” + знахідний відмінок: poproszę o rachunek (я попрошу рахунок), poprosisz o wodę (ти попросиш воду).", + "The verb „poprosić” (to ask for) + „o” + accusative: poproszę o rachunek (I'll ask for the bill), poprosisz o wodę (you'll ask for water)."), + + ("a2_food_restaurant_l07", 7, "smaki_vocabulary", "Podstawowe słowa: smaki", "Основные слова: вкусы", "Основні слова: смаки", "Basic words: tastes", + "Podstawowe przymiotniki opisujące smak: słodki, słony, ostry, kwaśny.", + "Основные прилагательные, описывающие вкус: słodki (сладкий), słony (солёный), ostry (острый), kwaśny (кислый).", + "Основні прикметники, що описують смак: słodki (солодкий), słony (солоний), ostry (гострий), kwaśny (кислий).", + "Basic adjectives describing taste: słodki (sweet), słony (salty), ostry (spicy), kwaśny (sour)."), + + ("a2_food_restaurant_l08", 8, "czasownik_smakowac", "Smakować + celownik", "Smakować + дательный падеж", "Smakować + давальний відмінок", "Smakować + dative", + "Czasownik „smakować” + celownik: smakuje mi, smakuje ci, smakuje nam.", + "Глагол „smakować” (быть вкусным для кого-то) + дательный падеж: smakuje mi (мне вкусно), smakuje ci (тебе вкусно), smakuje nam (нам вкусно).", + "Дієслово „smakować” (бути смачним для когось) + давальний відмінок: smakuje mi (мені смачно), smakuje ci (тобі смачно), smakuje nam (нам смачно).", + "The verb „smakować” (to taste good to someone) + dative: smakuje mi (I like it/it tastes good to me), smakuje ci (it tastes good to you), smakuje nam (it tastes good to us)."), + + ("a2_food_restaurant_l09", 9, "przeszly_czas_jedzenie", "Zjadłem/zjadłam + biernik (przeszłość)", "Zjadłem/zjadłam + винительный падеж (прошедшее)", "Zjadłem/zjadłam + знахідний відмінок (минулий час)", "Zjadłem/zjadłam + accusative (past)", + "Czas przeszły jedzenia tworzymy „zjadłem” (mężczyzna) lub „zjadłam” (kobieta) + biernik: zjadłem obiad, zjadłam całą pizzę.", + "Прошедшее время еды образуем „zjadłem” (мужчина) или „zjadłam” (женщина) + винительный падеж: zjadłem obiad (я съел обед), zjadłam całą pizzę (я съела всю пиццу).", + "Минулий час їжі утворюємо „zjadłem” (чоловік) або „zjadłam” (жінка) + знахідний відмінок: zjadłem obiad (я з'їв обід), zjadłam całą pizzę (я з'їла всю піцу).", + "We form the past tense of eating with „zjadłem” (male speaker) or „zjadłam” (female speaker) + accusative: zjadłem obiad (I ate lunch), zjadłam całą pizzę (I ate the whole pizza)."), + + ("a2_food_restaurant_l10", 10, "opisuje_swoj_posilek", "Opisuję swój posiłek", "Описываю свой приём пищи", "Описую свій прийом їжі", "Describing my meal", + "Żeby opisać posiłek, łączymy zdania: Zamawiam zupę. Smakuje mi ta zupa. Zjadłem cały obiad. Poproszę o rachunek.", + "Чтобы описать приём пищи, соединяем предложения: Zamawiam zupę. Smakuje mi ta zupa. Zjadłem cały obiad. Poproszę o rachunek. (Я заказываю суп. Мне нравится этот суп. Я съел весь обед. Я попрошу счёт.)", + "Щоб описати прийом їжі, поєднуємо речення: Zamawiam zupę. Smakuje mi ta zupa. Zjadłem cały obiad. Poproszę o rachunek. (Я замовляю суп. Мені смакує цей суп. Я з'їв весь обід. Я попрошу рахунок.)", + "To describe a meal, we combine sentences: Zamawiam zupę. Smakuje mi ta zupa. Zjadłem cały obiad. Poproszę o rachunek. (I'm ordering soup. I like this soup. I ate the whole lunch. I'll ask for the bill.)"), + ] + + for lesson in lessons_t5_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_food_restaurant', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t5_a2 = [ + ("a2_food_restaurant_l01", 1, "To jest chleb.", "Это хлеб.", "Це хліб.", "This is bread."), + ("a2_food_restaurant_l01", 2, "To jest ser.", "Это сыр.", "Це сир.", "This is cheese."), + ("a2_food_restaurant_l01", 3, "To są warzywa.", "Это овощи.", "Це овочі.", "These are vegetables."), + + ("a2_food_restaurant_l02", 1, "Chcę zamówić zupę.", "Я хочу заказать суп.", "Я хочу замовити суп.", "I want to order soup."), + ("a2_food_restaurant_l02", 2, "Chcesz zjeść deser?", "Ты хочешь съесть десерт?", "Ти хочеш з'їсти десерт?", "Do you want to eat dessert?"), + ("a2_food_restaurant_l02", 3, "Ona chce spróbować tej potrawy.", "Она хочет попробовать это блюдо.", "Вона хоче спробувати цю страву.", "She wants to try this dish."), + + ("a2_food_restaurant_l03", 1, "Lubię pizzę.", "Я люблю пиццу.", "Я люблю піцу.", "I like pizza."), + ("a2_food_restaurant_l03", 2, "Lubisz zupę?", "Ты любишь суп?", "Ти любиш суп?", "Do you like soup?"), + ("a2_food_restaurant_l03", 3, "On lubi owoce.", "Он любит фрукты.", "Він любить фрукти.", "He likes fruit."), + + ("a2_food_restaurant_l04", 1, "Idziemy do restauracji.", "Мы идём в ресторан.", "Ми йдемо в ресторан.", "We're going to a restaurant."), + ("a2_food_restaurant_l04", 2, "Kelner przynosi menu.", "Официант приносит меню.", "Офіціант приносить меню.", "The waiter brings the menu."), + ("a2_food_restaurant_l04", 3, "Proszę o rachunek.", "Счёт, пожалуйста.", "Рахунок, будь ласка.", "The bill, please."), + + ("a2_food_restaurant_l05", 1, "Zamawiam zupę.", "Я заказываю суп.", "Я замовляю суп.", "I'm ordering soup."), + ("a2_food_restaurant_l05", 2, "Zamawiasz kawę?", "Ты заказываешь кофе?", "Ти замовляєш каву?", "Are you ordering coffee?"), + ("a2_food_restaurant_l05", 3, "Ona zamawia deser.", "Она заказывает десерт.", "Вона замовляє десерт.", "She's ordering dessert."), + + ("a2_food_restaurant_l06", 1, "Poproszę o rachunek.", "Я попрошу счёт.", "Я попрошу рахунок.", "I'll ask for the bill."), + ("a2_food_restaurant_l06", 2, "Poprosisz o wodę?", "Ты попросишь воду?", "Ти попросиш воду?", "Will you ask for water?"), + ("a2_food_restaurant_l06", 3, "On poprosił o menu.", "Он попросил меню.", "Він попросив меню.", "He asked for the menu."), + + ("a2_food_restaurant_l07", 1, "Ten deser jest słodki.", "Этот десерт сладкий.", "Цей десерт солодкий.", "This dessert is sweet."), + ("a2_food_restaurant_l07", 2, "Ta zupa jest słona.", "Этот суп солёный.", "Цей суп солоний.", "This soup is salty."), + ("a2_food_restaurant_l07", 3, "To danie jest ostre.", "Это блюдо острое.", "Ця страва гостра.", "This dish is spicy."), + + ("a2_food_restaurant_l08", 1, "Smakuje mi ta zupa.", "Мне нравится этот суп.", "Мені смакує цей суп.", "I like this soup."), + ("a2_food_restaurant_l08", 2, "Smakuje ci to danie?", "Тебе нравится это блюдо?", "Тобі смакує ця страва?", "Do you like this dish?"), + ("a2_food_restaurant_l08", 3, "Nie smakuje mi kawa.", "Мне не нравится кофе.", "Мені не смакує кава.", "I don't like coffee."), + + ("a2_food_restaurant_l09", 1, "Zjadłem obiad.", "Я съел обед.", "Я з'їв обід.", "I ate lunch."), + ("a2_food_restaurant_l09", 2, "Zjadłaś śniadanie?", "Ты съела завтрак?", "Ти з'їла сніданок?", "Did you eat breakfast?"), + ("a2_food_restaurant_l09", 3, "Zjadł całą pizzę.", "Он съел всю пиццу.", "Він з'їв всю піцу.", "He ate the whole pizza."), + + ("a2_food_restaurant_l10", 1, "Zamawiam zupę.", "Я заказываю суп.", "Я замовляю суп.", "I'm ordering soup."), + ("a2_food_restaurant_l10", 2, "Smakuje mi ta zupa.", "Мне нравится этот суп.", "Мені смакує цей суп.", "I like this soup."), + ("a2_food_restaurant_l10", 3, "Poproszę o rachunek.", "Я попрошу счёт.", "Я попрошу рахунок.", "I'll ask for the bill."), + ] + + for ex in examples_t5_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t5_a2 = [ + # L01 — jedzenie_vocabulary (difficulty 1) + ("a2_food_restaurant_l01_q1", "a2_food_restaurant_l01", "lesson_practice", "recognition", "jedzenie_vocabulary", 1, + "Jak po polsku „мясо”?", "Как по-польски «мясо»?", "Як польською «м'ясо»?", "How do you say “meat” in Polish?", + "B", None, None), + ("a2_food_restaurant_l01_q2", "a2_food_restaurant_l01", "lesson_practice", "production", "jedzenie_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (сыр)", "Вставьте пропущенное слово: To jest ___. (сыр)", "Вставте пропущене слово: To jest ___. (сир)", "Fill in the missing word: To jest ___. (cheese)", + "ser", "first_letter", "s"), + ("a2_food_restaurant_l01_q3", "a2_food_restaurant_l01", "lesson_practice", "application", "jedzenie_vocabulary", 1, + "Chcesz zjeść coś zdrowego i lekkiego przed obiadem. Co wybierzesz?", "Ты хочешь съесть что-то полезное и лёгкое перед обедом. Что ты выберешь?", "Ти хочеш з'їсти щось корисне і легке перед обідом. Що ти обереш?", "You want to eat something healthy and light before lunch. What will you choose?", + "D", None, None), + + # L02 — chciec_bezokolicznik (difficulty 1) + ("a2_food_restaurant_l02_q1", "a2_food_restaurant_l02", "lesson_practice", "recognition", "chciec_bezokolicznik", 1, + "Wybierz poprawną formę: ___ zamówić zupę. (chcieć, ja)", "Выберите правильную форму: ___ zamówić zupę. (chcieć, ja)", "Виберіть правильну форму: ___ zamówić zupę. (chcieć, ja)", "Choose the correct form: ___ zamówić zupę. (chcieć, I)", + "A", None, None), + ("a2_food_restaurant_l02_q2", "a2_food_restaurant_l02", "lesson_practice", "production", "chciec_bezokolicznik", 1, + "Wpisz brakujące słowo: ___ zjeść deser? (ты хочешь)", "Вставьте пропущенное слово: ___ zjeść deser? (ты хочешь)", "Вставте пропущене слово: ___ zjeść deser? (ти хочеш)", "Fill in the missing word: ___ zjeść deser? (do you want)", + "Chcesz", "first_letter", "C"), + ("a2_food_restaurant_l02_q3", "a2_food_restaurant_l02", "lesson_practice", "application", "chciec_bezokolicznik", 1, + "Widzisz w menu ciekawe danie i chcesz je spróbować. Co powiesz?", "Ты видишь в меню интересное блюдо и хочешь его попробовать. Что ты скажешь?", "Ти бачиш у меню цікаву страву і хочеш її спробувати. Що ти скажеш?", "You see an interesting dish on the menu and want to try it. What do you say?", + "A", None, None), + + # L03 — lubic_biernik (difficulty 1) + ("a2_food_restaurant_l03_q1", "a2_food_restaurant_l03", "lesson_practice", "recognition", "lubic_biernik", 1, + "Co znaczy „Lubię pizzę”?", "Что означает «Lubię pizzę»?", "Що означає «Lubię pizzę»?", "What does “Lubię pizzę” mean?", + "D", None, None), + ("a2_food_restaurant_l03_q2", "a2_food_restaurant_l03", "lesson_practice", "production", "lubic_biernik", 1, + "Wpisz brakujące słowo: Lubisz ___? (суп)", "Вставьте пропущенное слово: Lubisz ___? (суп)", "Вставте пропущене слово: Lubisz ___? (суп)", "Fill in the missing word: Lubisz ___? (soup)", + "zupę", "first_letter", "z"), + ("a2_food_restaurant_l03_q3", "a2_food_restaurant_l03", "lesson_practice", "application", "lubic_biernik", 1, + "Kolega pyta, co lubisz jeść. Lubisz owoce. Co powiesz?", "Друг спрашивает, что ты любишь есть. Ты любишь фрукты. Что ты скажешь?", "Друг питає, що ти любиш їсти. Ти любиш фрукти. Що ти скажеш?", "A friend asks what you like to eat. You like fruit. What do you say?", + "C", None, None), + + # L04 — restauracja_vocabulary (difficulty 1) + ("a2_food_restaurant_l04_q1", "a2_food_restaurant_l04", "lesson_practice", "recognition", "restauracja_vocabulary", 1, + "Jak po polsku „официант”?", "Как по-польски «официант»?", "Як польською «офіціант»?", "How do you say “waiter” in Polish?", + "B", None, None), + ("a2_food_restaurant_l04_q2", "a2_food_restaurant_l04", "lesson_practice", "production", "restauracja_vocabulary", 1, + "Wpisz brakujące słowo: Proszę o ___. (счёт)", "Вставьте пропущенное слово: Proszę o ___. (счёт)", "Вставте пропущене слово: Proszę o ___. (рахунок)", "Fill in the missing word: Proszę o ___. (the bill)", + "rachunek", "first_letter", "r"), + ("a2_food_restaurant_l04_q3", "a2_food_restaurant_l04", "lesson_practice", "application", "restauracja_vocabulary", 1, + "Skończyłeś jeść i chcesz zapłacić. Co poprosisz?", "Ты закончил есть и хочешь заплатить. Что ты попросишь?", "Ти закінчив їсти і хочеш заплатити. Що ти попросиш?", "You've finished eating and want to pay. What will you ask for?", + "C", None, None), + + # L05 — zamawiac_biernik (difficulty 2) + ("a2_food_restaurant_l05_q1", "a2_food_restaurant_l05", "lesson_practice", "recognition", "zamawiac_biernik", 2, + "Wybierz poprawną formę: Zamawiam ___. (zupa)", "Выберите правильную форму: Zamawiam ___. (zupa)", "Виберіть правильну форму: Zamawiam ___. (zupa)", "Choose the correct form: Zamawiam ___. (zupa)", + "A", None, None), + ("a2_food_restaurant_l05_q2", "a2_food_restaurant_l05", "lesson_practice", "production", "zamawiac_biernik", 2, + "Wpisz brakujące słowo: Zamawiasz ___? (кофе)", "Вставьте пропущенное слово: Zamawiasz ___? (кофе)", "Вставте пропущене слово: Zamawiasz ___? (каву)", "Fill in the missing word: Zamawiasz ___? (coffee)", + "kawę", "first_letter", "k"), + ("a2_food_restaurant_l05_q3", "a2_food_restaurant_l05", "lesson_practice", "application", "zamawiac_biernik", 2, + "Kelner pyta, co zamawiasz. Chcesz deser. Co powiesz?", "Официант спрашивает, что ты заказываешь. Ты хочешь десерт. Что ты скажешь?", "Офіціант питає, що ти замовляєш. Ти хочеш десерт. Що ти скажеш?", "The waiter asks what you're ordering. You want dessert. What do you say?", + "C", None, None), + + # L06 — poprosic_o (difficulty 2) + ("a2_food_restaurant_l06_q1", "a2_food_restaurant_l06", "lesson_practice", "recognition", "poprosic_o", 2, + "Wybierz poprawną formę: Poproszę ___ rachunek.", "Выберите правильную форму: Poproszę ___ rachunek.", "Виберіть правильну форму: Poproszę ___ rachunek.", "Choose the correct form: Poproszę ___ rachunek.", + "A", None, None), + ("a2_food_restaurant_l06_q2", "a2_food_restaurant_l06", "lesson_practice", "production", "poprosic_o", 2, + "Wpisz brakujące słowo: Poprosisz o ___? (воду)", "Вставьте пропущенное слово: Poprosisz o ___? (воду)", "Вставте пропущене слово: Poprosisz o ___? (воду)", "Fill in the missing word: Poprosisz o ___? (water)", + "wodę", "first_letter", "w"), + ("a2_food_restaurant_l06_q3", "a2_food_restaurant_l06", "lesson_practice", "application", "poprosic_o", 2, + "Skończyłeś jeść i chcesz zapłacić. Co powiesz kelnerowi?", "Ты закончил есть и хочешь заплатить. Что ты скажешь официанту?", "Ти закінчив їсти і хочеш заплатити. Що ти скажеш офіціанту?", "You've finished eating and want to pay. What do you say to the waiter?", + "B", None, None), + + # L07 — smaki_vocabulary (difficulty 2) + ("a2_food_restaurant_l07_q1", "a2_food_restaurant_l07", "lesson_practice", "recognition", "smaki_vocabulary", 2, + "Jak po polsku „кислый”?", "Как по-польски «кислый»?", "Як польською «кислий»?", "How do you say “sour” in Polish?", + "D", None, None), + ("a2_food_restaurant_l07_q2", "a2_food_restaurant_l07", "lesson_practice", "production", "smaki_vocabulary", 2, + "Wpisz brakujące słowo: Ta zupa jest ___. (солёный)", "Вставьте пропущенное слово: Ta zupa jest ___. (солёный)", "Вставте пропущене слово: Ta zupa jest ___. (солоний)", "Fill in the missing word: Ta zupa jest ___. (salty)", + "słona", "first_letter", "s"), + ("a2_food_restaurant_l07_q3", "a2_food_restaurant_l07", "lesson_practice", "application", "smaki_vocabulary", 2, + "Zjadłeś danie z dużą ilością chili i teraz piecze cię w ustach. Jakie to danie?", "Ты съел блюдо с большим количеством чили, и теперь у тебя горит во рту. Какое это блюдо?", "Ти з'їв страву з великою кількістю чилі, і тепер у тебе пече в роті. Яка це страва?", "You ate a dish with a lot of chili and now your mouth is burning. What kind of dish is it?", + "C", None, None), + + # L08 — czasownik_smakowac (difficulty 2) + ("a2_food_restaurant_l08_q1", "a2_food_restaurant_l08", "lesson_practice", "recognition", "czasownik_smakowac", 2, + "Co znaczy „Smakuje mi ta zupa”?", "Что означает «Smakuje mi ta zupa»?", "Що означає «Smakuje mi ta zupa»?", "What does “Smakuje mi ta zupa” mean?", + "D", None, None), + ("a2_food_restaurant_l08_q2", "a2_food_restaurant_l08", "lesson_practice", "production", "czasownik_smakowac", 2, + "Wpisz brakujące słowo: Nie ___ mi kawa. (нравится)", "Вставьте пропущенное слово: Nie ___ mi kawa. (нравится)", "Вставте пропущене слово: Nie ___ mi kawa. (смакує)", "Fill in the missing word: Nie ___ mi kawa. (tastes good)", + "smakuje", "first_letter", "s"), + ("a2_food_restaurant_l08_q3", "a2_food_restaurant_l08", "lesson_practice", "application", "czasownik_smakowac", 2, + "Zjadłeś danie i było bardzo dobre. Co powiesz kucharzowi?", "Ты съел блюдо, и оно было очень вкусным. Что ты скажешь повару?", "Ти з'їв страву, і вона була дуже смачна. Що ти скажеш кухарю?", "You ate a dish and it was very good. What do you tell the cook?", + "B", None, None), + + # L09 — przeszly_czas_jedzenie (difficulty 3) + ("a2_food_restaurant_l09_q1", "a2_food_restaurant_l09", "lesson_practice", "recognition", "przeszly_czas_jedzenie", 3, + "Co znaczy „Zjadłem obiad”?", "Что означает «Zjadłem obiad»?", "Що означає «Zjadłem obiad»?", "What does “Zjadłem obiad” mean?", + "D", None, None), + ("a2_food_restaurant_l09_q2", "a2_food_restaurant_l09", "lesson_practice", "production", "przeszly_czas_jedzenie", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ całą pizzę. (я съела)", "Вставьте пропущенное слово (говорит женщина): ___ całą pizzę. (я съела)", "Вставте пропущене слово (говорить жінка): ___ całą pizzę. (я з'їла)", "Fill in the missing word (a woman is speaking): ___ całą pizzę. (I ate)", + "Zjadłam", "first_letter", "Z"), + ("a2_food_restaurant_l09_q3", "a2_food_restaurant_l09", "lesson_practice", "application", "przeszly_czas_jedzenie", 3, + "Mężczyzna opowiada, że wczoraj zjadł bardzo dobrą kolację. Co powie?", "Мужчина рассказывает, что вчера съел очень вкусный ужин. Что он скажет?", "Чоловік розповідає, що вчора з'їв дуже смачну вечерю. Що він скаже?", "A man is telling that yesterday he ate a very good dinner. What does he say?", + "B", None, None), + + # L10 — opisuje_swoj_posilek (difficulty 3) + ("a2_food_restaurant_l10_q1", "a2_food_restaurant_l10", "lesson_practice", "recognition", "opisuje_swoj_posilek", 3, + "Które zdanie poprawnie opisuje posiłek?", "Какое предложение правильно описывает приём пищи?", "Яке речення правильно описує прийом їжі?", "Which sentence correctly describes a meal?", + "D", None, None), + ("a2_food_restaurant_l10_q2", "a2_food_restaurant_l10", "lesson_practice", "production", "opisuje_swoj_posilek", 3, + "Przetłumacz: «Я попрошу счёт».", "Переведите: «Я попрошу счёт».", "Перекладіть: «Я попрошу рахунок».", "Translate: “I'll ask for the bill.”", + "Poproszę o rachunek", "first_letter", "P"), + ("a2_food_restaurant_l10_q3", "a2_food_restaurant_l10", "lesson_practice", "application", "opisuje_swoj_posilek", 3, + "Chcesz opisać koledze swój obiad: zamawiasz zupę, smakuje ci, prosisz o rachunek. Jak zaczniesz zdanie?", "Ты хочешь описать другу свой обед: ты заказываешь суп, тебе нравится, ты просишь счёт. Как ты начнёшь предложение?", "Ти хочеш описати другу свій обід: ти замовляєш суп, тобі смакує, ти просиш рахунок. Як ти почнеш речення?", "You want to describe your lunch to a friend: you order soup, you like it, you ask for the bill. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t5_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_food_restaurant', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t5_a2 = [ + # L01 + ("a2_food_restaurant_l01_q1", "A", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a2_food_restaurant_l01_q1", "B", "mięso", "мясо", "м'ясо", "meat", True, None), + ("a2_food_restaurant_l01_q1", "C", "ser", "сыр", "сир", "cheese", False, "wrong_word"), + ("a2_food_restaurant_l01_q1", "D", "warzywa", "овощи", "овочі", "vegetables", False, "wrong_word"), + + ("a2_food_restaurant_l01_q3", "A", "chleb", "хлеб", "хліб", "bread", False, "wrong_context"), + ("a2_food_restaurant_l01_q3", "B", "mięso", "мясо", "м'ясо", "meat", False, "wrong_context"), + ("a2_food_restaurant_l01_q3", "C", "ser", "сыр", "сир", "cheese", False, "wrong_context"), + ("a2_food_restaurant_l01_q3", "D", "warzywa", "овощи", "овочі", "vegetables", True, None), + + # L02 + ("a2_food_restaurant_l02_q1", "A", "Chcę", "я хочу", "я хочу", "I want", True, None), + ("a2_food_restaurant_l02_q1", "B", "Chcesz", "ты хочешь (не тот человек)", "ти хочеш (не та особа)", "you want (wrong person)", False, "wrong_context"), + ("a2_food_restaurant_l02_q1", "C", "Chce", "он/она хочет (не тот человек)", "він/вона хоче (не та особа)", "he/she wants (wrong person)", False, "wrong_context"), + ("a2_food_restaurant_l02_q1", "D", "Chcieli", "они хотели (неправильное число и время)", "вони хотіли (неправильне число і час)", "they wanted (wrong number and tense)", False, "wrong_number"), + + ("a2_food_restaurant_l02_q3", "A", "Chcę spróbować tego dania.", "Я хочу попробовать это блюдо.", "Я хочу спробувати цю страву.", "I want to try this dish.", True, None), + ("a2_food_restaurant_l02_q3", "B", "Chcę zapłacić rachunek.", "Я хочу оплатить счёт. (не соответствует ситуации)", "Я хочу сплатити рахунок. (не відповідає ситуації)", "I want to pay the bill. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_l02_q3", "C", "Chcę iść do restauracji.", "Я хочу пойти в ресторан. (не соответствует ситуации)", "Я хочу піти в ресторан. (не відповідає ситуації)", "I want to go to a restaurant. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_l02_q3", "D", "Chcę zamówić wodę.", "Я хочу заказать воду. (не соответствует ситуации)", "Я хочу замовити воду. (не відповідає ситуації)", "I want to order water. (doesn't match the situation)", False, "wrong_context"), + + # L03 + ("a2_food_restaurant_l03_q1", "A", "Jem pizzę.", "Я ем пиццу.", "Я їм піцу.", "I'm eating pizza.", False, "wrong_translation"), + ("a2_food_restaurant_l03_q1", "B", "Gotuję pizzę.", "Я готовлю пиццу.", "Я готую піцу.", "I'm cooking pizza.", False, "wrong_translation"), + ("a2_food_restaurant_l03_q1", "C", "Zamawiam pizzę.", "Я заказываю пиццу.", "Я замовляю піцу.", "I'm ordering pizza.", False, "wrong_translation"), + ("a2_food_restaurant_l03_q1", "D", "Lubię pizzę.", "Я люблю пиццу.", "Я люблю піцу.", "I like pizza.", True, None), + + ("a2_food_restaurant_l03_q3", "A", "Lubię pizzę.", "Я люблю пиццу. (не соответствует ситуации)", "Я люблю піцу. (не відповідає ситуації)", "I like pizza. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_l03_q3", "B", "Lubię zupę.", "Я люблю суп. (не соответствует ситуации)", "Я люблю суп. (не відповідає ситуації)", "I like soup. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_l03_q3", "C", "Lubię owoce.", "Я люблю фрукты.", "Я люблю фрукти.", "I like fruit.", True, None), + ("a2_food_restaurant_l03_q3", "D", "Gotuję owoce.", "Я готовлю фрукты. (неверный глагол)", "Я готую фрукти. (невірне дієслово)", "I'm cooking fruit. (wrong verb)", False, "wrong_context"), + + # L04 + ("a2_food_restaurant_l04_q1", "A", "restauracja", "ресторан", "ресторан", "restaurant", False, "wrong_word"), + ("a2_food_restaurant_l04_q1", "B", "kelner", "официант", "офіціант", "waiter", True, None), + ("a2_food_restaurant_l04_q1", "C", "menu", "меню", "меню", "menu", False, "wrong_word"), + ("a2_food_restaurant_l04_q1", "D", "rachunek", "счёт", "рахунок", "bill", False, "wrong_word"), + + ("a2_food_restaurant_l04_q3", "A", "menu", "меню", "меню", "menu", False, "wrong_context"), + ("a2_food_restaurant_l04_q3", "B", "kelnera", "официанта", "офіціанта", "waiter", False, "wrong_context"), + ("a2_food_restaurant_l04_q3", "C", "rachunek", "счёт", "рахунок", "bill", True, None), + ("a2_food_restaurant_l04_q3", "D", "restaurację", "ресторан", "ресторан", "restaurant", False, "wrong_context"), + + # L05 + ("a2_food_restaurant_l05_q1", "A", "zupę", "суп (вин.)", "суп (знах.)", "soup (acc.)", True, None), + ("a2_food_restaurant_l05_q1", "B", "zupa", "суп (им.)", "суп (наз.)", "soup (nom.)", False, "wrong_case"), + ("a2_food_restaurant_l05_q1", "C", "zupy", "супа (род.)", "супу (род.)", "soup (gen.)", False, "wrong_case"), + ("a2_food_restaurant_l05_q1", "D", "zupą", "супом (тв.)", "супом (ор.)", "soup (instr.)", False, "wrong_case"), + + ("a2_food_restaurant_l05_q3", "A", "Zamawiam zupę.", "Я заказываю суп. (не соответствует ситуации)", "Я замовляю суп. (не відповідає ситуації)", "I'm ordering soup. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_l05_q3", "B", "Zamawiam kawę.", "Я заказываю кофе. (не соответствует ситуации)", "Я замовляю каву. (не відповідає ситуації)", "I'm ordering coffee. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_l05_q3", "C", "Zamawiam deser.", "Я заказываю десерт.", "Я замовляю десерт.", "I'm ordering dessert.", True, None), + ("a2_food_restaurant_l05_q3", "D", "Zamawiam rachunek.", "Я заказываю счёт. (счёт не заказывают)", "Я замовляю рахунок. (рахунок не замовляють)", "I'm ordering the bill. (you don't „order” a bill)", False, "wrong_context"), + + # L06 + ("a2_food_restaurant_l06_q1", "A", "o", "о/за", "про/за", "for", True, None), + ("a2_food_restaurant_l06_q1", "B", "do", "в/к", "в/до", "to", False, "wrong_word"), + ("a2_food_restaurant_l06_q1", "C", "na", "на", "на", "for", False, "wrong_word"), + ("a2_food_restaurant_l06_q1", "D", "w", "в", "в", "in", False, "wrong_word"), + + ("a2_food_restaurant_l06_q3", "A", "Poproszę o menu.", "Я попрошу меню. (не соответствует ситуации)", "Я попрошу меню. (не відповідає ситуації)", "I'll ask for the menu. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_l06_q3", "B", "Poproszę o rachunek.", "Я попрошу счёт.", "Я попрошу рахунок.", "I'll ask for the bill.", True, None), + ("a2_food_restaurant_l06_q3", "C", "Poproszę o wodę.", "Я попрошу воду. (не соответствует ситуации)", "Я попрошу воду. (не відповідає ситуації)", "I'll ask for water. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_l06_q3", "D", "Poproszę o deser.", "Я попрошу десерт. (не соответствует ситуации)", "Я попрошу десерт. (не відповідає ситуації)", "I'll ask for dessert. (doesn't match the situation)", False, "wrong_context"), + + # L07 + ("a2_food_restaurant_l07_q1", "A", "słodki", "сладкий", "солодкий", "sweet", False, "wrong_word"), + ("a2_food_restaurant_l07_q1", "B", "słony", "солёный", "солоний", "salty", False, "wrong_word"), + ("a2_food_restaurant_l07_q1", "C", "ostry", "острый", "гострий", "spicy", False, "wrong_word"), + ("a2_food_restaurant_l07_q1", "D", "kwaśny", "кислый", "кислий", "sour", True, None), + + ("a2_food_restaurant_l07_q3", "A", "słodkie", "сладкое", "солодка", "sweet", False, "wrong_context"), + ("a2_food_restaurant_l07_q3", "B", "słone", "солёное", "солона", "salty", False, "wrong_context"), + ("a2_food_restaurant_l07_q3", "C", "ostre", "острое", "гостра", "spicy", True, None), + ("a2_food_restaurant_l07_q3", "D", "kwaśne", "кислое", "кисла", "sour", False, "wrong_context"), + + # L08 + ("a2_food_restaurant_l08_q1", "A", "Gotuję tę zupę.", "Я готовлю этот суп.", "Я готую цей суп.", "I'm cooking this soup.", False, "wrong_translation"), + ("a2_food_restaurant_l08_q1", "B", "Zamawiam tę zupę.", "Я заказываю этот суп.", "Я замовляю цей суп.", "I'm ordering this soup.", False, "wrong_translation"), + ("a2_food_restaurant_l08_q1", "C", "Nie lubię tej zupy.", "Мне не нравится этот суп.", "Мені не подобається цей суп.", "I don't like this soup.", False, "wrong_translation"), + ("a2_food_restaurant_l08_q1", "D", "Smakuje mi ta zupa.", "Мне нравится этот суп (он вкусный).", "Мені смакує цей суп.", "I like this soup (it tastes good to me).", True, None), + + ("a2_food_restaurant_l08_q3", "A", "Nie smakuje mi to danie.", "Мне не нравится это блюдо. (противоречит ситуации)", "Мені не смакує ця страва. (суперечить ситуації)", "I don't like this dish. (contradicts the situation)", False, "wrong_context"), + ("a2_food_restaurant_l08_q3", "B", "Smakuje mi to danie.", "Мне нравится это блюдо.", "Мені смакує ця страва.", "I like this dish.", True, None), + ("a2_food_restaurant_l08_q3", "C", "Gotuję to danie.", "Я готовлю это блюдо. (не о вкусе)", "Я готую цю страву. (не про смак)", "I'm cooking this dish. (not about taste)", False, "wrong_context"), + ("a2_food_restaurant_l08_q3", "D", "Zamawiam to danie.", "Я заказываю это блюдо. (не о вкусе)", "Я замовляю цю страву. (не про смак)", "I'm ordering this dish. (not about taste)", False, "wrong_context"), + + # L09 + ("a2_food_restaurant_l09_q1", "A", "Jem obiad.", "Я ем обед.", "Я їм обід.", "I'm eating lunch.", False, "wrong_translation"), + ("a2_food_restaurant_l09_q1", "B", "Gotuję obiad.", "Я готовлю обед.", "Я готую обід.", "I'm cooking lunch.", False, "wrong_translation"), + ("a2_food_restaurant_l09_q1", "C", "Zjem obiad.", "Я съем обед.", "Я з'їм обід.", "I will eat lunch.", False, "wrong_translation"), + ("a2_food_restaurant_l09_q1", "D", "Zjadłem obiad.", "Я съел обед.", "Я з'їв обід.", "I ate lunch.", True, None), + + ("a2_food_restaurant_l09_q3", "A", "Jem kolację.", "Я ем ужин. (настоящее время)", "Я їм вечерю. (теперішній час)", "I'm eating dinner. (present tense)", False, "wrong_sentence_type"), + ("a2_food_restaurant_l09_q3", "B", "Zjadłem pyszną kolację.", "Я съел вкусный ужин.", "Я з'їв смачну вечерю.", "I ate a delicious dinner.", True, None), + ("a2_food_restaurant_l09_q3", "C", "Będę jadł kolację.", "Я буду есть ужин. (будущее время)", "Я їстиму вечерю. (майбутній час)", "I will be eating dinner. (future tense)", False, "wrong_sentence_type"), + ("a2_food_restaurant_l09_q3", "D", "Zjadłam pyszną kolację.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + + # L10 + ("a2_food_restaurant_l10_q1", "A", "Zamawiam zupa, smakuje mi.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a2_food_restaurant_l10_q1", "B", "Ja zamawiam ja zupę ja smakuje.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_food_restaurant_l10_q1", "C", "Zamawiam smakuje zupę mi.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_food_restaurant_l10_q1", "D", "Zamawiam zupę, bo smakuje mi to danie.", "Я заказываю суп, потому что мне нравится это блюдо.", "Я замовляю суп, бо мені смакує ця страва.", "I'm ordering soup because I like this dish.", True, None), + + ("a2_food_restaurant_l10_q3", "A", "Poproszę o rachunek.", "Я попрошу счёт. (не начало описания)", "Я попрошу рахунок. (не початок опису)", "I'll ask for the bill. (not the opening line)", False, "wrong_context"), + ("a2_food_restaurant_l10_q3", "B", "Smakuje mi ta zupa.", "Мне нравится этот суп. (не начало описания)", "Мені смакує цей суп. (не початок опису)", "I like this soup. (not the opening line)", False, "wrong_context"), + ("a2_food_restaurant_l10_q3", "C", "Zamawiam zupę.", "Я заказываю суп.", "Я замовляю суп.", "I'm ordering soup.", True, None), + ("a2_food_restaurant_l10_q3", "D", "Zjadłem cały obiad.", "Я съел весь обед. (не начало описания)", "Я з'їв весь обід. (не початок опису)", "I ate the whole lunch. (not the opening line)", False, "wrong_context"), + ] + + for opt in options_t5_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t5_a2 = [ + ("a2_food_restaurant_t01", None, "topic_test", "recognition", "jedzenie_vocabulary", 1, + "Jak po polsku „мясо”?", "Как по-польски «мясо»?", "Як польською «м'ясо»?", "How do you say “meat” in Polish?", + "B", None, None, 1), + ("a2_food_restaurant_t02", None, "topic_test", "recognition", "chciec_bezokolicznik", 1, + "Wybierz poprawną formę: ___ zamówić zupę. (chcieć, ja)", "Выберите правильную форму: ___ zamówić zupę. (chcieć, ja)", "Виберіть правильну форму: ___ zamówić zupę. (chcieć, ja)", "Choose the correct form: ___ zamówić zupę. (chcieć, I)", + "A", None, None, 2), + ("a2_food_restaurant_t03", None, "topic_test", "recognition", "lubic_biernik", 1, + "Co znaczy „Lubię pizzę”?", "Что означает «Lubię pizzę»?", "Що означає «Lubię pizzę»?", "What does “Lubię pizzę” mean?", + "D", None, None, 3), + ("a2_food_restaurant_t04", None, "topic_test", "recognition", "restauracja_vocabulary", 1, + "Jak po polsku „официант”?", "Как по-польски «официант»?", "Як польською «офіціант»?", "How do you say “waiter” in Polish?", + "B", None, None, 4), + ("a2_food_restaurant_t05", None, "topic_test", "recognition", "zamawiac_biernik", 2, + "Wybierz poprawną formę: Zamawiam ___. (zupa)", "Выберите правильную форму: Zamawiam ___. (zupa)", "Виберіть правильну форму: Zamawiam ___. (zupa)", "Choose the correct form: Zamawiam ___. (zupa)", + "A", None, None, 5), + ("a2_food_restaurant_t06", None, "topic_test", "recognition", "przeszly_czas_jedzenie", 3, + "Co znaczy „Zjadłem obiad”?", "Что означает «Zjadłem obiad»?", "Що означає «Zjadłem obiad»?", "What does “Zjadłem obiad” mean?", + "D", None, None, 6), + + ("a2_food_restaurant_t07", None, "topic_test", "application", "jedzenie_vocabulary", 1, + "Chcesz zjeść coś zdrowego i lekkiego przed obiadem. Co wybierzesz?", "Ты хочешь съесть что-то полезное и лёгкое перед обедом. Что ты выберешь?", "Ти хочеш з'їсти щось корисне і легке перед обідом. Що ти обереш?", "You want to eat something healthy and light before lunch. What will you choose?", + "D", None, None, 7), + ("a2_food_restaurant_t08", None, "topic_test", "application", "chciec_bezokolicznik", 1, + "Widzisz w menu ciekawe danie i chcesz je spróbować. Co powiesz?", "Ты видишь в меню интересное блюдо и хочешь его попробовать. Что ты скажешь?", "Ти бачиш у меню цікаву страву і хочеш її спробувати. Що ти скажеш?", "You see an interesting dish on the menu and want to try it. What do you say?", + "A", None, None, 8), + ("a2_food_restaurant_t09", None, "topic_test", "application", "lubic_biernik", 1, + "Kolega pyta, co lubisz jeść. Lubisz owoce. Co powiesz?", "Друг спрашивает, что ты любишь есть. Ты любишь фрукты. Что ты скажешь?", "Друг питає, що ти любиш їсти. Ти любиш фрукти. Що ти скажеш?", "A friend asks what you like to eat. You like fruit. What do you say?", + "C", None, None, 9), + ("a2_food_restaurant_t10", None, "topic_test", "application", "poprosic_o", 2, + "Skończyłeś jeść i chcesz zapłacić. Co powiesz kelnerowi?", "Ты закончил есть и хочешь заплатить. Что ты скажешь официанту?", "Ти закінчив їсти і хочеш заплатити. Що ти скажеш офіціанту?", "You've finished eating and want to pay. What do you say to the waiter?", + "B", None, None, 10), + ("a2_food_restaurant_t11", None, "topic_test", "application", "smaki_vocabulary", 2, + "Zjadłeś danie z dużą ilością chili i teraz piecze cię w ustach. Jakie to danie?", "Ты съел блюдо с большим количеством чили, и теперь у тебя горит во рту. Какое это блюдо?", "Ти з'їв страву з великою кількістю чилі, і тепер у тебе пече в роті. Яка це страва?", "You ate a dish with a lot of chili and now your mouth is burning. What kind of dish is it?", + "C", None, None, 11), + ("a2_food_restaurant_t12", None, "topic_test", "application", "przeszly_czas_jedzenie", 3, + "Mężczyzna opowiada, że wczoraj zjadł bardzo dobrą kolację. Co powie?", "Мужчина рассказывает, что вчера съел очень вкусный ужин. Что он скажет?", "Чоловік розповідає, що вчора з'їв дуже смачну вечерю. Що він скаже?", "A man is telling that yesterday he ate a very good dinner. What does he say?", + "B", None, None, 12), + + ("a2_food_restaurant_t13", None, "topic_test", "production", "jedzenie_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (сыр)", "Вставьте пропущенное слово: To jest ___. (сыр)", "Вставте пропущене слово: To jest ___. (сир)", "Fill in the missing word: To jest ___. (cheese)", + "ser", "first_letter", "s", 13), + ("a2_food_restaurant_t14", None, "topic_test", "production", "restauracja_vocabulary", 1, + "Wpisz brakujące słowo: Proszę o ___. (счёт)", "Вставьте пропущенное слово: Proszę o ___. (счёт)", "Вставте пропущене слово: Proszę o ___. (рахунок)", "Fill in the missing word: Proszę o ___. (the bill)", + "rachunek", "first_letter", "r", 14), + ("a2_food_restaurant_t15", None, "topic_test", "production", "zamawiac_biernik", 2, + "Wpisz brakujące słowo: Zamawiasz ___? (кофе)", "Вставьте пропущенное слово: Zamawiasz ___? (кофе)", "Вставте пропущене слово: Zamawiasz ___? (каву)", "Fill in the missing word: Zamawiasz ___? (coffee)", + "kawę", "first_letter", "k", 15), + ("a2_food_restaurant_t16", None, "topic_test", "production", "poprosic_o", 2, + "Wpisz brakujące słowo: Poprosisz o ___? (воду)", "Вставьте пропущенное слово: Poprosisz o ___? (воду)", "Вставте пропущене слово: Poprosisz o ___? (воду)", "Fill in the missing word: Poprosisz o ___? (water)", + "wodę", "first_letter", "w", 16), + ("a2_food_restaurant_t17", None, "topic_test", "production", "smaki_vocabulary", 2, + "Wpisz brakujące słowo: Ta zupa jest ___. (солёный)", "Вставьте пропущенное слово: Ta zupa jest ___. (солёный)", "Вставте пропущене слово: Ta zupa jest ___. (солоний)", "Fill in the missing word: Ta zupa jest ___. (salty)", + "słona", "first_letter", "s", 17), + ("a2_food_restaurant_t18", None, "topic_test", "production", "opisuje_swoj_posilek", 3, + "Przetłumacz: «Я попрошу счёт».", "Переведите: «Я попрошу счёт».", "Перекладіть: «Я попрошу рахунок».", "Translate: “I'll ask for the bill.”", + "Poproszę o rachunek", "first_letter", "P", 18), + + ("a2_food_restaurant_t19", None, "topic_test", "mixed", "opisuje_swoj_posilek", 3, + "Wybierz poprawne tłumaczenie: «Я заказываю суп, мне очень нравится это блюдо, и я съел весь обед».", "Выберите правильный перевод: «Я заказываю суп, мне очень нравится это блюдо, и я съел весь обед».", "Виберіть правильний переклад: «Я замовляю суп, мені дуже подобається ця страва, і я з'їв весь обід».", "Choose the correct translation: “I'm ordering soup, I really like this dish, and I ate the whole lunch.”", + "C", None, None, 19), + ("a2_food_restaurant_t20", None, "topic_test", "mixed", "czasownik_smakowac", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Тебе нравится этот суп? — Да, он очень вкусный, я попрошу ещё.»", "Выберите правильный перевод диалога: «— Тебе нравится этот суп? — Да, он очень вкусный, я попрошу ещё.»", "Виберіть правильний переклад діалогу: «— Тобі смакує цей суп? — Так, він дуже смачний, я попрошу ще.»", "Choose the correct translation of the dialogue: “— Do you like this soup? — Yes, it's very tasty, I'll ask for more.”", + "C", None, None, 20), + ] + + for q in test_questions_t5_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_food_restaurant', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t5_a2 = [ + ("a2_food_restaurant_t01", "A", "chleb", "хлеб", "хліб", "bread", False, "wrong_word"), + ("a2_food_restaurant_t01", "B", "mięso", "мясо", "м'ясо", "meat", True, None), + ("a2_food_restaurant_t01", "C", "ser", "сыр", "сир", "cheese", False, "wrong_word"), + ("a2_food_restaurant_t01", "D", "warzywa", "овощи", "овочі", "vegetables", False, "wrong_word"), + + ("a2_food_restaurant_t02", "A", "Chcę", "я хочу", "я хочу", "I want", True, None), + ("a2_food_restaurant_t02", "B", "Chcesz", "ты хочешь (не тот человек)", "ти хочеш (не та особа)", "you want (wrong person)", False, "wrong_context"), + ("a2_food_restaurant_t02", "C", "Chce", "он/она хочет (не тот человек)", "він/вона хоче (не та особа)", "he/she wants (wrong person)", False, "wrong_context"), + ("a2_food_restaurant_t02", "D", "Chcieli", "они хотели (неправильное число и время)", "вони хотіли (неправильне число і час)", "they wanted (wrong number and tense)", False, "wrong_number"), + + ("a2_food_restaurant_t03", "A", "Jem pizzę.", "Я ем пиццу.", "Я їм піцу.", "I'm eating pizza.", False, "wrong_translation"), + ("a2_food_restaurant_t03", "B", "Gotuję pizzę.", "Я готовлю пиццу.", "Я готую піцу.", "I'm cooking pizza.", False, "wrong_translation"), + ("a2_food_restaurant_t03", "C", "Zamawiam pizzę.", "Я заказываю пиццу.", "Я замовляю піцу.", "I'm ordering pizza.", False, "wrong_translation"), + ("a2_food_restaurant_t03", "D", "Lubię pizzę.", "Я люблю пиццу.", "Я люблю піцу.", "I like pizza.", True, None), + + ("a2_food_restaurant_t04", "A", "restauracja", "ресторан", "ресторан", "restaurant", False, "wrong_word"), + ("a2_food_restaurant_t04", "B", "kelner", "официант", "офіціант", "waiter", True, None), + ("a2_food_restaurant_t04", "C", "menu", "меню", "меню", "menu", False, "wrong_word"), + ("a2_food_restaurant_t04", "D", "rachunek", "счёт", "рахунок", "bill", False, "wrong_word"), + + ("a2_food_restaurant_t05", "A", "zupę", "суп (вин.)", "суп (знах.)", "soup (acc.)", True, None), + ("a2_food_restaurant_t05", "B", "zupa", "суп (им.)", "суп (наз.)", "soup (nom.)", False, "wrong_case"), + ("a2_food_restaurant_t05", "C", "zupy", "супа (род.)", "супу (род.)", "soup (gen.)", False, "wrong_case"), + ("a2_food_restaurant_t05", "D", "zupą", "супом (тв.)", "супом (ор.)", "soup (instr.)", False, "wrong_case"), + + ("a2_food_restaurant_t06", "A", "Jem obiad.", "Я ем обед.", "Я їм обід.", "I'm eating lunch.", False, "wrong_translation"), + ("a2_food_restaurant_t06", "B", "Gotuję obiad.", "Я готовлю обед.", "Я готую обід.", "I'm cooking lunch.", False, "wrong_translation"), + ("a2_food_restaurant_t06", "C", "Zjem obiad.", "Я съем обед.", "Я з'їм обід.", "I will eat lunch.", False, "wrong_translation"), + ("a2_food_restaurant_t06", "D", "Zjadłem obiad.", "Я съел обед.", "Я з'їв обід.", "I ate lunch.", True, None), + + ("a2_food_restaurant_t07", "A", "chleb", "хлеб", "хліб", "bread", False, "wrong_context"), + ("a2_food_restaurant_t07", "B", "mięso", "мясо", "м'ясо", "meat", False, "wrong_context"), + ("a2_food_restaurant_t07", "C", "ser", "сыр", "сир", "cheese", False, "wrong_context"), + ("a2_food_restaurant_t07", "D", "warzywa", "овощи", "овочі", "vegetables", True, None), + + ("a2_food_restaurant_t08", "A", "Chcę spróbować tego dania.", "Я хочу попробовать это блюдо.", "Я хочу спробувати цю страву.", "I want to try this dish.", True, None), + ("a2_food_restaurant_t08", "B", "Chcę zapłacić rachunek.", "Я хочу оплатить счёт. (не соответствует ситуации)", "Я хочу сплатити рахунок. (не відповідає ситуації)", "I want to pay the bill. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_t08", "C", "Chcę iść do restauracji.", "Я хочу пойти в ресторан. (не соответствует ситуации)", "Я хочу піти в ресторан. (не відповідає ситуації)", "I want to go to a restaurant. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_t08", "D", "Chcę zamówić wodę.", "Я хочу заказать воду. (не соответствует ситуации)", "Я хочу замовити воду. (не відповідає ситуації)", "I want to order water. (doesn't match the situation)", False, "wrong_context"), + + ("a2_food_restaurant_t09", "A", "Lubię pizzę.", "Я люблю пиццу. (не соответствует ситуации)", "Я люблю піцу. (не відповідає ситуації)", "I like pizza. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_t09", "B", "Lubię zupę.", "Я люблю суп. (не соответствует ситуации)", "Я люблю суп. (не відповідає ситуації)", "I like soup. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_t09", "C", "Lubię owoce.", "Я люблю фрукты.", "Я люблю фрукти.", "I like fruit.", True, None), + ("a2_food_restaurant_t09", "D", "Gotuję owoce.", "Я готовлю фрукты. (неверный глагол)", "Я готую фрукти. (невірне дієслово)", "I'm cooking fruit. (wrong verb)", False, "wrong_context"), + + ("a2_food_restaurant_t10", "A", "Poproszę o menu.", "Я попрошу меню. (не соответствует ситуации)", "Я попрошу меню. (не відповідає ситуації)", "I'll ask for the menu. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_t10", "B", "Poproszę o rachunek.", "Я попрошу счёт.", "Я попрошу рахунок.", "I'll ask for the bill.", True, None), + ("a2_food_restaurant_t10", "C", "Poproszę o wodę.", "Я попрошу воду. (не соответствует ситуации)", "Я попрошу воду. (не відповідає ситуації)", "I'll ask for water. (doesn't match the situation)", False, "wrong_context"), + ("a2_food_restaurant_t10", "D", "Poproszę o deser.", "Я попрошу десерт. (не соответствует ситуации)", "Я попрошу десерт. (не відповідає ситуації)", "I'll ask for dessert. (doesn't match the situation)", False, "wrong_context"), + + ("a2_food_restaurant_t11", "A", "słodkie", "сладкое", "солодка", "sweet", False, "wrong_context"), + ("a2_food_restaurant_t11", "B", "słone", "солёное", "солона", "salty", False, "wrong_context"), + ("a2_food_restaurant_t11", "C", "ostre", "острое", "гостра", "spicy", True, None), + ("a2_food_restaurant_t11", "D", "kwaśne", "кислое", "кисла", "sour", False, "wrong_context"), + + ("a2_food_restaurant_t12", "A", "Jem kolację.", "Я ем ужин. (настоящее время)", "Я їм вечерю. (теперішній час)", "I'm eating dinner. (present tense)", False, "wrong_sentence_type"), + ("a2_food_restaurant_t12", "B", "Zjadłem pyszną kolację.", "Я съел вкусный ужин.", "Я з'їв смачну вечерю.", "I ate a delicious dinner.", True, None), + ("a2_food_restaurant_t12", "C", "Będę jadł kolację.", "Я буду есть ужин. (будущее время)", "Я їстиму вечерю. (майбутній час)", "I will be eating dinner. (future tense)", False, "wrong_sentence_type"), + ("a2_food_restaurant_t12", "D", "Zjadłam pyszną kolację.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + + ("a2_food_restaurant_t19", "A", "Zamawiałem zupę, bardzo smakowało mi to danie, i jadłem cały obiad.", "Я заказывал суп, мне очень нравилось это блюдо, и я поел весь обед. (неправильное время)", "Я замовляв суп, мені дуже подобалась ця страва, і я поїв весь обід. (неправильний час)", "I was ordering soup, I really liked this dish, and I ate the whole lunch. (wrong tense)", False, "wrong_sentence_type"), + ("a2_food_restaurant_t19", "B", "Będę zamawiać zupę, będzie mi smakować to danie, i zjem cały obiad.", "Я буду заказывать суп, мне будет нравиться это блюдо, и я съем весь обед. (будущее время)", "Я буду замовляти суп, мені подобатиметься ця страва, і я з'їм весь обід. (майбутній час)", "I will be ordering soup, I will like this dish, and I will eat the whole lunch. (future tense)", False, "wrong_sentence_type"), + ("a2_food_restaurant_t19", "C", "Zamawiam zupę, bardzo smakuje mi to danie, i zjadłem cały obiad.", "Я заказываю суп, мне очень нравится это блюдо, и я съел весь обед.", "Я замовляю суп, мені дуже подобається ця страва, і я з'їв весь обід.", "I'm ordering soup, I really like this dish, and I ate the whole lunch.", True, None), + ("a2_food_restaurant_t19", "D", "Zamawiam kawę, bardzo smakuje mi to danie, i zjadłem cały deser.", "Я заказываю кофе, мне очень нравится это блюдо, и я съел весь десерт. (неверные предметы)", "Я замовляю каву, мені дуже подобається ця страва, і я з'їв весь десерт. (невірні предмети)", "I'm ordering coffee, I really like this dish, and I ate the whole dessert. (wrong items)", False, "wrong_word"), + + ("a2_food_restaurant_t20", "A", "— Smakowała ci ta zupa? — Tak, była bardzo smaczna, poprosiłem jeszcze.", "— Тебе понравился этот суп? — Да, он был очень вкусный, я попросил ещё. (прошедшее время)", "— Тобі сподобався цей суп? — Так, він був дуже смачний, я попросив ще. (минулий час)", "— Did you like this soup? — Yes, it was very tasty, I asked for more. (past tense)", False, "wrong_sentence_type"), + ("a2_food_restaurant_t20", "B", "— Smakuje ci ta zupa? — Tak, jest bardzo smaczna, zjadłem już wszystko.", "— Тебе нравится этот суп? — Да, он очень вкусный, я уже всё съел. (неверный смысл)", "— Тобі смакує цей суп? — Так, він дуже смачний, я вже все з'їв. (невірний зміст)", "— Do you like this soup? — Yes, it's very tasty, I already ate it all. (wrong meaning)", False, "wrong_word"), + ("a2_food_restaurant_t20", "C", "— Smakuje ci ta zupa? — Tak, jest bardzo smaczna, poproszę jeszcze.", "— Тебе нравится этот суп? — Да, он очень вкусный, я попрошу ещё.", "— Тобі смакує цей суп? — Так, він дуже смачний, я попрошу ще.", "— Do you like this soup? — Yes, it's very tasty, I'll ask for more.", True, None), + ("a2_food_restaurant_t20", "D", "— Smakuje ci to danie? — Tak, jest bardzo smaczna, poproszę jeszcze.", "— Тебе нравится это блюдо? — Да, оно очень вкусное, я попрошу ещё. (несогласование рода)", "— Тобі смакує ця страва? — Так, вона дуже смачна, я попрошу ще. (невідповідність роду)", "— Do you like this dish? — Yes, it's very tasty, I'll ask for more. (gender mismatch)", False, "wrong_word"), + ] + + for opt in test_options_t5_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 6 (A2): ОТНОШЕНИЯ И ЭМОЦИИ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_relationships_emotions', 'A2', 6, + 'Relacje i emocje', + 'Отношения и эмоции', + 'Стосунки та емоції', + 'Relationships and Emotions') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t6_a2 = [ + ("a2_relationships_emotions_l01", 1, "emocje_vocabulary", "Podstawowe słowa: emocje", "Основные слова: эмоции", "Основні слова: емоції", "Basic words: emotions", + "Podstawowe nazwy emocji: radość, smutek, złość, strach.", + "Основные названия эмоций: radość (радость), smutek (грусть), złość (злость), strach (страх).", + "Основні назви емоцій: radość (радість), smutek (сум), złość (злість), strach (страх).", + "Basic emotion names: radość (joy), smutek (sadness), złość (anger), strach (fear)."), + + ("a2_relationships_emotions_l02", 2, "jestem_przymiotnik", "Być + przymiotnik: jestem szczęśliwy/szczęśliwa", "Być + прилагательное: jestem szczęśliwy/szczęśliwa", "Być + прикметник: jestem szczęśliwy/szczęśliwa", "Być + adjective: jestem szczęśliwy/szczęśliwa", + "Przymiotniki opisujące uczucia zgadzają się z rodzajem mówiącego: jestem szczęśliwy (mężczyzna) / jestem szczęśliwa (kobieta), jestem smutny/smutna, jestem zły/zła.", + "Прилагательные, описывающие чувства, согласуются с родом говорящего: jestem szczęśliwy (мужчина) / jestem szczęśliwa (женщина) — я счастлив/счастлива, jestem smutny/smutna (грустен/грустна), jestem zły/zła (зол/зла).", + "Прикметники, що описують почуття, узгоджуються з родом мовця: jestem szczęśliwy (чоловік) / jestem szczęśliwa (жінка) — я щасливий/щаслива, jestem smutny/smutna (сумний/сумна), jestem zły/zła (злий/зла).", + "Adjectives describing feelings agree with the speaker's gender: jestem szczęśliwy (male speaker) / jestem szczęśliwa (female speaker) — I am happy, jestem smutny/smutna (I am sad), jestem zły/zła (I am angry)."), + + ("a2_relationships_emotions_l03", 3, "lubic_osoby", "Lubić + biernik (osoby)", "Lubić + винительный падеж (люди)", "Lubić + знахідний відмінок (люди)", "Lubić + accusative (people)", + "Czasownik „lubić” + biernik zaimka osobowego: lubię go, lubisz ją, lubi ich.", + "Глагол „lubić” (нравиться) + винительный падеж личного местоимения: lubię go (он мне нравится), lubisz ją (она тебе нравится), lubi ich (они ему/ей нравятся).", + "Дієслово „lubić” (подобатися) + знахідний відмінок особового займенника: lubię go (він мені подобається), lubisz ją (вона тобі подобається), lubi ich (вони йому/їй подобаються).", + "The verb „lubić” (to like) + accusative of the personal pronoun: lubię go (I like him), lubisz ją (you like her), lubi ich (he/she likes them)."), + + ("a2_relationships_emotions_l04", 4, "relacje_vocabulary", "Podstawowe słowa: relacje", "Основные слова: отношения", "Основні слова: стосунки", "Basic words: relationships", + "Podstawowe słowa: przyjaciel, znajomy, partner/partnerka, rodzina.", + "Основные слова: przyjaciel (друг), znajomy (знакомый), partner/partnerka (партнёр/партнёрша), rodzina (семья).", + "Основні слова: przyjaciel (друг), znajomy (знайомий), partner/partnerka (партнер/партнерка), rodzina (родина).", + "Basic words: przyjaciel (friend), znajomy (acquaintance), partner/partnerka (partner), rodzina (family)."), + + ("a2_relationships_emotions_l05", 5, "czasownik_kochac", "Kochać + biernik", "Kochać + винительный падеж", "Kochać + знахідний відмінок", "Kochać + accusative", + "Czasownik „kochać” + biernik: kocham cię, kochasz go, kocha ją.", + "Глагол „kochać” (любить) + винительный падеж: kocham cię (я люблю тебя), kochasz go (ты любишь его), kocha ją (он/она любит её).", + "Дієслово „kochać” (кохати/любити) + знахідний відмінок: kocham cię (я тебе кохаю), kochasz go (ти його кохаєш), kocha ją (він/вона її кохає).", + "The verb „kochać” (to love) + accusative: kocham cię (I love you), kochasz go (you love him), kocha ją (he/she loves her)."), + + ("a2_relationships_emotions_l06", 6, "wyrazac_uczucia", "Czuć + biernik (emocje)", "Czuć + винительный падеж (эмоции)", "Czuć + знахідний відмінок (емоції)", "Czuć + accusative (emotions)", + "Czasownik „czuć” + biernik rzeczownika emocji: czuję radość, czujesz złość, czuje strach.", + "Глагол „czuć” (чувствовать) + винительный падеж существительного эмоции: czuję radość (я чувствую радость), czujesz złość (ты чувствуешь злость), czuje strach (он/она чувствует страх).", + "Дієслово „czuć” (відчувати) + знахідний відмінок іменника емоції: czuję radość (я відчуваю радість), czujesz złość (ти відчуваєш злість), czuje strach (він/вона відчуває страх).", + "The verb „czuć” (to feel) + accusative of the emotion noun: czuję radość (I feel joy), czujesz złość (you feel anger), czuje strach (he/she feels fear)."), + + ("a2_relationships_emotions_l07", 7, "przymiotniki_charakteru_vocabulary", "Podstawowe słowa: cechy charakteru", "Основные слова: черты характера", "Основні слова: риси характеру", "Basic words: character traits", + "Podstawowe przymiotniki opisujące charakter: miły, wesoły, spokojny, nerwowy.", + "Основные прилагательные, описывающие характер: miły (приятный), wesoły (весёлый), spokojny (спокойный), nerwowy (нервный).", + "Основні прикметники, що описують характер: miły (приємний), wesoły (веселий), spokojny (спокійний), nerwowy (нервовий).", + "Basic adjectives describing character: miły (nice), wesoły (cheerful), spokojny (calm), nerwowy (nervous)."), + + ("a2_relationships_emotions_l08", 8, "poniewaz_bo", "Bo + zdanie przyczyny", "Bo + придаточное причины", "Bo + підрядне речення причини", "Bo + clause of reason", + "Spójnik „bo” (ponieważ) łączy zdanie z przyczyną: jestem szczęśliwy, bo mam dobrą pracę.", + "Союз „bo” (потому что) соединяет предложение с причиной: jestem szczęśliwy, bo mam dobrą pracę (я счастлив, потому что у меня хорошая работа).", + "Сполучник „bo” (тому що) поєднує речення з причиною: jestem szczęśliwy, bo mam dobrą pracę (я щасливий, бо маю хорошу роботу).", + "The conjunction „bo” (because) links a sentence with its reason: jestem szczęśliwy, bo mam dobrą pracę (I am happy because I have a good job)."), + + ("a2_relationships_emotions_l09", 9, "przeszly_czas_uczucia", "Czułem/czułam się + przysłówek (przeszłość)", "Czułem/czułam się + наречие (прошедшее)", "Czułem/czułam się + прислівник (минулий час)", "Czułem/czułam się + adverb (past)", + "Czas przeszły samopoczucia tworzymy „czułem się” (mężczyzna) lub „czułam się” (kobieta) + przysłówek: czułem się źle wczoraj, czułam się szczęśliwa.", + "Прошедшее время самочувствия образуем „czułem się” (мужчина) или „czułam się” (женщина) + наречие: czułem się źle wczoraj (я чувствовал себя плохо вчера), czułam się szczęśliwa (я чувствовала себя счастливой).", + "Минулий час самопочуття утворюємо „czułem się” (чоловік) або „czułam się” (жінка) + прислівник: czułem się źle wczoraj (я почувався погано вчора), czułam się szczęśliwa (я почувалася щасливою).", + "We form the past tense of feelings with „czułem się” (male speaker) or „czułam się” (female speaker) + adverb: czułem się źle wczoraj (I felt bad yesterday), czułam się szczęśliwa (I felt happy)."), + + ("a2_relationships_emotions_l10", 10, "opisuje_swoje_relacje", "Opisuję swoje relacje i emocje", "Описываю свои отношения и эмоции", "Описую свої стосунки та емоції", "Describing my relationships and emotions", + "Żeby opisać relacje i emocje, łączymy zdania: Mam dobrego przyjaciela. Lubię go bardzo. Czuję radość, kiedy z nim rozmawiam. Jestem szczęśliwy, bo mam dobrych znajomych.", + "Чтобы описать отношения и эмоции, соединяем предложения: Mam dobrego przyjaciela. Lubię go bardzo. Czuję radość, kiedy z nim rozmawiam. Jestem szczęśliwy, bo mam dobrych znajomych. (У меня есть хороший друг. Он мне очень нравится. Я чувствую радость, когда с ним разговариваю. Я счастлив, потому что у меня хорошие знакомые.)", + "Щоб описати стосунки та емоції, поєднуємо речення: Mam dobrego przyjaciela. Lubię go bardzo. Czuję radość, kiedy z nim rozmawiam. Jestem szczęśliwy, bo mam dobrych znajomych. (У мене є хороший друг. Він мені дуже подобається. Я відчуваю радість, коли з ним розмовляю. Я щасливий, бо маю хороших знайомих.)", + "To describe relationships and emotions, we combine sentences: Mam dobrego przyjaciela. Lubię go bardzo. Czuję radość, kiedy z nim rozmawiam. Jestem szczęśliwy, bo mam dobrych znajomych. (I have a good friend. I like him a lot. I feel joy when I talk with him. I am happy because I have good acquaintances.)"), + ] + + for lesson in lessons_t6_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_relationships_emotions', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t6_a2 = [ + ("a2_relationships_emotions_l01", 1, "To jest radość.", "Это радость.", "Це радість.", "This is joy."), + ("a2_relationships_emotions_l01", 2, "To jest smutek.", "Это грусть.", "Це сум.", "This is sadness."), + ("a2_relationships_emotions_l01", 3, "To jest strach.", "Это страх.", "Це страх.", "This is fear."), + + ("a2_relationships_emotions_l02", 1, "Jestem szczęśliwy.", "Я счастлив.", "Я щасливий.", "I am happy."), + ("a2_relationships_emotions_l02", 2, "Jestem smutna.", "Я грустна.", "Я сумна.", "I am sad."), + ("a2_relationships_emotions_l02", 3, "Jesteś zły?", "Ты зол?", "Ти злий?", "Are you angry?"), + + ("a2_relationships_emotions_l03", 1, "Lubię go.", "Он мне нравится.", "Він мені подобається.", "I like him."), + ("a2_relationships_emotions_l03", 2, "Lubisz ją?", "Она тебе нравится?", "Вона тобі подобається?", "Do you like her?"), + ("a2_relationships_emotions_l03", 3, "On ich lubi.", "Они ему нравятся.", "Вони йому подобаються.", "He likes them."), + + ("a2_relationships_emotions_l04", 1, "To jest mój przyjaciel.", "Это мой друг.", "Це мій друг.", "This is my friend."), + ("a2_relationships_emotions_l04", 2, "To jest moja rodzina.", "Это моя семья.", "Це моя сім'я.", "This is my family."), + ("a2_relationships_emotions_l04", 3, "To jest mój znajomy.", "Это мой знакомый.", "Це мій знайомий.", "This is my acquaintance."), + + ("a2_relationships_emotions_l05", 1, "Kocham cię.", "Я люблю тебя.", "Я тебе кохаю.", "I love you."), + ("a2_relationships_emotions_l05", 2, "Kochasz go?", "Ты любишь его?", "Ти його кохаєш?", "Do you love him?"), + ("a2_relationships_emotions_l05", 3, "Ona kocha swoją rodzinę.", "Она любит свою семью.", "Вона любить свою родину.", "She loves her family."), + + ("a2_relationships_emotions_l06", 1, "Czuję radość.", "Я чувствую радость.", "Я відчуваю радість.", "I feel joy."), + ("a2_relationships_emotions_l06", 2, "Czujesz złość?", "Ты чувствуешь злость?", "Ти відчуваєш злість?", "Do you feel anger?"), + ("a2_relationships_emotions_l06", 3, "On czuje strach.", "Он чувствует страх.", "Він відчуває страх.", "He feels fear."), + + ("a2_relationships_emotions_l07", 1, "On jest miły.", "Он приятный.", "Він приємний.", "He is nice."), + ("a2_relationships_emotions_l07", 2, "Ona jest wesoła.", "Она весёлая.", "Вона весела.", "She is cheerful."), + ("a2_relationships_emotions_l07", 3, "On jest bardzo spokojny.", "Он очень спокойный.", "Він дуже спокійний.", "He is very calm."), + + ("a2_relationships_emotions_l08", 1, "Jestem szczęśliwy, bo mam dobrą pracę.", "Я счастлив, потому что у меня хорошая работа.", "Я щасливий, бо маю хорошу роботу.", "I am happy because I have a good job."), + ("a2_relationships_emotions_l08", 2, "Jestem smutna, bo tęsknię za rodziną.", "Я грустна, потому что скучаю по семье.", "Я сумна, бо сумую за родиною.", "I am sad because I miss my family."), + ("a2_relationships_emotions_l08", 3, "Jest zły, bo stracił pracę.", "Он зол, потому что потерял работу.", "Він злий, бо втратив роботу.", "He is angry because he lost his job."), + + ("a2_relationships_emotions_l09", 1, "Czułem się źle wczoraj.", "Я чувствовал себя плохо вчера.", "Я почувався погано вчора.", "I felt bad yesterday."), + ("a2_relationships_emotions_l09", 2, "Czułaś się szczęśliwa na urodzinach?", "Ты чувствовала себя счастливой на дне рождения?", "Ти почувалася щасливою на дні народження?", "Did you feel happy at the birthday party?"), + ("a2_relationships_emotions_l09", 3, "Czuł się spokojny po rozmowie.", "Он чувствовал себя спокойным после разговора.", "Він почувався спокійним після розмови.", "He felt calm after the conversation."), + + ("a2_relationships_emotions_l10", 1, "Mam dobrego przyjaciela.", "У меня есть хороший друг.", "У мене є хороший друг.", "I have a good friend."), + ("a2_relationships_emotions_l10", 2, "Lubię go bardzo.", "Он мне очень нравится.", "Він мені дуже подобається.", "I like him a lot."), + ("a2_relationships_emotions_l10", 3, "Jestem szczęśliwy, bo mam dobrych znajomych.", "Я счастлив, потому что у меня хорошие знакомые.", "Я щасливий, бо маю хороших знайомих.", "I am happy because I have good acquaintances."), + ] + + for ex in examples_t6_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t6_a2 = [ + # L01 — emocje_vocabulary (difficulty 1) + ("a2_relationships_emotions_l01_q1", "a2_relationships_emotions_l01", "lesson_practice", "recognition", "emocje_vocabulary", 1, + "Jak po polsku „злость”?", "Как по-польски «злость»?", "Як польською «злість»?", "How do you say “anger” in Polish?", + "C", None, None), + ("a2_relationships_emotions_l01_q2", "a2_relationships_emotions_l01", "lesson_practice", "production", "emocje_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (страх)", "Вставьте пропущенное слово: To jest ___. (страх)", "Вставте пропущене слово: To jest ___. (страх)", "Fill in the missing word: To jest ___. (fear)", + "strach", "first_letter", "s"), + ("a2_relationships_emotions_l01_q3", "a2_relationships_emotions_l01", "lesson_practice", "application", "emocje_vocabulary", 1, + "Widzisz coś niebezpiecznego i chcesz uciec. Co czujesz?", "Ты видишь что-то опасное и хочешь убежать. Что ты чувствуешь?", "Ти бачиш щось небезпечне і хочеш втекти. Що ти відчуваєш?", "You see something dangerous and want to run away. What do you feel?", + "D", None, None), + + # L02 — jestem_przymiotnik (difficulty 1) + ("a2_relationships_emotions_l02_q1", "a2_relationships_emotions_l02", "lesson_practice", "recognition", "jestem_przymiotnik", 1, + "Wybierz poprawną formę (kobieta mówi): Jestem ___. (szczęśliwy)", "Выберите правильную форму (говорит женщина): Jestem ___. (szczęśliwy)", "Виберіть правильну форму (говорить жінка): Jestem ___. (szczęśliwy)", "Choose the correct form (a woman is speaking): Jestem ___. (szczęśliwy)", + "A", None, None), + ("a2_relationships_emotions_l02_q2", "a2_relationships_emotions_l02", "lesson_practice", "production", "jestem_przymiotnik", 1, + "Wpisz brakujące słowo (mężczyzna mówi): Jestem ___. (грустный)", "Вставьте пропущенное слово (говорит мужчина): Jestem ___. (грустный)", "Вставте пропущене слово (говорить чоловік): Jestem ___. (сумний)", "Fill in the missing word (a man is speaking): Jestem ___. (sad)", + "smutny", "first_letter", "s"), + ("a2_relationships_emotions_l02_q3", "a2_relationships_emotions_l02", "lesson_practice", "application", "jestem_przymiotnik", 1, + "Ktoś zepsuł twoje plany i jesteś na niego bardzo zły. Co powiesz (mężczyzna mówi)?", "Кто-то испортил твои планы, и ты на него очень зол. Что ты скажешь (говорит мужчина)?", "Хтось зіпсував твої плани, і ти на нього дуже злий. Що ти скажеш (говорить чоловік)?", "Someone ruined your plans and you're very angry at them. What do you say (a man is speaking)?", + "B", None, None), + + # L03 — lubic_osoby (difficulty 1) + ("a2_relationships_emotions_l03_q1", "a2_relationships_emotions_l03", "lesson_practice", "recognition", "lubic_osoby", 1, + "Wybierz poprawną formę: Lubię ___. (on)", "Выберите правильную форму: Lubię ___. (on)", "Виберіть правильну форму: Lubię ___. (on)", "Choose the correct form: Lubię ___. (on)", + "A", None, None), + ("a2_relationships_emotions_l03_q2", "a2_relationships_emotions_l03", "lesson_practice", "production", "lubic_osoby", 1, + "Wpisz brakujące słowo: Lubisz ___? (её)", "Вставьте пропущенное слово: Lubisz ___? (её)", "Вставте пропущене слово: Lubisz ___? (її)", "Fill in the missing word: Lubisz ___? (her)", + "ją", "first_letter", "j"), + ("a2_relationships_emotions_l03_q3", "a2_relationships_emotions_l03", "lesson_practice", "application", "lubic_osoby", 1, + "Kolega pyta, czy lubisz nowych sąsiadów (mężczyznę i kobietę). Lubisz ich oboje. Co powiesz?", "Друг спрашивает, нравятся ли тебе новые соседи (мужчина и женщина). Они оба тебе нравятся. Что ты скажешь?", "Друг питає, чи подобаються тобі нові сусіди (чоловік і жінка). Вони обоє тобі подобаються. Що ти скажеш?", "A friend asks if you like the new neighbors (a man and a woman). You like them both. What do you say?", + "C", None, None), + + # L04 — relacje_vocabulary (difficulty 1) + ("a2_relationships_emotions_l04_q1", "a2_relationships_emotions_l04", "lesson_practice", "recognition", "relacje_vocabulary", 1, + "Jak po polsku „знакомый”?", "Как по-польски «знакомый»?", "Як польською «знайомий»?", "How do you say “acquaintance” in Polish?", + "B", None, None), + ("a2_relationships_emotions_l04_q2", "a2_relationships_emotions_l04", "lesson_practice", "production", "relacje_vocabulary", 1, + "Wpisz brakujące słowo: To jest moja ___. (семья)", "Вставьте пропущенное слово: To jest moja ___. (семья)", "Вставте пропущене слово: To jest moja ___. (родина)", "Fill in the missing word: To jest moja ___. (family)", + "rodzina", "first_letter", "r"), + ("a2_relationships_emotions_l04_q3", "a2_relationships_emotions_l04", "lesson_practice", "application", "relacje_vocabulary", 1, + "Znasz tę osobę, ale nie jesteście bliskimi przyjaciółmi. Kim ona dla ciebie jest?", "Ты знаешь этого человека, но вы не близкие друзья. Кто он для тебя?", "Ти знаєш цю людину, але ви не близькі друзі. Хто вона для тебе?", "You know this person, but you're not close friends. Who is she to you?", + "B", None, None), + + # L05 — czasownik_kochac (difficulty 2) + ("a2_relationships_emotions_l05_q1", "a2_relationships_emotions_l05", "lesson_practice", "recognition", "czasownik_kochac", 2, + "Wybierz poprawną formę: Kocham ___. (ty)", "Выберите правильную форму: Kocham ___. (ty)", "Виберіть правильну форму: Kocham ___. (ty)", "Choose the correct form: Kocham ___. (ty)", + "A", None, None), + ("a2_relationships_emotions_l05_q2", "a2_relationships_emotions_l05", "lesson_practice", "production", "czasownik_kochac", 2, + "Wpisz brakujące słowo: ___ swoją rodzinę. (она любит)", "Вставьте пропущенное слово: ___ swoją rodzinę. (она любит)", "Вставте пропущене слово: ___ swoją rodzinę. (вона любить)", "Fill in the missing word: ___ swoją rodzinę. (she loves)", + "Kocha", "first_letter", "K"), + ("a2_relationships_emotions_l05_q3", "a2_relationships_emotions_l05", "lesson_practice", "application", "czasownik_kochac", 2, + "Chcesz wyznać uczucia swojej dziewczynie. Co powiesz?", "Ты хочешь признаться в чувствах своей девушке. Что ты скажешь?", "Ти хочеш зізнатися в почуттях своїй дівчині. Що ти скажеш?", "You want to confess your feelings to your girlfriend. What do you say?", + "B", None, None), + + # L06 — wyrazac_uczucia (difficulty 2) + ("a2_relationships_emotions_l06_q1", "a2_relationships_emotions_l06", "lesson_practice", "recognition", "wyrazac_uczucia", 2, + "Wybierz poprawną formę: Czuję ___. (radość)", "Выберите правильную форму: Czuję ___. (radość)", "Виберіть правильну форму: Czuję ___. (radość)", "Choose the correct form: Czuję ___. (radość)", + "A", None, None), + ("a2_relationships_emotions_l06_q2", "a2_relationships_emotions_l06", "lesson_practice", "production", "wyrazac_uczucia", 2, + "Wpisz brakujące słowo: Czujesz ___? (злость)", "Вставьте пропущенное слово: Czujesz ___? (злость)", "Вставте пропущене слово: Czujesz ___? (злість)", "Fill in the missing word: Czujesz ___? (anger)", + "złość", "first_letter", "z"), + ("a2_relationships_emotions_l06_q3", "a2_relationships_emotions_l06", "lesson_practice", "application", "wyrazac_uczucia", 2, + "Boisz się ciemności i wchodzisz do ciemnego pokoju. Co czujesz?", "Ты боишься темноты и заходишь в тёмную комнату. Что ты чувствуешь?", "Ти боїшся темряви і заходиш у темну кімнату. Що ти відчуваєш?", "You're afraid of the dark and you enter a dark room. What do you feel?", + "C", None, None), + + # L07 — przymiotniki_charakteru_vocabulary (difficulty 2) + ("a2_relationships_emotions_l07_q1", "a2_relationships_emotions_l07", "lesson_practice", "recognition", "przymiotniki_charakteru_vocabulary", 2, + "Jak po polsku „нервный”?", "Как по-польски «нервный»?", "Як польською «нервовий»?", "How do you say “nervous” in Polish?", + "D", None, None), + ("a2_relationships_emotions_l07_q2", "a2_relationships_emotions_l07", "lesson_practice", "production", "przymiotniki_charakteru_vocabulary", 2, + "Wpisz brakujące słowo: Ona jest ___. (весёлая)", "Вставьте пропущенное слово: Ona jest ___. (весёлая)", "Вставте пропущене слово: Ona jest ___. (весела)", "Fill in the missing word: Ona jest ___. (cheerful)", + "wesoła", "first_letter", "w"), + ("a2_relationships_emotions_l07_q3", "a2_relationships_emotions_l07", "lesson_practice", "application", "przymiotniki_charakteru_vocabulary", 2, + "Twój kolega nigdy się nie denerwuje i zawsze zachowuje spokój. Jaki on jest?", "Твой друг никогда не нервничает и всегда сохраняет спокойствие. Какой он?", "Твій друг ніколи не нервує і завжди зберігає спокій. Який він?", "Your friend never gets nervous and always stays calm. What is he like?", + "C", None, None), + + # L08 — poniewaz_bo (difficulty 2) + ("a2_relationships_emotions_l08_q1", "a2_relationships_emotions_l08", "lesson_practice", "recognition", "poniewaz_bo", 2, + "Wybierz poprawną formę: Jestem szczęśliwy, ___ mam dobrą pracę.", "Выберите правильную форму: Jestem szczęśliwy, ___ mam dobrą pracę.", "Виберіть правильну форму: Jestem szczęśliwy, ___ mam dobrą pracę.", "Choose the correct form: Jestem szczęśliwy, ___ mam dobrą pracę.", + "A", None, None), + ("a2_relationships_emotions_l08_q2", "a2_relationships_emotions_l08", "lesson_practice", "production", "poniewaz_bo", 2, + "Wpisz brakujące słowo: Jestem smutna, ___ tęsknię za rodziną. (потому что)", "Вставьте пропущенное слово: Jestem smutna, ___ tęsknię za rodziną. (потому что)", "Вставте пропущене слово: Jestem smutna, ___ tęsknię za rodziną. (тому що)", "Fill in the missing word: Jestem smutna, ___ tęsknię za rodziną. (because)", + "bo", "first_letter", "b"), + ("a2_relationships_emotions_l08_q3", "a2_relationships_emotions_l08", "lesson_practice", "application", "poniewaz_bo", 2, + "Chcesz wyjaśnić koledze, dlaczego jesteś zły: straciłeś pracę. Co powiesz?", "Ты хочешь объяснить другу, почему ты зол: ты потерял работу. Что ты скажешь?", "Ти хочеш пояснити другу, чому ти злий: ти втратив роботу. Що ти скажеш?", "You want to explain to a friend why you're angry: you lost your job. What do you say?", + "A", None, None), + + # L09 — przeszly_czas_uczucia (difficulty 3) + ("a2_relationships_emotions_l09_q1", "a2_relationships_emotions_l09", "lesson_practice", "recognition", "przeszly_czas_uczucia", 3, + "Co znaczy „Czułem się źle wczoraj”?", "Что означает «Czułem się źle wczoraj»?", "Що означає «Czułem się źle wczoraj»?", "What does “Czułem się źle wczoraj” mean?", + "D", None, None), + ("a2_relationships_emotions_l09_q2", "a2_relationships_emotions_l09", "lesson_practice", "production", "przeszly_czas_uczucia", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ się szczęśliwa na urodzinach. (я чувствовала)", "Вставьте пропущенное слово (говорит женщина): ___ się szczęśliwa na urodzinach. (я чувствовала)", "Вставте пропущене слово (говорить жінка): ___ się szczęśliwa na urodzinach. (я почувалася)", "Fill in the missing word (a woman is speaking): ___ się szczęśliwa na urodzinach. (I felt)", + "Czułam", "first_letter", "C"), + ("a2_relationships_emotions_l09_q3", "a2_relationships_emotions_l09", "lesson_practice", "application", "przeszly_czas_uczucia", 3, + "Mężczyzna opowiada, że wczoraj czuł się bardzo spokojny po ważnej rozmowie. Co powie?", "Мужчина рассказывает, что вчера чувствовал себя очень спокойно после важного разговора. Что он скажет?", "Чоловік розповідає, що вчора почувався дуже спокійним після важливої розмови. Що він скаже?", "A man is telling that yesterday he felt very calm after an important conversation. What does he say?", + "B", None, None), + + # L10 — opisuje_swoje_relacje (difficulty 3) + ("a2_relationships_emotions_l10_q1", "a2_relationships_emotions_l10", "lesson_practice", "recognition", "opisuje_swoje_relacje", 3, + "Które zdanie poprawnie opisuje uczucia?", "Какое предложение правильно описывает чувства?", "Яке речення правильно описує почуття?", "Which sentence correctly describes feelings?", + "D", None, None), + ("a2_relationships_emotions_l10_q2", "a2_relationships_emotions_l10", "lesson_practice", "production", "opisuje_swoje_relacje", 3, + "Przetłumacz: «Он мне очень нравится».", "Переведите: «Он мне очень нравится».", "Перекладіть: «Він мені дуже подобається».", "Translate: “I like him a lot.”", + "Lubię go bardzo", "first_letter", "L"), + ("a2_relationships_emotions_l10_q3", "a2_relationships_emotions_l10", "lesson_practice", "application", "opisuje_swoje_relacje", 3, + "Chcesz opisać koledze swoją przyjaźń: masz dobrego przyjaciela, lubisz go, czujesz radość. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою дружбу: у тебя есть хороший друг, он тебе нравится, ты чувствуешь радость. Как ты начнёшь предложение?", "Ти хочеш описати другу свою дружбу: у тебе є хороший друг, він тобі подобається, ти відчуваєш радість. Як ти почнеш речення?", "You want to describe your friendship to someone: you have a good friend, you like him, you feel joy. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t6_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_relationships_emotions', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t6_a2 = [ + # L01 + ("a2_relationships_emotions_l01_q1", "A", "radość", "радость", "радість", "joy", False, "wrong_word"), + ("a2_relationships_emotions_l01_q1", "B", "smutek", "грусть", "сум", "sadness", False, "wrong_word"), + ("a2_relationships_emotions_l01_q1", "C", "złość", "злость", "злість", "anger", True, None), + ("a2_relationships_emotions_l01_q1", "D", "strach", "страх", "страх", "fear", False, "wrong_word"), + + ("a2_relationships_emotions_l01_q3", "A", "radość", "радость", "радість", "joy", False, "wrong_context"), + ("a2_relationships_emotions_l01_q3", "B", "smutek", "грусть", "сум", "sadness", False, "wrong_context"), + ("a2_relationships_emotions_l01_q3", "C", "złość", "злость", "злість", "anger", False, "wrong_context"), + ("a2_relationships_emotions_l01_q3", "D", "strach", "страх", "страх", "fear", True, None), + + # L02 + ("a2_relationships_emotions_l02_q1", "A", "szczęśliwa", "счастлива (ж.р.)", "щаслива (жін.р.)", "happy (fem.)", True, None), + ("a2_relationships_emotions_l02_q1", "B", "szczęśliwy", "счастлив (м.р.)", "щасливий (чол.р.)", "happy (masc.)", False, "wrong_gender"), + ("a2_relationships_emotions_l02_q1", "C", "szczęśliwe", "счастливое (ср.р.)", "щасливе (сер.р.)", "happy (neut.)", False, "wrong_gender"), + ("a2_relationships_emotions_l02_q1", "D", "szczęśliwi", "счастливые (мн.ч.)", "щасливі (мн.)", "happy (plural)", False, "wrong_number"), + + ("a2_relationships_emotions_l02_q3", "A", "Jestem szczęśliwy.", "Я счастлив. (не соответствует ситуации)", "Я щасливий. (не відповідає ситуації)", "I am happy. (doesn't match the situation)", False, "wrong_context"), + ("a2_relationships_emotions_l02_q3", "B", "Jestem zły.", "Я зол.", "Я злий.", "I am angry.", True, None), + ("a2_relationships_emotions_l02_q3", "C", "Jestem smutny.", "Я грустен. (не соответствует ситуации)", "Я сумний. (не відповідає ситуації)", "I am sad. (doesn't match the situation)", False, "wrong_context"), + ("a2_relationships_emotions_l02_q3", "D", "Jestem spokojny.", "Я спокоен. (не соответствует ситуации)", "Я спокійний. (не відповідає ситуації)", "I am calm. (doesn't match the situation)", False, "wrong_context"), + + # L03 + ("a2_relationships_emotions_l03_q1", "A", "go", "его (вин.)", "його (знах.)", "him (acc.)", True, None), + ("a2_relationships_emotions_l03_q1", "B", "ją", "её (не тот род)", "її (не той рід)", "her (wrong gender)", False, "wrong_word"), + ("a2_relationships_emotions_l03_q1", "C", "ich", "их (неправильное число)", "їх (неправильне число)", "them (wrong number)", False, "wrong_number"), + ("a2_relationships_emotions_l03_q1", "D", "je", "их/это (неправильное слово)", "їх/це (неправильне слово)", "them/it (wrong word)", False, "wrong_word"), + + ("a2_relationships_emotions_l03_q3", "A", "Lubię go.", "Он мне нравится. (только один из двух)", "Він мені подобається. (лише один із двох)", "I like him. (only one of the two)", False, "wrong_context"), + ("a2_relationships_emotions_l03_q3", "B", "Lubię ją.", "Она мне нравится. (только один из двух)", "Вона мені подобається. (лише один із двох)", "I like her. (only one of the two)", False, "wrong_context"), + ("a2_relationships_emotions_l03_q3", "C", "Lubię ich.", "Они мне нравятся.", "Вони мені подобаються.", "I like them.", True, None), + ("a2_relationships_emotions_l03_q3", "D", "Nie lubię ich.", "Они мне не нравятся. (противоположный смысл)", "Вони мені не подобаються. (протилежний зміст)", "I don't like them. (opposite meaning)", False, "wrong_context"), + + # L04 + ("a2_relationships_emotions_l04_q1", "A", "przyjaciel", "друг", "друг", "friend", False, "wrong_word"), + ("a2_relationships_emotions_l04_q1", "B", "znajomy", "знакомый", "знайомий", "acquaintance", True, None), + ("a2_relationships_emotions_l04_q1", "C", "partner", "партнёр", "партнер", "partner", False, "wrong_word"), + ("a2_relationships_emotions_l04_q1", "D", "rodzina", "семья", "родина", "family", False, "wrong_word"), + + ("a2_relationships_emotions_l04_q3", "A", "przyjacielem", "другом", "другом", "friend", False, "wrong_context"), + ("a2_relationships_emotions_l04_q3", "B", "znajomym", "знакомым", "знайомим", "acquaintance", True, None), + ("a2_relationships_emotions_l04_q3", "C", "partnerem", "партнёром", "партнером", "partner", False, "wrong_context"), + ("a2_relationships_emotions_l04_q3", "D", "rodziną", "семьёй", "родиною", "family", False, "wrong_context"), + + # L05 + ("a2_relationships_emotions_l05_q1", "A", "cię", "тебя (вин.)", "тебе (знах.)", "you (acc.)", True, None), + ("a2_relationships_emotions_l05_q1", "B", "ty", "ты (им.)", "ти (наз.)", "you (nom.)", False, "wrong_case"), + ("a2_relationships_emotions_l05_q1", "C", "tobie", "тебе (дат.)", "тобі (дав.)", "you (dat.)", False, "wrong_case"), + ("a2_relationships_emotions_l05_q1", "D", "tobą", "тобой (тв.)", "тобою (ор.)", "you (instr.)", False, "wrong_case"), + + ("a2_relationships_emotions_l05_q3", "A", "Lubię cię.", "Ты мне нравишься. (более слабое чувство)", "Ти мені подобаєшся. (слабше почуття)", "I like you. (weaker feeling)", False, "wrong_context"), + ("a2_relationships_emotions_l05_q3", "B", "Kocham cię.", "Я люблю тебя.", "Я тебе кохаю.", "I love you.", True, None), + ("a2_relationships_emotions_l05_q3", "C", "Znam cię.", "Я тебя знаю. (не о чувствах)", "Я тебе знаю. (не про почуття)", "I know you. (not about feelings)", False, "wrong_context"), + ("a2_relationships_emotions_l05_q3", "D", "Widzę cię.", "Я тебя вижу. (не о чувствах)", "Я тебе бачу. (не про почуття)", "I see you. (not about feelings)", False, "wrong_context"), + + # L06 + ("a2_relationships_emotions_l06_q1", "A", "radość", "радость (вин.)", "радість (знах.)", "joy (acc.)", True, None), + ("a2_relationships_emotions_l06_q1", "B", "radości", "радости (род.)", "радості (род.)", "joy (gen.)", False, "wrong_case"), + ("a2_relationships_emotions_l06_q1", "C", "radością", "радостью (тв.)", "радістю (ор.)", "joy (instr.)", False, "wrong_case"), + ("a2_relationships_emotions_l06_q1", "D", "radościom", "радостям (дат. мн.)", "радостям (дав. мн.)", "joys (dat. pl.)", False, "wrong_case"), + + ("a2_relationships_emotions_l06_q3", "A", "radość", "радость", "радість", "joy", False, "wrong_context"), + ("a2_relationships_emotions_l06_q3", "B", "złość", "злость", "злість", "anger", False, "wrong_context"), + ("a2_relationships_emotions_l06_q3", "C", "strach", "страх", "страх", "fear", True, None), + ("a2_relationships_emotions_l06_q3", "D", "smutek", "грусть", "сум", "sadness", False, "wrong_context"), + + # L07 + ("a2_relationships_emotions_l07_q1", "A", "miły", "приятный", "приємний", "nice", False, "wrong_word"), + ("a2_relationships_emotions_l07_q1", "B", "wesoły", "весёлый", "веселий", "cheerful", False, "wrong_word"), + ("a2_relationships_emotions_l07_q1", "C", "spokojny", "спокойный", "спокійний", "calm", False, "wrong_word"), + ("a2_relationships_emotions_l07_q1", "D", "nerwowy", "нервный", "нервовий", "nervous", True, None), + + ("a2_relationships_emotions_l07_q3", "A", "miły", "приятный", "приємний", "nice", False, "wrong_context"), + ("a2_relationships_emotions_l07_q3", "B", "wesoły", "весёлый", "веселий", "cheerful", False, "wrong_context"), + ("a2_relationships_emotions_l07_q3", "C", "spokojny", "спокойный", "спокійний", "calm", True, None), + ("a2_relationships_emotions_l07_q3", "D", "nerwowy", "нервный", "нервовий", "nervous", False, "wrong_context"), + + # L08 + ("a2_relationships_emotions_l08_q1", "A", "bo", "потому что", "тому що", "because", True, None), + ("a2_relationships_emotions_l08_q1", "B", "i", "и", "і", "and", False, "wrong_word"), + ("a2_relationships_emotions_l08_q1", "C", "ale", "но", "але", "but", False, "wrong_word"), + ("a2_relationships_emotions_l08_q1", "D", "lub", "или", "або", "or", False, "wrong_word"), + + ("a2_relationships_emotions_l08_q3", "A", "Jestem zły, bo straciłem pracę.", "Я зол, потому что потерял работу.", "Я злий, бо втратив роботу.", "I am angry because I lost my job.", True, None), + ("a2_relationships_emotions_l08_q3", "B", "Jestem zły i straciłem pracę.", "Я зол и потерял работу. (неверный союз)", "Я злий і втратив роботу. (невірний сполучник)", "I am angry and I lost my job. (wrong conjunction)", False, "wrong_word"), + ("a2_relationships_emotions_l08_q3", "C", "Jestem zły, ale straciłem pracę.", "Я зол, но потерял работу. (неверный союз)", "Я злий, але втратив роботу. (невірний сполучник)", "I am angry, but I lost my job. (wrong conjunction)", False, "wrong_word"), + ("a2_relationships_emotions_l08_q3", "D", "Straciłem pracę i jestem szczęśliwy.", "Я потерял работу и я счастлив. (противоречивый смысл)", "Я втратив роботу і я щасливий. (суперечливий зміст)", "I lost my job and I am happy. (contradictory meaning)", False, "wrong_context"), + + # L09 + ("a2_relationships_emotions_l09_q1", "A", "Czuję się źle dzisiaj.", "Я чувствую себя плохо сегодня.", "Я почуваюся погано сьогодні.", "I feel bad today.", False, "wrong_translation"), + ("a2_relationships_emotions_l09_q1", "B", "Będę się czuć źle jutro.", "Я буду чувствовать себя плохо завтра.", "Я почуватимусь погано завтра.", "I will feel bad tomorrow.", False, "wrong_translation"), + ("a2_relationships_emotions_l09_q1", "C", "Czułem się dobrze wczoraj.", "Я чувствовал себя хорошо вчера.", "Я почувався добре вчора.", "I felt good yesterday.", False, "wrong_translation"), + ("a2_relationships_emotions_l09_q1", "D", "Czułem się źle wczoraj.", "Я чувствовал себя плохо вчера.", "Я почувався погано вчора.", "I felt bad yesterday.", True, None), + + ("a2_relationships_emotions_l09_q3", "A", "Czuję się spokojny.", "Я чувствую себя спокойно. (настоящее время)", "Я почуваюся спокійним. (теперішній час)", "I feel calm. (present tense)", False, "wrong_sentence_type"), + ("a2_relationships_emotions_l09_q3", "B", "Czułem się spokojny.", "Я чувствовал себя спокойно.", "Я почувався спокійним.", "I felt calm.", True, None), + ("a2_relationships_emotions_l09_q3", "C", "Będę się czuć spokojny.", "Я буду чувствовать себя спокойно. (будущее время)", "Я почуватимусь спокійним. (майбутній час)", "I will feel calm. (future tense)", False, "wrong_sentence_type"), + ("a2_relationships_emotions_l09_q3", "D", "Czułam się spokojna.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + + # L10 + ("a2_relationships_emotions_l10_q1", "A", "Jestem szczęśliwy bo ja mam ja przyjaciela.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_relationships_emotions_l10_q1", "B", "Jestem szczęśliwy, mam bo przyjaciela.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_relationships_emotions_l10_q1", "C", "Jestem szczęśliwe, bo mam przyjaciela.", "Неправильная форма рода.", "Неправильна форма роду.", "Wrong gender form.", False, "wrong_gender"), + ("a2_relationships_emotions_l10_q1", "D", "Jestem szczęśliwy, bo mam dobrego przyjaciela.", "Я счастлив, потому что у меня хороший друг.", "Я щасливий, бо маю хорошого друга.", "I am happy because I have a good friend.", True, None), + + ("a2_relationships_emotions_l10_q3", "A", "Czuję radość.", "Я чувствую радость. (не начало описания)", "Я відчуваю радість. (не початок опису)", "I feel joy. (not the opening line)", False, "wrong_context"), + ("a2_relationships_emotions_l10_q3", "B", "Lubię go bardzo.", "Он мне очень нравится. (не начало описания)", "Він мені дуже подобається. (не початок опису)", "I like him a lot. (not the opening line)", False, "wrong_context"), + ("a2_relationships_emotions_l10_q3", "C", "Mam dobrego przyjaciela.", "У меня есть хороший друг.", "У мене є хороший друг.", "I have a good friend.", True, None), + ("a2_relationships_emotions_l10_q3", "D", "Jestem szczęśliwy.", "Я счастлив. (не начало описания)", "Я щасливий. (не початок опису)", "I am happy. (not the opening line)", False, "wrong_context"), + ] + + for opt in options_t6_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t6_a2 = [ + ("a2_relationships_emotions_t01", None, "topic_test", "recognition", "emocje_vocabulary", 1, + "Jak po polsku „злость”?", "Как по-польски «злость»?", "Як польською «злість»?", "How do you say “anger” in Polish?", + "C", None, None, 1), + ("a2_relationships_emotions_t02", None, "topic_test", "recognition", "jestem_przymiotnik", 1, + "Wybierz poprawną formę (kobieta mówi): Jestem ___. (szczęśliwy)", "Выберите правильную форму (говорит женщина): Jestem ___. (szczęśliwy)", "Виберіть правильну форму (говорить жінка): Jestem ___. (szczęśliwy)", "Choose the correct form (a woman is speaking): Jestem ___. (szczęśliwy)", + "A", None, None, 2), + ("a2_relationships_emotions_t03", None, "topic_test", "recognition", "lubic_osoby", 1, + "Wybierz poprawną formę: Lubię ___. (on)", "Выберите правильную форму: Lubię ___. (on)", "Виберіть правильну форму: Lubię ___. (on)", "Choose the correct form: Lubię ___. (on)", + "A", None, None, 3), + ("a2_relationships_emotions_t04", None, "topic_test", "recognition", "relacje_vocabulary", 1, + "Jak po polsku „знакомый”?", "Как по-польски «знакомый»?", "Як польською «знайомий»?", "How do you say “acquaintance” in Polish?", + "B", None, None, 4), + ("a2_relationships_emotions_t05", None, "topic_test", "recognition", "czasownik_kochac", 2, + "Wybierz poprawną formę: Kocham ___. (ty)", "Выберите правильную форму: Kocham ___. (ty)", "Виберіть правильну форму: Kocham ___. (ty)", "Choose the correct form: Kocham ___. (ty)", + "A", None, None, 5), + ("a2_relationships_emotions_t06", None, "topic_test", "recognition", "przeszly_czas_uczucia", 3, + "Co znaczy „Czułem się źle wczoraj”?", "Что означает «Czułem się źle wczoraj»?", "Що означає «Czułem się źle wczoraj»?", "What does “Czułem się źle wczoraj” mean?", + "D", None, None, 6), + + ("a2_relationships_emotions_t07", None, "topic_test", "application", "emocje_vocabulary", 1, + "Widzisz coś niebezpiecznego i chcesz uciec. Co czujesz?", "Ты видишь что-то опасное и хочешь убежать. Что ты чувствуешь?", "Ти бачиш щось небезпечне і хочеш втекти. Що ти відчуваєш?", "You see something dangerous and want to run away. What do you feel?", + "D", None, None, 7), + ("a2_relationships_emotions_t08", None, "topic_test", "application", "jestem_przymiotnik", 1, + "Ktoś zepsuł twoje plany i jesteś na niego bardzo zły. Co powiesz (mężczyzna mówi)?", "Кто-то испортил твои планы, и ты на него очень зол. Что ты скажешь (говорит мужчина)?", "Хтось зіпсував твої плани, і ти на нього дуже злий. Що ти скажеш (говорить чоловік)?", "Someone ruined your plans and you're very angry at them. What do you say (a man is speaking)?", + "B", None, None, 8), + ("a2_relationships_emotions_t09", None, "topic_test", "application", "lubic_osoby", 1, + "Kolega pyta, czy lubisz nowych sąsiadów (mężczyznę i kobietę). Lubisz ich oboje. Co powiesz?", "Друг спрашивает, нравятся ли тебе новые соседи (мужчина и женщина). Они оба тебе нравятся. Что ты скажешь?", "Друг питає, чи подобаються тобі нові сусіди (чоловік і жінка). Вони обоє тобі подобаються. Що ти скажеш?", "A friend asks if you like the new neighbors (a man and a woman). You like them both. What do you say?", + "C", None, None, 9), + ("a2_relationships_emotions_t10", None, "topic_test", "application", "wyrazac_uczucia", 2, + "Boisz się ciemności i wchodzisz do ciemnego pokoju. Co czujesz?", "Ты боишься темноты и заходишь в тёмную комнату. Что ты чувствуешь?", "Ти боїшся темряви і заходиш у темну кімнату. Що ти відчуваєш?", "You're afraid of the dark and you enter a dark room. What do you feel?", + "C", None, None, 10), + ("a2_relationships_emotions_t11", None, "topic_test", "application", "przymiotniki_charakteru_vocabulary", 2, + "Twój kolega nigdy się nie denerwuje i zawsze zachowuje spokój. Jaki on jest?", "Твой друг никогда не нервничает и всегда сохраняет спокойствие. Какой он?", "Твій друг ніколи не нервує і завжди зберігає спокій. Який він?", "Your friend never gets nervous and always stays calm. What is he like?", + "C", None, None, 11), + ("a2_relationships_emotions_t12", None, "topic_test", "application", "przeszly_czas_uczucia", 3, + "Mężczyzna opowiada, że wczoraj czuł się bardzo spokojny po ważnej rozmowie. Co powie?", "Мужчина рассказывает, что вчера чувствовал себя очень спокойно после важного разговора. Что он скажет?", "Чоловік розповідає, що вчора почувався дуже спокійним після важливої розмови. Що він скаже?", "A man is telling that yesterday he felt very calm after an important conversation. What does he say?", + "B", None, None, 12), + + ("a2_relationships_emotions_t13", None, "topic_test", "production", "emocje_vocabulary", 1, + "Wpisz brakujące słowo: To jest ___. (страх)", "Вставьте пропущенное слово: To jest ___. (страх)", "Вставте пропущене слово: To jest ___. (страх)", "Fill in the missing word: To jest ___. (fear)", + "strach", "first_letter", "s", 13), + ("a2_relationships_emotions_t14", None, "topic_test", "production", "relacje_vocabulary", 1, + "Wpisz brakujące słowo: To jest moja ___. (семья)", "Вставьте пропущенное слово: To jest moja ___. (семья)", "Вставте пропущене слово: To jest moja ___. (родина)", "Fill in the missing word: To jest moja ___. (family)", + "rodzina", "first_letter", "r", 14), + ("a2_relationships_emotions_t15", None, "topic_test", "production", "czasownik_kochac", 2, + "Wpisz brakujące słowo: ___ swoją rodzinę. (она любит)", "Вставьте пропущенное слово: ___ swoją rodzinę. (она любит)", "Вставте пропущене слово: ___ swoją rodzinę. (вона любить)", "Fill in the missing word: ___ swoją rodzinę. (she loves)", + "Kocha", "first_letter", "K", 15), + ("a2_relationships_emotions_t16", None, "topic_test", "production", "wyrazac_uczucia", 2, + "Wpisz brakujące słowo: Czujesz ___? (злость)", "Вставьте пропущенное слово: Czujesz ___? (злость)", "Вставте пропущене слово: Czujesz ___? (злість)", "Fill in the missing word: Czujesz ___? (anger)", + "złość", "first_letter", "z", 16), + ("a2_relationships_emotions_t17", None, "topic_test", "production", "przymiotniki_charakteru_vocabulary", 2, + "Wpisz brakujące słowo: Ona jest ___. (весёлая)", "Вставьте пропущенное слово: Ona jest ___. (весёлая)", "Вставте пропущене слово: Ona jest ___. (весела)", "Fill in the missing word: Ona jest ___. (cheerful)", + "wesoła", "first_letter", "w", 17), + ("a2_relationships_emotions_t18", None, "topic_test", "production", "opisuje_swoje_relacje", 3, + "Przetłumacz: «Он мне очень нравится».", "Переведите: «Он мне очень нравится».", "Перекладіть: «Він мені дуже подобається».", "Translate: “I like him a lot.”", + "Lubię go bardzo", "first_letter", "L", 18), + + ("a2_relationships_emotions_t19", None, "topic_test", "mixed", "opisuje_swoje_relacje", 3, + "Wybierz poprawne tłumaczenie: «Я счастлив, потому что у меня хороший друг, и я чувствую радость, когда с ним разговариваю».", "Выберите правильный перевод: «Я счастлив, потому что у меня хороший друг, и я чувствую радость, когда с ним разговариваю».", "Виберіть правильний переклад: «Я щасливий, бо маю хорошого друга, і відчуваю радість, коли з ним розмовляю».", "Choose the correct translation: “I am happy because I have a good friend, and I feel joy when I talk with him.”", + "C", None, None, 19), + ("a2_relationships_emotions_t20", None, "topic_test", "mixed", "poniewaz_bo", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Почему ты грустишь? — Я скучаю по семье, и мне нужна поддержка друзей.»", "Выберите правильный перевод диалога: «— Почему ты грустишь? — Я скучаю по семье, и мне нужна поддержка друзей.»", "Виберіть правильний переклад діалогу: «— Чому ти сумний? — Я сумую за родиною і мені потрібна підтримка друзів.»", "Choose the correct translation of the dialogue: “— Why are you sad? — I miss my family and need my friends' support.”", + "C", None, None, 20), + ] + + for q in test_questions_t6_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_relationships_emotions', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t6_a2 = [ + ("a2_relationships_emotions_t01", "A", "radość", "радость", "радість", "joy", False, "wrong_word"), + ("a2_relationships_emotions_t01", "B", "smutek", "грусть", "сум", "sadness", False, "wrong_word"), + ("a2_relationships_emotions_t01", "C", "złość", "злость", "злість", "anger", True, None), + ("a2_relationships_emotions_t01", "D", "strach", "страх", "страх", "fear", False, "wrong_word"), + + ("a2_relationships_emotions_t02", "A", "szczęśliwa", "счастлива (ж.р.)", "щаслива (жін.р.)", "happy (fem.)", True, None), + ("a2_relationships_emotions_t02", "B", "szczęśliwy", "счастлив (м.р.)", "щасливий (чол.р.)", "happy (masc.)", False, "wrong_gender"), + ("a2_relationships_emotions_t02", "C", "szczęśliwe", "счастливое (ср.р.)", "щасливе (сер.р.)", "happy (neut.)", False, "wrong_gender"), + ("a2_relationships_emotions_t02", "D", "szczęśliwi", "счастливые (мн.ч.)", "щасливі (мн.)", "happy (plural)", False, "wrong_number"), + + ("a2_relationships_emotions_t03", "A", "go", "его (вин.)", "його (знах.)", "him (acc.)", True, None), + ("a2_relationships_emotions_t03", "B", "ją", "её (не тот род)", "її (не той рід)", "her (wrong gender)", False, "wrong_word"), + ("a2_relationships_emotions_t03", "C", "ich", "их (неправильное число)", "їх (неправильне число)", "them (wrong number)", False, "wrong_number"), + ("a2_relationships_emotions_t03", "D", "je", "их/это (неправильное слово)", "їх/це (неправильне слово)", "them/it (wrong word)", False, "wrong_word"), + + ("a2_relationships_emotions_t04", "A", "przyjaciel", "друг", "друг", "friend", False, "wrong_word"), + ("a2_relationships_emotions_t04", "B", "znajomy", "знакомый", "знайомий", "acquaintance", True, None), + ("a2_relationships_emotions_t04", "C", "partner", "партнёр", "партнер", "partner", False, "wrong_word"), + ("a2_relationships_emotions_t04", "D", "rodzina", "семья", "родина", "family", False, "wrong_word"), + + ("a2_relationships_emotions_t05", "A", "cię", "тебя (вин.)", "тебе (знах.)", "you (acc.)", True, None), + ("a2_relationships_emotions_t05", "B", "ty", "ты (им.)", "ти (наз.)", "you (nom.)", False, "wrong_case"), + ("a2_relationships_emotions_t05", "C", "tobie", "тебе (дат.)", "тобі (дав.)", "you (dat.)", False, "wrong_case"), + ("a2_relationships_emotions_t05", "D", "tobą", "тобой (тв.)", "тобою (ор.)", "you (instr.)", False, "wrong_case"), + + ("a2_relationships_emotions_t06", "A", "Czuję się źle dzisiaj.", "Я чувствую себя плохо сегодня.", "Я почуваюся погано сьогодні.", "I feel bad today.", False, "wrong_translation"), + ("a2_relationships_emotions_t06", "B", "Będę się czuć źle jutro.", "Я буду чувствовать себя плохо завтра.", "Я почуватимусь погано завтра.", "I will feel bad tomorrow.", False, "wrong_translation"), + ("a2_relationships_emotions_t06", "C", "Czułem się dobrze wczoraj.", "Я чувствовал себя хорошо вчера.", "Я почувався добре вчора.", "I felt good yesterday.", False, "wrong_translation"), + ("a2_relationships_emotions_t06", "D", "Czułem się źle wczoraj.", "Я чувствовал себя плохо вчера.", "Я почувався погано вчора.", "I felt bad yesterday.", True, None), + + ("a2_relationships_emotions_t07", "A", "radość", "радость", "радість", "joy", False, "wrong_context"), + ("a2_relationships_emotions_t07", "B", "smutek", "грусть", "сум", "sadness", False, "wrong_context"), + ("a2_relationships_emotions_t07", "C", "złość", "злость", "злість", "anger", False, "wrong_context"), + ("a2_relationships_emotions_t07", "D", "strach", "страх", "страх", "fear", True, None), + + ("a2_relationships_emotions_t08", "A", "Jestem szczęśliwy.", "Я счастлив. (не соответствует ситуации)", "Я щасливий. (не відповідає ситуації)", "I am happy. (doesn't match the situation)", False, "wrong_context"), + ("a2_relationships_emotions_t08", "B", "Jestem zły.", "Я зол.", "Я злий.", "I am angry.", True, None), + ("a2_relationships_emotions_t08", "C", "Jestem smutny.", "Я грустен. (не соответствует ситуации)", "Я сумний. (не відповідає ситуації)", "I am sad. (doesn't match the situation)", False, "wrong_context"), + ("a2_relationships_emotions_t08", "D", "Jestem spokojny.", "Я спокоен. (не соответствует ситуации)", "Я спокійний. (не відповідає ситуації)", "I am calm. (doesn't match the situation)", False, "wrong_context"), + + ("a2_relationships_emotions_t09", "A", "Lubię go.", "Он мне нравится. (только один из двух)", "Він мені подобається. (лише один із двох)", "I like him. (only one of the two)", False, "wrong_context"), + ("a2_relationships_emotions_t09", "B", "Lubię ją.", "Она мне нравится. (только один из двух)", "Вона мені подобається. (лише один із двох)", "I like her. (only one of the two)", False, "wrong_context"), + ("a2_relationships_emotions_t09", "C", "Lubię ich.", "Они мне нравятся.", "Вони мені подобаються.", "I like them.", True, None), + ("a2_relationships_emotions_t09", "D", "Nie lubię ich.", "Они мне не нравятся. (противоположный смысл)", "Вони мені не подобаються. (протилежний зміст)", "I don't like them. (opposite meaning)", False, "wrong_context"), + + ("a2_relationships_emotions_t10", "A", "radość", "радость", "радість", "joy", False, "wrong_context"), + ("a2_relationships_emotions_t10", "B", "złość", "злость", "злість", "anger", False, "wrong_context"), + ("a2_relationships_emotions_t10", "C", "strach", "страх", "страх", "fear", True, None), + ("a2_relationships_emotions_t10", "D", "smutek", "грусть", "сум", "sadness", False, "wrong_context"), + + ("a2_relationships_emotions_t11", "A", "miły", "приятный", "приємний", "nice", False, "wrong_context"), + ("a2_relationships_emotions_t11", "B", "wesoły", "весёлый", "веселий", "cheerful", False, "wrong_context"), + ("a2_relationships_emotions_t11", "C", "spokojny", "спокойный", "спокійний", "calm", True, None), + ("a2_relationships_emotions_t11", "D", "nerwowy", "нервный", "нервовий", "nervous", False, "wrong_context"), + + ("a2_relationships_emotions_t12", "A", "Czuję się spokojny.", "Я чувствую себя спокойно. (настоящее время)", "Я почуваюся спокійним. (теперішній час)", "I feel calm. (present tense)", False, "wrong_sentence_type"), + ("a2_relationships_emotions_t12", "B", "Czułem się spokojny.", "Я чувствовал себя спокойно.", "Я почувався спокійним.", "I felt calm.", True, None), + ("a2_relationships_emotions_t12", "C", "Będę się czuć spokojny.", "Я буду чувствовать себя спокойно. (будущее время)", "Я почуватимусь спокійним. (майбутній час)", "I will feel calm. (future tense)", False, "wrong_sentence_type"), + ("a2_relationships_emotions_t12", "D", "Czułam się spokojna.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + + ("a2_relationships_emotions_t19", "A", "Byłem szczęśliwy, bo miałem dobrego przyjaciela, i czułem radość, kiedy z nim rozmawiałem.", "Я был счастлив, потому что у меня был хороший друг, и я чувствовал радость, когда с ним разговаривал. (прошедшее время)", "Я був щасливий, бо мав хорошого друга, і відчував радість, коли з ним розмовляв. (минулий час)", "I was happy because I had a good friend, and I felt joy when I talked with him. (past tense)", False, "wrong_sentence_type"), + ("a2_relationships_emotions_t19", "B", "Będę szczęśliwy, bo będę mieć dobrego przyjaciela, i będę czuć radość, kiedy z nim będę rozmawiać.", "Я буду счастлив, потому что у меня будет хороший друг, и я буду чувствовать радость, когда с ним буду разговаривать. (будущее время)", "Я буду щасливий, бо матиму хорошого друга, і відчуватиму радість, коли з ним розмовлятиму. (майбутній час)", "I will be happy because I will have a good friend, and I will feel joy when I talk with him. (future tense)", False, "wrong_sentence_type"), + ("a2_relationships_emotions_t19", "C", "Jestem szczęśliwy, bo mam dobrego przyjaciela, i czuję radość, kiedy z nim rozmawiam.", "Я счастлив, потому что у меня хороший друг, и я чувствую радость, когда с ним разговариваю.", "Я щасливий, бо маю хорошого друга, і відчуваю радість, коли з ним розмовляю.", "I am happy because I have a good friend, and I feel joy when I talk with him.", True, None), + ("a2_relationships_emotions_t19", "D", "Jestem smutny, bo mam dobrego przyjaciela, i czuję złość, kiedy z nim rozmawiam.", "Я грустен, потому что у меня хороший друг, и я чувствую злость, когда с ним разговариваю. (неверные эмоции)", "Я сумний, бо маю хорошого друга, і відчуваю злість, коли з ним розмовляю. (невірні емоції)", "I am sad because I have a good friend, and I feel anger when I talk with him. (wrong emotions)", False, "wrong_word"), + + ("a2_relationships_emotions_t20", "A", "— Dlaczego byłeś smutny? — Tęskniłem za rodziną i potrzebowałem wsparcia przyjaciół.", "— Почему ты был грустен? — Я скучал по семье и нуждался в поддержке друзей. (прошедшее время)", "— Чому ти був сумний? — Я сумував за родиною і потребував підтримки друзів. (минулий час)", "— Why were you sad? — I missed my family and needed my friends' support. (past tense)", False, "wrong_sentence_type"), + ("a2_relationships_emotions_t20", "B", "— Dlaczego jesteś szczęśliwy? — Tęsknię za rodziną i potrzebuję wsparcia przyjaciół.", "— Почему ты счастлив? — Я скучаю по семье и мне нужна поддержка друзей. (неверный вопрос)", "— Чому ти щасливий? — Я сумую за родиною і мені потрібна підтримка друзів. (невірне питання)", "— Why are you happy? — I miss my family and need my friends' support. (wrong question)", False, "wrong_word"), + ("a2_relationships_emotions_t20", "C", "— Dlaczego jesteś smutny? — Tęsknię za rodziną i potrzebuję wsparcia przyjaciół.", "— Почему ты грустишь? — Я скучаю по семье и мне нужна поддержка друзей.", "— Чому ти сумний? — Я сумую за родиною і мені потрібна підтримка друзів.", "— Why are you sad? — I miss my family and need my friends' support.", True, None), + ("a2_relationships_emotions_t20", "D", "— Dlaczego jesteś smutny? — Lubię swoją rodzinę i mam dobrych przyjaciół.", "— Почему ты грустишь? — Я люблю свою семью и у меня хорошие друзья. (не отвечает на вопрос)", "— Чому ти сумний? — Я люблю свою родину і маю хороших друзів. (не відповідає на питання)", "— Why are you sad? — I love my family and have good friends. (doesn't answer the question)", False, "wrong_context"), + ] + + for opt in test_options_t6_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 7 (A2): ОБРАЗОВАНИЕ И КУРСЫ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_education_courses', 'A2', 7, + 'Edukacja i kursy', + 'Образование и курсы', + 'Освіта і курси', + 'Education and Courses') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t7_a2 = [ + ("a2_education_courses_l01", 1, "edukacja_vocabulary", "Podstawowe słowa: edukacja", "Основные слова: образование", "Основні слова: освіта", "Basic words: education", + "Podstawowe słowa: szkoła, uniwersytet, kurs, egzamin.", + "Основные слова: szkoła (школа), uniwersytet (университет), kurs (курс), egzamin (экзамен).", + "Основні слова: szkoła (школа), uniwersytet (університет), kurs (курс), egzamin (іспит).", + "Basic words: szkoła (school), uniwersytet (university), kurs (course), egzamin (exam)."), + + ("a2_education_courses_l02", 2, "uczyc_sie_dopelniacz", "Uczyć się + dopełniacz", "Uczyć się + родительный падеж", "Uczyć się + родовий відмінок", "Uczyć się + genitive", + "Czasownik zwrotny „uczyć się” + dopełniacz języka lub przedmiotu: uczę się polskiego, uczysz się angielskiego, uczy się niemieckiego.", + "Возвратный глагол „uczyć się” (учиться) + родительный падеж языка или предмета: uczę się polskiego (я учу польский), uczysz się angielskiego (ты учишь английский), uczy się niemieckiego (он/она учит немецкий).", + "Зворотне дієслово „uczyć się” (вчитися) + родовий відмінок мови або предмета: uczę się polskiego (я вчу польську), uczysz się angielskiego (ти вчиш англійську), uczy się niemieckiego (він/вона вчить німецьку).", + "The reflexive verb „uczyć się” (to study/learn) + genitive of the language or subject: uczę się polskiego (I'm learning Polish), uczysz się angielskiego (you're learning English), uczy się niemieckiego (he/she is learning German)."), + + ("a2_education_courses_l03", 3, "chodzic_na_zajecia", "Chodzić na + biernik", "Chodzić na + винительный падеж", "Chodzić na + знахідний відмінок", "Chodzić na + accusative", + "Czasownik „chodzić” + „na” + biernik: chodzę na kurs, chodzisz na zajęcia, chodzi na wykład.", + "Глагол „chodzić” (ходить) + „na” + винительный падеж: chodzę na kurs (я хожу на курс), chodzisz na zajęcia (ты ходишь на занятия), chodzi na wykład (он/она ходит на лекцию).", + "Дієслово „chodzić” (ходити) + „na” + знахідний відмінок: chodzę na kurs (я ходжу на курс), chodzisz na zajęcia (ти ходиш на заняття), chodzi na wykład (він/вона ходить на лекцію).", + "The verb „chodzić” (to go regularly) + „na” + accusative: chodzę na kurs (I go to a course), chodzisz na zajęcia (you go to classes), chodzi na wykład (he/she goes to a lecture)."), + + ("a2_education_courses_l04", 4, "przedmioty_vocabulary", "Podstawowe słowa: przedmioty szkolne", "Основные слова: школьные предметы", "Основні слова: шкільні предмети", "Basic words: school subjects", + "Podstawowe nazwy przedmiotów: matematyka, historia, biologia, informatyka.", + "Основные названия предметов: matematyka (математика), historia (история), biologia (биология), informatyka (информатика).", + "Основні назви предметів: matematyka (математика), historia (історія), biologia (біологія), informatyka (інформатика).", + "Basic subject names: matematyka (math), historia (history), biologia (biology), informatyka (computer science)."), + + ("a2_education_courses_l05", 5, "umiec_bezokolicznik", "Umieć + bezokolicznik", "Umieć + инфинитив", "Umieć + інфінітив", "Umieć + infinitive", + "Czasownik „umieć” + bezokolicznik wyraża umiejętność: umiem czytać po polsku, umiesz pisać, umie liczyć.", + "Глагол „umieć” (уметь) + инфинитив выражает навык: umiem czytać po polsku (я умею читать по-польски), umiesz pisać (ты умеешь писать), umie liczyć (он/она умеет считать).", + "Дієслово „umieć” (уміти) + інфінітив виражає навичку: umiem czytać po polsku (я вмію читати польською), umiesz pisać (ти вмієш писати), umie liczyć (він/вона вміє рахувати).", + "The verb „umieć” (to know how to) + infinitive expresses a skill: umiem czytać po polsku (I know how to read in Polish), umiesz pisać (you know how to write), umie liczyć (he/she knows how to count)."), + + ("a2_education_courses_l06", 6, "zdawac_egzamin", "Zdawać / zdać egzamin", "Zdawać / zdać egzamin", "Zdawać / zdać egzamin", "Zdawać / zdać egzamin", + "Czasownik „zdawać” (proces) i „zdać” (dokonany, sukces) + biernik: zdaję egzamin (jestem w trakcie), zdałem egzamin (zdałem pomyślnie).", + "Глагол „zdawać” (процесс — сдавать экзамен) и „zdać” (совершенный вид — успешно сдать) + винительный падеж: zdaję egzamin (я сдаю экзамен, процесс), zdałem egzamin (я сдал экзамен, успешно).", + "Дієслово „zdawać” (процес — складати іспит) і „zdać” (доконаний вид — успішно скласти) + знахідний відмінок: zdaję egzamin (я складаю іспит, процес), zdałem egzamin (я склав іспит, успішно).", + "The verb „zdawać” (imperfective — to take an exam) and „zdać” (perfective — to pass) + accusative: zdaję egzamin (I'm taking the exam, in progress), zdałem egzamin (I passed the exam, successfully)."), + + ("a2_education_courses_l07", 7, "poziomy_jezykowe_vocabulary", "Podstawowe słowa: poziomy językowe", "Основные слова: языковые уровни", "Основні слова: мовні рівні", "Basic words: language levels", + "Podstawowe słowa opisujące poziom: podstawowy, średni, zaawansowany, biegły.", + "Основные слова, описывающие уровень: podstawowy (базовый), średni (средний), zaawansowany (продвинутый), biegły (свободный).", + "Основні слова, що описують рівень: podstawowy (базовий), średni (середній), zaawansowany (просунутий), biegły (вільний).", + "Basic words describing level: podstawowy (basic), średni (intermediate), zaawansowany (advanced), biegły (fluent)."), + + ("a2_education_courses_l08", 8, "zapisac_sie_na_kurs", "Zapisać się na + biernik", "Zapisać się na + винительный падеж", "Zapisać się na + знахідний відмінок", "Zapisać się na + accusative", + "Czasownik zwrotny „zapisać się” + „na” + biernik: zapisuję się na kurs, zapisujesz się na zajęcia.", + "Возвратный глагол „zapisać się” (записаться) + „na” + винительный падеж: zapisuję się na kurs (я записываюсь на курс), zapisujesz się na zajęcia (ты записываешься на занятия).", + "Зворотне дієслово „zapisać się” (записатися) + „na” + знахідний відмінок: zapisuję się na kurs (я записуюся на курс), zapisujesz się na zajęcia (ти записуєшся на заняття).", + "The reflexive verb „zapisać się” (to sign up) + „na” + accusative: zapisuję się na kurs (I'm signing up for a course), zapisujesz się na zajęcia (you're signing up for classes)."), + + ("a2_education_courses_l09", 9, "przeszly_czas_nauka", "Nauczyłem/nauczyłam się + dopełniacz (przeszłość)", "Nauczyłem/nauczyłam się + родительный падеж (прошедшее)", "Nauczyłem/nauczyłam się + родовий відмінок (минулий час)", "Nauczyłem/nauczyłam się + genitive (past)", + "Czas przeszły nauki tworzymy „nauczyłem się” (mężczyzna) lub „nauczyłam się” (kobieta) + dopełniacz: nauczyłem się polskiego, nauczyłam się gotować.", + "Прошедшее время обучения образуем „nauczyłem się” (мужчина) или „nauczyłam się” (женщина) + родительный падеж или инфинитив: nauczyłem się polskiego (я выучил польский), nauczyłam się gotować (я научилась готовить).", + "Минулий час навчання утворюємо „nauczyłem się” (чоловік) або „nauczyłam się” (жінка) + родовий відмінок або інфінітив: nauczyłem się polskiego (я вивчив польську), nauczyłam się gotować (я навчилася готувати).", + "We form the past tense of learning with „nauczyłem się” (male speaker) or „nauczyłam się” (female speaker) + genitive or infinitive: nauczyłem się polskiego (I learned Polish), nauczyłam się gotować (I learned to cook)."), + + ("a2_education_courses_l10", 10, "opisuje_swoja_nauke", "Opisuję swoją naukę", "Описываю своё обучение", "Описую своє навчання", "Describing my learning", + "Żeby opisać naukę, łączymy zdania: Uczę się polskiego. Chodzę na kurs raz w tygodniu. Zdałem egzamin. Nauczyłem się już dużo słów.", + "Чтобы описать обучение, соединяем предложения: Uczę się polskiego. Chodzę na kurs raz w tygodniu. Zdałem egzamin. Nauczyłem się już dużo słów. (Я учу польский. Я хожу на курс раз в неделю. Я сдал экзамен. Я уже выучил много слов.)", + "Щоб описати навчання, поєднуємо речення: Uczę się polskiego. Chodzę na kurs raz w tygodniu. Zdałem egzamin. Nauczyłem się już dużo słów. (Я вчу польську. Я ходжу на курс раз на тиждень. Я склав іспит. Я вже вивчив багато слів.)", + "To describe your learning, we combine sentences: Uczę się polskiego. Chodzę na kurs raz w tygodniu. Zdałem egzamin. Nauczyłem się już dużo słów. (I'm learning Polish. I go to a course once a week. I passed the exam. I've already learned a lot of words.)"), + ] + + for lesson in lessons_t7_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_education_courses', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t7_a2 = [ + ("a2_education_courses_l01", 1, "Idę do szkoły.", "Я иду в школу.", "Я йду в школу.", "I'm going to school."), + ("a2_education_courses_l01", 2, "Studiuję na uniwersytecie.", "Я учусь в университете.", "Я навчаюся в університеті.", "I study at university."), + ("a2_education_courses_l01", 3, "Mam egzamin jutro.", "У меня завтра экзамен.", "У мене завтра іспит.", "I have an exam tomorrow."), + + ("a2_education_courses_l02", 1, "Uczę się polskiego.", "Я учу польский.", "Я вчу польську.", "I'm learning Polish."), + ("a2_education_courses_l02", 2, "Uczysz się angielskiego?", "Ты учишь английский?", "Ти вчиш англійську?", "Are you learning English?"), + ("a2_education_courses_l02", 3, "Ona uczy się niemieckiego.", "Она учит немецкий.", "Вона вчить німецьку.", "She's learning German."), + + ("a2_education_courses_l03", 1, "Chodzę na kurs polskiego.", "Я хожу на курс польского.", "Я ходжу на курс польської.", "I go to a Polish course."), + ("a2_education_courses_l03", 2, "Chodzisz na zajęcia w piątki?", "Ты ходишь на занятия по пятницам?", "Ти ходиш на заняття по п'ятницях?", "Do you go to classes on Fridays?"), + ("a2_education_courses_l03", 3, "On chodzi na wykład o historii.", "Он ходит на лекцию по истории.", "Він ходить на лекцію з історії.", "He goes to a history lecture."), + + ("a2_education_courses_l04", 1, "Lubię matematykę.", "Я люблю математику.", "Я люблю математику.", "I like math."), + ("a2_education_courses_l04", 2, "Mam dziś historię.", "У меня сегодня история.", "У мене сьогодні історія.", "I have history today."), + ("a2_education_courses_l04", 3, "Studiuję informatykę.", "Я изучаю информатику.", "Я вивчаю інформатику.", "I'm studying computer science."), + + ("a2_education_courses_l05", 1, "Umiem czytać po polsku.", "Я умею читать по-польски.", "Я вмію читати польською.", "I know how to read in Polish."), + ("a2_education_courses_l05", 2, "Umiesz pisać po angielsku?", "Ты умеешь писать по-английски?", "Ти вмієш писати англійською?", "Do you know how to write in English?"), + ("a2_education_courses_l05", 3, "Ona umie dobrze liczyć.", "Она умеет хорошо считать.", "Вона вміє добре рахувати.", "She knows how to count well."), + + ("a2_education_courses_l06", 1, "Zdaję egzamin z polskiego.", "Я сдаю экзамен по польскому.", "Я складаю іспит з польської.", "I'm taking a Polish exam."), + ("a2_education_courses_l06", 2, "Zdałeś egzamin?", "Ты сдал экзамен?", "Ти склав іспит?", "Did you pass the exam?"), + ("a2_education_courses_l06", 3, "Ona zdała egzamin bardzo dobrze.", "Она сдала экзамен очень хорошо.", "Вона склала іспит дуже добре.", "She passed the exam very well."), + + ("a2_education_courses_l07", 1, "Mam podstawowy poziom angielskiego.", "У меня базовый уровень английского.", "У мене базовий рівень англійської.", "I have a basic level of English."), + ("a2_education_courses_l07", 2, "Ona mówi po niemiecku na poziomie średnim.", "Она говорит по-немецки на среднем уровне.", "Вона розмовляє німецькою на середньому рівні.", "She speaks German at an intermediate level."), + ("a2_education_courses_l07", 3, "On jest biegły w hiszpańskim.", "Он свободно владеет испанским.", "Він вільно володіє іспанською.", "He is fluent in Spanish."), + + ("a2_education_courses_l08", 1, "Zapisuję się na kurs polskiego.", "Я записываюсь на курс польского.", "Я записуюся на курс польської.", "I'm signing up for a Polish course."), + ("a2_education_courses_l08", 2, "Zapisujesz się na te zajęcia?", "Ты записываешься на эти занятия?", "Ти записуєшся на ці заняття?", "Are you signing up for these classes?"), + ("a2_education_courses_l08", 3, "On zapisał się na kurs programowania.", "Он записался на курс программирования.", "Він записався на курс програмування.", "He signed up for a programming course."), + + ("a2_education_courses_l09", 1, "Nauczyłem się polskiego.", "Я выучил польский.", "Я вивчив польську.", "I learned Polish."), + ("a2_education_courses_l09", 2, "Nauczyłaś się gotować?", "Ты научилась готовить?", "Ти навчилася готувати?", "Did you learn to cook?"), + ("a2_education_courses_l09", 3, "Nauczył się programować sam.", "Он научился программировать сам.", "Він навчився програмувати сам.", "He taught himself to program."), + + ("a2_education_courses_l10", 1, "Uczę się polskiego.", "Я учу польский.", "Я вчу польську.", "I'm learning Polish."), + ("a2_education_courses_l10", 2, "Chodzę na kurs raz w tygodniu.", "Я хожу на курс раз в неделю.", "Я ходжу на курс раз на тиждень.", "I go to a course once a week."), + ("a2_education_courses_l10", 3, "Nauczyłem się już dużo słów.", "Я уже выучил много слов.", "Я вже вивчив багато слів.", "I've already learned a lot of words."), + ] + + for ex in examples_t7_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t7_a2 = [ + # L01 — edukacja_vocabulary (difficulty 1) + ("a2_education_courses_l01_q1", "a2_education_courses_l01", "lesson_practice", "recognition", "edukacja_vocabulary", 1, + "Jak po polsku „экзамен”?", "Как по-польски «экзамен»?", "Як польською «іспит»?", "How do you say “exam” in Polish?", + "D", None, None), + ("a2_education_courses_l01_q2", "a2_education_courses_l01", "lesson_practice", "production", "edukacja_vocabulary", 1, + "Wpisz brakujące słowo: Studiuję na ___. (университете)", "Вставьте пропущенное слово: Studiuję na ___. (университете)", "Вставте пропущене слово: Studiuję na ___. (університеті)", "Fill in the missing word: Studiuję na ___. (university)", + "uniwersytecie", "first_letter", "u"), + ("a2_education_courses_l01_q3", "a2_education_courses_l01", "lesson_practice", "application", "edukacja_vocabulary", 1, + "Zapisałeś się na krótkie zajęcia z gotowania. Co to jest?", "Ты записался на короткие занятия по кулинарии. Что это?", "Ти записався на короткі заняття з кулінарії. Що це?", "You signed up for short cooking classes. What is this?", + "C", None, None), + + # L02 — uczyc_sie_dopelniacz (difficulty 1) + ("a2_education_courses_l02_q1", "a2_education_courses_l02", "lesson_practice", "recognition", "uczyc_sie_dopelniacz", 1, + "Wybierz poprawną formę: Uczę się ___. (polski)", "Выберите правильную форму: Uczę się ___. (polski)", "Виберіть правильну форму: Uczę się ___. (polski)", "Choose the correct form: Uczę się ___. (polski)", + "A", None, None), + ("a2_education_courses_l02_q2", "a2_education_courses_l02", "lesson_practice", "production", "uczyc_sie_dopelniacz", 1, + "Wpisz brakujące słowo: Uczysz się ___? (английского)", "Вставьте пропущенное слово: Uczysz się ___? (английского)", "Вставте пропущене слово: Uczysz się ___? (англійської)", "Fill in the missing word: Uczysz się ___? (English)", + "angielskiego", "first_letter", "a"), + ("a2_education_courses_l02_q3", "a2_education_courses_l02", "lesson_practice", "application", "uczyc_sie_dopelniacz", 1, + "Kolega pyta, jakiego języka się uczysz. Uczysz się niemieckiego. Co powiesz?", "Друг спрашивает, какой язык ты учишь. Ты учишь немецкий. Что ты скажешь?", "Друг питає, яку мову ти вчиш. Ти вчиш німецьку. Що ти скажеш?", "A friend asks what language you're learning. You're learning German. What do you say?", + "C", None, None), + + # L03 — chodzic_na_zajecia (difficulty 1) + ("a2_education_courses_l03_q1", "a2_education_courses_l03", "lesson_practice", "recognition", "chodzic_na_zajecia", 1, + "Wybierz poprawną formę: Chodzę ___ kurs. (na)", "Выберите правильную форму: Chodzę ___ kurs. (na)", "Виберіть правильну форму: Chodzę ___ kurs. (na)", "Choose the correct form: Chodzę ___ kurs. (na)", + "A", None, None), + ("a2_education_courses_l03_q2", "a2_education_courses_l03", "lesson_practice", "production", "chodzic_na_zajecia", 1, + "Wpisz brakujące słowo: Chodzisz na ___? (занятия)", "Вставьте пропущенное слово: Chodzisz na ___? (занятия)", "Вставте пропущене слово: Chodzisz na ___? (заняття)", "Fill in the missing word: Chodzisz na ___? (classes)", + "zajęcia", "first_letter", "z"), + ("a2_education_courses_l03_q3", "a2_education_courses_l03", "lesson_practice", "application", "chodzic_na_zajecia", 1, + "Regularnie uczestniczysz w kursie polskiego raz w tygodniu. Co powiesz?", "Ты регулярно посещаешь курс польского раз в неделю. Что ты скажешь?", "Ти регулярно відвідуєш курс польської раз на тиждень. Що ти скажеш?", "You regularly attend a Polish course once a week. What do you say?", + "A", None, None), + + # L04 — przedmioty_vocabulary (difficulty 1) + ("a2_education_courses_l04_q1", "a2_education_courses_l04", "lesson_practice", "recognition", "przedmioty_vocabulary", 1, + "Jak po polsku „биология”?", "Как по-польски «биология»?", "Як польською «біологія»?", "How do you say “biology” in Polish?", + "C", None, None), + ("a2_education_courses_l04_q2", "a2_education_courses_l04", "lesson_practice", "production", "przedmioty_vocabulary", 1, + "Wpisz brakujące słowo: Studiuję ___. (информатику)", "Вставьте пропущенное слово: Studiuję ___. (информатику)", "Вставте пропущене слово: Studiuję ___. (інформатику)", "Fill in the missing word: Studiuję ___. (computer science)", + "informatykę", "first_letter", "i"), + ("a2_education_courses_l04_q3", "a2_education_courses_l04", "lesson_practice", "application", "przedmioty_vocabulary", 1, + "Interesujesz się komputerami i programowaniem. Co studiujesz?", "Ты интересуешься компьютерами и программированием. Что ты изучаешь?", "Ти цікавишся комп'ютерами і програмуванням. Що ти вивчаєш?", "You're interested in computers and programming. What are you studying?", + "D", None, None), + + # L05 — umiec_bezokolicznik (difficulty 2) + ("a2_education_courses_l05_q1", "a2_education_courses_l05", "lesson_practice", "recognition", "umiec_bezokolicznik", 2, + "Wybierz poprawną formę: ___ czytać po polsku. (umieć, ja)", "Выберите правильную форму: ___ czytać po polsku. (umieć, ja)", "Виберіть правильну форму: ___ czytać po polsku. (umieć, ja)", "Choose the correct form: ___ czytać po polsku. (umieć, I)", + "A", None, None), + ("a2_education_courses_l05_q2", "a2_education_courses_l05", "lesson_practice", "production", "umiec_bezokolicznik", 2, + "Wpisz brakujące słowo: ___ pisać po angielsku? (ты умеешь)", "Вставьте пропущенное слово: ___ pisać po angielsku? (ты умеешь)", "Вставте пропущене слово: ___ pisać po angielsku? (ти вмієш)", "Fill in the missing word: ___ pisać po angielsku? (do you know how to)", + "Umiesz", "first_letter", "U"), + ("a2_education_courses_l05_q3", "a2_education_courses_l05", "lesson_practice", "application", "umiec_bezokolicznik", 2, + "Nauczyłeś się już czytać teksty po polsku. Co powiesz?", "Ты уже научился читать тексты по-польски. Что ты скажешь?", "Ти вже навчився читати тексти польською. Що ти скажеш?", "You've already learned to read texts in Polish. What do you say?", + "A", None, None), + + # L06 — zdawac_egzamin (difficulty 2) + ("a2_education_courses_l06_q1", "a2_education_courses_l06", "lesson_practice", "recognition", "zdawac_egzamin", 2, + "Co znaczy „Zdałem egzamin”?", "Что означает «Zdałem egzamin»?", "Що означає «Zdałem egzamin»?", "What does “Zdałem egzamin” mean?", + "D", None, None), + ("a2_education_courses_l06_q2", "a2_education_courses_l06", "lesson_practice", "production", "zdawac_egzamin", 2, + "Wpisz brakujące słowo: ___ egzamin z polskiego. (я сдаю, процесс)", "Вставьте пропущенное слово: ___ egzamin z polskiego. (я сдаю, процесс)", "Вставте пропущене слово: ___ egzamin z polskiego. (я складаю, процес)", "Fill in the missing word: ___ egzamin z polskiego. (I'm taking, in progress)", + "Zdaję", "first_letter", "Z"), + ("a2_education_courses_l06_q3", "a2_education_courses_l06", "lesson_practice", "application", "zdawac_egzamin", 2, + "Właśnie skończyłeś egzamin i wiesz, że zdałeś go pomyślnie. Co powiesz?", "Ты только что закончил экзамен и знаешь, что сдал его успешно. Что ты скажешь?", "Ти щойно закінчив іспит і знаєш, що склав його успішно. Що ти скажеш?", "You just finished the exam and know you passed it successfully. What do you say?", + "B", None, None), + + # L07 — poziomy_jezykowe_vocabulary (difficulty 2) + ("a2_education_courses_l07_q1", "a2_education_courses_l07", "lesson_practice", "recognition", "poziomy_jezykowe_vocabulary", 2, + "Jak po polsku „продвинутый”?", "Как по-польски «продвинутый»?", "Як польською «просунутий»?", "How do you say “advanced” in Polish?", + "C", None, None), + ("a2_education_courses_l07_q2", "a2_education_courses_l07", "lesson_practice", "production", "poziomy_jezykowe_vocabulary", 2, + "Wpisz brakujące słowo: On jest ___ w hiszpańskim. (свободно владеющий)", "Вставьте пропущенное слово: On jest ___ w hiszpańskim. (свободно владеющий)", "Вставте пропущене слово: On jest ___ w hiszpańskim. (вільно володіючий)", "Fill in the missing word: On jest ___ w hiszpańskim. (fluent)", + "biegły", "first_letter", "b"), + ("a2_education_courses_l07_q3", "a2_education_courses_l07", "lesson_practice", "application", "poziomy_jezykowe_vocabulary", 2, + "Znasz tylko podstawowe słowa i proste zdania w danym języku. Jaki masz poziom?", "Ты знаешь только базовые слова и простые предложения на этом языке. Какой у тебя уровень?", "Ти знаєш лише базові слова і прості речення цією мовою. Який у тебе рівень?", "You only know basic words and simple sentences in that language. What level do you have?", + "A", None, None), + + # L08 — zapisac_sie_na_kurs (difficulty 2) + ("a2_education_courses_l08_q1", "a2_education_courses_l08", "lesson_practice", "recognition", "zapisac_sie_na_kurs", 2, + "Wybierz poprawną formę: Zapisuję się ___ kurs. (na)", "Выберите правильную форму: Zapisuję się ___ kurs. (na)", "Виберіть правильну форму: Zapisuję się ___ kurs. (na)", "Choose the correct form: Zapisuję się ___ kurs. (na)", + "A", None, None), + ("a2_education_courses_l08_q2", "a2_education_courses_l08", "lesson_practice", "production", "zapisac_sie_na_kurs", 2, + "Wpisz brakujące słowo: Zapisujesz się na ___? (занятия)", "Вставьте пропущенное слово: Zapisujesz się na ___? (занятия)", "Вставте пропущене слово: Zapisujesz się na ___? (заняття)", "Fill in the missing word: Zapisujesz się na ___? (classes)", + "zajęcia", "first_letter", "z"), + ("a2_education_courses_l08_q3", "a2_education_courses_l08", "lesson_practice", "application", "zapisac_sie_na_kurs", 2, + "Chcesz zacząć uczyć się programowania i znalazłeś odpowiedni kurs. Co powiesz?", "Ты хочешь начать изучать программирование и нашёл подходящий курс. Что ты скажешь?", "Ти хочеш почати вивчати програмування і знайшов відповідний курс. Що ти скажеш?", "You want to start learning programming and found a suitable course. What do you say?", + "A", None, None), + + # L09 — przeszly_czas_nauka (difficulty 3) + ("a2_education_courses_l09_q1", "a2_education_courses_l09", "lesson_practice", "recognition", "przeszly_czas_nauka", 3, + "Co znaczy „Nauczyłem się polskiego”?", "Что означает «Nauczyłem się polskiego»?", "Що означає «Nauczyłem się polskiego»?", "What does “Nauczyłem się polskiego” mean?", + "D", None, None), + ("a2_education_courses_l09_q2", "a2_education_courses_l09", "lesson_practice", "production", "przeszly_czas_nauka", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ się gotować. (я научилась)", "Вставьте пропущенное слово (говорит женщина): ___ się gotować. (я научилась)", "Вставте пропущене слово (говорить жінка): ___ się gotować. (я навчилася)", "Fill in the missing word (a woman is speaking): ___ się gotować. (I learned)", + "Nauczyłam", "first_letter", "N"), + ("a2_education_courses_l09_q3", "a2_education_courses_l09", "lesson_practice", "application", "przeszly_czas_nauka", 3, + "Mężczyzna opowiada, że w zeszłym roku sam nauczył się programować. Co powie?", "Мужчина рассказывает, что в прошлом году сам научился программировать. Что он скажет?", "Чоловік розповідає, що минулого року сам навчився програмувати. Що він скаже?", "A man is telling that last year he taught himself to program. What does he say?", + "B", None, None), + + # L10 — opisuje_swoja_nauke (difficulty 3) + ("a2_education_courses_l10_q1", "a2_education_courses_l10", "lesson_practice", "recognition", "opisuje_swoja_nauke", 3, + "Które zdanie poprawnie opisuje naukę?", "Какое предложение правильно описывает обучение?", "Яке речення правильно описує навчання?", "Which sentence correctly describes learning?", + "D", None, None), + ("a2_education_courses_l10_q2", "a2_education_courses_l10", "lesson_practice", "production", "opisuje_swoja_nauke", 3, + "Przetłumacz: «Я сдал экзамен».", "Переведите: «Я сдал экзамен».", "Перекладіть: «Я склав іспит».", "Translate: “I passed the exam.”", + "Zdałem egzamin", "first_letter", "Z"), + ("a2_education_courses_l10_q3", "a2_education_courses_l10", "lesson_practice", "application", "opisuje_swoja_nauke", 3, + "Chcesz opisać koledze swoją naukę: uczysz się polskiego, chodzisz na kurs, zdałeś egzamin. Jak zaczniesz zdanie?", "Ты хочешь описать другу своё обучение: ты учишь польский, ходишь на курс, сдал экзамен. Как ты начнёшь предложение?", "Ти хочеш описати другу своє навчання: ти вчиш польську, ходиш на курс, склав іспит. Як ти почнеш речення?", "You want to describe your learning to a friend: you're learning Polish, you go to a course, you passed the exam. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t7_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_education_courses', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t7_a2 = [ + # L01 + ("a2_education_courses_l01_q1", "A", "szkoła", "школа", "школа", "school", False, "wrong_word"), + ("a2_education_courses_l01_q1", "B", "uniwersytet", "университет", "університет", "university", False, "wrong_word"), + ("a2_education_courses_l01_q1", "C", "kurs", "курс", "курс", "course", False, "wrong_word"), + ("a2_education_courses_l01_q1", "D", "egzamin", "экзамен", "іспит", "exam", True, None), + + ("a2_education_courses_l01_q3", "A", "szkoła", "школа", "школа", "school", False, "wrong_context"), + ("a2_education_courses_l01_q3", "B", "uniwersytet", "университет", "університет", "university", False, "wrong_context"), + ("a2_education_courses_l01_q3", "C", "kurs", "курс", "курс", "course", True, None), + ("a2_education_courses_l01_q3", "D", "egzamin", "экзамен", "іспит", "exam", False, "wrong_context"), + + # L02 + ("a2_education_courses_l02_q1", "A", "polskiego", "польского (род.)", "польської (род.)", "Polish (gen.)", True, None), + ("a2_education_courses_l02_q1", "B", "polski", "польский (им./вин.)", "польська (наз./знах.)", "Polish (nom./acc.)", False, "wrong_case"), + ("a2_education_courses_l02_q1", "C", "polskiemu", "польскому (дат.)", "польській (дав.)", "Polish (dat.)", False, "wrong_case"), + ("a2_education_courses_l02_q1", "D", "polskim", "польским (тв./местн.)", "польською (ор./місц.)", "Polish (instr./loc.)", False, "wrong_case"), + + ("a2_education_courses_l02_q3", "A", "Uczę się polskiego.", "Я учу польский. (не соответствует ситуации)", "Я вчу польську. (не відповідає ситуації)", "I'm learning Polish. (doesn't match the situation)", False, "wrong_context"), + ("a2_education_courses_l02_q3", "B", "Uczę się angielskiego.", "Я учу английский. (не соответствует ситуации)", "Я вчу англійську. (не відповідає ситуації)", "I'm learning English. (doesn't match the situation)", False, "wrong_context"), + ("a2_education_courses_l02_q3", "C", "Uczę się niemieckiego.", "Я учу немецкий.", "Я вчу німецьку.", "I'm learning German.", True, None), + ("a2_education_courses_l02_q3", "D", "Znam niemiecki.", "Я знаю немецкий. (не о процессе изучения)", "Я знаю німецьку. (не про процес вивчення)", "I know German. (not about the learning process)", False, "wrong_context"), + + # L03 + ("a2_education_courses_l03_q1", "A", "na", "на", "на", "to", True, None), + ("a2_education_courses_l03_q1", "B", "do", "в/к", "в/до", "to", False, "wrong_word"), + ("a2_education_courses_l03_q1", "C", "w", "в", "в", "in", False, "wrong_word"), + ("a2_education_courses_l03_q1", "D", "u", "у", "у", "at", False, "wrong_word"), + + ("a2_education_courses_l03_q3", "A", "Chodzę na kurs polskiego.", "Я хожу на курс польского.", "Я ходжу на курс польської.", "I go to a Polish course.", True, None), + ("a2_education_courses_l03_q3", "B", "Idę do szkoły.", "Я иду в школу. (не о регулярности)", "Я йду в школу. (не про регулярність)", "I'm going to school. (not about regularity)", False, "wrong_context"), + ("a2_education_courses_l03_q3", "C", "Mam egzamin.", "У меня экзамен. (не соответствует ситуации)", "У мене іспит. (не відповідає ситуації)", "I have an exam. (doesn't match the situation)", False, "wrong_context"), + ("a2_education_courses_l03_q3", "D", "Uczę się w domu.", "Я учусь дома. (не о курсе)", "Я вчуся вдома. (не про курс)", "I study at home. (not about the course)", False, "wrong_context"), + + # L04 + ("a2_education_courses_l04_q1", "A", "matematyka", "математика", "математика", "math", False, "wrong_word"), + ("a2_education_courses_l04_q1", "B", "historia", "история", "історія", "history", False, "wrong_word"), + ("a2_education_courses_l04_q1", "C", "biologia", "биология", "біологія", "biology", True, None), + ("a2_education_courses_l04_q1", "D", "informatyka", "информатика", "інформатика", "computer science", False, "wrong_word"), + + ("a2_education_courses_l04_q3", "A", "matematykę", "математику", "математику", "math", False, "wrong_context"), + ("a2_education_courses_l04_q3", "B", "historię", "историю", "історію", "history", False, "wrong_context"), + ("a2_education_courses_l04_q3", "C", "biologię", "биологию", "біологію", "biology", False, "wrong_context"), + ("a2_education_courses_l04_q3", "D", "informatykę", "информатику", "інформатику", "computer science", True, None), + + # L05 + ("a2_education_courses_l05_q1", "A", "Umiem", "я умею", "я вмію", "I know how to", True, None), + ("a2_education_courses_l05_q1", "B", "Umiesz", "ты умеешь (не тот человек)", "ти вмієш (не та особа)", "you know how to (wrong person)", False, "wrong_context"), + ("a2_education_courses_l05_q1", "C", "Umie", "он/она умеет (не тот человек)", "він/вона вміє (не та особа)", "he/she knows how to (wrong person)", False, "wrong_context"), + ("a2_education_courses_l05_q1", "D", "Umieli", "они умели (неправильное число и время)", "вони вміли (неправильне число і час)", "they knew how to (wrong number and tense)", False, "wrong_number"), + + ("a2_education_courses_l05_q3", "A", "Umiem czytać po polsku.", "Я умею читать по-польски.", "Я вмію читати польською.", "I know how to read in Polish.", True, None), + ("a2_education_courses_l05_q3", "B", "Uczę się polskiego.", "Я учу польский. (не о готовом навыке)", "Я вчу польську. (не про готову навичку)", "I'm learning Polish. (not about an achieved skill)", False, "wrong_context"), + ("a2_education_courses_l05_q3", "C", "Chcę czytać po polsku.", "Я хочу читать по-польски. (не о готовом навыке)", "Я хочу читати польською. (не про готову навичку)", "I want to read in Polish. (not about an achieved skill)", False, "wrong_context"), + ("a2_education_courses_l05_q3", "D", "Lubię czytać po polsku.", "Я люблю читать по-польски. (не о навыке)", "Я люблю читати польською. (не про навичку)", "I like reading in Polish. (not about a skill)", False, "wrong_context"), + + # L06 + ("a2_education_courses_l06_q1", "A", "Zdaję egzamin.", "Я сдаю экзамен (процесс).", "Я складаю іспит (процес).", "I'm taking the exam (in progress).", False, "wrong_translation"), + ("a2_education_courses_l06_q1", "B", "Piszę egzamin.", "Я пишу экзамен.", "Я пишу іспит.", "I'm writing the exam.", False, "wrong_translation"), + ("a2_education_courses_l06_q1", "C", "Będę zdawać egzamin.", "Я буду сдавать экзамен.", "Я буду складати іспит.", "I will take the exam.", False, "wrong_translation"), + ("a2_education_courses_l06_q1", "D", "Zdałem egzamin.", "Я сдал экзамен (успешно).", "Я склав іспит (успішно).", "I passed the exam.", True, None), + + ("a2_education_courses_l06_q3", "A", "Zdaję egzamin.", "Я сдаю экзамен. (процесс, а не результат)", "Я складаю іспит. (процес, а не результат)", "I'm taking the exam. (process, not result)", False, "wrong_sentence_type"), + ("a2_education_courses_l06_q3", "B", "Zdałem egzamin.", "Я сдал экзамен.", "Я склав іспит.", "I passed the exam.", True, None), + ("a2_education_courses_l06_q3", "C", "Będę zdawać egzamin.", "Я буду сдавать экзамен. (будущее время)", "Я буду складати іспит. (майбутній час)", "I will take the exam. (future tense)", False, "wrong_sentence_type"), + ("a2_education_courses_l06_q3", "D", "Uczę się do egzaminu.", "Я готовлюсь к экзамену. (не о результате)", "Я готуюся до іспиту. (не про результат)", "I'm studying for the exam. (not about the result)", False, "wrong_context"), + + # L07 + ("a2_education_courses_l07_q1", "A", "podstawowy", "базовый", "базовий", "basic", False, "wrong_word"), + ("a2_education_courses_l07_q1", "B", "średni", "средний", "середній", "intermediate", False, "wrong_word"), + ("a2_education_courses_l07_q1", "C", "zaawansowany", "продвинутый", "просунутий", "advanced", True, None), + ("a2_education_courses_l07_q1", "D", "biegły", "свободный", "вільний", "fluent", False, "wrong_word"), + + ("a2_education_courses_l07_q3", "A", "podstawowy", "базовый", "базовий", "basic", True, None), + ("a2_education_courses_l07_q3", "B", "średni", "средний", "середній", "intermediate", False, "wrong_context"), + ("a2_education_courses_l07_q3", "C", "zaawansowany", "продвинутый", "просунутий", "advanced", False, "wrong_context"), + ("a2_education_courses_l07_q3", "D", "biegły", "свободный", "вільний", "fluent", False, "wrong_context"), + + # L08 + ("a2_education_courses_l08_q1", "A", "na", "на", "на", "for", True, None), + ("a2_education_courses_l08_q1", "B", "do", "в/к", "в/до", "to", False, "wrong_word"), + ("a2_education_courses_l08_q1", "C", "w", "в", "в", "in", False, "wrong_word"), + ("a2_education_courses_l08_q1", "D", "u", "у", "у", "at", False, "wrong_word"), + + ("a2_education_courses_l08_q3", "A", "Zapisuję się na kurs programowania.", "Я записываюсь на курс программирования.", "Я записуюся на курс програмування.", "I'm signing up for a programming course.", True, None), + ("a2_education_courses_l08_q3", "B", "Uczę się programowania.", "Я учу программирование. (не о записи)", "Я вчу програмування. (не про запис)", "I'm learning programming. (not about signing up)", False, "wrong_context"), + ("a2_education_courses_l08_q3", "C", "Zdaję egzamin z programowania.", "Я сдаю экзамен по программированию. (не о записи)", "Я складаю іспит з програмування. (не про запис)", "I'm taking a programming exam. (not about signing up)", False, "wrong_context"), + ("a2_education_courses_l08_q3", "D", "Chodzę na wykład o programowaniu.", "Я хожу на лекцию о программировании. (не о записи)", "Я ходжу на лекцію про програмування. (не про запис)", "I go to a programming lecture. (not about signing up)", False, "wrong_context"), + + # L09 + ("a2_education_courses_l09_q1", "A", "Uczę się polskiego.", "Я учу польский (сейчас).", "Я вчу польську (зараз).", "I'm learning Polish (now).", False, "wrong_translation"), + ("a2_education_courses_l09_q1", "B", "Będę się uczyć polskiego.", "Я буду учить польский.", "Я буду вчити польську.", "I will learn Polish.", False, "wrong_translation"), + ("a2_education_courses_l09_q1", "C", "Chcę nauczyć się polskiego.", "Я хочу выучить польский.", "Я хочу вивчити польську.", "I want to learn Polish.", False, "wrong_translation"), + ("a2_education_courses_l09_q1", "D", "Nauczyłem się polskiego.", "Я выучил польский.", "Я вивчив польську.", "I learned Polish.", True, None), + + ("a2_education_courses_l09_q3", "A", "Uczę się programować.", "Я учусь программировать. (настоящее время)", "Я вчуся програмувати. (теперішній час)", "I'm learning to program. (present tense)", False, "wrong_sentence_type"), + ("a2_education_courses_l09_q3", "B", "Nauczyłem się programować.", "Я научился программировать.", "Я навчився програмувати.", "I taught myself to program.", True, None), + ("a2_education_courses_l09_q3", "C", "Będę się uczyć programować.", "Я буду учиться программировать. (будущее время)", "Я вчитимусь програмувати. (майбутній час)", "I will learn to program. (future tense)", False, "wrong_sentence_type"), + ("a2_education_courses_l09_q3", "D", "Nauczyłam się programować.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + + # L10 + ("a2_education_courses_l10_q1", "A", "Uczę się ja polskiego ja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_education_courses_l10_q1", "B", "Uczę polskiego się.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_education_courses_l10_q1", "C", "Uczę się polski.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a2_education_courses_l10_q1", "D", "Uczę się polskiego i chodzę na kurs raz w tygodniu.", "Я учу польский и хожу на курс раз в неделю.", "Я вчу польську і ходжу на курс раз на тиждень.", "I'm learning Polish and go to a course once a week.", True, None), + + ("a2_education_courses_l10_q3", "A", "Zdałem egzamin.", "Я сдал экзамен. (не начало описания)", "Я склав іспит. (не початок опису)", "I passed the exam. (not the opening line)", False, "wrong_context"), + ("a2_education_courses_l10_q3", "B", "Chodzę na kurs raz w tygodniu.", "Я хожу на курс раз в неделю. (не начало описания)", "Я ходжу на курс раз на тиждень. (не початок опису)", "I go to a course once a week. (not the opening line)", False, "wrong_context"), + ("a2_education_courses_l10_q3", "C", "Uczę się polskiego.", "Я учу польский.", "Я вчу польську.", "I'm learning Polish.", True, None), + ("a2_education_courses_l10_q3", "D", "Nauczyłem się już dużo słów.", "Я уже выучил много слов. (не начало описания)", "Я вже вивчив багато слів. (не початок опису)", "I've already learned a lot of words. (not the opening line)", False, "wrong_context"), + ] + + for opt in options_t7_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t7_a2 = [ + ("a2_education_courses_t01", None, "topic_test", "recognition", "edukacja_vocabulary", 1, + "Jak po polsku „экзамен”?", "Как по-польски «экзамен»?", "Як польською «іспит»?", "How do you say “exam” in Polish?", + "D", None, None, 1), + ("a2_education_courses_t02", None, "topic_test", "recognition", "uczyc_sie_dopelniacz", 1, + "Wybierz poprawną formę: Uczę się ___. (polski)", "Выберите правильную форму: Uczę się ___. (polski)", "Виберіть правильну форму: Uczę się ___. (polski)", "Choose the correct form: Uczę się ___. (polski)", + "A", None, None, 2), + ("a2_education_courses_t03", None, "topic_test", "recognition", "chodzic_na_zajecia", 1, + "Wybierz poprawną formę: Chodzę ___ kurs. (na)", "Выберите правильную форму: Chodzę ___ kurs. (na)", "Виберіть правильну форму: Chodzę ___ kurs. (na)", "Choose the correct form: Chodzę ___ kurs. (na)", + "A", None, None, 3), + ("a2_education_courses_t04", None, "topic_test", "recognition", "przedmioty_vocabulary", 1, + "Jak po polsku „биология”?", "Как по-польски «биология»?", "Як польською «біологія»?", "How do you say “biology” in Polish?", + "C", None, None, 4), + ("a2_education_courses_t05", None, "topic_test", "recognition", "umiec_bezokolicznik", 2, + "Wybierz poprawną formę: ___ czytać po polsku. (umieć, ja)", "Выберите правильную форму: ___ czytać po polsku. (umieć, ja)", "Виберіть правильну форму: ___ czytać po polsku. (umieć, ja)", "Choose the correct form: ___ czytać po polsku. (umieć, I)", + "A", None, None, 5), + ("a2_education_courses_t06", None, "topic_test", "recognition", "przeszly_czas_nauka", 3, + "Co znaczy „Nauczyłem się polskiego”?", "Что означает «Nauczyłem się polskiego»?", "Що означає «Nauczyłem się polskiego»?", "What does “Nauczyłem się polskiego” mean?", + "D", None, None, 6), + + ("a2_education_courses_t07", None, "topic_test", "application", "edukacja_vocabulary", 1, + "Zapisałeś się na krótkie zajęcia z gotowania. Co to jest?", "Ты записался на короткие занятия по кулинарии. Что это?", "Ти записався на короткі заняття з кулінарії. Що це?", "You signed up for short cooking classes. What is this?", + "C", None, None, 7), + ("a2_education_courses_t08", None, "topic_test", "application", "uczyc_sie_dopelniacz", 1, + "Kolega pyta, jakiego języka się uczysz. Uczysz się niemieckiego. Co powiesz?", "Друг спрашивает, какой язык ты учишь. Ты учишь немецкий. Что ты скажешь?", "Друг питає, яку мову ти вчиш. Ти вчиш німецьку. Що ти скажеш?", "A friend asks what language you're learning. You're learning German. What do you say?", + "C", None, None, 8), + ("a2_education_courses_t09", None, "topic_test", "application", "chodzic_na_zajecia", 1, + "Regularnie uczestniczysz w kursie polskiego raz w tygodniu. Co powiesz?", "Ты регулярно посещаешь курс польского раз в неделю. Что ты скажешь?", "Ти регулярно відвідуєш курс польської раз на тиждень. Що ти скажеш?", "You regularly attend a Polish course once a week. What do you say?", + "A", None, None, 9), + ("a2_education_courses_t10", None, "topic_test", "application", "zdawac_egzamin", 2, + "Właśnie skończyłeś egzamin i wiesz, że zdałeś go pomyślnie. Co powiesz?", "Ты только что закончил экзамен и знаешь, что сдал его успешно. Что ты скажешь?", "Ти щойно закінчив іспит і знаєш, що склав його успішно. Що ти скажеш?", "You just finished the exam and know you passed it successfully. What do you say?", + "B", None, None, 10), + ("a2_education_courses_t11", None, "topic_test", "application", "poziomy_jezykowe_vocabulary", 2, + "Znasz tylko podstawowe słowa i proste zdania w danym języku. Jaki masz poziom?", "Ты знаешь только базовые слова и простые предложения на этом языке. Какой у тебя уровень?", "Ти знаєш лише базові слова і прості речення цією мовою. Який у тебе рівень?", "You only know basic words and simple sentences in that language. What level do you have?", + "A", None, None, 11), + ("a2_education_courses_t12", None, "topic_test", "application", "przeszly_czas_nauka", 3, + "Mężczyzna opowiada, że w zeszłym roku sam nauczył się programować. Co powie?", "Мужчина рассказывает, что в прошлом году сам научился программировать. Что он скажет?", "Чоловік розповідає, що минулого року сам навчився програмувати. Що він скаже?", "A man is telling that last year he taught himself to program. What does he say?", + "B", None, None, 12), + + ("a2_education_courses_t13", None, "topic_test", "production", "edukacja_vocabulary", 1, + "Wpisz brakujące słowo: Studiuję na ___. (университете)", "Вставьте пропущенное слово: Studiuję na ___. (университете)", "Вставте пропущене слово: Studiuję na ___. (університеті)", "Fill in the missing word: Studiuję na ___. (university)", + "uniwersytecie", "first_letter", "u", 13), + ("a2_education_courses_t14", None, "topic_test", "production", "przedmioty_vocabulary", 1, + "Wpisz brakujące słowo: Studiuję ___. (информатику)", "Вставьте пропущенное слово: Studiuję ___. (информатику)", "Вставте пропущене слово: Studiuję ___. (інформатику)", "Fill in the missing word: Studiuję ___. (computer science)", + "informatykę", "first_letter", "i", 14), + ("a2_education_courses_t15", None, "topic_test", "production", "umiec_bezokolicznik", 2, + "Wpisz brakujące słowo: ___ pisać po angielsku? (ты умеешь)", "Вставьте пропущенное слово: ___ pisać po angielsku? (ты умеешь)", "Вставте пропущене слово: ___ pisać po angielsku? (ти вмієш)", "Fill in the missing word: ___ pisać po angielsku? (do you know how to)", + "Umiesz", "first_letter", "U", 15), + ("a2_education_courses_t16", None, "topic_test", "production", "zdawac_egzamin", 2, + "Wpisz brakujące słowo: ___ egzamin z polskiego. (я сдаю, процесс)", "Вставьте пропущенное слово: ___ egzamin z polskiego. (я сдаю, процесс)", "Вставте пропущене слово: ___ egzamin z polskiego. (я складаю, процес)", "Fill in the missing word: ___ egzamin z polskiego. (I'm taking, in progress)", + "Zdaję", "first_letter", "Z", 16), + ("a2_education_courses_t17", None, "topic_test", "production", "poziomy_jezykowe_vocabulary", 2, + "Wpisz brakujące słowo: On jest ___ w hiszpańskim. (свободно владеющий)", "Вставьте пропущенное слово: On jest ___ w hiszpańskim. (свободно владеющий)", "Вставте пропущене слово: On jest ___ w hiszpańskim. (вільно володіючий)", "Fill in the missing word: On jest ___ w hiszpańskim. (fluent)", + "biegły", "first_letter", "b", 17), + ("a2_education_courses_t18", None, "topic_test", "production", "opisuje_swoja_nauke", 3, + "Przetłumacz: «Я сдал экзамен».", "Переведите: «Я сдал экзамен».", "Перекладіть: «Я склав іспит».", "Translate: “I passed the exam.”", + "Zdałem egzamin", "first_letter", "Z", 18), + + ("a2_education_courses_t19", None, "topic_test", "mixed", "opisuje_swoja_nauke", 3, + "Wybierz poprawne tłumaczenie: «Я учу польский, хожу на курс раз в неделю, и уже выучил много слов».", "Выберите правильный перевод: «Я учу польский, хожу на курс раз в неделю, и уже выучил много слов».", "Виберіть правильний переклад: «Я вчу польську, ходжу на курс раз на тиждень, і вже вивчив багато слів».", "Choose the correct translation: “I'm learning Polish, I go to a course once a week, and I've already learned a lot of words.”", + "C", None, None, 19), + ("a2_education_courses_t20", None, "topic_test", "mixed", "zdawac_egzamin", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Ты сдал экзамен по польскому? — Да, я сдал его очень хорошо, потому что много учился.»", "Выберите правильный перевод диалога: «— Ты сдал экзамен по польскому? — Да, я сдал его очень хорошо, потому что много учился.»", "Виберіть правильний переклад діалогу: «— Ти склав іспит з польської? — Так, я склав його дуже добре, бо багато вчився.»", "Choose the correct translation of the dialogue: “— Did you pass the Polish exam? — Yes, I passed it very well, because I studied a lot.”", + "C", None, None, 20), + ] + + for q in test_questions_t7_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_education_courses', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t7_a2 = [ + ("a2_education_courses_t01", "A", "szkoła", "школа", "школа", "school", False, "wrong_word"), + ("a2_education_courses_t01", "B", "uniwersytet", "университет", "університет", "university", False, "wrong_word"), + ("a2_education_courses_t01", "C", "kurs", "курс", "курс", "course", False, "wrong_word"), + ("a2_education_courses_t01", "D", "egzamin", "экзамен", "іспит", "exam", True, None), + + ("a2_education_courses_t02", "A", "polskiego", "польского (род.)", "польської (род.)", "Polish (gen.)", True, None), + ("a2_education_courses_t02", "B", "polski", "польский (им./вин.)", "польська (наз./знах.)", "Polish (nom./acc.)", False, "wrong_case"), + ("a2_education_courses_t02", "C", "polskiemu", "польскому (дат.)", "польській (дав.)", "Polish (dat.)", False, "wrong_case"), + ("a2_education_courses_t02", "D", "polskim", "польским (тв./местн.)", "польською (ор./місц.)", "Polish (instr./loc.)", False, "wrong_case"), + + ("a2_education_courses_t03", "A", "na", "на", "на", "to", True, None), + ("a2_education_courses_t03", "B", "do", "в/к", "в/до", "to", False, "wrong_word"), + ("a2_education_courses_t03", "C", "w", "в", "в", "in", False, "wrong_word"), + ("a2_education_courses_t03", "D", "u", "у", "у", "at", False, "wrong_word"), + + ("a2_education_courses_t04", "A", "matematyka", "математика", "математика", "math", False, "wrong_word"), + ("a2_education_courses_t04", "B", "historia", "история", "історія", "history", False, "wrong_word"), + ("a2_education_courses_t04", "C", "biologia", "биология", "біологія", "biology", True, None), + ("a2_education_courses_t04", "D", "informatyka", "информатика", "інформатика", "computer science", False, "wrong_word"), + + ("a2_education_courses_t05", "A", "Umiem", "я умею", "я вмію", "I know how to", True, None), + ("a2_education_courses_t05", "B", "Umiesz", "ты умеешь (не тот человек)", "ти вмієш (не та особа)", "you know how to (wrong person)", False, "wrong_context"), + ("a2_education_courses_t05", "C", "Umie", "он/она умеет (не тот человек)", "він/вона вміє (не та особа)", "he/she knows how to (wrong person)", False, "wrong_context"), + ("a2_education_courses_t05", "D", "Umieli", "они умели (неправильное число и время)", "вони вміли (неправильне число і час)", "they knew how to (wrong number and tense)", False, "wrong_number"), + + ("a2_education_courses_t06", "A", "Uczę się polskiego.", "Я учу польский (сейчас).", "Я вчу польську (зараз).", "I'm learning Polish (now).", False, "wrong_translation"), + ("a2_education_courses_t06", "B", "Będę się uczyć polskiego.", "Я буду учить польский.", "Я буду вчити польську.", "I will learn Polish.", False, "wrong_translation"), + ("a2_education_courses_t06", "C", "Chcę nauczyć się polskiego.", "Я хочу выучить польский.", "Я хочу вивчити польську.", "I want to learn Polish.", False, "wrong_translation"), + ("a2_education_courses_t06", "D", "Nauczyłem się polskiego.", "Я выучил польский.", "Я вивчив польську.", "I learned Polish.", True, None), + + ("a2_education_courses_t07", "A", "szkoła", "школа", "школа", "school", False, "wrong_context"), + ("a2_education_courses_t07", "B", "uniwersytet", "университет", "університет", "university", False, "wrong_context"), + ("a2_education_courses_t07", "C", "kurs", "курс", "курс", "course", True, None), + ("a2_education_courses_t07", "D", "egzamin", "экзамен", "іспит", "exam", False, "wrong_context"), + + ("a2_education_courses_t08", "A", "Uczę się polskiego.", "Я учу польский. (не соответствует ситуации)", "Я вчу польську. (не відповідає ситуації)", "I'm learning Polish. (doesn't match the situation)", False, "wrong_context"), + ("a2_education_courses_t08", "B", "Uczę się angielskiego.", "Я учу английский. (не соответствует ситуации)", "Я вчу англійську. (не відповідає ситуації)", "I'm learning English. (doesn't match the situation)", False, "wrong_context"), + ("a2_education_courses_t08", "C", "Uczę się niemieckiego.", "Я учу немецкий.", "Я вчу німецьку.", "I'm learning German.", True, None), + ("a2_education_courses_t08", "D", "Znam niemiecki.", "Я знаю немецкий. (не о процессе изучения)", "Я знаю німецьку. (не про процес вивчення)", "I know German. (not about the learning process)", False, "wrong_context"), + + ("a2_education_courses_t09", "A", "Chodzę na kurs polskiego.", "Я хожу на курс польского.", "Я ходжу на курс польської.", "I go to a Polish course.", True, None), + ("a2_education_courses_t09", "B", "Idę do szkoły.", "Я иду в школу. (не о регулярности)", "Я йду в школу. (не про регулярність)", "I'm going to school. (not about regularity)", False, "wrong_context"), + ("a2_education_courses_t09", "C", "Mam egzamin.", "У меня экзамен. (не соответствует ситуации)", "У мене іспит. (не відповідає ситуації)", "I have an exam. (doesn't match the situation)", False, "wrong_context"), + ("a2_education_courses_t09", "D", "Uczę się w domu.", "Я учусь дома. (не о курсе)", "Я вчуся вдома. (не про курс)", "I study at home. (not about the course)", False, "wrong_context"), + + ("a2_education_courses_t10", "A", "Zdaję egzamin.", "Я сдаю экзамен. (процесс, а не результат)", "Я складаю іспит. (процес, а не результат)", "I'm taking the exam. (process, not result)", False, "wrong_sentence_type"), + ("a2_education_courses_t10", "B", "Zdałem egzamin.", "Я сдал экзамен.", "Я склав іспит.", "I passed the exam.", True, None), + ("a2_education_courses_t10", "C", "Będę zdawać egzamin.", "Я буду сдавать экзамен. (будущее время)", "Я буду складати іспит. (майбутній час)", "I will take the exam. (future tense)", False, "wrong_sentence_type"), + ("a2_education_courses_t10", "D", "Uczę się do egzaminu.", "Я готовлюсь к экзамену. (не о результате)", "Я готуюся до іспиту. (не про результат)", "I'm studying for the exam. (not about the result)", False, "wrong_context"), + + ("a2_education_courses_t11", "A", "podstawowy", "базовый", "базовий", "basic", True, None), + ("a2_education_courses_t11", "B", "średni", "средний", "середній", "intermediate", False, "wrong_context"), + ("a2_education_courses_t11", "C", "zaawansowany", "продвинутый", "просунутий", "advanced", False, "wrong_context"), + ("a2_education_courses_t11", "D", "biegły", "свободный", "вільний", "fluent", False, "wrong_context"), + + ("a2_education_courses_t12", "A", "Uczę się programować.", "Я учусь программировать. (настоящее время)", "Я вчуся програмувати. (теперішній час)", "I'm learning to program. (present tense)", False, "wrong_sentence_type"), + ("a2_education_courses_t12", "B", "Nauczyłem się programować.", "Я научился программировать.", "Я навчився програмувати.", "I taught myself to program.", True, None), + ("a2_education_courses_t12", "C", "Będę się uczyć programować.", "Я буду учиться программировать. (будущее время)", "Я вчитимусь програмувати. (майбутній час)", "I will learn to program. (future tense)", False, "wrong_sentence_type"), + ("a2_education_courses_t12", "D", "Nauczyłam się programować.", "Неправильная форма рода (для женщины).", "Неправильна форма роду (для жінки).", "Wrong gender form (for a woman).", False, "wrong_gender"), + + ("a2_education_courses_t19", "A", "Uczyłem się polskiego, chodziłem na kurs raz w tygodniu, i nauczyłem się już dużo słów.", "Я учил польский, ходил на курс раз в неделю, и выучил уже много слов. (неправильное время)", "Я вчив польську, ходив на курс раз на тиждень, і вже вивчив багато слів. (неправильний час)", "I was learning Polish, going to a course once a week, and I had already learned a lot of words. (wrong tense)", False, "wrong_sentence_type"), + ("a2_education_courses_t19", "B", "Będę się uczyć polskiego, będę chodzić na kurs raz w tygodniu, i nauczę się już dużo słów.", "Я буду учить польский, буду ходить на курс раз в неделю, и выучу уже много слов. (будущее время)", "Я буду вчити польську, буду ходити на курс раз на тиждень, і вивчу вже багато слів. (майбутній час)", "I will learn Polish, go to a course once a week, and will have already learned a lot of words. (future tense)", False, "wrong_sentence_type"), + ("a2_education_courses_t19", "C", "Uczę się polskiego, chodzę na kurs raz w tygodniu, i nauczyłem się już dużo słów.", "Я учу польский, хожу на курс раз в неделю, и уже выучил много слов.", "Я вчу польську, ходжу на курс раз на тиждень, і вже вивчив багато слів.", "I'm learning Polish, I go to a course once a week, and I've already learned a lot of words.", True, None), + ("a2_education_courses_t19", "D", "Uczę się angielskiego, chodzę na kurs raz w miesiącu, i nauczyłem się już dużo słów.", "Я учу английский, хожу на курс раз в месяц, и уже выучил много слов. (неверный язык и частота)", "Я вчу англійську, ходжу на курс раз на місяць, і вже вивчив багато слів. (невірна мова і частота)", "I'm learning English, I go to a course once a month, and I've already learned a lot of words. (wrong language and frequency)", False, "wrong_word"), + + ("a2_education_courses_t20", "A", "— Zdajesz egzamin z polskiego? — Tak, zdaję go bardzo dobrze, bo dużo się uczę.", "— Ты сдаёшь экзамен по польскому? — Да, я сдаю его очень хорошо, потому что много учусь. (настоящее время — процесс)", "— Ти складаєш іспит з польської? — Так, я складаю його дуже добре, бо багато вчуся. (теперішній час — процес)", "— Are you taking the Polish exam? — Yes, I'm doing very well, because I study a lot. (present tense — process)", False, "wrong_sentence_type"), + ("a2_education_courses_t20", "B", "— Zdałeś egzamin z polskiego? — Tak, zdałem go bardzo źle, bo mało się uczyłem.", "— Ты сдал экзамен по польскому? — Да, я сдал его очень плохо, потому что мало учился. (противоположный смысл)", "— Ти склав іспит з польської? — Так, я склав його дуже погано, бо мало вчився. (протилежний зміст)", "— Did you pass the Polish exam? — Yes, I did very badly, because I studied little. (opposite meaning)", False, "wrong_context"), + ("a2_education_courses_t20", "C", "— Zdałeś egzamin z polskiego? — Tak, zdałem go bardzo dobrze, bo dużo się uczyłem.", "— Ты сдал экзамен по польскому? — Да, я сдал его очень хорошо, потому что много учился.", "— Ти склав іспит з польської? — Так, я склав його дуже добре, бо багато вчився.", "— Did you pass the Polish exam? — Yes, I passed it very well, because I studied a lot.", True, None), + ("a2_education_courses_t20", "D", "— Zdałeś egzamin z angielskiego? — Tak, zdałem go bardzo dobrze, bo dużo się uczyłem.", "— Ты сдал экзамен по английскому? — Да, я сдал его очень хорошо, потому что много учился. (неверный язык)", "— Ти склав іспит з англійської? — Так, я склав його дуже добре, бо багато вчився. (невірна мова)", "— Did you pass the English exam? — Yes, I passed it very well, because I studied a lot. (wrong language)", False, "wrong_word"), + ] + + for opt in test_options_t7_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 8 (A2): PODRÓŻE I WAKACJE ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_travel_vacation', 'A2', 8, + 'Podróże i wakacje', + 'Путешествия и отпуск', + 'Подорожі та відпустка', + 'Travel and Vacation') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t8_a2 = [ + ("a2_travel_vacation_l01", 1, "podroze_vocabulary", "Podstawowe słowa: podróże", "Основные слова: путешествия", "Основні слова: подорожі", "Basic words: travel", + "Podstawowe słowa: bilet, walizka, paszport, lotnisko.", + "Основные слова: bilet (билет), walizka (чемодан), paszport (паспорт), lotnisko (аэропорт).", + "Основні слова: bilet (квиток), walizka (валіза), paszport (паспорт), lotnisko (аеропорт).", + "Basic words: bilet (ticket), walizka (suitcase), paszport (passport), lotnisko (airport)."), + + ("a2_travel_vacation_l02", 2, "jechac_do", "Jechać do + dopełniacz", "Jechać do + родительный падеж", "Jechać do + родовий відмінок", "Jechać do + genitive", + "Czasownik „jechać” + „do” + dopełniacz kraju lub miejsca: jadę do Polski, jedziesz do Włoch, jedzie do Niemiec.", + "Глагол „jechać” (ехать) + „do” + родительный падеж страны или места: jadę do Polski (я еду в Польшу), jedziesz do Włoch (ты едешь в Италию), jedzie do Niemiec (он/она едет в Германию).", + "Дієслово „jechać” (їхати) + „do” + родовий відмінок країни або місця: jadę do Polski (я їду до Польщі), jedziesz do Włoch (ти їдеш до Італії), jedzie do Niemiec (він/вона їде до Німеччини).", + "The verb „jechać” (to go/travel) + „do” + genitive of the country or place: jadę do Polski (I'm going to Poland), jedziesz do Włoch (you're going to Italy), jedzie do Niemiec (he/she is going to Germany)."), + + ("a2_travel_vacation_l03", 3, "wakacje_vocabulary", "Podstawowe słowa: wakacje", "Основные слова: отпуск", "Основні слова: відпустка", "Basic words: vacation", + "Podstawowe słowa: plaża, góry, morze, hotel.", + "Основные слова: plaża (пляж), góry (горы), morze (море), hotel (отель).", + "Основні слова: plaża (пляж), góry (гори), morze (море), hotel (готель).", + "Basic words: plaża (beach), góry (mountains), morze (sea), hotel (hotel)."), + + ("a2_travel_vacation_l04", 4, "chciec_bezokolicznik", "Chcieć + bezokolicznik", "Chcieć + инфинитив", "Chcieć + інфінітив", "Chcieć + infinitive", + "Czasownik „chcieć” + bezokolicznik wyraża pragnienie: chcę zwiedzać, chcesz odpoczywać, chce pływać.", + "Глагол „chcieć” (хотеть) + инфинитив выражает желание: chcę zwiedzać (я хочу осматривать достопримечательности), chcesz odpoczywać (ты хочешь отдыхать), chce pływać (он/она хочет плавать).", + "Дієслово „chcieć” (хотіти) + інфінітив виражає бажання: chcę zwiedzać (я хочу оглядати), chcesz odpoczywać (ти хочеш відпочивати), chce pływać (він/вона хоче плавати).", + "The verb „chcieć” (to want) + infinitive expresses a wish: chcę zwiedzać (I want to sightsee), chcesz odpoczywać (you want to relax), chce pływać (he/she wants to swim)."), + + ("a2_travel_vacation_l05", 5, "rezerwowac_hotel", "Rezerwować / zarezerwować + biernik", "Rezerwować / zarezerwować + винительный падеж", "Rezerwować / zarezerwować + знахідний відмінок", "Rezerwować / zarezerwować + accusative", + "Czasownik „rezerwować” (proces) i „zarezerwować” (dokonany, sukces) + biernik: rezerwuję pokój (jestem w trakcie), zarezerwowałem pokój (zrobiłem to skutecznie).", + "Глагол „rezerwować” (процесс — бронировать) и „zarezerwować” (совершенный вид — успешно забронировать) + винительный падеж: rezerwuję pokój (я бронирую номер, процесс), zarezerwowałem pokój (я забронировал номер, успешно).", + "Дієслово „rezerwować” (процес — бронювати) і „zarezerwować” (доконаний вид — успішно забронювати) + знахідний відмінок: rezerwuję pokój (я бронюю номер, процес), zarezerwowałem pokój (я забронював номер, успішно).", + "The verb „rezerwować” (imperfective — to book) and „zarezerwować” (perfective — to have booked) + accusative: rezerwuję pokój (I'm booking a room, in progress), zarezerwowałem pokój (I booked the room, successfully)."), + + ("a2_travel_vacation_l06", 6, "zwiedzac_biernik", "Zwiedzać + biernik", "Zwiedzać + винительный падеж", "Zwiedzać + знахідний відмінок", "Zwiedzać + accusative", + "Czasownik „zwiedzać” + biernik miejsca: zwiedzam miasto, zwiedzasz muzeum, zwiedza zamek.", + "Глагол „zwiedzać” (осматривать достопримечательности) + винительный падеж места: zwiedzam miasto (я осматриваю город), zwiedzasz muzeum (ты осматриваешь музей), zwiedza zamek (он/она осматривает замок).", + "Дієслово „zwiedzać” (оглядати визначні місця) + знахідний відмінок місця: zwiedzam miasto (я оглядаю місто), zwiedzasz muzeum (ти оглядаєш музей), zwiedza zamek (він/вона оглядає замок).", + "The verb „zwiedzać” (to sightsee/visit) + accusative of the place: zwiedzam miasto (I'm sightseeing the city), zwiedzasz muzeum (you're visiting the museum), zwiedza zamek (he/she is visiting the castle)."), + + ("a2_travel_vacation_l07", 7, "przymiotniki_podroz_vocabulary", "Podstawowe słowa: przymiotniki o podróży", "Основные слова: прилагательные о путешествии", "Основні слова: прикметники про подорож", "Basic words: travel adjectives", + "Podstawowe przymiotniki opisujące podróż: drogi, tani, ciekawy, nudny.", + "Основные прилагательные, описывающие путешествие: drogi (дорогой), tani (дешёвый), ciekawy (интересный), nudny (скучный).", + "Основні прикметники, що описують подорож: drogi (дорогий), tani (дешевий), ciekawy (цікавий), nudny (нудний).", + "Basic adjectives describing travel: drogi (expensive), tani (cheap), ciekawy (interesting), nudny (boring)."), + + ("a2_travel_vacation_l08", 8, "leciec_instrumental", "Lecieć / jechać + narzędnik (środek transportu)", "Lecieć / jechać + творительный падеж (транспорт)", "Lecieć / jechać + орудний відмінок (транспорт)", "Lecieć / jechać + instrumental (means of transport)", + "Środek transportu wyrażamy narzędnikiem: lecę samolotem, jedziesz pociągiem, jedzie autobusem.", + "Средство передвижения выражаем творительным падежом: lecę samolotem (я лечу самолётом), jedziesz pociągiem (ты едешь поездом), jedzie autobusem (он/она едет автобусом).", + "Засіб пересування виражаємо орудним відмінком: lecę samolotem (я лечу літаком), jedziesz pociągiem (ти їдеш потягом), jedzie autobusem (він/вона їде автобусом).", + "We express the means of transport with the instrumental case: lecę samolotem (I'm flying by plane), jedziesz pociągiem (you're going by train), jedzie autobusem (he/she is going by bus)."), + + ("a2_travel_vacation_l09", 9, "przeszly_czas_podroz", "Pojechałem/pojechałam + dopełniacz (przeszłość)", "Pojechałem/pojechałam + родительный падеж (прошедшее)", "Pojechałem/pojechałam + родовий відмінок (минулий час)", "Pojechałem/pojechałam + genitive (past)", + "Czas przeszły podróży tworzymy „pojechałem” (mężczyzna) lub „pojechałam” (kobieta) + dopełniacz lub biernik kierunku: pojechałem do Włoch, pojechałam nad morze, poleciał samolotem.", + "Прошедшее время путешествия образуем „pojechałem” (мужчина) или „pojechałam” (женщина) + падеж направления: pojechałem do Włoch (я поехал в Италию), pojechałam nad morze (я поехала на море), poleciał samolotem (он полетел самолётом).", + "Минулий час подорожі утворюємо „pojechałem” (чоловік) або „pojechałam” (жінка) + відмінок напрямку: pojechałem do Włoch (я поїхав до Італії), pojechałam nad morze (я поїхала на море), poleciał samolotem (він полетів літаком).", + "We form the past tense of travel with „pojechałem” (male speaker) or „pojechałam” (female speaker) + the case of the destination: pojechałem do Włoch (I went to Italy), pojechałam nad morze (I went to the seaside), poleciał samolotem (he flew by plane)."), + + ("a2_travel_vacation_l10", 10, "opisuje_swoja_podroz", "Opisuję swoją podróż", "Описываю своё путешествие", "Описую свою подорож", "Describing my trip", + "Żeby opisać podróż, łączymy zdania: Jadę do Polski. Chcę zwiedzać stare miasto. Zarezerwowałem hotel w centrum. Lecę tam samolotem.", + "Чтобы описать путешествие, соединяем предложения: Jadę do Polski. Chcę zwiedzać stare miasto. Zarezerwowałem hotel w centrum. Lecę tam samolotem. (Я еду в Польшу. Я хочу осматривать старый город. Я забронировал отель в центре. Я лечу туда самолётом.)", + "Щоб описати подорож, поєднуємо речення: Jadę do Polski. Chcę zwiedzać stare miasto. Zarezerwowałem hotel w centrum. Lecę tam samolotem. (Я їду до Польщі. Я хочу оглядати старе місто. Я забронював готель у центрі. Я лечу туди літаком.)", + "To describe a trip, we combine sentences: Jadę do Polski. Chcę zwiedzać stare miasto. Zarezerwowałem hotel w centrum. Lecę tam samolotem. (I'm going to Poland. I want to sightsee the old town. I booked a hotel in the center. I'm flying there by plane.)"), + ] + + for lesson in lessons_t8_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_travel_vacation', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t8_a2 = [ + ("a2_travel_vacation_l01", 1, "To jest mój bilet.", "Это мой билет.", "Це мій квиток.", "This is my ticket."), + ("a2_travel_vacation_l01", 2, "Mam paszport.", "У меня есть паспорт.", "Я маю паспорт.", "I have a passport."), + ("a2_travel_vacation_l01", 3, "Jestem na lotnisku.", "Я в аэропорту.", "Я в аеропорту.", "I'm at the airport."), + + ("a2_travel_vacation_l02", 1, "Jadę do Polski.", "Я еду в Польшу.", "Я їду до Польщі.", "I'm going to Poland."), + ("a2_travel_vacation_l02", 2, "Jedziesz do Włoch?", "Ты едешь в Италию?", "Ти їдеш до Італії?", "Are you going to Italy?"), + ("a2_travel_vacation_l02", 3, "On jedzie do Niemiec.", "Он едет в Германию.", "Він їде до Німеччини.", "He's going to Germany."), + + ("a2_travel_vacation_l03", 1, "Lubię plażę.", "Я люблю пляж.", "Я люблю пляж.", "I like the beach."), + ("a2_travel_vacation_l03", 2, "Jadę w góry.", "Я еду в горы.", "Я їду в гори.", "I'm going to the mountains."), + ("a2_travel_vacation_l03", 3, "Mieszkam w hotelu.", "Я живу в отеле.", "Я живу в готелі.", "I'm staying at a hotel."), + + ("a2_travel_vacation_l04", 1, "Chcę zwiedzać miasto.", "Я хочу осматривать город.", "Я хочу оглядати місто.", "I want to sightsee the city."), + ("a2_travel_vacation_l04", 2, "Chcesz odpoczywać czy zwiedzać?", "Ты хочешь отдыхать или осматривать достопримечательности?", "Ти хочеш відпочивати чи оглядати?", "Do you want to relax or sightsee?"), + ("a2_travel_vacation_l04", 3, "Ona chce pływać w morzu.", "Она хочет плавать в море.", "Вона хоче плавати в морі.", "She wants to swim in the sea."), + + ("a2_travel_vacation_l05", 1, "Rezerwuję pokój w hotelu.", "Я бронирую номер в отеле.", "Я бронюю номер у готелі.", "I'm booking a room at the hotel."), + ("a2_travel_vacation_l05", 2, "Zarezerwowałeś bilet?", "Ты забронировал билет?", "Ти забронював квиток?", "Did you book the ticket?"), + ("a2_travel_vacation_l05", 3, "Ona zarezerwowała hotel nad morzem.", "Она забронировала отель у моря.", "Вона забронювала готель біля моря.", "She booked a hotel by the sea."), + + ("a2_travel_vacation_l06", 1, "Zwiedzam stare miasto.", "Я осматриваю старый город.", "Я оглядаю старе місто.", "I'm sightseeing the old town."), + ("a2_travel_vacation_l06", 2, "Zwiedzasz muzeum?", "Ты осматриваешь музей?", "Ти оглядаєш музей?", "Are you visiting the museum?"), + ("a2_travel_vacation_l06", 3, "On zwiedza zamek w Krakowie.", "Он осматривает замок в Кракове.", "Він оглядає замок у Кракові.", "He's visiting the castle in Kraków."), + + ("a2_travel_vacation_l07", 1, "Ten hotel jest drogi.", "Этот отель дорогой.", "Цей готель дорогий.", "This hotel is expensive."), + ("a2_travel_vacation_l07", 2, "Bilet był tani.", "Билет был дешёвый.", "Квиток був дешевий.", "The ticket was cheap."), + ("a2_travel_vacation_l07", 3, "Ta wycieczka jest bardzo ciekawa.", "Эта экскурсия очень интересная.", "Ця екскурсія дуже цікава.", "This trip is very interesting."), + + ("a2_travel_vacation_l08", 1, "Lecę samolotem do Warszawy.", "Я лечу самолётом в Варшаву.", "Я лечу літаком до Варшави.", "I'm flying by plane to Warsaw."), + ("a2_travel_vacation_l08", 2, "Jedziesz pociągiem czy autobusem?", "Ты едешь поездом или автобусом?", "Ти їдеш потягом чи автобусом?", "Are you going by train or by bus?"), + ("a2_travel_vacation_l08", 3, "Ona jedzie autobusem na wakacje.", "Она едет автобусом в отпуск.", "Вона їде автобусом у відпустку.", "She's going by bus on vacation."), + + ("a2_travel_vacation_l09", 1, "Pojechałem do Włoch w zeszłym roku.", "Я поехал в Италию в прошлом году.", "Я поїхав до Італії минулого року.", "I went to Italy last year."), + ("a2_travel_vacation_l09", 2, "Pojechałaś nad morze latem?", "Ты ездила на море летом?", "Ти їздила на море влітку?", "Did you go to the sea in summer?"), + ("a2_travel_vacation_l09", 3, "On poleciał do Hiszpanii samolotem.", "Он полетел в Испанию самолётом.", "Він полетів до Іспанії літаком.", "He flew to Spain by plane."), + + ("a2_travel_vacation_l10", 1, "Jadę do Polski.", "Я еду в Польшу.", "Я їду до Польщі.", "I'm going to Poland."), + ("a2_travel_vacation_l10", 2, "Chcę zwiedzać stare miasto.", "Я хочу осматривать старый город.", "Я хочу оглядати старе місто.", "I want to sightsee the old town."), + ("a2_travel_vacation_l10", 3, "Zarezerwowałem hotel w centrum.", "Я забронировал отель в центре.", "Я забронював готель у центрі.", "I booked a hotel in the center."), + ] + + for ex in examples_t8_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t8_a2 = [ + # L01 — podroze_vocabulary (difficulty 1) + ("a2_travel_vacation_l01_q1", "a2_travel_vacation_l01", "lesson_practice", "recognition", "podroze_vocabulary", 1, + "Jak po polsku „чемодан”?", "Как по-польски «чемодан»?", "Як польською «валіза»?", "How do you say “suitcase” in Polish?", + "B", None, None), + ("a2_travel_vacation_l01_q2", "a2_travel_vacation_l01", "lesson_practice", "production", "podroze_vocabulary", 1, + "Wpisz brakujące słowo: Mam ___. (паспорт)", "Вставьте пропущенное слово: Mam ___. (паспорт)", "Вставте пропущене слово: Mam ___. (паспорт)", "Fill in the missing word: Mam ___. (passport)", + "paszport", "first_letter", "p"), + ("a2_travel_vacation_l01_q3", "a2_travel_vacation_l01", "lesson_practice", "application", "podroze_vocabulary", 1, + "Jesteś w budynku, gdzie odlatują samoloty. Gdzie jesteś?", "Ты находишься в здании, откуда вылетают самолёты. Где ты?", "Ти перебуваєш у будівлі, звідки вилітають літаки. Де ти?", "You're in a building where planes take off. Where are you?", + "A", None, None), + + # L02 — jechac_do (difficulty 1) + ("a2_travel_vacation_l02_q1", "a2_travel_vacation_l02", "lesson_practice", "recognition", "jechac_do", 1, + "Wybierz poprawną formę: Jadę do ___. (Polska)", "Выберите правильную форму: Jadę do ___. (Polska)", "Виберіть правильну форму: Jadę do ___. (Polska)", "Choose the correct form: Jadę do ___. (Polska)", + "A", None, None), + ("a2_travel_vacation_l02_q2", "a2_travel_vacation_l02", "lesson_practice", "production", "jechac_do", 1, + "Wpisz brakujące słowo: Jedziesz do ___? (Италии)", "Вставьте пропущенное слово: Jedziesz do ___? (Италии)", "Вставте пропущене слово: Jedziesz do ___? (Італії)", "Fill in the missing word: Jedziesz do ___? (Italy)", + "Włoch", "first_letter", "W"), + ("a2_travel_vacation_l02_q3", "a2_travel_vacation_l02", "lesson_practice", "application", "jechac_do", 1, + "Kolega pyta, dokąd jedziesz na wakacje. Jedziesz do Hiszpanii. Co powiesz?", "Друг спрашивает, куда ты едешь в отпуск. Ты едешь в Испанию. Что ты скажешь?", "Друг питає, куди ти їдеш у відпустку. Ти їдеш до Іспанії. Що ти скажеш?", "A friend asks where you're going on vacation. You're going to Spain. What do you say?", + "C", None, None), + + # L03 — wakacje_vocabulary (difficulty 1) + ("a2_travel_vacation_l03_q1", "a2_travel_vacation_l03", "lesson_practice", "recognition", "wakacje_vocabulary", 1, + "Jak po polsku „море”?", "Как по-польски «море»?", "Як польською «море»?", "How do you say “sea” in Polish?", + "C", None, None), + ("a2_travel_vacation_l03_q2", "a2_travel_vacation_l03", "lesson_practice", "production", "wakacje_vocabulary", 1, + "Wpisz brakujące słowo: Mieszkam w ___. (отеле)", "Вставьте пропущенное слово: Mieszkam w ___. (отеле)", "Вставте пропущене слово: Mieszkam w ___. (готелі)", "Fill in the missing word: Mieszkam w ___. (hotel)", + "hotelu", "first_letter", "h"), + ("a2_travel_vacation_l03_q3", "a2_travel_vacation_l03", "lesson_practice", "application", "wakacje_vocabulary", 1, + "Chcesz odpoczywać nad wodą i opalać się. Dokąd jedziesz?", "Ты хочешь отдыхать у воды и загорать. Куда ты едешь?", "Ти хочеш відпочивати біля води і засмагати. Куди ти їдеш?", "You want to relax by the water and sunbathe. Where are you going?", + "A", None, None), + + # L04 — chciec_bezokolicznik (difficulty 1) + ("a2_travel_vacation_l04_q1", "a2_travel_vacation_l04", "lesson_practice", "recognition", "chciec_bezokolicznik", 1, + "Wybierz poprawną formę: ___ zwiedzać miasto. (chcieć, ja)", "Выберите правильную форму: ___ zwiedzać miasto. (chcieć, ja)", "Виберіть правильну форму: ___ zwiedzać miasto. (chcieć, ja)", "Choose the correct form: ___ zwiedzać miasto. (chcieć, I)", + "A", None, None), + ("a2_travel_vacation_l04_q2", "a2_travel_vacation_l04", "lesson_practice", "production", "chciec_bezokolicznik", 1, + "Wpisz brakujące słowo: ___ odpoczywać? (ты хочешь)", "Вставьте пропущенное слово: ___ odpoczywać? (ты хочешь)", "Вставте пропущене слово: ___ odpoczywać? (ти хочеш)", "Fill in the missing word: ___ odpoczywać? (do you want)", + "Chcesz", "first_letter", "C"), + ("a2_travel_vacation_l04_q3", "a2_travel_vacation_l04", "lesson_practice", "application", "chciec_bezokolicznik", 1, + "Planujesz wakacje i marzysz o pływaniu w morzu. Co powiesz?", "Ты планируешь отпуск и мечтаешь плавать в море. Что ты скажешь?", "Ти плануєш відпустку і мрієш плавати в морі. Що ти скажеш?", "You're planning a vacation and dream of swimming in the sea. What do you say?", + "B", None, None), + + # L05 — rezerwowac_hotel (difficulty 2) + ("a2_travel_vacation_l05_q1", "a2_travel_vacation_l05", "lesson_practice", "recognition", "rezerwowac_hotel", 2, + "Wybierz poprawną formę: ___ pokój w hotelu. (rezerwować, ja)", "Выберите правильную форму: ___ pokój w hotelu. (rezerwować, ja)", "Виберіть правильну форму: ___ pokój w hotelu. (rezerwować, ja)", "Choose the correct form: ___ pokój w hotelu. (rezerwować, I)", + "A", None, None), + ("a2_travel_vacation_l05_q2", "a2_travel_vacation_l05", "lesson_practice", "production", "rezerwowac_hotel", 2, + "Wpisz brakujące słowo: ___ bilet? (ты забронировал)", "Вставьте пропущенное слово: ___ bilet? (ты забронировал)", "Вставте пропущене слово: ___ bilet? (ти забронював)", "Fill in the missing word: ___ bilet? (did you book)", + "Zarezerwowałeś", "first_letter", "Z"), + ("a2_travel_vacation_l05_q3", "a2_travel_vacation_l05", "lesson_practice", "application", "rezerwowac_hotel", 2, + "Właśnie skończyłeś proces rezerwacji hotelu przez internet i to się udało. Co powiesz?", "Ты только что закончил процесс бронирования отеля через интернет, и это удалось. Что ты скажешь?", "Ти щойно закінчив процес бронювання готелю через інтернет, і це вдалося. Що ти скажеш?", "You just finished booking a hotel online and it worked out. What do you say?", + "B", None, None), + + # L06 — zwiedzac_biernik (difficulty 2) + ("a2_travel_vacation_l06_q1", "a2_travel_vacation_l06", "lesson_practice", "recognition", "zwiedzac_biernik", 2, + "Wybierz poprawną formę: Zwiedzam ___. (zamek)", "Выберите правильную форму: Zwiedzam ___. (zamek)", "Виберіть правильну форму: Zwiedzam ___. (zamek)", "Choose the correct form: Zwiedzam ___. (zamek)", + "A", None, None), + ("a2_travel_vacation_l06_q2", "a2_travel_vacation_l06", "lesson_practice", "production", "zwiedzac_biernik", 2, + "Wpisz brakujące słowo: Zwiedzasz ___? (замок)", "Вставьте пропущенное слово: Zwiedzasz ___? (замок)", "Вставте пропущене слово: Zwiedzasz ___? (замок)", "Fill in the missing word: Zwiedzasz ___? (castle)", + "zamek", "first_letter", "z"), + ("a2_travel_vacation_l06_q3", "a2_travel_vacation_l06", "lesson_practice", "application", "zwiedzac_biernik", 2, + "Jesteś na wakacjach i chcesz zobaczyć stare budynki i zabytki miasta. Co powiesz?", "Ты в отпуске и хочешь увидеть старые здания и достопримечательности города. Что ты скажешь?", "Ти у відпустці і хочеш побачити старі будівлі та пам'ятки міста. Що ти скажеш?", "You're on vacation and want to see the old buildings and landmarks of the city. What do you say?", + "A", None, None), + + # L07 — przymiotniki_podroz_vocabulary (difficulty 2) + ("a2_travel_vacation_l07_q1", "a2_travel_vacation_l07", "lesson_practice", "recognition", "przymiotniki_podroz_vocabulary", 2, + "Jak po polsku „скучный”?", "Как по-польски «скучный»?", "Як польською «нудний»?", "How do you say “boring” in Polish?", + "D", None, None), + ("a2_travel_vacation_l07_q2", "a2_travel_vacation_l07", "lesson_practice", "production", "przymiotniki_podroz_vocabulary", 2, + "Wpisz brakujące słowo: Ten hotel jest ___. (дорогой)", "Вставьте пропущенное слово: Ten hotel jest ___. (дорогой)", "Вставте пропущене слово: Ten hotel jest ___. (дорогий)", "Fill in the missing word: Ten hotel jest ___. (expensive)", + "drogi", "first_letter", "d"), + ("a2_travel_vacation_l07_q3", "a2_travel_vacation_l07", "lesson_practice", "application", "przymiotniki_podroz_vocabulary", 2, + "Kupiłeś bardzo tani bilet na samolot. Jaki on jest?", "Ты купил очень дешёвый билет на самолёт. Какой он?", "Ти купив дуже дешевий квиток на літак. Який він?", "You bought a very cheap plane ticket. What is it like?", + "B", None, None), + + # L08 — leciec_instrumental (difficulty 2) + ("a2_travel_vacation_l08_q1", "a2_travel_vacation_l08", "lesson_practice", "recognition", "leciec_instrumental", 2, + "Wybierz poprawną formę: Lecę ___. (samolot)", "Выберите правильную форму: Lecę ___. (samolot)", "Виберіть правильну форму: Lecę ___. (samolot)", "Choose the correct form: Lecę ___. (samolot)", + "A", None, None), + ("a2_travel_vacation_l08_q2", "a2_travel_vacation_l08", "lesson_practice", "production", "leciec_instrumental", 2, + "Wpisz brakujące słowo: Jedziesz ___? (поездом)", "Вставьте пропущенное слово: Jedziesz ___? (поездом)", "Вставте пропущене слово: Jedziesz ___? (потягом)", "Fill in the missing word: Jedziesz ___? (by train)", + "pociągiem", "first_letter", "p"), + ("a2_travel_vacation_l08_q3", "a2_travel_vacation_l08", "lesson_practice", "application", "leciec_instrumental", 2, + "Wybierasz najszybszy sposób podróży do innego kraju. Czym lecisz?", "Ты выбираешь самый быстрый способ путешествия в другую страну. Чем ты летишь?", "Ти обираєш найшвидший спосіб подорожі до іншої країни. Чим ти летиш?", "You're choosing the fastest way to travel to another country. What do you fly by?", + "A", None, None), + + # L09 — przeszly_czas_podroz (difficulty 3) + ("a2_travel_vacation_l09_q1", "a2_travel_vacation_l09", "lesson_practice", "recognition", "przeszly_czas_podroz", 3, + "Co znaczy „Pojechałem do Włoch w zeszłym roku”?", "Что означает «Pojechałem do Włoch w zeszłym roku»?", "Що означає «Pojechałem do Włoch w zeszłym roku»?", "What does “Pojechałem do Włoch w zeszłym roku” mean?", + "D", None, None), + ("a2_travel_vacation_l09_q2", "a2_travel_vacation_l09", "lesson_practice", "production", "przeszly_czas_podroz", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ nad morze latem? (ты ездила)", "Вставьте пропущенное слово (говорит женщина): ___ nad morze latem? (ты ездила)", "Вставте пропущене слово (говорить жінка): ___ nad morze latem? (ти їздила)", "Fill in the missing word (a woman is speaking): ___ nad morze latem? (did you go)", + "Pojechałaś", "first_letter", "P"), + ("a2_travel_vacation_l09_q3", "a2_travel_vacation_l09", "lesson_practice", "application", "przeszly_czas_podroz", 3, + "Mężczyzna opowiada, że w zeszłym roku poleciał samolotem do Hiszpanii. Co powie?", "Мужчина рассказывает, что в прошлом году он полетел самолётом в Испанию. Что он скажет?", "Чоловік розповідає, що минулого року він полетів літаком до Іспанії. Що він скаже?", "A man is telling that last year he flew to Spain by plane. What does he say?", + "B", None, None), + + # L10 — opisuje_swoja_podroz (difficulty 3) + ("a2_travel_vacation_l10_q1", "a2_travel_vacation_l10", "lesson_practice", "recognition", "opisuje_swoja_podroz", 3, + "Które zdanie poprawnie opisuje podróż?", "Какое предложение правильно описывает путешествие?", "Яке речення правильно описує подорож?", "Which sentence correctly describes a trip?", + "D", None, None), + ("a2_travel_vacation_l10_q2", "a2_travel_vacation_l10", "lesson_practice", "production", "opisuje_swoja_podroz", 3, + "Przetłumacz: «Я забронировал отель в центре».", "Переведите: «Я забронировал отель в центре».", "Перекладіть: «Я забронював готель у центрі».", "Translate: “I booked a hotel in the center.”", + "Zarezerwowałem hotel w centrum", "first_letter", "Z"), + ("a2_travel_vacation_l10_q3", "a2_travel_vacation_l10", "lesson_practice", "application", "opisuje_swoja_podroz", 3, + "Chcesz opisać koledze swoją podróż: jedziesz do Polski, chcesz zwiedzać miasto, zarezerwowałeś hotel. Jak zaczniesz zdanie?", "Ты хочешь описать другу своё путешествие: ты едешь в Польшу, хочешь осматривать город, забронировал отель. Как ты начнёшь предложение?", "Ти хочеш описати другу свою подорож: ти їдеш до Польщі, хочеш оглядати місто, забронював готель. Як ти почнеш речення?", "You want to describe your trip to a friend: you're going to Poland, want to sightsee the city, booked a hotel. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t8_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_travel_vacation', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t8_a2 = [ + # L01 + ("a2_travel_vacation_l01_q1", "A", "bilet", "билет", "квиток", "ticket", False, "wrong_word"), + ("a2_travel_vacation_l01_q1", "B", "walizka", "чемодан", "валіза", "suitcase", True, None), + ("a2_travel_vacation_l01_q1", "C", "paszport", "паспорт", "паспорт", "passport", False, "wrong_word"), + ("a2_travel_vacation_l01_q1", "D", "lotnisko", "аэропорт", "аеропорт", "airport", False, "wrong_word"), + + ("a2_travel_vacation_l01_q3", "A", "Na lotnisku.", "В аэропорту.", "В аеропорту.", "At the airport.", True, None), + ("a2_travel_vacation_l01_q3", "B", "W hotelu.", "В отеле.", "У готелі.", "At the hotel.", False, "wrong_context"), + ("a2_travel_vacation_l01_q3", "C", "Na plaży.", "На пляже.", "На пляжі.", "At the beach.", False, "wrong_context"), + ("a2_travel_vacation_l01_q3", "D", "W samolocie.", "В самолёте.", "У літаку.", "On the plane.", False, "wrong_context"), + + # L02 + ("a2_travel_vacation_l02_q1", "A", "Polski", "Польши (род.)", "Польщі (род.)", "Poland (gen.)", True, None), + ("a2_travel_vacation_l02_q1", "B", "Polska", "Польша (им.)", "Польща (наз.)", "Poland (nom.)", False, "wrong_case"), + ("a2_travel_vacation_l02_q1", "C", "Polskę", "Польшу (вин.)", "Польщу (знах.)", "Poland (acc.)", False, "wrong_case"), + ("a2_travel_vacation_l02_q1", "D", "Polsce", "Польше (местн.)", "Польщі (місц.)", "Poland (loc.)", False, "wrong_case"), + + ("a2_travel_vacation_l02_q3", "A", "Jadę do Włoch.", "Я еду в Италию. (не соответствует ситуации)", "Я їду до Італії. (не відповідає ситуації)", "I'm going to Italy. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_l02_q3", "B", "Jadę do Niemiec.", "Я еду в Германию. (не соответствует ситуации)", "Я їду до Німеччини. (не відповідає ситуації)", "I'm going to Germany. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_l02_q3", "C", "Jadę do Hiszpanii.", "Я еду в Испанию.", "Я їду до Іспанії.", "I'm going to Spain.", True, None), + ("a2_travel_vacation_l02_q3", "D", "Jadę do Polski.", "Я еду в Польшу. (не соответствует ситуации)", "Я їду до Польщі. (не відповідає ситуації)", "I'm going to Poland. (doesn't match the situation)", False, "wrong_context"), + + # L03 + ("a2_travel_vacation_l03_q1", "A", "plaża", "пляж", "пляж", "beach", False, "wrong_word"), + ("a2_travel_vacation_l03_q1", "B", "góry", "горы", "гори", "mountains", False, "wrong_word"), + ("a2_travel_vacation_l03_q1", "C", "morze", "море", "море", "sea", True, None), + ("a2_travel_vacation_l03_q1", "D", "hotel", "отель", "готель", "hotel", False, "wrong_word"), + + ("a2_travel_vacation_l03_q3", "A", "Na plażę.", "На пляж.", "На пляж.", "To the beach.", True, None), + ("a2_travel_vacation_l03_q3", "B", "W góry.", "В горы.", "В гори.", "To the mountains.", False, "wrong_context"), + ("a2_travel_vacation_l03_q3", "C", "Do hotelu.", "В отель.", "До готелю.", "To the hotel.", False, "wrong_context"), + ("a2_travel_vacation_l03_q3", "D", "Do restauracji.", "В ресторан.", "До ресторану.", "To the restaurant.", False, "wrong_context"), + + # L04 + ("a2_travel_vacation_l04_q1", "A", "Chcę", "я хочу", "я хочу", "I want", True, None), + ("a2_travel_vacation_l04_q1", "B", "Chcesz", "ты хочешь (не тот человек)", "ти хочеш (не та особа)", "you want (wrong person)", False, "wrong_context"), + ("a2_travel_vacation_l04_q1", "C", "Chce", "он/она хочет (не тот человек)", "він/вона хоче (не та особа)", "he/she wants (wrong person)", False, "wrong_context"), + ("a2_travel_vacation_l04_q1", "D", "Chcieli", "они хотели (неправильное число и время)", "вони хотіли (неправильне число і час)", "they wanted (wrong number and tense)", False, "wrong_number"), + + ("a2_travel_vacation_l04_q3", "A", "Chcę zwiedzać miasto.", "Я хочу осматривать город. (не соответствует ситуации)", "Я хочу оглядати місто. (не відповідає ситуації)", "I want to sightsee the city. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_l04_q3", "B", "Chcę pływać w morzu.", "Я хочу плавать в море.", "Я хочу плавати в морі.", "I want to swim in the sea.", True, None), + ("a2_travel_vacation_l04_q3", "C", "Chcę odpoczywać w hotelu.", "Я хочу отдыхать в отеле. (не соответствует ситуации)", "Я хочу відпочивати в готелі. (не відповідає ситуації)", "I want to relax at the hotel. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_l04_q3", "D", "Lubię pływać.", "Я люблю плавать. (не о желании/плане)", "Я люблю плавати. (не про бажання/план)", "I like swimming. (not about a wish/plan)", False, "wrong_context"), + + # L05 + ("a2_travel_vacation_l05_q1", "A", "Rezerwuję", "я бронирую", "я бронюю", "I'm booking", True, None), + ("a2_travel_vacation_l05_q1", "B", "Rezerwujesz", "ты бронируешь (не тот человек)", "ти бронюєш (не та особа)", "you're booking (wrong person)", False, "wrong_context"), + ("a2_travel_vacation_l05_q1", "C", "Rezerwuje", "он/она бронирует (не тот человек)", "він/вона бронює (не та особа)", "he/she is booking (wrong person)", False, "wrong_context"), + ("a2_travel_vacation_l05_q1", "D", "Rezerwowaliśmy", "мы бронировали (неправильное число и время)", "ми бронювали (неправильне число і час)", "we were booking (wrong number and tense)", False, "wrong_number"), + + ("a2_travel_vacation_l05_q3", "A", "Rezerwuję hotel.", "Я бронирую отель. (процесс, а не результат)", "Я бронюю готель. (процес, а не результат)", "I'm booking the hotel. (process, not result)", False, "wrong_sentence_type"), + ("a2_travel_vacation_l05_q3", "B", "Zarezerwowałem hotel.", "Я забронировал отель.", "Я забронював готель.", "I booked the hotel.", True, None), + ("a2_travel_vacation_l05_q3", "C", "Będę rezerwować hotel.", "Я буду бронировать отель. (будущее время)", "Я буду бронювати готель. (майбутній час)", "I will book the hotel. (future tense)", False, "wrong_sentence_type"), + ("a2_travel_vacation_l05_q3", "D", "Chcę zarezerwować hotel.", "Я хочу забронировать отель. (ещё не сделано)", "Я хочу забронювати готель. (ще не зроблено)", "I want to book the hotel. (not done yet)", False, "wrong_context"), + + # L06 + ("a2_travel_vacation_l06_q1", "A", "zamek", "замок (вин.)", "замок (знах.)", "castle (acc.)", True, None), + ("a2_travel_vacation_l06_q1", "B", "zamku", "замка (род.)", "замку (род.)", "castle (gen.)", False, "wrong_case"), + ("a2_travel_vacation_l06_q1", "C", "zamkiem", "замком (тв.)", "замком (ор.)", "castle (instr.)", False, "wrong_case"), + ("a2_travel_vacation_l06_q1", "D", "zamkowi", "замку (дат.)", "замку (дав.)", "castle (dat.)", False, "wrong_case"), + + ("a2_travel_vacation_l06_q3", "A", "Zwiedzam stare miasto.", "Я осматриваю старый город.", "Я оглядаю старе місто.", "I'm sightseeing the old town.", True, None), + ("a2_travel_vacation_l06_q3", "B", "Mieszkam w hotelu.", "Я живу в отеле. (не соответствует ситуации)", "Я живу в готелі. (не відповідає ситуації)", "I'm staying at a hotel. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_l06_q3", "C", "Lecę samolotem.", "Я лечу самолётом. (не соответствует ситуации)", "Я лечу літаком. (не відповідає ситуації)", "I'm flying by plane. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_l06_q3", "D", "Rezerwuję pokój.", "Я бронирую номер. (не соответствует ситуации)", "Я бронюю номер. (не відповідає ситуації)", "I'm booking a room. (doesn't match the situation)", False, "wrong_context"), + + # L07 + ("a2_travel_vacation_l07_q1", "A", "drogi", "дорогой", "дорогий", "expensive", False, "wrong_word"), + ("a2_travel_vacation_l07_q1", "B", "tani", "дешёвый", "дешевий", "cheap", False, "wrong_word"), + ("a2_travel_vacation_l07_q1", "C", "ciekawy", "интересный", "цікавий", "interesting", False, "wrong_word"), + ("a2_travel_vacation_l07_q1", "D", "nudny", "скучный", "нудний", "boring", True, None), + + ("a2_travel_vacation_l07_q3", "A", "drogi", "дорогой", "дорогий", "expensive", False, "wrong_context"), + ("a2_travel_vacation_l07_q3", "B", "tani", "дешёвый", "дешевий", "cheap", True, None), + ("a2_travel_vacation_l07_q3", "C", "ciekawy", "интересный", "цікавий", "interesting", False, "wrong_context"), + ("a2_travel_vacation_l07_q3", "D", "nudny", "скучный", "нудний", "boring", False, "wrong_context"), + + # L08 + ("a2_travel_vacation_l08_q1", "A", "samolotem", "самолётом (тв.)", "літаком (ор.)", "by plane (instr.)", True, None), + ("a2_travel_vacation_l08_q1", "B", "samolot", "самолёт (им./вин.)", "літак (наз./знах.)", "plane (nom./acc.)", False, "wrong_case"), + ("a2_travel_vacation_l08_q1", "C", "samolotu", "самолёта (род.)", "літака (род.)", "plane (gen.)", False, "wrong_case"), + ("a2_travel_vacation_l08_q1", "D", "samolocie", "самолёте (местн.)", "літаку (місц.)", "plane (loc.)", False, "wrong_case"), + + ("a2_travel_vacation_l08_q3", "A", "Samolotem.", "Самолётом.", "Літаком.", "By plane.", True, None), + ("a2_travel_vacation_l08_q3", "B", "Pociągiem.", "Поездом. (не самый быстрый способ)", "Потягом. (не найшвидший спосіб)", "By train. (not the fastest way)", False, "wrong_context"), + ("a2_travel_vacation_l08_q3", "C", "Autobusem.", "Автобусом. (не самый быстрый способ)", "Автобусом. (не найшвидший спосіб)", "By bus. (not the fastest way)", False, "wrong_context"), + ("a2_travel_vacation_l08_q3", "D", "Samochodem.", "Автомобилем. (не самый быстрый способ)", "Автомобілем. (не найшвидший спосіб)", "By car. (not the fastest way)", False, "wrong_context"), + + # L09 + ("a2_travel_vacation_l09_q1", "A", "Jadę do Włoch w tym roku.", "Я еду в Италию в этом году.", "Я їду до Італії цього року.", "I'm going to Italy this year.", False, "wrong_translation"), + ("a2_travel_vacation_l09_q1", "B", "Będę jechać do Włoch w przyszłym roku.", "Я буду ехать в Италию в следующем году.", "Я буду їхати до Італії наступного року.", "I will be going to Italy next year.", False, "wrong_translation"), + ("a2_travel_vacation_l09_q1", "C", "Pojechałem do Hiszpanii w zeszłym roku.", "Я поехал в Испанию в прошлом году.", "Я поїхав до Іспанії минулого року.", "I went to Spain last year.", False, "wrong_translation"), + ("a2_travel_vacation_l09_q1", "D", "Pojechałem do Włoch w zeszłym roku.", "Я поехал в Италию в прошлом году.", "Я поїхав до Італії минулого року.", "I went to Italy last year.", True, None), + + ("a2_travel_vacation_l09_q3", "A", "Lecę samolotem do Hiszpanii.", "Я лечу самолётом в Испанию. (настоящее время)", "Я лечу літаком до Іспанії. (теперішній час)", "I'm flying to Spain by plane. (present tense)", False, "wrong_sentence_type"), + ("a2_travel_vacation_l09_q3", "B", "Poleciałem samolotem do Hiszpanii.", "Я полетел самолётом в Испанию.", "Я полетів літаком до Іспанії.", "I flew to Spain by plane.", True, None), + ("a2_travel_vacation_l09_q3", "C", "Polecę samolotem do Hiszpanii.", "Я полечу самолётом в Испанию. (будущее время)", "Я полечу літаком до Іспанії. (майбутній час)", "I will fly to Spain by plane. (future tense)", False, "wrong_sentence_type"), + ("a2_travel_vacation_l09_q3", "D", "Poleciałam samolotem do Hiszpanii.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + # L10 + ("a2_travel_vacation_l10_q1", "A", "Jadę ja do Polski ja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_travel_vacation_l10_q1", "B", "Jadę do Polska.", "Неправильный падеж.", "Неправильний відмінок.", "Wrong case.", False, "wrong_case"), + ("a2_travel_vacation_l10_q1", "C", "Jadę Polski do.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_travel_vacation_l10_q1", "D", "Jadę do Polski i chcę zwiedzać stare miasto.", "Я еду в Польшу и хочу осматривать старый город.", "Я їду до Польщі і хочу оглядати старе місто.", "I'm going to Poland and I want to sightsee the old town.", True, None), + + ("a2_travel_vacation_l10_q3", "A", "Zarezerwowałem hotel.", "Я забронировал отель. (не начало описания)", "Я забронював готель. (не початок опису)", "I booked a hotel. (not the opening line)", False, "wrong_context"), + ("a2_travel_vacation_l10_q3", "B", "Chcę zwiedzać miasto.", "Я хочу осматривать город. (не начало описания)", "Я хочу оглядати місто. (не початок опису)", "I want to sightsee the city. (not the opening line)", False, "wrong_context"), + ("a2_travel_vacation_l10_q3", "C", "Jadę do Polski.", "Я еду в Польшу.", "Я їду до Польщі.", "I'm going to Poland.", True, None), + ("a2_travel_vacation_l10_q3", "D", "Pojechałem do Polski.", "Я поехал в Польшу. (прошедшее время, не соответствует ситуации)", "Я поїхав до Польщі. (минулий час, не відповідає ситуації)", "I went to Poland. (past tense, doesn't match the situation)", False, "wrong_context"), + ] + + for opt in options_t8_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t8_a2 = [ + ("a2_travel_vacation_t01", None, "topic_test", "recognition", "podroze_vocabulary", 1, + "Jak po polsku „чемодан”?", "Как по-польски «чемодан»?", "Як польською «валіза»?", "How do you say “suitcase” in Polish?", + "B", None, None, 1), + ("a2_travel_vacation_t02", None, "topic_test", "recognition", "jechac_do", 1, + "Wybierz poprawną formę: Jadę do ___. (Polska)", "Выберите правильную форму: Jadę do ___. (Polska)", "Виберіть правильну форму: Jadę do ___. (Polska)", "Choose the correct form: Jadę do ___. (Polska)", + "A", None, None, 2), + ("a2_travel_vacation_t03", None, "topic_test", "recognition", "wakacje_vocabulary", 1, + "Jak po polsku „море”?", "Как по-польски «море»?", "Як польською «море»?", "How do you say “sea” in Polish?", + "C", None, None, 3), + ("a2_travel_vacation_t04", None, "topic_test", "recognition", "chciec_bezokolicznik", 1, + "Wybierz poprawną formę: ___ zwiedzać miasto. (chcieć, ja)", "Выберите правильную форму: ___ zwiedzać miasto. (chcieć, ja)", "Виберіть правильну форму: ___ zwiedzać miasto. (chcieć, ja)", "Choose the correct form: ___ zwiedzać miasto. (chcieć, I)", + "A", None, None, 4), + ("a2_travel_vacation_t05", None, "topic_test", "recognition", "rezerwowac_hotel", 2, + "Wybierz poprawną formę: ___ pokój w hotelu. (rezerwować, ja)", "Выберите правильную форму: ___ pokój w hotelu. (rezerwować, ja)", "Виберіть правильну форму: ___ pokój w hotelu. (rezerwować, ja)", "Choose the correct form: ___ pokój w hotelu. (rezerwować, I)", + "A", None, None, 5), + ("a2_travel_vacation_t06", None, "topic_test", "recognition", "przeszly_czas_podroz", 3, + "Co znaczy „Pojechałem do Włoch w zeszłym roku”?", "Что означает «Pojechałem do Włoch w zeszłym roku»?", "Що означає «Pojechałem do Włoch w zeszłym roku»?", "What does “Pojechałem do Włoch w zeszłym roku” mean?", + "D", None, None, 6), + + ("a2_travel_vacation_t07", None, "topic_test", "application", "podroze_vocabulary", 1, + "Jesteś w budynku, gdzie odlatują samoloty. Gdzie jesteś?", "Ты находишься в здании, откуда вылетают самолёты. Где ты?", "Ти перебуваєш у будівлі, звідки вилітають літаки. Де ти?", "You're in a building where planes take off. Where are you?", + "A", None, None, 7), + ("a2_travel_vacation_t08", None, "topic_test", "application", "jechac_do", 1, + "Kolega pyta, dokąd jedziesz na wakacje. Jedziesz do Hiszpanii. Co powiesz?", "Друг спрашивает, куда ты едешь в отпуск. Ты едешь в Испанию. Что ты скажешь?", "Друг питає, куди ти їдеш у відпустку. Ти їдеш до Іспанії. Що ти скажеш?", "A friend asks where you're going on vacation. You're going to Spain. What do you say?", + "C", None, None, 8), + ("a2_travel_vacation_t09", None, "topic_test", "application", "wakacje_vocabulary", 1, + "Chcesz odpoczywać nad wodą i opalać się. Dokąd jedziesz?", "Ты хочешь отдыхать у воды и загорать. Куда ты едешь?", "Ти хочеш відпочивати біля води і засмагати. Куди ти їдеш?", "You want to relax by the water and sunbathe. Where are you going?", + "A", None, None, 9), + ("a2_travel_vacation_t10", None, "topic_test", "application", "zwiedzac_biernik", 2, + "Jesteś na wakacjach i chcesz zobaczyć stare budynki i zabytki miasta. Co powiesz?", "Ты в отпуске и хочешь увидеть старые здания и достопримечательности города. Что ты скажешь?", "Ти у відпустці і хочеш побачити старі будівлі та пам'ятки міста. Що ти скажеш?", "You're on vacation and want to see the old buildings and landmarks of the city. What do you say?", + "A", None, None, 10), + ("a2_travel_vacation_t11", None, "topic_test", "application", "przymiotniki_podroz_vocabulary", 2, + "Kupiłeś bardzo tani bilet na samolot. Jaki on jest?", "Ты купил очень дешёвый билет на самолёт. Какой он?", "Ти купив дуже дешевий квиток на літак. Який він?", "You bought a very cheap plane ticket. What is it like?", + "B", None, None, 11), + ("a2_travel_vacation_t12", None, "topic_test", "application", "przeszly_czas_podroz", 3, + "Mężczyzna opowiada, że w zeszłym roku poleciał samolotem do Hiszpanii. Co powie?", "Мужчина рассказывает, что в прошлом году он полетел самолётом в Испанию. Что он скажет?", "Чоловік розповідає, що минулого року він полетів літаком до Іспанії. Що він скаже?", "A man is telling that last year he flew to Spain by plane. What does he say?", + "B", None, None, 12), + + ("a2_travel_vacation_t13", None, "topic_test", "production", "podroze_vocabulary", 1, + "Wpisz brakujące słowo: Mam ___. (паспорт)", "Вставьте пропущенное слово: Mam ___. (паспорт)", "Вставте пропущене слово: Mam ___. (паспорт)", "Fill in the missing word: Mam ___. (passport)", + "paszport", "first_letter", "p", 13), + ("a2_travel_vacation_t14", None, "topic_test", "production", "wakacje_vocabulary", 1, + "Wpisz brakujące słowo: Mieszkam w ___. (отеле)", "Вставьте пропущенное слово: Mieszkam w ___. (отеле)", "Вставте пропущене слово: Mieszkam w ___. (готелі)", "Fill in the missing word: Mieszkam w ___. (hotel)", + "hotelu", "first_letter", "h", 14), + ("a2_travel_vacation_t15", None, "topic_test", "production", "rezerwowac_hotel", 2, + "Wpisz brakujące słowo: ___ bilet? (ты забронировал)", "Вставьте пропущенное слово: ___ bilet? (ты забронировал)", "Вставте пропущене слово: ___ bilet? (ти забронював)", "Fill in the missing word: ___ bilet? (did you book)", + "Zarezerwowałeś", "first_letter", "Z", 15), + ("a2_travel_vacation_t16", None, "topic_test", "production", "zwiedzac_biernik", 2, + "Wpisz brakujące słowo: Zwiedzasz ___? (замок)", "Вставьте пропущенное слово: Zwiedzasz ___? (замок)", "Вставте пропущене слово: Zwiedzasz ___? (замок)", "Fill in the missing word: Zwiedzasz ___? (castle)", + "zamek", "first_letter", "z", 16), + ("a2_travel_vacation_t17", None, "topic_test", "production", "leciec_instrumental", 2, + "Wpisz brakujące słowo: Jedziesz ___? (поездом)", "Вставьте пропущенное слово: Jedziesz ___? (поездом)", "Вставте пропущене слово: Jedziesz ___? (потягом)", "Fill in the missing word: Jedziesz ___? (by train)", + "pociągiem", "first_letter", "p", 17), + ("a2_travel_vacation_t18", None, "topic_test", "production", "opisuje_swoja_podroz", 3, + "Przetłumacz: «Я забронировал отель в центре».", "Переведите: «Я забронировал отель в центре».", "Перекладіть: «Я забронював готель у центрі».", "Translate: “I booked a hotel in the center.”", + "Zarezerwowałem hotel w centrum", "first_letter", "Z", 18), + + ("a2_travel_vacation_t19", None, "topic_test", "mixed", "opisuje_swoja_podroz", 3, + "Wybierz poprawne tłumaczenie: «Я еду в Польшу, хочу осматривать старый город, и забронировал отель в центре».", "Выберите правильный перевод: «Я еду в Польшу, хочу осматривать старый город, и забронировал отель в центре».", "Виберіть правильний переклад: «Я їду до Польщі, хочу оглядати старе місто, і забронював готель у центрі».", "Choose the correct translation: “I'm going to Poland, I want to sightsee the old town, and I booked a hotel in the center.”", + "C", None, None, 19), + ("a2_travel_vacation_t20", None, "topic_test", "mixed", "rezerwowac_hotel", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Забронировал отель? — Да, забронировал очень хороший отель у моря, потому что хочу отдыхать.»", "Выберите правильный перевод диалога: «— Забронировал отель? — Да, забронировал очень хороший отель у моря, потому что хочу отдыхать.»", "Виберіть правильний переклад діалогу: «— Забронював готель? — Так, забронював дуже хороший готель біля моря, бо хочу відпочивати.»", "Choose the correct translation of the dialogue: “— Did you book a hotel? — Yes, I booked a very nice hotel by the sea, because I want to relax.”", + "C", None, None, 20), + ] + + for q in test_questions_t8_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_travel_vacation', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t8_a2 = [ + ("a2_travel_vacation_t01", "A", "bilet", "билет", "квиток", "ticket", False, "wrong_word"), + ("a2_travel_vacation_t01", "B", "walizka", "чемодан", "валіза", "suitcase", True, None), + ("a2_travel_vacation_t01", "C", "paszport", "паспорт", "паспорт", "passport", False, "wrong_word"), + ("a2_travel_vacation_t01", "D", "lotnisko", "аэропорт", "аеропорт", "airport", False, "wrong_word"), + + ("a2_travel_vacation_t02", "A", "Polski", "Польши (род.)", "Польщі (род.)", "Poland (gen.)", True, None), + ("a2_travel_vacation_t02", "B", "Polska", "Польша (им.)", "Польща (наз.)", "Poland (nom.)", False, "wrong_case"), + ("a2_travel_vacation_t02", "C", "Polskę", "Польшу (вин.)", "Польщу (знах.)", "Poland (acc.)", False, "wrong_case"), + ("a2_travel_vacation_t02", "D", "Polsce", "Польше (местн.)", "Польщі (місц.)", "Poland (loc.)", False, "wrong_case"), + + ("a2_travel_vacation_t03", "A", "plaża", "пляж", "пляж", "beach", False, "wrong_word"), + ("a2_travel_vacation_t03", "B", "góry", "горы", "гори", "mountains", False, "wrong_word"), + ("a2_travel_vacation_t03", "C", "morze", "море", "море", "sea", True, None), + ("a2_travel_vacation_t03", "D", "hotel", "отель", "готель", "hotel", False, "wrong_word"), + + ("a2_travel_vacation_t04", "A", "Chcę", "я хочу", "я хочу", "I want", True, None), + ("a2_travel_vacation_t04", "B", "Chcesz", "ты хочешь (не тот человек)", "ти хочеш (не та особа)", "you want (wrong person)", False, "wrong_context"), + ("a2_travel_vacation_t04", "C", "Chce", "он/она хочет (не тот человек)", "він/вона хоче (не та особа)", "he/she wants (wrong person)", False, "wrong_context"), + ("a2_travel_vacation_t04", "D", "Chcieli", "они хотели (неправильное число и время)", "вони хотіли (неправильне число і час)", "they wanted (wrong number and tense)", False, "wrong_number"), + + ("a2_travel_vacation_t05", "A", "Rezerwuję", "я бронирую", "я бронюю", "I'm booking", True, None), + ("a2_travel_vacation_t05", "B", "Rezerwujesz", "ты бронируешь (не тот человек)", "ти бронюєш (не та особа)", "you're booking (wrong person)", False, "wrong_context"), + ("a2_travel_vacation_t05", "C", "Rezerwuje", "он/она бронирует (не тот человек)", "він/вона бронює (не та особа)", "he/she is booking (wrong person)", False, "wrong_context"), + ("a2_travel_vacation_t05", "D", "Rezerwowaliśmy", "мы бронировали (неправильное число и время)", "ми бронювали (неправильне число і час)", "we were booking (wrong number and tense)", False, "wrong_number"), + + ("a2_travel_vacation_t06", "A", "Jadę do Włoch w tym roku.", "Я еду в Италию в этом году.", "Я їду до Італії цього року.", "I'm going to Italy this year.", False, "wrong_translation"), + ("a2_travel_vacation_t06", "B", "Będę jechać do Włoch w przyszłym roku.", "Я буду ехать в Италию в следующем году.", "Я буду їхати до Італії наступного року.", "I will be going to Italy next year.", False, "wrong_translation"), + ("a2_travel_vacation_t06", "C", "Pojechałem do Hiszpanii w zeszłym roku.", "Я поехал в Испанию в прошлом году.", "Я поїхав до Іспанії минулого року.", "I went to Spain last year.", False, "wrong_translation"), + ("a2_travel_vacation_t06", "D", "Pojechałem do Włoch w zeszłym roku.", "Я поехал в Италию в прошлом году.", "Я поїхав до Італії минулого року.", "I went to Italy last year.", True, None), + + ("a2_travel_vacation_t07", "A", "Na lotnisku.", "В аэропорту.", "В аеропорту.", "At the airport.", True, None), + ("a2_travel_vacation_t07", "B", "W hotelu.", "В отеле.", "У готелі.", "At the hotel.", False, "wrong_context"), + ("a2_travel_vacation_t07", "C", "Na plaży.", "На пляже.", "На пляжі.", "At the beach.", False, "wrong_context"), + ("a2_travel_vacation_t07", "D", "W samolocie.", "В самолёте.", "У літаку.", "On the plane.", False, "wrong_context"), + + ("a2_travel_vacation_t08", "A", "Jadę do Włoch.", "Я еду в Италию. (не соответствует ситуации)", "Я їду до Італії. (не відповідає ситуації)", "I'm going to Italy. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_t08", "B", "Jadę do Niemiec.", "Я еду в Германию. (не соответствует ситуации)", "Я їду до Німеччини. (не відповідає ситуації)", "I'm going to Germany. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_t08", "C", "Jadę do Hiszpanii.", "Я еду в Испанию.", "Я їду до Іспанії.", "I'm going to Spain.", True, None), + ("a2_travel_vacation_t08", "D", "Jadę do Polski.", "Я еду в Польшу. (не соответствует ситуации)", "Я їду до Польщі. (не відповідає ситуації)", "I'm going to Poland. (doesn't match the situation)", False, "wrong_context"), + + ("a2_travel_vacation_t09", "A", "Na plażę.", "На пляж.", "На пляж.", "To the beach.", True, None), + ("a2_travel_vacation_t09", "B", "W góry.", "В горы.", "В гори.", "To the mountains.", False, "wrong_context"), + ("a2_travel_vacation_t09", "C", "Do hotelu.", "В отель.", "До готелю.", "To the hotel.", False, "wrong_context"), + ("a2_travel_vacation_t09", "D", "Do restauracji.", "В ресторан.", "До ресторану.", "To the restaurant.", False, "wrong_context"), + + ("a2_travel_vacation_t10", "A", "Zwiedzam stare miasto.", "Я осматриваю старый город.", "Я оглядаю старе місто.", "I'm sightseeing the old town.", True, None), + ("a2_travel_vacation_t10", "B", "Mieszkam w hotelu.", "Я живу в отеле. (не соответствует ситуации)", "Я живу в готелі. (не відповідає ситуації)", "I'm staying at a hotel. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_t10", "C", "Lecę samolotem.", "Я лечу самолётом. (не соответствует ситуации)", "Я лечу літаком. (не відповідає ситуації)", "I'm flying by plane. (doesn't match the situation)", False, "wrong_context"), + ("a2_travel_vacation_t10", "D", "Rezerwuję pokój.", "Я бронирую номер. (не соответствует ситуации)", "Я бронюю номер. (не відповідає ситуації)", "I'm booking a room. (doesn't match the situation)", False, "wrong_context"), + + ("a2_travel_vacation_t11", "A", "drogi", "дорогой", "дорогий", "expensive", False, "wrong_context"), + ("a2_travel_vacation_t11", "B", "tani", "дешёвый", "дешевий", "cheap", True, None), + ("a2_travel_vacation_t11", "C", "ciekawy", "интересный", "цікавий", "interesting", False, "wrong_context"), + ("a2_travel_vacation_t11", "D", "nudny", "скучный", "нудний", "boring", False, "wrong_context"), + + ("a2_travel_vacation_t12", "A", "Lecę samolotem do Hiszpanii.", "Я лечу самолётом в Испанию. (настоящее время)", "Я лечу літаком до Іспанії. (теперішній час)", "I'm flying to Spain by plane. (present tense)", False, "wrong_sentence_type"), + ("a2_travel_vacation_t12", "B", "Poleciałem samolotem do Hiszpanii.", "Я полетел самолётом в Испанию.", "Я полетів літаком до Іспанії.", "I flew to Spain by plane.", True, None), + ("a2_travel_vacation_t12", "C", "Polecę samolotem do Hiszpanii.", "Я полечу самолётом в Испанию. (будущее время)", "Я полечу літаком до Іспанії. (майбутній час)", "I will fly to Spain by plane. (future tense)", False, "wrong_sentence_type"), + ("a2_travel_vacation_t12", "D", "Poleciałam samolotem do Hiszpanii.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + ("a2_travel_vacation_t19", "A", "Pojechałem do Polski, chciałem zwiedzać stare miasto, i zarezerwowałem hotel w centrum.", "Я поехал в Польшу, хотел осматривать старый город, и забронировал отель в центре. (прошедшее время)", "Я поїхав до Польщі, хотів оглядати старе місто, і забронював готель у центрі. (минулий час)", "I went to Poland, wanted to sightsee the old town, and booked a hotel in the center. (past tense)", False, "wrong_sentence_type"), + ("a2_travel_vacation_t19", "B", "Pojadę do Polski, będę chciał zwiedzać stare miasto, i zarezerwuję hotel w centrum.", "Я поеду в Польшу, буду хотеть осматривать старый город, и забронирую отель в центре. (будущее время)", "Я поїду до Польщі, хотітиму оглядати старе місто, і забронюю готель у центрі. (майбутній час)", "I will go to Poland, will want to sightsee the old town, and will book a hotel in the center. (future tense)", False, "wrong_sentence_type"), + ("a2_travel_vacation_t19", "C", "Jadę do Polski, chcę zwiedzać stare miasto, i zarezerwowałem hotel w centrum.", "Я еду в Польшу, хочу осматривать старый город, и забронировал отель в центре.", "Я їду до Польщі, хочу оглядати старе місто, і забронював готель у центрі.", "I'm going to Poland, I want to sightsee the old town, and I booked a hotel in the center.", True, None), + ("a2_travel_vacation_t19", "D", "Jadę do Niemiec, chcę zwiedzać stare miasto, i zarezerwowałem hotel w centrum.", "Я еду в Германию, хочу осматривать старый город, и забронировал отель в центре. (неверная страна)", "Я їду до Німеччини, хочу оглядати старе місто, і забронював готель у центрі. (невірна країна)", "I'm going to Germany, I want to sightsee the old town, and I booked a hotel in the center. (wrong country)", False, "wrong_word"), + + ("a2_travel_vacation_t20", "A", "— Rezerwujesz hotel? — Tak, rezerwuję bardzo dobry hotel nad morzem, bo chcę odpoczywać.", "— Ты бронируешь отель? — Да, я бронирую очень хороший отель у моря, потому что хочу отдыхать. (настоящее время)", "— Ти бронюєш готель? — Так, я бронюю дуже хороший готель біля моря, бо хочу відпочивати. (теперішній час)", "— Are you booking a hotel? — Yes, I'm booking a very nice hotel by the sea, because I want to relax. (present tense)", False, "wrong_sentence_type"), + ("a2_travel_vacation_t20", "B", "— Zarezerwowałeś hotel? — Nie, nie zarezerwowałem hotelu, bo nie mam pieniędzy.", "— Ты забронировал отель? — Нет, я не забронировал отель, потому что у меня нет денег. (противоположный смысл)", "— Ти забронював готель? — Ні, я не забронював готель, бо не маю грошей. (протилежний зміст)", "— Did you book a hotel? — No, I didn't book a hotel, because I don't have money. (opposite meaning)", False, "wrong_context"), + ("a2_travel_vacation_t20", "C", "— Zarezerwowałeś hotel? — Tak, zarezerwowałem bardzo dobry hotel nad morzem, bo chcę odpoczywać.", "— Ты забронировал отель? — Да, я забронировал очень хороший отель у моря, потому что хочу отдыхать.", "— Ти забронював готель? — Так, я забронював дуже хороший готель біля моря, бо хочу відпочивати.", "— Did you book a hotel? — Yes, I booked a very nice hotel by the sea, because I want to relax.", True, None), + ("a2_travel_vacation_t20", "D", "— Zarezerwowałeś bilet? — Tak, zarezerwowałem bardzo dobry hotel nad morzem, bo chcę odpoczywać.", "— Ты забронировал билет? — Да, я забронировал очень хороший отель у моря, потому что хочу отдыхать. (несоответствие вопроса и ответа)", "— Ти забронював квиток? — Так, я забронював дуже хороший готель біля моря, бо хочу відпочивати. (невідповідність питання і відповіді)", "— Did you book a ticket? — Yes, I booked a very nice hotel by the sea, because I want to relax. (mismatched question and answer)", False, "wrong_word"), + ] + + for opt in test_options_t8_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 9 (A2): SPORT I AKTYWNOŚĆ ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_sport_activity', 'A2', 9, + 'Sport i aktywność', + 'Спорт и активность', + 'Спорт та активність', + 'Sport and Activity') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t9_a2 = [ + ("a2_sport_activity_l01", 1, "sport_vocabulary", "Podstawowe słowa: sport", "Основные слова: спорт", "Основні слова: спорт", "Basic words: sport", + "Podstawowe słowa: piłka, boisko, basen, siłownia.", + "Основные слова: piłka (мяч), boisko (поле), basen (бассейн), siłownia (тренажёрный зал).", + "Основні слова: piłka (м'яч), boisko (поле), basen (басейн), siłownia (тренажерна зала).", + "Basic words: piłka (ball), boisko (field), basen (pool), siłownia (gym)."), + + ("a2_sport_activity_l02", 2, "grac_w_bierniku", "Grać w + biernik", "Grać w + винительный падеж", "Grać w + знахідний відмінок", "Grać w + accusative", + "Czasownik „grać” + „w” + biernik dyscypliny sportowej: gram w piłkę nożną, grasz w koszykówkę, gra w tenisa.", + "Глагол „grać” (играть) + „w” + винительный падеж вида спорта: gram w piłkę nożną (я играю в футбол), grasz w koszykówkę (ты играешь в баскетбол), gra w tenisa (он/она играет в теннис).", + "Дієслово „grać” (грати) + „w” + знахідний відмінок виду спорту: gram w piłkę nożną (я граю у футбол), grasz w koszykówkę (ти граєш у баскетбол), gra w tenisa (він/вона грає в теніс).", + "The verb „grać” (to play) + „w” + accusative of the sport: gram w piłkę nożną (I play soccer), grasz w koszykówkę (you play basketball), gra w tenisa (he/she plays tennis)."), + + ("a2_sport_activity_l03", 3, "aktywnosc_vocabulary", "Podstawowe słowa: aktywność", "Основные слова: активность", "Основні слова: активність", "Basic words: activity", + "Podstawowe słowa: bieganie, pływanie, jazda na rowerze, joga.", + "Основные слова: bieganie (бег), pływanie (плавание), jazda na rowerze (езда на велосипеде), joga (йога).", + "Основні слова: bieganie (біг), pływanie (плавання), jazda na rowerze (їзда на велосипеді), joga (йога).", + "Basic words: bieganie (running), pływanie (swimming), jazda na rowerze (cycling), joga (yoga)."), + + ("a2_sport_activity_l04", 4, "lubic_bezokolicznik", "Lubić + bezokolicznik", "Lubić + инфинитив", "Lubić + інфінітив", "Lubić + infinitive", + "Czasownik „lubić” + bezokolicznik wyraża upodobanie do czynności: lubię biegać, lubisz pływać, lubi jeździć na rowerze.", + "Глагол „lubić” (любить) + инфинитив выражает предпочтение к действию: lubię biegać (я люблю бегать), lubisz pływać (ты любишь плавать), lubi jeździć na rowerze (он/она любит кататься на велосипеде).", + "Дієслово „lubić” (любити) + інфінітив виражає уподобання до дії: lubię biegać (я люблю бігати), lubisz pływać (ти любиш плавати), lubi jeździć na rowerze (він/вона любить їздити на велосипеді).", + "The verb „lubić” (to like) + infinitive expresses a preference for an activity: lubię biegać (I like running), lubisz pływać (you like swimming), lubi jeździć na rowerze (he/she likes riding a bike)."), + + ("a2_sport_activity_l05", 5, "trenowac_biernik", "Trenować + biernik", "Trenować + винительный падеж", "Trenować + знахідний відмінок", "Trenować + accusative", + "Czasownik „trenować” + biernik dyscypliny: trenuję piłkę nożną, trenujesz koszykówkę, trenuje tenis.", + "Глагол „trenować” (тренировать/заниматься) + винительный падеж вида спорта: trenuję piłkę nożną (я тренирую футбол), trenujesz koszykówkę (ты тренируешь баскетбол), trenuje tenis (он/она тренирует теннис).", + "Дієслово „trenować” (тренувати/займатися) + знахідний відмінок виду спорту: trenuję piłkę nożną (я треную футбол), trenujesz koszykówkę (ти тренуєш баскетбол), trenuje tenis (він/вона тренує теніс).", + "The verb „trenować” (to train) + accusative of the sport: trenuję piłkę nożną (I train soccer), trenujesz koszykówkę (you train basketball), trenuje tenis (he/she trains tennis)."), + + ("a2_sport_activity_l06", 6, "chodzic_na_silownie", "Chodzić na + biernik", "Chodzić na + винительный падеж", "Chodzić na + знахідний відмінок", "Chodzić na + accusative", + "Czasownik „chodzić” + „na” + biernik: chodzę na siłownię, chodzisz na basen, chodzi na jogę.", + "Глагол „chodzić” (ходить) + „na” + винительный падеж: chodzę na siłownię (я хожу в тренажёрный зал), chodzisz na basen (ты ходишь в бассейн), chodzi na jogę (он/она ходит на йогу).", + "Дієслово „chodzić” (ходити) + „na” + знахідний відмінок: chodzę na siłownię (я ходжу в тренажерну залу), chodzisz na basen (ти ходиш у басейн), chodzi na jogę (він/вона ходить на йогу).", + "The verb „chodzić” (to go regularly) + „na” + accusative: chodzę na siłownię (I go to the gym), chodzisz na basen (you go to the pool), chodzi na jogę (he/she goes to yoga)."), + + ("a2_sport_activity_l07", 7, "przymiotniki_sport_vocabulary", "Podstawowe słowa: przymiotniki sportowe", "Основные слова: спортивные прилагательные", "Основні слова: спортивні прикметники", "Basic words: sport adjectives", + "Podstawowe przymiotniki opisujące formę fizyczną: silny, szybki, wytrzymały, zmęczony.", + "Основные прилагательные, описывающие физическую форму: silny (сильный), szybki (быстрый), wytrzymały (выносливый), zmęczony (уставший).", + "Основні прикметники, що описують фізичну форму: silny (сильний), szybki (швидкий), wytrzymały (витривалий), zmęczony (втомлений).", + "Basic adjectives describing physical condition: silny (strong), szybki (fast), wytrzymały (enduring), zmęczony (tired)."), + + ("a2_sport_activity_l08", 8, "umiec_grac", "Umieć + bezokolicznik", "Umieć + инфинитив", "Umieć + інфінітив", "Umieć + infinitive", + "Czasownik „umieć” + bezokolicznik wyraża umiejętność sportową: umiem grać w tenisa, umiesz pływać, umie jeździć na rowerze.", + "Глагол „umieć” (уметь) + инфинитив выражает спортивный навык: umiem grać w tenisa (я умею играть в теннис), umiesz pływać (ты умеешь плавать), umie jeździć na rowerze (он/она умеет кататься на велосипеде).", + "Дієслово „umieć” (уміти) + інфінітив виражає спортивну навичку: umiem grać w tenisa (я вмію грати в теніс), umiesz pływać (ти вмієш плавати), umie jeździć na rowerze (він/вона вміє їздити на велосипеді).", + "The verb „umieć” (to know how to) + infinitive expresses a sport skill: umiem grać w tenisa (I know how to play tennis), umiesz pływać (you know how to swim), umie jeździć na rowerze (he/she knows how to ride a bike)."), + + ("a2_sport_activity_l09", 9, "przeszly_czas_sport", "Biegałem/biegałam, wygrałem/wygrałam (przeszłość)", "Biegałem/biegałam, wygrałem/wygrałam (прошедшее)", "Biegałem/biegałam, wygrałem/wygrałam (минулий час)", "Biegałem/biegałam, wygrałem/wygrałam (past)", + "Czas przeszły sportu tworzymy „biegałem/biegałam” (proces) lub „wygrałem/wygrałam” (dokonany, sukces) zależnie od rodzaju mówiącego: biegałem codziennie, wygrałaś mecz, trenował pięć lat.", + "Прошедшее время спорта образуем „biegałem/biegałam” (процесс) или „wygrałem/wygrałam” (совершенный вид, успех) в зависимости от рода говорящего: biegałem codziennie (я бегал каждый день), wygrałaś mecz (ты выиграла матч), trenował pięć lat (он тренировал пять лет).", + "Минулий час спорту утворюємо „biegałem/biegałam” (процес) або „wygrałem/wygrałam” (доконаний вид, успіх) залежно від роду мовця: biegałem codziennie (я бігав щодня), wygrałaś mecz (ти виграла матч), trenował pięć lat (він тренував п'ять років).", + "We form the past tense of sport with „biegałem/biegałam” (imperfective) or „wygrałem/wygrałam” (perfective, success) depending on the speaker's gender: biegałem codziennie (I ran every day), wygrałaś mecz (you won the match), trenował pięć lat (he trained for five years)."), + + ("a2_sport_activity_l10", 10, "opisuje_swoja_aktywnosc", "Opisuję swoją aktywność", "Описываю свою активность", "Описую свою активність", "Describing my activity", + "Żeby opisać aktywność sportową, łączymy zdania: Lubię biegać rano. Chodzę na siłownię trzy razy w tygodniu. Wygrałem swój pierwszy mecz.", + "Чтобы описать спортивную активность, соединяем предложения: Lubię biegać rano. Chodzę na siłownię trzy razy w tygodniu. Wygrałem swój pierwszy mecz. (Я люблю бегать утром. Я хожу в тренажёрный зал три раза в неделю. Я выиграл свой первый матч.)", + "Щоб описати спортивну активність, поєднуємо речення: Lubię biegać rano. Chodzę na siłownię trzy razy w tygodniu. Wygrałem swój pierwszy mecz. (Я люблю бігати вранці. Я ходжу в тренажерну залу три рази на тиждень. Я виграв свій перший матч.)", + "To describe a sport activity, we combine sentences: Lubię biegać rano. Chodzę na siłownię trzy razy w tygodniu. Wygrałem swój pierwszy mecz. (I like running in the morning. I go to the gym three times a week. I won my first match.)"), + ] + + for lesson in lessons_t9_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_sport_activity', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t9_a2 = [ + ("a2_sport_activity_l01", 1, "Mam nową piłkę.", "У меня новый мяч.", "У мене новий м'яч.", "I have a new ball."), + ("a2_sport_activity_l01", 2, "Gramy na boisku.", "Мы играем на поле.", "Ми граємо на полі.", "We're playing on the field."), + ("a2_sport_activity_l01", 3, "Pływam na basenie.", "Я плаваю в бассейне.", "Я плаваю в басейні.", "I swim at the pool."), + + ("a2_sport_activity_l02", 1, "Gram w piłkę nożną.", "Я играю в футбол.", "Я граю у футбол.", "I play soccer."), + ("a2_sport_activity_l02", 2, "Grasz w koszykówkę?", "Ты играешь в баскетбол?", "Ти граєш у баскетбол?", "Do you play basketball?"), + ("a2_sport_activity_l02", 3, "On gra w tenisa.", "Он играет в теннис.", "Він грає в теніс.", "He plays tennis."), + + ("a2_sport_activity_l03", 1, "Uprawiam bieganie.", "Я занимаюсь бегом.", "Я займаюся бігом.", "I do running."), + ("a2_sport_activity_l03", 2, "Lubię pływanie.", "Я люблю плавание.", "Я люблю плавання.", "I like swimming."), + ("a2_sport_activity_l03", 3, "Jazda na rowerze to dobra aktywność.", "Езда на велосипеде — хорошая активность.", "Їзда на велосипеді — хороша активність.", "Cycling is a good activity."), + + ("a2_sport_activity_l04", 1, "Lubię biegać rano.", "Я люблю бегать утром.", "Я люблю бігати вранці.", "I like running in the morning."), + ("a2_sport_activity_l04", 2, "Lubisz pływać w morzu?", "Ты любишь плавать в море?", "Ти любиш плавати в морі?", "Do you like swimming in the sea?"), + ("a2_sport_activity_l04", 3, "Ona lubi jeździć na rowerze.", "Она любит кататься на велосипеде.", "Вона любить їздити на велосипеді.", "She likes riding a bike."), + + ("a2_sport_activity_l05", 1, "Trenuję piłkę nożną od dziecka.", "Я тренирую футбол с детства.", "Я треную футбол з дитинства.", "I've been training soccer since childhood."), + ("a2_sport_activity_l05", 2, "Trenujesz koszykówkę codziennie?", "Ты тренируешь баскетбол каждый день?", "Ти тренуєш баскетбол щодня?", "Do you train basketball every day?"), + ("a2_sport_activity_l05", 3, "Ona trenuje tenis w klubie.", "Она тренирует теннис в клубе.", "Вона тренує теніс у клубі.", "She trains tennis at a club."), + + ("a2_sport_activity_l06", 1, "Chodzę na siłownię trzy razy w tygodniu.", "Я хожу в тренажёрный зал три раза в неделю.", "Я ходжу в тренажерну залу три рази на тиждень.", "I go to the gym three times a week."), + ("a2_sport_activity_l06", 2, "Chodzisz na basen w weekendy?", "Ты ходишь в бассейн по выходным?", "Ти ходиш у басейн у вихідні?", "Do you go to the pool on weekends?"), + ("a2_sport_activity_l06", 3, "On chodzi na jogę po pracy.", "Он ходит на йогу после работы.", "Він ходить на йогу після роботи.", "He goes to yoga after work."), + + ("a2_sport_activity_l07", 1, "On jest bardzo silny.", "Он очень сильный.", "Він дуже сильний.", "He is very strong."), + ("a2_sport_activity_l07", 2, "Ona biega szybko, jest szybka.", "Она бегает быстро, она быстрая.", "Вона бігає швидко, вона швидка.", "She runs fast, she's fast."), + ("a2_sport_activity_l07", 3, "Jestem zmęczony po treningu.", "Я устал после тренировки.", "Я втомлений після тренування.", "I'm tired after training."), + + ("a2_sport_activity_l08", 1, "Umiem grać w tenisa.", "Я умею играть в теннис.", "Я вмію грати в теніс.", "I know how to play tennis."), + ("a2_sport_activity_l08", 2, "Umiesz pływać?", "Ты умеешь плавать?", "Ти вмієш плавати?", "Do you know how to swim?"), + ("a2_sport_activity_l08", 3, "On umie jeździć na rowerze.", "Он умеет кататься на велосипеде.", "Він вміє їздити на велосипеді.", "He knows how to ride a bike."), + + ("a2_sport_activity_l09", 1, "Biegałem codziennie w zeszłym miesiącu.", "Я бегал каждый день в прошлом месяце.", "Я бігав щодня минулого місяця.", "I ran every day last month."), + ("a2_sport_activity_l09", 2, "Wygrałaś ten mecz?", "Ты выиграла этот матч?", "Ти виграла цей матч?", "Did you win that match?"), + ("a2_sport_activity_l09", 3, "On trenował piłkę nożną przez pięć lat.", "Он тренировал футбол пять лет.", "Він тренував футбол п'ять років.", "He trained soccer for five years."), + + ("a2_sport_activity_l10", 1, "Lubię biegać rano.", "Я люблю бегать утром.", "Я люблю бігати вранці.", "I like running in the morning."), + ("a2_sport_activity_l10", 2, "Chodzę na siłownię trzy razy w tygodniu.", "Я хожу в тренажёрный зал три раза в неделю.", "Я ходжу в тренажерну залу три рази на тиждень.", "I go to the gym three times a week."), + ("a2_sport_activity_l10", 3, "Wygrałem swój pierwszy mecz.", "Я выиграл свой первый матч.", "Я виграв свій перший матч.", "I won my first match."), + ] + + for ex in examples_t9_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t9_a2 = [ + # L01 — sport_vocabulary (difficulty 1) + ("a2_sport_activity_l01_q1", "a2_sport_activity_l01", "lesson_practice", "recognition", "sport_vocabulary", 1, + "Jak po polsku „тренажёрный зал”?", "Как по-польски «тренажёрный зал»?", "Як польською «тренажерна зала»?", "How do you say “gym” in Polish?", + "D", None, None), + ("a2_sport_activity_l01_q2", "a2_sport_activity_l01", "lesson_practice", "production", "sport_vocabulary", 1, + "Wpisz brakujące słowo: Pływam na ___. (бассейне)", "Вставьте пропущенное слово: Pływam na ___. (бассейне)", "Вставте пропущене слово: Pływam na ___. (басейні)", "Fill in the missing word: Pływam na ___. (pool)", + "basenie", "first_letter", "b"), + ("a2_sport_activity_l01_q3", "a2_sport_activity_l01", "lesson_practice", "application", "sport_vocabulary", 1, + "Chcesz podnosić ciężary i ćwiczyć mięśnie w budynku ze sprzętem sportowym. Dokąd idziesz?", "Ты хочешь поднимать тяжести и качать мышцы в здании со спортивным оборудованием. Куда ты идёшь?", "Ти хочеш піднімати важкі ваги і качати м'язи в будівлі зі спортивним обладнанням. Куди ти йдеш?", "You want to lift weights and work out in a building with sports equipment. Where are you going?", + "C", None, None), + + # L02 — grac_w_bierniku (difficulty 1) + ("a2_sport_activity_l02_q1", "a2_sport_activity_l02", "lesson_practice", "recognition", "grac_w_bierniku", 1, + "Wybierz poprawną formę: Gram w ___. (piłka nożna)", "Выберите правильную форму: Gram w ___. (piłka nożna)", "Виберіть правильну форму: Gram w ___. (piłka nożna)", "Choose the correct form: Gram w ___. (piłka nożna)", + "A", None, None), + ("a2_sport_activity_l02_q2", "a2_sport_activity_l02", "lesson_practice", "production", "grac_w_bierniku", 1, + "Wpisz brakujące słowo: Grasz w ___? (баскетбол)", "Вставьте пропущенное слово: Grasz w ___? (баскетбол)", "Вставте пропущене слово: Grasz w ___? (баскетбол)", "Fill in the missing word: Grasz w ___? (basketball)", + "koszykówkę", "first_letter", "k"), + ("a2_sport_activity_l02_q3", "a2_sport_activity_l02", "lesson_practice", "application", "grac_w_bierniku", 1, + "Kolega pyta, w co grasz w wolnym czasie. Grasz w tenisa. Co powiesz?", "Друг спрашивает, во что ты играешь в свободное время. Ты играешь в теннис. Что ты скажешь?", "Друг питає, у що ти граєш у вільний час. Ти граєш у теніс. Що ти скажеш?", "A friend asks what you play in your free time. You play tennis. What do you say?", + "C", None, None), + + # L03 — aktywnosc_vocabulary (difficulty 1) + ("a2_sport_activity_l03_q1", "a2_sport_activity_l03", "lesson_practice", "recognition", "aktywnosc_vocabulary", 1, + "Jak po polsku „йога”?", "Как по-польски «йога»?", "Як польською «йога»?", "How do you say “yoga” in Polish?", + "D", None, None), + ("a2_sport_activity_l03_q2", "a2_sport_activity_l03", "lesson_practice", "production", "aktywnosc_vocabulary", 1, + "Wpisz brakujące słowo: Lubię ___. (плавание)", "Вставьте пропущенное слово: Lubię ___. (плавание)", "Вставте пропущене слово: Lubię ___. (плавання)", "Fill in the missing word: Lubię ___. (swimming)", + "pływanie", "first_letter", "p"), + ("a2_sport_activity_l03_q3", "a2_sport_activity_l03", "lesson_practice", "application", "aktywnosc_vocabulary", 1, + "Chcesz się zrelaksować i poprawić elastyczność ciała spokojnymi ćwiczeniami. Co wybierasz?", "Ты хочешь расслабиться и улучшить гибкость тела спокойными упражнениями. Что ты выбираешь?", "Ти хочеш розслабитися і покращити гнучкість тіла спокійними вправами. Що ти обираєш?", "You want to relax and improve your flexibility with calm exercises. What do you choose?", + "D", None, None), + + # L04 — lubic_bezokolicznik (difficulty 1) + ("a2_sport_activity_l04_q1", "a2_sport_activity_l04", "lesson_practice", "recognition", "lubic_bezokolicznik", 1, + "Wybierz poprawną formę: ___ biegać rano. (lubić, ja)", "Выберите правильную форму: ___ biegać rano. (lubić, ja)", "Виберіть правильну форму: ___ biegać rano. (lubić, ja)", "Choose the correct form: ___ biegać rano. (lubić, I)", + "A", None, None), + ("a2_sport_activity_l04_q2", "a2_sport_activity_l04", "lesson_practice", "production", "lubic_bezokolicznik", 1, + "Wpisz brakujące słowo: ___ pływać? (ты любишь)", "Вставьте пропущенное слово: ___ pływać? (ты любишь)", "Вставте пропущене слово: ___ pływać? (ти любиш)", "Fill in the missing word: ___ pływać? (do you like)", + "Lubisz", "first_letter", "L"), + ("a2_sport_activity_l04_q3", "a2_sport_activity_l04", "lesson_practice", "application", "lubic_bezokolicznik", 1, + "Codziennie rano wychodzisz biegać, bo sprawia ci to przyjemność. Co powiesz?", "Каждое утро ты выходишь бегать, потому что тебе это нравится. Что ты скажешь?", "Щоранку ти виходиш бігати, бо це приносить тобі задоволення. Що ти скажеш?", "Every morning you go running because you enjoy it. What do you say?", + "A", None, None), + + # L05 — trenowac_biernik (difficulty 2) + ("a2_sport_activity_l05_q1", "a2_sport_activity_l05", "lesson_practice", "recognition", "trenowac_biernik", 2, + "Wybierz poprawną formę: ___ piłkę nożną. (trenować, ja)", "Выберите правильную форму: ___ piłkę nożną. (trenować, ja)", "Виберіть правильну форму: ___ piłkę nożną. (trenować, ja)", "Choose the correct form: ___ piłkę nożną. (trenować, I)", + "A", None, None), + ("a2_sport_activity_l05_q2", "a2_sport_activity_l05", "lesson_practice", "production", "trenowac_biernik", 2, + "Wpisz brakujące słowo: ___ koszykówkę codziennie? (ты тренируешь)", "Вставьте пропущенное слово: ___ koszykówkę codziennie? (ты тренируешь)", "Вставте пропущене слово: ___ koszykówkę codziennie? (ти тренуєш)", "Fill in the missing word: ___ koszykówkę codziennie? (do you train)", + "Trenujesz", "first_letter", "T"), + ("a2_sport_activity_l05_q3", "a2_sport_activity_l05", "lesson_practice", "application", "trenowac_biernik", 2, + "Chcesz opowiedzieć, że regularnie ćwiczysz tenis w klubie sportowym. Co powiesz?", "Ты хочешь рассказать, что регулярно занимаешься теннисом в спортивном клубе. Что ты скажешь?", "Ти хочеш розповісти, що регулярно займаєшся тенісом у спортивному клубі. Що ти скажеш?", "You want to say that you regularly practice tennis at a sports club. What do you say?", + "A", None, None), + + # L06 — chodzic_na_silownie (difficulty 2) + ("a2_sport_activity_l06_q1", "a2_sport_activity_l06", "lesson_practice", "recognition", "chodzic_na_silownie", 2, + "Wybierz poprawną formę: Chodzę ___ siłownię. (na)", "Выберите правильную форму: Chodzę ___ siłownię. (na)", "Виберіть правильну форму: Chodzę ___ siłownię. (na)", "Choose the correct form: Chodzę ___ siłownię. (na)", + "A", None, None), + ("a2_sport_activity_l06_q2", "a2_sport_activity_l06", "lesson_practice", "production", "chodzic_na_silownie", 2, + "Wpisz brakujące słowo: Chodzisz na ___? (бассейн)", "Вставьте пропущенное слово: Chodzisz na ___? (бассейн)", "Вставте пропущене слово: Chodzisz na ___? (басейн)", "Fill in the missing word: Chodzisz na ___? (pool)", + "basen", "first_letter", "b"), + ("a2_sport_activity_l06_q3", "a2_sport_activity_l06", "lesson_practice", "application", "chodzic_na_silownie", 2, + "Regularnie uczestniczysz w zajęciach jogi po pracy. Co powiesz?", "Ты регулярно посещаешь занятия йогой после работы. Что ты скажешь?", "Ти регулярно відвідуєш заняття йогою після роботи. Що ти скажеш?", "You regularly attend yoga classes after work. What do you say?", + "A", None, None), + + # L07 — przymiotniki_sport_vocabulary (difficulty 2) + ("a2_sport_activity_l07_q1", "a2_sport_activity_l07", "lesson_practice", "recognition", "przymiotniki_sport_vocabulary", 2, + "Jak po polsku „выносливый”?", "Как по-польски «выносливый»?", "Як польською «витривалий»?", "How do you say “enduring” in Polish?", + "C", None, None), + ("a2_sport_activity_l07_q2", "a2_sport_activity_l07", "lesson_practice", "production", "przymiotniki_sport_vocabulary", 2, + "Wpisz brakujące słowo: Jestem ___ po treningu. (уставший)", "Вставьте пропущенное слово: Jestem ___ po treningu. (уставший)", "Вставте пропущене слово: Jestem ___ po treningu. (втомлений)", "Fill in the missing word: Jestem ___ po treningu. (tired)", + "zmęczony", "first_letter", "z"), + ("a2_sport_activity_l07_q3", "a2_sport_activity_l07", "lesson_practice", "application", "przymiotniki_sport_vocabulary", 2, + "Właśnie skończyłeś ciężki trening i czujesz brak energii. Co powiesz?", "Ты только что закончил тяжёлую тренировку и чувствуешь нехватку энергии. Что ты скажешь?", "Ти щойно закінчив важке тренування і відчуваєш брак енергії. Що ти скажеш?", "You just finished a hard workout and feel out of energy. What do you say?", + "D", None, None), + + # L08 — umiec_grac (difficulty 2) + ("a2_sport_activity_l08_q1", "a2_sport_activity_l08", "lesson_practice", "recognition", "umiec_grac", 2, + "Wybierz poprawną formę: ___ grać w tenisa. (umieć, ja)", "Выберите правильную форму: ___ grać w tenisa. (umieć, ja)", "Виберіть правильну форму: ___ grać w tenisa. (umieć, ja)", "Choose the correct form: ___ grać w tenisa. (umieć, I)", + "A", None, None), + ("a2_sport_activity_l08_q2", "a2_sport_activity_l08", "lesson_practice", "production", "umiec_grac", 2, + "Wpisz brakujące słowo: ___ pływać? (ты умеешь)", "Вставьте пропущенное слово: ___ pływać? (ты умеешь)", "Вставте пропущене слово: ___ pływać? (ти вмієш)", "Fill in the missing word: ___ pływać? (do you know how to)", + "Umiesz", "first_letter", "U"), + ("a2_sport_activity_l08_q3", "a2_sport_activity_l08", "lesson_practice", "application", "umiec_grac", 2, + "Nauczyłeś się już jeździć na rowerze i możesz to robić bez problemu. Co powiesz?", "Ты уже научился кататься на велосипеде и можешь делать это без проблем. Что ты скажешь?", "Ти вже навчився їздити на велосипеді і можеш робити це без проблем. Що ти скажеш?", "You've already learned to ride a bike and can do it without a problem. What do you say?", + "A", None, None), + + # L09 — przeszly_czas_sport (difficulty 3) + ("a2_sport_activity_l09_q1", "a2_sport_activity_l09", "lesson_practice", "recognition", "przeszly_czas_sport", 3, + "Co znaczy „Wygrałaś ten mecz”?", "Что означает «Wygrałaś ten mecz»?", "Що означає «Wygrałaś ten mecz»?", "What does “Wygrałaś ten mecz” mean?", + "D", None, None), + ("a2_sport_activity_l09_q2", "a2_sport_activity_l09", "lesson_practice", "production", "przeszly_czas_sport", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ codziennie w zeszłym miesiącu. (я бегала)", "Вставьте пропущенное слово (говорит женщина): ___ codziennie w zeszłym miesiącu. (я бегала)", "Вставте пропущене слово (говорить жінка): ___ codziennie w zeszłym miesiącu. (я бігала)", "Fill in the missing word (a woman is speaking): ___ codziennie w zeszłym miesiącu. (I ran)", + "Biegałam", "first_letter", "B"), + ("a2_sport_activity_l09_q3", "a2_sport_activity_l09", "lesson_practice", "application", "przeszly_czas_sport", 3, + "Mężczyzna opowiada, że trenował piłkę nożną przez pięć lat, ale już przestał. Co powie?", "Мужчина рассказывает, что тренировал футбол пять лет, но уже перестал. Что он скажет?", "Чоловік розповідає, що тренував футбол п'ять років, але вже перестав. Що він скаже?", "A man is telling that he trained soccer for five years, but has already stopped. What does he say?", + "B", None, None), + + # L10 — opisuje_swoja_aktywnosc (difficulty 3) + ("a2_sport_activity_l10_q1", "a2_sport_activity_l10", "lesson_practice", "recognition", "opisuje_swoja_aktywnosc", 3, + "Które zdanie poprawnie opisuje aktywność?", "Какое предложение правильно описывает активность?", "Яке речення правильно описує активність?", "Which sentence correctly describes an activity?", + "D", None, None), + ("a2_sport_activity_l10_q2", "a2_sport_activity_l10", "lesson_practice", "production", "opisuje_swoja_aktywnosc", 3, + "Przetłumacz: «Я выиграл свой первый матч».", "Переведите: «Я выиграл свой первый матч».", "Перекладіть: «Я виграв свій перший матч».", "Translate: “I won my first match.”", + "Wygrałem swój pierwszy mecz", "first_letter", "W"), + ("a2_sport_activity_l10_q3", "a2_sport_activity_l10", "lesson_practice", "application", "opisuje_swoja_aktywnosc", 3, + "Chcesz opisać koledze swoją aktywność: lubisz biegać, chodzisz na siłownię, wygrałeś mecz. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою активность: ты любишь бегать, ходишь в тренажёрный зал, выиграл матч. Как ты начнёшь предложение?", "Ти хочеш описати другу свою активність: ти любиш бігати, ходиш у тренажерну залу, виграв матч. Як ти почнеш речення?", "You want to describe your activity to a friend: you like running, go to the gym, won a match. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t9_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_sport_activity', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t9_a2 = [ + # L01 + ("a2_sport_activity_l01_q1", "A", "piłka", "мяч", "м'яч", "ball", False, "wrong_word"), + ("a2_sport_activity_l01_q1", "B", "boisko", "поле", "поле", "field", False, "wrong_word"), + ("a2_sport_activity_l01_q1", "C", "basen", "бассейн", "басейн", "pool", False, "wrong_word"), + ("a2_sport_activity_l01_q1", "D", "siłownia", "тренажёрный зал", "тренажерна зала", "gym", True, None), + + ("a2_sport_activity_l01_q3", "A", "Na boisko.", "На поле.", "На поле.", "To the field.", False, "wrong_context"), + ("a2_sport_activity_l01_q3", "B", "Na basen.", "В бассейн.", "У басейн.", "To the pool.", False, "wrong_context"), + ("a2_sport_activity_l01_q3", "C", "Na siłownię.", "В тренажёрный зал.", "У тренажерну залу.", "To the gym.", True, None), + ("a2_sport_activity_l01_q3", "D", "Na plażę.", "На пляж.", "На пляж.", "To the beach.", False, "wrong_context"), + + # L02 + ("a2_sport_activity_l02_q1", "A", "piłkę nożną", "футбол (вин.)", "футбол (знах.)", "soccer (acc.)", True, None), + ("a2_sport_activity_l02_q1", "B", "piłka nożna", "футбол (им.)", "футбол (наз.)", "soccer (nom.)", False, "wrong_case"), + ("a2_sport_activity_l02_q1", "C", "piłki nożnej", "футбола (род.)", "футболу (род.)", "soccer (gen.)", False, "wrong_case"), + ("a2_sport_activity_l02_q1", "D", "piłce nożnej", "футболу (местн./дат.)", "футболу (місц./дав.)", "soccer (loc./dat.)", False, "wrong_case"), + + ("a2_sport_activity_l02_q3", "A", "Gram w piłkę nożną.", "Я играю в футбол. (не соответствует ситуации)", "Я граю у футбол. (не відповідає ситуації)", "I play soccer. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l02_q3", "B", "Gram w koszykówkę.", "Я играю в баскетбол. (не соответствует ситуации)", "Я граю у баскетбол. (не відповідає ситуації)", "I play basketball. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l02_q3", "C", "Gram w tenisa.", "Я играю в теннис.", "Я граю в теніс.", "I play tennis.", True, None), + ("a2_sport_activity_l02_q3", "D", "Gram w siatkówkę.", "Я играю в волейбол. (не соответствует ситуации)", "Я граю в волейбол. (не відповідає ситуації)", "I play volleyball. (doesn't match the situation)", False, "wrong_context"), + + # L03 + ("a2_sport_activity_l03_q1", "A", "bieganie", "бег", "біг", "running", False, "wrong_word"), + ("a2_sport_activity_l03_q1", "B", "pływanie", "плавание", "плавання", "swimming", False, "wrong_word"), + ("a2_sport_activity_l03_q1", "C", "jazda na rowerze", "езда на велосипеде", "їзда на велосипеді", "cycling", False, "wrong_word"), + ("a2_sport_activity_l03_q1", "D", "joga", "йога", "йога", "yoga", True, None), + + ("a2_sport_activity_l03_q3", "A", "Bieganie.", "Бег. (не спокойное упражнение)", "Біг. (не спокійна вправа)", "Running. (not a calm exercise)", False, "wrong_context"), + ("a2_sport_activity_l03_q3", "B", "Pływanie.", "Плавание. (не о гибкости)", "Плавання. (не про гнучкість)", "Swimming. (not about flexibility)", False, "wrong_context"), + ("a2_sport_activity_l03_q3", "C", "Jazdę na rowerze.", "Езду на велосипеде. (не спокойное упражнение)", "Їзду на велосипеді. (не спокійна вправа)", "Cycling. (not a calm exercise)", False, "wrong_context"), + ("a2_sport_activity_l03_q3", "D", "Jogę.", "Йогу.", "Йогу.", "Yoga.", True, None), + + # L04 + ("a2_sport_activity_l04_q1", "A", "Lubię", "я люблю", "я люблю", "I like", True, None), + ("a2_sport_activity_l04_q1", "B", "Lubisz", "ты любишь (не тот человек)", "ти любиш (не та особа)", "you like (wrong person)", False, "wrong_context"), + ("a2_sport_activity_l04_q1", "C", "Lubi", "он/она любит (не тот человек)", "він/вона любить (не та особа)", "he/she likes (wrong person)", False, "wrong_context"), + ("a2_sport_activity_l04_q1", "D", "Lubili", "они любили (неправильное число и время)", "вони любили (неправильне число і час)", "they liked (wrong number and tense)", False, "wrong_number"), + + ("a2_sport_activity_l04_q3", "A", "Lubię biegać rano.", "Я люблю бегать утром.", "Я люблю бігати вранці.", "I like running in the morning.", True, None), + ("a2_sport_activity_l04_q3", "B", "Lubię pływać.", "Я люблю плавать. (не соответствует ситуации)", "Я люблю плавати. (не відповідає ситуації)", "I like swimming. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l04_q3", "C", "Lubię jeździć na rowerze.", "Я люблю кататься на велосипеде. (не соответствует ситуации)", "Я люблю їздити на велосипеді. (не відповідає ситуації)", "I like riding a bike. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l04_q3", "D", "Chcę biegać rano.", "Я хочу бегать утром. (не о привычке)", "Я хочу бігати вранці. (не про звичку)", "I want to run in the morning. (not about a habit)", False, "wrong_context"), + + # L05 + ("a2_sport_activity_l05_q1", "A", "Trenuję", "я тренирую", "я треную", "I train", True, None), + ("a2_sport_activity_l05_q1", "B", "Trenujesz", "ты тренируешь (не тот человек)", "ти тренуєш (не та особа)", "you train (wrong person)", False, "wrong_context"), + ("a2_sport_activity_l05_q1", "C", "Trenuje", "он/она тренирует (не тот человек)", "він/вона тренує (не та особа)", "he/she trains (wrong person)", False, "wrong_context"), + ("a2_sport_activity_l05_q1", "D", "Trenowaliśmy", "мы тренировали (неправильное число и время)", "ми тренували (неправильне число і час)", "we trained (wrong number and tense)", False, "wrong_number"), + + ("a2_sport_activity_l05_q3", "A", "Trenuję tenis w klubie.", "Я тренирую теннис в клубе.", "Я треную теніс у клубі.", "I train tennis at a club.", True, None), + ("a2_sport_activity_l05_q3", "B", "Gram w tenisa.", "Я играю в теннис. (не о регулярной тренировке)", "Я граю в теніс. (не про регулярне тренування)", "I play tennis. (not about regular training)", False, "wrong_context"), + ("a2_sport_activity_l05_q3", "C", "Lubię tenis.", "Мне нравится теннис. (не о тренировке)", "Мені подобається теніс. (не про тренування)", "I like tennis. (not about training)", False, "wrong_context"), + ("a2_sport_activity_l05_q3", "D", "Umiem grać w tenisa.", "Я умею играть в теннис. (не о тренировке)", "Я вмію грати в теніс. (не про тренування)", "I know how to play tennis. (not about training)", False, "wrong_context"), + + # L06 + ("a2_sport_activity_l06_q1", "A", "na", "на", "на", "to", True, None), + ("a2_sport_activity_l06_q1", "B", "do", "в/к", "в/до", "to", False, "wrong_word"), + ("a2_sport_activity_l06_q1", "C", "w", "в", "в", "in", False, "wrong_word"), + ("a2_sport_activity_l06_q1", "D", "u", "у", "у", "at", False, "wrong_word"), + + ("a2_sport_activity_l06_q3", "A", "Chodzę na jogę po pracy.", "Я хожу на йогу после работы.", "Я ходжу на йогу після роботи.", "I go to yoga after work.", True, None), + ("a2_sport_activity_l06_q3", "B", "Chodzę na siłownię rano.", "Я хожу в тренажёрный зал утром. (не соответствует ситуации)", "Я ходжу в тренажерну залу вранці. (не відповідає ситуації)", "I go to the gym in the morning. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l06_q3", "C", "Chodzę na basen w weekendy.", "Я хожу в бассейн по выходным. (не соответствует ситуации)", "Я ходжу в басейн у вихідні. (не відповідає ситуації)", "I go to the pool on weekends. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l06_q3", "D", "Trenuję jogę codziennie.", "Я тренирую йогу каждый день. (неверный глагол)", "Я треную йогу щодня. (невірне дієслово)", "I train yoga every day. (wrong verb)", False, "wrong_word"), + + # L07 + ("a2_sport_activity_l07_q1", "A", "silny", "сильный", "сильний", "strong", False, "wrong_word"), + ("a2_sport_activity_l07_q1", "B", "szybki", "быстрый", "швидкий", "fast", False, "wrong_word"), + ("a2_sport_activity_l07_q1", "C", "wytrzymały", "выносливый", "витривалий", "enduring", True, None), + ("a2_sport_activity_l07_q1", "D", "zmęczony", "уставший", "втомлений", "tired", False, "wrong_word"), + + ("a2_sport_activity_l07_q3", "A", "Jestem silny.", "Я сильный. (не соответствует ситуации)", "Я сильний. (не відповідає ситуації)", "I am strong. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l07_q3", "B", "Jestem szybki.", "Я быстрый. (не соответствует ситуации)", "Я швидкий. (не відповідає ситуації)", "I am fast. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l07_q3", "C", "Jestem wytrzymały.", "Я выносливый. (не соответствует ситуации)", "Я витривалий. (не відповідає ситуації)", "I am enduring. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_l07_q3", "D", "Jestem zmęczony.", "Я устал.", "Я втомлений.", "I am tired.", True, None), + + # L08 + ("a2_sport_activity_l08_q1", "A", "Umiem", "я умею", "я вмію", "I know how to", True, None), + ("a2_sport_activity_l08_q1", "B", "Umiesz", "ты умеешь (не тот человек)", "ти вмієш (не та особа)", "you know how to (wrong person)", False, "wrong_context"), + ("a2_sport_activity_l08_q1", "C", "Umie", "он/она умеет (не тот человек)", "він/вона вміє (не та особа)", "he/she knows how to (wrong person)", False, "wrong_context"), + ("a2_sport_activity_l08_q1", "D", "Umieli", "они умели (неправильное число и время)", "вони вміли (неправильне число і час)", "they knew how to (wrong number and tense)", False, "wrong_number"), + + ("a2_sport_activity_l08_q3", "A", "Umiem jeździć na rowerze.", "Я умею кататься на велосипеде.", "Я вмію їздити на велосипеді.", "I know how to ride a bike.", True, None), + ("a2_sport_activity_l08_q3", "B", "Lubię jeździć na rowerze.", "Я люблю кататься на велосипеде. (о симпатии, не о навыке)", "Я люблю їздити на велосипеді. (про симпатію, не про навичку)", "I like riding a bike. (about liking it, not the skill)", False, "wrong_context"), + ("a2_sport_activity_l08_q3", "C", "Chcę jeździć na rowerze.", "Я хочу кататься на велосипеде. (о желании, не о навыке)", "Я хочу їздити на велосипеді. (про бажання, не про навичку)", "I want to ride a bike. (about wanting to, not the skill)", False, "wrong_context"), + ("a2_sport_activity_l08_q3", "D", "Trenuję jazdę na rowerze.", "Я тренирую езду на велосипеде. (о тренировке, не о готовом навыке)", "Я треную їзду на велосипеді. (про тренування, не про готову навичку)", "I'm training cycling. (about training, not an achieved skill)", False, "wrong_context"), + + # L09 + ("a2_sport_activity_l09_q1", "A", "Wygrywasz ten mecz?", "Ты выигрываешь этот матч?", "Ти виграєш цей матч?", "Are you winning this match?", False, "wrong_translation"), + ("a2_sport_activity_l09_q1", "B", "Wygrasz ten mecz?", "Ты выиграешь этот матч?", "Ти виграєш цей матч?", "Will you win this match?", False, "wrong_translation"), + ("a2_sport_activity_l09_q1", "C", "Przegrałaś ten mecz?", "Ты проиграла этот матч?", "Ти програла цей матч?", "Did you lose that match?", False, "wrong_translation"), + ("a2_sport_activity_l09_q1", "D", "Wygrałaś ten mecz?", "Ты выиграла этот матч?", "Ти виграла цей матч?", "Did you win that match?", True, None), + + ("a2_sport_activity_l09_q3", "A", "Trenuję piłkę nożną.", "Я тренирую футбол. (настоящее время)", "Я треную футбол. (теперішній час)", "I train soccer. (present tense)", False, "wrong_sentence_type"), + ("a2_sport_activity_l09_q3", "B", "Trenowałem piłkę nożną przez pięć lat.", "Я тренировал футбол пять лет.", "Я тренував футбол п'ять років.", "I trained soccer for five years.", True, None), + ("a2_sport_activity_l09_q3", "C", "Będę trenować piłkę nożną przez pięć lat.", "Я буду тренировать футбол пять лет. (будущее время)", "Я буду тренувати футбол п'ять років. (майбутній час)", "I will train soccer for five years. (future tense)", False, "wrong_sentence_type"), + ("a2_sport_activity_l09_q3", "D", "Trenowałam piłkę nożną przez pięć lat.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + # L10 + ("a2_sport_activity_l10_q1", "A", "Lubię ja biegać ja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_sport_activity_l10_q1", "B", "Lubię rano biegać.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_sport_activity_l10_q1", "C", "Biegam lubię.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_sport_activity_l10_q1", "D", "Lubię biegać rano i chodzę na siłownię.", "Я люблю бегать утром и хожу в тренажёрный зал.", "Я люблю бігати вранці і ходжу в тренажерну залу.", "I like running in the morning and I go to the gym.", True, None), + + ("a2_sport_activity_l10_q3", "A", "Chodzę na siłownię.", "Я хожу в тренажёрный зал. (не начало описания)", "Я ходжу в тренажерну залу. (не початок опису)", "I go to the gym. (not the opening line)", False, "wrong_context"), + ("a2_sport_activity_l10_q3", "B", "Wygrałem mecz.", "Я выиграл матч. (не начало описания)", "Я виграв матч. (не початок опису)", "I won a match. (not the opening line)", False, "wrong_context"), + ("a2_sport_activity_l10_q3", "C", "Lubię biegać.", "Я люблю бегать.", "Я люблю бігати.", "I like running.", True, None), + ("a2_sport_activity_l10_q3", "D", "Trenowałem piłkę nożną.", "Я тренировал футбол. (прошедшее время, не соответствует ситуации)", "Я тренував футбол. (минулий час, не відповідає ситуації)", "I trained soccer. (past tense, doesn't match the situation)", False, "wrong_context"), + ] + + for opt in options_t9_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t9_a2 = [ + ("a2_sport_activity_t01", None, "topic_test", "recognition", "sport_vocabulary", 1, + "Jak po polsku „тренажёрный зал”?", "Как по-польски «тренажёрный зал»?", "Як польською «тренажерна зала»?", "How do you say “gym” in Polish?", + "D", None, None, 1), + ("a2_sport_activity_t02", None, "topic_test", "recognition", "grac_w_bierniku", 1, + "Wybierz poprawną formę: Gram w ___. (piłka nożna)", "Выберите правильную форму: Gram w ___. (piłka nożna)", "Виберіть правильну форму: Gram w ___. (piłka nożna)", "Choose the correct form: Gram w ___. (piłka nożna)", + "A", None, None, 2), + ("a2_sport_activity_t03", None, "topic_test", "recognition", "aktywnosc_vocabulary", 1, + "Jak po polsku „йога”?", "Как по-польски «йога»?", "Як польською «йога»?", "How do you say “yoga” in Polish?", + "D", None, None, 3), + ("a2_sport_activity_t04", None, "topic_test", "recognition", "lubic_bezokolicznik", 1, + "Wybierz poprawną formę: ___ biegać rano. (lubić, ja)", "Выберите правильную форму: ___ biegać rano. (lubić, ja)", "Виберіть правильну форму: ___ biegać rano. (lubić, ja)", "Choose the correct form: ___ biegać rano. (lubić, I)", + "A", None, None, 4), + ("a2_sport_activity_t05", None, "topic_test", "recognition", "trenowac_biernik", 2, + "Wybierz poprawną formę: ___ piłkę nożną. (trenować, ja)", "Выберите правильную форму: ___ piłkę nożną. (trenować, ja)", "Виберіть правильну форму: ___ piłkę nożną. (trenować, ja)", "Choose the correct form: ___ piłkę nożną. (trenować, I)", + "A", None, None, 5), + ("a2_sport_activity_t06", None, "topic_test", "recognition", "przeszly_czas_sport", 3, + "Co znaczy „Wygrałaś ten mecz”?", "Что означает «Wygrałaś ten mecz»?", "Що означає «Wygrałaś ten mecz»?", "What does “Wygrałaś ten mecz” mean?", + "D", None, None, 6), + + ("a2_sport_activity_t07", None, "topic_test", "application", "sport_vocabulary", 1, + "Chcesz podnosić ciężary i ćwiczyć mięśnie w budynku ze sprzętem sportowym. Dokąd idziesz?", "Ты хочешь поднимать тяжести и качать мышцы в здании со спортивным оборудованием. Куда ты идёшь?", "Ти хочеш піднімати важкі ваги і качати м'язи в будівлі зі спортивним обладнанням. Куди ти йдеш?", "You want to lift weights and work out in a building with sports equipment. Where are you going?", + "C", None, None, 7), + ("a2_sport_activity_t08", None, "topic_test", "application", "grac_w_bierniku", 1, + "Kolega pyta, w co grasz w wolnym czasie. Grasz w tenisa. Co powiesz?", "Друг спрашивает, во что ты играешь в свободное время. Ты играешь в теннис. Что ты скажешь?", "Друг питає, у що ти граєш у вільний час. Ти граєш у теніс. Що ти скажеш?", "A friend asks what you play in your free time. You play tennis. What do you say?", + "C", None, None, 8), + ("a2_sport_activity_t09", None, "topic_test", "application", "aktywnosc_vocabulary", 1, + "Chcesz się zrelaksować i poprawić elastyczność ciała spokojnymi ćwiczeniami. Co wybierasz?", "Ты хочешь расслабиться и улучшить гибкость тела спокойными упражнениями. Что ты выбираешь?", "Ти хочеш розслабитися і покращити гнучкість тіла спокійними вправами. Що ти обираєш?", "You want to relax and improve your flexibility with calm exercises. What do you choose?", + "D", None, None, 9), + ("a2_sport_activity_t10", None, "topic_test", "application", "chodzic_na_silownie", 2, + "Regularnie uczestniczysz w zajęciach jogi po pracy. Co powiesz?", "Ты регулярно посещаешь занятия йогой после работы. Что ты скажешь?", "Ти регулярно відвідуєш заняття йогою після роботи. Що ти скажеш?", "You regularly attend yoga classes after work. What do you say?", + "A", None, None, 10), + ("a2_sport_activity_t11", None, "topic_test", "application", "przymiotniki_sport_vocabulary", 2, + "Właśnie skończyłeś ciężki trening i czujesz brak energii. Co powiesz?", "Ты только что закончил тяжёлую тренировку и чувствуешь нехватку энергии. Что ты скажешь?", "Ти щойно закінчив важке тренування і відчуваєш брак енергії. Що ти скажеш?", "You just finished a hard workout and feel out of energy. What do you say?", + "D", None, None, 11), + ("a2_sport_activity_t12", None, "topic_test", "application", "przeszly_czas_sport", 3, + "Mężczyzna opowiada, że trenował piłkę nożną przez pięć lat, ale już przestał. Co powie?", "Мужчина рассказывает, что тренировал футбол пять лет, но уже перестал. Что он скажет?", "Чоловік розповідає, що тренував футбол п'ять років, але вже перестав. Що він скаже?", "A man is telling that he trained soccer for five years, but has already stopped. What does he say?", + "B", None, None, 12), + + ("a2_sport_activity_t13", None, "topic_test", "production", "sport_vocabulary", 1, + "Wpisz brakujące słowo: Pływam na ___. (бассейне)", "Вставьте пропущенное слово: Pływam na ___. (бассейне)", "Вставте пропущене слово: Pływam na ___. (басейні)", "Fill in the missing word: Pływam na ___. (pool)", + "basenie", "first_letter", "b", 13), + ("a2_sport_activity_t14", None, "topic_test", "production", "aktywnosc_vocabulary", 1, + "Wpisz brakujące słowo: Lubię ___. (плавание)", "Вставьте пропущенное слово: Lubię ___. (плавание)", "Вставте пропущене слово: Lubię ___. (плавання)", "Fill in the missing word: Lubię ___. (swimming)", + "pływanie", "first_letter", "p", 14), + ("a2_sport_activity_t15", None, "topic_test", "production", "trenowac_biernik", 2, + "Wpisz brakujące słowo: ___ koszykówkę codziennie? (ты тренируешь)", "Вставьте пропущенное слово: ___ koszykówkę codziennie? (ты тренируешь)", "Вставте пропущене слово: ___ koszykówkę codziennie? (ти тренуєш)", "Fill in the missing word: ___ koszykówkę codziennie? (do you train)", + "Trenujesz", "first_letter", "T", 15), + ("a2_sport_activity_t16", None, "topic_test", "production", "chodzic_na_silownie", 2, + "Wpisz brakujące słowo: Chodzisz na ___? (бассейн)", "Вставьте пропущенное слово: Chodzisz na ___? (бассейн)", "Вставте пропущене слово: Chodzisz na ___? (басейн)", "Fill in the missing word: Chodzisz na ___? (pool)", + "basen", "first_letter", "b", 16), + ("a2_sport_activity_t17", None, "topic_test", "production", "umiec_grac", 2, + "Wpisz brakujące słowo: ___ pływać? (ты умеешь)", "Вставьте пропущенное слово: ___ pływać? (ты умеешь)", "Вставте пропущене слово: ___ pływać? (ти вмієш)", "Fill in the missing word: ___ pływać? (do you know how to)", + "Umiesz", "first_letter", "U", 17), + ("a2_sport_activity_t18", None, "topic_test", "production", "opisuje_swoja_aktywnosc", 3, + "Przetłumacz: «Я выиграл свой первый матч».", "Переведите: «Я выиграл свой первый матч».", "Перекладіть: «Я виграв свій перший матч».", "Translate: “I won my first match.”", + "Wygrałem swój pierwszy mecz", "first_letter", "W", 18), + + ("a2_sport_activity_t19", None, "topic_test", "mixed", "opisuje_swoja_aktywnosc", 3, + "Wybierz poprawne tłumaczenie: «Я люблю бегать утром, хожу в тренажёрный зал три раза в неделю, и выиграл свой первый матч».", "Выберите правильный перевод: «Я люблю бегать утром, хожу в тренажёрный зал три раза в неделю, и выиграл свой первый матч».", "Виберіть правильний переклад: «Я люблю бігати вранці, ходжу в тренажерну залу три рази на тиждень, і виграв свій перший матч».", "Choose the correct translation: “I like running in the morning, I go to the gym three times a week, and I won my first match.”", + "C", None, None, 19), + ("a2_sport_activity_t20", None, "topic_test", "mixed", "trenowac_biernik", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Тренируешь баскетбол? — Да, тренирую баскетбол каждый день, потому что хочу быть сильным.»", "Выберите правильный перевод диалога: «— Тренируешь баскетбол? — Да, тренирую баскетбол каждый день, потому что хочу быть сильным.»", "Виберіть правильний переклад діалогу: «— Тренуєш баскетбол? — Так, треную баскетбол щодня, бо хочу бути сильним.»", "Choose the correct translation of the dialogue: “— Do you train basketball? — Yes, I train basketball every day because I want to be strong.”", + "A", None, None, 20), + ] + + for q in test_questions_t9_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_sport_activity', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t9_a2 = [ + ("a2_sport_activity_t01", "A", "piłka", "мяч", "м'яч", "ball", False, "wrong_word"), + ("a2_sport_activity_t01", "B", "boisko", "поле", "поле", "field", False, "wrong_word"), + ("a2_sport_activity_t01", "C", "basen", "бассейн", "басейн", "pool", False, "wrong_word"), + ("a2_sport_activity_t01", "D", "siłownia", "тренажёрный зал", "тренажерна зала", "gym", True, None), + + ("a2_sport_activity_t02", "A", "piłkę nożną", "футбол (вин.)", "футбол (знах.)", "soccer (acc.)", True, None), + ("a2_sport_activity_t02", "B", "piłka nożna", "футбол (им.)", "футбол (наз.)", "soccer (nom.)", False, "wrong_case"), + ("a2_sport_activity_t02", "C", "piłki nożnej", "футбола (род.)", "футболу (род.)", "soccer (gen.)", False, "wrong_case"), + ("a2_sport_activity_t02", "D", "piłce nożnej", "футболу (местн./дат.)", "футболу (місц./дав.)", "soccer (loc./dat.)", False, "wrong_case"), + + ("a2_sport_activity_t03", "A", "bieganie", "бег", "біг", "running", False, "wrong_word"), + ("a2_sport_activity_t03", "B", "pływanie", "плавание", "плавання", "swimming", False, "wrong_word"), + ("a2_sport_activity_t03", "C", "jazda na rowerze", "езда на велосипеде", "їзда на велосипеді", "cycling", False, "wrong_word"), + ("a2_sport_activity_t03", "D", "joga", "йога", "йога", "yoga", True, None), + + ("a2_sport_activity_t04", "A", "Lubię", "я люблю", "я люблю", "I like", True, None), + ("a2_sport_activity_t04", "B", "Lubisz", "ты любишь (не тот человек)", "ти любиш (не та особа)", "you like (wrong person)", False, "wrong_context"), + ("a2_sport_activity_t04", "C", "Lubi", "он/она любит (не тот человек)", "він/вона любить (не та особа)", "he/she likes (wrong person)", False, "wrong_context"), + ("a2_sport_activity_t04", "D", "Lubili", "они любили (неправильное число и время)", "вони любили (неправильне число і час)", "they liked (wrong number and tense)", False, "wrong_number"), + + ("a2_sport_activity_t05", "A", "Trenuję", "я тренирую", "я треную", "I train", True, None), + ("a2_sport_activity_t05", "B", "Trenujesz", "ты тренируешь (не тот человек)", "ти тренуєш (не та особа)", "you train (wrong person)", False, "wrong_context"), + ("a2_sport_activity_t05", "C", "Trenuje", "он/она тренирует (не тот человек)", "він/вона тренує (не та особа)", "he/she trains (wrong person)", False, "wrong_context"), + ("a2_sport_activity_t05", "D", "Trenowaliśmy", "мы тренировали (неправильное число и время)", "ми тренували (неправильне число і час)", "we trained (wrong number and tense)", False, "wrong_number"), + + ("a2_sport_activity_t06", "A", "Wygrywasz ten mecz?", "Ты выигрываешь этот матч?", "Ти виграєш цей матч?", "Are you winning this match?", False, "wrong_translation"), + ("a2_sport_activity_t06", "B", "Wygrasz ten mecz?", "Ты выиграешь этот матч?", "Ти виграєш цей матч?", "Will you win this match?", False, "wrong_translation"), + ("a2_sport_activity_t06", "C", "Przegrałaś ten mecz?", "Ты проиграла этот матч?", "Ти програла цей матч?", "Did you lose that match?", False, "wrong_translation"), + ("a2_sport_activity_t06", "D", "Wygrałaś ten mecz?", "Ты выиграла этот матч?", "Ти виграла цей матч?", "Did you win that match?", True, None), + + ("a2_sport_activity_t07", "A", "Na boisko.", "На поле.", "На поле.", "To the field.", False, "wrong_context"), + ("a2_sport_activity_t07", "B", "Na basen.", "В бассейн.", "У басейн.", "To the pool.", False, "wrong_context"), + ("a2_sport_activity_t07", "C", "Na siłownię.", "В тренажёрный зал.", "У тренажерну залу.", "To the gym.", True, None), + ("a2_sport_activity_t07", "D", "Na plażę.", "На пляж.", "На пляж.", "To the beach.", False, "wrong_context"), + + ("a2_sport_activity_t08", "A", "Gram w piłkę nożną.", "Я играю в футбол. (не соответствует ситуации)", "Я граю у футбол. (не відповідає ситуації)", "I play soccer. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_t08", "B", "Gram w koszykówkę.", "Я играю в баскетбол. (не соответствует ситуации)", "Я граю у баскетбол. (не відповідає ситуації)", "I play basketball. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_t08", "C", "Gram w tenisa.", "Я играю в теннис.", "Я граю в теніс.", "I play tennis.", True, None), + ("a2_sport_activity_t08", "D", "Gram w siatkówkę.", "Я играю в волейбол. (не соответствует ситуации)", "Я граю в волейбол. (не відповідає ситуації)", "I play volleyball. (doesn't match the situation)", False, "wrong_context"), + + ("a2_sport_activity_t09", "A", "Bieganie.", "Бег. (не спокойное упражнение)", "Біг. (не спокійна вправа)", "Running. (not a calm exercise)", False, "wrong_context"), + ("a2_sport_activity_t09", "B", "Pływanie.", "Плавание. (не о гибкости)", "Плавання. (не про гнучкість)", "Swimming. (not about flexibility)", False, "wrong_context"), + ("a2_sport_activity_t09", "C", "Jazdę na rowerze.", "Езду на велосипеде. (не спокойное упражнение)", "Їзду на велосипеді. (не спокійна вправа)", "Cycling. (not a calm exercise)", False, "wrong_context"), + ("a2_sport_activity_t09", "D", "Jogę.", "Йогу.", "Йогу.", "Yoga.", True, None), + + ("a2_sport_activity_t10", "A", "Chodzę na jogę po pracy.", "Я хожу на йогу после работы.", "Я ходжу на йогу після роботи.", "I go to yoga after work.", True, None), + ("a2_sport_activity_t10", "B", "Chodzę na siłownię rano.", "Я хожу в тренажёрный зал утром. (не соответствует ситуации)", "Я ходжу в тренажерну залу вранці. (не відповідає ситуації)", "I go to the gym in the morning. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_t10", "C", "Chodzę na basen w weekendy.", "Я хожу в бассейн по выходным. (не соответствует ситуации)", "Я ходжу в басейн у вихідні. (не відповідає ситуації)", "I go to the pool on weekends. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_t10", "D", "Trenuję jogę codziennie.", "Я тренирую йогу каждый день. (неверный глагол)", "Я треную йогу щодня. (невірне дієслово)", "I train yoga every day. (wrong verb)", False, "wrong_word"), + + ("a2_sport_activity_t11", "A", "Jestem silny.", "Я сильный. (не соответствует ситуации)", "Я сильний. (не відповідає ситуації)", "I am strong. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_t11", "B", "Jestem szybki.", "Я быстрый. (не соответствует ситуации)", "Я швидкий. (не відповідає ситуації)", "I am fast. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_t11", "C", "Jestem wytrzymały.", "Я выносливый. (не соответствует ситуации)", "Я витривалий. (не відповідає ситуації)", "I am enduring. (doesn't match the situation)", False, "wrong_context"), + ("a2_sport_activity_t11", "D", "Jestem zmęczony.", "Я устал.", "Я втомлений.", "I am tired.", True, None), + + ("a2_sport_activity_t12", "A", "Trenuję piłkę nożną.", "Я тренирую футбол. (настоящее время)", "Я треную футбол. (теперішній час)", "I train soccer. (present tense)", False, "wrong_sentence_type"), + ("a2_sport_activity_t12", "B", "Trenowałem piłkę nożną przez pięć lat.", "Я тренировал футбол пять лет.", "Я тренував футбол п'ять років.", "I trained soccer for five years.", True, None), + ("a2_sport_activity_t12", "C", "Będę trenować piłkę nożną przez pięć lat.", "Я буду тренировать футбол пять лет. (будущее время)", "Я буду тренувати футбол п'ять років. (майбутній час)", "I will train soccer for five years. (future tense)", False, "wrong_sentence_type"), + ("a2_sport_activity_t12", "D", "Trenowałam piłkę nożną przez pięć lat.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + ("a2_sport_activity_t19", "A", "Lubiłem biegać rano, chodziłem na siłownię trzy razy w tygodniu, i wygrałem swój pierwszy mecz.", "Я любил бегать утром, ходил в тренажёрный зал три раза в неделю, и выиграл свой первый матч. (прошедшее время)", "Я любив бігати вранці, ходив у тренажерну залу три рази на тиждень, і виграв свій перший матч. (минулий час)", "I used to like running in the morning, going to the gym three times a week, and I won my first match. (past tense)", False, "wrong_sentence_type"), + ("a2_sport_activity_t19", "B", "Będę lubić biegać rano, będę chodzić na siłownię trzy razy w tygodniu, i wygram swój pierwszy mecz.", "Я буду любить бегать утром, буду ходить в тренажёрный зал три раза в неделю, и выиграю свой первый матч. (будущее время)", "Я любитиму бігати вранці, буду ходити в тренажерну залу три рази на тиждень, і виграю свій перший матч. (майбутній час)", "I will like running in the morning, will go to the gym three times a week, and will win my first match. (future tense)", False, "wrong_sentence_type"), + ("a2_sport_activity_t19", "C", "Lubię biegać rano, chodzę na siłownię trzy razy w tygodniu, i wygrałem swój pierwszy mecz.", "Я люблю бегать утром, хожу в тренажёрный зал три раза в неделю, и выиграл свой первый матч.", "Я люблю бігати вранці, ходжу в тренажерну залу три рази на тиждень, і виграв свій перший матч.", "I like running in the morning, I go to the gym three times a week, and I won my first match.", True, None), + ("a2_sport_activity_t19", "D", "Lubię pływać rano, chodzę na siłownię trzy razy w tygodniu, i wygrałem swój pierwszy mecz.", "Я люблю плавать утром, хожу в тренажёрный зал три раза в неделю, и выиграл свой первый матч. (неверное слово)", "Я люблю плавати вранці, ходжу в тренажерну залу три рази на тиждень, і виграв свій перший матч. (невірне слово)", "I like swimming in the morning, I go to the gym three times a week, and I won my first match. (wrong word)", False, "wrong_word"), + + ("a2_sport_activity_t20", "A", "— Trenujesz koszykówkę? — Tak, trenuję koszykówkę codziennie, bo chcę być silny.", "— Ты тренируешь баскетбол? — Да, тренирую баскетбол каждый день, потому что хочу быть сильным.", "— Ти тренуєш баскетбол? — Так, треную баскетбол щодня, бо хочу бути сильним.", "— Do you train basketball? — Yes, I train basketball every day because I want to be strong.", True, None), + ("a2_sport_activity_t20", "B", "— Trenowałeś koszykówkę? — Tak, trenowałem koszykówkę codziennie, bo chciałem być silny.", "— Ты тренировал баскетбол? — Да, тренировал баскетбол каждый день, потому что хотел быть сильным. (прошедшее время)", "— Ти тренував баскетбол? — Так, тренував баскетбол щодня, бо хотів бути сильним. (минулий час)", "— Did you train basketball? — Yes, I trained basketball every day because I wanted to be strong. (past tense)", False, "wrong_sentence_type"), + ("a2_sport_activity_t20", "C", "— Trenujesz koszykówkę? — Nie, nie trenuję koszykówki, bo nie mam czasu.", "— Ты тренируешь баскетбол? — Нет, я не тренирую баскетбол, потому что у меня нет времени. (противоположный смысл)", "— Ти тренуєш баскетбол? — Ні, я не треную баскетбол, бо не маю часу. (протилежний зміст)", "— Do you train basketball? — No, I don't train basketball, because I don't have time. (opposite meaning)", False, "wrong_context"), + ("a2_sport_activity_t20", "D", "— Trenujesz piłkę nożną? — Tak, trenuję koszykówkę codziennie, bo chcę być silny.", "— Ты тренируешь футбол? — Да, тренирую баскетбол каждый день, потому что хочу быть сильным. (несоответствие вопроса и ответа)", "— Ти тренуєш футбол? — Так, треную баскетбол щодня, бо хочу бути сильним. (невідповідність питання і відповіді)", "— Do you train soccer? — Yes, I train basketball every day because I want to be strong. (mismatched question and answer)", False, "wrong_word"), + ] + + for opt in test_options_t9_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 10 (A2): ROZRYWKA I KULTURA ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_entertainment_culture', 'A2', 10, + 'Rozrywka i kultura', + 'Развлечения и культура', + 'Розваги та культура', + 'Entertainment and Culture') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t10_a2 = [ + ("a2_entertainment_culture_l01", 1, "rozrywka_vocabulary", "Podstawowe słowa: rozrywka", "Основные слова: развлечения", "Основні слова: розваги", "Basic words: entertainment", + "Podstawowe słowa: kino, teatr, koncert, muzeum.", + "Основные слова: kino (кино), teatr (театр), koncert (концерт), muzeum (музей).", + "Основні слова: kino (кіно), teatr (театр), koncert (концерт), muzeum (музей).", + "Basic words: kino (cinema), teatr (theater), koncert (concert), muzeum (museum)."), + + ("a2_entertainment_culture_l02", 2, "isc_do_dopelniacza", "Iść do + dopełniacz", "Iść do + родительный падеж", "Iść do + родовий відмінок", "Iść do + genitive", + "Czasownik „iść” + „do” + dopełniacz miejsca: idę do kina, idziesz do teatru, idzie do muzeum.", + "Глагол „iść” (идти) + „do” + родительный падеж места: idę do kina (я иду в кино), idziesz do teatru (ты идёшь в театр), idzie do muzeum (он/она идёт в музей).", + "Дієслово „iść” (йти) + „do” + родовий відмінок місця: idę do kina (я йду в кіно), idziesz do teatru (ти йдеш до театру), idzie do muzeum (він/вона йде до музею).", + "The verb „iść” (to go) + „do” + genitive of the place: idę do kina (I'm going to the cinema), idziesz do teatru (you're going to the theater), idzie do muzeum (he/she is going to the museum)."), + + ("a2_entertainment_culture_l03", 3, "kultura_vocabulary", "Podstawowe słowa: kultura", "Основные слова: культура", "Основні слова: культура", "Basic words: culture", + "Podstawowe słowa: film, książka, muzyka, sztuka.", + "Основные слова: film (фильм), książka (книга), muzyka (музыка), sztuka (искусство).", + "Основні слова: film (фільм), książka (книга), muzyka (музика), sztuka (мистецтво).", + "Basic words: film (movie), książka (book), muzyka (music), sztuka (art)."), + + ("a2_entertainment_culture_l04", 4, "lubic_rzeczownik", "Lubić + biernik (rzeczownik)", "Lubić + винительный падеж (существительное)", "Lubić + знахідний відмінок (іменник)", "Lubić + accusative (noun)", + "Czasownik „lubić” + biernik rzeczownika: lubię filmy, lubisz muzykę, lubi książki.", + "Глагол „lubić” (любить) + винительный падеж существительного: lubię filmy (я люблю фильмы), lubisz muzykę (ты любишь музыку), lubi książki (он/она любит книги).", + "Дієслово „lubić” (любити) + знахідний відмінок іменника: lubię filmy (я люблю фільми), lubisz muzykę (ти любиш музику), lubi książki (він/вона любить книги).", + "The verb „lubić” (to like) + accusative of the noun: lubię filmy (I like films), lubisz muzykę (you like music), lubi książki (he/she likes books)."), + + ("a2_entertainment_culture_l05", 5, "ogladac_biernik", "Oglądać + biernik", "Oglądać + винительный падеж", "Oglądać + знахідний відмінок", "Oglądać + accusative", + "Czasownik „oglądać” + biernik: oglądam film, oglądasz serial, ogląda spektakl.", + "Глагол „oglądać” (смотреть) + винительный падеж: oglądam film (я смотрю фильм), oglądasz serial (ты смотришь сериал), ogląda spektakl (он/она смотрит спектакль).", + "Дієслово „oglądać” (дивитися) + знахідний відмінок: oglądam film (я дивлюся фільм), oglądasz serial (ти дивишся серіал), ogląda spektakl (він/вона дивиться виставу).", + "The verb „oglądać” (to watch) + accusative: oglądam film (I'm watching a film), oglądasz serial (you're watching a series), ogląda spektakl (he/she is watching a play)."), + + ("a2_entertainment_culture_l06", 6, "chodzic_do_kina", "Chodzić do + dopełniacz", "Chodzić do + родительный падеж", "Chodzić do + родовий відмінок", "Chodzić do + genitive", + "Czasownik „chodzić” + „do” + dopełniacz miejsca: chodzę do kina, chodzisz do teatru, chodzi do muzeum.", + "Глагол „chodzić” (ходить) + „do” + родительный падеж места: chodzę do kina (я хожу в кино), chodzisz do teatru (ты ходишь в театр), chodzi do muzeum (он/она ходит в музей).", + "Дієслово „chodzić” (ходити) + „do” + родовий відмінок місця: chodzę do kina (я ходжу в кіно), chodzisz do teatru (ти ходиш до театру), chodzi do muzeum (він/вона ходить до музею).", + "The verb „chodzić” (to go regularly) + „do” + genitive of the place: chodzę do kina (I go to the cinema), chodzisz do teatru (you go to the theater), chodzi do muzeum (he/she goes to the museum)."), + + ("a2_entertainment_culture_l07", 7, "przymiotniki_kultura_vocabulary", "Podstawowe słowa: przymiotniki o kulturze", "Основные слова: прилагательные о культуре", "Основні слова: прикметники про культуру", "Basic words: culture adjectives", + "Podstawowe przymiotniki opisujące dzieła kultury: zabawny, smutny, wzruszający, nudny.", + "Основные прилагательные, описывающие произведения культуры: zabawny (смешной), smutny (грустный), wzruszający (трогательный), nudny (скучный).", + "Основні прикметники, що описують твори культури: zabawny (смішний), smutny (сумний), wzruszający (зворушливий), nudny (нудний).", + "Basic adjectives describing cultural works: zabawny (funny), smutny (sad), wzruszający (moving), nudny (boring)."), + + ("a2_entertainment_culture_l08", 8, "woleć_biernik", "Woleć + biernik / bezokolicznik", "Woleć + винительный падеж / инфинитив", "Woleć + знахідний відмінок / інфінітив", "Woleć + accusative / infinitive", + "Czasownik „woleć” + biernik lub bezokolicznik wyraża preferencję: wolę czytać, wolisz muzykę klasyczną, woli chodzić do teatru.", + "Глагол „woleć” (предпочитать) + винительный падеж или инфинитив выражает предпочтение: wolę czytać (я предпочитаю читать), wolisz muzykę klasyczną (ты предпочитаешь классическую музыку), woli chodzić do teatru (он/она предпочитает ходить в театр).", + "Дієслово „woleć” (віддавати перевагу) + знахідний відмінок або інфінітив виражає перевагу: wolę czytać (я віддаю перевагу читанню), wolisz muzykę klasyczną (ти віддаєш перевагу класичній музиці), woli chodzić do teatru (він/вона віддає перевагу ходінню до театру).", + "The verb „woleć” (to prefer) + accusative or infinitive expresses a preference: wolę czytać (I prefer reading), wolisz muzykę klasyczną (you prefer classical music), woli chodzić do teatru (he/she prefers going to the theater)."), + + ("a2_entertainment_culture_l09", 9, "przeszly_czas_rozrywka", "Obejrzałem/obejrzałam, przeczytałem/przeczytałam (przeszłość)", "Obejrzałem/obejrzałam, przeczytałem/przeczytałam (прошедшее)", "Obejrzałem/obejrzałam, przeczytałem/przeczytałam (минулий час)", "Obejrzałem/obejrzałam, przeczytałem/przeczytałam (past)", + "Czas przeszły rozrywki tworzymy „obejrzałem/obejrzałam” lub „przeczytałem/przeczytałam” zależnie od rodzaju mówiącego: obejrzałem film wczoraj, przeczytałaś tę książkę, obejrzała spektakl.", + "Прошедшее время развлечения образуем „obejrzałem/obejrzałam” или „przeczytałem/przeczytałam” в зависимости от рода говорящего: obejrzałem film wczoraj (я посмотрел фильм вчера), przeczytałaś tę książkę (ты прочитала эту книгу), obejrzała spektakl (она посмотрела спектакль).", + "Минулий час розваги утворюємо „obejrzałem/obejrzałam” або „przeczytałem/przeczytałam” залежно від роду мовця: obejrzałem film wczoraj (я подивився фільм учора), przeczytałaś tę książkę (ти прочитала цю книгу), obejrzała spektakl (вона подивилася виставу).", + "We form the past tense of entertainment with „obejrzałem/obejrzałam” or „przeczytałem/przeczytałam” depending on the speaker's gender: obejrzałem film wczoraj (I watched a film yesterday), przeczytałaś tę książkę (you read that book), obejrzała spektakl (she watched the play)."), + + ("a2_entertainment_culture_l10", 10, "opisuje_swoja_rozrywke", "Opisuję swoją rozrywkę", "Описываю своё развлечение", "Описую свою розвагу", "Describing my entertainment", + "Żeby opisać rozrywkę, łączymy zdania: Lubię filmy komediowe. Chodzę do kina raz w miesiącu. Obejrzałem wczoraj bardzo zabawny film.", + "Чтобы описать развлечение, соединяем предложения: Lubię filmy komediowe. Chodzę do kina raz w miesiącu. Obejrzałem wczoraj bardzo zabawny film. (Я люблю комедийные фильмы. Я хожу в кино раз в месяц. Я посмотрел вчера очень смешной фильм.)", + "Щоб описати розвагу, поєднуємо речення: Lubię filmy komediowe. Chodzę do kina raz w miesiącu. Obejrzałem wczoraj bardzo zabawny film. (Я люблю комедійні фільми. Я ходжу в кіно раз на місяць. Я подивився вчора дуже смішний фільм.)", + "To describe entertainment, we combine sentences: Lubię filmy komediowe. Chodzę do kina raz w miesiącu. Obejrzałem wczoraj bardzo zabawny film. (I like comedy films. I go to the cinema once a month. I watched a very funny film yesterday.)"), + ] + + for lesson in lessons_t10_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_entertainment_culture', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t10_a2 = [ + ("a2_entertainment_culture_l01", 1, "Idę do kina.", "Я иду в кино.", "Я йду в кіно.", "I'm going to the cinema."), + ("a2_entertainment_culture_l01", 2, "Byłem w teatrze.", "Я был в театре.", "Я був у театрі.", "I was at the theater."), + ("a2_entertainment_culture_l01", 3, "Mam bilety na koncert.", "У меня есть билеты на концерт.", "У мене є квитки на концерт.", "I have tickets to a concert."), + + ("a2_entertainment_culture_l02", 1, "Idę do kina.", "Я иду в кино.", "Я йду в кіно.", "I'm going to the cinema."), + ("a2_entertainment_culture_l02", 2, "Idziesz do teatru?", "Ты идёшь в театр?", "Ти йдеш до театру?", "Are you going to the theater?"), + ("a2_entertainment_culture_l02", 3, "Ona idzie do muzeum.", "Она идёт в музей.", "Вона йде до музею.", "She's going to the museum."), + + ("a2_entertainment_culture_l03", 1, "Oglądam ciekawy film.", "Я смотрю интересный фильм.", "Я дивлюся цікавий фільм.", "I'm watching an interesting film."), + ("a2_entertainment_culture_l03", 2, "Czytam dobrą książkę.", "Я читаю хорошую книгу.", "Я читаю хорошу книгу.", "I'm reading a good book."), + ("a2_entertainment_culture_l03", 3, "Lubię muzykę klasyczną.", "Я люблю классическую музыку.", "Я люблю класичну музику.", "I like classical music."), + + ("a2_entertainment_culture_l04", 1, "Lubię filmy komediowe.", "Я люблю комедийные фильмы.", "Я люблю комедійні фільми.", "I like comedy films."), + ("a2_entertainment_culture_l04", 2, "Lubisz muzykę pop?", "Ты любишь поп-музыку?", "Ти любиш поп-музику?", "Do you like pop music?"), + ("a2_entertainment_culture_l04", 3, "On lubi książki historyczne.", "Он любит исторические книги.", "Він любить історичні книги.", "He likes historical books."), + + ("a2_entertainment_culture_l05", 1, "Oglądam nowy film w kinie.", "Я смотрю новый фильм в кино.", "Я дивлюся новий фільм у кіно.", "I'm watching a new film at the cinema."), + ("a2_entertainment_culture_l05", 2, "Oglądasz ten serial?", "Ты смотришь этот сериал?", "Ти дивишся цей серіал?", "Are you watching this series?"), + ("a2_entertainment_culture_l05", 3, "Ona ogląda spektakl w teatrze.", "Она смотрит спектакль в театре.", "Вона дивиться виставу в театрі.", "She's watching a play at the theater."), + + ("a2_entertainment_culture_l06", 1, "Chodzę do kina raz w miesiącu.", "Я хожу в кино раз в месяц.", "Я ходжу в кіно раз на місяць.", "I go to the cinema once a month."), + ("a2_entertainment_culture_l06", 2, "Chodzisz do teatru często?", "Ты часто ходишь в театр?", "Ти часто ходиш до театру?", "Do you often go to the theater?"), + ("a2_entertainment_culture_l06", 3, "On chodzi do muzeum w weekendy.", "Он ходит в музей по выходным.", "Він ходить до музею у вихідні.", "He goes to the museum on weekends."), + + ("a2_entertainment_culture_l07", 1, "Ten film jest bardzo zabawny.", "Этот фильм очень смешной.", "Цей фільм дуже смішний.", "This film is very funny."), + ("a2_entertainment_culture_l07", 2, "Ta książka jest smutna.", "Эта книга грустная.", "Ця книга сумна.", "This book is sad."), + ("a2_entertainment_culture_l07", 3, "Spektakl był wzruszający.", "Спектакль был трогательный.", "Вистава була зворушлива.", "The play was moving."), + + ("a2_entertainment_culture_l08", 1, "Wolę czytać książki niż oglądać filmy.", "Я предпочитаю читать книги, чем смотреть фильмы.", "Я віддаю перевагу читанню книг, а не перегляду фільмів.", "I prefer reading books to watching films."), + ("a2_entertainment_culture_l08", 2, "Wolisz muzykę klasyczną czy pop?", "Ты предпочитаешь классическую музыку или поп?", "Ти віддаєш перевагу класичній музиці чи поп-музиці?", "Do you prefer classical music or pop?"), + ("a2_entertainment_culture_l08", 3, "Ona woli chodzić do teatru.", "Она предпочитает ходить в театр.", "Вона віддає перевагу ходінню до театру.", "She prefers going to the theater."), + + ("a2_entertainment_culture_l09", 1, "Obejrzałem ten film wczoraj.", "Я посмотрел этот фильм вчера.", "Я подивився цей фільм учора.", "I watched this film yesterday."), + ("a2_entertainment_culture_l09", 2, "Przeczytałaś tę książkę?", "Ты прочитала эту книгу?", "Ти прочитала цю книгу?", "Did you read that book?"), + ("a2_entertainment_culture_l09", 3, "Ona obejrzała spektakl w zeszłym tygodniu.", "Она посмотрела спектакль на прошлой неделе.", "Вона подивилася виставу минулого тижня.", "She watched the play last week."), + + ("a2_entertainment_culture_l10", 1, "Lubię filmy komediowe.", "Я люблю комедийные фильмы.", "Я люблю комедійні фільми.", "I like comedy films."), + ("a2_entertainment_culture_l10", 2, "Chodzę do kina raz w miesiącu.", "Я хожу в кино раз в месяц.", "Я ходжу в кіно раз на місяць.", "I go to the cinema once a month."), + ("a2_entertainment_culture_l10", 3, "Obejrzałem wczoraj bardzo zabawny film.", "Я посмотрел вчера очень смешной фильм.", "Я подивився вчора дуже смішний фільм.", "I watched a very funny film yesterday."), + ] + + for ex in examples_t10_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t10_a2 = [ + # L01 — rozrywka_vocabulary (difficulty 1) + ("a2_entertainment_culture_l01_q1", "a2_entertainment_culture_l01", "lesson_practice", "recognition", "rozrywka_vocabulary", 1, + "Jak po polsku „музей”?", "Как по-польски «музей»?", "Як польською «музей»?", "How do you say “museum” in Polish?", + "D", None, None), + ("a2_entertainment_culture_l01_q2", "a2_entertainment_culture_l01", "lesson_practice", "production", "rozrywka_vocabulary", 1, + "Wpisz brakujące słowo: Mam bilety na ___. (концерт)", "Вставьте пропущенное слово: Mam bilety na ___. (концерт)", "Вставте пропущене слово: Mam bilety na ___. (концерт)", "Fill in the missing word: Mam bilety na ___. (concert)", + "koncert", "first_letter", "k"), + ("a2_entertainment_culture_l01_q3", "a2_entertainment_culture_l01", "lesson_practice", "application", "rozrywka_vocabulary", 1, + "Chcesz zobaczyć aktorów na żywo na scenie. Dokąd idziesz?", "Ты хочешь увидеть актёров вживую на сцене. Куда ты идёшь?", "Ти хочеш побачити акторів наживо на сцені. Куди ти йдеш?", "You want to see actors live on stage. Where are you going?", + "B", None, None), + + # L02 — isc_do_dopelniacza (difficulty 1) + ("a2_entertainment_culture_l02_q1", "a2_entertainment_culture_l02", "lesson_practice", "recognition", "isc_do_dopelniacza", 1, + "Wybierz poprawną formę: Idę do ___. (kino)", "Выберите правильную форму: Idę do ___. (kino)", "Виберіть правильну форму: Idę do ___. (kino)", "Choose the correct form: Idę do ___. (kino)", + "A", None, None), + ("a2_entertainment_culture_l02_q2", "a2_entertainment_culture_l02", "lesson_practice", "production", "isc_do_dopelniacza", 1, + "Wpisz brakujące słowo: Idziesz do ___? (театра)", "Вставьте пропущенное слово: Idziesz do ___? (театра)", "Вставте пропущене слово: Idziesz do ___? (театру)", "Fill in the missing word: Idziesz do ___? (theater)", + "teatru", "first_letter", "t"), + ("a2_entertainment_culture_l02_q3", "a2_entertainment_culture_l02", "lesson_practice", "application", "isc_do_dopelniacza", 1, + "Kolega pyta, dokąd idziesz wieczorem. Idziesz do kina. Co powiesz?", "Друг спрашивает, куда ты идёшь вечером. Ты идёшь в кино. Что ты скажешь?", "Друг питає, куди ти йдеш увечері. Ти йдеш до кіно. Що ти скажеш?", "A friend asks where you're going in the evening. You're going to the cinema. What do you say?", + "C", None, None), + + # L03 — kultura_vocabulary (difficulty 1) + ("a2_entertainment_culture_l03_q1", "a2_entertainment_culture_l03", "lesson_practice", "recognition", "kultura_vocabulary", 1, + "Jak po polsku „искусство”?", "Как по-польски «искусство»?", "Як польською «мистецтво»?", "How do you say “art” in Polish?", + "D", None, None), + ("a2_entertainment_culture_l03_q2", "a2_entertainment_culture_l03", "lesson_practice", "production", "kultura_vocabulary", 1, + "Wpisz brakujące słowo: Czytam dobrą ___. (книгу)", "Вставьте пропущенное слово: Czytam dobrą ___. (книгу)", "Вставте пропущене слово: Czytam dobrą ___. (книгу)", "Fill in the missing word: Czytam dobrą ___. (book)", + "książkę", "first_letter", "k"), + ("a2_entertainment_culture_l03_q3", "a2_entertainment_culture_l03", "lesson_practice", "application", "kultura_vocabulary", 1, + "Interesujesz się obrazami i rzeźbami. Co lubisz?", "Ты интересуешься картинами и скульптурами. Что ты любишь?", "Ти цікавишся картинами і скульптурами. Що ти любиш?", "You're interested in paintings and sculptures. What do you like?", + "D", None, None), + + # L04 — lubic_rzeczownik (difficulty 1) + ("a2_entertainment_culture_l04_q1", "a2_entertainment_culture_l04", "lesson_practice", "recognition", "lubic_rzeczownik", 1, + "Wybierz poprawną formę: Lubię ___. (muzyka)", "Выберите правильную форму: Lubię ___. (muzyka)", "Виберіть правильну форму: Lubię ___. (muzyka)", "Choose the correct form: Lubię ___. (muzyka)", + "A", None, None), + ("a2_entertainment_culture_l04_q2", "a2_entertainment_culture_l04", "lesson_practice", "production", "lubic_rzeczownik", 1, + "Wpisz brakujące słowo: Lubisz ___? (книги)", "Вставьте пропущенное слово: Lubisz ___? (книги)", "Вставте пропущене слово: Lubisz ___? (книги)", "Fill in the missing word: Lubisz ___? (books)", + "książki", "first_letter", "k"), + ("a2_entertainment_culture_l04_q3", "a2_entertainment_culture_l04", "lesson_practice", "application", "lubic_rzeczownik", 1, + "Kolega pyta, jaką muzykę lubisz. Lubisz muzykę klasyczną. Co powiesz?", "Друг спрашивает, какую музыку ты любишь. Ты любишь классическую музыку. Что ты скажешь?", "Друг питає, яку музику ти любиш. Ти любиш класичну музику. Що ти скажеш?", "A friend asks what music you like. You like classical music. What do you say?", + "C", None, None), + + # L05 — ogladac_biernik (difficulty 2) + ("a2_entertainment_culture_l05_q1", "a2_entertainment_culture_l05", "lesson_practice", "recognition", "ogladac_biernik", 2, + "Wybierz poprawną formę: Oglądam ___. (serial)", "Выберите правильную форму: Oglądam ___. (serial)", "Виберіть правильну форму: Oglądam ___. (serial)", "Choose the correct form: Oglądam ___. (serial)", + "A", None, None), + ("a2_entertainment_culture_l05_q2", "a2_entertainment_culture_l05", "lesson_practice", "production", "ogladac_biernik", 2, + "Wpisz brakujące słowo: Oglądasz ___? (спектакль)", "Вставьте пропущенное слово: Oglądasz ___? (спектакль)", "Вставте пропущене слово: Oglądasz ___? (виставу)", "Fill in the missing word: Oglądasz ___? (play)", + "spektakl", "first_letter", "s"), + ("a2_entertainment_culture_l05_q3", "a2_entertainment_culture_l05", "lesson_practice", "application", "ogladac_biernik", 2, + "Chcesz opowiedzieć, że właśnie w tej chwili śledzisz nowy serial na streamingu. Co powiesz?", "Ты хочешь рассказать, что прямо сейчас смотришь новый сериал на стриминге. Что ты скажешь?", "Ти хочеш розповісти, що прямо зараз дивишся новий серіал на стримінгу. Що ти скажеш?", "You want to say that right now you're watching a new series on streaming. What do you say?", + "A", None, None), + + # L06 — chodzic_do_kina (difficulty 2) + ("a2_entertainment_culture_l06_q1", "a2_entertainment_culture_l06", "lesson_practice", "recognition", "chodzic_do_kina", 2, + "Wybierz poprawną formę: Chodzę ___ kina. (do)", "Выберите правильную форму: Chodzę ___ kina. (do)", "Виберіть правильну форму: Chodzę ___ kina. (do)", "Choose the correct form: Chodzę ___ kina. (do)", + "A", None, None), + ("a2_entertainment_culture_l06_q2", "a2_entertainment_culture_l06", "lesson_practice", "production", "chodzic_do_kina", 2, + "Wpisz brakujące słowo: Chodzisz do ___? (театра)", "Вставьте пропущенное слово: Chodzisz do ___? (театра)", "Вставте пропущене слово: Chodzisz do ___? (театру)", "Fill in the missing word: Chodzisz do ___? (theater)", + "teatru", "first_letter", "t"), + ("a2_entertainment_culture_l06_q3", "a2_entertainment_culture_l06", "lesson_practice", "application", "chodzic_do_kina", 2, + "Regularnie chodzisz do muzeum w każdy weekend. Co powiesz?", "Ты регулярно ходишь в музей каждые выходные. Что ты скажешь?", "Ти регулярно ходиш до музею щовихідних. Що ти скажеш?", "You regularly go to the museum every weekend. What do you say?", + "A", None, None), + + # L07 — przymiotniki_kultura_vocabulary (difficulty 2) + ("a2_entertainment_culture_l07_q1", "a2_entertainment_culture_l07", "lesson_practice", "recognition", "przymiotniki_kultura_vocabulary", 2, + "Jak po polsku „трогательный”?", "Как по-польски «трогательный»?", "Як польською «зворушливий»?", "How do you say “moving/touching” in Polish?", + "C", None, None), + ("a2_entertainment_culture_l07_q2", "a2_entertainment_culture_l07", "lesson_practice", "production", "przymiotniki_kultura_vocabulary", 2, + "Wpisz brakujące słowo: Ten film jest ___. (смешной)", "Вставьте пропущенное слово: Ten film jest ___. (смешной)", "Вставте пропущене слово: Ten film jest ___. (смішний)", "Fill in the missing word: Ten film jest ___. (funny)", + "zabawny", "first_letter", "z"), + ("a2_entertainment_culture_l07_q3", "a2_entertainment_culture_l07", "lesson_practice", "application", "przymiotniki_kultura_vocabulary", 2, + "Obejrzałeś film, który był bardzo nudny i nieciekawy. Jaki on był?", "Ты посмотрел фильм, который был очень скучный и неинтересный. Каким он был?", "Ти подивився фільм, який був дуже нудний і нецікавий. Яким він був?", "You watched a film that was very boring and uninteresting. What was it like?", + "D", None, None), + + # L08 — woleć_biernik (difficulty 2) + ("a2_entertainment_culture_l08_q1", "a2_entertainment_culture_l08", "lesson_practice", "recognition", "woleć_biernik", 2, + "Wybierz poprawną formę: ___ czytać książki. (woleć, ja)", "Выберите правильную форму: ___ czytać książki. (woleć, ja)", "Виберіть правильну форму: ___ czytać książki. (woleć, ja)", "Choose the correct form: ___ czytać książki. (woleć, I)", + "A", None, None), + ("a2_entertainment_culture_l08_q2", "a2_entertainment_culture_l08", "lesson_practice", "production", "woleć_biernik", 2, + "Wpisz brakujące słowo: ___ muzykę klasyczną? (ты предпочитаешь)", "Вставьте пропущенное слово: ___ muzykę klasyczną? (ты предпочитаешь)", "Вставте пропущене слово: ___ muzykę klasyczną? (ти віддаєш перевагу)", "Fill in the missing word: ___ muzykę klasyczną? (do you prefer)", + "Wolisz", "first_letter", "W"), + ("a2_entertainment_culture_l08_q3", "a2_entertainment_culture_l08", "lesson_practice", "application", "woleć_biernik", 2, + "Kolega pyta, co wolisz robić wieczorem: czytać czy oglądać telewizję. Wolisz czytać. Co powiesz?", "Друг спрашивает, что ты предпочитаешь делать вечером: читать или смотреть телевизор. Ты предпочитаешь читать. Что ты скажешь?", "Друг питає, що ти віддаєш перевагу робити ввечері: читати чи дивитися телевізор. Ти віддаєш перевагу читанню. Що ти скажеш?", "A friend asks what you prefer to do in the evening: read or watch TV. You prefer reading. What do you say?", + "B", None, None), + + # L09 — przeszly_czas_rozrywka (difficulty 3) + ("a2_entertainment_culture_l09_q1", "a2_entertainment_culture_l09", "lesson_practice", "recognition", "przeszly_czas_rozrywka", 3, + "Co znaczy „Przeczytałaś tę książkę”?", "Что означает «Przeczytałaś tę książkę»?", "Що означає «Przeczytałaś tę książkę»?", "What does “Przeczytałaś tę książkę” mean?", + "D", None, None), + ("a2_entertainment_culture_l09_q2", "a2_entertainment_culture_l09", "lesson_practice", "production", "przeszly_czas_rozrywka", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ ten film wczoraj. (я посмотрела)", "Вставьте пропущенное слово (говорит женщина): ___ ten film wczoraj. (я посмотрела)", "Вставте пропущене слово (говорить жінка): ___ ten film wczoraj. (я подивилася)", "Fill in the missing word (a woman is speaking): ___ ten film wczoraj. (I watched)", + "Obejrzałam", "first_letter", "O"), + ("a2_entertainment_culture_l09_q3", "a2_entertainment_culture_l09", "lesson_practice", "application", "przeszly_czas_rozrywka", 3, + "Mężczyzna opowiada, że wczoraj obejrzał ciekawy film w kinie. Co powie?", "Мужчина рассказывает, что вчера посмотрел интересный фильм в кино. Что он скажет?", "Чоловік розповідає, що вчора подивився цікавий фільм у кіно. Що він скаже?", "A man is telling that yesterday he watched an interesting film at the cinema. What does he say?", + "B", None, None), + + # L10 — opisuje_swoja_rozrywke (difficulty 3) + ("a2_entertainment_culture_l10_q1", "a2_entertainment_culture_l10", "lesson_practice", "recognition", "opisuje_swoja_rozrywke", 3, + "Które zdanie poprawnie opisuje rozrywkę?", "Какое предложение правильно описывает развлечение?", "Яке речення правильно описує розвагу?", "Which sentence correctly describes entertainment?", + "D", None, None), + ("a2_entertainment_culture_l10_q2", "a2_entertainment_culture_l10", "lesson_practice", "production", "opisuje_swoja_rozrywke", 3, + "Przetłumacz: «Я посмотрел вчера очень смешной фильм».", "Переведите: «Я посмотрел вчера очень смешной фильм».", "Перекладіть: «Я подивився вчора дуже смішний фільм».", "Translate: “I watched a very funny film yesterday.”", + "Obejrzałem wczoraj bardzo zabawny film", "first_letter", "O"), + ("a2_entertainment_culture_l10_q3", "a2_entertainment_culture_l10", "lesson_practice", "application", "opisuje_swoja_rozrywke", 3, + "Chcesz opisać koledze swoją rozrywkę: lubisz filmy komediowe, chodzisz do kina, obejrzałeś zabawny film. Jak zaczniesz zdanie?", "Ты хочешь описать другу своё развлечение: ты любишь комедийные фильмы, ходишь в кино, посмотрел смешной фильм. Как ты начнёшь предложение?", "Ти хочеш описати другу свою розвагу: ти любиш комедійні фільми, ходиш до кіно, подивився смішний фільм. Як ти почнеш речення?", "You want to describe your entertainment to a friend: you like comedy films, go to the cinema, watched a funny film. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t10_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_entertainment_culture', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t10_a2 = [ + # L01 + ("a2_entertainment_culture_l01_q1", "A", "kino", "кино", "кіно", "cinema", False, "wrong_word"), + ("a2_entertainment_culture_l01_q1", "B", "teatr", "театр", "театр", "theater", False, "wrong_word"), + ("a2_entertainment_culture_l01_q1", "C", "koncert", "концерт", "концерт", "concert", False, "wrong_word"), + ("a2_entertainment_culture_l01_q1", "D", "muzeum", "музей", "музей", "museum", True, None), + + ("a2_entertainment_culture_l01_q3", "A", "Do kina.", "В кино.", "До кіно.", "To the cinema.", False, "wrong_context"), + ("a2_entertainment_culture_l01_q3", "B", "Do teatru.", "В театр.", "До театру.", "To the theater.", True, None), + ("a2_entertainment_culture_l01_q3", "C", "Do muzeum.", "В музей.", "До музею.", "To the museum.", False, "wrong_context"), + ("a2_entertainment_culture_l01_q3", "D", "Na koncert.", "На концерт.", "На концерт.", "To a concert.", False, "wrong_context"), + + # L02 + ("a2_entertainment_culture_l02_q1", "A", "kina", "кино (род.)", "кіно (род.)", "cinema (gen.)", True, None), + ("a2_entertainment_culture_l02_q1", "B", "kino", "кино (им./вин.)", "кіно (наз./знах.)", "cinema (nom./acc.)", False, "wrong_case"), + ("a2_entertainment_culture_l02_q1", "C", "kinie", "кино (местн.)", "кіно (місц.)", "cinema (loc.)", False, "wrong_case"), + ("a2_entertainment_culture_l02_q1", "D", "kinu", "кино (дат.)", "кіно (дав.)", "cinema (dat.)", False, "wrong_case"), + + ("a2_entertainment_culture_l02_q3", "A", "Idę do teatru.", "Я иду в театр. (не соответствует ситуации)", "Я йду до театру. (не відповідає ситуації)", "I'm going to the theater. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l02_q3", "B", "Idę do muzeum.", "Я иду в музей. (не соответствует ситуации)", "Я йду до музею. (не відповідає ситуації)", "I'm going to the museum. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l02_q3", "C", "Idę do kina.", "Я иду в кино.", "Я йду до кіно.", "I'm going to the cinema.", True, None), + ("a2_entertainment_culture_l02_q3", "D", "Idę do domu.", "Я иду домой. (не соответствует ситуации)", "Я йду додому. (не відповідає ситуації)", "I'm going home. (doesn't match the situation)", False, "wrong_context"), + + # L03 + ("a2_entertainment_culture_l03_q1", "A", "film", "фильм", "фільм", "film", False, "wrong_word"), + ("a2_entertainment_culture_l03_q1", "B", "książka", "книга", "книга", "book", False, "wrong_word"), + ("a2_entertainment_culture_l03_q1", "C", "muzyka", "музыка", "музика", "music", False, "wrong_word"), + ("a2_entertainment_culture_l03_q1", "D", "sztuka", "искусство", "мистецтво", "art", True, None), + + ("a2_entertainment_culture_l03_q3", "A", "Film.", "Фильм.", "Фільм.", "Film.", False, "wrong_context"), + ("a2_entertainment_culture_l03_q3", "B", "Książkę.", "Книгу.", "Книгу.", "A book.", False, "wrong_context"), + ("a2_entertainment_culture_l03_q3", "C", "Muzykę.", "Музыку.", "Музику.", "Music.", False, "wrong_context"), + ("a2_entertainment_culture_l03_q3", "D", "Sztukę.", "Искусство.", "Мистецтво.", "Art.", True, None), + + # L04 + ("a2_entertainment_culture_l04_q1", "A", "muzykę", "музыку (вин.)", "музику (знах.)", "music (acc.)", True, None), + ("a2_entertainment_culture_l04_q1", "B", "muzyka", "музыка (им.)", "музика (наз.)", "music (nom.)", False, "wrong_case"), + ("a2_entertainment_culture_l04_q1", "C", "muzyki", "музыки (род.)", "музики (род.)", "music (gen.)", False, "wrong_case"), + ("a2_entertainment_culture_l04_q1", "D", "muzyce", "музыке (местн./дат.)", "музиці (місц./дав.)", "music (loc./dat.)", False, "wrong_case"), + + ("a2_entertainment_culture_l04_q3", "A", "Lubię filmy.", "Я люблю фильмы. (не соответствует ситуации)", "Я люблю фільми. (не відповідає ситуації)", "I like films. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l04_q3", "B", "Lubię książki.", "Я люблю книги. (не соответствует ситуации)", "Я люблю книги. (не відповідає ситуації)", "I like books. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l04_q3", "C", "Lubię muzykę klasyczną.", "Я люблю классическую музыку.", "Я люблю класичну музику.", "I like classical music.", True, None), + ("a2_entertainment_culture_l04_q3", "D", "Lubię sztukę.", "Я люблю искусство. (не соответствует ситуации)", "Я люблю мистецтво. (не відповідає ситуації)", "I like art. (doesn't match the situation)", False, "wrong_context"), + + # L05 + ("a2_entertainment_culture_l05_q1", "A", "serial", "сериал (вин.)", "серіал (знах.)", "series (acc.)", True, None), + ("a2_entertainment_culture_l05_q1", "B", "serialu", "сериала (род.)", "серіалу (род.)", "series (gen.)", False, "wrong_case"), + ("a2_entertainment_culture_l05_q1", "C", "serialem", "сериалом (тв.)", "серіалом (ор.)", "series (instr.)", False, "wrong_case"), + ("a2_entertainment_culture_l05_q1", "D", "serialowi", "сериалу (дат.)", "серіалу (дав.)", "series (dat.)", False, "wrong_case"), + + ("a2_entertainment_culture_l05_q3", "A", "Oglądam nowy serial.", "Я смотрю новый сериал.", "Я дивлюся новий серіал.", "I'm watching a new series.", True, None), + ("a2_entertainment_culture_l05_q3", "B", "Czytam nową książkę.", "Я читаю новую книгу. (не соответствует ситуации)", "Я читаю нову книгу. (не відповідає ситуації)", "I'm reading a new book. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l05_q3", "C", "Słucham muzyki.", "Я слушаю музыку. (не соответствует ситуации)", "Я слухаю музику. (не відповідає ситуації)", "I'm listening to music. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l05_q3", "D", "Idę do kina.", "Я иду в кино. (не соответствует ситуации)", "Я йду до кіно. (не відповідає ситуації)", "I'm going to the cinema. (doesn't match the situation)", False, "wrong_context"), + + # L06 + ("a2_entertainment_culture_l06_q1", "A", "do", "в/к", "в/до", "to", True, None), + ("a2_entertainment_culture_l06_q1", "B", "na", "на", "на", "to", False, "wrong_word"), + ("a2_entertainment_culture_l06_q1", "C", "w", "в", "в", "in", False, "wrong_word"), + ("a2_entertainment_culture_l06_q1", "D", "u", "у", "у", "at", False, "wrong_word"), + + ("a2_entertainment_culture_l06_q3", "A", "Chodzę do muzeum w weekendy.", "Я хожу в музей по выходным.", "Я ходжу до музею у вихідні.", "I go to the museum on weekends.", True, None), + ("a2_entertainment_culture_l06_q3", "B", "Chodzę do kina raz w miesiącu.", "Я хожу в кино раз в месяц. (не соответствует ситуации)", "Я ходжу до кіно раз на місяць. (не відповідає ситуації)", "I go to the cinema once a month. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l06_q3", "C", "Chodzę do teatru często.", "Я часто хожу в театр. (не соответствует ситуации)", "Я часто ходжу до театру. (не відповідає ситуації)", "I often go to the theater. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l06_q3", "D", "Oglądam telewizję w weekendy.", "Я смотрю телевизор по выходным. (неверный глагол)", "Я дивлюся телевізор у вихідні. (невірне дієслово)", "I watch TV on weekends. (wrong verb)", False, "wrong_word"), + + # L07 + ("a2_entertainment_culture_l07_q1", "A", "zabawny", "смешной", "смішний", "funny", False, "wrong_word"), + ("a2_entertainment_culture_l07_q1", "B", "smutny", "грустный", "сумний", "sad", False, "wrong_word"), + ("a2_entertainment_culture_l07_q1", "C", "wzruszający", "трогательный", "зворушливий", "moving", True, None), + ("a2_entertainment_culture_l07_q1", "D", "nudny", "скучный", "нудний", "boring", False, "wrong_word"), + + ("a2_entertainment_culture_l07_q3", "A", "Zabawny.", "Смешной.", "Смішний.", "Funny.", False, "wrong_context"), + ("a2_entertainment_culture_l07_q3", "B", "Smutny.", "Грустный.", "Сумний.", "Sad.", False, "wrong_context"), + ("a2_entertainment_culture_l07_q3", "C", "Wzruszający.", "Трогательный.", "Зворушливий.", "Moving.", False, "wrong_context"), + ("a2_entertainment_culture_l07_q3", "D", "Nudny.", "Скучный.", "Нудний.", "Boring.", True, None), + + # L08 + ("a2_entertainment_culture_l08_q1", "A", "Wolę", "я предпочитаю", "я віддаю перевагу", "I prefer", True, None), + ("a2_entertainment_culture_l08_q1", "B", "Wolisz", "ты предпочитаешь (не тот человек)", "ти віддаєш перевагу (не та особа)", "you prefer (wrong person)", False, "wrong_context"), + ("a2_entertainment_culture_l08_q1", "C", "Woli", "он/она предпочитает (не тот человек)", "він/вона віддає перевагу (не та особа)", "he/she prefers (wrong person)", False, "wrong_context"), + ("a2_entertainment_culture_l08_q1", "D", "Woleli", "они предпочитали (неправильное число и время)", "вони віддавали перевагу (неправильне число і час)", "they preferred (wrong number and tense)", False, "wrong_number"), + + ("a2_entertainment_culture_l08_q3", "A", "Wolę oglądać telewizję.", "Я предпочитаю смотреть телевизор. (не соответствует ситуации)", "Я віддаю перевагу перегляду телевізора. (не відповідає ситуації)", "I prefer watching TV. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l08_q3", "B", "Wolę czytać.", "Я предпочитаю читать.", "Я віддаю перевагу читанню.", "I prefer reading.", True, None), + ("a2_entertainment_culture_l08_q3", "C", "Wolę słuchać muzyki.", "Я предпочитаю слушать музыку. (не соответствует ситуации)", "Я віддаю перевагу слуханню музики. (не відповідає ситуації)", "I prefer listening to music. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_l08_q3", "D", "Lubię czytać.", "Мне нравится читать. (не о сравнении/предпочтении)", "Мені подобається читати. (не про порівняння/перевагу)", "I like reading. (not about a comparison/preference)", False, "wrong_context"), + + # L09 + ("a2_entertainment_culture_l09_q1", "A", "Czytasz tę książkę?", "Ты читаешь эту книгу?", "Ти читаєш цю книгу?", "Are you reading that book?", False, "wrong_translation"), + ("a2_entertainment_culture_l09_q1", "B", "Przeczytasz tę książkę?", "Ты прочитаешь эту книгу?", "Ти прочитаєш цю книгу?", "Will you read that book?", False, "wrong_translation"), + ("a2_entertainment_culture_l09_q1", "C", "Napisałaś tę książkę?", "Ты написала эту книгу?", "Ти написала цю книгу?", "Did you write that book?", False, "wrong_translation"), + ("a2_entertainment_culture_l09_q1", "D", "Przeczytałaś tę książkę?", "Ты прочитала эту книгу?", "Ти прочитала цю книгу?", "Did you read that book?", True, None), + + ("a2_entertainment_culture_l09_q3", "A", "Oglądam ciekawy film.", "Я смотрю интересный фильм. (настоящее время)", "Я дивлюся цікавий фільм. (теперішній час)", "I'm watching an interesting film. (present tense)", False, "wrong_sentence_type"), + ("a2_entertainment_culture_l09_q3", "B", "Obejrzałem ciekawy film.", "Я посмотрел интересный фильм.", "Я подивився цікавий фільм.", "I watched an interesting film.", True, None), + ("a2_entertainment_culture_l09_q3", "C", "Obejrzę ciekawy film.", "Я посмотрю интересный фильм. (будущее время)", "Я подивлюся цікавий фільм. (майбутній час)", "I will watch an interesting film. (future tense)", False, "wrong_sentence_type"), + ("a2_entertainment_culture_l09_q3", "D", "Obejrzałam ciekawy film.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + # L10 + ("a2_entertainment_culture_l10_q1", "A", "Lubię ja filmy ja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_entertainment_culture_l10_q1", "B", "Filmy lubię komediowe.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_entertainment_culture_l10_q1", "C", "Lubię komediowe filmy ja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_entertainment_culture_l10_q1", "D", "Lubię filmy komediowe i chodzę do kina raz w miesiącu.", "Я люблю комедийные фильмы и хожу в кино раз в месяц.", "Я люблю комедійні фільми і ходжу до кіно раз на місяць.", "I like comedy films and I go to the cinema once a month.", True, None), + + ("a2_entertainment_culture_l10_q3", "A", "Chodzę do kina.", "Я хожу в кино. (не начало описания)", "Я ходжу до кіно. (не початок опису)", "I go to the cinema. (not the opening line)", False, "wrong_context"), + ("a2_entertainment_culture_l10_q3", "B", "Obejrzałem zabawny film.", "Я посмотрел смешной фильм. (не начало описания)", "Я подивився смішний фільм. (не початок опису)", "I watched a funny film. (not the opening line)", False, "wrong_context"), + ("a2_entertainment_culture_l10_q3", "C", "Lubię filmy komediowe.", "Я люблю комедийные фильмы.", "Я люблю комедійні фільми.", "I like comedy films.", True, None), + ("a2_entertainment_culture_l10_q3", "D", "Oglądałem film.", "Я смотрел фильм. (прошедшее время, не соответствует ситуации)", "Я дивився фільм. (минулий час, не відповідає ситуації)", "I was watching a film. (past tense, doesn't match the situation)", False, "wrong_context"), + ] + + for opt in options_t10_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t10_a2 = [ + ("a2_entertainment_culture_t01", None, "topic_test", "recognition", "rozrywka_vocabulary", 1, + "Jak po polsku „музей”?", "Как по-польски «музей»?", "Як польською «музей»?", "How do you say “museum” in Polish?", + "D", None, None, 1), + ("a2_entertainment_culture_t02", None, "topic_test", "recognition", "isc_do_dopelniacza", 1, + "Wybierz poprawną formę: Idę do ___. (kino)", "Выберите правильную форму: Idę do ___. (kino)", "Виберіть правильну форму: Idę do ___. (kino)", "Choose the correct form: Idę do ___. (kino)", + "A", None, None, 2), + ("a2_entertainment_culture_t03", None, "topic_test", "recognition", "kultura_vocabulary", 1, + "Jak po polsku „искусство”?", "Как по-польски «искусство»?", "Як польською «мистецтво»?", "How do you say “art” in Polish?", + "D", None, None, 3), + ("a2_entertainment_culture_t04", None, "topic_test", "recognition", "lubic_rzeczownik", 1, + "Wybierz poprawną formę: Lubię ___. (muzyka)", "Выберите правильную форму: Lubię ___. (muzyka)", "Виберіть правильну форму: Lubię ___. (muzyka)", "Choose the correct form: Lubię ___. (muzyka)", + "A", None, None, 4), + ("a2_entertainment_culture_t05", None, "topic_test", "recognition", "ogladac_biernik", 2, + "Wybierz poprawną formę: Oglądam ___. (serial)", "Выберите правильную форму: Oglądam ___. (serial)", "Виберіть правильну форму: Oglądam ___. (serial)", "Choose the correct form: Oglądam ___. (serial)", + "A", None, None, 5), + ("a2_entertainment_culture_t06", None, "topic_test", "recognition", "przeszly_czas_rozrywka", 3, + "Co znaczy „Przeczytałaś tę książkę”?", "Что означает «Przeczytałaś tę książkę»?", "Що означає «Przeczytałaś tę książkę»?", "What does “Przeczytałaś tę książkę” mean?", + "D", None, None, 6), + + ("a2_entertainment_culture_t07", None, "topic_test", "application", "rozrywka_vocabulary", 1, + "Chcesz zobaczyć aktorów na żywo na scenie. Dokąd idziesz?", "Ты хочешь увидеть актёров вживую на сцене. Куда ты идёшь?", "Ти хочеш побачити акторів наживо на сцені. Куди ти йдеш?", "You want to see actors live on stage. Where are you going?", + "B", None, None, 7), + ("a2_entertainment_culture_t08", None, "topic_test", "application", "isc_do_dopelniacza", 1, + "Kolega pyta, dokąd idziesz wieczorem. Idziesz do kina. Co powiesz?", "Друг спрашивает, куда ты идёшь вечером. Ты идёшь в кино. Что ты скажешь?", "Друг питає, куди ти йдеш увечері. Ти йдеш до кіно. Що ти скажеш?", "A friend asks where you're going in the evening. You're going to the cinema. What do you say?", + "C", None, None, 8), + ("a2_entertainment_culture_t09", None, "topic_test", "application", "kultura_vocabulary", 1, + "Interesujesz się obrazami i rzeźbami. Co lubisz?", "Ты интересуешься картинами и скульптурами. Что ты любишь?", "Ти цікавишся картинами і скульптурами. Що ти любиш?", "You're interested in paintings and sculptures. What do you like?", + "D", None, None, 9), + ("a2_entertainment_culture_t10", None, "topic_test", "application", "chodzic_do_kina", 2, + "Regularnie chodzisz do muzeum w każdy weekend. Co powiesz?", "Ты регулярно ходишь в музей каждые выходные. Что ты скажешь?", "Ти регулярно ходиш до музею щовихідних. Що ти скажеш?", "You regularly go to the museum every weekend. What do you say?", + "A", None, None, 10), + ("a2_entertainment_culture_t11", None, "topic_test", "application", "przymiotniki_kultura_vocabulary", 2, + "Obejrzałeś film, który był bardzo nudny i nieciekawy. Jaki on był?", "Ты посмотрел фильм, который был очень скучный и неинтересный. Каким он был?", "Ти подивився фільм, який був дуже нудний і нецікавий. Яким він був?", "You watched a film that was very boring and uninteresting. What was it like?", + "D", None, None, 11), + ("a2_entertainment_culture_t12", None, "topic_test", "application", "przeszly_czas_rozrywka", 3, + "Mężczyzna opowiada, że wczoraj obejrzał ciekawy film w kinie. Co powie?", "Мужчина рассказывает, что вчера посмотрел интересный фильм в кино. Что он скажет?", "Чоловік розповідає, що вчора подивився цікавий фільм у кіно. Що він скаже?", "A man is telling that yesterday he watched an interesting film at the cinema. What does he say?", + "B", None, None, 12), + + ("a2_entertainment_culture_t13", None, "topic_test", "production", "rozrywka_vocabulary", 1, + "Wpisz brakujące słowo: Mam bilety na ___. (концерт)", "Вставьте пропущенное слово: Mam bilety na ___. (концерт)", "Вставте пропущене слово: Mam bilety na ___. (концерт)", "Fill in the missing word: Mam bilety na ___. (concert)", + "koncert", "first_letter", "k", 13), + ("a2_entertainment_culture_t14", None, "topic_test", "production", "kultura_vocabulary", 1, + "Wpisz brakujące słowo: Czytam dobrą ___. (книгу)", "Вставьте пропущенное слово: Czytam dobrą ___. (книгу)", "Вставте пропущене слово: Czytam dobrą ___. (книгу)", "Fill in the missing word: Czytam dobrą ___. (book)", + "książkę", "first_letter", "k", 14), + ("a2_entertainment_culture_t15", None, "topic_test", "production", "ogladac_biernik", 2, + "Wpisz brakujące słowo: Oglądasz ___? (спектакль)", "Вставьте пропущенное слово: Oglądasz ___? (спектакль)", "Вставте пропущене слово: Oglądasz ___? (виставу)", "Fill in the missing word: Oglądasz ___? (play)", + "spektakl", "first_letter", "s", 15), + ("a2_entertainment_culture_t16", None, "topic_test", "production", "chodzic_do_kina", 2, + "Wpisz brakujące słowo: Chodzisz do ___? (театра)", "Вставьте пропущенное слово: Chodzisz do ___? (театра)", "Вставте пропущене слово: Chodzisz do ___? (театру)", "Fill in the missing word: Chodzisz do ___? (theater)", + "teatru", "first_letter", "t", 16), + ("a2_entertainment_culture_t17", None, "topic_test", "production", "woleć_biernik", 2, + "Wpisz brakujące słowo: ___ muzykę klasyczną? (ты предпочитаешь)", "Вставьте пропущенное слово: ___ muzykę klasyczną? (ты предпочитаешь)", "Вставте пропущене слово: ___ muzykę klasyczną? (ти віддаєш перевагу)", "Fill in the missing word: ___ muzykę klasyczną? (do you prefer)", + "Wolisz", "first_letter", "W", 17), + ("a2_entertainment_culture_t18", None, "topic_test", "production", "opisuje_swoja_rozrywke", 3, + "Przetłumacz: «Я посмотрел вчера очень смешной фильм».", "Переведите: «Я посмотрел вчера очень смешной фильм».", "Перекладіть: «Я подивився вчора дуже смішний фільм».", "Translate: “I watched a very funny film yesterday.”", + "Obejrzałem wczoraj bardzo zabawny film", "first_letter", "O", 18), + + ("a2_entertainment_culture_t19", None, "topic_test", "mixed", "opisuje_swoja_rozrywke", 3, + "Wybierz poprawne tłumaczenie: «Я люблю комедийные фильмы, хожу в кино раз в месяц, и вчера посмотрел очень смешной фильм».", "Выберите правильный перевод: «Я люблю комедийные фильмы, хожу в кино раз в месяц, и вчера посмотрел очень смешной фильм».", "Виберіть правильний переклад: «Я люблю комедійні фільми, ходжу до кіно раз на місяць, і вчора подивився дуже смішний фільм».", "Choose the correct translation: “I like comedy films, I go to the cinema once a month, and yesterday I watched a very funny film.”", + "C", None, None, 19), + ("a2_entertainment_culture_t20", None, "topic_test", "mixed", "woleć_biernik", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Что предпочитаешь: читать или смотреть телевизор? — Предпочитаю читать, потому что люблю книги.»", "Выберите правильный перевод диалога: «— Что предпочитаешь: читать или смотреть телевизор? — Предпочитаю читать, потому что люблю книги.»", "Виберіть правильний переклад діалогу: «— Що віддаєш перевагу: читати чи дивитися телевізор? — Віддаю перевагу читанню, бо люблю книги.»", "Choose the correct translation of the dialogue: “— What do you prefer: reading or watching TV? — I prefer reading, because I like books.”", + "A", None, None, 20), + ] + + for q in test_questions_t10_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_entertainment_culture', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t10_a2 = [ + ("a2_entertainment_culture_t01", "A", "kino", "кино", "кіно", "cinema", False, "wrong_word"), + ("a2_entertainment_culture_t01", "B", "teatr", "театр", "театр", "theater", False, "wrong_word"), + ("a2_entertainment_culture_t01", "C", "koncert", "концерт", "концерт", "concert", False, "wrong_word"), + ("a2_entertainment_culture_t01", "D", "muzeum", "музей", "музей", "museum", True, None), + + ("a2_entertainment_culture_t02", "A", "kina", "кино (род.)", "кіно (род.)", "cinema (gen.)", True, None), + ("a2_entertainment_culture_t02", "B", "kino", "кино (им./вин.)", "кіно (наз./знах.)", "cinema (nom./acc.)", False, "wrong_case"), + ("a2_entertainment_culture_t02", "C", "kinie", "кино (местн.)", "кіно (місц.)", "cinema (loc.)", False, "wrong_case"), + ("a2_entertainment_culture_t02", "D", "kinu", "кино (дат.)", "кіно (дав.)", "cinema (dat.)", False, "wrong_case"), + + ("a2_entertainment_culture_t03", "A", "film", "фильм", "фільм", "film", False, "wrong_word"), + ("a2_entertainment_culture_t03", "B", "książka", "книга", "книга", "book", False, "wrong_word"), + ("a2_entertainment_culture_t03", "C", "muzyka", "музыка", "музика", "music", False, "wrong_word"), + ("a2_entertainment_culture_t03", "D", "sztuka", "искусство", "мистецтво", "art", True, None), + + ("a2_entertainment_culture_t04", "A", "muzykę", "музыку (вин.)", "музику (знах.)", "music (acc.)", True, None), + ("a2_entertainment_culture_t04", "B", "muzyka", "музыка (им.)", "музика (наз.)", "music (nom.)", False, "wrong_case"), + ("a2_entertainment_culture_t04", "C", "muzyki", "музыки (род.)", "музики (род.)", "music (gen.)", False, "wrong_case"), + ("a2_entertainment_culture_t04", "D", "muzyce", "музыке (местн./дат.)", "музиці (місц./дав.)", "music (loc./dat.)", False, "wrong_case"), + + ("a2_entertainment_culture_t05", "A", "serial", "сериал (вин.)", "серіал (знах.)", "series (acc.)", True, None), + ("a2_entertainment_culture_t05", "B", "serialu", "сериала (род.)", "серіалу (род.)", "series (gen.)", False, "wrong_case"), + ("a2_entertainment_culture_t05", "C", "serialem", "сериалом (тв.)", "серіалом (ор.)", "series (instr.)", False, "wrong_case"), + ("a2_entertainment_culture_t05", "D", "serialowi", "сериалу (дат.)", "серіалу (дав.)", "series (dat.)", False, "wrong_case"), + + ("a2_entertainment_culture_t06", "A", "Czytasz tę książkę?", "Ты читаешь эту книгу?", "Ти читаєш цю книгу?", "Are you reading that book?", False, "wrong_translation"), + ("a2_entertainment_culture_t06", "B", "Przeczytasz tę książkę?", "Ты прочитаешь эту книгу?", "Ти прочитаєш цю книгу?", "Will you read that book?", False, "wrong_translation"), + ("a2_entertainment_culture_t06", "C", "Napisałaś tę książkę?", "Ты написала эту книгу?", "Ти написала цю книгу?", "Did you write that book?", False, "wrong_translation"), + ("a2_entertainment_culture_t06", "D", "Przeczytałaś tę książkę?", "Ты прочитала эту книгу?", "Ти прочитала цю книгу?", "Did you read that book?", True, None), + + ("a2_entertainment_culture_t07", "A", "Do kina.", "В кино.", "До кіно.", "To the cinema.", False, "wrong_context"), + ("a2_entertainment_culture_t07", "B", "Do teatru.", "В театр.", "До театру.", "To the theater.", True, None), + ("a2_entertainment_culture_t07", "C", "Do muzeum.", "В музей.", "До музею.", "To the museum.", False, "wrong_context"), + ("a2_entertainment_culture_t07", "D", "Na koncert.", "На концерт.", "На концерт.", "To a concert.", False, "wrong_context"), + + ("a2_entertainment_culture_t08", "A", "Idę do teatru.", "Я иду в театр. (не соответствует ситуации)", "Я йду до театру. (не відповідає ситуації)", "I'm going to the theater. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_t08", "B", "Idę do muzeum.", "Я иду в музей. (не соответствует ситуации)", "Я йду до музею. (не відповідає ситуації)", "I'm going to the museum. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_t08", "C", "Idę do kina.", "Я иду в кино.", "Я йду до кіно.", "I'm going to the cinema.", True, None), + ("a2_entertainment_culture_t08", "D", "Idę do domu.", "Я иду домой. (не соответствует ситуации)", "Я йду додому. (не відповідає ситуації)", "I'm going home. (doesn't match the situation)", False, "wrong_context"), + + ("a2_entertainment_culture_t09", "A", "Film.", "Фильм.", "Фільм.", "Film.", False, "wrong_context"), + ("a2_entertainment_culture_t09", "B", "Książkę.", "Книгу.", "Книгу.", "A book.", False, "wrong_context"), + ("a2_entertainment_culture_t09", "C", "Muzykę.", "Музыку.", "Музику.", "Music.", False, "wrong_context"), + ("a2_entertainment_culture_t09", "D", "Sztukę.", "Искусство.", "Мистецтво.", "Art.", True, None), + + ("a2_entertainment_culture_t10", "A", "Chodzę do muzeum w weekendy.", "Я хожу в музей по выходным.", "Я ходжу до музею у вихідні.", "I go to the museum on weekends.", True, None), + ("a2_entertainment_culture_t10", "B", "Chodzę do kina raz w miesiącu.", "Я хожу в кино раз в месяц. (не соответствует ситуации)", "Я ходжу до кіно раз на місяць. (не відповідає ситуації)", "I go to the cinema once a month. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_t10", "C", "Chodzę do teatru często.", "Я часто хожу в театр. (не соответствует ситуации)", "Я часто ходжу до театру. (не відповідає ситуації)", "I often go to the theater. (doesn't match the situation)", False, "wrong_context"), + ("a2_entertainment_culture_t10", "D", "Oglądam telewizję w weekendy.", "Я смотрю телевизор по выходным. (неверный глагол)", "Я дивлюся телевізор у вихідні. (невірне дієслово)", "I watch TV on weekends. (wrong verb)", False, "wrong_word"), + + ("a2_entertainment_culture_t11", "A", "Zabawny.", "Смешной.", "Смішний.", "Funny.", False, "wrong_context"), + ("a2_entertainment_culture_t11", "B", "Smutny.", "Грустный.", "Сумний.", "Sad.", False, "wrong_context"), + ("a2_entertainment_culture_t11", "C", "Wzruszający.", "Трогательный.", "Зворушливий.", "Moving.", False, "wrong_context"), + ("a2_entertainment_culture_t11", "D", "Nudny.", "Скучный.", "Нудний.", "Boring.", True, None), + + ("a2_entertainment_culture_t12", "A", "Oglądam ciekawy film.", "Я смотрю интересный фильм. (настоящее время)", "Я дивлюся цікавий фільм. (теперішній час)", "I'm watching an interesting film. (present tense)", False, "wrong_sentence_type"), + ("a2_entertainment_culture_t12", "B", "Obejrzałem ciekawy film.", "Я посмотрел интересный фильм.", "Я подивився цікавий фільм.", "I watched an interesting film.", True, None), + ("a2_entertainment_culture_t12", "C", "Obejrzę ciekawy film.", "Я посмотрю интересный фильм. (будущее время)", "Я подивлюся цікавий фільм. (майбутній час)", "I will watch an interesting film. (future tense)", False, "wrong_sentence_type"), + ("a2_entertainment_culture_t12", "D", "Obejrzałam ciekawy film.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + ("a2_entertainment_culture_t19", "A", "Lubiłem filmy komediowe, chodziłem do kina raz w miesiącu, i wczoraj obejrzałem bardzo zabawny film.", "Я любил комедийные фильмы, ходил в кино раз в месяц, и вчера посмотрел очень смешной фильм. (прошедшее время)", "Я любив комедійні фільми, ходив до кіно раз на місяць, і вчора подивився дуже смішний фільм. (минулий час)", "I used to like comedy films, used to go to the cinema once a month, and yesterday I watched a very funny film. (past tense)", False, "wrong_sentence_type"), + ("a2_entertainment_culture_t19", "B", "Będę lubić filmy komediowe, będę chodzić do kina raz w miesiącu, i jutro obejrzę bardzo zabawny film.", "Я буду любить комедийные фильмы, буду ходить в кино раз в месяц, и завтра посмотрю очень смешной фильм. (будущее время)", "Я любитиму комедійні фільми, буду ходити до кіно раз на місяць, і завтра подивлюся дуже смішний фільм. (майбутній час)", "I will like comedy films, will go to the cinema once a month, and tomorrow I will watch a very funny film. (future tense)", False, "wrong_sentence_type"), + ("a2_entertainment_culture_t19", "C", "Lubię filmy komediowe, chodzę do kina raz w miesiącu, i wczoraj obejrzałem bardzo zabawny film.", "Я люблю комедийные фильмы, хожу в кино раз в месяц, и вчера посмотрел очень смешной фильм.", "Я люблю комедійні фільми, ходжу до кіно раз на місяць, і вчора подивився дуже смішний фільм.", "I like comedy films, I go to the cinema once a month, and yesterday I watched a very funny film.", True, None), + ("a2_entertainment_culture_t19", "D", "Lubię książki historyczne, chodzę do kina raz w miesiącu, i wczoraj obejrzałem bardzo zabawny film.", "Я люблю исторические книги, хожу в кино раз в месяц, и вчера посмотрел очень смешной фильм. (неверное слово)", "Я люблю історичні книги, ходжу до кіно раз на місяць, і вчора подивився дуже смішний фільм. (невірне слово)", "I like historical books, I go to the cinema once a month, and yesterday I watched a very funny film. (wrong word)", False, "wrong_word"), + + ("a2_entertainment_culture_t20", "A", "— Co wolisz: czytać czy oglądać telewizję? — Wolę czytać, bo lubię książki.", "— Что предпочитаешь: читать или смотреть телевизор? — Предпочитаю читать, потому что люблю книги.", "— Що віддаєш перевагу: читати чи дивитися телевізор? — Віддаю перевагу читанню, бо люблю книги.", "— What do you prefer: reading or watching TV? — I prefer reading, because I like books.", True, None), + ("a2_entertainment_culture_t20", "B", "— Co wolałeś: czytać czy oglądać telewizję? — Wolałem czytać, bo lubiłem książki.", "— Что ты предпочитал: читать или смотреть телевизор? — Я предпочитал читать, потому что любил книги. (прошедшее время)", "— Що ти віддавав перевагу: читати чи дивитися телевізор? — Я віддавав перевагу читанню, бо любив книги. (минулий час)", "— What did you prefer: reading or watching TV? — I preferred reading, because I liked books. (past tense)", False, "wrong_sentence_type"), + ("a2_entertainment_culture_t20", "C", "— Co wolisz: czytać czy oglądać telewizję? — Wolę oglądać telewizję, bo lubię filmy.", "— Что предпочитаешь: читать или смотреть телевизор? — Предпочитаю смотреть телевизор, потому что люблю фильмы. (противоположное предпочтение)", "— Що віддаєш перевагу: читати чи дивитися телевізор? — Віддаю перевагу перегляду телевізора, бо люблю фільми. (протилежна перевага)", "— What do you prefer: reading or watching TV? — I prefer watching TV, because I like films. (opposite preference)", False, "wrong_context"), + ("a2_entertainment_culture_t20", "D", "— Co wolisz: pisać czy oglądać telewizję? — Wolę czytać, bo lubię książki.", "— Что предпочитаешь: писать или смотреть телевизор? — Предпочитаю читать, потому что люблю книги. (несоответствие вопроса и ответа)", "— Що віддаєш перевагу: писати чи дивитися телевізор? — Віддаю перевагу читанню, бо люблю книги. (невідповідність питання і відповіді)", "— What do you prefer: writing or watching TV? — I prefer reading, because I like books. (mismatched question and answer)", False, "wrong_word"), + ] + + for opt in test_options_t10_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 11 (A2): TECHNOLOGIE I INTERNET ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_technology_internet', 'A2', 11, + 'Technologie i internet', + 'Технологии и интернет', + 'Технології та інтернет', + 'Technology and Internet') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t11_a2 = [ + ("a2_technology_internet_l01", 1, "technology_vocabulary", "Podstawowe słowa: technologia", "Основные слова: технологии", "Основні слова: технології", "Basic words: technology", + "Podstawowe słowa: komputer, telefon, internet, aplikacja.", + "Основные слова: komputer (компьютер), telefon (телефон), internet (интернет), aplikacja (приложение).", + "Основні слова: komputer (комп'ютер), telefon (телефон), internet (інтернет), aplikacja (додаток).", + "Basic words: komputer (computer), telefon (phone), internet (internet), aplikacja (app)."), + + ("a2_technology_internet_l02", 2, "korzystac_z_dopelniacza", "Korzystać z + dopełniacz", "Korzystać z + родительный падеж", "Korzystać z + родовий відмінок", "Korzystać z + genitive", + "Czasownik „korzystać” + „z” + dopełniacz rzeczownika: korzystam z komputera, korzystasz z telefonu, korzysta z internetu.", + "Глагол „korzystać” (пользоваться) + „z” + родительный падеж существительного: korzystam z komputera (я пользуюсь компьютером), korzystasz z telefonu (ты пользуешься телефоном), korzysta z internetu (он/она пользуется интернетом).", + "Дієслово „korzystać” (користуватися) + „z” + родовий відмінок іменника: korzystam z komputera (я користуюся комп'ютером), korzystasz z telefonu (ти користуєшся телефоном), korzysta z internetu (він/вона користується інтернетом).", + "The verb „korzystać” (to use) + „z” + genitive of the noun: korzystam z komputera (I use a computer), korzystasz z telefonu (you use a phone), korzysta z internetu (he/she uses the internet)."), + + ("a2_technology_internet_l03", 3, "internet_vocabulary", "Podstawowe słowa: internet", "Основные слова: интернет", "Основні слова: інтернет", "Basic words: internet", + "Podstawowe słowa: strona internetowa, e-mail, hasło, wiadomość.", + "Основные слова: strona internetowa (веб-сайт), e-mail (электронная почта), hasło (пароль), wiadomość (сообщение).", + "Основні слова: strona internetowa (веб-сайт), e-mail (електронна пошта), hasło (пароль), wiadomość (повідомлення).", + "Basic words: strona internetowa (website), e-mail (email), hasło (password), wiadomość (message)."), + + ("a2_technology_internet_l04", 4, "wysylac_biernik", "Wysyłać + biernik", "Wysyłać + винительный падеж", "Wysyłać + знахідний відмінок", "Wysyłać + accusative", + "Czasownik „wysyłać” + biernik: wysyłam e-mail, wysyłasz wiadomość, wysyła zdjęcie.", + "Глагол „wysyłać” (отправлять) + винительный падеж: wysyłam e-mail (я отправляю письмо), wysyłasz wiadomość (ты отправляешь сообщение), wysyła zdjęcie (он/она отправляет фото).", + "Дієслово „wysyłać” (надсилати) + знахідний відмінок: wysyłam e-mail (я надсилаю листа), wysyłasz wiadomość (ти надсилаєш повідомлення), wysyła zdjęcie (він/вона надсилає фото).", + "The verb „wysyłać” (to send) + accusative: wysyłam e-mail (I send an email), wysyłasz wiadomość (you send a message), wysyła zdjęcie (he/she sends a photo)."), + + ("a2_technology_internet_l05", 5, "pobierac_biernik", "Pobierać + biernik", "Pobierać + винительный падеж", "Pobierać + знахідний відмінок", "Pobierać + accusative", + "Czasownik „pobierać” + biernik: pobieram aplikację, pobierasz plik, pobiera program.", + "Глагол „pobierać” (скачивать) + винительный падеж: pobieram aplikację (я скачиваю приложение), pobierasz plik (ты скачиваешь файл), pobiera program (он/она скачивает программу).", + "Дієслово „pobierać” (завантажувати) + знахідний відмінок: pobieram aplikację (я завантажую додаток), pobierasz plik (ти завантажуєш файл), pobiera program (він/вона завантажує програму).", + "The verb „pobierać” (to download) + accusative: pobieram aplikację (I download an app), pobierasz plik (you download a file), pobiera program (he/she downloads a program)."), + + ("a2_technology_internet_l06", 6, "logowac_sie_do", "Logować się do + dopełniacz", "Logować się do + родительный падеж", "Logować się do + родовий відмінок", "Logować się do + genitive", + "Czasownik „logować się” + „do” + dopełniacz: loguję się do konta, logujesz się do aplikacji, loguje się do poczty.", + "Глагол „logować się” (входить в систему) + „do” + родительный падеж: loguję się do konta (я вхожу в аккаунт), logujesz się do aplikacji (ты входишь в приложение), loguje się do poczty (он/она входит в почту).", + "Дієслово „logować się” (входити в систему) + „do” + родовий відмінок: loguję się do konta (я входжу в акаунт), logujesz się do aplikacji (ти входиш у додаток), loguje się do poczty (він/вона входить у пошту).", + "The verb „logować się” (to log in) + „do” + genitive: loguję się do konta (I log in to the account), logujesz się do aplikacji (you log in to the app), loguje się do poczty (he/she logs in to the mail)."), + + ("a2_technology_internet_l07", 7, "przymiotniki_technologia_vocabulary", "Podstawowe słowa: przymiotniki o technologii", "Основные слова: прилагательные о технологиях", "Основні слова: прикметники про технології", "Basic words: technology adjectives", + "Podstawowe przymiotniki opisujące technologię: nowoczesny, szybki, wolny, zepsuty.", + "Основные прилагательные, описывающие технологии: nowoczesny (современный), szybki (быстрый), wolny (медленный), zepsuty (сломанный).", + "Основні прикметники, що описують технології: nowoczesny (сучасний), szybki (швидкий), wolny (повільний), zepsuty (зламаний).", + "Basic adjectives describing technology: nowoczesny (modern), szybki (fast), wolny (slow), zepsuty (broken)."), + + ("a2_technology_internet_l08", 8, "umiec_korzystac", "Umieć + bezokolicznik", "Umieć + инфинитив", "Umieć + інфінітив", "Umieć + infinitive", + "Czasownik „umieć” + bezokolicznik wyraża umiejętność techniczną: umiem korzystać z komputera, umiesz zainstalować aplikację, umie naprawić telefon.", + "Глагол „umieć” (уметь) + инфинитив выражает техническое умение: umiem korzystać z komputera (я умею пользоваться компьютером), umiesz zainstalować aplikację (ты умеешь установить приложение), umie naprawić telefon (он/она умеет починить телефон).", + "Дієслово „umieć” (уміти) + інфінітив виражає технічну навичку: umiem korzystać z komputera (я вмію користуватися комп'ютером), umiesz zainstalować aplikację (ти вмієш встановити додаток), umie naprawić telefon (він/вона вміє полагодити телефон).", + "The verb „umieć” (to know how to) + infinitive expresses a technical skill: umiem korzystać z komputera (I know how to use a computer), umiesz zainstalować aplikację (you know how to install an app), umie naprawić telefon (he/she knows how to fix a phone)."), + + ("a2_technology_internet_l09", 9, "przeszly_czas_technologia", "Kupiłem/kupiłam, zainstalowałem/zainstalowałam (przeszłość)", "Kupiłem/kupiłam, zainstalowałem/zainstalowałam (прошедшее)", "Kupiłem/kupiłam, zainstalowałem/zainstalowałam (минулий час)", "Kupiłem/kupiłam, zainstalowałem/zainstalowałam (past)", + "Czas przeszły technologii tworzymy „kupiłem/kupiłam” lub „zainstalowałem/zainstalowałam” zależnie od rodzaju mówiącego: kupiłem nowy telefon, zainstalowałaś tę aplikację, pobrał plik wczoraj.", + "Прошедшее время технологии образуем „kupiłem/kupiłam” или „zainstalowałem/zainstalowałam” в зависимости от рода говорящего: kupiłem nowy telefon (я купил новый телефон), zainstalowałaś tę aplikację (ты установила это приложение), pobrał plik wczoraj (он скачал файл вчера).", + "Минулий час технології утворюємо „kupiłem/kupiłam” або „zainstalowałem/zainstalowałam” залежно від роду мовця: kupiłem nowy telefon (я купив новий телефон), zainstalowałaś tę aplikację (ти встановила цей додаток), pobrał plik wczoraj (він завантажив файл учора).", + "We form the past tense of technology with „kupiłem/kupiłam” or „zainstalowałem/zainstalowałam” depending on the speaker's gender: kupiłem nowy telefon (I bought a new phone), zainstalowałaś tę aplikację (you installed that app), pobrał plik wczoraj (he downloaded the file yesterday)."), + + ("a2_technology_internet_l10", 10, "opisuje_swoja_technologie", "Opisuję swoją technologię", "Описываю свою технологию", "Описую свою технологію", "Describing my technology", + "Żeby opisać technologię, łączymy zdania: Korzystam z komputera codziennie. Wysyłam e-maile do pracy. Wczoraj zainstalowałem nową aplikację.", + "Чтобы описать технологию, соединяем предложения: Korzystam z komputera codziennie. Wysyłam e-maile do pracy. Wczoraj zainstalowałem nową aplikację. (Я пользуюсь компьютером каждый день. Я отправляю письма по работе. Вчера я установил новое приложение.)", + "Щоб описати технологію, поєднуємо речення: Korzystam z komputera codziennie. Wysyłam e-maile do pracy. Wczoraj zainstalowałem nową aplikację. (Я користуюся комп'ютером щодня. Я надсилаю листи по роботі. Учора я встановив новий додаток.)", + "To describe technology, we combine sentences: Korzystam z komputera codziennie. Wysyłam e-maile do pracy. Wczoraj zainstalowałem nową aplikację. (I use a computer every day. I send emails for work. Yesterday I installed a new app.)"), + ] + + for lesson in lessons_t11_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_technology_internet', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t11_a2 = [ + ("a2_technology_internet_l01", 1, "Mam nowy telefon.", "У меня новый телефон.", "У мене новий телефон.", "I have a new phone."), + ("a2_technology_internet_l01", 2, "Korzystam z komputera w pracy.", "Я пользуюсь компьютером на работе.", "Я користуюся комп'ютером на роботі.", "I use a computer at work."), + ("a2_technology_internet_l01", 3, "Ta aplikacja jest bardzo przydatna.", "Это приложение очень полезное.", "Цей додаток дуже корисний.", "This app is very useful."), + + ("a2_technology_internet_l02", 1, "Korzystam z komputera codziennie.", "Я пользуюсь компьютером каждый день.", "Я користуюся комп'ютером щодня.", "I use a computer every day."), + ("a2_technology_internet_l02", 2, "Korzystasz z telefonu w pracy?", "Ты пользуешься телефоном на работе?", "Ти користуєшся телефоном на роботі?", "Do you use your phone at work?"), + ("a2_technology_internet_l02", 3, "Ona korzysta z internetu do nauki.", "Она пользуется интернетом для учёбы.", "Вона користується інтернетом для навчання.", "She uses the internet for studying."), + + ("a2_technology_internet_l03", 1, "Ta strona internetowa jest ciekawa.", "Этот веб-сайт интересный.", "Цей веб-сайт цікавий.", "This website is interesting."), + ("a2_technology_internet_l03", 2, "Wysłałem ci e-mail.", "Я отправил тебе письмо.", "Я надіслав тобі листа.", "I sent you an email."), + ("a2_technology_internet_l03", 3, "Zapomniałem hasła.", "Я забыл пароль.", "Я забув пароль.", "I forgot my password."), + + ("a2_technology_internet_l04", 1, "Wysyłam e-mail do szefa.", "Я отправляю письмо начальнику.", "Я надсилаю листа начальнику.", "I'm sending an email to my boss."), + ("a2_technology_internet_l04", 2, "Wysyłasz wiadomość do kolegi?", "Ты отправляешь сообщение другу?", "Ти надсилаєш повідомлення другові?", "Are you sending a message to a friend?"), + ("a2_technology_internet_l04", 3, "Ona wysyła zdjęcie mamie.", "Она отправляет фото маме.", "Вона надсилає фото мамі.", "She's sending a photo to her mom."), + + ("a2_technology_internet_l05", 1, "Pobieram nową aplikację.", "Я скачиваю новое приложение.", "Я завантажую новий додаток.", "I'm downloading a new app."), + ("a2_technology_internet_l05", 2, "Pobierasz ten plik?", "Ты скачиваешь этот файл?", "Ти завантажуєш цей файл?", "Are you downloading this file?"), + ("a2_technology_internet_l05", 3, "On pobiera program na komputer.", "Он скачивает программу на компьютер.", "Він завантажує програму на комп'ютер.", "He's downloading a program to his computer."), + + ("a2_technology_internet_l06", 1, "Loguję się do konta rano.", "Я вхожу в аккаунт утром.", "Я входжу в акаунт вранці.", "I log in to my account in the morning."), + ("a2_technology_internet_l06", 2, "Logujesz się do aplikacji przez telefon?", "Ты входишь в приложение через телефон?", "Ти входиш у додаток через телефон?", "Do you log in to the app via phone?"), + ("a2_technology_internet_l06", 3, "Ona loguje się do poczty codziennie.", "Она входит в почту каждый день.", "Вона входить у пошту щодня.", "She logs in to her email every day."), + + ("a2_technology_internet_l07", 1, "Mam nowoczesny telefon.", "У меня современный телефон.", "У мене сучасний телефон.", "I have a modern phone."), + ("a2_technology_internet_l07", 2, "Internet jest dzisiaj szybki.", "Интернет сегодня быстрый.", "Інтернет сьогодні швидкий.", "The internet is fast today."), + ("a2_technology_internet_l07", 3, "Mój laptop jest zepsuty.", "Мой ноутбук сломан.", "Мій ноутбук зламаний.", "My laptop is broken."), + + ("a2_technology_internet_l08", 1, "Umiem korzystać z komputera.", "Я умею пользоваться компьютером.", "Я вмію користуватися комп'ютером.", "I know how to use a computer."), + ("a2_technology_internet_l08", 2, "Umiesz zainstalować tę aplikację?", "Ты умеешь установить это приложение?", "Ти вмієш встановити цей додаток?", "Do you know how to install this app?"), + ("a2_technology_internet_l08", 3, "On umie naprawić telefon.", "Он умеет починить телефон.", "Він вміє полагодити телефон.", "He knows how to fix a phone."), + + ("a2_technology_internet_l09", 1, "Kupiłem nowy telefon wczoraj.", "Я купил новый телефон вчера.", "Я купив новий телефон учора.", "I bought a new phone yesterday."), + ("a2_technology_internet_l09", 2, "Zainstalowałaś tę aplikację?", "Ты установила это приложение?", "Ти встановила цей додаток?", "Did you install this app?"), + ("a2_technology_internet_l09", 3, "Ona pobrała plik w zeszłym tygodniu.", "Она скачала файл на прошлой неделе.", "Вона завантажила файл минулого тижня.", "She downloaded the file last week."), + + ("a2_technology_internet_l10", 1, "Korzystam z komputera codziennie.", "Я пользуюсь компьютером каждый день.", "Я користуюся комп'ютером щодня.", "I use a computer every day."), + ("a2_technology_internet_l10", 2, "Wysyłam e-maile do pracy.", "Я отправляю письма по работе.", "Я надсилаю листи по роботі.", "I send emails for work."), + ("a2_technology_internet_l10", 3, "Wczoraj zainstalowałem nową aplikację.", "Вчера я установил новое приложение.", "Учора я встановив новий додаток.", "Yesterday I installed a new app."), + ] + + for ex in examples_t11_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t11_a2 = [ + # L01 — technology_vocabulary (difficulty 1) + ("a2_technology_internet_l01_q1", "a2_technology_internet_l01", "lesson_practice", "recognition", "technology_vocabulary", 1, + "Jak po polsku „приложение”?", "Как по-польски «приложение»?", "Як польською «додаток»?", "How do you say “app” in Polish?", + "D", None, None), + ("a2_technology_internet_l01_q2", "a2_technology_internet_l01", "lesson_practice", "production", "technology_vocabulary", 1, + "Wpisz brakujące słowo: Mam nowy ___. (телефон)", "Вставьте пропущенное слово: Mam nowy ___. (телефон)", "Вставте пропущене слово: Mam nowy ___. (телефон)", "Fill in the missing word: Mam nowy ___. (phone)", + "telefon", "first_letter", "t"), + ("a2_technology_internet_l01_q3", "a2_technology_internet_l01", "lesson_practice", "application", "technology_vocabulary", 1, + "Chcesz zadzwonić do przyjaciela. Czego używasz?", "Ты хочешь позвонить другу. Что ты используешь?", "Ти хочеш подзвонити другу. Що ти використовуєш?", "You want to call a friend. What do you use?", + "B", None, None), + + # L02 — korzystac_z_dopelniacza (difficulty 1) + ("a2_technology_internet_l02_q1", "a2_technology_internet_l02", "lesson_practice", "recognition", "korzystac_z_dopelniacza", 1, + "Wybierz poprawną formę: Korzystam z ___. (komputer)", "Выберите правильную форму: Korzystam z ___. (komputer)", "Виберіть правильну форму: Korzystam z ___. (komputer)", "Choose the correct form: Korzystam z ___. (komputer)", + "A", None, None), + ("a2_technology_internet_l02_q2", "a2_technology_internet_l02", "lesson_practice", "production", "korzystac_z_dopelniacza", 1, + "Wpisz brakujące słowo: Korzystasz z ___? (телефона)", "Вставьте пропущенное слово: Korzystasz z ___? (телефона)", "Вставте пропущене слово: Korzystasz z ___? (телефону)", "Fill in the missing word: Korzystasz z ___? (phone)", + "telefonu", "first_letter", "t"), + ("a2_technology_internet_l02_q3", "a2_technology_internet_l02", "lesson_practice", "application", "korzystac_z_dopelniacza", 1, + "Kolega pyta, z czego korzystasz do nauki polskiego. Korzystasz z aplikacji. Co powiesz?", "Друг спрашивает, чем ты пользуешься для изучения польского. Ты пользуешься приложением. Что ты скажешь?", "Друг питає, чим ти користуєшся для вивчення польської. Ти користуєшся додатком. Що ти скажеш?", "A friend asks what you use to study Polish. You use an app. What do you say?", + "C", None, None), + + # L03 — internet_vocabulary (difficulty 1) + ("a2_technology_internet_l03_q1", "a2_technology_internet_l03", "lesson_practice", "recognition", "internet_vocabulary", 1, + "Jak po polsku „пароль”?", "Как по-польски «пароль»?", "Як польською «пароль»?", "How do you say “password” in Polish?", + "C", None, None), + ("a2_technology_internet_l03_q2", "a2_technology_internet_l03", "lesson_practice", "production", "internet_vocabulary", 1, + "Wpisz brakujące słowo: Wysłałem ci ___. (письмо)", "Вставьте пропущенное слово: Wysłałem ci ___. (письмо)", "Вставте пропущене слово: Wysłałem ci ___. (листа)", "Fill in the missing word: Wysłałem ci ___. (email)", + "e-mail", "first_letter", "e"), + ("a2_technology_internet_l03_q3", "a2_technology_internet_l03", "lesson_practice", "application", "internet_vocabulary", 1, + "Nie pamiętasz, jak wejść na swoje konto, bo zapomniałeś ważnego ciągu znaków. Czego zapomniałeś?", "Ты не помнишь, как войти в свой аккаунт, потому что забыл важную последовательность символов. Что ты забыл?", "Ти не пам'ятаєш, як увійти в свій акаунт, бо забув важливу послідовність символів. Що ти забув?", "You can't remember how to log in to your account because you forgot an important sequence of characters. What did you forget?", + "C", None, None), + + # L04 — wysylac_biernik (difficulty 1) + ("a2_technology_internet_l04_q1", "a2_technology_internet_l04", "lesson_practice", "recognition", "wysylac_biernik", 1, + "Wybierz poprawną formę: ___ e-mail do szefa. (wysyłać, ja)", "Выберите правильную форму: ___ e-mail do szefa. (wysyłać, ja)", "Виберіть правильну форму: ___ e-mail do szefa. (wysyłać, ja)", "Choose the correct form: ___ e-mail do szefa. (wysyłać, I)", + "A", None, None), + ("a2_technology_internet_l04_q2", "a2_technology_internet_l04", "lesson_practice", "production", "wysylac_biernik", 1, + "Wpisz brakujące słowo: ___ wiadomość do kolegi? (ты отправляешь)", "Вставьте пропущенное слово: ___ wiadomość do kolegi? (ты отправляешь)", "Вставте пропущене слово: ___ wiadomość do kolegi? (ти надсилаєш)", "Fill in the missing word: ___ wiadomość do kolegi? (do you send)", + "Wysyłasz", "first_letter", "W"), + ("a2_technology_internet_l04_q3", "a2_technology_internet_l04", "lesson_practice", "application", "wysylac_biernik", 1, + "Chcesz przesłać zdjęcie mamie przez telefon. Co powiesz?", "Ты хочешь отправить фото маме через телефон. Что ты скажешь?", "Ти хочеш надіслати фото мамі через телефон. Що ти скажеш?", "You want to send a photo to your mom via phone. What do you say?", + "A", None, None), + + # L05 — pobierac_biernik (difficulty 2) + ("a2_technology_internet_l05_q1", "a2_technology_internet_l05", "lesson_practice", "recognition", "pobierac_biernik", 2, + "Wybierz poprawną formę: ___ nową aplikację. (pobierać, ja)", "Выберите правильную форму: ___ nową aplikację. (pobierać, ja)", "Виберіть правильну форму: ___ nową aplikację. (pobierać, ja)", "Choose the correct form: ___ nową aplikację. (pobierać, I)", + "A", None, None), + ("a2_technology_internet_l05_q2", "a2_technology_internet_l05", "lesson_practice", "production", "pobierac_biernik", 2, + "Wpisz brakujące słowo: ___ ten plik? (ты скачиваешь)", "Вставьте пропущенное слово: ___ ten plik? (ты скачиваешь)", "Вставте пропущене слово: ___ ten plik? (ти завантажуєш)", "Fill in the missing word: ___ ten plik? (are you downloading)", + "Pobierasz", "first_letter", "P"), + ("a2_technology_internet_l05_q3", "a2_technology_internet_l05", "lesson_practice", "application", "pobierac_biernik", 2, + "Chcesz opowiedzieć, że właśnie w tej chwili ściągasz nowy program na komputer. Co powiesz?", "Ты хочешь рассказать, что прямо сейчас скачиваешь новую программу на компьютер. Что ты скажешь?", "Ти хочеш розповісти, що прямо зараз завантажуєш нову програму на комп'ютер. Що ти скажеш?", "You want to say that right now you're downloading a new program to your computer. What do you say?", + "A", None, None), + + # L06 — logowac_sie_do (difficulty 2) + ("a2_technology_internet_l06_q1", "a2_technology_internet_l06", "lesson_practice", "recognition", "logowac_sie_do", 2, + "Wybierz poprawną formę: Loguję się ___ konta. (do)", "Выберите правильную форму: Loguję się ___ konta. (do)", "Виберіть правильну форму: Loguję się ___ konta. (do)", "Choose the correct form: Loguję się ___ konta. (do)", + "A", None, None), + ("a2_technology_internet_l06_q2", "a2_technology_internet_l06", "lesson_practice", "production", "logowac_sie_do", 2, + "Wpisz brakujące słowo: Logujesz się do ___? (почты)", "Вставьте пропущенное слово: Logujesz się do ___? (почты)", "Вставте пропущене слово: Logujesz się do ___? (пошти)", "Fill in the missing word: Logujesz się do ___? (email)", + "poczty", "first_letter", "p"), + ("a2_technology_internet_l06_q3", "a2_technology_internet_l06", "lesson_practice", "application", "logowac_sie_do", 2, + "Codziennie rano sprawdzasz swoją pocztę, wchodząc na konto. Co powiesz?", "Ты каждое утро проверяешь свою почту, заходя в аккаунт. Что ты скажешь?", "Ти щоранку перевіряєш свою пошту, заходячи в акаунт. Що ти скажеш?", "Every morning you check your email by logging in to your account. What do you say?", + "A", None, None), + + # L07 — przymiotniki_technologia_vocabulary (difficulty 2) + ("a2_technology_internet_l07_q1", "a2_technology_internet_l07", "lesson_practice", "recognition", "przymiotniki_technologia_vocabulary", 2, + "Jak po polsku „сломанный”?", "Как по-польски «сломанный»?", "Як польською «зламаний»?", "How do you say “broken” in Polish?", + "D", None, None), + ("a2_technology_internet_l07_q2", "a2_technology_internet_l07", "lesson_practice", "production", "przymiotniki_technologia_vocabulary", 2, + "Wpisz brakujące słowo: Internet jest bardzo ___. (медленный)", "Вставьте пропущенное слово: Internet jest bardzo ___. (медленный)", "Вставте пропущене слово: Internet jest bardzo ___. (повільний)", "Fill in the missing word: Internet jest bardzo ___. (slow)", + "wolny", "first_letter", "w"), + ("a2_technology_internet_l07_q3", "a2_technology_internet_l07", "lesson_practice", "application", "przymiotniki_technologia_vocabulary", 2, + "Twój laptop nie działa i nie można go włączyć. Jaki on jest?", "Твой ноутбук не работает и его нельзя включить. Какой он?", "Твій ноутбук не працює і його неможливо ввімкнути. Який він?", "Your laptop doesn't work and can't be turned on. What is it like?", + "D", None, None), + + # L08 — umiec_korzystac (difficulty 2) + ("a2_technology_internet_l08_q1", "a2_technology_internet_l08", "lesson_practice", "recognition", "umiec_korzystac", 2, + "Wybierz poprawną formę: ___ korzystać z komputera. (umieć, ja)", "Выберите правильную форму: ___ korzystać z komputera. (umieć, ja)", "Виберіть правильну форму: ___ korzystać z komputera. (umieć, ja)", "Choose the correct form: ___ korzystać z komputera. (umieć, I)", + "A", None, None), + ("a2_technology_internet_l08_q2", "a2_technology_internet_l08", "lesson_practice", "production", "umiec_korzystac", 2, + "Wpisz brakujące słowo: ___ zainstalować tę aplikację? (ты умеешь)", "Вставьте пропущенное слово: ___ zainstalować tę aplikację? (ты умеешь)", "Вставте пропущене слово: ___ zainstalować tę aplikację? (ти вмієш)", "Fill in the missing word: ___ zainstalować tę aplikację? (do you know how to)", + "Umiesz", "first_letter", "U"), + ("a2_technology_internet_l08_q3", "a2_technology_internet_l08", "lesson_practice", "application", "umiec_korzystac", 2, + "Nauczyłeś się już naprawiać telefony i możesz to robić bez problemu. Co powiesz?", "Ты уже научился чинить телефоны и можешь делать это без проблем. Что ты скажешь?", "Ти вже навчився лагодити телефони і можеш робити це без проблем. Що ти скажеш?", "You've already learned to fix phones and can do it without a problem. What do you say?", + "A", None, None), + + # L09 — przeszly_czas_technologia (difficulty 3) + ("a2_technology_internet_l09_q1", "a2_technology_internet_l09", "lesson_practice", "recognition", "przeszly_czas_technologia", 3, + "Co znaczy „Zainstalowałaś tę aplikację”?", "Что означает «Zainstalowałaś tę aplikację»?", "Що означає «Zainstalowałaś tę aplikację»?", "What does “Zainstalowałaś tę aplikację” mean?", + "D", None, None), + ("a2_technology_internet_l09_q2", "a2_technology_internet_l09", "lesson_practice", "production", "przeszly_czas_technologia", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ nowy telefon wczoraj. (я купила)", "Вставьте пропущенное слово (говорит женщина): ___ nowy telefon wczoraj. (я купила)", "Вставте пропущене слово (говорить жінка): ___ nowy telefon wczoraj. (я купила)", "Fill in the missing word (a woman is speaking): ___ nowy telefon wczoraj. (I bought)", + "Kupiłam", "first_letter", "K"), + ("a2_technology_internet_l09_q3", "a2_technology_internet_l09", "lesson_practice", "application", "przeszly_czas_technologia", 3, + "Mężczyzna opowiada, że wczoraj zainstalował nową aplikację na telefonie. Co powie?", "Мужчина рассказывает, что вчера установил новое приложение на телефон. Что он скажет?", "Чоловік розповідає, що вчора встановив новий додаток на телефон. Що він скаже?", "A man is telling that yesterday he installed a new app on his phone. What does he say?", + "B", None, None), + + # L10 — opisuje_swoja_technologie (difficulty 3) + ("a2_technology_internet_l10_q1", "a2_technology_internet_l10", "lesson_practice", "recognition", "opisuje_swoja_technologie", 3, + "Które zdanie poprawnie opisuje korzystanie z technologii?", "Какое предложение правильно описывает пользование технологиями?", "Яке речення правильно описує користування технологіями?", "Which sentence correctly describes using technology?", + "D", None, None), + ("a2_technology_internet_l10_q2", "a2_technology_internet_l10", "lesson_practice", "production", "opisuje_swoja_technologie", 3, + "Przetłumacz: «Вчера я установил новое приложение».", "Переведите: «Вчера я установил новое приложение».", "Перекладіть: «Учора я встановив новий додаток».", "Translate: “Yesterday I installed a new app.”", + "Wczoraj zainstalowałem nową aplikację", "first_letter", "W"), + ("a2_technology_internet_l10_q3", "a2_technology_internet_l10", "lesson_practice", "application", "opisuje_swoja_technologie", 3, + "Chcesz opisać koledze swoją technologię: korzystasz z komputera codziennie, wysyłasz e-maile, wczoraj zainstalowałeś aplikację. Jak zaczniesz zdanie?", "Ты хочешь описать другу свою технологию: ты пользуешься компьютером каждый день, отправляешь письма, вчера установил приложение. Как ты начнёшь предложение?", "Ти хочеш описати другу свою технологію: ти користуєшся комп'ютером щодня, надсилаєш листи, вчора встановив додаток. Як ти почнеш речення?", "You want to describe your technology use to a friend: you use a computer every day, send emails, yesterday installed an app. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t11_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_technology_internet', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t11_a2 = [ + # L01 + ("a2_technology_internet_l01_q1", "A", "komputer", "компьютер", "комп'ютер", "computer", False, "wrong_word"), + ("a2_technology_internet_l01_q1", "B", "telefon", "телефон", "телефон", "phone", False, "wrong_word"), + ("a2_technology_internet_l01_q1", "C", "internet", "интернет", "інтернет", "internet", False, "wrong_word"), + ("a2_technology_internet_l01_q1", "D", "aplikacja", "приложение", "додаток", "app", True, None), + + ("a2_technology_internet_l01_q3", "A", "Komputera.", "Компьютера.", "Комп'ютера.", "A computer.", False, "wrong_context"), + ("a2_technology_internet_l01_q3", "B", "Telefonu.", "Телефона.", "Телефону.", "A phone.", True, None), + ("a2_technology_internet_l01_q3", "C", "Internetu.", "Интернета.", "Інтернету.", "The internet.", False, "wrong_context"), + ("a2_technology_internet_l01_q3", "D", "Aplikacji.", "Приложения.", "Додатка.", "An app.", False, "wrong_context"), + + # L02 + ("a2_technology_internet_l02_q1", "A", "komputera", "компьютера (род.)", "комп'ютера (род.)", "computer (gen.)", True, None), + ("a2_technology_internet_l02_q1", "B", "komputer", "компьютер (им./вин.)", "комп'ютер (наз./знах.)", "computer (nom./acc.)", False, "wrong_case"), + ("a2_technology_internet_l02_q1", "C", "komputerze", "компьютере (местн.)", "комп'ютері (місц.)", "computer (loc.)", False, "wrong_case"), + ("a2_technology_internet_l02_q1", "D", "komputerowi", "компьютеру (дат.)", "комп'ютеру (дав.)", "computer (dat.)", False, "wrong_case"), + + ("a2_technology_internet_l02_q3", "A", "Korzystam z komputera.", "Я пользуюсь компьютером. (не соответствует ситуации)", "Я користуюся комп'ютером. (не відповідає ситуації)", "I use a computer. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_l02_q3", "B", "Korzystam z telefonu.", "Я пользуюсь телефоном. (не соответствует ситуации)", "Я користуюся телефоном. (не відповідає ситуації)", "I use a phone. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_l02_q3", "C", "Korzystam z aplikacji.", "Я пользуюсь приложением.", "Я користуюся додатком.", "I use an app.", True, None), + ("a2_technology_internet_l02_q3", "D", "Korzystam z internetu.", "Я пользуюсь интернетом. (не соответствует ситуации)", "Я користуюся інтернетом. (не відповідає ситуації)", "I use the internet. (doesn't match the situation)", False, "wrong_context"), + + # L03 + ("a2_technology_internet_l03_q1", "A", "e-mail", "электронная почта", "електронна пошта", "email", False, "wrong_word"), + ("a2_technology_internet_l03_q1", "B", "wiadomość", "сообщение", "повідомлення", "message", False, "wrong_word"), + ("a2_technology_internet_l03_q1", "C", "hasło", "пароль", "пароль", "password", True, None), + ("a2_technology_internet_l03_q1", "D", "strona internetowa", "веб-сайт", "веб-сайт", "website", False, "wrong_word"), + + ("a2_technology_internet_l03_q3", "A", "Strony internetowej.", "Веб-сайта.", "Веб-сайту.", "Of a website.", False, "wrong_context"), + ("a2_technology_internet_l03_q3", "B", "E-maila.", "Письма.", "Листа.", "Of an email.", False, "wrong_context"), + ("a2_technology_internet_l03_q3", "C", "Hasła.", "Пароля.", "Пароля.", "Of a password.", True, None), + ("a2_technology_internet_l03_q3", "D", "Wiadomości.", "Сообщения.", "Повідомлення.", "Of a message.", False, "wrong_context"), + + # L04 + ("a2_technology_internet_l04_q1", "A", "Wysyłam", "я отправляю", "я надсилаю", "I send", True, None), + ("a2_technology_internet_l04_q1", "B", "Wysyłasz", "ты отправляешь (не тот человек)", "ти надсилаєш (не та особа)", "you send (wrong person)", False, "wrong_context"), + ("a2_technology_internet_l04_q1", "C", "Wysyła", "он/она отправляет (не тот человек)", "він/вона надсилає (не та особа)", "he/she sends (wrong person)", False, "wrong_context"), + ("a2_technology_internet_l04_q1", "D", "Wysyłaliśmy", "мы отправляли (неправильное число и время)", "ми надсилали (неправильне число і час)", "we sent (wrong number and tense)", False, "wrong_number"), + + ("a2_technology_internet_l04_q3", "A", "Wysyłam zdjęcie mamie.", "Я отправляю фото маме.", "Я надсилаю фото мамі.", "I'm sending a photo to my mom.", True, None), + ("a2_technology_internet_l04_q3", "B", "Pobieram zdjęcie.", "Я скачиваю фото. (неверный глагол)", "Я завантажую фото. (невірне дієслово)", "I'm downloading a photo. (wrong verb)", False, "wrong_word"), + ("a2_technology_internet_l04_q3", "C", "Loguję się do aplikacji.", "Я вхожу в приложение. (не соответствует ситуации)", "Я входжу в додаток. (не відповідає ситуації)", "I'm logging in to an app. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_l04_q3", "D", "Korzystam z telefonu.", "Я пользуюсь телефоном. (не соответствует ситуации)", "Я користуюся телефоном. (не відповідає ситуації)", "I'm using a phone. (doesn't match the situation)", False, "wrong_context"), + + # L05 + ("a2_technology_internet_l05_q1", "A", "Pobieram", "я скачиваю", "я завантажую", "I download", True, None), + ("a2_technology_internet_l05_q1", "B", "Pobierasz", "ты скачиваешь (не тот человек)", "ти завантажуєш (не та особа)", "you download (wrong person)", False, "wrong_context"), + ("a2_technology_internet_l05_q1", "C", "Pobiera", "он/она скачивает (не тот человек)", "він/вона завантажує (не та особа)", "he/she downloads (wrong person)", False, "wrong_context"), + ("a2_technology_internet_l05_q1", "D", "Pobieraliśmy", "мы скачивали (неправильное число и время)", "ми завантажували (неправильне число і час)", "we downloaded (wrong number and tense)", False, "wrong_number"), + + ("a2_technology_internet_l05_q3", "A", "Pobieram program.", "Я скачиваю программу.", "Я завантажую програму.", "I'm downloading a program.", True, None), + ("a2_technology_internet_l05_q3", "B", "Wysyłam program.", "Я отправляю программу. (неверный глагол)", "Я надсилаю програму. (невірне дієслово)", "I'm sending a program. (wrong verb)", False, "wrong_word"), + ("a2_technology_internet_l05_q3", "C", "Loguję się do programu.", "Я вхожу в программу. (не соответствует ситуации)", "Я входжу в програму. (не відповідає ситуації)", "I'm logging in to a program. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_l05_q3", "D", "Korzystam z programu.", "Я пользуюсь программой. (не соответствует ситуации)", "Я користуюся програмою. (не відповідає ситуації)", "I'm using a program. (doesn't match the situation)", False, "wrong_context"), + + # L06 + ("a2_technology_internet_l06_q1", "A", "do", "в/к", "до", "to", True, None), + ("a2_technology_internet_l06_q1", "B", "na", "на", "на", "to", False, "wrong_word"), + ("a2_technology_internet_l06_q1", "C", "w", "в", "в", "in", False, "wrong_word"), + ("a2_technology_internet_l06_q1", "D", "u", "у", "у", "at", False, "wrong_word"), + + ("a2_technology_internet_l06_q3", "A", "Loguję się do poczty rano.", "Я вхожу в почту утром.", "Я входжу в пошту вранці.", "I log in to my email in the morning.", True, None), + ("a2_technology_internet_l06_q3", "B", "Wysyłam e-mail rano.", "Я отправляю письмо утром. (не соответствует ситуации)", "Я надсилаю листа вранці. (не відповідає ситуації)", "I send an email in the morning. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_l06_q3", "C", "Pobieram aplikację rano.", "Я скачиваю приложение утром. (не соответствует ситуации)", "Я завантажую додаток вранці. (не відповідає ситуації)", "I download an app in the morning. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_l06_q3", "D", "Korzystam z telefonu rano.", "Я пользуюсь телефоном утром. (не соответствует ситуации)", "Я користуюся телефоном вранці. (не відповідає ситуації)", "I use my phone in the morning. (doesn't match the situation)", False, "wrong_context"), + + # L07 + ("a2_technology_internet_l07_q1", "A", "nowoczesny", "современный", "сучасний", "modern", False, "wrong_word"), + ("a2_technology_internet_l07_q1", "B", "szybki", "быстрый", "швидкий", "fast", False, "wrong_word"), + ("a2_technology_internet_l07_q1", "C", "wolny", "медленный", "повільний", "slow", False, "wrong_word"), + ("a2_technology_internet_l07_q1", "D", "zepsuty", "сломанный", "зламаний", "broken", True, None), + + ("a2_technology_internet_l07_q3", "A", "Nowoczesny.", "Современный.", "Сучасний.", "Modern.", False, "wrong_context"), + ("a2_technology_internet_l07_q3", "B", "Szybki.", "Быстрый.", "Швидкий.", "Fast.", False, "wrong_context"), + ("a2_technology_internet_l07_q3", "C", "Wolny.", "Медленный.", "Повільний.", "Slow.", False, "wrong_context"), + ("a2_technology_internet_l07_q3", "D", "Zepsuty.", "Сломанный.", "Зламаний.", "Broken.", True, None), + + # L08 + ("a2_technology_internet_l08_q1", "A", "Umiem", "я умею", "я вмію", "I know how to", True, None), + ("a2_technology_internet_l08_q1", "B", "Umiesz", "ты умеешь (не тот человек)", "ти вмієш (не та особа)", "you know how to (wrong person)", False, "wrong_context"), + ("a2_technology_internet_l08_q1", "C", "Umie", "он/она умеет (не тот человек)", "він/вона вміє (не та особа)", "he/she knows how to (wrong person)", False, "wrong_context"), + ("a2_technology_internet_l08_q1", "D", "Umieli", "они умели (неправильное число и время)", "вони вміли (неправильне число і час)", "they knew how to (wrong number and tense)", False, "wrong_number"), + + ("a2_technology_internet_l08_q3", "A", "Umiem naprawić telefon.", "Я умею починить телефон.", "Я вмію полагодити телефон.", "I know how to fix a phone.", True, None), + ("a2_technology_internet_l08_q3", "B", "Lubię naprawiać telefon.", "Мне нравится чинить телефон. (о симпатии, не о навыке)", "Мені подобається лагодити телефон. (про симпатію, не про навичку)", "I like fixing phones. (about liking it, not the skill)", False, "wrong_context"), + ("a2_technology_internet_l08_q3", "C", "Chcę naprawić telefon.", "Я хочу починить телефон. (о желании, не о навыке)", "Я хочу полагодити телефон. (про бажання, не про навичку)", "I want to fix a phone. (about wanting to, not the skill)", False, "wrong_context"), + ("a2_technology_internet_l08_q3", "D", "Trenuję naprawianie telefonu.", "Я тренирую починку телефона. (о тренировке, не о готовом навыке)", "Я треную ремонт телефона. (про тренування, не про готову навичку)", "I'm training to fix a phone. (about training, not an achieved skill)", False, "wrong_context"), + + # L09 + ("a2_technology_internet_l09_q1", "A", "Instalujesz tę aplikację?", "Ты устанавливаешь это приложение?", "Ти встановлюєш цей додаток?", "Are you installing this app?", False, "wrong_translation"), + ("a2_technology_internet_l09_q1", "B", "Zainstalujesz tę aplikację?", "Ты установишь это приложение?", "Ти встановиш цей додаток?", "Will you install this app?", False, "wrong_translation"), + ("a2_technology_internet_l09_q1", "C", "Odinstalowałaś tę aplikację?", "Ты удалила это приложение?", "Ти видалила цей додаток?", "Did you uninstall this app?", False, "wrong_translation"), + ("a2_technology_internet_l09_q1", "D", "Zainstalowałaś tę aplikację?", "Ты установила это приложение?", "Ти встановила цей додаток?", "Did you install this app?", True, None), + + ("a2_technology_internet_l09_q3", "A", "Instaluję nową aplikację.", "Я устанавливаю новое приложение. (настоящее время)", "Я встановлюю новий додаток. (теперішній час)", "I'm installing a new app. (present tense)", False, "wrong_sentence_type"), + ("a2_technology_internet_l09_q3", "B", "Zainstalowałem nową aplikację wczoraj.", "Я установил новое приложение вчера.", "Я встановив новий додаток учора.", "I installed a new app yesterday.", True, None), + ("a2_technology_internet_l09_q3", "C", "Zainstaluję nową aplikację jutro.", "Я установлю новое приложение завтра. (будущее время)", "Я встановлю новий додаток завтра. (майбутній час)", "I will install a new app tomorrow. (future tense)", False, "wrong_sentence_type"), + ("a2_technology_internet_l09_q3", "D", "Zainstalowałam nową aplikację wczoraj.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + # L10 + ("a2_technology_internet_l10_q1", "A", "Korzystam ja komputera ja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_technology_internet_l10_q1", "B", "Komputera korzystam z.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_technology_internet_l10_q1", "C", "Korzystam z komputera ja.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_technology_internet_l10_q1", "D", "Korzystam z komputera i wysyłam e-maile do pracy.", "Я пользуюсь компьютером и отправляю письма по работе.", "Я користуюся комп'ютером і надсилаю листи по роботі.", "I use a computer and send emails for work.", True, None), + + ("a2_technology_internet_l10_q3", "A", "Wysyłam e-maile do pracy.", "Я отправляю письма по работе. (не начало описания)", "Я надсилаю листи по роботі. (не початок опису)", "I send emails for work. (not the opening line)", False, "wrong_context"), + ("a2_technology_internet_l10_q3", "B", "Zainstalowałem aplikację.", "Я установил приложение. (не начало описания)", "Я встановив додаток. (не початок опису)", "I installed an app. (not the opening line)", False, "wrong_context"), + ("a2_technology_internet_l10_q3", "C", "Korzystam z komputera codziennie.", "Я пользуюсь компьютером каждый день.", "Я користуюся комп'ютером щодня.", "I use a computer every day.", True, None), + ("a2_technology_internet_l10_q3", "D", "Pobrałem plik wczoraj.", "Я скачал файл вчера. (прошедшее время, не соответствует ситуации)", "Я завантажив файл учора. (минулий час, не відповідає ситуації)", "I downloaded a file yesterday. (past tense, doesn't match the situation)", False, "wrong_context"), + ] + + for opt in options_t11_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + test_questions_t11_a2 = [ + ("a2_technology_internet_t01", None, "topic_test", "recognition", "technology_vocabulary", 1, + "Jak po polsku „приложение”?", "Как по-польски «приложение»?", "Як польською «додаток»?", "How do you say “app” in Polish?", + "D", None, None, 1), + ("a2_technology_internet_t02", None, "topic_test", "recognition", "korzystac_z_dopelniacza", 1, + "Wybierz poprawną formę: Korzystam z ___. (komputer)", "Выберите правильную форму: Korzystam z ___. (komputer)", "Виберіть правильну форму: Korzystam z ___. (komputer)", "Choose the correct form: Korzystam z ___. (komputer)", + "A", None, None, 2), + ("a2_technology_internet_t03", None, "topic_test", "recognition", "internet_vocabulary", 1, + "Jak po polsku „пароль”?", "Как по-польски «пароль»?", "Як польською «пароль»?", "How do you say “password” in Polish?", + "C", None, None, 3), + ("a2_technology_internet_t04", None, "topic_test", "recognition", "wysylac_biernik", 1, + "Wybierz poprawną formę: ___ e-mail do szefa. (wysyłać, ja)", "Выберите правильную форму: ___ e-mail do szefa. (wysyłać, ja)", "Виберіть правильну форму: ___ e-mail do szefa. (wysyłać, ja)", "Choose the correct form: ___ e-mail do szefa. (wysyłać, I)", + "A", None, None, 4), + ("a2_technology_internet_t05", None, "topic_test", "recognition", "pobierac_biernik", 2, + "Wybierz poprawną formę: ___ nową aplikację. (pobierać, ja)", "Выберите правильную форму: ___ nową aplikację. (pobierać, ja)", "Виберіть правильну форму: ___ nową aplikację. (pobierać, ja)", "Choose the correct form: ___ nową aplikację. (pobierać, I)", + "A", None, None, 5), + ("a2_technology_internet_t06", None, "topic_test", "recognition", "przeszly_czas_technologia", 3, + "Co znaczy „Zainstalowałaś tę aplikację”?", "Что означает «Zainstalowałaś tę aplikację»?", "Що означає «Zainstalowałaś tę aplikację»?", "What does “Zainstalowałaś tę aplikację” mean?", + "D", None, None, 6), + + ("a2_technology_internet_t07", None, "topic_test", "application", "technology_vocabulary", 1, + "Chcesz zadzwonić do przyjaciela. Czego używasz?", "Ты хочешь позвонить другу. Что ты используешь?", "Ти хочеш подзвонити другу. Що ти використовуєш?", "You want to call a friend. What do you use?", + "B", None, None, 7), + ("a2_technology_internet_t08", None, "topic_test", "application", "korzystac_z_dopelniacza", 1, + "Kolega pyta, z czego korzystasz do nauki polskiego. Korzystasz z aplikacji. Co powiesz?", "Друг спрашивает, чем ты пользуешься для изучения польского. Ты пользуешься приложением. Что ты скажешь?", "Друг питає, чим ти користуєшся для вивчення польської. Ти користуєшся додатком. Що ти скажеш?", "A friend asks what you use to study Polish. You use an app. What do you say?", + "C", None, None, 8), + ("a2_technology_internet_t09", None, "topic_test", "application", "internet_vocabulary", 1, + "Nie pamiętasz, jak wejść na swoje konto, bo zapomniałeś ważnego ciągu znaków. Czego zapomniałeś?", "Ты не помнишь, как войти в свой аккаунт, потому что забыл важную последовательность символов. Что ты забыл?", "Ти не пам'ятаєш, як увійти в свій акаунт, бо забув важливу послідовність символів. Що ти забув?", "You can't remember how to log in to your account because you forgot an important sequence of characters. What did you forget?", + "C", None, None, 9), + ("a2_technology_internet_t10", None, "topic_test", "application", "logowac_sie_do", 2, + "Codziennie rano sprawdzasz swoją pocztę, wchodząc na konto. Co powiesz?", "Ты каждое утро проверяешь свою почту, заходя в аккаунт. Что ты скажешь?", "Ти щоранку перевіряєш свою пошту, заходячи в акаунт. Що ти скажеш?", "Every morning you check your email by logging in to your account. What do you say?", + "A", None, None, 10), + ("a2_technology_internet_t11", None, "topic_test", "application", "przymiotniki_technologia_vocabulary", 2, + "Twój laptop nie działa i nie można go włączyć. Jaki on jest?", "Твой ноутбук не работает и его нельзя включить. Какой он?", "Твій ноутбук не працює і його неможливо ввімкнути. Який він?", "Your laptop doesn't work and can't be turned on. What is it like?", + "D", None, None, 11), + ("a2_technology_internet_t12", None, "topic_test", "application", "przeszly_czas_technologia", 3, + "Mężczyzna opowiada, że wczoraj zainstalował nową aplikację na telefonie. Co powie?", "Мужчина рассказывает, что вчера установил новое приложение на телефон. Что он скажет?", "Чоловік розповідає, що вчора встановив новий додаток на телефон. Що він скаже?", "A man is telling that yesterday he installed a new app on his phone. What does he say?", + "B", None, None, 12), + + ("a2_technology_internet_t13", None, "topic_test", "production", "technology_vocabulary", 1, + "Wpisz brakujące słowo: Mam nowy ___. (телефон)", "Вставьте пропущенное слово: Mam nowy ___. (телефон)", "Вставте пропущене слово: Mam nowy ___. (телефон)", "Fill in the missing word: Mam nowy ___. (phone)", + "telefon", "first_letter", "t", 13), + ("a2_technology_internet_t14", None, "topic_test", "production", "internet_vocabulary", 1, + "Wpisz brakujące słowo: Wysłałem ci ___. (письмо)", "Вставьте пропущенное слово: Wysłałem ci ___. (письмо)", "Вставте пропущене слово: Wysłałem ci ___. (листа)", "Fill in the missing word: Wysłałem ci ___. (email)", + "e-mail", "first_letter", "e", 14), + ("a2_technology_internet_t15", None, "topic_test", "production", "pobierac_biernik", 2, + "Wpisz brakujące słowo: ___ ten plik? (ты скачиваешь)", "Вставьте пропущенное слово: ___ ten plik? (ты скачиваешь)", "Вставте пропущене слово: ___ ten plik? (ти завантажуєш)", "Fill in the missing word: ___ ten plik? (are you downloading)", + "Pobierasz", "first_letter", "P", 15), + ("a2_technology_internet_t16", None, "topic_test", "production", "logowac_sie_do", 2, + "Wpisz brakujące słowo: Logujesz się do ___? (почты)", "Вставьте пропущенное слово: Logujesz się do ___? (почты)", "Вставте пропущене слово: Logujesz się do ___? (пошти)", "Fill in the missing word: Logujesz się do ___? (email)", + "poczty", "first_letter", "p", 16), + ("a2_technology_internet_t17", None, "topic_test", "production", "umiec_korzystac", 2, + "Wpisz brakujące słowo: ___ zainstalować tę aplikację? (ты умеешь)", "Вставьте пропущенное слово: ___ zainstalować tę aplikację? (ты умеешь)", "Вставте пропущене слово: ___ zainstalować tę aplikację? (ти вмієш)", "Fill in the missing word: ___ zainstalować tę aplikację? (do you know how to)", + "Umiesz", "first_letter", "U", 17), + ("a2_technology_internet_t18", None, "topic_test", "production", "opisuje_swoja_technologie", 3, + "Przetłumacz: «Вчера я установил новое приложение».", "Переведите: «Вчера я установил новое приложение».", "Перекладіть: «Учора я встановив новий додаток».", "Translate: “Yesterday I installed a new app.”", + "Wczoraj zainstalowałem nową aplikację", "first_letter", "W", 18), + + ("a2_technology_internet_t19", None, "topic_test", "mixed", "opisuje_swoja_technologie", 3, + "Wybierz poprawne tłumaczenie: «Я пользуюсь компьютером каждый день, отправляю письма по работе, и вчера установил новое приложение».", "Выберите правильный перевод: «Я пользуюсь компьютером каждый день, отправляю письма по работе, и вчера установил новое приложение».", "Виберіть правильний переклад: «Я користуюся комп'ютером щодня, надсилаю листи по роботі, і вчора встановив новий додаток».", "Choose the correct translation: “I use a computer every day, I send emails for work, and yesterday I installed a new app.”", + "C", None, None, 19), + ("a2_technology_internet_t20", None, "topic_test", "mixed", "pobierac_biernik", 3, + "Wybierz poprawne tłumaczenie dialogu: «— Скачиваешь это приложение? — Да, скачиваю это приложение каждый день, потому что хочу учить польский.»", "Выберите правильный перевод диалога: «— Скачиваешь это приложение? — Да, скачиваю это приложение каждый день, потому что хочу учить польский.»", "Виберіть правильний переклад діалогу: «— Завантажуєш цей додаток? — Так, завантажую цей додаток щодня, бо хочу вивчати польську.»", "Choose the correct translation of the dialogue: “— Are you downloading this app? — Yes, I download this app every day because I want to learn Polish.”", + "A", None, None, 20), + ] + + for q in test_questions_t11_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_technology_internet', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t11_a2 = [ + ("a2_technology_internet_t01", "A", "komputer", "компьютер", "комп'ютер", "computer", False, "wrong_word"), + ("a2_technology_internet_t01", "B", "telefon", "телефон", "телефон", "phone", False, "wrong_word"), + ("a2_technology_internet_t01", "C", "internet", "интернет", "інтернет", "internet", False, "wrong_word"), + ("a2_technology_internet_t01", "D", "aplikacja", "приложение", "додаток", "app", True, None), + + ("a2_technology_internet_t02", "A", "komputera", "компьютера (род.)", "комп'ютера (род.)", "computer (gen.)", True, None), + ("a2_technology_internet_t02", "B", "komputer", "компьютер (им./вин.)", "комп'ютер (наз./знах.)", "computer (nom./acc.)", False, "wrong_case"), + ("a2_technology_internet_t02", "C", "komputerze", "компьютере (местн.)", "комп'ютері (місц.)", "computer (loc.)", False, "wrong_case"), + ("a2_technology_internet_t02", "D", "komputerowi", "компьютеру (дат.)", "комп'ютеру (дав.)", "computer (dat.)", False, "wrong_case"), + + ("a2_technology_internet_t03", "A", "e-mail", "электронная почта", "електронна пошта", "email", False, "wrong_word"), + ("a2_technology_internet_t03", "B", "wiadomość", "сообщение", "повідомлення", "message", False, "wrong_word"), + ("a2_technology_internet_t03", "C", "hasło", "пароль", "пароль", "password", True, None), + ("a2_technology_internet_t03", "D", "strona internetowa", "веб-сайт", "веб-сайт", "website", False, "wrong_word"), + + ("a2_technology_internet_t04", "A", "Wysyłam", "я отправляю", "я надсилаю", "I send", True, None), + ("a2_technology_internet_t04", "B", "Wysyłasz", "ты отправляешь (не тот человек)", "ти надсилаєш (не та особа)", "you send (wrong person)", False, "wrong_context"), + ("a2_technology_internet_t04", "C", "Wysyła", "он/она отправляет (не тот человек)", "він/вона надсилає (не та особа)", "he/she sends (wrong person)", False, "wrong_context"), + ("a2_technology_internet_t04", "D", "Wysyłaliśmy", "мы отправляли (неправильное число и время)", "ми надсилали (неправильне число і час)", "we sent (wrong number and tense)", False, "wrong_number"), + + ("a2_technology_internet_t05", "A", "Pobieram", "я скачиваю", "я завантажую", "I download", True, None), + ("a2_technology_internet_t05", "B", "Pobierasz", "ты скачиваешь (не тот человек)", "ти завантажуєш (не та особа)", "you download (wrong person)", False, "wrong_context"), + ("a2_technology_internet_t05", "C", "Pobiera", "он/она скачивает (не тот человек)", "він/вона завантажує (не та особа)", "he/she downloads (wrong person)", False, "wrong_context"), + ("a2_technology_internet_t05", "D", "Pobieraliśmy", "мы скачивали (неправильное число и время)", "ми завантажували (неправильне число і час)", "we downloaded (wrong number and tense)", False, "wrong_number"), + + ("a2_technology_internet_t06", "A", "Instalujesz tę aplikację?", "Ты устанавливаешь это приложение?", "Ти встановлюєш цей додаток?", "Are you installing this app?", False, "wrong_translation"), + ("a2_technology_internet_t06", "B", "Zainstalujesz tę aplikację?", "Ты установишь это приложение?", "Ти встановиш цей додаток?", "Will you install this app?", False, "wrong_translation"), + ("a2_technology_internet_t06", "C", "Odinstalowałaś tę aplikację?", "Ты удалила это приложение?", "Ти видалила цей додаток?", "Did you uninstall this app?", False, "wrong_translation"), + ("a2_technology_internet_t06", "D", "Zainstalowałaś tę aplikację?", "Ты установила это приложение?", "Ти встановила цей додаток?", "Did you install this app?", True, None), + + ("a2_technology_internet_t07", "A", "Komputera.", "Компьютера.", "Комп'ютера.", "A computer.", False, "wrong_context"), + ("a2_technology_internet_t07", "B", "Telefonu.", "Телефона.", "Телефону.", "A phone.", True, None), + ("a2_technology_internet_t07", "C", "Internetu.", "Интернета.", "Інтернету.", "The internet.", False, "wrong_context"), + ("a2_technology_internet_t07", "D", "Aplikacji.", "Приложения.", "Додатка.", "An app.", False, "wrong_context"), + + ("a2_technology_internet_t08", "A", "Korzystam z komputera.", "Я пользуюсь компьютером. (не соответствует ситуации)", "Я користуюся комп'ютером. (не відповідає ситуації)", "I use a computer. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_t08", "B", "Korzystam z telefonu.", "Я пользуюсь телефоном. (не соответствует ситуации)", "Я користуюся телефоном. (не відповідає ситуації)", "I use a phone. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_t08", "C", "Korzystam z aplikacji.", "Я пользуюсь приложением.", "Я користуюся додатком.", "I use an app.", True, None), + ("a2_technology_internet_t08", "D", "Korzystam z internetu.", "Я пользуюсь интернетом. (не соответствует ситуации)", "Я користуюся інтернетом. (не відповідає ситуації)", "I use the internet. (doesn't match the situation)", False, "wrong_context"), + + ("a2_technology_internet_t09", "A", "Strony internetowej.", "Веб-сайта.", "Веб-сайту.", "Of a website.", False, "wrong_context"), + ("a2_technology_internet_t09", "B", "E-maila.", "Письма.", "Листа.", "Of an email.", False, "wrong_context"), + ("a2_technology_internet_t09", "C", "Hasła.", "Пароля.", "Пароля.", "Of a password.", True, None), + ("a2_technology_internet_t09", "D", "Wiadomości.", "Сообщения.", "Повідомлення.", "Of a message.", False, "wrong_context"), + + ("a2_technology_internet_t10", "A", "Loguję się do poczty rano.", "Я вхожу в почту утром.", "Я входжу в пошту вранці.", "I log in to my email in the morning.", True, None), + ("a2_technology_internet_t10", "B", "Wysyłam e-mail rano.", "Я отправляю письмо утром. (не соответствует ситуации)", "Я надсилаю листа вранці. (не відповідає ситуації)", "I send an email in the morning. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_t10", "C", "Pobieram aplikację rano.", "Я скачиваю приложение утром. (не соответствует ситуации)", "Я завантажую додаток вранці. (не відповідає ситуації)", "I download an app in the morning. (doesn't match the situation)", False, "wrong_context"), + ("a2_technology_internet_t10", "D", "Korzystam z telefonu rano.", "Я пользуюсь телефоном утром. (не соответствует ситуации)", "Я користуюся телефоном вранці. (не відповідає ситуації)", "I use my phone in the morning. (doesn't match the situation)", False, "wrong_context"), + + ("a2_technology_internet_t11", "A", "Nowoczesny.", "Современный.", "Сучасний.", "Modern.", False, "wrong_context"), + ("a2_technology_internet_t11", "B", "Szybki.", "Быстрый.", "Швидкий.", "Fast.", False, "wrong_context"), + ("a2_technology_internet_t11", "C", "Wolny.", "Медленный.", "Повільний.", "Slow.", False, "wrong_context"), + ("a2_technology_internet_t11", "D", "Zepsuty.", "Сломанный.", "Зламаний.", "Broken.", True, None), + + ("a2_technology_internet_t12", "A", "Instaluję nową aplikację.", "Я устанавливаю новое приложение. (настоящее время)", "Я встановлюю новий додаток. (теперішній час)", "I'm installing a new app. (present tense)", False, "wrong_sentence_type"), + ("a2_technology_internet_t12", "B", "Zainstalowałem nową aplikację wczoraj.", "Я установил новое приложение вчера.", "Я встановив новий додаток учора.", "I installed a new app yesterday.", True, None), + ("a2_technology_internet_t12", "C", "Zainstaluję nową aplikację jutro.", "Я установлю новое приложение завтра. (будущее время)", "Я встановлю новий додаток завтра. (майбутній час)", "I will install a new app tomorrow. (future tense)", False, "wrong_sentence_type"), + ("a2_technology_internet_t12", "D", "Zainstalowałam nową aplikację wczoraj.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + ("a2_technology_internet_t19", "A", "Korzystałem z komputera codziennie, wysyłałem e-maile do pracy, i wczoraj zainstalowałem nową aplikację.", "Я пользовался компьютером каждый день, отправлял письма по работе, и вчера установил новое приложение. (прошедшее время)", "Я користувався комп'ютером щодня, надсилав листи по роботі, і вчора встановив новий додаток. (минулий час)", "I used to use a computer every day, sent emails for work, and yesterday I installed a new app. (past tense)", False, "wrong_sentence_type"), + ("a2_technology_internet_t19", "B", "Będę korzystać z komputera codziennie, będę wysyłać e-maile do pracy, i jutro zainstaluję nową aplikację.", "Я буду пользоваться компьютером каждый день, буду отправлять письма по работе, и завтра установлю новое приложение. (будущее время)", "Я користуватимусь комп'ютером щодня, надсилатиму листи по роботі, і завтра встановлю новий додаток. (майбутній час)", "I will use a computer every day, will send emails for work, and tomorrow I will install a new app. (future tense)", False, "wrong_sentence_type"), + ("a2_technology_internet_t19", "C", "Korzystam z komputera codziennie, wysyłam e-maile do pracy, i wczoraj zainstalowałem nową aplikację.", "Я пользуюсь компьютером каждый день, отправляю письма по работе, и вчера установил новое приложение.", "Я користуюся комп'ютером щодня, надсилаю листи по роботі, і вчора встановив новий додаток.", "I use a computer every day, I send emails for work, and yesterday I installed a new app.", True, None), + ("a2_technology_internet_t19", "D", "Korzystam z telefonu codziennie, wysyłam e-maile do pracy, i wczoraj zainstalowałem nową aplikację.", "Я пользуюсь телефоном каждый день, отправляю письма по работе, и вчера установил новое приложение. (неверное слово)", "Я користуюся телефоном щодня, надсилаю листи по роботі, і вчора встановив новий додаток. (невірне слово)", "I use a phone every day, I send emails for work, and yesterday I installed a new app. (wrong word)", False, "wrong_word"), + + ("a2_technology_internet_t20", "A", "— Pobierasz tę aplikację? — Tak, pobieram tę aplikację codziennie, bo chcę uczyć się polskiego.", "— Скачиваешь это приложение? — Да, скачиваю это приложение каждый день, потому что хочу учить польский.", "— Завантажуєш цей додаток? — Так, завантажую цей додаток щодня, бо хочу вивчати польську.", "— Are you downloading this app? — Yes, I download this app every day because I want to learn Polish.", True, None), + ("a2_technology_internet_t20", "B", "— Pobierałeś tę aplikację? — Tak, pobierałem tę aplikację codziennie, bo chciałem uczyć się polskiego.", "— Скачивал ли ты это приложение? — Да, скачивал это приложение каждый день, потому что хотел учить польский. (прошедшее время)", "— Ти завантажував цей додаток? — Так, завантажував цей додаток щодня, бо хотів вивчати польську. (минулий час)", "— Were you downloading this app? — Yes, I downloaded this app every day because I wanted to learn Polish. (past tense)", False, "wrong_sentence_type"), + ("a2_technology_internet_t20", "C", "— Pobierasz tę aplikację? — Nie, nie pobieram tej aplikacji, bo nie mam czasu.", "— Скачиваешь это приложение? — Нет, я не скачиваю это приложение, потому что у меня нет времени. (противоположный смысл)", "— Завантажуєш цей додаток? — Ні, я не завантажую цей додаток, бо не маю часу. (протилежний зміст)", "— Are you downloading this app? — No, I'm not downloading this app, because I don't have time. (opposite meaning)", False, "wrong_context"), + ("a2_technology_internet_t20", "D", "— Instalujesz tę aplikację? — Tak, pobieram tę aplikację codziennie, bo chcę uczyć się polskiego.", "— Устанавливаешь это приложение? — Да, скачиваю это приложение каждый день, потому что хочу учить польский. (несоответствие вопроса и ответа)", "— Встановлюєш цей додаток? — Так, завантажую цей додаток щодня, бо хочу вивчати польську. (невідповідність питання і відповіді)", "— Are you installing this app? — Yes, I download this app every day because I want to learn Polish. (mismatched question and answer)", False, "wrong_word"), + ] + + for opt in test_options_t11_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + +# ==================== ТЕМА 12 (A2): BANK I FINANSE ==================== + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ('a2_bank_finance', 'A2', 12, + 'Bank i finanse', + 'Банк и финансы', + 'Банк і фінанси', + 'Bank and Finance') + ON CONFLICT (topic_id) DO UPDATE SET + name_pl = EXCLUDED.name_pl, + name_ru = EXCLUDED.name_ru, + name_uk = EXCLUDED.name_uk, + name_en = EXCLUDED.name_en + """) + + lessons_t12_a2 = [ + ("a2_bank_finance_l01", 1, "bank_vocabulary", "Podstawowe słowa: bank", "Основные слова: банк", "Основні слова: банк", "Basic words: bank", + "Podstawowe słowa: bank, pieniądze, konto, karta.", + "Основные слова: bank (банк), pieniądze (деньги), konto (счёт), karta (карта).", + "Основні слова: bank (банк), pieniądze (гроші), konto (рахунок), karta (картка).", + "Basic words: bank (bank), pieniądze (money), konto (account), karta (card)."), + + ("a2_bank_finance_l02", 2, "placic_za_biernik", "Płacić za + biernik", "Płacić za + винительный падеж", "Płacić za + знахідний відмінок", "Płacić za + accusative", + "Czasownik „płacić” + „za” + biernik: płacę za bilet, płacisz za kawę, płaci za zakupy.", + "Глагол „płacić” (платить) + „za” + винительный падеж: płacę za bilet (я плачу за билет), płacisz za kawę (ты платишь за кофе), płaci za zakupy (он/она платит за покупки).", + "Дієслово „płacić” (платити) + „za” + знахідний відмінок: płacę za bilet (я плачу за квиток), płacisz za kawę (ти платиш за каву), płaci za zakupy (він/вона платить за покупки).", + "The verb „płacić” (to pay) + „za” + accusative: płacę za bilet (I pay for a ticket), płacisz za kawę (you pay for coffee), płaci za zakupy (he/she pays for shopping)."), + + ("a2_bank_finance_l03", 3, "finanse_vocabulary", "Podstawowe słowa: finanse", "Основные слова: финансы", "Основні слова: фінанси", "Basic words: finance", + "Podstawowe słowa: gotówka, przelew, rachunek, oszczędności.", + "Основные слова: gotówka (наличные), przelew (перевод), rachunek (счёт/чек), oszczędności (сбережения).", + "Основні слова: gotówka (готівка), przelew (переказ), rachunek (рахунок/чек), oszczędności (заощадження).", + "Basic words: gotówka (cash), przelew (transfer), rachunek (bill), oszczędności (savings)."), + + ("a2_bank_finance_l04", 4, "miec_biernik", "Mieć + biernik", "Mieć + винительный падеж", "Mieć + знахідний відмінок", "Mieć + accusative", + "Czasownik „mieć” + biernik: mam konto w banku, masz kartę kredytową, ma oszczędności.", + "Глагол „mieć” (иметь) + винительный падеж: mam konto w banku (у меня есть счёт в банке), masz kartę kredytową (у тебя есть кредитная карта), ma oszczędności (у него/неё есть сбережения).", + "Дієслово „mieć” (мати) + знахідний відмінок: mam konto w banku (у мене є рахунок у банку), masz kartę kredytową (у тебе є кредитна картка), ma oszczędności (у нього/неї є заощадження).", + "The verb „mieć” (to have) + accusative: mam konto w banku (I have an account at the bank), masz kartę kredytową (you have a credit card), ma oszczędności (he/she has savings)."), + + ("a2_bank_finance_l05", 5, "wyplacac_biernik", "Wypłacać + biernik", "Wypłacać + винительный падеж", "Wypłacać + знахідний відмінок", "Wypłacać + accusative", + "Czasownik „wypłacać” + biernik: wypłacam pieniądze, wypłacasz gotówkę, wypłaca sto złotych.", + "Глагол „wypłacać” (снимать/выплачивать деньги) + винительный падеж: wypłacam pieniądze (я снимаю деньги), wypłacasz gotówkę (ты снимаешь наличные), wypłaca sto złotych (он/она снимает сто злотых).", + "Дієслово „wypłacać” (знімати/виплачувати гроші) + знахідний відмінок: wypłacam pieniądze (я знімаю гроші), wypłacasz gotówkę (ти знімаєш готівку), wypłaca sto złotych (він/вона знімає сто злотих).", + "The verb „wypłacać” (to withdraw money) + accusative: wypłacam pieniądze (I withdraw money), wypłacasz gotówkę (you withdraw cash), wypłaca sto złotych (he/she withdraws a hundred zlotys)."), + + ("a2_bank_finance_l06", 6, "oszczedzac_na_biernik", "Oszczędzać na + biernik", "Oszczędzać na + винительный падеж", "Oszczędzać na + знахідний відмінок", "Oszczędzać na + accusative", + "Czasownik „oszczędzać” + „na” + biernik: oszczędzam na wakacje, oszczędzasz na samochód, oszczędza na dom.", + "Глагол „oszczędzać” (копить/экономить) + „na” + винительный падеж: oszczędzam na wakacje (я коплю на отпуск), oszczędzasz na samochód (ты копишь на машину), oszczędza na dom (он/она копит на дом).", + "Дієслово „oszczędzać” (заощаджувати) + „na” + знахідний відмінок: oszczędzam na wakacje (я заощаджую на відпустку), oszczędzasz na samochód (ти заощаджуєш на автомобіль), oszczędza na dom (він/вона заощаджує на будинок).", + "The verb „oszczędzać” (to save up) + „na” + accusative: oszczędzam na wakacje (I'm saving up for a vacation), oszczędzasz na samochód (you're saving up for a car), oszczędza na dom (he/she is saving up for a house)."), + + ("a2_bank_finance_l07", 7, "przymiotniki_finanse_vocabulary", "Podstawowe słowa: przymiotniki o finansach", "Основные слова: прилагательные о финансах", "Основні слова: прикметники про фінанси", "Basic words: finance adjectives", + "Podstawowe przymiotniki opisujące finanse: drogi, tani, bogaty, biedny.", + "Основные прилагательные, описывающие финансы: drogi (дорогой), tani (дешёвый), bogaty (богатый), biedny (бедный).", + "Основні прикметники, що описують фінанси: drogi (дорогий), tani (дешевий), bogaty (багатий), biedny (бідний).", + "Basic adjectives describing finance: drogi (expensive), tani (cheap), bogaty (rich), biedny (poor)."), + + ("a2_bank_finance_l08", 8, "musiec_placic", "Musieć + bezokolicznik", "Musieć + инфинитив", "Musieć + інфінітив", "Musieć + infinitive", + "Czasownik „musieć” + bezokolicznik wyraża obowiązek: muszę zapłacić rachunek, musisz oddać pieniądze, musi oszczędzać.", + "Глагол „musieć” (быть должным) + инфинитив выражает обязанность: muszę zapłacić rachunek (я должен оплатить счёт), musisz oddać pieniądze (ты должен вернуть деньги), musi oszczędzać (он/она должен(на) копить).", + "Дієслово „musieć” (бути зобов'язаним) + інфінітив виражає обов'язок: muszę zapłacić rachunek (я мушу оплатити рахунок), musisz oddać pieniądze (ти мусиш повернути гроші), musi oszczędzać (він/вона мусить заощаджувати).", + "The verb „musieć” (must/to have to) + infinitive expresses an obligation: muszę zapłacić rachunek (I have to pay the bill), musisz oddać pieniądze (you have to return the money), musi oszczędzać (he/she has to save)."), + + ("a2_bank_finance_l09", 9, "przeszly_czas_finanse", "Zapłaciłem/zapłaciłam, wypłaciłem/wypłaciłam (przeszłość)", "Zapłaciłem/zapłaciłam, wypłaciłem/wypłaciłam (прошедшее)", "Zapłaciłem/zapłaciłam, wypłaciłem/wypłaciłam (минулий час)", "Zapłaciłem/zapłaciłam, wypłaciłem/wypłaciłam (past)", + "Czas przeszły finansów tworzymy „zapłaciłem/zapłaciłam” lub „wypłaciłem/wypłaciłam” zależnie od rodzaju mówiącego: zapłaciłem rachunek wczoraj, wypłaciłaś pieniądze, zapłacił za bilet.", + "Прошедшее время финансов образуем „zapłaciłem/zapłaciłam” или „wypłaciłem/wypłaciłam” в зависимости от рода говорящего: zapłaciłem rachunek wczoraj (я оплатил счёт вчера), wypłaciłaś pieniądze (ты сняла деньги), zapłacił za bilet (он заплатил за билет).", + "Минулий час фінансів утворюємо „zapłaciłem/zapłaciłam” або „wypłaciłem/wypłaciłam” залежно від роду мовця: zapłaciłem rachunek wczoraj (я оплатив рахунок учора), wypłaciłaś pieniądze (ти зняла гроші), zapłacił za bilet (він заплатив за квиток).", + "We form the past tense of finance with „zapłaciłem/zapłaciłam” or „wypłaciłem/wypłaciłam” depending on the speaker's gender: zapłaciłem rachunek wczoraj (I paid the bill yesterday), wypłaciłaś pieniądze (you withdrew the money), zapłacił za bilet (he paid for the ticket)."), + + ("a2_bank_finance_l10", 10, "opisuje_swoje_finanse", "Opisuję swoje finanse", "Описываю свои финансы", "Описую свої фінанси", "Describing my finances", + "Żeby opisać finanse, łączymy zdania: Mam konto w banku. Płacę kartą za zakupy. Wczoraj zapłaciłem rachunek za prąd.", + "Чтобы описать финансы, соединяем предложения: Mam konto w banku. Płacę kartą za zakupy. Wczoraj zapłaciłem rachunek za prąd. (У меня есть счёт в банке. Я плачу картой за покупки. Вчера я оплатил счёт за электричество.)", + "Щоб описати фінанси, поєднуємо речення: Mam konto w banku. Płacę kartą za zakupy. Wczoraj zapłaciłem rachunek za prąd. (У мене є рахунок у банку. Я плачу карткою за покупки. Учора я оплатив рахунок за електрику.)", + "To describe finances, we combine sentences: Mam konto w banku. Płacę kartą za zakupy. Wczoraj zapłaciłem rachunek za prąd. (I have an account at the bank. I pay by card for shopping. Yesterday I paid the electricity bill.)"), + ] + + for lesson in lessons_t12_a2: + await conn.execute(""" + INSERT INTO learning_lessons (lesson_id, topic_id, order_number, skill_tag, title_pl, title_ru, title_uk, title_en, objective_pl, objective_ru, objective_uk, objective_en, explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, 'a2_bank_finance', $2, $3, $4, $5, $6, $7, $4, $5, $6, $7, $8, $9, $10, $11) + ON CONFLICT (lesson_id) DO NOTHING + """, lesson[0], lesson[1], lesson[2], lesson[3], lesson[4], lesson[5], lesson[6], lesson[7], lesson[8], lesson[9], lesson[10]) + + examples_t12_a2 = [ + ("a2_bank_finance_l01", 1, "Idę do banku.", "Я иду в банк.", "Я йду до банку.", "I'm going to the bank."), + ("a2_bank_finance_l01", 2, "Mam mało pieniędzy.", "У меня мало денег.", "У мене мало грошей.", "I have little money."), + ("a2_bank_finance_l01", 3, "Otworzyłem konto w banku.", "Я открыл счёт в банке.", "Я відкрив рахунок у банку.", "I opened an account at the bank."), + + ("a2_bank_finance_l02", 1, "Płacę za bilet.", "Я плачу за билет.", "Я плачу за квиток.", "I'm paying for a ticket."), + ("a2_bank_finance_l02", 2, "Płacisz za kawę?", "Ты платишь за кофе?", "Ти платиш за каву?", "Are you paying for the coffee?"), + ("a2_bank_finance_l02", 3, "Ona płaci za zakupy.", "Она платит за покупки.", "Вона платить за покупки.", "She's paying for the shopping."), + + ("a2_bank_finance_l03", 1, "Mam trochę gotówki.", "У меня есть немного наличных.", "У мене є трохи готівки.", "I have some cash."), + ("a2_bank_finance_l03", 2, "Zrobiłem przelew.", "Я сделал перевод.", "Я зробив переказ.", "I made a transfer."), + ("a2_bank_finance_l03", 3, "Zapłaciłem rachunek.", "Я оплатил счёт.", "Я оплатив рахунок.", "I paid the bill."), + + ("a2_bank_finance_l04", 1, "Mam konto w banku.", "У меня есть счёт в банке.", "У мене є рахунок у банку.", "I have an account at the bank."), + ("a2_bank_finance_l04", 2, "Masz kartę kredytową?", "У тебя есть кредитная карта?", "У тебе є кредитна картка?", "Do you have a credit card?"), + ("a2_bank_finance_l04", 3, "On ma duże oszczędności.", "У него большие сбережения.", "У нього великі заощадження.", "He has large savings."), + + ("a2_bank_finance_l05", 1, "Wypłacam pieniądze z bankomatu.", "Я снимаю деньги из банкомата.", "Я знімаю гроші з банкомату.", "I'm withdrawing money from the ATM."), + ("a2_bank_finance_l05", 2, "Wypłacasz gotówkę?", "Ты снимаешь наличные?", "Ти знімаєш готівку?", "Are you withdrawing cash?"), + ("a2_bank_finance_l05", 3, "Ona wypłaciła sto złotych.", "Она сняла сто злотых.", "Вона зняла сто злотих.", "She withdrew a hundred zlotys."), + + ("a2_bank_finance_l06", 1, "Oszczędzam na wakacje.", "Я коплю на отпуск.", "Я заощаджую на відпустку.", "I'm saving up for a vacation."), + ("a2_bank_finance_l06", 2, "Oszczędzasz na samochód?", "Ты копишь на машину?", "Ти заощаджуєш на автомобіль?", "Are you saving up for a car?"), + ("a2_bank_finance_l06", 3, "On oszczędza na dom.", "Он копит на дом.", "Він заощаджує на будинок.", "He's saving up for a house."), + + ("a2_bank_finance_l07", 1, "Ten telefon jest bardzo drogi.", "Этот телефон очень дорогой.", "Цей телефон дуже дорогий.", "This phone is very expensive."), + ("a2_bank_finance_l07", 2, "Znalazłem tani bilet.", "Я нашёл дешёвый билет.", "Я знайшов дешевий квиток.", "I found a cheap ticket."), + ("a2_bank_finance_l07", 3, "On jest bardzo bogaty.", "Он очень богатый.", "Він дуже багатий.", "He is very rich."), + + ("a2_bank_finance_l08", 1, "Muszę zapłacić rachunek.", "Я должен оплатить счёт.", "Я мушу оплатити рахунок.", "I have to pay the bill."), + ("a2_bank_finance_l08", 2, "Musisz oddać mi pieniądze.", "Ты должен вернуть мне деньги.", "Ти мусиш повернути мені гроші.", "You have to return the money to me."), + ("a2_bank_finance_l08", 3, "Ona musi oszczędzać na przyszłość.", "Она должна копить на будущее.", "Вона мусить заощаджувати на майбутнє.", "She has to save for the future."), + + ("a2_bank_finance_l09", 1, "Zapłaciłem rachunek wczoraj.", "Я оплатил счёт вчера.", "Я оплатив рахунок учора.", "I paid the bill yesterday."), + ("a2_bank_finance_l09", 2, "Wypłaciłaś pieniądze z konta?", "Ты сняла деньги со счёта?", "Ти зняла гроші з рахунку?", "Did you withdraw money from the account?"), + ("a2_bank_finance_l09", 3, "On zapłacił za bilet w zeszłym tygodniu.", "Он заплатил за билет на прошлой неделе.", "Він заплатив за квиток минулого тижня.", "He paid for the ticket last week."), + + ("a2_bank_finance_l10", 1, "Mam konto w banku.", "У меня есть счёт в банке.", "У мене є рахунок у банку.", "I have an account at the bank."), + ("a2_bank_finance_l10", 2, "Płacę kartą za zakupy.", "Я плачу картой за покупки.", "Я плачу карткою за покупки.", "I pay by card for shopping."), + ("a2_bank_finance_l10", 3, "Wczoraj zapłaciłem rachunek za prąd.", "Вчера я оплатил счёт за электричество.", "Учора я оплатив рахунок за електрику.", "Yesterday I paid the electricity bill."), + ] + + for ex in examples_t12_a2: + await conn.execute(""" + INSERT INTO lesson_examples (lesson_id, order_number, text_pl, text_ru, text_uk, text_en) + VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT DO NOTHING + """, ex[0], ex[1], ex[2], ex[3], ex[4], ex[5]) + + questions_t12_a2 = [ + # L01 — bank_vocabulary (difficulty 1) + ("a2_bank_finance_l01_q1", "a2_bank_finance_l01", "lesson_practice", "recognition", "bank_vocabulary", 1, + "Jak po polsku „счёт (банковский)”?", "Как по-польски «счёт (банковский)»?", "Як польською «рахунок (банківський)»?", "How do you say “account (bank)” in Polish?", + "D", None, None), + ("a2_bank_finance_l01_q2", "a2_bank_finance_l01", "lesson_practice", "production", "bank_vocabulary", 1, + "Wpisz brakujące słowo: Idę do ___. (банка)", "Вставьте пропущенное слово: Idę do ___. (банка)", "Вставте пропущене слово: Idę do ___. (банку)", "Fill in the missing word: Idę do ___. (bank)", + "banku", "first_letter", "b"), + ("a2_bank_finance_l01_q3", "a2_bank_finance_l01", "lesson_practice", "application", "bank_vocabulary", 1, + "Chcesz otworzyć nowe konto bankowe. Dokąd idziesz?", "Ты хочешь открыть новый банковский счёт. Куда ты идёшь?", "Ти хочеш відкрити новий банківський рахунок. Куди ти йдеш?", "You want to open a new bank account. Where are you going?", + "B", None, None), + + # L02 — placic_za_biernik (difficulty 1) + ("a2_bank_finance_l02_q1", "a2_bank_finance_l02", "lesson_practice", "recognition", "placic_za_biernik", 1, + "Wybierz poprawną formę: Płacę ___ bilet. (za)", "Выберите правильную форму: Płacę ___ bilet. (za)", "Виберіть правильну форму: Płacę ___ bilet. (za)", "Choose the correct form: Płacę ___ bilet. (za)", + "A", None, None), + ("a2_bank_finance_l02_q2", "a2_bank_finance_l02", "lesson_practice", "production", "placic_za_biernik", 1, + "Wpisz brakujące słowo: ___ za zakupy. (она платит)", "Вставьте пропущенное слово: ___ za zakupy. (она платит)", "Вставте пропущене слово: ___ za zakupy. (вона платить)", "Fill in the missing word: ___ za zakupy. (she pays)", + "Płaci", "first_letter", "P"), + ("a2_bank_finance_l02_q3", "a2_bank_finance_l02", "lesson_practice", "application", "placic_za_biernik", 1, + "Kelner przynosi rachunek za obiad. Co robisz?", "Официант приносит счёт за обед. Что ты делаешь?", "Офіціант приносить рахунок за обід. Що ти робиш?", "The waiter brings the bill for lunch. What do you do?", + "A", None, None), + + # L03 — finanse_vocabulary (difficulty 1) + ("a2_bank_finance_l03_q1", "a2_bank_finance_l03", "lesson_practice", "recognition", "finanse_vocabulary", 1, + "Jak po polsku „наличные”?", "Как по-польски «наличные»?", "Як польською «готівка»?", "How do you say “cash” in Polish?", + "C", None, None), + ("a2_bank_finance_l03_q2", "a2_bank_finance_l03", "lesson_practice", "production", "finanse_vocabulary", 1, + "Wpisz brakujące słowo: Zrobiłem ___. (перевод)", "Вставьте пропущенное слово: Zrobiłem ___. (перевод)", "Вставте пропущене слово: Zrobiłem ___. (переказ)", "Fill in the missing word: Zrobiłem ___. (transfer)", + "przelew", "first_letter", "p"), + ("a2_bank_finance_l03_q3", "a2_bank_finance_l03", "lesson_practice", "application", "finanse_vocabulary", 1, + "Musisz zapłacić za prąd, więc dostajesz dokument z kwotą do zapłacenia. Co to jest?", "Тебе нужно оплатить электричество, и ты получаешь документ с суммой к оплате. Что это?", "Тобі треба оплатити електрику, і ти отримуєш документ із сумою до сплати. Що це?", "You need to pay for electricity, so you get a document with the amount due. What is it?", + "C", None, None), + + # L04 — miec_biernik (difficulty 1) + ("a2_bank_finance_l04_q1", "a2_bank_finance_l04", "lesson_practice", "recognition", "miec_biernik", 1, + "Wybierz poprawną formę: Mam ___. (konto)", "Выберите правильную форму: Mam ___. (konto)", "Виберіть правильну форму: Mam ___. (konto)", "Choose the correct form: Mam ___. (konto)", + "A", None, None), + ("a2_bank_finance_l04_q2", "a2_bank_finance_l04", "lesson_practice", "production", "miec_biernik", 1, + "Wpisz brakujące słowo: Masz ___? (кредитную карту)", "Вставьте пропущенное слово: Masz ___? (кредитную карту)", "Вставте пропущене слово: Masz ___? (кредитну картку)", "Fill in the missing word: Masz ___? (credit card)", + "kartę kredytową", "first_letter", "k"), + ("a2_bank_finance_l04_q3", "a2_bank_finance_l04", "lesson_practice", "application", "miec_biernik", 1, + "Kolega pyta, czy masz oszczędności. Masz dużo oszczędności. Co powiesz?", "Друг спрашивает, есть ли у тебя сбережения. У тебя много сбережений. Что ты скажешь?", "Друг питає, чи маєш заощадження. Ти маєш багато заощаджень. Що ти скажеш?", "A friend asks if you have savings. You have a lot of savings. What do you say?", + "C", None, None), + + # L05 — wyplacac_biernik (difficulty 2) + ("a2_bank_finance_l05_q1", "a2_bank_finance_l05", "lesson_practice", "recognition", "wyplacac_biernik", 2, + "Wybierz poprawną formę: ___ pieniądze z bankomatu. (wypłacać, ja)", "Выберите правильную форму: ___ pieniądze z bankomatu. (wypłacać, ja)", "Виберіть правильну форму: ___ pieniądze z bankomatu. (wypłacać, ja)", "Choose the correct form: ___ pieniądze z bankomatu. (wypłacać, I)", + "A", None, None), + ("a2_bank_finance_l05_q2", "a2_bank_finance_l05", "lesson_practice", "production", "wyplacac_biernik", 2, + "Wpisz brakujące słowo: ___ gotówkę? (ты снимаешь)", "Вставьте пропущенное слово: ___ gotówkę? (ты снимаешь)", "Вставте пропущене слово: ___ gotówkę? (ти знімаєш)", "Fill in the missing word: ___ gotówkę? (are you withdrawing)", + "Wypłacasz", "first_letter", "W"), + ("a2_bank_finance_l05_q3", "a2_bank_finance_l05", "lesson_practice", "application", "wyplacac_biernik", 2, + "Chcesz opowiedzieć, że właśnie w tej chwili zdejmujesz pieniądze z bankomatu. Co powiesz?", "Ты хочешь рассказать, что прямо сейчас снимаешь деньги в банкомате. Что ты скажешь?", "Ти хочеш розповісти, що прямо зараз знімаєш гроші з банкомату. Що ти скажеш?", "You want to say that right now you're withdrawing money from the ATM. What do you say?", + "A", None, None), + + # L06 — oszczedzac_na_biernik (difficulty 2) + ("a2_bank_finance_l06_q1", "a2_bank_finance_l06", "lesson_practice", "recognition", "oszczedzac_na_biernik", 2, + "Wybierz poprawną formę: Oszczędzam ___ wakacje. (na)", "Выберите правильную форму: Oszczędzam ___ wakacje. (na)", "Виберіть правильну форму: Oszczędzam ___ wakacje. (na)", "Choose the correct form: Oszczędzam ___ wakacje. (na)", + "A", None, None), + ("a2_bank_finance_l06_q2", "a2_bank_finance_l06", "lesson_practice", "production", "oszczedzac_na_biernik", 2, + "Wpisz brakujące słowo: ___ na samochód? (ты копишь)", "Вставьте пропущенное слово: ___ na samochód? (ты копишь)", "Вставте пропущене слово: ___ na samochód? (ти заощаджуєш)", "Fill in the missing word: ___ na samochód? (are you saving up)", + "Oszczędzasz", "first_letter", "O"), + ("a2_bank_finance_l06_q3", "a2_bank_finance_l06", "lesson_practice", "application", "oszczedzac_na_biernik", 2, + "Chcesz kupić dom za kilka lat, więc regularnie odkładasz pieniądze. Co powiesz?", "Ты хочешь купить дом через несколько лет, поэтому регулярно откладываешь деньги. Что ты скажешь?", "Ти хочеш купити будинок за кілька років, тому регулярно відкладаєш гроші. Що ти скажеш?", "You want to buy a house in a few years, so you regularly set money aside. What do you say?", + "C", None, None), + + # L07 — przymiotniki_finanse_vocabulary (difficulty 2) + ("a2_bank_finance_l07_q1", "a2_bank_finance_l07", "lesson_practice", "recognition", "przymiotniki_finanse_vocabulary", 2, + "Jak po polsku „бедный”?", "Как по-польски «бедный»?", "Як польською «бідний»?", "How do you say “poor” in Polish?", + "D", None, None), + ("a2_bank_finance_l07_q2", "a2_bank_finance_l07", "lesson_practice", "production", "przymiotniki_finanse_vocabulary", 2, + "Wpisz brakujące słowo: Ten telefon jest bardzo ___. (дорогой)", "Вставьте пропущенное слово: Ten telefon jest bardzo ___. (дорогой)", "Вставте пропущене слово: Ten telefon jest bardzo ___. (дорогий)", "Fill in the missing word: Ten telefon jest bardzo ___. (expensive)", + "drogi", "first_letter", "d"), + ("a2_bank_finance_l07_q3", "a2_bank_finance_l07", "lesson_practice", "application", "przymiotniki_finanse_vocabulary", 2, + "Znalazłeś bilet, który kosztuje bardzo mało. Jaki on jest?", "Ты нашёл билет, который стоит очень мало. Какой он?", "Ти знайшов квиток, який коштує дуже мало. Який він?", "You found a ticket that costs very little. What is it like?", + "B", None, None), + + # L08 — musiec_placic (difficulty 2) + ("a2_bank_finance_l08_q1", "a2_bank_finance_l08", "lesson_practice", "recognition", "musiec_placic", 2, + "Wybierz poprawną formę: ___ zapłacić rachunek. (musieć, ja)", "Выберите правильную форму: ___ zapłacić rachunek. (musieć, ja)", "Виберіть правильну форму: ___ zapłacić rachunek. (musieć, ja)", "Choose the correct form: ___ zapłacić rachunek. (musieć, I)", + "A", None, None), + ("a2_bank_finance_l08_q2", "a2_bank_finance_l08", "lesson_practice", "production", "musiec_placic", 2, + "Wpisz brakujące słowo: ___ oddać mi pieniądze? (ты должен)", "Вставьте пропущенное слово: ___ oddać mi pieniądze? (ты должен)", "Вставте пропущене слово: ___ oddać mi pieniądze? (ти мусиш)", "Fill in the missing word: ___ oddać mi pieniądze? (do you have to)", + "Musisz", "first_letter", "M"), + ("a2_bank_finance_l08_q3", "a2_bank_finance_l08", "lesson_practice", "application", "musiec_placic", 2, + "Dostałeś rachunek za prąd i musisz go zapłacić do jutra. Co powiesz?", "Ты получил счёт за электричество, и должен оплатить его до завтра. Что ты скажешь?", "Ти отримав рахунок за електрику, і мусиш оплатити його до завтра. Що ти скажеш?", "You got an electricity bill and have to pay it by tomorrow. What do you say?", + "A", None, None), + + # L09 — przeszly_czas_finanse (difficulty 3) + ("a2_bank_finance_l09_q1", "a2_bank_finance_l09", "lesson_practice", "recognition", "przeszly_czas_finanse", 3, + "Co znaczy „Wypłaciłaś pieniądze z konta”?", "Что означает «Wypłaciłaś pieniądze z konta»?", "Що означає «Wypłaciłaś pieniądze z konta»?", "What does “Wypłaciłaś pieniądze z konta” mean?", + "D", None, None), + ("a2_bank_finance_l09_q2", "a2_bank_finance_l09", "lesson_practice", "production", "przeszly_czas_finanse", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ rachunek wczoraj. (я оплатила)", "Вставьте пропущенное слово (говорит женщина): ___ rachunek wczoraj. (я оплатила)", "Вставте пропущене слово (говорить жінка): ___ rachunek wczoraj. (я оплатила)", "Fill in the missing word (a woman is speaking): ___ rachunek wczoraj. (I paid)", + "Zapłaciłam", "first_letter", "Z"), + ("a2_bank_finance_l09_q3", "a2_bank_finance_l09", "lesson_practice", "application", "przeszly_czas_finanse", 3, + "Mężczyzna opowiada, że wczoraj zapłacił za bilet w kasie. Co powie?", "Мужчина рассказывает, что вчера заплатил за билет в кассе. Что он скажет?", "Чоловік розповідає, що вчора заплатив за квиток у касі. Що він скаже?", "A man is telling that yesterday he paid for the ticket at the counter. What does he say?", + "B", None, None), + + # L10 — opisuje_swoje_finanse (difficulty 3) + ("a2_bank_finance_l10_q1", "a2_bank_finance_l10", "lesson_practice", "recognition", "opisuje_swoje_finanse", 3, + "Które zdanie poprawnie opisuje finanse?", "Какое предложение правильно описывает финансы?", "Яке речення правильно описує фінанси?", "Which sentence correctly describes finances?", + "D", None, None), + ("a2_bank_finance_l10_q2", "a2_bank_finance_l10", "lesson_practice", "production", "opisuje_swoje_finanse", 3, + "Przetłumacz: «Вчера я оплатил счёт за электричество».", "Переведите: «Вчера я оплатил счёт за электричество».", "Перекладіть: «Учора я оплатив рахунок за електрику».", "Translate: “Yesterday I paid the electricity bill.”", + "Wczoraj zapłaciłem rachunek za prąd", "first_letter", "W"), + ("a2_bank_finance_l10_q3", "a2_bank_finance_l10", "lesson_practice", "application", "opisuje_swoje_finanse", 3, + "Chcesz opisać koledze swoje finanse: masz konto w banku, płacisz kartą, wczoraj zapłaciłeś rachunek. Jak zaczniesz zdanie?", "Ты хочешь описать другу свои финансы: у тебя есть счёт в банке, ты платишь картой, вчера оплатил счёт. Как ты начнёшь предложение?", "Ти хочеш описати другу свої фінанси: у тебе є рахунок у банку, ти платиш карткою, вчора оплатив рахунок. Як ти почнеш речення?", "You want to describe your finances to a friend: you have a bank account, you pay by card, yesterday you paid a bill. How do you start the sentence?", + "C", None, None), + ] + + for q in questions_t12_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question) + VALUES ($1, $2, 'a2_bank_finance', $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, FALSE) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[1], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12]) + + options_t12_a2 = [ + # L01 + ("a2_bank_finance_l01_q1", "A", "bank", "банк", "банк", "bank", False, "wrong_word"), + ("a2_bank_finance_l01_q1", "B", "pieniądze", "деньги", "гроші", "money", False, "wrong_word"), + ("a2_bank_finance_l01_q1", "C", "karta", "карта", "картка", "card", False, "wrong_word"), + ("a2_bank_finance_l01_q1", "D", "konto", "счёт", "рахунок", "account", True, None), + + ("a2_bank_finance_l01_q3", "A", "Do sklepu.", "В магазин.", "До магазину.", "To the store.", False, "wrong_context"), + ("a2_bank_finance_l01_q3", "B", "Do banku.", "В банк.", "До банку.", "To the bank.", True, None), + ("a2_bank_finance_l01_q3", "C", "Do teatru.", "В театр.", "До театру.", "To the theater.", False, "wrong_context"), + ("a2_bank_finance_l01_q3", "D", "Do szkoły.", "В школу.", "До школи.", "To school.", False, "wrong_context"), + + # L02 + ("a2_bank_finance_l02_q1", "A", "za", "за", "за", "for", True, None), + ("a2_bank_finance_l02_q1", "B", "do", "в/к", "до", "to", False, "wrong_word"), + ("a2_bank_finance_l02_q1", "C", "na", "на", "на", "on", False, "wrong_word"), + ("a2_bank_finance_l02_q1", "D", "z", "с/из", "з", "with/from", False, "wrong_word"), + + ("a2_bank_finance_l02_q3", "A", "Płacę za obiad.", "Я плачу за обед.", "Я плачу за обід.", "I'm paying for lunch.", True, None), + ("a2_bank_finance_l02_q3", "B", "Wypłacam pieniądze.", "Я снимаю деньги. (неверный глагол)", "Я знімаю гроші. (невірне дієслово)", "I'm withdrawing money. (wrong verb)", False, "wrong_word"), + ("a2_bank_finance_l02_q3", "C", "Oszczędzam na obiad.", "Я коплю на обед. (не соответствует ситуации)", "Я заощаджую на обід. (не відповідає ситуації)", "I'm saving up for lunch. (doesn't match the situation)", False, "wrong_context"), + ("a2_bank_finance_l02_q3", "D", "Mam obiad.", "У меня есть обед. (не соответствует ситуации)", "У мене є обід. (не відповідає ситуації)", "I have lunch. (doesn't match the situation)", False, "wrong_context"), + + # L03 + ("a2_bank_finance_l03_q1", "A", "przelew", "перевод", "переказ", "transfer", False, "wrong_word"), + ("a2_bank_finance_l03_q1", "B", "rachunek", "счёт/чек", "рахунок/чек", "bill", False, "wrong_word"), + ("a2_bank_finance_l03_q1", "C", "gotówka", "наличные", "готівка", "cash", True, None), + ("a2_bank_finance_l03_q1", "D", "oszczędności", "сбережения", "заощадження", "savings", False, "wrong_word"), + + ("a2_bank_finance_l03_q3", "A", "Gotówka.", "Наличные.", "Готівка.", "Cash.", False, "wrong_context"), + ("a2_bank_finance_l03_q3", "B", "Przelew.", "Перевод.", "Переказ.", "Transfer.", False, "wrong_context"), + ("a2_bank_finance_l03_q3", "C", "Rachunek.", "Счёт.", "Рахунок.", "Bill.", True, None), + ("a2_bank_finance_l03_q3", "D", "Oszczędności.", "Сбережения.", "Заощадження.", "Savings.", False, "wrong_context"), + + # L04 + ("a2_bank_finance_l04_q1", "A", "konto", "счёт (им./вин.)", "рахунок (наз./знах.)", "account (nom./acc.)", True, None), + ("a2_bank_finance_l04_q1", "B", "kontu", "счёту (дат.)", "рахунку (дав.)", "account (dat.)", False, "wrong_case"), + ("a2_bank_finance_l04_q1", "C", "koncie", "счёте (местн.)", "рахунку (місц.)", "account (loc.)", False, "wrong_case"), + ("a2_bank_finance_l04_q1", "D", "kontem", "счётом (тв.)", "рахунком (ор.)", "account (instr.)", False, "wrong_case"), + + ("a2_bank_finance_l04_q3", "A", "Mam kartę.", "У меня есть карта. (не соответствует ситуации)", "У мене є картка. (не відповідає ситуації)", "I have a card. (doesn't match the situation)", False, "wrong_context"), + ("a2_bank_finance_l04_q3", "B", "Mam konto.", "У меня есть счёт. (не соответствует ситуации)", "У мене є рахунок. (не відповідає ситуації)", "I have an account. (doesn't match the situation)", False, "wrong_context"), + ("a2_bank_finance_l04_q3", "C", "Mam duże oszczędności.", "У меня большие сбережения.", "У мене великі заощадження.", "I have large savings.", True, None), + ("a2_bank_finance_l04_q3", "D", "Mam gotówkę.", "У меня есть наличные. (не соответствует ситуации)", "У мене є готівка. (не відповідає ситуації)", "I have cash. (doesn't match the situation)", False, "wrong_context"), + + # L05 + ("a2_bank_finance_l05_q1", "A", "Wypłacam", "я снимаю", "я знімаю", "I withdraw", True, None), + ("a2_bank_finance_l05_q1", "B", "Wypłacasz", "ты снимаешь (не тот человек)", "ти знімаєш (не та особа)", "you withdraw (wrong person)", False, "wrong_context"), + ("a2_bank_finance_l05_q1", "C", "Wypłaca", "он/она снимает (не тот человек)", "він/вона знімає (не та особа)", "he/she withdraws (wrong person)", False, "wrong_context"), + ("a2_bank_finance_l05_q1", "D", "Wypłacaliśmy", "мы снимали (неправильное число и время)", "ми знімали (неправильне число і час)", "we withdrew (wrong number and tense)", False, "wrong_number"), + + ("a2_bank_finance_l05_q3", "A", "Wypłacam pieniądze.", "Я снимаю деньги.", "Я знімаю гроші.", "I'm withdrawing money.", True, None), + ("a2_bank_finance_l05_q3", "B", "Płacę za zakupy.", "Я плачу за покупки. (неверный глагол)", "Я плачу за покупки. (невірне дієслово)", "I'm paying for shopping. (wrong verb)", False, "wrong_word"), + ("a2_bank_finance_l05_q3", "C", "Oszczędzam pieniądze.", "Я коплю деньги. (не соответствует ситуации)", "Я заощаджую гроші. (не відповідає ситуації)", "I'm saving money. (doesn't match the situation)", False, "wrong_context"), + ("a2_bank_finance_l05_q3", "D", "Mam pieniądze.", "У меня есть деньги. (не соответствует ситуации)", "У мене є гроші. (не відповідає ситуації)", "I have money. (doesn't match the situation)", False, "wrong_context"), + + # L06 + ("a2_bank_finance_l06_q1", "A", "na", "на", "на", "for", True, None), + ("a2_bank_finance_l06_q1", "B", "do", "в/к", "до", "to", False, "wrong_word"), + ("a2_bank_finance_l06_q1", "C", "z", "с/из", "з", "with/from", False, "wrong_word"), + ("a2_bank_finance_l06_q1", "D", "za", "за", "за", "for/behind", False, "wrong_word"), + + ("a2_bank_finance_l06_q3", "A", "Wypłacam pieniądze na dom.", "Я снимаю деньги на дом. (неверный глагол)", "Я знімаю гроші на будинок. (невірне дієслово)", "I'm withdrawing money for a house. (wrong verb)", False, "wrong_word"), + ("a2_bank_finance_l06_q3", "B", "Płacę za dom.", "Я плачу за дом. (не соответствует ситуации)", "Я плачу за будинок. (не відповідає ситуації)", "I'm paying for a house. (doesn't match the situation)", False, "wrong_context"), + ("a2_bank_finance_l06_q3", "C", "Oszczędzam na dom.", "Я коплю на дом.", "Я заощаджую на будинок.", "I'm saving up for a house.", True, None), + ("a2_bank_finance_l06_q3", "D", "Mam dom.", "У меня есть дом. (не соответствует ситуации)", "У мене є будинок. (не відповідає ситуації)", "I have a house. (doesn't match the situation)", False, "wrong_context"), + + # L07 + ("a2_bank_finance_l07_q1", "A", "drogi", "дорогой", "дорогий", "expensive", False, "wrong_word"), + ("a2_bank_finance_l07_q1", "B", "tani", "дешёвый", "дешевий", "cheap", False, "wrong_word"), + ("a2_bank_finance_l07_q1", "C", "bogaty", "богатый", "багатий", "rich", False, "wrong_word"), + ("a2_bank_finance_l07_q1", "D", "biedny", "бедный", "бідний", "poor", True, None), + + ("a2_bank_finance_l07_q3", "A", "Drogi.", "Дорогой.", "Дорогий.", "Expensive.", False, "wrong_context"), + ("a2_bank_finance_l07_q3", "B", "Tani.", "Дешёвый.", "Дешевий.", "Cheap.", True, None), + ("a2_bank_finance_l07_q3", "C", "Bogaty.", "Богатый.", "Багатий.", "Rich.", False, "wrong_context"), + ("a2_bank_finance_l07_q3", "D", "Biedny.", "Бедный.", "Бідний.", "Poor.", False, "wrong_context"), + + # L08 + ("a2_bank_finance_l08_q1", "A", "Muszę", "я должен", "я мушу", "I must", True, None), + ("a2_bank_finance_l08_q1", "B", "Musisz", "ты должен (не тот человек)", "ти мусиш (не та особа)", "you must (wrong person)", False, "wrong_context"), + ("a2_bank_finance_l08_q1", "C", "Musi", "он/она должен(на) (не тот человек)", "він/вона мусить (не та особа)", "he/she must (wrong person)", False, "wrong_context"), + ("a2_bank_finance_l08_q1", "D", "Musieli", "они были должны (неправильное число и время)", "вони мусили (неправильне число і час)", "they had to (wrong number and tense)", False, "wrong_number"), + + ("a2_bank_finance_l08_q3", "A", "Muszę zapłacić rachunek.", "Я должен оплатить счёт.", "Я мушу оплатити рахунок.", "I have to pay the bill.", True, None), + ("a2_bank_finance_l08_q3", "B", "Chcę zapłacić rachunek.", "Я хочу оплатить счёт. (о желании, не об обязанности)", "Я хочу оплатити рахунок. (про бажання, не про обов'язок)", "I want to pay the bill. (about wanting to, not obligation)", False, "wrong_context"), + ("a2_bank_finance_l08_q3", "C", "Lubię płacić rachunki.", "Мне нравится платить по счетам. (о симпатии, не об обязанности)", "Мені подобається платити рахунки. (про симпатію, не про обов'язок)", "I like paying bills. (about liking it, not obligation)", False, "wrong_context"), + ("a2_bank_finance_l08_q3", "D", "Wolę zapłacić rachunek.", "Я предпочитаю оплатить счёт. (о предпочтении, не об обязанности)", "Я віддаю перевагу оплаті рахунку. (про перевагу, не про обов'язок)", "I prefer to pay the bill. (about preference, not obligation)", False, "wrong_context"), + + # L09 + ("a2_bank_finance_l09_q1", "A", "Wpłacasz pieniądze na konto?", "Ты кладёшь деньги на счёт?", "Ти кладеш гроші на рахунок?", "Are you depositing money into the account?", False, "wrong_translation"), + ("a2_bank_finance_l09_q1", "B", "Wpłacisz pieniądze na konto?", "Ты положишь деньги на счёт?", "Ти покладеш гроші на рахунок?", "Will you deposit money into the account?", False, "wrong_translation"), + ("a2_bank_finance_l09_q1", "C", "Wpłaciłaś pieniądze na konto?", "Ты положила деньги на счёт?", "Ти поклала гроші на рахунок?", "Did you deposit money into the account?", False, "wrong_translation"), + ("a2_bank_finance_l09_q1", "D", "Wypłaciłaś pieniądze z konta?", "Ты сняла деньги со счёта?", "Ти зняла гроші з рахунку?", "Did you withdraw money from the account?", True, None), + + ("a2_bank_finance_l09_q3", "A", "Płacę za bilet.", "Я плачу за билет. (настоящее время)", "Я плачу за квиток. (теперішній час)", "I'm paying for the ticket. (present tense)", False, "wrong_sentence_type"), + ("a2_bank_finance_l09_q3", "B", "Zapłaciłem za bilet.", "Я заплатил за билет.", "Я заплатив за квиток.", "I paid for the ticket.", True, None), + ("a2_bank_finance_l09_q3", "C", "Zapłacę za bilet.", "Я заплачу за билет. (будущее время)", "Я заплачу за квиток. (майбутній час)", "I will pay for the ticket. (future tense)", False, "wrong_sentence_type"), + ("a2_bank_finance_l09_q3", "D", "Zapłaciłam za bilet.", "Неправильная форма рода (для мужчины).", "Неправильна форма роду (для чоловіка).", "Wrong gender form (for a man).", False, "wrong_gender"), + + # L10 + ("a2_bank_finance_l10_q1", "A", "Konto ja mam w banku.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_bank_finance_l10_q1", "B", "W banku konto mam.", "Неправильный порядок слов.", "Неправильний порядок слів.", "Wrong word order.", False, "wrong_sentence_type"), + ("a2_bank_finance_l10_q1", "C", "Mam ja konto w banku.", "Неправильная конструкция.", "Неправильна конструкція.", "Incorrect construction.", False, "wrong_sentence_type"), + ("a2_bank_finance_l10_q1", "D", "Mam konto w banku i płacę kartą za zakupy.", "У меня есть счёт в банке и я плачу картой за покупки.", "У мене є рахунок у банку і я плачу карткою за покупки.", "I have a bank account and I pay by card for shopping.", True, None), + + ("a2_bank_finance_l10_q3", "A", "Płacę kartą za zakupy.", "Я плачу картой за покупки. (не начало описания)", "Я плачу карткою за покупки. (не початок опису)", "I pay by card for shopping. (not the opening line)", False, "wrong_context"), + ("a2_bank_finance_l10_q3", "B", "Wczoraj zapłaciłem rachunek.", "Вчера я оплатил счёт. (не начало описания)", "Учора я оплатив рахунок. (не початок опису)", "Yesterday I paid the bill. (not the opening line)", False, "wrong_context"), + ("a2_bank_finance_l10_q3", "C", "Mam konto w banku.", "У меня есть счёт в банке.", "У мене є рахунок у банку.", "I have an account at the bank.", True, None), + ("a2_bank_finance_l10_q3", "D", "Oszczędzam pieniądze.", "Я коплю деньги. (не упоминалось)", "Я заощаджую гроші. (не згадувалося)", "I'm saving money. (not mentioned)", False, "wrong_context"), + ] + + for opt in options_t12_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) + + # 🔧 ИСПРАВЛЕНО: тестовые вопросы НЕ дублируют уроковые — другие формулировки, + # комбинируют скиллы, активнее используют production и application. + test_questions_t12_a2 = [ + # t01 — bank_vocabulary: контекст «зачем идти в банк», не перевод слова + ("a2_bank_finance_t01", None, "topic_test", "application", "bank_vocabulary", 1, + "Potrzebujesz otworzyć konto, bo pracodawca chce wysyłać ci wynagrodzenie przelewem. Dokąd idziesz?", + "Тебе нужно открыть счёт, потому что работодатель хочет перечислять зарплату переводом. Куда ты идёшь?", + "Тобі треба відкрити рахунок, бо роботодавець хоче надсилати тобі зарплату переказом. Куди ти йдеш?", + "You need to open an account because your employer wants to send your salary by transfer. Where do you go?", + "B", None, None, 1), + + # t02 — placic_za_biernik + контекст: как заплатить за билет + ("a2_bank_finance_t02", None, "topic_test", "application", "placic_za_biernik", 1, + "Jesteś w kasie na dworcu i chcesz zapłacić kartą za bilet. Jak to powiesz?", + "Ты в кассе на вокзале и хочешь оплатить билет картой. Как ты это скажешь?", + "Ти в касі на вокзалі і хочеш оплатити квиток карткою. Як ти це скажеш?", + "You're at the ticket counter at the station and want to pay for the ticket by card. How do you say it?", + "C", None, None, 2), + + # t03 — finanse_vocabulary: разница gotówka/przelew + ("a2_bank_finance_t03", None, "topic_test", "recognition", "finanse_vocabulary", 1, + "Kolega pyta, jak wolisz płacić — gotówką czy kartą. Jak nazywa się płatność fizycznymi pieniędzmi?", + "Друг спрашивает, как ты предпочитаешь платить — наличными или картой. Как называется оплата физическими деньгами?", + "Друг питає, як ти віддаєш перевагу платити — готівкою чи карткою. Як називається оплата фізичними грошима?", + "A friend asks how you prefer to pay — cash or card. What is payment with physical money called?", + "A", None, None, 3), + + # t04 — miec_biernik + грамматика: какой падеж у «konto» после «mieć» + ("a2_bank_finance_t04", None, "topic_test", "production", "miec_biernik", 1, + "Wpisz brakujące słowo: Mam ___ w banku. (счёт)", + "Вставьте пропущенное слово: Mam ___ w banku. (счёт)", + "Вставте пропущене слово: Mam ___ w banku. (рахунок)", + "Fill in the missing word: Mam ___ w banku. (account)", + "konto", "first_letter", "k", 4), + + # t05 — wyplacac_biernik + контекст: зачем идти к банкомату + ("a2_bank_finance_t05", None, "topic_test", "application", "wyplacac_biernik", 2, + "Potrzebujesz gotówki, ale masz tylko kartę. Co robisz w bankomacie?", + "Тебе нужны наличные, но у тебя только карта. Что ты делаешь в банкомате?", + "Тобі потрібна готівка, але в тебе лише картка. Що ти робиш у банкоматі?", + "You need cash, but you only have a card. What do you do at the ATM?", + "B", None, None, 5), + + # t06 — przeszly_czas_finanse + признание пола: женщина говорит + ("a2_bank_finance_t06", None, "topic_test", "production", "przeszly_czas_finanse", 3, + "Wpisz brakujące słowo (kobieta mówi): ___ za zakupy wczoraj. (я заплатила)", + "Вставьте пропущенное слово (говорит женщина): ___ za zakupy wczoraj. (я заплатила)", + "Вставте пропущене слово (говорить жінка): ___ za zakupy wczoraj. (я оплатила)", + "Fill in the missing word (a woman is speaking): ___ za zakupy wczoraj. (I paid)", + "Zapłaciłam", "first_letter", "Z", 6), + + # t07 — bank_vocabulary: синонимия «karta» в разных смыслах + ("a2_bank_finance_t07", None, "topic_test", "recognition", "bank_vocabulary", 1, + "Co dostajesz w banku, kiedy otwierasz konto i chcesz płacić bez gotówki?", + "Что ты получаешь в банке, когда открываешь счёт и хочешь платить без наличных?", + "Що ти отримуєш у банку, коли відкриваєш рахунок і хочеш платити без готівки?", + "What do you get at the bank when you open an account and want to pay without cash?", + "D", None, None, 7), + + # t08 — placic_za_biernik + отрицание: разница между «płacę za» и «nie płacę za» + ("a2_bank_finance_t08", None, "topic_test", "application", "placic_za_biernik", 1, + "Kolega proponuje, że zapłaci za twoją kawę. Chcesz powiedzieć, что сам заплатишь. Co powiesz?", + "Друг предлагает, что заплатит за твой кофе. Ты хочешь сказать, что сам заплатишь. Что ты скажешь?", + "Друг пропонує, що заплатить за твою каву. Ти хочеш сказати, що сам заплатиш. Що ти скажеш?", + "A friend offers to pay for your coffee. You want to say you'll pay yourself. What do you say?", + "A", None, None, 8), + + # t09 — finanse_vocabulary + контекст: что такое przelew + ("a2_bank_finance_t09", None, "topic_test", "application", "finanse_vocabulary", 1, + "Nie masz gotówki, ale chcesz przelać komuś pieniądze na konto. Jak nazywa się taka operacja?", + "У тебя нет наличных, но ты хочешь перевести кому-то деньги на счёт. Как называется такая операция?", + "У тебе немає готівки, але ти хочеш переказати комусь гроші на рахунок. Як називається така операція?", + "You don't have cash, but you want to send money to someone's account. What is this operation called?", + "C", None, None, 9), + + # t10 — oszczedzac_na_biernik + цель (на что копим) + ("a2_bank_finance_t10", None, "topic_test", "application", "oszczedzac_na_biernik", 2, + "Od roku odkładasz pieniądze na wakacje w Grecji. Jak to powiesz?", + "Уже год ты откладываешь деньги на отпуск в Греции. Как ты это скажешь?", + "Уже рік ти відкладаєш гроші на відпустку в Греції. Як ти це скажеш?", + "You've been setting money aside for a year for a vacation in Greece. How do you say it?", + "A", None, None, 10), + + # t11 — przymiotniki_finanse_vocabulary: антонимы + ("a2_bank_finance_t11", None, "topic_test", "recognition", "przymiotniki_finanse_vocabulary", 2, + "Kolega mówi, że nie stać go na wakacje i nie ma oszczędności. Jaki on jest?", + "Друг говорит, что не может позволить себе отпуск и у него нет сбережений. Какой он?", + "Друг каже, що не може дозволити собі відпустку і в нього немає заощаджень. Який він?", + "A friend says he can't afford a vacation and has no savings. What is he like?", + "D", None, None, 11), + + # t12 — musiec_placic + отрицание: «nie muszę» + ("a2_bank_finance_t12", None, "topic_test", "application", "musiec_placic", 2, + "Kolega myśli, że musisz zapłacić za jego bilet, ale to nieprawda. Jak zaprzeczysz?", + "Друг думает, что ты должен оплатить его билет, но это неправда. Как ты возразишь?", + "Друг думає, що ти мусиш оплатити його квиток, але це неправда. Як ти заперечиш?", + "A friend thinks you have to pay for his ticket, but that's not true. How do you deny it?", + "B", None, None, 12), + + # t13 — production: написать "наличные" + ("a2_bank_finance_t13", None, "topic_test", "production", "finanse_vocabulary", 1, + "Wpisz brakujące słowo: Zapłaciłem ___, nie kartą. (наличными)", + "Вставьте пропущенное слово: Zapłaciłem ___, nie kartą. (наличными)", + "Вставте пропущене слово: Zapłaciłem ___, nie kartą. (готівкою)", + "Fill in the missing word: Zapłaciłem ___, nie kartą. (cash)", + "gotówką", "first_letter", "g", 13), + + # t14 — production: написать "кредитную карту" + ("a2_bank_finance_t14", None, "topic_test", "production", "miec_biernik", 1, + "Wpisz brakujące słowo: Masz ___? (кредитную карту)", + "Вставьте пропущенное слово: Masz ___? (кредитную карту)", + "Вставте пропущене слово: Masz ___? (кредитну картку)", + "Fill in the missing word: Masz ___? (credit card)", + "kartę kredytową", "first_letter", "k", 14), + + # t15 — production: написать "снимаешь" (2 л. ед. ч.) + ("a2_bank_finance_t15", None, "topic_test", "production", "wyplacac_biernik", 2, + "Wpisz brakujące słowo: ___ pieniądze z bankomatu? (ты снимаешь)", + "Вставьте пропущенное слово: ___ pieniądze z bankomatu? (ты снимаешь)", + "Вставте пропущене слово: ___ pieniądze z bankomatu? (ти знімаєш)", + "Fill in the missing word: ___ pieniądze z bankomatu? (are you withdrawing)", + "Wypłacasz", "first_letter", "W", 15), + + # t16 — production: написать "копить" (инфинитив) + ("a2_bank_finance_t16", None, "topic_test", "production", "oszczedzac_na_biernik", 2, + "Wpisz brakujące słowo: Muszę ___ na nowy samochód. (копить)", + "Вставьте пропущенное слово: Muszę ___ na nowy samochód. (копить)", + "Вставте пропущене слово: Muszę ___ na nowy samochód. (заощаджувати)", + "Fill in the missing word: Muszę ___ na nowy samochód. (to save up)", + "oszczędzać", "first_letter", "o", 16), + + # t17 — production: перевести «я должен» + ("a2_bank_finance_t17", None, "topic_test", "production", "musiec_placic", 2, + "Wpisz brakujące słowo: ___ zapłacić ten rachunek. (я должен)", + "Вставьте пропущенное слово: ___ zapłacić ten rachunek. (я должен)", + "Вставте пропущене слово: ___ zapłacić ten рахунок. (я мушу)", + "Fill in the missing word: ___ zapłacić ten rachunek. (I have to)", + "Muszę", "first_letter", "M", 17), + + # t18 — production: перевести «вчера я оплатил счёт» + ("a2_bank_finance_t18", None, "topic_test", "production", "przeszly_czas_finanse", 3, + "Przetłumacz: «Вчера я оплатил счёт».", + "Переведите: «Вчера я оплатил счёт».", + "Перекладіть: «Учора я оплатив рахунок».", + "Translate: “Yesterday I paid the bill.”", + "Wczoraj zapłaciłem rachunek", "first_letter", "W", 18), + + # t19 — mixed: связка 3 скиллов, полное описание ситуации + ("a2_bank_finance_t19", None, "topic_test", "mixed", "opisuje_swoje_finanse", 3, + "Wybierz poprawne tłumaczenie: «У меня есть счёт в банке, я плачу картой, но иногда снимаю наличные в банкомате».", + "Выберите правильный перевод: «У меня есть счёт в банке, я плачу картой, но иногда снимаю наличные в банкомате».", + "Виберіть правильний переклад: «У мене є рахунок у банку, я плачу карткою, але іноді знімаю готівку в банкоматі».", + "Choose the correct translation: “I have a bank account, I pay by card, but sometimes I withdraw cash at the ATM.”", + "A", None, None, 19), + + # t20 — mixed: диалог в банке, скиллы bank_vocabulary + miec_biernik + ("a2_bank_finance_t20", None, "topic_test", "mixed", "bank_vocabulary", 3, + "Wybierz poprawne tłumaczenie диалога: «— Хочешь открыть счёт в банке? — Да, хочу, потому что мне нужно получать зарплату переводом.»", + "Выберите правильный перевод диалога: «— Хочешь открыть счёт в банке? — Да, хочу, потому что мне нужно получать зарплату переводом.»", + "Виберіть правильний переклад діалогу: «— Хочеш відкрити рахунок у банку? — Так, хочу, бо мені треба отримувати зарплату переказом.»", + "Choose the correct translation of the dialogue: “— Do you want to open a bank account? — Yes, I do, because I need to receive my salary by transfer.”", + "C", None, None, 20), + ] + + for q in test_questions_t12_a2: + await conn.execute(""" + INSERT INTO learning_questions (question_id, lesson_id, topic_id, context_type, question_type, skill_tag, difficulty, prompt_pl, prompt_ru, prompt_uk, prompt_en, correct_answer, hint_type, hint_value, is_test_question, test_order) + VALUES ($1, NULL, 'a2_bank_finance', $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, TRUE, $13) + ON CONFLICT (question_id) DO NOTHING + """, q[0], q[2], q[3], q[4], q[5], q[6], q[7], q[8], q[9], q[10], q[11], q[12], q[13]) + + test_options_t12_a2 = [ + # t01 — правильный B (Do banku) + ("a2_bank_finance_t01", "A", "Do sklepu.", "В магазин.", "До магазину.", "To the store.", False, "wrong_context"), + ("a2_bank_finance_t01", "B", "Do banku.", "В банк.", "До банку.", "To the bank.", True, None), + ("a2_bank_finance_t01", "C", "Do urzędu pocztowego.", "На почту.", "На пошту.", "To the post office.", False, "wrong_context"), + ("a2_bank_finance_t01", "D", "Do pracy.", "На работу.", "На роботу.", "To work.", False, "wrong_context"), + + # t02 — правильный C (Płacę za bilet kartą) + ("a2_bank_finance_t02", "A", "Kupuję kartę do banku.", "Покупаю карту в банк. (не о платеже)", "Купую картку до банку. (не про платіж)", "I'm buying a bank card. (not about payment)", False, "wrong_word"), + ("a2_bank_finance_t02", "B", "Mam bilet.", "У меня есть билет. (не о платеже)", "У мене є квиток. (не про платіж)", "I have a ticket. (not about payment)", False, "wrong_context"), + ("a2_bank_finance_t02", "C", "Płacę kartą za bilet.", "Я плачу картой за билет.", "Я плачу карткою за квиток.", "I'm paying by card for the ticket.", True, None), + ("a2_bank_finance_t02", "D", "Bilet jest w kasie.", "Билет в кассе. (не о платеже)", "Квиток у касі. (не про платіж)", "The ticket is at the counter. (not about payment)", False, "wrong_context"), + + # t03 — правильный A (gotówka) + ("a2_bank_finance_t03", "A", "gotówka", "наличные", "готівка", "cash", True, None), + ("a2_bank_finance_t03", "B", "przelew", "перевод", "переказ", "transfer", False, "wrong_word"), + ("a2_bank_finance_t03", "C", "karta", "карта", "картка", "card", False, "wrong_word"), + ("a2_bank_finance_t03", "D", "konto", "счёт", "рахунок", "account", False, "wrong_word"), + + # t04 — правильный "konto" (production, не из вариантов) + # Для production-вопроса options не нужны, но на всякий случай оставим одну опцию + ("a2_bank_finance_t04", "A", "konto", "счёт", "рахунок", "account", True, None), + + # t05 — правильный B (wypłacam gotówkę / wypłacasz gotówkę) + ("a2_bank_finance_t05", "A", "Płacę gotówką w bankomacie.", "Я плачу наличными в банкомате. (неверно, банкомат не принимает оплату)", "Я плачу готівкою в банкоматі. (невірно, банкомат не приймає оплату)", "I pay with cash at the ATM. (wrong — ATMs don't accept payments)", False, "wrong_context"), + ("a2_bank_finance_t05", "B", "Wypłacam gotówkę z bankomatu.", "Я снимаю наличные из банкомата.", "Я знімаю готівку з банкомату.", "I'm withdrawing cash from the ATM.", True, None), + ("a2_bank_finance_t05", "C", "Oszczędzam gotówkę w bankomacie.", "Я коплю наличные в банкомате. (бессмысленно)", "Я заощаджую готівку в банкоматі. (безглуздо)", "I save cash at the ATM. (nonsensical)", False, "wrong_word"), + ("a2_bank_finance_t05", "D", "Mam gotówkę w bankomacie.", "У меня есть наличные в банкомате. (неверный контекст)", "У мене є готівка в банкоматі. (невірний контекст)", "I have cash at the ATM. (wrong context)", False, "wrong_context"), + + # t06 — правильный "Zapłaciłam" (production, женская форма) + ("a2_bank_finance_t06", "A", "Zapłaciłam", "Я заплатила (ж.р.)", "Я оплатила (ж.р.)", "I paid (female)", True, None), + + # t07 — правильный D (karta) + ("a2_bank_finance_t07", "A", "banknot", "банкнота", "банкнота", "banknote", False, "wrong_word"), + ("a2_bank_finance_t07", "B", "moneta", "монета", "монета", "coin", False, "wrong_word"), + ("a2_bank_finance_t07", "C", "paragon", "чек", "чек", "receipt", False, "wrong_word"), + ("a2_bank_finance_t07", "D", "karta", "карта", "картка", "card", True, None), + + # t08 — правильный A (Płacę sam) + ("a2_bank_finance_t08", "A", "Dziękuję, ale sam zapłacę za siebie.", "Спасибо, но я сам за себя заплачу.", "Дякую, але я сам за себе заплачу.", "Thanks, but I'll pay for myself.", True, None), + ("a2_bank_finance_t08", "B", "Nie płacę za kawę.", "Я не плачу за кофе. (неверный смысл)", "Я не плачу за каву. (невірний зміст)", "I don't pay for coffee. (wrong meaning)", False, "wrong_translation"), + ("a2_bank_finance_t08", "C", "Nie mam pieniędzy.", "У меня нет денег. (неверный смысл)", "У мене немає грошей. (невірний зміст)", "I don't have money. (wrong meaning)", False, "wrong_context"), + ("a2_bank_finance_t08", "D", "Ty płacisz za mnie.", "Ты платишь за меня. (неверный смысл)", "Ти платиш за мене. (невірний зміст)", "You pay for me. (wrong meaning)", False, "wrong_translation"), + + # t09 — правильный C (przelew) + ("a2_bank_finance_t09", "A", "gotówka", "наличные", "готівка", "cash", False, "wrong_word"), + ("a2_bank_finance_t09", "B", "karta", "карта", "картка", "card", False, "wrong_word"), + ("a2_bank_finance_t09", "C", "przelew", "перевод", "переказ", "transfer", True, None), + ("a2_bank_finance_t09", "D", "rachunek", "счёт/чек", "рахунок/чек", "bill", False, "wrong_word"), + + # t10 — правильный A (Oszczędzam na wakacje) + ("a2_bank_finance_t10", "A", "Oszczędzam na wakacje w Grecji.", "Я коплю на отпуск в Греции.", "Я заощаджую на відпустку в Греції.", "I'm saving up for a vacation in Greece.", True, None), + ("a2_bank_finance_t10", "B", "Płacę za wakacje w Grecji.", "Я плачу за отпуск в Греции. (не о накоплении)", "Я плачу за відпустку в Греції. (не про накопичення)", "I'm paying for a vacation in Greece. (not about saving)", False, "wrong_context"), + ("a2_bank_finance_t10", "C", "Wypłacam na wakacje w Grecji.", "Я снимаю на отпуск в Греции. (неверный глагол)", "Я знімаю на відпустку в Греції. (невірне дієслово)", "I'm withdrawing for a vacation in Greece. (wrong verb)", False, "wrong_word"), + ("a2_bank_finance_t10", "D", "Mam wakacje w Grecji.", "У меня отпуск в Греции. (не о деньгах)", "У мене відпустка в Греції. (не про гроші)", "I have a vacation in Greece. (not about money)", False, "wrong_context"), + + # t11 — правильный D (biedny) + ("a2_bank_finance_t11", "A", "bogaty", "богатый", "багатий", "rich", False, "wrong_word"), + ("a2_bank_finance_t11", "B", "drogi", "дорогой", "дорогий", "expensive", False, "wrong_word"), + ("a2_bank_finance_t11", "C", "tani", "дешёвый", "дешевий", "cheap", False, "wrong_word"), + ("a2_bank_finance_t11", "D", "biedny", "бедный", "бідний", "poor", True, None), + + # t12 — правильный B (Nie muszę) + ("a2_bank_finance_t12", "A", "Muszę zapłacić za bilet.", "Я должен оплатить билет. (не отрицание)", "Я мушу оплатити квиток. (не заперечення)", "I have to pay for the ticket. (not a denial)", False, "wrong_translation"), + ("a2_bank_finance_t12", "B", "Nie muszę płacić za twój bilet.", "Я не должен платить за твой билет.", "Я не мушу платити за твій квиток.", "I don't have to pay for your ticket.", True, None), + ("a2_bank_finance_t12", "C", "Zapłacę za twój bilet.", "Я заплачу за твой билет. (не отрицание)", "Я заплачу за твій квиток. (не заперечення)", "I'll pay for your ticket. (not a denial)", False, "wrong_translation"), + ("a2_bank_finance_t12", "D", "Chcę zapłacić za twój bilet.", "Я хочу оплатить твой билет. (не отрицание)", "Я хочу оплатити твій квиток. (не заперечення)", "I want to pay for your ticket. (not a denial)", False, "wrong_translation"), + + # t13 — production + ("a2_bank_finance_t13", "A", "gotówką", "наличными", "готівкою", "in cash", True, None), + + # t14 — production + ("a2_bank_finance_t14", "A", "kartę kredytową", "кредитную карту", "кредитну картку", "credit card", True, None), + + # t15 — production + ("a2_bank_finance_t15", "A", "Wypłacasz", "ты снимаешь", "ти знімаєш", "you withdraw", True, None), + + # t16 — production + ("a2_bank_finance_t16", "A", "oszczędzać", "копить", "заощаджувати", "to save up", True, None), + + # t17 — production + ("a2_bank_finance_t17", "A", "Muszę", "я должен", "я мушу", "I have to", True, None), + + # t18 — production + ("a2_bank_finance_t18", "A", "Wczoraj zapłaciłem rachunek", "Вчера я оплатил счёт", "Учора я оплатив рахунок", "Yesterday I paid the bill", True, None), + + # t19 — правильный A + ("a2_bank_finance_t19", "A", "Mam konto w banku, płacę kartą, ale czasami wypłacam gotówkę z bankomatu.", "У меня есть счёт в банке, я плачу картой, но иногда снимаю наличные в банкомате.", "У мене є рахунок у банку, я плачу карткою, але іноді знімаю готівку в банкоматі.", "I have a bank account, I pay by card, but sometimes I withdraw cash at the ATM.", True, None), + ("a2_bank_finance_t19", "B", "Mam konto w banku, płacę gotówką, ale czasami wypłacam kartę z bankomatu.", "У меня есть счёт в банке, я плачу наличными, но иногда снимаю карту в банкомате. (смысл перевёрнут)", "У мене є рахунок у банку, я плачу готівкою, але іноді знімаю картку в банкоматі. (сенс перевернуто)", "I have a bank account, I pay in cash, but sometimes I withdraw the card from the ATM. (meaning reversed)", False, "wrong_translation"), + ("a2_bank_finance_t19", "C", "Mam kartę w banku, płacę kontem, ale czasami wypłacam gotówkę z karty.", "У меня есть карта в банке, я плачу счётом, но иногда снимаю наличные с карты. (неправильные термины)", "У мене є картка в банку, я плачу рахунком, але іноді знімаю готівку з картки. (неправильні терміни)", "I have a card at the bank, I pay with the account, but sometimes I withdraw cash from the card. (wrong terms)", False, "wrong_word"), + ("a2_bank_finance_t19", "D", "Mam konto w banku, płacę kartą, ale czasami oszczędzam gotówkę w bankomacie.", "У меня есть счёт в банке, я плачу картой, но иногда коплю наличные в банкомате. (бессмысленно)", "У мене є рахунок у банку, я плачу карткою, але іноді заощаджую готівку в банкоматі. (безглуздо)", "I have a bank account, I pay by card, but sometimes I save cash at the ATM. (nonsensical)", False, "wrong_word"), + + # t20 — правильный C + ("a2_bank_finance_t20", "A", "— Chcesz zamknąć konto w banku? — Tak, chcę, bo muszę płacić kartą.", "— Хочешь закрыть счёт в банке? — Да, хочу, потому что должен платить картой. (смысл перевёрнут)", "— Хочеш закрити рахунок у банку? — Так, хочу, бо мушу платити карткою. (сенс перевернуто)", "— Do you want to close your bank account? — Yes, I do, because I have to pay by card. (meaning reversed)", False, "wrong_translation"), + ("a2_bank_finance_t20", "B", "— Chcesz otworzyć konto w banku? — Nie, nie chcę, bo nie mam pieniędzy.", "— Хочешь открыть счёт в банке? — Нет, не хочу, потому что у меня нет денег. (противоположный смысл)", "— Хочеш відкрити рахунок у банку? — Ні, не хочу, бо не маю грошей. (протилежний зміст)", "— Do you want to open a bank account? — No, I don't, because I don't have money. (opposite meaning)", False, "wrong_context"), + ("a2_bank_finance_t20", "C", "— Chcesz otworzyć konto w banku? — Tak, chcę, bo muszę otrzymywać wynagrodzenie przelewem.", "— Хочешь открыть счёт в банке? — Да, хочу, потому что мне нужно получать зарплату переводом.", "— Хочеш відкрити рахунок у банку? — Так, хочу, бо мушу отримувати зарплату переказом.", "— Do you want to open a bank account? — Yes, I do, because I need to receive my salary by transfer.", True, None), + ("a2_bank_finance_t20", "D", "— Chcesz wypłacić konto w banku? — Tak, chcę, bo muszę otrzymywać wynagrodzenie przelewem.", "— Хочешь снять счёт в банке? — Да, хочу... (неправильный глагол)", "— Хочеш зняти рахунок у банку? — Так, хочу... (невірне дієслово)", "— Do you want to withdraw the account at the bank? — Yes, I do... (wrong verb)", False, "wrong_word"), + ] + + for opt in test_options_t12_a2: + await conn.execute(""" + INSERT INTO question_options (question_id, option_key, text_pl, text_ru, text_uk, text_en, is_correct, wrong_because) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + ON CONFLICT (question_id, option_key) DO NOTHING + """, opt[0], opt[1], opt[2], opt[3], opt[4], opt[5], opt[6], opt[7]) \ No newline at end of file diff --git a/routers/learning_data/level_b1.py b/routers/learning_data/level_b1.py new file mode 100644 index 0000000..91670e0 --- /dev/null +++ b/routers/learning_data/level_b1.py @@ -0,0 +1,3 @@ +async def init_level_b1(conn): + """Уровень B1 — пока пусто""" + pass \ No newline at end of file diff --git a/routers/learning_data/level_b2.py b/routers/learning_data/level_b2.py new file mode 100644 index 0000000..892d2ac --- /dev/null +++ b/routers/learning_data/level_b2.py @@ -0,0 +1,3 @@ +async def init_level_b2(conn): + """Уровень B2 — пока пусто""" + pass \ No newline at end of file diff --git a/routers/learning_data/level_c1.py b/routers/learning_data/level_c1.py new file mode 100644 index 0000000..36ee0cf --- /dev/null +++ b/routers/learning_data/level_c1.py @@ -0,0 +1,3 @@ +async def init_level_c1(conn): + """Уровень C1 — пока пусто""" + pass \ No newline at end of file diff --git a/routers/learning_data/level_c2.py b/routers/learning_data/level_c2.py new file mode 100644 index 0000000..998afbf --- /dev/null +++ b/routers/learning_data/level_c2.py @@ -0,0 +1,3 @@ +async def init_level_c2(conn): + """Уровень C2 — пока пусто""" + pass \ No newline at end of file diff --git a/routers/learning_profile.py b/routers/learning_profile.py new file mode 100644 index 0000000..e37c7b6 --- /dev/null +++ b/routers/learning_profile.py @@ -0,0 +1,56 @@ +""" +Единый профиль ученика — источник правды для аналитики и повторения. +Никакой LLM здесь нет — только детерминированная бизнес-логика. +""" +import hashlib +import json +from decimal import Decimal + + +async def get_weak_skills(conn, user_id: int, limit: int = 5): + """Получить слабые навыки (mastery < 75 или needs_review/overdue или repeated_error). + Одинаково используется в /analytics и /review.""" + rows = await conn.fetch(""" + SELECT skill_tag, mastery_score, repeated_error_count, + retention_status, trend, recent_accuracy, + recognition_score, production_score, application_score, + median_correct_time_ms, days_since_last_attempt + FROM user_skill_mastery + WHERE user_id = $1 AND attempts_count >= 2 + AND (mastery_score < 75 + OR retention_status IN ('needs_review', 'overdue') + OR repeated_error_count > 0) + ORDER BY mastery_score ASC + LIMIT $2 + """, user_id, limit) + + return [dict(r) for r in rows] + + +async def get_strong_skills(conn, user_id: int, limit: int = 8): + """Получить сильные навыки (mastery >= 75).""" + rows = await conn.fetch(""" + SELECT skill_tag, mastery_score FROM user_skill_mastery + WHERE user_id = $1 AND attempts_count >= 2 AND mastery_score >= 75 + ORDER BY mastery_score DESC + LIMIT $2 + """, user_id, limit) + + return [dict(r) for r in rows] + + +def get_profile_hash(weak_skills: list) -> str: + """Хэш списка слабых навыков — для инвалидации кэша.""" + # Конвертируем Decimal в float для JSON + serializable = [] + for s in weak_skills: + item = {} + for k, v in s.items(): + if isinstance(v, Decimal): + item[k] = float(v) + else: + item[k] = v + serializable.append(item) + + canonical = json.dumps(serializable, sort_keys=True, ensure_ascii=False) + return hashlib.sha256(canonical.encode()).hexdigest()[:16] \ No newline at end of file diff --git a/routers/orchestrator.py b/routers/orchestrator.py new file mode 100644 index 0000000..4f6a31c --- /dev/null +++ b/routers/orchestrator.py @@ -0,0 +1,286 @@ +""" +Orchestrator — мозг чат-учителя. +Выбирает следующий урок для пользователя на основе: +1. retention_status = 'overdue' или 'needs_review' → повторение +2. mastery_score < 75 → повторение слабого навыка +3. Иначе → следующий урок по порядку + +Никакого AI — только детерминированная логика. +""" +import logging +from typing import Optional, Dict, Any + +logger = logging.getLogger(__name__) + + +async def get_next_lesson(conn, user_id: int) -> Dict[str, Any]: + """ + Выбирает следующий урок для пользователя. + + Возвращает: + { + "type": "new" | "review" | "test", + "lesson": {...} | None, + "reason": str, + "skill_tag": str | None + } + """ + + # Получаем текущий уровень пользователя + current_level = await conn.fetchval(""" + SELECT current_level FROM users WHERE telegram_id = $1 + """, user_id) or "A1" + + # ============ ШАГ 1: Проверяем retention_status ============ + # Если есть навыки, которые давно не повторяли — повторяем их + overdue_skill = await conn.fetchrow(""" + SELECT skill_tag, mastery_score, days_since_last_attempt, retention_status + FROM user_skill_mastery + WHERE user_id = $1 + AND retention_status IN ('overdue', 'needs_review') + AND attempts_count >= 2 + ORDER BY days_since_last_attempt DESC + LIMIT 1 + """, user_id) + + if overdue_skill: + lesson = await conn.fetchrow(""" + SELECT l.lesson_id, l.topic_id, l.skill_tag, l.title_pl, l.title_ru, l.title_uk, l.title_en + FROM learning_lessons l + WHERE l.skill_tag = $1 + AND l.is_active = TRUE + ORDER BY l.order_number + LIMIT 1 + """, overdue_skill["skill_tag"]) + + if lesson: + logger.info(f"Orchestrator: review (overdue) for user={user_id}, skill={overdue_skill['skill_tag']}") + return { + "type": "review", + "lesson": dict(lesson), + "reason": "overdue", + "skill_tag": overdue_skill["skill_tag"], + } + + # ============ ШАГ 2: Проверяем mastery < 75 ============ + weak_skill = await conn.fetchrow(""" + SELECT skill_tag, mastery_score, repeated_error_count, trend + FROM user_skill_mastery + WHERE user_id = $1 + AND mastery_score < 75 + AND attempts_count >= 2 + ORDER BY mastery_score ASC + LIMIT 1 + """, user_id) + + if weak_skill: + lesson = await conn.fetchrow(""" + SELECT l.lesson_id, l.topic_id, l.skill_tag, l.title_pl, l.title_ru, l.title_uk, l.title_en + FROM learning_lessons l + WHERE l.skill_tag = $1 + AND l.is_active = TRUE + ORDER BY l.order_number + LIMIT 1 + """, weak_skill["skill_tag"]) + + if lesson: + logger.info(f"Orchestrator: review (weak) for user={user_id}, skill={weak_skill['skill_tag']}, mastery={weak_skill['mastery_score']}") + return { + "type": "review", + "lesson": dict(lesson), + "reason": "weak_mastery", + "skill_tag": weak_skill["skill_tag"], + } + + # ============ ШАГ 3: Проверяем, нужно ли пройти тест темы ============ + # Если пользователь завершил все уроки темы, но не прошёл тест + topic_for_test = await conn.fetchrow(""" + SELECT tp.topic_id, tp.lessons_total, tp.lessons_completed, tp.test_completed + FROM user_topic_progress tp + WHERE tp.user_id = $1 + AND tp.lessons_completed >= tp.lessons_total + AND tp.lessons_total > 0 + AND tp.test_completed = FALSE + ORDER BY tp.topic_id + LIMIT 1 + """, user_id) + + if topic_for_test: + logger.info(f"Orchestrator: test for user={user_id}, topic={topic_for_test['topic_id']}") + return { + "type": "test", + "lesson": None, + "reason": "topic_completed_no_test", + "topic_id": topic_for_test["topic_id"], + } + + # ============ ШАГ 4: Следующий урок по порядку ============ + # Находим первый непройденный урок в текущем уровне + next_lesson = await conn.fetchrow(""" + SELECT l.lesson_id, l.topic_id, l.skill_tag, l.title_pl, l.title_ru, l.title_uk, l.title_en, + t.topic_id as topic_id, t.order_number as topic_order + FROM learning_lessons l + JOIN learning_topics t ON l.topic_id = t.topic_id + WHERE t.level_code = $1 + AND l.is_active = TRUE + AND l.lesson_id NOT IN ( + SELECT lesson_id FROM user_lesson_progress + WHERE user_id = $2 AND completed = TRUE + ) + ORDER BY t.order_number, l.order_number + LIMIT 1 + """, current_level, user_id) + + if next_lesson: + logger.info(f"Orchestrator: new lesson for user={user_id}, lesson={next_lesson['lesson_id']}") + return { + "type": "new", + "lesson": dict(next_lesson), + "reason": "next_in_order", + "skill_tag": next_lesson["skill_tag"], + } + + # ============ ШАГ 5: Всё пройдено ============ + logger.info(f"Orchestrator: all completed for user={user_id}") + return { + "type": "completed", + "lesson": None, + "reason": "all_completed", + "skill_tag": None, + } + + +async def get_lesson_by_id(conn, lesson_id: str) -> Optional[Dict[str, Any]]: + """Получает урок по ID со всеми данными: объяснение, примеры, вопросы.""" + + lesson = await conn.fetchrow(""" + SELECT * FROM learning_lessons WHERE lesson_id = $1 AND is_active = TRUE + """, lesson_id) + + if not lesson: + return None + + examples = await conn.fetch(""" + SELECT * FROM lesson_examples WHERE lesson_id = $1 ORDER BY order_number + """, lesson_id) + + questions = await conn.fetch(""" + SELECT * FROM learning_questions + WHERE lesson_id = $1 AND is_test_question = FALSE + ORDER BY id + """, lesson_id) + + questions_data = [] + for q in questions: + options = await conn.fetch(""" + SELECT * FROM question_options WHERE question_id = $1 + """, q["question_id"]) + questions_data.append({ + "question": dict(q), + "options": [dict(o) for o in options], + }) + + return { + "lesson": dict(lesson), + "examples": [dict(e) for e in examples], + "questions": questions_data, + } + + +async def get_lesson_questions(conn, lesson_id: str) -> list: + """Получает только вопросы урока (без объяснения).""" + + questions = await conn.fetch(""" + SELECT * FROM learning_questions + WHERE lesson_id = $1 AND is_test_question = FALSE + ORDER BY id + """, lesson_id) + + questions_data = [] + for q in questions: + options = await conn.fetch(""" + SELECT * FROM question_options WHERE question_id = $1 + """, q["question_id"]) + questions_data.append({ + "question": dict(q), + "options": [dict(o) for o in options], + }) + + return questions_data + + +async def get_test_questions(conn, topic_id: str) -> list: + """Получает вопросы финального теста по теме.""" + + questions = await conn.fetch(""" + SELECT * FROM learning_questions + WHERE topic_id = $1 AND is_test_question = TRUE + ORDER BY test_order + """, topic_id) + + questions_data = [] + for q in questions: + options = await conn.fetch(""" + SELECT * FROM question_options WHERE question_id = $1 + """, q["question_id"]) + questions_data.append({ + "question": dict(q), + "options": [dict(o) for o in options], + }) + + return questions_data + + +async def get_random_reaction(conn, reaction_type: str, lang: str) -> str: + """Получает случайную реакцию из банка по типу.""" + + row = await conn.fetchrow(""" + SELECT text_pl, text_ru, text_uk, text_en + FROM teacher_reactions + WHERE reaction_type = $1 + ORDER BY RANDOM() + LIMIT 1 + """, reaction_type) + + if not row: + # Запасные реакции, если таблица пуста + fallbacks = { + "correct": { + "pl": "Świetnie!", + "ru": "Отлично!", + "uk": "Чудово!", + "en": "Great!" + }, + "almost": { + "pl": "Prawie!", + "ru": "Почти!", + "uk": "Майже!", + "en": "Almost!" + }, + "wrong": { + "pl": "Nie tym razem.", + "ru": "Не в этот раз.", + "uk": "Не цього разу.", + "en": "Not this time." + }, + } + return fallbacks.get(reaction_type, {}).get(lang, "OK") + + field = f"text_{lang}" + return row.get(field) or row.get("text_en") or "OK" + + +async def get_wrong_because_explanation(conn, wrong_because: str, lang: str) -> str: + """Получает объяснение ошибки по тегу wrong_because.""" + + row = await conn.fetchrow(""" + SELECT explanation_pl, explanation_ru, explanation_uk, explanation_en + FROM wrong_because_explanations + WHERE wrong_because = $1 + """, wrong_because) + + if not row: + return "" + + field = f"explanation_{lang}" + return row.get(field) or row.get("explanation_en") or "" \ No newline at end of file diff --git a/routers/pronunciation.py b/routers/pronunciation.py new file mode 100644 index 0000000..729d632 --- /dev/null +++ b/routers/pronunciation.py @@ -0,0 +1,46 @@ +import random +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool + +router = APIRouter(prefix="/pronunciation", tags=["pronunciation"]) + + +@router.get("/next") +async def get_next_word(request: Request): + """Выдаёт случайное слово из всех уровней для раздела Произношение.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT app_language FROM users WHERE telegram_id = $1", telegram_id + ) + if not user: + raise HTTPException(401, "User not registered") + + lang = user["app_language"] or "pl" + + # Берём случайное слово из всех уровней (без привязки к конкретному уровню) + word = await conn.fetchrow(""" + SELECT word_pl, translation_ru, translation_uk, translation_en, level + FROM ( + SELECT DISTINCT ON (word_pl) word_pl, translation_ru, translation_uk, translation_en, level + FROM level_words + WHERE level_id IS NULL + ) AS unique_words + ORDER BY RANDOM() + LIMIT 1 + """) + + if not word: + raise HTTPException(404, "No words found") + + translation_field = f"translation_{lang}" + translation = word.get(translation_field) or word.get("translation_en") or word["word_pl"] + + return { + "word_pl": word["word_pl"], + "translation": translation, + "level": word["level"] or "A1", + } \ No newline at end of file diff --git a/routers/sentences.py b/routers/sentences.py new file mode 100644 index 0000000..c2b7a35 --- /dev/null +++ b/routers/sentences.py @@ -0,0 +1,290 @@ +import csv +import random +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool + +router = APIRouter(prefix="/sentences", tags=["sentences"]) + + +@router.get("/{sentence_id}/hint") +async def get_sentence_hint(sentence_id: int, request: Request): + """Получить правильное предложение в качестве подсказки (одноразово)""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + row = await conn.fetchrow( + "SELECT sentence_pl FROM sentences WHERE id = $1", sentence_id + ) + if not row: + raise HTTPException(404, "Sentence not found") + + return { + "sentence_pl": row["sentence_pl"], + } + + +def load_sentences_from_csv(filename): + """Загружает предложения из CSV файла (формат: polish,english,russian,ukrainian).""" + sentences = [] + with open(filename, 'r', encoding='utf-8') as f: + reader = csv.DictReader(f) + for row in reader: + sentences.append({ + "sentence_pl": row["polish"].strip(), + "translation_ru": row.get("russian", ""), + "translation_uk": row.get("ukrainian", ""), + "translation_en": row.get("english", ""), + }) + return sentences + + +async def init_sentences(): + """Инициализирует таблицу предложений из CSV файлов по уровням.""" + pool = await get_pool() + async with pool.acquire() as conn: + level_files = [ + ("A1", "sentences_a1.csv"), + ("A2", "sentences_a2.csv"), + ("B1", "sentences_b1.csv"), + ] + + for level, filename in level_files: + sentences = load_sentences_from_csv(filename) + for i, s in enumerate(sentences): + words_count = len(s["sentence_pl"].split()) + difficulty = 1 if words_count <= 4 else 2 if words_count <= 6 else 3 + + await conn.execute( + """INSERT INTO sentences (sentence_number, sentence_pl, translation_ru, translation_uk, translation_en, difficulty, level) + VALUES ($1, $2, $3, $4, $5, $6, $7) + ON CONFLICT (level, sentence_number) DO NOTHING""", + i + 1, s["sentence_pl"], + s["translation_ru"], s["translation_uk"], s["translation_en"], + difficulty, level + ) + + +def normalize_word_for_display(word: str) -> str: + """Убирает знаки конца предложения и приводит к нижнему регистру. + Запятые, точки с запятой, двоеточия и кавычки ОСТАЮТСЯ — игрок должен их видеть.""" + return word.strip('.!?…').lower() + + +def normalize_word_for_check(word: str) -> str: + """Убирает ВСЮ пунктуацию для сравнения — игрок не обязан расставлять запятые.""" + return word.strip('.,!?;:()[]{}"\'-…').lower() + + +@router.get("/next") +async def get_next_sentence(request: Request): + """Получить следующее непройденное предложение для выбранного уровня""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT app_language, current_level FROM users WHERE telegram_id = $1", telegram_id + ) + if not user: + raise HTTPException(401, "User not registered") + + lang = user["app_language"] or "pl" + current_level = user["current_level"] or "A1" + + # Находим случайное непройденное предложение нужного уровня + row = await conn.fetchrow(""" + SELECT s.* FROM sentences s + WHERE s.level = $1 + AND s.id NOT IN ( + SELECT sentence_id FROM sentence_progress WHERE user_id = $2 + ) + ORDER BY RANDOM() + LIMIT 1 + """, current_level, telegram_id) + + if not row: + return {"completed": True, "message": "All sentences completed!"} + + # Оригинальные слова (для проверки) + correct_words = row["sentence_pl"].split() + + # Слова для ОТОБРАЖЕНИЯ — запятые остаются, убираем только точки/воскл/вопрос + display_words = [normalize_word_for_display(w) for w in correct_words] + shuffled_words = display_words.copy() + random.shuffle(shuffled_words) + + translation_field = f"translation_{lang}" + translation = row.get(translation_field, "") or row.get("translation_en", "") + + return { + "id": row["id"], + "sentence_number": row["sentence_number"], + "words": shuffled_words, + "correct_words": display_words, + "translation": translation, + "difficulty": row["difficulty"], + "level": row["level"], + } + + +@router.post("/check") +async def check_sentence(request: Request): + """Проверка предложения с защитой от повторного прохождения и выдачей достижений""" + telegram_id, _ = await require_auth(request) + body = await request.json() + sentence_id = body.get("sentence_id") + user_words = body.get("words", []) + completion_time = body.get("completion_time") + + if not sentence_id or not user_words: + raise HTTPException(400, "sentence_id and words required") + + if len(user_words) > 20: + raise HTTPException(400, "Too many words") + + pool = await get_pool() + async with pool.acquire() as conn: + user_exists = await conn.fetchval( + "SELECT 1 FROM users WHERE telegram_id = $1", telegram_id + ) + if not user_exists: + raise HTTPException(401, "User not registered") + + row = await conn.fetchrow( + "SELECT id, sentence_pl, level FROM sentences WHERE id = $1", sentence_id + ) + if not row: + raise HTTPException(404, "Sentence not found") + + existing_progress = await conn.fetchrow( + "SELECT score, completed_at FROM sentence_progress WHERE user_id = $1 AND sentence_id = $2", + telegram_id, sentence_id + ) + + if existing_progress: + return { + "correct": True, + "correct_words": [normalize_word_for_display(w) for w in row["sentence_pl"].split()], + "already_completed": True, + "score": existing_progress["score"], + "completed_at": existing_progress["completed_at"].isoformat() if existing_progress["completed_at"] else None, + "new_achievements": [] + } + + # Защита от читерства: минимальное время 3 секунды + if completion_time is not None and completion_time < 3: + return { + "correct": False, + "correct_words": [normalize_word_for_display(w) for w in row["sentence_pl"].split()], + "already_completed": False, + "new_achievements": [], + "error": "Too fast. Please take your time." + } + + # Нормализуем для СРАВНЕНИЯ — без запятых и прочей пунктуации + correct_words_original = row["sentence_pl"].split() + correct_words_normalized = [normalize_word_for_check(w) for w in correct_words_original] + user_words_normalized = [normalize_word_for_check(w) for w in user_words] + + is_correct = user_words_normalized == correct_words_normalized + + if is_correct: + word_count = len(correct_words_original) + if word_count <= 4: + score = 50 + elif word_count <= 6: + score = 75 + else: + score = 100 + + await conn.execute( + """INSERT INTO sentence_progress (user_id, sentence_id, completed_at, score, level) + VALUES ($1, $2, NOW(), $3, $4)""", + telegram_id, sentence_id, score, row["level"], + ) + + from routers.achievements import check_and_award_achievements + new_achievements = [] + + sentences_completed = await conn.fetchval( + "SELECT COUNT(*) FROM sentence_progress WHERE user_id = $1", + telegram_id + ) + ach = await check_and_award_achievements(telegram_id, "sentences_completed", sentences_completed) + new_achievements.extend(ach) + + if completion_time is not None and completion_time > 0: + ach = await check_and_award_achievements(telegram_id, "speed_sentence", int(completion_time)) + new_achievements.extend(ach) + + # Общий счёт по ВСЕМ играм + wordsearch_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM user_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + sentence_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM sentence_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + wordquiz_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + bubblewords_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) or 0 + grand_total = wordsearch_score + sentence_score + wordquiz_score + bubblewords_score + ach = await check_and_award_achievements(telegram_id, "total_score", grand_total) + new_achievements.extend(ach) + + return { + "correct": True, + "correct_words": [normalize_word_for_display(w) for w in correct_words_original], + "already_completed": False, + "score": score, + "new_achievements": new_achievements + } + + return { + "correct": False, + "correct_words": [normalize_word_for_display(w) for w in correct_words_original], + "already_completed": False, + "new_achievements": [] + } + + +@router.get("/stats") +async def get_sentence_stats(request: Request): + """Статистика по предложениям для выбранного уровня""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT current_level FROM users WHERE telegram_id = $1", telegram_id + ) + current_level = user["current_level"] if user else "A1" + + total = await conn.fetchval( + "SELECT COUNT(*) FROM sentences WHERE level = $1", current_level + ) + completed = await conn.fetchval( + "SELECT COUNT(*) FROM sentence_progress WHERE user_id = $1 AND level = $2", + telegram_id, current_level + ) + total_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM sentence_progress WHERE user_id = $1 AND level = $2", + telegram_id, current_level + ) + + return { + "total_sentences": total, + "completed": completed or 0, + "remaining": total - (completed or 0), + "total_score": total_score or 0, + "progress_percent": round(((completed or 0) / total * 100), 1) if total > 0 else 0, + "level": current_level, + } \ No newline at end of file diff --git a/routers/support.py b/routers/support.py new file mode 100644 index 0000000..a7d7a9d --- /dev/null +++ b/routers/support.py @@ -0,0 +1,359 @@ +""" +Support Router — система поддержки пользователей. +Пользователи пишут админу о багах, неточностях и предложениях. +Админ отвечает. Обе стороны могут переводить сообщения через AI (MiniMax-M3). +""" +import logging +import httpx +import re +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool +from config import TOGETHER_API_KEY, ADMIN_IDS + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/support", tags=["support"]) + +TOGETHER_API_URL = "https://api.together.xyz/v1/chat/completions" +SUPPORT_MODEL = "MiniMaxAI/MiniMax-M3" + + +async def call_ai_translate(text: str, target_lang: str) -> str: + """Переводит текст через AI (MiniMax-M3).""" + if not TOGETHER_API_KEY: + return "" + + try: + async with httpx.AsyncClient(timeout=90.0) as client: + response = await client.post( + TOGETHER_API_URL, + headers={ + "Authorization": f"Bearer {TOGETHER_API_KEY}", + "Content-Type": "application/json", + }, + json={ + "model": SUPPORT_MODEL, + "messages": [ + {"role": "system", "content": f"Ты — переводчик. Переведи текст на язык: {target_lang}. Отвечай только переводом без пояснений. Не используй markdown."}, + {"role": "user", "content": text}, + ], + "max_tokens": 500, + "temperature": 0.3, + }, + ) + + if response.status_code != 200: + logger.error(f"Translate API error: {response.status_code}") + return "" + + data = response.json() + translated = data["choices"][0]["message"]["content"].strip() + translated = re.sub(r'\s*\([a-z_]+_[a-z_]+\)', '', translated) + return translated + except Exception as e: + logger.error(f"Translate error: {str(e)}") + return "" + + +async def get_user_lang(conn, user_id: int) -> str: + """Получает язык интерфейса пользователя.""" + lang = await conn.fetchval(""" + SELECT app_language FROM users WHERE telegram_id = $1 + """, user_id) + return lang if lang in ["pl", "ru", "uk", "en"] else "pl" + + +@router.post("/send") +async def send_support_message(request: Request): + """ + Пользователь отправляет сообщение в поддержку. + Если у пользователя нет открытого тикета — создаётся новый. + """ + telegram_id, _ = await require_auth(request) + body = await request.json() + message = body.get("message", "").strip() + + if not message: + raise HTTPException(400, "message is required") + + if len(message) > 1000: + raise HTTPException(400, "Message too long (max 1000 characters)") + + pool = await get_pool() + async with pool.acquire() as conn: + # Ищем открытый тикет пользователя + ticket = await conn.fetchrow(""" + SELECT id FROM support_tickets + WHERE user_id = $1 AND status = 'open' + ORDER BY id DESC + LIMIT 1 + """, telegram_id) + + ticket_id = None + + if ticket: + ticket_id = ticket["id"] + # Обновляем updated_at + await conn.execute(""" + UPDATE support_tickets SET updated_at = NOW() WHERE id = $1 + """, ticket_id) + else: + # Создаём новый тикет + new_ticket = await conn.fetchrow(""" + INSERT INTO support_tickets (user_id, status) + VALUES ($1, 'open') RETURNING id + """, telegram_id) + ticket_id = new_ticket["id"] + + # Сохраняем сообщение (юзер написал — админ ещё не прочитал) + await conn.execute(""" + INSERT INTO support_messages (ticket_id, sender_id, message, is_read) + VALUES ($1, $2, $3, FALSE) + """, ticket_id, telegram_id, message) + + return {"status": "ok", "ticket_id": ticket_id} + + +@router.get("/user-tickets") +async def get_user_tickets(request: Request): + """Пользователь получает список своих тикетов.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + tickets = await conn.fetch(""" + SELECT id, status, created_at, updated_at + FROM support_tickets + WHERE user_id = $1 + ORDER BY updated_at DESC + """, telegram_id) + + return {"tickets": [dict(t) for t in tickets]} + + +@router.get("/user-messages/{ticket_id}") +async def get_user_messages(request: Request, ticket_id: int): + """Пользователь получает сообщения своего тикета и отмечает ответы админа прочитанными.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + # Проверяем, что тикет принадлежит пользователю + ticket = await conn.fetchrow(""" + SELECT id FROM support_tickets WHERE id = $1 AND user_id = $2 + """, ticket_id, telegram_id) + + if not ticket: + raise HTTPException(404, "Ticket not found") + + # Отмечаем сообщения админа как прочитанные + await conn.execute(""" + UPDATE support_messages SET is_read = TRUE + WHERE ticket_id = $1 AND sender_id != $2 + """, ticket_id, telegram_id) + + messages = await conn.fetch(""" + SELECT id, sender_id, message, is_read, created_at + FROM support_messages + WHERE ticket_id = $1 + ORDER BY id ASC + """, ticket_id) + + return {"messages": [dict(m) for m in messages]} + + +@router.get("/user-unread-count") +async def get_user_unread_count(request: Request): + """Пользователь получает количество непрочитанных ответов админа.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + count = await conn.fetchval(""" + SELECT COUNT(*) FROM support_messages m + JOIN support_tickets t ON m.ticket_id = t.id + WHERE t.user_id = $1 + AND m.is_read = FALSE + AND m.sender_id != $1 + """, telegram_id) + + return {"unread_count": count or 0} + + +@router.post("/delete-ticket/{ticket_id}") +async def delete_ticket(request: Request, ticket_id: int): + """ + Удаляет тикет. + Может удалить: сам пользователь (свой тикет) или админ (любой). + """ + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + # Проверяем права + if telegram_id in ADMIN_IDS: + # Админ может удалить любой + result = await conn.execute("DELETE FROM support_tickets WHERE id = $1", ticket_id) + else: + # Пользователь может удалить только свой + result = await conn.execute(""" + DELETE FROM support_tickets WHERE id = $1 AND user_id = $2 + """, ticket_id, telegram_id) + + affected = int(result.split()[-1]) + if affected == 0: + raise HTTPException(404, "Ticket not found or no permission") + + return {"status": "ok"} + + +# ============ АДМИНСКИЕ ЭНДПОИНТЫ ============ + +@router.get("/admin-tickets") +async def get_admin_tickets(request: Request): + """Админ получает список всех тикетов.""" + telegram_id, _ = await require_auth(request) + + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + pool = await get_pool() + async with pool.acquire() as conn: + tickets = await conn.fetch(""" + SELECT + t.id, + t.user_id, + t.status, + t.created_at, + t.updated_at, + u.username, + u.app_language, + (SELECT COUNT(*) FROM support_messages m WHERE m.ticket_id = t.id AND m.is_read = FALSE) as unread_count, + (SELECT message FROM support_messages m WHERE m.ticket_id = t.id ORDER BY m.id DESC LIMIT 1) as last_message + FROM support_tickets t + LEFT JOIN users u ON t.user_id = u.telegram_id + ORDER BY t.updated_at DESC + """) + + return {"tickets": [dict(t) for t in tickets]} + + +@router.get("/admin-messages/{ticket_id}") +async def get_admin_messages(request: Request, ticket_id: int): + """Админ получает сообщения тикета и отмечает их как прочитанные.""" + telegram_id, _ = await require_auth(request) + + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + pool = await get_pool() + async with pool.acquire() as conn: + ticket = await conn.fetchrow(""" + SELECT id FROM support_tickets WHERE id = $1 + """, ticket_id) + + if not ticket: + raise HTTPException(404, "Ticket not found") + + # Отмечаем сообщения пользователя как прочитанные + await conn.execute(""" + UPDATE support_messages SET is_read = TRUE + WHERE ticket_id = $1 AND sender_id != $2 + """, ticket_id, telegram_id) + + messages = await conn.fetch(""" + SELECT id, sender_id, message, is_read, created_at + FROM support_messages + WHERE ticket_id = $1 + ORDER BY id ASC + """, ticket_id) + + return {"messages": [dict(m) for m in messages]} + + +@router.post("/admin-reply") +async def admin_reply(request: Request): + """Админ отвечает пользователю.""" + telegram_id, _ = await require_auth(request) + + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + body = await request.json() + ticket_id = body.get("ticket_id") + message = body.get("message", "").strip() + + if not ticket_id or not message: + raise HTTPException(400, "ticket_id and message required") + + if len(message) > 1000: + raise HTTPException(400, "Message too long (max 1000 characters)") + + pool = await get_pool() + async with pool.acquire() as conn: + ticket = await conn.fetchrow(""" + SELECT id FROM support_tickets WHERE id = $1 + """, ticket_id) + + if not ticket: + raise HTTPException(404, "Ticket not found") + + # 🔧 ИСПРАВЛЕНО: админ написал — юзер ЕЩЁ НЕ ПРОЧИТАЛ, поэтому is_read = FALSE + # Раньше было TRUE, из-за чего бейдж непрочитанных у пользователя не появлялся + await conn.execute(""" + INSERT INTO support_messages (ticket_id, sender_id, message, is_read) + VALUES ($1, $2, $3, FALSE) + """, ticket_id, telegram_id, message) + + await conn.execute(""" + UPDATE support_tickets SET updated_at = NOW() WHERE id = $1 + """, ticket_id) + + return {"status": "ok"} + + +@router.get("/unread-count") +async def get_unread_count(request: Request): + """Админ получает количество непрочитанных сообщений.""" + telegram_id, _ = await require_auth(request) + + if telegram_id not in ADMIN_IDS: + raise HTTPException(403, "Access denied") + + pool = await get_pool() + async with pool.acquire() as conn: + count = await conn.fetchval(""" + SELECT COUNT(*) FROM support_messages + WHERE is_read = FALSE AND sender_id != $1 + """, telegram_id) + + return {"unread_count": count or 0} + + +@router.post("/translate") +async def translate_message(request: Request): + """ + Перевод сообщения через AI (MiniMax-M3). + Доступно и пользователю, и админу. + """ + telegram_id, _ = await require_auth(request) + body = await request.json() + text = body.get("text", "").strip() + target_lang = body.get("target_lang", "ru") + + if not text: + raise HTTPException(400, "text is required") + + if len(text) > 1000: + raise HTTPException(400, "Text too long (max 1000 characters)") + + if target_lang not in ["pl", "ru", "uk", "en"]: + target_lang = "ru" + + translated = await call_ai_translate(text, target_lang) + + if not translated: + raise HTTPException(500, "Translation failed") + + return {"translation": translated} \ No newline at end of file diff --git a/routers/teacher.py b/routers/teacher.py new file mode 100644 index 0000000..3510f63 --- /dev/null +++ b/routers/teacher.py @@ -0,0 +1,1164 @@ +""" +Teacher Router — гибридный чат-учитель. +Контент из БД (бесплатно), AI только для реакций и пробелов. + +Типы сообщений: +1. Объяснение — из learning_lessons +2. Вопрос recognition — кнопки A/B/C/D +3. Вопрос production — поле ввода +4. Реакция — шаблон + wrong_because_explanations (без AI) +5. AI-сообщение — только по явному триггеру + +Слэш-команды: +- /start — начать урок +- /resume — восстановить сессию +- /answer — проверить ответ +- /explain — AI-объяснение +- /examples — 5 примеров по теме (после теста темы) +- /free-message — свободное сообщение +- /diagnostic-test — тест на определение уровня +- /translate-to-polish — перевод на польский +""" +import logging +import json +import httpx +import re +import unicodedata +from datetime import datetime, timezone +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool +from config import TOGETHER_API_KEY, ADMIN_IDS +from .orchestrator import ( + get_next_lesson, + get_lesson_by_id, + get_lesson_questions, + get_test_questions, + get_random_reaction, + get_wrong_because_explanation, +) + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/teacher", tags=["teacher"]) + +TOGETHER_API_URL = "https://api.together.xyz/v1/chat/completions" +TEACHER_MODEL = "MiniMaxAI/MiniMax-M3" + +TEACHER_AI_DAILY_LIMIT = 5 + + +def get_ai_limit_message(lang: str) -> str: + """Возвращает локализованное сообщение о исчерпании AI-лимита.""" + messages = { + "pl": "Dziś wykorzystałeś już limit AI-pomocy. Wróć jutro!", + "ru": "Сегодня ты использовал лимит AI-помощи. Возвращайся завтра!", + "uk": "Сьогодні ти використав ліміт AI-допомоги. Повертайся завтра!", + "en": "You've used your AI help limit today. Come back tomorrow!", + } + return messages.get(lang, messages["en"]) + + +def normalize_answer(text: str) -> str: + """Нормализует ответ: нижний регистр, убирает диакритику и пунктуацию.""" + if not text: + return "" + text = text.strip().lower() + text = re.sub(r'[.,!?;:()\[\]{}"\'\-—–…]', '', text) + text = unicodedata.normalize('NFKD', text) + text = ''.join(c for c in text if not unicodedata.combining(c)) + text = ' '.join(text.split()) + return text + + +async def get_user_lang(conn, user_id: int) -> str: + """Получает язык интерфейса пользователя.""" + lang = await conn.fetchval(""" + SELECT app_language FROM users WHERE telegram_id = $1 + """, user_id) + return lang if lang in ["pl", "ru", "uk", "en"] else "pl" + + +async def get_teacher_ai_usage(conn, user_id: int) -> int: + """Получает количество AI-команд учителя за сегодня.""" + count = await conn.fetchval(""" + SELECT COUNT(*) FROM teacher_ai_usage + WHERE user_id = $1 AND usage_date = CURRENT_DATE + """, user_id) + return count or 0 + + +async def increment_teacher_ai_usage(conn, user_id: int) -> None: + """Увеличивает счётчик AI-команд учителя за сегодня.""" + await conn.execute(""" + INSERT INTO teacher_ai_usage (user_id, usage_date, command_count) + VALUES ($1, CURRENT_DATE, 1) + ON CONFLICT (user_id, usage_date) + DO UPDATE SET command_count = teacher_ai_usage.command_count + 1 + """, user_id) + + +async def check_ai_limit(conn, user_id: int) -> bool: + """Проверяет, может ли пользователь использовать AI-команду.""" + if user_id in ADMIN_IDS: + return True + usage = await get_teacher_ai_usage(conn, user_id) + return usage < TEACHER_AI_DAILY_LIMIT + + +async def start_learning_session(conn, user_id: int, level_code: str, topic_id: str, session_type: str) -> int: + """Создаёт сессию обучения и возвращает session_id.""" + row = await conn.fetchrow(""" + INSERT INTO learning_sessions (user_id, level_code, topic_id, session_type) + VALUES ($1, $2, $3, $4) RETURNING id + """, user_id, level_code, topic_id, session_type) + return row["id"] + + +async def save_answer_to_session(conn, user_id: int, session_id: int, question_data: dict, selected_answer: str, correct: bool, time_taken_ms: int = 0, hint_used: bool = False) -> None: + """Сохраняет ответ в user_learning_answers.""" + q = question_data["question"] + + wrong_because = None + if not correct: + for opt in question_data.get("options", []): + if opt.get("option_key") == selected_answer and opt.get("wrong_because"): + wrong_because = opt["wrong_because"] + break + + await conn.execute(""" + INSERT INTO user_learning_answers ( + user_id, session_id, level_code, topic_id, lesson_id, + question_id, selected_answer, correct, skill_tag, + question_type, context_type, difficulty, time_taken_ms, + hint_used, wrong_because, is_final_answer + ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, TRUE) + """, + user_id, session_id, q.get("level_code", "A1"), q.get("topic_id", ""), q.get("lesson_id"), + q["question_id"], selected_answer, correct, q["skill_tag"], + q["question_type"], q["context_type"], q["difficulty"], time_taken_ms, + hint_used, wrong_because) + + +async def update_mastery_after_lesson(conn, user_id: int, session_id: int) -> None: + """Обновляет mastery и прогресс урока после завершения.""" + from .learning import update_skill_mastery, update_topic_progress, update_ai_context + + skill_tags = await conn.fetch(""" + SELECT DISTINCT skill_tag FROM user_learning_answers WHERE session_id = $1 + """, session_id) + + for st in skill_tags: + await update_skill_mastery(conn, user_id, st["skill_tag"]) + + session = await conn.fetchrow("SELECT * FROM learning_sessions WHERE id = $1", session_id) + + if session and session["session_type"] == "teacher_lesson": + lesson_row = await conn.fetchrow(""" + SELECT DISTINCT lesson_id FROM user_learning_answers + WHERE session_id = $1 AND lesson_id IS NOT NULL + """, session_id) + + if lesson_row and lesson_row["lesson_id"]: + lesson_id = lesson_row["lesson_id"] + + stats = await conn.fetchrow(""" + SELECT COUNT(*) as total, + COALESCE(SUM(CASE WHEN correct THEN 1 ELSE 0 END), 0) as correct_count + FROM user_learning_answers + WHERE session_id = $1 AND is_final_answer = TRUE + """, session_id) + + total = stats["total"] if stats["total"] else 0 + correct_count = stats["correct_count"] if stats["correct_count"] else 0 + score = round((correct_count / total * 100), 2) if total > 0 else 0 + + await conn.execute(""" + INSERT INTO user_lesson_progress (user_id, lesson_id, started_at, completed_at, attempts_count, correct_count, best_score, completed) + VALUES ($1, $2, NOW(), NOW(), 1, $3, $4, TRUE) + ON CONFLICT (user_id, lesson_id) DO UPDATE + SET completed_at = NOW(), + attempts_count = user_lesson_progress.attempts_count + 1, + correct_count = user_lesson_progress.correct_count + $3, + best_score = GREATEST(user_lesson_progress.best_score, $4), + completed = TRUE + """, user_id, lesson_id, correct_count, score) + + if session and session["topic_id"]: + if session["session_type"] == "teacher_test": + stats = await conn.fetchrow(""" + SELECT COUNT(*) as total, + COALESCE(SUM(CASE WHEN correct THEN 1 ELSE 0 END), 0) as correct_count + FROM user_learning_answers + WHERE session_id = $1 AND is_final_answer = TRUE + """, session_id) + + total = stats["total"] if stats["total"] else 0 + correct_count = stats["correct_count"] if stats["correct_count"] else 0 + test_score = round((correct_count / total * 100), 2) if total > 0 else 0 + + await conn.execute(""" + INSERT INTO user_topic_progress (user_id, topic_id, test_started, test_completed, test_score, completed_at) + VALUES ($1, $2, TRUE, TRUE, $3, NOW()) + ON CONFLICT (user_id, topic_id) DO UPDATE + SET test_completed = TRUE, + test_score = $3, + completed_at = NOW() + """, user_id, session["topic_id"], test_score) + + await update_topic_progress(conn, user_id, session["topic_id"]) + + await update_ai_context(conn, user_id) + + +async def call_ai(prompt: str, system_prompt: str, max_tokens: int = 500) -> str: + """Вызывает AI и возвращает ответ.""" + if not TOGETHER_API_KEY: + return "" + + try: + async with httpx.AsyncClient(timeout=90.0) as client: + response = await client.post( + TOGETHER_API_URL, + headers={ + "Authorization": f"Bearer {TOGETHER_API_KEY}", + "Content-Type": "application/json", + }, + json={ + "model": TEACHER_MODEL, + "messages": [ + {"role": "system", "content": system_prompt}, + {"role": "user", "content": prompt}, + ], + "max_tokens": max_tokens, + "temperature": 0.7, + }, + ) + + if response.status_code != 200: + logger.error(f"AI API error: {response.status_code}, body={response.text[:200]}") + return "" + + data = response.json() + ai_response = data["choices"][0]["message"]["content"].strip() + ai_response = re.sub(r'\s*\([a-z_]+_[a-z_]+\)', '', ai_response) + return ai_response + except Exception as e: + logger.error(f"AI error: {str(e)}") + return "" + + +async def get_wrong_answer_ai_explanation(telegram_id: int, lang: str, prompt_text: str, selected_answer: str, correct_answer_text: str) -> str: + """ + Получает AI-объяснение для неправильного ответа. + Проверяет лимит и инкрементирует счётчик. + Если лимит исчерпан — возвращает локализованное сообщение. + """ + pool = await get_pool() + + async with pool.acquire() as conn: + if not await check_ai_limit(conn, telegram_id): + return get_ai_limit_message(lang) + + ai_prompt = f"""Вопрос: {prompt_text} +Ответ ученика: {selected_answer} +Правильный ответ: {correct_answer_text} + +Объясни кратко (1-2 предложения), почему правильный ответ именно такой.""" + system_prompt = f"""Ты — Марек, учитель польского языка. Объясняй ошибки кратко и понятно. +Отвечай на языке: {lang}. Не используй markdown.""" + + ai_response = await call_ai(ai_prompt, system_prompt, max_tokens=200) + + if ai_response: + async with pool.acquire() as conn: + await increment_teacher_ai_usage(conn, telegram_id) + else: + ai_response = get_ai_limit_message(lang) if not await _check_ai_limit_for_fallback(telegram_id, lang) else "" + + return ai_response + + +async def _check_ai_limit_for_fallback(telegram_id: int, lang: str) -> bool: + """Проверяет, был ли лимит исчерпан (для fallback-сообщения).""" + pool = await get_pool() + async with pool.acquire() as conn: + return await check_ai_limit(conn, telegram_id) + + +# ============ ФРАЗА ДНЯ ============ +@router.get("/phrase-of-day") +async def get_phrase_of_day(request: Request): + """ + Возвращает фразу дня. + Фраза кэшируется для всех пользователей на 24 часа. + Не тратит AI-лимит пользователя. + """ + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + await conn.execute(""" + CREATE TABLE IF NOT EXISTS daily_phrases ( + id SERIAL PRIMARY KEY, + phrase_date DATE UNIQUE NOT NULL, + phrase_pl TEXT NOT NULL, + translations JSONB NOT NULL DEFAULT '{}', + grammar_breakdowns JSONB NOT NULL DEFAULT '{}', + created_at TIMESTAMP DEFAULT NOW() + ) + """) + + today = datetime.now(timezone.utc).date() + + today_phrase = await conn.fetchrow(""" + SELECT * FROM daily_phrases WHERE phrase_date = $1 + """, today) + + if not today_phrase: + # Список тем для фразы дня + topics_list = [ + "приветствие и знакомство", + "семья и друзья", + "еда и напитки", + "покупки и магазины", + "транспорт и путешествия", + "работа и профессии", + "погода и времена года", + "дом и квартира", + "хобби и свободное время", + "здоровье и самочувствие", + "город и местность", + "ежедневная рутина" + ] + + # Выбираем случайную тему + import random + selected_topic = random.choice(topics_list) + + system_prompt = f"""Ты — учитель польского языка. Создай фразу дня для изучения польского. +Тема фразы: {selected_topic}. +Фраза должна быть уровня A2-B1, полезной в повседневной жизни. + +Верни ответ строго в таком формате (без markdown, просто текст): + +PHRASE: [фраза на польском] +RU: [перевод на русский] +UK: [перевод на украинский] +EN: [перевод на английский] +PL_GRAMMAR: [грамматический разбор на польском, 1-2 предложения] +RU_GRAMMAR: [грамматический разбор на русском, 1-2 предложения] +UK_GRAMMAR: [грамматический разбор на украинском, 1-2 предложения] +EN_GRAMMAR: [грамматический разбор на английском, 1-2 предложения]""" + + user_prompt = f"Создай фразу дня на тему: {selected_topic}." + + ai_response = await call_ai(user_prompt, system_prompt, max_tokens=1000) + + # Fallback значения + phrase_pl = "Lepiej późno niż wcale." + translations = { + "ru": "Лучше поздно, чем никогда.", + "uk": "Краще пізно, ніж ніколи.", + "en": "Better late than never." + } + grammar_breakdowns = { + "pl": "Lepiej - przyslowek w stopniu wyzszym. Pozno - przyslowek.", + "ru": "Lepiej - наречие в сравнительной степени. Pozno - наречие.", + "uk": "Lepiej - прислівник у вищому ступені. Pozno - прислівник.", + "en": "Lepiej - adverb in comparative degree. Pozno - adverb." + } + + if ai_response: + # Парсим текстовый ответ построчно + lines = ai_response.strip().split('\n') + for line in lines: + line = line.strip() + if line.startswith('PHRASE:'): + phrase_pl = line.replace('PHRASE:', '').strip() + elif line.startswith('RU:'): + translations["ru"] = line.replace('RU:', '').strip() + elif line.startswith('UK:'): + translations["uk"] = line.replace('UK:', '').strip() + elif line.startswith('EN:'): + translations["en"] = line.replace('EN:', '').strip() + elif line.startswith('PL_GRAMMAR:'): + grammar_breakdowns["pl"] = line.replace('PL_GRAMMAR:', '').strip() + elif line.startswith('RU_GRAMMAR:'): + grammar_breakdowns["ru"] = line.replace('RU_GRAMMAR:', '').strip() + elif line.startswith('UK_GRAMMAR:'): + grammar_breakdowns["uk"] = line.replace('UK_GRAMMAR:', '').strip() + elif line.startswith('EN_GRAMMAR:'): + grammar_breakdowns["en"] = line.replace('EN_GRAMMAR:', '').strip() + + await conn.execute(""" + INSERT INTO daily_phrases (phrase_date, phrase_pl, translations, grammar_breakdowns) + VALUES ($1, $2, $3::jsonb, $4::jsonb) + ON CONFLICT (phrase_date) DO UPDATE SET + phrase_pl = EXCLUDED.phrase_pl, + translations = EXCLUDED.translations, + grammar_breakdowns = EXCLUDED.grammar_breakdowns + """, today, phrase_pl, json.dumps(translations, ensure_ascii=False), json.dumps(grammar_breakdowns, ensure_ascii=False)) + + today_phrase = await conn.fetchrow(""" + SELECT * FROM daily_phrases WHERE phrase_date = $1 + """, today) + + translations = today_phrase["translations"] + grammar_breakdowns = today_phrase["grammar_breakdowns"] + + if isinstance(translations, str): + translations = json.loads(translations) + if isinstance(grammar_breakdowns, str): + grammar_breakdowns = json.loads(grammar_breakdowns) + + result = { + "phrase_pl": today_phrase["phrase_pl"], + "date": today_phrase["phrase_date"].isoformat() if today_phrase["phrase_date"] else None, + } + + if lang != "pl": + result["translation"] = translations.get(lang, translations.get("en", "")) + + result["grammar_breakdown"] = grammar_breakdowns.get(lang, grammar_breakdowns.get("en", "")) + + return result + + +@router.post("/resume") +async def teacher_resume(request: Request): + """ + Восстанавливает активную сессию. + Проверяет, есть ли незавершённая сессия и возвращает текущий вопрос. + """ + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + session = await conn.fetchrow(""" + SELECT * FROM learning_sessions + WHERE user_id = $1 AND is_completed = FALSE + ORDER BY id DESC + LIMIT 1 + """, telegram_id) + + if not session: + return {"has_active_session": False} + + last_answer = await conn.fetchrow(""" + SELECT question_id FROM user_learning_answers + WHERE session_id = $1 + ORDER BY id DESC + LIMIT 1 + """, session["id"]) + + if not last_answer: + if session["session_type"] == "teacher_test": + questions = await get_test_questions(conn, session["topic_id"]) + else: + lesson_id = await conn.fetchval(""" + SELECT lesson_id FROM learning_sessions WHERE id = $1 + """, session["id"]) + if lesson_id: + questions = await get_lesson_questions(conn, lesson_id) + else: + questions = [] + + if questions: + return { + "has_active_session": True, + "session_id": session["id"], + "session_type": session["session_type"], + "topic_id": session["topic_id"], + "question": questions[0], + "question_index": 0, + "total_questions": len(questions), + } + return {"has_active_session": False} + + if session["session_type"] == "teacher_test": + questions = await get_test_questions(conn, session["topic_id"]) + else: + lesson_id = await conn.fetchval(""" + SELECT lesson_id FROM user_learning_answers + WHERE session_id = $1 AND lesson_id IS NOT NULL + LIMIT 1 + """, session["id"]) + if lesson_id: + questions = await get_lesson_questions(conn, lesson_id) + else: + questions = [] + + last_question_id = last_answer["question_id"] + last_index = 0 + for i, q in enumerate(questions): + if q["question"]["question_id"] == last_question_id: + last_index = i + break + + next_index = last_index + 1 + + if next_index >= len(questions): + await conn.execute(""" + UPDATE learning_sessions SET is_completed = TRUE, completed_at = NOW() + WHERE id = $1 + """, session["id"]) + await update_mastery_after_lesson(conn, telegram_id, session["id"]) + return {"has_active_session": False, "session_completed": True} + + next_question = questions[next_index] + + return { + "has_active_session": True, + "session_id": session["id"], + "session_type": session["session_type"], + "topic_id": session["topic_id"], + "question": next_question, + "question_index": next_index, + "total_questions": len(questions), + } + + +@router.post("/start") +async def teacher_start(request: Request): + """ + Начинает или продолжает урок. + Возвращает первое сообщение от учителя. + """ + telegram_id, username = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + first_name = username or "uczniu" + + next_lesson = await get_next_lesson(conn, telegram_id) + + if next_lesson["type"] == "completed": + return { + "message_type": "completed", + "text": "Wszystkie lekcje ukończone! Świetna robota!" if lang == "pl" else + "Все уроки пройдены! Отличная работа!" if lang == "ru" else + "Всі уроки пройдені! Чудова робота!" if lang == "uk" else + "All lessons completed! Great job!", + } + + if next_lesson["type"] == "test": + topic_id = next_lesson.get("topic_id") + test_questions = await get_test_questions(conn, topic_id) + + if not test_questions: + return { + "message_type": "error", + "text": "No test questions found.", + } + + session_id = await start_learning_session(conn, telegram_id, "A1", topic_id, "teacher_test") + + first_question = test_questions[0] + + return { + "message_type": "test_start", + "session_id": session_id, + "topic_id": topic_id, + "topic_name": "", + "text": "Czas na test!" if lang == "pl" else + "Время теста!" if lang == "ru" else + "Час тесту!" if lang == "uk" else + "Test time!", + "question": first_question, + "question_index": 0, + "total_questions": len(test_questions), + "has_translate_command": True, + } + + lesson_id = next_lesson["lesson"]["lesson_id"] + lesson_data = await get_lesson_by_id(conn, lesson_id) + + if not lesson_data: + return { + "message_type": "error", + "text": "Lesson not found.", + } + + session_id = await start_learning_session( + conn, telegram_id, "A1", lesson_data["lesson"]["topic_id"], "teacher_lesson" + ) + + lesson = lesson_data["lesson"] + examples = lesson_data["examples"] + + explanation_field = f"explanation_{lang}" + title_field = f"title_{lang}" + + explanation_text = lesson.get(explanation_field) or lesson.get("explanation_en") or "" + title_text = lesson.get(title_field) or lesson.get("title_en") or "" + + examples_text = "" + for ex in examples: + ex_field = f"text_{lang}" + ex_translation = ex.get(ex_field) or ex.get("text_en") or "" + examples_text += f"🇵🇱 {ex['text_pl']} → {ex_translation}\n" + + full_text = f"{title_text}\n\n{explanation_text}" + if examples_text: + full_text += f"\n\nPrzykłady:\n{examples_text}" + + questions = lesson_data["questions"] + first_question = questions[0] if questions else None + + if not first_question: + return { + "message_type": "lesson_completed", + "session_id": session_id, + "text": "Lekcja zakończona!" if lang == "pl" else + "Урок завершён!" if lang == "ru" else + "Урок завершено!" if lang == "uk" else + "Lesson completed!", + } + + return { + "message_type": "lesson_explanation", + "session_id": session_id, + "lesson_id": lesson_id, + "topic_id": lesson_data["lesson"]["topic_id"], + "topic_name": title_text, + "text": full_text, + "question": first_question, + "question_index": 0, + "total_questions": len(questions), + "has_explain_command": True, + "has_translate_command": True, + } + + +@router.post("/answer") +async def teacher_answer(request: Request): + """ + Проверяет ответ пользователя и возвращает реакцию + следующий вопрос. + """ + telegram_id, _ = await require_auth(request) + body = await request.json() + + session_id = body.get("session_id") + question_id = body.get("question_id") + selected_answer = body.get("answer", "") + time_taken_ms = body.get("time_taken_ms", 0) + + if not session_id or not question_id: + raise HTTPException(400, "session_id and question_id required") + + pool = await get_pool() + + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + question_row = await conn.fetchrow(""" + SELECT * FROM learning_questions WHERE question_id = $1 + """, question_id) + + if not question_row: + raise HTTPException(404, "Question not found") + + options = await conn.fetch(""" + SELECT * FROM question_options WHERE question_id = $1 + """, question_id) + + correct_answer = question_row["correct_answer"] or "" + is_correct = normalize_answer(selected_answer) == normalize_answer(correct_answer) + + wrong_because = None + for opt in options: + if opt["option_key"] == selected_answer and not is_correct and opt.get("wrong_because"): + wrong_because = opt["wrong_because"] + break + + question_data = { + "question": dict(question_row), + "options": [dict(o) for o in options], + } + await save_answer_to_session( + conn, telegram_id, session_id, question_data, + selected_answer, is_correct, time_taken_ms + ) + + if is_correct: + reaction_type = "correct" + else: + reaction_type = "wrong" if wrong_because else "almost" + + reaction_text = await get_random_reaction(conn, reaction_type, lang) + + db_explanation = "" + if not is_correct and wrong_because: + db_explanation = await get_wrong_because_explanation(conn, wrong_because, lang) + + session = await conn.fetchrow("SELECT * FROM learning_sessions WHERE id = $1", session_id) + if not session: + raise HTTPException(404, "Session not found") + + if session["session_type"] == "teacher_test": + questions = await get_test_questions(conn, session["topic_id"]) + else: + lesson_id = question_row["lesson_id"] + if lesson_id: + questions = await get_lesson_questions(conn, lesson_id) + else: + questions = [] + + current_index = 0 + for i, q in enumerate(questions): + if q["question"]["question_id"] == question_id: + current_index = i + break + + next_index = current_index + 1 + + options_language = question_row.get("options_language") or "pl" + correct_answer_text = "" + for opt in options: + if opt["is_correct"]: + if options_language == "user": + correct_answer_text = opt.get(f"text_{lang}", "") or opt.get("text_pl", "") or "" + else: + correct_answer_text = opt.get("text_pl", "") or opt.get("text_ru", "") or "" + break + + prompt_text = question_row.get(f"prompt_{lang}") or question_row.get("prompt_en") or "" + + needs_ai_explanation = not is_correct and not db_explanation + session_completed = next_index >= len(questions) + next_question_data = None if session_completed else questions[next_index] + + if session_completed: + stats = await conn.fetchrow(""" + SELECT COUNT(*) as total, + COALESCE(SUM(CASE WHEN correct THEN 1 ELSE 0 END), 0) as correct_count + FROM user_learning_answers + WHERE session_id = $1 AND is_final_answer = TRUE + """, session_id) + session_stats = { + "total": stats["total"] if stats["total"] else 0, + "correct_count": stats["correct_count"] if stats["correct_count"] else 0, + } + session_type = session["session_type"] + + await conn.execute(""" + UPDATE learning_sessions SET is_completed = TRUE, completed_at = NOW() + WHERE id = $1 + """, session_id) + await update_mastery_after_lesson(conn, telegram_id, session_id) + + explanation_text = db_explanation + if needs_ai_explanation: + explanation_text = await get_wrong_answer_ai_explanation( + telegram_id, lang, prompt_text, selected_answer, correct_answer_text + ) + + if session_completed: + return { + "message_type": "lesson_completed", + "reaction": reaction_text, + "explanation": explanation_text, + "is_correct": is_correct, + "correct_answer": correct_answer_text, + "wrong_because": wrong_because or "", + "session_completed": True, + "session_stats": session_stats, + "session_type": session_type, + } + + return { + "message_type": "next_question", + "reaction": reaction_text, + "explanation": explanation_text, + "is_correct": is_correct, + "correct_answer": correct_answer_text, + "wrong_because": wrong_because or "", + "question": next_question_data, + "question_index": next_index, + "total_questions": len(questions), + "has_explain_command": not is_correct, + } + + +@router.post("/explain") +async def teacher_explain(request: Request): + """ + AI-объяснение текущего урока или ошибки. + """ + telegram_id, _ = await require_auth(request) + body = await request.json() + lesson_id = body.get("lesson_id", "") + question_id = body.get("question_id", "") + topic = body.get("topic", "") + + pool = await get_pool() + + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + if not await check_ai_limit(conn, telegram_id): + return { + "response": "", + "limit_exceeded": True, + "message": get_ai_limit_message(lang) + } + + content = "" + if lesson_id: + lesson = await conn.fetchrow(""" + SELECT * FROM learning_lessons WHERE lesson_id = $1 + """, lesson_id) + if lesson: + content = lesson.get(f"explanation_{lang}") or lesson.get("explanation_en") or "" + elif question_id: + question = await conn.fetchrow(""" + SELECT * FROM learning_questions WHERE question_id = $1 + """, question_id) + if question: + content = question.get(f"prompt_{lang}") or question.get("prompt_en") or "" + else: + content = topic + + if not content: + return {"response": "", "error": "No content to explain"} + + system_prompt = f"""Ты — учитель польского языка. Объясни материал простыми словами. +Отвечай на языке: {lang}. Не используй markdown.""" + + ai_response = await call_ai(content, system_prompt) + + if ai_response: + async with pool.acquire() as conn: + await increment_teacher_ai_usage(conn, telegram_id) + + return {"response": ai_response} + + +@router.post("/examples") +async def teacher_examples(request: Request): + """ + Даёт 5 примеров предложений по текущей теме. + Формат: 🇵🇱 польская фраза → перевод на язык пользователя. + AI-команда, лимит 5/день. + """ + telegram_id, _ = await require_auth(request) + body = await request.json() + topic = body.get("topic", "") + lesson_id = body.get("lesson_id", "") + topic_id = body.get("topic_id", "") + + pool = await get_pool() + + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + if not await check_ai_limit(conn, telegram_id): + return { + "response": "", + "limit_exceeded": True, + "message": get_ai_limit_message(lang) + } + + # Если не передан topic — берём по lesson_id + if lesson_id and not topic: + lesson = await conn.fetchrow(""" + SELECT title_pl, title_ru, title_uk, title_en + FROM learning_lessons WHERE lesson_id = $1 + """, lesson_id) + if lesson: + topic = lesson.get(f"title_{lang}") or lesson.get("title_en") or "" + + # Если не передан topic и lesson_id — берём по topic_id + if topic_id and not topic: + topic_row = await conn.fetchrow(""" + SELECT name_pl, name_ru, name_uk, name_en + FROM learning_topics WHERE topic_id = $1 + """, topic_id) + if topic_row: + topic = topic_row.get(f"name_{lang}") or topic_row.get("name_en") or "" + + if not topic: + topic = "polish language" + + lang_names = { + "pl": "polskiego", + "ru": "русский", + "uk": "украинский", + "en": "English", + } + lang_name = lang_names.get(lang, "English") + + system_prompt = f"""Ты — учитель польского языка. Дай ровно 5 примеров предложений по теме: {topic}. +Каждый пример — простое предложение уровня A2, полезное в повседневной жизни. + +Формат ответа (без markdown, каждый пример с новой строки): +🇵🇱 [польское предложение] → [перевод на {lang_name}] + +Пример: +🇵🇱 Jestem nauczycielem. → Я учитель. +🇵🇱 Pracuję w biurze. → Я работаю в офисе. + +Верни только 5 примеров, без вступлений и пояснений.""" + + ai_response = await call_ai(topic, system_prompt, max_tokens=500) + + if ai_response: + async with pool.acquire() as conn: + await increment_teacher_ai_usage(conn, telegram_id) + + return {"response": ai_response} + + +@router.post("/free-message") +async def teacher_free_message(request: Request): + """ + Обрабатывает свободное сообщение пользователя. + """ + telegram_id, _ = await require_auth(request) + body = await request.json() + user_message = body.get("message", "").strip() + lesson_id = body.get("lesson_id", "") + topic_id = body.get("topic_id", "") + topic_name = body.get("topic_name", "") + + if not user_message: + raise HTTPException(400, "message is required") + + if len(user_message) > 300: + raise HTTPException(400, "Message too long (max 300 characters)") + + pool = await get_pool() + + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + if not await check_ai_limit(conn, telegram_id): + return { + "response": "", + "limit_exceeded": True, + "message": get_ai_limit_message(lang) + } + + context_parts = [] + if topic_name: + context_parts.append(f"Текущая тема урока: {topic_name}") + if lesson_id: + lesson = await conn.fetchrow(""" + SELECT title_pl, title_ru, title_uk, title_en + FROM learning_lessons WHERE lesson_id = $1 + """, lesson_id) + if lesson: + lesson_title = lesson.get(f"title_{lang}") or lesson.get("title_en") or "" + context_parts.append(f"Текущий урок: {lesson_title}") + + context_text = "\n".join(context_parts) if context_parts else "" + + system_prompt = f"""Ты — Марек, учитель польского языка в приложении Filwords PL. +Ты дружелюбный, поддерживающий и краткий. +Отвечай на языке: {lang}. +Не используй markdown. +{context_text} + +Ученик может спросить что угодно: объяснить тему, перевести фразу, дать пример. +Отвечай кратко (1-3 предложения) и по делу.""" + + ai_response = await call_ai(user_message, system_prompt, max_tokens=300) + + if ai_response: + async with pool.acquire() as conn: + await increment_teacher_ai_usage(conn, telegram_id) + + return {"response": ai_response} + + +@router.post("/diagnostic-test") +async def teacher_diagnostic_test(request: Request): + """ + Тест на определение уровня языка. + Берёт случайные вопросы разных тем и уровней. + """ + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + questions = await conn.fetch(""" + SELECT * FROM learning_questions + WHERE is_test_question = TRUE + ORDER BY RANDOM() + LIMIT 15 + """) + + if not questions: + return {"error": "No questions available"} + + session_id = await start_learning_session(conn, telegram_id, "A1", "", "diagnostic_test") + + questions_data = [] + for q in questions: + options = await conn.fetch(""" + SELECT * FROM question_options WHERE question_id = $1 + """, q["question_id"]) + questions_data.append({ + "question": dict(q), + "options": [dict(o) for o in options], + }) + + return { + "session_id": session_id, + "questions": questions_data, + "total_questions": len(questions_data), + } + + +@router.post("/translate-to-polish") +async def teacher_translate_to_polish(request: Request): + """ + Переводит текст на польский язык. + AI-команда, лимит 5/день. + """ + telegram_id, _ = await require_auth(request) + body = await request.json() + text = body.get("text", "").strip() + + if not text: + raise HTTPException(400, "text is required") + + if len(text) > 300: + raise HTTPException(400, "Text too long (max 300 characters)") + + pool = await get_pool() + + async with pool.acquire() as conn: + lang = await get_user_lang(conn, telegram_id) + + if not await check_ai_limit(conn, telegram_id): + return { + "response": "", + "limit_exceeded": True, + "message": get_ai_limit_message(lang) + } + + system_prompt = f"""Ты — переводчик польского языка. Переведи текст на польский. +Отвечай только переводом без пояснений. Не используй markdown.""" + + ai_response = await call_ai(text, system_prompt, max_tokens=300) + + if ai_response: + async with pool.acquire() as conn: + await increment_teacher_ai_usage(conn, telegram_id) + + return {"response": ai_response} + + +# ============ ПРОГРЕСС ПО УРОВНЯМ ============ +@router.get("/progress") +async def teacher_progress(request: Request): + """ + Возвращает прогресс пользователя по всем уровням (A1-C2). + Для каждого уровня: сколько тем пройдено из общего количества. + """ + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + levels = await conn.fetch(""" + SELECT code, name_pl, name_ru, name_uk, name_en + FROM learning_levels + WHERE is_active = TRUE + ORDER BY sort_order + """) + + result = [] + + for level in levels: + code = level["code"] + + topics_total = await conn.fetchval(""" + SELECT COUNT(*) FROM learning_topics + WHERE level_code = $1 AND is_active = TRUE + """, code) or 0 + + topics_completed = await conn.fetchval(""" + SELECT COUNT(*) FROM user_topic_progress + WHERE user_id = $1 AND topic_id IN ( + SELECT topic_id FROM learning_topics WHERE level_code = $2 AND is_active = TRUE + ) AND test_completed = TRUE + """, telegram_id, code) or 0 + + result.append({ + "code": code, + "name_pl": level["name_pl"], + "name_ru": level["name_ru"], + "name_uk": level["name_uk"], + "name_en": level["name_en"], + "topics_total": topics_total, + "topics_completed": topics_completed, + }) + + return {"levels": result} + + +@router.post("/history/save") +async def save_teacher_history(request: Request): + """Сохраняет историю чата учителя на сервере.""" + telegram_id, _ = await require_auth(request) + body = await request.json() + messages = body.get("messages", []) + + if not isinstance(messages, list): + raise HTTPException(400, "messages must be a list") + + pool = await get_pool() + async with pool.acquire() as conn: + await conn.execute(""" + INSERT INTO teacher_chat_history (user_id, messages, updated_at) + VALUES ($1, $2::jsonb, NOW()) + ON CONFLICT (user_id) DO UPDATE + SET messages = $2::jsonb, updated_at = NOW() + """, telegram_id, json.dumps(messages, ensure_ascii=False)) + + return {"status": "ok"} + + +@router.get("/history/load") +async def load_teacher_history(request: Request): + """Загружает историю чата учителя с сервера.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + row = await conn.fetchrow(""" + SELECT messages FROM teacher_chat_history WHERE user_id = $1 + """, telegram_id) + + if row and row["messages"]: + messages = row["messages"] + if isinstance(messages, str): + messages = json.loads(messages) + return {"messages": messages} + + return {"messages": []} + + +@router.post("/history/clear") +async def clear_teacher_history(request: Request): + """Очищает историю чата учителя на сервере.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + await conn.execute(""" + DELETE FROM teacher_chat_history WHERE user_id = $1 + """, telegram_id) + + return {"status": "ok"} \ No newline at end of file diff --git a/routers/tts.py b/routers/tts.py new file mode 100644 index 0000000..0cb566e --- /dev/null +++ b/routers/tts.py @@ -0,0 +1,99 @@ +""" +TTS Router — озвучка текста через Edge TTS. +Бесплатный, качественный синтез речи для польского языка. +Кэш хранится в файлах на диске. +""" +import logging +import io +import os +import hashlib +import edge_tts +from fastapi import APIRouter, Request, HTTPException +from fastapi.responses import Response +from auth import require_auth + +logger = logging.getLogger(__name__) + +router = APIRouter(prefix="/tts", tags=["tts"]) + +# Голоса Edge TTS для польского +VOICE_PL = "pl-PL-MarekNeural" # Мужской голос (основной) +VOICE_PL_FEMALE = "pl-PL-AgnieszkaNeural" # Женский голос + +# Директория для кэша +CACHE_DIR = "/root/filwordspl/backend/tts_cache" +os.makedirs(CACHE_DIR, exist_ok=True) + + +def get_cache_path(voice_name: str, text: str) -> str: + """Создаёт путь к файлу кэша на основе хеша текста и голоса""" + cache_key = hashlib.md5(f"{voice_name}:{text}".encode()).hexdigest() + return os.path.join(CACHE_DIR, f"{cache_key}.mp3") + + +@router.get("") +async def text_to_speech(request: Request, text: str = "", voice: str = "male"): + """ + Озвучивает текст через Edge TTS. + + Параметры: + - text: текст для озвучки + - voice: male (Marek) или female (Agnieszka) + + Возвращает: audio/mpeg + """ + await require_auth(request) + + if not text or len(text) > 500: + raise HTTPException(400, "Text is required (max 500 characters)") + + # Выбираем голос + if voice == "female": + voice_name = VOICE_PL_FEMALE + else: + voice_name = VOICE_PL + + # Путь к файлу кэша + cache_path = get_cache_path(voice_name, text) + + # Проверяем файловый кэш + if os.path.exists(cache_path): + logger.info(f"TTS: cache hit for text: {text[:50]}...") + with open(cache_path, 'rb') as f: + return Response( + content=f.read(), + media_type="audio/mpeg", + ) + + try: + logger.info(f"TTS: synthesizing text: {text[:50]}...") + + # Синтезируем речь + communicate = edge_tts.Communicate(text, voice_name) + audio_data = io.BytesIO() + + async for chunk in communicate.stream(): + if chunk["type"] == "audio": + audio_data.write(chunk["data"]) + + audio_bytes = audio_data.getvalue() + + if not audio_bytes: + raise HTTPException(500, "TTS generation failed") + + # Сохраняем в файловый кэш + with open(cache_path, 'wb') as f: + f.write(audio_bytes) + + logger.info(f"TTS: done, size={len(audio_bytes)} bytes, cached to {os.path.basename(cache_path)}") + + return Response( + content=audio_bytes, + media_type="audio/mpeg", + ) + + except HTTPException: + raise + except Exception as e: + logger.error(f"TTS error: {str(e)}") + raise HTTPException(500, f"TTS error: {str(e)}") \ No newline at end of file diff --git a/routers/typing.py b/routers/typing.py new file mode 100644 index 0000000..22fc8b2 --- /dev/null +++ b/routers/typing.py @@ -0,0 +1,141 @@ +""" +Typing Router — раздел "Печать". +Пользователь печатает польские предложения, система проверяет. +Без AI — просто сравнение с правильным ответом из БД. +""" +import random +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool + +router = APIRouter(prefix="/typing", tags=["typing"]) + + +def normalize_text(text: str) -> str: + """Нормализует текст для сравнения: нижний регистр, убирает лишние пробелы.""" + return ' '.join(text.strip().lower().split()) + + +@router.get("/next") +async def get_next_typing_sentence(request: Request): + """Выдаёт случайное непройденное предложение для выбранного уровня.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow(""" + SELECT app_language, current_level FROM users WHERE telegram_id = $1 + """, telegram_id) + if not user: + raise HTTPException(401, "User not registered") + + lang = user["app_language"] or "pl" + current_level = user["current_level"] or "A1" + + # Находим случайное непройденное предложение + row = await conn.fetchrow(""" + SELECT s.id, s.sentence_pl, s.translation_ru, s.translation_uk, s.translation_en, s.level + FROM sentences s + WHERE s.level = $1 + AND s.id NOT IN ( + SELECT sentence_id FROM typing_progress WHERE user_id = $2 + ) + ORDER BY RANDOM() + LIMIT 1 + """, current_level, telegram_id) + + if not row: + return {"completed": True, "message": "Все предложения пройдены!"} + + translation_field = f"translation_{lang}" + translation = row.get(translation_field) or row.get("translation_en") or row["sentence_pl"] + + return { + "completed": False, + "sentence_id": row["id"], + "translation": translation, + "level": row["level"], + } + + +@router.post("/check") +async def check_typing_sentence(request: Request): + """Проверяет напечатанное предложение.""" + telegram_id, _ = await require_auth(request) + body = await request.json() + sentence_id = body.get("sentence_id") + user_text = body.get("text", "") + + if not sentence_id or not user_text: + raise HTTPException(400, "sentence_id and text required") + + pool = await get_pool() + async with pool.acquire() as conn: + row = await conn.fetchrow(""" + SELECT sentence_pl FROM sentences WHERE id = $1 + """, sentence_id) + if not row: + raise HTTPException(404, "Sentence not found") + + correct_text = normalize_text(row["sentence_pl"]) + user_normalized = normalize_text(user_text) + + is_correct = correct_text == user_normalized + + if is_correct: + # Сохраняем прогресс + await conn.execute(""" + INSERT INTO typing_progress (user_id, sentence_id, completed_at) + VALUES ($1, $2, NOW()) + ON CONFLICT (user_id, sentence_id) DO NOTHING + """, telegram_id, sentence_id) + + return { + "correct": is_correct, + "correct_answer": row["sentence_pl"], + } + + +@router.get("/hint/{sentence_id}") +async def get_typing_hint(request: Request, sentence_id: int): + """Возвращает правильный ответ для подсказки.""" + await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + row = await conn.fetchrow(""" + SELECT sentence_pl FROM sentences WHERE id = $1 + """, sentence_id) + if not row: + raise HTTPException(404, "Sentence not found") + + return {"correct_answer": row["sentence_pl"]} + + +@router.get("/progress") +async def get_typing_progress(request: Request): + """Статистика по печати.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow(""" + SELECT current_level FROM users WHERE telegram_id = $1 + """, telegram_id) + current_level = user["current_level"] if user else "A1" + + total = await conn.fetchval(""" + SELECT COUNT(*) FROM sentences WHERE level = $1 + """, current_level) or 0 + + completed = await conn.fetchval(""" + SELECT COUNT(*) FROM typing_progress tp + JOIN sentences s ON tp.sentence_id = s.id + WHERE tp.user_id = $1 AND s.level = $2 + """, telegram_id, current_level) or 0 + + return { + "total": total, + "completed": completed, + "remaining": total - completed, + } \ No newline at end of file diff --git a/routers/users.py b/routers/users.py new file mode 100644 index 0000000..2c7c9e1 --- /dev/null +++ b/routers/users.py @@ -0,0 +1,106 @@ +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool +from config import SUPPORTED_LANGUAGES, ADMIN_IDS + +router = APIRouter(prefix="/users", tags=["users"]) + +SUPPORTED_LEVELS = {"A1", "A2", "B1", "B2", "C1", "C2"} + + +@router.post("/register") +async def register_user(request: Request): + user_id, username = await require_auth(request) + pool = await get_pool() + async with pool.acquire() as conn: + # Проверяем существует ли пользователь + existing = await conn.fetchrow( + "SELECT id, app_language, current_level FROM users WHERE telegram_id = $1", user_id + ) + + if existing: + return { + "status": "ok", + "app_language": existing["app_language"], + "current_level": existing["current_level"] or "A1", + "user_id": existing["id"], + "is_admin": user_id in ADMIN_IDS, + } + + # Создаем нового пользователя + row = await conn.fetchrow( + """INSERT INTO users (telegram_id, username, current_level) + VALUES ($1, $2, 'A1') + RETURNING id, app_language, current_level""", + user_id, username or f"id{user_id}", + ) + return { + "status": "ok", + "app_language": row["app_language"], + "current_level": row["current_level"], + "user_id": row["id"], + "is_admin": user_id in ADMIN_IDS, + } + + +@router.get("/me/is-admin") +async def check_is_admin(request: Request): + """Проверяет, является ли текущий пользователь администратором.""" + user_id, _ = await require_auth(request) + return {"is_admin": user_id in ADMIN_IDS} + + +@router.post("/set-language") +async def set_language(request: Request): + user_id, _ = await require_auth(request) + body = await request.json() + lang = body.get("language", "pl") + if lang not in SUPPORTED_LANGUAGES: + raise HTTPException(400, "Unsupported language") + + pool = await get_pool() + async with pool.acquire() as conn: + await conn.execute( + "UPDATE users SET app_language = $1 WHERE telegram_id = $2", + lang, user_id, + ) + + # 🔧 ИСПРАВЛЕНО: вызов достижений ВНЕ блока async with pool.acquire() + from routers.achievements import check_and_award_achievements + new_achievements = await check_and_award_achievements(user_id, "language_changed", 1) + + return { + "status": "ok", + "app_language": lang, + "new_achievements": new_achievements + } + + +@router.post("/set-level") +async def set_level(request: Request): + """Устанавливает текущий уровень пользователя (A1, A2, B1, B2, C1, C2)""" + user_id, _ = await require_auth(request) + body = await request.json() + level = body.get("level", "A1") + + if level not in SUPPORTED_LEVELS: + raise HTTPException(400, "Unsupported level") + + pool = await get_pool() + async with pool.acquire() as conn: + # Проверяем, что пользователь существует + user_exists = await conn.fetchval( + "SELECT 1 FROM users WHERE telegram_id = $1", user_id + ) + if not user_exists: + raise HTTPException(401, "User not registered") + + await conn.execute( + "UPDATE users SET current_level = $1 WHERE telegram_id = $2", + level, user_id, + ) + + return { + "status": "ok", + "level": level, + } \ No newline at end of file diff --git a/routers/wordquiz.py b/routers/wordquiz.py new file mode 100644 index 0000000..5678b22 --- /dev/null +++ b/routers/wordquiz.py @@ -0,0 +1,282 @@ +import random +from fastapi import APIRouter, Request, HTTPException +from auth import require_auth +from database import get_pool + +router = APIRouter(prefix="/wordquiz", tags=["wordquiz"]) + + +@router.get("/next") +async def get_next_quiz(request: Request): + """Выдаёт случайное слово из базы выбранного уровня. Исключает недавно показанные.""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + user = await conn.fetchrow( + "SELECT app_language, current_level FROM users WHERE telegram_id = $1", telegram_id + ) + if not user: + raise HTTPException(401, "User not registered") + + lang = user["app_language"] or "pl" + current_level = user["current_level"] or "A1" + + progress = await conn.fetchrow( + "SELECT words_guessed, recent_words FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) + total_guessed = progress["words_guessed"] if progress else 0 + recent_words = list(progress["recent_words"]) if progress and progress["recent_words"] else [] + + async def pick_word(exclude, respect_exclude=True): + if respect_exclude and exclude: + placeholders = ",".join([f"${i+2}" for i in range(len(exclude))]) + return await conn.fetchrow(f""" + SELECT word_pl, translation_ru, translation_uk, translation_en + FROM ( + SELECT DISTINCT ON (word_pl) word_pl, translation_ru, translation_uk, translation_en + FROM level_words + WHERE level = $1 AND level_id IS NULL AND word_pl NOT IN ({placeholders}) + ) AS unique_words + ORDER BY RANDOM() + LIMIT 1 + """, current_level, *exclude) + return await conn.fetchrow(""" + SELECT word_pl, translation_ru, translation_uk, translation_en + FROM ( + SELECT DISTINCT ON (word_pl) word_pl, translation_ru, translation_uk, translation_en + FROM level_words + WHERE level = $1 AND level_id IS NULL + ) AS unique_words + ORDER BY RANDOM() + LIMIT 1 + """, current_level) + + word = await pick_word(recent_words, respect_exclude=True) + if not word: + word = await pick_word([], respect_exclude=False) + + if not word: + raise HTTPException(404, "No words found") + + correct_polish = word["word_pl"] + translation_field = f"translation_{lang}" + translation = word.get(translation_field) or word.get("translation_en") or correct_polish + + # Ищем неправильные варианты + exclude_for_wrong = recent_words + [correct_polish] + placeholders = ",".join([f"${i+3}" for i in range(len(exclude_for_wrong))]) + wrong_words = await conn.fetch(f""" + SELECT word_pl + FROM ( + SELECT DISTINCT ON (word_pl) word_pl + FROM level_words + WHERE level = $1 AND level_id IS NULL AND word_pl != $2 AND word_pl NOT IN ({placeholders}) + ) AS unique_wrong + ORDER BY RANDOM() + LIMIT 5 + """, current_level, correct_polish, *exclude_for_wrong) + + if len(wrong_words) < 2: + wrong_words = await conn.fetch(""" + SELECT word_pl + FROM ( + SELECT DISTINCT ON (word_pl) word_pl + FROM level_words + WHERE level = $1 AND level_id IS NULL AND word_pl != $2 + ) AS unique_wrong + ORDER BY RANDOM() + LIMIT 5 + """, current_level, correct_polish) + + wrong_options = [] + seen = {correct_polish.lower()} + for w in wrong_words: + wl = w["word_pl"].lower() + if wl not in seen: + wrong_options.append(w["word_pl"]) + seen.add(wl) + if len(wrong_options) >= 2: + break + + recent_words = recent_words + [correct_polish] + wrong_options + if len(recent_words) > 45: + recent_words = recent_words[-45:] + + await conn.execute(""" + INSERT INTO word_quiz_progress (user_id, words_guessed, total_score, recent_words) + VALUES ($1, 0, 0, $2::text[]) + ON CONFLICT (user_id) DO UPDATE + SET recent_words = $2::text[] + """, telegram_id, recent_words) + + options = wrong_options + [correct_polish] + random.shuffle(options) + + if total_guessed <= 10: + difficulty = "easy" + elif total_guessed <= 30: + difficulty = "medium" + elif total_guessed <= 60: + difficulty = "hard" + else: + difficulty = "expert" + + return { + "correct_polish": correct_polish, + "translation": translation, + "options": options, + "difficulty": difficulty, + } + + +@router.post("/check") +async def check_quiz_answer(request: Request): + """Проверяет ответ, начисляет очки и проверяет достижения""" + telegram_id, _ = await require_auth(request) + body = await request.json() + correct_polish = body.get("correct_polish", "") + user_answer = body.get("answer", "") + mistakes = body.get("mistakes", 0) + completion_time = body.get("completion_time") + + if not correct_polish or not user_answer: + raise HTTPException(400, "correct_polish and answer required") + + # Защита от читерства: минимальное время 1 секунда + if completion_time is not None and completion_time < 1: + return { + "correct": False, + "correct_streak": 0, + "error": "Too fast. Please take your time." + } + + is_correct = user_answer.strip().lower() == correct_polish.strip().lower() + + pool = await get_pool() + async with pool.acquire() as conn: + current_streak = await conn.fetchval( + "SELECT correct_streak FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + + if is_correct: + current_streak += 1 + else: + current_streak = 0 + + if is_correct: + score = max(10, 50 - (mistakes * 20)) + + await conn.execute(""" + INSERT INTO word_quiz_progress (user_id, words_guessed, total_score, correct_streak) + VALUES ($1, 1, $2, $3) + ON CONFLICT (user_id) DO UPDATE + SET words_guessed = word_quiz_progress.words_guessed + 1, + total_score = word_quiz_progress.total_score + $2, + correct_streak = $3 + """, telegram_id, score, current_streak) + + from routers.achievements import check_and_award_achievements + new_achievements = [] + + total_guessed = await conn.fetchval( + "SELECT words_guessed FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + ach = await check_and_award_achievements(telegram_id, "quiz_guessed", total_guessed) + new_achievements.extend(ach) + + if current_streak >= 10: + ach = await check_and_award_achievements(telegram_id, "quiz_perfect_streak", current_streak) + new_achievements.extend(ach) + + if mistakes == 0: + ach = await check_and_award_achievements(telegram_id, "quiz_no_mistakes", 1) + new_achievements.extend(ach) + + if completion_time is not None and completion_time > 0 and int(completion_time) <= 3: + ach = await check_and_award_achievements(telegram_id, "quiz_speed", 3) + new_achievements.extend(ach) + + wordsearch_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM user_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + sentence_score = await conn.fetchval( + "SELECT COALESCE(SUM(score), 0) FROM sentence_progress WHERE user_id = $1 AND completed_at IS NOT NULL", + telegram_id + ) or 0 + wordquiz_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) or 0 + bubblewords_score = await conn.fetchval( + "SELECT COALESCE(total_score, 0) FROM bubble_words_progress WHERE user_id = $1", + telegram_id + ) or 0 + grand_total = wordsearch_score + sentence_score + wordquiz_score + bubblewords_score + ach = await check_and_award_achievements(telegram_id, "total_score", grand_total) + new_achievements.extend(ach) + + return { + "correct": True, + "score": score, + "correct_streak": current_streak, + "new_achievements": new_achievements, + } + else: + # При 3 ошибках — начисляем утешительные 10 очков + if mistakes >= 3: + await conn.execute(""" + INSERT INTO word_quiz_progress (user_id, words_guessed, total_score, correct_streak) + VALUES ($1, 0, 10, 0) + ON CONFLICT (user_id) DO UPDATE + SET total_score = word_quiz_progress.total_score + 10, + correct_streak = 0 + """, telegram_id) + else: + await conn.execute(""" + INSERT INTO word_quiz_progress (user_id, words_guessed, total_score, correct_streak) + VALUES ($1, 0, 0, $2) + ON CONFLICT (user_id) DO UPDATE + SET correct_streak = $2 + """, telegram_id, current_streak) + + return { + "correct": False, + "correct_streak": current_streak, + "consolation_score": 10 if mistakes >= 3 else 0, + } + + +@router.get("/progress") +async def get_quiz_progress(request: Request): + """Статистика пользователя в квизе""" + telegram_id, _ = await require_auth(request) + + pool = await get_pool() + async with pool.acquire() as conn: + progress = await conn.fetchrow( + "SELECT words_guessed, total_score, correct_streak FROM word_quiz_progress WHERE user_id = $1", + telegram_id + ) + + total_guessed = progress["words_guessed"] if progress else 0 + + if total_guessed <= 10: + difficulty = "easy" + elif total_guessed <= 30: + difficulty = "medium" + elif total_guessed <= 60: + difficulty = "hard" + else: + difficulty = "expert" + + return { + "words_guessed": total_guessed, + "total_score": progress["total_score"] if progress else 0, + "correct_streak": progress["correct_streak"] if progress else 0, + "difficulty": difficulty + } \ No newline at end of file diff --git a/sentences_a1.csv b/sentences_a1.csv new file mode 100644 index 0000000..07ff7bf --- /dev/null +++ b/sentences_a1.csv @@ -0,0 +1,201 @@ +polish,english,russian,ukrainian +Cześć jak się masz,Hi how are you,Привет как дела,Привіт як справи +Mam na imię Anna,My name is Anna,Меня зовут Анна,Мене звати Анна +Miło mi cię poznać,Nice to meet you,Приятно познакомиться,Приємно познайомитися +Skąd jesteś,Where are you from,Откуда ты,Звідки ти +Jestem z Polski,I am from Poland,Я из Польши,Я з Польщі +Ile masz lat,How old are you,Сколько тебе лет,Скільки тобі років +Mam trzydzieści cztery lata,I am thirty-four years old,Мне тридцать четыре года,Мені тридцять чотири роки +Dziękuję bardzo,Thank you very much,Большое спасибо,Дуже дякую +Proszę bardzo,You're welcome,Пожалуйста,Будь ласка +Do widzenia,Goodbye,До свидания,До побачення +To jest moja rodzina,This is my family,Это моя семья,Це моя сім'я +Mam brata i siostrę,I have a brother and a sister,У меня есть брат и сестра,У мене є брат і сестра +Moja mama jest lekarzem,My mother is a doctor,Моя мама врач,Моя мама лікарка +Mój tata pracuje w biurze,My father works in an office,Мой папа работает в офисе,Мій тато працює в офісі +Mam dwoje dzieci,I have two children,У меня двое детей,У мене двоє дітей +Moja babcia mieszka w mieście,My grandmother lives in the city,Моя бабушка живёт в городе,Моя бабуся живе в місті +To jest mój mąż,This is my husband,Это мой муж,Це мій чоловік +To jest moja żona,This is my wife,Это моя жена,Це моя дружина +Kocham moją rodzinę,I love my family,Я люблю свою семью,Я люблю свою родину +Mój syn ma pięć lat,My son is five years old,Моему сыну пять лет,Моєму сину п'ять років +Która jest godzina,What time is it,Который час,Котра година +Jest trzecia godzina,It is three o'clock,Сейчас три часа,Зараз третя година +Dzisiaj jest poniedziałek,Today is Monday,Сегодня понедельник,Сьогодні понеділок +Jutro jest wtorek,Tomorrow is Tuesday,Завтра вторник,Завтра вівторок +Mam spotkanie o dziesiątej,I have a meeting at ten,У меня встреча в десять,У мене зустріч о десятій +Wstaję o siódmej rano,I get up at seven in the morning,Я встаю в семь утра,Я встаю о сьомій ранку +Pracuję od poniedziałku do piątku,I work from Monday to Friday,Я работаю с понедельника по пятницу,Я працюю з понеділка до п'ятниці +W sobotę odpoczywam,On Saturday I rest,В субботу я отдыхаю,У суботу я відпочиваю +Ile to kosztuje,How much does this cost,Сколько это стоит,Скільки це коштує +To kosztuje dziesięć złotych,This costs ten zlotys,Это стоит десять злотых,Це коштує десять злотих +Lubię jeść owoce,I like eating fruit,Я люблю есть фрукты,Я люблю їсти фрукти +Chcę pić kawę,I want to drink coffee,Я хочу пить кофе,Я хочу пити каву +Jem śniadanie o ósmej,I eat breakfast at eight,Я завтракаю в восемь,Я снідаю о восьмій +Lubię chleb i ser,I like bread and cheese,Я люблю хлеб и сыр,Я люблю хліб і сир +Nie lubię ryb,I don't like fish,Я не люблю рыбу,Я не люблю рибу +Poproszę wodę,I'd like water please,Дайте пожалуйста воду,Будь ласка дайте воду +Ta zupa jest smaczna,This soup is tasty,Этот суп вкусный,Цей суп смачний +Kupuję warzywa na targu,I buy vegetables at the market,Я покупаю овощи на рынке,Я купую овочі на ринку +On je jabłko,He is eating an apple,Он ест яблоко,Він їсть яблуко +Ona pije herbatę,She is drinking tea,Она пьёт чай,Вона п'є чай +Codziennie chodzę do pracy,Every day I go to work,Каждый день я хожу на работу,Щодня я ходжу на роботу +Rano myję zęby,In the morning I brush my teeth,Утром я чищу зубы,Вранці я чищу зуби +Potem jem śniadanie,Then I eat breakfast,Потом я завтракаю,Потім я снідаю +Jadę autobusem do szkoły,I go to school by bus,Я езжу в школу на автобусе,Я їжджу до школи автобусом +Po pracy wracam do domu,After work I go back home,После работы я возвращаюсь домой,Після роботи я повертаюся додому +Wieczorem oglądam telewizję,In the evening I watch TV,Вечером я смотрю телевизор,Увечері я дивлюся телевізор +Idę spać o jedenastej,I go to sleep at eleven,Я ложусь спать в одиннадцать,Я лягаю спати об одинадцятій +W weekend sprzątam mieszkanie,On the weekend I clean the flat,На выходных я убираю квартиру,На вихідних я прибираю квартиру +Gotuję obiad dla rodziny,I cook dinner for my family,Я готовлю обед для семьи,Я готую обід для родини +Czytam książkę przed snem,I read a book before sleep,Я читаю книгу перед сном,Я читаю книгу перед сном +Dzisiaj jest ciepło,Today it is warm,Сегодня тепло,Сьогодні тепло +Pada deszcz,It is raining,Идёт дождь,Йде дощ +Jutro będzie zimno,Tomorrow it will be cold,Завтра будет холодно,Завтра буде холодно +Świeci słońce,The sun is shining,Светит солнце,Світить сонце +Zimą pada śnieg,In winter it snows,Зимой идёт снег,Взимку йде сніг +Lubię lato bo jest gorąco,I like summer because it is hot,Я люблю лето потому что жарко,Я люблю літо бо спекотно +Wieje silny wiatr,There is a strong wind,Дует сильный ветер,Дме сильний вітер +Jaka jest dzisiaj pogoda,What is the weather like today,Какая сегодня погода,Яка сьогодні погода +Wiosną jest ładna pogoda,In spring the weather is nice,Весной хорошая погода,Навесні гарна погода +Jesienią jest chłodno,In autumn it is cool,Осенью прохладно,Восени прохолодно +Idę do sklepu,I am going to the shop,Я иду в магазин,Я йду до магазину +Chcę kupić nowe buty,I want to buy new shoes,Я хочу купить новую обувь,Я хочу купити нове взуття +Ta koszula jest za droga,This shirt is too expensive,Эта рубашка слишком дорогая,Ця сорочка занадто дорога +Czy macie mniejszy rozmiar,Do you have a smaller size,У вас есть размер поменьше,У вас є менший розмір +Płacę kartą,I pay by card,Я плачу картой,Я плачу карткою +Ile to kosztuje razem,How much is it in total,Сколько это стоит в общем,Скільки це коштує загалом +Ten sklep jest zamknięty,This shop is closed,Этот магазин закрыт,Цей магазин зачинений +Supermarket jest blisko domu,The supermarket is close to home,Супермаркет находится близко к дому,Супермаркет знаходиться близько до дому +Potrzebuję mleka i chleba,I need milk and bread,Мне нужны молоко и хлеб,Мені потрібні молоко і хліб +Ta sukienka jest bardzo ładna,This dress is very pretty,Это платье очень красивое,Ця сукня дуже гарна +Mieszkam w Warszawie,I live in Warsaw,Я живу в Варшаве,Я живу у Варшаві +Szkoła jest niedaleko parku,The school is near the park,Школа находится недалеко от парка,Школа знаходиться недалеко від парку +Biblioteka jest otwarta do szóstej,The library is open until six,Библиотека открыта до шести,Бібліотека відкрита до шостої +W mieście jest dużo sklepów,There are many shops in the city,В городе много магазинов,У місті багато магазинів +Lubię spacerować w parku,I like walking in the park,Я люблю гулять в парке,Я люблю гуляти в парку +Dworzec jest obok szpitala,The station is next to the hospital,Вокзал находится рядом с больницей,Вокзал знаходиться поруч з лікарнею +Jedziemy na wakacje nad morze,We are going on holiday to the sea,Мы едем в отпуск на море,Ми їдемо у відпустку на море +To muzeum jest bardzo stare,This museum is very old,Этот музей очень старый,Цей музей дуже старий +Restauracja jest na rogu ulicy,The restaurant is on the street corner,Ресторан находится на углу улицы,Ресторан знаходиться на розі вулиці +Mój dom jest mały ale ładny,My house is small but nice,Мой дом маленький но красивый,Мій дім маленький але гарний +Jak masz na imię,What is your name,Как тебя зовут,Як тебе звати +Co robisz,What are you doing,Что ты делаешь,Що ти робиш +Gdzie mieszkasz,Where do you live,Где ты живёшь,Де ти живеш +Czy mówisz po angielsku,Do you speak English,Ты говоришь по-английски,Ти розмовляєш англійською +Kim jesteś z zawodu,What is your profession,Кто ты по профессии,Хто ти за професією +Czy lubisz muzykę,Do you like music,Тебе нравится музыка,Тобі подобається музика +Kiedy masz urodziny,When is your birthday,Когда у тебя день рождения,Коли у тебе день народження +Czy masz braci lub siostry,Do you have brothers or sisters,У тебя есть братья или сёстры,У тебе є брати чи сестри +Dlaczego jesteś smutny,Why are you sad,Почему ты грустный,Чому ти сумний +Co lubisz robić w wolnym czasie,What do you like to do in your free time,Что ты любишь делать в свободное время,Що ти любиш робити у вільний час +Moja koszula jest niebieska,My shirt is blue,Моя рубашка синяя,Моя сорочка синя +Ten samochód jest czerwony,This car is red,Эта машина красная,Ця машина червона +Kot jest czarny i biały,The cat is black and white,Кот чёрно-белый,Кіт чорно-білий +Mam zielony plecak,I have a green backpack,У меня зелёный рюкзак,У мене зелений рюкзак +Kwiaty w ogrodzie są żółte,The flowers in the garden are yellow,Цветы в саду жёлтые,Квіти в саду жовті +To jest mój telefon,This is my phone,Это мой телефон,Це мій телефон +Gdzie są moje klucze,Where are my keys,Где мои ключи,Де мої ключі +Na stole leży książka,There is a book on the table,На столе лежит книга,На столі лежить книга +Mam nowy komputer,I have a new computer,У меня новый компьютер,У мене новий комп'ютер +To wszystko na dzisiaj,That's all for today,Это всё на сегодня,Це все на сьогодні +To jest mój pokój,This is my room,Это моя комната,Це моя кімната +W kuchni gotuję obiad,I cook dinner in the kitchen,Я готовлю обед на кухне,Я готую обід на кухні +Łazienka jest obok sypialni,The bathroom is next to the bedroom,Ванная рядом со спальней,Ванна кімната поруч зі спальнею +Mam duży salon,I have a big living room,У меня большая гостиная,У мене велика вітальня +Okno w moim pokoju jest duże,The window in my room is big,Окно в моей комнате большое,Вікно в моїй кімнаті велике +Drzwi są otwarte,The door is open,Дверь открыта,Двері відчинені +W domu mam dwa piętra,My house has two floors,В моём доме два этажа,У моєму домі два поверхи +Lubię siedzieć na balkonie,I like sitting on the balcony,Я люблю сидеть на балконе,Я люблю сидіти на балконі +Ogród jest za domem,The garden is behind the house,Сад находится за домом,Сад знаходиться за будинком +Mieszkanie jest na trzecim piętrze,The flat is on the third floor,Квартира на третьем этаже,Квартира на третьому поверсі +NoszÄ™ czarne buty,I wear black shoes,Я ношу чёрную обувь,Я ношу чорне взуття +Ubieram ciepłą kurtkę zimą,I wear a warm jacket in winter,Зимой я ношу тёплую куртку,Взимку я ношу теплу куртку +Ta czapka jest dla ciebie,This hat is for you,Эта шапка для тебя,Ця шапка для тебе +Mam nową sukienkę na wesele,I have a new dress for the wedding,У меня новое платье на свадьбу,У мене нова сукня на весілля +Te spodnie są za długie,These trousers are too long,Эти брюки слишком длинные,Ці штани занадто довгі +Włóż szalik bo jest zimno,Put on a scarf because it's cold,Надень шарф потому что холодно,Одягни шарф бо холодно +Lubię nosić kolorowe koszule,I like wearing colorful shirts,Я люблю носить цветные рубашки,Я люблю носити кольорові сорочки +Gdzie kupiłeś te rękawiczki,Where did you buy these gloves,Где ты купил эти перчатки,Де ти купив ці рукавички +Moje okulary są na stole,My glasses are on the table,Мои очки на столе,Мої окуляри на столі +Ten sweter jest bardzo miękki,This sweater is very soft,Этот свитер очень мягкий,Цей светр дуже м'який +Idę do szkoły o ósmej,I go to school at eight,Я иду в школу в восемь,Я йду до школи о восьмій +Uczę się matematyki,I study mathematics,Я учу математику,Я вивчаю математику +Mam dzisiaj trzy lekcje,I have three lessons today,Сегодня у меня три урока,Сьогодні в мене три уроки +Nauczycielka jest bardzo miła,The teacher is very nice,Учительница очень добрая,Вчителька дуже добра +Piszę zadanie domowe,I am writing my homework,Я пишу домашнее задание,Я пишу домашнє завдання +W klasie jest dwadzieścia uczniów,There are twenty students in the class,В классе двадцать учеников,У класі двадцять учнів +Lubię przerwę między lekcjami,I like the break between lessons,Мне нравится перерыв между уроками,Мені подобається перерва між уроками +Mam plecak pełen książek,I have a backpack full of books,У меня рюкзак полный книг,У мене рюкзак повний книг +Egzamin jest w piątek,The exam is on Friday,Экзамен в пятницу,Іспит у п'ятницю +Czytamy nową lekturę,We are reading a new book,Мы читаем новую книгу,Ми читаємо нову книгу +Mam psa i kota,I have a dog and a cat,У меня есть собака и кот,У мене є собака і кіт +Pies biega po parku,The dog is running in the park,Собака бегает по парку,Собака бігає по парку +Kot śpi na kanapie,The cat is sleeping on the sofa,Кот спит на диване,Кіт спить на дивані +W zoo widzieliśmy słonia,We saw an elephant at the zoo,В зоопарке мы видели слона,У зоопарку ми бачили слона +Ptaki śpiewają rano,Birds sing in the morning,Птицы поют утром,Птахи співають вранці +Ryby pływają w akwarium,Fish swim in the aquarium,Рыбы плавают в аквариуме,Риби плавають в акваріумі +Konie są bardzo silne,Horses are very strong,Лошади очень сильные,Коні дуже сильні +Mój królik je marchewkę,My rabbit eats a carrot,Мой кролик ест морковь,Мій кролик їсть моркву +Krowy dają mleko,Cows give milk,Коровы дают молоко,Корови дають молоко +Lubię oglądać filmy o zwierzętach,I like watching movies about animals,Я люблю смотреть фильмы о животных,Я люблю дивитися фільми про тварин +Mam długie włosy,I have long hair,У меня длинные волосы,У мене довге волосся +Boli mnie noga,My leg hurts,У меня болит нога,У мене болить нога +Jestem bardzo szczęśliwy,I am very happy,Я очень счастлив,Я дуже щасливий +Ona jest zmęczona po pracy,She is tired after work,Она устала после работы,Вона втомлена після роботи +Czuję się dzisiaj świetnie,I feel great today,Сегодня я чувствую себя отлично,Сьогодні я почуваюся чудово +Jestem trochę zdenerwowany,I am a bit nervous,Я немного нервничаю,Я трохи нервую +Mam duże oczy i krótkie włosy,I have big eyes and short hair,У меня большие глаза и короткие волосы,У мене великі очі і коротке волосся +On jest głodny i chce jeść,He is hungry and wants to eat,Он голоден и хочет есть,Він голодний і хоче їсти +Jestem dumny z mojej pracy,I am proud of my work,Я горжусь своей работой,Я пишаюся своєю роботою +Czasem czuję się samotny,Sometimes I feel lonely,Иногда я чувствую себя одиноким,Іноді я почуваюся самотнім +W niedzielę śpię dłużej,On Sunday I sleep longer,В воскресенье я сплю дольше,У неділю я сплю довше +Biorę prysznic każdego ranka,I take a shower every morning,Я принимаю душ каждое утро,Я приймаю душ щоранку +RobiÄ™ zakupy w sobotÄ™,I do the shopping on Saturday,Я делаю покупки в субботу,Я роблю покупки в суботу +Piszę wiadomość do przyjaciela,I am writing a message to my friend,Я пишу сообщение другу,Я пишу повідомлення другу +Dzwonię do mamy co wieczór,I call my mom every evening,Я звоню маме каждый вечер,Я телефоную мамі щовечора +Słucham muzyki podczas pracy,I listen to music while working,Я слушаю музыку во время работы,Я слухаю музику під час роботи +Ćwiczę jogę rano,I do yoga in the morning,Я занимаюсь йогой утром,Я займаюся йогою вранці +Karmię kota przed pracą,I feed the cat before work,Я кормлю кота перед работой,Я годую кота перед роботою +Podlewam kwiaty co dwa dni,I water the flowers every two days,Я поливаю цветы каждые два дня,Я поливаю квіти кожні два дні +Wychodzę z domu o ósmej,I leave home at eight,Я выхожу из дома в восемь,Я виходжу з дому о восьмій +Jadę do pracy samochodem,I drive to work by car,Я езжу на работу на машине,Я їжджу на роботу машиною +Wolę pociąg niż autobus,I prefer the train over the bus,Я предпочитаю поезд автобусу,Я віддаю перевагу потягу над автобусом +Rower stoi w garażu,The bike is in the garage,Велосипед стоит в гараже,Велосипед стоїть у гаражі +Metro jest szybkie i tanie,The subway is fast and cheap,Метро быстрое и дешёвое,Метро швидке і дешеве +Czekam na przystanku dziesięć minut,I wait at the stop for ten minutes,Я жду на остановке десять минут,Я чекаю на зупинці десять хвилин +Samolot ląduje o północy,The plane lands at midnight,Самолёт приземляется в полночь,Літак приземляється опівночі +Taksówka jest droga ale wygodna,A taxi is expensive but comfortable,Такси дорогое но удобное,Таксі дороге але зручне +Idę pieszo do sklepu,I walk to the shop,Я иду пешком в магазин,Я йду пішки до магазину +Statek płynie do portu,The ship sails to the port,Корабль плывёт в порт,Корабель пливе до порту +Muszę zatankować samochód,I have to refuel the car,Мне нужно заправить машину,Мені потрібно заправити машину +Zadzwonię do ciebie później,I will call you later,Я позвоню тебе позже,Я подзвоню тобі пізніше +Napisz do mnie wiadomość,Write me a message,Напиши мне сообщение,Напиши мені повідомлення +Mój telefon jest wyłączony,My phone is off,Мой телефон выключен,Мій телефон вимкнений +Nie słyszę cię dobrze,I can't hear you well,Я плохо тебя слышу,Я погано тебе чую +Zostaw wiadomość po sygnale,Leave a message after the beep,Оставьте сообщение после сигнала,Залиште повідомлення після сигналу +Czy masz mój numer,Do you have my number,У тебя есть мой номер,Ти маєш мій номер +Rozmawiamy przez internet,We talk over the internet,Мы разговариваем через интернет,Ми розмовляємо через інтернет +Wyślę ci zdjęcie,I will send you a photo,Я пришлю тебе фото,Я надішлю тобі фото +Muszę naładować telefon,I have to charge my phone,Мне нужно зарядить телефон,Мені потрібно зарядити телефон +Zadzwoń jak dojedziesz,Call when you arrive,Позвони когда приедешь,Подзвони коли приїдеш +Lubię słodycze,I like sweets,Я люблю сладости,Я люблю солодощі +Nie lubię wstawać wcześnie,I don't like getting up early,Я не люблю рано вставать,Я не люблю рано вставати +Uwielbiam podróżować,I love traveling,Я обожаю путешествовать,Я обожнюю подорожувати +Nienawidzę czekać w kolejce,I hate waiting in line,Я ненавижу стоять в очереди,Я ненавиджу стояти в черзі +Wolę zimę od lata,I prefer winter to summer,Я предпочитаю зиму лету,Я віддаю перевагу зимі над літом +Bardzo lubię ten kolor,I really like this color,Мне очень нравится этот цвет,Мені дуже подобається цей колір +Nie interesuje mnie polityka,I am not interested in politics,Меня не интересует политика,Мене не цікавить політика +Lubimy razem gotować,We like cooking together,Мы любим готовить вместе,Ми любимо готувати разом +Ona nie lubi hałasu,She doesn't like noise,Она не любит шум,Вона не любить шум +Uwielbiam zapach kawy,I love the smell of coffee,Я обожаю запах кофе,Я обожнюю запах кави +Otwórz okno proszę,Open the window please,Открой окно пожалуйста,Відкрий вікно будь ласка +Zamknij drzwi,Close the door,Закрой дверь,Закрий двері +Usiądź tutaj,Sit here,Сядь здесь,Сядь тут +Poczekaj chwilę,Wait a moment,Подожди немного,Зачекай хвилинку +Chodź ze mną,Come with me,Пойдём со мной,Ходімо зі мною +Nie martw się,Don't worry,Не волнуйся,Не хвилюйся +Wszystko będzie dobrze,Everything will be fine,Всё будет хорошо,Все буде добре +To jest bardzo proste,This is very simple,Это очень просто,Це дуже просто +Masz rację,You are right,Ты прав,Ти маєш рацію +Miłego dnia,Have a nice day,Хорошего дня,Гарного дня \ No newline at end of file diff --git a/sentences_a2.csv b/sentences_a2.csv new file mode 100644 index 0000000..75d1829 --- /dev/null +++ b/sentences_a2.csv @@ -0,0 +1,101 @@ +polish,english,russian,ukrainian +Wczoraj byłem w kinie,Yesterday I was at the cinema,Вчера я был в кино,Вчора я був у кіно +Obejrzeliśmy ciekawy film,We watched an interesting movie,Мы посмотрели интересный фильм,Ми подивилися цікавий фільм +W zeszłym roku pojechałem do Włoch,Last year I went to Italy,В прошлом году я ездил в Италию,Минулого року я їздив до Італії +Spotkałam starą przyjaciółkę,I met an old friend,Я встретила старую подругу,Я зустріла стару подругу +Kupiliśmy nowy samochód,We bought a new car,Мы купили новую машину,Ми купили нову машину +Nie mogłem spać całą noc,I couldn't sleep all night,Я не мог спать всю ночь,Я не міг спати всю ніч +Skończyłam studia w zeszłym roku,I finished my studies last year,Я закончила учёбу в прошлом году,Я закінчила навчання минулого року +Zapomniałem klucza w domu,I forgot my key at home,Я забыл ключ дома,Я забув ключ вдома +Rozmawialiśmy o pracy przez godzinę,We talked about work for an hour,Мы разговаривали о работе целый час,Ми розмовляли про роботу цілу годину +Ona urodziła się w Krakowie,She was born in Krakow,Она родилась в Кракове,Вона народилася в Кракові +W przyszłym tygodniu pojadę do rodziny,Next week I will go to my family,На следующей неделе я поеду к семье,Наступного тижня я поїду до родини +Będziemy szukać nowego mieszkania,We will be looking for a new flat,Мы будем искать новую квартиру,Ми будемо шукати нову квартиру +Planuję zmienić pracę,I am planning to change jobs,Я планирую сменить работу,Я планую змінити роботу +Chciałbym nauczyć się nowego języka,I would like to learn a new language,Я хотел бы выучить новый язык,Я хотів би вивчити нову мову +Za miesiąc zaczynam nowy kurs,In a month I am starting a new course,Через месяц я начинаю новый курс,Через місяць я починаю новий курс +Mam nadzieję że pogoda będzie dobra,I hope the weather will be good,Я надеюсь что погода будет хорошей,Я сподіваюся що погода буде гарною +Zamierzam odwiedzić rodziców w niedzielę,I intend to visit my parents on Sunday,Я собираюсь навестить родителей в воскресенье,Я маю намір відвідати батьків у неділю +Będę pracować z domu jutro,I will work from home tomorrow,Завтра я буду работать из дома,Завтра я працюватиму з дому +Chcemy kupić dom za kilka lat,We want to buy a house in a few years,Мы хотим купить дом через несколько лет,Ми хочемо купити будинок за кілька років +Wkrótce zdam egzamin z polskiego,I will soon pass my Polish exam,Скоро я сдам экзамен по польскому,Скоро я складу іспит з польської +Moim zdaniem ten film jest nudny,In my opinion this movie is boring,По-моему этот фильм скучный,На мою думку цей фільм нудний +Wolę herbatę niż kawę,I prefer tea over coffee,Я предпочитаю чай кофе,Я віддаю перевагу чаю над кавою +Uważam że to dobry pomysł,I think it is a good idea,Я считаю что это хорошая идея,Я вважаю що це гарна ідея +Bardziej podoba mi się góra niż morze,I like the mountains more than the sea,Мне больше нравятся горы чем море,Мені більше подобаються гори ніж море +Nie zgadzam się z tobą,I don't agree with you,Я не согласен с тобой,Я не погоджуюся з тобою +Myślę że powinniśmy odpocząć,I think we should rest,Я думаю нам стоит отдохнуть,Я думаю нам варто відпочити +To jest najlepsza restauracja w mieście,This is the best restaurant in the city,Это лучший ресторан в городе,Це найкращий ресторан у місті +Wydaje mi się że masz rację,It seems to me that you are right,Мне кажется что ты прав,Мені здається що ти маєш рацію +Wolałabym zostać w domu,I would rather stay at home,Я бы предпочла остаться дома,Я б краще залишилась вдома +Nie mam nic przeciwko temu,I don't mind that,Я не против этого,Я не проти цього +Musimy zarezerwować bilety na pociąg,We have to book train tickets,Нам нужно забронировать билеты на поезд,Нам потрібно забронювати квитки на потяг +Samolot odlatuje o szóstej rano,The plane departs at six in the morning,Самолёт вылетает в шесть утра,Літак вилітає о шостій ранку +Zgubiliśmy się w nowym mieście,We got lost in the new city,Мы заблудились в новом городе,Ми загубилися в новому місті +Hotel był blisko plaży,The hotel was close to the beach,Отель был близко к пляжу,Готель був близько до пляжу +Musimy przesiąść się na inny autobus,We have to change to a different bus,Нам нужно пересесть на другой автобус,Нам потрібно пересісти на інший автобус +Podróż trwała prawie dziesięć godzin,The journey took almost ten hours,Поездка длилась почти десять часов,Подорож тривала майже десять годин +Czy mogę zobaczyć pana paszport,May I see your passport sir,Могу я увидеть ваш паспорт,Чи можу я побачити ваш паспорт +Zwiedzaliśmy muzeum przez cały dzień,We visited the museum all day,Мы осматривали музей целый день,Ми оглядали музей цілий день +Zapomnieliśmy zabrać mapę,We forgot to bring a map,Мы забыли взять карту,Ми забули взяти карту +To była nasza najlepsza podróż,That was our best trip,Это была наша лучшая поездка,Це була наша найкраща подорож +Boli mnie głowa,I have a headache,У меня болит голова,У мене болить голова +Muszę iść do lekarza,I have to go to the doctor,Мне нужно пойти к врачу,Мені потрібно піти до лікаря +Czuję się dzisiaj lepiej,I feel better today,Сегодня я чувствую себя лучше,Сьогодні я почуваюся краще +Mam katar i kaszel,I have a runny nose and a cough,У меня насморк и кашель,У мене нежить і кашель +Lekarz przepisał mi leki,The doctor prescribed me medicine,Врач выписал мне лекарства,Лікар виписав мені ліки +Powinieneś więcej odpoczywać,You should rest more,Тебе следует больше отдыхать,Тобі слід більше відпочивати +Złamałem rękę podczas gry w piłkę,I broke my arm while playing football,Я сломал руку во время игры в футбол,Я зламав руку під час гри у футбол +Ważne jest jedzenie zdrowej żywności,It is important to eat healthy food,Важно есть здоровую пищу,Важливо їсти здорову їжу +Codziennie biegam żeby być zdrowym,I run every day to be healthy,Я бегаю каждый день чтобы быть здоровым,Я бігаю щодня щоб бути здоровим +Ona źle się czuje od rana,She has felt unwell since the morning,Она плохо себя чувствует с утра,Вона погано почувається з ранку +Pracuję jako nauczyciel w szkole,I work as a teacher at a school,Я работаю учителем в школе,Я працюю вчителем у школі +Mam dużo pracy w tym tygodniu,I have a lot of work this week,У меня много работы на этой неделе,У мене багато роботи цього тижня +Uczę się polskiego od roku,I have been learning Polish for a year,Я учу польский уже год,Я вивчаю польську вже рік +Muszę przygotować raport na jutro,I have to prepare a report for tomorrow,Мне нужно подготовить отчёт на завтра,Мені потрібно підготувати звіт на завтра +Mój szef jest bardzo wymagający,My boss is very demanding,Мой начальник очень требовательный,Мій керівник дуже вимогливий +Studiuję informatykę na uniwersytecie,I study computer science at university,Я изучаю информатику в университете,Я вивчаю інформатику в університеті +Mam egzamin w przyszłym tygodniu,I have an exam next week,У меня экзамен на следующей неделе,У мене іспит наступного тижня +Pracujemy razem nad nowym projektem,We are working together on a new project,Мы вместе работаем над новым проектом,Ми разом працюємо над новим проєктом +Codziennie chodzę na zajęcia,I go to classes every day,Я каждый день хожу на занятия,Я щодня ходжу на заняття +Trudno jest znaleźć dobrą pracę,It is difficult to find a good job,Трудно найти хорошую работу,Важко знайти хорошу роботу +Ten dom jest większy niż tamten,This house is bigger than that one,Этот дом больше чем тот,Цей будинок більший ніж той +Zima jest zimniejsza niż jesień,Winter is colder than autumn,Зима холоднее осени,Зима холодніша за осінь +Moja siostra jest młodsza ode mnie,My sister is younger than me,Моя сестра младше меня,Моя сестра молодша за мене +Ten pociąg jest szybszy niż autobus,This train is faster than the bus,Этот поезд быстрее автобуса,Цей потяг швидший за автобус +To jest najdroższy sklep w mieście,This is the most expensive shop in the city,Это самый дорогой магазин в городе,Це найдорожчий магазин у місті +On mówi lepiej po angielsku niż ja,He speaks English better than me,Он говорит по-английски лучше меня,Він говорить англійською краще за мене +To zadanie jest trudniejsze od poprzedniego,This task is harder than the previous one,Это задание сложнее предыдущего,Це завдання складніше за попереднє +Wolę tę kawiarnię bo jest cichsza,I prefer this café because it is quieter,Я предпочитаю это кафе потому что оно тише,Я віддаю перевагу цій кав'ярні бо вона тихіша +Ten telefon jest tańszy niż tamten,This phone is cheaper than that one,Этот телефон дешевле того,Цей телефон дешевший за той +To był najlepszy dzień w moim życiu,That was the best day of my life,Это был лучший день в моей жизни,Це був найкращий день у моєму житті +W wolnym czasie gram na gitarze,In my free time I play guitar,В свободное время я играю на гитаре,У вільний час я граю на гітарі +Uwielbiam czytać kryminały,I love reading crime novels,Я обожаю читать детективы,Я обожнюю читати детективи +Co weekend jeżdżę na rowerze,Every weekend I ride a bike,Каждые выходные я катаюсь на велосипеде,Кожні вихідні я катаюся на велосипеді +Interesuję się fotografią,I am interested in photography,Я интересуюсь фотографией,Я цікавлюся фотографією +Lubię gotować dla przyjaciół,I like cooking for friends,Я люблю готовить для друзей,Я люблю готувати для друзів +Chodzę na siłownię trzy razy w tygodniu,I go to the gym three times a week,Я хожу в спортзал три раза в неделю,Я ходжу до спортзалу тричі на тиждень +Moim hobby jest malowanie,My hobby is painting,Моё хобби рисование,Моє хобі малювання +Gramy w piłkę nożną w niedziele,We play football on Sundays,Мы играем в футбол по воскресеньям,Ми граємо у футбол по неділях +Ona uwielbia tańczyć,She loves dancing,Она обожает танцевать,Вона обожнює танцювати +Zbieram stare monety,I collect old coins,Я собираю старые монеты,Я збираю старі монети +Przepraszam jak dojść do dworca,Excuse me how do I get to the station,Извините как добраться до вокзала,Перепрошую як дістатися до вокзалу +Proszę iść prosto a potem skręcić w lewo,Please go straight and then turn left,Идите прямо а потом поверните налево,Ідіть прямо а потім поверніть ліворуч +Czy może mi pan pomóc,Can you help me sir,Вы можете мне помочь,Чи можете ви мені допомогти +Nie wiem gdzie jest najbliższy przystanek,I don't know where the nearest stop is,Я не знаю где ближайшая остановка,Я не знаю де найближча зупинка +To jest bardzo daleko stąd,It is very far from here,Это очень далеко отсюда,Це дуже далеко звідси +Czy mógłby pan powtórzyć,Could you repeat sir,Не могли бы вы повторить,Чи могли б ви повторити +Poszukuję apteki w pobliżu,I am looking for a pharmacy nearby,Я ищу аптеку поблизости,Я шукаю аптеку поблизу +Dziękuję za pomoc,Thank you for the help,Спасибо за помощь,Дякую за допомогу +Zgubiłem drogę do hotelu,I lost my way to the hotel,Я заблудился по дороге в отель,Я загубив дорогу до готелю +Ile czasu zajmuje dojazd do centrum,How long does it take to get downtown,Сколько времени занимает дорога до центра,Скільки часу займає дорога до центру +Mój komputer się zepsuł,My computer broke down,Мой компьютер сломался,Мій комп'ютер зламався +Nie mogę znaleźć kluczy,I can't find my keys,Я не могу найти ключи,Я не можу знайти ключі +Zapomniałem hasła do konta,I forgot my account password,Я забыл пароль от аккаунта,Я забув пароль від акаунта +Autobus się spóźnia,The bus is late,Автобус опаздывает,Автобус запізнюється +Skończył mi się czas,I ran out of time,У меня закончилось время,У мене закінчився час +Mam problem z internetem,I have a problem with the internet,У меня проблема с интернетом,У мене проблема з інтернетом +Zepsuła się pralka,The washing machine broke,Стиральная машина сломалась,Пральна машина зламалася +Musimy naprawić dach,We have to fix the roof,Нам нужно починить крышу,Нам потрібно полагодити дах +Sąsiedzi są bardzo głośni,The neighbors are very loud,Соседи очень шумные,Сусіди дуже галасливі +To był naprawdę trudny dzień,That was a really difficult day,Это был действительно трудный день,Це був справді важкий день \ No newline at end of file diff --git a/sentences_b1.csv b/sentences_b1.csv new file mode 100644 index 0000000..5fc2904 --- /dev/null +++ b/sentences_b1.csv @@ -0,0 +1,101 @@ +polish,english,russian,ukrainian +Gdybym miał więcej czasu podróżowałbym częściej,If I had more time I would travel more often,Если бы у меня было больше времени я бы путешествовал чаще,Якби я мав більше часу я б подорожував частіше +Gdyby padało zostalibyśmy w domu,If it rained we would stay at home,Если бы шёл дождь мы бы остались дома,Якби йшов дощ ми б залишились удома +Zrobiłbym to inaczej gdybym mógł,I would do it differently if I could,Я бы сделал это по-другому если бы мог,Я б зробив це по-іншому якби міг +Gdybyś mnie zapytał pomógłbym ci,If you had asked me I would have helped you,Если бы ты меня спросил я бы тебе помог,Якби ти мене запитав я б тобі допоміг +Co byś zrobił na moim miejscu,What would you do in my place,Что бы ты сделал на моём месте,Що б ти зробив на моєму місці +Gdyby nie deszcz poszlibyśmy na spacer,If it weren't for the rain we would go for a walk,Если бы не дождь мы бы пошли гулять,Якби не дощ ми б пішли на прогулянку +Chciałbym żeby to było prostsze,I wish it were simpler,Я хотел бы чтобы это было проще,Я хотів би щоб це було простіше +Gdybym wygrał na loterii kupiłbym dom,If I won the lottery I would buy a house,Если бы я выиграл в лотерею я бы купил дом,Якби я виграв у лотерею я б купив будинок +Na twoim miejscu porozmawiałbym z szefem,In your place I would talk to the boss,На твоём месте я бы поговорил с начальником,На твоєму місці я б поговорив з керівником +Gdyby wszyscy się starali świat byłby lepszy,If everyone tried the world would be better,Если бы все старались мир был бы лучше,Якби всі старались світ був би кращим +Uważam że edukacja jest najważniejsza,I believe education is most important,Я считаю что образование важнее всего,Я вважаю що освіта найважливіша +Moim zdaniem warto inwestować w siebie,In my opinion it's worth investing in yourself,По-моему стоит инвестировать в себя,На мою думку варто інвестувати в себе +Zgadzam się z tym stwierdzeniem tylko częściowo,I agree with this statement only partially,Я согласен с этим утверждением лишь частично,Я погоджуюся з цим твердженням лише частково +Z jednej strony to dobry pomysł z drugiej ryzykowny,On one hand it's a good idea on the other it's risky,С одной стороны это хорошая идея с другой рискованная,З одного боку це гарна ідея з іншого ризикована +Wydaje mi się że przesadzasz,It seems to me that you are exaggerating,Мне кажется что ты преувеличиваешь,Мені здається що ти перебільшуєш +Trudno powiedzieć kto ma rację,It's hard to say who is right,Трудно сказать кто прав,Важко сказати хто має рацію +Nie da się tego zrobić bez wsparcia innych,It's impossible to do this without others' support,Это невозможно сделать без поддержки других,Це неможливо зробити без підтримки інших +Według mnie powinniśmy zmienić nasze podejście,In my view we should change our approach,По-моему нам следует изменить наш подход,На мою думку нам слід змінити наш підхід +Argument ten wydaje się dość przekonujący,This argument seems quite convincing,Этот аргумент кажется довольно убедительным,Цей аргумент здається досить переконливим +Nie zawsze zgadzam się z opinią większości,I don't always agree with the majority opinion,Я не всегда согласен с мнением большинства,Я не завжди погоджуюся з думкою більшості +Awansowałem po dwóch latach pracy,I got promoted after two years of work,Я получил повышение через два года работы,Я отримав підвищення через два роки роботи +Zmiana pracy była dla mnie dużym wyzwaniem,Changing jobs was a big challenge for me,Смена работы была для меня большим вызовом,Зміна роботи була для мене великим викликом +Rozważam założenie własnej firmy,I am considering starting my own company,Я подумываю открыть собственную фирму,Я розглядаю можливість відкрити власну фірму +Praca zdalna daje mi więcej wolności,Remote work gives me more freedom,Удалённая работа даёт мне больше свободы,Віддалена робота дає мені більше свободи +Współpraca w zespole nie zawsze jest łatwa,Teamwork is not always easy,Работа в команде не всегда даётся легко,Робота в команді не завжди дається легко +Muszę rozwijać swoje umiejętności zawodowe,I need to develop my professional skills,Мне нужно развивать свои профессиональные навыки,Мені потрібно розвивати свої професійні навички +Wypalenie zawodowe dotyka coraz więcej ludzi,Burnout affects more and more people,Профессиональное выгорание затрагивает всё больше людей,Професійне вигорання торкається дедалі більшої кількості людей +Negocjacje trwały kilka godzin,The negotiations lasted several hours,Переговоры длились несколько часов,Переговори тривали кілька годин +Ostatecznie zdecydowałem się zostać w tej firmie,In the end I decided to stay at this company,В итоге я решил остаться в этой компании,Зрештою я вирішив залишитися в цій компанії +Praca daje mi poczucie spełnienia,Work gives me a sense of fulfillment,Работа даёт мне ощущение самореализации,Робота дає мені відчуття самореалізації +Powinniśmy ograniczyć zużycie plastiku,We should reduce plastic consumption,Нам следует сократить потребление пластика,Нам слід скоротити споживання пластику +Zmiany klimatyczne dotyczą nas wszystkich,Climate change concerns all of us,Изменение климата касается всех нас,Зміна клімату стосується всіх нас +Segreguję śmieci od kilku lat,I have been sorting trash for several years,Я сортирую мусор уже несколько лет,Я сортую сміття вже кілька років +Coraz więcej ludzi rezygnuje z samochodu,More and more people are giving up cars,Всё больше людей отказываются от машины,Дедалі більше людей відмовляються від машини +Zanieczyszczenie powietrza wpływa na nasze zdrowie,Air pollution affects our health,Загрязнение воздуха влияет на наше здоровье,Забруднення повітря впливає на наше здоров'я +Warto sadzić drzewa w miastach,It's worth planting trees in cities,Стоит сажать деревья в городах,Варто садити дерева в містах +Musimy oszczędzać wodę na co dzień,We must save water every day,Нам нужно экономить воду каждый день,Нам потрібно економити воду щодня +Odnawialne źródła energii stają się popularniejsze,Renewable energy sources are becoming more popular,Возобновляемые источники энергии становятся всё популярнее,Відновлювані джерела енергії стають дедалі популярнішими +Ludzie coraz bardziej dbają o środowisko,People are increasingly taking care of the environment,Люди всё больше заботятся об окружающей среде,Люди дедалі більше турбуються про довкілля +To miasto wprowadziło zakaz jednorazowych toreb,This city introduced a ban on single-use bags,Этот город ввёл запрет на одноразовые пакеты,Це місто запровадило заборону на одноразові пакети +Sztuczna inteligencja zmienia nasz sposób pracy,Artificial intelligence is changing the way we work,Искусственный интеллект меняет то как мы работаем,Штучний інтелект змінює те як ми працюємо +Nie wyobrażam sobie życia bez telefonu,I can't imagine life without a phone,Я не представляю жизни без телефона,Я не уявляю життя без телефону +Wiele osób spędza za dużo czasu w internecie,Many people spend too much time online,Многие люди проводят слишком много времени в интернете,Багато людей проводять забагато часу в інтернеті +Ta aplikacja pomaga mi organizować dzień,This app helps me organize my day,Это приложение помогает мне организовать день,Цей додаток допомагає мені організувати день +Technologia rozwija się szybciej niż kiedykolwiek,Technology is developing faster than ever,Технологии развиваются быстрее чем когда-либо,Технології розвиваються швидше ніж будь-коли +Praca zdalna stała się możliwa dzięki internetowi,Remote work became possible thanks to the internet,Удалённая работа стала возможной благодаря интернету,Віддалена робота стала можливою завдяки інтернету +Powinniśmy uważać na to co udostępniamy online,We should be careful about what we share online,Нам следует быть осторожными с тем что мы публикуем в сети,Нам слід бути обережними з тим що ми публікуємо в мережі +Media społecznościowe wpływają na nasze samopoczucie,Social media affects our wellbeing,Социальные сети влияют на наше самочувствие,Соціальні мережі впливають на наше самопочуття +Kupiłem nowy laptop bo stary się zepsuł,I bought a new laptop because the old one broke,Я купил новый ноутбук потому что старый сломался,Я купив новий ноутбук бо старий зламався +Roboty coraz częściej zastępują ludzi w pracy,Robots are increasingly replacing people at work,Роботы всё чаще заменяют людей на работе,Роботи дедалі частіше замінюють людей на роботі +W wiadomościach mówili o nowych przepisach,The news talked about new regulations,В новостях говорили о новых правилах,У новинах говорили про нові правила +Bezrobocie w tym regionie znacznie wzrosło,Unemployment in this region has increased significantly,Безработица в этом регионе значительно выросла,Безробіття в цьому регіоні значно зросло +Wielu ludzi protestowało przeciwko podwyżkom cen,Many people protested against price increases,Многие люди протестовали против повышения цен,Багато людей протестували проти підвищення цін +Rząd ogłosił nowe reformy edukacyjne,The government announced new educational reforms,Правительство объявило о новых реформах образования,Уряд оголосив нові освітні реформи +Nierówności społeczne są coraz bardziej widoczne,Social inequalities are becoming more and more visible,Социальное неравенство становится всё более заметным,Соціальна нерівність стає дедалі помітнішою +Wybory odbędą się w przyszłym miesiącu,The elections will take place next month,Выборы состоятся в следующем месяце,Вибори відбудуться наступного місяця +Media często przesadzają z opisem wydarzeń,The media often exaggerate the description of events,Медиа часто преувеличивают описание событий,Медіа часто перебільшують опис подій +Coraz więcej młodych ludzi emigruje za pracą,More and more young people emigrate for work,Всё больше молодых людей эмигрируют за работой,Дедалі більше молодих людей емігрують за роботою +Społeczeństwo powinno wspierać osoby starsze,Society should support elderly people,Общество должно поддерживать пожилых людей,Суспільство повинно підтримувати літніх людей +Ta decyzja wywołała wiele kontrowersji,This decision caused a lot of controversy,Это решение вызвало много споров,Це рішення викликало багато суперечок +Podróżowanie nauczyło mnie otwartości na inne kultury,Traveling taught me to be open to other cultures,Путешествия научили меня открытости к другим культурам,Подорожі навчили мене відкритості до інших культур +W tym kraju ludzie mają inne zwyczaje niż my,People in this country have different customs than us,В этой стране у людей другие обычаи чем у нас,У цій країні в людей інші звичаї ніж у нас +Byłem zaskoczony gościnnością mieszkańców,I was surprised by the hospitality of the residents,Я был удивлён гостеприимством жителей,Я був здивований гостинністю мешканців +Ta podróż zmieniła moje spojrzenie na życie,This trip changed my outlook on life,Эта поездка изменила мой взгляд на жизнь,Ця подорож змінила мій погляд на життя +Zwiedziliśmy stare miasto pełne zabytków,We visited the old town full of historical monuments,Мы осмотрели старый город полный достопримечательностей,Ми оглянули старе місто повне пам'яток +Lokalna kuchnia bardzo mi się spodobała,I really liked the local cuisine,Мне очень понравилась местная кухня,Мені дуже сподобалась місцева кухня +Warto poznawać tradycje innych narodów,It's worth learning about the traditions of other nations,Стоит узнавать традиции других народов,Варто пізнавати традиції інших народів +Podczas podróży poznałem ludzi z całego świata,During the trip I met people from all over the world,Во время поездки я познакомился с людьми со всего мира,Під час подорожі я познайомився з людьми з усього світу +Ten festiwal przyciąga turystów z całej Europy,This festival attracts tourists from all over Europe,Этот фестиваль привлекает туристов со всей Европы,Цей фестиваль приваблює туристів з усієї Європи +Kultura tego regionu jest bardzo zróżnicowana,The culture of this region is very diverse,Культура этого региона очень разнообразна,Культура цього регіону дуже різноманітна +Przyjaźń wymaga zaufania i cierpliwości,Friendship requires trust and patience,Дружба требует доверия и терпения,Дружба вимагає довіри й терпіння +Rzadko się kłócimy ale gdy tak długo nie rozmawiamy,We rarely argue but when we do we don't talk for a long time,Мы редко ссоримся но когда это случается долго не разговариваем,Ми рідко сваримося але коли так довго не розмовляємо +Trudno jest utrzymać kontakt z dawnymi znajomymi,It's difficult to stay in touch with old acquaintances,Трудно поддерживать связь со старыми знакомыми,Важко підтримувати зв'язок зі старими знайомими +Nasza relacja z czasem stała się silniejsza,Our relationship has become stronger over time,Наши отношения со временем стали крепче,Наші стосунки з часом стали міцнішими +Warto rozmawiać otwarcie o swoich uczuciach,It's worth talking openly about your feelings,Стоит открыто говорить о своих чувствах,Варто відкрито говорити про свої почуття +Czasami trudno zrozumieć punkt widzenia drugiej osoby,Sometimes it's hard to understand another person's point of view,Иногда трудно понять точку зрения другого человека,Іноді важко зрозуміти точку зору іншої людини +Znamy się od dzieciństwa,We have known each other since childhood,Мы знакомы с детства,Ми знайомі з дитинства +Wsparcie rodziny pomogło mi przetrwać trudny czas,My family's support helped me survive a difficult time,Поддержка семьи помогла мне пережить трудное время,Підтримка родини допомогла мені пережити важкий час +Zaufanie buduje się latami a traci w chwilę,Trust is built over years and lost in a moment,Доверие строится годами а теряется в один миг,Довіра будується роками а втрачається за мить +Nie każda znajomość musi przerodzić się w przyjaźń,Not every acquaintance has to turn into a friendship,Не каждое знакомство должно перерасти в дружбу,Не кожне знайомство має перерости в дружбу +Marzę o tym żeby zwiedzić cały świat,I dream of traveling the whole world,Я мечтаю объехать весь мир,Я мрію об'їхати весь світ +Mam nadzieję osiągnąć sukces w tej dziedzinie,I hope to achieve success in this field,Я надеюсь добиться успеха в этой области,Я сподіваюся досягти успіху в цій галузі +Planuję zdobyć nowe kwalifikacje zawodowe,I plan to gain new professional qualifications,Я планирую получить новую профессиональную квалификацию,Я планую здобути нову професійну кваліфікацію +Moim celem jest otworzenie własnej działalności,My goal is to start my own business,Моя цель открыть собственный бизнес,Моя мета відкрити власний бізнес +Chciałbym w przyszłości mieszkać za granicą,I would like to live abroad in the future,В будущем я хотел бы жить за границей,У майбутньому я хотів би жити за кордоном +Staram się realizować swoje marzenia krok po kroku,I try to pursue my dreams step by step,Я стараюсь воплощать свои мечты шаг за шагом,Я намагаюся втілювати свої мрії крок за кроком +Wierzę że ciężka praca się opłaca,I believe that hard work pays off,Я верю что тяжёлый труд окупается,Я вірю що важка праця окупається +Postawiłem sobie ambitny cel na ten rok,I set myself an ambitious goal for this year,Я поставил себе амбициозную цель на этот год,Я поставив собі амбітну мету на цей рік +Nie boję się zmian wręcz przeciwnie ich szukam,I am not afraid of change quite the opposite I seek it,Я не боюсь перемен наоборот ищу их,Я не боюся змін навпаки шукаю їх +Wierzę że za kilka lat będę w innym miejscu w życiu,I believe that in a few years I will be in a different place in life,Я верю что через несколько лет буду в другом месте в жизни,Я вірю що за кілька років буду в іншому місці в житті +Czas płynie szybciej niż nam się wydaje,Time flies faster than we think,Время летит быстрее чем нам кажется,Час минає швидше ніж нам здається +Szczęście nie zawsze zależy od pieniędzy,Happiness doesn't always depend on money,Счастье не всегда зависит от денег,Щастя не завжди залежить від грошей +Każdy z nas popełnia błędy i uczy się na nich,Each of us makes mistakes and learns from them,Каждый из нас совершает ошибки и учится на них,Кожен з нас робить помилки і вчиться на них +Warto doceniać to co się ma,It's worth appreciating what you have,Стоит ценить то что имеешь,Варто цінувати те що маєш +Wolność wiąże się z odpowiedzialnością,Freedom is connected with responsibility,Свобода связана с ответственностью,Свобода пов'язана з відповідальністю +Trudne doświadczenia często czynią nas silniejszymi,Difficult experiences often make us stronger,Трудный опыт часто делает нас сильнее,Важкий досвід часто робить нас сильнішими +Nie zawsze łatwo jest podjąć właściwą decyzję,It's not always easy to make the right decision,Не всегда легко принять правильное решение,Не завжди легко прийняти правильне рішення +Ludzie zmieniają się wraz z upływem czasu,People change as time passes,Люди меняются с течением времени,Люди змінюються з плином часу +Sens życia każdy definiuje inaczej,Everyone defines the meaning of life differently,Каждый по-своему определяет смысл жизни,Кожен по-своєму визначає сенс життя +Warto czasem zatrzymać się i pomyśleć o priorytetach,Sometimes it's worth stopping to think about priorities,Иногда стоит остановиться и подумать о приоритетах,Іноді варто зупинитися і подумати про пріоритети \ No newline at end of file diff --git a/services/__init__.py b/services/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/services/grid_generator.py b/services/grid_generator.py new file mode 100644 index 0000000..e69de29 diff --git a/services/word_bank.py b/services/word_bank.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..8cd21f0 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Tests package for Filwords PL backend.""" \ No newline at end of file diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..31e4ca7 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,120 @@ +""" +Общие фикстуры для тестов Filwords PL. +Использует реальную БД (dev), но с изолированными тестовыми данными. +После каждого теста данные удаляются. +""" +import pytest +from config import DB_CONFIG +from database import get_pool, init_db + + +# Тестовые ID — чтобы не пересекаться с реальными данными +TEST_USER_ID = 999999999 +TEST_TOPIC_ID = "test_topic_zzz" + + +@pytest.fixture(scope="session", autouse=True) +async def setup_database(): + """Один раз на сессию: инициализирует БД (миграции).""" + await init_db() + yield + + +@pytest.fixture +async def conn(): + """Соединение с БД для одного теста.""" + pool = await get_pool() + async with pool.acquire() as connection: + yield connection + + +@pytest.fixture +async def test_user(conn): + """Создаёт тестового юзера, удаляет после теста.""" + await conn.execute(""" + INSERT INTO users (telegram_id, username, app_language, current_level) + VALUES ($1, 'test_user', 'ru', 'A2') + ON CONFLICT (telegram_id) DO NOTHING + """, TEST_USER_ID) + + yield TEST_USER_ID + + # Cleanup — удаляем всё, что связано с юзером. + # ВАЖНО: порядок — сначала дочерние таблицы (FK), потом родительские. + await conn.execute("DELETE FROM user_skill_mastery WHERE user_id = $1", TEST_USER_ID) + await conn.execute("DELETE FROM user_learning_answers WHERE user_id = $1", TEST_USER_ID) + await conn.execute("DELETE FROM user_lesson_progress WHERE user_id = $1", TEST_USER_ID) + await conn.execute("DELETE FROM user_topic_progress WHERE user_id = $1", TEST_USER_ID) + await conn.execute("DELETE FROM user_achievements WHERE user_id = $1", TEST_USER_ID) + await conn.execute("DELETE FROM learning_sessions WHERE user_id = $1", TEST_USER_ID) + await conn.execute("DELETE FROM users WHERE telegram_id = $1", TEST_USER_ID) + + +@pytest.fixture +async def test_session(conn, test_user): + """Тестовая сессия обучения (для FK в user_learning_answers).""" + row = await conn.fetchrow(""" + INSERT INTO learning_sessions (user_id, level_code, topic_id, session_type) + VALUES ($1, 'A2', 'test_topic', 'lesson') + RETURNING id + """, test_user) + + session_id = row["id"] + yield session_id + + # 🔧 ФИКС: сначала удаляем ответы, ссылающиеся на сессию (FK), + # только потом саму сессию + await conn.execute("DELETE FROM user_learning_answers WHERE session_id = $1", session_id) + await conn.execute("DELETE FROM learning_sessions WHERE id = $1", session_id) + + +@pytest.fixture +async def test_topic(conn): + """Создаёт тестовый топик, удаляет после теста.""" + await conn.execute(""" + INSERT INTO learning_topics (topic_id, level_code, order_number, name_pl, name_ru, name_uk, name_en) + VALUES ($1, 'A2', 999, 'Test Topic', 'Тестовый топик', 'Тестовий топік', 'Test Topic') + ON CONFLICT (topic_id) DO NOTHING + """, TEST_TOPIC_ID) + + yield TEST_TOPIC_ID + + await conn.execute("DELETE FROM learning_lessons WHERE topic_id = $1", TEST_TOPIC_ID) + await conn.execute("DELETE FROM learning_topics WHERE topic_id = $1", TEST_TOPIC_ID) + + +@pytest.fixture +async def create_test_lesson(conn, test_topic): + """ + Фабрика: создаёт урок с произвольным skill_tag. + Использование: await create_test_lesson("test_skill") + """ + created_ids = [] + + async def _create(skill_tag: str, order: int = 1) -> str: + lesson_id = f"test_lesson_{skill_tag}" + await conn.execute(""" + INSERT INTO learning_lessons + (lesson_id, topic_id, order_number, skill_tag, + title_pl, title_ru, title_uk, title_en, + explanation_pl, explanation_ru, explanation_uk, explanation_en) + VALUES ($1, $2, $3, $4, + 'Test Lesson', 'Тестовый урок', 'Тестовий урок', 'Test Lesson', + 'Test', 'Test', 'Test', 'Test') + ON CONFLICT (lesson_id) DO NOTHING + """, lesson_id, test_topic, order, skill_tag) + created_ids.append(lesson_id) + return lesson_id + + yield _create + + for lid in created_ids: + await conn.execute("DELETE FROM learning_lessons WHERE lesson_id = $1", lid) + + +@pytest.fixture +async def clean_mastery(conn, test_user): + """Очищает user_skill_mastery для тестового юзера до и после теста.""" + await conn.execute("DELETE FROM user_skill_mastery WHERE user_id = $1", test_user) + yield + await conn.execute("DELETE FROM user_skill_mastery WHERE user_id = $1", test_user) \ No newline at end of file diff --git a/tests/test_achievements.py b/tests/test_achievements.py new file mode 100644 index 0000000..a5ce455 --- /dev/null +++ b/tests/test_achievements.py @@ -0,0 +1,75 @@ +""" +Тесты для check_and_award_achievements. +Проверяют выдачу ачивок без дублей. +""" +import pytest + + +async def test_achievement_not_awarded_twice(conn, test_user): + """ + Если ачивка уже выдана — второй раз не выдаётся. + """ + from routers.achievements import check_and_award_achievements + + # Чистим ачивки тестового юзера + await conn.execute("DELETE FROM user_achievements WHERE user_id = $1", test_user) + + # Первый раз + result1 = await check_and_award_achievements(test_user, "levels_completed", 1000) + + # Второй раз с тем же значением + result2 = await check_and_award_achievements(test_user, "levels_completed", 1000) + + # Второй раз должен вернуть пустой список + assert len(result2) == 0 + + # Cleanup + await conn.execute("DELETE FROM user_achievements WHERE user_id = $1", test_user) + + +async def test_achievement_awarded_for_matching_value(conn, test_user): + """ + Ачивка выдаётся, если value соответствует требованию. + """ + from routers.achievements import check_and_award_achievements + + await conn.execute("DELETE FROM user_achievements WHERE user_id = $1", test_user) + + # Уровень 1 завершён — ачивка "first_level" (levels_completed >= 1) + result = await check_and_award_achievements(test_user, "levels_completed", 1) + + # Должна быть минимум одна ачивка (first_level) + assert len(result) >= 1 + assert any("first" in a["code"].lower() or "level" in a["code"].lower() for a in result) + + await conn.execute("DELETE FROM user_achievements WHERE user_id = $1", test_user) + + +async def test_achievement_returns_localized_name(conn, test_user): + """ + Название ачивки возвращается на языке пользователя (RU). + """ + from routers.achievements import check_and_award_achievements + + await conn.execute("DELETE FROM user_achievements WHERE user_id = $1", test_user) + await conn.execute("UPDATE users SET app_language = 'ru' WHERE telegram_id = $1", test_user) + + result = await check_and_award_achievements(test_user, "levels_completed", 1) + + assert len(result) >= 1 + # Название должно быть непустой строкой (RU) + assert result[0]["name"] # не пусто + assert isinstance(result[0]["name"], str) + + await conn.execute("DELETE FROM user_achievements WHERE user_id = $1", test_user) + + +async def test_achievement_unknown_type_returns_empty(conn, test_user): + """ + Неизвестный тип требования → пустой список. + """ + from routers.achievements import check_and_award_achievements + + result = await check_and_award_achievements(test_user, "nonexistent_type_xyz", 999) + + assert result == [] \ No newline at end of file diff --git a/tests/test_mastery.py b/tests/test_mastery.py new file mode 100644 index 0000000..a34fc7d --- /dev/null +++ b/tests/test_mastery.py @@ -0,0 +1,171 @@ +""" +Тесты для update_skill_mastery. +Проверяют формулы расчёта mastery, retention, trend. +""" +import pytest +from datetime import datetime, timedelta + + +# ───────────────────────────────────────────── +# ХЕЛПЕР: вставить ответ напрямую в БД +# ───────────────────────────────────────────── + +async def insert_answer( + conn, + user_id: int, + session_id: int, + skill_tag: str, + correct: bool, + question_type: str = "recognition", + wrong_because: str | None = None, + days_ago: int = 0, +): + """Вставляет один ответ в user_learning_answers.""" + created_at = datetime.now() - timedelta(days=days_ago) + await conn.execute(""" + INSERT INTO user_learning_answers ( + user_id, session_id, level_code, topic_id, question_id, + selected_answer, correct, skill_tag, question_type, + context_type, difficulty, time_taken_ms, hint_used, + wrong_because, is_final_answer, created_at + ) VALUES ( + $1, $2, 'A2', 'test_topic', 'test_q', + 'x', $3, $4, $5, + 'lesson_practice', 1, 5000, FALSE, + $6, TRUE, $7 + ) + """, user_id, session_id, correct, skill_tag, question_type, wrong_because, created_at) + + +# ───────────────────────────────────────────── +# ТЕСТЫ +# ───────────────────────────────────────────── + +async def test_mastery_no_answers_returns_none(conn, test_user, clean_mastery): + """Если у юзера нет ответов по skill_tag — функция возвращает None.""" + from routers.learning import update_skill_mastery + + result = await update_skill_mastery(conn, test_user, "nonexistent_skill") + assert result is None + + +async def test_mastery_100_percent_accuracy(conn, test_user, test_session, clean_mastery): + """Если все ответы правильные — accuracy = 100, mastery = высокая.""" + from routers.learning import update_skill_mastery + + for _ in range(5): + await insert_answer(conn, test_user, test_session, "test_skill", correct=True) + + result = await update_skill_mastery(conn, test_user, "test_skill") + + assert result is not None + assert result["attempts"] == 5 + assert result["accuracy"] == 100.0 + assert result["mastery"] >= 90.0 + + +async def test_mastery_0_percent_accuracy(conn, test_user, test_session, clean_mastery): + """Если все ответы неправильные — accuracy = 0, mastery = низкая.""" + from routers.learning import update_skill_mastery + + for _ in range(5): + await insert_answer(conn, test_user, test_session, "test_skill", correct=False, wrong_because="wrong_case") + + result = await update_skill_mastery(conn, test_user, "test_skill") + + assert result is not None + assert result["accuracy"] == 0.0 + assert result["mastery"] <= 30.0 + + +async def test_mastery_50_percent_accuracy(conn, test_user, test_session, clean_mastery): + """50% accuracy → mastery в среднем диапазоне.""" + from routers.learning import update_skill_mastery + + for i in range(6): + await insert_answer(conn, test_user, test_session, "test_skill", correct=(i % 2 == 0)) + + result = await update_skill_mastery(conn, test_user, "test_skill") + + assert result is not None + assert 40.0 <= result["accuracy"] <= 60.0 + assert 40.0 <= result["mastery"] <= 80.0 + + +async def test_mastery_retention_fresh(conn, test_user, test_session, clean_mastery): + """Если последний ответ был сегодня — retention_status = 'fresh'.""" + from routers.learning import update_skill_mastery + + await insert_answer(conn, test_user, test_session, "test_skill", correct=True, days_ago=0) + await insert_answer(conn, test_user, test_session, "test_skill", correct=True, days_ago=0) + + result = await update_skill_mastery(conn, test_user, "test_skill") + + assert result["retention_status"] == "fresh" + + +async def test_mastery_retention_needs_review(conn, test_user, test_session, clean_mastery): + """Если последний ответ 10 дней назад — retention_status = 'needs_review'.""" + from routers.learning import update_skill_mastery + + await insert_answer(conn, test_user, test_session, "test_skill", correct=True, days_ago=10) + await insert_answer(conn, test_user, test_session, "test_skill", correct=True, days_ago=10) + + result = await update_skill_mastery(conn, test_user, "test_skill") + + assert result["retention_status"] == "needs_review" + + +async def test_mastery_retention_overdue(conn, test_user, test_session, clean_mastery): + """Если последний ответ 20 дней назад — retention_status = 'overdue'.""" + from routers.learning import update_skill_mastery + + await insert_answer(conn, test_user, test_session, "test_skill", correct=True, days_ago=20) + await insert_answer(conn, test_user, test_session, "test_skill", correct=True, days_ago=20) + + result = await update_skill_mastery(conn, test_user, "test_skill") + + assert result["retention_status"] == "overdue" + + +async def test_mastery_trend_improving(conn, test_user, test_session, clean_mastery): + """Если последние 3 ответа лучше, чем общая точность — trend = 'improving'.""" + from routers.learning import update_skill_mastery + + # 7 старых неправильных, 3 свежих правильных + for _ in range(7): + await insert_answer(conn, test_user, test_session, "test_skill", correct=False, days_ago=5) + for _ in range(3): + await insert_answer(conn, test_user, test_session, "test_skill", correct=True, days_ago=0) + + result = await update_skill_mastery(conn, test_user, "test_skill") + + # 3 правильных из 10 = 30% accuracy, но recent_accuracy = 100% → improving + assert result["trend"] == "improving" + + +async def test_mastery_trend_declining(conn, test_user, test_session, clean_mastery): + """Если последние 3 ответа хуже, чем общая точность — trend = 'declining'.""" + from routers.learning import update_skill_mastery + + # 7 старых правильных, 3 свежих неправильных + for _ in range(7): + await insert_answer(conn, test_user, test_session, "test_skill", correct=True, days_ago=5) + for _ in range(3): + await insert_answer(conn, test_user, test_session, "test_skill", correct=False, days_ago=0) + + result = await update_skill_mastery(conn, test_user, "test_skill") + + assert result["trend"] == "declining" + + +async def test_mastery_trend_insufficient_data(conn, test_user, test_session, clean_mastery): + """Если меньше 3 ответов — trend = 'insufficient_data'.""" + from routers.learning import update_skill_mastery + + await insert_answer(conn, test_user, test_session, "test_skill", correct=True) + await insert_answer(conn, test_user, test_session, "test_skill", correct=True) + + result = await update_skill_mastery(conn, test_user, "test_skill") + + assert result["trend"] == "insufficient_data" \ No newline at end of file diff --git a/tests/test_orchestrator.py b/tests/test_orchestrator.py new file mode 100644 index 0000000..75de0d6 --- /dev/null +++ b/tests/test_orchestrator.py @@ -0,0 +1,99 @@ +""" +Тесты для get_next_lesson. +Проверяют приоритеты: overdue → weak → test → next. +""" +import pytest +from datetime import datetime, timedelta + + +# ───────────────────────────────────────────── +# ХЕЛПЕРЫ +# ───────────────────────────────────────────── + +async def set_user_level(conn, user_id: int, level: str): + await conn.execute("UPDATE users SET current_level = $1 WHERE telegram_id = $2", level, user_id) + + +async def insert_mastery( + conn, + user_id: int, + skill_tag: str, + mastery: float, + retention: str = "fresh", + attempts: int = 3, + days_since: int = 0, +): + """Вставляет запись в user_skill_mastery.""" + last_attempt = datetime.now() - timedelta(days=days_since) + await conn.execute(""" + INSERT INTO user_skill_mastery ( + user_id, skill_tag, mastery_score, retention_status, + attempts_count, last_attempt_at + ) VALUES ($1, $2, $3, $4, $5, $6) + ON CONFLICT (user_id, skill_tag) DO UPDATE SET + mastery_score = $3, + retention_status = $4, + attempts_count = $5, + last_attempt_at = $6 + """, user_id, skill_tag, mastery, retention, attempts, last_attempt) + + +# ───────────────────────────────────────────── +# ТЕСТЫ +# ───────────────────────────────────────────── + +async def test_orchestrator_prioritizes_overdue(conn, test_user, create_test_lesson, clean_mastery): + """Если есть overdue навык — он выбирается первым.""" + from routers.orchestrator import get_next_lesson + + await set_user_level(conn, test_user, "A2") + await create_test_lesson("test_skill") + await insert_mastery(conn, test_user, "test_skill", mastery=50.0, retention="overdue", days_since=20) + + result = await get_next_lesson(conn, test_user) + + assert result["type"] == "review" + assert result["reason"] == "overdue" + + +async def test_orchestrator_prioritizes_weak(conn, test_user, create_test_lesson, clean_mastery): + """Если нет overdue, но есть weak (mastery < 75) — выбирается он.""" + from routers.orchestrator import get_next_lesson + + await set_user_level(conn, test_user, "A2") + await create_test_lesson("test_skill") + await insert_mastery(conn, test_user, "test_skill", mastery=50.0, retention="fresh", days_since=1) + + result = await get_next_lesson(conn, test_user) + + assert result["type"] == "review" + assert result["reason"] == "weak_mastery" + + +async def test_orchestrator_prefers_overdue_over_weak(conn, test_user, create_test_lesson, clean_mastery): + """Если есть и overdue, и weak — overdue важнее.""" + from routers.orchestrator import get_next_lesson + + await set_user_level(conn, test_user, "A2") + await create_test_lesson("weak_skill", order=1) + await create_test_lesson("overdue_skill", order=2) + + await insert_mastery(conn, test_user, "weak_skill", mastery=40.0, retention="fresh", days_since=1) + await insert_mastery(conn, test_user, "overdue_skill", mastery=60.0, retention="overdue", days_since=20) + + result = await get_next_lesson(conn, test_user) + + assert result["reason"] == "overdue" + + +async def test_orchestrator_weak_requires_min_attempts(conn, test_user, create_test_lesson, clean_mastery): + """Weak skill требует минимум 2 попытки — если меньше, он не выбирается.""" + from routers.orchestrator import get_next_lesson + + await set_user_level(conn, test_user, "A2") + await create_test_lesson("test_skill") + await insert_mastery(conn, test_user, "test_skill", mastery=50.0, retention="fresh", attempts=1) + + result = await get_next_lesson(conn, test_user) + + assert result["reason"] != "weak_mastery" \ No newline at end of file diff --git a/words_a1.csv b/words_a1.csv new file mode 100644 index 0000000..ba6ebce --- /dev/null +++ b/words_a1.csv @@ -0,0 +1,758 @@ +polish,english,russian,ukrainian +adres,address,адрес,адреса +akapit,paragraph,абзац,абзац +akcja,action,действие,дія +aktor,actor,актёр,актор +aktorka,actress,актриса,акторка +aktywność,activity,активность,активність +ale,but,но,але +artykuł,article,статья,стаття +artysta,artist,артист,артист +autobus,bus,автобус,автобус +babcia,grandmother,бабушка,бабуся +banan,banana,банан,банан +bardzo,very,очень,дуже +basen,swimming pool,бассейн,басейн +będę,I will be,я буду,я буду +bez,without,без,без +biały,white,белый,білий +biblioteka,library,библиотека,бібліотека +biedny,poor,бедный,бідний +biegać,to run,бегать,бігати +bilet,ticket,билет,квиток +biurko,desk,письменный стол,письмовий стіл +biuro,office,офис,офіс +biznes,business,бизнес,бізнес +błąd,mistake / error,ошибка,помилка +blisko,close / near,близко,близько +blond,blond / blonde,светловолосый,білявий +bogaty,rich,богатый,багатий +brać,to take,брать,брати +brat,brother,брат,брат +brązowy,brown,коричневый,коричневий +brudny,dirty,грязный,брудний +budować,to build,строить,будувати +budynek,building,здание,будівля +but,shoe,туфля / ботинок,черевик / туфля +butelka,bottle,бутылка,пляшка +cebula,onion,лук,цибуля +cena,price,цена,ціна +centrum,centre / center,центр,центр +chciałbym,I would like,я хотел бы,я хотів би +chcieć,to want,хотеть,хотіти +chleb,bread,хлеб,хліб +chłodny,cool,прохладный,прохолодний +chłopak,boy / boyfriend,парень,хлопець +chłopiec,boy,мальчик,хлопчик +chodzić,to walk / to go regularly,ходить,ходити +chory,sick / ill,больной,хворий +ciąć,to cut,резать,різати +ciało,body,тело,тіло +ciasto,cake,торт,торт +cichy,quiet,тихий,тихий +ciemny,dark,тёмный,темний +ciepły,warm,тёплый,теплий +ciężarówka,truck,грузовик,вантажівка +ciocia,aunt,тётя,тітка +cokolwiek,anything,что угодно,що завгодно +córka,daughter,дочь,донька +coś,something,что-то,щось +cudowny,wonderful,чудесный,чудовий +cukier,sugar,сахар,цукор +ćwiartka,quarter,четверть,чверть +ćwiczenie,exercise,упражнение,вправа +czarny,black,чёрный,чорний +czas,time,время,час +czasami,sometimes,иногда,іноді +czekać,wait,ждать,чекати +czekolada,chocolate,шоколад,шоколад +czerwiec,June,июнь,червень +czerwony,red,красный,червоний +cześć,hello; hi,привет,привіт +część,part; piece,часть,частина +często,often,часто,часто +czterdzieści,forty,сорок,сорок +czternaście,fourteen,четырнадцать,чотирнадцять +cztery,four,четыре,чотири +czujny,alert; vigilant,бдительный,пильний +Czwartek,Thursday,четверг,четвер +czwarty,fourth,четвёртый,четвертий +czysty,clean,чистый,чистий +czytać,read,читать,читати +czytanie,reading,чтение,читання +czytelnik,reader,читатель,читач +dać,give,дать,дати +daleko,far,далеко,далеко +darmowy,free,бесплатный,безкоштовний +decydować,decide,решать,вирішувати +deszcz,rain,дождь,дощ +dialog,dialogue,диалог,діалог +dieta,diet,диета,дієта +dla,for,для,для +dlaczego,why,почему,чому +długi,long,длинный,довгий +długopis,pen,ручка,ручка +do,to; until,до,до +dobry,good,хороший,добрий +dobrze,well; okay,хорошо,добре +dodać,add,добавить,додати +dodatkowy,additional,дополнительный,додатковий +dołączyć,join,присоединиться,приєднатися +dom,house; home,дом,дім +dorosły,adult,взрослый,дорослий +dość,enough,достаточно,достатньо +doskonały,excellent; perfect,отличный; идеальный,відмінний; ідеальний +dostać,get; receive,получить,отримати +dowolny,any,любой,будь-який +droga,road; way,дорога; путь,дорога; шлях +drogi,expensive; dear,дорогой,дорогий +drużyna,team,команда,команда +drzewo,tree,дерево,дерево +drzwi,door,дверь,двері +dużo,a lot; much; many,много,багато +duży,big; large,большой,великий +dwa,two,два,два +dwadzieścia,twenty,двадцать,двадцять +dwanaście,twelve,двенадцать,дванадцять +dyskutować,discuss,обсуждать,обговорювати +dziadek,grandfather,дедушка,дідусь +dziecko,child,ребёнок,дитина +dziękować,thank,благодарить,дякувати +dziękuję,thank you,спасибо,дякую +dzielić,divide; share,делить; делиться,ділити; ділитися +dzień,day,день,день +dziesięć,ten,десять,десять +dziewczyna,girl,девушка; девочка,дівчина; дівчинка +dziewięć,nine,девять,дев'ять +dziewięćdziesiąt,ninety,девяносто,дев'яносто +dziewiętnaście,nineteen,девятнадцать,дев'ятнадцять +dżinsy,jeans,джинсы,джинси +dziś,today,сегодня,сьогодні +dźwięk,sound,звук,звук +egzamin,exam,экзамен,іспит +ekscytujący,exciting,захватывающий,захопливий +fakt,fact,факт,факт +fałszywy,false; fake,ложный; поддельный,хибний; підроблений +fantastyczny,fantastic,фантастический; замечательный,фантастичний; чудовий +farba,paint,краска,фарба +farma,farm,ферма,ферма +festiwal,festival,фестиваль,фестиваль +film,film; movie,фильм,фільм +finałowy,final,финальный,фінальний +fioletowy,purple,фиолетовый,фіолетовий +firma,company; firm,компания,компанія +forma,form; shape,форма,форма +fortepian,piano,фортепиано,фортепіано +fotografia,photograph; photography,фотография; фотография как искусство,фотографія; фотографія як мистецтво +fraza,phrase,фраза,фраза +funt,pound,фунт,фунт +gazeta,newspaper,газета,газета +gdzie,where,где,де +geografia,geography,география,географія +gitara,guitar,гитара,гітара +głodny,hungry,голодный,голодний +głowa,head,голова,голова +główny,main; main/primary,главный,головний +godzina,hour; o'clock,час,година +góra,mountain; hill,гора; холм,гора; пагорб +gorący,hot,горячий,гарячий +gotować,to cook,готовить,готувати +gotowanie,cooking,готовка; приготовление пищи,готування +gotowy,ready,готовый,готовий +gra,game; play,игра,гра +grać,to play,играть,грати +gracz,player,игрок,гравець +gruby,fat; thick,толстый,товстий +grudzień,December,декабрь,грудень +grupa,group,группа,група +gwiazda,star,звезда,зірка +hej,hey; hi,эй; привет,гей; привіт +herbata,tea,чай,чай +historia,history; story,история; рассказ,історія; розповідь +hobby,hobby,хобби,хобі +hotel,hotel,отель; гостиница,готель +ich,their,их,їхній +imię,name; first name,имя,ім'я +impreza,party; event,вечеринка; мероприятие,вечірка; захід +informacja,information,информация,інформація +inny,other; different,другой; иной,інший +inteligentny,intelligent; smart,умный; интеллектуальный,розумний; інтелектуальний +interesujący,interesting,интересный,цікавий +internet,internet,интернет,інтернет +iść,to go; to walk,идти,йти +ją,her,её,її +jabłko,apple,яблоко,яблуко +jajko,egg,яйцо,яйце +jak,how; like,как,як +jeden,one; one (masculine),один,один +jedenaście,eleven,одиннадцать,одинадцять +jednak,however; nevertheless,однако; всё же,однак; все ж +jedzenie,food; eating,еда; питание,їжа; харчування +jego,his,его,його +jeść,to eat,есть,їсти +jeśli,if,если,якщо +jeździć,to travel; to ride; to go regularly,ездить; путешествовать,їздити; подорожувати +język,language; tongue,язык,мова; язик +jutro,tomorrow,завтра,завтра +kanapka,sandwich,бутерброд; сэндвич,бутерброд; сендвіч +kapelusz,hat,шляпа,капелюх +kąpiel,bath; bathing,ванна; купание,ванна; купання +kariera,career,карьера,кар'єра +karta,card; menu,карта; карточка; меню,картка; меню +kawa,coffee,кофе,кава +kawał,piece; bit,кусок; немного,шматок; трохи +kawiarnia,café; coffee shop,кафе,кав'ярня; кафе +każdy,every; each; everyone,каждый,кожен +kelner,waiter,официант,офіціант +kiedy,when,когда,коли +kiedykolwiek,ever; at any time,когда-либо,коли-небудь +kierowca,driver,водитель,водій +kilka,several; a few,несколько,кілька +klasa,class,класс,клас +klub,club,клуб,клуб +klucz,key,ключ,ключ +kobieta,woman,женщина,жінка +kochać,to love,любить,кохати; любити +kolacja,dinner; supper,ужин,вечеря +kolor,color,цвет,колір +komputer,computer,компьютер,комп'ютер +koń,horse,лошадь,кінь +koncert,concert,концерт,концерт +koniec,end,конец,кінець +koszt,cost,стоимость; цена,вартість; ціна +koszula,shirt,рубашка,сорочка +koszykówka,basketball,баскетбол,баскетбол +kot,cat,кот; кошка,кіт; кішка +kraj,country; land,страна; государство,країна; держава +krótki,short,короткий,короткий +krowa,cow,корова,корова +krzesło,chair,стул,стілець +książka,book,книга,книга +kto,who,кто,хто +który,which; which one,который; какой,який; котрий +ktoś,someone; somebody,кто-то; кто-нибудь,хтось; хтось +kubek,cup; mug,чашка,чашка +kuchnia,kitchen; cuisine,кухня; кухня (национальная),кухня +kultura,culture,культура,культура +kupić,to buy,купить,купити +kurczak,chicken,курица; цыплёнок,курка; курча +kurs,course; course of study,курс,курс +kurtka,jacket,куртка,куртка +kuzyn,cousin (male),двоюродный брат; кузен,двоюрідний брат; кузен +kwiat,flower,цветок,квітка +kwiecień,April,апрель,квітень +ładny,pretty; nice,красивый; симпатичный,гарний; симпатичний +lato,summer,лето,літо +łatwy,easy,лёгкий,легкий +łazienka,bathroom,ванная комната,ванна кімната +lekarz,doctor,врач,лікар +lekcja,lesson,урок,урок +lepszy,better,лучший; лучше,кращий; краще +lew,lion,лев,лев +leżeć,to lie; to be lying,лежать,лежати +licznik,meter; counter,счётчик; измерительный прибор,лічильник; вимірювальний прилад +linia,line,линия; линия,лінія +lipiec,July,июль,липень +list,letter,письмо,лист +lista,list,список,список +listopad,November,ноябрь,листопад +literować,to spell,произносить по буквам,називати по літерах +lód,ice,лёд,лід +lody,ice cream,мороженое,морозиво +łódź,boat,лодка,човен +lokalny,local,местный,місцевий +lot,flight,полёт; рейс,політ; рейс +lotnisko,airport,аэропорт,аеропорт +łóżko,bed,кровать,ліжко +lub,or,или,або +lubić,to like,любить; нравиться,любити; подобатися +ludzie,people,люди,люди +lunch,lunch,обед; ланч,обід; ланч +luty,February,февраль,лютий +magazyn,magazine; warehouse,журнал; склад,журнал; склад +maj,May,май,травень +mały,small; little,маленький,малий +mama,mum; mother,мама,мама +mapa,map,карта,карта +marchew,carrot,морковь,морква +marzec,March,март,березень +masło,butter,сливочное масло,вершкове масло +maszyna,machine,машина; механизм,машина; механізм +matka,mother,мать,мати +mąż,husband,муж,чоловік +menu,menu,меню,меню +mężczyzna,man,мужчина,чоловік +miasto,city; town,город,місто +mieć,to have,иметь,мати +miejsce,place; seat,место,місце +miesiąc,month,месяц,місяць +mięso,meat,мясо,м'ясо +mieszkanie,flat; apartment,квартира,квартира +mila,mile,миля,миля +milion,million,миллион,мільйон +miły,nice; kind,милый; добрый,милий; добрий +minuta,minute,минута,хвилина +mleko,milk,молоко,молоко +młody,young,молодой,молодий +mnie,me,меня; мне,мене; мені +móc,to be able to; can,мочь,могти +model,model,модель,модель +mógł,could; was able to,мог,міг +mój,my,мой,мій +moment,moment,момент,момент +mówić,to speak; to say,говорить,говорити +może,maybe; perhaps,может быть; возможно,можливо; мабуть +możliwy,possible,возможный,можливий +musieć,to have to; must,быть вынужденным; должен,мусити; бути змушеним +muzeum,museum,музей,музей +muzyka,music,музыка,музика +my,we,мы,ми +myć,to wash,мыть,мити +myśleć,to think,думать,думати +nad,over; above; by,над; выше; у,над; біля +najlepszy,best,лучший,найкращий +najpierw,first; firstly,сначала; сперва,спочатку +najwięcej,the most,больше всего; наиболее,найбільше +napełniać,to fill,наполнять,наповнювати +naprawdę,really,действительно; правда,справді; насправді +nas,us,нас,нас +następny,next,следующий,наступний +nasz,our,наш,наш +naturalny,natural,естественный; натуральный,природний; натуральний +nauczyciel,teacher,учитель,учитель +nauka,learning; science,учёба; наука,навчання; наука +naukowiec,scientist,учёный,науковець +nawet,even,даже,навіть +negatywny,negative,негативный,негативний +nic,nothing,ничего; ничто,нічого; ніщо +nie,no; not,не; нет,не; ні +niebezpieczny,dangerous,опасный,небезпечний +niebieski,blue,синий; голубой,синій; блакитний +niedziela,Sunday,воскресенье,неділя +niektóre,some; certain,некоторые,деякі +niemowlę,baby; infant,младенец,немовля +nienawidzić,to hate,ненавидеть,ненавидіти +niesamowity,amazing; incredible,невероятный; потрясающий,неймовірний; дивовижний +nigdy,never,никогда,ніколи +nikt,nobody; no one,никто,ніхто +niż,than,чем; нежели,ніж +noc,night,ночь,ніч +noga,leg; foot,нога,нога +nos,nose,нос,ніс +nosić,to wear; to carry,носить,носити +notatka,note,заметка; записка,нотатка; записка +nowoczesny,modern,современный,сучасний +nowy,new,новый,новий +nudny,boring,скучный,нудний +numer,number,номер; число,номер; число +obiekt,object; facility,объект,об'єкт +obok,next to; beside,рядом; возле,поруч; біля +obraz,picture; image,картина; изображение,картина; зображення +obszar,area,область; район,область; район +ocean,ocean,океан,океан +odpowiedzieć,to answer; to reply,ответить,відповісти +odwiedzać,to visit,посещать; навещать,відвідувати +odwiedzający,visitor,посетитель,відвідувач +odwrotny,opposite; reverse,обратный; противоположный,зворотний; протилежний +ogień,fire,огонь,вогонь +oglądać,to watch; to look at,смотреть,дивитися +ogród,garden,сад,сад +ojciec,father,отец,батько +okno,window,окно,вікно +oko,eye,глаз,око +okres,period; period of time,период; промежуток времени,період; проміжок часу +ołówek,pencil,карандаш,олівець +on,he,он,він +ona,she,она,вона +oni,they; they (masculine personal),они; они (мужчины/мужская группа),вони; вони (чоловічо-особова група) +opinia,opinion,мнение,думка +opis,description,описание,опис +opisać,to describe,описать,описати +opowieść,story; tale,рассказ; история,розповідь; історія +opublikować,to publish,опубликовать,опублікувати +ortografia,spelling; orthography,правописание,правопис +osiem,eight,восемь,вісім +osiemdziesiąt,eighty,восемьдесят,вісімдесят +osiemnaście,eighteen,восемнадцать,вісімнадцять +osoba,person,человек; лицо,особа; людина +osobisty,personal,личный,особистий +ostatni,last; final,последний; заключительный,останній; заключний +oświadczenie,statement; declaration,заявление; утверждение,заява; твердження +otworzyć,to open,открыть,відкрити +owca,sheep,овца,вівця +owoc,fruit,фрукт,фрукт +oznaczać,to mean; to indicate,означать; обозначать,означати; позначати +pamiętać,to remember,помнить,пам'ятати +papier,paper,бумага,папір +para,pair; couple,пара,пара +parasol,umbrella,зонт,парасоля +park,park,парк,парк +partner,partner,партнёр,партнер +pasować,to fit; to suit,подходить,підходити +paszport,passport,паспорт,паспорт +patrzeć,to look; to watch,смотреть,дивитися +październik,October,октябрь,жовтень +pełny,full,полный,повний +piątek,Friday,пятница,п’ятниця +piąty,fifth,пятый,п’ятий +pić,to drink,пить,пити +pięć,five,пять,п’ять +pięćdziesiąt,fifty,пятьдесят,п’ятдесят +piękny,beautiful,красивый,красивий +pielęgniarka,nurse,медсестра,медсестра +pieniądze,money,деньги,гроші +pieprz,pepper,перец,перець +pies,dog,собака,собака +piętnaście,fifteen,пятнадцать,п’ятнадцять +piłka,ball,мяч,м’яч +piosenka,song,песня,пісня +pisać,to write,писать,писати +pisanie,writing,написание,написання +pisarz,writer,писатель,письменник +płacić,to pay,платить,платити +plan,plan,план,план +płaszcz,coat,пальто,пальто +plaża,beach,пляж,пляж +plecy,back,спина,спина +pływanie,swimming,плавание,плавання +pociąg,train,поезд,поїзд +początek,beginning,начало,початок +pod,under,под,під +podczas,during,во время,під час +podekscytowany,excited,взволнованный,схвильований +podłoga,floor,пол,підлога +podobny,similar,похожий,схожий +podróż,trip / journey,поездка / путешествие,подорож +podróżować,to travel,путешествовать,подорожувати +podwórko,yard,двор,подвір’я +pogoda,weather,погода,погода +pokazać,to show,показать,показати +pokój,room,комната,кімната +policja,police,полиция,поліція +policjant,police officer,полицейский,поліцейський +północ,midnight / north,полночь / север,опівніч / північ +połowa,half,половина,половина +położyć,to put / to lay,положить,покласти +południe,noon / south,полдень / юг,полудень / південь +pomagać,to help,помогать,допомагати +pomarańcza,orange,апельсин,апельсин +pomidor,tomato,помидор,помідор +pomiędzy,between,между,між +pomysł,idea,идея,ідея +poniedziałek,Monday,понедельник,понеділок +popołudnie,afternoon,послеобеденное время,післяобідній час +poprawić,to improve / to correct,улучшить / исправить,покращити / виправити +poprawny,correct,правильный,правильний +popularny,popular,популярный,популярний +porównać,to compare,сравнить,порівняти +posiłek,meal,приём пищи,прийом їжі +potrzebować,to need,нуждаться / нуждаться в,потребувати +powiedzieć,to say / to tell,сказать,сказати +powietrze,air,воздух,повітря +powinien,should,должен,повинен +powód,reason,причина,причина +powszechny,common,распространённый,поширений +powtórzyć,to repeat,повторить,повторити +później,later,позже,пізніше +późno,late,поздно,пізно +pozwolić,to allow / to let,позволить / разрешить,дозволити +pozytywny,positive,положительный,позитивний +praca,work / job,работа,робота +pracować,to work,работать,працювати +pracownik,employee / worker,работник / сотрудник,працівник / співробітник +praktyka,practice,практика,практика +prawdopodobnie,probably,вероятно,ймовірно +prawdziwy,true / real,настоящий / истинный,справжній +prawo,law / right,закон / право,закон / право +preferować,to prefer,предпочитать,надавати перевагу +prezent,gift / present,подарок,подарунок +problem,problem,проблема,проблема +próbować,to try,пытаться / пробовать,намагатися / пробувати +produkt,product,продукт / товар,продукт / товар +program,program,программа,програма +projekt,project,проект,проєкт +proszę,please / you're welcome,пожалуйста / не за что,будь ласка / нема за що +prowadzić,to drive / to lead,водить / руководить,керувати / вести +prysznic,shower,душ,душ +przeciwny,opposite,противоположный,протилежний +przed,before / in front of,перед / до,перед / до +przedmiot,object / subject,предмет,предмет +przedstawić,to introduce / to present,представить,представити +przestraszony,scared / frightened,испуганный,наляканий +przestrzeń,space,пространство,простір +przesunąć,to move / to shift,сдвинуть / передвинуть,посунути / пересунути +przeszłość,past,прошлое,минуле +przez,through / across,через / сквозь,через / крізь +przód,front,передняя часть / перед,передня частина / перед +przybyć,to arrive,прибыть / приехать,прибути / приїхати +przygotować,to prepare,подготовить,підготувати +przyjaciel,friend,друг,друг +przyjazny,friendly,дружелюбный,дружній +przyjść,to come,прийти,прийти +przykład,example,пример,приклад +przynieść,to bring,принести,принести +przyszłość,future,будущее,майбутнє +ptak,bird,птица,птах +pudełko,box,коробка,коробка +punkt,point,точка / пункт,точка / пункт +pyszny,delicious,вкусный,смачний +pytać,to ask,спрашивать,запитувати +pytanie,question,вопрос,питання +rachunek,bill / check,счёт,рахунок +rada,advice,совет,порада +radio,radio,радио,радіо +rano,in the morning,утром,вранці +raport,report,отчёт,звіт +raz,once / one time,раз / один раз,раз / один раз +razem,together,вместе,разом +ręka,hand / arm,рука,рука +restauracja,restaurant,ресторан,ресторан +robić,to do / to make,делать,робити +rodzina,family,семья,сім’я +rok,year,год,рік +rolnik,farmer,фермер,фермер +roślina,plant,растение,рослина +rosnąć,to grow,расти,рости +rower,bicycle / bike,велосипед,велосипед +rozmawiać,to talk,разговаривать,розмовляти +rozmowa,conversation,разговор,розмова +różnica,difference,разница,різниця +różowy,pink,розовый,рожевий +rozumieć,to understand,понимать,розуміти +ruch,movement / traffic,движение / дорожное движение,рух / дорожній рух +rutyna,routine,распорядок / рутина,розпорядок / рутина +ryba,fish,рыба,риба +rynek,market,рынок,ринок +rysować,to draw,рисовать,малювати +ryż,rice,рис,рис +rzecz,thing,вещь,річ +rzeka,river,река,річка +sałatka,salad,салат,салат +samochód,car,автомобиль / машина,автомобіль / машина +samolot,airplane,самолёт,літак +sąsiad,neighbor,сосед,сусід +sąsiedztwo,neighborhood,соседство,сусідство +ściana,wall,стена,стіна +sekcja,section,раздел / секция,розділ / секція +sekunda,second,секунда,секунда +ser,cheese,сыр,сир +siebie,oneself,себя,себе +siedem,seven,семь,сім +siedemdziesiąt,seventy,семьдесят,сімдесят +siedemnaście,seventeen,семнадцать,сімнадцять +siedzieć,to sit,сидеть,сидіти +sierpień,August,август,серпень +silny,strong,сильный,сильний +siłownia,gym,спортзал,спортзал +siostra,sister,сестра,сестра +sklep,shop / store,магазин,магазин +skończyć,to finish,закончить,закінчити +skręcić,to turn,повернуть / свернуть,повернути / звернути +sławny,famous,знаменитый,відомий +śledzić,to follow / to track,следить / отслеживать,стежити / відстежувати +słoń,elephant,слон,слон +słońce,sun,солнце,сонце +słownik,dictionary,словарь,словник +słowo,word,слово,слово +słuchać,to listen,слушать,слухати +słyszeć,to hear,слышать,чути +śmietana,sour cream,сметана,сметана +smutny,sad,грустный,сумний +śniadanie,breakfast,завтрак,сніданок +śnieg,snow,снег,сніг +sobota,Saturday,суббота,субота +sok,juice,сок,сік +sól,salt,соль,сіль +spać,to sleep,спать,спати +specjalny,special,особенный / специальный,особливий / спеціальний +śpiewak,singer,певец,співак +spódnica,skirt,юбка,спідниця +spodnie,trousers / pants,брюки,штани +sport,sport,спорт,спорт +sposób,way / method,способ / метод,спосіб / метод +spotkać,to meet,встретить / встретиться,зустріти / зустрітися +spotkanie,meeting,встреча,зустріч +sprawdzić,to check,проверить,перевірити +sprzedać,to sell,продать,продати +środa,Wednesday,среда,середа +stać,to stand / to cost,стоять / стоить,стояти / коштувати +stacja,station,станция,станція +stary,old,старый,старий +sto,hundred,сто,сто +stół,table,стол,стіл +stolica,capital,столица,столиця +stopa,foot,ступня / стопа,стопа / ступня +straszny,scary / terrible,страшный / ужасный,страшний / жахливий +strona,side / page,сторона / страница,сторона / сторінка +student,student,студент,студент +styczeń,January,январь,січень +styl,style,стиль,стиль +sukces,success,успех,успіх +sukienka,dress,платье,сукня +supermarket,supermarket,супермаркет,супермаркет +sweter,sweater,свитер,светр +świat,world,мир,світ +światło,light,свет,світло +świetny,great / excellent,отличный,чудовий +świnia,pig,свинья,свиня +syn,son,сын,син +sypialnia,bedroom,спальня,спальня +sytuacja,situation,ситуация,ситуація +szary,gray / grey,серый,сірий +szczegół,detail,деталь,деталь +szczęśliwy,happy,счастливый,щасливий +sześć,six,шесть,шість +sześćdziesiąt,sixty,шестьдесят,шістдесят +szesnaście,sixteen,шестнадцать,шістнадцять +szkło,glass,стекло,скло +szkoła,school,школа,школа +szpital,hospital,больница,лікарня +sztuka,art,искусство,мистецтво +szybki,fast / quick,быстрый,швидкий +szybko,quickly / fast,быстро,швидко +tak,yes,да,так +taksówka,taxi,такси,таксі +talerz,plate,тарелка,тарілка +tam,there,там,там +tancerz,dancer,танцор,танцівник +tańczyć,to dance,танцевать,танцювати +tani,cheap,дешёвый,дешевий +taniec,dance,танец,танець +tata,dad / father,папа / отец,тато / батько +teatr,theater / theatre,театр,театр +tekst,text,текст,текст +telefon,telephone / phone,телефон,телефон +telewizor,TV / television,телевизор,телевізор +temat,topic / subject,тема,тема +ten,this / this one,этот,цей +tenis,tennis,теннис,теніс +teraz,now,сейчас,зараз +test,test,тест,тест +też,also / too,тоже / также,теж / також +to,this / it,это,це +toaleta,toilet / restroom,туалет,туалет +torba,bag,сумка,сумка +trudny,difficult / hard,трудный,складний +trzeci,third,третий,третій +trzy,three,три,три +trzydzieści,thirty,тридцать,тридцять +trzynaście,thirteen,тринадцать,тринадцять +turysta,tourist,турист,турист +tutaj,here,здесь,тут +twarz,face,лицо,обличчя +twój,your,твой,твій +tworzyć,to create,создавать,створювати +ty,you,ты,ти +tydzień,week,неделя,тиждень +tylko,only,только,тільки +typ,type / kind,тип / вид,тип / вид +tysiąc,thousand,тысяча,тисяча +tytuł,title,название / заголовок,назва / заголовок +ubrania,clothes,одежда,одяг +ucho,ear,ухо,вухо +uczucie,feeling,чувство,почуття +uczyć,to learn / to teach,учить / учиться,вчити / вчитися +ukończyć,to complete / to finish,закончить / завершить,закінчити +ulica,street,улица,вулиця +ulubiony,favorite,любимый,улюблений +umiejętność,skill / ability,навык / способность,навичка / здатність +umrzeć,to die,умереть,померти +uniwersytet,university,университет,університет +upaść,to fall,упасть,впасти +urodziny,birthday,день рождения,день народження +użyteczny,useful,полезный,корисний +używać,to use,использовать,використовувати +wakacje,holiday / vacation,каникулы / отпуск,канікули / відпустка +warzywo,vegetable,овощ,овоч +wąż,snake,змея,змія +ważny,important,важный,важливий +wciąż,still,всё ещё,досі / все ще +wcześnie,early,рано,рано +wczoraj,yesterday,вчера,вчора +weekend,weekend,выходные,вихідні +wiadomość,message / news,сообщение / новость,повідомлення / новина +wiadomości,news,новости,новини +wideo,video,видео,відео +widzieć,to see,видеть,бачити +więc,so / therefore,так что / поэтому,тому / отже +więcej,more,больше,більше +wieczór,evening,вечер,вечір +wiedzieć,to know,знать,знати +wiek,age,возраст,вік +wiele,many / much,много,багато +wierzyć,to believe,верить,вірити +wino,wine,вино,вино +wiosna,spring,весна,весна +wkrótce,soon,скоро,скоро +własny,own,собственный,власний +włosy,hair,волосы,волосся +woda,water,вода,вода +wokoło,around,вокруг,навколо +wolny,free / slow,свободный / медленный,вільний / повільний +wrócić,to return / to come back,вернуться,повернутися +wrzesień,September,сентябрь,вересень +wschód,east / sunrise,восток / восход,схід / схід сонця +wszyscy,everyone / everybody,все / все люди,усі / всі +wszystko,everything,всё,все +wtedy,then,тогда,тоді +wtorek,Tuesday,вторник,вівторок +wujek,uncle,дядя,дядько +wybierać,to choose,выбирать,вибирати +wydarzenie,event,событие,подія +wydawać,to spend / to seem,тратить / казаться,витрачати / здаватися +wygrać,to win,выиграть,виграти +wyjaśnić,to explain,объяснить,пояснити +wykres,chart / graph,график / диаграмма,графік / діаграма +wynik,result,результат,результат +wysłać,to send,отправить,надіслати +wysoki,tall / high,высокий,високий +wyspa,island,остров,острів +ząb,tooth,зуб,зуб +żaba,frog,лягушка,жаба +zabawa,fun / party,веселье / вечеринка,розвага / вечірка +zabawny,funny,смешной,смішний +zachód,west / sunset,запад / закат,захід / захід сонця +zacząć,to start / to begin,начать,почати +zaczynać,to start / to begin,начинать,починати +zadzwonić,to call,позвонить,зателефонувати +zainteresowanie,interest,интерес,інтерес +zainteresowany,interested,заинтересованный,зацікавлений +zajęty,busy,занятый,зайнятий +zakupy,shopping,покупки,покупки +zamknąć,to close,закрыть,закрити +zamówienie,order,заказ,замовлення +zapomnieć,to forget,забыть,забути +zasada,rule,правило,правило +zatrzymać,to stop / to hold,остановить / удержать,зупинити / утримати +zawierać,to contain,содержать,містити +zawsze,always,всегда,завжди +zdanie,sentence,предложение,речення +zdjęcie,photo / picture,фотография / фото,фотографія / фото +zdrowie,health,здоровье,здоров’я +zdrowy,healthy,здоровый,здоровий +zegar,clock,часы,годинник +zespół,team / group,команда / группа,команда / група +zgadywać,to guess,угадывать,вгадувати +zgubić,to lose,потерять,загубити +zielony,green,зелёный,зелений +ziemia,earth / soil,земля,земля +ziemniak,potato,картофель / картошка,картопля +zima,winter,зима,зима +zimny,cold,холодный,холодний +złamać,to break,сломать,зламати +zły,bad / angry,плохой / злой,поганий / злий +zmęczony,tired,уставший,втомлений +zmiana,change,изменение / перемена,зміна +znaczenie,meaning,значение,значення +znaleźć,to find,найти,знайти +znowu,again,снова,знову +znudzony,bored,скучающий,знудьгований +żółty,yellow,жёлтый,жовтий +żona,wife,жена,дружина +żonaty,married,женатый,одружений +zostać,to stay / to become,остаться / стать,залишитися / стати +zupa,soup,суп,суп +zwierzę,animal,животное,тварина +zwykle,usually,обычно,зазвичай +żyć,to live,жить,жити +życie,life,жизнь,життя \ No newline at end of file diff --git a/words_a2.csv b/words_a2.csv new file mode 100644 index 0000000..4d020e4 --- /dev/null +++ b/words_a2.csv @@ -0,0 +1,843 @@ +polish,english,russian,ukrainian +adwokat,lawyer,адвокат,адвокат +akceptuję,I accept,я принимаю,я приймаю +aktywny,active,активный,активний +albo,or,или,або +alternatywa,alternative,альтернатива,альтернатива +analizować,to analyze,анализировать,аналізувати +aplikacja,application,приложение,додаток +aplikować,to apply,подавать заявление,подавати заяву +architekt,architect,архитектор,архітектор +architektura,architecture,архитектура,архітектура +armia,army,армия,армія +asystent,assistant,ассистент,асистент +atrakcyjny,attractive,привлекательный,привабливий +autor,author,автор,автор +aż,as much as / until,аж / пока,аж / поки +badacz,researcher,исследователь,дослідник +badania,research,исследования,дослідження +badanie,examination / study,обследование / исследование,обстеження / дослідження +bezpieczny,safe,безопасный,безпечний +bezpośredni,direct,прямой,прямий +biały,white,белый,білий +bić,to beat,бить,бити +bieg,run / race,бег / забег,біг / забіг +biegacz,runner,бегун,бігун +bieganie,running,бег,біг +biologia,biology,биология,біологія +biznesmen,businessman,бизнесмен,бізнесмен +biżuteria,jewelry,ювелирные изделия,ювелірні вироби +błąd,mistake,ошибка,помилка +blisko,near,близко,близько +bliźniak,twin,близнец,близнюк +blok,block,блок,блок +błyskotliwy,brilliant,блестящий,блискучий +bóg,god,бог,бог +bohater,hero,герой,герой +bok,side,бок,бік +ból,pain,боль,біль +brakujący,missing,отсутствующий,відсутній +brama,gate,ворота,ворота +brązowy,brown,коричневый,коричневий +brzmieć,to sound,звучать,звучати +burmistrz,mayor,мэр,мер +być,to be,быть,бути +całkowicie,completely,полностью,повністю +cały,whole,целый,цілий +cecha,feature,черта,риса +cel,goal,цель,мета +cela,cell,камера,камера +celebryta,celebrity,знаменитость,знаменитість +centrum,center,центр,центр +chemia,chemistry,химия,хімія +chmura,cloud,облако,хмара +chociaż,although,хотя,хоча +choroba,illness,болезнь,хвороба +chory,sick,больной,хворий +chronić,to protect,защищать,захищати +ciągnąć,to pull,тянуть,тягнути +ciastko,cookie,печенье,печиво +cicho,quietly,тихо,тихо +ciemność,darkness,темнота,темрява +cienki,thin,тонкий,тонкий +ciepło,warmth,тепло,тепло +ciężki,heavy,тяжёлый,важкий +ciężko,heavily,тяжело,важко +co,what,что,що +codzienny,daily,ежедневный,щоденний +cukierki,candies,конфеты,цукерки +ćwiczyć,to exercise,тренироваться,тренуватися +cyfrowy,digital,цифровой,цифровий +cykl,cycle,цикл,цикл +cytryna,lemon,лимон,лимон +czarny,black,чёрный,чорний +czekanie,waiting,ожидание,очікування +czerwony,red,красный,червоний +człowiek,person,человек,людина +czubek,tip,кончик,кінчик +czyj,whose,чей,чий +czynnik,factor,фактор,фактор +czyścić,to clean,чистить,чистити +czysty,clean,чистый,чистий +dach,roof,крыша,дах +dalej,further,дальше,далі +daleko,far,далеко,далеко +dane,data,данные,дані +darmowy,free,бесплатный,безкоштовний +decyzja,decision,решение,рішення +dentysta,dentist,стоматолог,стоматолог +departament,department,департамент,департамент +deser,dessert,десерт,десерт +deska,board,доска,дошка +detektyw,detective,детектив,детектив +długo,long,долго,довго +dmuchać,to blow,дуть,дмухати +dno,bottom,дно,дно +dobroczynność,charity,благотворительность,благодійність +dobry,good,хороший,добрий +dobrze,well,хорошо,добре +dokładnie,exactly,точно,точно +dokładny,precise,точный,точний +dokument,document,документ,документ +dolina,valley,долина,долина +dom,home,дом,дім +dorosły,adult,взрослый,дорослий +dość,enough,достаточно,достатньо +doskonały,perfect,отличный,відмінний +dostępny,available,доступный,доступний +doświadczenie,experience,опыт,досвід +dotknąć,to touch,тронуть,торкнутися +dowcip,joke,шутка,жарт +dowód,proof,доказательство,доказ +drama,drama,драма,драма +drewniany,wooden,деревянный,дерев'яний +drewno,wood,древесина,деревина +drugi,second,второй,другий +drukarka,printer,принтер,принтер +drukować,to print,печатать,друкувати +dużo,many,много,багато +dyrektor,director,директор,директор +dyskusja,discussion,дискуссия,дискусія +dywan,carpet,ковёр,килим +dżem,jam,джем,джем +działać,to work,действовать,діяти +dziecko,child,ребёнок,дитина +dziennik,diary / journal,дневник / журнал,щоденник / журнал +dziennikarz,journalist,журналист,журналіст +dziki,wild,дикий,дикий +dzisiaj,today,сегодня,сьогодні +dziura,hole,дыра,діра +dziwny,strange,странный,дивний +dzwonić,to call,звонить,телефонувати +edukacja,education,образование,освіта +efekt,effect,эффект,ефект +ekran,screen,экран,екран +ekspert,expert,эксперт,експерт +eksperyment,experiment,эксперимент,експеримент +ekstremalny,extreme,экстремальный,екстремальний +elektroniczny,electronic,электронный,електронний +elektryczność,electricity,электричество,електрика +elektryczny,electric,электрический,електричний +energia,energy,энергия,енергія +esej,essay,эссе,есе +fabryka,factory,фабрика,фабрика +facet,guy,парень,хлопець +farma,farm,ферма,ферма +fasola,beans,фасоль,квасоля +fikcja,fiction,вымысел,вигадка +film,film,фильм,фільм +finał,final,финал,фінал +fioletowy,purple,фиолетовый,фіолетовий +fizyczny,physical,физический,фізичний +fizyka,physics,физика,фізика +formalny,formal,формальный,формальний +formować,to form,формировать,формувати +fotografować,to photograph,фотографировать,фотографувати +galeria,gallery,галерея,галерея +garnitur,suit,костюм,костюм +gaz,gas,газ,газ +gdzie,where,где,де +gdziekolwiek,anywhere,где угодно,де завгодно +gdzieś,somewhere,где-то,десь +głęboki,deep,глубокий,глибокий +głos,voice,голос,голос +głośno,loudly,громко,голосно +głośny,loud,громкий,голосний +głównie,mainly,в основном,в основному +główny,main,главный,головний +głupi,stupid,глупый,дурний +golf,golf,гольф,гольф +gorączka,fever,лихорадка,гарячка +gorszy,worse,хуже,гірше +gość,guest,гость,гість +gotować,to cook,готовить,готувати +gotówka,cash,наличные,готівка +gra,game,игра,гра +grosz,grosz / penny,грош / копейка,гріш / копійка +gruby,thick,толстый,товстий +grypa,flu,грипп,грип +grzeczny,polite,вежливый,ввічливий +guzik,button,пуговица,гудзик +gwiazda,star,звезда,зірка +hałas,noise,шум,шум +hałaśliwy,noisy,шумный,шумний +harmonogram,schedule,расписание,розклад +hokej,hockey,хоккей,хокей +idealny,perfect,идеальный,ідеальний +ilość,quantity,количество,кількість +inaczej,differently,иначе,інакше +inny,other,другой,інший +instrukcja,instruction,инструкция,інструкція +instruktor,instructor,инструктор,інструктор +instrument,instrument,инструмент,інструмент +inteligentny,intelligent,умный,розумний +interesować,to interest,интересовать,цікавити +inżynier,engineer,инженер,інженер +istnieć,to exist,существовать,існувати +jak,how,как,як +jakość,quality,качество,якість +jasny,bright,светлый,світлий +jazda,driving / ride,езда,їзда +jeden,one,один,один +jednostka,unit,единица,одиниця +jego,his,его,його +jej,her,её,її +jeszcze,still,ещё,ще +jezioro,lake,озеро,озеро +jutro,tomorrow,завтра,завтра +już,already,уже,вже +kamień,stone,камень,камінь +kampus,campus,кампус,кампус +katastrofa,disaster,катастрофа,катастрофа +kawałek,piece,кусок,шматок +każdy,every,каждый,кожен +kiedy,when,когда,коли +kierunek,direction,направление,напрямок +kieszeń,pocket,карман,кишеня +kilka,several,несколько,кілька +kilometr,kilometer,километр,кілометр +klasyczny,classic,классический,класичний +klimat,climate,климат,клімат +kłótnia,argument,ссора,сварка +kluczowy,key,ключевой,ключовий +kod,code,код,код +kolano,knee,колено,коліно +kolega,colleague,коллега,колега +kolej,railway,железная дорога,залізниця +koło,wheel,колесо,колесо +kolumna,column,колонна,колона +komedia,comedy,комедия,комедія +komentarz,comment,комментарий,коментар +kompletny,complete,полный,повний +komunikować,to communicate,общаться,спілкуватися +konferencja,conference,конференция,конференція +koniec,end,конец,кінець +konieczny,necessary,необходимый,необхідний +konkurs,competition,конкурс,конкурс +kontekst,context,контекст,контекст +kontrolować,to control,контролировать,контролювати +kontynent,continent,континент,континент +kontynuować,to continue,продолжать,продовжувати +kopiować,to copy,копировать,копіювати +korzyść,benefit,польза,користь +kość,bone,кость,кістка +kościół,church,церковь,церква +kostka,cube,кубик,кубик +kosztować,to cost,стоить,коштувати +kraść,to steal,красть,красти +kreatywny,creative,творческий,творчий +kręcony,curly,кудрявый,кучерявий +kredyt,loan,кредит,кредит +kreskówka,cartoon,мультфильм,мультфільм +krew,blood,кровь,кров +krok,step,шаг,крок +król,king,король,король +królowa,queen,королева,королева +krzyczeć,to shout,кричать,кричати +księżyc,moon,луна,місяць +kształt,shape,форма,форма +ktokolwiek,anyone,кто угодно,хто завгодно +który,which,который,який +kucharz,cook,повар,кухар +kuchenka,stove,плита,плита +kwadratowy,square,квадратный,квадратний +laboratorium,laboratory,лаборатория,лабораторія +lądować,to land,приземляться,приземлятися +lampa,lamp,лампа,лампа +las,forest,лес,ліс +latanie,flying,полёт,політ +łatwo,easily,легко,легко +lek,medicine,лекарство,ліки +lekarstwo,medicine,лекарство,ліки +lekki,light,лёгкий,легкий +leniwy,lazy,ленивый,лінивий +lewy,left,левый,лівий +liczba,number,число,число +liczyć,to count,считать,рахувати +lider,leader,лидер,лідер +link,link,ссылка,посилання +lodówka,fridge,холодильник,холодильник +luka,gap,пробел,прогалина +lustro,mirror,зеркало,дзеркало +łyżka,spoon,ложка,ложка +machnięcie,wave,взмах,змах +malarz,painter,художник,художник +mało,little,мало,мало +malować,to paint,рисовать,малювати +małpa,monkey,обезьяна,мавпа +matematyka,mathematics,математика,математика +materiał,material,материал,матеріал +meble,furniture,мебель,меблі +media,media,медиа,медіа +medyczny,medical,медицинский,медичний +menedżer,manager,менеджер,менеджер +męski,male,мужской,чоловічий +metal,metal,металл,метал +metoda,method,метод,метод +metro,subway,метро,метро +mieć,to have,иметь,мати +międzynarodowy,international,международный,міжнародний +miejsce,place,место,місце +miękki,soft,мягкий,м'який +miliard,billion,миллиард,мільярд +miłość,love,любовь,любов +minąć,to pass,пройти,минути +miniony,past,прошлый,минулий +miska,bowl,миска,миска +mniej,less,меньше,менше +moda,fashion,мода,мода +modelka,model,модель,модель +mój,my,мой,мій +mokry,wet,мокрый,мокрий +morze,sea,море,море +most,bridge,мост,міст +motocykl,motorcycle,мотоцикл,мотоцикл +mowa,speech,речь,мова +mówca,speaker,оратор,оратор +może,maybe,возможно,можливо +mózg,brain,мозг,мозок +możliwość,possibility,возможность,можливість +mundur,uniform,униформа,уніформа +muzyczny,musical,музыкальный,музичний +muzyk,musician,музыкант,музикант +mycie,washing,мытьё,миття +mydło,soap,мыло,мило +myśl,thought,мысль,думка +myślenie,thinking,мышление,мислення +nad,above,над,над +nadzieja,hope,надежда,надія +nagle,suddenly,вдруг,раптом +nagranie,recording,запись,запис +nagroda,prize,приз,приз +nagrywać,to record,записывать,записувати +najgorszy,worst,худший,найгірший +najlepiej,best,лучше всего,найкраще +najmniej,least,меньше всего,найменше +najwięcej,most,больше всего,найбільше +napój,drink,напиток,напій +naprawić,to repair,починить,полагодити +naprzód,forward,вперёд,вперед +narciarstwo,skiing,лыжный спорт,лижний спорт +narodowy,national,национальный,національний +narodziny,birth,рождение,народження +narzędzie,tool,инструмент,інструмент +narzekać,to complain,жаловаться,скаржитися +następny,next,следующий,наступний +natura,nature,природа,природа +natychmiast,immediately,немедленно,негайно +nauczanie,teaching,преподавание,викладання +nauka,learning,обучение,навчання +nawyk,habit,привычка,звичка +nazywać,to call,называть,називати +nerwowy,nervous,нервный,нервовий +niebezpieczeństwo,danger,опасность,небезпека +niebieski,blue,синий,синій +niebo,sky,небо,небо +niedawno,recently,недавно,нещодавно +niedawny,recent,недавний,нещодавній +niedźwiedź,bear,медведь,ведмідь +nieformalny,informal,неформальный,неформальний +niegrzeczny,impolite,невежливый,неввічливий +niektóre,some,некоторые,деякі +niemożliwy,impossible,невозможный,неможливий +niespodzianka,surprise,сюрприз,сюрприз +niestety,unfortunately,к сожалению,на жаль +nieszczęśliwy,unhappy,несчастный,нещасливий +nietypowy,unusual,необычный,незвичайний +niewiarygodny,incredible,невероятный,неймовірний +niezależny,independent,независимый,незалежний +niezwykle,extremely,чрезвычайно,надзвичайно +nigdzie,nowhere,нигде,ніде +niski,low,низкий,низький +normalnie,normally,обычно,зазвичай +normalny,normal,нормальный,нормальний +nóż,knife,нож,ніж +obietnica,promise,обещание,обіцянка +oblać,to fail,провалить,провалити +obóz,camp,лагерь,табір +obraz,picture,картина,картина +oczekiwać,to expect,ожидать,очікувати +od,from,от,від +oddzielny,separate,отдельный,окремий +odkryć,to discover,обнаружить,виявити +odkrycie,discovery,открытие,відкриття +odległość,distance,расстояние,відстань +odmówić,to refuse,отказать,відмовити +odnosić,to relate,относиться,ставитися +odpoczynek,rest,отдых,відпочинок +odpowiedź,answer,ответ,відповідь +odpowiedzieć,to answer,ответить,відповісти +odzież,clothing,одежда,одяг +oferować,to offer,предлагать,пропонувати +ogólny,general,общий,загальний +ogromny,huge,огромный,величезний +okazja,opportunity,возможность,можливість +około,about,около,близько +okrągły,round,круглый,круглий +okropny,terrible,ужасный,жахливий +olej,oil,масло,олія +oparty,based,основанный,заснований +opcja,option,вариант,варіант +oprócz,except,кроме,крім +organizacja,organization,организация,організація +organizować,to organize,организовывать,організовувати +oryginalny,original,оригинальный,оригінальний +orzech,nut,орех,горіх +osiągnąć,to achieve,достичь,досягти +osobowość,personality,личность,особистість +ostatni,last,последний,останній +ostrożnie,carefully,осторожно,обережно +ostrożny,careful,осторожный,обережний +otrzymać,to receive,получить,отримати +otwarty,open,открытый,відкритий +owad,insect,насекомое,комаха +oznaczyć,to mark,обозначить,позначити +pacjent,patient,пациент,пацієнт +padać,to fall,падать,падати +pająk,spider,паук,павук +pakować,to pack,паковать,пакувати +pałac,palace,дворец,палац +palec,finger,палец,палець +palenie,smoking,курение,куріння +palić,to smoke,курить,курити +pamięć,memory,память,пам'ять +pan,sir,господин,пан +pani,madam,госпожа,пані +papieros,cigarette,сигарета,цигарка +para,pair,пара,пара +parkowanie,parking,парковка,паркування +pasażer,passenger,пассажир,пасажир +pasek,belt,ремень,ремінь +pasować,to fit,подходить,підходити +pchać,to push,толкать,штовхати +pędzel,paintbrush,кисть,пензель +pęk,bundle,связка,в'язка +peron,platform,платформа,платформа +pewien,certain,определённый,певний +piec,to bake,печь,пекти +pierścionek,ring,кольцо,каблучка +pierwszy,first,первый,перший +pilot,remote,пульт,пульт +płaca,wage,зарплата,зарплата +płakać,to cry,плакать,плакати +plakat,poster,плакат,плакат +planeta,planet,планета,планета +planować,to plan,планировать,планувати +płaski,flat,плоский,плаский +plastik,plastic,пластик,пластик +pobrać,to download,скачать,завантажити +pobyt,stay,пребывание,перебування +początek,beginning,начало,початок +poczta,post office,почта,пошта +pod,under,под,під +podczas,during,во время,під час +podnieść,to lift,поднять,підняти +podróż,journey,путешествие,подорож +podróżny,traveler,путешественник,мандрівник +podwójny,double,двойной,подвійний +pojedynczy,single,одиночный,одиничний +pokaz,show,показ,показ +pokój,room,комната,кімната +połączony,connected,соединённый,з'єднаний +połączyć,to connect,соединить,з'єднати +pole,field,поле,поле +polecać,to recommend,рекомендовать,рекомендувати +północ,north,север,північ +połowa,half,половина,половина +południowy,southern,южный,південний +pomarańczowy,orange,оранжевый,помаранчевий +pomiędzy,between,между,між +pomoc,help,помощь,допомога +pomocny,helpful,полезный,корисний +poprawić,to improve,улучшить,покращити +poprawnie,correctly,правильно,правильно +populacja,population,население,населення +posiadać,to own,владеть,володіти +post,post,пост,пост +postać,character,персонаж,персонаж +postęp,progress,прогресс,прогрес +potrzeba,need,потребность,потреба +poważny,serious,серьёзный,серйозний +powieść,novel,роман,роман +powitać,to welcome,приветствовать,вітати +powrót,return,возвращение,повернення +poziom,level,уровень,рівень +później,later,позже,пізніше +pozwalać,to allow,позволять,дозволяти +pozwolenie,permission,разрешение,дозвіл +pozycja,position,позиция,позиція +pożyczyć,to borrow,занять,позичити +praca,work,работа,робота +pracodawca,employer,работодатель,роботодавець +pracownik,employee,работник,працівник +pracujący,working,работающий,працюючий +pranie,laundry,стирка,прання +prawdopodobny,probable,вероятный,ймовірний +prawidłowy,correct,правильный,правильний +prawie,almost,почти,майже +prawo,law,закон,закон +prędkość,speed,скорость,швидкість +prezent,gift,подарок,подарунок +prezentować,to present,представлять,представляти +prezydent,president,президент,президент +problem,problem,проблема,проблема +procent,percent,процент,відсоток +proces,process,процесс,процес +produkować,to produce,производить,виробляти +profesjonalny,professional,профессиональный,професійний +profesor,professor,профессор,професор +profil,profile,профиль,профіль +projektant,designer,дизайнер,дизайнер +projektować,to design,проектировать,проєктувати +propozycja,proposal,предложение,пропозиція +prośba,request,просьба,прохання +prosto,straight,прямо,прямо +prosty,simple,простой,простий +proszę,please,пожалуйста,будь ласка +prowadzić,to drive,водить,керувати +przechodzić,to cross,переходить,переходити +przeciw,against,против,проти +przeciwieństwo,opposite,противоположность,протилежність +przed,before,перед,перед +przedni,front,передний,передній +przedstawienie,performance,представление,вистава +przejażdżka,ride,поездка,поїздка +przemysł,industry,промышленность,промисловість +przepis,recipe,рецепт,рецепт +przerwa,break,перерыв,перерва +prześcieradło,sheet,простыня,простирадло +przestępca,criminal,преступник,злочинець +przestępstwo,crime,преступление,злочин +przestraszony,scared,испуганный,наляканий +przewidzieć,to predict,предвидеть,передбачити +przez,through,через,через +przeziębienie,cold,простуда,застуда +przyczyna,cause,причина,причина +przygoda,adventure,приключение,пригода +przykryć,to cover,накрыть,накрити +przypadek,case,случай,випадок +przystanek,stop,остановка,зупинка +przyszłość,future,будущее,майбутнє +publiczność,audience,аудитория,аудиторія +publikować,to publish,публиковать,публікувати +pukać,to knock,стучать,стукати +pusty,empty,пустой,порожній +pustynia,desert,пустыня,пустеля +pytanie,question,вопрос,питання +raczej,rather,скорее,скоріше +radośnie,joyfully,радостно,радісно +raportować,to report,отчитываться,звітувати +reagować,to react,реагировать,реагувати +recykling,recycling,переработка,переробка +ręcznik,towel,полотенце,рушник +region,region,регион,регіон +regularny,regular,регулярный,регулярний +reklama,advertisement,реклама,реклама +reklamować,to advertise,рекламировать,рекламувати +reporter,reporter,репортёр,репортер +robić,to do,делать,робити +rodzaj,type,тип,тип +rodzina,family,семья,сім'я +róg,corner,угол,кут +rola,role,роль,роль +rolnictwo,agriculture,сельское хозяйство,сільське господарство +rozdawać,to distribute,раздавать,роздавати +rozmawiać,to talk,разговаривать,розмовляти +rozmiar,size,размер,розмір +rozmowa,conversation,разговор,розмова +różnorodność,diversity,разнообразие,різноманітність +różowy,pink,розовый,рожевий +rozpoznać,to recognize,распознать,розпізнати +rozważać,to consider,рассматривать,розглядати +rozwiązać,to solve,решить,вирішити +rozwiązanie,solution,решение,рішення +rozwiedziony,divorced,разведённый,розлучений +rozwijać,to develop,развивать,розвивати +ruch,movement,движение,рух +rysunek,drawing,рисунок,малюнок +rywalizować,to compete,соревноваться,змагатися +rząd,government,правительство,уряд +rzucać,to throw,бросать,кидати +sala,room,зал,зал +sam,alone,один,сам +scena,scene,сцена,сцена +schodek,step,ступенька,сходинка +ścigać,to chase,преследовать,переслідувати +sekret,secret,секрет,секрет +sekretarz,secretary,секретарь,секретар +sen,dream,сон,сон +serce,heart,сердце,серце +seria,series,серия,серія +serwować,to serve,подавать,подавати +siebie,oneself,себя,себе +sieć,network,сеть,мережа +siedzenie,seat,сиденье,сидіння +silnik,engine,двигатель,двигун +skakać,to jump,прыгать,стрибати +skarpetka,sock,носок,шкарпетка +skóra,skin,кожа,шкіра +słaby,weak,слабый,слабкий +słodki,sweet,сладкий,солодкий +ślub,wedding,свадьба,весілля +słuchacz,listener,слушатель,слухач +smak,taste,вкус,смак +śmiech,laughter,смех,сміх +śmieci,trash,мусор,сміття +smutnie,sadly,грустно,сумно +śnić,to dream,сниться,снитися +śnieg,snow,снег,сніг +sos,sauce,соус,соус +spacer,walk,прогулка,прогулянка +specyficzny,specific,специфический,специфічний +śpiący,sleepy,сонный,сонний +śpiew,singing,пение,спів +społeczeństwo,society,общество,суспільство +społeczność,community,сообщество,спільнота +społeczny,social,социальный,соціальний +sportowiec,athlete,спортсмен,спортсмен +sposób,way,способ,спосіб +spóźniony,late,опоздавший,запізнілий +sprawa,matter,дело,справа +sprawdzenie,check,проверка,перевірка +sprawiedliwy,fair,справедливый,справедливий +sprzedaż,sale,продажа,продаж +sprzęt,equipment,оборудование,обладнання +srebro,silver,серебро,срібло +średni,medium,средний,середній +środkowy,middle,средний,середній +środowisko,environment,окружающая среда,довкілля +stan,state,состояние,стан +starożytny,ancient,древний,давній +statek,ship,корабль,корабель +stawka,rate,ставка,ставка +stopień,degree,степень,ступінь +strach,fear,страх,страх +straszny,terrible,ужасный,жахливий +strategia,strategy,стратегия,стратегія +stres,stress,стресс,стрес +struktura,structure,структура,структура +strzelać,to shoot,стрелять,стріляти +suchy,dry,сухой,сухий +sugerować,to suggest,предлагать,пропонувати +święto,holiday,праздник,свято +tablet,tablet,планшет,планшет +tak,yes,да,так +taki,such,такой,такий +talerz,plate,тарелка,тарілка +taniec,dance,танец,танець +technologia,technology,технология,технологія +telefon,phone,телефон,телефон +telefonować,to call,звонить,телефонувати +temperatura,temperature,температура,температура +ten,this,этот,цей +termin,deadline,срок,термін +testować,to test,тестировать,тестувати +tło,background,фон,тло +tłum,crowd,толпа,натовп +tłuszcz,fat,жир,жир +tor,track,трасса,траса +tradycja,tradition,традиция,традиція +tradycyjny,traditional,традиционный,традиційний +trampki,sneakers,кеды,кросівки +transport,transport,транспорт,транспорт +trasa,route,маршрут,маршрут +trawa,grass,трава,трава +trener,coach,тренер,тренер +trenować,to train,тренироваться,тренуватися +trochę,little,немного,трохи +troska,concern,забота,турбота +trząść,to shake,трясти,трясти +trzeci,third,третий,третій +trzymać,to hold,держать,тримати +turystyka,tourism,туризм,туризм +twój,your,твой,твій +tylko,only,только,тільки +typowy,typical,типичный,типовий +ubierać,to dress,одевать,одягати +uczenie,learning,обучение,навчання +uczestniczyć,to participate,участвовать,брати участь +uderzyć,to hit,ударить,вдарити +układ,arrangement,расположение,розташування +układać,to arrange,раскладывать,розкладати +ukryć,to hide,спрятать,сховати +ulubieniec,favorite,любимец,улюбленець +umysł,mind,разум,розум +unikać,to avoid,избегать,уникати +upadek,fall,падение,падіння +upuścić,to drop,уронить,упустити +uraz,injury,травма,травма +urządzenie,device,устройство,пристрій +urzędnik,official,чиновник,чиновник +usługa,service,услуга,послуга +uśmiech,smile,улыбка,усмішка +usunąć,to remove,удалить,видалити +uświadomić,to realize,осознать,усвідомити +uwaga,attention,внимание,увага +użycie,use,использование,використання +użytkownik,user,пользователь,користувач +wąchać,to smell,нюхать,нюхати +waga,weight,вес,вага +walczyć,to fight,сражаться,боротися +wąski,narrow,узкий,вузький +wcale,at all,вовсе,зовсім +wcześnie,early,рано,рано +wczoraj,yesterday,вчера,вчора +wędkarstwo,fishing,рыбалка,рибальство +wejść,to enter,войти,увійти +wiatr,wind,ветер,вітер +widelec,fork,вилка,виделка +widok,view,вид,краєвид +więcej,more,больше,більше +wiedza,knowledge,знание,знання +wiek,age,возраст,вік +wiele,many,много,багато +wieś,village,деревня,село +wieża,tower,башня,вежа +więzienie,prison,тюрьма,в'язниця +winda,elevator,лифт,ліфт +wirus,virus,вирус,вірус +witaj,hello,здравствуй,вітаю +wizyta,visit,визит,візит +władza,power,власть,влада +właściciel,owner,владелец,власник +właściwie,actually,собственно,власне +własność,property,собственность,власність +wliczony,included,включённый,включений +wokoło,around,вокруг,навколо +wolno,allowed,разрешено,дозволено +wołowina,beef,говядина,яловичина +wow,wow,вау,вау +wpływać,to affect,влиять,впливати +wschodni,eastern,восточный,східний +wspierać,to support,поддерживать,підтримувати +wspomnieć,to mention,упомянуть,згадати +wśród,among,среди,серед +wszędzie,everywhere,везде,скрізь +wszystko,everything,всё,все +wybierać,to choose,выбирать,обирати +wybór,choice,выбор,вибір +wybrzeże,coast,побережье,узбережжя +wycieczka,trip,поездка,поїздка +wygląd,appearance,внешность,зовнішність +wygodny,comfortable,удобный,зручний +wyjaśnienie,explanation,объяснение,пояснення +wykład,lecture,лекция,лекція +wykonać,to perform,выполнить,виконати +wymawiać,to pronounce,произносить,вимовляти +wynagrodzenie,salary,зарплата,заробітна плата +wynalazek,invention,изобретение,винахід +wynaleźć,to invent,изобрести,винайти +wypadek,accident,авария,аварія +wypisać,to write out,выписать,виписати +wyraz,word,слово,слово +wyrazić,to express,выразить,висловити +wyraźnie,clearly,ясно,чітко +wysłać,to send,отправить,надіслати +wysoki,high,высокий,високий +wysokość,height,высота,висота +wystarczająco,enough,достаточно,достатньо +wzdłuż,along,вдоль,уздовж +wzgórze,hill,холм,пагорб +wznosić,to raise,поднимать,піднімати +wzór,pattern,узор,візерунок +zaangażować,to involve,вовлечь,залучити +zaatakować,to attack,атаковать,атакувати +zabawka,toy,игрушка,іграшка +zabawny,funny,смешной,смішний +zachodni,western,западный,західний +zachowanie,behavior,поведение,поведінка +zadanie,task,задание,завдання +żaden,none,никакой,жоден +zadowolony,satisfied,довольный,задоволений +zagraniczny,foreign,иностранный,іноземний +zagubiony,lost,потерянный,загублений +zakładać,to assume,предполагать,припускати +zakończenie,ending,окончание,закінчення +zakończyć,to finish,закончить,закінчити +zakręt,turn,поворот,поворот +zaleta,advantage,преимущество,перевага +zależeć,to depend,зависеть,залежати +zamiast,instead,вместо,замість +zamknąć,to close,закрыть,закрити +zamknięty,closed,закрытый,закритий +zamówić,to order,заказать,замовити +zanieczyszczenie,pollution,загрязнение,забруднення +zapałka,match,спичка,сірник +zaparkować,to park,припарковать,припаркувати +zapewnić,to ensure,обеспечить,забезпечити +zapisać,to save,сохранить,зберегти +zapobiegać,to prevent,предотвращать,запобігати +zaprosić,to invite,пригласить,запросити +zaproszenie,invitation,приглашение,запрошення +zarabiać,to earn,зарабатывать,заробляти +zarezerwować,to book,забронировать,забронювати +zarządzać,to manage,управлять,керувати +zaskakujący,surprising,удивительный,дивовижний +zastąpić,to replace,заменить,замінити +zatłoczony,crowded,переполненный,переповнений +zatrudniać,to employ,нанимать,наймати +zauważyć,to notice,заметить,помітити +zawierać,to contain,содержать,містити +zbierać,to collect,собирать,збирати +zdecydowanie,definitely,определённо,безумовно +zdobyć,to gain,получить,здобути +zdolność,ability,способность,здатність +zdolny,able,способный,здатний +zdziwiony,surprised,удивлённый,здивований +zegarek,watch,часы,годинник +żeglarstwo,sailing,парусный спорт,вітрильний спорт +żeglować,to sail,плавать,плавати +żeński,female,женский,жіночий +zepsuty,broken,сломанный,зламаний +zero,zero,ноль,нуль +zgadywanie,guessing,угадывание,вгадування +zidentyfikować,to identify,идентифицировать,ідентифікувати +zielony,green,зелёный,зелений +ziemia,earth / soil,земля / почва,земля / ґрунт +zjednoczony,united,объединённый,об'єднаний +złapać,to catch,поймать,спіймати +źle,badly,плохо,погано +złodziej,thief,вор,злодій +złoto,gold,золото,золото +zmartwiony,worried,обеспокоенный,стурбований +zmiana,change,изменение,зміна +zmniejszyć,to reduce,уменьшить,зменшити +zmysł,sense,чувство,відчуття +znaczek,stamp,марка,марка +znak,sign,знак,знак +zniknąć,to disappear,исчезнуть,зникнути +zniszczyć,to destroy,уничтожить,знищити +żołądek,stomach,желудок,шлунок +żołnierz,soldier,солдат,солдат +żółty,yellow,жёлтый,жовтий +zranić,to hurt,ранить,поранити +źródło,source,источник,джерело +zrozumienie,understanding,понимание,розуміння +związać,to tie,связать,зв'язати +związek,relationship,отношения,стосунки +zwiększyć,to increase,увеличить,збільшити +zwycięzca,winner,победитель,переможець +zwyczajny,ordinary,обычный,звичайний +zwykły,usual,обычный,звичайний +życzyć,to wish,желать,бажати +żywy,alive,живой,живий \ No newline at end of file diff --git a/words_b1.csv b/words_b1.csv new file mode 100644 index 0000000..2dda632 --- /dev/null +++ b/words_b1.csv @@ -0,0 +1,848 @@ +polish,english,russian,ukrainian +absolutnie,absolutely,абсолютно,абсолютно +administracja,administration,администрация,адміністрація +agent,agent,агент,агент +akademicki,academic,академический,академічний +aktualizować,to update,обновлять,оновлювати +alarm,alarm,сигнализация,сигналізація +albo,or,или,або +album,album,альбом,альбом +alternatywny,alternative,альтернативный,альтернативний +ambicja,ambition,амбиция,амбіція +analiza,analysis,анализ,аналіз +ani,neither / nor,ни,ні +aplikacja,application,приложение,додаток +asortyment,assortment,ассортимент,асортимент +asystent,assistant,ассистент,асистент +atak,attack,атака,атака +atmosfera,atmosphere,атмосфера,атмосфера +atrakcja,attraction,аттракцион,атракціон +automatycznie,automatically,автоматически,автоматично +automatyczny,automatic,автоматический,автоматичний +autorytet,authority,авторитет,авторитет +autostrada,highway,автострада,автострада +bąbel,bubble,пузырь,бульбашка +badać,to research,исследовать,досліджувати +bałagan,mess,беспорядок,безлад +bardzo,very,очень,дуже +bateria,battery,батарея,батарея +bawełna,cotton,хлопок,бавовна +bęben,drum,барабан,барабан +bezpieczeństwo,safety,безопасность,безпека +bezpośrednio,directly,непосредственно,безпосередньо +bezrobocie,unemployment,безработица,безробіття +bezrobotny,unemployed,безработный,безробітний +bieda,poverty,бедность,бідність +bielizna,underwear,нижнее бельё,нижня білизна +bieżący,current,текущий,поточний +bitwa,battle,битва,битва +biwakować,to camp,ходить в поход,ходити в похід +blady,pale,бледный,блідий +blisko,near,близко,близько +bliźniak,twin,близнец,близнюк +blokować,to block,блокировать,блокувати +błoto,mud,грязь,багнюка +błyszczący,shiny,блестящий,блискучий +bójka,fight,драка,бійка +bolesny,painful,болезненный,болісний +brakować,to lack,не хватать,бракувати +brzeg,shore,берег,берег +brzydki,ugly,некрасивый,негарний +burza,storm,гроза,гроза +całkowicie,completely,полностью,повністю +całkowity,total,полный,повний +całość,whole,целое,ціле +całować,to kiss,целовать,цілувати +cel,goal,цель,мета +celować,to aim,целиться,цілитися +cenny,valuable,ценный,цінний +centralny,central,центральный,центральний +centrować,to center,центрировать,центрувати +centrum,center,центр,центр +ceremonia,ceremony,церемония,церемонія +chociaż,although,хотя,хоча +ciągły,continuous,непрерывный,безперервний +ciągnięcie,pulling,тяга,тягнення +ciasny,tight,тесный,тісний +cichy,quiet,тихий,тихий +ciecz,liquid,жидкость,рідина +cierpieć,to suffer,страдать,страждати +ciśnienie,pressure,давление,тиск +codziennie,daily,ежедневно,щоденно +cokolwiek,anything,что угодно,що завгодно +cytat,quote,цитата,цитата +cytować,to quote,цитировать,цитувати +czapka,cap,шапка,шапка +często,often,часто,часто +czy,whether,ли,чи +czyj,whose,чей,чий +czyn,deed,поступок,вчинок +dalej,further,дальше,далі +daleki,far,далёкий,далекий +definicja,definition,определение,визначення +definiować,to define,определять,визначати +definitywny,definitive,окончательный,остаточний +dekada,decade,десятилетие,десятиліття +diament,diamond,алмаз,діамант +długość,length,длина,довжина +dno,bottom,дно,дно +doceniać,to appreciate,ценить,цінувати +dodanie,addition,добавление,додавання +dodatkowy,additional,дополнительный,додатковий +dokument,document,документ,документ +dołączyć,to join,присоединиться,приєднатися +dom,home,дом,дім +doradzać,to advise,советовать,радити +doskonale,perfectly,отлично,відмінно +dostarczać,to deliver,доставлять,доставляти +dostarczyć,to deliver,доставить,доставити +dostęp,access,доступ,доступ +doświadczenie,experience,опыт,досвід +doświadczony,experienced,опытный,досвідчений +dotyk,touch,прикосновение,дотик +do tyłu,backwards,назад,назад +drugi,second,второй,другий +drugorzędny,secondary,второстепенный,другорядний +druk,printing,печать,друк +drżenie,trembling,дрожь,тремтіння +duch,spirit,дух,дух +dumny,proud,гордый,гордий +dużo,many,много,багато +dym,smoke,дым,дим +dyrektor,director,директор,директор +dżentelmen,gentleman,джентльмен,джентльмен +działanie,action,действие,дія +dzieciństwo,childhood,детство,дитинство +dzielnica,district,район,район +dziennik,diary,дневник,щоденник +dziwny,strange,странный,дивний +dzwon,bell,колокол,дзвін +dzwonić,to call,звонить,телефонувати +edukacyjny,educational,образовательный,освітній +edukować,to educate,обучать,навчати +efektywnie,effectively,эффективно,ефективно +ekonomiczny,economic,экономический,економічний +ekscytacja,excitement,волнение,хвилювання +ekspert,expert,эксперт,експерт +eksperymentować,to experiment,экспериментировать,експериментувати +eksplodować,to explode,взрываться,вибухати +eksplozja,explosion,взрыв,вибух +eksport,export,экспорт,експорт +elegancki,elegant,элегантный,елегантний +element,element,элемент,елемент +emeryt,retiree,пенсионер,пенсіонер +emocja,emotion,эмоция,емоція +etykieta,label,этикетка,етикетка +ewentualnie,possibly,возможно,можливо +fabuła,plot,сюжет,сюжет +fascynujący,fascinating,захватывающий,захопливий +federalny,federal,федеральный,федеральний +filmować,to film,снимать,знімати +finansowy,financial,финансовый,фінансовий +flaga,flag,флаг,прапор +fokus,focus,фокус,фокус +fotograf,photographer,фотограф,фотограф +fotografia,photography,фотография,фотографія +funkcja,function,функция,функція +futro,fur,мех,хутро +gałąź,branch,ветка,гілка +garaż,garage,гараж,гараж +gardło,throat,горло,горло +garnek,pot,кастрюля,каструля +gdziekolwiek,anywhere,где угодно,де завгодно +gdzieś,somewhere,где-то,десь +gigantyczny,gigantic,гигантский,гігантський +gładki,smooth,гладкий,гладкий +gleba,soil,почва,ґрунт +głęboki,deep,глубокий,глибокий +globalny,global,глобальный,глобальний +głośny,loud,громкий,голосний +głosować,to vote,голосовать,голосувати +głównie,mainly,в основном,в основному +głupi,stupid,глупый,дурний +gorzej,worse,хуже,гірше +gospodarka,economy,экономика,економіка +gospodarz,host,хозяин,господар +granica,border,граница,кордон +groza,horror,ужас,жах +gryźć,to bite,кусать,кусати +gwałtowny,violent,резкий,різкий +gwiazda,star,звезда,зірка +gwóźdź,nail,гвоздь,цвях +handlować,to trade,торговать,торгувати +historyczny,historical,исторический,історичний +hojny,generous,щедрый,щедрий +huragan,hurricane,ураган,ураган +ich,their,их,їх +igła,needle,игла,голка +ignorować,to ignore,игнорировать,ігнорувати +imigrant,immigrant,иммигрант,іммігрант +imponujący,impressive,впечатляющий,вражаючий +import,import,импорт,імпорт +indywidualny,individual,индивидуальный,індивідуальний +inteligencja,intelligence,интеллект,інтелект +intencja,intention,намерение,намір +inwestować,to invest,инвестировать,інвестувати +inżynieria,engineering,инженерия,інженерія +irytujący,irritating,раздражающий,дратівливий +iść,to go,идти,йти +jądrowy,nuclear,ядерный,ядерний +jakikolwiek,any,любой,будь-який +jasny,bright,светлый,світлий +jeden,one,один,один +język,language,язык,мова +kabel,cable,кабель,кабель +kampania,campaign,кампания,кампанія +kanał,channel,канал,канал +kandydat,candidate,кандидат,кандидат +kapitan,captain,капитан,капітан +kara,punishment,наказание,покарання +kategoria,category,категория,категорія +każdy,every,каждый,кожен +kiedy,when,когда,коли +kiedykolwiek,ever,когда-либо,коли-небудь +kilka,several,несколько,кілька +kłamstwo,lie,ложь,брехня +klauzula,clause,пункт,пункт +klawiatura,keyboard,клавиатура,клавіатура +klient,client,клиент,клієнт +kliknąć,to click,кликнуть,клацнути +klucz,key,ключ,ключ +kobieta,woman,женщина,жінка +kolekcja,collection,коллекция,колекція +kolorowy,colorful,цветной,кольоровий +komentować,to comment,комментировать,коментувати +komercyjny,commercial,коммерческий,комерційний +komunikacja,communication,коммуникация,комунікація +koncentrować,to concentrate,концентрировать,концентрувати +koniecznie,necessarily,обязательно,обов'язково +konkretnie,specifically,конкретно,конкретно +konkurencyjny,competitive,конкурентоспособный,конкурентоспроможний +konkurent,competitor,конкурент,конкурент +konsekwencja,consequence,последствие,наслідок +konsument,consumer,потребитель,споживач +kontakt,contact,контакт,контакт +konto,account,счёт,рахунок +kontrast,contrast,контраст,контраст +kontrola,control,контроль,контроль +kopalnia,mine,шахта,шахта +kopia,copy,копия,копія +kopnąć,to kick,пнуть,копнути +korzystać,to use,пользоваться,користуватися +kostium,costume,костюм,костюм +krawat,tie,галстук,краватка +krawędź,edge,край,край +krążyć,to circulate,циркулировать,циркулювати +kremowy,creamy,кремовый,кремовий +krewny,relative,родственник,родич +królewski,royal,королевский,королівський +kropla,drop,капля,крапля +kryminalny,criminal,криминальный,кримінальний +krzyk,scream,крик,крик +krzyż,cross,крест,хрест +ksiądz,priest,священник,священник +książę,prince,князь,князь +księżniczka,princess,принцесса,принцеса +kukurydza,corn,кукуруза,кукурудза +kulturalny,cultural,культурный,культурний +kurz,dust,пыль,пил +kwadrat,square,квадрат,квадрат +kwalifikacja,qualification,квалификация,кваліфікація +kwalifikować,to qualify,квалифицировать,кваліфікувати +laboratorium,laboratory,лаборатория,лабораторія +lać,to pour,лить,лити +łączyć,to connect,соединять,з'єднувати +łagodny,gentle,мягкий,м'який +łańcuch,chain,цепь,ланцюг +latający,flying,летающий,літаючий +leczenie,treatment,лечение,лікування +ledwie,barely,едва,ледве +lepszy,better,лучший,кращий +liczba,number,число,число +limit,limit,лимит,ліміт +lina,rope,верёвка,мотузка +liść,leaf,лист,лист +literatura,literature,литература,література +lokalizacja,location,местоположение,місцезнаходження +ludzie,people,люди,люди +ludzki,human,человеческий,людський +luksus,luxury,роскошь,розкіш +machnąć,to wave,махнуть,махнути +magia,magic,магия,магія +mąka,flour,мука,борошно +mało,little,мало,мало +mały,small,маленький,малий +małżeństwo,marriage,брак,шлюб +marka,brand,бренд,бренд +marketing,marketing,маркетинг,маркетинг +marnować,to waste,тратить впустую,витрачати даремно +martwić,to worry,беспокоить,хвилювати +martwienie,worrying,беспокойство,хвилювання +marynarz,sailor,моряк,моряк +mentalny,mental,ментальный,ментальний +mężczyzna,man,мужчина,чоловік +miejscowy,local,местный,місцевий +mierzyć,to measure,измерять,вимірювати +mięsień,muscle,мышца,м'яз +mieszać,to mix,мешать,змішувати +mieszanka,mixture,смесь,суміш +mistrz,master,мастер,майстер +młodość,youth,молодость,молодість +młody,young,молодой,молодий +mniej,less,меньше,менше +mocno,strongly,сильно,сильно +modlić,to pray,молиться,молитися +modlitwa,prayer,молитва,молитва +modny,fashionable,модный,модний +moneta,coin,монета,монета +morderstwo,murder,убийство,вбивство +mówiony,spoken,разговорный,розмовний +muszla,shell,ракушка,мушля +nagle,suddenly,вдруг,раптом +nagłówek,headline,заголовок,заголовок +nagranie,recording,запись,запис +najbardziej,most,больше всего,найбільше +najgorszy,worst,худший,найгірший +najlepszy,best,лучший,найкращий +najmniej,least,меньше всего,найменше +najnowszy,newest,новейший,найновіший +najwyższy,highest,высочайший,найвищий +namiot,tent,палатка,намет +napisany,written,написанный,написаний +napiwek,tip,чаевые,чайові +naprawa,repair,ремонт,ремонт +naprzeciw,opposite,напротив,навпроти +naród,nation,нация,нація +narracja,narration,повествование,оповідь +narta,ski,лыжа,лижа +nasionko,seed,семечко,насіння +nastawienie,attitude,настрой,налаштування +następny,next,следующий,наступний +nastrój,mood,настроение,настрій +nasz,our,наш,наш +naturalnie,naturally,естественно,природно +natychmiastowy,immediate,немедленный,негайний +naukowy,scientific,научный,науковий +niedbały,negligent,небрежный,недбалий +niedogodność,inconvenience,неудобство,незручність +nielegalny,illegal,нелегальный,нелегальний +nienawiść,hatred,ненависть,ненависть +niepotrzebny,unnecessary,ненужный,непотрібний +nieprzyjemny,unpleasant,неприятный,неприємний +nieśmiały,shy,застенчивый,сором'язливий +niesprawiedliwy,unfair,несправедливый,несправедливий +niewiarygodnie,incredibly,невероятно,неймовірно +niewinny,innocent,невинный,невинний +niewolnik,slave,раб,раб +niewygodny,uncomfortable,неудобный,незручний +niezbędny,essential,необходимый,необхідний +niezdolny,incapable,неспособный,нездатний +niski,low,низкий,низький +normalny,normal,нормальный,нормальний +obcy,foreign,чужой,чужий +obecnie,currently,в настоящее время,наразі +obecny,present,настоящий,теперішній +obietnica,promise,обещание,обіцянка +objaw,symptom,симптом,симптом +obok,next to,рядом,поруч +obowiązek,duty,обязанность,обов'язок +ocena,rating,оценка,оцінка +oceniać,to rate,оценивать,оцінювати +oczekiwany,expected,ожидаемый,очікуваний +oczywiście,of course,конечно,звичайно +oczywisty,obvious,очевидный,очевидний +od,from,от,від +odcinek,episode,эпизод,епізод +oddech,breath,дыхание,дихання +oddychać,to breathe,дышать,дихати +oddychanie,breathing,дыхание,дихання +oddzielić,to separate,отделить,відокремити +odjazd,departure,отъезд,від'їзд +odległy,distant,далёкий,далекий +odpoczynek,rest,отдых,відпочинок +odpowiedni,suitable,подходящий,відповідний +odpowiedź,answer,ответ,відповідь +odpowiedzialność,responsibility,ответственность,відповідальність +odpowiedzialny,responsible,ответственный,відповідальний +odrzucać,to reject,отклонять,відхиляти +odważny,brave,смелый,сміливий +odzwierciedlać,to reflect,отражать,відображати +oferta,offer,предложение,пропозиція +ofiara,victim,жертва,жертва +ofiarować,to offer,предлагать,пропонувати +oficjalny,official,официальный,офіційний +oglądać,to watch,смотреть,дивитися +ogłosić,to announce,объявить,оголосити +ogłoszenie,announcement,объявление,оголошення +ogólnoświatowy,worldwide,всемирный,всесвітній +ogon,tail,хвост,хвіст +ogrzewanie,heating,отопление,опалення +okazja,opportunity,возможность,можливість +okładka,cover,обложка,обкладинка +około,about,около,близько +określić,to define,определить,визначити +okropny,terrible,ужасный,жахливий +okrutny,cruel,жестокий,жорстокий +ołów,lead,свинец,свинець +opieka,care,забота,турбота +opłata,fee,плата,плата +opona,tire,шина,шина +oprócz,except,кроме,крім +oprogramowanie,software,программное обеспечение,програмне забезпечення +opróżnić,to empty,опустошить,спорожнити +organizator,organizer,организатор,організатор +oryginał,original,оригинал,оригінал +osiągnięcie,achievement,достижение,досягнення +osobiście,personally,лично,особисто +osobno,separately,отдельно,окремо +ostry,sharp,острый,гострий +ostrzegać,to warn,предупреждать,попереджати +ostrzeżenie,warning,предупреждение,попередження +oszukać,to cheat,обмануть,обдурити +oszukiwać,to deceive,обманывать,обманювати +paczka,package,посылка,посилка +palec,finger,палец,палець +paliwo,fuel,топливо,паливо +paragon,receipt,чек,чек +pasja,passion,страсть,пристрасть +pasować,to fit,подходить,підходити +patelnia,frying pan,сковорода,сковорода +pchnięcie,push,толчок,поштовх +personel,staff,персонал,персонал +piasek,sand,песок,пісок +piec,oven,печь,піч +piękno,beauty,красота,краса +pierwotnie,originally,изначально,спочатку +pierwotny,original,первоначальный,первісний +pierwszy,first,первый,перший +pijany,drunk,пьяный,п'яний +pikantny,spicy,острый,гострий +pisać,to write,писать,писати +plama,stain,пятно,пляма +planowanie,planning,планирование,планування +plasterek,slice,ломтик,скибка +plastikowy,plastic,пластиковый,пластиковий +płatność,payment,оплата,оплата +płeć,gender,пол,стать +plik,file,файл,файл +płot,fence,забор,паркан +plus,plus,плюс,плюс +płynąć,to flow,плыть,плисти +pływanie,swimming,плавание,плавання +po,after,после,після +pobieranie,downloading,скачивание,завантаження +pochować,to bury,похоронить,поховати +podać,to pass,подать,подати +podatek,tax,налог,податок +podczas,during,во время,під час +podgrzewać,to heat,подогревать,підігрівати +podkreślać,to emphasize,подчёркивать,підкреслювати +podlewać,to water,поливать,поливати +podobieństwo,similarity,сходство,схожість +podobnie,similarly,похоже,схоже +podobny,similar,похожий,схожий +podpisać,to sign,подписать,підписати +podróż,journey,путешествие,подорож +podstawa,basis,основа,основа +podstawowy,basic,основной,основний +podsumować,to summarize,подытожить,підсумувати +podwójnie,doubly,вдвойне,подвійно +podwyżka,raise,повышение,підвищення +podzielić,to divide,разделить,розділити +podziemny,underground,подземный,підземний +podziwiać,to admire,восхищаться,захоплюватися +poeta,poet,поэт,поет +poezja,poetry,поэзия,поезія +pojedynczy,single,одиночный,одиничний +pojemnik,container,контейнер,контейнер +pokazać,to show,показать,показати +pokierować,to direct,направить,спрямувати +pokolenie,generation,поколение,покоління +pokryty,covered,покрытый,покритий +połączenie,connection,соединение,з'єднання +połączyć,to connect,соединить,з'єднати +polityczny,political,политический,політичний +polityk,politician,политик,політик +polityka,politics,политика,політика +półka,shelf,полка,полиця +północ,north,север,північ +północny,northern,северный,північний +połowa,half,половина,половина +polować,to hunt,охотиться,полювати +położony,located,расположенный,розташований +położyć,to put,положить,покласти +południe,south,юг,південь +południowy,southern,южный,південний +pomimo,despite,несмотря на,незважаючи на +pomnik,monument,памятник,пам'ятник +pomóc,to help,помочь,допомогти +pop,pop,поп,поп +poprawa,improvement,улучшение,покращення +poprawnie,correctly,правильно,правильно +poprzedni,previous,предыдущий,попередній +porównanie,comparison,сравнение,порівняння +port,port,порт,порт +portret,portrait,портрет,портрет +porządkowy,ordinal,порядковый,порядковий +pośpiech,hurry,спешка,поспіх +pośredni,indirect,косвенный,непрямий +poszukiwanie,search,поиск,пошук +potężny,powerful,могущественный,могутній +potrzebować,to need,нуждаться,потребувати +potwierdzić,to confirm,подтвердить,підтвердити +poważnie,seriously,серьёзно,серйозно +powiązany,related,связанный,пов'язаний +powierzchnia,surface,поверхность,поверхня +powiesić,to hang,повесить,повісити +powinien,should,должен,повинен +powtarzany,repeated,повторяемый,повторюваний +powtórzenie,repetition,повторение,повторення +poziomy,horizontal,горизонтальный,горизонтальний +pozostać,to remain,остаться,залишитися +praktyczny,practical,практичный,практичний +prasa,press,пресса,преса +prawda,truth,правда,правда +prawidłowo,correctly,правильно,правильно +prawny,legal,правовой,правовий +prezentacja,presentation,презентация,презентація +prezentować,to present,представлять,представляти +próba,attempt,попытка,спроба +próbka,sample,образец,зразок +problem,problem,проблема,проблема +procent,percent,процент,відсоток +producent,producer,производитель,виробник +produkcja,production,производство,виробництво +prognoza,forecast,прогноз,прогноз +programować,to program,программировать,програмувати +promować,to promote,продвигать,просувати +prosić,to ask,просить,просити +prosty,simple,простой,простий +proszek,powder,порошок,порошок +protest,protest,протест,протест +prywatny,private,частный,приватний +przechowywać,to store,хранить,зберігати +przed,before,перед,перед +przedstawienie,performance,представление,вистава +przekonać,to convince,убедить,переконати +przełączyć,to switch,переключить,перемкнути +przeprosić,to apologize,извиниться,вибачитися +przerażający,terrifying,ужасающий,жахливий +przestraszony,scared,испуганный,наляканий +przestraszyć,to scare,испугать,налякати +przeszkadzać,to disturb,мешать,заважати +przeszły,past,прошлый,минулий +przetłumaczyć,to translate,перевести,перекласти +przewodnik,guide,гид,гід +przez,through,через,через +przeżyć,to survive,пережить,пережити +przybycie,arrival,прибытие,прибуття +przyciągać,to attract,привлекать,приваблювати +przygotowany,prepared,подготовленный,підготовлений +przyjaźń,friendship,дружба,дружба +przyjemność,pleasure,удовольствие,задоволення +przyjemny,pleasant,приятный,приємний +przykleić,to stick,приклеить,приклеїти +przypominać,to remind,напоминать,нагадувати +przysługa,favor,услуга,послуга +przyznać,to admit,признать,визнати +pszczoła,bee,пчела,бджола +publiczny,public,публичный,публічний +pukanie,knocking,стук,стук +pusty,empty,пустой,порожній +ramka,frame,рамка,рамка +ranny,wounded,раненый,поранений +rasa,breed,порода,порода +reakcja,reaction,реакция,реакція +recenzja,review,обзор,огляд +redaktor,editor,редактор,редактор +referencja,reference,референция,референція +regularnie,regularly,регулярно,регулярно +rękawiczka,glove,перчатка,рукавичка +relacja,relation,отношение,відношення +relaksujący,relaxing,расслабляющий,розслаблюючий +religia,religion,религия,релігія +religijny,religious,религиозный,релігійний +reprezentować,to represent,представлять,представляти +rezerwacja,reservation,бронирование,бронювання +robot,robot,робот,робот +rodzimy,native,родной,рідний +romantyczny,romantic,романтический,романтичний +również,also,также,також +równowaga,balance,равновесие,рівновага +równy,equal,равный,рівний +rozcięcie,cut,разрез,розріз +rozczarowany,disappointed,разочарованный,розчарований +rozczarowujący,disappointing,разочаровывающий,розчаровуючий +rozdział,chapter,глава,розділ +rozmowa,conversation,разговор,розмова +różny,different,разный,різний +rozprzestrzeniać,to spread,распространять,поширювати +rozrywka,entertainment,развлечение,розвага +rozsądny,reasonable,разумный,розумний +rozszerzać,to expand,расширять,розширювати +rozwój,development,развитие,розвиток +ruch,movement,движение,рух +rura,pipe,труба,труба +ryzyko,risk,риск,ризик +rząd,government,правительство,уряд +rzadki,rare,редкий,рідкісний +rzadko,rarely,редко,рідко +rządzić,to rule,править,правити +rzeczy,things,вещи,речі +rzeczywiście,indeed,действительно,дійсно +rzeczywistość,reality,реальность,реальність +rzeźba,sculpture,скульптура,скульптура +sąd,court,суд,суд +sam,alone,один,сам +samotny,lonely,одинокий,самотній +scenariusz,script,сценарий,сценарій +schłodzić,to cool,охладить,охолодити +ścieżka,path,тропинка,стежка +sekret,secret,секрет,секрет +sen,dream,сон,сон +serce,heart,сердце,серце +sieć,network,сеть,мережа +siła,strength,сила,сила +skała,rock,скала,скеля +skanować,to scan,сканировать,сканувати +skarga,complaint,жалоба,скарга +składać,to compose,составлять,складати +skoczyć,to jump,прыгнуть,стрибнути +skok,jump,прыжок,стрибок +skóra,skin,кожа,шкіра +skrzydło,wing,крыло,крило +skuteczny,effective,эффективный,ефективний +słodycz,sweetness,сладость,солодкість +sługa,servant,слуга,слуга +smakować,to taste,пробовать,куштувати +smażyć,to fry,жарить,смажити +śmigłowiec,helicopter,вертолёт,гелікоптер +sortować,to sort,сортировать,сортувати +spokój,calm,спокойствие,спокій +spokojny,calm,спокойный,спокійний +spotkanie,meeting,встреча,зустріч +spowodować,to cause,вызвать,спричинити +spowolnić,to slow down,замедлить,уповільнити +spożywać,to consume,потреблять,споживати +sprawiedliwie,fairly,справедливо,справедливо +sprytny,clever,хитрый,хитрий +srebrny,silver,серебряный,срібний +średni,medium,средний,середній +średnia,average,среднее,середнє +środek,middle,середина,середина +środowiskowy,environmental,экологический,екологічний +stadion,stadium,стадион,стадіон +stały,constant,постоянный,постійний +standard,standard,стандарт,стандарт +staromodny,old-fashioned,старомодный,старомодний +statystyka,statistics,статистика,статистика +strata,loss,потеря,втрата +strażnik,guard,охранник,охоронець +streszczenie,summary,резюме,резюме +strzelać,to shoot,стрелять,стріляти +studio,studio,студия,студія +stwierdzić,to state,заявить,заявити +substancja,substance,вещество,речовина +sufit,ceiling,потолок,стеля +suszyć,to dry,сушить,сушити +świadomy,aware,осознанный,свідомий +świecić,to shine,светить,світити +święto,holiday,праздник,свято +sygnalizować,to signal,сигнализировать,сигналізувати +szacunek,respect,уважение,повага +szafka,cabinet,шкафчик,шафка +szalony,crazy,сумасшедший,божевільний +szczególnie,especially,особенно,особливо +szczęście,happiness,счастье,щастя +szczotkować,to brush,чистить щёткой,чистити щіткою +szkoda,pity,жаль,шкода +sznurek,string,верёвка,мотузка +szorstki,rough,шероховатый,шорсткий +szpilka,pin,булавка,шпилька +tajemnica,secret,тайна,таємниця +tak,yes,да,так +taki,such,такой,такий +talent,talent,талант,талант +tani,cheap,дешёвый,дешевий +taśma,tape,лента,стрічка +techniczny,technical,технический,технічний +technika,technique,техника,техніка +temat,topic,тема,тема +teoria,theory,теория,теорія +teraz,now,сейчас,зараз +tkanina,fabric,ткань,тканина +tłumaczenie,translation,перевод,переклад +to,this,это,це +toczyć,to roll,катить,котити +tona,ton,тонна,тонна +tonąć,to drown,тонуть,тонути +tożsamość,identity,идентичность,ідентичність +transportować,to transport,транспортировать,транспортувати +trend,trend,тренд,тренд +trener,coach,тренер,тренер +trochę,little,немного,трохи +troszczyć,to care,заботиться,піклуватися +trucizna,poison,яд,отрута +trudność,difficulty,трудность,трудність +trujący,poisonous,ядовитый,отруйний +trwać,to last,длиться,тривати +twierdzić,to claim,утверждать,стверджувати +typowo,typically,типично,типово +ubrany,dressed,одетый,одягнений +uciec,to escape,убежать,втекти +uczciwy,honest,честный,чесний +uczestniczyć,to participate,участвовать,брати участь +udawać,to pretend,притворяться,прикидатися +udowodnić,to prove,доказать,довести +udział,participation,участие,участь +ukarać,to punish,наказать,покарати +ukończyć,to complete,закончить,закінчити +umieścić,to place,разместить,розмістити +umowa,contract,договор,договір +uprzątnąć,to clean up,убрать,прибрати +uśmiech,smile,улыбка,усмішка +ustawienie,setting,настройка,налаштування +utalentowany,talented,талантливый,талановитий +uwolnić,to release,освободить,звільнити +używany,used,подержанный,вживаний +walka,fight,борьба,боротьба +waluta,currency,валюта,валюта +warga,lip,губа,губа +warstwa,layer,слой,шар +wartość,value,ценность,цінність +wartościowy,valuable,ценный,цінний +wątpliwość,doubt,сомнение,сумнів +ważność,importance,важность,важливість +ważyć,to weigh,взвешивать,зважувати +wcześniej,earlier,раньше,раніше +wdzięczny,grateful,благодарный,вдячний +węgiel,coal,уголь,вугілля +wejście,entrance,вход,вхід +wełna,wool,шерсть,вовна +wersja,version,версия,версія +wesoły,cheerful,весёлый,веселий +wewnątrz,inside,внутри,всередині +wewnętrzny,internal,внутренний,внутрішній +wiara,faith,вера,віра +wiarygodny,credible,достоверный,достовірний +wiązać,to tie,связывать,зв'язувати +widok,view,вид,краєвид +widz,viewer,зритель,глядач +więcej,more,больше,більше +wiersz,poem,стихотворение,вірш +wieś,village,деревня,село +więzień,prisoner,заключённый,в'язень +winny,guilty,виновный,винний +wiodący,leading,ведущий,провідний +własność,property,собственность,власність +własny,own,собственный,власний +wokół,around,вокруг,навколо +wola,will,воля,воля +wolontariusz,volunteer,волонтёр,волонтер +wpływ,influence,влияние,вплив +wrażenie,impression,впечатление,враження +wróg,enemy,враг,ворог +wschód,east,восток,схід +wschodni,eastern,восточный,східний +wsiąść,to get on,сесть,сісти +wskazać,to indicate,указать,вказати +wskazówka,hint,подсказка,підказка +wsparcie,support,поддержка,підтримка +wspomnieć,to mention,упомянуть,згадати +wszyscy,everyone,все,усі +wybory,election,выборы,вибори +wydatki,expenses,расходы,витрати +wygodny,comfortable,удобный,зручний +wyimaginowany,imaginary,воображаемый,уявний +wyjście,exit,выход,вихід +wykład,lecture,лекция,лекція +wykształcony,educated,образованный,освічений +wykwalifikowany,qualified,квалифицированный,кваліфікований +wymagać,to require,требовать,вимагати +wymiana,exchange,обмен,обмін +wynająć,to rent,арендовать,орендувати +wynik,result,результат,результат +wyróżnić,to distinguish,выделить,виділити +wyścigi,racing,гонки,перегони +wysiłek,effort,усилие,зусилля +wysłać,to send,отправить,надіслати +wystąpić,to appear,выступить,виступити +wystarczająco,enough,достаточно,достатньо +wystawa,exhibition,выставка,виставка +wyzwanie,challenge,вызов,виклик +wzdłuż,along,вдоль,уздовж +wzrost,growth,рост,зріст +zaangażowany,engaged,вовлечённый,залучений +zaawansowany,advanced,продвинутый,просунутий +zabawiać,to entertain,развлекать,розважати +zabawny,funny,смешной,смішний +zabójstwo,murder,убийство,вбивство +zachęcać,to encourage,поощрять,заохочувати +zachód,west,запад,захід +zachodni,western,западный,західний +zadanie,task,задание,завдання +zadowolony,satisfied,довольный,задоволений +zafundować,to treat,угостить,пригостити +żagiel,sail,парус,вітрило +zakazać,to forbid,запретить,заборонити +zakończenie,ending,окончание,закінчення +zakończyć,to finish,закончить,закінчити +zalewać,to flood,заливать,заливати +zaliczenie,credit,зачёт,залік +zamarznięty,frozen,замёрзший,замерзлий +zamek,castle,замок,замок +zamierzać,to intend,намереваться,мати намір +zamknięty,closed,закрытый,закритий +zamrozić,to freeze,заморозить,заморозити +zapach,smell,запах,запах +zapał,enthusiasm,энтузиазм,ентузіазм +zapiąć,to fasten,застегнуть,застебнути +żart,joke,шутка,жарт +zarządzanie,management,управление,управління +zaskoczyć,to surprise,удивить,здивувати +zasłona,curtain,занавеска,завіса +zasób,resource,ресурс,ресурс +zatrudnić,to hire,нанять,найняти +zatrudnienie,employment,трудоустройство,працевлаштування +zauważyć,to notice,заметить,помітити +zawartość,content,содержимое,вміст +zawód,profession,профессия,професія +zawstydzony,embarrassed,смущённый,збентежений +zazwyczaj,usually,обычно,зазвичай +zbierać,to collect,собирать,збирати +zdecydowany,determined,решительный,рішучий +zdezorientować,to disorient,дезориентировать,дезорієнтувати +zdezorientowany,confused,растерянный,розгублений +zdumiony,amazed,изумлённый,здивований +żelazo,iron,железо,залізо +żenujący,embarrassing,неловкий,ніяковий +zestaw,set,набор,набір +zginać,to bend,сгибать,згинати +ziarno,grain,зерно,зерно +ziemia,earth,земля,земля +zirytowany,irritated,раздражённый,роздратований +zlokalizować,to locate,локализовать,локалізувати +złoto,gold,золото,золото +złożony,complex,сложный,складний +zły,bad,плохой,поганий +zmartwiony,worried,обеспокоенный,стурбований +zmiana,change,изменение,зміна +znak,sign,знак,знак +znany,known,известный,відомий +zniżka,discount,скидка,знижка +zobowiązać,to oblige,обязать,зобов'язати +zorganizowany,organized,организованный,організований +zranić,to hurt,ранить,поранити +zraniony,injured,раненый,поранений +zrelaksowany,relaxed,расслабленный,розслаблений +zrewidować,to revise,пересмотреть,переглянути +zrezygnować,to resign,отказаться,відмовитися +związek,relationship,отношения,стосунки +zwiedzać,to sightsee,осматривать,оглядати +zwolennicy,supporters,сторонники,прихильники +zwolennik,supporter,сторонник,прихильник +zwycięstwo,victory,победа,перемога +zwyczaj,custom,обычай,звичай +życzenie,wish,пожелание,побажання +życzliwy,kind,доброжелательный,доброзичливий +zysk,profit,прибыль,прибуток \ No newline at end of file