Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
197 changes: 161 additions & 36 deletions Lesson18/practice/LearnEnglish/solution.py
Original file line number Diff line number Diff line change
@@ -1,70 +1,195 @@
import sqlite3
import random
from datetime import datetime

import database
from helpers.connection import Connect
# from helpers.connection import Connect
from pathlib import Path

PATH_TO_DB = Path('vocabulary.db')

def add_word_in_db(english: str, russian: str, db_path: Path) ->None:
try:
message = database.add_word(english, russian, db_path)
print(message)
except ValueError as e:
if str(e) == "ПустойВвод":
print("⚠️ Поля не должны быть пустыми. \033[94mПопробуй еще раз!\033[0m")
elif "UNIQUE" in str(e):
print(f"⚠️ Дідько!!! Возможно, слово \033[31m{english}\033[0m уже есть в словаре.\n\n\n{e}")
else:
print(f"{e} \n⚠️ \033[94mЧто то пошло не так!\033[0m")

def choose_test_type()->str:
print(" 🧠 Выберите тип теста:")
print(" 1️⃣ Английский ➡️ Русский (en_ru)")
print(" 2️⃣ Русский ➡️ Английский (ru_en)")
while True:
choice = input("Введите 1️⃣ / 2️⃣: ").strip()
if choice == '1':
return 'en_ru'
elif choice == '2':
return 'ru_en'
else:
print(" ⚠️ Неверный выбор. Пожалуйста, введите 1 или 2.")

def show_words(db_path: Path):
rows = database.view_words(db_path)
if rows:
print(f" 🗂️ {'Слово':<13} | {'Перевод':<13} |")
for index, row in enumerate(rows):
print(f" \033[31m{index +1:<3}\033[0m \033[94m{row[0]:<13}\033[0m | \033[93m{row[1]:<13}\033[0m |")
else:
print("❗ Словарь пуст.")
input("\033[90m<-press Enter->\033[0m")

def start_test(cursor):
def start_test(db_path: Path):
"""Запускает режим тестирования."""
all_words = database.get_words(cursor)
try:
all_words = database.get_words(db_path)
if not all_words:
return

if not all_words:
return
flag = True
correct_answers_session = 0
total_questions = 0
test_type = choose_test_type()

while True:
# Выбираем случайное слово
# TODO: слова не должны выдаваться повторно в рамках одного теста
english_word, correct_translation = random.choice(list(all_words.items()))
if test_type == 'en_ru':
# Для en_ru: вопрос по english_word, ожидаем russian_translation
get_question_word = lambda word_data: word_data[1] # english_word
get_expected_answer = lambda word_data: word_data[2] # russian_translation
exit_test = "exit"
print(f"▶️ Начинаем тест на перевод с EN на RU")
else:# ru_en
# Для ru_en: вопрос по russian_translation, ожидаем english_word
get_question_word = lambda word_data: word_data[2] # russian_translation
get_expected_answer = lambda word_data: word_data[1] # english_word
exit_test = "стоп"
print(f"▶️ Начинаем тест на перевод с RU на EN")
while flag:
new_all_words = random.sample(all_words, len(all_words))
for word_id, english_word, russian_translation in new_all_words:
# Получаем слово для вопроса и ожидаемый ответ в зависимости от типа теста
question_word = get_question_word((word_id, english_word, russian_translation))
# print(f"question_word={question_word}")
expected_answer = get_expected_answer((word_id, english_word, russian_translation))
# print(f"expected_answer={expected_answer}")
print(f"🧠 Как переводится \033[94m'{question_word}'\033[0m?")
user_input = input(f"\033[91m'{exit_test}'\033[0m для выхода или ✍️ Введите ваш ответ: ").strip().lower()

user_input = input(f"Как переводится '{english_word}'? (или 'стоп'/'exit' для выхода): ").strip().lower()
if user_input == exit_test:
print("\n🛑 Тест остановлен пользователем.")
flag = False
break
if user_input == expected_answer:
correct_answers_session += 1
is_correct = 1
print("✅ Верно!\n")
else:
is_correct = 0
print(f"❌ Неверно. Правильный перевод: \033[93m'{expected_answer}'\033[0m.\n")
# print("-" * 20) # Разделитель для следующего вопроса
total_questions += 1
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
try:
database.log_answer(word_id, timestamp,test_type ,is_correct ,db_path)
except sqlite3.Error as e:
print(f"Не удалось добавить log_answer в базу данных: {e}")
print(f"📊 Статистика:\n Всего вопросов: {total_questions}\n Правильных: {correct_answers_session} 📈\n"
f" Ошибок: {total_questions - correct_answers_session} ❌\n")
input("\033[90m<-press Enter->\033[0m")
except sqlite3.Error as e:
print(f"Ошибка при получении слов: {e}")

if user_input in ('стоп', 'exit'):
print("Тест завершен.")
break

