Категория: Компьютеры

Заметки о программировании и на околокомпьютерные темы

Вложенные категории: Delphi, Игры

Simcracy

Последние пару недель я играю в симулятор капитализма “Simcracy”. Давайте все регистрируйтесь и становитесь моими рефералами, вам от этого хуже не будет, а мне дополнительно золото придёт.
Ну ладно, если вы против рефералов – вот чистая регистрация.

Чтобы вам далеко не ходить, тут же расскажу вкратце, как устроена игра, и как в неё играть.

как устроена игра, и как в неё играть.

Как устроена игра

В Симкраци вы строите рудники, добываете ресурсы и продаёте их – в этом суть игры. Из одних ресурсов можно производить другие, более сложные, например, из песка делать стекло – для этого нужны специальные фабрики. И, наконец, из ресурсов можно делать различные предметы, которые нужны для игровых действий – еду, медикаменты, учебники и оружие.

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

Итак, вы начали играть.

Выбор участка

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

В каждой зоне свои бонусы на разные типы ресурсов: есть такие, где легко добывать нефть, есть – где навалом песка. Выбирая себе дом, подумайте, на каком ресурсе станете зарабатывать. Более простые ресурсы (дерево, глина) сразу принесут доход, но рынок насыщен ими. Более сложные – например, нефть – помогут извлечь выгоду, когда вы немного разовьёте своё производство.

В каждой зоне свой мэр – или нет мэра. Мэры избираются голосованием игроков этой зоны с уровнем выше 18, и единственное, что могут делать – брать с вас налоги за работу. Так что выгоднее найти заброшеную зону без мэра, или такую зону, где уверенно лидирует мэр, не ставящий налогов. Мэров сейчас немного.

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

Чтобы добраться до нужной зоны, до неё нужно пропутешествовать. Это лучше делать не пешком, а на велосипеде – и один велосипед вам как раз дарят при регистрации. Переключение в режим карты мира доступно из меню игры, а чтобы переключиться на просмотр зоны, на неё нужно нажать.

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

Выработка ресурсов

Теперь у вас есть участок. Чтобы зарабатывать деньги, нужно добывать ресурсы, а для этого надо построить рудник. На постройку простого рудника вам как раз хватит начальных ресурсов – обычно требуется только дерево.

На руднике нужно работать. При этом вы расходуете энергию – а восстанавливается она неторопливо. Таким образом, в день вы можете совершить лишь ограниченное количество работы, и лучше тратить её с максимальной пользой. Энергия – самый ценный и единственный невосполнимый ресурс в игре.

Кроме того, для работы нужно быть сытым на 120 очков, а для этого потреблять еду. Не бойтесь – на первых порах вы едой обеспечены очень хорошо. Однако не ешьте просто так: с голоду вы не умрёте. Расходуйте еду только перед тем, как начать работать.

Ваш рудник приносит не слишком много ресурсов в день, и когда дневная норма выработана, дальше вы на нём работать не можете – остаётся только ждать. Чтобы увеличить дневную норму и сделать работу на руднике более эффективной (тратящей меньше энергии), рудники можно апгрейдить. Для этого тоже нужны ресурсы.

Рудник по добыче леса начального уровня требует около 0.75 энергии и столько же сытости для совершения единицы работы и добычи единицы леса. Этот же рудник, апгрейженный до десятого уровня, требует около 0.35 энергии и совсем незначительное количество сытости. Так что апгрейдить рудники – это выгодное вложение денег. Вы сможете добывать на них больше и эффективнее.

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

Если зона имеет бонус к ресурсу, то рудники по добыче этого ресурса будут сразу требовать меньше энергии и сытости за единицу работы. Однако количество добытого ресурса за единицу работы всегда будет неизменным.

Рынок

Добытые ресурсы можно использовать самому, а можно продать. Для этого существует рынок, доступный из меню игры. Цены на рынке пока не устоялись и постоянно падают, так что если вы хотите, чтобы ваше предложение нашло спрос, нужно назначать цену, близкую к минимальным предложениям конкурентов – или даже меньше. Вы убедитесь, что вашу небольшую цену всё равно скоро кто-нибудь перебьёт.

