<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>хабрахабр:все записи</title>
    <link>http://habrahabr.ru/rss/new/</link>
    <atom:link href="http://rss-farm.ru/rssfarmru/habrahabr-all" rel="self" type="application/rss+xml" />
    <description></description>
    <pubDate>Sun, 05 Feb 2012 22:15:31 GMT</pubDate>
    <lastBuildDate>Sun, 05 Feb 2012 22:15:31 GMT</lastBuildDate>
    <dc:creator>rssfarmru</dc:creator>
    <item>
      <title>JAVA / Тестирование в Java. Spock Framework</title>
      <link>http://habrahabr.ru/blogs/java/137561/</link>
      <pubDate>Sun, 05 Feb 2012 21:52:33 GMT</pubDate>
      <description>
  	&lt;img align="left" src="http://habrastorage.org/storage2/9a8/94f/3cc/9a894f3cc2204d959c37766c57cbd806.png"&gt;&lt;br&gt;
В предыдущих статьях на примерах &lt;a href="http://habrahabr.ru/blogs/java/120101/"&gt;JUnit&lt;/a&gt; и &lt;a href="http://habrahabr.ru/blogs/java/121234/"&gt;TestNG&lt;/a&gt; я упоминал о &lt;a href="http://ru.wikipedia.org/wiki/Разработка_через_тестирование"&gt;test-driven development(TDD)&lt;/a&gt; и &lt;a href="http://en.wikipedia.org/wiki/Data-driven_testing"&gt;data-driven testing(DDT)&lt;/a&gt;. Но есть еще один активно набирающий популярность подход, &lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;behaviour-driven development(BDD)&lt;/a&gt;. Это такое развитие TDD техники, при котором на тест смотрят не как на тестирование каких-то компонентов системы, а как на требования к функционалу. Если TDD оперирует такими понятиями, как тест или метод, то для BDD это спецификация и требования. Про эту технику уже говорили на хабре ранее: &lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://habrahabr.ru/blogs/tdd/107262/"&gt;Эволюция юнит-теста&lt;/a&gt;, &lt;/li&gt;
&lt;li&gt;&lt;a href="http://habrahabr.ru/blogs/testing/52929/"&gt;Экстремальное программирование, знакомство с Behavior Driven Development и RSpec&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
Этот подход применим используя и JUnit, и TestNG. Но есть и другие инструменты заточенные именно под BDD. В этой статье я расскажу про такой фреймворк. Называется он &lt;a href="http://code.google.com/p/spock/"&gt;Spock Framework&lt;/a&gt; и сочетает в себе не только принципы BDD, но и достоинства &lt;a href="http://groovy.codehaus.org/"&gt;Groovy&lt;/a&gt;. Да-да, именно Groovy. И хотя используется Groovy, используется он и для тестирования Java кода. Примерами использования могут служить Spring, Grails, Tapestry5. Интересно? Тогда читаем дальше.&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Behaviour-driven development&lt;/h2&gt;&lt;br&gt;
Итак, напомню что же это такое. Рассмотрим пример. Есть утилита, работающая с ant шаблонами(это те, что для выборки файлов).? — любой 1 и только 1 символ, * — любое количество любых символов, ** — любой путь. Выглядит как-то так:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="java"&gt;public abstract class PathUtils {

  public static boolean matchAntPath(final String path, final String pattern) {
    // ...
  }

  public static boolean matchAntPattern(final String path, final String pattern) {
    // ...
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Оба метода проверяют соответствует ли переданная строка шаблону или нет, но метод &lt;i&gt;matchAntPattern&lt;/i&gt; учитывает только локальный паттерн без учета пути, &lt;i&gt;matchAntPath&lt;/i&gt; учитывает полный путь. Следуя принципам TDD будет создан тест на каждый метод с некоторым набором входных данных и некоторым набором ожидаемых результатов.&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="java"&gt;public class TestPathUtils extends Assert {

  @Test(dataProvider = &amp;quot;matchAntPatternData&amp;quot;)
  public void testMatchAntPattern(final String pattern, final String text, final boolean expected) {
    final boolean actual = PathUtils.matchAntPattern(text, pattern);
    assertEquals(actual, expected);
  }

  @Test(dataProvider = &amp;quot;matchAntPathData&amp;quot;)
  public void testMatchAntPath(final String pattern, final String path, final boolean expected) {
    final boolean actual = PathUtils.matchAntPath(path, pattern);
    assertEquals(actual, expected);
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Возможно сюда еще добавятся тесты на неправильные параметры, когда должны выбрасываться исключения. Теперь давайте посмотрим на это с точки зрения BDD.&lt;br&gt;
Тест есть не просто тест, а спецификация, и состоит не из методов, а из требований. Выделим требования к &lt;i&gt;PathUtils&lt;/i&gt;:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;Символ? в шаблоне должен быть эквивалентен любому символу в проверяемой строке&lt;/li&gt;
&lt;li&gt;Символ? в шаблоне должен быть эквивалентен 1 и только 1 символу в проверяемой строке&lt;/li&gt;
&lt;li&gt;Символ * в шаблоне должен быть эквивалентен любому символу в проверяемой строке&lt;/li&gt;
&lt;li&gt;Символ * в шаблоне должен быть эквивалентен любому количеству символов в проверяемой строке&lt;/li&gt;
&lt;li&gt;Значения шаблона и проверяемой строки не должны быть null&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
Далее, каждое требование имеет свой сценарий проверки, обычно для этого используют термины дано-когда-то(given-when-then). Дано — установки для начала сценария, когда — причина, то — условие выполнения сценария. Например:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code&gt;Given:
PathUtils
---
When:
matchAntPattern(null, &amp;quot;some string&amp;quot;)
---
Then:
NullPointerException should be thrown
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Таким образом тест будет выглядеть примерно так:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="java"&gt;public class PathUtilsSpec extends Assert {

  @Test
  public void question_character_should_mean_any_character() {
    assertTrue(PathUtils.matchAntPattern(&amp;quot;abb&amp;quot;, &amp;quot;a?b&amp;quot;));
    assertTrue(PathUtils.matchAntPattern(&amp;quot;a1b&amp;quot;, &amp;quot;a?b&amp;quot;));
    assertTrue(PathUtils.matchAntPattern(&amp;quot;a@b&amp;quot;, &amp;quot;a?b&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;abb&amp;quot;, &amp;quot;a?b&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;a1b&amp;quot;, &amp;quot;a?b&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;a@b&amp;quot;, &amp;quot;a?b&amp;quot;));
    // ...
  }

  @Test
  public void question_character_should_mean_only_one_character() {
    assertFalse(PathUtils.matchAntPattern(&amp;quot;ab&amp;quot;, &amp;quot;a?b&amp;quot;));
    assertFalse(PathUtils.matchAntPattern(&amp;quot;aabb&amp;quot;, &amp;quot;a?b&amp;quot;));
    assertFalse(PathUtils.matchAntPath(&amp;quot;ab&amp;quot;, &amp;quot;a?b&amp;quot;));
    assertFalse(PathUtils.matchAntPath(&amp;quot;aabb&amp;quot;, &amp;quot;a?b&amp;quot;));
    // ...
  }

  @Test
  public void asterisk_character_should_mean_any_character() {
    assertTrue(PathUtils.matchAntPattern(&amp;quot;abb&amp;quot;, &amp;quot;a*b&amp;quot;));
    assertTrue(PathUtils.matchAntPattern(&amp;quot;a1b&amp;quot;, &amp;quot;a*b&amp;quot;));
    assertTrue(PathUtils.matchAntPattern(&amp;quot;a@b&amp;quot;, &amp;quot;a*b&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;abb&amp;quot;, &amp;quot;a*b&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;a1b&amp;quot;, &amp;quot;a*b&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;a@b&amp;quot;, &amp;quot;a*b&amp;quot;));
    // ...
  }

  @Test
  public void asterisk_character_should_mean_any_number_of_characters() {
    assertTrue(PathUtils.matchAntPattern(&amp;quot;ab&amp;quot;, &amp;quot;a*b&amp;quot;));
    assertTrue(PathUtils.matchAntPattern(&amp;quot;aabb&amp;quot;, &amp;quot;a*b&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;ab&amp;quot;, &amp;quot;a*b&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;aabb&amp;quot;, &amp;quot;a*b&amp;quot;));
    // ...
  }

  @Test
  public void double_asterisk_character_should_mean_any_path() {
    assertTrue(PathUtils.matchAntPath(&amp;quot;aaa/bbb&amp;quot;, &amp;quot;aaa/**/bbb&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;aaa/ccc/bbb&amp;quot;, &amp;quot;aaa/**/bbb&amp;quot;));
    assertTrue(PathUtils.matchAntPath(&amp;quot;aaa/c/c/c/bbb&amp;quot;, &amp;quot;aaa/**/bbb&amp;quot;));
    // ...
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Теперь подробнее о Spock Framework.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Основные возможности&lt;/h2&gt;&lt;br&gt;
Как я уже говорил, сценарии пишутся на Groovy. Хорошо это или плохо? Решайте сами, новички могут почитать &lt;a href="http://habrahabr.ru/blogs/java/122127/"&gt;Groovy за 15 минут – краткий обзор&lt;/a&gt;. &lt;br&gt;
&lt;br&gt;
Спецификация должна быть унаследована от &lt;i&gt;spock.lang.Specification&lt;/i&gt;. Она может содержать поля, установочные методы(fixture methods), сценарии требований(feature methods), вспомогательные методы(helper methods).&lt;br&gt;
&lt;br&gt;
Поля по умолчанию не шарятся между сценариями, т.е. изменения поля из одного сценария не будут видны из другого сценария. Чтобы расшарить можно зааннотировать с помощью &lt;i&gt;@Shared&lt;/i&gt;.&lt;br&gt;
&lt;br&gt;
Установочные методы это:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;setup()&lt;/i&gt; — аналог &lt;i&gt;@Before&lt;/i&gt; в JUnit, выполняется перед каждым сценарием&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cleanup()&lt;/i&gt; — аналог &lt;i&gt;@After&lt;/i&gt; в JUnit, выполняется после каждого сценария&lt;/li&gt;
&lt;li&gt;&lt;i&gt;setupSpec()&lt;/i&gt; — аналог &lt;i&gt;@BeforeClass&lt;/i&gt; в JUnit, выполняется до первого сценария в спецификации&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cleanupSpec()&lt;/i&gt; — аналог &lt;i&gt;@AfterClass&lt;/i&gt; в JUnit, выполняется после последнего сценария в спецификации&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
Как и в других тестовых фреймворках эти методы используются для того, чтобы не писать один и тот же установочный код для каждого сценария.&lt;br&gt;
&lt;br&gt;
Сценарии требований — это основная часть спецификации. Именно здесь описывается поведение компонента. Принято называть их используя строковые литералы, причем можно использовать любые символы, главное чтобы это название как можно более четко описывало, что этот сценарий делает. Например, в нашем случае:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class PathUtilsSpec extends Specification {

  def &amp;quot;? character should mean any character&amp;quot;() {
    // ...
  }

  def &amp;quot;? character should mean only one character&amp;quot;() {
    // ...
  }

  def &amp;quot;* character should mean any character&amp;quot;() {
    // ...
  }

  def &amp;quot;* character should mean any number of characters&amp;quot;() {
    // ...
  }

  def &amp;quot;** character should mean any path&amp;quot;() {
    // ...
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Каждый сценарий состоит из блоков, которые обозначаются метками:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;setup&lt;/i&gt; — то же самое что и установочный метод &lt;i&gt;setup()&lt;/i&gt;, только применяется к конкретному сценарию. Обязательно должен находится до остальных блоков и не должен повторяться. Метка &lt;i&gt;setup&lt;/i&gt; может отсутствовать, также вместо &lt;i&gt;setup&lt;/i&gt; можно писать &lt;i&gt;given&lt;/i&gt;, это сделано для лучшей читаемости(given-when-then)&lt;/li&gt;
&lt;li&gt;&lt;i&gt;cleanup&lt;/i&gt; — то же самое что и метод &lt;i&gt;cleanup()&lt;/i&gt;, только применяется к конкретному сценарию. Обязательно должен находиться в конце сценария до блока &lt;i&gt;where&lt;/i&gt;, если он есть, и не должен повторяться&lt;/li&gt;
&lt;li&gt;&lt;i&gt;when-then&lt;/i&gt; — это причина и условие выполнения. В &lt;i&gt;when&lt;/i&gt; части обычно объявляются переменные, выполняются необходимые действия, в &lt;i&gt;then&lt;/i&gt; части проверяются некоторые условия. Это могут быть проверки условий, проверка выброса исключения либо ожидания выполнения некоторых методов у мок-объектов. Данный блок может повторяться, но авторы фреймворка рекомендуют не увлекаться, хороший сценарий должен содержать от 1 до 5 таких блоков&lt;/li&gt;
&lt;li&gt;&lt;i&gt;expect&lt;/i&gt; — это упрощенный &lt;i&gt;when-then&lt;/i&gt; блок, где действие и проверка находятся в одном выражении&lt;/li&gt;
&lt;li&gt;&lt;i&gt;where&lt;/i&gt; — это аналог &lt;i&gt;@DataProvider&lt;/i&gt; из TestNG, предназначен для создания набора данных для теста&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
Теперь обо всем поподробнее. Рассмотрим еще один пример. &lt;i&gt;PathSearcher&lt;/i&gt;, предназначен для поиска файлов, использует ant-шаблоны как фильтр для файлов.&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="java"&gt;public class PathSearcher {

  public PathSearcher(final String path) {...}

  public PathSearcher include(final String... patterns) {...}

  public PathSearcher exclude(final String... patterns) {...}

  public Set&amp;lt;String&amp;gt; search() {...}
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Напишем к нему требование «должен искать файлы на файловой системе»:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class PathSearcherSpec extends Specification {

  def &amp;quot;it should search files under the file system&amp;quot;() {
    given:
    def searcher = PathSearcher.create(inClasspath(&amp;quot;test1&amp;quot;))
    when:
    def results = searcher.search();
    then:
    results.containsAll([&amp;quot;1.txt&amp;quot;, &amp;quot;2.txt&amp;quot;]);
    results.size() == 2
  }

  private String inClasspath(path) {
    return ClassLoader.getSystemResource(path).toExternalForm()
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Итак, дано — поисковик, который ищет в папке &lt;i&gt;test1&lt;/i&gt; из &lt;i&gt;classpath&lt;/i&gt;, проверяем поиск, условие выполнения — поисковик должен найти наши файлы. &lt;i&gt;inClasspath&lt;/i&gt; — вспомогательный метод, возвращающий абсолютный путь файла из &lt;i&gt;classpath&lt;/i&gt;.&lt;br&gt;
&lt;br&gt;
Еще один пример для &lt;i&gt;PathUtils&lt;/i&gt; «значения шаблона и проверяемой строки не должны быть null»&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class PathUtilsSpec extends Specification {

  def &amp;quot;null parameter values are not allowed&amp;quot;() {
    when:
    PathUtils.matchAntPattern(null, &amp;quot;some string&amp;quot;)
    then:
    thrown(NullPointerException)

    when:
    PathUtils.matchAntPattern(&amp;quot;some string&amp;quot;, null)
    then:
    thrown(NullPointerException)

    when:
    PathUtils.matchAntPath(null, &amp;quot;some string&amp;quot;)
    then:
    thrown(NullPointerException)

    when:
    PathUtils.matchAntPath(&amp;quot;some string&amp;quot;, null)
    then:
    thrown(NullPointerException)
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Здесь мы видим метод&lt;i&gt; thrown(...)&lt;/i&gt;, это ожидание указанного исключения, есть также метод &lt;i&gt;notThrown(...)&lt;/i&gt; и &lt;i&gt;noExceptionThrown()&lt;/i&gt;. Они для проверки, что заданное/никакое исключение не выбрасывается. Также в &lt;i&gt;then&lt;/i&gt; части могут присутствовать ожидания выполнения некоторых методов у мок-объектов, но о них чуть позже. Еще один пример:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class PathUtilsSpec extends Specification {

  def &amp;quot;? character should mean any character&amp;quot;() {
    expect:
    PathUtils.matchAntPattern(&amp;quot;abb&amp;quot;, &amp;quot;a?b&amp;quot;)
    PathUtils.matchAntPattern(&amp;quot;a1b&amp;quot;, &amp;quot;a?b&amp;quot;)
    PathUtils.matchAntPattern(&amp;quot;a@b&amp;quot;, &amp;quot;a?b&amp;quot;)
    PathUtils.matchAntPath(&amp;quot;abb&amp;quot;, &amp;quot;a?b&amp;quot;)
    PathUtils.matchAntPath(&amp;quot;a1b&amp;quot;, &amp;quot;a?b&amp;quot;)
    PathUtils.matchAntPath(&amp;quot;a@b&amp;quot;, &amp;quot;a?b&amp;quot;)
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Как видно из примера, если и &lt;i&gt;when&lt;/i&gt;, и &lt;i&gt;then&lt;/i&gt; части можно объединить в одно условие, то удобнее использовать блок &lt;i&gt;expect&lt;/i&gt;. Данный сценарий можно улучшить сделав его параметризируемым с помощью блока &lt;i&gt;where&lt;/i&gt;:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class PathUtilsSpec extends Specification {

  def &amp;quot;? character should mean any character&amp;quot;() {
    expect:
    PathUtils.matchAntPattern(text, pattern)
    PathUtils.matchAntPath(text, pattern)

    where:
    pattern | text
    &amp;quot;ab?&amp;quot;   | &amp;quot;abc&amp;quot;
    &amp;quot;ab?&amp;quot;   | &amp;quot;ab1&amp;quot;
    &amp;quot;ab?&amp;quot;   | &amp;quot;ab@&amp;quot;
    &amp;quot;a?b&amp;quot;   | &amp;quot;abb&amp;quot;
    &amp;quot;a?b&amp;quot;   | &amp;quot;a1b&amp;quot;
    &amp;quot;a?b&amp;quot;   | &amp;quot;a@b&amp;quot;
    &amp;quot;?ab&amp;quot;   | &amp;quot;aab&amp;quot;
    &amp;quot;?ab&amp;quot;   | &amp;quot;1ab&amp;quot;
    &amp;quot;?ab&amp;quot;   | &amp;quot;@ab&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Или так:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class PathUtilsSpec extends Specification {

  def &amp;quot;? character should mean any character&amp;quot;() {
    expect:
    PathUtils.matchAntPattern(text, pattern)
    PathUtils.matchAntPath(text, pattern)

    where:
    pattern &amp;lt;&amp;lt; [&amp;quot;ab?&amp;quot;, &amp;quot;ab?&amp;quot;, &amp;quot;ab?&amp;quot;, &amp;quot;a?b&amp;quot;, &amp;quot;a?b&amp;quot;, &amp;quot;a?b&amp;quot;, &amp;quot;?ab&amp;quot;, &amp;quot;?ab&amp;quot;, &amp;quot;?ab&amp;quot;]
    text    &amp;lt;&amp;lt; [&amp;quot;abc&amp;quot;, &amp;quot;ab1&amp;quot;, &amp;quot;ab@&amp;quot;, &amp;quot;abb&amp;quot;, &amp;quot;a1b&amp;quot;, &amp;quot;a@b&amp;quot;, &amp;quot;aab&amp;quot;, &amp;quot;1ab&amp;quot;, &amp;quot;@ab&amp;quot;]
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Или так:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class PathUtilsSpec extends Specification {

  def &amp;quot;? character should mean any character&amp;quot;() {
    expect:
    PathUtils.matchAntPattern(text, pattern)
    PathUtils.matchAntPath(text, pattern)

    where:
    [pattern, text] &amp;lt;&amp;lt; [
        [&amp;quot;ab?&amp;quot;, &amp;quot;abc&amp;quot;],
        [&amp;quot;ab?&amp;quot;, &amp;quot;ab1&amp;quot;],
        [&amp;quot;ab?&amp;quot;, &amp;quot;ab@&amp;quot;],
        [&amp;quot;a?b&amp;quot;, &amp;quot;abb&amp;quot;],
        [&amp;quot;a?b&amp;quot;, &amp;quot;a1b&amp;quot;],
        [&amp;quot;a?b&amp;quot;, &amp;quot;a@b&amp;quot;],
        [&amp;quot;?ab&amp;quot;, &amp;quot;aab&amp;quot;],
        [&amp;quot;?ab&amp;quot;, &amp;quot;1ab&amp;quot;],
        [&amp;quot;?ab&amp;quot;, &amp;quot;@ab&amp;quot;]
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Или даже так:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class PathUtilsSpec extends Specification {

  def &amp;quot;? character should mean any character&amp;quot;() {
    expect:
    PathUtils.matchAntPattern(text, pattern)
    PathUtils.matchAntPath(text, pattern)

    where:
    [pattern, text] = sql.execute(&amp;quot;select pattern, text from path_utils_test&amp;quot;)
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Думаю из примеров все и так понятно, поэтому не буду заострять на этом внимание. Отмечу только что в &lt;i&gt;where&lt;/i&gt; блоке нельзя использовать поля, не помеченные как &lt;i&gt;@Shared&lt;/i&gt;.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Взаимодействия&lt;/h2&gt;&lt;br&gt;
Помимо всего прочего, фреймворк позволяет работать с мок-объектами без дополнительных зависимостей. Можно создавать моки для интерфейсов и не final классов. Создание выглядит так:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;    def dao1 = Mock(UserDAO)
    UserDAO dao2 = Mock()
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Можно переопределять возвращаемые значения либо сами методы таких объектов. Авторы называют это взаимодействиями (interactions).&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;    dao1.findAll() &amp;gt;&amp;gt; [
        new User(name: &amp;quot;test1&amp;quot;, description: &amp;quot;Test User&amp;quot;),
        new User(name: &amp;quot;test2&amp;quot;, description: &amp;quot;Test User&amp;quot;),
        new User(name: &amp;quot;test3&amp;quot;, description: &amp;quot;Test User&amp;quot;)
    ]
    dao2.findAll() &amp;gt;&amp;gt; { throw new UnsupportedOperationException() }
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Взаимодействия бывают локальными (определенные в &lt;i&gt;then&lt;/i&gt; блоке) и глобальными(определенные в любом другом месте). Локальные доступны только в &lt;i&gt;then&lt;/i&gt; блоке, глобальные доступны везде, начиная с точки их определения. Также для локальных взаимодействий можно указать их мощность, это ожидаемое количество вызовов методов.&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class UserCacheSpec extends Specification {
  def users = [
      new User(name: &amp;quot;test1&amp;quot;, description: &amp;quot;Test User&amp;quot;),
      new User(name: &amp;quot;test2&amp;quot;, description: &amp;quot;Test User&amp;quot;),
      new User(name: &amp;quot;test3&amp;quot;, description: &amp;quot;Test User&amp;quot;)
  ]

  def &amp;quot;dao should be used only once for all user searches until invalidated&amp;quot;() {
    setup:
    def dao = Mock(UserDAO)
    def cache = new UserCacheImpl(dao)

    when:
    cache.getUser(&amp;quot;test1&amp;quot;)
    cache.getUser(&amp;quot;test2&amp;quot;)
    cache.getUser(&amp;quot;test3&amp;quot;)
    cache.getUser(&amp;quot;test4&amp;quot;)

    then:
    1 * dao.findAll() &amp;gt;&amp;gt; users
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
В этом примере мы создаем мок для &lt;i&gt;UserDAO&lt;/i&gt; и реальный объект &lt;i&gt;UserCache&lt;/i&gt; использующий этот мок(setup-блок). Затем мы ищем несколько пользователей по имени(&lt;i&gt;when&lt;/i&gt;-блок) и в завершение проверяем, чтобы &lt;i&gt;findAll&lt;/i&gt; метод, возвращающий заранее подготовленный результат, вызывался только 1 раз.&lt;br&gt;
Описывая взаимодействия можно использовать шаблоны:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;    1 * dao.findAll() &amp;gt;&amp;gt; users
    (1..4) * dao.findAll() &amp;gt;&amp;gt; users
    (2.._) * dao.findAll() &amp;gt;&amp;gt; users
    (_..4) * dao.findAll() &amp;gt;&amp;gt; users

    _.findAll() &amp;gt;&amp;gt; users
    dao./find.*/(_) &amp;gt;&amp;gt; users
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Подробнее можно почитать &lt;a href="http://code.google.com/p/spock/wiki/Interactions"&gt;здесь&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Дополнительные возможности&lt;/h2&gt;&lt;br&gt;
Как видно фреймворк и так обладает большим количеством возможностей. Но как и у других фреймворков есть возможность расширения функционала. Примерами могут служить встроенные расширения:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;@Timeout&lt;/i&gt; — задает максимальное время ожидания для сценария, аналог &lt;i&gt;timeout&lt;/i&gt; атрибута у &lt;i&gt;@Test&lt;/i&gt; из JUnit-а&lt;/li&gt;
&lt;li&gt;&lt;i&gt;@Ignore&lt;/i&gt; — отключает сценарий, аналог &lt;i&gt;@Ignore&lt;/i&gt; из JUnit&lt;/li&gt;
&lt;li&gt;&lt;i&gt;@IgnoreRest&lt;/i&gt; — отключает все сценарий кроме зааннотированного, полезно, если надо проверить только 1 тест&lt;/li&gt;
&lt;li&gt;&lt;i&gt;@FailsWith&lt;/i&gt; — задает ожидаемое исключение, аналог аттрибута &lt;i&gt;expected&lt;/i&gt; у &lt;i&gt;@Test&lt;/i&gt; из JUnit&lt;/li&gt;
&lt;li&gt;&lt;i&gt;@Unroll&lt;/i&gt; — указывает что параметризированные сценарии должны быть указаны как отдельные сценарии для каждой итерации, здесь можно также указать шаблон названия требования, по умолчанию это &lt;i&gt;&amp;quot;#featureName[#iterationCount]&amp;quot;&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class InternalExtensionsSpec extends Specification {

  @FailsWith(NumberFormatException)
  @Unroll(&amp;quot;#featureName (#data)&amp;quot;)
  def &amp;quot;integer parse method should throw exception for wrong parameters&amp;quot;() {
    Integer.parseInt(data)
    where:
    data &amp;lt;&amp;lt; [&amp;quot;Hello, World!!!&amp;quot;, &amp;quot;0x245&amp;quot;, &amp;quot;1798237199878129387197238&amp;quot;]
  }

  @Ignore
  @Timeout(3)
  def &amp;quot;temporary disabled feature&amp;quot;() {
    setup:
    sleep(20000)
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Интеграции с другими фреймворками вынесены в отдельные модули:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;Spring — спецификация аннотируется с помощью &lt;i&gt;@ContextConfiguration(locations = «application_context_xml»)&lt;/i&gt; и в поля можно внедрять зависимости с помощью &lt;i&gt;@Autowired&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;@ContextConfiguration(locations = &amp;quot;context.xml&amp;quot;)
class SpringIntegrationSpec extends Specification {

  @Autowired
  String testSymbol

  def &amp;quot;test-symbol should be spring&amp;quot;() {
    expect:
    testSymbol == &amp;quot;spring&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;Guice — спецификация аннотируется с помощью &lt;i&gt;@UseModules(guice_module_class)&lt;/i&gt; и в поля можно внедрять зависимости с помощью &lt;i&gt;@Inject&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;public class GuiceModule extends AbstractModule {

  @Override
  protected void configure() {
    bind(String.class).annotatedWith(Names.named(&amp;quot;test-symbol&amp;quot;)).toInstance(&amp;quot;guice&amp;quot;);
  }
}

@UseModules(GuiceModule)
class GuiceIntegrationSpec extends Specification {

  @Inject
  @Named(&amp;quot;test-symbol&amp;quot;)
  String testSymbol

  def &amp;quot;test-symbol should be guice&amp;quot;() {
    expect:
    testSymbol == &amp;quot;guice&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;Tapestry — спецификация аннотируется с помощью &lt;i&gt;@SubModule(tapestry_module_class)&lt;/i&gt; и в поля можно внедрять зависимости с помощью аннотации &lt;i&gt;@Inject&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;public class TapestryModule {

  public void contributeApplicationDefaults(final MappedConfiguration&amp;lt;String, String&amp;gt; configuration) {
    configuration.add(&amp;quot;test-symbol&amp;quot;, &amp;quot;tapestry&amp;quot;);
  }
}

@SubModule(TapestryModule)
class TapestryIntegrationSpec extends Specification {

  @Inject
  @Symbol(&amp;quot;test-symbol&amp;quot;)
  String testSymbol

  def &amp;quot;test-symbol should be tapestry&amp;quot;() {
    expect:
    testSymbol == &amp;quot;tapestry&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
Ну и самое главное, если возникла надобность в собственном функционале, можно добавить свои расширения. Ключевые классы для расширения функционала:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;i&gt;IMethodInterceptor, IMethodInvocation&lt;/i&gt; — первый для проксирования методов спецификации, позволяет добавлять свой код до и после вызова метода, для упрощения работы можно воспользоваться классом &lt;i&gt;AbstractMethodInterceptor&lt;/i&gt;. Второй доступен из первого, служит для работы с оригинальным(проксируемым) методом&lt;/li&gt;
&lt;li&gt;&lt;i&gt;IGlobalExtension&lt;/i&gt; — позволяет работать с метаданными спецификации(&lt;i&gt;SpecInfo&lt;/i&gt;), здесь можно посмотреть метаданные по любым компонентам спецификации(поля, установочные методы, сценарии требований) и добавить им свои интерсепторы&lt;/li&gt;
&lt;li&gt;&lt;i&gt;IAnnotationDrivenExtension&lt;/i&gt; — тоже что и предыдущий, только упрощает задачу, если наше расширение привязано к какой-то конкретной аннотации, для упрощения работы можно воспользоваться классом &lt;i&gt;AbstractAnnotationDrivenExtension&lt;/i&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
Для создания собственного расширения нужно создать класс-наследник &lt;i&gt;IGlobalExtension&lt;/i&gt; либо &lt;i&gt;IAnnotationDrivenExtension&lt;/i&gt;, в котором скорее всего к компонентам спецификации будет добавляться свой &lt;i&gt;IMethodInterceptor&lt;/i&gt;, и в завершение для &lt;i&gt;IGlobalExtension&lt;/i&gt; нужно добавить &lt;a href="http://habrahabr.ru/blogs/java/118488/"&gt;spi расширение&lt;/a&gt; в &lt;i&gt;META-INF/services/org.spockframework.runtime.extension.IGlobalExtension&lt;/i&gt;, для &lt;i&gt;IAnnotationDrivenExtension&lt;/i&gt; нашу аннотацию нужно зааннотировать с помощью &lt;i&gt;@ExtensionAnnotation(extension_class)&lt;/i&gt;.&lt;br&gt;
Пример расширения, которое запускает сценарий указанное число раз:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="java"&gt;@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
@ExtensionAnnotation(RepeatExtension.class)
public @interface Repeat {
  int value() default 1;
}

public class RepeatExtension extends AbstractAnnotationDrivenExtension&amp;lt;Repeat&amp;gt; {

  @Override
  public void visitFeatureAnnotation(Repeat annotation, FeatureInfo feature) {
    feature.addInterceptor(new RepeatInterceptor(annotation.value()));
  }
}

public class RepeatInterceptor extends AbstractMethodInterceptor{
  private final int count;

  public RepeatInterceptor(int count) {
    this.count = count;
  }

  @Override
  public void interceptFeatureExecution(IMethodInvocation invocation) throws Throwable {
    for (int i = 0; i &amp;lt; count; i++) {
      invocation.proceed();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="groovy"&gt;class CustomExtensionsSpec extends Specification {

  @Repeat(10)
  def &amp;quot;custom extension&amp;quot;() {
    expect:
    Integer.parseInt(&amp;quot;123&amp;quot;) == 123
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Запуск тестов&lt;/h2&gt;&lt;br&gt;
Благодаря тому, что Spock-тесты запускаются с помощью JUnit запускалки(&lt;i&gt;Sputnik&lt;/i&gt;), они отлично работают под различными IDE(так говорят авторы, я проверял только под идеей). Также можно настроить запуск тестов из ant, maven, gradle. Всю необходимую информацию о настройках можно найти &lt;a href="http://code.google.com/p/spock/wiki/GettingStarted"&gt;здесь&lt;/a&gt;.&lt;br&gt;
Добавлю еще, что для себя я немного подшаманил конфигурацию под maven, т.к. предложенная авторами не работала под maven3. Вот мой вариант конфигурации:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="xml"&gt;&amp;lt;project xmlns=&amp;quot;http://maven.apache.org/POM/4.0.0&amp;quot;
         xmlns:xsi=&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;
         xsi:schemaLocation=&amp;quot;http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd&amp;quot;&amp;gt;
  &amp;lt;modelVersion&amp;gt;4.0.0&amp;lt;/modelVersion&amp;gt;

  &amp;lt;parent&amp;gt;
    &amp;lt;groupId&amp;gt;com.example&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;testing-example&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
  &amp;lt;/parent&amp;gt;

  &amp;lt;groupId&amp;gt;com.example&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;testing-spock&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;1.0-SNAPSHOT&amp;lt;/version&amp;gt;
  &amp;lt;packaging&amp;gt;jar&amp;lt;/packaging&amp;gt;

  &amp;lt;name&amp;gt;Testing Spock Framework Example&amp;lt;/name&amp;gt;
  &amp;lt;description&amp;gt;
    This is an example application that demonstrates Spock Framework usage.
  &amp;lt;/description&amp;gt;

  &amp;lt;dependencies&amp;gt;
    &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.codehaus.groovy&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;groovy-all&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;${groovy-version}&amp;lt;/version&amp;gt;
      &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
    &amp;lt;/dependency&amp;gt;
    &amp;lt;dependency&amp;gt;
      &amp;lt;groupId&amp;gt;org.spockframework&amp;lt;/groupId&amp;gt;
      &amp;lt;artifactId&amp;gt;spock-core&amp;lt;/artifactId&amp;gt;
      &amp;lt;version&amp;gt;${spock.version}&amp;lt;/version&amp;gt;
      &amp;lt;scope&amp;gt;test&amp;lt;/scope&amp;gt;
    &amp;lt;/dependency&amp;gt;
  &amp;lt;/dependencies&amp;gt;

  &amp;lt;build&amp;gt;
    &amp;lt;testResources&amp;gt;
      &amp;lt;testResource&amp;gt;
        &amp;lt;directory&amp;gt;src/test/groovy&amp;lt;/directory&amp;gt;
      &amp;lt;/testResource&amp;gt;
      &amp;lt;testResource&amp;gt;
        &amp;lt;directory&amp;gt;src/test/resources&amp;lt;/directory&amp;gt;
      &amp;lt;/testResource&amp;gt;
    &amp;lt;/testResources&amp;gt;
    &amp;lt;plugins&amp;gt;
      &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.apache.maven.plugins&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;maven-surefire-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;configuration&amp;gt;
          &amp;lt;includes&amp;gt;
            &amp;lt;include&amp;gt;**/*Spec.groovy&amp;lt;/include&amp;gt;
          &amp;lt;/includes&amp;gt;
        &amp;lt;/configuration&amp;gt;
      &amp;lt;/plugin&amp;gt;
      &amp;lt;plugin&amp;gt;
        &amp;lt;groupId&amp;gt;org.codehaus.gmaven&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;gmaven-plugin&amp;lt;/artifactId&amp;gt;
        &amp;lt;version&amp;gt;${gmaven-version}&amp;lt;/version&amp;gt;
        &amp;lt;configuration&amp;gt;
          &amp;lt;providerSelection&amp;gt;${gmaven-provider}&amp;lt;/providerSelection&amp;gt;
        &amp;lt;/configuration&amp;gt;
        &amp;lt;executions&amp;gt;
          &amp;lt;execution&amp;gt;
            &amp;lt;goals&amp;gt;
              &amp;lt;goal&amp;gt;testCompile&amp;lt;/goal&amp;gt;
            &amp;lt;/goals&amp;gt;
          &amp;lt;/execution&amp;gt;
        &amp;lt;/executions&amp;gt;
        &amp;lt;dependencies&amp;gt;
          &amp;lt;dependency&amp;gt;
            &amp;lt;groupId&amp;gt;org.codehaus.groovy&amp;lt;/groupId&amp;gt;
            &amp;lt;artifactId&amp;gt;groovy-all&amp;lt;/artifactId&amp;gt;
            &amp;lt;version&amp;gt;${groovy-version}&amp;lt;/version&amp;gt;
          &amp;lt;/dependency&amp;gt;
        &amp;lt;/dependencies&amp;gt;
      &amp;lt;/plugin&amp;gt;
    &amp;lt;/plugins&amp;gt;
  &amp;lt;/build&amp;gt;

  &amp;lt;properties&amp;gt;
    &amp;lt;groovy-version&amp;gt;1.7.10&amp;lt;/groovy-version&amp;gt;
    &amp;lt;gmaven-version&amp;gt;1.3&amp;lt;/gmaven-version&amp;gt;
    &amp;lt;gmaven-provider&amp;gt;1.7&amp;lt;/gmaven-provider&amp;gt;
    &amp;lt;spock.version&amp;gt;0.5-groovy-1.7&amp;lt;/spock.version&amp;gt;
  &amp;lt;/properties&amp;gt;
&amp;lt;/project&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Вывод&lt;/h2&gt;&lt;br&gt;
Несмотря на то, что познакомился с этим замечательным фреймворком я совсем недавно и опыта использования его практически не имею, могу с уверенностью сказать, что по возможностям он не уступает, а в некоторых моментах даже превосходит другие фреймворки. Мне очень понравилось писать тесты на Groovy, понравилось писать тесты руководствуясь BDD. Поэтому и вам советую попробовать.&lt;br&gt;
&lt;br&gt;
Примеры можно найти &lt;a href="https://github.com/sody/samples/tree/master/testing/testing-spock"&gt;здесь&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Литература&lt;/h2&gt;&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://behaviour-driven.org/"&gt;Behaviour-Driven Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development"&gt;Behaviour Driven Development&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://code.google.com/p/spock/wiki/SpockBasics"&gt;Spock Basics&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt; 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/java/137561/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/java/137561/</guid>
      <dc:creator>sody</dc:creator>
    </item>
    <item>
      <title>Алгоритмы / Еще раз о поиске наибольшего сгущения в облаке точек</title>
      <link>http://habrahabr.ru/blogs/algorithm/137652/</link>
      <pubDate>Sun, 05 Feb 2012 21:17:41 GMT</pubDate>
      <description>
  	В очередной раз мне попалась задача – найти в облаке точек место их наибольшего сгущения. На этот раз ситуация была такой:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;есть некоторое количество (можно считать, что не более 16 миллионов) измерений набора параметров. Число параметров в наборе – от 2 до 5.&lt;/li&gt;
&lt;li&gt;измерение параметров может быть относительно успешным – тогда их результат будет неподалеку от истинного (параметры и тип распределения неизвестны), либо не успешным – тогда результат будет случайным (опять-таки с неизвестными параметрами распределения). Определить по одиночному измерению, было ли оно успешным, нельзя.&lt;/li&gt;
&lt;li&gt;Можно считать, что точка сгущения существует. Если их несколько с близким качеством (которое формально так и не определяется), можно выдать любую. &lt;/li&gt;
&lt;li&gt;ответ нужно дать за один проход по исходным данным: перевычислять их или сохранять целиком – дорого.&lt;/li&gt;
&lt;li&gt;И, как обычно, хочется, чтобы алгоритм выглядел попроще, а работал побыстрее.&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
Для простоты можно считать, что измеренные значения параметров – вещественные числа от 0 до 1. Результат хочется получить с разрешением 3 десятичных знака для случая 5 параметров, и 4 или больше – для 4 и менее параметров.&lt;br&gt;
&lt;br&gt;
Понятно, что большое число исходных точек делает сомнительными методы, основанные на обработке пар точек. Даже эффективный поиск расстояния до ближайшей точки потребует заметных усилий по реализации. &lt;br&gt;
&lt;br&gt;
Построение гистограмм тоже непросто: заранее неизвестен даже желаемый размер ячейки. Возможно, например, что все измерения дадут результаты в шарике диамером 0.1, а успешные будут локализованы в области размером 0.003. И надо будет выдать положение этой области (в N-мерном пространстве!)&lt;br&gt;
&lt;br&gt;
Можно было бы построить гистограммы распределения отдельных параметров, понадеявшись, что сгущение N-мерных точек можно будет восстановить по положениям сгущений проекций точек на отдельные координаты, но лучше оставить этот вариант в качестве запасного: терять информацию о взаимосвязях параметров опасно, а при проекциях могут возникнуть паразитные области сгущения.&lt;br&gt;
&lt;br&gt;
Вариант, который мне показался наиболее перспективным – использование k-d дерева. Если мы построим бинарное дерево, каждый узел которого соответствует делению области пространства на две части по одной из координат (координаты перебираются по циклу – x&lt;sub&gt;1&lt;/sub&gt;,x&lt;sub&gt;2&lt;/sub&gt;,…,x&lt;sub&gt;k&lt;/sub&gt;,x&lt;sub&gt;1&lt;/sub&gt;,x&lt;sub&gt;2&lt;/sub&gt;,…), и найдем количество точек, попавших в каждую из областей, то можно сделать так.&lt;br&gt;
&lt;br&gt;
Пусть точек N. Выберем значение K, меньшее N, например, K=[sqrt(N)] или K=[N&lt;sup&gt;2/3&lt;/sup&gt;]. Найдем область наименьшего объема (т.е. лежащую на наибольшей глубине дерева), содержащую не менее K точек. Если таких областей несколько, возьмем ту, в которой точек больше всего. После этого начнем делить ее пополам (спускаться по дереву дальше), каждый раз выбирая половину, в которой точек больше. Когда дошли до листа (например, до отдельной точки), выдаем его в качестве ответа.&lt;br&gt;
&lt;br&gt;
Можно найти примеры, в которых этот алгоритм упустит главную область сгущения, а выберет вместо нее какую-нибудь локальную аномалию, или в качестве ответа выдаст точку, находящуюся далеко от центра сгущения, но можно ожидать, что в большинстве случаев его ответы будут более-менее адекватными. К сожалению, строить k-d дерево дорого, да и памяти оно занимает немало. Я готов выделить 8 байт на точку, но тратить больше было бы нежелательно.&lt;br&gt;
&lt;br&gt;
Чтобы сэкономить время и память, я решил построить k-d дерево неявно. &lt;br&gt;
&lt;br&gt;
Пусть у нас есть точка (x&lt;sub&gt;1&lt;/sub&gt;,x&lt;sub&gt;2&lt;/sub&gt;,…,x&lt;sub&gt;k&lt;/sub&gt;). Запишем ее координаты в двоичной системе&lt;br&gt;
x&lt;sub&gt;1&lt;/sub&gt;=0.x&lt;sub&gt;11&lt;/sub&gt;x&lt;sub&gt;12&lt;/sub&gt; x&lt;sub&gt;13&lt;/sub&gt;…&lt;br&gt;
x&lt;sub&gt;2&lt;/sub&gt;=0.x&lt;sub&gt;21&lt;/sub&gt;x&lt;sub&gt;22&lt;/sub&gt; x&lt;sub&gt;23&lt;/sub&gt;…&lt;br&gt;
x&lt;sub&gt;3&lt;/sub&gt;=0.x&lt;sub&gt;31&lt;/sub&gt;x&lt;sub&gt;32&lt;/sub&gt; x&lt;sub&gt;33&lt;/sub&gt;…&lt;br&gt;
…&lt;br&gt;
&lt;br&gt;
И постоим 64-битное целое число&lt;br&gt;
P= x&lt;sub&gt;11&lt;/sub&gt; x&lt;sub&gt;21&lt;/sub&gt;… x&lt;sub&gt;k1&lt;/sub&gt; x&lt;sub&gt;12&lt;/sub&gt;… x&lt;sub&gt;k2&lt;/sub&gt;…&lt;br&gt;
&lt;br&gt;
Это число представляет путь по дереву на глубину 64 уровня. Кроме того, оно позволяет восстановить координаты точки с требуемой точностью.&lt;br&gt;
&lt;br&gt;
Если мы отсортируем коды P для всех точек по возрастанию, то получим точки в порядке обхода дерева. Для любых двух точек P&lt;sub&gt;a&lt;/sub&gt; и P&lt;sub&gt;b&lt;/sub&gt; легко найти самый глубокий узел, общими потомками которого они являются: достаточно найти старший ненулевой бит в числе P&lt;sub&gt;a&lt;/sub&gt;^P&lt;sub&gt;b&lt;/sub&gt;. И все необходимые фрагменты задачи на таком представлении решаются в несколько строчек:&lt;br&gt;
&lt;br&gt;
Поиск уровня, на котором находится самая маленькая точка, содержащая не менее K точек:&lt;br&gt;
&lt;pre&gt;&lt;code&gt;    ulong mask=ulong.MaxValue;
    K--;
    for(int i=K;i&amp;lt;m_np;i++) mask=Math.Min(mask,m_Arr[i]^m_Arr[i-K]);
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Здесь m_Arr – массив кодов, m_np – число заполненных элементов в нем, mask – число, старший бит которого определяет искомый уровень.&lt;br&gt;
&lt;br&gt;
Поиск области на найденном уровне, содержащей максимальное количество точек (мы знаем, что их не меньше K):&lt;br&gt;
&lt;pre&gt;&lt;code&gt;    mask=InvMask(mask);
    int ms=0,me=0;
    for(int i=0;i&amp;lt;m_np-K;i++){
        ulong a=m_Arr[i];
        int h=i+K;
        if(((a^m_Arr[h])&amp;mask)==0){
            while(h&amp;lt;m_np-1 &amp;&amp; ((a^m_Arr[h+1])&amp;mask)==0) h++;
            K=h-i; 
            ms=i; me=i=h;
        }
    }
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
Здесь InvMask(mask) – вычисление маски, содержащей 1 во всех разрядах, более старших, чем старший ненулевой разряд маски mask. Вычисляется ms – начало искомой области и me – ее конец.&lt;br&gt;
&lt;br&gt;
Поиск более тяжелого потомка:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code&gt;    int h=(ms+me)/2;
    ulong samp=m_Arr[h];
    ulong cb=samp^m_Arr[ms],ce=samp^m_Arr[me];
    if(cb&amp;gt;ce) {
        ms=h;
        ce=InvMask(ce);
        while(ms&amp;gt;0 &amp;&amp; ((m_Arr[ms-1]^samp)&amp;ce)==0) ms--;
    } else {
        me=h;
        cb=InvMask(cb);
        while(me&amp;lt;m_np-1 &amp;&amp; ((m_Arr[me+1]^samp)&amp;cb)==0) me++;
    }
&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
Здесь спуск идет не обязательно на один уровень.&lt;br&gt;
Таким образом, задача поиска сгущения решается. &lt;br&gt;
&lt;br&gt;
Вся программа уложилась в 100 строк, исходник (на C#) можно найти &lt;a href="http://astr73.narod.ru/Files/FindDens.cs"&gt;здесь&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
Реальная задача имеет несколько более сложную формулировку. Диапазон изменения параметров заранее неизвестен, кроме того, измерений в выборке может быть больше запланированных 16 миллионов, причем «хорошие» измерения могут идти ближе к концу. Но небольшие модификации алгоритма позволяют справиться с этими проблемами. Например, если место в массиве кончилось, а точки продолжают поступать, мы можем отсортировать и проредить массив уже набранных кодов – на положение и качество сгущения это не повлияет. 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/algorithm/137652/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/algorithm/137652/</guid>
      <dc:creator>Mrrl</dc:creator>
    </item>
    <item>
      <title>Программинг микроконтроллеров / Модельно-ориентированное проектирование, или продолжаем приручение Cortex&amp;nbsp;M3 с помощью Matlab/Simulink</title>
      <link>http://habrahabr.ru/blogs/controllers/133911/</link>
      <pubDate>Sun, 05 Feb 2012 19:51:58 GMT</pubDate>
      <description>
  	&lt;img src="http://habrastorage.org/storage2/5b6/7f3/29f/5b67f329f8cd7179b8ac7e946cadef72.jpg"&gt;&lt;br&gt;
&lt;i&gt;Изображение взято, и слегка отредактировано, из блога &lt;a href="http://antonlo.blogspot.com/"&gt;Антона Лопатина©&lt;/a&gt;. Ну очень вдохновляет.&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
Добрый день, уважаемое сообщество!&lt;br&gt;
&lt;br&gt;
В прошлом &lt;a href="http://habrahabr.ru/blogs/controllers/129519/"&gt;топике&lt;/a&gt; я постарался сделать вводной экскурс в модельно-ориентированное проектирование встраиваемых систем с использованием ARM микропроцессоров Cortex M3 и MATLAB/Simulink. Продолжаем погружение, усложняем задачу. Жаль до концепта на заглавной иллюстрации еще далеко, но процесс разработки одного из важнейших его узлов, а именно системы самонаведения турели, я попытаюсь показать.&lt;br&gt;
&lt;br&gt;
&lt;i&gt;Ниже довольно много изображений, но без них скучновато и не наглядно.&lt;/i&gt;&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Аппаратное обеспечение&lt;/h4&gt;&lt;br&gt;
В отличии от первого топика теперь у нас в руках имеются:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt; Отладочная плата FiO Std от таиландских друзей из &lt;a href="http://aimagin.com"&gt;aimagin&lt;/a&gt;. Без нее работа с библиотекой RapidSTM32 для Simulink слегка затруднительна. Используется и как hardware key для rapidSTM32, и как управляющий модуль. На борту имеет камень STM32F103RET6.&lt;img src="http://habrastorage.org/storage2/d2f/a83/597/d2fa83597465662775a534e97271aed7.jpg"&gt;&lt;/li&gt;
&lt;li&gt; 2 простецких сервомотора SG-5010&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/676/b72/3c8/676b723c8fc66ade57a90c513caaa7a9.jpg"&gt;&lt;/li&gt;
&lt;li&gt; WEB камера &lt;a href="http://www.logitech.com/ru-ru/webcam-communications/webcams/devices/7079"&gt;Logitech HD Webcam C270&lt;/a&gt;. Но не настолько гламурная, как в обзоре и на фото.&lt;img src="http://habrastorage.org/storage2/e9a/260/957/e9a260957fd21a3820759dfa2862aeea.png"&gt;&lt;/li&gt;
&lt;li&gt; Пара резисторов, проводки, коннекторы, макетная плата, блок питания от старого принтера, резиночки для ватмана, медная проволока, кабель mini USB, ноутбук, и, главное, самодельный держатель для паяльника из седла предохранителя (сделан дядей Сашей©, используется в качестве станины).&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
Еще одним отличием от красивого концепта будет то, что для нашей поделки понятие «собранная на коленке» максимально приближено к действительности. Яркий пример рапид разработки. Быстро, дешево, работоспособно.&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Постановка задачи и подзадач&lt;/h4&gt;&lt;br&gt;
Главной задачей является реализация функций захвата и сопровождения цели. Для достижения намеченного нам предстоит:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt; Организовать связь с ПК.&lt;br&gt;
Устройство наше будет распознаваться как HID, и будет слушать мой ноутбук через USB.&lt;/li&gt;
&lt;li&gt;Механизировать головку самонаведения.&lt;br&gt;
Хватит мигать диодами, переходим на сервы. Классика жанра постигания премудростей работы с мехатроникой.&lt;/li&gt;
&lt;li&gt;Создать систему управления на стороне железа.&lt;br&gt;
Мех. составляющая + HIL влечет за собой более сложные алгоритмы управления на стороне железа. Как минимум применение PID регулятора. &lt;u&gt;&lt;b&gt;ТАУ наше все!&lt;/b&gt;&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;Реализовать алгоритм распознавания видео и выдачи управляющих сигналов на стороне хоста.&lt;br&gt;
Для слежения за объектом необходимо этот объект идентифицировать. Пока этим будет заниматься мой ноутбук, но в будущем можно переложить и эту задачу на крепкие плечи ARM. Здесь, возможно, стоит присмотреться к &lt;a href="http://www.mathworks.com/academia/beagleboard/"&gt;bigle board&lt;/a&gt; на процессоре TI OMAP3530. То ли еще будет.&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Модель на стороне хоста&lt;/h4&gt;&lt;br&gt;
Свернутая модель, на которую возлагаются функции обработки видео и выдачи управляющих сигналов выглядит так:&lt;img src="http://habrastorage.org/storage2/0a2/19b/744/0a219b7449026dd6f0ceae79652cf454.png"&gt;&lt;br&gt;
Видеосигнал разделенный на каналы передается на подсистемы детектирования и обработки. После них выходные сигналы передаются через USB на плату управления.&lt;br&gt;
&lt;br&gt;
Допустим объект у нас подсвечивается лазером с определенной длиной волны. Главной задачей подсистемы распознавания видео будет выделение заданного цветового оттенка, фильтрация возможных помех и выдача лаконичного сигнала о расположении объекта. Для нашего «быка» мы будем использовать не красный платок, а зеленый, что опять-таки не столь важно. Можно и движение сюда подвязать…&lt;br&gt;
Подсистемы детектирования выглядят так:&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/5e1/091/5c2/5e10915c28bfa05266484771ee1b0e48.png"&gt;&lt;br&gt;
Подсистемы фильтрации выглядят так&lt;img src="http://habrastorage.org/storage2/22a/306/02a/22a30602acd18e874a33afba90f61c14.png"&gt;&lt;br&gt;
С распознаванием видео я знакомился в процессе разработки, потому и алгоритм выбрал самый простой. Расщепленный видеосигнал проходит через ветви условий, которые возвращают true или false (вместо процентовки RGB) в зависимости от заданных условий. Как видно из числовых значений, я ориентировался на зеленый цвет.&lt;br&gt;
&lt;br&gt;
На выходе систем мы вместо видео получаем матрицу из поля нулей и замкнутых островков из единиц. Подсистема обработки полученной информации определяет площади и центры полученных «островков», обрисовывает их границами и эквивалентными окружностями, а так же определяет расстояние центра объекта от центра матрицы. На сторону железа передается ошибка с строках и колонках для наибольшего островка, и количество островков. Если этот самый num==0, то турель переходит в дежурный режим и выполняет плановое сканирование местности по горизонтали. Отсчет ошибок ведется не от абсолютного центра изображения, а от границ прямоугольной «нулевой зоны». Внутри этой зоны объект считается «захваченным» и камера фиксирует свое положение. Все дополнительные построения налаживаются на оригинальное видео, дополняя серую и невеселую &lt;s&gt;стену моей комнаты&lt;/s&gt;реальность нашу бодрыми прямоугольничками и кружочками.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/8f2/e91/1f8/8f2e911f860d8b17ea2aeea5c4042f56.png"&gt;&lt;br&gt;
&lt;br&gt;
Подсистемы черчения дополнительной графики и определения ошибки выглядят так:&lt;img src="http://habrastorage.org/storage2/0d8/141/aa2/0d8141aa29d1e210379d1448e826f144.png"&gt;&lt;br&gt;
&lt;i&gt;Simulink учтиво и заранее напоминает нам, что блоки клейменные пометкой «Reglace» следует заменить до выхода новой версии программы. Иначе модель будет не совместима с ней.&lt;/i&gt;&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/13a/b6b/f1e/13ab6bf1e1cf66cf5156af757a1d91f5.png"&gt;&lt;br&gt;
Следует отметить, что привязка к запущенному Simulink не обязательна. Используя тот же Simulink Coder можно сгенерить С++ код для сборки самостоятельного приложения как для Windows, так и для Linux. Я в этом пока не силен, поэтому ограничился работающей Simulink моделью в режиме Accelerator, то есть в режиме частичной компиляции для увеличения скорости выполнения:&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/ac0/a4f/86d/ac0a4f86d06e6c480ac3c79b54d19c26.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Модель на стороне железа&lt;/h4&gt;&lt;br&gt;
Модель Simulink из которой генерится код для заливки в микроконтроллер выглядит как показано на иллюстрации ниже:&lt;img src="http://habrastorage.org/storage2/7f9/31f/75e/7f931f75eaca20212dc732b3bf461be5.png"&gt; Выполнена в едином тактировании, что и видно по одинаковой цветовой подсветке для всех блоков модели после обновления. Как и упоминалось ранее, помимо элементарных блоков типа сложения или умножения, модель содержит два PID регулятора. Скорее даже PI, потому как коэффициент дифференцирующей составляющей равен нулю.&lt;img src="http://habrastorage.org/storage2/1f5/3e7/0ff/1f53e70ff9a161b401e1c37f846d3b93.png"&gt;&lt;br&gt;
&lt;br&gt;
Параметры подбирались вручную опытным путем. Но для более серьезных систем у MATLAB есть специальный инструмент &lt;a href="http://www.mathworks.com/products/control/"&gt;Control&amp;nbsp;System&amp;nbsp;Toolbox&lt;/a&gt; для «тюнинга» линейных систем управления на основе экспериментальных данных с возможностью задания требуемых параметров регулирования.&lt;br&gt;
Малый пропорциональный коэффициент и нулевой дифференциальный обусловлены довольно ощутимой задержкой по времени, в которую каждый элемент системы вносит свою лепту.&lt;br&gt;
&lt;br&gt;
Назначения блоков Saturation и Dead Zone думаю ясны из графиков на их пиктограммах.&lt;br&gt;
&lt;br&gt;
Вначале реализация «дежурного» и «боевого» режимов задумывалась с использованием конечных автоматов, но потом оказалось, что вопрос можно решить проще. Поэтому &lt;a href="http://en.wikipedia.org/wiki/Finite-state_machine"&gt;FSM&lt;/a&gt; еще впереди. Реализуется эта концепция внутри Simulink с помощью изящного инструмента &lt;a href="http://www.mathworks.com/products/stateflow/"&gt;Stateflow&lt;/a&gt;, и так же легко заливается внутрь МК.&lt;br&gt;
&lt;br&gt;
Генерация, компиляция и заливка кода выполняется полностью из под MATLAB. Keil даже запускать отдельно нет нужды.&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Собственно процесс разработки&lt;/h4&gt;&lt;br&gt;
&lt;br&gt;
Все перечисленное выше является большей частью уже результатами нежели этапами разработки.&lt;br&gt;
&lt;br&gt;
Пока не было серв (читай отсутствие аппаратной составляющей как таковой) алгоритмы работы системы отрабатывались на вот такой некрасивой, монстрообразной черновой модели:&lt;img src="http://habrastorage.org/storage2/151/b23/111/151b23111c2961582428665128dbc6ef.png"&gt;&lt;br&gt;
&lt;br&gt;
Потом она стала вот такой:&lt;img src="http://habrastorage.org/storage2/923/0cb/83a/9230cb83ac08f54b80ead55ae3cc0306.png"&gt;&lt;br&gt;
&lt;br&gt;
Главной отличительной частью этих моделей является механическая подсистема (выделено синим цветом на предыдущей иллюстрации), которая позволяла оценить работу системы исключительно с помощью ПК. В моем случае важно было оптимизировать угловую скорость вращения серв, и коэффициенты PI регуляторов, но возможен и полный механический анализ системы.&lt;br&gt;
Так выглядела сборка в Solidworks:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/dc7/835/708/dc78357082e60cd4e00b54152bdd6bda.png"&gt;&lt;br&gt;
&lt;br&gt;
А так выглядит симуляция движения сборки уже внутри модели Simulink:&lt;br&gt;
&lt;br&gt;
&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/Sz32y9C4fTw" frameborder="0" allowfullscreen=""&gt;&lt;/iframe&gt;&lt;br&gt;
&lt;br&gt;
Очень серьезный инструмент симуляции динамики и статики есть и внутри Solidworks, но мне работа с MATLAB пока роднее. Экспортируется сборка с помощью утилиты SimMechanics Link. &lt;a href="http://www.mathworks.com/help/toolbox/physmod/smlink/"&gt;Здесь&lt;/a&gt; про нее много чего написано.&lt;br&gt;
Одним словом, когда приехало «железо», у меня уже было почти все готово. Я просто удалил все лишнее и разделил модель на две составляющие: Host и Target.&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Результаты испытаний&lt;/h4&gt;&lt;br&gt;
Ну и наконец видео полевых испытаний:&lt;br&gt;
&lt;br&gt;
&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/_o4WZt8sskM" frameborder="0" allowfullscreen=""&gt;&lt;/iframe&gt;&lt;br&gt;
&lt;br&gt;
Да, довольно страшненькая сборка. На премию супер прямых рук точно не претендует.&lt;br&gt;
&lt;br&gt;
На экране ноутбука творится следующее:&lt;br&gt;
&lt;br&gt;
&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/HZ39OkM3iEg" frameborder="0" allowfullscreen=""&gt;&lt;/iframe&gt;&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Выводы&lt;/h4&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Позитив:&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
&lt;ol&gt;
&lt;li&gt;Разработка заняла минимум времени и ресурсов. Все работает удовлетворительно, и легко поддается модернизации. Реализация «спускового крючка» — нет ничего легче. На плате осталось еще &lt;s&gt;100500&lt;/s&gt;много свободный портов. Нужно всего лишь добавить ветвь условия при нахождении центра объекта в зоне захвата, которая будет подавать лог. 1 в определенный порт и &lt;a href="http://www.youtube.com/watch?v=ycRDMYaWgAA"&gt;&lt;s&gt;спускать с цепи рейл ган&lt;/s&gt;&lt;/a&gt; имитировать выстрел.&lt;/li&gt;
&lt;/ol&gt;&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Поучительный негатив:&lt;/b&gt;&lt;br&gt;
&lt;ol&gt;
&lt;li&gt;Использовать кота в качестве мишени не получилось. Серый камуфляж не поддается обнаружению, а попытка нацепить на него метку увенчалась провалом. К тому же он еще и ужасно боится жужжания серв. Пришлось испытывать все на себе.&lt;/li&gt;
&lt;li&gt;Для увеличения быстродействия и стабильности работы нужно еще много чего совершенствовать. Механическая часть оказалась самой капризной. Калибровка серв заняла большую часть времени отведенной на пусконаладку. При дальнейшем развитии проекта нужно будет обязательно переходить на более качественные девайсы, возможно с последующей доработкой и введением собственной обратной связи.&lt;/li&gt;
&lt;li&gt;Я не смог совладать с автоматическим изменением настроек яркости камеры в зависимости от освещения и окружающего фона. Понятно, что это влияло на селективность системы распознавания. В дальнейшем планируется использовать отдельный модуль камеры (возможно с упором на ИК диапазон с соответствующей подсветкой) с прямым присоединением к управляющей плате.&lt;/li&gt;
&lt;li&gt;С превеликим удовольствием и безграничной благодарностью приму к сведению разумную критику в комментариях. И здесь же допишу!&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt; 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/controllers/133911/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/controllers/133911/</guid>
      <dc:creator>slovak</dc:creator>
    </item>
    <item>
      <title>Информационная безопасность / Alarmist, или история одного параноика</title>
      <link>http://habrahabr.ru/blogs/infosecurity/137646/</link>
      <pubDate>Sun, 05 Feb 2012 17:02:38 GMT</pubDate>
      <description>
  	&lt;img src="http://s1.hostingkartinok.com/uploads/images/2012/02/34d517876f0a56f91525a97d0ab64484.png" alt="Alarmist in action"&gt;&lt;br&gt;
&lt;br&gt;
Так уж случилось, что мне понадобилось полное шифрование ОС на моём ноутбуке. Как бы мне ни хотелось воспользоваться для этого одним из дистрибутивов GNU/Linux, к сожалению, мне пришлось остаться на Windows, поскольку мне было необходимо определенное ПО, доступное только под Windows (а Wine я слишком сильно не люблю, чтобы пользоваться им почти ежедневно). Зато такой выбор ОС сразу упростил выбор системы шифрования, поскольку под Windows ничего сто?ящего, кроме TrueCrypt, нет (upd: оказывается, &lt;a href="http://diskcryptor.net/wiki/Main_Page"&gt;есть&lt;/a&gt;).&lt;br&gt;
&lt;br&gt;
Итак, я зашифровал весь свой жесткий диск, установил TrueCrypt'овый загрузчик и вроде бы всё у меня сразу стало хорошо. &lt;a name="habracut"&gt;&lt;/a&gt;Однако, у меня было одно опасение: а что, если мой ноутбук попадёт в чужие руки &lt;i&gt;включенным&lt;/i&gt;? Ведь тогда все мои старания будут бесполезными, поскольку ключ шифрования будет в оперативной памяти и новый владелец без проблем сможет просматривать любые данные на моём жестком диске.&lt;br&gt;
&lt;br&gt;
Я начал думать над решением новонайденной проблемы. На ArchLinux Wiki я вычитал идею написать приложение, которое выключает ноутбук, если не может найти какое-то заданное Bluetooth-устройство. Идея, в общем-то, показалась мне неплохой, но мне не хотелось, чтобы работоспособность моего ноутбука зависила не только от его аккумулятора, но ещё и от аккумулятора какого-то другого устройства. Да и постоянно включенный и используемый Bluetooth не понизит энергопотребление.&lt;br&gt;
&lt;br&gt;
И тут я очень вовремя вспомнил, что мой ноутбук относиться к объективно самой лучшей серии ноутбуков в мире, а именно, к серии ThinkPad. Одной из функций, присущей всем новым (и не очень) ноутбукам этой серии, является т.н. &lt;a href="http://www.thinkwiki.org/wiki/Active_Protection_System"&gt;Active Protection System&lt;/a&gt;. Говоря простым языком, это акселерометр на материнской плате, преназначенный для того, чтобы детектировать падения ноутбука, дабы заранее припарковать головку жесткого диска, таким образом уменьшаяя вероятность нанесения урона жесткому диску в результате падения. Но кого, собственно, интересует, для чего эта штука &lt;i&gt;предназначена&lt;/i&gt;? Ведь главное — то, что у нас есть акселерометр, при помощи которого можно определить, когда ноутбук подняли или другим образом пытаются переместить с одного места на другое.&lt;br&gt;
&lt;br&gt;
Так родилась идея Alarmist. Alarmist — программа на языке Python, которая умеет брать показатели с &lt;i&gt;датчиков&lt;/i&gt; и, если датчики показывают что-нибудь страшное, подавать &lt;i&gt;сигнал паники&lt;/i&gt;. Как датчики, так и реализации паники можно легко заменять и модифицировать. Конечно же, Alarmist можно легко на время приостанавливать, например, если необходимо передвинуть ноутбук с одного места на другое.&lt;br&gt;
&lt;br&gt;
Сейчас Alarmist умеет получать данные с ThinkPad'овского акселерометра (правда, только под Windows) и выполнять произвольные консольные команды в случае паники (по умолчанию — гибернация). За исключением датчика ThinkPadShockSensor, Alarmist полностью кроссплатформенный (в теории, на практике я его не тестировал под другими ОС). Мне большего и не нужно, но я был бы рад увидеть реализации других датчиков и методов паник, благо Alarmist &lt;a href="https://raw.github.com/popoffka/alarmist/master/LICENSE"&gt;свободен&lt;/a&gt; и &lt;a href="https://github.com/popoffka/alarmist"&gt;доступен на github&lt;/a&gt;. Интересными (на мой взгляд) идеями для новых датчиков является уже упомянутое выше использование Bluetooth и устройства-«маячка», использование модулей GPS/GSM/WiMax и анализ поведения пользователя.&lt;br&gt;
&lt;br&gt;
Я буду очень рад, если моя разработка пригодится ещё кому-нибудь, поэтому и делюсь ею здесь. Тем, кто захочет ею воспользоваться, я хотел бы дать ещё один совет: не забудьте о настроенных действиях при закрытии крышки ноутбука и нажатии на кнопку выключения, поскольку, если у вас там «sleep», ничто не помешаети злоумышленнику закрыть крышку ноутбука, отнести его к себе в логово и уже там открыть, на ровной поверхности, не вызвав никаких подозрений у Alarmist.&lt;br&gt;
&lt;br&gt;
Кстати, вот видео с демонстрацией работы Alarmist (уж простите за качество):&lt;br&gt;
&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/l0SKIhsyJqQ" frameborder="0" allowfullscreen=""&gt;&lt;/iframe&gt; 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/infosecurity/137646/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/infosecurity/137646/</guid>
      <dc:creator>mariofag</dc:creator>
    </item>
    <item>
      <title>Смартфоны и коммуникаторы / Зачем компаниям мобильные приложения или почему в Маркетах столько барахла</title>
      <link>http://habrahabr.ru/blogs/smartphone_ru/137644/</link>
      <pubDate>Sun, 05 Feb 2012 16:14:42 GMT</pubDate>
      <description>
  	Сейчас любая компания хочет себе мобильное приложение. Когда мы стали заниматься разработкой iPhone и Android аппов на заказ, мы стали получать огромное количество запросов от клиентов. Первое время мы очень радовались этому факту, однако вскоре это стало нас расстраивать. Потому что большинство клиентов на самом деле не отдает себе отчет в том, зачем нужны мобильные приложения, как их используют люди и как они могут помочь в бизнесе. В этой статье я решил написать о типичных запросах клиентов, и почему нам часто приходится их расстраивать. А также о том, что же все-таки со всем этим делать.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Мобильное приложение — визитка&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
Клиент говорит:&lt;br&gt;
 — Мы хотим сделать приложение о нашей компании. &lt;br&gt;
 — Какие функции Вы бы хотели в нем видеть?&lt;br&gt;
 — Ну, информацию о нашей компании, контакты, форму заказа обязательно, новости, отзывы.&lt;br&gt;
 — Окей, а сколько на вашем сайте посетителей?&lt;br&gt;
 — Не знаю, может быть, 50&lt;br&gt;
 — А есть те, которые приходят повторно?&lt;br&gt;
 — Вряд ли, в основном люди попадают на наш сайт из поиска.&lt;br&gt;
&lt;br&gt;
На вопрос «А зачем тогда люди станут устанавливать программу на телефон?» клиенты уже ответить не могут. &lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
На самом деле все очень просто. Приложение — это инструмент для решения какой-то задачи. Вот три основных задачи, которые люди решают с помощью мобильных приложений:&lt;br&gt;
 — скоротать время;&lt;br&gt;
 — получить доступ в интернет при отсутствии других способов;&lt;br&gt;
 — срочно получить необходимую информацию;&lt;br&gt;
&lt;br&gt;
Если приложение не решает ни одной из этих задач, оно скорее всего не нужно людям. Лучше потратьте деньги на хорошую мобильную версию сайта, и будет вам счастье! А если вы видите, что люди &lt;b&gt;регулярно&lt;/b&gt; заходят на ваш сайт, то скорее всего сайт позволяет решить им какую-то задачу. Отразив ее в мобильном приложении, вы скорее всего получите довольных клиентов!&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Мобильно приложение для Интернет-магазина&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
Клиент говорит: &lt;br&gt;
 — Мы хотим сделать приложение, с помощью которого можно будет просматривать каталог нашей продукции и делать заказ&lt;br&gt;
 — Окей, а какие цели вы преследуете?&lt;br&gt;
 — Мы бы хотели, чтобы люди находили наше приложение в Appstore и Android Market и совершали покупки.&lt;br&gt;
&lt;br&gt;
На самом деле мобильное приложение делается для &lt;b&gt;уже существующих постоянных&lt;/b&gt; клиентов. Если люди регулярно делают заказы в определенном магазине, то мобильное приложение для них может быть более удобным инструментом сделать заказ. Но много вы знаете таких интернет-магазинов? Большинство людей ищут товар в Яндексе, потом попадают в нужный интернет-магазин, делает заказ &lt;b&gt;один раз&lt;/b&gt; и уходят. Неужели они станут ради одного заказа скачивать приложение? Гораздо лучше здесь подойдет мобильная версия сайта, на которую будут попадать люди, ищущие товары с мобильных устройств.&lt;br&gt;
&lt;br&gt;
В этом случае клиенты часто приводят в пример Тануки и Империю Пиццы, приложения которых стали очень популярными. Но не надо забывать, что люди и так регулярно заказывали еду в этих заведениях. Приложение позволило делать это более удобно и из любого места. Конечно, пользователи были рады! Кроме того, эти заведения были одни из первых в России, которые сделали мобильное приложение, а сейчас этим уже никого не удивишь.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Но айфоны и айпэды — это ведь так модно. Можно нам все-таки сделать какое-нибудь приложение?&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
Конечно можно! Но предварительно надо все-таки хорошенько подумать, зачем люди будут его использовать регулярно. Если нет прямого очевидного применения, придумайте дополнительный, который и будет заставлять людей регулярно открывать приложение. Вот простые примеры, как сделать обычное приложение о компании нужным для постоянного использования.&lt;br&gt;
&lt;br&gt;
 — Приложение о фитнес-клубе, содержащее также дневник тренировок и сборник упражнений&lt;br&gt;
 — Приложение о розничной сети, также включающее удобный список покупок&lt;br&gt;
 — Приложение ресторана, также включающее в себя рецепты блюд&lt;br&gt;
 — Приложение салона красоты с советами по макияжу на каждый день&lt;br&gt;
&lt;br&gt;
Пока еще все-таки относительно мало российских компаний имеют свои мобильные приложения, поэтому выделиться на этом рынке не так сложно. Главное, слишком сильно не увлекаться, и не пытаться вставить аналог Angry Birds на одну из вкладок приложения инвестиционной компании. 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/smartphone_ru/137644/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/smartphone_ru/137644/</guid>
      <dc:creator>somneart</dc:creator>
    </item>
    <item>
      <title>Типографика / Вышел стандарт Unicode 6.1, добавлено 732 новых символа</title>
      <link>http://habrahabr.ru/blogs/typography/137639/</link>
      <pubDate>Sun, 05 Feb 2012 14:08:32 GMT</pubDate>
      <description>
  	31 января официально представлена новая версия стандарта &lt;a href="http://www.unicode.org/versions/Unicode6.1.0/"&gt;Unicode 6.1.0&lt;/a&gt;, это минорный релиз по сравнению с Unicode 6.0.0 (&lt;a href="http://habrahabr.ru/blogs/typography/106091/"&gt;октябрь 2010 г.&lt;/a&gt;).&lt;br&gt;
&lt;br&gt;
Последняя версия включает &lt;a href="http://www.unicode.org/charts/PDF/Unicode-6.1/"&gt;732 новых символа&lt;/a&gt;, в том числе семь новых письменностей: китайские, азиатские и африканские. Среди 110 тыс. символов Unicode можно найти глифы на любой вкус, например, вот символ &lt;a href="http://www.fileformat.info/info/unicode/char/1f3e9/index.htm"&gt;LOVE HOTEL&lt;/a&gt; (U+1F3E9):&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/e26/92b/f26/e2692bf26ccf406d0ca45680a88be3c9.png"&gt;&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
В Unicode 6.1 добавлена поддержка 200 вариаторов для иконок (смайликов) Emoji, так что теперь эти значки можно описывать как в чёрно-белом (text style), так и в цветном варианте (emoji style).&lt;br&gt;
&lt;br&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;26FA FE0E&lt;/td&gt;
&lt;td&gt;&lt;img alt="U+26FA+U+FE0E/" src="http://www.unicode.org/cgi-bin/varglyph?24-26FA-FE0E"&gt;&lt;/td&gt;
&lt;td&gt;TENT text style&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26FA FE0F&lt;/td&gt;
&lt;td&gt;&lt;img alt="U+26FA+U+FE0F/" src="http://www.unicode.org/cgi-bin/varglyph?24-26FA-FE0F"&gt;&lt;/td&gt;
&lt;td&gt;TENT emoji style&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26FD FE0E&lt;/td&gt;
&lt;td&gt;&lt;img alt="U+26FD+U+FE0E/" src="http://www.unicode.org/cgi-bin/varglyph?24-26FD-FE0E"&gt;&lt;/td&gt;
&lt;td&gt;FUEL PUMP text style&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26FD FE0F&lt;/td&gt;
&lt;td&gt;&lt;img alt="U+26FD+U+FE0F/" src="http://www.unicode.org/cgi-bin/varglyph?24-26FD-FE0F"&gt;&lt;/td&gt;
&lt;td&gt;FUEL PUMP emoji style&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;Из других улучшений в Unicode 6.1: добавлены два новых свойства разбивки строк для текстов на японском языке и иврите; улучшена сегментация текстов для тайского, лаосского и схожих языков; улучшена обработка китайских текстов за счёт более точного мэппинга между упрощёнными и традиционными китайскими иероглифами. 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/typography/137639/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/typography/137639/</guid>
      <dc:creator>alizar</dc:creator>
    </item>
    <item>
      <title>Информационная безопасность / [Из песочницы] Взлом капчи LostFilm (php)</title>
      <link>http://habrahabr.ru/blogs/infosecurity/137601/</link>
      <pubDate>Sun, 05 Feb 2012 13:48:22 GMT</pubDate>
      <description>
      Решив скачать очередную серия Хауса я заглянул на &lt;a href="http://lostfilm.tv"&gt;LostFilm&lt;/a&gt; и обнаружил, что теперь на сайте, чтобы скачать нужно регистрироваться. &lt;br&gt;
Только я решил зарегистрироваться, как на глаза мне попалась их новомодная капча:&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/418/9af/89f/4189af89f236d9794ec358f274584f6c.png"&gt;&lt;br&gt;
&lt;br&gt;
Капча показалась мне довольно простой (хоть и не лишена она дольки оригинальности).&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
Итак, капча представляет собой изображение с тремя фигурами и надписью.&lt;br&gt;
Фигуры отображаются в случайном порядке, без каких либо искажений или изменений положения по осям (меняется только тип фигуры и порядок). Всего фигур четыре: круг (circle), квадрат (square), треугольник (triangle) и крестик (x).&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/435/8e3/2b9/4358e32b9de924c48ac4415adb6fff4b.png"&gt;&lt;br&gt;
&lt;br&gt;
Под фигурами выводится надпись, на которой указано какую из фигур необходимо выбрать.&lt;br&gt;
&lt;br&gt;
Всё это «чудо» располагается в файле &lt;a href="http://login.bogi.ru/captcha.php"&gt;login.bogi.ru/captcha.php&lt;/a&gt;, выводится стандартной phpGD библиотекой, размеры файла 170x95px, тип PNG.&lt;br&gt;
&lt;br&gt;
Регистрация происходит по отправке GET HTTP запроса (в данном случае XHR, но это никакого значения не имеет, т.к. проверки на подмену нет): &lt;br&gt;
&lt;code&gt;&lt;a href="http://bogi.ru/auth/registration?first=FIRST_NAME"&gt;bogi.ru/auth/registration?first=FIRST_NAME&lt;/a&gt;&lt;br&gt;
&amp;last=LAST_NAME&lt;br&gt;
&amp;nick=NICK&lt;br&gt;
&amp;email=EMAIL&lt;br&gt;
&amp;password=PASSWORD&lt;br&gt;
&amp;sex=1&lt;br&gt;
&amp;captcha=1&lt;br&gt;
&amp;sid=&lt;br&gt;
&amp;ajax=1&lt;br&gt;
&amp;target=http%3A%2F%2Flostfilm.tv%2F&lt;/code&gt;&lt;br&gt;
Больше всего нас интересуют поля email, password, captcha и sid. &lt;br&gt;
&lt;br&gt;
Через sid передаётся идентификатор капчи по которому и ведётся проверка подлинности.&lt;br&gt;
В параметре captcha указывается номер фигуры 1, 2 или 3.&lt;br&gt;
&lt;br&gt;
Полный путь к картинке капчи будет выглядеть так:&lt;br&gt;
&lt;a href="http://login.bogi.ru/captcha.php?sid=a0vxd4rgs0gsz5gh38gan903sac"&gt;login.bogi.ru/captcha.php?sid=a0vxd4rgs0gsz5gh38gan903sac&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;img src="http://login.bogi.ru/captcha.php?sid=a0vxd4rgs0gsz5gh38gan903sac" alt="image"&gt;&lt;br&gt;
&lt;br&gt;
Получим картинку из исходного кода страницы регистрации, например из скрытого поля sid:&lt;br&gt;
&lt;br&gt;
&lt;pre&gt;&lt;code class="php"&gt;$reg = &amp;quot;/name=\&amp;quot;sid\&amp;quot; value=\&amp;quot;([^\/]+)\&amp;quot;/&amp;quot;;//&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;sid&amp;quot; value=&amp;quot;7cf6e89e9ee5dd19cdae1328208198&amp;quot; /&amp;gt;
preg_match($reg, $site_html, $sid);
$sid = $sid[1];&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
Получив изображение, можно переходить к его разбору.&lt;br&gt;
Для начала я разделил всё изображение на две области:&lt;br&gt;
1) Фигуры&lt;br&gt;
2) Надпись&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/680/1c8/e5f/6801c8e5fa17598be7cb8ddabf6620ff.png"&gt;&lt;br&gt;
&lt;br&gt;
Так как ни фигуры, ни надпись не искажаются и не меняют свое положение, легко составить их матрицы для каждого случая (4*2 = 8 матриц).&lt;br&gt;
Например, так:&lt;br&gt;
&lt;pre&gt;&lt;code class="php"&gt;for($x=0; $x&amp;lt;$width; $x++)
{
    for($y=0; $y&amp;lt;$height; $y++)
    { 
        
        $color[$x][$y] = imagecolorat($img, $x, $y);
        //sign
        if($y &amp;gt; 70)
        {
            $sign[$x1][$y1]  .= ($color[$x][$y]==2147483647?0:1);
            $y1++;
        }
        //FIGURE 1
        if($y &amp;gt; 10 &amp;&amp; $y &amp;lt; 40 &amp;&amp; $x &amp;gt; 20 &amp;&amp; $x &amp;lt; 50)
        {
            $figures[0][$f0x] .= ($color[$x][$y]==16777215?0:1);
        }
        
        //FIGURE 2
        if($y &amp;gt; 10 &amp;&amp; $y &amp;lt; 40 &amp;&amp; $x &amp;gt; 70 &amp;&amp; $x &amp;lt; 100)
        {
            $figures[1][$f1x] .= ($color[$x][$y]==16777215?0:1);
        }
        
        //FIGURE 3
        if($y &amp;gt; 10 &amp;&amp; $y &amp;lt; 40 &amp;&amp; $x &amp;gt; 120 &amp;&amp; $x &amp;lt; 150)
        {
            $figures[2][$f2x] .= ($color[$x][$y]==16777215?0:1);
        }

    }

    if(count($sign)){$x1++; $y1=0;}

    if($x &amp;gt; 20 &amp;&amp; $x &amp;lt; 50) $f0x++;
    if($x &amp;gt; 70 &amp;&amp; $x &amp;lt; 100) $f1x++;
    if($x &amp;gt; 120 &amp;&amp; $x &amp;lt; 150) $f2x++;
}&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
Здесь я делаю матрицы для 3 фигур ($figures) и матрицу для надписи ($sign). Фоновые цвета (у фигур белый, у надписи прозрачный) я заменяю на 0, остальные — 1. &lt;br&gt;
В итоге получаются матрицы наподобие такой:&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/53e/df4/c81/53edf4c813463f27c85088fa0dd7096e.png"&gt;&lt;br&gt;
&lt;br&gt;
Остаётся дело за малым, нужно составить банк матриц для всех фигур и надписей, а затем сравнивая разобранные изображения с заранее сохраненными матрицами можно будет установить номер фигуры, а следовательно — разгадать капчу.&lt;br&gt;
&lt;br&gt;
Код сверки довольно простой:&lt;br&gt;
&lt;pre&gt;&lt;code class="php"&gt;if($sign == $signs['x']) 
{
    if($figures[0] == $drawings['x']){$result = 1;}
    elseif($figures[1] == $drawings['x']){$result = 2;}
    elseif($figures[2] == $drawings['x']){$result = 3;}
    else{$result = 0;}
}
elseif($sign == $signs['circle'])
{
    if($figures[0] == $drawings['circle']){$result = 1;}
    elseif($figures[1] == $drawings['circle']){$result = 2;}
    elseif($figures[2] == $drawings['circle']){$result = 3;}
    else{$result = 0;}
}
elseif($sign == $signs['square'])
{
    if($figures[0] == $drawings['square']){$result = 1;}
    elseif($figures[1] == $drawings['square']){$result = 2;}
    elseif($figures[2] == $drawings['square']){$result = 3;}
    else{$result = 0;}
}
elseif($sign == $signs['triangle'])
{
    if($figures[0] == $drawings['triangle']){$result = 1;}
    elseif($figures[1] == $drawings['triangle']){$result = 2;}
    elseif($figures[2] == $drawings['triangle']){$result = 3;}
    else{$result = 0;}
}&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
Здесь, $signs — матрицы надписей, $drawings — набор матриц фигур, $sign — текущая надпись, $figures — набор текущих фигур.&lt;br&gt;
&lt;br&gt;
В результате получаем номер картинки (или 0 если не удалось разобрать).&lt;br&gt;
&lt;br&gt;
Всё что осталось — отправить запрос на регистрацию:&lt;br&gt;
&lt;pre&gt;&lt;code class="php"&gt;$regURL = &amp;quot;http://bogi.ru/auth/registration?first=TestBot&amp;last=Bot1a&amp;nick=bot&amp;quot;.substr(uniqid(), 0, 5).&amp;quot;&amp;email=bot&amp;quot;.substr(uniqid(), 0, 5).&amp;quot;@gmail.com&amp;password=qwerty123&amp;sex=1&amp;captcha=&amp;quot;.$result.&amp;quot;&amp;sid=&amp;quot;.$sid.&amp;quot;&amp;ajax=1&amp;target=http%3A%2F%2Flostfilm.tv%2F&amp;quot;;
$data = file_get_contents($regURL);&lt;/code&gt;&lt;/pre&gt;&lt;br&gt;
&lt;br&gt;
В ответ получаем &lt;br&gt;
&lt;code&gt;callback({&amp;quot;error&amp;quot;:0,&amp;quot;text&amp;quot;:&amp;quot;&amp;quot;});&lt;/code&gt;&lt;br&gt;
Что значит &lt;b&gt;«Ура! Регистрация пройдена успешно»&lt;/b&gt;.&lt;br&gt;
&lt;br&gt;
Хотел бы заметить, что эта капча крайне не надёжна, легко взламывается даже неопытным программистом за короткое время, и использовать её, если вы хотите оградить свой сайт от ботов и спамеров разумеется не стоит.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;P.S.&lt;/b&gt; В общем, на «взлом» этой капчи ушло около часа, на разбор одной картинки (вместе с парсингом и регистрацией) уходит около 5 секунд. На всякий случай, отчёт о проделанном я отправил в тех. поддержку LostFilm, а затем отправился смотреть 10 серию Хауса.
  		&lt;div class="clear"&gt;&lt;/div&gt;
    &lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/infosecurity/137601/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/infosecurity/137601/</guid>
      <dc:creator>ozver</dc:creator>
    </item>
    <item>
      <title>Информационная безопасность / Боитесь что снова закроют ex.ua? Не стоит — все можно скачать на сервере Министерства внутренних дел Украины</title>
      <link>http://habrahabr.ru/blogs/infosecurity/137634/</link>
      <pubDate>Sun, 05 Feb 2012 13:00:08 GMT</pubDate>
      <description>
  	Заходим на &lt;a href="ftp://91.227.69.2/Install/"&gt;91.227.69.2/Install/&lt;/a&gt; и качаем. Там и пиратская Windows с ключем и MS Office, и еще много чего:&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;img src="http://dl.dropbox.com/u/858463/Untitled-1.png" alt="image"&gt;&lt;br&gt;
&lt;blockquote&gt; &lt;br&gt;
inetnum: 91.227.69.0 — 91.227.69.255&lt;br&gt;
netname: MVS-NET&lt;br&gt;
descr: Ministry of Internal Affairs of Ukraine&lt;br&gt;
country: UA&lt;br&gt;
org: ORG-MoIA2-RIPE&lt;br&gt;
admin-c: MRA75-RIPE&lt;br&gt;
tech-c: MRA75-RIPE&lt;br&gt;
status: ASSIGNED PI&lt;br&gt;
mnt-by: RIPE-NCC-END-MNT&lt;br&gt;
mnt-lower: RIPE-NCC-END-MNT&lt;br&gt;
mnt-by: MNT-MVS&lt;br&gt;
mnt-routes: MNT-MVS&lt;br&gt;
mnt-domains: MNT-MVS&lt;br&gt;
source: RIPE # Filtered&lt;br&gt;
&lt;br&gt;
organisation: ORG-MoIA2-RIPE&lt;br&gt;
org-name: Ministry of Internal Affairs of Ukraine&lt;br&gt;
org-type: OTHER&lt;br&gt;
address: 10 Bohomoltsa str.,&lt;br&gt;
address: Kyiv 01024, Ukraine&lt;br&gt;
phone: +380 44 2561439&lt;br&gt;
fax-no: +380 44 2561697&lt;br&gt;
admin-c: MRA75-RIPE&lt;br&gt;
tech-c: MRA75-RIPE&lt;br&gt;
e-mail: &lt;br&gt;
e-mail: &lt;br&gt;
source: RIPE # Filtered&lt;br&gt;
mnt-by: MNT-MVS&lt;br&gt;
mnt-ref: MNT-MVS&lt;br&gt;
&lt;/blockquote&gt; 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/infosecurity/137634/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/infosecurity/137634/</guid>
      <dc:creator>inoname</dc:creator>
    </item>
    <item>
      <title>Информационная безопасность / Спецам из Рурского университета удалось взломать систему шифрования спутниковой телефонной связи</title>
      <link>http://habrahabr.ru/blogs/infosecurity/137633/</link>
      <pubDate>Sun, 05 Feb 2012 12:54:24 GMT</pubDate>
      <description>
  	&lt;img src="http://habrastorage.org/storage2/85e/a8e/65a/85ea8e65a3133aeba4ca69c80541b7c9.jpg"&gt;&lt;br&gt;
&lt;br&gt;
Да, «И на старуху найдется проруха», правильно говорит эта народная поговорка (или пословица, никогда не понимал между ними разницы). Специалисты по информационной безопасности из университета города Бохум (Рурский университет) на днях заявили об успешном взломе стандарта шифрования спутниковой связи, используемого для переговоров по спутниковым телефонам. При этом исследователям не понадобились экзотичные средства связи и многие тысячи долларов. Достаточно любого ПК и обычного радиоприемника.&lt;br&gt;
&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;Такой системы, при наличии специализированного программного обеспечения, хватит для того, чтобы без всяких проблем прослушивать телефонные переговоры находящихся неподалеку абонентов, использующих спутниковую телефонную связь. По мнению экспертов, все это делает уязвимыми спутниковые телефоны всего мира, при условии использования стандартов шифрования GMR-1 и GMR-2. Эксперты смогли провести так называемый реверс-инжиниринг указанных стандартов связи. &lt;br&gt;
&lt;br&gt;
Упомянутые стандарты шифрования спутниковой связи используются большинством провайдеров спутниковой телефонной связи, включая и такую крупную компанию, как Thuraya. Рабоают с GMR-1 и GMR-2 и военные средства связи, которые также автоматически становятся неустойчивыми к взлому. Стандартизацией алгоритмов шифрования для спутниковой связи занимается ETSI, и именно к этой организации немцы обратились прежде всего, надеясь, что разработчики из ETSI создадут более надежные стандарты шифрования.&lt;br&gt;
&lt;br&gt;
Немецкие специалисты проводят аналогию между сотовой связью и спутниковой связью, обращая внимание на то, что операторы мобильной связи уже занимаются внедрением более надежных средств шифрования в свои сети, в то время, как операторы спутниковой связи пока ничего не делают. Или, если и делают, то все это идет достаточно медленно — а ведь взломщики разных мастей не дремлют.&lt;br&gt;
&lt;br&gt;
Via &lt;a href="http://www.theinquirer.net/inquirer/news/2143626/researchers-crack-satellite-phone-encryption"&gt;theinquirer&lt;/a&gt; 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/infosecurity/137633/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/infosecurity/137633/</guid>
      <dc:creator>marks</dc:creator>
    </item>
    <item>
      <title>Apple / Motorola делает успехи в судебном процессе с Apple</title>
      <link>http://habrahabr.ru/blogs/apple/137602/</link>
      <pubDate>Sun, 05 Feb 2012 12:11:52 GMT</pubDate>
      <description>
  	Как уже писалось ранее на Хабре, корпорация Motorola, а вернее, подразделение Motorola Mobility, еще не перешедшее под юрисдикцию Google, подала в суд на Apple. Суть иска обычное — нарушения патентов. В декабре 2011 года Motorola предприняла попытку договорится с «яблочниками», но, похоже, ничего не вышло. После этого начался судебный процесс, который проходит не лучшим образом для Apple. Тяжба идет в Германии, и немецкий суд уже постановил приостановить продажи iPhone 3G, 3GS и iPhone 4. Правда, это касается только немецкого подразделения корпорации Apple, а не партнеров корпорации.&lt;br&gt;
&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;Тем не менее, Apple Germany уже пришлось отозвать из продажи в этой стране указаннные устройства, включая также и свои планшеты. Все это немного похоже на аналогичный судебный процесс Apple с Samsung, когда последней компании пришлось отзывать собственные устройства из продажи в некоторых странах. Тогда, в прошлом году, южнокорейскому гиганту пришлось даже отозвать планшеты с технологической выставки, т.е. поснимать устройства со стендов. Apple теперь приходится «есть» то, чем компания долгое время «кормила» других, если так можно выразиться.&lt;br&gt;
&lt;br&gt;
Стоит напомнить, что суть претензий Motorola — патенты на беспроводную передачу данных по GPRS, именно эта технология используется в подавляющем большинстве мобильных устройств современности. Используется она и в девайсах от Apple, которые теперь наказаны в Германии. По условиям патента, компании должны запрашивать у Motorola лицензирование на указанную технологию.&lt;br&gt;
&lt;br&gt;
Стоит отметить, что у Apple могут быть и проблемы с работой своего «облачного» сервиса iCloud, поскольку Motorola подала иск и в этом направлении. Суд пока не запретил работу этого сервиса, но в ближайшем будущем это все же возможно. Интересно, поможет ли этот судебный процесс научить Apple вести себя более сдержанно? Наверное, вряд ли.&lt;br&gt;
&lt;br&gt;
Via &lt;a href="http://www.fudzilla.com/home/item/25836-apple-takes-product-from-sale-in-germany"&gt;fudzilla&lt;/a&gt; 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/apple/137602/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/apple/137602/</guid>
      <dc:creator>marks</dc:creator>
    </item>
    <item>
      <title>Android / История заблокированного приложения</title>
      <link>http://habrahabr.ru/blogs/android/137630/</link>
      <pubDate>Sun, 05 Feb 2012 11:55:30 GMT</pubDate>
      <description>
  	&lt;img src="http://www.mobilityfeeds.com/.a/6a0134862db50d970c0153923cd29c970b-250wi" align="left"&gt;Несколько дней назад я писал в &lt;a href="http://habrahabr.ru/blogs/webdev/137496/"&gt;этой &lt;/a&gt; статье о деталях того как можно скачать видео с YouTube. В этой же статье была ссылка на Android-приложение, использующее описанный алгоритм. В комментариях к той статье меня предупреждали, что приложение могут скоро заблокировать, так как оно нарушает правила использования сервиса YouTube. Так и случилось… Через двое суток после публикации приложение стало недоступно для установки из Android маркета. Цель написания этой статьи: показать на своем примере, какие реальные санкции со стороны Google ожидают разработчика если его приложение окажется «вне закона».&lt;br&gt;
Если интересно, добро пожаловать под кат.&lt;br&gt;
&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
Для начала приведу немного статистики:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;С момента публикации до блокировки прошло почти 48 часов;&lt;/li&gt;
&lt;li&gt;За это время приложение было установлено 26 943 раза;&lt;/li&gt;
&lt;li&gt;Благодаря встроенной рекламе я заработал около 100$ (правда снять их не получилось, подробности ниже).&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
Разрабатывая YouTube Downloader я не рассчитывал, что подобное приложение будет пользоваться такой дикой популярностью. Учитывая, что я не прилагал особых усилий, чтобы как-то продвинуть его, кроме того, что запостил на своих страницах Facebook, Вконтакте, Twitter сообщение типа «написал новое приложение, если интересно можете установить». На разработку кода ушло в целом около 8 часов времени. Естественно, никакого особенного дизайна там не было, так как в дизайне я не слишком силен. Чисто ради интереса я так же встроил в приложение 2 самых маленьких баннера (320х50) доступных в системе &lt;a href="http://www.admob.com/"&gt;AdMob&lt;/a&gt;. Приложение было бесплатным. Была мысль сделать его платным, но я из Украины, поэтому на данный момент это оказалось невозможным.&lt;br&gt;
Уже через несколько часов после публикации было больше сотни установок. Вместе с установками пошли и клики по баннерам. Поначалу прирост составлял порядка 0.5$ в час, потом все больше и больше. К началу вторых суток на виртуальном счету было уже около 40$. Я уже было решил, что наткнулся на золотую жилу. Мысленно я представлял, что такими темпами через полгода буду рассекать по родному городу на BMW-Z4. Но не тут-то было…&lt;br&gt;
После очередного обновления страницы статистики в маркете я увидел, что приложение перешло в статус «Приостановлено». &lt;br&gt;
&lt;br&gt;
&lt;img src="http://dl.dropbox.com/u/26865519/abdroid_console.jpg"&gt;&lt;br&gt;
&lt;br&gt;
Почти одновременно с этим пришло письмо от саппорта следующего содержания:&lt;br&gt;
&lt;blockquote&gt;Hello,&lt;br&gt;
&lt;br&gt;
This is a notification that the application, YouTube Downloader, with package ID com.youtubedownloader has been removed from Android Market due to a violation of the Developer Content Policy. Please review the &lt;a href="http://market.android.com/support/bin/answer.py?answer=113474"&gt;Content Policies&lt;/a&gt;, &lt;a href="http://www.android.com/us/developer-distribution-agreement.html"&gt;Developer Distribution Agreement&lt;/a&gt;, and &lt;a href="http://www.google.com/mobile/android/market-policies.html"&gt;Business and Program Policies&lt;/a&gt; before you create or upload additional applications. Please also consult our &lt;a href="https://www.google.com/support/androidmarket/developer/bin/answer.py?&amp;amp;&amp;amp;answer=188189"&gt;guidelines on rating your application&lt;/a&gt;. If your developer account is still in good standing, and the nature of your application allows for it; please make any necessary revisions and upload a new version that is compliant with the above Terms.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Please be advised that violations may result in a suspension of your Android Market Publisher account, and may also result in actions, including possible suspension, taken against any associated Android Market Publisher, AdSense, Google Checkout, or AdMob accounts.&lt;/b&gt;&lt;br&gt;
&lt;br&gt;
To appeal this decision, please reply to this email, or visit the &lt;a href="http://market.android.com/support"&gt;Android Market Help Center&lt;/a&gt; for additional information.&lt;br&gt;
&lt;br&gt;
Thanks,&lt;br&gt;
The Android Market Team&lt;/blockquote&gt;&lt;br&gt;
Я конечно расстроился, но не удивился (предупреждали ведь) и первым делом отправился читать &lt;a href="http://www.youtube.com/t/terms"&gt;правила пользования сервисом YouTube&lt;/a&gt; и нашел пункт, согласно которому можно однозначно сказать: скачивать видео с YouTube запрещено (кроме специально оговоренных случаев). Вот выдержка из правил:&lt;br&gt;
&lt;blockquote&gt;Content is provided to you AS IS. You may access Content for your information and personal use solely as intended through the provided functionality of the Service and as permitted under these Terms of Service. You shall not download any Content unless you see a “download” or similar link displayed by YouTube on the Service for that Content. You shall not copy, reproduce, distribute, transmit, broadcast, display, sell, license, or otherwise exploit any Content for any other purposes without the prior written consent of YouTube or the respective licensors of the Content. YouTube and its licensors reserve all rights not expressly granted in and to the Service and the Content.&lt;/blockquote&gt;&lt;br&gt;
Таким образом все даунлоадеры, сервисы, скрипты, расширения для браузера и тому подобные утилиты являются вне закона. Скачивать можно только разрешенные для скачивания видео, а все остальное от лукавого.&lt;br&gt;
Но блокировкой приложения санкции не закончились. На следующие сутки я попробовал зайти в аккаунт AdMob чтобы проверить сколько там «накапало» и не смог этого сделать: аккаунт заблокировали. Официальное сообщение при логине:&lt;br&gt;
&lt;blockquote&gt;Your account has been disabled for invalid activity or repeated policy violations. Some examples include recurring manual clicks or impressions, violation of our content policies which can be found &lt;a href="http://www.google.com/support/admob/bin/answer.py?answer=1307237"&gt;here&lt;/a&gt;, robots, automated click and impression generating tools, third-party services that generate clicks or impressions such as pay-to-click, pay-to-surf, autosurf, and click-exchange programs, or any deceptive software. If you have any questions or concerns about the actions we've taken, how you can appeal this decision, or invalid activity in general, you can find more information &lt;a href="http://www.google.com/support/admob/bin/answer.py?answer=1693551"&gt;here&lt;/a&gt;.&lt;br&gt;
&lt;/blockquote&gt;&lt;br&gt;
Получается, что все что было заработано при помощи нелегального приложения получить не удастся, питать ложных надежд не стоит. Более того, единственный способ получить свой аккаунт обратно, это заполнить &lt;a href="https://support.google.com/admob/as/bin/request.py?hl=ru&amp;amp;contact_type=disablement_appeal"&gt;эту форму&lt;/a&gt; и рассчитывать на снисхождение администрации. Но и это еще не все. Если аккаунт не разблокируют, а ты создашь новый и этот новый аккаунт будет уличен в связи с заблокированным, то и новый заблокируют. Получается пожизненный бан и в дальнейшем можно забыть о том, чтобы зарабатывать на своих приложениях с помощью AdMob. А это уже довольно серьезный демотиватор…&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Выводы&lt;/h4&gt;&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;Волне реально за короткие сроки и без особых вложений написать популярное приложение, которое будет приносить хороший дополнительный доход;&lt;/li&gt;
&lt;li&gt;Перед тем, как публиковать приложение, следует убедиться что оно не нарушает авторские права и не использует нелегальный контент;&lt;/li&gt;
&lt;li&gt;Если приложение будет нарушать чьи-либо права или использовать нелегальный контент оно обязательно будет заблокировано;&lt;/li&gt;
&lt;li&gt;Если нелегальное приложение показывало рекламу AdMob, соответствующий аккаунт так же будет заблокирован за накручивание кликов и получить его обратно будет крайне сложно.&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Вместо послесловия&lt;/h4&gt;&lt;br&gt;
Я рассказал эту историю, чтобы показать какие последствия ожидают тебя если ты невнимательно подойдешь к вопросу нарушения авторских прав. Впрочем, если ты такой же как и я, то наверняка решишь рискнуть. А вдруг пронесет?.. 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/android/137630/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/android/137630/</guid>
      <dc:creator>alexrewa</dc:creator>
    </item>
    <item>
      <title>Системное администрирование / Юзеры делятся на тех, кто еще не делает бекапы и тех, кто уже делает</title>
      <link>http://habrahabr.ru/blogs/sysadm/137610/</link>
      <pubDate>Sun, 05 Feb 2012 11:22:50 GMT</pubDate>
      <description>
  	&lt;h4&gt;Почему?&lt;/h4&gt;&lt;br&gt;
&lt;br&gt;
Ежедневно происходит множество случаев, когда пользователи \ администраторы теряют свои данные. Это может происходить из-за многих факторов.&lt;br&gt;
&lt;br&gt;
1. Выходят из строя жесткие диски на сервере. Даже если на Вашем сервере работает RAID массив (с уровнями надежности, такие как 1, 1Е, 10, 5, 50, 5Е, 5ЕЕ, 6, 60), данные могут быть потеряны. Во многих случаях, RAID не спасет Ваши данные, например, в результате удаления файлов\папок. И если у Вас нет резервной копии — у Вас могут быть проблемы.&lt;br&gt;
&lt;br&gt;
2. В дата-центре &lt;a href="http://habrahabr.ru/blogs/hosting/89172/"&gt;может быть пожар&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
3. Дата-центр &lt;a href="http://habrahabr.ru/blogs/personal/131029/"&gt;может убежать с серверами&lt;/a&gt; :). Да-да, бывает и такое. Так же сервера могут отобрать за долги.&lt;br&gt;
&lt;br&gt;
4. Вашего хостера &lt;a href="http://habrahabr.ru/company/oversun-mercury/blog/90171/"&gt;могут отключить за долги&lt;/a&gt;. (Дата-центр, операторы связи)&lt;br&gt;
&lt;br&gt;
5. Хостеру &lt;a href="http://habrahabr.ru/blogs/hosting/61324/"&gt;прекратили&lt;/a&gt; доступ в сеть&lt;br&gt;
&lt;br&gt;
Таких случаев — море, можно целую коллекцию собрать :-)&lt;br&gt;
&lt;br&gt;
В любом случае, нужно &lt;b&gt;всегда делать бекапы, причем на другой сервер&lt;/b&gt;. Как их делать и как не тратить «лишних» денег, если важные данные не занимают много места.&lt;br&gt;
&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;img src="http://watcher.com.ua/wp-content/uploads/IMG_4046__-500x333.jpg" alt="image"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Как делать бекапы?&lt;/h4&gt;&lt;br&gt;
&lt;br&gt;
Обычно, на серверах установлены панели управления. В большинстве случаев, в них уже встроен механизм резервного копирования:&lt;br&gt;
&lt;br&gt;
1) ISPManager. Резервное копирование на уровне &lt;a href="http://ru.ispdoc.com/index.php/%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8_%D1%80%D0%B5%D0%B7%D0%B5%D1%80%D0%B2%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_(ISPmanager)#.D0.94.D0.BE.D0.B1.D0.B0.D0.B2.D0.BB.D0.B5.D0.BD.D0.B8.D0.B5_.D0.BD.D0.BE.D0.B2.D0.BE.D0.B3.D0.BE_.D0.B7.D0.B0.D0.B4.D0.B0.D0.BD.D0.B8.D1.8F"&gt;пользователя&lt;/a&gt;, на уровне &lt;a href="http://ru.ispdoc.com/index.php/%D0%9D%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B8_%D1%80%D0%B5%D0%B7%D0%B5%D1%80%D0%B2%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_(ISPmanager)#.D0.94.D0.BE.D0.B1.D0.B0.D0.B2.D0.BB.D0.B5.D0.BD.D0.B8.D0.B5_.D0.BD.D0.BE.D0.B2.D0.BE.D0.B3.D0.BE_.D0.B7.D0.B0.D0.B4.D0.B0.D0.BD.D0.B8.D1.8F"&gt;администратора&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
2) &lt;a href="http://www.directadmin.name/backup.html"&gt;DirectAdmin&lt;/a&gt;. &lt;br&gt;
&lt;br&gt;
3) &lt;a href="http://docs.cpanel.net/twiki/bin/view/AllDocumentation/CpanelDocs/BackUps"&gt;CPanel&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
Во всех этих панелях, есть функция удаленного резервного копирования. Рекомендую использовать &lt;b&gt;SFTP&lt;/b&gt;, но если такой возможности нет, то просто FTP.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Резервное копирование баз данных MySQL и файлов на удаленный FTP.&lt;/b&gt;.&lt;br&gt;
Я не буду приводить примеры резервного копирования mysql и файлов, так как этих скриптов навалом на хабре.&lt;br&gt;
Собственно, вот статья с этими &lt;a href="http://habrahabr.ru/company/nqhost/blog/117771/"&gt;скриптами&lt;/a&gt;.&lt;br&gt;
Так же можно использовать &lt;a href="http://sourceforge.net/projects/automysqlbackup/"&gt;AutoMySQLBackup&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
Что касается файлов. Это действительно самый простой пример бекапа. На деле нужно поднимать систему инкрементального бекапа, так как хранить копии одинаковых файлов невыгодно и глупо. Но это уже отдельная статья.&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Куда сливать бекапы?&lt;/h4&gt;&lt;br&gt;
Далее, возникает логичный вопрос. &lt;b&gt;Где хранить эти бекапы?&lt;/b&gt;&lt;br&gt;
Для новичков, подойдет &lt;a href="https://my.majorhost.net/manager/billmgr?func=register&amp;amp;welcomfunc=backupftp.order&amp;amp;welcomparam=price=192&amp;amp;project=1"&gt;тариф&lt;/a&gt; от хостера majorhost — &lt;b&gt;бесплатный&lt;/b&gt; аккаунт с пространством 1гб. Этого хватит для инкрементального бекапа всех файлов и нескольких бекапов базы данных небольшого сайта. Если Вам этого пространства уже не хватает, вы всегда можете «проапгрейдить» свой аккаунт. К тому же, имеется веб интерфейс для управления Вашими файлами и FTP аккаунтами.&lt;br&gt;
&lt;br&gt;
В биллинге зарегистрировались, &lt;a href="https://my.majorhost.net/manager/billmgr?func=register&amp;amp;welcomfunc=backupftp.order&amp;amp;welcomparam=price=192&amp;amp;project=1"&gt;заказали услугу&lt;/a&gt;, а как получить конечный аккаунт FTP?&lt;br&gt;
&lt;br&gt;
Переходим в пункт меню &lt;b&gt;FTP бекап&lt;/b&gt;, выбираем заказанную услугу кликом, нажимаем кнопку &lt;b&gt;«на сервер»&lt;/b&gt;.&lt;br&gt;
Вы попали в веб-интерфейс управления аккаунтом.&lt;br&gt;
&lt;br&gt;
Главное меню — FTP аккаунты. Нажимаем создать новый, или меняем пароль у существующего. В качестве адреса сервера, используем адрес из URL, например: srv**.majorhost.net&lt;br&gt;
&lt;br&gt;
Некоторые еще делают &lt;a href="http://habrahabr.ru/search/?q=dropbox+%D0%B1%D0%B5%D0%BA%D0%B0%D0%BF"&gt;бекапы&lt;/a&gt; на &lt;a href="http://www.dropbox.com"&gt;dropbox&lt;/a&gt;, но мне этот вариант не понравился. Не стабилен, от меня пинг туда 190ms, скорость закачки тоже не супер. Да и места там не на много больше…&lt;br&gt;
&lt;br&gt;
Многие хостеры дают с заказанными серверами FTP аккаунт для бекапов.&lt;br&gt;
P.S Если еще какие-нибудь хостеры предоставляют FTP for free :), пишите в личку, добавлю.&lt;br&gt;
&lt;br&gt;
Помните. Настроить систему бекапа, даже для новичка — 5 минут. Контролировать резервные копии — 1 минута в неделю. Восстанавливать информацию — бесценно. Куча потерянного времени и нервов, + прибавка седых волосинок на вашей голове :)&lt;br&gt;
&lt;br&gt;
Желаю удачи! 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/sysadm/137610/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/sysadm/137610/</guid>
      <dc:creator>artamonovg</dc:creator>
    </item>
    <item>
      <title>Телефония / Что такое iNum, и чем мы можем помочь развитию данного проекта</title>
      <link>http://habrahabr.ru/blogs/telephony/135938/</link>
      <pubDate>Sun, 05 Feb 2012 11:06:03 GMT</pubDate>
      <description>
  	&lt;h4&gt;Что такое iNum&lt;/h4&gt;&lt;br&gt;
&lt;img src="http://inum.xaker1.ru/wp-content/themes/showtime/sliders/images/logo.png" alt="image" align="left"&gt;iNum, international Number, международный номер. Данные номера позиционируются как глобальные телефонные номера для нового мира, не зависящего от географической привязки, текущего местоположения, расстояния и государственных границ. &lt;br&gt;
&lt;br&gt;
iNum использует телефонный код +883, выделенный ITU (международный союз электросвязи) компании Voxbone для нужд IP телефонии, помимо голосовых вызовов на данные номера доступны и sms сообщения.&lt;br&gt;
&lt;br&gt;
Предполагается, что вызовы на данные номера с ТфОП будут равны по стоимости местным вызовам. Но увы, еще далеко не все ОпСоСы и обычные телефонные провайдеры маршрутизируют звонки в данном направлении (да и не все VoIP провайдеры тоже).&lt;br&gt;
&lt;br&gt;
Предоставление номера в массиве +883 абсолютно бесплатно. В России этим занимаются всего 2 провайдера:&lt;a href="http://www.youmagic.com/"&gt;YouMagic&lt;/a&gt; и &lt;a href="http://www.mob1.biz/"&gt;Mobile One&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;h4&gt;Способы подключения&lt;/h4&gt;&lt;br&gt;
Существует 2 способа подключения к iNum.&lt;br&gt;
&lt;br&gt;
Первый, он же простейший — просто переадресовывать звонки на SIP номера _number_@inum.net (например, 883510000000091@inum.net), а sms сообщения отсылать по протоколу XMPP на тот же адрес (_number_@inum.net, например 883510000000094@inum.net)&lt;br&gt;
&lt;br&gt;
Второй — подать заявку через &lt;a href="http://inum.net/contact/"&gt;форму обратной связи&lt;/a&gt; и получить прямой доступ к iNum. В данном случае SMS сообщения оправляются в качестве SIP сообщений.&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Проверка маршрутизации&lt;/h4&gt;&lt;br&gt;
&lt;br&gt;
Существует 2 номера для проверки маршрутизации (везде по 8 нулей):&lt;br&gt;
Echo тест: 883510000000091&lt;br&gt;
DTMF тест: 883510000000092&lt;br&gt;
CallerID тест: 883510000000093&lt;br&gt;
SMS тест: 883510000000094 — оправляем свой email, в случае успешной доставки на email получаете уведомление.&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Чем Хабрасообщество может помочь развитию iNum?&lt;/h4&gt;&lt;br&gt;
Вариантов несколько:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;Проверить доступность вызовов и sms на iNum со своего провайдера (в т.ч. и в роуминге)&lt;/li&gt;
&lt;li&gt;Связаться со своим провайдером, с просьбой о поддержке iNum.&lt;/li&gt;
&lt;li&gt;Сообщить о iNum в Twitter, FaceBook, G+, etc.&lt;/li&gt;
&lt;li&gt;Общаться на форуме iNum, предлагать свои идеи для развития iNum&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
&lt;br&gt;
Предлагаю проверять возможность звонков\отправки смс сообщений (не только мобильных и стационарных провайдеров, но и и VOIP), оставлять свои пожелания оператору и в комментариях сообщать о результатах — добавлю в табличку ниже. Так же оставлять результаты можно на форуме проекта.&lt;br&gt;
&lt;br&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;Оператор&lt;/td&gt;
&lt;td&gt;Поддерживает ли звонки по номерам iNum&lt;/td&gt;
&lt;td&gt;Поддерживает ли sms по номерам iNum&lt;/td&gt;
&lt;td&gt;Запрос отослан&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Beeline&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MTS&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Megafon&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tele2&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LMT&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Life&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;U-tel&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ростелеком&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kyivstar&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Нет&lt;/td&gt;
&lt;td&gt;Да&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Ссылки&lt;/h4&gt;&lt;br&gt;
&lt;a href="http://inum.net"&gt;Официальный сайт проекта&lt;/a&gt;&lt;br&gt;
&lt;a href="http://inum.xaker1.ru"&gt;Русскоязычное зеркало проекта&lt;/a&gt;&lt;br&gt;
&lt;a href="http://www.inum.net/forum/"&gt;Форум проекта&lt;/a&gt; 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/telephony/135938/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/telephony/135938/</guid>
      <dc:creator>xaker1</dc:creator>
    </item>
    <item>
      <title>Интерфейсы / Перенос корпоративной почты на почту для домена от Яндекса</title>
      <link>http://habrahabr.ru/blogs/ui/136542/</link>
      <pubDate>Sun, 05 Feb 2012 10:07:01 GMT</pubDate>
      <description>
  	&lt;h1&gt;Дисклеймер&lt;/h1&gt;&lt;br&gt;
Может показаться, что в этом топике я ругаю Яндекс, но на самом деле все совсем не так. Эта история о том, как мелочи могут серьезно повлиять на впечатление от продукта, или помочь в решении проблемы. Также, я надеюсь, что эта статья поможет «собратьям по несчастью» пока в Яндексе занимаются доработками продукта.&lt;br&gt;
&lt;br&gt;
&lt;h1&gt;Предыстория&lt;/h1&gt;&lt;br&gt;
Одним прекрасным зимним днем решили мы перенести корпоративную почту на Яндекс, ибо старая почта доставляла лишние хлопоты: то надо было освобождать место для новых писем, то ящики переставали работать без видимых причин. В общем, по сравнению с тем, что было, Яндекс.почта представлялась чем-то далеким и прекрасным…&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;h1&gt;Приключения админа — тайна Яндекса&lt;/h1&gt;&lt;br&gt;
&lt;h2&gt;Начало&lt;/h2&gt;&lt;br&gt;
Первым делом я открыл хром, залогинился на Яндексе и попробовал подключить домен. Имя домена ввелось, кнопка нажалась и мне предстала надпись «Проверка подключения домена может занять продолжительное время». Минут 5 я сосредоточенно ожидал результата, после чего решил пройтись по офисам и решить организационные вопросы.&lt;br&gt;
&lt;br&gt;
Вернувшись через пару часов я обнаружил точно такую же картину и решил поискать решение в интернетах. К счастью, &lt;a href="http://habrahabr.ru/links/73490/#comment_2113829"&gt;полезный комментарий&lt;/a&gt; нагуглился почти сразу. Из него стало ясно, что у хрома и сафари есть «семейные» проблемы с работой яндексовского кода — через пару минут домен был успешно добавлен через IE и с его подтверждением проблем не возникло.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Заметка номер раз&lt;/b&gt;: Сообщение о «проверке подключения» малоинформативно — слишком уж растяжимое понятие «продолжительное время». Может быть, кто-то уже неделю ждет, пока эта продолжительность пройдет. О кроссбраузерности я скажу ниже…&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;А настроить?&lt;/h2&gt;&lt;br&gt;
Есть у меня одна привычка: тестировать перед введением в эсплуатацию. Поэтому мне не очень понравился подход Яндекса, при котором ничего нельзя настроить, не прописав MX-записи. Значит, придется поработать во внеурочное время. Я разослал всем сообщения о том, что с завтра вся почта будет уже в другом месте и подготовился к рабочему вечеру.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Заметка номер два&lt;/b&gt;: Не стоит недооценивать песочницы и возможности опробовать продукт, особенно если он создан для администраторов. Из-за того, что пришлось работать «по-живому», сотрудникам предприятия добавилось лишнего геморрою при переносе почты.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Дружественный интерфейс&lt;/h2&gt;&lt;br&gt;
Воспользовавшись &lt;a href="https://pdd.yandex.ru/help/section61/"&gt;инструкцией&lt;/a&gt;, я подключил поддомен для входа в почту. Поддомен mail уже активно использовался для старой почты (с него забирают почту Thunderbird'ы), поэтому я решил, что от использования поддомена pochta хуже не станет. На первый взгляд все работало нормально — форма входа отображалась. А проверять её было нечем — почтовые ящики нельзя создать до переезда.&lt;br&gt;
Забегая вперед, скажу, что затея провалилась: после входа в почту всем пользователям вываливалась вот такая «красота»:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/32f/ccb/361/32fccb361ae4535e90b08a4db25fe55d.png"&gt;&lt;br&gt;
Паника, хаос и звонки админу были обеспечены.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Заметка номер три&lt;/b&gt;: Если Вы активно следите за безопасностью, то делайте так, чтобы пользователь понимал что «что-то не так» как можно раньше. Лучше бы предупреждение о безопасности выдавалось до ввода данных — тогда мне не пришлось бы вводить пользователей в заблуждение.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Создание ящиков&lt;/h2&gt;&lt;br&gt;
Создать ящики заранее нельзя, добавить ящики пачкой нельзя — строго ручками по одному. Ну да ладно, на что не пойдешь ради светлого будущего… Подвох оказался там, где не ждали: интерфейс отчаянно тупил после добавления пары ящиков. Надпись «Выполняется...» могла висеть сколько угодно — приходилось постоянно перезагружать страницу, чтобы проверить результат действия. Рабочий вечер плавно перетекал в рабочую ночь…&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Заметка номер четыре&lt;/b&gt;: Новые технологии не всегда так хороши, как говорят маркетологи. Модный «аяксовый» интерфейс может перестать нормально работать даже у Яндекса. Так что иногда лучше по-старому, но надежно.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Безопасность превыше всего&lt;/h2&gt;&lt;br&gt;
Не все ящики удалось создать со старыми паролями. У кого-то пароли были недостаточно заковыристыми, у кого-то недостаточно длинными. Из-за того, что в Яндексе такого не терпят, приходилось объяснять, что другая не только страница для входа, но и пароль. Не очень радостное известие среди нежданной рабочей ночи.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Заметка номер пять&lt;/b&gt;: Безопасность — это всегда неудобно. Не забывайте об этом и не фанатейте от всевозможных проверок и шифрований, пользователи вряд ли это оценят.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Сохраняя лучшее&lt;/h2&gt;&lt;br&gt;
За годы работы в старой почте сотрудники собрали ценную переписку, которую необходимо было оставить в целости и сохранности. Причем непременно со структурой папок. Но перенос почты по IMAP тоже не пожелал работать в хроме, причем без каких-либо сообщений.&lt;br&gt;
&lt;br&gt;
В одном ящике лежали только системные уведомления, которые никто не сортировал. Я попробовал перенести его через POP3. И здесь оказался нежданный подвох — все письма начали переадресовываться. К счастью, я к тому времени не настроил всю переадресацию, и 10 000 писем свалились в тестовый ящик. Вот бы удивились пользователи…&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Песец подкрался незаметно&lt;/h2&gt;&lt;br&gt;
Подозревая Яндекс в нелюбви к творению конкурента, я открыл &lt;i&gt;старый добрый&lt;/i&gt; IE. Это мало чем помогло. Попытки открыть вкладку «Другой почтовый сервер» заканчиваются ничем — пользователи IE могут попытаться перенести почту только из gmail. Осознаю, что в Яндексе недолюбливают многих :).&lt;br&gt;
&lt;br&gt;
Когда все плохо, обычно почему-то вспоминают рыжих. Так произошло и в моем случае — на помощь был призван Firefox. И случилось маленькое чудо, все заработало довольно сносно. Похоже, разработчики Яндекса пользуются только им.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Заметка номер шесть&lt;/b&gt;: Если вы разрабатываете веб-приложения — не спешите делить браузеры на хорошие и плохие или хоронить их. Оставьте это развлечение админам и пользователям. В большинстве случаев пользователь посчитает плохим веб-сервис а не браузер.&lt;br&gt;
&lt;br&gt;
&lt;h2&gt;Продолжая сохранять&lt;/h2&gt;&lt;br&gt;
Однако, перенос через IMAP сразу не захотел работать и в firefox'е. На этот раз уже с сообщением о «внутренней ошибке». Решаю отложить перенос на следующий день — утро обещает быть неспокойным.&lt;br&gt;
&lt;br&gt;
После долгих объяснений и обещаний «все будет» начинаю заниматься переносом переписки. Приходится переносить по одному ящику по ряду причин:&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;В админке Яндекса можно увидеть лишь количество перенесенных писем, и то только во время переноса.&lt;/li&gt;
&lt;li&gt;В старой админке есть только размер ящика в мегабайтах.&lt;/li&gt;
&lt;li&gt;Сообщения об ошибках при переносе крайне неинформативны. Их всего два:&lt;br&gt;
«Проверьте правильность введенных данных и списка логинов и паролей. Затем попробуйте ещё раз.» и&lt;br&gt;
«Внутренняя ошибка. Попробуйте повторить операцию позже, или обратитесь в службу поддержки.»&lt;/li&gt;
&lt;li&gt;Нельзя понять, при переносе какого ящика возникла ошибка.&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
&lt;br&gt;
Поэтому перенос шел медленно и печально: запустить процесс, дождаться окончания (некоторые ящики переносились 1-2 час), открыть старую почту, открыть новую почту и визуально сравнить их соответствие.&lt;br&gt;
&lt;br&gt;
&lt;b&gt;Заметка номер семь&lt;/b&gt;: Все должно быть сделано так просто, как это возможно. Но не проще.&lt;br&gt;
Чрезмерное упрощение интерфейса может быть вредно. В моем случае помогла бы любая дополнительная информация о ящиках. Но интерфейс яндекс-почты для домена слабо приспособлен для корпоративной почты — нет ни информации о ящиках, ни полей для комментариев (которые будут полезны другим администраторам компании). 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/ui/136542/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/ui/136542/</guid>
      <dc:creator>TipTop</dc:creator>
    </item>
    <item>
      <title>Mobile Development / Native vs Web. Часть 0: +1 аргумент в пользу разработки native мобильных приложений</title>
      <link>http://habrahabr.ru/blogs/mobiledev/137600/</link>
      <pubDate>Sun, 05 Feb 2012 08:33:33 GMT</pubDate>
      <description>
  	&lt;img src="http://lh4.googleusercontent.com/-t8ncnqUChyY/Ty0DyB_C46I/AAAAAAAAATw/Pd6MqQBzlvc/s400/NativeVsWeb.png" alt="image"&gt;&lt;br&gt;
&lt;br&gt;
&lt;i&gt;Как-то вечером мне захотелось написать статью о разработке приложений для мобильных устройств, но тут Остапа понесло...&lt;/i&gt;&lt;br&gt;
&lt;br&gt;
Так же как &lt;a href="http://www.youtube.com/watch?v=1yjjNiu4i3k"&gt;киборги в свое время заполонили всю планету&lt;/a&gt;, сейчас мобильные девайсы заполоняют нашу жизнь. А что это означает для нас, гиков? Новые возможности даже обсуждать не стоит — это вкусные плоды с дерева под названием “гаджет”. А раз есть плоды и толпы страждущих, то почему бы не начать их выращивать (я про плоды, выращивать же страждущих умеет лишь Apple )? И тот вырастит больше и вкуснее, у кого инструмент лучше. Какие есть подходы в мобильном приложениеводстве? Как минимум можно использовать старую проверенную web-платформу и заняться написанием мобильных web-приложений, либо освоить молодую отрасль разработки под iOS и Android. Выбор, не простой, и чаши весов качались крайне долго в моей голове, пока на сторону разработки приложений под iOS (потенциально и под Android) не пал один весомый аргумент, о котором сегодня и пойдет речь. Но для начала краткий экскурс в технологии и их возможности.&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;h4&gt;Что нам стоит инструмент освоить?&lt;/h4&gt;&lt;br&gt;
Как минимум нужно с чего-то начинать. Это могут быть либо книги, либо туториалы. В области мобильных web-приложений все просто: о без года совершеннолетнем JavaScript (прим. для танкистов: он в 1995 году появился), его сестре погодоке CSS и старшем брате HTML 1991 года рождения написано книг на терабайт, а может и более. Одним словом, сфера развитая, готового материала в ней много, как и специалистов (прим. автора: и тех кто считает себя таковыми), и процесс обучения не должен вызвать особых трудностей. Молодые бойцы могут начать тренироваться на кошках, разрабатывая обычные десктопные web-приложения, а затем планомерно перейти на мобильные платформы. Единственное, что для вас изменится — вы будете использовать jQuery Mobile с вкраплениями jQTouch вместо классического JQuery. В довесок вы получите GEO-API, события поворота устройства (увы, полноценного доступа к гироскопам и акселерометрам вам не дадут, так что написать аналог &lt;a href="http://itunes.apple.com/ru/app/multiponk/id366322908?mt=8"&gt;Multiponk&lt;/a&gt; у вас не выйдет) и довольно убогий мультитач. По вышеупомянутым “довескам”, кстати сказать, материал придется собирать в сети по крупицам, книг или руководств в стиле “Пишем современное работающее приложение для mobile web с поддержкой GEO, Rotation и Multitouch” вы скорее всего не найдете (или я плохо искал?).&lt;br&gt;
&lt;br&gt;
Хорошо, а как дело обстоит с нативными платформами? Т.к. нас интересует лишь рынок, то отвернем головы от MeeGo, Symbian, RIM. И вот мы видим симпотяжку робота четырех лет от роду и вкусненькое яблоко, появившееся на свет годом ранее. Из хороших моментов можно отметить, что за годы существования было написано много фундаментальных изданий как для iOS, так и для Android. Писать для Android несколько проще: в качестве язык SDK — Java, взнос за Android Market составляет 25 енотов единоразово, а SDK доступен почти под любую вменяемую OS. С iOS дела обстоят несколько сложнее, т.к. денежных вливаний будет много: вначале вам придется купить Mac, после того, как вам надоест возиться с хакинтошами, затем вы выложите около сотни енотов за аккаунт разработчика в год, без него, кстати говоря, вы не получите доступ к полной документации SDK и видео с WWDC (качаешь с торрентов?! — типун тебе в карму). За все эти денежно/временные вложения вы получите полноценную поддержку GEO-API, полноценный гироскоп (либо акселерометр), микрофон, камеру, доступ к фото галерее, хранилище данных, мультитач. Выбор плюшек явно богаче чем при web-разработке. &lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Быстрее, выше, сильнее&lt;/h4&gt;&lt;br&gt;
Дьявол в деталях. А в мобильных устройствах, на мой взгляд, самый большой дьявол скрыт в скорости отклика приложения на действия пользователя. И ни один браузер не сможет работать быстрее, чем нативное приложение. Это может показаться несущественно: разница отклика на открытие вкладки, или выбора пункта меню может исчисляться в миллисекундах, но на мобильных устройствах она будет плавнее и быстрее на десяток миллисекунд, и это ощущение не будет вас покидать. Откройте &lt;a href="http://m.youtube.com/"&gt;m.youtube.com&lt;/a&gt; (а ведь это пожалуй одно из лучших web-приложений для мобильных устройств) и походите по сайту. Зайдите во вкладку категорий, поверните ваш гаджет. А теперь откройте встроенное приложение YouTube. И сравните. Детали незначительны, но с нативным приложением работать приятнее, чем с web-версией — плавность и скорость берут свое.&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Эталоны графического дизайна&lt;/h4&gt;&lt;br&gt;
Пожалуй, среди пользователей можно выделить две категории людей: одни кричат “Мы хотим свободы самовыражения в том, что мы создаем”, а другая категория просто делает удобные приложения выдержанные в едином стиле. С такими приложениями легче разобраться, понять, как они работают и какие возможности предоставляют. В web-приложениях же царит буйство красок и форм. Возможно необычный дизайн это и здорово, но чтобы его оценил пользователь, он должен с ним хоть немного поработать, а не закрыть вкладку со словами “не понимаю, зачем оно мне?”. В нативных приложениях платформа диктует принципы построения дизайна — проще сделать классический дизайн, чем придумывать что-то свое. Web же всегда отличался разнообразием подходов к построению пользовательского интерфейса. &lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Аргумент&lt;/h4&gt;&lt;br&gt;
“Gillette — рекламируем станки, а подымаем на лезвиях”. Помимо прямого зарабатывания денег на мобильных приложениях (дядь, купи приложение всего за 1 вечный и зеленый!), сами App-маркеты (AppStore, Android Market) являются потрясающим маркетинговым инструментом! Вы можете использовать мобильное приложение для продажи вашего сервиса.&lt;br&gt;
&lt;br&gt;
Сделав мобильное приложение под Android или iOS, вы запускаете его в уже существующую сеть распространения товаров в категорию FREE. И так же как в обычных супермаркетах, люди пришедшие за молоком могут обратить внимание на йогурт-новинку, так и в AppStore человек пришедший за текстовым редактором может заинтересоваться вашим приложением “Блокнотус”. Но ведь у вас, как у разработчика “блокнотуса” истинная цель привлечь пользователей к вашему сервису и не дать &lt;a href="http://www.evernote.com/"&gt;слонам&lt;/a&gt; голодать ;-)&lt;br&gt;
&lt;br&gt;
Планшеты и прочие мобильные устройства вошли в моду. Люди регулярно ищут новинки в AppStore и Android Market для своих карманных зверюшек. Вероятность того, что они наткнутся на ваше приложение — очень велика. А т.к. оно быстро работает, имеет каноническую графику и простой интерфейс управления, то пользователь сможет понять его и заинтересоваться им. Овладев же его интересом вы овладеваете потенциальным заказчиком услуг вашего интернет-сервиса.&lt;br&gt;
&lt;br&gt;
&lt;i&gt;P.S.0:&lt;/i&gt; это первая статья из серии сравнения процесса разработки мобильных native и web приложений. Несмотря на то, что я убедился (я надеюсь, и вы тоже) в доминировании native-платформы, иногда встречаются задачи, для которых web — это быстрое и дешевое решение, от которого лишь требуется принимать пару строк текста от пользователя и возвращать результат (даю волю вашей фантазии!).&lt;br&gt;
&lt;i&gt;P.S.1:&lt;/i&gt; интересный факт, ранее Apple активно продвигал &lt;a href="http://www.apple.com/webapps"&gt;Apple WebApps&lt;/a&gt; — каталог web-приложений для iOS. Но видимо что-то пошло не так и каталоги прекратили пополняться.&lt;br&gt;
&lt;i&gt;P.S._the_last:&lt;/i&gt; побудили меня на творчество две статьи: &lt;a href="http://beyondplm.com/2012/01/23/plm-mobile-optimized-sites-vs-mobile-apps"&gt;раз&lt;/a&gt; и &lt;a href="http://niallohiggins.com/2011/09/23/3-pros-cons-mobile-apps-with-jquery-mobile-and-html5/"&gt;два&lt;/a&gt;. 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/mobiledev/137600/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/mobiledev/137600/</guid>
      <dc:creator>redcraft</dc:creator>
    </item>
    <item>
      <title>Биоинформатика / Практическая биоинформатика ч.5. Секвенирование ДНК</title>
      <link>http://habrahabr.ru/blogs/bioinformatics/137626/</link>
      <pubDate>Sun, 05 Feb 2012 08:01:45 GMT</pubDate>
      <description>
  	&lt;img src="http://habrastorage.org/storage2/b2d/3a8/e29/b2d3a8e290b637c3ecbcb423237059ac.jpg" align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;В стремлении рассказать о самом сложном, как можно быстрее, очевидно, забываешь о самом простом. И, в моем случае, не только о простом, но и о важном связывающем звене. Причинно-следственная связь слегка нарушилась. В моих предыдущих статьях (&lt;a href="http://habrahabr.ru/blogs/bioinformatics/137069/"&gt;1&lt;/a&gt;, &lt;a href="http://habrahabr.ru/blogs/bioinformatics/137082/"&gt;2&lt;/a&gt;, &lt;a href="http://habrahabr.ru/blogs/bioinformatics/137267/"&gt;3&lt;/a&gt;, &lt;a href="http://habrahabr.ru/blogs/bioinformatics/137453/"&gt;4&lt;/a&gt;) описаны математический аспект и программирование, но в них практически нет биологии. Поэтому эта статья о том, какую именно часть молекулярной биологии пытаются раскрыть, предсказать, увидеть и решить описываемые мною программы и алгоритмы.&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br clear="all"&gt;
&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Картинка с изображением яйцеклетки и сперматозоидов на поверхности символизирует пропущенный мною этап, когда все только зарождается. Интересный факт, что объединение двух клеток дает начало примерно 10 триллионам клеткам человеческого тела.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Начнем с небольшого экскурса в молекулярную биологию. Я постараюсь описать простыми словами сложные вещи, опуская детали. ДНК находится в клетке. Мы рассматриваем именно ДНК и процессы, которые протекают на ней, нас не очень интересует, где именно в клетке она расположена. Необходимо уточнить, что примеры будут приведены для клеток &lt;a href="http://en.wikipedia.org/wiki/Eukaryote"&gt;eukaryotic&lt;/a&gt;, с которыми я работаю, но скорее всего многие вещи подойдут и для &lt;a href="http://en.wikipedia.org/wiki/Prokaryote"&gt;prokaryotic&lt;/a&gt;.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Все процессы в клетке начинаются с ДНК, именно на ДНК находятся последовательности &lt;a href="http://en.wikipedia.org/wiki/Nucleotide"&gt;нуклеотидов&lt;/a&gt;, копирование которых в дальнейшем отвечает за реакции и преобразования в клетках. Нас интересует процесс копирования, называемый &lt;a href="http://en.wikipedia.org/wiki/Transcription_(genetics)"&gt;транскрипцией&lt;/a&gt;. Процесс копирования транскриптов и количество полученных конечных продуктов называется &lt;a href="http://en.wikipedia.org/wiki/Gene_expression"&gt;генной экспрессией.&lt;/a&gt; Но мы называем генной экспрессией и измеряем именно количество копирований транскрипта (вне зависимости от количества полученных конечных продуктов). &lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Ниже приведена иллюстрация из учебника по биологии, называемая “четыре основных генетических процесса, происходящие в клетке” (см. Рис. 1). В данный момент я занимаюсь процессами, изображенными на картинке между номерами 1 и 2. Технологии, которые помогают их изучить, называются DNA-seq и RNA-seq. Эти технологии могут использоваться как по отдельности, так и совместно. В этой статье я более подробно остановлюсь на механизмах работы DNA-seq.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/b61/b51/a8b/b61b51a8b5e332a86e84cc0261ede874.png"&gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Рис. 1&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/9c2/ffd/43d/9c2ffd43d1c0b77467d43a4af1df3944.png" align="left"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;В качестве частного случая DNA-seq рассмотрим “DNA-seq Pol II” (также см. в “&lt;a href="http://habrahabr.ru/blogs/bioinformatics/137453/"&gt;Готовимся работать с ZINBA&lt;/a&gt;”). В основе понимания полученного с ее помощью результата лежит процесс траскрипции. Важную роль в процессе траскрипции играет белок РНК-полимераза (&lt;a href="http://en.wikipedia.org/wiki/RNA_polymerase"&gt;RNA Polymerase&lt;/a&gt;). Полимераза закрепляется на специальном участке ДНК (см. Рис. 2.1), который называется промоутером. Пока проходят подготовительные операции процесса транскрипции (этап Initiation), полимераза остается закрепленной на промоутере. Полимераза начинает создавать копию верхней спирали от старт сайта (начало копируемой цепочки, на рисунке обозначено синей точкой). Потом, двигаясь со скоростью примерно 1000 оснований в минуту (при температуре 37C), она копирует участок ДНК до стоп сайта (конец копируемой цепочки, на рисунке обозначен красной точкой). Еще раз подчеркну, что в положении промоутера полимераза находится большую часть времени, а на каждом участке копируемой ДНК — меньшее. Для дальнейшего изучения ученых интересует промоутер и старт сайт, являющиеся необходимым условием начала транскрипции. Также в промоутере заложена информация о количестве копирований, что тоже является немаловажным объектом изучения. &lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Процесс DNA-seq Pol II с осаждением проходит в несколько этапов: 1. фиксируем текущее положение полимеразы химически или температурно (фиксирование полимеразы означает, что процессы остановились, полимераза не двигается более по ДНК); 2. произвольным способом (ультразвук, &lt;a href="http://en.wikipedia.org/wiki/Micrococcal_nuclease"&gt;MNase &lt;/a&gt;и т.д.) нарезаем ДНК (в большинстве случаев разрезаются незащищённые полимеразой участки ДНК); 3. с помощью иммунопреципитации хроматина (антитела, иммунного ко всем остальным белкам, кроме Pol II) выбираем те участки, которые содержат полимеразу. В результате получаем фрагменты около 150 оснований в длину, которые в дальнейшем отправим в секвенатор. Следует подчеркнуть, что нарезка полимеразы происходит не строго по краям. Таким образом процесс получается следующим: мы подготовили миллионы одной и той же ДНК из разных клеток, зафиксировали полимеразы, большая часть которых находится на промоутере, а часть случайным образом распределена по гену. Результат оцифровки описанного процесса мы наблюдаем на следующем рисунке, приведенном в одной из статей (см. Рис.3). Зелёным обведены риды, определяющие предполагаемый промоутер (риды с высокой плотностью), а за ним располагаются риды с низкой плотностью, соответствующие полимеразе в движении.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/a20/4c2/66b/a204c266b79679219700a145fd53e93b.png"&gt;&lt;br&gt;
&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Рис. 3&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Далее я кратко расскажу о некоторых других белках. В верхней части рисунка 4 можно увидеть, каким образом упакована ДНК (см. Рис. 4.1.), а в нижней части рисунка более детально изображен процесс транскрипции, о котором говорилось выше (см. Рис. 4.2.). Как видно на рисунке 4.1., упаковка ДНК очень плотная, двойная спираль намотана на нуклеосому, длина витка ДНК составляет примерно 146 оснований. Нуклеосома состоит из белков — гистонов. Гистоны могут иметь различные модификации, модификация гистонов — тема огромной отдельной статьи. Антитела разрабатываются на конкретную модификацию гистона, и именно участки ДНК, которые обмотаны вокруг этой модификации гистона, будут осаждены (отфильтрованы). Приведем пример обозначения модификации: H3K4Me3. Он будет читаться, как триметилирование лизина на четвертой позиции гистона H3. Таких модификаций гистонов может быть много, и все они раскиданы по ДНК, поэтому в статье “&lt;a href="http://habrahabr.ru/blogs/bioinformatics/137453/"&gt;Готовимся работать с ZINBA&lt;/a&gt;” на рисунке 2, где изображен ландшафт H3K27Me3 (триметилирование лизина 27 гистона 3), наблюдается такое частое нагромождение пиков.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Существуют технологии DNA-seq без осаждения, когда ДНК просто нарезается, например, при помощи DNase фермента, и мы получаем огромное количество фрагментов. В большинстве случаев фрагменты будут соответствовать виткам, которые обмотаны вокруг нуклеосом, поскольку DNase режет между ними. Получившиеся фрагменты отправляем в секвенатор. Считается, что при глубоком секвенировании (огромное количество фрагментов, около 100 миллионов ридов, идет в секвенатор, пока является дорогим удовольствием) по получившемуся ландшафту можно распознать, где именно находится белок. Причем ландшафт будет иметь вид, как у вулкана, небольшое углубление на вершине должно соответствовать белку. Чаще всего DNase метод используют, чтобы найти участки ДНК, чувствительные к этому ферменту, т.е. те участки, которые лучше всего режутся.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/6d7/d5e/2b2/6d7d5e2b247f0903dd316c9c4684d1eb.png"&gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Рис. 4&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;На нижней части рисунка мы видим РНК-полимеразу, а также разноцветные облака и овалы, размещенные в ней и на ДНК. Эти дополнительные элементы называют транскриптационными факторами, они играют важную роль в регуляции генной экспрессии. Транскриптационные факторы могут как увеличивать, так и уменьшать или просто блокировать возможность присоединения других транскипционных факторов, тем самым неявно приводя к регуляции экспресии. Они также являются белками. Как и ко всем остальным белкам, к ним разрабатываются антитела. В качестве примера транскриптационного фактора возьмем белок &lt;a href="http://en.wikipedia.org/wiki/CTCF"&gt;CTCF&lt;/a&gt;, одна из его ролей состоит в блокировании работы других транскриптационных факторов. DNA-seq эксперименты с ним описаны в статье “&lt;a href="http://habrahabr.ru/blogs/bioinformatics/137453/"&gt;Готовимся работать с ZINBA&lt;/a&gt;”, соответствующий CTCF иммунопреципитации хроматина ландшафт можно увидеть на следующей &lt;a href="http://habrastorage.org/storage2/a18/5f5/7bf/a185f57bf97a494a167b3d275c33abe0.png"&gt;картинке&lt;/a&gt;. Как видно, регионы, защищенные этим белком, небольшие, поэтому и разброс в окрестности невысокий, всего 150-200bp.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Примерная схема видов DNA-seq экспериментов:&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/a71/73e/434/a7173e434742f764f5b6d452db8b36a1.jpg"&gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Рис. 5&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Схему я разбил на четыре условных уровня. Первый уровень — фиксация, она может проводиться с формальдегидом или без. Второй уровень — способ нарезки ДНК. Третий уровень — фильтрация по размеру, в дополнении к этому фильтрация может проводиться с помощью иммунопреципитации хроматина. Четвертый уровень — способ секвенирования.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Таким образом, каждому виду проводимого эксперимента соответствует способ секвинирования. В зависимости от способа секвенирования создаются различные виды фрагментов. Рассмотрим те эксперименты, результатами которых являются фрагменты, содержащие в себе белок. Белок может быть размещен по центру кусочка или с одной из двух сторон кусочка. Секвенатор декодирует не весь отрезок, а только его небольшую часть со стороны 5’ конца спирали каждого фрагмента. Декодированные кусочки называются ридами. На рисунке 6 красными точками отмечены 5’ концы каждой спирали. Синей и красной стрелками отмечены начала ридов. Эти начала распределены случайным образом от 5’ конца каждой спирали до границы белка. &lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/5bd/bb7/220/5bdbb7220bed1b236c6085a9158fa0db.png"&gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Рис. 6&lt;br&gt;
 &lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;В эксперименте участвует множество исходных молекул, их ДНК нарезают в некоторой окрестности белка, когда множество ридов отображают на координатную ось (одного из белков), получается картинка, похожая на эту:&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/146/a7e/801/146a7e8011019dfd33f5fbca99dc446f.png"&gt;&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Рис. 7&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Выше координатной оси (темно-синего цвета) отображены риды с верхней спирали («+» strand), а ниже оси (светло-синего цвета) отображены риды с нижней спирали («-» strand). Точно сказать, где был белок невозможно, предполагается, что центр связывания белка расположен между этими двумя пиками. &lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Полученная картинка напоминает сигнал, и поэтому к данным стали применять некоторые алгоритмы для анализа сигналов, один из которых описан в этой статье &lt;a href="http://habrahabr.ru/blogs/algorithm/135281/"&gt;habrahabr.ru/blogs/algorithm/135281/&lt;/a&gt; — “Что такое скрытые модели Маркова”.&lt;br&gt;
&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Надеюсь, после этой статьи предмет стал более понятен, и дальнейшее изучение не будет вызывать легкий ужас. Если кто-то заинтересуется более подробным изложением материала, есть замечательная книжка Molecular Cell Biology под редакцией Lodish, в которой очень информативно и доступно изложены основы молекулярной биологии.&lt;br&gt;
Review is prepared by Andrey Kartashov, Cincinnati, OH, porter@porter.st. 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/bioinformatics/137626/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/bioinformatics/137626/</guid>
      <dc:creator>Portah</dc:creator>
    </item>
    <item>
      <title>Информационная безопасность / Перспективы развития цивилизации в контексте проблемы бесконтактного информационного обмена</title>
      <link>http://habrahabr.ru/blogs/infosecurity/137625/</link>
      <pubDate>Sun, 05 Feb 2012 03:10:31 GMT</pubDate>
      <description>
  	&lt;img src="http://cs11170.vk.com/u13506726/151878649/x_626be31c.jpg" alt="image"&gt;&lt;br&gt;
&lt;br&gt;
Я нередко ловлю себя на мысли как беспомощны мы становимся без интернета. Зачем воспринимать информацию, накоплять опыт и знания, если в любой момент можно выйти в сеть и воспользоваться поисковыми механизмами? Наука утверждает, что начиная с 80-х прогрессирует количество детей с врожденной социальной дезадаптацией. Это пересекается с так называемым «правилом сотой обезьяны», согласно которому при достижении критического количества особей с определенным опытом, последний становится частью информационного поля всего общества.&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
Сейчас уже мало кто отрицает, что компьютер является органичным продолжением нашего интеллекта. Идея технологической сингулярности, возрождение в 90-х науки эниологии, в конце концов наш с вами образ жизни тому подтверждение. Вопрос в том, как оценивать и как воспользоваться этим знанием. &lt;br&gt;
&lt;br&gt;
Преимущество рассматриваемой системы состоит в нивелировании значения местонахождения человека: вы нигде и в то же время вы везде, пока вы подключены к мировой сети. У вас есть неограниченный доступ к информации и возможность посвятить себя истинному творчеству, ведь вычислительные и физические функции остаются за автоматизированными механизмами. Мы живем на заре эпохи, в которой сфера деятельности человека ограничится культурой и искусствами в самых разных их проявлениях, а весь рутинный труд останется за теми кто пишет программный код. &lt;br&gt;
&lt;br&gt;
Конечно, всегда будут существовать отклонения от предполагаемой тенденции, ведь при любой общественной организации существует субъект власти. Вопрос, в том, сможет ли периферия глобализации(вроде Китая) удержать «железный занавес» в условиях передачи информации бесконтактным путем. Скорее нет, чем да, но это вопрос отдаленного будущего. &lt;br&gt;
&lt;br&gt;
Опасность во всей этой ситуации ровно одна: при крахе системы, которая формируется на наших глазах, человечество будет отброшено в каменный век. История всегда повторяется, развитие цивилизаций протекает по модели цикла и финальный крах неизбежен. Конечный результат размышления с первого взгляда показался абсурдным даже мне, но в попытке заглянуть далеко вперед я вижу светлое будущее только в колонизации окружающей нас вселенной. Ведь первичным механизмом защиты любой системы есть процесс «бэкапа»(создание копии данных на носителе для восстановления данных в оригинальном или новом месте их расположения в случае их повреждения или разрушения). 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/infosecurity/137625/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/infosecurity/137625/</guid>
      <dc:creator>fxmemfis</dc:creator>
    </item>
    <item>
      <title>Обработка изображений / Алгоритм ImageZero (IZ): быстрое сжатие без потери качества</title>
      <link>http://habrahabr.ru/blogs/image_processing/137624/</link>
      <pubDate>Sun, 05 Feb 2012 02:35:00 GMT</pubDate>
      <description>
  	JPEG является стандартом в области компрессии изображений и это один из самых быстрых алгоритмов, но у него одна проблема: JPEG сжимает с потерей качества. Если фотография подвергается многократной обработке, это неприемлемо, и в таких случаях приходится искать альтернативу. Хочется чего-нибудь быстрого и при этом с приемлемой степенью сжатия.&lt;br&gt;
&lt;br&gt;
Беглый взгляд на &lt;a href="http://www.imagecompression.info/gralic/LPCB.html"&gt;бенчмарки&lt;/a&gt; losless-алгоритмов на выборке фотографий не даёт оснований для радости: оказывается, PNG очень быстр на распаковке, но исключительно медленно работает на сжатии изображений. &lt;br&gt;
&lt;br&gt;
Есть ещё JPEG-LS, хороший на первый взгляд. Но на него патент у компании HP, так что без шансов на использование. Немецкий программист Кристоф Фек (Christoph Feck) решил исправить ситуацию и &lt;a href="http://encode.ru/threads/1471-iz-New-fast-lossless-RGB-photo-compression"&gt;выпустил свой алгоритм ImageZero&lt;/a&gt; сжатия фотографий без потери качества. Он примерно в 20 раз быстрее PNG, а по степени сжатия сравним с JPEG-LS. &lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/d91/9a6/8e9/d919a68e9173908c483956338574b99f.jpg"&gt;&lt;br&gt;
&lt;sup&gt; London Bridge (Tower Bridge): Reflection on the River Thames. Автор фотографии: &lt;a href="http://www.flickr.com/photos/anirudhkoul/"&gt;Anirudh Koul&lt;/a&gt;&lt;/sup&gt;&lt;br&gt;
&lt;br&gt;
Результаты обработки &lt;a href="http://www.flickr.com/photos/anirudhkoul/3499471010/sizes/o/in/photostream/"&gt;полноразмерной&lt;/a&gt; версии фотографии London Bridge (4507?3512 пикселей)&lt;br&gt;
&lt;table&gt;
&lt;tr&gt;
&lt;td&gt;&lt;b&gt;Метод&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Размер файла&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Сжатие&lt;/b&gt;&lt;/td&gt;
&lt;td&gt;&lt;b&gt;Распаковка&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Без сжатия&lt;/td&gt;
&lt;td&gt;46380 КБ&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JLS&lt;/td&gt;
&lt;td&gt;14984 КБ&lt;/td&gt;
&lt;td&gt;6,6 с&lt;/td&gt;
&lt;td&gt;7,3 с&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PNG&lt;/td&gt;
&lt;td&gt;16256 КБ&lt;/td&gt;
&lt;td&gt;42,4 с&lt;/td&gt;
&lt;td&gt;2,4 с&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IZ&lt;/td&gt;
&lt;td&gt;15496 КБ&lt;/td&gt;
&lt;td&gt;1,2 с&lt;/td&gt;
&lt;td&gt;1,3 с&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;Судя по первым независимым тестам, IZ претендует на то, чтобы быть вообще самым быстрым lossless-алгоритмом для 24-битных фотографий, и по степени сжатия тоже хорошо выглядит. &lt;br&gt;
&lt;br&gt;
Автор алгоритма &lt;a href="https://kdepepo.wordpress.com/2012/01/30/fast-lossless-color-image-compression/"&gt;пишет&lt;/a&gt;, что IZ не предназначен для greyscale-изображений или синтетических изображений, но он может его приспособить для этих задач. Сейчас IZ лучше всего работает на полноцветных фотографиях и может использоваться в системах хранения, для генерации уменьшенных копий для предпросмотра, ну и как будущий формат для иконок.&lt;br&gt;
&lt;br&gt;
&lt;a href="https://gitorious.org/imagezero"&gt;Исходный код ImageZero&lt;/a&gt; (под лицензией BSD) 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/image_processing/137624/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/image_processing/137624/</guid>
      <dc:creator>alizar</dc:creator>
    </item>
    <item>
      <title>Arduino / Механический дисплей на Arduino — работа над ошибками</title>
      <link>http://habrahabr.ru/blogs/arduino/137444/</link>
      <pubDate>Sat, 04 Feb 2012 23:35:48 GMT</pubDate>
      <description>
  	&lt;a href="http://habrahabr.ru/blogs/arduino/135709/"&gt;Механический дисплей из лего и Arduino&lt;/a&gt;, о котором я писал в начале января оказался, по-моему, довольно неплох для конструкции собранной за вечер. Однако в комментариях справедливо указали на возможности его улучшения. Заодно, читая отзывы, я узнал что такое «POV», спасибо всем откликнувшимся!&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Выявленные недостатки&lt;/h4&gt;&lt;br&gt;
&lt;ul&gt;
&lt;li&gt;Малый размер «экрана», недостаточный для написания слова «Хабрахабр»&lt;/li&gt;
&lt;li&gt;Монохромность&lt;/li&gt;
&lt;li&gt;Неравномерность шага пикселей, расчитанного простым делением времени цикла на разрешение&lt;/li&gt;
&lt;li&gt;Разочарование ожидавших увидеть видео хаброюзеров&lt;/li&gt;
&lt;li&gt;Необходимость вручную побитово кодировать изображение каждой буквы&lt;/li&gt;
&lt;li&gt;Общая нестабильность конструкции — «дисплей» при работе сильно раскачивается&lt;/li&gt;
&lt;li&gt;Холостой обратный ход планки со светодиодами. Они подсвечиваются только во время движения справа налево&lt;/li&gt;
&lt;/ul&gt;&lt;br&gt;
За прошедшие четыре недели конструкцию удалось доработать, и вот что получилось в результате:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/f01/12d/1bb/f0112d1bb4309a1e299131029a9bf36a.jpg" alt="Улучшенная модель дисплея"&gt;&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;&lt;br&gt;
&lt;br&gt;
&lt;h4&gt;Работа над ошибками&lt;/h4&gt;&lt;br&gt;
&lt;h5&gt;Стабильность и размер&lt;/h5&gt;&lt;br&gt;
Улучшить механическую стабильность оказалось проще всего — у ребёнка были позаимствованы кубики Duplo (lego двойного размера совместимое со стандартным), и из них собрана прочная и тяжёлая платформа. После этого удлинил кривошип и нарастил качающуюся планку со светодиодами, тем самым увеличив горизонтальное разрешение. Сперва думал поставить более мощный мотор, но хватило замены батареек на стабилизированный блок питания и небольшого повышения напряжения. При 10,3 вольт моя конструкция делает ровно 6 полных колебаний в секунду.&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/fb8/1d1/95b/fb81d195b04da6bce49094d183306715.jpg" alt="механика"&gt;&lt;br&gt;
&lt;br&gt;
На переднем плане видны две оптические пары — теперь можно ловить и начало обратного хода.&lt;br&gt;
&lt;br&gt;
&lt;h5&gt;Цвет&lt;/h5&gt;&lt;br&gt;
Сделать дисплей цветным казалось лёгкой задачей — достаточно заменить одноцветные светодиоды на RGB. Сказано — сделано. Общие аноды через ограничительные резисторы соединил с шиной данных, а катоды спаял вместе поцветно и подсоединил к выходам Arduino, ответственным за выбор цвета. Когда горят все восемь светодиодов, по каждому проводу выбора цвета стекает до 39 миллиампер, при том что Arduino может максимум 40. Для гарантии добавил три MOSFET транзистора IRF 540 — по одному на каждый цвет. Получилось примерно такая схема (показаны лишь три RGB светодиода):&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/676/bbb/ff2/676bbbff211b6377a03d03584b301566.jpg" alt="Схема включения светодиодов"&gt;&lt;br&gt;
&lt;br&gt;
Качающаяся планка соединяется с контроллером 8+3 тонкими проводами. Немало, но если их аккуратно проложить, то движению они не мешают.&lt;br&gt;
&lt;br&gt;
&lt;h6&gt;Грабли номер один&lt;/h6&gt;&lt;br&gt;
Подаём логическую единицу на нужный анод (D6-D13), единицей-же открываем ответственный за цвет транзистор(D0-D2) и светодиод зажигается. Если на управляющие цветом выходы подать 001, то загорается красный, 010 — зелёный, 011… снова красный, хотя ожидался жёлтый.&lt;br&gt;
&lt;br&gt;
Чтение даташита показало, что красный светодиод зажигается при напряжении в 2,0 Вольта, тогда как зелёному и синему нужны 3,2. В результате после открытия красного диода напряжение практически не растёт, только увеличивается ток, и зелёный с синим не открываются. Решения проблемы для приведёной схемы подключения с ограничивающими ток резисторами в цепи анода я так и не нашёл. Если подключить резисторы к катодам, то на каждом диоде будет падать своё, нужное ему напряжение, но резисторов понадобится 24 штуки, что для моей подвижной конструкции слишком тяжело. Гугль нашёл несколько микросхем драйверов матриц светодиодов, но у меня в хозяйстве их не было. В результате обошёл проблему программно, быстро зажигая цвета по очереди. При задержке в 50 микросекунд на цвет, за время показа одного пикселя элементарные цвета успевают смениться много раз и сливаются в один.&lt;br&gt;
&lt;br&gt;
&lt;h6&gt;Грабли номер два&lt;/h6&gt;&lt;br&gt;
В неподвижном положении устройство теперь показывает ожидаемые цвета, пора опробовать его в движении. Запускаю мотор, и обнаруживаю следующую проблему:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/ed4/559/b11/ed4559b110721e8e7d722f84a2156661.jpg"&gt;&lt;br&gt;
&lt;br&gt;
В RGB cветодиоде красный и синий элементы находятся на противоположных сторонах корпуса, и в результате вместо сиреневого цвета получаем две хорошо различимые отдельные полоски — красную и синюю. На стыке красной и зелёной областей тоже хорошо видна разница в расположении светоизлучающих точек. Эту проблему удалось полностью решить заменой прозрачных светодиодов на матовые.&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/8fd/990/c86/8fd990c863b26a1afb58c01d1ddac666.jpg"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h5&gt;Механическая развёртка&lt;/h5&gt;&lt;br&gt;
&lt;br&gt;
Удлинение планки и увеличение её размаха повысило теоретическое количество пикселей, однако нисколько не решило проблемы неравномерности движения. В крайнем правом положении около двух десятков миллисекунд светодиоды практически неподвижны, в то время как слева они мгновенно меняют направление движения на противоположное. Мотор неидеален и скорость вращения зависит от нагрузки. Гибкий пластик и люфты в соедиениях окончательно запутывают картину. Учебник по теоретической механике я в последний раз открывал лет пятнадцать назад, так что даже не пытался рассчитать динамику движения моего дисплея, и сразу решил измерять как он ведёт себя в реальности. Это оказалось не так уж трудно: впереди поставил маску с равномерно расположенными отверстиями, направил на неё свет яркой лампы, а на конце планки закрепил фоторезистор. &lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/d06/90a/30a/d0690a30a0612f199bb409504eeefdce.jpg"&gt;&lt;br&gt;
&lt;br&gt;
Осталось написать несложную программу, которая сперва делает несколько холостых циклов и усредняет для точности их период, а потом собирает через АЦП данные об освещённости фотодиода. Каждое измерение сопровождается вызовом функции micros, выдающей количество прошедших микросекунд. Массив с данными по последовательному порту перекачал в компьютер и проанализировал в Экселе.&lt;br&gt;
&lt;br&gt;
Вот как выглядит напряжение на фоторезисторе — отлично видно когда на него попадал свет сквозь отверстия в маске:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/d94/0df/511/d940df51112eb9307974352b2e97566b.jpg"&gt;&lt;br&gt;
&lt;br&gt;
А вот нелинейность во всей своей красе, хорошо что не стал пытаться это смоделировать и рассчитать:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/696/dde/ce1/696ddece1a1121d797c7d3e7cb950234.jpg"&gt;&lt;br&gt;
&lt;br&gt;
Эксель умеет аппроксимировать произвольные наборы данных полиномами до пятого порядка, так что через несколько минут в моих руках была заветная формула описывающая движение:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/004/b1d/6fe/004b1d6fe006f46ffff01a5cf5611ff3.jpg"&gt;&lt;br&gt;
&lt;br&gt;
Здесь &lt;b&gt;y&lt;/b&gt; это задержка в микросекундах от начала цикла, &lt;b&gt;x&lt;/b&gt; — номер виртуального пикселя меняющийся от 1 до 20 (у меня в калибровочной маске было 20 отверстий). Давая x дробные значения, можно расчитать задержки для произвольного разрешения. Я остановился на 54 пикселях.&lt;br&gt;
&lt;br&gt;
&lt;h5&gt;Пиксели&lt;/h5&gt;&lt;br&gt;
Для проверки формулы написал простенькую программку, выводящую попеременно 0x55 и 0xAA для подсвечивания пикселей в шахматном порядке. &lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/861/dc0/f47/861dc0f4735d8650c70e92595050ba16.jpg"&gt;&lt;br&gt;
&lt;br&gt;
Экселевская математика не подвела, и к равномерности шага растра претензий нет, но вот сами пиксели получились вместо прямоугольных овальными. Не удивительно, ведь формула рассчитывает задержки для центра идеального пикселя, а реальный светодиод имеет 5 мм в диаметре, и засвечивает прилегающие области. Прямоугольные пиксели проще рисовать прямоугольными светодиодами, чего я и добился, наклеив по бокам непрозрачный скотч:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/73a/9b2/859/73a9b2859452be04daf6a03427f0b9e8.jpg"&gt;&lt;br&gt;
&lt;br&gt;
Контрольная «шахматная доска» подтвердила, что так действительно намного лучше:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/63d/f8b/e9f/63df8be9fb8fc0ea30b81582db70416d.jpg"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h5&gt;Программирование&lt;/h5&gt;&lt;br&gt;
Алгоритм простой и сложностей не предвиделось, однако в определённый момент написания кода программа стала давать странные, непредсказуемые, результаты. Оказалось, что кончилась оперативная память, которой в Arduino UNO всего два килобайта. В микроконтроллере нет следящей за распределением памяти операционной системы, так что никаких ошибок он не замечает и о переполнении не сигнализирует. Я предполагал, что объявленные как const массивы хранятся в Flash-памяти, однако выяснилось, что это не так. Точнее говоря, они сперва лежат действительно в постоянной памяти, но при запуске копируются в RAM, хотя их и нельзя изменять. Чтобы этого избежать, переменные нужно объявлять через PROGMEM, про это &lt;a href="http://arduino.cc/en/Reference/PROGMEM"&gt;нашлась статья &lt;/a&gt; на сайте ардуино. В общем «читайте маны, они рулез».&lt;br&gt;
&lt;br&gt;
&lt;h6&gt;Руссификация&lt;/h6&gt;&lt;br&gt;
Рисовать буквы по-точкам неудобно, так что положил в тот же PROGMEM таблицу знакогенератора и написал функцию отрисовки букв. С английскими символами никаких проблем, а вот вместо русских выводилась белиберда. В качестве среды разработки использовался VisualStudio 2010 с плагином &lt;a href="http://www.visualmicro.com/"&gt;Visaul Micro Arduino&lt;/a&gt;. Несмотря на то, что файлы исходников сохранялись в кодировке Win1251 (один байт на символ), строка вида&lt;br&gt;
&lt;br&gt;
&lt;code&gt;char* text = &amp;quot;ХАБРАХАБР&amp;quot;;&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
объявляла массив длиной 27+1 байт, в котором каждая тройка имела одинаковое содержание, к исходному тексту никакого отношения не имеющее. Тот же код из-под среды Arduino UNO пишет по два байта на русский символ, скорей всего в UTF8. Проблему удалось обойти, закодировав строку посимвольно:&lt;br&gt;
&lt;br&gt;
&lt;code&gt;char russianText[] = {'Х', 'А', 'Б', 'Р', 'А', 'Х', 'А', 'Б', 'Р', '\0'};&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
Теперь, как и ожидалось, получаем 9 байт текста плюс ещё один на завершающий ноль. Запускаем программу и видим… совсем другие символы. Исследование показало, что большая русская буква «А» компилируется в код 144, что никак не соответсвует ожидаемому для Win1251 коду 192. Не поленился и&lt;br&gt;
почитал в Интернете &lt;a href="http://aspell.net/charsets/cyrillic.html"&gt;про возможные кодировки русских букв&lt;/a&gt;, в том числе и весьма экзотические. Ни в одной из них А не транслируется в 144. Единственное приходящее в голову объяснение, это представление русских букв в юникоде, после чего из буквы А (U+0410) вырезается младший байт, к которому почему-то добавляется 128. Почему так — непонятно, но после добавления к коду букв нужной константы, они встали на свои места.&lt;br&gt;
&lt;br&gt;
Вот что получилось в итоге:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/2bb/2b7/9c6/2bb2b79c669f306abb413d2604ff447b.jpg"&gt;&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/e7b/ab5/ea4/e7bab5ea4adf6a50f30e21d4f0848ee4.jpg"&gt;&lt;br&gt;
&lt;br&gt;
&lt;img src="http://habrastorage.org/storage2/51e/ad6/8ac/51ead68ac9458126f880c2598fd94492.jpg"&gt;&lt;br&gt;
&lt;br&gt;
&lt;h5&gt;Видео&lt;/h5&gt;&lt;br&gt;
А как же без него?&lt;br&gt;
&lt;iframe width="560" height="349" src="http://www.youtube.com/embed/y0etgiwv1nc" frameborder="0" allowfullscreen=""&gt;&lt;/iframe&gt;&lt;br&gt;
&lt;br&gt;
При длительности цикла в 170 миллисекунд получается почти точно шесть кадров в секунду. У камеры же — 30 кадров в секунду, и из-за кратности частот на видео заметно сильное мерцание. Если смотреть глазами, то картинка выглядит намного стабильней.&lt;br&gt;
&lt;br&gt;
&lt;h5&gt;Что дальше?&lt;/h5&gt;&lt;br&gt;
Вывод изображения при обратном ходе развёртки пока не запрограммировал. Это позволило бы удвоить частоту кадров, но усложнило бы программирование анимации и прокрутки текста. При рисовании только во время прямого хода у микроконтроллера есть целых 80 миллисекунд, чтобы неторопливо рассчитать следующий кадр. 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/arduino/137444/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/arduino/137444/</guid>
      <dc:creator>commanderxo</dc:creator>
    </item>
    <item>
      <title>Смартфоны и коммуникаторы / Смартфоны совсем недавно и сейчас</title>
      <link>http://habrahabr.ru/blogs/smartphone_ru/137622/</link>
      <pubDate>Sat, 04 Feb 2012 23:22:03 GMT</pubDate>
      <description>
  	Недавно перешёл на следующий смартфон положив Nokia N900 в архив старых кирпичей и задумался о тренде, как было раньше на полках магазинов, и как сейчас:&lt;br&gt;
&lt;br&gt;
&lt;img src="http://sincere.ly/mark/files/2012/02/cell-phones-then-and-now.jpeg" alt="cell-phones-then-and-now"&gt;&lt;br&gt;
&lt;br&gt;
Поначалу меня это улыбныло. Но затем решил &lt;a href="http://many.at/smartfonynahabre/"&gt;полистать архивы на Хабре&lt;/a&gt; – так оно оказывается и есть.&lt;br&gt;
&lt;br&gt;
&lt;a name="habracut"&gt;&lt;/a&gt;Помнится, в начале 2000-х годов шведский Ericsson (тогда ещё без Sony) уступил финской Nokia, так как первые считали, что мобильники – это для бизнесменов. Шведы отказались запускать съемные панели, особенно розовые. Финны – поняли рынок по-другому, и на пике завоевали выше 40% рынка.&lt;br&gt;
&lt;br&gt;
Сегодня же чётко наблюдается обратный тренд, как минимум во внешнем оформлении телефонов. Может уже проелось? Может все равняются на лидеров? Как Вы думаете? 
  	&lt;div class="clear"&gt;&lt;/div&gt; 	
  	&lt;p&gt;
                            &lt;sub&gt;
                                Источник: &lt;a href='http://habrahabr.ru/blogs/smartphone_ru/137622/'&gt;habrahabr.ru&lt;/a&gt;, 
                                получено с помощью &lt;a href='http://rss-farm.ru'&gt;rss-farm.ru&lt;/a&gt;
                            &lt;/sub&gt;
                        &lt;img src='http://c.statcounter.com/5485188/0/94140fb5/1/' alt='' border='0'&gt;
                     &lt;/p&gt;</description>
      <guid isPermaLink="true">http://habrahabr.ru/blogs/smartphone_ru/137622/</guid>
      <dc:creator>Londain</dc:creator>
    </item>
  </channel>
</rss>
