Там можно отметиться о том, куда собираешься переехать в случае закрытия дайари, чтобы потом можно было легче тебя обнаружить.
И это мне остро напомнило то, о чём я обещал написать в посте про смерть.
О том, как закрывался nnm-club в 2008 году.
RAM
DATE&TIME
2008/12/??
SCENE TITLE
Дом, который я потерял: как умирал nnm-club
OUTLINE
zHz мирно проживает на nnm-club'е, но внезапно случается неприятность...
DISCLAIMER. 1. Я рассказываю так, как помню. Если у вас есть уточнения или важные дополнения (а некоторые участники тех событий меня читают) -- сообщите мне. 2. Я постараюсь воздержаться от оценочных суждений и излагать только факты. Однако даже факты могут быть ложны, ибо всю правду знают только администраторы.
I. Что было такого в nnm-club'е до начала инцидента.
Что это вообще такое? Это торрент-трекер. Насколько я знаю, он появился из сайта nnm.ru, когда некоторым авторам надоело выкладывать варез и прочее на файл-хостинги типа рапидшары.
Основатели были немного анимешниками. Поэтому там всегда был сильный аниме-раздел. Я тоже был анимешником. И я там плотно тусовался. Висел практически круглосуточно. Делал релизы (25+ штук). Помогал модераторам (без их просьбы), указывая начинающим релизерам на ошибки в оформлении. И так далее.
Фишка аниме-раздела ннм-клуба была проста. Все релизы проходили жёсткий контроль по оформлению и по составу раздачи. Никаких русских озвучек, только титры. Никаких хардсабов. Если появлялся материал лучшего качества, старый уходил в архив. В оформлении должны были быть подробно указаны характеристики аудио и видео, а также приведены скриншоты. Посторонние файлы в раздачах были запрещены. Раздачи одним файлом-архивом были также запрещены.
Сейчас рутрекер, к примеру, пред'являет схожие требования, однако гораздо более лояльно относится к русской озвучке. В результате либо приходится качать раздачи не целиком, если озвучка присутствует в виде отдельных файлов, либо получать озвучку в нагрузку.
Был у нас и уникальный контент. Собственная релиз-группа N^A выпускала релизы особого качества. Также отдельные сознательные личности самостоятельно рипали диски, делали переводы, либо выкачивали то, чего не было на других отечественных трекерах, из Share/Perfect Dark.
А то, что трекер был закрытым (требовалась регистрация+при ратио меньшем 0.3 не давали скачивать), приводило к очень долгой жизни раздач.
Короче говоря, аниме-раздел представлял из себя весьма качественную коллекцию. Я пишу в прошедшем времени, поскольку не знаю, как там обстоят дела в текущий момент. Сейчас я там бываю редко.
Модераторами тогда были Tark и Lin_Thei.
Также необходимо упомянть таких знаковых личностей в разделе, как: BALROG (позже он создал группу Yousei-Raws), sumire, nb48, s19, Svartalf, mixrin, A.Rei, Nesmejana, DonCiHot, ATI, OnZa, RiLTiX. И, конечно, ssvda и alex14n. Сейчас их уже нет в живых. Были и другие люди. Eсли бы я писал исландскую сагу, надо было бы про каждого из них что-нибудь написать. И про большинство из них мне есть что написать. Но всё же делать этого я не буду. Не уверен, какие из этих сведений можно публиковать.
II. Начало проблем.
Это был декабрь 2008 года. Почти 10 лет прошло! Тогда я тусовался на ннм-клубе не менее года. И тайно мечтал быть модератором аниме-раздела, но меня никто не звал, а предлагать себя я не решался.
В один прекрасный день на сайте появилось об'явление примерно следующего содержания (полный текст сейчас уже не найти):
"Я, Alien, являюсь администратором данного сайта. Извещаю о следующем. С такого-то числа вводятся новые правила: 1. Ннм-клуб -- религиозная организация, исповедующая информизм. 2. Главным ритуалом информизма является обмен информации между прихожанами. 3. Свою деятельность ннм-клуб осуществляет на деньги прихожан. Это членские взносы. 4. Прихожане, не внесшие членские взносы, к ритуалам допущены не будут."
Это была не шутка. Почему надо было излагать именно в такой форме известие о том, что теперь на ннм-клубе будут членские взносы, я не знаю. Подозреваю, что это связано с обходом борьбы с пиратством. Членские взносы вводились с 1 января 2009 года.
Подробных комментариев от администрации добиться не удалось. Но косвенным путём удалось выяснить следующее: 1. Alien не сошёл с ума, а принял решение о членских взносах совершенно сознательно и с согласия других администраторов. 2. Причиной такого решения было то, что один из администраторов, NorthOn, пропал в неизвестном направлении, прихватив с собой деньги, которые предназначались для оплаты хостинга.
III. Врезка о том, что такое анимпиада.
Теперь надо пояснить, что такое анимпиада. Это вид спорта, который был популярен в аниме-разделе в то время. Суть такова. Один из игроков ведущий. Остальные нет. Все заходят на одну и ту же жаббер-конференцию. Дальше происходит следующее: 1. Ведущий постит скриншот из аниме. 2. Участники пытаются угадать, что это за аниме. 3. Угадавший получает 2 очка. 4. Если никто угадать не может, ведущий постит ещё один скриншот из того же аниме. 5. Обычно со второго скрина уж кто-нибудь да угадывал (и получал уже 1 очко), но если нет, то давались дополнительные словесные подсказки. 6. Получивший больше всего очков становился ведущим следующей анимпиады.
Проводились они раз в неделю. Количество участников было разным, но человек 10 набиралось, кажется. За одну анимпиаду загадывали 20-30 тайтлов. Было очень весело. Я даже пару раз водил.
IV. Революция.
Недовольных лиц было множество. В целом, основная мысль была в том (и с ней я согласен), что торрент-трекер на членских взносах существовать не может. Слишком мало останется пользователей для поддержки существующих раздач, которых было МНОГО.
Кто подал идею, я уже забыл. А идея была в том, что пора валить. У нас был отличный раздел, все друг друга знали. Естественно, разговаривать на эту тему надо было в тайне от администрации. И у нас была исключительная возможность для обсуждения этого с теми пользователями раздела, которые не входили в инициативную группу. Анимпиада. Кроме того, были сделаны некоторые дополнительные действия, которые я опишу ниже.
V. Что было с данными раздела.
Мы решили для начала выкачать весь раздел! И Музыку восточной Азии заодно. В итоге все раздачи оказались на винчестере у хоть кого-нибудь из основного костяка (10-20 человек). И мы знали, у кого что. По данному пункту успех был полным. Теперь данные раздела можно было восстановить на новом месте без особых проблем.
BALROG прямо на ннм-клубе публиковал алфавитные списки скачанного. По этим спискам потом ещё несколько лет сверялись, у кого равка круче.
VI. Что было с пользователями.
Я (zHz) взял на себя роль связиста. Это было общественно одобрено. Я решил установить контакт с самыми активными пользователями раздела способом, независящим от ннм-клуба. Это было нужно, чтобы держать их в курсе событий и пригласить их на новую площадку.
Я обнаружил около 50 человек, которых можно было бы агитировать. Я стал им писать личные сообщения в ещё работающем ннм-клубе. Пояснял ситуацию и просил сказать номер аськи (типа "скоро введут членские взносы, сообщите номер аськи, чтобы не потерять связь с вами, когда доступ неоплатившим закроют"). Тогда она была ещё популярна.
Хотя в тексте сообщения я напрямую и не указывал, что мы собираемся переезжать, однако то, чем я занимаюсь, администрации не понравилось.
Мне отключили личные сообщения.
Я вышел через альтернативные каналы связи на одного из администратовов. Его звали akaDJon. Я спросил его, что случилось, и можно ли включить сообщения обратно? Он сказал что можно, если я прекращу спрашивать номера асек. Я спросил, противозаконно ли спрашивать номера асек? Он сказал, что нет, но ничего хорошего в этом сейчас нету. В итоге я пошёл на сделку с администрацией и перестал спрашивать аськи. Личные сообщения мне включили. С разрешения администрации я повесил номер аськи в профиле. Новый номер завёл для этого.
Да, связаться удалось не со всеми, но со многими.
Я был не единственной жертвой отключения: администрация целенаправленно читала личные сообщения пользователей и удаляла упоминания иных ресурсов. Мы были не единственной группой, уходящей организованно. Была ещё минимум одна. Если я правильно помню, её возглавлял MechanismEight (mech8).
VII. Анимпиада.
Это было 15 декабря 2008 года.
Я написал в аську тем, с кем удалось связаться, чтобы они явились на анимпиаду. И что это очень важно. Как вы догадываетесь, никакой анимпиады не было.
Мы решали организационные вопросы переезда.
Когда весь народ набился в конференцию, стало понятно, что жаббер для таких больших конференций не предназначен. Он тормозил. Тем не менее, обсуждение состоялось. По итогам обсуждения была принята следующая резолюция:
1. Мы переезжаем. 2. Для начала у нас будет хотя бы форум. 3. Потом либо мы прикрутим трекер, либо будем раздавать на открытых трекерах, а на форуме будут туда ссылки.
Стали выбирать движок для форума. Mixrin (один из самых активных участников инициативной группы) топил за MiniBB, но у него пришлось бы слишком много допиливать. В итоге выбрали SMF.
VIII. Разработка.
Я и ssvda вызвались допиливать ПО (т.е. SMF). Я взял себе для начала задачу релиз-визарда (заполняешь форму на странице, нажимаешь некст -- и получаешь готовое оформление в BB-кодах). И ещё расширение, которое позволит сделать в постах нормальный спойлер (их было много, но все не подходили). ssvda делал навороченную систему поиска с облаком тегов. Он об'яснял, что это будет похоже на подсказки от гугла.
Эти задачи лично для меня стали большим толчков в изучении программирования. Я познал основы Четырёх Языков. И если с тремя из них отношения у меня особо не сложились, то PHP я до сих пор иногда использую. Он мне очень понравился.
У нас была ещё одна дополнительная задача. Надо было сохранить оформления всех текущих релизов. Я взялся за это дело и сделал специальный скрипт под названием nnm-dumper. Задаёшь ему название раздела, а он автоматом скачивает все тексты (сразу преобразуя их в правильные BB-коды) и сохраняет в древовидной структуре на винчестер.
IX. Crimes? Crimes.
Потом мне в голову пришла идея, что неплохо было бы слить таким образом и модераторскую. Но к ней у меня не было доступа. Однако я обратился к одному модератору, имя которого я указывать не буду. Он без особых колебаний отдал мне свой пароль. И модераторскую я слил тоже. В целях секретности я сливал, подключившись к интернету из неожиданного места, которое нельзя было по айпи-адресу связать со мной, с тем модератором, либо с кем-нибудь ещё. По-видимому, администрация сего действия не заметила.
Почему же модератор так легко пошёл на это? Атмосфера в ннм-клубе тогда была весьма своеобразная. Членские взносы ещё не ввели, но это должны были сделать со дня на день. При этом многие пользователи платить не собирались. Поэтому считали, что это их последние дни на трекере. Чумной город, где свирепствует не только чума, но и мародёры -- вот, наверное, лучшее сравнение. Когда всем всё равно, что происходит.
В том числе произошёл следующий случай. В качестве протеста куратор раздела "Игры" удалил все свои раздачи. Его отстранили от должности. Один из оставшихся модераторов продолжил дело куратора. Его тоже отстранили. Третьим был DeadlyMercury. Он отдал свой аккаунт куратору. А куратор снёс весь раздел. Так за три недели от ннм-клуба были отлучены три модератора только из раздела "Игры". Их учётные записи были заблокированы навсегда (в тогдашних терминах это называлось "деактивация"). Раздел восстановили из бэкапа. После этого модераторам удалять темы запретили.
Да, модераторы тоже возражали против решения администрации. Но их никто не спрашивал.
X. Крах.
Где разместили форум, я не помню. Но он заработал. В дополнение мы создали секретный канал в ирке, где тусовались. Администратором сайта сделали mixrin'а.
А дальше случилось вот что.
Он пропал. При этом он был единственным администратором. И хостинга, и форума. В итоге у нас был форум, где мы могли общаться, но ничего больше с ним сделать не могли.
Свои задачи я доделал. Но не мог их внедрить.
При этом ещё более новый форум мы не делали. Я не знаю, почему. В принципе, может до этого мы бы и дошли. Если бы не одно событие.
XI. Забытье.
Неизвестно откуда появился NorthOn. С деньгами. Ничего не об'яснил. Но вся история с членскими взносами отменилась. В связи с этим пропал стимул развивать форум.
Спустя полгода (!) неизвестно откуда появился mixrin (тоже ничего не об'яснив!), естественно сразу сделал второго администратора (меня). Однако никто ничего уже не хотел. И проект собственного аниме-форума-трекера развалился. Кто-то вернулся на ннм-клуб (некоторых забаненных разбанили). Кто-то ушёл совсем. Я тусовался на ннм-клубе ещё некоторое время, но уже не чувствовал такого родства с сайтом и с другими пользователями. Я практически перестал туда заходить. Спустя год или около того мне предложили должность модератора "Музыки восточной Азии". Но я отказался. В итоге модератором взяли ssvda.
Что выжило -- так это секретный чатик. Людей там мало, но общение ведётся довольно активно.
XII. Мораль.
У сайта должно быть не меньше двух администраторов.
XIII. Паранойя.
Сходство событий, произошедших с NorthOn и mixrin, очень подозрительно -- оба пропали, когда были нужны, а вернувшись, ничего не об'яснили. Свои гипотезы на сей счёт я, пожалуй, высказывать не буду.
Итак, у меня было две версии функции. Одна была отлично откомментирована и хорошо разбита на блоки. Но она не работала. Это было следствие рефакторинга.
Другая работала. Изначальная. Но выглядела мягко говоря... не очень.
Передо мной стояла задача: надо было заставить первую работать.
Было две стратегии: 1. Долгим вдумчивым взглядом пытаться понять, чем же эти функции различаются, и где я облажался; 2. По частям вводить отрефакторенные блоки в старую функцию и следить, когда она перестанет работать.
В большинстве дневников слетело оформление до такой степени, что прям слетело-слетело.
Поэтому интересный пост писать сегодня не хочу. Напишу ерунду.
В японском языке нет пробелов. Как же можно без напряга читать японские тексты? Как определять, где одно слово кончается, а следующее начинается? Честно говоря, я об этом не задумывался. Читал и читал. Но теперь подумал.
Тут есть две смежные проблемы: а) как определить конец слова б) как определить начало слова.
В японском языке тексты пишутся на смеси иероглифов (знаков, имеющих и смысл и чтение) и т.н. "хираганы" (эти знаки имеют только чтение). Иероглифами обычно записываются знаменательные слова. То есть те, которые имеют смысл. А хираганой записываются окончания слов и служебные слова, не имеющие собственного смысла.
Очевидно, что при записи иероглифы и хирагана будут постоянно между собой чередоваться. И каждое следующее смысловое слово будет начинаться с иероглифа.
А теперь главный ключ. Иероглифы и хирагана выглядят очень по-разному. Иероглифы угловатые (например, 本, 曜, 顰. Хирагана же круглая (например, の, ふ, ゑ.
Поэтому начало каждого слова в тексте определяется чисто визуально. Вот пример текста из Википедии, свободной энциклопедии:
С концами слов сложнее. Тут уже приходится думать. Если слово состоит из двух и более иероглифов, то оно, как правило, не имеет окончания (потому что слова из нескольких иероглифов заимствованы из китайского языка "как есть", а там нет окончаний). Поэтому последний иероглиф перед хираганой -- это конец слова. Однако если слово состоит из одного иероглифа, то обычно это исконно японское слово. В таких словах может как быть окончание, так и не быть. Тут возможны несколько вариантов:
иероглиф -- служебное слово -- следующий иероглиф иероглиф -- окончание -- следующий иероглиф иероглиф -- окончание -- служебное слово -- следующий иероглиф
При этом окончание может быть замешано из 3-4 кусочков, каждый из которых немного меняет смысл иероглифа, к которому они относятся (т.е. предыдущего). Это называется агглютинация.
Тут ключ в другом. Служебные слова, даже если они есть, тоже меняют смысл предыдущего иероглифа. Поэтому нет никакой нужды разделять окончание и служебное слово. Их надо брать одной кучей и разбирать, что они делают с иероглифом.
А вот как люди умудряются читать КИТАЙСКИЙ текст -- мне действительно интересно.
Там же будет продублирована информаци о том, где меня искать, если закрытие будет не внезапным, а плановым. Также я проверяю почту mailto:[email protected] .
Хочу поддаться тренду и высказаться по вопросу, обозначенному в заголовке.
Дальнейший текст не предназначен для чтения лицами, которые излишне впечатлились новостями. Для которых дайари дом родной. Для которых непредставимо, что они будут жить на другом ресурсе. Если вы из этой категории, не читайте дальше. Вам будет неприятно.
(я прочитал предупреждение и готов узнать, что там понаписал этот уёбок) Наблюдая за поведением администрации, я сделал следующие выводы: 1. Администрация не хочет или не может заниматься спасением сайта. 2. Истинная причина -- не та, что сообщена официально. Какова она -- неясно. Очевидный вариант -- что администрации надоело тянуть ресурс (хотя они это отрицают). Параноидальный вариант -- что это происки Роскомнадзора. (варианты придумал не я) 3. Фактически, администрация не идёт на диалог с пользователями. 4. Администрация ноет.
Это было что-то вроде фактов. А теперь я хочу пофилософствовать. Сегодня Самайн, и тема есть подходящая.
Рисунок выше -- это карта Таро. Знакомьтесь, называется "Смерть" (в Марсельских колодах писать название этой карты не принято). Посмотрите на неё внимательно. Это не опасно. Видите, на одной из срубленных голов корона? Это значит, что перед смертью все равны.
Однако основное значение данной карты -- вовсе не смерть физическая. Это смерть метафорическая. Трансформация. Чтобы пройти в будущее, надо отсечь прошлое.
Я поясню на примере: ребёнок закончил школу и поступил в институт. Это смерть школьника, но рождение студента.
Дайари уже давно находится в стагнации. Меня она вполне устраивает. Но вечно стагнация продолжаться не может.
Что теперь будет? Я вижу четыре варианта.
1. Дайари это не только сервера, но и коллектив авторов. Если заработает хотя бы один из двух сайтов-клонов, и они действительно будут поддерживать функцию восстановления дневника из архива, то в случае закрытия дайари часть пользователей перейдёт туда.
Это -- коллективная перезагрузка. И она необходима. Пора почистить груз многих лет и оставить только актуальное.
Хотя без жертв обойтись не получится, я всё же считаю, что если дайари закроются окончательно в таком варианте -- это будет очень хорошо.
2. Возможно, администраци согласится перепродать ресурс желающим (такие есть). В этом случае ресурс тоже ждёт трансформация, поскольку новые владельцы будут заведомо вести себя иначе чем текущие. (поскольку если бы они были в таком же состоянии, как текущие, они бы просто не захотели покупать ресурс)
Это тоже будет хорошо.
3. Возможно, клонов создано не будет, сайт закроется и все разбредутся.
Это не очень хорошо. Но и не слишком плохо. И вот почему:
4. Возможно, получится подсобрать денег и немного приподнять дайари. Уговорить администраторов продолжить их дело. Но этот вариант -- это просто поддержание текущего состояния. Это болото. И из всех четырёх вариантов именно болото я считаю наихудшим.
===
Кроме смерти дайари, которая может быть как абсолютная, так и трансформационная, есть ещё (метафорическая) смерть каждого конкретного пользователя. Принудительная трансформация. Каждый сам решит, что ему делать не здесь. Потому что "здесь" уже не будет.
Однажды я уже переживал закрытие ресурса, на котором плотно тусовался. Дом родной, все дела. F5-F5-F5. Ресурс, правда, в итоге не закрыли. И хотя его и не закрыли, ощущение дома в нём я уже потерял (об этом я расскажу в другой раз UPD. Вот: zhz00.diary.ru/p214101309.htm). Уже позднее, думая о том случае, я пришёл к такому выводу: место, где обретаешься, вторично. Первично -- это то, что ты представляешь сам по себе.
Поэтому я начинаю собирать чемоданы.
Я веду этот дневник шесть лет с гаком. Я пишу сюда каждый день. Читателей у меня мало, но они в тельняшках.
Хотя в первую очередь дневник я веду для себя, но и для читателей тоже. Безусловно, в случае закрытия площадки, я буду вести его где-то ещё.
Коллега1 принёс на работу пирожки, которые испекла его жена. Я вижу -- в них есть дырки. По одной дырке на пирожок.
Я спрашиваю: А зачем в пирожках отверстия?
И тут коллега1 и коллега2 отвечают хором:
Коллега1: Это чтобы пирожки не взрывались! Коллега2: Это для стравливания избыточного давления!
Смех тут в том, что коллега1 -- доктор наук, а коллега2 -- кандидат.
А потом коллега1 рассказал ещё более потрясающую вещь. Если отверстие одно -- то пирожок с яблоком, если два (таких не было), то с капустой. И так далее.
То ли я раньше этого не замечал, то ли в Москве действительно весьма усилилась подсветка неба наземными источниками света. Когда пасмурно, некоторые выступы облаков имеют цвет, заметно отличающийся от фона. При этом кажется, будто источник света расположен ЗА облаком, а не перед ним.
И вот один из примеров этого.
Иду я как-то и вижу -- луна за облаками. Полная. Но постойте, ведь сейчас новолуние! Кроме того, полная луна за облаками на самом деле выглядит не так. Она формирует вокруг себя огромный полуосвещённый круг, а тут был маленький, аккуратненький, точно размером с луну. Что за ерунда.
Прошло несколько часов. Иду обратно. Облачность в том месте рассеялась. И стало видно, что там ничего не видно (в этом странного ничего нет, т.к. если бы это была луна, она бы за это время уехала). Однако появился небольшой туман. И вот этот туман проявил столб света, выходящий вертикально вверх -- в то место, где некоторое время назад была "луна".
То есть, на самом деле это был бетмен-прожектор! Только без летучей мыши.
Авторам явно пришлось по душе то, как необычно выглядит один из персонажей сериала Demi-chan wa kataritai, а именно -- безголовая девушка. Нет, такое было и в других местах, к примеру, в Durarararararara. Однако там не было головы. В Demi-chan... же голова есть. И она активно участвует в повествовании. Это вызывает какое-то инфернально-сюрреалистичное чувство, поскольку все окружающие к безголовой девушке с головой подмышкой относятся нормально.
В данном же сериале решили сделать, чтобы ВСЕ персонажи выглядели необычно. Хотя большая часть необычных персонажей для аниме как раз довольно обычна, типа ангелочков и чёртиков, есть и те, которые смотрятся примерно так же, как дуллахан из Demi-chan... И это кентавр и человек-змея.
Я буду продолжать сравнивать Centaur no Nayami с Demi-chan... , поскольку у них много общего. Оба сериала номинально -- комедийная повседневность. Однако если Demi-chan более-менее хаотичен, то Centaur no Nayami -- систематичен. И главный элемент системы -- это внутрисериальное пояснение о том, почему у всех живых существ либо есть крылья, либо рога, либо что-нибудь ещё. Ниже я коротко перескажу это пояснение:
"Давным-давно вся жизнь на земле разделилась на четвероногих и шестиногих животных. А четвероногие вымерли. Поэтому мы все являемся потомками выживших шестиногих".
У этой легенды, безусловно, есть недостатки, однако в большинстве других сериалов, где фигурируют необычные существа, нет и этого. Так что такая легенда -- безусловный плюс.
Что же ещё есть в этом сериале, кроме комедийной повседневности, ради которой его, безусловно, стоит смотреть?
Социальная сатира. Присутствует она не всегда, а только иногда. Как будто автор пытается изо всех сил удерживаться в обычной комедии, но срывается. Посмотрев на пару сатирических эпизодов, я понял, что мир, в котором живут персонажи, вовсе не такой стандартно-добрый, каким казался изначально. Он гораздо сложнее и серьёзнее, просто в кадр это редко попадает. Но на самом деле сложность и серьёзность постоянно присутствует фоном. И давит.
И основная тема, которая высмеивается в данном сериале -- это толерантность. Толерантность доходящая до абсурда. А почва тут богатая, т.к. все живые существа имеют характерные особенности, причём они весьма заметны.
Рекомендую тем, кого устраивают комедийные сериалы, но хочется немного специй иного сорта, чем сиськи-письки (хотя про них тоже кое-что есть).
Старушки иногда обращаются ко мне с целью перемещения их тележек по лестничным пролётам.
Иду по лестнице. Посередине стоит старушка с тележкой. Старушка: -- Кто-нибудь, помогите поднять тележку! Я подхожу и встаю рядом. -- Помогите поднять тележку! Я стою, смотрю на неё. Она смотрит в сторону. Потом поворачивается. -- Да я не вас прошу, а их!
Машет рукой в сторону. Я смотрю туда -- там стоят два лица без национальности. Я пожимаю плечами и иду по лестнице дальше.
Тут эти два лица меня обгоняют и быстро исчезают в дали. Без тележки.
Кредитными картами я не пользуюсь. Была у меня одна, пролежала на полочке 3 года, потом закрыл. Тем не менее, условия кредитных карт, как правило, стандартные. Они мне известны.
Предоставляется беспроцентный кредит на 50 дней. Месяц средства расходуешь, потом ещё 20 дней есть, чтобы погасить задолженность. Если погасил частично (обычно 5-10% задолженности), на остаток проценты начисляются в размере 20-30% годовых. Но зато на следующий месяц заново открывается полный об'ём кредита. Называется -- револьверный кредит.
Вроде всё чётко и ясно. Условия более-менее драконовские, но честные. Я думал, тут нет никаких подвохов.
Пока краем глаза не увидел весьма странное утверждение, которое потом мне подтвердили вербально в Сбербанке.
ОКАЗЫВАЕТСЯ беспроцентный кредит действует только при безналичной оплате. Если осуществить операцию "получить наличные" в банкомате, то 50-дневный срок сбрасывается в 0 и сразу начинают начисляться проценты в том самом размере 20-30% годовых!
Anki -- программа для зазубривания связанных фактов. Часто её используют для заучивания слов и иероглифов (связка слово -- перевод). Анки в переводе с японского означает "помнить наизусть".
В основе обучения лежит метод интервальных повторений. Второй показ факта производится через одну минуту после первого. Потом через 10 минут. Потом через сутки. Дальше интервал увеличивается по сложной схеме. Если вы не помните иероглиф, вас отсылают в начало цепочки. (помнит человек или нет, он определяет сам, а не по вариантам ответа: он жмёт "показать ответ", а потом сравнивает с тем, что вспомнил сам)
Авторы программы сочли, что такие промежутки приводят к наиболее эффективному запоминанию.
На разных каналах по-разному, но допустим, что по телевидению во время показа фильмов рекламу пускают каждые 20 минут и длится она 5 минут.
Однажды я смотрел фильм по телевизору и обнаружил, что во время рекламной паузы один из роликов был показан дважды. И во время следующей рекламной паузы тоже.
Очевидно, заказчики показа знали о методе интервальных повторений. Человек, смотрящий фильм даже не целиком, имеет все шансы увидеть ролик 4 и более раз по схеме:
первый показ -- 2 минуты -- второй показ -- 20 минут -- третий показ ( -- 2 минуты -- четвёртый показ).
Это способствует наиболее эффективному запоминанию рекламы.
Заходит мужик в автобус. Говорит водителю: -- Скажите, а я до улицы Копытной доеду? -- Возможно. -- Э, что значит "возможно"?! -- (раздражённо) Ну откуда ж я знаю, может вы раньше выйдете?
На эту тему существует несколько заметок, однако я счёл, что все они обладают недостатками. Поэтому решил написать свою.
Ключевое слово static -- наверное, самое эзотерическое слово в языках Си-группы. Во-первых, оно довольно редко нужно (но volatile, конечно, круче). Во-вторых, в зависимости от контекста это слово может означать довольно разные вещи.
(читать дальше)Если пытаться найти что-то общее среди всех применений, то static следует переводить как "глобальный, но скрывает это".
1 Язык Си
1.1 Статическая локальная переменная
С этим применением сталкивались многие. Как известно, локальные переменные теряют свои значения после завершения функции. Каждый раз функция начинает работать с чистого (а точнее, с грязного) листа. Если же локальную переменную об'явить как статическую, она будет начинать с тем значением, на котором закончила в предыдущий раз. Даже если присутствует инициализация, та будет выполняться только один раз. При первом вызове (а на самом деле -- при старте программы).
Пример.
void f(void) { static int n=0; printf("n=%d\n",n); n++; }
int main (void) { f(); f(); f(); }
На экране должно появиться:
0 1 2
Зачем. В данном случае переменная просто является счётчиком вызовов (что может быть полезно). Основное же применение статической локальной переменной -- это сохранение состояния вычислений внутри функции. Имеет смысл в различных итерационных методах, когда каждый вызов функции должен учитывать результаты работы предыдущих. Например, так можно реализовать конечный автомат.
Для сохранения состояния придётся делать одно из трёх. Либо нам придётся хранить состояние в глобальных переменных (а это всегда методически плохо), либо каждый раз его возвращать из функции, чтобы получить при следующем вызове (потеря времени), либо вот это.
Как известно, данные программа размещает в трёх местах. Во-первых, это стек. Там хранятся все локальные переменные. Во-вторых, это так называемая "область данных". Некая область, куда при старте программы складываются все глобальные переменные. Туда же попадают, к примеру, строковые константы. В примере выше строка "n=%d\n" будет храниться в области данных. Третье место -- это динамическая память. То, что получается через malloc/new. Эта память выделяется на ходу и не имеет отношения к двум предыдущим.
Ясное дело, что статическая переменная не может располагаться в динамической памяти, т.к. мы не вызывали malloc. На стеке ей тоже не место, т.к. содержимое стека постоянно гуляет. После завершения функции все данные этой функции заменяются новыми, которые туда записывают другие функции (именно поэтому значения не сохраняются). Да, статические локальные переменные хранятся в области данных. Там же, где глобальные переменные. Ими они, по сути, и являются. Просто видны исключительно внутри конкретной функции.
1.2 Статическая глобальная переменная
Это вообще отдельная песня. Если глобальная переменная об'явлена как статическая, она видна только в текущем c-файле (модуле; дальше для краткости я буду писать именно "модуль", а не "единица трансляции" и не "c-файл").
Пример.
file1.c:
static int i;//1
file2.c:
int i;//2
file3.c:
extern int i;
К глобальным переменным нельзя просто так получить доступ из других модулей. Надо в этих других модулях об'явить переменную как extern. Тогда при сборке компоновщик (linker) будет искать переменную с таким именем в других модулях. Однако если переменная статическая, компоновщик к ней не привяжется, а будет искать другую. В данном случае в file3.c будет использоваться переменная, у которой в комментарии указано "2". (Переменные, обозначенные "1" и "2" -- разные.)
Зачем. Чтобы у вас не возникло конфликта с каким-нибудь ушлёпком, который в соседнем модуле сделал глобальную переменную с таким же именем.
1.3 Статическая (глобальная) функция
А неглобальных функций в Си и нет. Тут то же, что и глобальная переменная, но есть особенность.
По-умолчанию, все функции автоматически видны из других модулей. Если в модуле отсутствует функция, при сборке автоматически проверяются все остальные модули. Если же в текущем модуле нету необходимой переменной, программа соберётся только если в модуле, где переменной нет, вместо переменной присутствует указание extern (как в примере выше). Обращаю внимание, что об'явление переменной как extern -- "ненастоящее". Оно не резервирует память. Оно просто указывает, что такая переменная есть где-то ещё.
Это несколько влияет на те случаи, когда функцию надо об'являть статической.
Так или иначе, статическая функция не сможет быть вызвана из других модулей, кроме текущего. Либо будет вызвана одноимённая ещё из какого-нибудь модуля, либо программа не соберётся вообще.
2 C++
То, что работало в Си, точно так же работает и в Си++, но тут на это ключевое слово навесили ещё кое-что.
В качестве предупреждения о разнице между Си и Си++ указываю на то, что лично для меня оказалось неожиданностью: локальная статическая переменная метода класса существует в единственном экземпляре на все экземпляры класса.
2.1 Статическое поле класса
Статическое поле (переменная-член) класса существует в единственном экземпляре на все экземпляры класса. И хранится оно, как вы уже догадываетесь, в области глобальных переменных.
Пример.
struct A { static int i; int a; A(){a=0;} };
int A::i=5;//*
int main(void) { A a,b; a.a=7; a.i=8;
printf("b.a=%d\n",b.a,"b.i=%d\n",b.i); }
Мы увидим: 0 8
Хотя 8 мы записывали только в об'ект a!
Обратите внимание на строчку, помеченную звёздочкой. Дело в том, что об'явление статического поля класса не производит выделения памяти под него в области данных. На самом деле это странно, но вот так. Поэтому надо выбрать модуль, в котором реально будет храниться это поле, и сделать там его настоящее определение так, как это указано выше (при этом об'являть как extern в других модулях поле не надо!). Там же можно его инициализировать (и это единственный способ). В конструкторах "инициализировать" статические поля не советую, т.к. при создании каждого об'екта значение поля будет перезаписываться.
Также можно получать доступ к статическому полю иным способом:
A::i=9;
При этом существование хотя бы одного экземпляра класса необязательно.
Я пишу про классы, но почему-то в примере у меня структура. Почему я так сделал -- предлагаю разобрать самостоятельно. Вместо этого я укажу на совершенно неожиданное свойство, касающееся об'единений (union). Оказывается, поля об'единения не могут быть статическими, кроме одного очень особого случая. Если об'единение у вас анонимное и глобальное, то все его поля должны быть явно об'явлены как static. Пруф.
Зачем. Я могу придумать несколько применений: 1. Общие данные класса. Например, счётчик экземпляров. Можно в каждом конструкторе увеличивать поле на 1, тогда его значение будет показывать число созданных экземпляров. Для корректной работы требуется создание отдельного конструктора копий, иначе может возникнуть казус. 2. Общие ресурсы класса. Если все экземпляры класса работают с каким-либо оборудованием, то через статические поля можно реализовать работу с мьютексом (взаимоисключением). 3. Данные, предназначенные специально для работы со статическими методами (см. ниже).
Статическое поле класса по сути является глобальной переменной, но об этом знает только класс, полем которого оно является.
2.2 Статический метод класса
Чем на низком уровне отличается метод класса от простой функции? Наличием скрытого параметра. Вы никогда не задумывались о том, как метод класса определяет, у какого экземпляра его вызвали? Может быть, на каждый экземпляр создаётся отдельная функция, в которой прибиты адреса полей к полям конкретного экземпляра класса?
Нет.
Метод класса получает ещё один, невидимый параметр. И это указатель this. Все обращения к полям внутри метода осуществляются через него. Мы пишем:
void A::f(void) { a=3; } //... A a; a.f();
А на самом деле это (я по ассемблеру проверил):
void f(A *this) { this->a=3; } //... A a; f(&a);
(естественно в жизни это не заработает, т.к. компилятор не разрешит использовать this как имя переменной; для проверки я использовал имя _this)
Наличие скрытого параметра накладывает ряд ограничений на метод класса. Например, некоторые функции стандартной библиотеки, WinAPI и т.п. от нас хотят получить в качестве аргумента указатель на функцию (например, функции qsort, CreateThread). Однако даже при совпадении прототипа мы не можем передать указатель на метод класса, т.к. на самом-то деле прототип не совпадает! Есть только видимость совпадения. И как бы мы прототип не меняли, мы не сможем избавиться от скрытого параметра.
Если не об'явим метод статическим.
Статический метод не получает указателя this. Таким образом, он может обращаться напрямую только к статическим полям класса. Чтобы получить доступ к остальным, ему надо как-то (например, через параметры) получить указатель на какой-нибудь экземпляр класса.
Конструктор и деструктор статическими быть не могут (в C# конструктор статическим быть может, см. далее).
Пример. CreateThread -- отличный пример.
struct A { int i; static DWORD ThreadFunc(LPVOID _this) { for( ; ; ) { ((A*)_this)->i++; Sleep(1); } } }; //... A a,b,c; CreateThread(NULL,0,ThreadFunc,(void*)&a,0,NULL); CreateThread(NULL,0,ThreadFunc,(void*)&b,0,NULL); CreateThread(NULL,0,ThreadFunc,(void*)&c,0,NULL);
CreateThread создаёт новый поток программы, который выполняется одновременно с main. В качестве третьего параметра функция хочет получить указатель на функцию со следующим прототипом:
DWORD ThreadFunc(LPVOID *p);
Возвращаемое значение нужно как результат работы функции. А указатель в качестве параметра (LPVOID это то же, что и void*) позволяет функции потока понять, с какими данными работать.
Четвёртый параметр CreateThread является тем самым указателем, который потом передаётся функции потока. (остальные параметры в данном случае значения не имеют)
Таким образом, статическая функция вызывается трижды и каждый раз при вызове получает указатель на свой об'ект класса A. В данном случае эта функция ничего особенного не делает, просто увеличивает значение поля класса. В приведённом выше примере значения полей каждого из трёх экземпляров будут расти синхронно.
Зачем. 1. Пример выше: мы хотим передать указатель на метод класса как аргумент другой функции. 2. Метод не зависит от данных класса. Типичный пример этого -- математические библиотеки. Создаётся класс без полей, но с кучей статических методов, которые делают сложные расчёты. Экземпляра класса может даже не быть, а методы могут вызываться через имя_класса::метод(). Преимущество тут в том, что нам не надо создавать отдельный экземпляр класса при вызове. И не надо думать, имеется ли сейчас в области видимости хотя бы один. Хотя я считаю, что для этих целей лучше подходят пространства имён (namespace). 3. Метод требует статических данных подобных статической локальной переменной, однако необходимо, чтобы экземпляры класса имели к этим данным доступ. Это как раз тот случай, о котором я писал в п. 2.1, когда статические поля класса создаются по нужде статического метода.
3 С# и Java
Поскольку я не знаю этих языков, в тексте ниже могут быть неточности. Информация ниже почёрпнута из открытых источников. Буду благодарен за исправления и дополнения.
3.1 Java: статический вложенный класс
В Яве нету:
глобальных переменных (а значит, и их статичности);
глобальных функций (а значит, и их статичности);
статических локальных переменных.
Однако статические методы и поля классов работают точно так же.
Появляется одна новая фишка -- статический вложенный класс. (подробности тут)
Оказывается, чтобы создать экземпляр вложенного класса, сначала надо создать экземпляр внешнего класса:
public class A { public class B { } }
A a= new A(); B b = a.new B();
Однако если вложенный класс статический, то можно делать так:
public class A { public static class B { } }
B b = new B();
3.2 C#: статический класс и статический конструктор
Глобальных переменных и функций тоже нет. Статические локальные переменные поддерживаются. Статические поля и методы классов тоже.
Тут новая фишка называется почти так же, а значит совсем другое. Тут просто "статический класс".
public static class A { }
Статический класс -- это класс, все методы и поля которого должны быть статическими. При этом нельзя создать ни одного экземпляра данного класса. По-видимому это костыль, заменяющий глобальные переменные.
Кроме того, поддерживается статический конструктор (не поддерживаемый в Яве и Си++), предназначенный для инициализации статических полей. Указано, что он вызывается в промежутке между стартом программы и созданием первого экземпляра класса. По-видимому, использовать статические поля без хотя бы одного экземпляра нельзя, иначе когда будет вызываться конструктор?
4 PHP: позднее статическое связывание
Статически локальные переменные работают в PHP примерно так же. Статические поля класса и методы тоже (но статическое поле нельзя указать через стрелку, только через два двоеточия). Но всё же слово static явно мёдом намазано, поэтому в PHP на нём висит ещё одно совершенно особенное действие: static, подобно self, раскрывается как имя класса. но не того класса, где слово static написано (как это происходит с self), а того, в котором реально происходит вызов. Это называется позднее статическое связывание (late static binding, подробнее об этом тут).
class a { static protected $test="class a"; public function static_test() { echo static::$test."\n"; // Results class b echo self::$test."\n"; // Results class a }
}
class b extends a { static protected $test="class b"; }
Я уже встречался с чужими механическими фейлами при проектировании электроники.
И вот ещё один.
Изготовитель знал, в какой корпус мы будем монтировать их платы. И даже получил образец корпуса во временное пользование.
Все крепёжные отверстия в плате оказались сделаны очень точно: отлично влезла внутрь корпуса и надёжно закрепилась.
Однако.
На плате ещё были раз'ёмы, к которым мы, вообще-то, собирались подключаться. И вот эти раз'ёмы оказались загорожены конструкцией корпуса. Таким образом, доступ к ним снаружи отсутствует. При этом расстояние от плоскости раз'ёма до стенки корпуса оказалось около 5 мм. Поэтому подключить туда кабель и вывести его в другом месте корпуса не представляется возможным. Ответная часть раз'ёма в эту щель тупо не влезает.
Оправдываться, когда тебя не спрашивают -- плохо. Долгое время я думал, что это не так. Но сейчас моё мнение иное.
Короткие оправдания -- ещё ладно. Но длинные -- однозначное зло. (к случаям, когда у вас интересуются, почему вы так себя ведёте, оправдания не относятся)
Мнение моё изменилось во многом благодаря одному случаю, когда оправдываться стали передо мной.
Однажды я заказал себе книжку через сайт типа интернет-аукциона. Точнее, нажал кнопку "купить". После этого со мной должен был выйти на связь посредник, у которого она была. Однако он не выходил на связь неделю. Мне не горело, поэтому я его не подпихивал. Но был уже готов это сделать. И тут он мне звонит. И начинается треш.
Он начинает мне сходу об'яснять, почему до сих пор со мной не связался. Оказывается у него склад книг переезжает. И он её засунул в какой-то ящик, а в какой -- он не помнит. Подробно мне рассказал про процесс переезда. Пожаловался на жизнь. На рабочих. Излил душу, можно сказать.
А я стою и думаю... эм... зачем мне всё это нужно знать? Мне неинтересно. Мне плевать. Меня бы полностью устроило, если бы он вообще мне не сказал о причинах. Задержка мне некритична, и претензий у меня не было изначально.
Слушать эту историю мне было просто неприятно. Но в конце произошло чудесное преображение.
Он сказал: "Раз я задержал книжку, вам скидка 100 рублей".
Преображение произошло у меня в сознании. А точнее -- в эмоциях. Моё неприятие как рукой сняло. Я даже немножко положительно стал к нему относиться.
Из этого я сделал вывод, что вместо оправданий лучше предложить компенсацию.
Вот что мне рассказали (и разрешили пересказывать).
Одна учительница английского языка учила с младшеклассниками новые слова. И одно из слов было -- duck. Спрашивает на следующем занятии, как будет "утка" -- никто не помнит.
Учительница: Я вам подскажу. Я начну, а вы продолжайте. Дональд... Дети: ТРАМП!
Текст ниже изначально предназначался для двача, где и был мной опубликован. Орфография и пунктуация сохранены.
(18+) Вот тут некоторые недовольны сюжетом, говорят, что он туп, либо бессвязен, нелогичен.
Горите в аду.
Вы нихуя не поняли, что вам показали. РАСКРОООЙТЕ ГЛАЗААА. Сюжет этого фильма -- хрестоматийное инициатическое путешествие (мономиф Кэмпбелла ( www.youtube.com/watch?v=2174B8fVZ6g ), путешествие героя в Таро (описано у Банцхафа) -- вот это всё). При этом поезд следует, блядь, со всеми остановками. С посещением мира мёртвых. Каждый этап чётко локализуется.
Это, блядь, лучший фильм, что я видел в последние годы. Уровня Одиссеи Гомера или Ночной Земли Ходжсона (это, правда, не фильмы).
Кто разбирается в Таро, очень рекомендую растащить фильм по арканам. Получите огромное удовольствие.
[далее возможны спойлеры]
Твайлайт Спаркл (и её команда) проходит инициацию как принцесса дружбы не тогда, когда получает крылья. И не тогда, когда её поселяют в замке. А именно (!) во время этого фильма. И то, что она выигрывает несмотря на свой фейл -- лишь подтверждает её статус: дружеская поддержка организуется как отдалённое следствие всех её действий в прошлом. И единичный фейл не в состоянии всё перечеркнуть.
И сокровище, которое она должна обрести по схеме мономифа -- вовсе не та магическая сфера. Эта сфера -- хуйня. Настоящее сокровище -- вот эта вот поддержка. И Твайлайт обретает её по-настоящему, как Наноха.
Вы помните, как в первых сериях первого сезона Тавайлайт говорила, что рада, что нашла друзей? Меня очень коробило это место. Что-то быстро они у неё друзьями стали. Да, тогда они тоже прошли путешествие, подобное этому. Но уровень его был гораздо ниже (и уровень исполнения авторами, надо сказать, тоже). То был первый, самый маленький виток спирали развития.
А этот фильм -- гигантская веха.
Следующие две добавки не относятся к тексту выше.
(добавка, без спойлеров) Добавка, без спойлеров: В фильме много фансервиса для тех, кто кое-что знает о сеттинге.
Песни злодеев великолепны и не бесят.
Про Таро: Сестра: А когда они идут по пустыне -- это Колесница! Я: Перевёрнутая! Сестра (возмущённо): Ну уж какая есть!
(добавка, со спойлерами) Добавка, со спойлерами: Я надеялся, что Буре рог вернут. И для этого был отличный момент, когда её только оживили. Однако ни она про это не попросила, ни Твайлайт ей этого не предложила. Странно. Видимо, это действительно политкорректная тема инвалидности.
Также я надеялся, что после событий остальные принцессы придут к выводу, что жмотить свою магию не следует. Но про это ничего не сказали.
Кот -- типичный Локи.
Любопытно, что фильм поощряет пиратство. Интересно, является ли это типа "пасхальным яйцом"?
Также любопытно, что авторы фильма знают, как их фильм выглядит со стороны. Их самоирония проявляется в реплике Спайка, когда пони, курицы, кот и гиппогриф об'единяются. Он говорит: -- Я так... на всякий случай... мы больше ни с кем не подружились?..
Я хранил массивы данных разных типов. Но для передачи их из микроконтроллера мне показалось логичным их все представлять как один тип. uint32_t (беззнаковый, 32-битный). Естественно, я просто записывал знаковые числа по нужному адресу, на который указывал беззнаковый указатель. В компьютере я всё проделывал наоборот и получал своё изначальное число.
Всё было хорошо, пока я не стал вводить усреднение: я получаю с датчика несколько чисел, складываю их, а потом делю на количество. Получаю вместо 10 чисел -- одно. И отправляю в компьютер только его.
Так вот, когда среднее должно было равняться примерно нулю, я получал в массиве данных непонятный выброс -- всё время разной величины. В остальных случаях усреднение работало правильно.
Датчики возвращали только 18 бит в дополнительном коде (потому что датчики 18-разрядные). Старшие биты 32-разрядных чисел были забиты нулями.
Почему дополнительный код для отрицательных чисел так часто используется? У него есть фишка: сложение и вычитание знаковых и беззнаковых чисел происходит одинаковым образом. Поэтому храня и даже складывая знаковые числа я ошибки не совершал. А ошибка была при делении. Делить знаковые числа как беззнаковые нельзя.
Что же происходило?
Пусть есть два числа и мы хотим посчитать среднее. Рассмотрим три случая.
1. Оба числа положительные Допустим, это числа 16 (0x00000010) и 18 (0x00000012). При сложении (в 32-разрядной сетке) мы получим число 0x00000022. И при делении 0x00000011. Это 17. Всё правильно.
2. Оба числа отрицательные Пусть теперь оба числа будут отрицательными, 18-разрядными в дополнительном коде, расширенные слева нулями до 32-бит. -16 и -18.
В шестндацатеричном виде это будет 0x0003FFEA и 0x0003FFE8. При сложении это даёт 0x0007FFD2. При делении пополам как беззнакового это даёт 0x0003FFE9. Если взять младшие 18 разрядов и рассмотреть их как знаковое число в дополнительном коде, мы получим как раз -17 (подробный разбор преобразований я не привожу). Пока всё правильно.
3. Одно положительное, другое отрицательное Когда же результат должен быть около нуля, то часть чисел при усреднении могут быть положительными, а часть отрицательными. И именно этот-то случай и вызывал ошибку. В качестве супер-примера теперь будут числа 1 и -1. Очевидно, в среднем они должны давать ноль. В шестнадцатеричном виде 1 это будет 0x00000001. А -1 (по тем же правилам: дополнительный код 18 бит, расширенный нулями до 32) это будет 0x0003FFFF. Если сложить эти два числа, получается 0x00040000. Деление пополам как беззнакового даёт 0x00020000.
Вот тут я обратное преобразование из дополнительного кода распишу подробно:
В двоичном виде число выглядит так: 0b00000000 00000010 00000000 00000000
Единичный бит означает, что число отрицательное (число 18-разрядное, поэтому старшим следует рассматривать 18-й бит, если младший считать первым). Остальные биты равны нулю. И эти нули надо преобразовать в модуль отрицательного числа. Для этого надо все (младшие) биты инвертировать и прибавить единицу (это правила работы с дополнительным кодом). Результат надо трактовать как беззнаковое число. Получается:
(кстати, получилось побитово то же, что и было) В итоге модуль этого числа будет 131072, а знак отрицательный. Т.е. это -131072. А должно было быть 0, вообще-то.
В итоге я стал суммировать и делить в знаковой переменной, а только потом записывать в массив как беззнаковое. И тогда всё стало работать.