ПитательныйБот или как я хочу отобрать хлеб у фитнес-тренеров

    Всем привет! Все разработчики сталкиваются однажды с желанием покодить что-нибудь для себя, и даже становится неважна материальная ценность продукта, главное, что оно работает само по себе. Кайф.  

    Так и мне, одиноким майским отпуском, захотелось объединить знания кодинга и какие-нибудь другие, жизненные, в один проект. Получился, на мой взгляд, интересный сервис, которому хочу дать жизнь и рассказать об этом. 

    Я не диетолог, не профессиональный спортсмен и, конечно, не претендую на то, что мне без вопросов будут доверять. Но, однажды, меня сильно заинтересовала тема правильного питания, и я начала изучать статьи, общаться с крутыми тренерами в залах, которые посещала, и заметила такую вещь: люди тратят немаленькие деньги за составление планов питания.

    И я решила: а создам-ка я такую систему, которая будет автоматически высчитывать людям продукты в граммах, в зависимости от их цели и параметров.

    Так как я бэкенд разработчик, с фронтом сталкиваюсь редко, обдумала и решила сделать бота. На выбор мессенджера повлияли несколько факторов: востребованность и наличие платежных систем. Подошла социальная сеть Вконтакте.

    Для расчетов я использовала формулу Харриса- Бенедикта. В учет брала такие входные параметры ( которые пользователь бота вводит):

    • Вес
    • Рост
    • Цель (похудеть/ набрать массу/ поддерживать)
    • Физическая активность (вся информация доступная и стандартная для расчетов по формуле Харриса-Бенедикта)
    • Переносимость лактозы
    • Пол

    Создала базу продуктов, в которой у продукта были поля: Белки, Жиры, Углеводы, Ккал, ГИ (гликемический индекс), а также содержание лактозы. Вообще, хочу привести листинг и по ходу комментировать.

    У Вконтакте доступный и понятный API

    Использовала язык PHP.

    Во-первых, определила несколько нужных функций и констант:

    header('Content-Type: text/html; charset=utf-8');
    $request = file_get_contents("php://input"); 
    $input = json_decode($request, true);
    
    define('VK_API_VERSION', '5.95'); //Используемая версия API 
    define('VK_API_ENDPOINT', "https://api.vk.com/method/"); 
    
    //Функция для вызова произвольного метода API 
    function _vkApi_call($method, $params = array()) { 
      $params['access_token'] = //Тут должен быть ваш токен, который вы получаете при создании бота в паблике; 
      $params['v'] = VK_API_VERSION; 
      $url = VK_API_ENDPOINT.$method.'?'.http_build_query($params); 
      $curl = curl_init($url); 
      curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
      $json = curl_exec($curl); 
      curl_close($curl); 
      $response = json_decode($json, true); 
      return $response['error']['error_msg']; 
      $err=$response['error']['error_msg'];
    } 
    
    //Функция для вызова messages.send 
    function vkApi_messagesSend($peer_id, $message) { 
     return _vkApi_call('messages.send', array( 
     'peer_id' => $peer_id, 
     'user_id' => $peer_id, 
     'message' => $message, 
     'random_id' => rand(), 
     'qroup_id' => //Здесь должен быть айдишник вашей группы (паблика)    
      ));} 
    
    //Функция для отправки кнопок с сообщением
    function vkApi_buttonSend($peer_id, $message,$button) { 
    return _vkApi_call('messages.send', array( 
    'peer_id' => $peer_id, 
    'user_id' => $peer_id, 
    'message' => $message, 
    'random_id' => rand(), 
    'keyboard' => $button, 
    'qroup_id' => //Здесь должен быть айдишник вашей группы (паблика)       
      ));} 
    

    В настройках бота вы указывается ссылку на свой скрипт (вебхук). Кстати, в API VK можно использовать два метода для получения сообщений. Я использовала вебхуки. Мне кажется, что это удобнее, привычнее.

    Далее обрабатываю полученный json.

    $test_type=$input['type'];
    $test_group_id=$input['group_id'];
    $user_id=$input['object']['user_id'];
    $text=$input['object']['body'];
    $text_body=explode(" ", $text);
    
    $vk_pay=$text_body[0];
    $caption=$input['object']['attachments'][0]['link']['caption'];
    $url=$input['object']['attachments'][0]['link']['url'];
    $str3=$input['object']['attachments'][0]['link']['title'];
    $str2 = explode(" ", $str3);
    $money =(int)$str2[0];
    $money=strstr($str3, ' ', true);
    $money=(int)$money;
    

    Так как у VK есть платежные системы, я предусмотрела оплату через VK pay (сервера VK отправляют на ваш вебхук такие запросы, но только если у вас паблик указан как МАГАЗИН и есть ТОВАР, который можно оплатить через VK pay), а также оплату простым денеженым переводом, который можно прикрепить к сообщению.

    Каждого пользователя, который пишет что-то боту, сохраняю в базе, и далее всё общение с ботом происходит в зависимости от оплаты. Если оплаты не было, бот скажет, что нужно сначала оплатить, если оплата произошла — подскажет, что делать дальше. Для тестирования можно ввести любое сообщение боту для составления плана.

    После оплаты, бот будет спрашивать параметры, необходимые для расчета, сохраняю это всё в базе для конкретного пользователя, а после всей полученной информацию считаю и выдаю ответ. Отправляю сообщение, используя созданную функцию, указав user_id пользователя:

    vkApi_messagesSend($user_id, 'Отлично! Какой твой возраст?'); 
    

    Также учла момент неправильного ввода пользователем какой-нибудь информации: в таком случае нужно отправить боту число 404, и он начнет спрашивать сначала, обнулив данные в базе.

    Для некоторых сообщений мне было удобно сделать кнопки, при нажатии на которую мне на вебхук прилетало сообщение с текстом, который был указан на кнопке.

    $buttons='{ 
    "one_time":true, 
     "buttons":[[{ 
     "action":{ 
     "type":"text", 
     "payload":"{\"button\": \"1\"}", 
     "label":"Я женщина" }, 
     "color":"primary" }, 
     { 
     "action":{ 
     "type":"text", 
     "payload":"{\"button\": \"2\"}", 
     "label":"Я мужчина" }, 
     "color":"primary"}]]}';
    vkApi_buttonSend($user_id,'Укажи пол',$buttons) ;
    

    А дальше всё самое интересное! После собранных данных происходит сам расчет. Ничего не придумываю сама, лишь правильно оформляю нужные формулы, опираясь на формулу Харриса-Бенедикта, а также знания в области правильного питания (здесь важны количества приемов пищи, процентное распределение белков/жиров/углеводов на эти приемы и т.д.).

    Вообщем, подобные вещи:

    $BMR=88.363+(13.397*$weight)+(4.799*$height)-(5.677*$age);
    $BMR_AMR=$BMR*1.2-500;
    $b_kkal=0.35*$BMR_AMR;
    $b_gr=$b_kkal/4;
    $g_kkal=0.3*$BMR_AMR;
    $g_gr=$g_kkal/9;
    $u_kkal=0.35*$BMR_AMR;
    $u_gr=$u_kkal/4;
    $break_b=0.15*$b_gr;
    $break_u=0.25*$u_gr;
    $break_g=0.25*$g_gr;
    $break_kk=0.25*$BMR_AMR;
    $snack_b=0.1*$b_gr;
    $snack_u=0.1*$u_gr;
    $snack_g=0.15*$g_gr;
    $snack_kk=1*$BMR_AMR;
    $snack2_b=0.05*$b_gr;
    $snack2_u=0.05*$u_gr;
    $snack2_kk=0.05*$BMR_AMR;
    $lunch_b=0.45*$b_gr;
    $lunch_u=0.4*$u_gr;
    $lunch_g=0.4*$g_gr;
    $lunch_kk=0.4*$BMR_AMR;
    $dinner_b=0.25*$b_gr;
    $dinner_u=0.2*$u_gr;
    $dinner_g=0.2*$g_gr;
    $dinner_kk=0.2*$BMR_AMR;
    

    Соответственно, для людей с сидячим образом жизни и людей с гиперактивностью будут другие коэффициенты, я привела небольшой пример.

    После высчитанных БЖУ и ККАЛ собираю набор продуктов. Кстати, если после полученного плана питания ввести число 404 и начать сначала (возможнно похудели/набрали вес, изменился образ жизни и т.д.), набор продуктов рандомно изменится. И вот у вас уже другой план питания!

    В итоге получился вот такой вот сервис (я его официально разместила ВК для тестирования, разработчик я начинающий, и сама не могу поймать все свои баги, если вдруг они есть):

    скриншоты бота
    image image
    image image


    Из замеченных мною ошибок (требует доработки) :


    • Кнопки не открываются сразу. Нужно найти возле кнопки «отправить» значок клавиатуры. Это очень путает людей, и пишут неправильно (если кнопка нажата, то я обрабатываю текст с кнопки, данные, которые пользователь вводит сам, игнорируются).
    • Не очень большая база продуктов, столкнулась с тем, что такое кушать никто не будет.

    Для желающих потестить и посмотреть ссылка на паблик.
    Share post
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 23

      0
      3. Сколько вешать в граммах? Что такое «льняное масло 10г» и самое главное «мюсли 14 г»? Или их водой заливать?
        0
        Льняное масло 10гр, это и значит, что льняного масло нужно выпить 10 гр) Это получается как столовая ложка. Мюсли да, конечно, водой заливать. Можно и молоком, если убрать что-то из других блюд) Взаимозаменяемо должно быть. Ну тут я уже поняла, что не особо понятный итог получается :(
        0
        1. не надо на каждом новом скриншоте дублировать 90% предыдущего.
        2. «мюсли, творог, булочка, говядина, творог, молоко, драники» — это все продукты у которых и калорийность и бжу могут отличаться радикально, поэтому бесполезные данные.
        3. Бот должен предлагать выбор пола, а не спрашивать текстом, как человек должен догадаться написать «я мужчина/женщина» вместо просто м/ж?
          +1
          3. Так там и есть выбор пола кнопками
          0
          Первое что бросилось в глаза — красный перец на обед. После него, как мне кажется, образ жизни будет слишком активный.
            0
            Ой! Это красный болгарский) Ну, вот, спасибо)
            0
            1. Как насчёт репозитория на Гитхабе?
            2. Не возникало мыслей по улучшению читабельности кода? И вообще по стилю
              0

              Коммерческий же продукт...

                0
                Это как-то противоречит открытости? Самое ценное здесь — содержание БД. И уж точно это не мешает приведению кода в порядок, не так ли?
                  0

                  Ну да, не противоречит. Что-то я ляпнул, не подумав.
                  А по коду полностью согласен

              0
              Вычитайте текстовку описания. Присутствуют грамматические ошибки и корявый язык. В первом приветственном сообщении тоже как-то коряво: «в минуту». После скринов в статью стоимость уже в 2 раза подрасла.
                +2
                1. поработайте над кодстайлом — раз публикуете и показываете код, то следуйте стандартам, почитайте про psr, сделайте названия переменных более читабельными и т.п…
                2. формула Харрисса- Беннедикта не совсем точная, не учитывает соотношение жировой и мышечной массы, двигательную активность — люди ее преувеличивают и т.п., да и вообще универсально посчитать сколько и что нужно есть человеку не выйдет
                3. раз уж учитываете переносимость лактозы, учитывайте и аллергию на продукты, а то кто-нибудь загнется от рыбы к примеру и калорийность рыбы придется выкидывать и пересчитывать саму
                ну и брать деньги за такое — ну я даже не знаю, стыдно как-то. тем более сами пишете что не особо знакомы с предметной областью —
                Я не диетолог, не профессиональный спортсмен и, конечно, не претендую на то, что мне без вопросов будут доверять


                  +5
                  Несколько замечаний:

                  1. Прежде чем просить за свое творчество деньги, допилите его до вменяемого состояния. А то баги вы искать не умеете, никаких чудес не обещаете, но многаденех уже хотите. :)

                  2. Толку в одноразовой рекомендации ноль. Ценность таких сервисов — в ежедневном отслеживании параметров и автоматической корректировке меню. Заодно ваш бот должен заботиться о разнообразии меню и подстраиваться под вкусы пользователя (например, кто-то не любит болгарский перец).

                  2.1 Следовательно, должен быть способ ввести новую информацию не обнуляя всё ранее введенное.

                  2.2 Должен быть способ сообщить боту, что меню не нравится (и вот почему).

                  2.3 Раз есть функция отслеживания параметров во времени — должны быть и соответствующие плюшки: графики, экстраполяции («за месяц удалось похудеть на 200 грамм, а это значит, что всего через 4 года и 2 месяца вы достигнете поставленной цели!»), поздравления с достижением поставленной цели.

                  3. Просто список ингредиентов — это ни о чем. Вот выпал мне стакан крупы на завтрак — и что мне с ним делать? Кашу варить? Насухую грызть? В ступке толочь и в чай добавлять? Нужны не просто списки ингредиентов, а конкретные рецепты, желательно простые.

                  Теперь то, что лично меня покоробило:

                  4. Смайлики и эмодзи. Нет, я понимаю, для чего их нынешнее поколение школьников использует: они не приучены понимать смысл прочитанного, поэтому стараются расставлять «визуальные подсказки» для таких же инвалидов людей. К сожалению, если человек не приучен понимать смысл слов, ему эмодзи могут не помочь (завтрак — нарисован хлеб и кофе, а в списке продуктов хлеба нет).

                  5. Обращение на «ты». Я понимаю, что это рассчитано на аудиторию читательниц «Космополитен», но могут ведь и нормальные забежать.

                  6. Составили меню с конкретными продуктами — ну так используйте данное знание в рекомендациях. А то в предложенном меню нет ни единого слова про яйца, овсянку и макароны, а в рекомендациях в конце — целый абзац про то, чем их можно заменить и какие надо выбирать.
                    0
                    Одним питанием вес не сбросить, особенно поедая продукты с высоким содержанием фруктозы (мёд, помидоры, сладкий перец). Обязательно нужны физические нагрузки (не прогулки в обёртке ЗОЖ, а нагрузки до перехода в физ.кетоз): сколько съел — столько сжёг.
                    Хотя, что я, диванный аналитик, об этом знаю. У меня никогда не было проблем с лишним весом.
                    ЗЫ: Отмечайтесь, кто брал годовой абонемент, и перестал посещать тренировки через пару месяцев? :D
                      +2
                      У Гоблина(Дмитрий Пучков) на ютубе есть ролик с старым прожжёным культуристом, как раз на тему «похудение».
                      Так вот тот культурист говорил, что сбрасывать вес большими нагрузками, это примерно тоже самое, что и при необходимости заправить машину 40л бензина, заправить в нее 50л и дать 500 кругов вокруг заправки (пока бензина в баке не станет нужное кол-во 40л)

                      Физ.нагрузки при похудении нужны в основном только для сохранения мышечной массы (при «голодании» она убывает).

                      А так же дал полный расклад, как организм сжигает калории (жиры и углеводы) и почему физ.нагрузки малоэффективны при похудении.
                        0
                        КдПВ
                        image
                        … за почтовым отделением давно уже установилась репутация учреждения, в котором страшно бывать. Всё знают и всё понимают только дураки да шарлатаны.
                        Не стоит мешать людям сходить с ума.
                        А. П. Чехов

                        ЗЫ: мой пузырь по запросу «культурист в гостях у гоблина» выдаёт интервью с Савельевым :3
                      0

                      полно бесплатных онлайн калькуляторов по этой формуле
                      Поражаюсь, как любят некоторые программисты деньги из воздуха получать.

                        0
                        Все любят деньги из воздуха получать, не только программисты.
                        Другое дело, что первое же «серьезное» творение начинающий программист норовит сделать платным. А поскольку нет ни опыта, ни понимания того, что нужно людям — результат очевиден.
                        • UFO just landed and posted this here
                          +1
                          $buttons='{
                          "one_time":true,
                          "buttons":[[{
                          "action":{

                          Как же бесит json написанный руками, и ладно бы так только начинающие делали… а есть же народ с n-лет опыта на каком-нибудь фреймворке, которые собирают динамические массивы через строковые функции со счётчиком запятых. Эй, зелёные человечки, есть json_encode($array)

                            0
                            «Инженер — программист» научитесь пожалуйста писать читабельный код
                              0
                              Вообще отличная идея писать подобный код:
                              1. Для саморазвития и мотивации
                              2. Для получения замечаний от неравнодушных
                              3. Думаю даже получится заработать на что-то

                              Статья понравилась, бросилось в глаза только наименование функций
                                0
                                Да, платность это хорошо, но сначала надо оттестировать. А у вас пользователей нет, и группа на 15 человек? Не той дорожкой…

                                Only users with full accounts can post comments. Log in, please.