Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
efd8bbb
Впервые загрузил мой заготовочный код.
Alexonys1 Mar 14, 2023
6e166cf
Дополнение
Alexonys1 Mar 15, 2023
d4c8bfd
Отправляю файлы перед сном.
Alexonys1 Mar 15, 2023
062837e
Вторая версия навыка!
Alexonys1 Mar 20, 2023
ed17685
Вторая версия навыка.
Alexonys1 Mar 22, 2023
df127a7
Ещё одно обновление второй версии.
Alexonys1 Mar 23, 2023
2e799e2
Обновил вторую версию.
Alexonys1 Mar 23, 2023
8402b71
3-я немного изменённая версия.
Alexonys1 Mar 25, 2023
f50ef61
Кое-что переделал
Alexonys1 Mar 25, 2023
d8f4037
add tasks
TchTech Mar 25, 2023
32851d4
Merge branch 'Alexonys'-code' of https://github.com/TchTech/edu_skill…
TchTech Mar 25, 2023
5a21654
consultant plus
TchTech Mar 25, 2023
7777c5f
Update consultant.py
TchTech Mar 26, 2023
2ea9616
Update consultant.py
TchTech Mar 26, 2023
4307c72
consultant plus plus
TchTech Mar 26, 2023
fe55a54
Update consultant.py
TchTech Mar 26, 2023
dd37d64
Update consultant.py
TchTech Mar 26, 2023
ba95582
Update consultant.py
TchTech Mar 26, 2023
4bcac75
Обновление 3-й версии навыка
Alexonys1 Mar 26, 2023
f6647de
tasks
TchTech Mar 26, 2023
9e3d84c
Merge branch 'Alexonys'-code' of https://github.com/TchTech/edu_skill…
TchTech Mar 26, 2023
8033c18
Большое дополнение от Кирилла
Alexonys1 Mar 26, 2023
d647ee8
smth
TchTech Mar 26, 2023
a576e30
Ещё одно обновление звуков и картинок
Alexonys1 Mar 27, 2023
4c5188e
Update main4.py
TchTech Mar 27, 2023
e9a32ad
Обновил навык.
Alexonys1 Mar 28, 2023
d656d79
Update consultant.py
TchTech Mar 29, 2023
87cc255
Merge branch 'Alexonys'-code' of https://github.com/TchTech/edu_skill…
TchTech Mar 29, 2023
1cc73b4
upd
TchTech Mar 30, 2023
433ff1d
Полностью рабочий навык для Алисы.
Alexonys1 Apr 4, 2023
440e217
fix for public release
TchTech Jun 18, 2025
df0c879
Merge branch 'Alexonys'-code' of https://github.com/TchTech/edu_skill…
TchTech Jun 18, 2025
a9b5f6f
Update README.md
TchTech Jun 18, 2025
d4fa4df
картинки для ридми
TchTech Jun 18, 2025
b255e32
Update README.md
TchTech Jun 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 80 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,80 @@
# edu_skill
Alice Python education skill
# Учим Python: Ваш Голосовой Наставник по Python в Алисе 🐍

[![Skill Status: Active](https://img.shields.io/badge/Status-Active-brightgreen)](https://dialogs.yandex.ru/store/skills/9aa2ecba-alisas-test)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Yandex Dialogs](https://img.shields.io/badge/Platform-Yandex%20Dialogs-blue)](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 логика)

## 🖼 Скриншоты

<div>
<img src="https://github.com/TchTech/edu_skill/blob/Alexonys'-code/images/1.png" />
<img src="https://github.com/TchTech/edu_skill/blob/Alexonys'-code/images/2.png" />
<img src="https://github.com/TchTech/edu_skill/blob/Alexonys'-code/images/3.png" />
</div>

## 🤝 Вклад

Мы открыты для предложений и идей! Если у вас есть какие-либо предложения по улучшению навыка, пожалуйста, свяжитесь с нами.

## 📜 Лицензия

Этот проект лицензирован по лицензии MIT - смотрите файл [LICENSE](LICENSE) для деталей.
53 changes: 53 additions & 0 deletions alisa's response.json
Original file line number Diff line number Diff line change
@@ -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"
}
26 changes: 26 additions & 0 deletions buttons.py
Original file line number Diff line number Diff line change
@@ -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)
33 changes: 33 additions & 0 deletions consultant.py
Original file line number Diff line number Diff line change
@@ -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])
41 changes: 41 additions & 0 deletions email_sender.py
Original file line number Diff line number Diff line change
@@ -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...")
24 changes: 24 additions & 0 deletions enums.py
Original file line number Diff line number Diff line change
@@ -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 = "")
Binary file added images/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 127 additions & 0 deletions json_manager.py
Original file line number Diff line number Diff line change
@@ -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 "<speaker audio=\"dialogs-upload/5cef3ba2-6ab9-4297-8e09-176c9297e1b1/d5cbb919-c5c1-4691-a8f5-ebdfdee3152d.opus\">"

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"])
Loading