<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Дизайнер учит код</title><author><name>Дизайнер учит код</name></author><id>https://teletype.in/atom/semeonboboshko</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/semeonboboshko?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@semeonboboshko?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=semeonboboshko"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/semeonboboshko?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-05-26T09:51:06.897Z</updated><entry><id>semeonboboshko:test-task</id><link rel="alternate" type="text/html" href="https://teletype.in/@semeonboboshko/test-task?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=semeonboboshko"></link><title>Зачем нужно тестовое задание для дизайнера и почему его нельзя делать до знакомства с командой</title><published>2022-11-07T09:48:24.367Z</published><updated>2022-11-07T09:48:24.367Z</updated><summary type="html">Как правило, с помощью тестового задания пытаются оценить заявленные навыки. Также, проверяют логику принятия решений, технические знания и ещё ряд особенностей, которые важны конкретному нанимающему менеджеру или компании.</summary><content type="html">
  &lt;h2 id=&quot;YZbS&quot;&gt;Зачем нужно тестовые задания для дизайнера?&lt;/h2&gt;
  &lt;p id=&quot;kTPO&quot;&gt;Как правило, с помощью тестового задания пытаются оценить заявленные навыки. Также, проверяют логику принятия решений, технические знания и ещё ряд особенностей, которые важны конкретному нанимающему менеджеру или компании.&lt;/p&gt;
  &lt;h2 id=&quot;hj3x&quot;&gt;В каких случаях дают тестовые задания?&lt;/h2&gt;
  &lt;p id=&quot;DCpB&quot;&gt;Если человек не сталкивался с определённой спецификой, а она нужна в работе. Например, кандидат проектировал интерфейсы для web, а работать предстоит над мобильным приложением. Тут нужно проверить, как человек справится и это оправдано.&lt;/p&gt;
  &lt;p id=&quot;Tmht&quot;&gt;Также, тестовое задание могут дать, если у кандидата мало опыта. Как правило, это касается начальных позиций: стажёров или junior-дизайнеров. Опять же, нужна проверка навыков и она оправдана.&lt;/p&gt;
  &lt;p id=&quot;bkKj&quot;&gt;Иногда, тестовое задание дают, потому, что «так принято в компании», лично у руководителя или нанимающего менеджера. Даже если с кандидатом и всё понятно. Подобная риторика — плохой знак по целому ряду причин и лучше от сотрудничества сразу отказаться.&lt;/p&gt;
  &lt;p id=&quot;z3Ib&quot;&gt;В остальных случаях, считаю, что тестовое задание давать нецелесообразно. После просмотра портфолио и общения с кандидатом, с вероятностью в 90% всё будет понятно.&lt;/p&gt;
  &lt;h2 id=&quot;loBH&quot;&gt;Как выглядит плохое тестовое задание?&lt;/h2&gt;
  &lt;p id=&quot;rawZ&quot;&gt;У меня был случай, когда компания вела реальный проект и предложила сделать его часть в качестве тестового задания. Мне это сразу не понравилось по нескольким причинам.&lt;/p&gt;
  &lt;p id=&quot;FcvM&quot;&gt;Во-первых, это был реальный проект и результат моей работы компания могла бы использовать не заплатив мне.&lt;/p&gt;
  &lt;p id=&quot;KvoM&quot;&gt;Во-вторых, нет никаких гарантий, что компания на самом деле ищет сотрудника. Вполне возможно, что таким образом пытаются закрыть небольшую потребность в специалисте на конкретном проекте. Вариантов для спекуляций — масса.&lt;/p&gt;
  &lt;p id=&quot;jUwC&quot;&gt;В итоге я предложил оплатить моё время, которое я должен был потратить на выполнение тестового задания. Компания отказалась.&lt;/p&gt;
  &lt;p id=&quot;t9GP&quot;&gt;Вот ещё несколько моментов, на которые стоит обратить внимание. Размытые критерии задачи (непонятно, как будут оценивать результат), сжатые сроки (компания торопится) или ещё хуже, когда компания сама устанавливает сроки для выполнения тестового задания. Это всё повод задуматься и отказаться от сотрудничества. Вполне возможно, что подбор происходит «на потоке».&lt;/p&gt;
  &lt;h2 id=&quot;4zrT&quot;&gt;Как выглядит хорошее тестовое задание?&lt;/h2&gt;
  &lt;p id=&quot;80AC&quot;&gt;Хорошее тестовое задание должно быть абстрагировано от текущих проектов компании, чётко сформулировано и не должны занимать больше 2-3 часов. Сроки выполнения кандидат должен назначать сам исходя из своей загруженности на текущий момент.&lt;/p&gt;
  &lt;h2 id=&quot;4zyb&quot;&gt;Какие альтернативы бывают у тестовых заданий?&lt;/h2&gt;
  &lt;h3 id=&quot;85eS&quot;&gt;Техническое интервью&lt;/h3&gt;
  &lt;p id=&quot;8mr4&quot;&gt;На таком интервью просят решить какие-нибудь несложные задачи прямо здесь и сейчас. Задачи бывают разными: от продуктовых до технических. Вопросы могут варьироваться от специфики компании и требований для кандидата на конкретную позицию.&lt;/p&gt;
  &lt;p id=&quot;ZMlZ&quot;&gt;Но бывают такие ситуации, когда техническое интервью не исключает наличие тестового задания. А само интервью — часть процесса найма сотрудников у компании.&lt;/p&gt;
  &lt;h3 id=&quot;HH4H&quot;&gt;Тестовый день&lt;/h3&gt;
  &lt;p id=&quot;2KhC&quot;&gt;С тестовым днём дела обстоят иначе. Он полностью должен исключать тестовое задание. Суть в том, что кандидат «устраивается» в компанию на один день и выполняет свои обязанности так, если бы он уже работал по-настоящему.&lt;/p&gt;
  &lt;p id=&quot;qwZZ&quot;&gt;Я с таким ни разу не сталкивался на своей практике и по личным ощущениям, в России подобный подход почти на распространён. Но я знаю как минимум одного человека, который предлагает своим кандидатам подобный вариант. В идеале, такой день должен быть оплачен.&lt;/p&gt;
  &lt;h2 id=&quot;Cs0e&quot;&gt;Что даёт знакомство с командой?&lt;/h2&gt;
  &lt;p id=&quot;iujf&quot;&gt;Тут важно уточнить, что под «командой» я понимаю 2-3 человека с которыми нужно будет взаимодействовать больше всего. Как правило, это непосредственный руководитель и менеджер. Но состав может отличаться.&lt;/p&gt;
  &lt;p id=&quot;onid&quot;&gt;Знакомство с командой даёт общее понимание её зрелости, адекватности и главное — комфортности общения. Нужно узнать, как устроен процесс внутри, от кого поступают задачи и кто их будет принимать или оценивать (это может быть вовсе не руководитель).&lt;/p&gt;
  &lt;p id=&quot;NyUQ&quot;&gt;Если на этом этапе что-то не нравится, то лучше отказаться от сотрудничества.&lt;/p&gt;
  &lt;h2 id=&quot;45hw&quot;&gt;Что плохого в том, чтобы сделать тестовое задание до знакомства с командой?&lt;/h2&gt;
  &lt;p id=&quot;UUx3&quot;&gt;Если резюмировать всё, что я сказал выше, то получается следующее.&lt;/p&gt;
  &lt;p id=&quot;FIP4&quot;&gt;Во-первых, кандидат рискует своим временем. После выполнения тестового задания, может оказаться, что человеку просто не комфортно общаться с командой или руководителем.&lt;/p&gt;
  &lt;p id=&quot;PYOu&quot;&gt;Во-вторых, кандидата могут обмануть.&lt;/p&gt;
  &lt;p id=&quot;3d9T&quot;&gt;В-третьих, можно банально быстро «выгореть», если кандидат активно ищет работу.&lt;/p&gt;
  &lt;p id=&quot;S5qU&quot;&gt;В-четвёртых, это просто неуважительно. Кандидат ещё ничего не знает толком про компанию и условия, а его уже просят поработать, чтобы просто начать диалог по существу.&lt;/p&gt;
  &lt;p id=&quot;gPGH&quot;&gt;А если кандидата торопят или для начала общения нужно сделать тестовое — скорее всего подбор на вакансию происходит «на потоке» и компания не заинтересована в конкретном человеке.&lt;/p&gt;
  &lt;h2 id=&quot;vmt8&quot;&gt;Вывод&lt;/h2&gt;
  &lt;p id=&quot;sGyr&quot;&gt;Конечно, политика «сперва общение — потом тестовое» тоже не страхует от всего, что я написал выше. Но по крайней мере она кратно снижает риски.&lt;/p&gt;

