Detlef Rössler – Mykene. Burg des Agamemnon

Книга из той же серии, что упомянутая раньше Kre­ta. Insel des Minos. Идём хронологически – сначала критяне, потом завоевавшие их минойцы, а дальше будут этруски из той же серии.
Скроена по тому же принципу, что предыдущая:

  1. Как раскопали
  2. Как жили цари
  3. Как велось хозяйство
  4. Как жил народ
  5. Каким богам поклонялись
  6. Как пришли завоеватели (в случае критян – минойцы, в случае минойцев – дорийцы) и всех завоевали

Sitecore: Database returns old value

Вы исправили какие-то данные в базе Sitecore, но на странице у вас то же самое? Значит, надо проверить следующие варианты:

  1. Вы исправили в mas­ter, но забыли опубликовать это в web. Перейдите в web и провериться.
  2. Вы изменили не во всех языках. Вернитесь в mas­ter и проверьте, выбрав другой флаг. Этот шаг очень часто забывают.
  3. Вы используете дурацкую систему кэширования и она возвращает вам старые значения.

Чтобы 1 и 2 портили вам как можно меньше крови — везде, где можно, заменяйте текстовые константы на внутренние ссылки sitecore. И тогда даже если элемент куда-нибудь переедет,  ссылка будет в порядке.

UnitTest: Что такое UnitTest?

Unit в UnitTest — это unit of work. То есть a use case, вызванный pub­lic method-ом и закончившийся result-ом. А result-ом может быть:

  1. Возвращаемое значение или Excep­tion.
  2. Заметные изменения в системе. Заметные - значит, система после них работает по-другому. Например, добавление пользователя — это заметное изменение, потому что теперь под ним можно заходить.
  3. Вызов внешней системы, которую мы не можем контролировать во время теста. Например, файловая система, сеть, user threads, или любая другая зависимость, которую мы не можем контролировать и которая выполняется медленно.

Для 3-его типа нужно использовать mock-объекты. Для 1–2 — порвать все зависимости и проверять возвращаемое значение или состояние системы.

Вроде бы просто. Тем не менее, я понял, что отчего-то был уверен, что UnitTest-у и случая 1 достаточно. Хотя уже созданы обёртки для эмуляции файловой системы. Или вот эксперименты над Python

Subversion: How to use SVN with Google code

Как использовать SVN в Google Code? Вроде бы всё очень просто, но всё равно постоянно забываешь. Поэтому переведём замечательный мануал по настройке.

Более поздняя версия статьи публиковалась на Stand­alone автора. Stand­alone давно умер, а блог на word­press жив до сих пор

Помечаю в основном для себя, так что картинок не будет.

Если нужно просто утащить последний release чужого проекта, а пароля вы не знаете — достаточно выполнить пункты 1–4, а потом регулярно делать Update. Google Code даёт read-only доступ всем желающим.

  1. Скачиваем последний Tor­tois­eSVN.
  2. Устанавливаем его и перезагружаемся.
  3. Создаём папку, щёлкаем по ней правой кнопкой, жмём SVN Check­out.
  4. URL of repos­i­to­ry = https://[ProjectName].googlecode.com/svn/trunk, где [Pro­ject­Name] — имя нужного проекта. Если вы его забыли, посмотрите URL его профиля на Google Code — он будет иметь вид http://code.google.com/p/[ProjectName]/.
  5. Идём в профиль нашего Google Code Host­ing и смотрим там пароль.
  6. Потом, когда будем делать Com­mit, у нас спросят имя и пароль. Вводим то, что нам показали на шаге 5.

SVN ещё долго не умрёт — ведь он прост, как грабли.

Script: Play mp3 at background with JavaScript

Как сделать фоновую мелодию для веб-страницы из mp3-файла?

Для начала — убедиться, что она нужна. Я, например, считаю, что единственное место во всём Вебе, где уместны фоновые мелодии — это игры. Пожалуйста, ставьте такие скрипты только в них.

Так как стандарт очень долго хранил молчание насчёт фоновых мелодий, каждый браузер реализовывал его по-своему

Путаница тут страшная. <embed>, который часто советуют, например, требует от Fire­fox подгружать плагин. <audio> толком не поддерживается даже в IE. Да и вообще, ещё 2 года назад разные браузеры поддерживали разные форматы и табличка выглядела приблизительно так:

Brows­er Ogg MP3 WAV
Fire­Fox 3.6+
Safari 5+
Chrome 6
Opera 10.5+
Inter­net Explor­er 9 (beta)

