yurikhan: (Default)

Из обсуждения, как людям объяснять Git:

X: Do not mention DAG to people who do not have a formal computer science background. […] The word “graph” has a completely different meaning to laypeople.

Me: You mean the graph plot? Well, in Russian the word for graph-as-in-graph-theory is an homonym of the word for count-as-in-count-Dracula.

yurikhan: (Default)
ар‧хи‧ва́ж, сущ., неод., м., 2-е скл.
Действие по гл. архивировать.
ар‧хи‧ва́ж‧ный, прил.
Относящийся к архиважу. Я к вам по архиважному вопросу.
yurikhan: (Default)

Хочу человеческий синтаксис для описания графов.

Что у нас сейчас есть: Graph description languages.

  • Половина из них основана на XML, что хорошо для инструментов, но плохо для написания руками.

  • DOT спроектирован математиками и из-за этого тоже излишне многословен. Мы можем определить в графе дефолтные свойства вершин и рёбер, и это позволяет немного экономить. Но если у нас в графе два типа рёбер, то один можно сделать дефолтным, а второй приходится выписывать каждый раз:

    digraph G {
      edge [arrowhead=empty] # inheritance
    
      Derived -> Base
    
      Aggregate -> Part [arrowtail=odiamond, arrowhead=open] # aggregation
    }

    Или можно определить подграф и рёбра второго типа определять в нём, что плохо для локальности (часто хочется описывать рёбра, относящиеся к одной вершине, рядом):

    digraph G {
      subgraph {
        edge [arrowhead=empty] # inheritance
        Derived -> Base
      }
      subgraph {
        edge [arrowtail=odiamond, arrowhead=open] # aggregation
        Aggregate -> Part
      }
    }

Как надо:

  • Есть классы вершин и рёбер. Все общие свойства вершин или рёбер одного класса описываются в определении класса. Важно, что определения классов можно вынести в библиотеки и подключать их, когда надо.

  • Минимальное определение вершины состоит из имени класса вершины и имени вершины, на отдельной строке, через пробел. Далее опционально индивидуальные свойства вершины. (Тут решить между синтаксисом со скобками и разделителями или просто indentation-based.) Имя может быть одним словом или произвольной строкой в кавычках.

  • Минимальное определение ребра состоит из имени начальной вершины, имени класса ребра и имени конечной вершины, также на отдельной строке через пробел, также с опциональным блоком свойств.

Пример:

node.class [shape=box]
node.interface [shape=circle]
edge.is-a [arrowhead=empty]
edge.implements [arrowhead=empty, style=dashed]
edge.has-a [arrowtail=odiamond, arrowhead=open]
edge.owns-a [arrowtail=diamond, arrowhead=open]

interface IThing

class Base

class Derived
Derived is-a Base
Derived implements IThing

class Part

class Aggregate
Aggregate has-a Part

Буду в отпуске, сяду и напишу парсер этого и конвертор в DOT.

Stretch goal: какой-нибудь способ указать, что одни «node1 relation node2» отображать рёбрами, а другие — вложением в кластер-подграф. Типа nginx deployed-on cache-server.

yurikhan: (Default)

Где-то в параллельной вселенной магнаты и магниты — это соли магниевой и магнистой кислот, соответственно.

yurikhan: (Default)

Берём таблицу времён восхода/заката за последний год. Видим такую фигню: зимой восход в девять, закат в четыре. Летом восход в четыре, закат в девять. Астрономический полдень плавает в районе 12:30. Что как бы указывает на примерное соответствие поясного и астрономического времени, но ни фига не соотносится с реальными надобностями.

Если у меня рабочий день начинается скрам-митингом в 11:00 и кончается в 19:30, то просыпаюсь я в 9–9:30. Значит, летом первые пять часов светового дня я тупо просыпаю. А вечером темнеет раньше, чем хочется спать.

Зимой с утром как-то получше, но вся вторая половина рабочего дня приходится на световую ночь.