Разумеется, ресурсы на рынке можно и покупать. Если вы производите лес, а для апгрейда лесопилки вам нужен камень – гораздо выгодней купить его по дешёвой цене, чем строить каменоломню, апгрейдить её и работать на ней, тратя бесценную энергию.

Квесты

Из игрового меню доступен пункт “Квесты” – это задания для новичков, выполнение которых принесёт вам бесплатно некоторое количество ресурсов. Прочитайте эти задания и выполните их – большинство из них простые.

Сложные ресурсы

Некоторые ресурсы можно перерабатывать в другие. Для этого нужны фабрики, которые тоже можно апгрейдить, как и рудники.

Если простые ресурсы обычно добываются по единице за единицу работы, то для производства сложных товаров уже часто требуется десять или двадцать, а то и несколько сотен единиц работы. Также на фабриках и рудниках часто можно переключать режим производства: одна и та же фабрика способна производить разные товары. Например, кузня может производить:
– 1 железо за 10 работы (потребив 10 дерева и 2 руды)
– 1 нож за 220 работы (потребив 60 дерева и 10 железа)

Не обязательно вкладывать всю работу сразу: здание запоминает, какая часть ножа уже сделана.

Бонусов для вторичных ресурсов и товаров не существует. Их производство одинаково эффективно в любой зоне.

Навыки

Чем больше вы добываете лес или вырабатываете песок из стекла, тем лучше у вас это получается. На странице настроек персонажа можно посмотреть, какие навыки у вас насколько развиты. При высоком навыке на единицу одной и той же работы у вас уйдёт меньше энергии и сытости (выработка с единицы работы будет той же).

Поэтому выгоднее не метаться между разными производствами, а вложить все силы в добычу или изготовление чего-то одного. Со временем вам это будет даваться куда лучше, чем другим начинающим.

Навыки можно искусственно повышать в школах, но за это придётся платить хозяевам школ. Список школ доступен из меню игры. Отношение к ним встречается разное: на мой взгляд, они бесполезны, и гораздо выгодней развивать навык, работая на руднике – но у успешных игроков я встречал и обратное мнение.

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

От уровня персонажа зависит несколько привелегий: возможность покупать второй участок земли (кажется, 12-й уровень), баллотироваться в мэры и голосовать за мэра (18-й уровень) и участвовать в выборах президента (21-й уровень).

Найм

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

Обратите внимание, что цена назначается за единицу работы, а не потраченной энергии и не произведённого товара. Затраты энергии на единицу работы зависят от уровня рудника, от бонусов зоны и от навыка работника. Для нанимателя неважно, прокачан рудник или нет, и какой навык у работника. Сколько бы энергии не затратил работник на единицу работы, он получит одну и ту же плату. А поскольку за единицу работы рудник всегда даст одно и то же количество ресурсов, можно считать, что назначая зарплату, вы просто приобретаете ресурс по соответствующей цене.

Наоборот, с точки зрения работника, имеет смысл внимательно выбирать, на какой рудник наниматься. Смотреть следует не только на зарплату, но и на то, сколько энергии придётся потратить на этом конкретном руднике за одну единицу работы.

Существование навыков и найма открывает стратегию развития “профессионал”: не строить рудников и фабрик, а вместо этого работать на других, прокачивая свой навык какого-то одного производства.

Однако сейчас биржа труда в игре устроена таким неудобным образом, что пользоваться ей практически невозможно, и рынок труда не развит. Не рассчитывайте нанять людей за разумную стоимость, при которой вы сможете извлечь прибыль из продажи добытого ресурса. Конечно, назначить заведомо выгодную плату за работу просто на всякий случай, вдруг кто наймётся – это не повредит. Но будьте осторожны, цены на ресурсы падают, и заведомо выгодная вчера оплата сегодня может оказаться выше, чем цена этого ресурса на рынке.

Точно так же и работнику на рынке крайне неудобно: все топовые предложения на самом деле уже выработаны (у рудников ведь есть дневная норма), и реальные предложения начинаются только на третьей-четвёртой странице, а ведь вам надо ещё выбрать апгрейженный рудник на земле с бонусами, чтобы не тратить силы впустую. Механизмов для быстрого отсева предложений нет.

