Вкратце мой бэкграунд - с 2010г в качестве хобби разрабатывал всякие разные проекты для себя на энтузиазме, успел немного пофрилансить на апворке в 2015г, но серьезного опыта работы по найму в IT не было, в связи с чем я не в курсе какие цены сейчас считаются нормальными и почти не имею опыта общения с клиентами. Затем был большой перерыв в несколько лет, и вернулся в программирование только в этом году. Кароче говоря, я не суперспец 300к/наносек, но и не зеленый новичок.
Ко мне обратился близкий друг, репетитор, с просьбой сделать сайт для автоматизации работы с группами учеников - выдавать домашку, проверять её, составлять отчеты, и т.д.
Я предложил сделать бота в телеге чтобы не запариваться с дизайном и версткой, регистрацией и прочией рутиной, а сосредоточиться непосредственно на нашем функционале. Да и ученикам так будет удобнее.
Срок - до 4 сентября (начало этого учебного года).
ТЗ и какого-то конкретного функционала согласовано не было, соответственно и четких сроков я назвать не мог, хоть и всё это казалось достаточно простым делом.
Изучал фреймворк для создания ТГ-ботов, продумывал архитектуру программы и экспериментировал пару-тройку недель (всё таки это новая для меня сфера), но засекать время начал только во время написания непосредственно кода для проекта. В дальнейшем аналогично засекал время только при непосредственном наборе кода и дебаге, но не когда думал над алгоритмами или тупил, не зная что дальше делать.
Пока что не могу выложить исходники, но было сделано следующее:
spoiler1. чтобы начать пользоваться ботом, репетитор выдаёт инвайты для учеников, ученик может авторизоваться по инвайту. соответственно, механизм авторизации различающий гостей / учеников / репетитора
2. создание, переименование и удаление групп
3. переименование и блокировка учеников (для тех кто не оплатил занятия).
4. добавление учеников в группы
5. рассылка сообщений всей группе, в т.ч. медиа, стикеров, голосовых, кружочков, и тд. сообщения не рассылаются заблокированным и тем кто ещё не активировал инвайт.
6. загрузка домашки в бота. домашка представляет из себя ряд картинок с изображенными на них заданиями (типа "найдите значение выражения") и в названии картинки записан правильный ответ, который парсит бот и заносит в БД. картинки загружаются в zip архиве. zip разархивируется через bsdtar для поддержки виндовых кодировок. при возникновении ошибок разархивирования zip текст ошибки будет показан репетитору. каждое изображение проверяется на формат (только png), ограничения телеги (размер и разрешение), наличие правильного ответа в названии, является ли правильный ответ float 32, и для каждого задания отдельно показывается текст ошибки, чтобы репетитор мог оперативно выявить проблемы и исправить их. кроме того, с помощью imagemagick при необходимости изменяется соотношение сторон картинки, т.к. слишком длинные картинки телега не позволяет загружать, а те которые позволяет -
уродует. Кроме того, есть ещё задания второго типа, где ученик должен решить задачу в тетради и выслать решение боту. Тогда в названии картинки (в zip архиве) мы ищем не правильный ответ, а максимальный балл за это задание (для отчета)
7. рассылка домашки всем ученикам группы. домашка не рассылается заблокированным, тем кто её уже решил и тем кто ещё не активировал инвайт. можно отменить рассылку если она была по ошибке. при получении домашки все ученики получают уведомление.
8. ученик выбирает домашку для решения и для заданий первого типа просто вбивает ответы, а для второго - отправляет фотки с решением (до 10 штук). соответственно, для некорректных ответов показываем предупреждение. ученик может пропустить задание и вернуться к нему позднее, бот будет ротировать пропущенные задания, не показывая ему одно и то же подряд. после решения домашки репетитор получает уведомление. для заданий первого типа ученик сразу видит результаты - какие ответы правильные, а какие - нет. для заданий второй части видит строку "ожидает проверки". из-за ограничений телеги при выводе заданий кэшируется file-id изображений.
9. репетитор может просматривать результаты решения домашек. для заданий второго типа видит фотки ученика. если фоток несколько - телега не спамит ими, а объединяет в медиа-группу. репетитор может скачать эти фото к себе на ПК, отметить ошибки ученика (например красным цветом) и отправить ученику новые изображения. кроме того, для каждого задания учитель может поставить оценку. соответственно, после оценивания ученик получит уведомление и сможет увидеть новые фото и свои оценки, здесь функционал зеркален.
10. для гостей, учеников и репетитора - команда /help с разным содержанием
Соответственно, всё это получилось не сразу. Изначально планировался неудобный интерфейс с десятками команд телеги, в которых черт ногу сломит. Пользоваться этим было невозможно, поэтому я упростил интерфейс до четырех команд, которые показывают удобные inline-меню с отображением списков групп, учеников, домашек и ответов учеников. Для этих списков был написан пагинатор с возможностью сортировать элементы по дате либо по имени, отображать иконки рядом с элементами для обозначения статуса (разные иконки в разных контекстах), с возможностью возвращаться обратно на ту же страницу с той же сортировкой, и всё это пришлось умудриться впихнуть в 64 байта поля параметров телеги, притом что меню могут быть довольно многоуровневыми.
Естественно, для всего этого - диспетчеризация команд с десятками состояний и авторизацией учеников и репетитора, и десятки функций для связи с БД. И разбиение длинных сообщений на части по строкам, т.к. телега не позволяет отправлять более 4000тыс символов за раз.
Суммарно вышло 4412 строк кода на rust (хотя это мало о чем говорит, мы ж не индусы чтоб результат по кол-ву строк оценивать).
В результате я не вписался в сроки и сдал проект через неделю от дедлайна. Насчитал 91 час (без учета времени на проектирование и дообучение). Зная положение друга, его доходы, наличие кредитов и тд, не стал наглеть и посчитал всё по минимальной для себя ставке 500р/час. Округлив, получаем 50к руб с запасом для торга. Соответственно, 45тыр я бы счел достойной оплатой моего труда, а нижняя планка - 40тыр. В итоге, с учетом просрочки, я согласился на скидку до 45к, но т.к. друг не имеет возможности выдать такую сумму здесь и сейчас и предложил разбить эту сумму аж до мая следующего года. Я в ответ предложил ещё уступить до 40к но закрыть всё до конца этого года.
На этом бы всё закончили, но есть ощущение, будто у него осадочек остался. Понятно по какой причине - ТЗ мы не согласовывали, объемов работ оговорено не было, никаких трекеров я не запускал и экран не записывал. Даже в git историю изменений не записывал, т.к. не было времени на всё это, да и толку мало когда не в команде работаешь и в опенсорс публиковать не будешь. Человек явно рассчитывал услышать сумму гораздо меньшую, чем 50к.
Но свою цену я взял не с потолка, а исходя из отработанных часов. Соответственно, где я мог соврать? В почасовой ставке, в оценке кол-ва отработанных часов и что проектирование и реализация этого функционала реально требует 90 часов.
1. почасовая ставка. сейчас глянул цены на фрилансе, дешевле 500р/час никто не работает. тут я максимально уступил, если считать по рыночным ценам - я бы себя оценил где-то в 1500р/час, учитывая свой опыт и навыки
2. по кол-ву отработанных часов я опять же максимально уступил, учитывая что обычно у фрилансеров принято учитывать не только программирование и дебаг, но и проектирование, и даже обучение и общение с клиентом. по крайней мере, те кто работал на апворке советовали делать так.
3. можно ли было сделать быстрее? а вот ради этого и задаю вопрос.
Помогите понять пожалуйста, это я себя недооцениваю, или же реально загнул с ценой?
Вы бы какую цену назвали за такое ТЗ?