if user_input == correct_translation:
print("Верно!")
def view_overall_status(db_path: Path):
try:
rows = database.view_overall_stats(db_path)
print("\n--- 📊 Общая статистика по словам ---")
print(f" {'Слово':<15} | {'Перевод':<15} | Всего | \033[92m✔\033[0m Верно | ✘ Неверно | Точность %")
print("-" * 75)
for index, row in enumerate(rows):
eng, rus, total, correct, incorrect, accuracy = row
accuracy_str = f"{accuracy}%" if accuracy is not None else "—"
print(f"\033[31m{index +1:<3}\033[0m \033[94m{eng:<15}\033[0m | \033[93m{rus:<15}\033[0m | {total:^5} | \033[92m{correct:^7}\033[0m | {incorrect:^9} | {accuracy_str:^10}")
input("\033[90m<-press Enter->\033[0m")
except sqlite3.Error as e:
print(f"Ошибка при получении слов: {e}")

def get_problem_words(db_path: Path):
limit = 5 # Максимальное количество слов для вывода (топ N).
min_attempts = 1 # Минимальное количество попыток для слова, чтобы оно было включено в выборку.
# ANSI-коды # Оттенки от красного (яркий) до серого (тусклый)
gradient_colors = [196, 160, 131, 102, 245]
reset = "\033[0m"
try:
problem_words = database.view_problem_words(limit, min_attempts, db_path)
if not problem_words:
print("Пока нет слов, достаточно протестированных для выявления проблемных, "
"или по всем словам хорошие результаты.")
else:
print(f"Неправильно. Правильный перевод: '{correct_translation}'.")
print("\n--- 🔍 Проблемные слова TOP 5 ---")
print(f" {'Слово':<13} | {'Перевод':<13} | Всего | ✔ Верно | ✘ Неверно | Точность %")
print("-" * 75)
for index, word in enumerate(problem_words):
en, ru, total, wrong, correct, acc = word
if index >= len(gradient_colors) - 1: # если limit > 5 делаем защиту, что бы не вылететь за пределы массива gradient_colors
index = len(gradient_colors) - 1
color = f"\033[38;5;{gradient_colors[index]}m"
print(f"{color} {en:<13} | {ru:<13} | {total:^5} | {correct:^7} | {wrong:^9} | {acc:^10}%{reset}")
input("\033[90m<-press Enter->\033[0m")
except sqlite3.Error as e:
print(f"Не удалось получить проблемные слова: {e}")

print("-" * 20) # Разделитель для следующего вопроса
def delete_word_db(english, db_path: Path) -> None:
try:
count = database.delete_word(english, db_path)
if count == 0:
print(f"❗ Слово \033[31m{english}\033[0m в словаре не найдено")
else:
print(f"🗑️ Слово \033[31m{english}\033[0m удалено!")
except sqlite3.Error as e:
print(f"Не удалось удалить слово из базы данных: {e}")


def main_menu(cursor):
def main_menu(db_path: Path):
"""Главное меню приложения."""
while True:
print("\n--- Меню приложения 'Английский для новичков' ---")
print("1. Добавить слово")
print("2. Посмотреть слова")
print("3. Удалить слово")
print("4. Начать тест")
print("5. Выход")
print("\n--- 📘 Меню приложения 'Английский для новичков' ---")
print(" 1. ➕ Добавить слово")
print(" 2. 🗂️ Посмотреть слова")
print(" 3. 🗑️ Удалить слово")
print(" 4. ▶️ Начать тест")
print(" 5. 📊 Общая статистика по словам")
print(" 6. 🐌 Слова с проблемами")
print(" 7. 🚪 Выход")
print("-------------------------------------------------")

choice = input("Выберите действие: ").strip()

if choice == '1':
english = input("Введите английское слово: ").strip().lower()
russian = input("Введите русский перевод: ").strip().lower()
database.add_word(english, russian, cursor)
english = input("📥 Введите английское слово: ").strip().lower()
russian = input("📥 Введите русский перевод: ").strip().lower()
add_word_in_db(english, russian, db_path)
elif choice == '2':
database.view_words(cursor)
show_words(db_path)
elif choice == '3':
english = input("Введите английское слово, которое хотите удалить: ").strip().lower()
database.delete_word(english, cursor)
english = input("🗑️ Введите английское слово, которое хотите удалить: ").strip().lower()
delete_word_db(english, db_path)
elif choice == '4':
start_test(cursor)
start_test(db_path)
elif choice == '5':
print("До свидания!")
view_overall_status(db_path)
elif choice == '6':
get_problem_words(db_path)
elif choice == '7':
print("👋 До свидания!")
break
else:
print("Неверный выбор. Пожалуйста, введите число от 1 до 5.")
print("Неверный выбор. Пожалуйста, введите число от 1 до 7.")


if __name__ == "__main__":
with Connect(PATH_TO_DB) as cursor:
database.init_db(cursor)
main_menu(cursor)
database.init_db(PATH_TO_DB)
main_menu(PATH_TO_DB)