В общем, биржа труда в игре не развита, и полагаться на неё сейчас не стоит.

Демократия

В каждой зоне можно голосованием выбрать мэра. И кандидаты, и голосующие должны достичь 18-го уровня, так что на первых порах демократия вам не светит. Но надо знать, что мэр может устанавливать налог на работу, и в существующих реалиях игры единственный налог, который можно терпеть – это 0%.

Точно так же, по достижении 21-го уровня можно выдвигаться на пост президента и голосовать за кандидатов. Президент устанавливает налоги на торговлю, и точно так же, единственный налог, который стоит терпеть – это 0%. На нейтрале президента нет и налогов нет.

Учтите, что существуют разные страны и разные коллективы – кое-где пытаются реализовать коммунизм или формы плановой экономики. В таких случаях, разумеется, налоги имеют смысл – и если вы решите присоединиться к такой группе людей, то советы выше не для вас.

Война

На карте мира большинство зон нейтральны, но некоторые помечены названиями стран. Чтобы захватить квадратик, за него нужно воевать – это дело долгое, требует суммарно сотен тысяч энергии, а поскольку влияние ещё и падает со временем, то завоевать квадратик можно только силами десятков людей сразу.

В общем – это дело не для новичков, и если вы с места в карьер не прыгнули в какое-либо плановое общество, где нужно слушать приказ, то воевать вам совершенно ни к чему. Навоюйте 500 очков, как требуется для одного из квестов, и забудьте об этой возможности.

Золото и деньги

Кроме ресурсов, которыми торгуют на рынке, и денег, в игре существует золото. У него особенная роль. Золото нельзя произвести: вы получаете небольшое его количество с каждым уровнем. Поскольку уровни идут всё реже, приток золота вскоре практически прекратится.

Точно то же самое и с деньгами. Общая масса денег на рынке составляется из денег, которые каждый игрок понемногу получает вместе с уровнями.

Золотом, как любым ресурсом, можно торговать. Но оно не нужно ни для каких производств. Золото можно только есть.

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

Таким образом:
1. Общая масса денег на рынке в целом остаётся неизменной, чуть увеличиваясь с появлением новых игроков.
2. Общая масса золота на рынке в целом уменьшается.

Возможно, это не сразу очевидно, но отсюда следует простая стратегия торговли и потребления золота: золото нельзя есть никогда.

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

Золото – вложение в будущее, когда в игру придёт достаточно игроков, чтобы рынок золота сначала выровнялся, а потом продолжил обоснованный рост. Таково моё мнение.

Существуют две другие точки зрения на этот вопрос. Одна: золото необходимо тратить, чтобы быстрее восстановить энергию, потратить её, получить опыт, а с ним – уровни, и оказавшись впереди прочих игроков, пользоваться этим преимуществом для извлечения прибыли. Чтобы задействовать эту стратегию, нужно иметь хорошее представление о том, как именно вы собираетесь обналичить своё преимущество в уровне.

Другая: золото необходимо продавать прямо сейчас, получить в своё распоряжение существенно больше денег, и, опять же, раскрутиться за их счёт.

Как зарабатывать

Подведу итог, ещё раз дав простую инструкцию: как зарабатывать деньги, если никаких других идей нет.

Постройте несколько рудников, так, чтобы их дневные нормы выработки перекрывали вашу доступную энергию, работайте на них и продавайте ресурсы по достаточно низкой цене. Если рынок перенасыщен – начинайте добывать другой ресурс.

Чтобы узнать, какие ресурсы требуются, изучите доступные рудники и фабрики и их таблицы апгрейдов. Самый часто требующийся ресурс – дерево, но рынок дерева уже давно перенасыщен. За ним идут кирпич (производится из глины) и железные кубы (из дерева и руды). Потенциал рынка кирпича огромен, хотя сейчас кирпич ещё покупают мало. Рынок железа будет развиваться следующим после насыщения рынка кирпича.

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

Ну вот, теперь у меня очень, очень быстрый интернет. Как я давно о нём мечтал! Но зачем он мне был нужен?..

Skyrim: Finding Lydia

