Автоматизируем новости

Сего­дня у нас про­ект по авто­ма­ти­за­ции: будем уско­рять то, что мы дела­ем в жур­на­ле каж­дый день. Если вы дела­е­те что-то похо­жее — тоже може­те такое авто­ма­ти­зи­ро­вать.

Предыстория

У нас есть руб­ри­ка «Ново­сти» — там наши кол­ле­ги каж­дый день пуб­ли­ку­ют замет­ки о тех­но­ло­ги­че­ских и науч­ных новин­ках.
Рань­ше про­цесс был устро­ен так:

  1. Каж­дый автор «пыле­со­сит» свои источ­ни­ки.
  2. Авто­ры дела­ют под­бор­ки собы­тий и изоб­ре­те­ний, о кото­рых мож­но напи­сать.
  3. Авто­ры при­сы­ла­ют под­бор­ки дежур­но­му редак­то­ру руб­ри­ки. Тот при­ни­ма­ет реше­ние, какие ново­сти сто­ит взять в «Код», а какие — нет.
  4. Авто­ры пишут ново­сти.
  5. Дежур­ный редак­тор про­ве­ря­ет и доде­лы­ва­ет ново­сти.

Основ­ной затык с п. 3 — если редак­тор зату­пил или дол­го не отве­ча­ет, редак­ци­он­ный про­цесс может встать.

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

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

Что будем делать

Самый про­стой спо­соб решить эту зада­чу — сде­лать веб-страницу с вари­ан­та­ми отве­тов. Вы выби­ра­е­те нуж­ные и полу­ча­е­те ответ: сто­ит эту новость брать или нет.

В чек-листе у нас есть знач­ки: ✅ и ❌. Пусть галоч­ка обо­зна­ча­ет плюс 1 балл, а кре­стик — минус 1 балл. За каж­дый ответ мы при­бав­ля­ем или отни­ма­ем нуж­ное коли­че­ство бал­лов и смот­рим на резуль­тат.

Что­бы понять, брать новость или нет, сде­ла­ем такую гра­да­цию:

  • если новость наби­ра­ет отри­ца­тель­ное коли­че­ство бал­лов, то точ­но не берём;
  • если сум­ма бал­лов рав­на нулю — пере­спро­сить шефа;
  • если новость набра­ла один балл, то всё реша­ют кар­тин­ки или видео — если они есть, то новость тоже есть;
  • если у ново­сти в сум­ме 2 бал­ла и выше — одно­знач­но берём в рабо­ту.

Выбираем варианты ответов

Нам пона­до­бят­ся пере­клю­ча­те­ли — спе­ци­аль­ные поля, где мож­но выбрать толь­ко один из несколь­ких вари­ан­тов. Выгля­дят они так:

Синяя точ­ка озна­ча­ет, что мы выбра­ли пер­вый вари­ант. Если выбе­рем вто­рой, то на пер­вом она авто­ма­ти­че­ски сни­мет­ся:

За такой пере­клю­ча­тель в HTML отве­ча­ет эле­мент <input> со свой­ством type="radio". Что­бы поста­вить его на стра­ни­цу, пишут так:

<input name="result" type="radio" value="2">

Послед­нее свой­ство value отве­ча­ет за резуль­тат — какой ответ мы полу­чим, если выбе­рем этот вари­ант. Двой­ка у нас полу­чи­лась от того, что в чек-листе напро­тив это­го отве­та сто­я­ло две галоч­ки. Если бы было два кре­сти­ка, мы бы напи­са­ли value="-2".

Теперь у нас есть всё, что­бы офор­мить пер­вый вопрос в виде кода на HTML:

<!-- Заголовок вопроса -->
<p><b>
    Это результат или мысли?
  </b></p>
<!-- Абзац, который состоит из переключателя и текста -->
<!-- У каждого ответа есть свой рейтинг, он записан в значение value -->
<p><input name="result" type="radio" value="2">
  Что-то изобрели, получили результаты исследования, ключевое слово — результаты
</p>
<!-- Дальше всё то же самое -->
<p>
  <input name="result" type="radio" value="-1">
  Только думают, планируют, размышляют
</p>
<p><input name="result" type="radio" value="-2">
  Статья-обзор, как кто-то фантазирует о будущем
</p>
<br>

Мы сде­ла­ли три пере­клю­ча­те­ля с оди­на­ко­вым име­нем result. Это нуж­но для того, что­бы бра­у­зер пони­мал, что все три отве­та отно­сят­ся к одно­му вопро­су и нуж­но выбрать один из них. Если бы мы вез­де поста­ви­ли раз­ные име­на для свой­стваname, то мож­но было бы выбрать все три одно­вре­мен­но, а нам это не нуж­но.

