diff --git a/README.md b/README.md index 48f42e21..6b8725a4 100644 --- a/README.md +++ b/README.md @@ -10,3 +10,98 @@ ## Задания - [Часть 1. Генератор идентификаторов Twitter Snowflake](src/part1/TASK.md) — нужно написать генератор 64-битных числовых идентификаторов, в которые упакованы метка времени, номер узла и счётчик последовательности. Такие идентификаторы уникальны и примерно упорядочены по времени, а из самого идентификатора можно узнать, когда и на каком узле он был создан. + +## Критерии оценивания + +Максимальный балл за каждое задание — **10**. Правильность решения проверяется закрытыми тестами. + +### Условия принятия работы + +Работа принимается к оцениванию, только если выполнены **все** условия: + +- код проходит проверки [ruff](https://docs.astral.sh/ruff/) и [MyPy](https://mypy-lang.org/) (запустить их можно [локально](manuals/local_checks.md)); +- работа сдана до дедлайна. + +Если хотя бы одно условие не выполнено, работа не принимается и оценивается в 0 баллов. + +### Как считается балл за правильность + +Тесты разбиты на функциональные блоки: каждый блок соответствует функции или классу из задания и имеет свой вес (более сложные блоки весят больше). Внутри блока тесты делятся на две группы: + +| Группа тестов | Доля веса блока | Что проверяет | +|---|---|---| +| Базовые (типичные входные данные) | 70% | Основная логика реализована верно | +| Граничные (пустой ввод, нулевые и предельные значения, повторы и т. п.) | 30% | Обработка особых случаев | + +Формулы: + +``` +балл_блока = 0.7 · доля_пройденных_базовых + 0.3 · доля_пройденных_граничных +балл_за_правильность = 10 · Σ(вес_блока · балл_блока) / Σ(вес_блока) +``` + +Дополнительные правила: + +- **Нереализованный функционал.** Блок, в котором функционал не реализован (заглушка, `pass`, `NotImplementedError`), получает 0 баллов. Остальные блоки оцениваются как обычно, дополнительного штрафа за нереализованное нет. +- **Ошибки выполнения.** Тест, в котором возникло необработанное исключение, считается проваленным. +- **Зависание.** У каждого теста есть ограничение по времени выполнения. Если решение не укладывается в него (например, из-за бесконечного цикла), тест считается проваленным. + +### Штрафы за оформление + +Кроме правильности, оценивается качество кода. За нарушения ниже из балла за правильность вычитаются штрафы. Каждое нарушение штрафуется **один раз**, сколько бы раз оно ни встретилось в работе. + +У каждого нарушения есть уникальный код: `S` — серьёзные, `M` — средние, `T` — типовые. При проверке преподаватель указывает в комментарии к работе только коды (например, `S1, M2, T1`), а расшифровку и штраф можно найти в таблицах ниже. + +#### Серьёзные нарушения (−1 балл за каждое) + +| Код | Нарушение | Что имеется в виду | +|---|---|---| +| `S1` | Копипаста | Вместо вынесения повторяющейся логики в функцию, метод или цикл один и тот же (или почти тот же) код скопирован несколько раз. Мешает расширяемости: любое изменение приходится вносить во все копии | +| `S2` | Слишком длинные функции | Функция делает много разных вещей одновременно (вычисления, проверки, преобразования, форматирование в одном месте) и не читается целиком. Ориентир: более 30–40 строк или несколько несвязанных обязанностей. Такой код тяжело читать и поддерживать | +| `S3` | Магические значения | Числа и строки с неочевидным смыслом прописаны прямо в коде, а не вынесены в именованные константы. Как и копипаста, мешает расширяемости: значение приходится искать и менять по всему коду | +| `S4` | Слишком широкий перехват исключений | Голый `except:` или `except Exception:` без необходимости; молча проглоченные ошибки (`except ...: pass`). Так можно пропустить что-то важное | +| `S5` | Изменение входных данных | Функция неожиданно изменяет переданные ей аргументы, хотя из названия и описания это не следует. Неожиданное поведение, источник серьёзных ошибок | + +#### Средние нарушения (−0.5 балла за каждое) + +| Код | Нарушение | Что имеется в виду | +|---|---|---| +| `M1` | Большая вложенность | Более трёх уровней вложенности (`if`, `for`, `while`, `try`, `with`) внутри одной функции. Лечится ранним возвратом (`return`, `continue`) и выносом логики в отдельные функции | +| `M2` | Неинформативные имена | Имена вроде `a`, `tmp`, `data2`, `x1`, а также имена, не отражающие суть, или не соответствующие PEP 8 (например, `camelCase` для функций и переменных) | +| `M3` | Избыточные глобальные переменные | Изменяемое глобальное состояние там, где достаточно параметров, возвращаемых значений или атрибутов класса | +| `M4` | Мёртвый код | Код, который нигде не используется: неиспользуемые функции, классы, переменные, константы, импорты, недостижимые ветки. Сюда же относятся крупные куски закомментированного кода «на будущее» и оставленный отладочный `print`. Затрудняет чтение, но на работу программы не влияет | + +#### Типовые нарушения хорошего тона (−0.25 балла за каждое) + +| Код | Нарушение | +|---|---| +| `T1` | `else` или `elif` после `return`, `raise`, `continue` или `break` | +| `T2` | Явное приведение к `bool` в условиях (`if bool(x):`) и сравнение с `True` / `False` (`if x == True:`) | +| `T3` | Сравнение с синглтонами и членами enum'ов через `==` / `!=` вместо `is` / `is not` | +| `T4` | Проверка пустоты коллекции через `len(x) == 0` вместо `if not x` | +| `T5` | Обход через `for i in range(len(items))`, когда индекс не нужен (вместо `for item in items` или `enumerate`) | +| `T6` | `if cond: return True else: return False` вместо `return cond` | +| `T7` | Изменяемое значение по умолчанию у аргумента (`def f(x=[])`) | +| `T8` | Ручная конкатенация строк вместо f-строк | +| `T9` | Избыточные комментарии, пересказывающие очевидный код | + +### Штраф за списывание + +Если работа подозревается в списывании, студент получает **−5 баллов**. Эти баллы не вычитаются из оценки за правильность, а **заменяют** итоговую оценку: итоговой оценкой становится −5, независимо от результата тестов. + +Студент может оспорить этот балл на занятии, доказав, что не списывал, а написал код самостоятельно (например, объяснив решение и ответив на вопросы по нему). Если подозрение снимается, работа оценивается по обычным критериям. + +### Итоговая оценка + +``` +если есть подозрение в списывании: + итоговая_оценка = −5 +иначе: + итоговая_оценка = max(0, балл_за_правильность − штрафы_за_оформление) +``` + +Итоговая оценка за домашнее задание округляется до ближайшего целого по правилам математики: дробная часть от 0.5 и выше округляется вверх, меньше 0.5 — вниз (например, 7.5 → 8, 7.4 → 7). + +### Как оспорить оценку + +Если вы не согласны с оценкой, напишите преподавателю. Укажите, с каким блоком или с какой частью критериев вы не согласны, и приведите аргументы. Оценка пересматривается по тем же критериям, которые описаны выше.