Если по Скайриму снимут художественный фильм, он должен называться “Skyrim: Finding Lydia”. На секунду о ней забудешь, – Лидии уже нет. ГДЕ?!! ГДЕ ОНА?!! Убили, что ли?! Лихорадочно вспоминаешь, где бывал последние полчаса. Когда в Виндхельме вещи продавал, Лидия ещё была. Потом на поле с драконом дрались. Не могла же она…
Телепортируешься туда, и точно – ночь, трава колышется, Луна в небе, Лидия стоит посреди бескрайней степи и ЖДЁТ. “Идём, хозяин?”

Ни мимо одного врага пройти не может. “Лидия, оставь в покое этого краба, он нам ничего не сделал! Пошли!” – “Нет, хозяин, пока я не добью тут каждого краба в округе, мы с вами дальше не пойдём.” – “Лидия! Опять пропала! Где она?!” – потерялась на морском берегу, моржей бьёт.
Влезли в чужой дом, тихо-тихо крадёмся, чтобы не разбудить жильцов. Нажимаю на шкаф, чтобы его обследовать, но под палец услужливо подворачивается Лидия. И голосит: “Хозяин, зачем мы сюда залезли?!”
Очень помогла!
Ни одного моего фаерболла не пропускает, и укоряюще говорит: “Хозяин, зачем же в меня-то?” А зачем же ты встала-то между мной и противником?

Сейчас снова обнаружил, что Лидии нет, когда уже сохранился. В ужасе бегу туда – нет! Сюда – нет! В доме – нет! Где бандитов били – нет! Ну всё, думаю, конец Лидии. Где-нибудь решила срезать путь, грохнулась со скалы да и померла. На всякий случай телепортнулся ещё в королевский дворец, где вещи заговаривал.
Точно. Откуда ни возьмись, выбегает Лидия и хвостом за хозяином. Как будто и не терялась.
Лидия, блин! Не пугай меня так.

И вот, так-то я о ней забочусь, так-то оберегаю, броню ей самую лучшую, оружие даю. Но шли мы с ней как-то по подземелью, напали на нас скелеты, а я решил свиток огненной мантии испытать, и весь покрылся страшным огнём.
Скелеты полопались. А Лидия от избытка чувств, чтоб быть поближе ко мне, в этот огонь полезла.
И обожглась.

В ту же секунду:
“Лидия больше не следует за вами”, и –
“ЛУЧШЕ БЫЛО ТЕБЕ НИКОГДА НЕ РОЖДАТЬСЯ НА СВЕТ!!!” — Хрясь! – Лидия отрубила мне голову.
Вот она, женская верность.

Ладно, Лидия. Я-то перезагружусь! Главное, сама не теряйся.

One hyperlink multiple hrefs

The simple thing that HTML really lacks is the ability to set multiple HREF targets for a single link:

<a href="iichan.ru" href="iichan.hk">

Why would you need this?
1. To specify multiple hosts serving the same thing, ensuring that even if one host goes down, it’s still accessible (for instance, multiple sources for a pic you’re linking to)
2. To aid with domain name changes (linking to both old and new domains)
3. To keep information well-organized (for instance, there’s a well-known domain hosting this which is down now, but may be revived later, and you’re linking to a google cache copy or a mirror, and still want the main domain to be the logical “target”)

How to implement this:
Browsers shall try HREF links one after another, in the order of declaration. They MAY probe them all at once and choose the fastest server, or probe in batches. They MUST though choose one “default” HREF and display it in the interface, and navigate to other HREFs only after asking for permission from the user. They MAY let the user choose the HREF manually when clicking on link.

Correct: The browser randomly chooses second HREF as the default HREF. When the user clicks on link, the server is not accessible, so the browser asks for permission to use next randomly chosen (fifth) HREF. This one is not accessible too. The browser asks for permission to use next randomly chosen (first) HREF, which turns out to be available.
Correct: When the user clicks on link, the browser probes all the available HREFs. Since the default one is not accessible, the browser asks for permission to use the fastest available alternative.
Correct: When rendering the page, the browser probes all the available HREFs and uses the fastest available server as the default HREF.
Correct: When rendering the page, the browser uses it’s knowledge of which servers were available and which were down before, to guess the best default HREF without actually probing HREFs.

