Было бы сорок лет хора, если бы без перерывов

Если правильно помню, Владимир Александрович Шереметьев пришёл в наш детский сад прослушивать потенциальных участников хора мальчиков студии «Мечта» в феврале 1984-го — ровно 40 лет назад. Кажется, чуть ли не половину прослушанных он пригласил ближе к лету прийти во Дворец культуры железнодорожников, где проходили репетиции — пришёл в итоге я один и задержался лет на 10, до осени 1994-го, когда пришлось уйти из-за того, что не хватало времени на одновременные занятия учёбой (был первый курс) и хором. А потом лет через 10 снова пришёл и пел до самого отъезда из Челябинска с перерывами на пандемию и долгие поездки в Москву и Вильнюс.

Тогда Владимир Александрович был даже моложе, чем я сейчас, а теперь ему 84 и он по-прежнему — хоровой дирижёр. Многая лета! გაუმარჯოს!

30 или 31

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

Итак, в языках с си-подобным синтаксисом (хотя подойдёт и для питона) определить, сколько же дней в месяце, можно по формуле

days = 30 + (month + 4) * 13 / 12 % 2

где month — номер месяца начиная с 1.

Работает для всех месяцев кроме февраля. Например, перловый однострочник

perl -e 'printf "%2d → %d\n", $_, 30 + ($_ + 4) * 13 / 12 % 2 for 1 .. 12'

выведет

 1 → 31
 2 → 30
 3 → 31
 4 → 30
 5 → 31
 6 → 30
 7 → 31
 8 → 31
 9 → 30
10 → 31
11 → 30
12 → 31

С февралём ситуация чуть более сложная, потому что число дней в нём зависит от номера года: в григорианском календаре високосным годом является такой, который делится на 4, но не на 100, хотя если при этом делится на 400 — всё равно високосный. Например, 1900 год — обычный, а 2000 — високосный, как и 2004.

year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)

можно вообще переписать как

!!(!(year % 4) && ((year % 100) || !(year % 400)))

однако такой вариант хуже — хоть и компактнее, но менее понятен.

Проверим (в перле «из коробки» нет булевых типов, поэтому выводятся нули и единицы)

1600 → 1
1700 → 0
1799 → 0
1800 → 0
1899 → 0
1900 → 0
1901 → 0
1944 → 1
1988 → 1
1999 → 0
2000 → 1
2001 → 0
2004 → 1

Осталось объединить всё в одну формулу

Без второго питона

Время второго питона прошло — вокруг уже третий, а после обновления операционной системы на компьютере до Debian GNU/Linux 11 (bullseye) из доступных к установке пакетов пропало почти всё, относившееся ко второму питону.

computer with Debian linux and two pythons -- yellow and blue one

Однако встречаются ещё программы, которым для работы нужен именно второй питон — для таких случаев можно воспользоваться методом, описанным на compsmag.com/blog/how-you-can-install-python-3-x-or-2-7-on-debian-11-bullseye-linux/, только подходить к написанному надо критически, не копировать команды бездумно — они там содержат избыточное число пробелов, но в них нет переводов строк.

# python2.7 ./get-pip.py 
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
Collecting pip<21.0
  Downloading pip-20.3.4-py2.py3-none-any.whl (1.5 MB)
     |████████████████████████████████| 1.5 MB 1.2 MB/s 
Collecting setuptools<45
  Downloading setuptools-44.1.1-py2.py3-none-any.whl (583 kB)
     |████████████████████████████████| 583 kB 5.2 MB/s 
Collecting wheel
  Downloading wheel-0.37.1-py2.py3-none-any.whl (35 kB)
Installing collected packages: pip, setuptools, wheel
Successfully installed pip-20.3.4 setuptools-44.1.1 wheel-0.37.1

Ну а при наличии pip можно ставить и остальные модули, хоть для них и нет готовых пакетов. Например, для редактора карт JOSM есть плагин ext_tools, вызывающий трассировщик снимков Scanaerial, которому нужны модули pillow и pyproj — в одиннадцатом дебиане их нельзя поставить командой apt install python-pillow python-pyproj

# python2.7 -m pip install pillow pyproj
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support pip 21.0 will remove support for this functionality.
Collecting pillow
  Downloading Pillow-6.2.2-cp27-cp27mu-manylinux1_x86_64.whl (2.1 MB)
     |████████████████████████████████| 2.1 MB 1.1 MB/s 
Collecting pyproj
  Downloading pyproj-2.2.2-cp27-cp27mu-manylinux1_x86_64.whl (11.2 MB)
     |████████████████████████████████| 11.2 MB 4.2 MB/s 
Collecting aenum; python_version < "3.6"
  Downloading aenum-3.1.8-py2-none-any.whl (120 kB)
     |████████████████████████████████| 120 kB 4.9 MB/s 
Installing collected packages: pillow, aenum, pyproj
Successfully installed aenum-3.1.8 pillow-6.2.2 pyproj-2.2.2

Редких животных

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

🇬🇪 На грузинском первом уроке дают слова «ка́ци» — мужчина, «ка́ли» — женщина», «би́чи» — мальчик и «го́го» — девочка, а на втором сразу переходят к числам, и это не «э́рти», «о́ри», «са́ми», то есть 1, 2, 3, а внезапно 25, 12, 14, 40. Ну и алфавит куда-то спрятали: в описании есть уроки по нему, но я их не вижу. Впрочем, с грузинским алфавитом я пробовал разобраться ещё давным-давно, начиная с девяностых, и после приезда в Батуми достаточно быстро освоил оставшиеся буквы.