Полу­ча­ет­ся, что для осталь­ных вопро­сов нам нуж­но сде­лать то же самое, толь­ко поста­вить уни­каль­ный пара­метр name для каж­дой груп­пы вопро­сов и про­сле­дить за бал­ла­ми за отве­ты:

<p><b>
    Это прорыв для человека?
  </b></p>
<p><input name="mega" type="radio" value="-2">
  Что-то существующее немного улучшат с помощью технологий
</p>
<p><input name="mega" type="radio" value="1">
  Что-то существующее выведут на новый уровень с помощью технологий
</p>
<p><input name="mega" type="radio" value="2">
  Речь о чём-то, что резко повышает качество жизни человека
</p>
<p><input name="mega" type="radio" value="-2">
  Речь о чём-то, что в первую очередь поможет учёным или исследователям
</p>
<br>
<p><b>
    Это на хайпе?
  </b></p>
<p><input name="hype" type="radio" value="1">
  Новость про публичную фигуру: Маска, Безоса и т. д.
</p>
<p><input name="hype" type="radio" value="2">
  Это касается сервисов или продуктов, доступных в России
</p>
<p><input name="hype" type="radio" value="2">
  Это сделано или будет использоваться в России
</p>
<p><input name="hype" type="radio" value="-3">
  Это касается продуктов или сервисов, которых нет в России? Алекса, например
</p>
<br>
<p><b>
    Можно посмотреть?
  </b></p>
<p><input name="see" type="radio" value="3">
  Есть красивая картинка или видео, где демонстрируются результаты работы
</p>
<p><input name="see" type="radio" value="-1">
  У учёных есть идея, но пока нет картинок. Или есть картинка, но это скорее график
</p>
<p><input name="see" type="radio" value="1">
  Эта картинка демонстрирует конкретно то, что изобрели?
</p>
<p><input name="see" type="radio" value="-1">
  То, что изобрели, невозможно продемонстрировать как таковое, например, это скрытый алгоритм
</p>
<br>
Даже без дизай­на и сти­лей стра­ни­ца выгля­дит как рабо­чий про­дукт

Добавляем кнопку подсчёта баллов

Доба­вим на стра­ни­цу кноп­ку, по нажа­тию на кото­рую запу­стит­ся скрипт под­счё­та бал­лов:

<button onclick="count()"> Оценить </button>

К кноп­ке при­вя­зан обра­бот­чик собы­тий onclick — он сле­дит за нажа­ти­я­ми и запус­ка­ет нуж­ный скрипт. Скрип­та у нас ещё нет, поэто­му им и зай­мём­ся.

Логи­ка будет такая:

  1. Обну­ля­ем коли­че­ство отме­чен­ных вопро­сов и набран­ных бал­лов.
  2. Нахо­дим все пере­клю­ча­те­ли на стра­ни­це.
  3. Счи­та­ем, сколь­ко из них отме­че­но. Если мень­ше четы­рёх (у нас 4 вопро­са), то выво­дим сооб­ще­ние, что не всё отме­че­но.
  4. Для каж­до­го отме­чен­но­го счи­та­ем, сколь­ко он даёт нам бал­лов, поло­жи­тель­ных или отри­ца­тель­ных, и скла­ды­ва­ем бал­лы вме­сте.
  5. Если у нас есть 4 отве­та, то в зави­си­мо­сти от набран­ных бал­лов выво­дим резуль­тат.

Что­бы у нас на стра­ни­це появи­лась инфор­ма­ция с резуль­та­та­ми, доба­вим пустой абзац и про­пи­шем ему своё имя клас­са. Так мы смо­жем отли­чать его от дру­гих абза­цев. Когда нам что-то пона­до­бит­ся туда поме­стить, мы най­дём его по име­ни клас­са и поло­жим в него нуж­ный текст.

Доба­вим абзац в самый конец стра­ни­цы:

<!-- В самом низу сделаем пустой абзац, куда будем выводить результаты --> <p class = "itogo"></p>

Пишем скрипт

В скрип­те мы будем исполь­зо­вать три коман­ды, кото­рые нам ещё не встре­ча­лись, но они доволь­но про­стые.

Что­бы не под­клю­чать jQuery и при этом нахо­дить нуж­ные эле­мен­ты на стра­ни­це, исполь­зу­ем функ­цию document.getElementsByClassName("itogo"). Она най­дёт все эле­мен­ты на стра­ни­це с ука­зан­ным клас­сом (itogo) и вер­нёт мас­сив из най­ден­ных эле­мен­тов. Так как на стра­ни­це у нас толь­ко один такой эле­мент с таким клас­сом, то это сра­зу всё упро­ща­ет.