Впрочем, в этом году новосибирские чиновники внезапно взялись за ум (или что у них есть… ещё там), провели опрос и с 24 июля зона Asia/Novosibirsk переходит из UTC+6 в UTC+7. Соответственно, световой день летом — с пяти до десяти, зимой — с десяти до пяти, полдень ≈13:30.

Как по мне, направление правильное, но мало. Будь моя воля, я б токийское время установил, UTC+9.

yurikhan: (Default)

Четыре года назад я жаловался на тенденцию запихивать векторные иконки в кастомные шрифты и стучал ногами, что надо использовать SVG. В этом году ГитХаб это сделал.

Ну и что же мы теперь имеем: мыло.

Потому что в шрифтах есть хинтинг, привязывающий тонкие линии к пиксельной сетке. А в SVG его ещё нет.

Поэтому вот они нарисовали иконки, выровняли их так, чтоб при дефолтных стилях было чётко, ну и всё. А я предпочитаю шрифт достаточного размера и интерлиньяж посвободнее, и у меня на рабочем месте они съезжают на полпикселя. Причём не все. (На домашней машине у меня HiDPI, поэтому SVG-иконки выглядят просто отлично.)

По-правильному, надо в SVG для тех линий, которые важно привязать к сетке, указывать атрибут shape-rendering="crispEdges". Но в качестве костыля можно накладывать его сверху при помощи юзерстиля. Только для тех иконок, где есть тонкие вертикальные или горизонтальные линии.

@namespace svg url(http://www.w3.org/2000/svg);

@-moz-document domain("github.com") {
  
  .octicon-plus, .octicon-file-directory, .octicon-file-text,
  .octicon-graph, .octicon-book, .octicon-trashcan, .octicon-repo,
  .octicon-comment
  { shape-rendering: crispEdges !important; position: relative; left: 0.1px }

}
yurikhan: (Default)

Раздаточный материал: Описание протокола WialonRetranslator 1.0 (PDF, 156K, 3 не очень плотных страницы)

Задача 1: Перечислите ошибки, допущенные при документировании этого протокола.

Задача 2*: Перечислите ошибки, допущенные при проектировании этого протокола.

Комменты не скринятся. Ответы выложу через пару-тройку дней.

Upd: [livejournal.com profile] kgeorgiy нашёл практически все ошибки документирования.

Ответы )

Вот с такой фигнёй иногда приходится работать.

yurikhan: (Default)

На столе лежала какая-то книга; Алиса взяла её и стала листать, поглядывая время от времени на Белого Короля. (Она всё ещё волновалась за него и держала чернила наготове — на случай, если ему снова станет плохо.) Она надеялась, что сумеет прочитать в книге хоть одну страничку, но всё было написано на каком-то непонятном языке.

Вот как это выглядело.8

Пуськи бятые

Сяпала Калуша с Калушатами по напушке. И увазила Бутявку, и волит:

— Калушата! Калушаточки! Бутявка!

Калушата присяпали и Бутявку стрямкали. И подудонились.

А Калуша волит:

— Оёё! Оёё! Бутявка-то некузявая!

Калушата Бутявку вычучили.

Бутявка вздребезнулась, сопритюкнулась и усяпала с напушки.

А Калуша волит калушатам:

— Калушаточки! Не трямкайте бутявок, бутявки дюбые и зюмо-зюмо некузявые. От бутявок дудонятся.

А Бутявка волит за напушкой:

— Калушата подудонились! Зюмо некузявые! Пуськи бятые!

yurikhan: (Default)

Когда я пришёл в веб, считалось дурным тоном делать сайты, не помещающиеся в 800×600.

Потом распространились разрешения 1024×768, 1152×864, 1280×1024 и, наконец, 1600×1200. В какой-то момент вебостроители решили, что 1024 пикселя в ширину есть у всех. А у кого нет, тот лох.

