программирование
Взрывающийся компьютер
Помню
Это было очень смешно и смотрелось столь же нелепо, как драки в болливудских фильмах, в реальности такого произойти не могло — в те времена возгорание и тем более взрыв компьютерной техники нельзя было вызвать
Ну что ж, отныне можно говорить, что эти фильмы просто предвосхитили время:
Исследователи безопасности из китайской компании Tencent представили новый класс атак BadPower, нацеленный на поражение зарядных устройств для смартфонов и ноутбуков, поддерживающих протокол быстрой зарядки.
Атака позволяет инициировать передачу зарядным устройством чрезмерной мощности, на которую не рассчитано оборудование, что может привести к выходу из строя, расплавлению частей или даже возгоранию устройства.
Как знать, может в скором будущем мы будем взламывать банки, летая через тоннели в сеточку, или программировать со скоростью машинистки,
Арктическое хранилище кода
Прочитал на «Оупеннете», что «Гитхаб» создал архив открытого кода в арктическом хранилище:
GitHub объявил о воплощении проекта по созданию архива открытых исходных текстов, размещённого в арктическом хранилище Arctic World Archive, способного уцелеть в случае наступления глобальной катастрофы. 186 плёночных накопителей piqlFilm, которые содержат фотоснимки информации и позволяют сохранять информацию более 1000 лет (по другим данным срок службы составляет 500 лет), успешно размещены в подземном хранилище на острове Шпицберген. Хранилище создано из заброшенной угольной шахты глубиной 150 метров, достаточной чтобы обеспечить сохранность информации даже в случае применения ядерного или электромагнитного оружия.
В архив попали все проекты, у которых по меньшей мере одна «звезда» и есть хотя бы один коммит, сделанный за год до снятия архива или позже, а так же проекты, у которых 250 «звёзд» и больше.
У каждого разработчика, чей код попал в архив, в профиле появилась отметка «Arctic Code Vault Contributor», у меня она тоже появилась. За шахматы на языке редактора sed и пару чужих проектов, в которые я даже не помню что коммитил и по какому поводу.
Забавно, что часть кода, написанного мной, будет гнить
Починил ucfirst в PHP
В отпуске дошли руки посмотреть и починить баг в функции ucfirst — по задумке она должна приводить в верхний регистр первый символ однобайтовой строки, учитывая текущую локаль. Всё бы хорошо, но с буквой «я» кодовой страницы 1251 это не срабатывало — она оставалась в нижнем регистре.
Интересно, что похожая функция — strtoupper тут работает прекрасно, то есть вот такой код на текущих версиях ПХП выдаёт false:
if (setlocale(LC_CTYPE, "ru_RU.cp1251") === false) {
throw new RuntimeException();
}
// буква «я» имеет в кодировке «1251» код 255
var_dump(ucfirst(chr(255)) === strtoupper(chr(255));Поскольку эта беда уже второй раз ломает тесты в нашем продукте (программисты об этой особенности просто забывают), решил глянуть в исходники. Внутри ПХП обе функции — проблемная и рабочая, используют вызов toupper, в документации к которой человеческим языком сказано, что передаваемый параметр должен иметь тип unsigned char.
Функция strtoupper как раз использует unsigned char, а ucfirst — char (который signed). Документация к toupper такую вольность по отношению к типам осуждает — там прямым текстом написано, что могут быть проблемы, так как внутри входной параметр будет расширен до int, знак перенесётся на старший разряд и всё сломается.
Что, собственно, и происходит с буквой «я», код которой как раз получается отрицательным. Удивительно, что с другими «отрицательными» буквами всё
В общем, мой патч приняли в версию 7.3, и как только выйдут новые версии поддерживаемых веток интерпретаторов, мы, наконец, перестанем спотыкаться об этот баг.
«Магический шар» ★
Свой путь в вебе я начинал с вёрстки — в конце
Из того набора атрибутов и тегов, что тогда были доступны, мне довелось использовать всё, кроме
Использование его в те годы могло бы выглядеть
<A HREF=/cgi-bin/action.pl><IMG SRC=/i/pict.gif WIDTH=200 HEIGHT=100 ISMAP></A>Чтобы вы прочувствовали дух времени, специально пишу большими буквами (так было принято) и без кавычек (экономили и на этом тоже).
При нажатии на картинку с этим атрибутом и ссылкой к урлу добавляются в качестве параметров координаты курсора на картинке. Видимо это нужно было
Я уже несколько лет как не верстаю,
И вот два года назад меня осенило использовать его в вёрстке «магического шара» из фильма «Трасса 60». Если не смотрели, там у главного героя был шар, который давал ответы на заданные вопросы, если его потрясти.
Мой шар «отвечает» в том случае, если на нём щёлкнуть мышкой. В качестве случайных значений используются координаты, передаваемые при помощи атрибута ISMAP, плюс картинка вращается при помощи CSS, поэтому даже под неподвижным курсором всегда разные координаты.
Принцип получился довольно простой — все координаты, в которые пользователь может щёлкнуть мышкой, заданы как идентификаторы скрытых слоёв, лежащих поверх рисунка шара. Как только пользователь выбирает
HTML с таким подходом становится довольно жирным — у меня получился 1,2 мегабайта, но по нынешним временам это не объём.
Вообще я планировал дооформить шар и сгенерировать координаты более экономно (сейчас я генерирую под охватывающий квадрат, получается, что у меня есть бесполезные строки в его углах), но проект два года провалялся в локальном репозитории, а воз и ныне там.
Поэтому решил выложить что есть,
JUnix в книге
Пока ещё далеко не ушёл от этой темы, напишу.
Недавно выкладывал в открытый доступ свой проект начала нулевых — JUnix, «эмулятор» Линукса на ДжаваСкрипте. Заодно для интереса погуглил много ли ссылок осталось на прежний сайт проекта — junix.kzn.ru.
Ссылок оказалось немало, заодно нагуглилось несколько статей, которых я не видел, когда проект был жив. Но удивительнее всего было встретить упоминание моего «эмулятора» в бумажной книге — учебном пособии по операционным системам.
Книга, как оказалось, всё ещё выпускается и продаётся, правда есть ли в переизданиях упоминание «ДжУникса» выяснить не удалось —
К слову, это не первая книжка, на страницы которой попал «ДжУникс». Первой была моя зачётная книжка. Поскольку во время увлечения этим проектом к учёбе я относился с прохладцей, пришлось совмещать приятное с полезным, и защищать «эмулятор» в качестве курсовой — как среду для обучения студентов операционной системе «Линукс».
Точную тему не помню, надо будет проверить по зачётке, благо я её не сдал после окончания учёбы.
JUnix ★
Вкратце: выложил на гитхаб свой старый проект «эмулятора» Линукса, который я писал
Мне тогда этот язык невероятно нравился, я был в бешеном восторге и такое вот несерьёзное к нему отношение меня очень задевало.
Эта фантазия меня так увлекла, что примерно год я посвящал ей все вечера, в ущерб учёбе в Университете и личной жизни. Позже я ещё долго возвращался к этому проекту, правда моя активность всё угасала, пока
Конечно настоящий эмулятор у меня не получился, да я и не пытался его создать, получилась имитация командной строки «Линукса» на том уровне знаний, который у меня был в те годы.
Реализованы
Поскольку шеллом
В своё время появление этого «эмулятора» понаделало шуму — о нём написали все основные российские сайты про программирование, а я каждый день получал письма от тех, кому понравилась моя игрушка.
Постепенно домен, на котором это всё располагалось, потерялся, а потом со старым винтом умер и бакап сайта. Осталась только копия
Так бы он там и лежал, но вчера в разговоре Леонидом Кагановым я случайно помянул почивший проект и Леонид, который его моментально вспомнил, предложил забрать сохранившееся
Честно говоря, я и сам давно об этом думал —
И вот вчера я наконец выкачал слепок первой попавшейся качалкой, поправил очевидные баги, чтобы всё заработало в современных браузерах — они
Кстати, если вам нравится в таком копаться, можете посмотреть сколько костылей в то время приходилось городить и как беден был раньше этот ДжаваСкрипт.
Я потестировал
Репозиторий проекта: https://github.com/bolknote/junix.
Сайт проекта, где можно посмотреть всё в действии: https://bolknote.github.io/junix.
99 бутылок: Старсет
Семьдесят четвёртый выпуск считалочки «песни о пиве», которую я пишу на разных языках программирования, для разнообразия сделаю на языке родом из СССР.
74. Старсет — язык программирования высокого уровня, разработанный в Институте программных систем РАН в 1991 году. К сожалению, мне не удалось обнаружить компиляторов или интерпретаторов этого языка, и даже упоминания, что они вообще
Поэтому программировать пришлось исключительно по описанию языка, почерпнутого из книжки, купленной за двести рублей с рук в интернете.
Язык, кстати говоря, небезынтересный — в наличие имеется развитая работа со множествами и свой язык регулярных выражений («образцов»), который может применяться не только на скалярах, но и на множествах! Кроме того имеются операторы, позволяющие распараллеливать вычисления!
Помимо скаляров и множеств, язык поддерживает «классы» — насколько я понял, своеобразные вычисляемые «срезы» множеств
Например, попробуйте разобраться в этом отрывке («каноническая запись», как утверждается выше процитированного — это когда отброшены все незначащие нули):
Каноническим числовым представлением нуля будем считать слово 0. В частности, каноническим числовым значением слова 1 является оно само, каноническим представлением слова 2 является слово −6, каноническим представлением слова 3 — слово 67000000000000000.
Я, сколько ни пытался, не смог уловить закономерность.
Программы по внешнему виду сильно напоминают «Паскаль» — совпадают некоторые конструкции и принципы, но, конечно же, есть и вещи, которые сильно отличаются.
Выполнение программы выполняется с первой процедуры и завершается с выходом из неё. Возврат значения из функции (тут она называется
/* Считалочка про пиво на языке «Старсет». Написал Евгений Степанищев */
/* https://bolknote.ru */
Func Бутылки(колво)
Word: Бутылки, колво;
Choice
Case колво = 1 Do Бутылки := '1 bottle' End
Case колво = 0 Do Бутылки := 'no bottles' End
Otherwise Do Бутылки := колво^' bottles' End
Endfunc
Proc Песня()
Word: колво, бутылок;
колво := 99;
бутылок := Бутылки(колво);
While колво > 0 Do
Write бутылок^' of beer on the wall, '^бутылок^' of beer.';
колво := колво - 1;
бутылок := Бутылки(колво);
Write 'Take one down and pass it around, '^бутылок^' of beer on the wall.';
Write ''
End
Write 'No more bottles of beer on the wall, no more bottles of beer.';
Write 'Go to the store and buy some more, 99 bottles of beer on the wall.'
EndprocВсе строки заключаются в апострофы, которые в книге имеют непривычный вид (’), я не стал их тут использовать, вряд ли это
Ещё необычно выглядит операция конкатенации — ^ и повторения строки — ^^.
Write 'МА' ^^ '2 раза' /* Будет выведено «МАМА», так как «2 раза» преобразуется к двойке */С удовольствием познакомился с языком, благо он не выглядит, как
99 бутылок: Lua
Пока ещё помню язык Луа, который я использовал для написания «Морского боя» в азбуке Морзе, надо бы продолжить им сериал о «99 бутылках пива на стене».
73. Lua — скриптовый язык, который чаще всего применяют для встраивания, например — нередко используют для описания сценариев в играх. Объектная модель прототипная, напоминает ДжаваСкрипт, но в Луа она мощнее.
Язык очень простой, учится элементарно, но при этом довольно мощный.
А вот стандартная библиотека подкачала, простой пример — в ней нет функции задержки, когда она мне понадобилась, пришлось её импортировать из Си. Или есть модуль, который хоть
function beer(b)
if b == 1 then
return '1 bottle'
else
return (b == 0 and 'no' or b) .. ' bottles'
end
end
b = beer(99)
for i = 99, 1, -1 do
print(b .. ' of beer on the wall, ' .. b .. ' of beer.')
b = beer(i - 1)
print('Take one down and pass it around, ' .. b .. ' of beer on the wall.\n')
end
print([[No more bottles of beer on the wall, no more bottles of beer.
Go to the store and buy some more, 99 bottles of beer on the wall.]])День Радио ★
Сегодня, 7 мая в России отмечают День радио — в этот день, 125 лет назад российский физик Александр Степанович Попов на заседании Русского
К этому юбилею, превозмогая лень, прокрастинацию и уныние от «самоизоляции», мне удалось наконец дописать игрушку, которую я задумал ещё несколько лет назад. Игра была готова неделю назад, но я всё никак не мог сделать последний шаг — добавить описание и выложить наружу.
Для практики в моей любимой дисциплине — «ненормальном программировании», очень хотелось написать
В итоге, для этого я выбрал «Морской бой». В моём варианте игрок вводит информацию клавишей левого «Шифта», а компьютер отвечает, мигая светодиодом кнопки «Капс Лок». Чуть более подробные правила есть в репозитории проекта.
Обёртка и некоторые функции (мигание светодиодом, опрос «Шифта» и функция задержки) написаны на Си, остальная часть — на языке «Лу́а» (Lua). Давно хотелось изучить этот странноватый язык поглубже, а тут ещё удалось поучиться встраивать его в Си.
Чтобы увеличить градус безумия всего проекта, в Си были использованы диграфы — они очень странно выглядят и дают ощущение, что используется
Пока работал над игрой, приходилось много гуглить, в очередной раз поразился, как много кода люди бездумно копируют друг у друга. Реализация мигания светодиодом, например, кочует из проекта в проект в неизменном виде — видно, что никто из скопировавших не понимает как этот код вообще работает. Я в нём попытался разобраться и написать чуть чище, чем буквально везде.
Для тех безумцев, которые захотят попробовать скопмилировать этот вариант «Морского боя» и сыграть, ещё раз привожу репозиторий проекта (только под «МакОСь») — https://github.com/bolknote/battleship.
«Разрабы»
На четвёртой неделе «самоизоляции» почувствовал явные накапливающиеся отрицательные эффекты. Как я уже говорил, мне совершенно не подходит работа из дома, возможно прежде всего потому, что у меня нет оборудованного домашнего офиса, в отличие от многих ребят, работавших удалённо в последние годы, да и оборудовать его негде, под него просто нет места.
Раньше к утру я был в относительной норме, но теперь чувствую, как внутри копится
Чтобы его
Вчера начал смотреть сериал «Разрабы» («Devs»), очень уж заинтересовало описание. На фоне предыдущего («Сказки из Петли») пока смотрится бледновато, но надеюсь ещё втянусь. По сюжету команда элитных программистов, называющихся «Разрабы» пишут
Тема квантовых компьютеров находится на самой границе моих интересов, но всё же в их сторону я иногда поглядываю.
Пока посмотрел только первую серию. В ней заметную часть экранного времени только что принятый в команду русский программист Сергей Павлов шокировано пялится на некий квантовый код, который довольно чётко видно зрителю.
Меня заинтересовало на чём же они там пишут. Знающие люди в чате бывших коллег сказали, что в кадре редактор «Емакс» («EMACS»). Я им никогда не пользовался, поэтому верю на слово.
Язык программирования в центре — преимущественно Пайтон с подключенными модулями (из знакомых мне — математический пакет numpy и пакет квантовых вычислений qiskit), но видны вкрапления
Честно сказать, я ждал
Вокруг окна с кодом наверное
Интересно для чего потребовалось делать мешанину из языков? Чтобы подчеркнуть, что это фантастика, а не реальный код? Или консультант тупо скопировал
99 бутылок: CFAQ
Отдаю очередную дань своему давнему хобби — написанию американской традиционной песни про пиво на разнообразных языках программирования.
72. CFAQ (читается «СИФАК»). Очень люблю самодельные языки программирования, есть в них
Когда узнал, что у известного
Язык, конечно, довольно простой, без поддержки подпрограмм или функций (их можно эмулировать отдельными файлами, передавая параметры через глобальные переменные), но с циклами, ветвлениями и переменными.
# 99.TXT. Написано Степанищевым Евгением, апрель 2020
B = 99
repeat -1 {
Bt = {B}
repeat 2 {
if {Bt} = 0 {
set S = no bottles
} else {
if {Bt} = 1 {
set S = 1 bottle
} else {
set S = {Bt} bottles
}
}
if {Bt} = {B} {
echo {S} of beer on the wall, {S} of beer.<br>
} else {
echo Take one down and pass it around, {S} of beer on the wall.<br>
}
Bt -= 1
}
B -= 1
if {B} = 0 {
echo No more bottles of beer on the wall, no more bottles of beer.<br>
echo Go to the store and buy some more, 99 bottles of beer on the wall.
exit
}
}Первую версию программы писал вайтбордингом — мне её просто негде было запустить. К счастью Леонид предоставил тестовый стенд на побаловаться, я исправил все ошибки и теперь программа гарантированно работает, проверено. Правда все 99 «бутылок» она вывести не может — не хватает памяти в буфере вывода, так что испытывал на десяти.
Скудность конструкций языка компенсируется относительным богатством встроенных функций для работы с различным оборудованием и взаимодействия с внешним миром (например, он умеет выводить информацию через бота в мессенджер «Телеграм»), но в моей программе это, разумеется, не пригодилось.
Три новые старые статьи
Свой собственный сайт появился у меня в ноябре 2000 года, кажется по адресу bolk.chat.ru. Позже мы познакомились с Алексом Экслером, который предложил хостится у него по адресу bolk.exler.ru,
Естественно моё присутствие в интернете началось не в 1989 году, но и до двухтысячного года
Недавно, перевёрстывая некоторые старые заметки начала
Точные даты публикаций, к сожалению, неизвестны, но я восстановил примерные, ориентируясь на дату появления моих заметок на сайте
Что нового в JavaScript версии 1.3 от Netscape
Найди картинку. Неизведанные возможности
Блоки try… catch… finally… в JScript 5
Cookie в PHP 7.4
Обнаружилась очень странная проблема у меня на сайте — некоторые комментаторы стали подписываться с плюсом между именем и фамилией. В первый раз я решил, что у человека это вышло случайно или, может, это
Выяснилось, что плюс появился сам собой, люди его и не думали ставить. Так я понял, что столкнулся
В чём примерно дело, понятно стало почти сразу — в вебе пробел иногда кодируется как «+», видимо ошибка
Проблема воспроизводится у тех комментаторов, которые оставили свой первый комментарий до того, как мой сайт перешёл на ПХП 7.4. В этой версии сменился способ кодирования пробела в «куках» (см. на скриншоте) — был +, стало %20.
В принципе, можно вернуть
if (strpos($_SERVER['HTTP_COOKIE'], '+') !== false) {
parse_str(strtr($_SERVER['HTTP_COOKIE'], ['; ' => '&']), $_COOKIE);
}Но хорошо бы внедрить в движок блога код, который будет перекодировать такие куки у пользователей.
FFI: баг не будет исправлен?
В пхпешном FFI есть баг — можно, вызывав сишную функцию случайно изменить значение совершенно других переменных
Очень не хочется это признавать, но похоже тот баг, который я обнаружил в реализации FFI (интерфейса к языку Си) в ПХП, исправлен не будет. Собственно, на это мне давно указал один из читателей в комментариях к прошлой заметке на эту тему, но мне всё не верилось.
В тикете, который я завёл по проблеме, один из разработчиков языка написал, что придерживается мысли, что это преднамеренное проектное решение. Не думаю, что это действительно так, наверняка получилось случайно, но как всё поправить, не снизив существенно производительность модуля FFI, — неясно.
Видимо, придётся жить с тем, что есть.
В прошлый раз, в качестве временной меры, я предлагал использовать str_repeat (или эквивалент) для того, чтобы разорвать запутанность двух переменных и таким образом предотвратить неожиданное их изменение. Это плохой приём, но я его задумывал в качестве временной меры.
Но раз это навсегда, давайте избегать сторонние эффекты правильно. Тот же читатель предлагает более корректный способ:
Первый параметр memcpy должен быть указателем на отдельно выделенную память достаточного размера. И в FFI есть метод для выделения памяти: FFI::new. Его и надо использовать вместо str_repeat.
Таким образом правильная работа с указателями должна выглядеть примерно вот так:
function memcpy(?string &$dst, string $src):void
{
$len = strlen($src);
// изготавливаем тип, в котором уместится копируемая строка
$type = FFI::arrayType(FFI::type('char'), [$len]);
// выделяем место под изготовленный тип
$destination = FFI::new($type);
FFI::cdef('char *memcpy(char *dst, const char *src, size_t len);')
->memcpy($destination, $src, $len);
// преобразуем область памяти в строку
$dst = FFI::string($destination, $len);
}
$rock = "ROCK";
var_dump($rock); // «ROCK»
memcpy($rock, "SOCK");
var_dump($rock); // «SOCK»Что тут происходит?
Мы хотим вызвать сишную функцию для копирования одной строки в другую. В месте, куда мы собираемся копировать, должно быть выделено достаточное количество памяти, мы её выделяем методом FFI::new, передавая ему на вход специально изготовленный тип — указатель на массив однобайтовых символов длиной c копируемую строку.
После копирования преобразуем область памяти в пхпешную строку. Память, выделенная при помощи FFI::new, освободится автоматически.
UnknownPlatformer

В ней пока мало что есть — лес с эффектом параллакса, персонаж на первом плане, который управляется стрелками на клавиатуре, но всё это уже очень интересно.
Демка сделана на авторском микродвижке «Bic» (Because I Can), выглядит хорошо и я надеюсь на продолжение, к счастью автор забрасывать (пока?) его не намерен — следующим шагом собирается добавить камеру, нормальный viewport и внедрить паттерн «Entity component system». Движок мультиплатформенный, работает под всеми тремя основными операционными системами — «Виндоуз», «МакОС», «Линукс».
Если тоже захотите полюбопытствовать, то просто скачайте архив, распакуйте его
composer install
:; [[ $(uname) == "Darwin" ]] && brew install sdl2_image
php app.php
PHP 7.4 vs. PHP 8.0a
Резюме — в моём частном случае стало ощутимо быстрее, PHP 7.4 работал 63,9 секунд, 8.0a — 42,6.
Как многие знают, основной фишкой восьмой версии интерпретатора ПХП будет JIT. Обещают ускорение вычислительных задач, что немного не про веб, где в основном используется этот язык, но всё равно выглядит интересно.
В официальном репозитории альфа восьмой версии лежит уже давно, стало интересно сравнить её с «семёркой» — много ли даёт JIT приросту. Для подобных тестов я давно использую свой оптимизирующий транслятор «Брейнфака», с загруженной в него задачей вычисления числа Пи.
Восьмой ПХП собрался на моём «Макбуке» следующей последовательностью команд:
PATH=/usr/local/Cellar/bison/3.5.3/bin/:$PATH ./buildconf
./configure --prefix=/opt/php-bin/ --without-iconv --disable-xml \
--without-libxml --disable-simplexml --disable-xmlwriter --disable-dom --disable-xmlreader
make -j4
make installВерсию 7.4 ставил через «брю», сборочную конфигурацию оставил как есть, ничего не менял.
После небольшой коррекции php.ini в информации об интерпретаторе появились OPcache и JIT:
Вообще свой брейфаковский транслятор
Каждую версию интерпретатора я тестировал со включенным и выключенным OPcache десять раз, а результаты усреднил. Как видите, JIT существенно ускорил выполнение программы в моём случае (там огромное количество циклов и ветвлений) — 63,9 секунды против 42,6.
Что интересно — PHP 8.a без OPcache обогнал версию 7.4 со включенным opcache, это примечательный результат— значит сам «голый» интерпретатор тоже оптимизируют.
Комментарии в Си
Из документации к языку Си на сайте «Микрософта», секция про комментарии, описывается нестандартное расширение спецификации:
Comments beginning with two forward slashes (//) are terminated by the next newline character that is not preceded by an escape character. […] the newline character is preceded by a backslash (\), creating an «escape sequence». This escape sequence causes the compiler to treat the next line as part of the previous line. (For more information, see Escape Sequences.)
The default for Microsoft C is that the Microsoft extensions are enabled. Use /Za to disable these extensions.
То есть в примере ниже, если его скомпилировать в «Визуал Студио», выражение i++; на самом деле будет частью комментарий и не выполнится:
// мой комментарий \
i++;Счастливой отладки!
Добавлено позднее: в компиляторе gcc тоже работает, причём раскрашивается как комментарий в редакторах vim и «Саблайм».
Юзерпики в «Эгее»
Во второй раз занимаюсь разовой конвертацией блогов в формат «Эгеи», надо бы записать
В основном обращаться приходится к трём таблицам, имеющим довольно говорящие названия: Notes — сами заметки, Comments — комментарии к ним (там же хранятся и авторы комментариев, единого профиля у них нет) и Aliases — адреса, по которым доступны страницы (в моей схеме в этой таблице нет поля Alias, куда и записывается сам адрес).
Назначения полей, в основном, понятны из названий, кроме разве что поля Stamp — это временная метка создания чего либо в секундах (timestamp) и поля с префиксом GIP, об этом чуть ниже.
Если вам интересны метки (теги), то понадобятся ещё две таблицы: Keywords — где хранится русское название метки и её урл и NotesKeywords, таблица, связывающая метки и заметки.
Теперь про GIP. Если флаг IsGIPUsed в таблице Comments установлен в ноль, то это прежняя схема хранения автора комментарий — без юзерпика, чтобы юзерпик появился, надо выставить IsGIPUsed в единицу, в поле GIP записать сервис, через который была проведена аутентификация (facebook, vk или twitter), а в GIPAuthorID записать некий идентификатор пользователя во внешнем сервисе.
Юзерпик нужно положить в pictures/avatar/ с именем, составленным из полей GIP и GIPAuthorID, записанных через дефисоминус. Например: vk-1.jpg — это был бы юзерпик Дурова, создателя «Вконтакте», если бы он
Тут есть одна интересная деталь. Дело в том, что у меня в блоге, когда он ещё работал на самописном движке, уже были юзерпики, были они и у Олега Петровича, блог которого я переносил сегодня ночью. Причём и у меня, и у Олега авторизация была своя собственная, не обязательно через те сервисы, которые поддерживает «Эгея». Как же мне удалось перенести юзерпики?
«Эгея» в этом месте имеет простой механизм расширений — в принципе в неё несложно добавить любой внешний механизм аутентификации, что я и сделал. Подобрал в папке system/theme/images/, где движок ищет картинки внешних сервисов, подходящую картинку (email.svg) и написал фейковый плагин для сервиса email, который положил в файл system/gips/email.php:
<?php
class E2GIPEmail extends E2GIP {
protected $type = 'email';
private function _get_instance() {
return (object) [];
}
public function get_auth_url() {
return '';
}
public static function get_profile_url($id, $link) {
return false;
}
public function callback() {
return true;
}
}Файл плагина (и его тип) должны называться так же как и выбранная картинка — email и в базе его пользователи записываются с тем же значением поля GIP. В итоге, все свои старые комментарии я положил, как принадлежащие сервису email, а в качестве GIPAuthorID (это строка) взял
Добавлено позднее: невероятно, но факт, оказалось, что GIP-плагины можно класть ещё и в users/gips/, что гораздо удобнее, так как в этой папке он не перетрётся при обновлении «Эгеи».
AppleScript Tetris ★
Я очень люблю «ненормальное программирование» — где вместо получения результата (такого мне и на работе хватает), приходится преодолевать нетривиальные трудности, придумывать
Недостатка в таких задачах у меня в голове не бывает, но руки приложить к ним получается нечасто. «Тетрис» на ЭплСкрипте — один из примеров такого «приложения рук», прошло три года, но он до сих пор мне так нравится, что я решил рассказать о нём ещё раз.
Для начала немного об ЭплСкрипте. Это скриптовый язык для автоматизации, который встроен в МакОС в незапамятные времена — в «Википедии» написано, что он появился аж в 1993 году, то есть широкоизвестный ПХП его младше аж на два года!
Несмотря на то, что язык уже несколько лет не обновляется, заброшенным его не назовёшь, скорее всего в нём просто нечего обновлять — все задачи, которые он призван решать, он решает, в МакОСи есть даже встроенный визуальный редактор и я знаю ребят, которые делают на нём потрясающие вещи в плане создания
Естественно можно программировать и в обычном текстовом редакторе, программы в этом случае выглядят как текст на немного необычном английском языке:
tell application "Microsoft Word" to quit
display dialog "Hello, world!"
print pages 1 thru 5 of document 2Сильно популярным его не назовёшь, но в своей нише он хорош и продвинутые «маководы» о нём знают. До «Тетриса» я писал на нём «песню о пиве» и интерпретатор Брейфака.
За всё историю существования на ЭплСкрипте никто никогда не писал графических интерактивных игр. Причина проста: в языке нет поддержки графики и опроса клавиатуры. ?, расходимся!
Тем не менее идея создать на нём
Первым придумался способ вывода графики — я подумал, что фигуры можно рисовать свёрнутыми окошками
Для этого, в припципе, всё есть — ЭплСкрипт умеет запускать программы и управлять размерами и расположением окон:
tell application "TextEdit"
set the bounds of 1st window whose id is wid to {x, y, (x + |size|), (y + |size|)}
endКогда я попробовал это запрограммировать, меня ждал сюрприз: оказывается программно размер окна можно стягивать в точки разных размеров (мышкой это сделать не получается), составленные из них стакан и фигуры выглядели вполне приемлемо.
Так как вся графика создаётся окошками приложений, то традиционного окна, в котором всё работает, у программы нет — его роль выполняет рабочий стол. Стакан тетриса прилеплен к верхнему краю и отцентрирован по горизонтали.
В первом же прототипе появилась ещё одна проблема — наверху у «МакОСи» есть строка меню, приложения не могут на неё залезать, при попытке вывести в эти координаты окно, оно «сползает» вниз. В итоге первые несколько точек выводились в других координатах и всё рушилось. Было два решения — центрировать ещё и по вертикали
В итоге, способ придумался. Сразу после запуска я вывожу окно в нулевые координаты и смотрю на сколько пикселей оно съехало, это и будет высотой меню:
-- Get height of menu bar
tell application "TextEdit"
activate
make new document at the front
set the bounds of 1st window to {0, 0, 0, 0}
set coords to bounds of 1st window
close 1st window
end
set minimalY to coords's item 2С графикой разобрались, а что с клавишами? В ЭплСкрипте, как я уже говорил, нет способов опросить клавиатуру, существуют плагины и сторонние решения, но их использование рушит всю идею. Хотелось чистого решения.
Голову пришлось ломать очень долго, пока в один момент я не додумался заиспользовать под это опрос значения громкости — уменьшение и увеличение громкости как кнопки влево/вправо, а отключение динамика — для поворота фигуры.
Для этого на пуске я устанавливаю громкость на середину и в цикле опрашиваю текущее значение. После каждого изменения значение опять сбрасывается на среднее:
on levelReset()
set volume output volume volumeMiddle without muted
end
on checkDirection()
set level to output volume of (get volume settings)
levelReset()
_sign(level - volumeMiddle)
end
on checkRotate()
return output muted of (get volume settings)
endТут _sign — моя собственная функция взятия знака, у ЭплСкрипта нет встроенной.
В получившийся вариант вполне можно играть — я пробовал. Немного странное управление через несколько минут уже перестаёшь замечать, единственное, чего не хватает — кнопки сброса фигуры, но тут уж ничего не попишешь.
Если вдруг
Полный исходный код есть на гитхабе.
99 бутылок: V
71. V — один из языков, за развитием которых я пристально наблюдаю. Искренне желаю ему развития и процветания — под влиянием «Раста», «Гоу»
Сил авторам не занимать — работает (за редким исключением) почти весь заявленный синтаксис, есть компиляция, трансляция в Си и ДжаваСкрипт, а так же обратная трансляция из Си в Ви (на гитхабе есть оттранслированный в Ви «Дум»).
Сильнее всего язык, кажется, похож на Гоу — есть даже синтаксически такой же оператор go, позволяющий запускать
Есть обобщённое программирование (которого так не хватает в Гоу), интерполяция переменных в строках (привычная ребятам, программирующим на ПХП, Перле и шеллах) и ограниченная перегрузка операторов (как в Си++).
Насколько я понял из сайта и блога, язык нацелен на безопасное программирование, скорость, как выполнения (проигрывает Си всего на три процента), так и выполнения и простоту кода. Повторюсь, выглядит очень интересно.
// 99.v by Evgeny Stepanischev Feb 2020
fn bottles(beer byte) string {
return match beer {
0 {
'no bottles'
}
1 {
'1 bottle'
}
else {
'$beer bottles'
}
}
}
fn main() {
mut b := bottles(99)
for i := 98; i >= 0; {
println('$b of beer on the wall, $b of beer.')
b = bottles(i--)
println('Take one down and pass it around, $b of beer on the wall.\n')
}
println('No more bottles of beer on the wall, no more bottles of beer.')
println('Go to the store and buy some more, 99 bottles of beer on the wall.')
}