Вто­рая коман­да — функ­ция document.getElementsByTagName('input'). Она нахо­дит все тэги input и дела­ет из них мас­сив с объ­ек­та­ми. Даль­ше с ними мож­но уже рабо­тать как с обыч­ны­ми эле­мен­та­ми — про­ве­рять их свой­ства и зна­че­ния.

Тре­тье — свой­ствоgetAttribute(). С его помо­щью мы выяс­ним, пере­клю­ча­тель перед нами или нет. Если свой­ство getAttribute('type') сов­па­да­ет с 'radio', зна­чит это пере­клю­ча­тель.

// Функция, которая делает всю работу и срабатывает после нажатия «Оценить»
function count() {
  // общее количество баллов
  let score = 0;
  // Сколько вопросов отмечено
  let set = 0;
  // Находим элемент на странице, куда будем выводить результат
  let el = document.getElementsByClassName("itogo");
  // А сюда получаем все элементы ввода, в том числе и переключатели
  let inputs = document.getElementsByTagName('input');
  // Перебираем все элементы ввода по порядку и смотрим
  for (var i = 0; i < inputs.length; i++) {
    // Если перед нами — переключатель и он отмечен, то…
    if ((inputs[i].getAttribute('type') == 'radio') && (inputs[i].checked == true)) {
      // Увеличиваем общее количество отмеченных переключателей
      set += 1;
      // Обновляем рейтинг для новости: берём значение, переводим его в число и складываем
      score = score + Number(inputs[i].getAttribute('value'));
    }
  }
  // Если есть ответы на все 4 вопроса
  if (set == 4) {
    // то смотрим на рейтинг и выводим итоговый вердикт, а в скобках — сколько баллов набрала новость
    if (score < 0) { el[0].innerHTML = 'Не берём (' + score + ')' };
    if (score == 0) { el[0].innerHTML = 'Ни туда, ни сюда (' + score + ')' };
    if (score == 1) { el[0].innerHTML = 'Если есть картинки — берём (' + score + ')' };
    if (score > 1) { el[0].innerHTML = 'Точно берём (' + score + ')' };
  }
  // А если какой-то вопрос пропустили, то так и пишем
  else {
    el[0].innerHTML = 'Отмечены не все вопросы';
  }
}

Сбрасываем ответы

Что­бы не путать­ся, доба­вим кноп­ку сбро­са. Она убе­рёт все отме­чен­ные вари­ан­ты, и сле­ду­ю­щую новость мож­но оце­ни­вать зано­во:

<button onclick="clear()"> Сбросить </button>

Для функ­ции clear() мы возь­мём код из преды­ду­щей функ­ции и немно­го его попра­вим:

// Сброс ответов
function clearall() {
  // Получаем все элементы ввода, в том числе и переключатели
  let inputs = document.getElementsByTagName('input');
  // Перебираем все элементы ввода по порядку и смотрим
  for (var i = 0; i < inputs.length; i++) {
    // Если перед нами — переключатель, то…
    if (inputs[i].getAttribute('type') == 'radio') {
      // …сбрасываем его
      inputs[i].checked = false;
    }
  }
  // Находим элемент на странице, куда будем выводить результат
  let el = document.getElementsByClassName("itogo");
  // Очищаем абзац с результатами
  el[0].innerHTML = '';
}
Сра­зу вид­но, что с таки­ми отве­та­ми новость мож­но брать в рабо­ту

Если вам пока этот сер­вис не нужен, мож­но про­сто посмот­реть гото­вый резуль­тат.

Что дальше

Кажет­ся, что про­бле­ма реше­на, но на самом деле нет, смот­ри­те:

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

Всё это сде­ла­ем в сле­ду­ю­щий раз. Не пере­клю­чай­тесь.

Готовый код

<html>
<!-- служебная часть -->

