mirror of
https://gitlab.com/megazordpobeda/DataRush.git
synced 2026-05-22 23:17:09 +00:00
Merge branch 'master' of https://gitlab.prodcontest.ru/team-15/project
This commit is contained in:
@@ -1 +1,33 @@
|
|||||||
# DataRush
|
# DataRush
|
||||||
|
|
||||||
|
Инновационный сервис для проведения соревнований по анализу данных
|
||||||
|
|
||||||
|
|
||||||
|
## Запуск
|
||||||
|
|
||||||
|
Склонируйте репозиторий и пропишите
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
## Основные ручки
|
||||||
|
|
||||||
|
* `/` - основное приложение
|
||||||
|
* `/api/v1/docs` - swagger-ui документация
|
||||||
|
* `/admin` - админка
|
||||||
|
* `/admin/grafana` - графана
|
||||||
|
* `/docs` - гайд по анализу данных
|
||||||
|
|
||||||
|
После запуска по методу выше создается пользователь в админке (`/admin`) с данными ниже:`admin`
|
||||||
|
- `admin` - логин
|
||||||
|
- `proooooood` - пароль
|
||||||
|
|
||||||
|
|
||||||
|
## Тесты
|
||||||
|
|
||||||
|
Написаны unit-тесты (на базе Django TestCase) и E2E (Postman коллекция)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
![django test]()
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 261 KiB |
@@ -67,3 +67,4 @@ class TaskAttachmentSchema(ModelSchema):
|
|||||||
class TaskStatusSchema(Schema):
|
class TaskStatusSchema(Schema):
|
||||||
task_name: str
|
task_name: str
|
||||||
result: int
|
result: int
|
||||||
|
max_points: int
|
||||||
|
|||||||
@@ -196,14 +196,21 @@ def get_competition_results(request, competition_id: UUID):
|
|||||||
for task in tasks:
|
for task in tasks:
|
||||||
submissions = CompetitionTaskSubmission.objects.filter(
|
submissions = CompetitionTaskSubmission.objects.filter(
|
||||||
user=request.auth, task=task
|
user=request.auth, task=task
|
||||||
).filter(status="checked").all()
|
).filter(status="checked").order_by("-earned_points").all()
|
||||||
if not submissions:
|
if not submissions:
|
||||||
result = 0
|
all_submissions_count = CompetitionTaskSubmission.objects.filter(
|
||||||
|
user=request.auth, task=task
|
||||||
|
).count()
|
||||||
|
if all_submissions_count == 0:
|
||||||
|
result = -2
|
||||||
|
else:
|
||||||
|
result = -1
|
||||||
else:
|
else:
|
||||||
result = submissions[0].earned_points
|
result = submissions[0].earned_points
|
||||||
data.append(TaskStatusSchema(
|
data.append(TaskStatusSchema(
|
||||||
task_name=task.title,
|
task_name=task.title,
|
||||||
result=result
|
result=result,
|
||||||
|
max_points=task.points,
|
||||||
))
|
))
|
||||||
|
|
||||||
return status.OK, data
|
return status.OK, data
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 116 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
@@ -2,6 +2,7 @@ import random
|
|||||||
import uuid
|
import uuid
|
||||||
from datetime import timedelta, datetime
|
from datetime import timedelta, datetime
|
||||||
|
|
||||||
|
from PIL.Image import Image
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth.hashers import make_password
|
from django.contrib.auth.hashers import make_password
|
||||||
from django.core.files.base import ContentFile, File
|
from django.core.files.base import ContentFile, File
|
||||||
@@ -13,10 +14,11 @@ from apps.review.models import Reviewer
|
|||||||
from apps.task.models import (
|
from apps.task.models import (
|
||||||
CompetitionTask,
|
CompetitionTask,
|
||||||
CompetitionTaskCriteria,
|
CompetitionTaskCriteria,
|
||||||
CompetitionTaskSubmission,
|
CompetitionTaskSubmission, CompetitionTaskAttachment,
|
||||||
)
|
)
|
||||||
from apps.user.models import User, UserRole
|
from apps.user.models import User, UserRole
|
||||||
|
|
||||||
|
# Примеры файлов с правильными ответами
|
||||||
ans1 = ContentFile(
|
ans1 = ContentFile(
|
||||||
b"1984",
|
b"1984",
|
||||||
name=f"submission_{uuid.uuid4().hex}.txt",
|
name=f"submission_{uuid.uuid4().hex}.txt",
|
||||||
@@ -25,46 +27,86 @@ ans2 = ContentFile(
|
|||||||
b"3",
|
b"3",
|
||||||
name=f"submission_{uuid.uuid4().hex}.txt",
|
name=f"submission_{uuid.uuid4().hex}.txt",
|
||||||
)
|
)
|
||||||
|
ans3 = ContentFile(
|
||||||
|
b"42",
|
||||||
|
name=f"submission_{uuid.uuid4().hex}.txt",
|
||||||
|
)
|
||||||
|
ans4 = ContentFile(
|
||||||
|
b"11",
|
||||||
|
name=f"submission_{uuid.uuid4().hex}.txt",
|
||||||
|
)
|
||||||
|
dataset = ContentFile(
|
||||||
|
b"it is a dataset",
|
||||||
|
name=f"dataset-{uuid.uuid4().hex}.txt",
|
||||||
|
)
|
||||||
|
dataset2 = ContentFile(
|
||||||
|
b"it is a dataset",
|
||||||
|
name=f"dataset-{uuid.uuid4().hex}.csv",
|
||||||
|
)
|
||||||
|
|
||||||
now = timezone.now()
|
now = timezone.now()
|
||||||
|
|
||||||
|
image_dir = f"{settings.BASE_DIR}/apps/core/contents/images"
|
||||||
|
f = open(f"{image_dir}/dano.jpg", "rb")
|
||||||
|
dano_image = File(f, name="dano.jpg")
|
||||||
|
|
||||||
|
# Расширенный список соревнований, включая 3 новых
|
||||||
competitions = [
|
competitions = [
|
||||||
{
|
{
|
||||||
"obj": None, # докидывает в процессе
|
"obj": None, # будет заполнено позже
|
||||||
"title": "DANO. Финал",
|
"title": "DANO. Финал",
|
||||||
"description": "Олимпиада по анализу данных от Т-Банка и ВШЭ",
|
"description": "Олимпиада по анализу данных от Т-Банка и ВШЭ",
|
||||||
"start_date": now - timedelta(days=2),
|
"start_date": now - timedelta(days=2),
|
||||||
"end_date": now + timedelta(days=5),
|
"end_date": now + timedelta(days=5),
|
||||||
"type": "competitive",
|
"type": "competitive",
|
||||||
"participation_type": "solo",
|
"participation_type": "solo",
|
||||||
|
"image": dano_image,
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"title": "Задача 1",
|
"title": "Задача 1",
|
||||||
"description": """На маркетплейсе «Е-шопинг» продаются различные товары. Одна из задач аналитика —
|
"description": (
|
||||||
прогнозировать, сколько товаров будет продаваться при определенной цене. В ходе
|
"""
|
||||||
исследований и экспериментов был выявлен вид зависимости:
|
На маркетплейсе «Е-шопинг» продаются различные товары. Одна из задач аналитика —
|
||||||
$Q(P) = Q_0 \times e^{E \times \frac{P_0 - P}{P_0}}$
|
прогнозировать, сколько товаров будет продаваться при определенной цене. В ходе исследований
|
||||||
|
был выявлен вид зависимости:\n
|
||||||
|
$Q(P) = Q_0 \\times e^{E \\times \\frac{P_0 - P}{P_0}}$\n
|
||||||
где Q — это количество проданных единиц товара при цене P,
|
где Q — это количество проданных единиц товара при цене P,
|
||||||
Q 0 — количество проданных единиц товара при цене P0 ,
|
Q 0 — количество проданных единиц товара при цене P0 ,
|
||||||
E — коэффициент чувствительности количества проданных единиц товара к изменению
|
E — коэффициент чувствительности количества проданных единиц товара к изменению
|
||||||
цены.
|
цены.
|
||||||
|
1. Кофемашину «Кофе каждый день» купили 200 000 раз (Q 0 ) при цене 20 000 ₽ (P 0
|
||||||
|
).
|
||||||
|
Позже продавец поднял цену на 5 000 ₽, при этом продажи сократились на 24 000
|
||||||
|
штук. Какой коэффициент чувствительности Е имеет этот товар? Ответ округлите
|
||||||
|
до двух знаков после запятой.
|
||||||
|
2. Потом продавец решил поставить новую цену на эту же модель: 22 000 ₽. Сколько
|
||||||
|
продаж согласно нашей зависимости будет у этого товара? Используйте результаты
|
||||||
|
предыдущего пункта. Ответ округлите до целых.
|
||||||
|
3. Другой продавец предлагает на нашем маркетплейсе кухонные ножи и сковородки.
|
||||||
|
Благодаря исследованиям были получены следующие формулы зависимостей
|
||||||
|
количества проданных товаров:
|
||||||
|
|
||||||
Найдите, сколько заработает продавец при цене по 3 000 ₽ за нож и сковороду
|
Найдите, сколько заработает продавец при цене по 3 000 ₽ за нож и сковороду
|
||||||
при условии, что себестоимость ножа — 1 000 ₽, а сковородки — 2 000 ₽.Ответ
|
при условии, что себестоимость ножа — 1 000 ₽, а сковородки — 2 000 ₽.Ответ
|
||||||
округлите до целых.""".strip(),
|
округлите до целых.
|
||||||
|
Найдите, сколько заработает продавец при цене по 3 000 ₽ за нож и сковороду при условии,
|
||||||
|
что себестоимость ножа — 1 000 ₽, а сковородки — 2 000 ₽. Ответ округлите до целых.
|
||||||
|
""".strip()
|
||||||
|
),
|
||||||
"type": CompetitionTask.CompetitionTaskType.INPUT.value,
|
"type": CompetitionTask.CompetitionTaskType.INPUT.value,
|
||||||
"points": 3,
|
"points": 3,
|
||||||
"submission_reviewers_count": 2,
|
"submission_reviewers_count": 2,
|
||||||
"max_attempts": 20,
|
"max_attempts": 20,
|
||||||
"correct_answer_file": ans1
|
"correct_answer_file": ans1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"title": "Задача 2",
|
"title": "Задача 2",
|
||||||
"description": """
|
"description": "Найдите максимальную зарплату программиста из датасета на питоне",
|
||||||
Напишите "hello_dano" на питоне
|
|
||||||
""".strip(),
|
|
||||||
"type": CompetitionTask.CompetitionTaskType.CHECKER.value,
|
"type": CompetitionTask.CompetitionTaskType.CHECKER.value,
|
||||||
|
"attachment": dataset,
|
||||||
|
"attachment_path": "dataset",
|
||||||
"points": 25,
|
"points": 25,
|
||||||
"submission_reviewers_count": 2,
|
"submission_reviewers_count": 2,
|
||||||
"max_attempts": 50,
|
"max_attempts": 50,
|
||||||
@@ -72,60 +114,66 @@ E — коэффициент чувствительности количеств
|
|||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"title": "Задача 3",
|
"title": "Задача 3",
|
||||||
"description": """Небольшой интернет-магазин собрал данные о действиях пользователей на своем сайте
|
"attachment": dataset2,
|
||||||
|
"attachment_path": "dataset2",
|
||||||
|
"description": """
|
||||||
|
Небольшой интернет-магазин собрал данные о действиях пользователей на своем сайте
|
||||||
за последние несколько месяцев.
|
за последние несколько месяцев.
|
||||||
ecommerce_logs.csv — журнал действий пользователей:
|
ecommerce_logs.csv — журнал действий пользователей:
|
||||||
• user_id — идентификатор пользователя.
|
• user_id — идентификатор пользователя.
|
||||||
• action — тип действия пользователя:
|
• action — тип действия пользователя:
|
||||||
— visit — посещение сайта;
|
— visit — посещение сайта;
|
||||||
— click — клик на карточку товара;
|
— click — клик на карточку товара;
|
||||||
— cart — добавление товара в корзину;
|
— cart — добавление товара в корзину;
|
||||||
— delete — удаление товара из корзины;
|
— delete — удаление товара из корзины;
|
||||||
— purchase — покупка товаров.
|
— purchase — покупка товаров.
|
||||||
• date_time — время совершения действия.
|
• date_time — время совершения действия.
|
||||||
• product_id — идентификатор товара.
|
• product_id — идентификатор товара.
|
||||||
• quantity — количество добавленного в корзину товара.
|
• quantity — количество добавленного в корзину товара.
|
||||||
• delivery_price — стоимость доставки.
|
• delivery_price — стоимость доставки.
|
||||||
• sex — пол пользователя.
|
• sex — пол пользователя.
|
||||||
• region — регион пользователя.
|
• region — регион пользователя.
|
||||||
• price — цена товара.
|
• price — цена товара.
|
||||||
|
Ваша задача — проанализировать поведение пользователей, выявить возможные
|
||||||
|
проблемы при покупке и предложить решения. Ваш анализ поможет понять, на каком
|
||||||
|
этапе воронки магазин теряет покупателей и какие изменения можно внести, чтобы
|
||||||
|
улучшить процесс покупок в интернет-магазине.
|
||||||
|
Как правило, количество пользователей на каждом последующем шаге уменьшается,
|
||||||
|
и такая ситуация называется “воронкой”. Конверсия — это отношение количества
|
||||||
|
пользователей на каком-то одном шаге к количеству пользователей на одном
|
||||||
|
из предыдущих шагов. Например, конверсия из визита сайта в добавление товара
|
||||||
|
в корзину рассчитывается так: количество пользователей, добавивших товар в корзину,
|
||||||
|
делится на количество пользователей, посетивших сайт.
|
||||||
Вам нужно изучить воронку конверсии, которая показывает, как пользователи переходят
|
Вам нужно изучить воронку конверсии, которая показывает, как пользователи переходят
|
||||||
от одного шага к другому на сайте. В нашем случае воронка состоит из следующих шагов:
|
от одного шага к другому на сайте. В нашем случае воронка состоит из следующих шагов:
|
||||||
1. Посещение сайта.
|
1. Посещение сайта.
|
||||||
2. Просмотр карточки товара.
|
2. Просмотр карточки товара.
|
||||||
3. Добавление товара в корзину.
|
3. Добавление товара в корзину.
|
||||||
4. Покупка.
|
4. Покупка.
|
||||||
|
|
||||||
1. Посещение сайта.
|
|
||||||
2. Просмотр карточки товара.
|
|
||||||
3. Добавление товара в корзину.
|
|
||||||
4. Покупка.
|
|
||||||
3 / 11
|
|
||||||
1.) Посчитайте конверсию (округлите ответ до 3 знаков после запятой):
|
1.) Посчитайте конверсию (округлите ответ до 3 знаков после запятой):
|
||||||
• Из визита на сайт в клик на карточку товара.
|
• Из визита на сайт в клик на карточку товара.
|
||||||
• Из клика в добавление в корзину.
|
• Из клика в добавление в корзину.
|
||||||
• Из добавления в корзину в покупку.
|
• Из добавления в корзину в покупку.
|
||||||
• Из визита на сайт в добавление в корзину.
|
• Из визита на сайт в добавление в корзину.
|
||||||
• Из визита на сайт в покупку.
|
• Из визита на сайт в покупку.
|
||||||
2. Постройте воронку конверсии с помощью столбчатой диаграммы:
|
2. Постройте воронку конверсии с помощью столбчатой диаграммы:
|
||||||
• По оси X — шаги воронки.
|
• По оси X — шаги воронки.
|
||||||
• По оси Y — количество уникальных пользователей на каждом шаге.
|
• По оси Y — количество уникальных пользователей на каждом шаге.
|
||||||
3. Определите, на каком этапе конверсия из предыдущего шага ниже всего.
|
3. Определите, на каком этапе конверсия из предыдущего шага ниже всего.
|
||||||
Сформулируйте одну гипотезу, связанную с поведением пользователей, которая
|
Сформулируйте одну гипотезу, связанную с поведением пользователей, которая
|
||||||
может объяснить падение конверсии именно на этом этапе. Обоснуйте механизм
|
может объяснить падение конверсии именно на этом этапе. Обоснуйте механизм
|
||||||
работы приведенной гипотезы.
|
работы приведенной гипотезы.
|
||||||
4. Постройте график динамики (по оси X — дни) для каждой из конверсий:
|
4. Постройте график динамики (по оси X — дни) для каждой из конверсий:
|
||||||
• Конверсия из визита в клик.
|
• Конверсия из визита в клик.
|
||||||
• Конверсия из визита в добавление в корзину.
|
• Конверсия из визита в добавление в корзину.
|
||||||
• Конверсия из визита в покупку.
|
• Конверсия из визита в покупку.
|
||||||
5. На графике найдите просадку конверсии: укажите, какая конверсия просела
|
5. На графике найдите просадку конверсии: укажите, какая конверсия просела
|
||||||
и в какой примерно период это произошло (допустимая погрешность — 1–3
|
и в какой примерно период это произошло (допустимая погрешность — 1–3
|
||||||
дня).
|
дня).
|
||||||
6. Чем вызвано снижение конверсии в этот период? Какие изменения в бизнесе
|
6. Чем вызвано снижение конверсии в этот период? Какие изменения в бизнесе
|
||||||
или поведении пользователей могли бы объяснить это? Ответьте на оба
|
или поведении пользователей могли бы объяснить это? Ответьте на оба
|
||||||
вопроса, опираясь на данные.
|
вопроса, опираясь на данные.
|
||||||
""".strip(),
|
""".strip(),
|
||||||
"type": CompetitionTask.CompetitionTaskType.REVIEW.value,
|
"type": CompetitionTask.CompetitionTaskType.REVIEW.value,
|
||||||
"points": 10,
|
"points": 10,
|
||||||
"submission_reviewers_count": 2,
|
"submission_reviewers_count": 2,
|
||||||
@@ -136,18 +184,18 @@ ecommerce_logs.csv — журнал действий пользователей:
|
|||||||
"name": "Обоснованность решения",
|
"name": "Обоснованность решения",
|
||||||
"slug": "validity",
|
"slug": "validity",
|
||||||
"description": "Аргументация",
|
"description": "Аргументация",
|
||||||
"max_value": 5
|
"max_value": 5,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"name": "Правильность",
|
"name": "Правильность",
|
||||||
"slug": "correctness",
|
"slug": "correctness",
|
||||||
"description": "Насколько точные и верные ответы были представлены.",
|
"description": "Точность вычислений",
|
||||||
"max_value": 5
|
"max_value": 5,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
@@ -161,53 +209,225 @@ ecommerce_logs.csv — журнал действий пользователей:
|
|||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"title": "Задача 1",
|
"title": "Задача 1",
|
||||||
"description": """Сколько этапов в DANO?""".strip(),
|
"description": """
|
||||||
|
Конверсия — это доля клиентов, перешедших с одного этапа на другой. Например,
|
||||||
|
на сайт с заявками на кредитные карты зашли 50 человек, после ознакомления
|
||||||
|
с условиями заявку на оформление карты (далее — заявку) оставили только 45
|
||||||
|
из них. В данном случае конверсия составляет 90% = 45/50.
|
||||||
|
Рассмотрим следующую ситуацию. В ноябре сайт посетили 100 мужчин и 100
|
||||||
|
женщин, при этом из них заявки оставили 10 мужчин и всего 5 женщин.
|
||||||
|
1. Посчитайте конверсии для мужчин и для женщин из захода на сайт
|
||||||
|
в оформление заявки.
|
||||||
|
2. Посчитайте общую конверсию для всех пользователей.
|
||||||
|
3. В декабре была проведена дополнительная рекламная компания, и общее
|
||||||
|
число зашедших на сайт стало больше. При этом конверсия для мужчин стала
|
||||||
|
равна 12%, а для женщин — 7%. Может ли быть такое, что общая конверсия
|
||||||
|
в декабре упала? Если да, то приведите численный пример. Если нет —
|
||||||
|
докажите.
|
||||||
|
4. При условии увеличения конверсий у мужчин и у женщин до 12% и 7%
|
||||||
|
соответственно в каком интервале будет лежать общая конверсия? Обоснуйте
|
||||||
|
свой ответ.
|
||||||
|
""".strip(),
|
||||||
"type": CompetitionTask.CompetitionTaskType.INPUT.value,
|
"type": CompetitionTask.CompetitionTaskType.INPUT.value,
|
||||||
"points": 3,
|
"points": 3,
|
||||||
"submission_reviewers_count": 2,
|
"submission_reviewers_count": 2,
|
||||||
"max_attempts": 20,
|
"correct_answer_file": ans2,
|
||||||
"correct_answer_file": ans2
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"title": "Задача 2",
|
"title": "Задача 2",
|
||||||
"description": """
|
"description": """
|
||||||
Напишите отзыв про DANO(Хороший)
|
Каждый день Дима звонит в пекарню, чтобы узнать, есть ли сегодня в продаже его
|
||||||
""".strip(),
|
любимые булочки с повидлом. За последние 3 дня булочки были в наличии 2 раза,
|
||||||
|
а 1 раз их не было.
|
||||||
|
Пусть переменная Х = 0, если булочек нет, и Х = 1, если булочки есть. Наличие
|
||||||
|
булочек в конкретный день не зависит от наличия булочек в любой другой день.
|
||||||
|
1. Сколько наблюдений собрал Дима? Выпишите все значения из его выборки
|
||||||
|
через запятую. Посчитайте для этой выборки среднее значение Х, дисперсию Х.
|
||||||
|
В какой доле случаев булочки были в наличии?
|
||||||
|
2. Пусть p — вероятность того, что булочки в наличии (p не может быть меньше 0
|
||||||
|
и больше 1. Например, p может быть равно 0,2 = 1/5 — то есть в одном из пяти
|
||||||
|
случаев булочки в наличии). Чему равна вероятность, что сегодня булочки
|
||||||
|
есть, а завтра их не будет? Чему равна вероятность, что за два дня в один день
|
||||||
|
булочки будут, а в другой — не будут? (Напишите два выражения, зависящие
|
||||||
|
от p.)
|
||||||
|
3. Чему равна вероятность получения наблюдений как у Димы? (Напишите одно
|
||||||
|
выражение, зависящее от p.)
|
||||||
|
4. При каком значении p вероятность получить выборку как у Димы максимальна?
|
||||||
|
Вычислите его. Как это значение соотносится с наблюдениями Димы?
|
||||||
|
5. Дима нашел значение p из предыдущего пункта и сделал вывод, что
|
||||||
|
на следующий день булочки испекут с вероятностью p. Верный ли вывод сделал
|
||||||
|
Дима? Поясните свой ответ.
|
||||||
|
6. Рядом с домом Димы открыли новую пекарню, где тоже делают булочки
|
||||||
|
с повидлом. Дима решил сравнить две пекарни. Для этого он собрал выборку
|
||||||
|
за 100 дней: в новой пекарне булочки были в наличии 70 дней, в старой — 60
|
||||||
|
дней. Какую гипотезу может проверить Дима? Какой механизм, может лежать
|
||||||
|
в основе этой гипотезы? При описании механизма вы можете сами дополнить
|
||||||
|
историю Димы (например, предположить расположение старой пекарни,
|
||||||
|
себестоимость повидла и другое, что могло бы помочь объяснить гипотезу,
|
||||||
|
необязательно рассматривать приведенные примеры). Помогите Диме
|
||||||
|
проверить описанную вами гипотезу. Есть ли разница в производительности
|
||||||
|
между новой пекарней и старой?
|
||||||
|
""".strip(),
|
||||||
"type": CompetitionTask.CompetitionTaskType.REVIEW.value,
|
"type": CompetitionTask.CompetitionTaskType.REVIEW.value,
|
||||||
"points": 15,
|
"points": 15,
|
||||||
"submission_reviewers_count": 2,
|
"submission_reviewers_count": 2,
|
||||||
"max_attempts": 1,
|
|
||||||
"criteries": [
|
"criteries": [
|
||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"name": "Хорошесть отзыва",
|
"name": "Хорошесть отзыва",
|
||||||
"slug": "validity",
|
"slug": "validity",
|
||||||
"description": "Хорошесть",
|
"description": "Критерий качества отзыва",
|
||||||
"max_value": 10
|
"max_value": 10,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"name": "Подробность",
|
"name": "Подробность",
|
||||||
"slug": "detail",
|
"slug": "detail",
|
||||||
"description": "Насколько подробно расписан ответ.",
|
"description": "Насколько подробно расписан ответ",
|
||||||
"max_value": 5
|
"max_value": 5,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"obj": None,
|
"obj": None,
|
||||||
"title": "Задача 3",
|
"title": "Задача 3",
|
||||||
"description": """
|
"description": """
|
||||||
Напишите выведите 1+3 на питоне
|
Вы аналитик ведущей игровой компании GameMasters Inc., которая
|
||||||
""".strip(),
|
специализируется на разработке мобильных игр. Ваши коллеги разработали
|
||||||
|
обновленный игровой магазин, в котором игроки могут приобретать внутриигровые
|
||||||
|
предметы и суперспособности. Ваша задача — провести сравнение, чтобы
|
||||||
|
определить, как внедрение нового магазина повлияло на поведение пользователей
|
||||||
|
в игре.
|
||||||
|
Для этого пользователи были разделены на две равные группы случайным образом:
|
||||||
|
А — пользователи, которым доступен только старый магазин;
|
||||||
|
B — пользователи, которым доступен только обновленный магазин.
|
||||||
|
Спустя месяц после запуска по каждому пользователю из каждой группы были
|
||||||
|
посчитаны следующие метрики:
|
||||||
|
‘revenue_per_user’ — доход, который был получен от пользователя за период;
|
||||||
|
‘orders_cnt_per_user’ — количество заказов, которое совершено пользователем
|
||||||
|
за период;
|
||||||
|
‘converted_from_main_screen_to_item_card_screen’ — флаг захода на экран
|
||||||
|
с товарами (0 — если пользователь не заходил на карточку товара, 1 — если
|
||||||
|
заходил).
|
||||||
|
В таблице приведены значения этих метрик. Также в ней находится столбец ‘group’,
|
||||||
|
в котором указано, к какой группе (A или B) относится пользователь и столбец
|
||||||
|
‘period’ — характеризующий значение метрик до начала теста и во время проведения
|
||||||
|
теста. На карточке товара содержится дополнительная информация, фотография
|
||||||
|
и его характеристики. Однако оплатить товар можно и без захода на карточку
|
||||||
|
товара.
|
||||||
|
Задача: сравните группы по каждой метрике и сделайте вывод о том, стоит ли
|
||||||
|
продолжить внедрение обновленного магазина или нужно вернуть старый
|
||||||
|
""".strip(),
|
||||||
"type": CompetitionTask.CompetitionTaskType.CHECKER.value,
|
"type": CompetitionTask.CompetitionTaskType.CHECKER.value,
|
||||||
"points": 30,
|
"points": 30,
|
||||||
"submission_reviewers_count": 2,
|
"submission_reviewers_count": 2,
|
||||||
"max_attempts": 100,
|
},
|
||||||
}
|
],
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
|
"obj": None,
|
||||||
|
"title": "Data Challenge 2025(FAKE DANO)",
|
||||||
|
"description": """
|
||||||
|
Ну типо дано
|
||||||
|
""".strip(),
|
||||||
|
"start_date": now - timedelta(days=1),
|
||||||
|
"end_date": now + timedelta(days=10),
|
||||||
|
"type": "competitive",
|
||||||
|
"participation_type": "solo",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"obj": None,
|
||||||
|
"title": "Анализ трендов", # TODO сюда добавить бд
|
||||||
|
"description": """
|
||||||
|
Скачайте базу данных со специальной страницы (https://dano.hse.ru/data), изучите ее более
|
||||||
|
внимательно: посмотрите на переменные, посчитайте описательные статистики, постройте
|
||||||
|
предварительные графики и таблицы, обратите внимание на выбросы.
|
||||||
|
Продумайте все детали: исследовательский вопрос, гипотезу, механизм и пр.
|
||||||
|
Разработайте дизайн исследования:
|
||||||
|
• что вам нужно для того, чтобы ответить на исследовательский вопрос
|
||||||
|
• что нужно чтобы проверить ту или иную гипотезу
|
||||||
|
• какие таблицы и графики вам понадобятся
|
||||||
|
• какую информацию из них можно извлечь
|
||||||
|
• как интерпретировать получаемые результаты
|
||||||
|
• помогает ли это в вашем исследовании
|
||||||
|
• несет ли полезную информацию
|
||||||
|
• действительно ли эти построенные таблицы и графики необходимы и продвигают ваш
|
||||||
|
проект или может быть необходимы другие
|
||||||
|
• какие методы и модели вам нужны
|
||||||
|
• в какой последовательности выполнять все расчеты и построения
|
||||||
|
Обращайте особое внимание на то, что все эти процедуры должны быть оправданы и
|
||||||
|
продвигать вас в направлении поиска ответа на исследовательский вопрос.
|
||||||
|
Распределите задачи между членами команды. Установите сроки. Придерживайтесь взятых
|
||||||
|
на себя обязательств и данных друг другу обещаний – делайте все в срок. Обсуждайте между
|
||||||
|
собой полученные результаты, ищите наиболее удачный способ проверить ваши гипотезы,
|
||||||
|
наиболее удачные графики и таблицы. Советуйтесь с ментором, обращайтесь к нему за
|
||||||
|
помощью – его задача помочь вам отобрать правильные идеи и подсказать как их технически
|
||||||
|
реализовать.
|
||||||
|
Заведите общее облачное пространство, где будут хранится все ваши результаты.
|
||||||
|
Структурируйте, создавайте необходимые папки, называйте папки и документы говорящими
|
||||||
|
именами, оставляйте комментарии
|
||||||
|
""".strip(),
|
||||||
|
"type": CompetitionTask.CompetitionTaskType.REVIEW.value,
|
||||||
|
"points": 20,
|
||||||
|
"submission_reviewers_count": 3,
|
||||||
|
"max_attempts": 2,
|
||||||
|
"attachment": dataset,
|
||||||
|
"attachment_path": "dataset",
|
||||||
|
"criteries": [
|
||||||
|
{
|
||||||
|
"obj": None,
|
||||||
|
"name": "Качество анализа",
|
||||||
|
"slug": "analysis_quality",
|
||||||
|
"description": "Глубина анализа данных",
|
||||||
|
"max_value": 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"obj": None,
|
||||||
|
"name": "Обоснованность выводов",
|
||||||
|
"slug": "insight",
|
||||||
|
"description": "Логичность выводов",
|
||||||
|
"max_value": 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"obj": None,
|
||||||
|
"title": "Ещё задачка",
|
||||||
|
"description": """
|
||||||
|
Как известно, Израиль является одной из лидирующих стран по темпам вакцинации. По
|
||||||
|
данным на июнь 2021 г. в стране вакцинировано 60% граждан (85% взрослого населения).
|
||||||
|
Однако среди заразившихся в этом же месяце (июне 2021 года), как признали власти
|
||||||
|
Израиля, примерно половина была уже вакцинирована. Что можно сказать об
|
||||||
|
эффективности вакцины на основании этих данных?
|
||||||
|
1) Данные не свидетельствуют об эффективности вакцины, т. к. вероятность
|
||||||
|
заразиться составляет 50%, независимо от того, вакцинировался человек или нет
|
||||||
|
2) Данные не свидетельствуют об эффективности вакцины, т. к. среди
|
||||||
|
вакцинированных есть заразившиеся
|
||||||
|
3) Данные свидетельствуют об эффективности вакцины, т. к. если бы она не работала,
|
||||||
|
доля вакцинированных среди заболевших была бы равна доле вакцинированных
|
||||||
|
среди всего населения страны
|
||||||
|
4) Данные свидетельствуют об эффективности вакцины, т. к. вакцинированные
|
||||||
|
переносят болезнь в более легкой форме
|
||||||
|
""".strip(),
|
||||||
|
"type": CompetitionTask.CompetitionTaskType.INPUT.value,
|
||||||
|
"points": 15,
|
||||||
|
"submission_reviewers_count": 2,
|
||||||
|
"max_attempts": 50,
|
||||||
|
"correct_answer_file": ans3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"obj": None,
|
||||||
|
"title": "Быстрый ответ",
|
||||||
|
"description": "Сколько будет 6 * 7?",
|
||||||
|
"type": CompetitionTask.CompetitionTaskType.INPUT.value,
|
||||||
|
"points": 5,
|
||||||
|
"submission_reviewers_count": 2,
|
||||||
|
"max_attempts": 10,
|
||||||
|
"correct_answer_file": ans3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
users = [
|
users = [
|
||||||
@@ -222,20 +442,163 @@ users = [
|
|||||||
"username": "dreamonovich",
|
"username": "dreamonovich",
|
||||||
"password": "password123!",
|
"password": "password123!",
|
||||||
"role": UserRole.STUDENT.value,
|
"role": UserRole.STUDENT.value,
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"email": "alisa.kuznetsova@gmail.com",
|
||||||
|
"username": "alisa_kuz",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "ivan.petrov@gmail.com",
|
||||||
|
"username": "ivan_petrov",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "olga.sidorova@gmail.com",
|
||||||
|
"username": "olga_sid",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "karim@gmail.com",
|
||||||
|
"username": "karim",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "noble@gmail.com",
|
||||||
|
"username": "noble",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "koller@gmail.com",
|
||||||
|
"username": "koller",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "gold_checker@gmail.com",
|
||||||
|
"username": "gold_checker",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "looka@gmail.com",
|
||||||
|
"username": "looka",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "danil_malikov@gmail.com",
|
||||||
|
"username": "danil_malikov",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "marina-looks@gmail.com",
|
||||||
|
"username": "marina-looks",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "pasha@gmail.com",
|
||||||
|
"username": "pasha",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "oleg-tinkov@gmail.com",
|
||||||
|
"username": "oleg-tinkov",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"email": "baron_ivanych@gmail.com",
|
||||||
|
"username": "baron_ivanych",
|
||||||
|
"password": "password123!",
|
||||||
|
"role": UserRole.STUDENT.value,
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
reviewers = [
|
reviewers = [
|
||||||
{
|
{
|
||||||
"name": "Владислав",
|
"name": "Владислав",
|
||||||
"surname": "Пикиневич",
|
"surname": "Пикиневич",
|
||||||
"token": "aa443163-9861-4b8d-b8f7-81ecd25f6088"
|
"token": "aa443163-9861-4b8d-b8f7-81ecd25f6088",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Александр",
|
"name": "Александр",
|
||||||
"surname": "Шахов",
|
"surname": "Шахов",
|
||||||
"token": "d2e8904a-01dd-4f84-a8b0-8a60f1a3b6c0"
|
"token": "d2e8904a-01dd-4f84-a8b0-8a60f1a3b6c0",
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"name": "Мария",
|
||||||
|
"surname": "Иванова",
|
||||||
|
"token": "e3f8904a-23cd-4f84-a8b0-9b70f1a4b7d1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Сергей",
|
||||||
|
"surname": "Смирнов",
|
||||||
|
"token": "f4g9015b-45de-5g95-b9c1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Паша",
|
||||||
|
"surname": "Проверкин",
|
||||||
|
"token": "f4g9015b-45de-5g95-b9c1-0c81g2b3c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Илья",
|
||||||
|
"surname": "Продкин",
|
||||||
|
"token": "f4g9015b-45de-5g95-b8c1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Влад",
|
||||||
|
"surname": "Проверкин",
|
||||||
|
"token": "f4g9015b-45de-5g95-b9c1-0c81g2b5c8e1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Сашка",
|
||||||
|
"surname": "Пашкин",
|
||||||
|
"token": "f4g9015b-45de-5g95-b9c1-1c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Чарльз",
|
||||||
|
"surname": "Проверкин",
|
||||||
|
"token": "b4g9015b-45de-5g95-b9g1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Тимурка",
|
||||||
|
"surname": "Проверкин",
|
||||||
|
"token": "f4g9015b-25de-5g95-b9c1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Александр",
|
||||||
|
"surname": "Даношкин",
|
||||||
|
"token": "f4g9015t-45de-5g95-b9c1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Паша",
|
||||||
|
"surname": "Проверкин",
|
||||||
|
"token": "f4g9015r-45de-5g95-b9c1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Лука",
|
||||||
|
"surname": "Проверкин",
|
||||||
|
"token": "f4g9015e-45de-5g95-b9c1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Кирилл",
|
||||||
|
"surname": "Проверкин",
|
||||||
|
"token": "f4g9015w-45de-5g95-b9c1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Олег",
|
||||||
|
"surname": "Проверкин",
|
||||||
|
"token": "f4g9015q-45de-5g95-b9c1-0c81g2b5c8e2",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
@@ -251,6 +614,8 @@ class Command(BaseCommand):
|
|||||||
self.create_states(competitions, users)
|
self.create_states(competitions, users)
|
||||||
self.stdout.write("Data generation completed.")
|
self.stdout.write("Data generation completed.")
|
||||||
|
|
||||||
|
f.close()
|
||||||
|
|
||||||
def create_reviewers(self, count):
|
def create_reviewers(self, count):
|
||||||
reviewers_objs = []
|
reviewers_objs = []
|
||||||
for reviewer in reviewers:
|
for reviewer in reviewers:
|
||||||
@@ -290,6 +655,10 @@ class Command(BaseCommand):
|
|||||||
participation_type=competition['participation_type'],
|
participation_type=competition['participation_type'],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if competition.get("image"):
|
||||||
|
competition_obj.image_url = competition['image']
|
||||||
|
competition_obj.save()
|
||||||
|
|
||||||
competitions[i]['obj'] = competition_obj
|
competitions[i]['obj'] = competition_obj
|
||||||
competition_obj.participants.add(*users)
|
competition_obj.participants.add(*users)
|
||||||
competitions_objs.append(competition_obj)
|
competitions_objs.append(competition_obj)
|
||||||
@@ -306,19 +675,26 @@ class Command(BaseCommand):
|
|||||||
for i, competition in enumerate(competitions):
|
for i, competition in enumerate(competitions):
|
||||||
for j, task in enumerate(competition['tasks']):
|
for j, task in enumerate(competition['tasks']):
|
||||||
task_obj = CompetitionTask.objects.create(
|
task_obj = CompetitionTask.objects.create(
|
||||||
in_competition_position=j,
|
in_competition_position=j+1,
|
||||||
competition=competition['obj'],
|
competition=competition['obj'],
|
||||||
title=task['title'],
|
title=task['title'],
|
||||||
description=task['description'],
|
description=task['description'],
|
||||||
type=task['type'],
|
type=task['type'],
|
||||||
points=task['points'],
|
points=task['points'],
|
||||||
submission_reviewers_count=task['submission_reviewers_count'],
|
submission_reviewers_count=task['submission_reviewers_count'],
|
||||||
max_attempts=task['max_attempts'],
|
max_attempts=task.get('max_attempts'),
|
||||||
)
|
)
|
||||||
competitions[i]['tasks'][j]['obj'] = task_obj
|
competitions[i]['tasks'][j]['obj'] = task_obj
|
||||||
|
|
||||||
if task['type'] == CompetitionTask.CompetitionTaskType.INPUT.value:
|
if task['type'] == CompetitionTask.CompetitionTaskType.INPUT.value:
|
||||||
task_obj.correct_answer_file = task['correct_answer_file']
|
task_obj.correct_answer_file = task['correct_answer_file']
|
||||||
|
if task.get("attachment"):
|
||||||
|
CompetitionTaskAttachment.objects.create(
|
||||||
|
task=task_obj,
|
||||||
|
file=task['attachment'],
|
||||||
|
bind_at=task['attachment_path'],
|
||||||
|
public=True
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
task['type']
|
task['type']
|
||||||
@@ -383,4 +759,4 @@ class Command(BaseCommand):
|
|||||||
)
|
)
|
||||||
self.stdout.write(
|
self.stdout.write(
|
||||||
f"Created state '{state_obj.state}' for user '{user.username}' in competition '{comp.title}'"
|
f"Created state '{state_obj.state}' for user '{user.username}' in competition '{comp.title}'"
|
||||||
)
|
)
|
||||||
Reference in New Issue
Block a user