🇱🇹 А в литовской части даже моего почти никакого знания языка хватает на то, чтобы находить ошибки в каждом уроке. В каждом. Вот и сейчас, простите за неровный почерк…

В дуолинго 🦉 этих языков нет.
В 50languages 🗨️ они есть, но там интерфейс неудобный и всё очень мелкое.

P. S. КДПВ созданы c помощью Image Creator from Designer (ранее — Bing Image Creator).

Белое на… Каком?

Малоконтрастный текст (например, светло-серый на белом) плохо читается, как, впрочем, и белый на светло-сером или вовсе голубом. В борьбу за право читать с комфортом даже поисковые системы вступили — насколько помню, и Google, и Bing (про Яндекс не уверен, но возможно) учитывают доступность сайтов при поиске — сайты с хорошей доступностью (в смысле accessibility как возможность воспринять) занимают в нём позиции ближе к началу. Аналогичная ситуация и с мобильной доступностью — вес сайта, скорость загрузки и его отображение на телефонах тоже важны.

Есть разные инструменты для подбора хороших цветов и некоторые совсем рядом — в отладчике браузера — в случае Хрома на Линуксе и Windows он открывается клавишей F12. Отладчик Google Chrome показывает предупреждение, если в паре цветов контраст недостаточен и позволяет исправить цвет текста для соответствия уровням AA и AAA (см. стандарты WCAG 2.0 или ГОСТ Р 52872-2019). Но оно не может подобрать допустимый цвет, когда фон светлый, а текст белый — предлагает лишь поменять белый на точно такой же цвет, не трогая фон. Выход — поменять цвета местами — тогда подбор будет доступен.

Отладчик Google Chrome

Как перенаправить посетителя на HTTPS, если Апач глубоко

Время от времени помогаю знакомым старта́перам в части, относящейся к вебу. В процессе обнаруживаю странное: есть сайты, которыми не сильно можно порулить, даже если и хочется: хостинг-провайдер предоставляет лишь возможность править апачный конфигурационный файл .htaccess. Всё бы ничего, но между файлами и посетителем сайта не только Apache — там ещё и Nginx, чья конфигурация вообще недоступна.

Сейчас в 2023 году редко какой сайт не использует HTTPS (этот — один из них, но сейчас не о нём речь). Если сайт сделан на какой-нибудь CMS, там вполне может существовать возможность указать в настройках основной адрес сайта и включить перенаправление на него — так можно перенаправляться на использование HTTPS и в WordPress, и в Open Journal Systems.

Но что делать, если сайт — статичный? Вроде бы, можно обойтись средствами самого́ Апача, а точнее, его модуля mod_rewrite — напишем в .htaccess:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

Этот код включает механизм перенаправлений, проверяет, используется ли HTTPS и если нет — перенаправляет посетителя. Только в нашем случае условие RewriteCond всегда истинно, что вызывает циклические перенаправления. Причина — Apache в конкретном случае работает всегда по HTTP, поэтому значение переменной HTTPS — всегда off. С другими переменными аналогично — например, SERVER_PORT всегда равен 80.

В случае, когда есть доступ к настройкам Nginx, проблем нет — всё настраивается там. Но если нет, приходится искать другие переменные, которые однозначно покажут, как именно посетитель обращается к сайту. Nginx, передавая запрос Апачу, добавляет в него поля, чьи имена начинаются с X-Forwarded — среди них есть и X-Forwarded-Proto, где хранится запрашиваемый посетителем протокол — http или https. В итоге работоспособным оказался такой код:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{HTTP:X-Forwarded-Proto} !https
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

Может возникнуть вопрос — нельзя ли в условии вместо !https написать более короткое http? Оказалось, что нет — сама по себе строка без знака равенства не проверяется на совпадение, а сопоставляется с образцом, то есть, происходит pattern matching. А такому условию удовлетворяли бы оба рассмотренных значения и условие всегда оказывалось бы истинным, что снова бы вызвало циклические перенаправления.

Четыре и шесть

0. КДПВ — четыре синеньких луча да шесть рыженьких:

1. На Урале уже пятнадцатое — можно поздравлять.

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

Узковатое меню

Open Journal Systems 3 вышла уже шесть лет назад — в 2016 году, но за всё это время русское меню, отображаемое администратору в шапке страниц в теме оформления, включенной по умолчанию (Manuscript), слишком узкое:

OJS 3 с узким административным меню

Я этот баг 🐞 видел, но как-то не до него было — я поддерживал старые журналы, сделанные ещё на OJS 2. Сейчас посмотрел — исправляется буквально изменением одного байта — github.com/pkp/ojs/pull/3618

Меню стало чуть шире

Когда пулл-реквест будет принят и это изменение появится в новых версиях OJS, пока не знаю, но кому не терпится, может добавить собственное стилевое правило:

@media (min-width: @screen-desktop) {
    .pkp_navigation_user {
        ul {
            width: 13em;
        }
    }
}

Переводы для темы оформления Manuscript лежат в plugins/themes/default/locale — можно найти слово «Администрирование» на разных языках и сравнить ширину:

grep -R 'msgid "navigation.admin"' -A 1 \
| sort \
| perl -nle 'print qq{<li title="$1">$2</li>} if m{^(.+)/.*msgstr "(.*)"}'
Список переводов
Ширина голубой части — 10em

Оказывается русское слово — самое длинное. И самое широкое, потому что буква и шире, чем i.