Контакты

Реально не хватает какого-нибудь сервиса, чтобы отметить друзей, и они автоматически синхронизировались между всеми соц. сетями. Я уж молчу о дайри, которые деревня, но вконтакте, фейсбук, гугл плюс, контакты телефона, твиттер, скайп! И везде всех ищи заново.

Ещё в каждой соц. сети должны быть “Заметки о друге, видимые только вам”, чтоб написать там, допустим:
Девушка такого-то знакомого
Задавал вопросы по Харухи 3 года назад
Познакомились на ДР такого-то друга
А то смотришь на список друзей – кто эти люди?! (Ещё и фамилию некоторые меняют)

Дыра на дыре!

Компьютерщики, сыграем в игру: вас связали, все ваши компьютеры – в руках злоумышленников. Отвёртка в попе не помогает, вы молчите как партизан и паролей не говорите. Смогут ли вас в целом взломать?

Один-два сайта – это мелочи. Будем считать, злоумышленнику нужно ваше хранилище паролей или его аналог, т.е. способ получения паролей для всех сайтов, где вы зарегистрированы, а также личные секретные данные с каждого из устройств. Допускается заявить, что на каком-то устройстве их нет, но только на одном-двух.
У вас есть домашний ПК, рабочий ПК, ноутбук, планшет, мобильник. Как вы организуете защиту?

Обратите внимание:
– Если получен доступ к почте – вы взломаны! Через неё можно восстановить почти любой пароль.
– Используете куки на компьютере, и к браузеру получен доступ – вы крупно попали! Если не используете, опишите, как вы это устроили. Настройки браузера? Временный диск в памяти для кеша?
– Используете куки и залогинены в почту – вы взломаны полностью!
– Пользуетесь почтовым клиентом? Дважды попали! Пароль к почте можно вытащить из его настроек, а пароли к другим сервисам – из кешированных локально писем.
– Пользуетесь браузером? В вашем кеше много всего интересного! Незащищённый кеш приравнивается к незащищённым личным данным (с той разницей, что кеш разрешается уничтожать, а не шифровать/прятать).
– Ваша почта находится на собственном сервере? Пароль от хостинга равносилен взлому!
– Почта находится на собственном домене? Пароль от регистратора равносилен взлому! Перенаправляем почту на другой ящик и восстанавливаем пароли.
– Мобильник или планшетка в дурных руках? Там были ваши логины почты, и кешированные локально письма – вы взломаны!
– Сим-карту с вашим номером отняли? С помощью СМС на телефон восстанавливают пароль многие сервисы.
– Храните на дропбоксе бэкапы ключей шифрования, паролей, настройки подключения к компьютерам? Враг попал в дропбокс – и всё это взломано! Для простоты считаем, что сам дропбокс без пароля не откроется, хотя были случаи… Дополнительные очки тем, кто воспользуется только локально-шифрующимися сервисами типа SpiderOak/LastPass.

И ещё дополнительные очки тем, кто позаботится о бэкапе, так, чтобы когда злоумышленники сдадутся и отступят, и на прощание из вредности отформатируют вам диски, вы легко могли восстановить свою секретную и важную информацию!

Барри Келли ушёл из Дельфи, надо же. Язык ему надоел. Интересно почитать его объяснения в комментариях:

Delphi is very procedural. It grew out of Pascal, a language designed in an era when memory was very expensive. So most of its core runtime is based around mutation and destructive updates.

But the longer I’ve been coding, the greater and greater benefit I see to more functional approaches – which pretty much require garbage collection – and persistent data structures like you see in Clojure.

Этого я не понимаю, слишком плохо разбираюсь в функциональных языках. Они кажутся мне математическими упражнениями без настоящих применений. А с другим согласен:

I see the bureaucracy and busywork involved in creating class hierarchies, how it can fool you into thinking you’re doing productive work when you’re filling out various idioms and “patterns”.

Но идиомы и паттерны – это опыт: “такой подход работает”. Там, где их нет, обо всём надо подумать заново. Так что и тут не всё однозначно.

Metro 2033

Прошёл игру.