</content></entry><entry><id>semeonboboshko:zarya-2</id><link rel="alternate" type="text/html" href="https://teletype.in/@semeonboboshko/zarya-2?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=semeonboboshko"></link><title>Домашняя метеостанция. Часть 2</title><published>2020-10-31T21:03:49.898Z</published><updated>2021-01-20T14:58:56.998Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/67/3f/673f7e1b-8c2a-4dad-ba13-2d1f28a06622.png"></media:thumbnail><category term="meteostation" label="Метеостанция"></category><summary type="html">&lt;img src=&quot;https://teletype.in/files/e6/f4/e6f4e3bf-df76-4935-ab4f-72ef9324c5bc.jpeg&quot;&gt;Важно понимать, что API, о котором пойдёт речь ниже — это компиляция нескольких курсов найденных мной в интернете, постоянного чтения документации и регулярных консультаций неравнодушных людей. В текущем виде исходный код не претендует на оригинальность.</summary><content type="html">
  &lt;p&gt;Важно понимать, что API, о котором пойдёт речь ниже — это компиляция нескольких курсов найденных мной в интернете, постоянного чтения документации и регулярных консультаций неравнодушных людей. В текущем виде исходный код не претендует на оригинальность.&lt;/p&gt;
  &lt;p&gt;💫 &lt;a href=&quot;https://www.facebook.com/onlysemeon/posts/582696555261097&quot; target=&quot;_blank&quot;&gt;Вдохновлено мечтой&lt;/a&gt;.&lt;/p&gt;
  &lt;h2&gt;Название&lt;/h2&gt;
  &lt;p&gt;&lt;a href=&quot;https://t.me/semeonboboshko/147&quot; target=&quot;_blank&quot;&gt;В первой части&lt;/a&gt; я говорил, что разделил процесс создания метеостанции на три этапа. По сути, это три отдельных проекта, которые теперь объединены под одним общим названием — Zarya.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://github.com/boboshko/zarya-meteostation&quot; target=&quot;_blank&quot;&gt;Zarya Meteostation&lt;/a&gt; — это метеостанция на базе Iskra JS, которая собирает погодные данные и передаёт их на сервер. Подробнее про неё написано &lt;a href=&quot;https://t.me/semeonboboshko/147&quot; target=&quot;_blank&quot;&gt;в первой части&lt;/a&gt; цикла.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://github.com/boboshko/zarya-api&quot; target=&quot;_blank&quot;&gt;Zarya API&lt;/a&gt; — это API, который принимает погодные данные от Zarya Meteostation. В данном материале речь пойдёт о Zarya API.&lt;/p&gt;
  &lt;p&gt;Zarya Assistant — это Telegram-бот, который будет использоваться в качестве интерфейса для получения погодных данных из Zarya API. На данный момент проект разрабатывается и третья часть цикла будет посвящена Zarya Assistant.&lt;/p&gt;
  &lt;p&gt;Кажется, это звучит лучше, чем безликая «домашняя метеостанция».&lt;/p&gt;
  &lt;h2&gt;Общее описание API&lt;/h2&gt;
  &lt;p&gt;&lt;a href=&quot;https://github.com/boboshko/zarya-api&quot; target=&quot;_blank&quot;&gt;Zarya API&lt;/a&gt; — это небольшой API, написанный на &lt;a href=&quot;https://nodejs.org/en&quot; target=&quot;_blank&quot;&gt;Node JS&lt;/a&gt;, позволяющий принимать данные с Zarya Meteostation (метеостанция на основе &lt;a href=&quot;http://wiki.amperka.ru/js:iskra_js&quot; target=&quot;_blank&quot;&gt;Iskra JS&lt;/a&gt;) и записывать их в &lt;a href=&quot;https://www.mongodb.com&quot; target=&quot;_blank&quot;&gt;MongoDB&lt;/a&gt;. Обладает методами &lt;code&gt;GET&lt;/code&gt; (получение), &lt;code&gt;POST&lt;/code&gt; (добавление), &lt;code&gt;PUT&lt;/code&gt; (изменение) и &lt;code&gt;DELETE&lt;/code&gt; (удаление). Имеет Basic-авторизацию через &lt;code&gt;HTTP&lt;/code&gt;.&lt;/p&gt;
  &lt;h2&gt;Как работает API&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/e6/f4/e6f4e3bf-df76-4935-ab4f-72ef9324c5bc.jpeg&quot; width=&quot;4032&quot; /&gt;
    &lt;figcaption&gt;Примерный принцип работы проекта, я понимал ещё в декабре 2017-го. Но необходимый уровень знаний для его реализации у меня появился только в 2019-м. Запись из личного дневника.&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Клиент (в моём случае, это Iskra JS) по специальному URL отправляет запрос на сервер. Чтобы сервер принял запрос, на нём нужно авторизоваться. В противном случае, сервер отклонит его.&lt;/p&gt;
  &lt;p&gt;Затем, происходит проверка передаваемых данных с помощью схемы валидации. Если с данными всё хорошо, они записываются в базу.&lt;/p&gt;
  &lt;p&gt;После того, как данные попали в базу, ими можно манипулировать: менять, удалять, возвращать или производить вычисления.&lt;/p&gt;
  &lt;p&gt;Например, чтобы Zarya Assistant получил текущую погоду, нужно выполнить запрос и вернуть данные.&lt;/p&gt;
  &lt;p&gt;Это несколько упрощённое описание работы API. Можно &lt;a href=&quot;https://github.com/boboshko/zarya-api&quot; target=&quot;_blank&quot;&gt;самостоятельно ознакомиться с репозиторием&lt;/a&gt; на GitHub и вникнуть в код.&lt;/p&gt;
  &lt;h2&gt;Stack технологий&lt;/h2&gt;
  &lt;h3&gt;Сервер&lt;/h3&gt;
  &lt;p&gt;Когда API был почти готов, я задумался о том, где и как его размещать, чтобы передавать через него данные. На первых шагах нужно было определиться с хостингом и ОС для сервера.&lt;/p&gt;
  &lt;p&gt;Хостинг я выбрал давно — это &lt;a href=&quot;https://m.do.co/c/ce9b64dd2cc6&quot; target=&quot;_blank&quot;&gt;Digital Ocean&lt;/a&gt;. В качестве ОС для сервера я выбирал между &lt;a href=&quot;https://www.debian.org&quot; target=&quot;_blank&quot;&gt;Debian&lt;/a&gt; и &lt;a href=&quot;https://ubuntu.com&quot; target=&quot;_blank&quot;&gt;Ubuntu&lt;/a&gt;. На первый взгляд, особой разницы нет. После небольшого исследования, я выяснил, что Debian более стабильный, потому и выбрал его.&lt;/p&gt;
  &lt;p&gt;За Node JS на сервере отвечает &lt;a href=&quot;https://github.com/nvm-sh/nvm&quot; target=&quot;_blank&quot;&gt;NVM&lt;/a&gt; (Node Version Manager) — это небольшой скрипт, который позволяет легко контролировать версии Node JS.&lt;/p&gt;
  &lt;p&gt;Следить за процессами Node JS мне помогает менеджер процессов &lt;a href=&quot;https://pm2.keymetrics.io&quot; target=&quot;_blank&quot;&gt;pm2&lt;/a&gt;. Он может автоматически перезапускать приложения, если они прекращают работу.&lt;/p&gt;
  &lt;p&gt;Чтобы мой API был доступен не только по IP-адресу, но и по URL, нужен веб-сервер и домен. Домен у меня есть, а веб-сервера не было. Сначала я установил и настроил &lt;a href=&quot;https://nginx.org&quot; target=&quot;_blank&quot;&gt;Nginx&lt;/a&gt;. Выбрал его только из-за того, что он наиболее популярный. Но затем, по совету моего бывшего коллеги Саши Купоросова, я обратил внимание на &lt;a href=&quot;https://caddyserver.com&quot; target=&quot;_blank&quot;&gt;Caddy&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Caddy оказалось гораздо легче настраивать, чем Nginx. К тому же он автоматически запрашивает SSL-сертификаты для доменов через &lt;a href=&quot;https://letsencrypt.org&quot; target=&quot;_blank&quot;&gt;Let’s Encrypt&lt;/a&gt; и поддерживает &lt;a href=&quot;https://ru.wikipedia.org/wiki/HTTP/2&quot; target=&quot;_blank&quot;&gt;HTTP 2&lt;/a&gt;. Nginx тоже может автоматически получать сертификаты и поддерживает HTTP 2, но для этого нужно устанавливать &lt;a href=&quot;https://certbot.eff.org&quot; target=&quot;_blank&quot;&gt;Certbot&lt;/a&gt;, настраивать его через &lt;a href=&quot;https://ru.wikipedia.org/wiki/Cron&quot; target=&quot;_blank&quot;&gt;Cron&lt;/a&gt;, и конфигурировать каждый файл каждого сайта. В Caddy один конфигурационный файл на всё.&lt;/p&gt;
  &lt;p&gt;В качестве защиты работает &lt;a href=&quot;https://wiki.debian.org/Uncomplicated%2520Firewall%2520%2528ufw%2529&quot; target=&quot;_blank&quot;&gt;UFW&lt;/a&gt; (Uncomplicated Firewall) — это довольно простой firewall, но обращаться с ним нужно аккуратно. Иначе можно остаться без доступа по &lt;a href=&quot;https://ru.wikipedia.org/wiki/SSH&quot; target=&quot;_blank&quot;&gt;SSH&lt;/a&gt;.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/53/7b/537b865a-bf27-4ea1-b3ec-bb6abcf6daa3.jpeg&quot; width=&quot;4032&quot; /&gt;
    &lt;figcaption&gt;Мой комплект Raspberry Pi 3 Model B+, который несколько раз спасал меня от потери доступа по SSH к основному серверу&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;У меня почти не было опыта взаимодействия с UNIX-системами (кроме macOS) и чтобы потренироваться, я купил себе &lt;a href=&quot;https://www.raspberrypi.org/products/raspberry-pi-3-model-b-plus&quot; target=&quot;_blank&quot;&gt;Raspberry Pi 3 Model B+&lt;/a&gt;. Мой основной страх в тот момент — это то, что я что-нибудь сделаю не так и потеряю удалённый доступ по SSH. А если я всё испытаю локально на Raspberry Pi и что-то пойдёт не так, то я всегда смогу всё исправить. И сейчас я могу уверенно сказать, что это было стратегически верным решением. После того как я несколько раз терял доступ по SSH, мне удалось избежать допущенных ошибок на основном сервере.&lt;/p&gt;
  &lt;h3&gt;API&lt;/h3&gt;
  &lt;p&gt;API построен на ряде библиотек, каждая из которых отвечает за свою функцию.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://expressjs.com&quot; target=&quot;_blank&quot;&gt;Express JS&lt;/a&gt; — фреймворк для написания веб-приложений. С его помощью API создаёт веб-сервер и маршрутизацию.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/express-basic-auth&quot; target=&quot;_blank&quot;&gt;Express Basic Auth&lt;/a&gt; — простая библиотека для Express JS, которая позволяет производить авторизацию в приложении по HTTP. Это не самый надёжный вариант для авторизации, но пока и такого хватит.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/body-parser&quot; target=&quot;_blank&quot;&gt;Body Parser&lt;/a&gt; — библиотека для парсинга запросов.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://www.mongodb.com&quot; target=&quot;_blank&quot;&gt;MongoDB&lt;/a&gt; — не реляционная (&lt;a href=&quot;https://ru.wikipedia.org/wiki/NoSQL&quot; target=&quot;_blank&quot;&gt;NoSQL&lt;/a&gt;) база данных. В ней хранятся все данные, которые получает метеостанция.&lt;/p&gt;
  &lt;p&gt;Основное отличие от реляционных баз данных в том, что MongoDB хранит в себе &lt;a href=&quot;https://ru.wikipedia.org/wiki/BSON&quot; target=&quot;_blank&quot;&gt;BSON&lt;/a&gt; — это JSON-подобные документы. В то время как реляционные базы используют табличный тип хранения данных.&lt;/p&gt;
  &lt;p&gt;Возможно, позже MongoDB будет заменена на &lt;a href=&quot;https://en.wikipedia.org/wiki/Time_series_database&quot; target=&quot;_blank&quot;&gt;time series&lt;/a&gt; базу данных.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://www.npmjs.com/package/mongodb&quot; target=&quot;_blank&quot;&gt;MongoDB Driver&lt;/a&gt; — официальная библиотека MongoDB для Node JS. Используется для подключения API к базе данных.&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://mongoosejs.com&quot; target=&quot;_blank&quot;&gt;Mongoose&lt;/a&gt; — библиотека для MongoDB, которая позволяет API производить валидацию получаемых данных по заранее заданной схеме.&lt;/p&gt;
  &lt;h2&gt;Развитие&lt;/h2&gt;
  &lt;p&gt;На данный момент этой функциональности API хватает для того, чтобы доделать до конца MVP. Но у меня уже есть backlog задач, который поможет сделать проект более гибким в будущем. Вы можете написать мне (@&lt;a href=&quot;http://t.me/boboshko&quot; target=&quot;_blank&quot;&gt;boboshko&lt;/a&gt;), если хотите присоединиться к разработке.&lt;/p&gt;
  &lt;h2&gt;Благодарности&lt;/h2&gt;
  &lt;p&gt;Сложные вещи не делаются в одиночку. В разное время, мне помогали советом разные ребята.&lt;/p&gt;
  &lt;p&gt;Я хочу поблагодарить: Сашу Купоросова, Вову Артамонова, Влада Самойлова, Стаса Понаморёва, Вадима Репина, Диму Гуденкова и Женю Кочеткова.&lt;/p&gt;
  &lt;p&gt;Отдельно хочу отметить своих товарищей &lt;a href=&quot;https://alexanderkatin.ru&quot; target=&quot;_blank&quot;&gt;Сашу Катина&lt;/a&gt; (помог с переводом репозитория) и &lt;a href=&quot;https://www.instagram.com/lytkini&quot; target=&quot;_blank&quot;&gt;Илью Лыткина&lt;/a&gt; (он помогал с документацией).&lt;/p&gt;
  &lt;p&gt;Если я кого-то упустил, напишите мне и я всё исправлю.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;p&gt;Если у вас остались вопросы, вы можете их задать в чате канала: @&lt;a href=&quot;https://t.me/codeque&quot; target=&quot;_blank&quot;&gt;codeque&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Подписывайтесь на мой &lt;a href=&quot;https://t.me/semeonboboshko&quot; target=&quot;_blank&quot;&gt;канал&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/semeonboboshko&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; и &lt;a href=&quot;https://www.instagram.com/boboshko&quot; target=&quot;_blank&quot;&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</content></entry><entry><id>semeonboboshko:photos</id><link rel="alternate" type="text/html" href="https://teletype.in/@semeonboboshko/photos?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=semeonboboshko"></link><title>Как я научился собирать front-end, чтобы публиковать фотографии</title><published>2020-09-21T22:54:59.445Z</published><updated>2020-09-23T09:37:40.468Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/b4/bc/b4bc0e65-5773-49d3-b2d0-f819e0537df1.jpeg"></media:thumbnail><summary type="html">&lt;img src=&quot;https://teletype.in/files/28/6e/286e2ef0-0b4e-4a57-8800-3ccccf22989c.jpeg&quot;&gt;В мае 2019-го Саша Катин одолжил мне «Зенит» своего отца в путешествие во Вьетнам. Это был чуть ли не первый раз, когда мне довелось пользоваться подобным плёночным фотоаппаратом. Несмотря на отсутствие опыта, процесс съёмки мне понравился и дело быстро пошло.</summary><content type="html">
  &lt;p&gt;В мае 2019-го &lt;a href=&quot;https://alexanderkatin.ru&quot; target=&quot;_blank&quot;&gt;Саша Катин&lt;/a&gt; одолжил мне «Зенит» своего отца в путешествие во Вьетнам. Это был чуть ли не первый раз, когда мне довелось пользоваться подобным плёночным фотоаппаратом. Несмотря на отсутствие опыта, процесс съёмки мне понравился и дело быстро пошло.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/28/6e/286e2ef0-0b4e-4a57-8800-3ccccf22989c.jpeg&quot; width=&quot;4032&quot; /&gt;
    &lt;figcaption&gt;Тот самый «Зенит», который Саша одолжил мне в путешествие. В конечном итоге, я выкупил этот фотоаппарат.&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Помимо Вьетнама, «Зенит» успел съездить со мной в Индию и прокатиться по некоторым городам России. Количество фотографий росло и встал вопрос о том, где и в каком виде их публиковать.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/15/1c/151c7d83-c854-4408-865d-33695a2f1b12.jpeg&quot; width=&quot;4032&quot; /&gt;
    &lt;figcaption&gt;9 102,42 ₽ — столько я потратил в 2019-м году на покупку, проявку и сканирование фотоплёнок&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;h2&gt;Решение&lt;/h2&gt;
  &lt;figure class=&quot;m_original&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/98/fe/98fe89e9-d030-4400-9739-443fce6a1142.jpeg&quot; width=&quot;3584&quot; /&gt;
    &lt;figcaption&gt;&lt;a href=&quot;https://boboshko.me/photos/&quot; target=&quot;_blank&quot;&gt;https://boboshko.me/photos/&lt;/a&gt;&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Я практически сразу понял, что хочу размещать свои фотографии у себя на сайте, минуя популярные сервисы фотографий. Но для этого нужен сайт или его подобие.&lt;/p&gt;
  &lt;p&gt;Сначала, я сделал очень простой шаблон на чистом HTML и размещал готовые снимки в нём у себя на сервере. Этого было достаточно, чтобы отправить кому-нибудь ссылку на фотографии.&lt;/p&gt;
  &lt;p&gt;Шаблон не имел никакого оформления, не умел адаптироваться под разные разрешения экранов (не было CSS) и отсутствовал &lt;a href=&quot;https://en.wikipedia.org/wiki/Lazy_loading&quot; target=&quot;_blank&quot;&gt;lazy load&lt;/a&gt;. Так продолжалось около года.&lt;/p&gt;
  &lt;p&gt;После начала карантина, я практически сразу начал изучать вёрстку по урокам на YouTube. И уже через пару недель после начала, у меня было готово две адаптивные страницы: общая со списком всех фотографий и внутренняя.&lt;/p&gt;
  &lt;p&gt;Готовый результат можно посмотреть: &lt;a href=&quot;http://boboshko.me/photos/?utm_source=telegram&amp;utm_medium=article&amp;utm_content=link&quot; target=&quot;_blank&quot;&gt;https://boboshko.me/photos/&lt;/a&gt;.&lt;/p&gt;
  &lt;h2&gt;Stack технологий&lt;/h2&gt;
  &lt;p&gt;На самом деле, тут всё просто. Сетка реализована на &lt;a href=&quot;https://developer.mozilla.org/ru/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout&quot; target=&quot;_blank&quot;&gt;CSS Grid&lt;/a&gt;. Ещё я смотрел на &lt;a href=&quot;https://developer.mozilla.org/ru/docs/Learn/CSS/CSS_layout/Flexbox&quot; target=&quot;_blank&quot;&gt;Flexbox&lt;/a&gt;, но мне показалось, что оно того не стоит.&lt;/p&gt;
  &lt;p&gt;Никаких &lt;a href=&quot;https://developer.mozilla.org/ru/docs/%D0%A1%D0%BB%D0%BE%D0%B2%D0%B0%D1%80%D1%8C/CSS_preprocessor&quot; target=&quot;_blank&quot;&gt;препроцессоров CSS&lt;/a&gt; на начальном этапе я не использовал.&lt;/p&gt;
  &lt;p&gt;Во время эксплуатации шаблона, я понял, что новые фотографии в таком виде добавлять сложно. Из-за этого я решил сильно упростить процесс с помощью шаблонизатора &lt;a href=&quot;https://pugjs.org&quot; target=&quot;_blank&quot;&gt;Pug&lt;/a&gt;, препроцессора &lt;a href=&quot;https://sass-lang.com&quot; target=&quot;_blank&quot;&gt;SASS&lt;/a&gt; и таск-менеджера &lt;a href=&quot;https://gulpjs.com&quot; target=&quot;_blank&quot;&gt;Gulp&lt;/a&gt; с набором плагинов. За lazy load фотографий отвечает небольшой скрипт — &lt;a href=&quot;https://github.com/aFarkas/lazysizes&quot; target=&quot;_blank&quot;&gt;lazysizes&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Теперь, если мне нужно внести какие-то изменения в дизайне, я делаю это в одном месте. А не в десяти, как раньше. И Gulp соберёт весь front-end за меня, используя Pug и SASS. Дополнительные плагины оптимизируют все изображения, HTML и CSS. Всё автоматически.&lt;/p&gt;
  &lt;p&gt;В качестве веб-сервера я использую &lt;a href=&quot;https://caddyserver.com&quot; target=&quot;_blank&quot;&gt;Caddy&lt;/a&gt;. Он умеет автоматически получать SSL-сертификаты от &lt;a href=&quot;https://letsencrypt.org&quot; target=&quot;_blank&quot;&gt;Let’s Encrypt&lt;/a&gt;. К тому же, он очень прост в настройке.&lt;/p&gt;
  &lt;p&gt;Остаётся подключить какую-нибудь систему &lt;a href=&quot;https://ru.wikipedia.org/wiki/CI/CD&quot; target=&quot;_blank&quot;&gt;CI / CD&lt;/a&gt;, чтобы можно было делать автоматические сборки на сервере.&lt;/p&gt;
  &lt;p&gt;В общем, теперь я могу говорить заветное «&lt;em&gt;сбилдилось&lt;/em&gt;»!&lt;/p&gt;
  &lt;hr /&gt;
  &lt;p&gt;Если у вас остались вопросы, вы можете их задать в чате канала: @&lt;a href=&quot;https://t.me/codeque&quot; target=&quot;_blank&quot;&gt;codeque&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Подписывайтесь на мой &lt;a href=&quot;https://t.me/semeonboboshko&quot; target=&quot;_blank&quot;&gt;канал&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/semeonboboshko&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; и &lt;a href=&quot;https://www.instagram.com/boboshko&quot; target=&quot;_blank&quot;&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</content></entry><entry><id>semeonboboshko:highroller</id><link rel="alternate" type="text/html" href="https://teletype.in/@semeonboboshko/highroller?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=semeonboboshko"></link><title>Стенд Avito для фестиваля 404 в Самаре</title><published>2020-09-10T19:13:17.465Z</published><updated>2020-09-21T22:33:23.547Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/35/6e/356eb9d6-9906-4e4f-85ed-73e35e9e659f.jpeg"></media:thumbnail><summary type="html">&lt;img src=&quot;https://teletype.in/files/03/4d/034d0a21-7606-484c-bf8d-834a1a0bb528.jpeg&quot;&gt;Весной 2019-го я попал в Avito по рекомендации Саши Катина. Несмотря на то, что мы находились в разных юнитах, вместе с Сашей мы иногда занимались совместными проектами.</summary><content type="html">
  &lt;p&gt;Весной 2019-го я попал в Avito по рекомендации &lt;a href=&quot;https://alexanderkatin.ru&quot; target=&quot;_blank&quot;&gt;Саши Катина&lt;/a&gt;. Несмотря на то, что мы находились в разных юнитах, вместе с Сашей мы иногда занимались совместными проектами.&lt;/p&gt;
  &lt;p&gt;Один из них — стенд Avito для фестиваля &lt;a href=&quot;https://404fest.ru&quot; target=&quot;_blank&quot;&gt;404&lt;/a&gt; в Самаре, который прошёл в том же году.&lt;/p&gt;
  &lt;h2&gt;Как работал стенд&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/VwnMZ1_qh9k?autoplay=0&amp;loop=0&amp;mute=0&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;Саша Катин и Дима Сергутов демонстрируют работу стенда&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Человек пришедший на стенд, видел перед собой два экрана: один большой (для информации) и поменьше (для взаимодействия).&lt;/p&gt;
  &lt;p&gt;На экране поменьше была большая кнопка. При нажатии на неё, появлялась случайная фраза на большом экране, которая сразу же печаталась в виде стикера.&lt;/p&gt;
  &lt;p&gt;Если у фразы в конце была звёздочка (вот такая *), человек получал приз и стикер. Если звёздочки не было, получал только стикер.&lt;/p&gt;
  &lt;p&gt;Это были абсурдные фразы в духе &lt;em&gt;«Аварийный кастет со смазкой»&lt;/em&gt; или &lt;em&gt;«Безвкусное кольцо 80-го уровня»&lt;/em&gt;. Предполагалось, что люди будут их клеить на телефоны и ноутбуки.&lt;/p&gt;
  &lt;h2&gt;Процесс разработки&lt;/h2&gt;
  &lt;p&gt;Сразу скажу, что я не могу показать получившийся код, NDA. Но могу в общих чертах рассказать про процесс создания стенда.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/03/4d/034d0a21-7606-484c-bf8d-834a1a0bb528.jpeg&quot; width=&quot;1280&quot; /&gt;
    &lt;figcaption&gt;Через iPad посетители взаимодействовали со стендом&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Как я уже сказал выше, в системе было задействовано два экрана (телевизор и iPad), ноутбук и специальный принтер для печати этикеток.&lt;/p&gt;
  &lt;p&gt;Саша взял на себя весь front-end, взаимодействие пользователя со стендом и сделал так, чтобы принтер, экраны и ноутбук — подружились. Это сложнее, чем кажется.&lt;/p&gt;
  &lt;p&gt;За проектирование и монтаж стенда отвечал подрядчик.&lt;/p&gt;
  &lt;p&gt;Моя задача заключалась в том, чтобы написать логику формирования случайных фраз. Ещё мне предстояло реализовать случайное выпадение звёздочки, сбалансировать шанс её появления и привязать всё это к датам проведения фестиваля. В довесок, нужно ограничить количество побед, чтобы их не было больше положенного количества в день (подарков на всех бы просто не хватило).&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/79/79/79796884-df13-48c4-a63f-b1154fb0a3a9.jpeg&quot; width=&quot;1144&quot; /&gt;
    &lt;figcaption&gt;Так выглядел стенд в разобранном состоянии&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;В лучших традициях, прототип стенда был собран на Google Sheets кем-то из креативной группы. В таблицах находились слова, которые были разбиты по родам. При обновлении страницы, появлялась случайная фраза из них.&lt;/p&gt;
  &lt;p&gt;Чтобы начать работу, нужно было выгрузить всё из таблиц и подготовить данные. В итоге, у меня получилось 4 разных файла: &lt;code&gt;he.js&lt;/code&gt;, &lt;code&gt;she.js&lt;/code&gt;, &lt;code&gt;it.js&lt;/code&gt; и &lt;code&gt;together.js&lt;/code&gt;. Внутри файлов было по два массива с подлежащим и сказуемым (в &lt;code&gt;together.js&lt;/code&gt; было только местоимение).&lt;/p&gt;
  &lt;p&gt;После этого, я повторил логику работы прототипа на JavaScript. В общем, это было не сложно. Только было нужно определять первый выпавший случайный массив, чтобы все следующие слова брались из нужных файлов. Это делалось, чтобы получались осмысленные фразы, а не что-то в духе &lt;em&gt;«Алкогольный бегство анонимно»&lt;/em&gt;.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/8d/92/8d9260c8-f19f-4a60-8a04-966c3356b00d.jpeg&quot; width=&quot;1144&quot; /&gt;
    &lt;figcaption&gt;Сборка рабочего прототипа на моём рабочем месте (офис Avito в Москве)&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Статистику и все сгенерированные фразы мы записывали в &lt;code&gt;local storage&lt;/code&gt;браузера. В нём же хранили количество оставшихся подарков. Каждый раз, при срабатывании скрипта, если выпадал приз, то из числа в &lt;code&gt;local storage&lt;/code&gt;вычитался &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;
  &lt;p&gt;Больше всего сложностей было с балансировкой шансов выпадения приза. Мне показалось, что проще всего это будет сделать через подбрасывание монетки. Монетка, конечно, не настоящая и выдаёт &lt;code&gt;0&lt;/code&gt; или &lt;code&gt;1&lt;/code&gt;. Всё это привязывалось к датам проведения фестиваля и было сбалансировано так, чтобы в первый день мы раздали 2 / 3 подарков, а во второй 1 / 3.&lt;/p&gt;
  &lt;h2&gt;Результат&lt;/h2&gt;
  &lt;p&gt;На написание всего кода и отладку, вместе с Сашей мы потратили около двух недель, работая вечерами.&lt;/p&gt;
  &lt;p&gt;За 2 дня фестиваля, стендом воспользовалось более 1 000 человек. Были розданы все подарки.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/a4/7a/a47a8557-9a02-4779-8918-19b9fb7e3682.jpeg&quot; width=&quot;1144&quot; /&gt;
    &lt;figcaption&gt;Довольный посетитель и стенд&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;К сожалению, я не попал на сам фестиваль и не видел, как люди пользуются стендом. По отзывам ребят, многим из посетителей он понравился.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;p&gt;За фотографии и видео я хочу поблагодарить &lt;a href=&quot;https://alexanderkatin.ru&quot; target=&quot;_blank&quot;&gt;Сашу Катина&lt;/a&gt;. Если у вас остались вопросы, вы можете их задать в чате канала: @&lt;a href=&quot;https://t.me/codeque&quot; target=&quot;_blank&quot;&gt;codeque&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Подписывайтесь на мой &lt;a href=&quot;https://t.me/semeonboboshko&quot; target=&quot;_blank&quot;&gt;канал&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/semeonboboshko&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; и &lt;a href=&quot;https://www.instagram.com/boboshko&quot; target=&quot;_blank&quot;&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</content></entry><entry><id>semeonboboshko:shuttles</id><link rel="alternate" type="text/html" href="https://teletype.in/@semeonboboshko/shuttles?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=semeonboboshko"></link><title>Бот с расписанием шаттлов</title><published>2020-08-06T19:22:38.501Z</published><updated>2021-01-20T14:14:32.474Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/1b/42/1b42450c-a809-43d8-a3cd-c33204b9f454.png"></media:thumbnail><category term="bots" label="Боты"></category><summary type="html">&lt;img src=&quot;https://teletype.in/files/79/53/7953c7cf-9fb1-4656-a8d9-a3eba6411a47.png&quot;&gt;После Avito, я перешёл в «Ренессанс здоровье» по приглашению своего давнего товарища Лёши Кожевникова.</summary><content type="html">
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/79/53/7953c7cf-9fb1-4656-a8d9-a3eba6411a47.png&quot; width=&quot;2200&quot; /&gt;
    &lt;figcaption&gt;Иллюстрация — Илья Казаков&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;После Avito, я перешёл в «Ренессанс здоровье» по приглашению своего давнего товарища &lt;a href=&quot;https://www.facebook.com/alexeykozhevnikov&quot; target=&quot;_blank&quot;&gt;Лёши Кожевникова&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;У «Ренессанса» ходят собственные автобусы от метро до офиса и обратно. Это шаттлы, которые не отображаются в приложениях типа «Яндекс.Транспорт». А расписание их движения присылает HR в виде JPEG.&lt;/p&gt;
  &lt;p&gt;Такой формат показался мне неудобным и я решил упростить процесс восприятия информации.&lt;/p&gt;
  &lt;p&gt;Так появился Telegram-бот Shuttles (@&lt;a href=&quot;https://t.me/ShuttlesRobot&quot; target=&quot;_blank&quot;&gt;ShuttlesRobot&lt;/a&gt;), о котором пойдёт рассказ.&lt;/p&gt;
  &lt;h2&gt;Что умеет бот&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;iframe src=&quot;https://www.youtube.com/embed/gw-uCVvm06U?autoplay=0&amp;loop=0&amp;mute=0&quot;&gt;&lt;/iframe&gt;
    &lt;figcaption&gt;Демонстрация работы бота&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Сначала нужно понять, почему бот полезнее, чем JPEG.&lt;/p&gt;
  &lt;p&gt;Бот умеет показывать время прибытия ближайшего автобуса и минуты до него. Например, &lt;em&gt;«Через 30 минут в 7:30»&lt;/em&gt;.&lt;/p&gt;
  &lt;p&gt;Он также умеет склонять слово «минут». Например, &lt;em&gt;«Через 30 минут»&lt;/em&gt; или &lt;em&gt;«Через 32 минуты»&lt;/em&gt;.&lt;/p&gt;
  &lt;p&gt;Ещё бот определяет текущий день недели. Это нужно для того, чтобы напоминать, что в пятницу сокращённое расписание движения. А по выходным автобусы не ходят вовсе.&lt;/p&gt;
  &lt;p&gt;Текущая функциональность — MVP. И у меня в backlog уже есть идеи, как сделать бота удобнее и дружелюбнее.&lt;/p&gt;
  &lt;h2&gt;Реализация&lt;/h2&gt;
  &lt;p&gt;Я не планировал публиковать код этого проекта, ограничившись рассказом. Но затем понял, что ещё никогда не писал так много математики. И было бы здорово, чтобы более опытные ребята могли мне что-нибудь подсказать.&lt;/p&gt;
  &lt;p&gt;Если у вас есть замечания или предложения, вы смело можете их мне озвучить (@&lt;a href=&quot;https://t.me/boboshko&quot; target=&quot;_blank&quot;&gt;boboshko&lt;/a&gt;).&lt;/p&gt;
  &lt;p&gt;&lt;a href=&quot;https://github.com/boboshko/shuttles-robot&quot; target=&quot;_blank&quot;&gt;Репозиторий проекта&lt;/a&gt;.&lt;/p&gt;
  &lt;h3&gt;Бот&lt;/h3&gt;
  &lt;p&gt;Основой для бота служит &lt;a href=&quot;https://telegraf.js.org&quot; target=&quot;_blank&quot;&gt;Telegraf&lt;/a&gt;. На данный момент, это единственная подключаемая библиотека в проекте. Чтобы понимать, как с ней работать, можно почитать документацию или &lt;a href=&quot;https://telegraf.js.org/#/?id=example&quot; target=&quot;_blank&quot;&gt;посмотреть примеры&lt;/a&gt;.&lt;/p&gt;
  &lt;h3&gt;Расчёт времени&lt;/h3&gt;
  &lt;p&gt;Все операции со временем и определение текущего дня недели происходят в файле &lt;code&gt;timeCalculation.js&lt;/code&gt;. Я не буду полностью рассказывать о том, как происходят вычисления (в коде есть комментарии), а только затрону способ решения главной проблемы — получении массива с нужными значениями &lt;code&gt;&lt;a href=&quot;https://ru.wikipedia.org/wiki/%25D0%2592%25D1%2580%25D0%25B5%25D0%25BC%25D0%25B5%25D0%25BD%25D0%25BD%25D0%25B0%25D1%258F_%25D0%25BC%25D0%25B5%25D1%2582%25D0%25BA%25D0%25B0&quot; target=&quot;_blank&quot;&gt;timestamp&lt;/a&gt;&lt;/code&gt;.&lt;/p&gt;
  &lt;p&gt;Расписание хранится файле &lt;code&gt;schedule.json&lt;/code&gt; в формате матрицы. Каждый массив представляет из себя последовательность чисел. Например, &lt;code&gt;[21, 25, 0, 0]&lt;/code&gt; — это &lt;code&gt;21:25:00:00&lt;/code&gt;. Такой формат времени обусловлен тем, что функция &lt;code&gt;setHours&lt;/code&gt; для объекта &lt;code&gt;Date&lt;/code&gt; принимает аргументы в таком формате и помогает сохранить читаемость расписания для человека в &lt;code&gt;schedule.json&lt;/code&gt;.&lt;/p&gt;
  &lt;p&gt;Чтобы дальше было удобнее работать со временем, его нужно перевести в &lt;code&gt;timestamp&lt;/code&gt;. И &lt;code&gt;setHours&lt;/code&gt; помогает с этим справиться, возвращая &lt;code&gt;timestamp&lt;/code&gt; в часовом поясе UTC (минус три часа по Москве). В дальнейшем, для корректного отображения времени в интерфейсе пользователя, эту разницу нужно будет компенсировать вручную.&lt;/p&gt;
  &lt;p&gt;Но не всё так просто с &lt;code&gt;timestamp&lt;/code&gt;. Например, &lt;code&gt;21:25 UTC&lt;/code&gt; текущего дня — это &lt;code&gt;1591478700&lt;/code&gt;. А следующего — &lt;code&gt;1591565100&lt;/code&gt;. Следовательно, нужно рассчитывать значения &lt;code&gt;timestamp&lt;/code&gt; для всего расписания, каждый раз, когда нужно произвести остальные вычисления.&lt;/p&gt;
  &lt;p&gt;За это отвечает функция &lt;code&gt;convertTime&lt;/code&gt;. Результатом её работы будет массив &lt;code&gt;outArray&lt;/code&gt;, в котором хранится всё расписание на день в &lt;code&gt;timestamp&lt;/code&gt;.&lt;/p&gt;
  &lt;p&gt;Скорее всего, это не самый элегантный способ хранения времени. Расскажите мне, если знаете, как лучше (@&lt;a href=&quot;https://t.me/boboshko&quot; target=&quot;_blank&quot;&gt;boboshko&lt;/a&gt;).&lt;/p&gt;
  &lt;p&gt;Ну и вообще, буду рад, если кто-нибудь захочется присоединиться к разработке проекта.&lt;/p&gt;
  &lt;h2&gt;Принцип разработки&lt;/h2&gt;
  &lt;p&gt;Влад Самойлов, с которым я познакомился в Avito, рассказал мне об атомарном подходе в разработке.&lt;/p&gt;
  &lt;p&gt;Атомарный подход — это когда ты декомпозируешь большую задачу на более мелкие и выполняешь их последовательно. Этим методом я воспользовался, когда писал математику.&lt;/p&gt;
  &lt;p&gt;Я разбил все нужные действия для подсчёта времени на небольшии функции, в конце объединив их все в одну большую. А результат её выполнения экспортирую в файл с обработчиками бота.&lt;/p&gt;
  &lt;p&gt;Хочу поблагодарить Влада за совет и то, что он помогает мне с кодом, время от времени. Спасибо!&lt;/p&gt;
  &lt;h2&gt;Что бы хотелось&lt;/h2&gt;
  &lt;p&gt;Хотелось бы аналитику. В 2017-м для её сбора, я пользовался сервисом Botan от «Яндекса». Но сервис закрыли в 2018-м году. Я искал ему замену и сумел найти &lt;a href=&quot;https://chatbase.com&quot; target=&quot;_blank&quot;&gt;Chatbase&lt;/a&gt;. Но подключить его не вышло.&lt;/p&gt;
  &lt;p&gt;Ещё нужно понять, как читабельно выводить сразу всё расписание на день. Я пока не придумал хорошего варианта.&lt;/p&gt;
  &lt;p&gt;Расскажите мне, если можете помочь мне с этими вопросами.&lt;/p&gt;
  &lt;h2&gt;Как добавить свои шаттлы&lt;/h2&gt;
  &lt;p&gt;Вы можете добавить расписание своих автобусов в @&lt;a href=&quot;https://t.me/ShuttlesRobot&quot; target=&quot;_blank&quot;&gt;ShuttlesRobot&lt;/a&gt;, если они курсируют между двух точек. Это бесплатно.&lt;/p&gt;
  &lt;p&gt;От вас нужно только их расписание. После чего, вы и ваши товарищи смогут пользоваться ботом.&lt;/p&gt;
  &lt;p&gt;Присылать сюда (@&lt;a href=&quot;https://t.me/boboshko&quot; target=&quot;_blank&quot;&gt;boboshko&lt;/a&gt;).&lt;/p&gt;
  &lt;hr /&gt;
  &lt;p&gt;Если у вас остались вопросы, вы можете их задать в чате канала: @&lt;a href=&quot;https://t.me/codeque&quot; target=&quot;_blank&quot;&gt;codeque&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Подписывайтесь на мой &lt;a href=&quot;https://t.me/semeonboboshko&quot; target=&quot;_blank&quot;&gt;канал&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/semeonboboshko&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt; и &lt;a href=&quot;https://www.instagram.com/boboshko&quot; target=&quot;_blank&quot;&gt;Instagram&lt;/a&gt;.&lt;/p&gt;

</content></entry><entry><id>semeonboboshko:zarya-1</id><link rel="alternate" type="text/html" href="https://teletype.in/@semeonboboshko/zarya-1?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=semeonboboshko"></link><title>Домашняя метеостанция. Часть 1</title><published>2018-08-25T21:52:16.988Z</published><updated>2021-01-20T14:47:04.245Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/c4/c4189bad-3bc4-4790-a3be-4739c1c19cf7.png"></media:thumbnail><category term="meteostation" label="Метеостанция"></category><summary type="html">&lt;img src=&quot;https://teletype.in/files/07/0712dc14-a2d6-4b5d-964b-cd9199498dbb.gif&quot;&gt;Сегодня я не стану подробно разбирать написанный мною код (но без него не обойдётся). Сегодня я расскажу про свою мечту и её реализацию.</summary><content type="html">
  &lt;p&gt;Сегодня я не стану подробно разбирать написанный мною код (но без него не обойдётся). Сегодня я расскажу про свою мечту и её реализацию.&lt;/p&gt;
  &lt;h2&gt;Мечта&lt;/h2&gt;
  &lt;p&gt;Ещё &lt;a href=&quot;https://www.facebook.com/onlysemeon/posts/582696555261097&quot; target=&quot;_blank&quot;&gt;в начале&lt;/a&gt; 2017-го я загорелся идеей окутать свой дом погодными датчиками и получать с них данные в реальном времени через бота в Telegram.&lt;/p&gt;
  &lt;p&gt;Тогда эта идея мне казалась недосягаемой и мало практичной. Я до сих пор считаю свою идею мало практичной, но если что-то хочется — надо делать.&lt;/p&gt;
  &lt;h2&gt;Концепция метеостанции&lt;/h2&gt;
  &lt;p&gt;В моём представлении, метеостанция должна работать следующим образом. Раз в какой-то промежуток времени, платформа опрашивает погодные датчики и передаёт полученные данные в базу на сервер. Данные в базе копятся и с помощью Telegram-бота, можно их запрашивать. Например, можно узнать данные, за минуту, час, неделю, месяц, и так далее.&lt;/p&gt;
  &lt;h2&gt;Шаг за шагом&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/07/0712dc14-a2d6-4b5d-964b-cd9199498dbb.gif&quot; width=&quot;600&quot; /&gt;
    &lt;figcaption&gt;Вывод данных с датчиков в консоль Espruino Web IDE&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Для меня эта задача очень большая и, кажется, почти неподъёмная. Я решил действовать последовательно и разбить всё на этапы:&lt;/p&gt;
  &lt;ol&gt;
    &lt;li&gt;Настройка датчиков и платформы. Вывод данных в консоль.&lt;/li&gt;
    &lt;li&gt;Настройка сервера и передача полученных данных в базу.&lt;/li&gt;
    &lt;li&gt;Написание Telegram-бота и передача в него данных из базы.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h2&gt;Платформа&lt;/h2&gt;
  &lt;p&gt;В качестве основы для своей метеостанции я выбрал Iskra JS. Iskra JS — это, как &lt;a href=&quot;https://www.arduino.cc&quot; target=&quot;_blank&quot;&gt;Arduino&lt;/a&gt;, только производится в России и работает на JavaScript. Можно было бы остановиться на Arduino, но я не знаю C++. А с JavaScript уже хоть как-то знаком.&lt;/p&gt;
  &lt;p&gt;Все датчики, которые подходят к Arduino, можно подключить и к Iskra JS (если есть нужная библиотека). Обе платы находятся примерно в одном ценовом диапазоне. Конечно, если сравнивать Iskra JS с оригиналом Arduino, а не Китайской репликой. К слову, Китайскую реплику можно купить где-то за 200 рублей на AliExpress. Так что имейте в виду.&lt;/p&gt;
  &lt;p&gt;В остальном, отличий вроде бы нет.&lt;/p&gt;
  &lt;h2&gt;Конфигурация&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/b5/b5aa13c1-99fe-4da3-893f-2ba36355d97b.jpeg&quot; width=&quot;1920&quot; /&gt;
    &lt;figcaption&gt;Слева направо: Iskra JS, Slot Shield, Wi-Fi (ESP8266), термометр (TMP36), часы реального времени (DS1307) и барометр (LPS331AP)&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;Для первого этапа я взял аналоговый термометр (TMP36) и барометр (LPS331AP). Ещё понадобились часы реального времени (DS1307). Данные с этих датчиков передаются с помощью Wi-Fi (ESP8266). Он работает на частоте 2.4 GHz.&lt;/p&gt;
  &lt;p&gt;Все датчики имеют специальный форм-фактор и устанавливаются без пайки на Iskra JS с помощью переходника Slot Shield.&lt;/p&gt;
  &lt;h2&gt;Принципы работы&lt;/h2&gt;
  &lt;figure class=&quot;m_column&quot; data-caption-align=&quot;center&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/49/49d34b83-2c14-4e0d-9e6a-dbd976aa5b1b.gif&quot; width=&quot;600&quot; /&gt;
    &lt;figcaption&gt;Загрузка Wi-Fi модуля и последующий запрос к API «Яндекса»&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p&gt;При подаче питания на плату, через 10-15 секунд Wi-Fi модуль загружается и подключается к интернету. Затем, он делает запрос к API Яндекса и получает точное Московское время. После чего, полученное значение передаётся в часы реального времени. И только после этого, начинают работать все остальные датчики.&lt;/p&gt;
  &lt;p&gt;Я немного упрощённо описал принципы работы. Можно ознакомиться с &lt;a href=&quot;https://github.com/boboshko/zarya-meteostation&quot; target=&quot;_blank&quot;&gt;репозиторием&lt;/a&gt; на GitHub и самому вникнуть в код.&lt;/p&gt;
  &lt;h2&gt;Проблемы&lt;/h2&gt;
  &lt;p&gt;Конечно же, не всё так гладко.&lt;/p&gt;
  &lt;p&gt;Во-первых, у меня есть подозрения, что в определённый момент у Iskra JS заканчивается память и в консоль выводится что-то странное. Я пока не знаю, как это проверить и исправить.&lt;/p&gt;
  &lt;p&gt;Во-вторых, мне очень не нравится этот кусок:&lt;/p&gt;
  &lt;pre&gt;var wifi = require(&amp;#x27;@amperka/wifi&amp;#x27;).setup(PrimarySerial, function(err) {
  wifi.connect(SSID, PSWD, function(err) {
    print(&amp;#x27;Connected to Wi-Fi&amp;#x27;);
    getTime();
  });
});
&lt;/pre&gt;
  &lt;p&gt;Но другие варианты почему-то не срабатывают и переписать эту часть у меня пока не вышло.&lt;/p&gt;
  &lt;h2&gt;Благодарности&lt;/h2&gt;
  &lt;p&gt;Благодарности: &lt;a href=&quot;https://t.me/tynopet&quot; target=&quot;_blank&quot;&gt;Диме Гуденкову&lt;/a&gt; и &lt;a href=&quot;https://t.me/evgenykochetkov&quot; target=&quot;_blank&quot;&gt;Жене Кочеткову&lt;/a&gt; — за помощь с кодом. &lt;a href=&quot;https://www.instagram.com/lytkini&quot; target=&quot;_blank&quot;&gt;Илье Лыткину&lt;/a&gt; — за перевод описания &lt;a href=&quot;https://github.com/boboshko/zarya-meteostation&quot; target=&quot;_blank&quot;&gt;репозитория&lt;/a&gt;.&lt;/p&gt;
  &lt;hr /&gt;
  &lt;p&gt;Подписывайтесь на Telegram-канал «Дизайнер учит код». Меня всегда можно найти в &lt;a href=&quot;https://instagram.com/boboshko&quot; target=&quot;_blank&quot;&gt;Instagram&lt;/a&gt;, &lt;a href=&quot;https://fb.me/onlysemeon&quot; target=&quot;_blank&quot;&gt;Facebook&lt;/a&gt; или &lt;a href=&quot;https://twitter.com/semeonboboshko&quot; target=&quot;_blank&quot;&gt;Twitter&lt;/a&gt;. Или напишите моему &lt;a href=&quot;http://t.me/BoboshkoRobot&quot; target=&quot;_blank&quot;&gt;боту-резюме&lt;/a&gt;.&lt;/p&gt;

</content></entry></feed>