Потом пошла мода на 16:10 и 16:9 и разрешения типа 1920×1080. И вот про это разрешение поговорим подробнее.

Дело в том, что при 24 дюймах диагонали, формате 16:9 и разрешении 1920×1080 CSS-пикселей (тех, которые 1/96 дюйма, а не обязательно один минимальный элемент изображения) уже начинает быть удобно работать не с одним развёрнутым на весь экран окном, а с двумя неперекрывающимися половинками. И в такой конфигурации сайту в браузере остаётся 960px ширины, с поправкой на скроллбар — ≈940px.

Сто́ит вспомнить правила приличия девяностых и двухтысячных. Сайт не должен вызывать горизонтального скроллинга при ширине окна в 940px.

(Персональные лучи поноса — Альфа-Клику, Гитхабу, Гуглу, Джире, Пейпэлу, библиотеке Сафари Букс Онлайн, всей сети Стек Эксчендж и Яндекс-Погоде.)

yurikhan: (Default)

Когда-то в прошлой жизни я сидел на Windows. Там был FAR. FAR был инструментом для всего.

Потом я пересел на X11/GNU/Linux. Там FAR’а нет. Есть отдельно Midnight Commander, у которого убогий редактор, и отдельно Emacs, у которого убогий файловый менеджер. Об Emacs’е я здесь и сейчас говорить не буду. Буду говорить о классе программ, позиционирующихся как файловые менеджеры. Говорить буду резко и в основном для себя и про себя. Всем остальным читателям к каждому высказыванию неявно добавлять «IMHO».

Итак, что такое файловый менеджер? Многие считают, что файловый менеджер — это две синие панельки, между которыми можно копировать файлы. Ну и изредка запускать команды шелла. А вот и ни фига.

Read more... )
yurikhan: (Default)

Повадились тут интернет-провайдеры звонить мне в телефон.

Интернет-провайдеры, Карл, в телефон!

Я допускаю, что мой интернет-провайдер может позвонить мне в телефон в трёх случаях:

  • Моё оборудование, подключённое к сети провайдера, своим действием или бездействием наносит ущерб ему или другим пользователям.
  • Другие пользователи наносят ущерб моему оборудованию.
  • Я заранее договорился с провайдером о каких-либо работах, где требуется моё присутствие.

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

картинка )
yurikhan: (Default)

Или о бесявости отсутствия таковых.

Альфа-Клик, интернет-банк Альфа-Банка. Чтобы сделать перевод между счетами, приходится (1) навестись на «Переводы» в строке меню, (2) в попап-меню ткнуть в «Между своими счетами», выбрать в выпадающих списках сначала (3) счёт Откуда, потом (4) счёт Куда, потом (5) ввести сумму. Именно в этом порядке, потому что преждевременная валидация ввода.

Как должно быть: В списке счетов вижу название и текущий остаток. Дальше несколько способов.

  • Способ А: (1а) Дрэг-эн-дроп из текущего остатка на другой счёт открывает форму перевода, заранее заполненную исходным и целевым счетами, остаётся только (2а) ввести сумму.
  • Способ Б: (1б) Клик в название открывает выписку. На экране выписки должна быть (2б) кнопка «Перевести отсюда», открывающая ту же форму с предзаполненным исходным счётом, остаётся (3б) выбрать целевой счёт и (4б) ввести сумму.
  • Если переводим не между своими счетами, то сценарий (б) тот же самый, только в (3б) указываем счёт получателя не выбором из списка своих счетов, а каким-то другим способом (выбор из закладок или, на худой конец, заполнение формы с опциональным созданием закладки).

Zabbix, система мониторинга с веб-мордой. Вижу график трафика по семи серверам. Хочу добавить к нему недавно развёрнутый восьмой. Для этого приходится: (1) в строке меню навестись на Configure; (2) вспомнить, определён ли график для какого-то Хоста или в каком-то Шаблоне; (3) ткнуть соответственно в Hosts или Templates; (4) найти нужный хост или шаблон в двухстраничной таблице; (5) ткнуть в ссылку Graphs в его строке; (6) в открывшемся списке графиков этого хоста ткнуть в нужный график.