Сцены разрушенного города и метро интересны. Могло быть лучше, но всё-таки неплохо. Заброшенные туннели, подземные реки, разрушенная Останкинская башня (на неё можно залезть) – на всё это стоит посмотреть.
Графика ничем не удивляет.
Геймплей тоже, хотя кое-что неплохо (патроны как валюта). Но в целом тупые рельсы с тупыми заданиями.
Сюжет и его воплощение в игре бездарные абсолютно. Смеюсь с американцев, которые в эту чушь играют и говорят “необычный сюжет”. Куда пальцем не ткни – какая-нибудь нестыковка, нелепость, условность. Как в Doom3, короче.

Играть не особо интересно, но пройти один раз можно.

День, когда WordPress подавился метадатой

Сегодняшняя история програмистская. Кому компьютеры скучны, можете смело пропускать.

Как все знают, у меня есть отдельный блог на boku.ru. Записи туда по большей части копируются отсюда – в виде исключения я пару раз выложил там скучные рассказы, чтобы включить их в архив, но не афишировать.

Блог сделан на WordPress. Копирование записей устроено так: специальный скрипт генерирует RSS из дневника на Diary, а плагин FeedWordPress забирает RSS и импортирует в WordPress.

Категории при этом сохраняются, внутренние ссылки мой собственный плагин заменяет на местные, а если пост на дайри изменился – изменяется и пост на boku.ru, так что всё устроено достаточно удобно.

Но есть проблема. (далее)

Код FeedWordPress выглядит примерно так:

function WhatToDo(post)
  localPost = FindLocalCopy(post);
  if localPost==null then
    //New post!
    AddPostMeta(localPost, 'syndication_item_hash', post.Hash);
    return doCreateNewPost;
  else
  if not FindMeta(localPost, 'syndication_item_hash', post.Hash) then
    //Post changed!
    AddPostMeta(localPost, 'syndication_item_hash', post.Hash);
    return doUpdatePost;
  else
    //No changes.
    return doNothing;

Если пост на дайри не менялся, FeedWordPress не будет заново его импортировать и не создаст новой ревизии местного поста. Это хорошо. Но перед тем, как записать пост в базу, WordPress прогоняет его через ряд плагинов, которые меняют его содержание:
Пост на дайри (из RSS) –> (замена ссылок на местные) —-> (исправление форматирования) –> Пост на boku.ru

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

Но как это сделать? Ведь пост уже импортирован, и с точки зрения FeedWordPress, его содержимое не менялось (на дайри он остался тем же).

Для этой цели я влез в файлы FeedWordPress, и временно покромсал описанную выше процедуру. Она стала выглядеть так:

function WhatToDo(post)
  localPost = FindLocalCopy(post);
  if localPost==null then
    //New post!
    AddPostMeta(localPost, 'syndication_item_hash', post.Hash);
    return doCreateNewPost;
  else
  if not FindMeta(localPost, 'syndication_item_hash', post.Hash) then
    //Hack: Post is always changed!
    AddPostMeta(localPost, 'syndication_item_hash', post.Hash);
    return doUpdatePost;
    //TODO: Restore normal version.

Менялся пост или нет, мы всегда импортируем его заново. Конечно, при этом создаётся новая ревизия и захламляется база, но подумаешь, мне же ненадолго… А старые ревизии поста легко удалить.

Поправив таким образом FeedWordPress, я залил новые файлы на сервер и стал искать баг в своих плагинах. И нашёл. Исправил. Убедился, что теперь посты преобразуются правильно. Всё сохранил, применил, закрыл… а отключить хак забыл.

И ушёл.

Вторая половина этой истории началась через месяц, когда я зашёл на блог на boku.ru. Все страницы с последними постами не работали.

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

php error: maximum memory allocation exceeded

Какой-то из скриптов жрёт память? Но почему? Что я менял?

И тут я вспомнил, что забыл отключить хак.

Но постойте, а что такого? Проверки раз в полчаса – это 48 проверок в день, жалкие полторы тысячи ревизий за месяц. WordPress может обслуживать десятки тысяч постов, для MySQL лишние несколько тысяч ревизий – пустяк.

