diff --git a/README.md b/README.md
index 239e895..9810a99 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,80 @@
-# edu_skill
- Alice Python education skill
+# Учим Python: Ваш Голосовой Наставник по Python в Алисе 🐍
+
+[](https://dialogs.yandex.ru/store/skills/9aa2ecba-alisas-test)
+[](https://opensource.org/licenses/MIT)
+[](https://dialogs.yandex.ru/)
+
+**Хотите освоить Python, но нет времени на учебники? "Учим Python" – это навык для Алисы, который превратит изучение Python в увлекательное голосовое приключение!**
+
+## 🤖 О навыке
+
+"Учим Python" – это ваш персональный AI-ассистент по изучению Python. Независимо от вашего уровня подготовки, навык поможет вам:
+
+* **Получить знания:** Узнавайте, как реализовать различные конструкции и концепции в Python, просто задавая вопросы Алисе голосом.
+* **Проверить себя:** Отвечайте на вопросы в формате увлекательного квеста и закрепляйте свои знания.
+* **Получить консультацию:** Обратитесь к навыку, и он проконсультирует вас по любым вопросам, связанным с Python.
+* **Решать задачи:** Тренируйте свои навыки программирования, решая тщательно отобранные задачки.
+* **Стать питонистом:** Копите опыт и знания, чтобы стать настоящим мастером Python!
+
+## ✨ Ключевые возможности
+
+* **Голосовой интерфейс:** Учитесь Python, используя только свой голос.
+* **Интерактивные уроки:** Получайте знания в удобном и интерактивном формате.
+* **Квест-викторина:** Проверьте свои знания в Python с помощью увлекательного квеста.
+* **Персональные консультации:** Получайте ответы на свои вопросы по Python в режиме реального времени.
+* **Практические задачи:** Решайте задачи по программированию и развивайте свои навыки.
+* **Поддержка:** Просто скажите "Помощь" или "Что ты умеешь", и Алиса расскажет вам обо всех возможностях навыка.
+
+## 🗣️ Как начать
+
+Чтобы начать изучение Python с Алисой:
+
+1. Активируйте навык, сказав: "Алиса, запусти навык Учим Python".
+2. Используйте голосовые команды, чтобы задавать вопросы, проходить квест или решать задачи.
+3. Если вам нужна помощь, просто скажите "Помощь" или "Что ты умеешь".
+
+**Примеры команд:**
+
+* "Алиса, как создать список в Python?"
+* "Алиса, начни квест по Python."
+* "Алиса, дай мне задачу по программированию."
+* "Алиса, помощь."
+
+## 🎯 Для кого этот навык
+
+Этот навык создан для:
+
+* Начинающих программистов, которые хотят изучить Python с нуля.
+* Опытных программистов, которые хотят освежить свои знания Python.
+* Всех, кто интересуется IT и хочет попробовать себя в программировании.
+
+## 💡 Вдохновение
+
+Мы создали этот навык для самых смышлёных людей, интересующихся IT. В наши дни таких всё больше и больше. Так почему бы тебе не присоединиться к ним?
+
+Удачи тебе, юный падаван! 🙂
+
+## 🔗 Ссылка на навык
+
+[Учим Python в магазине навыков Алисы](https://dialogs.yandex.ru/store/skills/9aa2ecba-alisas-test)
+
+## 💻 Технологии
+
+* Яндекс.Диалоги
+* Python (backend логика)
+
+## 🖼 Скриншоты
+
+
+
+## 🤝 Вклад
+
+Мы открыты для предложений и идей! Если у вас есть какие-либо предложения по улучшению навыка, пожалуйста, свяжитесь с нами.
+
+## 📜 Лицензия
+
+Этот проект лицензирован по лицензии MIT - смотрите файл [LICENSE](LICENSE) для деталей.
diff --git a/alisa's response.json b/alisa's response.json
new file mode 100644
index 0000000..149808e
--- /dev/null
+++ b/alisa's response.json
@@ -0,0 +1,53 @@
+{
+ "meta": {
+ "client_id": "ru.yandex.searchplugin/7.16 (none none; android 4.4.2)",
+ "interfaces": {
+ "account_linking": {},
+ "payments": {},
+ "screen": {}
+ },
+ "locale": "ru-RU",
+ "timezone": "UTC"
+ },
+ "request": {
+ "original_utterance": "user text",
+ "command": "user text",
+ "nlu": {
+ "entities": [],
+ "tokens": [
+ "да"
+ ],
+ "intents": {}
+ },
+ "markup": {
+ "dangerous_context": false
+ },
+ "type": "SimpleUtterance"
+ },
+ "session": {
+ "message_id": 0,
+ "new": false,
+ "session_id": "ea6be08d-9794-4ae2-89e2-e94f6734cc65",
+ "skill_id": "a8f78148-8184-4010-b508-ec70badddf82",
+ "user_id": "94748746704CDF263F766BC5E1F0F9D68CD6DB739F2E7CCEF975EC7FCF2A9666",
+ "user": {
+ "user_id": "86507D953A1790E1F26F46ED4874098F7BC2658CFC9588F9CCC3E1DD9C061A95"
+ },
+ "application": {
+ "application_id": "94748746704CDF263F766BC5E1F0F9D68CD6DB739F2E7CCEF975EC7FCF2A9666"
+ }
+ },
+ "state": {
+ "session": {
+ "lesson_choice": true,
+ "user_choice": true
+ },
+ "user": {
+ "new_user": false,
+ "last_lesson": 0,
+ "last_task": 0
+ },
+ "application": {}
+ },
+ "version": "1.0"
+}
\ No newline at end of file
diff --git a/buttons.py b/buttons.py
new file mode 100644
index 0000000..8f9ee72
--- /dev/null
+++ b/buttons.py
@@ -0,0 +1,26 @@
+from json_manager import get_main_commands_of_skill_as_list
+
+
+class Buttons:
+ """Класс для работы с кнопками Алисы."""
+ def __init__ (self):
+ self.BUTTONS = [ ]
+
+ def add_buttons (self, *button_texts: str, hide_all: bool) -> None:
+ """Добавляет новые кнопки."""
+ for button_text in button_texts:
+ self.BUTTONS.append ({"title": button_text, "hide": hide_all})
+
+ def remove_all_buttons (self) -> None:
+ """Удаляет все кнопки."""
+ self.BUTTONS = [ ]
+
+ def add_buttons_of_main_menu_in_text (self) -> None:
+ """Добавляет команды навыка на главное меню в текст."""
+ self.add_buttons (*get_main_commands_of_skill_as_list ( ), hide_all = False)
+
+
+if __name__ == '__main__':
+ buttons = Button ( )
+ buttons.add_buttons ("test1", "test2", "test3", hide_all = True)
+ print (buttons.BUTTONS)
\ No newline at end of file
diff --git a/consultant.py b/consultant.py
new file mode 100644
index 0000000..1ebb3d7
--- /dev/null
+++ b/consultant.py
@@ -0,0 +1,33 @@
+from sklearn.feature_extraction.text import TfidfVectorizer
+from sklearn.metrics.pairwise import cosine_similarity
+import json
+
+
+def index_of_max(lst):
+ maxi = 0
+ for i in range(len(lst)):
+ if lst[i] > lst[maxi]:
+ maxi = i
+ return maxi
+
+
+class ArtificialIntelligence:
+ def __init__(self, name_of_file):
+ with open(name_of_file, "r", encoding="utf-8") as f:
+ doc = dict(json.load(f))
+ self.base = []
+ a = [list(i.values()) for i in list(doc.values())]
+ print(a)
+ [self.base.extend(i) for i in a]
+ self.vectorizer = TfidfVectorizer()
+ self.docs_tfidf = self.vectorizer.fit_transform(self.base)
+
+ def get_similarity(self, query):
+ query = self.filter_of_query(query)
+ query_tfidf = self.vectorizer.transform([query])
+ a = list(cosine_similarity(query_tfidf, self.docs_tfidf).flatten())
+ return [self.base[index_of_max(a)], max(a)]
+
+ def filter_of_query(self, query):
+ stop_words = ["не", "без", "через", "у", "но", "о", "и", "как", "python", "а", "к", "в", "с", "за", "или", "либо", "же", "ж", "совсем", "ничуть", "отнюдь", "перед", "при", "про", "под", "по", "до", "чуть", "чуть-чуть"]
+ return " ".join([i for i in query.split(" ") if not i in stop_words])
\ No newline at end of file
diff --git a/email_sender.py b/email_sender.py
new file mode 100644
index 0000000..cc769a1
--- /dev/null
+++ b/email_sender.py
@@ -0,0 +1,41 @@
+import smtplib
+from email.mime.text import MIMEText
+from email.mime.multipart import MIMEMultipart
+
+
+class EmailSender:
+ def __init__(self, email, password, smtp_server='smtp.gmail.com', smtp_port=587):
+ self.email = email
+ self.password = password
+ self.smtp_server = smtp_server
+ self.smtp_port = smtp_port
+ self.server = None
+
+ def login(self):
+ try:
+ self.server = smtplib.SMTP(self.smtp_server, self.smtp_port)
+ self.server.starttls()
+ self.server.login(self.email, self.password)
+ print('Logged in successfully.')
+ except Exception as e:
+ print(f'Error: Could not login to the email server.\n{e}')
+
+ def send_email(self, to_addr, subject, body):
+ if self.server is None:
+ self.login()
+ from_addr = self.email
+ message = MIMEMultipart()
+ message['From'] = from_addr
+ message['To'] = to_addr
+ message['Subject'] = subject
+ message.attach(MIMEText(body, 'plain'))
+ try:
+ self.server.sendmail(from_addr, to_addr, message.as_string())
+ print(f'Sent email to {to_addr} with subject "{subject}" and message: {body}')
+ except Exception as e:
+ print(f'Error: Could not send email.\n{e}')
+
+
+if __name__ == '__main__':
+ email_sender = EmailSender ("leha.bondar.05@mail.ru", "Sstrelo4gGvip")
+ email_sender.send_email ("leha.bondar.05@mail.ru", "Test message", "Test text...")
\ No newline at end of file
diff --git a/enums.py b/enums.py
new file mode 100644
index 0000000..a5c662b
--- /dev/null
+++ b/enums.py
@@ -0,0 +1,24 @@
+import enum
+import random
+
+from typing import Literal
+
+
+@enum.unique
+class DifficultyLevels (enum.IntEnum):
+ EASY = 0
+ MEDIUM = 1
+ HARD = 2
+ VERY_HARD = 3
+
+ def get_random_difficulty_level_for_quest ( ) -> Literal[0, 1, 2]:
+ return random.randint (0, 2)
+
+ def get_random_difficulty_level_for_task ( ) -> Literal[0, 1, 2, 3]:
+ return random.randint (0, 3)
+
+
+if __name__ == '__main__':
+ print ("DifficultyLevels.get_random_difficulty_level_for_task: ",
+ DifficultyLevels.get_random_difficulty_level_for_task ( ),
+ sep = "")
\ No newline at end of file
diff --git a/images/1.png b/images/1.png
new file mode 100644
index 0000000..acec2d0
Binary files /dev/null and b/images/1.png differ
diff --git a/images/2.png b/images/2.png
new file mode 100644
index 0000000..0bd9f64
Binary files /dev/null and b/images/2.png differ
diff --git a/images/3.png b/images/3.png
new file mode 100644
index 0000000..5074cca
Binary files /dev/null and b/images/3.png differ
diff --git a/json_manager.py b/json_manager.py
new file mode 100644
index 0000000..73d547b
--- /dev/null
+++ b/json_manager.py
@@ -0,0 +1,127 @@
+import json
+import random
+
+
+with open ("texts_for_users.json", "r") as file:
+ texts_for_users = json.load (file)
+
+
+
+def get_text_for_new_user ( ) -> str:
+ return texts_for_users["for_new_user"]
+
+
+def get_hello_text ( ) -> str:
+ return random.choice (texts_for_users["hello_text"])
+
+
+def get_introduction_to_course ( ) -> str:
+ return texts_for_users["introduction_to_course"]
+
+
+def get_text_asking_if_user_has_forgotten_commands ( ) -> str:
+ return random.choice (texts_for_users["if_user_has_forgotten_commands"])
+
+
+def get_main_commands_of_skill_as_list ( ) -> list[str]:
+ return texts_for_users["main_commands_of_skill"]
+
+
+def get_main_commands_of_skill ( ) -> str:
+ commands_of_skill = ""
+ for command in texts_for_users["main_commands_of_skill"]:
+ commands_of_skill += command + "\n"
+ return commands_of_skill
+
+
+def get_text_that_says_which_lesson_user_stopped (lesson_number: int) -> str:
+ return random.choice (texts_for_users["you_stopped_at_lesson"]) + str (lesson_number)
+
+
+def get_theme_of_lesson (lesson_number: int) -> str:
+ return "ЗАТЫЧКА"
+ #return lessons[str(lesson_number)]["theme"]
+
+
+def get_lesson_text (lesson_number: int) -> str:
+ return "Затычка..."
+
+
+def get_text_that_says_which_task_user_stopped (task_number: int) -> str:
+ return random.choice (texts_for_users["you_stopped_at_task"]) + str (task_number)
+
+
+def get_text_that_says_answer_is_correct ( ) -> str:
+ return random.choice (texts_for_users["correct_answer"])
+
+
+def get_text_that_says_answer_is_wrong ( ) -> str:
+ return random.choice (texts_for_users["wrong_answer"])
+
+
+def get_text_that_says_there_is_no_answer_like_that ( ) -> str:
+ return random.choice (texts_for_users["there_is_no_answer_like_that"])
+
+
+def get_text_that_suggests_to_continue_or_change_difficulty_level ( ) -> str:
+ return random.choice (texts_for_users["continue_or_change_difficulty_level"])
+
+
+def get_apology_text ( ) -> str:
+ return random.choice (texts_for_users["something_is_unclear"])
+ # Выбирается одно случайное извинение от Алисы, если она что-то не поняла.
+
+
+def get_farewell_text ( ) -> str:
+ head_of_farewell: str = random.choice (texts_for_users["head_of_farewell"])
+ body_of_farewell: str = random.choice (texts_for_users["body_of_farewell"])
+ return head_of_farewell + body_of_farewell
+ # Достаётся начало прощания, например: "До свидания";
+ # а потом тело прощания, например: ", хорошего дня!"
+
+
+def get_random_win_sound ( ) -> str:
+ return random.choice (texts_for_users["win_sounds"])
+
+def get_random_lose_sound ( ) -> str:
+ return random.choice (texts_for_users["lose_sounds"])
+
+def get_random_sound_of_looking_results ( ) -> str:
+ return random.choice (texts_for_users["sound_of_looking_results"])
+
+def get_introduction_sound ( ) -> str:
+ return ""
+
+def get_random_farewell_sound ( ) -> str:
+ return random.choice (texts_for_users["farewell_sounds"])
+
+
+def get_random_win_picture ( ) -> str:
+ return random.choice (texts_for_users["win_pictures"])
+
+def get_random_looking_results_pictures ( ) -> str:
+ return random.choice (texts_for_users["looking_results_pictures"])
+
+def get_random_level_up_picture ( ) -> str:
+ return random.choice (texts_for_users["level_up_pictures"])
+
+def get_random_farewell_picture ( ) -> str:
+ return random.choice (texts_for_users["farewell_pictures"])
+
+
+def get_random_lesson_completion ( ) -> str:
+ return random.choice (texts_for_users["user_has_completed_lesson"])
+
+def get_random_sequel_of_lesson ( ) -> str:
+ return random.choice (texts_for_users["ask_user_if_he_wants_to_take_next_lesson"])
+
+def get_random_course_completion ( ) -> str:
+ return random.choice (texts_for_users["user_has_completed_course"])
+
+
+def get_resume_text ( ) -> str:
+ return random.choice (texts_for_users["resume"])
+
+
+def get_soothing_text ( ) -> str:
+ return random.choice (texts_for_users["soothing_text"])
\ No newline at end of file
diff --git a/lesson_getter.py b/lesson_getter.py
new file mode 100644
index 0000000..811806d
--- /dev/null
+++ b/lesson_getter.py
@@ -0,0 +1,117 @@
+import json
+
+
+class LessonGetter:
+ """Класс для работы с уроками Курса.
+ В конструкторе принимает тему урока и тему его подурока.
+ """
+ def __init__ (self, lesson_theme: str, sublesson_theme: str):
+ self.current_lesson_theme = lesson_theme
+ self.current_sublesson_theme = sublesson_theme
+ self._check_current_lesson_theme_and_current_sublesson_theme_in_init ( )
+ self._read_file_with_lessons ( )
+ self._set_initial_lesson_values_if_necessary ( )
+ self._check_sublesson_is_in_lesson ( )
+
+ def _read_file_with_lessons (self) -> None:
+ with open (self._name_of_file_with_lessons, "r", encoding = "utf8") as file_with_lessons:
+ self.all_lessons: dict = json.load (file_with_lessons)
+ self.lesson_themes = tuple (self.all_lessons.keys())
+ self._find_sublesson_themes ( )
+
+ @property
+ def _name_of_file_with_lessons (self) -> str:
+ return "lessons.json"
+
+ def _find_sublesson_themes (self) -> None:
+ self.all_sublesson_themes = { }
+ for lesson_theme in self.lesson_themes:
+ self.all_sublesson_themes[lesson_theme] = tuple (self.all_lessons[lesson_theme].keys())
+
+ def _check_current_lesson_theme_and_current_sublesson_theme_in_init (self) -> None:
+ if not self.current_lesson_theme and self.current_sublesson_theme:
+ raise ValueError (f"Не указано имя урока в конструкторе класса {__class__.__name__}!")
+ elif self.current_lesson_theme and not self.current_sublesson_theme:
+ raise ValueError (f"Не указано имя подурока в конструкторе класса {__class__.__name__}!")
+
+ def _set_initial_lesson_values_if_necessary (self) -> None:
+ # Если не указаны тема урока и тема его подурока, то
+ if not self.current_lesson_theme and not self.current_sublesson_theme:
+ # Поставить тему первого урока и тему первого его подурока
+ self.current_lesson_theme = self.lesson_themes[0]
+ self.current_sublesson_theme = self._get_first_sublesson_theme ( )
+
+ def _get_first_sublesson_theme (self) -> str:
+ return self.all_sublesson_themes[self.current_lesson_theme][0]
+
+ def _check_sublesson_is_in_lesson (self) -> None:
+ if not self.current_sublesson_theme in self.all_sublesson_themes[self.current_lesson_theme]:
+ raise ValueError ("Нет такого подурока в текущем уроке: " +
+ f"\"{self.current_sublesson_theme}\" не принадлежит \"{self.current_lesson_theme}\"!")
+
+
+ @property
+ def text_of_current_sublesson (self) -> str:
+ """Текст текущего подурока."""
+ return self.all_lessons[self.current_lesson_theme][self.current_sublesson_theme]["text"]
+
+ @property
+ def use_function_to_read_code (self) -> bool:
+ """Нужно ли использовать функцию для чтения кода."""
+ return self.all_lessons[self.current_lesson_theme][self.current_sublesson_theme]["use_function_to_read_code"]
+
+
+ def move_to_next_sublesson (self) -> None:
+ """Перейти к следующему подуроку.
+ Если его нет, то current_sublesson_theme будет равен None.
+ В случае чего будет возвращена ошибка ValueError с пояснением проблемы.
+ """
+ sublesson_themes_of_current_lesson = tuple (self.all_sublesson_themes[self.current_lesson_theme])
+ self._check_current_sublesson_theme ( )
+ index_of_current_sublesson_theme = sublesson_themes_of_current_lesson.index (self.current_sublesson_theme)
+ # Если тема текущего подурока не последняя, то
+ if self.current_sublesson_theme != sublesson_themes_of_current_lesson[-1]:
+ self.current_sublesson_theme = sublesson_themes_of_current_lesson[index_of_current_sublesson_theme + 1]
+ else:
+ self.current_sublesson_theme = None # Значит, следующей темы подурока нет
+
+ def move_to_next_lesson (self) -> None:
+ """Перейти к следующему уроку.
+ Если его нет, то current_lesson_theme и current_sublesson_theme будут равны None.
+ В случае чего будет возвращена ошибка ValueError с пояснением проблемы.
+ """
+ self._check_current_lesson_theme ( )
+ index_of_current_lesson_theme = self.lesson_themes.index(self.current_lesson_theme)
+ # Если тема текущего урока не последняя, то
+ if self.current_lesson_theme != self.lesson_themes[-1]:
+ self.current_lesson_theme = self.lesson_themes[index_of_current_lesson_theme + 1]
+ self.current_sublesson_theme = self._get_first_sublesson_theme ( )
+ else:
+ self.current_lesson_theme = "" # Значит, все уроки пройдены
+ self.current_sublesson_theme = ""
+
+ def move_to_lesson (self, lesson_theme: str) -> None:
+ """Перейти к указанному уроку, если он есть.
+ Иначе выдать ошибку ValueError."""
+ if lesson_theme in self.lesson_themes: self.current_lesson_theme = lesson_theme
+ else: raise ValueError ("Нельзя перейти к несуществующему уроку!")
+ self.current_sublesson_theme = self._get_first_sublesson_theme ( )
+
+
+ def _check_current_sublesson_theme (self) -> None:
+ if self.current_sublesson_theme is None:
+ raise ValueError ("Это последний подурок! Перейти к следующему нельзя!")
+
+ def _check_current_lesson_theme (self) -> None:
+ if self.current_lesson_theme is None:
+ raise ValueError ("Это последний урок! Перейти к следующему нельзя!")
+
+
+
+if __name__ == '__main__':
+ lesson_getter = LessonGetter ("", "") # Так должно быть в первый раз
+ print ("Все уроки с подуроками:")
+ print (lesson_getter.all_sublesson_themes)
+ print ( )
+ print ("Текущий урок:", lesson_getter.current_lesson_theme)
+ print ("Текущий подурок:", lesson_getter.current_sublesson_theme)
\ No newline at end of file
diff --git a/lessons.json b/lessons.json
index 82f2cb7..ea2b5aa 100644
--- a/lessons.json
+++ b/lessons.json
@@ -1,52 +1,411 @@
-{
- "введение" :
- {
- "text" :
- [
- "Предисловие.\nPython - это высокоуровневый, интерпретируемый язык программирования, который был создан в конце 1980-х годов Гвидо ван Россумом.",
- "Он обладает простым и понятным синтаксисом, что делает его очень популярным среди начинающих программистов и профессионалов. Python поддерживает множество парадигм программирования, включая процедурное, объектно-ориентированное и функциональное программирование. ",
- "Кроме того, Python имеет большое количество библиотек и фреймворков, которые делают его подходящим для различных задач, включая научные вычисления, веб-разработку, анализ данных и машинное обучение. Python также является платформонезависимым языком, что позволяет использовать его на разных операционных системах.",
- "Все это делает Python одним из самых популярных языков программирования в мире, и он продолжает расти и развиваться с каждым годом.",
- "Давайте начнем с приветствия мира Python! Откройте свой любимый текстовый редактор и введите следующий код: \nprint('Привет, мир!')\nСохраните файл с расширением .py, например, hello_world.py, и запустите его. Вы должны увидеть сообщение \"Привет, мир!\" на экране.",
- "Это был очень простой пример, но Python имеет много возможностей и функций, которые мы будем изучать вместе по мере продвижения.",
- "Курс начнется с изучения основных конструкций языка, таких как переменные, условные выражения, циклы и функции. Это поможет вам получить крепкую основу для дальнейшего изучения языка.",
- "Удачного изучения Python!"
- ],
- "index":0,
- "max_index":7
- },
- "комментарии":
- {
- "text" :
- [
- "Второй урок. Комментарии. \nКомментарии в Python - это текст, который игнорируется интерпретатором Python при выполнении программы. Они используются для пояснения кода, описания работы программы или напоминания о том, что нужно доделать.",
- "Комментарии начинаются с символа решетки (#) и идут до конца строки. Вот несколько примеров:\n# Это комментарий, который игнорируется интерпретатором\nprint(\"Hello!\") # Это комментарий после выражения",
- "Комментарии могут быть как однострочными, так и многострочными. Однострочные комментарии удобны для коротких пояснений, а многострочные - для более подробного описания. Для создания многострочных комментариев в Python можно использовать тройные кавычки, как в примере ниже:\n\"\"\"\nЭто многострочный комментарий, который может\nсодержать несколько строк.\nОн игнорируется интерпретатором Python.\n\"\"\"",
- "Кроме того, комментарии можно использовать для временного отключения участков кода. Например, если нужно проверить, как работает программа без определенного участка кода, его можно закомментировать, добавив символ # в начало каждой строки, и выполнить программу. Если нужно восстановить работу участка кода, символы # можно убрать.",
- "Важно помнить, что комментарии должны быть понятными и информативными. Хороший комментарий должен описывать не только то, что делает код, но и почему это нужно, какие альтернативы были рассмотрены, какие возможные проблемы могут возникнуть, и т.д."
- ],
- "index":1,
- "max_index":4
- },
- "переменные":
- {
- "text" :
- [
- "Третий урок. Переменные. \nВ этом уроке я расскажу тебе о переменных в Python. Переменная - это место, где мы можем хранить данные в программе. В Python переменная создается присвоением значения с помощью знака \"=\". Например, чтобы создать переменную с именем \"x\" и присвоить ей значение 5, нужно написать:\nx = 5\nЗдесь мы создали переменную \"x\" и присвоили ей значение 5.",
- "Имя переменной может состоять из букв, цифр и символа подчеркивания \"_\", но оно не может начинаться с цифры. Также в Python существует ряд зарезервированных слов, которые нельзя использовать в качестве имени переменной (например, \"if\", \"else\", \"for\" и т.д.).",
- "Значение переменной можно изменить путем повторного присваивания. Например, чтобы изменить значение переменной \"x\" на 10, нужно написать:\nx = 10",
- "В Python существует несколько встроенных типов данных, таких как:\nЦелые числа (int)\nВещественные числа (float)\nСтроки (str)\nБулевы значения (bool)\nСписки (list)\nКортежи (tuple)\nСловари (dict)\nМножества (set)\nКаждый тип имеет свои специфические методы и свойства, которые можно использовать для работы с данными.",
- "Давайте рассмотрим их подробнее:\nЦелые числа (int)\nЦелые числа представляют собой положительные или отрицательные числа без дробной части. В Python целочисленные значения записываются без десятичной точки. Примеры:\nx = 5\ny = -10",
- "Вещественные числа (float)\nВещественные числа представляют собой числа с дробной частью. В Python вещественные значения записываются с десятичной точкой. Примеры:\nx = 3.14\ny = -0.5\n",
- "Строки (str)\nСтроки представляют собой последовательности символов в кавычках. \nВ Python строки можно задавать как в одинарных, так и в двойных кавычках. Примеры:\nx = 'Hello, World!'\ny = \"Python is awesome\"",
- "Булевы значения (bool)\nБулевы значения представляют собой логические значения и могут быть либо True (истина), либо False (ложь). В будущем мы узнаем, что булевы значения используются в условных операторах (if, while, for) и логических выражениях. Примеры:\nx = True\ny = False\nС остальными типами данных мы познакомимся позже",
- "Python является языком с динамической типизацией, что означает, что тип переменной определяется автоматически во время выполнения программы, в зависимости от значения, которое мы присваиваем ей. Например, если мы присваиваем переменной \"x\" значение 5, то ее тип будет целочисленным (int), а если мы присваиваем ей значение \"Hello, World!\", то ее тип будет строковым (str).",
- "Чтобы узнать тип переменной, можно использовать функцию \"type()\". Например:\nx = 5\nprint(type(x)) # int\ny = \"Hello, World!\"\nprint(type(y)) # str",
- "Несколько полезных советов по использованию переменных в Python:\nИспользуйте осмысленные имена переменных, чтобы код был более читаемым.\nИзбегайте использования зарезервированных слов в качестве имен переменных.\nИзбегайте использования слишком длинных имен переменных, чтобы не усложнять код.\nИспользуйте комментарии для пояснения, что делает каждая переменная в вашем коде.",
- "Важно помнить, что комментарии должны быть понятными и информативными. Хороший комментарий должен описывать не только то, что делает код, но и почему это нужно, какие альтернативы были рассмотрены, какие возможные проблемы могут возникнуть, и т.д.",
- "Сегодня мы закончили наш курс, этот урок был последним. Мы прошли все темы и научились многому новому. Удачи в дальнейшем изучении Python!"
- ],
- "index":2,
- "max_index":11
- }
+{
+ "Урок 1: Введение в Python": {
+ "Предисловие": {
+ "text": "Python – простой и минималистичный язык. Чтение хорошей программы на Python очень напоминает чтение английского текста, хотя и достаточно строгого! Такая псевдо-кодовая природа Python является одной из его самых сильных сторон. Она позволяет вам сосредоточиться на решении задачи, а не на самом языке.",
+ "use_function_to_read_code": false
+ },
+ "Python - Язык высокого уровня": {
+ "text": "При написании программы на Python вам никогда не придётся отвлекаться на такие низкоуровневые детали, как управление памятью, используемой вашей программой, и т.п.",
+ "use_function_to_read_code": false
+ },
+ "Python - Язык объектно-ориентированный": {
+ "text": "Python поддерживает как процедурно-ориентированное, так и объектноориентированное программирование. В процедурно-ориентированных языках программы строятся на основе процедур или функций, которые представляют собой просто-напросто многократно используемые фрагменты программы. В объектно-ориентированных языках программирования программы строятся на основе объектов, объединяющих в себе данные и функционал. \n\nPython предоставляет простые, но мощные средства для ООП, особенно в сравнении с такими большими языками программирования, как C++ или Java.",
+ "use_function_to_read_code": false
+ },
+ "Python - Язык встраиваемый": {
+ "text": "В Python можно встраивать в программы на C/C++, чтобы предоставлять возможности написания сценариев их пользователям.",
+ "use_function_to_read_code": false
+ }
+ },
+
+ "Урок 2: Установка Python": {
+ "Предисловие": {
+ "text": "Итак для того чтобы нам начать писать код нужно установть сам Python, а так же редактор для него ",
+ "use_function_to_read_code": false
+ },
+ "Установка в Windows": {
+ "text": "Посетите страницу http://www.python.org/download/ и загрузите последнюю версию. Установка производится так же, как и для любых других программ для Windows.",
+ "use_function_to_read_code": false
+ },
+ "Выбор редактора": {
+ "text": "Поскольку мы не можем набирать программу в командной так как, нам понадобится сохранять программы в файлах. \n\nИтак нам нужен редактор для работы с файлами программ. Выбор редактора крайне важен. Хороший редактор поможет вам легко писать программы на Python, делая ваше путешествие более комфортным, а также позволяя быстрее и безопаснее достичь вашей цели. \n\nОдно из самых основных требований – это подсветка синтаксиса, когда разные элементы программы на Python раскрашены так, чтобы вы могли легко видеть вашу программу и ход её выполнения. \n\nЕсли вы не знаете, с чего начать, мы бы порекомендовали вам пользоваться программой PyCharm",
+ "use_function_to_read_code": false
+ },
+ "Создание проекта": {
+ "text": "Запустите выбранный вами редактор, введите следующую программу и сохраните её под именем helloworld.py . \n\nЕсли вы пользуетесь PyCharm, нажмите «New Project» → «выберете путь где будут хранится ваши программы» → «создавайте проект!»",
+ "use_function_to_read_code": false
+ }
+ },
+
+ "Урок 3: Основы": {
+ "Мощный язык": {
+ "text": "Python – это, один из немногих языков программирования, простых в освоении и одновременно мощных. \n\nЭто очень важно и для начинающих, и для специалистов, но что ещё важнее – на нём приятно программировать.",
+ "use_function_to_read_code": false
+ },
+ "Комментарии": {
+ "text": "Комментарии – это то, что пишется после символа #, и представляет интерес лишь как заметка для читающего программу. \n\nНапример: \nprint(Привет, Мир!) # print -- это функция",
+ "use_function_to_read_code": false
+ },
+ "Строки": {
+ "text": "Строка – это последовательность символов, записанная в массиве. Чаще всего строки – это просто некоторые наборы слов. \n\nСлова могут быть как на английском языке, так и на любом другом, поддерживаемом стандартом Unicode, что означает почти на любом языке мира.",
+ "use_function_to_read_code": false
+ },
+ "Одинарные кавычки": {
+ "text": "Строку можно указать, используя одинарные кавычки, как например, 'Фраза в кавычках'. Все пробелы и знаки табуляции сохранятся, как есть.",
+ "use_function_to_read_code": false
+ },
+ "Двойные кавычки": {
+ "text": "Строки в двойных кавычках работают точно так же, как и в одинарных. Например,\"Как тебя зовут?\".",
+ "use_function_to_read_code": false
+ },
+ "Типы данных": {
+ "text": "Переменные могут хранить значения разных типов, называемых типами данных. Основными типами являются числа и строки, о которых мы уже говорили. В дальнейших главах мы увидим, как создавать свои собственные типы при помощи классов.",
+ "use_function_to_read_code": false
+ },
+ "Переменные": {
+ "text": "Использование одних лишь литеральных констант может скоро наскучить – нам ведь нужен способ хранения любой информации и манипулирования ею. Вот здесь на сцену выходят переменные. Слово «переменные» говорит само за себя – их значение может меняться, а значит, вы можете хранить в переменной всё что угодно. \n\nПеременные – это просто области памяти компьютера, в которых вы храните некоторую информацию. В отличие от констант, к такой информации нужно каким-то образом получать доступ, поэтому переменным даются имена.",
+ "use_function_to_read_code": false
+ }
+ },
+
+ "Урок 4: Операторы и выражения": {
+ "О операндах и выражениях": {
+ "text": "Большинство предложений (логических строк) в программах содержат выражения. Простой пример выражения: 2 + 3. Выражение можно разделить на операторы и операнды. Операторы – это некий функционал, производящий какие-либо действия, который может быть представлен в виде символов, как например +, или специальных зарезервированных слов. Операторы могут производить некоторые действия над данными, и эти данные называются операндами. В нашем случае 2 и 3 – это операнды.",
+ "use_function_to_read_code": false
+ },
+ "Оператор сложения": {
+ "text": "Объяснение: суммирует два объекта. \n\nПример: 3 + 5 даст 8; 'aboba' + 'baba' даст 'abobababa'",
+ "use_function_to_read_code": false
+ },
+ "Оператор вычитания": {
+ "text": "Объяснение: Даёт разность двух чисел; если первый операнд отсутствует, он считается равным нулю. \n\nПример: -5.2 даст отрицательное число, а 50 - 24 даст 26.",
+ "use_function_to_read_code": false
+ },
+ "Оператор умножения": {
+ "text": "Объяснение: Даёт произведение двух чисел или возвращает строку, повторённую заданное число раз. \n\nПример: 2 * 3 даст 6. 'la' * 3 даст 'lalala'",
+ "use_function_to_read_code": false
+ },
+ "Оператор деления": {
+ "text": "Объяснение: Возвращает частное от деления x на y. \n\nПример: 4 / 2 даст 2",
+ "use_function_to_read_code": false
+ },
+ "Оператор меньше": {
+ "text": "Объяснение: Определяет, верно ли, что x меньше y. Все операторы сравнения возвращают True или False. Обратите внимание на заглавные буквы в этих словах. \n\nПример: 5 < 3 даст False",
+ "use_function_to_read_code": false
+ },
+ "Оператор больше": {
+ "text": "Объяснение: Определяет, верно ли, что x больше y. \n\nПример: 5 > 3 даст True",
+ "use_function_to_read_code": false
+ },
+ "Оператор равенства": {
+ "text": "Объяснение: Проверяет,одинаковы ли объекты. \n\nПример: x = 2; y = 2; x == y даёт True",
+ "use_function_to_read_code": false
+ },
+ "Оператор неравенства": {
+ "text": "Объяснение: Проверяет, верно ли, что объекты не равны. \n\nПример: x = 2; y = 3; x != y даёт True",
+ "use_function_to_read_code": false
+ },
+ "Оператор логического НЕ": {
+ "text": "Объяснение: Если x равно True, оператор вернёт False. Если же x равно False, получим True. \n\nПример: x = True; not x даёт False",
+ "use_function_to_read_code": false
+ },
+ "Оператор логического И": {
+ "text": "Объяснение: x and y даёт False, если x равно False , в противном случае возвращает значение y. \n\nПример: x = False; y = True; x and y возвращает False, поскольку x равно False",
+ "use_function_to_read_code": false
+ },
+ "Оператор логического ИЛИ": {
+ "text": "Объяснение: Если x равно True, в результате получим True, в противном случае получим значение y. \n\nПример: x = True; y = False; x or y даёт True",
+ "use_function_to_read_code": false
+ }
+ },
+
+ "Урок 5: Поток команд": {
+ "Предисловие": {
+ "text": "В программах, которые мы до сих пор рассматривали, последовательность команд всегда выполнялась Python по порядку строго сверху вниз. А что, если нам необходимо изменить поток выполняющихся команд? Например, если требуется, чтобы программа принимала некоторое решение и выполняла различные действия в зависимости от ситуации; скажем, печатала «Доброе утро» или «Добрый вечер» в зависимости от времени суток. \n\nКак вы уже, наверное, догадались, этого можно достичь при помощи операторов управления потоком. В Python есть три оператора управления потоком: if, for и while.",
+ "use_function_to_read_code": false
+ },
+ "Оператор if": {
+ "text": "Оператор if используется для проверки условий: если условие верно, выполняется блок выражений (называемый «if-блок»), иначе выполняется другой блок выражений (называемый «else-блок»). Блок «else» является необязательным.",
+ "use_function_to_read_code": false
+ },
+ "Пример оператора if": {
+ "text": "a = 2\nb = 5\nif a > b:\n print (a)\nelif a < b:\n print (b)\nelse:\n print (\"a и b равны\")",
+ "use_function_to_read_code": true
+ },
+ "Оператор while": {
+ "text": "Оператор while позволяет многократно выполнять блок команд до тех пор, пока выполняется некоторое условие. Это один из так называемых операторов цикла. Он также может иметь необязательный пункт else.",
+ "use_function_to_read_code": false
+ },
+ "Пример оператора while": {
+ "text": "while 1 == 1:\n print (\"Бесконечный цикл\")",
+ "use_function_to_read_code": true
+ },
+ "Цикл for": {
+ "text": "Оператор for..in также является оператором цикла, который осуществляет итерацию по последовательности объектов, т.е. проходит через каждый элемент в последовательности. Мы узнаем больше о последовательностях в дальнейших главах, а пока просто запомните, что последовательность – это упорядоченный набор элементов.",
+ "use_function_to_read_code": false
+ },
+ "Пример цикла for": {
+ "text": "for i in range(10):\n print(i)\nprint('Цикл for закончен')",
+ "use_function_to_read_code": true
+ },
+ "Оператор break": {
+ "text": "Оператор break служит для прерывания цикла, т.е. остановки выполнения команд даже если условие выполнения цикла ещё не приняло значения False или последовательность элементов не закончилась.\n\nВажно отметить, что если циклы for или while прервать оператором break, соответствующие им блоки else выполняться не будут.",
+ "use_function_to_read_code": false
+ },
+ "Пример оператора break": {
+ "text": "while 1 == 1:\n print (\"Бесконечный цикл\")\n break",
+ "use_function_to_read_code": true
+ },
+ "Оператор continue": {
+ "text": "Оператор continue используется для указания Python, что необходимо пропустить все оставшиеся команды в текущем блоке цикла и продолжить со следующей итерации цикла",
+ "use_function_to_read_code": false
+ },
+ "Пример оператора continue": {
+ "text": "for count in range (10):\n if count == 7: continue\n print (count)",
+ "use_function_to_read_code": true
+ }
+ },
+
+ "Урок 6: Функции": {
+ "Предисловие": {
+ "text": "Функции – это многократно используемые фрагменты программы. Они позволяют дать имя определённому блоку команд с тем, чтобы впоследствии запускать этот блок по указанному имени в любом месте программы и сколь угодно много раз. Это называется вызовом функции. Мы уже использовали много встроенных функций, как то len и range.\n\nФункции определяются при помощи зарезервированного слова def. После этого слова указывается имя функции, за которым следует пара скобок, в которых можно указать имена некоторых переменных, и заключительное двоеточие в конце строки. Далее следует блок команд, составляющих функцию.",
+ "use_function_to_read_code": false
+ },
+ "Пример применения функций": {
+ "text": "def sayHello():\n print('Привет, Мир!')\nsayHello() # вызов функции",
+ "use_function_to_read_code": true
+ },
+ "Как работают функции": {
+ "text": "Мы определили функцию с именем sayHello, используя описанный выше синтаксис. Эта функция не принимает параметров, поэтому в скобках не объявлены какие-либо переменные. Параметры функции – это некие входные данные, которые мы можем передать функции, чтобы получить соответствующий им результат.",
+ "use_function_to_read_code": false
+ },
+ "Параметры функций": {
+ "text": "Функции могут принимать параметры, т.е. некоторые значения, передаваемые функции для того, чтобы она что-либо сделала с ними. Эти параметры похожи на переменные, за исключением того, что значение этих переменных указывается при вызове функции, и во время работы функции им уже присвоены их значения.\n\nПараметры указываются в скобках при объявлении функции и разделяются запятыми. Аналогично мы передаём значения, когда вызываем функцию. Обратите внимание на терминологию: имена, указанные в объявлении функции, называются параметрами, тогда как значения, которые вы передаёте в функцию при её вызове, – аргументами.",
+ "use_function_to_read_code": false
+ },
+ "Пример": {
+ "text": "def maximum(x, y):\n if x > y:\n return x\n elif x == y:\n return 'Числа равны.'\n else:\n return y\n\nprint(maximum(2, 3))",
+ "use_function_to_read_code": true
+ },
+ "Как это работает": {
+ "text": "Функция maximum возвращает максимальный из двух параметров, которые в\nданном случае передаются ей при вызове. Она использует обычный условный оператор if..else для определения наибольшего числа, а затем возвращает это число.",
+ "use_function_to_read_code": false
+ },
+ "Локальные переменные": {
+ "text": "При объявлении переменных внутри определения функции, они никоим образом не связаны с другими переменными с таким же именем за пределами функции – т.е. имена переменных являются локальными в функции. Это называется областью видимости переменной. Область видимости всех переменных ограничена блоком, в котором они объявлены, начиная с точки объявления имени.",
+ "use_function_to_read_code": false
+ },
+ "Зарезервированное слово global": {
+ "text": "Чтобы присвоить некоторое значение переменной, определённой на высшем уровне программы необходимо указать глобально. Сделаем это при помощи зарезервированного слова global. Без применения global невозможно присвоить значение переменной, определённой за пределами функции.\n\nИспользование зарезервированного слова global достаточно ясно показывает, что переменная объявлена в самом внешнем блоке.",
+ "use_function_to_read_code": false
+ },
+ "Зарезервированное слово nonlocal": {
+ "text": "****\n\nМы увидели, как получать доступ к переменным в локальной и глобальной области видимости. Есть ещё один тип области видимости, называемый «нелокальной» (nonlocal) областью видимости, который представляет собой нечто среднее между первыми двумя. Нелокальные области видимости встречаются, когда вы определяете функции внутри функций.",
+ "use_function_to_read_code": false
+ },
+ "Значения аргументов по умолчанию": {
+ "text": "Зачастую часть параметров функций могут быть необязательными, и для них будут использоваться некоторые заданные значения по умолчанию, если пользователь не укажет собственных. Этого можно достичь с помощью значений аргументов по умолчанию. Их можно указать, добавив к имени параметра в определении функции оператор присваивания (=) с последующим значением.",
+ "use_function_to_read_code": false
+ },
+ "Ключевые аргументы": {
+ "text": "Если имеется некоторая функция с большим числом параметров, и при её вызове требуется указать только некоторые из них, значения этих параметров могут задаваться по их имени – это называется ключевые параметры. В этом случае для передачи аргументов функции используется имя (ключ) вместо позиции (как было до сих пор).\n\nЕсть два преимущества такого подхода: во-первых, использование функции становится легче, поскольку нет необходимости отслеживать порядок аргументов; во-вторых, можно задавать значения только некоторым избранным аргументам, при условии, что остальные параметры имеют значения аргумента по умолчанию.",
+ "use_function_to_read_code": false
+ },
+ "Переменное число параметров": {
+ "text": "Иногда бывает нужно определить функцию, способную принимать любое число параметров. Этого можно достичь при помощи звёздочек",
+ "use_function_to_read_code": false
+ },
+ "Оператор return": {
+ "text": "Оператор return используется для возврата из функции, т.е. для прекращения её работы и выхода из неё. При этом можно также вернуть некоторое значение из функции.",
+ "use_function_to_read_code": false
+ }
+ },
+
+ "Урок 7: Модули": {
+ "Предисловие": {
+ "text": "Как можно использовать код повторно, помещая его в функции, мы уже видели. А что, если нам понадобится повторно использовать различные функции в других наших программах? Как вы уже, наверное, догадались, ответ – модули.\n\nСуществуют разные способы составления модулей, но самый простой – это создать файл с расширением .py, содержащий функции и переменные.\n\nДругой способ – написать модуль на том языке программирования, на котором написан сам интерпретатор Python. Например, можно писать модули на языке программирования C, которые после компиляции могут использоваться стандартным интерпретатором Python\n\nСперва посмотрим, как использовать модули стандартной библиотеки.",
+ "use_function_to_read_code": false
+ },
+ "Пример": {
+ "text": "Представим, что мы хотим создать пакет под названием «world» с субпакетами «asia», «africa» и т.д., которые, в свою очередь, будут содержать модули «india», «madagascar» и т.д.\n\nДля этого следовало бы создать следующую структуру каталогов:\n\n| - <некоторый каталог из sys.path>/\n| |---- world/\n| |---- init.py\n| |---- asia/\n| | |---- init.py\n| | |---- india/\n| | |---- init.py\n| | |---- foo.py\n| |---- africa/\n| |---- init.py\n| |---- madagascar/\n| |---- init.py\n| |---- bar.py",
+ "use_function_to_read_code": false
+ },
+ "Как это работает": {
+ "text": "Мы вызываем функцию dir, не передавая ей параметров. По умолчанию, она возвращает список атрибутов текущего модуля. Обратите внимание, что список импортированных модулей также входит туда.\n\nЧтобы пронаблюдать за действием dir, мы определяем новую переменную a и присваиваем ей значение, а затем снова вызываем dir. Видим, что в полученном списке появилось дополнительное значение. Удалим переменную/атрибут из текущего модуля при помощи оператора del, и изменения вновь отобразятся на выводе функции dir.\n\nЗамечание по поводу del: этот оператор используется для удаления переменной/имени, и после его выполнения, в данном случае – del a, к переменной a больше невозможно обратиться – её как будто никогда и не было.",
+ "use_function_to_read_code": false
+ },
+ "Файлы байткода .pyc": {
+ "text": "Импорт модуля – относительно дорогостоящее мероприятие, поэтому Python предпринимает некоторые трюки для ускорения этого процесса. Один из способов – создать байткомпилированные файлы (или байткод) с расширением .pyc, которые являются некой промежуточной формой, в которую Python переводит программу (помните раздел «Введение» о том, как работает Python?). Такой файл .pyc полезен при импорте модуля в следующий раз в другую программу – это произойдёт намного быстрее, поскольку значительная часть обработки, требуемой при импорте модуля, будет уже проделана. Этот байткод также является платформо-независимым.",
+ "use_function_to_read_code": false
+ },
+ "Оператор from... import...": {
+ "text": "Чтобы импортировать переменную argv прямо в программу и не писать всякий раз sys. При обращении к ней, можно воспользоваться выражением «from sys import argv».\n\nДля импорта всех имён, использующихся в модуле sys, можно выполнить команду «from sys import *». Это работает для любых модулей.\n\nВ общем случае вам следует избегать использования этого оператора и использовать вместо этого оператор import, чтобы предотвратить конфликты имён и не затруднять чтение программы.",
+ "use_function_to_read_code": false
+ },
+ "Создание собственных модулей": {
+ "text": "Создать собственный модуль очень легко. Да вы всё время делали это! Ведь каждая программа на Python также является и модулем. Необходимо лишь убедиться, что у неё установлено расширение .py.",
+ "use_function_to_read_code": false
+ },
+ "Функция dir": {
+ "text": "Встроенная функция dir() возвращает список имён, определяемых объектом. Например, для модуля в этот список входят функции, классы и переменные, определённые в этом модуле.\n\nЭта функция может принимать аргументы. Если в качестве аргумента указано имя модуля, она возвращает список имён, определённых в этом модуле. Если никакого аргумента не передавать, она вернёт список имён, определённых в текущем модуле.",
+ "use_function_to_read_code": false
+ },
+ "Пакеты": {
+ "text": "К настоящему времени вы, вероятно, начали наблюдать некоторую иерархию в организации ваших программ. Переменные обычно находятся в функциях. Функции и глобальные переменные обычно находятся в модулях. А что, если возникнет необходимость как-то организовать модули? Вот здесь-то и выходят на сцену пакеты.\n\nПакеты – это просто каталоги с модулями и специальным файлом init.py, который показывает Python, что этот каталог особый, так как содержит модули Python.\n\nПредставим, что мы хотим создать пакет под названием «world» с субпакетами «asia», «africa» и т.д., которые, в свою очередь, будут содержать модули «india», «madagascar» и т.д.",
+ "use_function_to_read_code": false
+ }
+ },
+
+ "Урок 8: Структуры данных": {
+ "Структуры данных": {
+ "text": "Структуры данных – это, по сути, и есть структуры, которые могут хранить некоторые данные вместе. Другими словами, они используются для хранения связанных данных.\n\nВ Python существуют четыре встроенных структуры данных: список, кортеж, словарь и множество. Посмотрим, как ими пользоваться, и как они могут облегчить нам жизнь.",
+ "use_function_to_read_code": false
+ },
+ "Список": {
+ "text": "Список – это структура данных, которая содержит упорядоченный набор элементов, т.е. хранит последовательность элементов. Это легко представить, если вспомнить список покупок, в котором перечисляется, что нужно купить, с тем лишь исключением, что в списке покупок каждый элемент обычно размещается на отдельной строке, тогда как в Python они разделяются запятыми.\n\nСписок элементов должен быть заключён в квадратные скобки, чтобы Python понял, что это список. Как только список создан, можно добавлять, удалять или искать элементы в нём. Поскольку элементы можно добавлять и удалять, мы говорим, что список – это изменяемый тип данных, т.е. его можно модифицировать.",
+ "use_function_to_read_code": false
+ },
+ "Краткое введение в объекты и классы": {
+ "text": "Список – это один из примеров использования объектов и классов. Когда мы назначаем некоторой переменной i значение, скажем, целое число 5, это можно представить себе как создание объекта (т.е. экземпляра) i класса (т.е. типа) int. Чтобы лучше понять это, прочитайте help(int).\n\nКласс может также иметь методы, т.е. функции, определённые для использования только применительно к данному классу. Этот функционал будет доступен только когда имеется объект данного класса. Например, Python предоставляет метод append для класса list, который позволяет добавлять элемент к концу списка. Так mylist.append('and item') добавит эту строку к списку mylist. Обратите внимание на обозначение точкой для доступа к методам объектов.",
+ "use_function_to_read_code": false
+ },
+ "Пример": {
+ "text": "m = [\"obj1\", \"obj2\", \"obj3\"]\nprint (m[0])",
+ "use_function_to_read_code": true
+ },
+ "Как это работает": {
+ "text": "Мы создаём словарь ab. Затем мы обращаемся к парам ключ-значение. Как видите, синтаксис прост.\n\nУдалять пары ключ-значение можно при помощи оператора del. Мы указываем имя словаря и оператор индексирования для удаляемого ключа, после чего передаём это оператору del.\n\nДалее мы обращаемся ко всем парам ключ-значение нашего словаря, используя метод items, который возвращает список кортежей, каждый из которых содержит пару элементов: ключ и значение. Мы получаем эту пару и присваиваем её значение переменным name и address соответственно в цикле for..in, а затем выводим эти значения на экран в блоке for.",
+ "use_function_to_read_code": false
+ },
+ "Кортеж": {
+ "text": "Кортежи служат для хранения нескольких объектов вместе. Их можно рассматривать как аналог списков, но без такой обширной функциональности, которую предоставляет класс списка. Одна из важнейших особенностей кортежей заключается в том, что они неизменяемы, так же, как и строки. Т.е. модифицировать кортежи невозможно.\n\nКортежи обозначаются указанием элементов, разделённых запятыми; по желанию их можно ещё заключить в круглые скобки.\n\nКортежи обычно используются в тех случаях, когда оператор или пользовательская функция должны наверняка знать, что набор значений, т.е. кортеж значений, не изменится.",
+ "use_function_to_read_code": false
+ },
+ "Словарь": {
+ "text": "Словарь – это некий аналог адресной книги, в которой можно найти адрес или контактную информацию о человеке, зная лишь его имя; т.е. некоторые ключи связаны со значениями.\n\nПары ключ-значение указываются в словаре следующим образом: «d = {key1 : value1, key2 : value2 }». Обратите внимание, что ключ и значение разделяются двоеточием, а пары друг от друга отделяются запятыми, а затем всё это заключается в фигурные скобки.",
+ "use_function_to_read_code": false
+ },
+ "Последовательности": {
+ "text": "Списки, кортежи и строки являются примерами последовательностей. Но что такое последовательности и что в них такого особенного?\n\nОсновные возможности – это проверка принадлежности (т.е. выражения «in» и «not in») и оператор индексирования, позволяющий получить напрямую некоторый элемент последовательности.\n\nВсе три типа последовательностей, упоминавшиеся выше (списки, кортежи и строки), также предоставляют операцию получения вырезки, которая позволяет получить вырезку последовательности, т.е. её фрагмент.",
+ "use_function_to_read_code": false
+ }
+ },
+
+ "Урок 9: Исключения": {
+ "Предисловие": {
+ "text": "Исключения возникают тогда, когда в программе возникает некоторая исключительная ситуация. Например, к чему приведёт попытка чтения несуществующего файла? Или если файл был случайно удалён, пока программа работала? Такие ситуации обрабатываются при помощи исключений.\n\nЭто касается и программ, содержащих недействительные команды. В этом случае Python поднимает руки и сообщает, что обнаружил ошибку.",
+ "use_function_to_read_code": false
+ },
+ "Ошибки": {
+ "text": "Рассмотрим простой вызов функции print. Что, если мы ошибочно напишем print как Print? Обратите внимание на заглавную букву. В этом случае Python поднимает синтаксическую ошибку.",
+ "use_function_to_read_code": false
+ },
+ "Пример": {
+ "text": "with open(\"poem.txt\") as f:\n for line in f:\n print(line, end='')",
+ "use_function_to_read_code": true
+ },
+ "Исключения": {
+ "text": "Попытаемся считать что-либо от пользователя. Нажмите Сtrl-D (или Ctrl+Z в Windows) и посмотрите, что произойдёт.",
+ "use_function_to_read_code": false
+ },
+ "Обработка исключений": {
+ "text": "Обрабатывать исключения можно при помощи оператора try..except. При этом все обычные команды помещаются внутрь try-блока, а все обработчики исключений – в except-блок.",
+ "use_function_to_read_code": false
+ },
+ "Как это работает": {
+ "text": "Существует некий протокол, используемый оператором with. Он считывает объект, возвращаемый операторомopen.Назовём его в данном случае «thefile».\n\nПеред запуском блока кода, содержащегося в нём, оператор with всегда вызывает функцию thefile.enter, а также всегда вызывает thefile.exit после завершения выполнения этого блока кода.\n\nТак что код, который мы бы написали в блоке finally, будет автоматически обработан методом exit. Это избавляет нас от необходимости повторно в явном виде указывать операторы try..finally.",
+ "use_function_to_read_code": false
+ },
+ "Вызов исключения": {
+ "text": "Исключение можно поднять при помощи оператора raise, передав ему имя ошибки/исключения, а также объект исключения, который нужно выбросить.\n\nВызываемая ошибка или исключение должна быть классом, который прямо или непрямо является производным от класса Exception.",
+ "use_function_to_read_code": false
+ },
+ "Try .. Finally": {
+ "text": "Представим, что в программе происходит чтение файла и необходимо убедиться, что объект файла был корректно закрыт и что не возникло никакого исключения. Этого можно достичь с применением блока finally.",
+ "use_function_to_read_code": false
+ },
+ "Оператор with": {
+ "text": "Типичной схемой является запрос некоторого ресурса в блоке try с последующим освобождением этого ресурса в блоке finally. Для того, чтобы сделать это более «чисто»,существует оператор with:",
+ "use_function_to_read_code": false
+ }
+ },
+
+ "Урок 10: Дополнительно": {
+ "Предисловие": {
+ "text": "К настоящему моменту мы уже рассмотрели большую часть того, что вам придётся использовать при работе с Python. В этой главе мы охватим некоторые дополнительные аспекты, которые помогут отшлифовать ваши знания.",
+ "use_function_to_read_code": false
+ },
+ "Self": {
+ "text": "Методы класса имеют одно отличие от обычных функций: они должны иметь дополнительно имя, добавляемое к началу списка параметров. Однако, при вызове метода никакого значения этому параметру присваивать не нужно – его укажет Python. Эта переменная указывает на сам объект экземпляра класса, и по традиции она называется self.\n\nХотя этому параметру можно дать любое имя, настоятельно рекомендуется использовать только имя self; использование любого другого имени не приветствуется. Есть много достоинств использования стандартного имени: во-первых, любой человек, просматривающий вашу программу, легко узнает его; во-вторых, некоторые специализированные Интегрированные среды разработки (IDE) изначально рассчитаны на использование self.",
+ "use_function_to_read_code": false
+ },
+ "Классы": {
+ "text": "Классы предоставляют средства объединения данных и функциональности вместе. Создание нового класса создает объект нового типа, позволяя создавать новые экземпляры этого типа. К каждому экземпляру класса могут быть прикреплены атрибуты для поддержания его состояния. Экземпляры класса также могут иметь методы (определенные его классом) для изменения его состояния.",
+ "use_function_to_read_code": false
+ },
+ "Пример": {
+ "text": "i = []\ni.append('объект')\ni.append('новый объект')",
+ "use_function_to_read_code": true
+ },
+ "Как это работает": {
+ "text": "В этом примере мы создали новый список и добавили к нему \"объект\" и \"новый объект\". Суть такой простой программы - показать, что переменные на самом деле не переменные, а экземпляры классов. Это звучит странно, но, например, в языке Си++ переменные, массивы, словари и кортежи не имеют никаких встроенных методов. То есть вот так вот просто \"добавить\" новый элемент к массиву в Си++ и других языках нельзя. А в Python можно! В этом и заключается один из элементов \"силы\" языка!",
+ "use_function_to_read_code": false
+ },
+ "Методы объектов": {
+ "text": "Итак, мы выяснили что классы/объекты могут иметь методы, представляющие собой функции, за исключением дополнительной переменной self. А теперь давайте рассмотрим пример",
+ "use_function_to_read_code": false
+ },
+ "Блоки в одно выражение": {
+ "text": "Мы неоднократно говорили, что каждый блок команд отделяется от других своим собственным уровнем отступа. Однако, существует и исключение. Если блок команд содержит только одно выражение, его можно указывать в одной строке с условным оператором или, скажем, оператором цикла. Рассмотрим это на примере:",
+ "use_function_to_read_code": false
+ },
+ "Lambda-функции": {
+ "text": "Ключевое слово lambda используется для создания функций и возврата их значения во время выполнения программы. lambda принимает параметр, за которым следует одно выражение, которое становится телом функции, а значение этого выражения возвращается новой функцией.",
+ "use_function_to_read_code": false
+ },
+ "Генераторы списков": {
+ "text": "Генераторы списков служат для создания новых списков на основе существующих. Представьте, что имеется список чисел, на основе которого требуется получить новый список, состоящий из всех чисел, умноженных на 2, но только при условии, что само число больше 2. Генераторы списков подходят для таких задач как нельзя лучше.",
+ "use_function_to_read_code": false
+ },
+ "Передача кортежей и словарей в функции": {
+ "text": "Для получения параметров, переданных функции, в виде кортежа или словаря, существуют специальные приставки «*» или «**» соответственно. Это особенно полезно в случаях, когда функция может принимать переменное число параметров.",
+ "use_function_to_read_code": false
+ },
+ "exec и eval": {
+ "text": "Функция exec служит для выполнения команд Python, содержащихся в строке или файле, в отличие от самого текста программы. Например, во время выполнения программы можно сформировать строку, содержащую текст программы на Python, и запустить его при помощи exec:",
+ "use_function_to_read_code": false
+ },
+ "Оператор assert": {
+ "text": "Оператор assert существует для того, чтобы указать, что нечто является истиной. Например, если требуется гарантировать, что в списке будет хотя бы один элемент, и вызвать ошибку, если это не так, то оператор assert идеально подойдёт для такой задачи. Когда заявленное выражение ложно, вызывается ошибка AssertionError. Метод pop() возвращает последний элемент списка, одновременно удаляя его оттуда.",
+ "use_function_to_read_code": false
+ },
+ "Функция repr": {
+ "text": "Функция repr используется для получения канонического строкового представления объекта. Любопытно, что в большинстве случаев eval(repr(object)) == object.",
+ "use_function_to_read_code": false
+ },
+ "Установка библиотек": {
+ "text": "В Каталоге пакетов Python существует колоссальное количество открытых библиотек, которые вы можете использовать в своих программах. Для их установки можно воспользоваться pip.",
+ "use_function_to_read_code": false
+ },
+ "Графические программы": {
+ "text": "Для создания собственной графической программы на Python понадобится какая-нибудь библиотека ГИП (графического интерфейса пользователя) со своими привязками к Python. Привязки позволяют писать программу на Python, используя библиотеки, которые сами по себе написаны на C, C++ или других языках.",
+ "use_function_to_read_code": false
+ },
+ "Kivy": {
+ "text": "https://kivy.org",
+ "use_function_to_read_code": false
+ },
+ "PyGTK": {
+ "text": "Это привязки Python к инструментарию GTK+, на основе которого построен GNOME. У GTK+ есть много своих особенностей, но как только вы освоитесь, вы сможете создавать ГИП очень быстро. Что касается дизайнера графического интерфейса Glade, то он просто незаменим. Документация же всё ещё требует некоторых улучшений. GTK+ хорошо работает в GNU/Linux, но его порт на Windows пока не закончен. При помощи GTK+ можно создавать как свободные, так и проприетарные программы. Для начала прочитайте Учебник по PyGTK.",
+ "use_function_to_read_code": false
+ },
+ "PyQt": {
+ "text": "Это привязки Python к инструментарию Qt, на основе которого построена KDE. Qt чрезвычайно прост в использовании, особенно благодаря Qt Designer и изумительной документации Qt. PyQt бесплатно, если используется для создания свободных программ (с лицензией GPL). Для создания закрытых проприетарных программ вам придётся его купить. Начиная с Qt 4.5, разрешается создавать при помощи него не только GPL’ные программы.",
+ "use_function_to_read_code": false
+ },
+ "wxPython": {
+ "text": "Это привязки Python к инструментарию wxWidgets. wxPython не так прост в освоении, но зато он переносим и работает на GNU/Linux, Windows, Mac и даже на встраиваемых платформах. Многие среды разработки для wxPython, такие как SPE (Stani’s Python Editor) и wxGlade включают дизайнеры графического интерфейса. При помощи wxPython можно создавать как свободные, так и проприетарные программы.",
+ "use_function_to_read_code": false
+ }
+ }
}
\ No newline at end of file
diff --git a/main.py b/main.py
new file mode 100644
index 0000000..421bcd5
--- /dev/null
+++ b/main.py
@@ -0,0 +1,260 @@
+from json_manager import *
+from useful_functions import *
+from enums import *
+
+
+class HandlerOfAlisa:
+ def __init__ (self, request: dict):
+ self._VERSION: str = request["version"]
+ self._TEXT_IN_LOWER: str = request["request"]["command"]
+ self._ORIGINAL_TEXT: str = request["request"]["original_utterance"]
+ self._WORDS_OF_TEXT_IN_LOWER: list = request["request"]["nlu"]["tokens"]
+ self._OUTPUT_TEXT = ""
+ self._IS_FIRST_MESSAGE: bool = request["session"]["new"]
+ self._IS_END_SESSION: bool = False
+ self._SESSIONAL_DATA: dict = request["state"]["session"]
+ self._INTERSESSIONAL_DATA: dict = request["state"]["user"] # Межсессионные данные
+ self._BUTTONS = [ ]
+ self._buttons_of_main_menu = create_buttons (*get_main_commands_of_skill_as_list ( ))
+ self._create_intersessional_data_if_necessary ( )
+ self._working_with_user ( )
+
+ def _create_intersessional_data_if_necessary (self) -> None:
+ # Я думаю, что у нового пользователя межсессионные данные пусты,
+ # поэтому создаю их, если это необходимо
+ if "new_user" in self._INTERSESSIONAL_DATA.keys ( ):
+ self._IS_NEW_USER: bool = self._INTERSESSIONAL_DATA["new_user"]
+ else:
+ self._IS_NEW_USER = True
+ self._INTERSESSIONAL_DATA["new_user"] = True
+ self._INTERSESSIONAL_DATA["last_lesson"] = 0
+ self._INTERSESSIONAL_DATA["last_task"] = 0
+
+ def _working_with_user (self) -> None:
+ if "user_should_choose_something" in self._SESSIONAL_DATA.keys():
+ if self._SESSIONAL_DATA["user_should_choose_something"]:
+ self._interception_of_attention ( )
+ else:
+ self._choosing_function_in_main_menu ( )
+ else:
+ self._choosing_function_in_main_menu ( )
+
+ def _interception_of_attention (self) -> None:
+ if "choosing_lesson" in self._SESSIONAL_DATA.keys():
+ self._do_something_if_choosing_lesson_is_true ( )
+
+ if "choosing_task" in self._SESSIONAL_DATA.keys():
+ pass # FIXME
+
+ if "choosing_right_answer_for_quest" in self._SESSIONAL_DATA.keys():
+ self._do_something_if_choosing_right_answer_for_quest ( )
+
+ if "quest_difficulty_selection" in self._SESSIONAL_DATA.keys():
+ self._do_something_if_quest_difficulty_selection_is_true ( )
+
+ def _do_something_if_choosing_lesson_is_true (self) -> None:
+ if self._SESSIONAL_DATA["choosing_lesson"]:
+ if self._has_one_word_in_text_in_lower ("далее", "дальше", "следующий", "продолжи"):
+ self._INTERSESSIONAL_DATA["last_lesson"] += 1
+ lesson_number = self._INTERSESSIONAL_DATA["last_lesson"]
+ self._OUTPUT_TEXT = "Тема урока: " + get_theme_of_lesson (lesson_number) + "\n"
+ self._OUTPUT_TEXT += get_lesson_text (lesson_number)
+ self._BUTTONS = create_buttons ("Далее.", "Повтор.", "На главное меню.", "Выйти.")
+
+ elif self._has_one_word_in_text_in_lower ("повтор", "повтори"):
+ self._OUTPUT_TEXT = "Хорошо.\n" + get_lesson_text (
+ self._INTERSESSIONAL_DATA["last_lesson"])
+ self._BUTTONS = create_buttons ("Далее.", "Повтор.", "На главное меню.", "Выйти.")
+
+ elif self._has_all_words_in_text_in_lower ("на", "главное", "меню"):
+ self._user_is_in_main_menu ( )
+
+ elif self._has_one_word_in_text_in_lower ("выключись", "выход", "выйти"):
+ self._OUTPUT_TEXT = get_farewell_text ( )
+ self._IS_END_SESSION = True
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+ def _do_something_if_quest_difficulty_selection_is_true (self) -> None:
+ if self._SESSIONAL_DATA["quest_difficulty_selection"]:
+ # Переделать все уровни сложности в квестах!!!
+ if self._has_one_word_in_text_in_lower ("лёгкий", "лёгкого", "лёгкому", "лёгким", "лёгком"):
+ difficulty_level = DifficultyLevelsOfCourse.EASY.value
+ is_difficulty_level = True
+
+ elif self._has_one_word_in_text_in_lower ("средний", "среднего", "среднему", "среднем", "средним"):
+ difficulty_level = DifficultyLevelsOfCourse.MEDIUM.value
+ is_difficulty_level = True
+
+ elif self._has_one_word_in_text_in_lower ("сложный", "сложного", "сложному", "сложным", "сложном"):
+ difficulty_level = DifficultyLevelsOfCourse.HARD.value
+ is_difficulty_level = True
+
+ elif self._has_one_word_in_text_in_lower ("рандом", "рандома", "рандому", "рандомом", "рандоме"):
+ difficulty_level = DifficultyLevelsOfCourse.RANDOM.value
+ is_difficulty_level = True
+
+ elif self._has_all_words_in_text_in_lower ("на", "главное", "меню"):
+ self._user_is_in_main_menu ( )
+
+ elif self._has_one_word_in_text_in_lower ("выключись", "выход", "выйти"):
+ self._OUTPUT_TEXT = get_farewell_text ( )
+ self._IS_END_SESSION = True
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+ if is_difficulty_level:
+ self._SESSIONAL_DATA["choosing_right_answer_for_quest"] = True
+ self._BUTTONS = create_buttons ("а", "б", "в")
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = difficulty_level
+ self._SESSIONAL_DATA["quest_difficulty_selection"] = False
+ self._SESSIONAL_DATA["random_text_and_correct_answer_of_quest"] = get_random_quest_text_and_currect_answer_of_correct_level (difficulty_level)
+ self._OUTPUT_TEXT = self._SESSIONAL_DATA["random_text_and_correct_answer_of_quest"][0]
+
+ def _do_something_if_choosing_right_answer_for_quest (self) -> None:
+ if self._SESSIONAL_DATA["choosing_right_answer_for_quest"]:
+ if self._has_one_word_in_text_in_lower ("а"):
+ self._BUTTONS = create_buttons ("а", "б", "в")
+ if self._SESSIONAL_DATA["random_text_and_correct_answer_of_quest"][1] == 0:
+ self._OUTPUT_TEXT = "Верно!"
+ self._user_is_in_main_menu ( ) # FIXME
+ else:
+ self._OUTPUT_TEXT = "К сожалению, это неправильный ответ.\n"
+
+ elif self._has_one_word_in_text_in_lower ("б"):
+ self._BUTTONS = create_buttons ("а", "б", "в")
+ if self._SESSIONAL_DATA["random_text_and_correct_answer_of_quest"][1] == 1:
+ self._OUTPUT_TEXT = "Верно!"
+ self._user_is_in_main_menu ( ) # FIXME
+ else:
+ self._OUTPUT_TEXT = "К сожалению, это неправильный ответ.\n"
+
+ elif self._has_one_word_in_text_in_lower ("в"):
+ self._BUTTONS = create_buttons ("а", "б", "в")
+ if self._SESSIONAL_DATA["random_text_and_correct_answer_of_quest"][1] == 2:
+ self._OUTPUT_TEXT = "Верно!"
+ self._user_is_in_main_menu ( ) # FIXME
+ else:
+ self._OUTPUT_TEXT = "К сожалению, это неправильный ответ.\n"
+
+ elif self._has_all_words_in_text_in_lower ("на", "главное", "меню"):
+ self._user_is_in_main_menu ( )
+
+ elif self._has_one_word_in_text_in_lower ("выключись", "выход", "выйти"):
+ self._OUTPUT_TEXT = get_farewell_text ( )
+ self._IS_END_SESSION = True
+
+ else:
+ self._OUTPUT_TEXT = "Такого варианта ответа нет!"
+
+ def _user_is_in_main_menu (self) -> None:
+ self._OUTPUT_TEXT = "Вы на главном меню!\nМои основные команды:\n"
+ self._OUTPUT_TEXT += get_main_commands_of_skill ( )
+ self._SESSIONAL_DATA["user_should_choose_something"] = False
+ self._SESSIONAL_DATA["quest_difficulty_selection"] = False
+ self._SESSIONAL_DATA["choosing_lesson"] = False
+ self._SESSIONAL_DATA["choosing_task"] = False
+ self._BUTTONS = self._buttons_of_main_menu
+
+
+ def _choosing_function_in_main_menu (self) -> None:
+ if self._IS_NEW_USER:
+ self._OUTPUT_TEXT = get_text_for_new_user ( )
+ self._IS_NEW_USER = False
+ self._INTERSESSIONAL_DATA["new_user"] = False
+ self._BUTTONS = self._buttons_of_main_menu
+
+ elif self._IS_FIRST_MESSAGE:
+ self._OUTPUT_TEXT = get_hello_text ( ) + "\n"
+ self._OUTPUT_TEXT += get_text_asking_if_user_has_forgotten_commands ( ) + "\n"
+ self._OUTPUT_TEXT += get_main_commands_of_skill ( )
+ self._BUTTONS = self._buttons_of_main_menu
+ self._SESSIONAL_DATA["user_should_choose_something"] = False
+ self._SESSIONAL_DATA["quest_difficulty_selection"] = False
+ self._SESSIONAL_DATA["choosing_answer_of_quest"] = False
+ self._SESSIONAL_DATA["choosing_lesson"] = False
+ self._SESSIONAL_DATA["choosing_taskho"] = False
+
+ # Пока навык разрабатывается
+ elif self._has_all_words_in_text_in_lower ("сбрось", "настройки") or\
+ self._has_all_words_in_text_in_lower ("сбросить", "настройки"):
+ self._IS_NEW_USER = True
+ self._INTERSESSIONAL_DATA["new_user"] = True
+ self._INTERSESSIONAL_DATA["last_lesson"] = 0
+ self._INTERSESSIONAL_DATA["last_task"] = 0
+ self._OUTPUT_TEXT = "Настройки сброшены."
+
+ elif self._has_one_word_in_text_in_lower (
+ "курс", "курса", "курсу", "курсе", "курсом"):
+ last_lesson: int = self._INTERSESSIONAL_DATA["last_lesson"]
+ if last_lesson != 0:
+ self._OUTPUT_TEXT = get_text_that_says_which_lesson_user_stopped (last_lesson) + "\n"
+ self._OUTPUT_TEXT += "Его тема: " + get_theme_of_lesson (last_lesson) + "\n"
+ self._OUTPUT_TEXT += "Если хотите перейти к следующему уроку, то скажите: \"Далее\".\n"
+ self._OUTPUT_TEXT += "Если хотите выйти на главное меню, скажите: \"На главное меню\".\n"
+ self._OUTPUT_TEXT += "Также вы можете прослушать урок ещё раз, сказав: \"Повтор\"."
+ else:
+ self._OUTPUT_TEXT = get_introduction_to_course ( )
+
+ self._BUTTONS = create_buttons ("Далее.", "На главное меню.", "Повтор.")
+ self._SESSIONAL_DATA["user_should_choose_something"] = True
+ self._SESSIONAL_DATA["choosing_lesson"] = True
+ # FIXME
+
+ elif self._has_all_words_in_text_in_lower ("продолжи", "курс"):
+ self._OUTPUT_TEXT = "Хорошо!\n"
+ last_lesson: int = self._INTERSESSIONAL_DATA["last_lesson"]
+ next_lesson = last_lesson + 1
+ self._OUTPUT_TEXT += "Тема урока: " + get_theme_of_lesson (next_lesson) + "\n"
+ self._OUTPUT_TEXT += "ЗАТЫЧКА: показан текст следующего урока."
+
+ elif self._has_one_word_in_text_in_lower (
+ "квест", "квеста", "квесту", "квесте", "квесту"):
+ self._OUTPUT_TEXT = "Отличный выбор!\nЗдесь вы можете потренироваться в коротких вопросах.\n"
+ self._OUTPUT_TEXT += "Есть 3 уровня сложности: лёгкий, средний и сложный\n."
+ self._OUTPUT_TEXT += "Также есть \"Рандом\"."
+ self._BUTTONS = create_buttons ("Лёгкий.", "Средний.", "Сложный.", "Рандом", "На главное меню.", "Выйти.")
+ self._SESSIONAL_DATA["user_should_choose_something"] = True
+ self._SESSIONAL_DATA["quest_difficulty_selection"] = True
+
+ elif self._has_one_word_in_text_in_lower (
+ "пока", "пака", "прощай", "свидания", "пора", "чао", "выход", "выйти", "отбой"):
+ self._OUTPUT_TEXT = get_farewell_text ( )
+ self._IS_END_SESSION = True
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+
+ def _has_all_words_in_text_in_lower (self, *words) -> bool:
+ for word in words:
+ if not word in self._WORDS_OF_TEXT_IN_LOWER:
+ return False
+ return True
+
+ def _has_one_word_in_text_in_lower (self, *words) -> bool:
+ for word in words:
+ if word in self._WORDS_OF_TEXT_IN_LOWER:
+ return True
+ return False
+
+
+ def get_response (self) -> dict:
+ return {
+ "version": self._VERSION,
+ "response": {
+ "text": self._OUTPUT_TEXT,
+ "end_session": self._IS_END_SESSION,
+ "buttons": self._BUTTONS},
+ "session_state": self._SESSIONAL_DATA,
+ "user_state_update": self._INTERSESSIONAL_DATA
+ }
+
+
+
+# Функция, вызываемая Яндексом для запуска скрипта Алисы (в коде вызывать её не нужно).
+def main (request_from_alisa: dict, context) -> dict:
+ handler_of_alisa = HandlerOfAlisa (request_from_alisa)
+ return handler_of_alisa.get_response ( )
\ No newline at end of file
diff --git a/main2.py b/main2.py
new file mode 100644
index 0000000..2bda608
--- /dev/null
+++ b/main2.py
@@ -0,0 +1,520 @@
+import random
+
+from json_manager import *
+from useful_functions import *
+from quest_getter import QuestGetter
+from buttons import Buttons
+from enums import *
+
+
+class HandlerOfAlisa:
+ def __init__ (self, request: dict):
+ self._VERSION: str = request["version"]
+ self._TEXT_IN_LOWER: str = request["request"]["command"]
+ self._ORIGINAL_TEXT: str = request["request"]["original_utterance"]
+ self._WORDS_OF_TEXT_IN_LOWER: list = request["request"]["nlu"]["tokens"]
+ self._IS_FIRST_MESSAGE: bool = request["session"]["new"]
+ self._IS_END_SESSION: bool = False
+ self._SESSIONAL_DATA: dict = create_sessional_data (request["state"]["session"])
+ self._INTERSESSIONAL_DATA: dict = create_intersessional_data (request["state"]["user"])
+ self._TEXT_TO_SPEECH = ""
+ self._BUTTONS = Buttons ( )
+ self._working_with_user ( )
+
+
+ def _working_with_user (self) -> None:
+ # Абсолютно новый пользователь
+ if self._INTERSESSIONAL_DATA["new_user"]:
+ self._OUTPUT_TEXT = get_text_for_new_user ( )
+ self._TEXT_TO_SPEECH = get_text_for_new_user ( ) + "\n"
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._INTERSESSIONAL_DATA["new_user"] = False
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ # Пользователь в главном меню впервые
+ elif self._user_is_in_main_menu and self._IS_FIRST_MESSAGE:
+ user_greeting = get_user_greeting ( )
+ self._OUTPUT_TEXT = user_greeting
+ self._TEXT_TO_SPEECH = user_greeting
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ # Пользователь просто в главном меню
+ elif self._user_is_in_main_menu:
+ text_that_says_user_is_just_in_main_menu = get_text_that_says_user_is_just_in_main_menu ( )
+ self._OUTPUT_TEXT = text_that_says_user_is_just_in_main_menu
+ self._TEXT_TO_SPEECH = text_that_says_user_is_just_in_main_menu
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+ self._working_with_user_in_main_menu ( )
+
+ # Пользователь не в главном меню
+ else:
+ self._working_with_user_outside_main_menu ( )
+
+ @property
+ def _user_is_in_main_menu (self) -> bool:
+ # Если в _SESSIONAL_DATA есть хоть одно True-значение,
+ # то это значит, что пользователь не в главном меню
+ sessional_data = self._SESSIONAL_DATA
+ for key in sessional_data.keys():
+ if sessional_data[key]:
+ return False
+ return True
+
+
+ def _working_with_user_in_main_menu (self) -> None:
+ self._BUTTONS.remove_all_buttons ( )
+ self._TEXT_TO_SPEECH = ""
+ # Пока навык в разработке
+ if self._has_all_words_in_text_in_lower ("сбрось", "настройки") or \
+ self._has_all_words_in_text_in_lower ("сбросить", "настройки"):
+ self._INTERSESSIONAL_DATA["new_user"] = True
+ self._INTERSESSIONAL_DATA["last_lesson"] = 0
+ self._INTERSESSIONAL_DATA["last_task"] = 0
+ self._OUTPUT_TEXT = "Настройки сброшены.\n"
+ self._OUTPUT_TEXT = "Перезагрузите навык."
+
+ elif self._has_one_word_in_text_in_lower (
+ "курс", "курса", "курсу", "курсом", "курсе"):
+ """Последняя тема, на которой вы остановились: (ТЕМА) /
+ (если пользователь ещё не проходил темы то Алиса пишет:
+ "Вы ещё не прошли ни одной темы").
+ Продолжим?
+ """
+ # FIXME
+ self._SESSIONAL_DATA["working_with_course"] = True
+ self._OUTPUT_TEXT = "Пока \"Курс\" ничего не умеет...\n"
+ self._OUTPUT_TEXT += "Может, на главное меню?"
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "задачка", "задачки", "задачку", "задачке", "задачкой",
+ "задача", "задачи", "задачу", "задаче", "задачей"):
+ """Чем отличаются задачки от квеста?"""
+ # FIXME
+ self._SESSIONAL_DATA["working_with_tasks"] = True
+ self._OUTPUT_TEXT = "Пока \"Задачка\" ничего не умеет...\n"
+ self._OUTPUT_TEXT += "Может, на главное меню?"
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "квест", "квеста", "квесту", "квестом", "квесте"):
+ # Просто доделать
+ self._SESSIONAL_DATA["working_with_quest"] = True
+ self._OUTPUT_TEXT = "Какой уровень сложности вы предпочитаете?\n"
+ self._TEXT_TO_SPEECH = "Какой уровень сложности вы предпочитаете?\n"
+ self._TEXT_TO_SPEECH += f"{', '.join (self._difficulty_levels)}"
+ self._BUTTONS.add_buttons (*self._difficulty_levels, hide_all = False)
+ self._BUTTONS.add_buttons ("Узнать мои результаты", "На главное меню", "Пока", hide_all = True)
+
+ elif self._has_all_words_in_text_in_lower ("на", "урок"):
+ self._SESSIONAL_DATA["working_with_course"] = True
+ self._OUTPUT_TEXT = "Пока \"Перейти на урок\" ничего не умеет...\n"
+ self._OUTPUT_TEXT += "Может, на главное меню?"
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "пожаловаться", "жалоба", "жалобу", "отчёт", "отчет"):
+ self._SESSIONAL_DATA["sending_report"] = True
+ self._OUTPUT_TEXT = "Я не знаю, на какую почту отправлять жалобу...\n"
+ self._OUTPUT_TEXT += "Может, на главное меню?"
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "консультант", "консультанта", "консультанту", "консультантом", "консультанте"
+ "консультация", "консультации", "консультацию", "консультацией", "проконсультируй"):
+ self._SESSIONAL_DATA["consulting"] = True
+ self._OUTPUT_TEXT = "Пока я не могу вас проконсультировать, извините...\n"
+ self._OUTPUT_TEXT += "Может, на главное меню?"
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ elif self._has_all_words_in_text_in_lower ("оцени", "знания"):
+ self._OUTPUT_TEXT = "Зачем \"Оцени мои знания\", когда есть \"Квест\"?\n"
+ self._OUTPUT_TEXT += "Скажи \"Квест\", чтобы его попробовать."
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._OUTPUT_TEXT = "Вы уже на главном меню!"
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+ @property
+ def _difficulty_levels (self) -> tuple[str, str, str, str]:
+ return "Лёгкий", "Средний", "Высокий", "Случайный"
+
+ @property
+ def _buttons_for_choosing_difficutly_level (self) -> dict:
+ return "Лёгкий", "Средний", "Высокий", "Случайный", "Узнать мои результаты", "На главное меню", "Пока!"
+
+
+ def _working_with_user_outside_main_menu (self) -> None:
+ # Само собой нужно доработать working-методы
+ if self._SESSIONAL_DATA["working_with_course"]:
+ self._working_with_course ( )
+ elif self._SESSIONAL_DATA["working_with_tasks"]:
+ self._working_with_tasks ( )
+ elif self._SESSIONAL_DATA["working_with_quest"]:
+ self._working_with_quest ( )
+ elif self._SESSIONAL_DATA["choosing_right_answer_for_quest"]:
+ self._choosing_right_answer_for_quest ( )
+ elif self._SESSIONAL_DATA["viewing_quest_results"]:
+ self._viewing_quest_results ( )
+ elif self._SESSIONAL_DATA["sending_report"]:
+ self._sending_report ( )
+ elif self._SESSIONAL_DATA["consulting"]:
+ self._consulting ( )
+
+ def _working_with_course (self) -> None:
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ @property
+ def _user_wants_to_go_to_main_menu (self) -> bool:
+ if self._has_all_words_in_text_in_lower ("на", "главное", "меню"):
+ return True
+ else:
+ return False
+
+ @property
+ def _user_wants_to_end_session (self) -> bool:
+ if self._has_one_word_in_text_in_lower ("выход", "выйти", "пока", "прощай"):
+ return True
+ else:
+ return False
+
+ def _working_with_tasks (self) -> None:
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ def _working_with_quest (self) -> None:
+ if self._has_one_word_in_text_in_lower (
+ "лёгкий", "лёгкого", "лёгкому", "лёгким", "лёгком",
+ "легкий", "легкого", "легкому", "легким", "легком"):
+ self._SESSIONAL_DATA["difficulty_level"] = DifficultyLevelsOfQuest.EASY.value
+ self._SESSIONAL_DATA["working_with_quest"] = False
+ self._SESSIONAL_DATA["choosing_right_answer_for_quest"] = True
+ self._save_text_and_correct_answer_of_easy_quest_in_session_data ( )
+ well = random.choice (("Хорошо.", "Отлично.", "Прекрасно.")) + "\n\n"
+ self._OUTPUT_TEXT = well
+ self._TEXT_TO_SPEECH = well
+ self._say_that_user_can_change_their_difficulty_level_if_it_is_not_said_yet ( )
+ self._OUTPUT_TEXT += self._get_text_of_current_quest ( )
+ self._TEXT_TO_SPEECH += self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "средний", "среднего", "среднему", "среднем",
+ "средняя", "средней", "среднюю"):
+ self._SESSIONAL_DATA["difficulty_level"] = DifficultyLevelsOfQuest.MEDIUM.value
+ self._SESSIONAL_DATA["working_with_quest"] = False
+ self._SESSIONAL_DATA["choosing_right_answer_for_quest"] = True
+ self._save_text_and_correct_answer_of_medium_quest_in_session_data ( )
+ well = random.choice (("Хорошо.", "Отлично.", "Прекрасно.")) + "\n\n"
+ self._OUTPUT_TEXT = well
+ self._TEXT_TO_SPEECH = well
+ self._say_that_user_can_change_their_difficulty_level_if_it_is_not_said_yet ( )
+ self._OUTPUT_TEXT += self._get_text_of_current_quest ( )
+ self._TEXT_TO_SPEECH += self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "высокий", "высокого", "высокому", "высоким", "высоком",
+ "сложный", "сложного", "сложному", "сложным", "сложном"):
+ self._SESSIONAL_DATA["difficulty_level"] = DifficultyLevelsOfQuest.HARD.value
+ self._SESSIONAL_DATA["working_with_quest"] = False
+ self._SESSIONAL_DATA["choosing_right_answer_for_quest"] = True
+ self._save_text_and_correct_answer_of_hard_quest_in_session_data ( )
+ well = random.choice (("Хорошо.", "Отлично.", "Прекрасно.")) + "\n\n"
+ self._OUTPUT_TEXT = well
+ self._TEXT_TO_SPEECH = well
+ self._say_that_user_can_change_their_difficulty_level_if_it_is_not_said_yet ( )
+ self._OUTPUT_TEXT += self._get_text_of_current_quest ( )
+ self._TEXT_TO_SPEECH += self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "случайный", "случайного", "случайному", "случайным", "случайном",
+ "случайная", "случайной", "случайную",
+ "рандом", "рандома", "рандому", "рандомом", "рандоме",
+ "рандомный", "рандомного", "рандомному", "рандомном",
+ "рандомная", "рандомной", "рандомную"):
+ difficulty_level = DifficultyLevelsOfQuest.get_random_difficulty_level ( )
+ self._SESSIONAL_DATA["difficulty_level"] = difficulty_level
+ self._SESSIONAL_DATA["working_with_quest"] = False
+ self._SESSIONAL_DATA["choosing_right_answer_for_quest"] = True
+ self._save_text_and_correct_answer_of_quest_in_session_data (difficulty_level)
+ well = random.choice (("Хорошо.", "Отлично.", "Прекрасно.")) + "\n\n"
+ self._OUTPUT_TEXT = well
+ self._TEXT_TO_SPEECH = well
+ self._say_that_user_can_change_their_difficulty_level_if_it_is_not_said_yet ( )
+ self._OUTPUT_TEXT += self._get_text_of_current_quest ( )
+ self._TEXT_TO_SPEECH += self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower ("результат", "результаты"):
+ self._show_results_of_quest_and_next_quest ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_difficutly_level, hide_all = True)
+
+ def _save_text_and_correct_answer_of_easy_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_easy_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_easy_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_easy_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_easy_quest_as_str
+
+ def _save_text_and_correct_answer_of_medium_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_medium_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_medium_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_medium_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_medium_quest_as_str
+
+ def _save_text_and_correct_answer_of_hard_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_hard_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_hard_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_hard_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_hard_quest_as_str
+
+ def _save_text_and_correct_answer_of_quest_in_session_data (self, difficulty_level: int) -> None:
+ match difficulty_level:
+ case DifficultyLevelsOfQuest.EASY.value:
+ self._save_text_and_correct_answer_of_easy_quest_in_session_data ( )
+ case DifficultyLevelsOfQuest.MEDIUM.value:
+ self._save_text_and_correct_answer_of_medium_quest_in_session_data ( )
+ case DifficultyLevelsOfQuest.HARD.value:
+ self._save_text_and_correct_answer_of_hard_quest_in_session_data ( )
+ case _:
+ raise ValueError ("Указан неправильный уровень сложности!")
+
+ def _say_that_user_can_change_their_difficulty_level_if_it_is_not_said_yet (self) -> None:
+ if not self._SESSIONAL_DATA["was_said_that_user_can_change_difficulty_level"]:
+ text = [
+ "В любой момент вы можете сменить уровень сложности, сказав: \"Хочу сменить сложность\";\n",
+ "или выйти на главное меню, сказав: \"На главное меню\".\n",
+ "Так же вы можете узнать количество правильно отвеченных вопросов, сказав: \"Покажи результаты\".\n",
+ "Вот квест.\n\n"
+ ]
+ self._OUTPUT_TEXT += "".join (text)
+ self._TEXT_TO_SPEECH += "".join (text)
+ self._SESSIONAL_DATA["was_said_that_user_can_change_difficulty_level"] = True
+
+ def _get_text_of_current_quest (self) -> str:
+ return self._SESSIONAL_DATA["text_of_quest"]
+
+ @property
+ def _buttons_for_choosing_correct_answer (self) -> dict:
+ return "Первое", "Второе", "Третье", "Изменить уровень сложности", "Узнать мои результаты", "На главное меню", "Пока!"
+
+
+ def _choosing_right_answer_for_quest (self) -> None:
+ if self._has_one_word_in_text_in_lower ("1", "один", "первый", "первое"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 1:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_one_word_in_text_in_lower ("2", "два", "второй", "второе"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 2:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_one_word_in_text_in_lower ("3", "три", "третий", "третье"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 3:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_all_words_in_text_in_lower ("уровень", "сложности") or \
+ self._has_one_word_in_text_in_lower ("сложность"):
+ self._SESSIONAL_DATA["choosing_right_answer_for_quest"] = False
+ self._SESSIONAL_DATA["working_with_quest"] = True
+ self._OUTPUT_TEXT = random.choice (("Хорошо.", "Отлично.")) + "\n"
+ self._OUTPUT_TEXT += "Теперь просто скажите нужный уровень сложности."
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_difficutly_level, hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower ("результат", "результаты"):
+ self._show_results_of_quest_and_next_quest ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_text_that_says_there_is_no_answer_like_that ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ def _correct_answer_of_quest_is_selected (self) -> None:
+ text_that_says_answer_is_correct = get_text_that_says_answer_is_correct ( ) + "\n\n"
+ self._OUTPUT_TEXT = text_that_says_answer_is_correct
+ self._TEXT_TO_SPEECH = text_that_says_answer_is_correct
+ current_difficulty_level = self._SESSIONAL_DATA["difficulty_level"]
+ self._save_text_and_correct_answer_of_quest_in_session_data (current_difficulty_level)
+ self._OUTPUT_TEXT += self._get_text_of_current_quest ( )
+ self._TEXT_TO_SPEECH += self._get_text_of_current_quest ( )
+ self._SESSIONAL_DATA["number_of_correct_quest_answers"] += 1
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ def _show_results_of_quest_and_next_quest (self) -> None:
+ correct_quest_answers = int (self._SESSIONAL_DATA["number_of_correct_quest_answers"])
+ wrong_quest_answers = int (self._SESSIONAL_DATA["number_of_wrong_quest_answers"])
+ if correct_quest_answers and wrong_quest_answers:
+ self._OUTPUT_TEXT = f"Количество правильных ответов: {correct_quest_answers}.\n"
+ self._OUTPUT_TEXT += f"Количество неправильных ответов: {wrong_quest_answers}.\n"
+ python_knowledge = calculate_python_knowledge (correct_quest_answers, wrong_quest_answers)
+ self._OUTPUT_TEXT += f"Ваше знание Python: {python_knowledge}%."
+ self._make_all_sessional_data_false ( )
+ self._SESSIONAL_DATA["viewing_quest_results"] = True
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ elif not correct_quest_answers and wrong_quest_answers:
+ self._OUTPUT_TEXT = "Жаль, но у вас нет ни одного правильного ответа на квест."
+ self._make_all_sessional_data_false ( )
+ self._SESSIONAL_DATA["viewing_quest_results"] = True
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ elif correct_quest_answers and not wrong_quest_answers:
+ self._OUTPUT_TEXT = "Все ваши ответы верны! Похоже, вы профессиональный программист!"
+ self._make_all_sessional_data_false ( )
+ self._SESSIONAL_DATA["viewing_quest_results"] = True
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ else:
+ self._OUTPUT_TEXT = "Пока вы не ответили ни на один квест."
+ self._make_all_sessional_data_false ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+
+ def _wrong_answer_of_quest_is_selected (self) -> None:
+ self._OUTPUT_TEXT = get_text_that_says_answer_is_wrong ( )
+ self._SESSIONAL_DATA["number_of_wrong_quest_answers"] += 1
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+
+ def _viewing_quest_results (self) -> None:
+ if self._has_one_word_in_text_in_lower ("продолжить"):
+ self._SESSIONAL_DATA["viewing_quest_results"] = False
+ self._SESSIONAL_DATA["choosing_right_answer_for_quest"] = True
+ current_difficulty_level = self._SESSIONAL_DATA["difficulty_level"]
+ self._save_text_and_correct_answer_of_quest_in_session_data (current_difficulty_level)
+ self._OUTPUT_TEXT = self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+
+ def _sending_report (self) -> None:
+ # Доработать # FIXME
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+
+ def _consulting (self) -> None:
+ # Доработать # FIXME
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+
+ def _has_all_words_in_text_in_lower (self, *words) -> bool:
+ """Есть ли все слова в ответе пользователя?"""
+ for word in words:
+ if not word in self._WORDS_OF_TEXT_IN_LOWER:
+ return False
+ return True
+
+ def _has_one_word_in_text_in_lower (self, *words) -> bool:
+ """Есть ли хоть одно слово в ответе пользователя?"""
+ for word in words:
+ if word in self._WORDS_OF_TEXT_IN_LOWER:
+ return True
+ return False
+
+
+ def _go_to_main_menu (self) -> None:
+ self._OUTPUT_TEXT = get_text_that_says_user_is_just_in_main_menu ( )
+ self._TEXT_TO_SPEECH = get_text_that_says_user_is_just_in_main_menu ( )
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+ self._make_all_sessional_data_false ( )
+
+ def _make_all_sessional_data_false (self) -> None:
+ """Если всё в _SESSIONAL_DATA будет False,
+ значит пользователь на главном меню"""
+ for key in self._SESSIONAL_DATA.keys():
+ self._SESSIONAL_DATA[key] = False
+
+
+ def _end_the_session (self) -> None:
+ self._OUTPUT_TEXT = get_farewell_text ( )
+ self._IS_END_SESSION = True
+
+
+ def get_response (self) -> dict:
+ return {
+ "version": self._VERSION,
+ "response": {
+ "text": self._OUTPUT_TEXT,
+ "tts": self._TEXT_TO_SPEECH,
+ "end_session": self._IS_END_SESSION,
+ "buttons": self._BUTTONS.BUTTONS},
+ "session_state": self._SESSIONAL_DATA,
+ "user_state_update": self._INTERSESSIONAL_DATA
+ }
+ # Даже если self._TEXT_TO_SPEECH ничего не содержит (""),
+ # то будет сказан текст, который написан в поле ["response"]["text"]
+
+
+
+# Функция, вызываемая Яндексом для запуска скрипта Алисы (в коде вызывать её не нужно).
+def main (request_from_alisa: dict, context) -> dict:
+ handler_of_alisa = HandlerOfAlisa (request_from_alisa)
+ return handler_of_alisa.get_response ( )
\ No newline at end of file
diff --git a/main3.py b/main3.py
new file mode 100644
index 0000000..f99139b
--- /dev/null
+++ b/main3.py
@@ -0,0 +1,795 @@
+import random
+
+from json_manager import *
+from useful_functions import *
+from quest_getter import QuestGetter
+from lesson_getter import LessonGetter
+from task_getter import TaskGetter
+from buttons import Buttons
+from email_sender import EmailSender
+from enums import *
+
+from typing import Literal
+
+
+class HandlerOfAlisa:
+ def __init__ (self, request: dict):
+ self._VERSION: str = request["version"]
+ self._TEXT_IN_LOWER: str = request["request"]["command"]
+ self._ORIGINAL_TEXT: str = request["request"]["original_utterance"]
+ self._WORDS_OF_TEXT_IN_LOWER: list = request["request"]["nlu"]["tokens"]
+ self._IS_FIRST_MESSAGE: bool = request["session"]["new"]
+ self._IS_END_SESSION: bool = False
+ # Заранее создаются сессионные и межсессионные данные
+ self._SESSIONAL_DATA: dict = create_sessional_data (request["state"]["session"])
+ self._INTERSESSIONAL_DATA: dict = create_intersessional_data (request["state"]["user"])
+ self._TEXT_TO_SPEECH = ""
+ self._CARD = { }
+ self._BUTTONS = Buttons ( )
+ self._working_with_user ( )
+
+
+ # Декоратор, сохраняющий посленюю фразу и кнопки в сессионных данных
+ def save_last_phrase (function: callable) -> callable:
+ def _wrapper (self, *args, **kwargs):
+ function (self, *args, **kwargs)
+ self._SESSIONAL_DATA["last_output_text"] = self._OUTPUT_TEXT
+ self._SESSIONAL_DATA["last_text_to_speech"] = self._TEXT_TO_SPEECH
+ self._SESSIONAL_DATA["last_buttons"] = self._BUTTONS.BUTTONS
+ return _wrapper
+
+
+ @save_last_phrase
+ def _working_with_user (self) -> None:
+ """Во время запуска навыка Алиса получает пустой текстовый запрос,
+ на который она тут же отвечает. Этот ответ мы воспринимаем
+ как первое сообщение (хотя оно уже по факту второе, но это неважно).
+ """
+ # Абсолютно новый пользователь
+ if self._INTERSESSIONAL_DATA["new_user"]:
+ self._OUTPUT_TEXT = get_text_for_new_user ( )
+ self._TEXT_TO_SPEECH = get_introduction_sound ( ) + get_text_for_new_user ( ) + "\n"
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._INTERSESSIONAL_DATA["new_user"] = False
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ # Пользователь в главном меню впервые
+ elif self._user_is_in_main_menu and self._IS_FIRST_MESSAGE:
+ user_greeting = get_user_greeting ( )
+ self._OUTPUT_TEXT = user_greeting
+ self._TEXT_TO_SPEECH = get_introduction_sound ( ) + user_greeting
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ # Пользователь просто в главном меню
+ elif self._user_is_in_main_menu:
+ text_that_says_user_is_just_in_main_menu = get_text_that_says_user_is_just_in_main_menu ( )
+ self._OUTPUT_TEXT = text_that_says_user_is_just_in_main_menu
+ self._TEXT_TO_SPEECH = text_that_says_user_is_just_in_main_menu
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+ self._working_with_user_in_main_menu ( )
+
+ # Пользователь не в главном меню
+ else:
+ self._working_with_user_outside_main_menu ( )
+
+ @property
+ def _user_is_in_main_menu (self) -> bool:
+ if self._SESSIONAL_DATA["state"] == "in_main_menu":
+ return True
+ else:
+ return False
+
+
+ @save_last_phrase
+ def _working_with_user_in_main_menu (self) -> None:
+ self._BUTTONS.remove_all_buttons ( )
+ self._TEXT_TO_SPEECH = ""
+ # Пока навык в разработке
+ if self._has_all_words_in_text_in_lower ("сбрось", "настройки") or \
+ self._has_all_words_in_text_in_lower ("сбросить", "настройки"):
+ self._INTERSESSIONAL_DATA["new_user"] = True
+ self._INTERSESSIONAL_DATA["last_lesson"] = 0
+ self._INTERSESSIONAL_DATA["last_task"] = 0
+ self._OUTPUT_TEXT = "Настройки сброшены.\n"
+ self._OUTPUT_TEXT = "Перезагрузите навык."
+
+ elif self._has_one_word_in_text_in_lower (
+ "курс", "курса", "курсу", "курсом", "курсе"):
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._OUTPUT_TEXT = "Вы находитесь в меню Курса.\n"
+ self._OUTPUT_TEXT += "Здесь вы можете посмотреть список тем и выбрать любую,\n"
+ self._OUTPUT_TEXT += "можете продолжить последнюю или переслушать текущую."
+ self._BUTTONS.add_buttons (*self._commands_of_course, hide_all = False)
+
+ elif self._has_one_word_in_text_in_lower (
+ "задачка", "задачки", "задачку", "задачке", "задачкой",
+ "задача", "задачи", "задачу", "задаче", "задачей",
+ "задачек", "задачкам", "задачками", "задачках"):
+ # FIXME
+ self._SESSIONAL_DATA["state"] = "working_with_tasks"
+ self._OUTPUT_TEXT = "Какой уровень сложности вы хотите выбрать?\n"
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT
+ self._TEXT_TO_SPEECH += ", ".join (self._difficulty_levels_of_course)
+ self._BUTTONS.add_buttons (*self._difficulty_levels_of_course, hide_all = False)
+ self._BUTTONS.add_buttons ("Узнать мои результаты", "На главное меню", "Пока", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "квест", "квеста", "квесту", "квестом", "квесте",
+ "квесты", "квестов", "квестам", "квестами", "квестах"):
+ self._SESSIONAL_DATA["state"] = "working_with_quest"
+ self._OUTPUT_TEXT = "Какой уровень сложности вы хотите выбрать?\n"
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT
+ self._TEXT_TO_SPEECH += ", ".join (self._difficulty_levels_of_quest)
+ self._BUTTONS.add_buttons (*self._difficulty_levels_of_quest, hide_all = False)
+ self._BUTTONS.add_buttons ("Узнать мои результаты", "На главное меню", "Пока", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "пожаловаться", "жалоба", "жалобу", "отчёт", "отчет"):
+ self._SESSIONAL_DATA["state"] = "sending_report"
+ self._OUTPUT_TEXT = "Если вы хотите пожаловаться, то сейчас просто скажите вашу жалобу. Я вас внимательно слушаю."
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "консультант", "консультанта", "консультанту", "консультантом", "консультанте"
+ "консультация", "консультации", "консультацию", "консультацией", "проконсультируй"):
+ self._SESSIONAL_DATA["state"] = "consulting"
+ self._OUTPUT_TEXT = "Пока я не могу вас проконсультировать, извините...\n"
+ self._OUTPUT_TEXT += "Может, на главное меню?"
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ elif self._has_all_words_in_text_in_lower ("оцени", "знания"):
+ self._OUTPUT_TEXT = "Зачем \"Оцени мои знания\", когда есть \"Квест\"?\n"
+ self._OUTPUT_TEXT += "Скажи \"Квест\", чтобы его попробовать."
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._OUTPUT_TEXT = "Вы уже на главном меню!"
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+ @property
+ def _commands_of_course (self) -> tuple[str]:
+ return "Посмотреть список тем", "Текущая тема", "Продолжить последнюю", "Переслушать текущую", "На главное меню", "Пока!"
+
+ @property
+ def _difficulty_levels_of_quest (self) -> tuple[str, str, str, str]:
+ return "Лёгкий", "Средний", "Высокий", "Случайный"
+
+ @property
+ def _difficulty_levels_of_course (self) -> tuple[str, str, str, str, str]:
+ return "Лёгкий", "Средний", "Высокий", "Очень высокий", "Случайный"
+
+ @property
+ def _user_wants_to_hear_last_phrase (self) -> bool:
+ if self._has_one_word_in_text_in_lower ("повтори", "повторить", "что", "чего"):
+ return True
+ else:
+ return False
+
+ def _say_last_phrase (self) -> None:
+ self._OUTPUT_TEXT = self._SESSIONAL_DATA["last_output_text"]
+ self._TEXT_TO_SPEECH = self._SESSIONAL_DATA["last_text_to_speech"]
+ self._BUTTONS.BUTTONS = self._SESSIONAL_DATA["last_buttons"]
+ self._CARD = self._SESSIONAL_DATA["last_card"]
+
+
+ @save_last_phrase
+ def _working_with_user_outside_main_menu (self) -> None:
+ match self._SESSIONAL_DATA["state"]:
+ case "working_with_course":
+ self._working_with_course ( )
+ case "choosing_course_theme":
+ self._choosing_course_theme ( )
+ case "start_next_lesson_or_not":
+ self._start_next_lesson_or_not ( )
+ case "working_with_tasks":
+ self._working_with_tasks ( )
+ case "choosing_right_answer_for_task":
+ self._choosing_right_answer_for_task ( )
+ case "working_with_quest":
+ self._working_with_quest ( )
+ case "choosing_right_answer_for_quest":
+ self._choosing_right_answer_for_quest ( )
+ case "viewing_quest_results":
+ self._viewing_quest_results ( )
+ case "sending_report":
+ self._sending_report ( )
+ case "consulting":
+ self._consulting ( )
+
+
+ @save_last_phrase
+ def _working_with_course (self) -> None:
+ lesson_getter = LessonGetter ( )
+ current_lesson_theme = self._INTERSESSIONAL_DATA["current_lesson"]
+ current_lesson_subtheme = self._INTERSESSIONAL_DATA["current_sublesson"]
+
+ if self._has_one_word_in_text_in_lower ("список", "списка", "списку", "списком", "списке") or \
+ self._has_one_word_in_text_in_lower ("списки", "списка", "спискам", "списками", "списках"):
+ self._SESSIONAL_DATA["state"] = "choosing_course_theme"
+ self._OUTPUT_TEXT = "Список тем уроков:"
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT
+ for lesson_theme in lesson_getter.themes:
+ self._BUTTONS.add_buttons (lesson_theme, hide_all = False)
+ self._TEXT_TO_SPEECH += lesson_theme + "\n"
+ self._BUTTONS.add_buttons ("Назад", "На главное меню", "Выход", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower ("продолжить", "дальше", "далее"):
+ if current_lesson_theme:
+ next_subtheme = lesson_getter.get_name_of_next_subtheme (theme = current_lesson_theme,
+ subtheme = current_lesson_subtheme)
+ else:
+ next_subtheme = None
+
+ if next_subtheme:
+ self._INTERSESSIONAL_DATA["current_sublesson"] = next_subtheme
+ self._OUTPUT_TEXT = lesson_getter.get_subtheme_text (theme = current_lesson_theme,
+ subtheme = next_subtheme)
+ self._BUTTONS.add_buttons ("Продолжить", "Переслушать", "Список тем",
+ "На главное меню", "Пока", hide_all = True)
+ elif not next_subtheme and current_lesson_subtheme:
+ self._OUTPUT_TEXT = "Поздравляю! Вы прошли целый урок.\n"
+ self._OUTPUT_TEXT += "Следующий - это " + lesson_getter.get_name_of_next_theme (current_lesson_theme) + "\n"
+ self._OUTPUT_TEXT += "Хотите продолжить?"
+ self._SESSIONAL_DATA["state"] = "start_next_lesson_or_not"
+ self._BUTTONS.add_buttons ("Да, хочу!", "Нет, позже.", hide_all = False)
+ self._BUTTONS.add_buttons ("На главное меню", "Пока", hide_all = True)
+
+ else:
+ self._user_has_not_listened_to_any_lesson ( )
+
+ elif self._has_all_words_in_text_in_lower ("переслушать"):
+ if current_lesson_theme:
+ self._OUTPUT_TEXT = lesson_getter.get_subtheme_text (theme = current_lesson_theme,
+ subtheme = current_lesson_subtheme)
+ self._OUTPUT_TEXT += "\nСкажите: \"Продолжить\", чтобы продолжить."
+ self._BUTTONS.add_buttons ("Продолжить", "Переслушать", "Список тем", "Текущая тема",
+ "На главное меню", "Пока", hide_all = True)
+ else:
+ self._user_has_not_listened_to_any_lesson ( )
+
+ elif self._has_one_word_in_text_in_lower ("текущая", "текущую"):
+ if current_lesson_theme:
+ self._OUTPUT_TEXT = "Текущая тема урока: " + current_lesson_theme + "\n"
+ self._OUTPUT_TEXT += "Подтема: " + current_lesson_subtheme
+ self._BUTTONS.add_buttons ("Продолжить", "Переслушать", "На главное меню", "Пока", hide_all = True)
+ else:
+ self._user_has_not_listened_to_any_lesson ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ @property
+ def _user_wants_to_go_to_main_menu (self) -> bool:
+ if self._has_all_words_in_text_in_lower ("на", "главное", "меню"):
+ return True
+ else:
+ return False
+
+ @property
+ def _user_wants_to_end_session (self) -> bool:
+ if self._has_one_word_in_text_in_lower ("выход", "выйти", "пока", "прощай"):
+ return True
+ else:
+ return False
+
+
+ def _user_has_not_listened_to_any_lesson (self) -> None:
+ self._OUTPUT_TEXT = "Вы ещё не прошли ни одного урока.\n"
+ self._OUTPUT_TEXT += "Скажите: \"Покажи список тем\", чтобы начать изучать курс."
+ self._BUTTONS.add_buttons ("Покажи список тем", "На главное меню", "Выход", hide_all = True)
+
+
+ @save_last_phrase
+ def _choosing_course_theme (self) -> None:
+ if self._has_one_word_in_text_in_lower ("1", "введение"):
+ self._start_next_lesson_and_sublesson (1)
+
+ elif self._has_one_word_in_text_in_lower ("2", "устанока"):
+ self._start_next_lesson_and_sublesson (2)
+
+ elif self._has_one_word_in_text_in_lower ("3", "основы"):
+ self._start_next_lesson_and_sublesson (3)
+
+ elif self._has_one_word_in_text_in_lower ("4", "операторы", "выражения"):
+ self._start_next_lesson_and_sublesson (4)
+
+ elif self._has_one_word_in_text_in_lower ("5"):
+ self._start_next_lesson_and_sublesson (5)
+
+ elif self._has_one_word_in_text_in_lower ("6"):
+ self._start_next_lesson_and_sublesson (6)
+
+ elif self._has_one_word_in_text_in_lower ("7"):
+ self._start_next_lesson_and_sublesson (7)
+
+ elif self._has_one_word_in_text_in_lower ("8"):
+ self._start_next_lesson_and_sublesson (8)
+
+ elif self._has_one_word_in_text_in_lower ("9"):
+ self._start_next_lesson_and_sublesson (9)
+
+ elif self._has_one_word_in_text_in_lower ("10"):
+ self._start_next_lesson_and_sublesson (10)
+
+ elif self._has_one_word_in_text_in_lower ("назад", "обратно"):
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._OUTPUT_TEXT = "Вы находитесь в меню Курса.\n"
+ self._OUTPUT_TEXT += "Здесь вы можете посмотреть список тем и выбрать любую,\n"
+ self._OUTPUT_TEXT += "можете продолжить последнюю или переслушать текущую."
+ self._BUTTONS.add_buttons (*self._commands_of_course, hide_all = False)
+ self._BUTTONS.add_buttons ("Покажи список тем", "На главное меню", "Выход", hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+ def _start_next_lesson_and_sublesson (self, theme_number: Literal[1, 2, 3, 4, 5]) -> None:
+ lesson_getter = LessonGetter ( )
+ theme_number = theme_number - 1 # Первый урок под номером 0, а не 1
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._INTERSESSIONAL_DATA["current_lesson"] = (name_of_current_theme := lesson_getter.themes[theme_number]) # Морожовый, он самый)
+ self._INTERSESSIONAL_DATA["current_sublesson"] = (name_of_current_subtheme := lesson_getter.get_first_subtheme_name (name_of_current_theme))
+ self._OUTPUT_TEXT = random.choice (("Хорошо, ", "Отлично, ", "Прекрасно, ")) + "тогда начнём?" + "\n\n"
+ self._OUTPUT_TEXT += "Предисловие первого занятия:\n"
+ self._OUTPUT_TEXT += lesson_getter.get_subtheme_text (theme = name_of_current_theme,
+ subtheme = name_of_current_subtheme)
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT
+ self._BUTTONS.add_buttons ("Далее", "Переслушать", "На главное меню", "Пока", hide_all = True)
+
+
+ @save_last_phrase
+ def _start_next_lesson_or_not (self) -> None:
+ old_lesson_theme = self._INTERSESSIONAL_DATA["current_lesson"]
+ lesson_getter = LessonGetter ( )
+ next_lesson_theme = lesson_getter.get_name_of_next_theme (old_lesson_theme)
+ first_lesson_subtheme = lesson_getter.get_first_subtheme_name (next_lesson_theme)
+ self._INTERSESSIONAL_DATA["current_lesson"] = next_lesson_theme
+ self._INTERSESSIONAL_DATA["current_sublesson"] = first_lesson_subtheme
+
+ if self._has_one_word_in_text_in_lower ("да", "конечно", "дальше", "далее"):
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._OUTPUT_TEXT = lesson_getter.get_subtheme_text (theme = next_lesson_theme,
+ subtheme = first_lesson_subtheme)
+ self._BUTTONS.add_buttons ("Далее", "Переслушать", "На главное меню", "Пока", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower ("не", "нет", "позже", "потом"):
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._OUTPUT_TEXT = "Как хотите. В любой момент скажите просто скажите: \"Продолжить\"."
+ self._BUTTONS.add_buttons (*self._commands_of_course, hide_all = False)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("Да, хочу!", "Нет, позже.", hide_all = True)
+
+
+ @save_last_phrase
+ def _working_with_tasks (self) -> None:
+ if self._has_one_word_in_text_in_lower (
+ "лёгкий", "лёгкого", "лёгкому", "лёгким", "лёгком",
+ "легкий", "легкого", "легкому", "легким", "легком"):
+ self._OUTPUT_TEXT = random.choice (("Хорошо, ", "Отлично, ", "Прекрасно, ")) + "тогда начнём?\n"
+ self._SESSIONAL_DATA["difficulty_level_of_task"] = DifficultyLevels.EASY.value
+ self._SESSIONAL_DATA["state"] = "choosing_between_solve_and_code"
+
+ elif self._has_one_word_in_text_in_lower (
+ "средний", "среднего", "среднему", "среднем",
+ "средняя", "средней", "среднюю"):
+ self._OUTPUT_TEXT = random.choice (("Хорошо, ", "Отлично, ", "Прекрасно, ")) + "тогда начнём?\n"
+ self._SESSIONAL_DATA["difficulty_level_of_task"] = DifficultyLevels.MEDIUM.value
+ self._SESSIONAL_DATA["state"] = "choosing_between_solve_and_code"
+
+ elif self._has_one_word_in_text_in_lower (
+ "высокий", "высокого", "высокому", "высоким", "высоком",
+ "сложный", "сложного", "сложному", "сложным", "сложном"):
+ self._OUTPUT_TEXT = random.choice (("Хорошо, ", "Отлично, ", "Прекрасно, ")) + "тогда начнём?\n"
+ self._SESSIONAL_DATA["difficulty_level_of_task"] = DifficultyLevels.HARD.value
+ self._SESSIONAL_DATA["state"] = "choosing_between_solve_and_code"
+
+ elif self._has_one_word_in_text_in_lower (
+ "случайный", "случайного", "случайному", "случайным", "случайном",
+ "случайная", "случайной", "случайную",
+ "рандом", "рандома", "рандому", "рандомом", "рандоме",
+ "рандомный", "рандомного", "рандомному", "рандомном",
+ "рандомная", "рандомной", "рандомную"):
+ self._OUTPUT_TEXT = random.choice (("Хорошо, ", "Отлично, ", "Прекрасно, ")) + "\n"
+ self._SESSIONAL_DATA["difficulty_level_of_task"] = DifficultyLevels.get_random_difficulty_level_for_task ( )
+ self._SESSIONAL_DATA["state"] = "choosing_between_solve_and_code"
+
+ elif self._has_one_word_in_text_in_lower ("результат", "результаты"):
+ pass
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+
+ @save_last_phrase
+ def _choosing_right_answer_for_task (self) -> None:
+ # FIXME
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+
+ @save_last_phrase
+ def _working_with_quest (self) -> None:
+ if self._has_one_word_in_text_in_lower (
+ "лёгкий", "лёгкого", "лёгкому", "лёгким", "лёгком",
+ "легкий", "легкого", "легкому", "легким", "легком"):
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = DifficultyLevels.EASY.value
+ self._save_text_and_correct_answer_of_easy_quest_in_session_data ( )
+ self._show_quest ( )
+
+ elif self._has_one_word_in_text_in_lower (
+ "средний", "среднего", "среднему", "среднем",
+ "средняя", "средней", "среднюю"):
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = DifficultyLevels.MEDIUM.value
+ self._save_text_and_correct_answer_of_medium_quest_in_session_data ( )
+ self._show_quest ( )
+
+ elif self._has_one_word_in_text_in_lower (
+ "высокий", "высокого", "высокому", "высоким", "высоком",
+ "сложный", "сложного", "сложному", "сложным", "сложном"):
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = DifficultyLevels.HARD.value
+ self._save_text_and_correct_answer_of_hard_quest_in_session_data ( )
+ self._show_quest ( )
+
+ elif self._has_one_word_in_text_in_lower (
+ "случайный", "случайного", "случайному", "случайным", "случайном",
+ "случайная", "случайной", "случайную",
+ "рандом", "рандома", "рандому", "рандомом", "рандоме",
+ "рандомный", "рандомного", "рандомному", "рандомном",
+ "рандомная", "рандомной", "рандомную"):
+ difficulty_level = DifficultyLevels.get_random_difficulty_level_for_quest ( )
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = difficulty_level
+ self._save_text_and_correct_answer_of_quest_in_session_data (difficulty_level)
+ self._show_quest ( )
+
+ elif self._has_one_word_in_text_in_lower ("результат", "результаты"):
+ self._show_results_of_quest_and_next_quest ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_difficutly_level, hide_all = True)
+
+ @property
+ def _buttons_for_choosing_difficutly_level (self) -> dict:
+ return "Лёгкий", "Средний", "Высокий", "Случайный", "Узнать мои результаты", "На главное меню", "Пока!"
+
+ def _save_text_and_correct_answer_of_easy_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_easy_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_easy_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_easy_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_easy_quest_as_str
+
+ def _save_text_and_correct_answer_of_medium_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_medium_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_medium_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_medium_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_medium_quest_as_str
+
+ def _save_text_and_correct_answer_of_hard_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_hard_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_hard_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_hard_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_hard_quest_as_str
+
+ def _save_text_and_correct_answer_of_quest_in_session_data (self, difficulty_level: int) -> None:
+ match difficulty_level:
+ case DifficultyLevels.EASY.value:
+ self._save_text_and_correct_answer_of_easy_quest_in_session_data ( )
+ case DifficultyLevels.MEDIUM.value:
+ self._save_text_and_correct_answer_of_medium_quest_in_session_data ( )
+ case DifficultyLevels.HARD.value:
+ self._save_text_and_correct_answer_of_hard_quest_in_session_data ( )
+ case _:
+ raise ValueError ("Указан неправильный уровень сложности!")
+
+ def _say_that_user_can_change_their_difficulty_level_of_quest_if_it_is_not_said_yet (self) -> None:
+ if not self._SESSIONAL_DATA["was_said_that_user_can_change_difficulty_level_in_quest"]:
+ text = (
+ "В любой момент вы можете сменить уровень сложности, сказав: \"Хочу сменить сложность\";\n",
+ "или выйти на главное меню, сказав: \"На главное меню\".\n",
+ "Так же вы можете узнать количество правильно отвеченных вопросов, сказав: \"Покажи результаты\".\n",
+ "Вот квест.\n\n"
+ )
+ self._OUTPUT_TEXT += "".join (text)
+ self._SESSIONAL_DATA["was_said_that_user_can_change_difficulty_level_in_quest"] = True
+
+ def _get_text_of_current_quest (self) -> str:
+ return self._SESSIONAL_DATA["text_of_quest"]
+
+ @property
+ def _buttons_for_choosing_correct_answer (self) -> dict:
+ return "Первое", "Второе", "Третье", "Изменить уровень сложности", "Узнать мои результаты", "На главное меню", "Пока!"
+
+ def _show_quest (self) -> None:
+ self._SESSIONAL_DATA["state"] = "choosing_right_answer_for_quest"
+ self._OUTPUT_TEXT = random.choice (("Хорошо.", "Отлично.", "Прекрасно.")) + "\n\n"
+ self._say_that_user_can_change_their_difficulty_level_of_quest_if_it_is_not_said_yet ( )
+ self._OUTPUT_TEXT += self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+
+ @save_last_phrase
+ def _choosing_right_answer_for_quest (self) -> None:
+ if self._has_one_word_in_text_in_lower ("1", "один", "первый", "первое"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 1:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_one_word_in_text_in_lower ("2", "два", "второй", "второе"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 2:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_one_word_in_text_in_lower ("3", "три", "третий", "третье"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 3:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_all_words_in_text_in_lower ("уровень", "сложности") or \
+ self._has_one_word_in_text_in_lower ("сложность"):
+ self._SESSIONAL_DATA["state"] = "working_with_quest"
+ self._OUTPUT_TEXT = random.choice (("Хорошо.", "Отлично.")) + "\n"
+ self._OUTPUT_TEXT += "Теперь просто скажите нужный уровень сложности."
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_difficutly_level, hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower ("результат", "результаты"):
+ self._show_results_of_quest_and_next_quest ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_text_that_says_there_is_no_answer_like_that ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ def _correct_answer_of_quest_is_selected (self) -> None:
+ text_that_says_answer_is_correct = get_text_that_says_answer_is_correct ( ) + "\n\n"
+ text_of_next_quest = self._get_text_of_current_quest ( )
+ self._CARD = self._make_big_win_picture (title = text_that_says_answer_is_correct, description = text_of_next_quest)
+ self._TEXT_TO_SPEECH = get_random_win_sound ( ) + text_that_says_answer_is_correct
+ current_difficulty_level = self._SESSIONAL_DATA["difficulty_level_of_quest"]
+ self._save_text_and_correct_answer_of_quest_in_session_data (current_difficulty_level)
+ self._TEXT_TO_SPEECH += text_of_next_quest
+ self._OUTPUT_TEXT = text_that_says_answer_is_correct + "\n" + text_of_next_quest
+ self._SESSIONAL_DATA["number_of_correct_quest_answers"] += 1
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ def _show_results_of_quest_and_next_quest (self) -> None:
+ correct_quest_answers = int (self._SESSIONAL_DATA["number_of_correct_quest_answers"])
+ wrong_quest_answers = int (self._SESSIONAL_DATA["number_of_wrong_quest_answers"])
+ if correct_quest_answers and wrong_quest_answers:
+ self._OUTPUT_TEXT = f"Количество правильных ответов: {correct_quest_answers}.\n"
+ self._OUTPUT_TEXT += f"Количество неправильных ответов: {wrong_quest_answers}.\n"
+ python_knowledge = calculate_python_knowledge (correct_quest_answers, wrong_quest_answers)
+ self._OUTPUT_TEXT += f"Ваше знание Python: {python_knowledge}%."
+ self._SESSIONAL_DATA["state"] = "viewing_quest_results"
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ elif not correct_quest_answers and wrong_quest_answers:
+ self._OUTPUT_TEXT = "Жаль, но у вас нет ни одного правильного ответа на квест."
+ self._SESSIONAL_DATA["state"] = "viewing_quest_results"
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ elif correct_quest_answers and not wrong_quest_answers:
+ self._OUTPUT_TEXT = "Все ваши ответы верны! Похоже, вы профессиональный программист!"
+ self._SESSIONAL_DATA["state"] = "viewing_quest_results"
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ else:
+ self._OUTPUT_TEXT = "Пока вы не ответили ни на один квест."
+ self._make_all_sessional_data_false ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ self._TEXT_TO_SPEECH = get_random_sound_of_looking_results ( ) + self._OUTPUT_TEXT
+
+
+ def _wrong_answer_of_quest_is_selected (self) -> None:
+ self._OUTPUT_TEXT = get_text_that_says_answer_is_wrong ( )
+ self._TEXT_TO_SPEECH = get_random_lose_sound ( ) + self._OUTPUT_TEXT
+ self._SESSIONAL_DATA["number_of_wrong_quest_answers"] += 1
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+
+ @save_last_phrase
+ def _viewing_quest_results (self) -> None:
+ if self._has_one_word_in_text_in_lower ("продолжить"):
+ self._SESSIONAL_DATA["state"] = "choosing_right_answer_for_quest"
+ current_difficulty_level = self._SESSIONAL_DATA["difficulty_level_of_quest"]
+ self._save_text_and_correct_answer_of_quest_in_session_data (current_difficulty_level)
+ self._OUTPUT_TEXT = self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+
+ @save_last_phrase
+ def _sending_report (self) -> None:
+ # Доработать # FIXME
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+ else:
+ email_sender = EmailSender ("leha.bondar.05@mail.ru", "Sstrelo4gGvip")
+ email_sender.send_email ("leha.bondar.2005@mail.ru", "Test theme", "Какой-то текст...")
+
+
+ @save_last_phrase
+ def _consulting (self) -> None:
+ # Доработать # FIXME
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+
+ def _has_all_words_in_text_in_lower (self, *words) -> bool:
+ """Есть ли все слова в ответе пользователя?"""
+ for word in words:
+ if not word in self._WORDS_OF_TEXT_IN_LOWER:
+ return False
+ return True
+
+ def _has_one_word_in_text_in_lower (self, *words) -> bool:
+ """Есть ли хоть одно слово в ответе пользователя?"""
+ for word in words:
+ if word in self._WORDS_OF_TEXT_IN_LOWER:
+ return True
+ return False
+
+
+ def _go_to_main_menu (self) -> None:
+ self._OUTPUT_TEXT = get_text_that_says_user_is_just_in_main_menu ( )
+ self._TEXT_TO_SPEECH = get_text_that_says_user_is_just_in_main_menu ( )
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._SESSIONAL_DATA["state"] = "in_main_menu"
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+
+ def _end_the_session (self) -> None:
+ self._OUTPUT_TEXT = get_farewell_text ( )
+ self._IS_END_SESSION = True
+
+
+ def _make_big_win_picture (self, title: str, description: str) -> dict:
+ return {
+ "type": "BigImage",
+ "image_id": get_random_bonus_picture ( ),
+ "title": title,
+ "description": description
+ }
+
+
+ def get_response (self) -> dict:
+ if self._CARD:
+ return {
+ "version": self._VERSION,
+ "response": {
+ "text": self._OUTPUT_TEXT,
+ "tts": self._TEXT_TO_SPEECH,
+ "end_session": self._IS_END_SESSION,
+ "buttons": self._BUTTONS.BUTTONS,
+ "card": self._CARD},
+ "session_state": self._SESSIONAL_DATA,
+ "user_state_update": self._INTERSESSIONAL_DATA
+ }
+ else:
+ return {
+ "version": self._VERSION,
+ "response": {
+ "text": self._OUTPUT_TEXT,
+ "tts": self._TEXT_TO_SPEECH,
+ "end_session": self._IS_END_SESSION,
+ "buttons": self._BUTTONS.BUTTONS},
+ "session_state": self._SESSIONAL_DATA,
+ "user_state_update": self._INTERSESSIONAL_DATA
+ }
+ # Даже если self._TEXT_TO_SPEECH ничего не содержит (""),
+ # то будет сказан текст, который написан в поле ["response"]["text"]
+
+
+
+# Функция, вызываемая Яндексом для запуска скрипта Алисы (в коде вызывать её не нужно).
+def main (request_from_alisa: dict, context) -> dict:
+ handler_of_alisa = HandlerOfAlisa (request_from_alisa)
+ return handler_of_alisa.get_response ( )
\ No newline at end of file
diff --git a/main4.py b/main4.py
new file mode 100644
index 0000000..844472f
--- /dev/null
+++ b/main4.py
@@ -0,0 +1,969 @@
+import random
+
+from json_manager import *
+from useful_functions import *
+from quest_getter import QuestGetter
+from lesson_getter import LessonGetter
+from task_getter import TaskGetter
+from buttons import Buttons
+from enums import *
+from consultant import ArtificialIntelligence
+from typing import Literal
+
+def code_to_speech(code: str) -> str:
+ """Переводит код в слова и выводит готовый текст в пронумерованном столбце."""
+ REPLACEMENTS: dict = _get_replacements ( )
+
+ PAUSE = "sil<[250]>"
+ lines = code.split("\n")
+ formatted_lines = [ ]
+ for i, line in enumerate(lines, start=1):
+ formatted_line = line
+ for key in REPLACEMENTS.keys():
+ formatted_line = formatted_line.replace(key, REPLACEMENTS[key])
+ formatted_line = formatted_line.split("#")[0]
+ formatted_lines.append(f"{PAUSE} код {PAUSE} {formatted_line}")
+ return "\n".join(formatted_lines) + PAUSE
+
+def _get_replacements ( ) -> dict:
+ """Возвращает словарь с заменами символов на слова."""
+ return {
+ ")": " скобка ",
+ "(": " скобка ",
+ "*": " звёздочка ",
+ "'": " кавычки ",
+ '"': " кавычки ",
+ "{": " фигурная скобка ",
+ "}": " фигурная скобка ",
+ ":": " двоеточие ",
+ "!": " восклицательный знак ",
+ ".": " точка ",
+ ",": " запятая ",
+ "[": " квадратная скобка ",
+ "]": " квадратная скобка ",
+ "||": " or ",
+ ">": " больше ",
+ "<": " меньше ",
+ "/": " разделить ",
+ "-": " минус ",
+ "+": " плюс ",
+ "%": " процент ",
+ "@": " собачка ",
+ "&": " and "
+ }
+
+
+def tts_format(text):
+ c = text.split("`")
+ i = 1
+ while i callable:
+ def _wrapper (self, *args, **kwargs):
+ function (self, *args, **kwargs)
+ self._SESSIONAL_DATA["last_output_text"] = self._OUTPUT_TEXT
+ self._SESSIONAL_DATA["last_text_to_speech"] = self._TEXT_TO_SPEECH
+ self._SESSIONAL_DATA["last_buttons"] = self._BUTTONS.BUTTONS
+ self._SESSIONAL_DATA["last_card"] = self._CARD
+ return _wrapper
+
+
+ @save_last_phrase
+ def _working_with_user (self) -> None:
+ """Во время запуска навыка Алиса получает пустой текстовый запрос,
+ на который она тут же отвечает. Этот ответ мы воспринимаем
+ как первое сообщение (хотя оно уже по факту второе, но это неважно).
+ """
+ # Абсолютно новый пользователь
+ if self._INTERSESSIONAL_DATA["new_user"]:
+ self._OUTPUT_TEXT = get_text_for_new_user ( )
+ self._TEXT_TO_SPEECH = get_introduction_sound ( ) + get_text_for_new_user ( ) + "\n"
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._INTERSESSIONAL_DATA["new_user"] = False
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ # Пользователь в главном меню впервые
+ elif self._user_is_in_main_menu and self._IS_FIRST_MESSAGE:
+ user_greeting = get_user_greeting ( )
+ self._OUTPUT_TEXT = user_greeting
+ self._TEXT_TO_SPEECH = get_introduction_sound ( ) + user_greeting
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ # Пользователь просто в главном меню
+ elif self._user_is_in_main_menu:
+ self._OUTPUT_TEXT = get_text_that_says_user_is_just_in_main_menu ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+ self._working_with_user_in_main_menu ( )
+
+ # Пользователь не в главном меню
+ else:
+ self._working_with_user_outside_main_menu ( )
+
+ @property
+ def _user_is_in_main_menu (self) -> bool:
+ if self._SESSIONAL_DATA["state"] == "in_main_menu":
+ return True
+ else:
+ return False
+
+
+ def _working_with_user_in_main_menu (self) -> None:
+ self._BUTTONS.remove_all_buttons ( )
+ self._TEXT_TO_SPEECH = ""
+ # Пока навык в разработке
+ if self._has_all_words_in_text_in_lower ("сбрось", "настройки") or \
+ self._has_all_words_in_text_in_lower ("сбросить", "настройки"):
+ self._INTERSESSIONAL_DATA["new_user"] = True
+ self._INTERSESSIONAL_DATA["last_lesson"] = 0
+ self._INTERSESSIONAL_DATA["last_task"] = 0
+ self._OUTPUT_TEXT = "Настройки сброшены.\n"
+ self._OUTPUT_TEXT = "Перезагрузите навык."
+
+ elif self._has_one_word_in_text_in_lower (
+ "курс", "курса", "курсу", "курсом", "курсе"):
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._OUTPUT_TEXT = "Вы находитесь в меню Курса.\n"
+ self._OUTPUT_TEXT += "Здесь вы можете посмотреть список тем и выбрать любую,\n"
+ self._OUTPUT_TEXT += "можете продолжить последнюю или переслушать текущую."
+ self._BUTTONS.add_buttons (*self._commands_of_course, hide_all = False)
+ self._BUTTONS.add_buttons ("Повтори", hide_all = True)
+ elif self._has_one_word_in_text_in_lower(
+ "консультант", "консультанту", "консультанта", "консультанты", "консультанте", "консультация", "консультацию", "консультации", "консультацией", "консультантом"
+ ):
+ self._SESSIONAL_DATA["state"] = "consulting"
+ self._OUTPUT_TEXT = "Я готова подобрать вам справку по теме вашей проблемы. С чем вам помочь?\n"
+ elif self._has_one_word_in_text_in_lower (
+ "задачка", "задачки", "задачку", "задачке", "задачкой",
+ "задача", "задачи", "задачу", "задаче", "задачей",
+ "задачек", "задачкам", "задачками", "задачках"):
+ # FIXME
+ self._SESSIONAL_DATA["state"] = "working_with_tasks"
+ self._OUTPUT_TEXT = "Какой уровень сложности вы хотите выбрать?\n"
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT
+ self._TEXT_TO_SPEECH += ", ".join (self._difficulty_levels)
+ self._BUTTONS.add_buttons (*self._difficulty_levels, hide_all = False)
+ self._BUTTONS.add_buttons ("На главное меню", "Повтори", "Пока", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "квест", "квеста", "квесту", "квестом", "квесте",
+ "квесты", "квестов", "квестам", "квестами", "квестах"):
+ self._SESSIONAL_DATA["state"] = "working_with_quest"
+ self._OUTPUT_TEXT = "Какой уровень сложности вы хотите выбрать?\n"
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT
+ self._TEXT_TO_SPEECH += ", ".join (self._difficulty_levels)
+ self._BUTTONS.add_buttons (*self._difficulty_levels, hide_all = False)
+ self._BUTTONS.add_buttons ("Узнать мои результаты", "Повтори", "На главное меню", "Пока", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower (
+ "пожаловаться", "жалоба", "жалобу", "отчёт", "отчет"):
+ self._SESSIONAL_DATA["state"] = "sending_report"
+ self._OUTPUT_TEXT = "Я не знаю, на какую почту отправлять жалобу...\n"
+ self._OUTPUT_TEXT += "Может, на главное меню?"
+ self._BUTTONS.add_buttons ("На главное меню", "Повтори", "Пока!", hide_all = True)
+
+ elif self._user_needs_help:
+ self._OUTPUT_TEXT = "Сейчас я вам помогу. В главном меню есть следующие команды: "
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT + get_main_commands_of_skill ( )
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._OUTPUT_TEXT = "Вы уже на главном меню!"
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+ @property
+ def _commands_of_course (self) -> tuple[str]:
+ return "Посмотреть список тем", "Текущая тема", "Продолжить последнюю", "Переслушать текущую", "Помощь", "На главное меню", "Пока!"
+
+ @property
+ def _difficulty_levels (self) -> tuple[str, str, str, str]:
+ return "Лёгкий", "Средний", "Высокий", "Случайный"
+
+ @property
+ def _user_wants_to_hear_last_phrase (self) -> bool:
+ if self._has_one_word_in_text_in_lower ("повтори", "повторить", "что", "чего"):
+ return True
+ else:
+ return False
+
+ @property
+ def _user_needs_help (self) -> bool:
+ if self._has_one_word_in_text_in_lower ("помощь", "помоги", "забыл", "забыла", "команды"):
+ return True
+ else:
+ return False
+
+ def _say_last_phrase (self) -> None:
+ self._OUTPUT_TEXT = self._SESSIONAL_DATA["last_output_text"]
+ self._TEXT_TO_SPEECH = self._SESSIONAL_DATA["last_text_to_speech"]
+ self._BUTTONS.BUTTONS = self._SESSIONAL_DATA["last_buttons"]
+ self._CARD = self._SESSIONAL_DATA["last_card"]
+
+
+ @save_last_phrase
+ def _working_with_user_outside_main_menu (self) -> None:
+ match self._SESSIONAL_DATA["state"]:
+ case "working_with_course":
+ self._working_with_course ( )
+ case "choosing_course_theme":
+ self._choosing_course_theme ( )
+ case "start_next_lesson_or_not":
+ self._start_next_lesson_or_not ( )
+ case "working_with_tasks":
+ self._working_with_tasks ( )
+ case "working_with_quest":
+ self._working_with_quest ( )
+ case "choosing_right_answer_for_quest":
+ self._choosing_right_answer_for_quest ( )
+ case "viewing_quest_results":
+ self._viewing_quest_results ( )
+ case "sending_report":
+ self._sending_report ( )
+ case "choosing_between_solve_and_code":
+ self._choosing_between_solve_and_code()
+ case "_wish_to_see_solve":
+ self._wish_to_see_solve()
+ case "_wish_to_see_solve":
+ self._wish_to_see_solve()
+ case "consulting":
+ self._consulting ( )
+
+
+ def _working_with_course (self) -> None:
+ lesson_getter = LessonGetter ( )
+ current_lesson_theme = self._INTERSESSIONAL_DATA["current_lesson"]
+ current_lesson_subtheme = self._INTERSESSIONAL_DATA["current_sublesson"]
+
+ if self._has_one_word_in_text_in_lower ("список", "списка", "списку", "списком", "списке") or \
+ self._has_one_word_in_text_in_lower ("списки", "списка", "спискам", "списками", "списках"):
+ self._SESSIONAL_DATA["state"] = "choosing_course_theme"
+ self._OUTPUT_TEXT = "Список тем уроков:"
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT
+ for lesson_theme in lesson_getter.themes:
+ self._BUTTONS.add_buttons (lesson_theme, hide_all = False)
+ self._TEXT_TO_SPEECH += lesson_theme + "\n"
+ self._BUTTONS.add_buttons ("Назад", "Повтори", "На главное меню", "Выход", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower ("продолжить", "дальше", "далее"):
+ if current_lesson_theme:
+ next_subtheme = lesson_getter.get_name_of_next_subtheme (theme = current_lesson_theme,
+ subtheme = current_lesson_subtheme)
+ else:
+ next_subtheme = None
+
+ if next_subtheme:
+ text = lesson_getter.get_subtheme_text (theme = current_lesson_theme,
+ subtheme = next_subtheme)
+ self._INTERSESSIONAL_DATA["current_sublesson"] = next_subtheme
+ self._OUTPUT_TEXT = text
+ self._BUTTONS.add_buttons ("Продолжить", "Переслушать", "Список тем",
+ "На главное меню", "Пока", hide_all = True)
+ self._TEXT_TO_SPEECH = tts_format(text)
+ elif not next_subtheme and current_lesson_subtheme:
+ self._TEXT_TO_SPEECH = get_random_sound_of_looking_results ( )
+ self._CARD = make_big_level_up_picture (title = "Поздравляю! Вы прошли целый урок.", description = "Следующий - это " + lesson_getter.get_name_of_next_theme (current_lesson_theme) + ".\n" + "Хотите продолжить?")
+ self._TEXT_TO_SPEECH += "Поздравляю! Вы прошли целый урок.\n"
+ self._TEXT_TO_SPEECH += "Следующий - это " + lesson_getter.get_name_of_next_theme (current_lesson_theme) + "\n"
+ self._TEXT_TO_SPEECH += "Хотите продолжить?"
+ self._OUTPUT_TEXT = self._TEXT_TO_SPEECH
+ self._SESSIONAL_DATA["state"] = "start_next_lesson_or_not"
+ self._BUTTONS.add_buttons ("Да, хочу!", "Нет, позже.", hide_all = False)
+ self._BUTTONS.add_buttons ("На главное меню", "Пока", hide_all = True)
+
+ else:
+ self._user_has_not_listened_to_any_lesson ( )
+
+ elif self._has_all_words_in_text_in_lower ("переслушать"):
+ if current_lesson_theme:
+ self._OUTPUT_TEXT = lesson_getter.get_subtheme_text (theme = current_lesson_theme,
+ subtheme = current_lesson_subtheme)
+ self._OUTPUT_TEXT += "\nСкажите: \"Продолжить\", чтобы продолжить."
+ self._BUTTONS.add_buttons ("Продолжить", "Переслушать", "Список тем", "Текущая тема",
+ "На главное меню", "Пока", hide_all = True)
+ else:
+ self._user_has_not_listened_to_any_lesson ( )
+
+ elif self._has_one_word_in_text_in_lower ("текущая", "текущую"):
+ if current_lesson_theme:
+ self._OUTPUT_TEXT = "Текущая тема урока: " + current_lesson_theme + ".\n"
+ self._OUTPUT_TEXT += "Подтема: " + current_lesson_subtheme + ".\n"
+ self._OUTPUT_TEXT += "Скажите, если хотите переслушать или продолжить."
+ self._BUTTONS.add_buttons ("Продолжить", "Переслушать", "На главное меню", "Пока", hide_all = True)
+ else:
+ self._user_has_not_listened_to_any_lesson ( )
+
+ elif self._user_needs_help:
+ self._OUTPUT_TEXT = "Не волнуйтесь! В меню курса есть команды: "
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT + ", ".join (self._commands_of_course) + "."
+ self._BUTTONS.add_buttons (*self._commands_of_course, hide_all = False)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ @property
+ def _user_wants_to_go_to_main_menu (self) -> bool:
+ if self._has_all_words_in_text_in_lower ("на", "главное", "меню"):
+ return True
+ else:
+ return False
+
+ @property
+ def _user_wants_to_end_session (self) -> bool:
+ if self._has_one_word_in_text_in_lower ("выход", "выйти", "пока", "прощай"):
+ return True
+ else:
+ return False
+
+
+ def _choosing_between_solve_and_code(self) -> None:
+ entering = ["Ха! Сдаётесь?", "Сдаётесь?", "Ну что, у вас получилось?", "Что скажете?", "Уже?"]
+ a = random.choice(entering)
+ if self._has_one_word_in_text_in_lower ("решение", "решению", "реши", "решил", "ответ", "решай", "отвечай", "решении", "ответе"):
+ self._OUTPUT_TEXT = a + "\nИтак, решение: " + self._SESSIONAL_DATA["solve_of_task"] + "\nХотите услышать код решения на Python?"
+ self._SESSIONAL_DATA["state"] = "_wish_to_see_solve"
+ self._BUTTONS.add_buttons ("Да", "На главное меню", "Пока", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower ("код", "коды", "кода", "скрипт", "скрипты", "скрипта", "скрипте", "коде"):
+ self._OUTPUT_TEXT = a + "\nИтак, код: " + self._SESSIONAL_DATA["code_of_task"] + "\nХотите услышать объяснение?"
+ self._TEXT_TO_SPEECH = a + "Итак код. " + code_to_speech(self._SESSIONAL_DATA["code_of_task"]) + ".Хотите услышать объяснение?"
+ self._SESSIONAL_DATA["state"] = "_wish_to_see_solve"
+ self._BUTTONS.add_buttons ("Да", "На главное меню", "Пока", hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+
+ def _wish_to_see_solve(self):
+ if self._has_one_word_in_text_in_lower ("да", "ага", "давай", "поехали", "ес", "погнали", "говори", "гони"):
+ self._OUTPUT_TEXT = "Итак, код: " + self._SESSIONAL_DATA["code_of_task"] + "\nХотите ещё задачу? Тогда просто назовите желаемую сложность."
+ self._TEXT_TO_SPEECH = "итак код. " + code_to_speech(self._SESSIONAL_DATA["code_of_task"]) + ".хотите ещё задачу? Тогда просто назовите желаемую сложность."
+ self._SESSIONAL_DATA["state"] = "working_with_tasks"
+ self._BUTTONS.add_buttons ("Лёгкий", "Средний", "Высокий", "Очень высокий", "Рандом", hide_all = False)
+ self._BUTTONS.add_buttons ("Повторить", "На главное меню", "Пока", hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+
+ def _wish_to_see_solve(self):
+ if self._has_one_word_in_text_in_lower ("да", "ага", "давай", "поехали", "ес", "погнали", "говори", "гони"):
+ self._OUTPUT_TEXT = "Итак, решение: " + self._SESSIONAL_DATA["solve_of_task"] + "\nХотите ещё задачу? Тогда просто назовите желаемую сложность."
+ self._SESSIONAL_DATA["state"] = "working_with_tasks"
+ self._BUTTONS.add_buttons ("Лёгкий", "Средний", "Высокий", "Очень высокий", "Рандом", hide_all = False)
+ self._BUTTONS.add_buttons ("Повторить", "На главное меню", "Пока", hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+
+ def _user_has_not_listened_to_any_lesson (self) -> None:
+ self._OUTPUT_TEXT = "Вы ещё не прошли ни одного урока.\n"
+ self._OUTPUT_TEXT += "Скажите: \"Покажи список тем\", чтобы начать изучать курс."
+ self._BUTTONS.add_buttons ("Покажи список тем", "Повтори", "На главное меню", "Выход", hide_all = True)
+
+
+ def _choosing_course_theme (self) -> None:
+ if self._has_one_word_in_text_in_lower ("1", "введение"):
+ self._start_next_lesson_and_sublesson (1)
+
+ elif self._has_one_word_in_text_in_lower ("2", "устанока"):
+ self._start_next_lesson_and_sublesson (2)
+
+ elif self._has_one_word_in_text_in_lower ("3", "основы"):
+ self._start_next_lesson_and_sublesson (3)
+
+ elif self._has_one_word_in_text_in_lower ("4", "операторы", "выражения"):
+ self._start_next_lesson_and_sublesson (4)
+
+ elif self._has_one_word_in_text_in_lower ("5"):
+ self._start_next_lesson_and_sublesson (5)
+
+ elif self._has_one_word_in_text_in_lower ("6"):
+ self._start_next_lesson_and_sublesson (6)
+
+ elif self._has_one_word_in_text_in_lower ("7"):
+ self._start_next_lesson_and_sublesson (7)
+
+ elif self._has_one_word_in_text_in_lower ("8"):
+ self._start_next_lesson_and_sublesson (8)
+
+ elif self._has_one_word_in_text_in_lower ("9"):
+ self._start_next_lesson_and_sublesson (9)
+
+ elif self._has_one_word_in_text_in_lower ("10"):
+ self._start_next_lesson_and_sublesson (10)
+
+ elif self._has_one_word_in_text_in_lower ("назад", "обратно"):
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._OUTPUT_TEXT = "Вы находитесь в меню Курса.\n"
+ self._OUTPUT_TEXT += "Здесь вы можете посмотреть список тем и выбрать любую,\n"
+ self._OUTPUT_TEXT += "можете продолжить последнюю или переслушать текущую."
+ self._BUTTONS.add_buttons (*self._commands_of_course, hide_all = False)
+ self._BUTTONS.add_buttons ("Покажи список тем", "Повтори", "На главное меню", "Выход", hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+ def _start_next_lesson_and_sublesson (self, theme_number: Literal[1, 2, 3, 4, 5]) -> None:
+ lesson_getter = LessonGetter ( )
+ theme_number = theme_number - 1 # Первый урок под номером 0, а не 1
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._INTERSESSIONAL_DATA["current_lesson"] = (name_of_current_theme := lesson_getter.themes[theme_number]) # Морожовый, он самый)
+ self._INTERSESSIONAL_DATA["current_sublesson"] = (name_of_current_subtheme := lesson_getter.get_first_subtheme_name (name_of_current_theme))
+ self._OUTPUT_TEXT = random.choice (("Хорошо, ", "Отлично, ", "Прекрасно, ")) + "тогда начнём?" + "\n\n"
+ self._OUTPUT_TEXT += "Предисловие первого занятия:\n"
+ self._OUTPUT_TEXT += lesson_getter.get_subtheme_text (theme = name_of_current_theme,
+ subtheme = name_of_current_subtheme)
+ self._TEXT_TO_SPEECH = self._OUTPUT_TEXT
+ self._BUTTONS.add_buttons ("Далее", "Переслушать", "На главное меню", "Пока", hide_all = True)
+
+
+ def _start_next_lesson_or_not (self) -> None:
+ old_lesson_theme = self._INTERSESSIONAL_DATA["current_lesson"]
+ lesson_getter = LessonGetter ( )
+ next_lesson_theme = lesson_getter.get_name_of_next_theme (old_lesson_theme)
+ first_lesson_subtheme = lesson_getter.get_first_subtheme_name (next_lesson_theme)
+ self._INTERSESSIONAL_DATA["current_lesson"] = next_lesson_theme
+ self._INTERSESSIONAL_DATA["current_sublesson"] = first_lesson_subtheme
+
+ if self._has_one_word_in_text_in_lower ("да", "конечно", "дальше", "далее"):
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._OUTPUT_TEXT = lesson_getter.get_subtheme_text (theme = next_lesson_theme,
+ subtheme = first_lesson_subtheme)
+ self._BUTTONS.add_buttons ("Далее", "Переслушать", "На главное меню", "Пока", hide_all = True)
+
+ elif self._has_one_word_in_text_in_lower ("не", "нет", "позже", "потом"):
+ self._SESSIONAL_DATA["state"] = "working_with_course"
+ self._OUTPUT_TEXT = "Как хотите. В любой момент просто скажите: \"Продолжить последний урок\"."
+ self._BUTTONS.add_buttons (*self._commands_of_course, hide_all = False)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("Да, хочу!", "Нет, позже.", hide_all = True)
+
+
+ def _working_with_tasks (self) -> None:
+ if self._has_one_word_in_text_in_lower (
+ "лёгкий", "лёгкого", "лёгкому", "лёгким", "лёгком",
+ "легкий", "легкого", "легкому", "легким", "легком"):
+ self._SESSIONAL_DATA["difficulty_level_of_task"] = DifficultyLevels.EASY.value
+ self._SESSIONAL_DATA["state"] = "choosing_between_solve_and_code"
+ self._save_text_and_solve_of_easy_task_in_session_data()
+ a = ['Хорошо', 'Итак', "Отлично", "Так-с", "Ага", "Замечательно", "Супер"]
+ self._OUTPUT_TEXT = random.choice(a)+", давайте приступим. Задача называется \""+self._SESSIONAL_DATA["title_of_task"]+"\".\nЧитаю условие: \""+self._SESSIONAL_DATA["text_of_task"]+"\"\nПопробуйте решить сами.\nЕсли захотите услышать решение или код, просто скажите мне \"Решение\" или \"Код\"."
+ self._BUTTONS.add_buttons ("Устное решение", "Код", "Повтори", "На главное меню", "Пока", hide_all = True)
+
+
+ elif self._has_one_word_in_text_in_lower (
+ "средний", "среднего", "среднему", "среднем",
+ "средняя", "средней", "среднюю"):
+ self._SESSIONAL_DATA["difficulty_level_of_task"] = DifficultyLevels.MEDIUM.value
+ self._SESSIONAL_DATA["state"] = "choosing_between_solve_and_code"
+ self._save_text_and_solve_of_medium_task_in_session_data()
+ a = ['Хорошо', 'Итак', "Отлично", "Так-с", "Ага", "Замечательно", "Супер"]
+ self._OUTPUT_TEXT = random.choice(a)+", давайте приступим. Задача называется \""+self._SESSIONAL_DATA["title_of_task"]+"\".\nЧитаю условие: \""+self._SESSIONAL_DATA["text_of_task"]+"\"\nПопробуйте решить сами.\nЕсли захотите услышать решение или код, просто скажите мне \"Решение\" или \"Код\"."
+ self._BUTTONS.add_buttons ("Устное решение", "Код", "Повтори", "На главное меню", "Пока", hide_all = True)
+
+
+ elif self._has_one_word_in_text_in_lower (
+ "высокий", "высокого", "высокому", "высоким", "высоком",
+ "сложный", "сложного", "сложному", "сложным", "сложном"):
+ self._SESSIONAL_DATA["difficulty_level_of_task"] = DifficultyLevels.HARD.value
+ self._SESSIONAL_DATA["state"] = "choosing_between_solve_and_code"
+ self._save_text_and_solve_of_hard_task_in_session_data()
+ a = ['Хорошо', 'Итак', "Отлично", "Так-с", "Ага", "Замечательно", "Супер"]
+ self._OUTPUT_TEXT = random.choice(a)+", давайте приступим. Задача называется \""+self._SESSIONAL_DATA["title_of_task"]+"\".\nЧитаю условие: \""+self._SESSIONAL_DATA["text_of_task"]+"\"\nПопробуйте решить сами.\nЕсли захотите услышать решение или код, просто скажите мне \"Решение\" или \"Код\"."
+ self._BUTTONS.add_buttons ("Устное решение", "Код", "Повтори", "На главное меню", "Пока", hide_all = True)
+
+
+ elif self._has_one_word_in_text_in_lower (
+ "случайный", "случайного", "случайному", "случайным", "случайном",
+ "случайная", "случайной", "случайную",
+ "рандом", "рандома", "рандому", "рандомом", "рандоме",
+ "рандомный", "рандомного", "рандомному", "рандомном",
+ "рандомная", "рандомной", "рандомную"):
+ self._SESSIONAL_DATA["difficulty_level_of_task"] = DifficultyLevels.get_random_difficulty_level_for_task ( )
+ self._SESSIONAL_DATA["state"] = "choosing_between_solve_and_code"
+ self._save_text_and_solve_of_random_task_in_session_data()
+ a = ['Хорошо', 'Итак', "Отлично", "Так-с", "Ага", "Замечательно", "Супер"]
+ self._OUTPUT_TEXT = random.choice(a)+", давайте приступим. Задача называется \""+self._SESSIONAL_DATA["title_of_task"]+"\".\nЧитаю условие: \""+self._SESSIONAL_DATA["text_of_task"]+"\"\nПопробуйте решить сами.\nЕсли захотите услышать решение или код, просто скажите мне \"Решение\" или \"Код\"."
+ self._BUTTONS.add_buttons ("Устное решение", "Код", "Повтори", "На главное меню", "Пока", hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_needs_help:
+ self._OUTPUT_TEXT = "Всё будет хорошо! Здесь вам нужно всего лишь выбрать уровень сложности: лёгкий, средний или высокий.\n"
+ self._OUTPUT_TEXT += "Также вы можете в любой момент переслушать задачу или выйти на главное меню."
+ self._BUTTONS.add_buttons (*self._difficulty_levels, "На главное меню", hide_all = False)
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+ def _save_text_and_solve_of_random_task_in_session_data(self):
+ task_getter = TaskGetter ( )
+ task = task_getter.get_random_task ( )
+ self._SESSIONAL_DATA["title_of_task"] = task["title"]
+ self._SESSIONAL_DATA["text_of_task"] = task["task_text"]
+ self._SESSIONAL_DATA["solve_of_task"] = task["solve"]
+ self._SESSIONAL_DATA["code_of_task"] = task["code"]
+
+ def _choosing_right_answer_for_task (self) -> None:
+ # FIXME
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+
+
+ def _working_with_quest (self) -> None:
+ if self._has_one_word_in_text_in_lower (
+ "лёгкий", "лёгкого", "лёгкому", "лёгким", "лёгком",
+ "легкий", "легкого", "легкому", "легким", "легком"):
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = DifficultyLevels.EASY.value
+ self._save_text_and_correct_answer_of_easy_quest_in_session_data ( )
+ self._show_quest ( )
+
+ elif self._has_one_word_in_text_in_lower (
+ "средний", "среднего", "среднему", "среднем",
+ "средняя", "средней", "среднюю"):
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = DifficultyLevels.MEDIUM.value
+ self._save_text_and_correct_answer_of_medium_quest_in_session_data ( )
+ self._show_quest ( )
+
+ elif self._has_one_word_in_text_in_lower (
+ "высокий", "высокого", "высокому", "высоким", "высоком",
+ "сложный", "сложного", "сложному", "сложным", "сложном"):
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = DifficultyLevels.HARD.value
+ self._save_text_and_correct_answer_of_hard_quest_in_session_data ( )
+ self._show_quest ( )
+
+ elif self._has_one_word_in_text_in_lower (
+ "случайный", "случайного", "случайному", "случайным", "случайном",
+ "случайная", "случайной", "случайную",
+ "рандом", "рандома", "рандому", "рандомом", "рандоме",
+ "рандомный", "рандомного", "рандомному", "рандомном",
+ "рандомная", "рандомной", "рандомную"):
+ difficulty_level = DifficultyLevels.get_random_difficulty_level_for_quest ( )
+ self._SESSIONAL_DATA["difficulty_level_of_quest"] = difficulty_level
+ self._save_text_and_correct_answer_of_quest_in_session_data (difficulty_level)
+ self._show_quest ( )
+
+ elif self._has_one_word_in_text_in_lower ("результат", "результаты"):
+ self._show_results_of_quest_and_next_quest ( )
+
+ elif self._user_needs_help:
+ self._OUTPUT_TEXT = "Не волнуйтесь! Здесь вы должны всего лишь выбрать уровень сложности: лёгкий, средний, высокий.\n"
+ self._OUTPUT_TEXT += "Также вы можете узнать свои результаты, сказав: \"Покажи результаты\", или "
+ self._OUTPUT_TEXT += "перейти на главное меню, сказав: \"На главное меню\"."
+ self._BUTTONS.add_buttons (*self._difficulty_levels, "Покажи результаты", "На главное меню", hide_all = False)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_difficutly_level, hide_all = True)
+
+ @property
+ def _buttons_for_choosing_difficutly_level (self) -> dict:
+ return "Лёгкий", "Средний", "Высокий", "Случайный", "Узнать мои результаты", "На главное меню", "Пока!"
+
+ def _save_text_and_correct_answer_of_easy_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_easy_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_easy_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_easy_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_easy_quest_as_str
+
+ def _save_text_and_correct_answer_of_medium_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_medium_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_medium_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_medium_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_medium_quest_as_str
+
+ def _save_text_and_correct_answer_of_hard_quest_in_session_data (self) -> None:
+ quest_getter = QuestGetter ( )
+ quest_getter.save_random_hard_quest ( )
+ self._SESSIONAL_DATA["text_of_quest"] = quest_getter.prepared_text_of_random_hard_quest
+ self._SESSIONAL_DATA["correct_answer_of_quest"] = quest_getter.correct_answer_of_random_hard_quest
+ #self._TEXT_TO_SPEECH = quest_getter.answers_to_speech_of_random_hard_quest_as_str
+
+ def _save_text_and_solve_of_easy_task_in_session_data (self) -> None:
+ task_getter = TaskGetter ( )
+ task = task_getter.get_random_easy_task ( )
+ self._SESSIONAL_DATA["title_of_task"] = task["title"]
+ self._SESSIONAL_DATA["text_of_task"] = task["task_text"]
+ self._SESSIONAL_DATA["solve_of_task"] = task["solve"]
+ self._SESSIONAL_DATA["code_of_task"] = task["code"]
+
+ def _save_text_and_solve_of_medium_task_in_session_data (self) -> None:
+ task_getter = TaskGetter ( )
+ task = task_getter.get_random_medium_task ( )
+ self._SESSIONAL_DATA["title_of_task"] = task["title"]
+ self._SESSIONAL_DATA["text_of_task"] = task["task_text"]
+ self._SESSIONAL_DATA["solve_of_task"] = task["solve"]
+ self._SESSIONAL_DATA["code_of_task"] = task["code"]
+
+ def _save_text_and_solve_of_hard_task_in_session_data (self) -> None:
+ task_getter = TaskGetter ( )
+ task = task_getter.get_random_hard_task ( )
+ self._SESSIONAL_DATA["title_of_task"] = task["title"]
+ self._SESSIONAL_DATA["text_of_task"] = task["task_text"]
+ self._SESSIONAL_DATA["solve_of_task"] = task["solve"]
+ self._SESSIONAL_DATA["code_of_task"] = task["code"]
+
+ def _save_text_and_solve_of_task_of_very_hard_task_in_session_data (self) -> None:
+ task_getter = TaskGetter ( )
+ task = task_getter.get_random_very_hard_task ( )
+ self._SESSIONAL_DATA["title_of_task"] = task["title"]
+ self._SESSIONAL_DATA["text_of_task"] = task["task_text"]
+ self._SESSIONAL_DATA["solve_of_task"] = task["solve"]
+ self._SESSIONAL_DATA["code_of_task"] = task["code"]
+
+ def _save_text_and_correct_answer_of_quest_in_session_data (self, difficulty_level: int) -> None:
+ match difficulty_level:
+ case DifficultyLevels.EASY.value:
+ self._save_text_and_correct_answer_of_easy_quest_in_session_data ( )
+ case DifficultyLevels.MEDIUM.value:
+ self._save_text_and_correct_answer_of_medium_quest_in_session_data ( )
+ case DifficultyLevels.HARD.value:
+ self._save_text_and_correct_answer_of_hard_quest_in_session_data ( )
+ case _:
+ raise ValueError ("Указан неправильный уровень сложности!")
+
+
+ def _get_text_of_current_quest (self) -> str:
+ return self._SESSIONAL_DATA["text_of_quest"]
+
+ @property
+ def _buttons_for_choosing_correct_answer (self) -> dict:
+ return "Первое", "Второе", "Третье", "Изменить уровень сложности", "Узнать мои результаты", "На главное меню", "Пока!"
+
+ def _show_quest (self) -> None:
+ self._SESSIONAL_DATA["state"] = "choosing_right_answer_for_quest"
+ self._OUTPUT_TEXT = random.choice (("Хорошо.", "Отлично.", "Прекрасно.")) + "\n\n"
+ self._say_that_user_can_change_their_difficulty_level_of_quest_if_it_is_not_said_yet ( )
+ self._OUTPUT_TEXT += self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ def _say_that_user_can_change_their_difficulty_level_of_quest_if_it_is_not_said_yet (self) -> None:
+ if not self._SESSIONAL_DATA["was_said_that_user_can_change_difficulty_level_in_quest"]:
+ text = [
+ "Вы можете узнать количество правильно отвеченных вопросов, сказав: \"Покажи результаты\".\n",
+ "Также вы можете сменить уровень сложности, сказав: \"Хочу сменить сложность\";\n",
+ "или выйти на главное меню, сказав: \"На главное меню\".\n",
+ "Вот квест.\n\n"
+ ]
+ self._OUTPUT_TEXT += "".join (text)
+ self._SESSIONAL_DATA["was_said_that_user_can_change_difficulty_level_in_quest"] = True
+
+
+ def _choosing_right_answer_for_quest (self) -> None:
+ if self._has_one_word_in_text_in_lower ("1", "один", "первый", "первое"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 1:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_one_word_in_text_in_lower ("2", "два", "второй", "второе"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 2:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_one_word_in_text_in_lower ("3", "три", "третий", "третье"):
+ if self._SESSIONAL_DATA["correct_answer_of_quest"] == 3:
+ self._correct_answer_of_quest_is_selected ( )
+ else:
+ self._wrong_answer_of_quest_is_selected ( )
+
+ elif self._has_all_words_in_text_in_lower ("уровень", "сложности") or \
+ self._has_one_word_in_text_in_lower ("сложность"):
+ self._SESSIONAL_DATA["state"] = "working_with_quest"
+ self._OUTPUT_TEXT = random.choice (("Хорошо.", "Отлично.")) + "\n"
+ self._OUTPUT_TEXT += "Теперь просто скажите нужный уровень сложности."
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_difficutly_level, hide_all = False)
+
+ elif self._has_one_word_in_text_in_lower ("результат", "результаты"):
+ self._show_results_of_quest_and_next_quest ( )
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_text_that_says_there_is_no_answer_like_that ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ def _correct_answer_of_quest_is_selected (self) -> None:
+ text_that_says_answer_is_correct = get_text_that_says_answer_is_correct ( ) + "\n\n"
+ self._OUTPUT_TEXT = text_that_says_answer_is_correct
+ self._TEXT_TO_SPEECH = get_random_win_sound ( ) + text_that_says_answer_is_correct
+ current_difficulty_level = self._SESSIONAL_DATA["difficulty_level_of_quest"]
+ self._save_text_and_correct_answer_of_quest_in_session_data (current_difficulty_level)
+ text_of_current_quest = self._get_text_of_current_quest ( )
+ self._OUTPUT_TEXT += text_of_current_quest
+ self._TEXT_TO_SPEECH += text_of_current_quest
+ self._CARD = make_big_win_picture (text_that_says_answer_is_correct, text_of_current_quest)
+ self._SESSIONAL_DATA["number_of_correct_quest_answers"] += 1
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ def _show_results_of_quest_and_next_quest (self) -> None:
+ correct_quest_answers = int (self._SESSIONAL_DATA["number_of_correct_quest_answers"])
+ wrong_quest_answers = int (self._SESSIONAL_DATA["number_of_wrong_quest_answers"])
+ if correct_quest_answers and wrong_quest_answers:
+ self._OUTPUT_TEXT = f"Количество правильных ответов: {correct_quest_answers}.\n"
+ self._OUTPUT_TEXT += f"Количество неправильных ответов: {wrong_quest_answers}.\n"
+ python_knowledge = calculate_python_knowledge (correct_quest_answers, wrong_quest_answers)
+ self._OUTPUT_TEXT += f"Ваше знание Python: {python_knowledge}%."
+ self._SESSIONAL_DATA["state"] = "viewing_quest_results"
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ elif not correct_quest_answers and wrong_quest_answers:
+ self._OUTPUT_TEXT = "Жаль, но у вас нет ни одного правильного ответа на квест."
+ self._SESSIONAL_DATA["state"] = "viewing_quest_results"
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ elif correct_quest_answers and not wrong_quest_answers:
+ self._OUTPUT_TEXT = "Все ваши ответы верны! Похоже, вы профессиональный программист!"
+ self._SESSIONAL_DATA["state"] = "viewing_quest_results"
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+ else:
+ self._OUTPUT_TEXT = "Пока вы не ответили ни на один квест.\nСкажите уровень сложности (лёгкий, средний, высокий или случайный), чтобы проверить ваши знания."
+ self._BUTTONS.add_buttons (*self._difficulty_levels, hide_all = False)
+
+ self._CARD = make_big_looking_results_picture ("Результаты", self._OUTPUT_TEXT)
+ self._TEXT_TO_SPEECH = get_random_sound_of_looking_results ( ) + self._OUTPUT_TEXT
+
+
+ def _wrong_answer_of_quest_is_selected (self) -> None:
+ self._OUTPUT_TEXT = get_text_that_says_answer_is_wrong ( )
+ self._TEXT_TO_SPEECH = get_random_lose_sound ( ) + self._OUTPUT_TEXT
+ self._SESSIONAL_DATA["number_of_wrong_quest_answers"] += 1
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+
+ def _viewing_quest_results (self) -> None:
+ if self._has_one_word_in_text_in_lower ("продолжить"):
+ self._SESSIONAL_DATA["state"] = "choosing_right_answer_for_quest"
+ current_difficulty_level = self._SESSIONAL_DATA["difficulty_level_of_quest"]
+ self._save_text_and_correct_answer_of_quest_in_session_data (current_difficulty_level)
+ self._OUTPUT_TEXT = self._get_text_of_current_quest ( )
+ self._BUTTONS.add_buttons (*self._buttons_for_choosing_correct_answer, hide_all = True)
+
+ elif self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+ self._BUTTONS.add_buttons ("Продолжить квест", "На главное меню", "Пока", hide_all = True)
+
+
+ def _sending_report (self) -> None:
+ # Доработать # FIXME
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+ if self._user_wants_to_go_to_main_menu:
+ self._go_to_main_menu ( )
+ elif self._user_wants_to_hear_last_phrase:
+ self._say_last_phrase ( )
+ elif self._user_wants_to_end_session:
+ self._end_the_session ( )
+ else:
+ self._OUTPUT_TEXT = get_apology_text ( )
+
+
+ def _consulting (self) -> None:
+ ai = ArtificialIntelligence("lessons.json")
+ self._BUTTONS.add_buttons ("На главное меню", "Пока!", hide_all = True)
+ a = ["Хм...", "Ага...", "Итак,", "Хорошо,", "Смотрите,"]
+ outpt = ai.get_similarity(" ".join(self._WORDS_OF_TEXT_IN_LOWER))
+ if outpt[1] != 0:
+ self._OUTPUT_TEXT = random.choice(a)+" я нашла что-то, что может вам помочь, послушайте: " + outpt[0] + "\nКуда теперь?"
+ else:
+ self._OUTPUT_TEXT = "Извините, я ничего не смогла найти по вашему запросу.\nКуда теперь?"
+ self._SESSIONAL_DATA['state'] = "in_main_menu"
+
+
+ def _has_all_words_in_text_in_lower (self, *words) -> bool:
+ """Есть ли все слова в ответе пользователя?"""
+ for word in words:
+ if not word in self._WORDS_OF_TEXT_IN_LOWER:
+ return False
+ return True
+
+ def _has_one_word_in_text_in_lower (self, *words) -> bool:
+ """Есть ли хоть одно слово в ответе пользователя?"""
+ for word in words:
+ if word in self._WORDS_OF_TEXT_IN_LOWER:
+ return True
+ return False
+
+
+ def _go_to_main_menu (self) -> None:
+ self._OUTPUT_TEXT = get_text_that_says_user_is_just_in_main_menu ( )
+ self._TEXT_TO_SPEECH = get_text_that_says_user_is_just_in_main_menu ( )
+ self._TEXT_TO_SPEECH += get_main_commands_of_skill ( )
+ self._SESSIONAL_DATA["state"] = "in_main_menu"
+ self._BUTTONS.add_buttons_of_main_menu_in_text ( )
+
+
+ def _end_the_session (self) -> None:
+ farewell_text = get_farewell_text ( )
+ self._CARD = make_big_farewell_picture (farewell_text)
+ self._OUTPUT_TEXT = farewell_text # Без этого выдаёт ошибку, что self._OUTPUT_TEXT нет
+ self._TEXT_TO_SPEECH = farewell_text
+ self._IS_END_SESSION = True
+
+
+ def get_response (self) -> dict:
+ if self._CARD:
+ return {
+ "version": self._VERSION,
+ "response": {
+ "text": self._OUTPUT_TEXT,
+ "tts": self._TEXT_TO_SPEECH,
+ "end_session": self._IS_END_SESSION,
+ "buttons": self._BUTTONS.BUTTONS,
+ "card": self._CARD},
+ "session_state": self._SESSIONAL_DATA,
+ "user_state_update": self._INTERSESSIONAL_DATA
+ }
+ else:
+ return {
+ "version": self._VERSION,
+ "response": {
+ "text": self._OUTPUT_TEXT,
+ "tts": self._TEXT_TO_SPEECH,
+ "end_session": self._IS_END_SESSION,
+ "buttons": self._BUTTONS.BUTTONS},
+ "session_state": self._SESSIONAL_DATA,
+ "user_state_update": self._INTERSESSIONAL_DATA
+ }
+ # Даже если self._TEXT_TO_SPEECH ничего не содержит (""),
+ # то будет сказан текст, который написан в поле ["response"]["text"]
+
+
+
+# Функция, вызываемая Яндексом для запуска скрипта Алисы (в коде вызывать её не нужно).
+def main (request_from_alisa: dict, context) -> dict:
+ handler_of_alisa = HandlerOfAlisa (request_from_alisa)
+ return handler_of_alisa.get_response ( )
\ No newline at end of file
diff --git a/quest_getter.py b/quest_getter.py
new file mode 100644
index 0000000..6c10232
--- /dev/null
+++ b/quest_getter.py
@@ -0,0 +1,145 @@
+import json
+import random
+
+from typing import Literal
+from enums import DifficultyLevels
+
+
+class QuestGetter:
+ """Создаётся экземпляр класса, затем вызывается метод,
+ сохраняющий один случайный квест указанной сложности.
+ Затем можно получить подготовленный текст сохраннённого
+ квеста и правильный ответ на него."""
+ def __init__ (self):
+ self._load_all_quests_from_file ( )
+ self._group_quests ( )
+
+ def _load_all_quests_from_file (self) -> None:
+ with open (self._name_of_file_with_quests, "r") as file:
+ self.all_quests: dict = json.load (file)
+
+ @property
+ def _name_of_file_with_quests (self) -> str:
+ return "quests.json"
+
+ def _group_quests (self) -> None:
+ self._create_empty_grouped_quests ( )
+ for key in self.all_quests.keys():
+ match self.all_quests[key]["difficulty_level"]:
+ case DifficultyLevels.EASY.value:
+ self.easy_quests.append (self.all_quests[key])
+ case DifficultyLevels.MEDIUM.value:
+ self.medium_quests.append (self.all_quests[key])
+ case DifficultyLevels.HARD.value:
+ self.hard_quests.append (self.all_quests[key])
+ case _:
+ raise ValueError ("Указан неверный уровень сложности " +
+ f"в файле {self._name_of_file_with_quests}\n." +
+ f"Номер неправильного квеста: {key}.")
+
+ def _create_empty_grouped_quests (self) -> None:
+ self.easy_quests = [ ]
+ self.medium_quests = [ ]
+ self.hard_quests = [ ]
+
+
+ def save_random_easy_quest (self) -> None:
+ self.saved_random_easy_quest = random.choice (self.easy_quests)
+
+ def save_random_medium_quest (self) -> None:
+ self.saved_random_medium_quest = random.choice (self.medium_quests)
+
+ def save_random_hard_quest (self) -> None:
+ self.saved_random_hard_quest = random.choice (self.hard_quests)
+
+
+ def get_random_easy_quest (self) -> None:
+ return random.choice (self.easy_quests)
+
+ def get_random_medium_quest (self) -> None:
+ return random.choice (self.medium_quests)
+
+ def get_random_hard_quest (self) -> None:
+ return random.choice (self.hard_quests)
+
+
+ @property
+ def text_of_random_easy_quest (self) -> str:
+ return self.saved_random_easy_quest["quest_text"]
+
+ @property
+ def prepared_text_of_random_easy_quest (self) -> str:
+ return self._get_prepared_quest_text_for_user (self.saved_random_easy_quest)
+
+ @property
+ def correct_answer_of_random_easy_quest (self) -> Literal[1, 2, 3]:
+ return self.saved_random_easy_quest["correct_answer"] + 1 # В файле первый ответ 0, а не 1
+
+ @property
+ def answers_of_random_easy_quest_as_str (self) -> list[str]:
+ return "\n".join (self.saved_random_easy_quest["answers"] )
+
+ @property
+ def answers_to_speech_of_random_easy_quest (self) -> list[str]:
+ return self.saved_random_easy_quest["answers_to_speech"]
+
+ @property
+ def answers_to_speech_of_random_easy_quest_as_str (self) -> str:
+ return " ".join (self.answers_to_speech_of_random_easy_quest)
+
+ @property
+ def text_of_random_medium_quest (self) -> str:
+ return self.saved_random_medium_quest["quest_text"]
+
+ @property
+ def prepared_text_of_random_medium_quest (self) -> str:
+ return self._get_prepared_quest_text_for_user (self.saved_random_medium_quest)
+
+ @property
+ def correct_answer_of_random_medium_quest (self) -> Literal[1, 2, 3]:
+ return self.saved_random_medium_quest["correct_answer"] + 1 # В файле первый ответ 0, а не 1
+
+ @property
+ def answers_of_random_medium_quest_as_str (self) -> list[str]:
+ return "\n".join (self.saved_random_medium_quest["answers"] )
+
+ @property
+ def answers_to_speech_of_random_medium_quest (self) -> list[str]:
+ return self.saved_random_medium_quest["answers_to_speech"]
+
+ @property
+ def answers_to_speech_of_random_medium_quest_as_str (self) -> str:
+ return " ".join (self.answers_to_speech_of_random_medium_quest)
+
+ @property
+ def text_of_random_hard_quest (self) -> str:
+ return self.saved_random_hard_quest["quest_text"]
+
+ @property
+ def prepared_text_of_random_hard_quest (self) -> str:
+ return self._get_prepared_quest_text_for_user (self.saved_random_hard_quest)
+
+ @property
+ def correct_answer_of_random_hard_quest (self) -> Literal[1, 2, 3]:
+ return self.saved_random_hard_quest["correct_answer"] + 1 # В файле первый ответ 0, а не 1
+
+ @property
+ def answers_of_random_hard_quest_as_str (self) -> list[str]:
+ return "\n".join (self.saved_random_hard_quest["answers"] )
+
+ @property
+ def answers_to_speech_of_random_hard_quest (self) -> list[str]:
+ return self.saved_random_hard_quest["answers_to_speech"]
+
+ @property
+ def answers_to_speech_of_random_hard_quest_as_str (self) -> str:
+ return " ".join (self.answers_to_speech_of_random_hard_quest)
+
+
+ def _get_prepared_quest_text_for_user (self, quest: dict) -> str:
+ prepared_quest_text = quest["quest_text"] + "\n"
+ answer_number = 1
+ for answer in quest["answers"]:
+ prepared_quest_text += f"{answer_number}) {answer}\n"
+ answer_number += 1
+ return prepared_quest_text
\ No newline at end of file
diff --git a/quests.json b/quests.json
new file mode 100644
index 0000000..c76c755
--- /dev/null
+++ b/quests.json
@@ -0,0 +1,641 @@
+{
+ "1": {
+ "quest_text": "Какая команда в Python используется для вывода текста на экран?",
+ "answers": [
+ "input()",
+ "print()",
+ "int()"
+ ],
+ "answers_to_speech": [
+ "инпут",
+ "принт",
+ "инт"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 1
+ },
+
+ "2": {
+ "quest_text": "Какая функция Python используется для чтения пользовательского ввода с клавиатуры?",
+ "answers": [
+ "input()",
+ "read()",
+ "get_input()"
+ ],
+ "answers_to_speech": [
+ "инпут",
+ "рид",
+ "гет инпут"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 0
+ },
+
+ "3": {
+ "quest_text": "Какая из этих операций увеличивает значение переменной на 1?",
+ "answers": [
+ "x = x - 1",
+ "x = x * 2",
+ "x = x + 1"
+ ],
+ "answers_to_speech": [
+ "икс равно икс минус один",
+ "икс равно икс умножить на два",
+ "икс равно икс плюс один"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 2
+ },
+
+ "4": {
+ "quest_text": " Какой оператор используется для присвоения значения переменной в Python?",
+ "answers": [
+ ":=",
+ "=",
+ "=="
+ ],
+ "answers_to_speech": [
+ "двоеточие равно",
+ "равно",
+ "равно равно"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 1
+ },
+
+ "5": {
+ "quest_text": "Какой оператор в Python используется для проверки равенства значений?",
+ "answers": [
+ ":=",
+ "!=",
+ "=="
+ ],
+ "answers_to_speech": [
+ "двоеточие равно",
+ "восклицательный знак равно",
+ "равно равно"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 2
+ },
+
+ "6": {
+ "quest_text": "Какой оператор используется для осуществления логического НЕ в Python?",
+ "answers": [
+ "!",
+ "%",
+ "not"
+ ],
+ "answers_to_speech": [
+ "восклицательный знак",
+ "процент",
+ "нот"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 2
+ },
+
+ "7": {
+ "quest_text": "Какие ключевые слова в Python используются для определения условных операторов?",
+ "answers": [
+ "if и else",
+ "while и for",
+ "try и except"
+ ],
+ "answers_to_speech": [
+ "иф и эльс",
+ "вайл и фор",
+ "трай и эксэпт"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 0
+ },
+
+ "8": {
+ "quest_text": "Как создать цикл for, который будет выполняться 10 раз?",
+ "answers": [
+ "for i in range(1, 10):",
+ "for i in range(10):",
+ "for i in range(1, 11):"
+ ],
+ "answers_to_speech": [
+ "фор ай ин рэндж один десять двоеточие",
+ "фор ай ин рэндж десять двоеточие",
+ "фор ай ин рэндж один одиннадцать двоеточие"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 1
+ },
+
+ "9": {
+ "quest_text": "Как создать пустой словарь в Python?",
+ "answers": [
+ "()",
+ "{}",
+ "[]"
+ ],
+ "answers_to_speech": [
+ "круглые скобки",
+ "фигурные кобки",
+ "квадратные скобки"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 1
+ },
+
+ "10": {
+ "quest_text": "Какой тип данных используется для хранения списка элементов?",
+ "answers": [
+ "list",
+ "bool",
+ "int"
+ ],
+ "answers_to_speech": [
+ "лист",
+ "бул",
+ "инт"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 0
+ },
+
+ "11": {
+ "quest_text": "Каким будет результат выполнения данного кода: items = [1, 2, 3, 4, 5] print(items[2])",
+ "answers": [
+ "1",
+ "2",
+ "3"
+ ],
+ "answers_to_speech": [
+ "один",
+ "два",
+ "три"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 2
+ },
+
+ "12": {
+ "quest_text": "Какая функция в Python используется для создания пустого списка?",
+ "answers": [
+ "list()",
+ "dict()",
+ "set()"
+ ],
+ "answers_to_speech": [
+ "лист",
+ "дикт",
+ "сэт"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 0
+ },
+
+ "13": {
+ "quest_text": "От какого родительского класса нужно наследовать дочерний, чтобы создать перечисление?",
+ "answers": [
+ "ABC",
+ "Exception",
+ "enum"
+ ],
+ "answers_to_speech": [
+ "эй би си",
+ "эксэпшен",
+ "энам"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 2
+ },
+
+ "14": {
+ "quest_text": "Что такое генераторы в Python?",
+ "answers": [
+ "Это функции, которые создают последовательность значений",
+ "Это объекты, которые создают последовательность значений",
+ "Это операторы, которые создают последовательность значений"
+ ],
+ "answers_to_speech": [
+ "это функции которые создают последовательность значений",
+ "это объекты которые создают последовательность значений",
+ "это операторы которые создают последовательность значений"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 1
+ },
+
+ "15": {
+ "quest_text": "С помощью какой функции можно узнать длину строки в Python?",
+ "answers": [
+ "length()",
+ "len()",
+ "size()"
+ ],
+ "answers_to_speech": [
+ "лэнгф",
+ "лэн",
+ "сайз"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 1
+ },
+
+ "16": {
+ "quest_text": "Какая функция используется для генерации случайного числа в Python?",
+ "answers": [
+ "random()",
+ "randint()",
+ "choice()"
+ ],
+ "answers_to_speech": [
+ "рэндом",
+ "рэндинт",
+ "чойз"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 1
+ },
+
+ "17": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с датами и временем?",
+ "answers": [
+ "datetime",
+ "time",
+ "calendar"
+ ],
+ "answers_to_speech": [
+ "дэйта тайм",
+ "тайм",
+ "кэленда"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 0
+ },
+
+ "18": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с базами данных?",
+ "answers": [
+ "sqlite",
+ "reportlab",
+ "scipy"
+ ],
+ "answers_to_speech": [
+ "скьюлайт",
+ "репорт лаб",
+ "сайпи"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 0
+ },
+
+ "19": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с графиками и диаграммами?",
+ "answers": [
+ "pandas",
+ "matplotlib",
+ "numpy"
+ ],
+ "answers_to_speech": [
+ "пэндас",
+ "матплотлиб",
+ "нампи"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 1
+ },
+
+ "20": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с научными расчетами и численными методами?",
+ "answers": [
+ "sympy",
+ "tensorflow",
+ "scipy"
+ ],
+ "answers_to_speech": [
+ "саймпи",
+ "тэнсо флоу",
+ "сайпи"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 2
+ },
+
+ "21": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с обработкой естественного языка?",
+ "answers": [
+ "Theano",
+ "PyTorch",
+ "gensim"
+ ],
+ "answers_to_speech": [
+ "фино",
+ "пай торч",
+ "генсим"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 2
+ },
+
+ "22": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с созданием PDF-файлов?",
+ "answers": [
+ "Keras",
+ "pdfkit",
+ "PyWin32"
+ ],
+ "answers_to_speech": [
+ "кэрас",
+ "пэ дэ эф кит",
+ "пай вин тридцать два"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 1
+ },
+
+ "23": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать со статистическим анализом данных?",
+ "answers": [
+ "Bokeh",
+ "numpy",
+ "statsmodels"
+ ],
+ "answers_to_speech": [
+ "бокех",
+ "нампи",
+ "статс модэлс"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 2
+ },
+
+ "24": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с машинным обучением и глубоким обучением?",
+ "answers": [
+ "tensorflow",
+ "Flask ",
+ "Plotly "
+ ],
+ "answers_to_speech": [
+ "тэнсо флоу",
+ "флэск",
+ "плотли"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 0
+ },
+
+ "25": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с RESTful API?",
+ "answers": [
+ "django",
+ "requests ",
+ "Scrapy"
+ ],
+ "answers_to_speech": [
+ "джэнго",
+ "реквестс",
+ "скрэпи"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 1
+ },
+
+ "26": {
+ "quest_text": "Какую библиотеку нужно использовать, чтобы работать с веб-скрапингом?",
+ "answers": [
+ "PyOpenGL",
+ "OpenCV",
+ "BeautifulSoup"
+ ],
+ "answers_to_speech": [
+ "пай оупэн джи эль",
+ "оупэн си ви",
+ "бьютифул соуп"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 2
+ },
+
+ "27": {
+ "quest_text": "Какое ключевое слово используется для создания функции в Python?",
+ "answers": [
+ "func",
+ "def",
+ "define"
+ ],
+ "answers_to_speech": [
+ "фанк",
+ "дэф",
+ "дэфайн"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 1
+ },
+
+ "28": {
+ "quest_text": "Какое ключевое слово используется для создания класса в Python?",
+ "answers": [
+ "class",
+ "def",
+ "define"
+ ],
+ "answers_to_speech": [
+ "клэс",
+ "дэф",
+ "дэфайн"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 0
+ },
+
+ "29": {
+ "quest_text": "Какое ключевое слово дает возможность пропустить часть цикла, где активируется внешнее условие?",
+ "answers": [
+ "continue",
+ "exit",
+ "break"
+ ],
+ "answers_to_speech": [
+ "континью",
+ "эксит",
+ "брэйк"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 0
+ },
+
+ "30": {
+ "quest_text": "Что такое списковое включение (list comprehension)?",
+ "answers": [
+ "Функция, возвращающая случайный элемент списка",
+ "Способ создания нового списка на основе старого с использованием условий и циклов",
+ "Метод для добавления элемента в список"
+ ],
+ "answers_to_speech": [
+ "Функция возвращающая случайный элемент списка",
+ "Способ создания нового списка на основе старого с использованием условий и циклов",
+ "Метод для добавления элемента в список"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 1
+ },
+
+ "31": {
+ "quest_text": "Что такое лямбда-функция?",
+ "answers": [
+ "Инструмент для чтения файлов",
+ "Функция без имени, которая может быть передана в другую функцию",
+ "Инструмент для работы с базами данных"
+ ],
+ "answers_to_speech": [
+ "Инструмент для чтения файлов",
+ "Функция без имени которая может быть передана в другую функцию",
+ "Инструмент для работы с базами данных"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 1
+ },
+
+ "32": {
+ "quest_text": "Что означает ключевое слово global?",
+ "answers": [
+ "Объявление переменной в глобальной области видимости",
+ "Объявление переменной в локальной области видимости",
+ "Объявление функции"
+ ],
+ "answers_to_speech": [
+ "Объявление переменной в глобальной области видимости",
+ "Объявление переменной в локальной области видимости",
+ "Объявление функции"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 0
+ },
+
+ "33": {
+ "quest_text": "Какой метод используется для перевода строки в нижний регистр?",
+ "answers": [
+ "to_lower()",
+ "lower()",
+ "casefold()"
+ ],
+ "answers_to_speech": [
+ "ту ловэр",
+ "ловэр",
+ "кейс фолд"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 1
+ },
+
+ "34": {
+ "quest_text": "Что такое рекурсия?",
+ "answers": [
+ "Способ создания списка на основе другого списка",
+ "Цикл, повторяющийся до тех пор, пока не будет выполнено определенное условие",
+ "Функция, вызывающая саму себя"
+ ],
+ "answers_to_speech": [
+ "способ создания списка на основе другого списка",
+ "цикл повторяющийся до тех пор пока не будет выполнено определенное условие",
+ "функция вызывающая саму себя"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 2
+ },
+
+ "35": {
+ "quest_text": "Что такое словарь (dict) в Python?",
+ "answers": [
+ "Список, содержащий элементы разных типов данных",
+ "Массив фиксированной длины",
+ "Коллекция, содержащая пары ключ-значение"
+ ],
+ "answers_to_speech": [
+ "список содержащий элементы разных типов данных",
+ "массив фиксированной длины",
+ "коллекция содержащая пары ключ-значение"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 2
+ },
+
+ "36": {
+ "quest_text": "Что такое генератор (generator) в Python?",
+ "answers": [
+ "Функция, которая возвращает последовательность значений без генерации списка целиком",
+ "Функция, которая может быть вызвана с любым количеством аргументов",
+ "Функция, которая принимает список и возвращает новый список, содержащий только уникальные значения"
+ ],
+ "answers_to_speech": [
+ "функция которая возвращает последовательность значений без генерации списка целиком",
+ "функция которая может быть вызвана с любым количеством аргументов",
+ "функция которая принимает список и возвращает новый список, содержащий только уникальные значения"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 0
+ },
+
+ "37": {
+ "quest_text": "Какой модуль используется для работы с регулярными выражениями?",
+ "answers": [
+ "regex",
+ "re",
+ "reg"
+ ],
+ "answers_to_speech": [
+ "рэджэкс",
+ "рэ",
+ "рэг"
+ ],
+ "difficulty_level": 2,
+ "correct_answer": 1
+ },
+
+ "38": {
+ "quest_text": "Что означает ключевое слово pass?",
+ "answers": [
+ "Оператор, который не делает ничего",
+ "Оператор, который прерывает выполнение программы",
+ "Оператор, который возвращает значение из функции"
+ ],
+ "answers_to_speech": [
+ "Оператор который не делает ничего",
+ "Оператор который прерывает выполнение программы",
+ "Оператор который возвращает значение из функции"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 0
+ },
+
+ "39": {
+ "quest_text": "Какой метод используется для разделения строки на список по заданному разделителю?",
+ "answers": [
+ "join()",
+ "split()",
+ "separate()"
+ ],
+ "answers_to_speech": [
+ "джоин",
+ "сплит",
+ "сэпэрэйт"
+ ],
+ "difficulty_level": 1,
+ "correct_answer": 1
+ },
+
+ "40": {
+ "quest_text": "Какое ключевое слово используется для импорта модуля в Python?",
+ "answers": [
+ "include",
+ "require",
+ "import"
+ ],
+ "answers_to_speech": [
+ "инклюд",
+ "рекваир",
+ "импорт"
+ ],
+ "difficulty_level": 0,
+ "correct_answer": 2
+ }
+}
\ No newline at end of file
diff --git a/sounds/entering/entering.mp3 b/sounds/entering/entering.mp3
new file mode 100644
index 0000000..4e3dc3a
Binary files /dev/null and b/sounds/entering/entering.mp3 differ
diff --git "a/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/1_wrong_quests.mp3" "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/1_wrong_quests.mp3"
new file mode 100644
index 0000000..b195e06
Binary files /dev/null and "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/1_wrong_quests.mp3" differ
diff --git "a/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/2_wrong_quests.mp3" "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/2_wrong_quests.mp3"
new file mode 100644
index 0000000..62af755
Binary files /dev/null and "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/2_wrong_quests.mp3" differ
diff --git "a/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/3_wrong_quests.mp3" "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/3_wrong_quests.mp3"
new file mode 100644
index 0000000..e654d66
Binary files /dev/null and "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/3_wrong_quests.mp3" differ
diff --git "a/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/4_wrong_quests.mp3" "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/4_wrong_quests.mp3"
new file mode 100644
index 0000000..c9c6d66
Binary files /dev/null and "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/4_wrong_quests.mp3" differ
diff --git "a/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/5_wrong_quests.mp3" "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/5_wrong_quests.mp3"
new file mode 100644
index 0000000..0465fbc
Binary files /dev/null and "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/5_wrong_quests.mp3" differ
diff --git "a/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/6_wrong_quests.mp3" "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/6_wrong_quests.mp3"
new file mode 100644
index 0000000..9261fbf
Binary files /dev/null and "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/6_wrong_quests.mp3" differ
diff --git "a/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/7_wrong_quests.mp3" "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/7_wrong_quests.mp3"
new file mode 100644
index 0000000..56f2e98
Binary files /dev/null and "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/7_wrong_quests.mp3" differ
diff --git "a/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/8_wrong_quests.mp3" "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/8_wrong_quests.mp3"
new file mode 100644
index 0000000..0dfe555
Binary files /dev/null and "b/sounds/quests/\320\235\320\265\320\277\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/8_wrong_quests.mp3" differ
diff --git "a/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/1_right_quests.mp3" "b/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/1_right_quests.mp3"
new file mode 100644
index 0000000..946a429
Binary files /dev/null and "b/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/1_right_quests.mp3" differ
diff --git "a/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/2_right_quests.mp3" "b/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/2_right_quests.mp3"
new file mode 100644
index 0000000..77e3735
Binary files /dev/null and "b/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/2_right_quests.mp3" differ
diff --git "a/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/3_right_quests.mp3" "b/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/3_right_quests.mp3"
new file mode 100644
index 0000000..bfd33b7
Binary files /dev/null and "b/sounds/quests/\320\237\321\200\320\260\320\262\320\270\320\273\321\214\320\275\320\276/3_right_quests.mp3" differ
diff --git "a/sounds/quests/\320\243\320\267\320\275\320\260\321\202\321\214 \320\274\320\276\320\270 \321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\321\213/get_results.mp3" "b/sounds/quests/\320\243\320\267\320\275\320\260\321\202\321\214 \320\274\320\276\320\270 \321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\321\213/get_results.mp3"
new file mode 100644
index 0000000..e1114d9
Binary files /dev/null and "b/sounds/quests/\320\243\320\267\320\275\320\260\321\202\321\214 \320\274\320\276\320\270 \321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\321\213/get_results.mp3" differ
diff --git a/sounds/tasks/tasks_1.mp3 b/sounds/tasks/tasks_1.mp3
new file mode 100644
index 0000000..0e3c676
Binary files /dev/null and b/sounds/tasks/tasks_1.mp3 differ
diff --git a/sounds/tasks/tasks_2.mp3 b/sounds/tasks/tasks_2.mp3
new file mode 100644
index 0000000..c11b29a
Binary files /dev/null and b/sounds/tasks/tasks_2.mp3 differ
diff --git a/sounds/tasks/tasks_3.mp3 b/sounds/tasks/tasks_3.mp3
new file mode 100644
index 0000000..852cf1e
Binary files /dev/null and b/sounds/tasks/tasks_3.mp3 differ
diff --git a/sounds/tasks/tasks_4.mp3 b/sounds/tasks/tasks_4.mp3
new file mode 100644
index 0000000..8d628c4
Binary files /dev/null and b/sounds/tasks/tasks_4.mp3 differ
diff --git a/task_getter.py b/task_getter.py
new file mode 100644
index 0000000..0892e5c
--- /dev/null
+++ b/task_getter.py
@@ -0,0 +1,55 @@
+import json
+import random
+
+from enums import DifficultyLevels
+
+
+class TaskGetter:
+ def __init__ (self):
+ self._load_all_tasks_from_file ( )
+ self._create_groups ( )
+ self._group_tasks ( )
+
+ def _load_all_tasks_from_file (self) -> None:
+ with open (self._name_of_file_with_tasks, "r") as file_with_tasks:
+ self.all_tasks = json.load (file_with_tasks)
+
+ @property
+ def _name_of_file_with_tasks (self) -> str:
+ return "tasks.json"
+
+ def _create_groups (self) -> None:
+ self.easy_tasks = [ ]
+ self.medium_tasks = [ ]
+ self.hard_tasks = [ ]
+
+ def _group_tasks (self) -> None:
+ for task_number in self.all_tasks.keys():
+ task = self.all_tasks[task_number]
+ match task["difficulty"]:
+ case DifficultyLevels.EASY.value:
+ self.easy_tasks.append (task)
+ case DifficultyLevels.MEDIUM.value:
+ self.medium_tasks.append (task)
+ case DifficultyLevels.HARD.value:
+ self.hard_tasks.append (task)
+ case _:
+ raise ValueError (f"Неправильно задана сложность квеста №{task_number}!")
+
+
+ def get_random_easy_task (self) -> dict[str, str]:
+ return random.choice (self.easy_tasks)
+
+ def get_random_medium_task (self) -> dict[str, str]:
+ return random.choice (self.medium_tasks)
+
+ def get_random_hard_task (self) -> dict[str, str]:
+ return random.choice (self.hard_tasks)
+
+ def get_random_task (self) -> dict[str, str]:
+ func_calls = [
+ self.get_random_easy_task,
+ self.get_random_medium_task,
+ self.get_random_hard_task
+ ]
+ return random.choice (func_calls)( )
\ No newline at end of file
diff --git a/tasks.json b/tasks.json
new file mode 100644
index 0000000..c54c0e3
--- /dev/null
+++ b/tasks.json
@@ -0,0 +1,97 @@
+{
+ "1": {
+ "title": "Умножение чисел.",
+ "task_text": "Напишите программу, которая принимает на вход два числа и выводит их произведение.",
+ "solve": "Запросим у пользователя два числа c помощью 'input()'. Затем умножим два полученных числа и выведем результат на экран через 'print()'.",
+ "code": "num1 = float(input()) \n num2 = float(input()) \n print(num1 * num2)",
+ "difficulty": 0
+ },
+
+ "2": {
+ "title": "Инверсия.",
+ "task_text": "Реализуйте функцию, которая принимает на вход строку и возвращает ее в обратном порядке.",
+ "solve": "Функция `reverse_string()` принимает один аргумент - `s`, который является строкой. Для разворота строки мы используем срезы с отрицательным шагом. Срез `[::-1]` означает, что мы берем все символы строки от конца к началу с шагом -1, то есть в обратном порядке.",
+ "code": "def reverse_string(s):\n return s[::-1]",
+ "difficulty": 0
+ },
+
+ "3": {
+ "title": "Пересечение.",
+ "task_text": "Напишите функцию, которая принимает на вход два списка чисел и возвращает список, содержащий только числа, которые есть в обоих списках.",
+ "solve": "Функция `common_elements()` принимает два аргумента - `list1` и `list2`, которые являются списками чисел. Сначала функция преобразует списки во множества с помощью встроенной функции `set()`. Затем функция находит пересечение множеств с помощью метода `intersection()`. Наконец, функция преобразует множество обратно в список с помощью встроенной функции `list()` и возвращает его.",
+ "code": "def common_elements(list1, list2): \n set1 = set(list1) \n set2 = set(list2) \n result = set1.intersection(set2) \n return list(result)",
+ "difficulty": 0
+ },
+
+ "4": {
+ "title": "Подсчёт букв.",
+ "task_text": "Создайте программу, которая просит пользователя ввести слово и затем выводит количество гласных букв в этом слове.",
+ "solve": "Код начинается с запроса на ввод слова от пользователя с помощью `input()`. Затем мы создаем список гласных букв и инициализируем переменную `count` для подсчета гласных букв. Далее, мы перебираем каждую букву в слове с помощью цикла `for`, проверяем, является ли буква гласной, и если да, увеличиваем счетчик `count`.",
+ "code": "word = input() \nvowels = ['a', 'e', 'i', 'o', 'u'] \ncount = 0 \n for letter in word: \n if letter.lower() in vowels: \n count += 1 \n print('Количество гласных букв в слове', word, ':',count)",
+ "difficulty": 0
+ },
+
+ "5": {
+ "title": "Строки.",
+ "task_text": "Напишите программу, которая принимает на вход две строки и возвращает последнее слово в каждой из них.",
+ "solve": "Функция `last_words()` принимает два аргумента - `s1` и `s2`, которые являются строками. Для нахождения последнего слова в каждой строке мы используем метод `split()`, который разбивает строку на слова. Затем мы берем последнее слово в списке слов с помощью индекса `-1`. Возвращается список с последними словами.",
+ "code": "def last_words(s1, s2): \n last_word1 = s1.split()[-1] \n last_word2 = s2.split()[-1] \n return [last_word1, last_word2]",
+ "difficulty": 0
+ },
+
+ "6": {
+ "title": "Среднее арифметическое.",
+ "task_text": "Реализуйте функцию, которая принимает на вход список чисел и возвращает среднее значение этого списка.",
+ "solve": "Функция `average()` принимает один аргумент - `numbers`, который является списком чисел. Для вычисления среднего значения мы сначала вычисляем сумму всех чисел в списке с помощью встроенной функции `sum()`, а затем количество чисел в списке с помощью встроенной функции `len()`. Затем мы вычисляем среднее значение, которое равно сумме чисел, деленной на количество чисел. Наконец, мы возвращаем среднее значение с помощью ключевого слова `return`.",
+ "code": "def average(numbers): \n return sum(numbers) / len(numbers)",
+ "difficulty": 0
+ },
+
+ "7": {
+ "title": "Числа Фибоначчи.",
+ "task_text": "Напишите программу, которая просит пользователя ввести число N и затем выводит первые N чисел Фибоначчи.",
+ "solve": "Сначала мы запрашивает у пользователя число N с помощью функции `input()`. Далее инициализирует переменные `a` и `b`, которые будут использоваться для вычисления чисел Фибоначчи. Затем использует цикл `for` для вычисления и вывода первых N чисел Фибоначчи. В каждой итерации цикла программа выводит текущее число Фибоначчи и обновляет значения переменных `a` и `b` для вычисления следующего числа Фибоначчи. Наконец, выводим последовательность чисел Фибоначчи на экран.",
+ "code": "n = int(input()) \na, b = 0, 1 \n for i in range(n): \n print(a, end=' ') \n a, b = b, a + b",
+ "difficulty": 0
+ },
+
+ "8": {
+ "title": "Илон Шмаск и список.",
+ "task_text": "Напишите программу для Илона Шмаска с созданием списка чисел от 1 до 10 включительно.",
+ "solve": "Мы создаем при помощи генератора список чисел от 0 до 10 включительно. Затем мы выводим список на экран с помощью функции `print()`.",
+ "code": "\nprint('Добро пожаловать в компанию SpaceY!') \nprint([i for i in range(11)])",
+ "difficulty": 1
+ },
+
+ "9": {
+ "title": "Билл Герц и генератор паролей.",
+ "task_text": "Напишите программу для Билла Герца с генерацией случайного пароля длиной 8 символов, содержащего только буквы латинского алфавита (в верхнем и нижнем регистре) и цифры.",
+ "solve": "Мы импортируем модули `random` и `string`, чтобы использовать функции для генерации случайных чисел и создания списка символов, которые могут входить в пароль. Затем мы создаем пустую строку `password` и используем цикл `for` для генерации случайного пароля длиной 8 символов. В каждой итерации цикла мы добавляем случайный символ из списка `characters` к строке `password` с помощью метода `random.choice()`. Наконец, мы выводим пароль на экран с помощью функции `print()`.",
+ "code": "import random, string \ncharacters = string.ascii_letters + string.digits \npassword = '' \nfor i in range(8): \n password += random.choice(characters \nprint(password)",
+ "difficulty": 2
+ },
+
+ "10": {
+ "title": "День недели.",
+ "task_text": "Напишите программу, которая запрашивает у пользователя день недели (например, 'понедельник') и выводит сообщение 'Сегодня <день недели>', где <день недели> - введенный пользователем день недели.",
+ "solve": "Мы запрашиваем у пользователя день недели с помощью функции `input()` и сохраняем его в переменную `day`. Наконец, мы выводим сообщение с указанием введенного дня недели, используя форматирование строк с помощью f-строк.",
+ "code": "day = input('Введите день недели: ') \nprint(f'Сегодня {day}') \n",
+ "difficulty": 0
+ },
+
+ "11": {
+ "title": "Cумма чисел до 10.",
+ "task_text": "Напишите программу для нахождения суммы всех чисел от 1 до 10 включительно.",
+ "solve": "Применим в решении генератор для чисел от 0 до 10 включительно. При помощи функции `sum` получим их сумму и выведем ее на экран при помощи `print`.",
+ "code": "print(sum([i for i in range(11)]))",
+ "difficulty": 1
+ },
+
+ "12": {
+ "title": "Угадай-ка.",
+ "task_text": "Напишите программу, которая загадывает случайное число от 1 до 10 и просит пользователя угадать это число. Если пользователь угадал число, выводится сообщение 'Поздравляю, вы победили!'. Если нет, выводится сообщение 'К сожалению, вы проиграли. Загаданное число было <число>'.",
+ "solve": "Мы используем модуль `random`, чтобы загадать случайное число от 1 до 10. Затем мы просим пользователя ввести число и проверяем, угадал ли он загаданное число. Если пользователь угадал число, то выводится сообщение об победе, иначе программа выводит сообщение о проигрыше.",
+ "code": "import random \n number = random.randint(1, 10) \nguess = input('Введите число от 1 до 10: ') \nif int(guess) == number: \n print('Поздравляю, вы победили!') \nelse: \n print(f'К сожалению, вы проиграли. Загаданное число было {number}.')",
+ "difficulty": 1
+ }
+}
\ No newline at end of file
diff --git a/texts_for_users.json b/texts_for_users.json
new file mode 100644
index 0000000..5300415
--- /dev/null
+++ b/texts_for_users.json
@@ -0,0 +1,207 @@
+{
+ "for_new_user": "Здесь вы сможете глубже погрузиться в удивительный мир программирования на языке Python. Навык создан для всех желающих познать программирование с нуля. От мала до велика. У нас много разделов: \"Курс\" - для желающих познать всё с азов, \"Квест\" - для тех, кто хочет быстро проверить свои знания, \"Задачки\" - для гуру-олимпиадников и тех, кто только собирается таковым стать. Кроме того, у нас имеется функция \"Консультанта\", который готов помочь вам в решении ошибок в коде.",
+ "hello_text": [
+ "Привет!",
+ "Приветик!",
+ "Приветствую!",
+ "Приветствую вас!",
+ "Здравствуйте!",
+ "Доброго дня!",
+ "С добрым временем суток!",
+ "Hello!"
+ ],
+ "introduction_to_course": "Что ж, вы решили начать изучение языка Python.\nПройдя этот курс вы познакомитесь с основами программирования, научитесь писать простые программы и понимать код!\nЗдесь и дальше просто скажите: \"Далее\".\nЕсли хотите попасть на главное меню скажите: \"На главное меню\".",
+ "if_user_has_forgotten_commands": [
+ "Как ваше настроение? Готовы учиться? Просто скажите одну из моих команд.",
+ "Как вы? Хотите учиться Python? Просто скажите одну из моих команд.",
+ "Как насчёт узнать что-нибудь новое? Просто скажите одну из моих команд.",
+ "Как насчёт выучить всё-таки Python? Скажите любую мою команду.",
+ "Почему бы не выучить Python прямо сейчас? Скажите любую мою команду."
+ ],
+ "main_commands_of_skill": [
+ "Курс",
+ "Задачка",
+ "Квест",
+ "Консультант по Python",
+ "Отправить отчёт",
+ "Что ты умеешь?",
+ "Помощь"
+ ],
+ "you_stopped_at_lesson": [
+ "Что ж, вы остановились на уроке №",
+ "Итак, вы остановились на уроке №",
+ "Урок, на котором вы остановились - №",
+ "Ваш последний урок - №"
+ ],
+ "you_stopped_at_task": [
+ "Что ж, ваша последняя задачка - №",
+ "Итак, вы остановились на задачке №",
+ "Задачка, на которой вы остановились - №",
+ "Вы остановились на задачке №",
+ "Ваша последняя задачка - №"
+ ],
+ "something_is_unclear": [
+ "Извините, я вас не поняла.",
+ "Простите, я вас не поняла.",
+ "Извините, не поняла вас.",
+ "Простите, не поняла вас.",
+ "Извините, не могу разобрать.",
+ "Простите, не могу разобрать.",
+ "Извините, я не могу разобрать.",
+ "Простите, я не могу разобрать.",
+ "Извините, не разобрала.",
+ "Простите, не разобрала.",
+ "Извините, не поняла, что вы имеете в виду.",
+ "Простите, не поняла, что вы имеете в виду.",
+ "Извините, я не поняла, что вы имеете в виду.",
+ "Простите, я не поняла, что вы имеете в виду."
+ ],
+ "correct_answer": [
+ "Ура! Ты ответил правильно!",
+ "Ты ответил правильно!",
+ "Ура! Твой ответ верный!",
+ "Твой ответ верный!",
+ "Ура! Так держать!",
+ "Супер! Это правильный ответ!",
+ "Супер! Это верный ответ!" ,
+ "Так держать!",
+ "Верно!"
+ ],
+ "wrong_answer": [
+ "Извините, но это неправильный ответ.",
+ "Извините, это неправильный ответ.",
+ "Неправильный ответ.",
+ "Неправильно."
+ ],
+ "there_is_no_answer_like_that": [
+ "Извините, но такого ответа нет.",
+ "Извините, такого ответа нет.",
+ "Такого ответа нет.",
+ "Нет такого ответа."
+ ],
+ "continue_or_change_difficulty_level": [
+ "Показать следующий квест или сменить уровень сложности?",
+ "Следующий квест или хотите сменить уровень сложности?",
+ "Следующий квест или сменить уровень сложности?",
+ "Дальше по квестам или хотите сменить уровень сложности?"
+ ],
+ "head_of_farewell": [
+ "До свидания",
+ "Прощайте",
+ "Чао",
+ "Goodbye",
+ "Bye-bye"
+ ],
+ "body_of_farewell": [
+ "!",
+ ", приятного дня!",
+ ", успехов вам!",
+ ", вы многому научились!",
+ ", вы большой молодец!",
+ ", вы просто молодец!"
+ ],
+ "resume": [
+ "Продолжить?",
+ "Продолжим?",
+ "Далее?",
+ "Дальше?",
+ "Вперёд?"
+ ],
+ "user_has_completed_lesson": [
+ "Поздравляю, вы прошли урок!",
+ "Вы прошли целый урок!",
+ "Супер, вы прошли урок!",
+ "Вы прошли урок!",
+ "Урок пройден, поздравляю!",
+ "Супер, урок пройден!",
+ "Вы закончили изучение целого урока. Вы большой молодец!",
+ "Вы завершили изучение урока! Поздравляю!"
+ ],
+ "ask_user_if_he_wants_to_take_next_lesson": [
+ "Хотите его изучить?",
+ "Хотите начать его изучать?",
+ "Хотите его начать?",
+ "Хотите его прослушать?",
+ "Как насчёт продолжить?",
+ "Продолжим?"
+ ],
+ "user_has_completed_course": [
+ "Поздравляю! Вы прошли Курс!",
+ "Поздравляю вас! Вы прошли Курс!",
+ "Ух ты! Вы прошли весь Курс!",
+ "Вы полностью прошли Курс! Вы супер-молодец!",
+ "Вы супер-молодец! Вы прошли Курс целиком!",
+ "Вы супер-молодец! Вы полностью прошли Курс!"
+ ],
+ "soothing_text": [
+ "Не волнуйтесь!",
+ "Не беспокойтесь!",
+ "Я помогу вам!",
+ "Всё хорошо!"
+ ],
+ "win_sounds": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "lose_sounds": [
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "sound_of_looking_results": [
+ ""
+ ],
+ "farewell_sounds": [
+ "",
+ "",
+ "",
+ "",
+ ""
+ ],
+ "win_pictures": [
+ "1540737/634a305ed56f6f7ede01",
+ "213044/9c1470ed03227033b661",
+ "937455/004bdc782fbcccd77531",
+ "997614/1e6d664287e83afa03f5",
+ "937455/ab221dde314bcd195fbc",
+ "1030494/94a1abd2d495abd8a5eb",
+ "1030494/2cfb128332b743887193"
+ ],
+ "looking_results_pictures": [
+ "1540737/a6bf94f7ebc94229d96b",
+ "1652229/ff10d6281e46e9b5becf",
+ "965417/b11257b12517bf440d31",
+ "997614/e720f4e3e6e5bf590e3a",
+ "1540737/e659da2f5522ed7075e3",
+ "213044/df61b01ad55bb8361e58",
+ "965417/be6bb1930cc55456d9ed"
+ ],
+ "level_up_pictures": [
+ "213044/0bfd3d679fbd6602077b",
+ "997614/a0f708b6be670871c16e",
+ "1030494/16ddb523730ae56eec5c",
+ "1540737/d54af27b7569052bd88d"
+ ],
+ "farewell_pictures": [
+ "937455/56a988584d91787345e6",
+ "1030494/6f0db7964ca9d22546dc",
+ "937455/b0ced309358328e459cb",
+ "213044/ca81b57f73a34a12758d",
+ "1533899/2e9809613f8f8dc0266c",
+ "937455/a820c0631dfc61cc0a06",
+ "213044/c1a8157f80e4c57d38b4",
+ "1540737/1f1d45c8e2769da37f08",
+ "1652229/9c3d0955a53dd162354a"
+ ]
+}
\ No newline at end of file
diff --git a/useful_functions.py b/useful_functions.py
new file mode 100644
index 0000000..baf0e40
--- /dev/null
+++ b/useful_functions.py
@@ -0,0 +1,167 @@
+from json_manager import *
+
+
+def create_sessional_data (sessional_data: dict) -> dict:
+ if sessional_data == { }: # То есть это первое сообщение
+ return {
+ "state": "in_main_menu",
+ "last_output_text": "",
+ "last_text_to_speech": "",
+ "last_buttons": [ ],
+ "last_card": { },
+ "text_of_quest": "",
+ "correct_answer_of_quest": 0,
+ "difficulty_level_of_quest": 0,
+ "number_of_correct_quest_answers": 0,
+ "number_of_wrong_quest_answers": 0,
+ "was_said_that_user_can_change_difficulty_level_in_quest": False,
+
+ "title_of_task": "",
+ "text_of_task": "",
+ "difficulty_level_of_task": 0,
+ "solve_of_task": "",
+ "code_of_task": ""
+ }
+ # Все состояния: in_main_menu, working_with_course, choosing_course_theme, start_next_lesson_or_not,
+ # working_with_quest, choosing_right_answer_for_quest, choosing_between_repeating_and_changing_difficulty_level,
+ # viewing_quest_results, working_with_tasks, sending_report, consulting.
+ else: # Значит, сообщение уже не первое
+ return sessional_data
+
+
+def create_intersessional_data (intersessional_data: dict) -> dict:
+ if not "new_user" in intersessional_data.keys() or intersessional_data["new_user"]:
+ return {
+ "new_user": True,
+ "current_lesson": "",
+ "current_sublesson": ""
+ }
+ else:
+ return intersessional_data
+
+
+def get_user_greeting ( ) -> str:
+ hello_text = get_hello_text ( ) + "\n"
+ hello_text += get_text_asking_if_user_has_forgotten_commands ( ) + "\n"
+ #hello_text += get_main_commands_of_skill ( )
+ return hello_text
+
+
+def get_text_that_says_user_is_just_in_main_menu ( ) -> str:
+ return "Вы на главном меню!"
+
+def get_text_that_says_what_skill_can_do ( ) -> str:
+ return "Давайте расскажу, Я - ваш личный эксперт в области Python. Хотите отдохнуть и послушать курс? или потренироваться на практике в задачах и квесте? А может получить оценку своих знаний теории? Я всегда готова вам помочь! Может вы хотите получить консультацию от моего гениального интеллекта либо узнать как пофиксить ошибку? Тут я тоже могу подсказать. Так чем бы вы хотели заняться?"
+
+
+def create_buttons (*button_texts: str) -> list[dict]:
+ ready_buttons = [ ]
+ for text_of_button in button_texts:
+ ready_buttons.append ({"title": text_of_button, "hide": True})
+ return ready_buttons
+
+def create_buttons_in_text (*button_texts: str) -> list[dict]:
+ ready_buttons = [ ]
+ for text_of_button in button_texts:
+ ready_buttons.append ({"title": text_of_button, "hide": False})
+ return ready_buttons
+
+
+def create_buttons_of_main_menu ( ) -> list:
+ return create_buttons (*get_main_commands_of_skill_as_list ( ))
+
+def create_buttons_of_main_menu_in_text ( ) -> list:
+ return create_buttons_in_text (*get_main_commands_of_skill_as_list ( ))
+
+
+def calculate_python_knowledge (number_of_correct_answers: int,
+ number_of_wrong_answers: int) -> float:
+ if number_of_correct_answers == number_of_wrong_answers:
+ python_knowledge = 50 # 50% знания Python
+ else:
+ python_knowledge = number_of_correct_answers / (number_of_correct_answers + number_of_wrong_answers) * 100
+
+ return round (python_knowledge, 1)
+
+
+def code_to_speech (code: str) -> str:
+ """Переводит код в слова и выводит готовый текст в пронумерованном столбце."""
+ REPLACEMENTS: dict = _get_replacements ( )
+
+ PAUSE = "sil<[250]>"
+ lines = code.split("\n")
+ formatted_lines = [ ]
+ for i, line in enumerate(lines, start=1):
+ formatted_line = line
+ for key in REPLACEMENTS.keys():
+ formatted_line = formatted_line.replace(key, REPLACEMENTS[key])
+ formatted_lines.append(f"{PAUSE}строка{i}{PAUSE}{formatted_line}")
+ return "\n".join(formatted_lines) + PAUSE
+
+def _get_replacements ( ) -> dict:
+ """Возвращает словарь с заменами символов на слова."""
+ return {
+ ")": " скобка закрывается ",
+ "(": " скобка открывается ",
+ "*": " звёздочка ",
+ "'": " кавычки ",
+ '"': " кавычки ",
+ "{": " фигурная скобка открывается ",
+ "}": " фигурная скобка закрывается ",
+ ":": " двоеточие ",
+ "!": " восклицательный знак ",
+ ".": " точка ",
+ ",": " запятая ",
+ "[": " квадратная скобка открывается ",
+ "]": " квадратная скобка закрывается ",
+ "||": " две вертикальные линии (операция или) ",
+ ">": " больше ",
+ "<": " меньше ",
+ "/": " разделить ",
+ "-": " минус ",
+ "+": " плюс ",
+ "%": " процент ",
+ "@": " собачка ",
+ "&": " амперсанд "
+ }
+
+
+def make_big_hello_picture (title: str, description: str = "") -> dict:
+ return {
+ "type": "BigImage",
+ "image_id": "1540737/103847d7e3468a494c6c",
+ "title": title,
+ "description": description
+ }
+
+def make_big_win_picture (title: str, description: str = "") -> dict:
+ return {
+ "type": "BigImage",
+ "image_id": get_random_win_picture ( ),
+ "title": title,
+ "description": description
+ }
+
+def make_big_level_up_picture (title: str, description: str = "") -> dict:
+ return {
+ "type": "BigImage",
+ "image_id": get_random_level_up_picture ( ),
+ "title": title,
+ "description": description
+ }
+
+def make_big_looking_results_picture (title: str, description: str = "") -> dict:
+ return {
+ "type": "BigImage",
+ "image_id": get_random_looking_results_pictures ( ),
+ "title": title,
+ "description": description
+ }
+
+def make_big_farewell_picture (title: str, description: str = "") -> dict:
+ return {
+ "type": "BigImage",
+ "image_id": get_random_farewell_picture ( ),
+ "title": title,
+ "description": description
+ }
\ No newline at end of file