summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend_api.py18
-rw-r--r--bot.py5
-rw-r--r--keyboards.py2
-rw-r--r--rules.jpgbin0 -> 1216722 bytes
-rw-r--r--states.py127
5 files changed, 137 insertions, 15 deletions
diff --git a/backend_api.py b/backend_api.py
index 491560f..a8270a4 100644
--- a/backend_api.py
+++ b/backend_api.py
@@ -115,10 +115,20 @@ def get_profile(tg_id: int):
def publish_task(title: str):
url_title = urllib.parse.quote(title)
- return patch_request(f"{BACKEND_URL}/api/tasks/{url_title}/update/", data={
- "first_published": dt.datetime.now(),
- "is_public": True
- })
+ code, resp = get_task(title)
+
+ if code != 200:
+ return code, {}
+
+ if resp["first_published"] is None:
+ return patch_request(f"{BACKEND_URL}/api/tasks/{url_title}/update/", data={
+ "first_published": dt.datetime.now(),
+ "is_public": True
+ })
+ else:
+ return patch_request(f"{BACKEND_URL}/api/tasks/{url_title}/update/", data={
+ "is_public": True
+ })
def hide_task(title: str):
diff --git a/bot.py b/bot.py
index d9aae67..aee7d82 100644
--- a/bot.py
+++ b/bot.py
@@ -17,7 +17,7 @@ from keyboards import (
from utils import *
from states import States, AdminStates
-logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
@@ -108,7 +108,8 @@ conversation_handler = ConversationHandler(
],
TASK_SHOWN: [
MessageHandler(Filters.regex(TaskChosenKeyboard.CANCEL), States.choose_task, pass_user_data=True),
- MessageHandler(Filters.regex(TaskChosenKeyboard.TYPE_ANSWER), States.type_answer, pass_user_data=True),
+ MessageHandler(Filters.text, States.accept_answer, pass_user_data=True),
+ # MessageHandler(Filters.regex(TaskChosenKeyboard.TYPE_ANSWER), States.type_answer, pass_user_data=True),
],
ANSWERING: [
MessageHandler(Filters.regex(AnsweringKeyboard.CANCEL), States.show_task, pass_user_data=True),
diff --git a/keyboards.py b/keyboards.py
index 1d815f4..b2ed775 100644
--- a/keyboards.py
+++ b/keyboards.py
@@ -72,7 +72,7 @@ class TaskChosenKeyboard(Keyboard):
@classmethod
def get_keyboard(cls, telegram_id=None):
return [
- [cls.TYPE_ANSWER],
+ # [cls.TYPE_ANSWER],
[cls.CANCEL],
]
diff --git a/rules.jpg b/rules.jpg
new file mode 100644
index 0000000..3e40f8b
--- /dev/null
+++ b/rules.jpg
Binary files differ
diff --git a/states.py b/states.py
index 9aaa777..eaadd4a 100644
--- a/states.py
+++ b/states.py
@@ -7,6 +7,8 @@ from keyboards import (
from utils import *
import backend_api
from time import sleep
+import datetime as dt
+from decimal import Decimal
import logging
# Typing
@@ -28,6 +30,18 @@ def save_state(func):
return wrapper
+def calc_score(t, base_score=1000):
+ base_score = Decimal(base_score)
+ min_score = Decimal(100)
+ max_t = Decimal(720)
+ k = (base_score - min_score) / (max_t * max_t)
+
+ return round(min(k * (t - max_t) * (t - max_t) + min_score, base_score), 2)
+
+
+def calculate_attempts(attempts):
+ pass
+
class States:
@staticmethod
@save_state
@@ -53,13 +67,30 @@ class States:
]
+ full_score = Decimal(0.0)
if status_code == 200:
if len(response) != 0:
menu_text.append("Твои решенные задачи:")
+
for attempt in response:
+ try:
+ ts = dt.datetime.strptime(attempt["timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ")
+ except ValueError:
+ ts = dt.datetime.strptime(attempt["timestamp"], "%Y-%m-%dT%H:%M:%SZ")
+
+ try:
+ fp = dt.datetime.strptime(attempt["task"]["first_published"], "%Y-%m-%dT%H:%M:%S.%fZ")
+ except ValueError:
+ fp = dt.datetime.strptime(attempt["task"]["first_published"], "%Y-%m-%dT%H:%M:%SZ")
+
+ t = Decimal((ts - fp).total_seconds()) / Decimal(60)
+ plr_score = calc_score(t, attempt["task"]["base_score"])
+ print(plr_score)
+ full_score += plr_score
+
menu_text.append(
f"_{attempt['task']['title']}_ "
- f"({attempt['task']['base_score']})"
+ f"({plr_score})"
)
else:
menu_text.append("У тебя еще нет решенных задач")
@@ -69,7 +100,7 @@ class States:
"Попробуй обратиться к боту чуть позже."
)
- menu_text.append("\n*Итоговый счет*: 0\n*Место в топе*: 0")
+ menu_text.append(f"\n*Итоговый счет*: {full_score}\n*Место в топе*: 0")
update.message.reply_text("\n".join(menu_text), parse_mode="Markdown")
@@ -104,13 +135,64 @@ class States:
@staticmethod
@save_state
def top_10(bot: Bot, update: Update, user_data: dict):
- update.message.reply_text("какая то хуйня")
+ code, attempts = backend_api.get_attempts()
+
+ top = {}
+
+ for attempt in attempts:
+ if not attempt["solved"]:
+ continue
+
+ if attempt["profile"]["tg_id"] not in top:
+ top[attempt["profile"]["tg_id"]] = {
+ "fullname": attempt["profile"]["fullname"],
+ "username": attempt["profile"]["username"],
+ "score": Decimal(0.0)
+ }
+
+ try:
+ ts = dt.datetime.strptime(attempt["timestamp"], "%Y-%m-%dT%H:%M:%S.%fZ")
+ except ValueError:
+ ts = dt.datetime.strptime(attempt["timestamp"], "%Y-%m-%dT%H:%M:%SZ")
+
+ try:
+ fp = dt.datetime.strptime(attempt["task"]["first_published"], "%Y-%m-%dT%H:%M:%S.%fZ")
+ except ValueError:
+ fp = dt.datetime.strptime(attempt["task"]["first_published"], "%Y-%m-%dT%H:%M:%SZ")
+
+ t = Decimal((ts - fp).total_seconds()) / Decimal(60)
+ plr_score = calc_score(t, attempt["task"]["base_score"])
+ top[attempt["profile"]["tg_id"]]["score"] += plr_score
+
+ try:
+ top_list = []
+ for tg_id, stats in top.items():
+ top_list.append((
+ stats['score'],
+ f"{stats['fullname']} (@{stats['username']}) -- {stats['score']}pts"
+ ))
+
+ top_list.sort(key=lambda p: p[0], reverse=True)
+
+ top = ["Топ-10:"]
+ print(top_list)
+ for place, (score, text) in enumerate(top_list, 1):
+ top.append(str(place).rjust(2, " ") + ". " + text)
+ except Exception as e:
+ print(e)
+
+ update.message.reply_text("\n".join(top))
return MAIN_MENU
@staticmethod
@save_state
def rules(bot: Bot, update: Update, user_data: dict):
- update.message.reply_text("какая то хуйня")
+ with open("rules.jpg", "rb") as f:
+ try:
+ print(update.message.reply_photo(f, timeout=5))
+ except Exception as e:
+ print(e)
+
return MAIN_MENU
@staticmethod
@@ -122,6 +204,30 @@ class States:
task_title = update.message.text
user_data["chosen_task"] = task_title
+ status_code, response = backend_api.get_attempts(
+ tg_id=update.message.from_user.id,
+ task_title=user_data["chosen_task"]
+ )
+ if status_code != 200:
+ user_data["chosen_task"] = None
+
+ update.message.reply_text(
+ "Произошла ошибка в работе квиза. Мы уже работаем над её устранением!",
+ reply_markup=ReplyKeyboardMarkup(TasksKeyboard.get_keyboard())
+ )
+
+ return TASK_CHOOSING
+
+ if len(response) != 0:
+ user_data["chosen_task"] = None
+
+ update.message.reply_text(
+ "Ты уже решил эту задачу! Выбери другую.",
+ reply_markup=ReplyKeyboardMarkup(TasksKeyboard.get_keyboard())
+ )
+
+ return TASK_CHOOSING
+
status_code, tasks_response = backend_api.get_published_tasks()
if status_code != 200:
update.message.reply_text(
@@ -141,7 +247,6 @@ class States:
return TASK_CHOOSING
- # status_code, task = backend_api.get_task(task_title)
task = titles[task_title]
message = '\n'.join([
@@ -157,6 +262,11 @@ class States:
reply_markup=ReplyKeyboardMarkup(keyboard)
)
+ update.message.reply_text(
+ "Вводи свой ответ и я его проверю, "
+ "или нажми кнопку Назад, чтобы выбрать другую задачу"
+ )
+
return TASK_SHOWN
@staticmethod
@@ -198,11 +308,12 @@ class States:
return ANSWER_RIGHT
else:
update.message.reply_text(
- "К сожалению, твой ответ неверный =(",
- reply_markup=ReplyKeyboardMarkup(ContinueKeyboard.get_keyboard())
+ "К сожалению, твой ответ неверный =( Попробуй ввести другой ответ.",
+ reply_markup=ReplyKeyboardMarkup(TaskChosenKeyboard.get_keyboard())
)
- return ANSWER_WRONG
+ # return ANSWER_WRONG
+ return TASK_SHOWN
else:
update.message.reply_text(