Как должно быть: На странице с графиком должна быть кнопка «Конфигурировать это».

Outlook Web Access, веб-морда к корпоративной почте. Чтобы подписаться на рассылку, приходится: (1) в меню опций ткнуть в Options; (2) ткнуть в Groups; (3) нажать кнопку Join; (4) в открывшемся диалоге ткнуть в нужную группу; (5) в окне информации о группе нажать кнопку Join.

Как должно быть: (1) На вкладке People или на главной можно поиском найти нужную группу. (2) В панели информации о группе должна быть кнопка «Вступить в это».

Gajim, jabber-клиент. Чтобы добавить контакт, нужно: (1) выбрать в меню Actions | Add contact | (нужный jabber-аккаунт); (2) в диалоге ввести JID; (3) в выпадающем списке выбрать группу.

Как должно быть: Ростер уже сгруппирован сначала по аккаунтам, потом по группам. (1) В контекстном меню группы должен быть пункт «Добавить сюда». Остаётся (2) в диалоге ввести JID.

Magit, git-фронтэнд для Emacs’а. Чтобы создать новую ветку от текущего коммита, нужно: (1) нажать b B (magit-branch-and-checkout); (2) ввести хэш или имя ветки начального коммита или согласиться на предлагаемый по умолчанию; (3) ввести имя новой ветки.

Как должно быть: (1) В графе коммитов навести курсор на нужный коммит; (2) дать команду «создать ветку отсюда»; (3) ввести имя новой ветки.

Jenkins, инструмент для continuous integration. Чтобы склонировать задачу, нужно (1) ткнуть New Item, (2) выбрать радиокнопку Copy existing item, (3) выбрать клонируемую задачу из комбо-списка.

Как должно быть: В контекстном меню задачи должен быть пункт «Склонировать это».

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

Положительные примеры: на картах в карточке здания «Проехать сюда» и «Проехать отсюда». В почтовиках «Filter messages like this».

yurikhan: (Default)

Придумалось (или, даже, почти приснилось) слово:

boolsheet [ˈbuːlˌʃiːt]
  1. n. Таблица истинности логической функции.
  2. n. Карта Карно.
yurikhan: (Default)

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

Ну и ключевой инсайт, после которого картинка сложилась, был в духе «123.456.78.90 не может быть IP-адресом, значит, это DNS-имя».

Забавно, что наяву две разные версии спецификации URI разрешают эту неоднозначность грамматики по-разному. RFC 2369 §3.2.2:

[…]The rightmost domain label of a fully qualified domain name will never start with a digit, thus syntactically distinguishing domain names from IPv4 addresses[…]

RFC 3986 §3.2.2:

The syntax rule for host is ambiguous because it does not completely distinguish between an IPv4address and a reg-name. In order to disambiguate the syntax, we apply the “first-match-wins” algorithm: If host matches the rule for IPv4address, then it should be considered an IPv4 address literal and not a reg-name.

и ниже:

IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet

dec-octet   = DIGIT                 ; 0-9
            / %x31-39 DIGIT         ; 10-99
            / "1" 2DIGIT            ; 100-199
            / "2" %x30-34 DIGIT     ; 200-249
            / "25" %x30-35          ; 250-255

Таким образом, по более новому RFC 123.456.78.90 — это действительно доменное имя (а в старом — таки IPv4-адрес).

yurikhan: (Default)

Однажды к Студии Артемия Татьяновича™ Лебедева подъехал автомобиль с дипломатическими номерами. Из него вышел господин в строгом костюме и два телохранителя. Артемий Татьянович™ лично встретил их и провёл в свой кабинет.