Так что используйте JPlay­er. Но иногда и он обваливается с ошибкой, что b.test — не является функцией :(.
Мне jPlay­er не помог. Пришлось родить кроссплатформенное решение:

<bgsound src="sound/plan.mp3" loop="1">
<object id="opera_player1" data="sound/plan.mp3" type="application/x-mplayer2" width="0" height="0">
 <param name="filename" value="sound/plan.mp3">
 <param name="autostart" value="1">
 <param name="autoplay" value="1">
 <param name="hidden" value="1">
 <param name="playcount" value="9999">
</object>
<audio src="sound/plan.mp3" autoplay="autoplay" loop="loop">
<object id="webkit_player" data="sound/plan.mp3" type="application/x-mplayer2" width="0" height="0">
 <param name="filename" value="sound/plan.mp3">
 <param name="autostart" value="1">
 <param name="autoplay" value="1">
 <param name="hidden" value="1">>
</object>
</audio>

В IE я это, впрочем, пока не тестировал.

Первый блок — исключительно для Opera. Во втором не забываем loop=“loop” — Chrome игнорирует Play­count.

Важно помнить, что object в Fire­fox не понимает loop. Так что просто ставьте большой play­count. А вот webkit-браузеры понимают его слишком хорошо и будут играть мелодию, даже когда вы покините сайт. Поэтому не забудьте убрать param loop во втором блоке.

И никогда не пытайтесь сгенерировать этот код через JavaScript. Такая реализация страшно тормозит даже на локальном компьютере.

А ещё не забывайте, что браузеры — умные создания и если поместить эти object’ы в скрытый блок (не важно, через, dis­play: none; или vis­i­bil­i­ty: hid­den), Fire­fox их проигрывать не будет.

Причём мы говорим, разумеется, о desk­top-ных браузерах. Про мобильные даже вспоминать страшно.

C++: Счастливый билет с длинной арифметикой

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

Сколько таких билетов всего? Какова вероятность встретить счастливый?

Алгоритм для этих вычислений в Википедии настолько ужасен, что народ с Хабра довольно быстро породил в комментариях огромное количество вариантов на C++, Perl и… SQL.

Я тоже не смог пройти мимо и написал считалку на C++ с арифметикой указателей и поддержкой длинной арифметики. При желании она может считать хоть 12-значные числа.

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

void inline count_lucky(unsigned int num_length_val)
{
  bool is_odd = (num_length_val % 2) > 0;
  unsigned int num_length = (is_odd) ? num_length_val - 1 : num_length_val;
  register unsigned int lucky=1, total=pow(10.0,(int)num_length), i;
  char *num = new char[num_length], *end=num+(num_length-1);
  register char *pos=end;
  for(i=0; i < num_length; i++)
    num[i]=0;
  while(pos>=num)
  {
     if((*pos)<9)
     {
        (*pos)++;
        if(pos==end)
        {
           if(is_lucky((unsigned char*)num, num_length))
             lucky++;
        }
        else
          pos++;
     }
     else
     {
       *pos=-1;
       pos--;
     }
  }
  printf("Lucky are %d of %d (%.3f%%)n",(is_odd) ? lucky * 10 : lucky, (is_odd) ? total * 10 : total,((float)lucky/total*100));
  delete[] num;
}
bool inline is_lucky(unsigned char* items, unsigned int items_count)
{
  unsigned char val1=0, val2=0;
  unsigned int half = items_count >> 1;
  for(unsigned int i=0; i < half; i++)
  {
    val1 += items[i];
    val2 += items[items_count-1-i];
  }
  return (val1==val2);
}

Увы! Как показывает практика, уже на 7-значном билете тупой перебор, развёрнутый и оптимизированный компилятором, оказывается эффективней. Похоже, компилятор попросту выполняет сам большую часть явно заданных вычислений.
В этом легко убедиться, запустив тест хотя бы для 7 разрядов:

void inline count_lucky(unsigned int num_length);
bool inline is_lucky(unsigned char* items, unsigned int items_count);
int _tmain(int argc, _TCHAR* argv[])
{
  clock_t start = clock(), mine;
  count_lucky(7);
  mine=clock();
  printf("Mine time was: %dn", (mine - start));
  count_lucky_fromwiki();
  printf("His time was: %dn", (clock() - mine));
  return 0;
}

void count_lucky_fromwiki()
{
  int total=0,lucky=0;
  for(int i1=0; i1<10; i1++)
    for(int i2=0; i2<10; i2++)
      for(int i3=0; i3<10; i3++)
        for(int i4=0; i4<10; i4++)
          for(int i5=0; i5<10; i5++)
            for(int i6=0; i6<10; i6++)
              for(int i7=0; i7<10; i7++, total++)
                if(i1+i2+i3 == i5+i6+i7)
                  lucky++;
   printf("Lucky are %d of %d (%.3f%%)n",lucky,total,((float)lucky/total*100));
}

Человек уже не может обогнать машину :(. Слава роботам!

В качестве утешения — на 8 вложенный циклах валился компилятор из Bor­land C++ Builder 6.

Reinhard Witte – Kreta. Insel des Minos

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

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

Интересно, что гомеровские цитаты я понимал легче, чем весь остальной текст.