<head>
  <!-- заголовок страницы -->
  <title>Отбор новостей</title>
  <!-- настраиваем служебную информацию для браузеров -->
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <!-- закрываем служебную часть страницы -->
</head>
<script type="text/javascript">
  // Функция, которая делает всю работу и срабатывает после нажатия «Оценить»
  function count() {
    // общее количество баллов
    letscore = 0;
    // Сколько вопросов отмечено
    letset = 0;
    // Находим элемент на странице, куда будем выводить результат
    letel = document.getElementsByClassName("itogo");
    // А сюда получаем все элементы ввода, в том числе и переключатели
    letinputs = document.getElementsByTagName('input');
    // Перебираем все элементы ввода по порядку и смотрим
    for (var i = 0; i < inputs.length; i++) {
      // Если перед нами — переключатель, и он отмечен, то…
      if ((inputs[i].getAttribute('type') == 'radio') && (inputs[i].checked == true)) {
        // Увеличиваем общее количество отмеченных переключателей
        set += 1;
        // Обновляем рейтинг для новости: берём значение, переводим его в число и складываем
        score = score + Number(inputs[i].getAttribute('value'));
      }
    }
    // Если есть ответы на все 4 вопроса
    if (set == 4) {
      // то смотрим на рейтинг и выводим итоговый вердикт, а в скобках — сколько баллов набрала новость
      if (score < 0) { el[0].innerHTML = 'Не берём (' + score + ')' };
      if (score == 0) { el[0].innerHTML = 'Ни туда, ни сюда (' + score + ')' };
      if (score == 1) { el[0].innerHTML = 'Если есть картинки — берём (' + score + ')' };
      if (score > 1) { el[0].innerHTML = 'Точно берём (' + score + ')' };
    }
    // А если какой-то вопрос пропустили, то так и пишем
    else {
      el[0].innerHTML = 'Отмечены не все вопросы';
    }
  }
  // Сброс ответов
  function clearall() {
    // Получаем все элементы ввода, в том числе и переключатели
    let inputs = document.getElementsByTagName('input');
    // Перебираем все элементы ввода по порядку и смотрим
    for (var i = 0; i < inputs.length; i++) {
      // Если перед нами — переключатель, то…
      if (inputs[i].getAttribute('type') == 'radio') {
        // …сбрасываем его
        inputs[i].checked = false;
      }
    }
    // Находим элемент на странице, куда будем выводить результат
    let el = document.getElementsByClassName("itogo");

    // Очищаем абзац с результатами
    el[0].innerHTML = '';
  }
</script>
<!-- началось содержимое страницы -->

<body>
  <!-- Заголовок вопроса -->
  <p><b>
      Это результат или мысли?
    </b></p>
  <!-- Абзац, который состоит из переключателя и текста -->
  <!-- У каждого ответа есть свой рейтинг, он записан в значение value -->
  <p><input name="result" type="radio" value="2">
    Что-то изобрели, получили результаты исследования, ключевое слово — результаты
  </p>
  <!-- Дальше всё то же самое -->
  <p><input name="result" type="radio" value="-1">
    Только думают, планируют, размышляют
  </p>
  <p><input name="result" type="radio" value="-2">
    Статья-обзор, как кто-то фантазирует о будущем
  </p>
  <br>
  <p><b>
      Это прорыв для человека?
    </b></p>
  <p><input name="mega" type="radio" value="-2">
    Что-то существующее немного улучшат с помощью технологий
  </p>
  <p><input name="mega" type="radio" value="1">
    Что-то существующее выведут на новый уровень с помощью технологий
  </p>
  <p><input name="mega" type="radio" value="2">
    Речь о чём-то, что резко повышает качество жизни человека
  </p>
  <p><input name="mega" type="radio" value="-2">
    Речь о чем-то, что в первую очередь поможет учёным или исследователям
  </p>
  <br>
  <p><b>
      Это на хайпе?
    </b></p>
  <p><input name="hype" type="radio" value="1">
    Новость про публичную фигуру: Маска, Безоса и т. д.
  </p>
  <p><input name="hype" type="radio" value="2">
    Это касается сервисов или продуктов, доступных в России
  </p>
  <p><input name="hype" type="radio" value="2">
    Это сделано или будет использоваться в России
  </p>
  <p><input name="hype" type="radio" value="-3">
    Это касается продуктов или сервисов, которых нет в России? Алекса, например
  </p>
  <br>
  <p><b>
      Можно посмотреть?
    </b></p>
  <p><input name="see" type="radio" value="3">
    Есть красивая картинка или видео, где демонстрируются результаты работы
  </p>
  <p><input name="see" type="radio" value="-1">
    У учёных есть идея, но пока нет картинок. Или есть картинка, но это скорее график
  </p>
  <p><input name="see" type="radio" value="1">
    Эта картинка демонстрирует конкретно то, что изобрели?
  </p>
  <p><input name="see" type="radio" value="-1">
    То, что изобрели, невозможно продемонстрировать как таковое, например, это скрытый алгоритм
  </p>
  <br>
  <!-- Рисуем кнопку, по нажатию на которую запустится подсчёт рейтинга для новости -->
  <button onclick="count()"> Оценить </button>
  <!-- Кнопка, которая сбрасывает все ответы -->
  <button onclick="clearall()"> Сбросить </button>
  <!-- Делаем отступ -->
  <br>

  <!-- В самом низу сделаем пустой абзац, куда будем выводить результаты -->
  <p class="itogo"></p>
</body>

</html>

Текст и код:
Миха­ил Поля­нин

Редак­тор:
Мак­сим Илья­хов

Кор­рек­тор:
Ира Михе­е­ва

Вёрст­ка:
Маша Дро­но­ва

Худож­ник:
Даня Бер­ков­ский

Соц­се­ти:
Олег Веш­кур­цев