— Здравствуйте, — начал гость с чуть заметным акцентом. — Я представляю правительство Королевства Норвегии. Мы хотели бы заказать вашей Студии редизайн нашего веб-сайта.

— Разумеется, — ответил Артемий Татьянович™. — Мы начнём с регистрации домена.

— В этом нет необходимости. У нас уже есть домен.

— Нет, мы начнём с регистрации нового домена, — продолжал настаивать Артемий Татьянович™. — Потому что ваш домен — gov.no!

yurikhan: (Default)

До чего же всё плохо с тем, что называется syndication.

Во-первых, читалки. Подавляющее большинство — на PHP с базой MySQL. В лучшем случае — с PostgreSQL, но всё равно PHP. Есть одна на Go с базой Google App Engine Datastore. What is this I don’t even. (Нет, десктопные читалки рассматривать принципиально не будем, потому что они не дают гарантию непропуска постов.)

Казалось бы, чего сидишь, ниша открыта, напиши RSS-читалку с архитектурой, которая не будет оскорблять твои чувства.

Да только дело в том, что сами форматы данных (RSS 0.9, RSS 1.0, RSS 0.91, RSS 2.0 и Atom вместе с ними) — тяжело больны антипаттерном «само выросло». Сначала у item’ов вообще были только название и ссылка. Потом добавилось описание, предполагаемое коротким и неформатированным. Потом внезапно оказалось, что люди пихают туда HTML! Иногда даже забывая сохранить well-formedness окружающего XML’я. Окей, сняли ограничения на длину, задокументировали, что блин, раз уж вы туда пишете HTML, то эскейпьте его по правилам XML’я. Ну и под конец Atom — «пишите хоть плейн текст, хоть заэскейпленный HTML, хоть валидный XHTML, но явно подпишите, какой именно формат вы используете».

Естественно, при прочих равных софт на стороне производителя генерирует тот формат, к которому проще привести входные данные. А входные данные у большинства[citation needed] блогов — не валидируемый и потому массово невалидный HTML. '<[CDATA[' + post_body + ']]>' и не волнует, пусть кто-то другой с этим потом мучается.

Поэтому всякий, кто решает сейчас писать RSS-читалку, через некоторое время погружается в бочку этого самого… дёгтя.

Пойду засуну свой инстанс Tiny Tiny RSS в контейнер от греха подальше. Тем более что оно, оказывается, перешло с нормальной модели релизов «вот вам полурегулярные orig.tar.gz, собирайте себе пакеты под что хотите» на rolling-модель «текущая стабильная версия — это то, что сейчас в master’е».

yurikhan: (Default)

За всю историю Интернета в новосибирском Академгородке мне довелось пользоваться целой кучей провайдеров.

Read more... )
yurikhan: (Default)

Первое время Inbox работал только в Chrome. Это было достаточным поводом не принимать его всерьёз.

Потом они поддержали Firefox и что-то там ещё. Для активации требуется поставить и запустить Android-приложение. Немножко bullshit’но. Но ok, поставил в виртуалке, активировал, удалил.