Если я напишу ещё полторы тысячи постов – вордпресс даже не поперхнётся. А полторы тысячи ревизий вывели его из строя?

Да ну! Не так он написан.

Тогда почему любая страница, которая обращается к последним постам – вылетает с переполнением памяти? База данных находится на диске – что вообще вордпресс грузит в память?

Метадату.

Каждый раз, загружая очередной пост для печати, вордпресс делает примерно следующее:

rows = exec_sql('SELECT * FROM post_metadata WHERE post_id=id');
while rows.MoveNext() do
  metadata[rows['name']]=rows['value']

То есть, читает из базы все относящиеся к посту записи метадаты и загружает их для быстрого доступа в память.

Обычно таких записей 8-10, иногда до 15 – мелочи, в общем.
У последних записей в моём блоге их было по 60 000.

Ничего удивительного, что обращаясь к этим записям, вордпресс падал. Он не рассчитан на 60 000 записей метадаты у поста. Удивительно, откуда эти записи взялись.

Я открыл таблицу phpMyAdmin-ом, и увидел, что все они – это копии параметра syndication_permalink. Тогда всё стало ясно.

Описанная выше функция WhatToDo решает, что делать с постом из RSS – добавить новый, обновить существующий или пропустить. При этом она регистрирует syndication_permalink, чтобы второй раз не обновлять одно и то же.

Да, импорт RSS происходит лишь раз в полчаса, 48 раз в сутки, и каждый пост импортируется лишь однажды – но функция проверки WhatToDo вызывается десятки раз за процедуру одного импорта. Только однажды её результат имеет значение, поэтому ревизий в базе действительно создано лишь полторы тысячи – но при каждом вызове она добавляет syndication_permalink, и этих пермалинков, совершенно одинаковых, у одного поста набираются десятки тысяч.

Ирония: вордпресс мог бы вынести десятки тысяч постов – но не десятки тысяч свойств поста.

Как всё это чинить?
Итак, испорчена таблица post_metadata: в ней для некоторых постов некоторые записи продублированы десятки тысяч раз. Нужно удалить дубли, но оставить по одной копии каждой записи.

После некоторой возни и гуглинга сотворился следующий манёвр:

CREATE TABLE `keep_ids` AS (
  SELECT MIN(`rowid`) AS `rowid` FROM `post_metadata` GROUP BY `postid`, `name`, `value`
)

Этим запросом мы находим все цепочки дублей (записей с одинаковыми данными в полях postid, name и value), и в каждой выбираем наименьший номер записи. Таким образом, мы получаем по одной копии каждой уникальной записи. Эти копии надо сохранить, а всё остальное удалить.

ALTER TABLE `keep_ids` ADD UNIQUE INDEX `rowid` (`rowid`)

Это чтобы операции с новой таблицей были быстрыми – сейчас понадобится.

DELETE FROM `post_metadata` WHERE `rowid` NOT IN (SELECT `rowid` FROM `keep_ids`)

Удаляем все записи из исходной таблицы, которые не вошли в наш “список на сохранение”. Если б в `keep_ids` не было индексов, мы бы тут завязли на несколько минут, а так – только секунд.

Ну и, наконец, удаляем временную таблицу:

DROP TABLE `keep_ids`

Победа! Число записей в post_metadata резко падает с сотен тысяч до 13 000 и блог снова работает нормально.

Названия таблиц и полей в примерах условны, и не соответствуют настоящим названиям в базе вордпресс. Код написан на условном языке, а код SQL может быть не совсем правильным, но передаёт общую мысль.

Игра по Back to the Future

Конечно, это фанфик, но очень хороший фанфик. Настолько кинематографичный и похожий на оригинал, что сцены из игры в голове путаются со сценами из фильма. Даже сюжет, который местами выбивается из стилистики, по большому счёту всё-таки “настоящий” – приключенческий и интересный. Не перечесть всех моментов, когда думаешь “чёрт, а ведь это правда могло быть и в фильмах”.

А знакомая музыка и знакомые голоса Марти и Дока (трудно поверить, что их играли другие люди) сшивают любые разрывы и заставляют поверить, что это действительно “Назад в будущее”. Авторы могли ошибиться во стольких местах, но в большинстве не ошиблись.