Ну и таки вот что я имею сказать по всему этому поводу.

  • Недостатки внешнего оформления
    • Небесно-ярко-голубой фон пустого инбокса — вырвиглазен.
    • Ярко-красная кнопка «Compose» — тоже вырвиглазна.
    • По умолчанию используется немоноширинный шрифт, даже для plain text писем.
    Это бы всё легко лечилось Stylish’ем. Но у гугла, как всегда, CSS-классы названы по-клингонски, при этом сервис обслуживает несколько серверов и на разных серверах имена классов разные. Поэтому оно лечится Stylish’ем сложно и костыльно.
  • Функциональные недостатки
    • Горячие клавиши. Разработчики веб-приложений, запомните: у Firefox’а есть фича «Find as you type». Когда она включена, все события ввода символов после обработки страницей проваливаются в браузер, где приводят к поднятию строки поиска по странице. Если только страница не сделает event.preventDefault(). И вот Inbox это делает только для основных двух шорткатов — n и p, а про остальные забывает.
    • Слева есть список лейблов. Но они все отрисовываются bold’ом, независимо от того, в каких из них есть непрочитанные сообщения. Факт наличия и количество непрочитанных сообщений определить никак нельзя. Предполагается, что все непрочитанные сообщения лежат либо в Inbox’е, либо в Snoozed, а потом ты их прочитываешь, отмечаешь Done и они архивируются. То есть, переезжая с Gmail на Inbox, нужно во всех фильтрах снять флажок «Skip Inbox», и панель настройки лейблов позволяет это весьма нетрудозатратно проделать. (Для этого нужно прокликать переключатель Bundled in Inbox для всех лейблов в положение On.)
    • Ну окей, после всего этого читать даже приятно. Все непрочитанные сообщения — в одном списке, причём сгруппированы по лейблу. Это хорошо и примерно соответствует обычному сценарию «тыкаем в первую папку, где есть непрочитанные, прочитываем их все, тыкаем в следующую». Но кроме читать, иногда бывает нужно писать. И тут всё резко плохо.
      • Панелька, в которой предлагается писать, узкая и сбоку. Вместо того, чтобы занимать всё доступное пространство в окне. В заголовке панельки есть кнопки «_» и «×». Кнопки «развернуть» нет.
      • И главный блокер. Инбокс не даёт писать plain text. Каждое сообщение отсылается как multipart/alternative [ text/plain; text/html ]. То есть, натурально, у почтового приложения отсутствует* функция написания сообщений. Какого хрена, Гугл?
  • А теперь на сладкое. Чтобы вернуться обратно на Gmail и чтобы непрочитанные сообщения с проставленными лейблами не светились в инбоксе, нужно пойти в настройки фильтров и там прокликать их все по более длинному маршруту: edit, Continue », [x] Skip Inbox, Save. А у меня их там около сотни, например.
yurikhan: (Default)

В каких-то темах оформления ЖЖ есть пометка непрочитанных комментариев жёлтой плашкой. В моей — нет. А я предпочитаю чужие журналы читать в своей теме (потому что у всех слишком мелко и/или слишком ярко).

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

Тестировалось на Firefox 35.0.1; LJ схема Lynx (light), тема Cuteness Attack; DW схема Lynx (light mode), тема Tabula Rasa. Для использования с другими схемами и темами может понадобиться настроить селекторы, определяющие видимость текста комментария (помечено [1]) и стили самого индикатора ([2]).

Read more... )
yurikhan: (Default)

Заказал на DealExtreme светодиодных лампочек. (Светодиодных, потому что стоят они уже примерно столько же, как и компактные люминесцентные, но вроде бы должны быть ярче и долговечнее; и на DealExtreme, потому что там есть 6500K, в отличие от всего новосибирского оффлайна, где максимум 4200K.)

По техническим и одному DealExtreme’у ведомым причинам, посылка выходит из Литвы. Трекаю её на соответствующем сайте. Трекер говорит, что отправлено 14 октября, вышло в Россию 24 октября. Кажется несколько прибалтиииийско.

Давайте посчитаем. По запросу «диаметр Литвы» ничего релевантного не находится, но мы можем взять из Википедии площадь и из неё вычислить диаметр, аппроксимируя Литву кругом:

d = 2⋅√65301 км²/π ≈ 288 км

Предполагая 5-дневную рабочую неделю и 8-часовой рабочий день, получаем в интервале между 14 и 24 октября 8⋅8 = 64 рабочих часа.

Итого, средняя скорость посылки: 288 км/64 ч ≈ 4.5 км/ч. Они её несли пешком!

Profile

yurikhan: (Default)
Yuri Khan

August 2018

S M T W T F S
   1234
567891011
12131415161718
19202122232425
26 2728293031 

Links

Syndicate

RSS Atom

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated 2025-06-24 04:33
Powered by Dreamwidth Studios